Incorrectly reporting shadowingOuterLocalVar within macro included

closes #161
This commit is contained in:
Vitalii Elenhaupt 2020-07-15 10:18:12 +03:00
parent 7f501a1df5
commit d650ca5477
No known key found for this signature in database
GPG key ID: CD0BF17825928BC0
4 changed files with 41 additions and 7 deletions

View file

@ -114,19 +114,30 @@ module Ameba::AST
end end
end end
describe "#macro?" do describe "#in_macro?" do
it "returns true if Crystal::Macro" do it "returns true if Crystal::Macro" do
nodes = as_nodes %( nodes = as_nodes %(
macro included macro included
end end
) )
scope = Scope.new nodes.macro_nodes.first scope = Scope.new nodes.macro_nodes.first
scope.macro?.should be_true scope.in_macro?.should be_true
end
it "returns true if node is nested to Crystal::Macro" do
nodes = as_nodes %(
macro included
{{@type.each do |type| a = type end}}
end
)
outer_scope = Scope.new nodes.macro_nodes.first
scope = Scope.new nodes.block_nodes.first, outer_scope
scope.in_macro?.should be_true
end end
it "returns false otherwise" do it "returns false otherwise" do
scope = Scope.new as_node "a = 1" scope = Scope.new as_node "a = 1"
scope.macro?.should be_false scope.in_macro?.should be_false
end end
end end
end end

View file

@ -213,6 +213,29 @@ module Ameba::Rule::Lint
) )
subject.catch(source).should be_valid subject.catch(source).should be_valid
end end
it "does not report shadowed vars withing nested macro" do
source = Source.new %(
module Foo
macro included
def foo
{% for ann in instance_vars %}
{% pos_args = ann.args.empty? ? "Tuple.new".id : ann.args %}
{% end %}
end
def bar
{{@type.instance_vars.map do |ivar|
ivar.annotations(Name).each do |ann|
puts ann.args
end
end}}
end
end
end
)
subject.catch(source).should be_valid
end
end end
end end
end end

View file

@ -110,9 +110,9 @@ module Ameba::AST
call.try(&.name) == "spawn" call.try(&.name) == "spawn"
end end
# Returns true if current scope represents a macro. # Returns true if current scope sits inside a macro.
def macro? def in_macro?
node.is_a?(Crystal::Macro) node.is_a?(Crystal::Macro) || !!outer_scope.try(&.in_macro?)
end end
# Returns true instance variable assinged in this scope. # Returns true instance variable assinged in this scope.

View file

@ -54,7 +54,7 @@ module Ameba::Rule::Lint
private def find_shadowing(source, scope) private def find_shadowing(source, scope)
outer_scope = scope.outer_scope outer_scope = scope.outer_scope
return if outer_scope.nil? || outer_scope.macro? return if outer_scope.nil? || outer_scope.in_macro?
scope.arguments.reject(&.ignored?).each do |arg| scope.arguments.reject(&.ignored?).each do |arg|
variable = outer_scope.find_variable(arg.name) variable = outer_scope.find_variable(arg.name)