Merge pull request #430 from crystal-ameba/fix-issue-429

Report unused type declarations in `Lint/UselessAssign` rule
This commit is contained in:
Sijawusz Pur Rahnama 2024-01-01 12:22:01 +01:00 committed by GitHub
commit 452a7a867e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 318 additions and 343 deletions

View file

@ -1,8 +1,6 @@
require "../../../spec_helper"
module Ameba::AST
source = Source.new ""
describe FlowExpressionVisitor do
it "creates an expression for return" do
rule = FlowExpressionRule.new

File diff suppressed because it is too large Load diff

View file

@ -186,9 +186,19 @@ module Ameba::AST
node.is_a?(Crystal::Def)
end
# Returns `true` if current scope is a class, `false` otherwise.
def class_def?
node.is_a?(Crystal::ClassDef)
end
# Returns `true` if current scope is a module, `false` otherwise.
def module_def?
node.is_a?(Crystal::ModuleDef)
end
# Returns `true` if this scope is a top level scope, `false` otherwise.
def top_level?
outer_scope.nil? || type_definition?
outer_scope.nil?
end
# Returns `true` if var is an argument in current scope, `false` otherwise.

View file

@ -32,9 +32,7 @@ module Ameba::AST
return unless scope = @variable.scope
@branch = Branch.of(@node, scope)
@referenced = true if @variable.special? ||
@variable.scope.type_definition? ||
referenced_in_loop?
@referenced = true if @variable.special? || referenced_in_loop?
end
def referenced_in_loop?

View file

@ -170,22 +170,29 @@ module Ameba::AST
# :nodoc:
def visit(node : Crystal::Call)
case
when @current_scope.def?
if node.name.in?(SPECIAL_NODE_NAMES) && node.args.empty?
@current_scope.arguments.each do |arg|
variable = arg.variable
scope = @current_scope
ref = variable.reference(variable.node, @current_scope)
ref.explicit = false
end
case
when scope.top_level? && record_macro?(node) then return false
when scope.type_definition? && record_macro?(node) then return false
when scope.type_definition? && accessor_macro?(node) then return false
when scope.def? && special_node?(node)
scope.arguments.each do |arg|
variable = arg.variable
ref = variable.reference(variable.node, scope)
ref.explicit = false
end
true
when @current_scope.top_level? && record_macro?(node)
false
else
true
end
true
end
private def special_node?(node)
node.name.in?(SPECIAL_NODE_NAMES) && node.args.empty?
end
private def accessor_macro?(node)
node.name.matches? /^(class_)?(getter[?!]?|setter|property[?!]?)$/
end
private def record_macro?(node)

View file

@ -24,10 +24,12 @@ module Ameba::Rule::Lint
# ```
# Lint/UselessAssign:
# Enabled: true
# ExcludeTypeDeclarations: false
# ```
class UselessAssign < Base
properties do
description "Disallows useless variable assignments"
exclude_type_declarations false
end
MSG = "Useless assignment to variable `%s`"
@ -39,7 +41,7 @@ module Ameba::Rule::Lint
def test(source, node, scope : AST::Scope)
scope.variables.each do |var|
next if var.ignored? || var.used_in_macro? || var.captured_by_block?
next if scope.assigns_type_dec?(var.name)
next if exclude_type_declarations? && scope.assigns_type_dec?(var.name)
var.assignments.each do |assign|
next if assign.referenced?