-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Finally a new rule in the `performance` category! And this is quite a fun one. I was curious to see how many violations this would find in the Regal codebase, if any. It did find a few, and good ones to fix! In order to keep it simple, this first implementation is perhaps a bit too cautious about what it considers deferrable. Check the implementation to see what exactly, but pretty much only assignments where the next line is a not an assignment, a potential loop, or something else that *might* make deferring the assignment undesirable. Fixes #1147 Signed-off-by: Anders Eknert <anders@styra.com>
- Loading branch information
1 parent
234e36b
commit 877372b
Showing
17 changed files
with
406 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
bundle/regal/rules/performance/defer-assignment/defer_assignment.rego
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
# METADATA | ||
# description: Assignment can be deferred | ||
package regal.rules.performance["defer-assignment"] | ||
|
||
import rego.v1 | ||
|
||
import data.regal.ast | ||
import data.regal.result | ||
|
||
report contains violation if { | ||
some i, rule in input.rules | ||
some j, expr in rule.body | ||
|
||
[var, rhs] := ast.assignment_terms(expr) | ||
|
||
not _ref_with_vars(rhs) | ||
|
||
# for now, only simple var assignment counts.. later we can | ||
# consider checking the contents of arrays here | ||
var.type == "var" | ||
|
||
next := rule.body[j + 1] | ||
|
||
not ast.is_assignment(next) | ||
not ast.var_in_head(rule.head, var.value) | ||
not _var_used_in_expression(var, next) | ||
not _iteration_expression(next) | ||
not _print_call(next) | ||
|
||
violation := result.fail(rego.metadata.chain(), result.location(expr)) | ||
} | ||
|
||
_ref_with_vars(node) if { | ||
node.type == "ref" | ||
|
||
some i, term in node.value | ||
|
||
i > 0 | ||
term.type == "var" | ||
} | ||
|
||
_var_used_in_expression(var, expr) if { | ||
not expr.terms.symbols | ||
|
||
is_array(expr.terms) | ||
|
||
some term in expr.terms | ||
|
||
walk(term, [_, value]) | ||
|
||
value.type == "var" | ||
value.value == var.value | ||
} | ||
|
||
_var_used_in_expression(var, expr) if { | ||
some w in expr["with"] | ||
|
||
w.value.type == "var" | ||
w.value.value == var.value | ||
} | ||
|
||
_var_used_in_expression(var, expr) if { | ||
# `not x` | ||
is_object(expr.terms) | ||
|
||
expr.terms.type == "var" | ||
expr.terms.value == var.value | ||
} else if { | ||
# `not x.y` | ||
is_object(expr.terms) | ||
|
||
some term in expr.terms.value | ||
|
||
walk(term, [_, value]) | ||
|
||
value.type == "var" | ||
value.value == var.value | ||
} | ||
|
||
# while not technically checking of use here: | ||
# the next expression having symbols indicate iteration, and | ||
# we don't want to defer assignment into a loop | ||
_iteration_expression(expr) if expr.terms.symbols | ||
|
||
# likewise with every | ||
_iteration_expression(expr) if expr.terms.domain | ||
|
||
# and walk | ||
_iteration_expression(expr) if { | ||
expr.terms[0].value[0].type == "var" | ||
expr.terms[0].value[0].value == "walk" | ||
} | ||
|
||
_print_call(expr) if { | ||
expr.terms[0].value[0].type == "var" | ||
expr.terms[0].value[0].value == "print" | ||
} |
Oops, something went wrong.