mirror of
https://gitea.invidious.io/iv-org/shard-ameba.git
synced 2024-08-15 00:53:29 +00:00
Variable scope & useless assignments (#41)
* AST::Visitor -> AST::NodeVisitor * Scope & ScopeVisitor * Useless assignment rule * Instance vars and useless assignments * Multiple assigns one by one * Support outer scope * Variable used in the useless assignment * Support OpAssign & MultiAssign * Captured by block * Variable, Assignment, Reference & Refactoring * Variable has references, Assignment can be referenced * Branch entity * Handle useless assignments in branches * Handle assignments in a loop * Handle branch equality * Handle special var `$?` assignment * Improve captured by block stuff * Avoid assignments in property definitions (UselessAssign rule reports an warning) * Support MacroIf and MacroFor branches * Handle assignments with shadowed vars in inner scopes * Add method arguments as scope variables * Handle case if branch is blank * Top level scope * Handle case when branch is nop?
This commit is contained in:
parent
60c1b86890
commit
6475c2bb25
50 changed files with 2521 additions and 124 deletions
18
spec/ameba/ast/visitors/node_visitor_spec.cr
Normal file
18
spec/ameba/ast/visitors/node_visitor_spec.cr
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
require "../../../spec_helper"
|
||||
|
||||
module Ameba::AST
|
||||
rule = DummyRule.new
|
||||
source = Source.new ""
|
||||
|
||||
describe NodeVisitor do
|
||||
{% for name in NODES %}
|
||||
describe "{{name}}" do
|
||||
it "allow to visit {{name}} node" do
|
||||
visitor = NodeVisitor.new rule, source
|
||||
nodes = Crystal::Parser.new("").parse
|
||||
nodes.accept visitor
|
||||
end
|
||||
end
|
||||
{% end %}
|
||||
end
|
||||
end
|
||||
58
spec/ameba/ast/visitors/scope_visitor_spec.cr
Normal file
58
spec/ameba/ast/visitors/scope_visitor_spec.cr
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
require "../../../spec_helper"
|
||||
|
||||
module Ameba::AST
|
||||
describe ScopeVisitor do
|
||||
it "creates a scope for the def" do
|
||||
rule = ScopeRule.new
|
||||
ScopeVisitor.new rule, Source.new %(
|
||||
def method
|
||||
end
|
||||
)
|
||||
rule.scopes.size.should eq 1
|
||||
end
|
||||
|
||||
it "creates a scope for the proc" do
|
||||
rule = ScopeRule.new
|
||||
ScopeVisitor.new rule, Source.new %(
|
||||
-> {}
|
||||
)
|
||||
rule.scopes.size.should eq 1
|
||||
end
|
||||
|
||||
it "creates a scope for the block" do
|
||||
rule = ScopeRule.new
|
||||
ScopeVisitor.new rule, Source.new %(
|
||||
3.times {}
|
||||
)
|
||||
rule.scopes.size.should eq 2
|
||||
end
|
||||
|
||||
context "inner scopes" do
|
||||
it "creates scope for block inside def" do
|
||||
rule = ScopeRule.new
|
||||
ScopeVisitor.new rule, Source.new %(
|
||||
def method
|
||||
3.times {}
|
||||
end
|
||||
)
|
||||
rule.scopes.size.should eq 2
|
||||
rule.scopes.last.outer_scope.should_not be_nil
|
||||
rule.scopes.first.outer_scope.should eq rule.scopes.last
|
||||
end
|
||||
|
||||
it "creates scope for block inside block" do
|
||||
rule = ScopeRule.new
|
||||
ScopeVisitor.new rule, Source.new %(
|
||||
3.times do
|
||||
2.times {}
|
||||
end
|
||||
)
|
||||
rule.scopes.size.should eq 3
|
||||
inner_block = rule.scopes.first
|
||||
outer_block = rule.scopes.last
|
||||
inner_block.outer_scope.should_not eq outer_block
|
||||
outer_block.outer_scope.should be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue