Lint/UselessAssign: ignore transformed assignemnts by the compiler

closes #127
This commit is contained in:
Vitalii Elenhaupt 2020-01-11 23:50:42 +02:00
parent 976f9729d5
commit 74dfa0b934
No known key found for this signature in database
GPG key ID: CD0BF17825928BC0
4 changed files with 82 additions and 1 deletions

View file

@ -87,5 +87,32 @@ module Ameba::AST
assignment.branch.should be_nil
end
end
describe "#transformed?" do
it "returns false if the assignment is not transformed by the compiler" do
nodes = as_nodes %(
def method(a)
a = 2
end
)
scope = Scope.new nodes.def_nodes.first
variable = Variable.new(nodes.var_nodes.first, scope)
assignment = Assignment.new(nodes.assign_nodes.first, variable)
assignment.transformed?.should be_false
end
it "returns true if the assignment is transformed by the compiler" do
nodes = as_nodes %(
array.each do |(a, b)|
end
)
scope = Scope.new nodes.block_nodes.first
variable = Variable.new(nodes.var_nodes.first, scope)
assignment = Assignment.new(nodes.assign_nodes.first, variable)
assignment.transformed?.should be_true
end
end
end
end

View file

@ -225,6 +225,34 @@ module Ameba::Rule::Lint
subject.catch(s).should be_valid
end
context "when transformed" do
it "does not report if the first arg is transformed and not used" do
s = Source.new %(
collection.each do |(a, b)|
puts b
end
)
subject.catch(s).should be_valid
end
it "does not report if the second arg is transformed and not used" do
s = Source.new %(
collection.each do |(a, b)|
puts a
end
)
subject.catch(s).should be_valid
end
it "does not report if all transformed args are not used in a block" do
s = Source.new %(
collection.each do |(foo, bar), (baz, _qux), index, object|
end
)
subject.catch(s).should be_valid
end
end
it "does not report if global var" do
s = Source.new %(
def method

View file

@ -74,5 +74,31 @@ module Ameba::AST
node
end
end
# Indicates whether the node is a transformed assignment by the compiler.
# i.e.
#
# ```
# collection.each do |(a, b)|
# puts b
# end
# ```
#
# is transformed to:
#
# ```
# collection.each do |__arg0|
# a = __arg0[0]
# b = __arg0[1]
# puts(b)
# end
# ```
#
def transformed?
return false unless (assign = node).is_a?(Crystal::Assign)
return false unless (value = assign.value).is_a?(Crystal::Call)
return false unless (obj = value.obj).is_a?(Crystal::Var)
obj.name.starts_with? "__arg"
end
end
end

View file

@ -42,7 +42,7 @@ module Ameba::Rule::Lint
next if var.captured_by_block? || var.used_in_macro?
var.assignments.each do |assign|
next if assign.referenced?
next if assign.referenced? || assign.transformed?
issue_for assign.target_node, MSG % var.name
end
end