mirror of
https://gitea.invidious.io/iv-org/shard-ameba.git
synced 2024-08-15 00:53:29 +00:00
Merge pull request #430 from crystal-ameba/fix-issue-429
Report unused type declarations in `Lint/UselessAssign` rule
This commit is contained in:
commit
452a7a867e
6 changed files with 318 additions and 343 deletions
|
@ -1,8 +1,6 @@
|
||||||
require "../../../spec_helper"
|
require "../../../spec_helper"
|
||||||
|
|
||||||
module Ameba::AST
|
module Ameba::AST
|
||||||
source = Source.new ""
|
|
||||||
|
|
||||||
describe FlowExpressionVisitor do
|
describe FlowExpressionVisitor do
|
||||||
it "creates an expression for return" do
|
it "creates an expression for return" do
|
||||||
rule = FlowExpressionRule.new
|
rule = FlowExpressionRule.new
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -186,9 +186,19 @@ module Ameba::AST
|
||||||
node.is_a?(Crystal::Def)
|
node.is_a?(Crystal::Def)
|
||||||
end
|
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.
|
# Returns `true` if this scope is a top level scope, `false` otherwise.
|
||||||
def top_level?
|
def top_level?
|
||||||
outer_scope.nil? || type_definition?
|
outer_scope.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns `true` if var is an argument in current scope, `false` otherwise.
|
# Returns `true` if var is an argument in current scope, `false` otherwise.
|
||||||
|
|
|
@ -32,9 +32,7 @@ module Ameba::AST
|
||||||
return unless scope = @variable.scope
|
return unless scope = @variable.scope
|
||||||
|
|
||||||
@branch = Branch.of(@node, scope)
|
@branch = Branch.of(@node, scope)
|
||||||
@referenced = true if @variable.special? ||
|
@referenced = true if @variable.special? || referenced_in_loop?
|
||||||
@variable.scope.type_definition? ||
|
|
||||||
referenced_in_loop?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def referenced_in_loop?
|
def referenced_in_loop?
|
||||||
|
|
|
@ -170,22 +170,29 @@ module Ameba::AST
|
||||||
|
|
||||||
# :nodoc:
|
# :nodoc:
|
||||||
def visit(node : Crystal::Call)
|
def visit(node : Crystal::Call)
|
||||||
case
|
scope = @current_scope
|
||||||
when @current_scope.def?
|
|
||||||
if node.name.in?(SPECIAL_NODE_NAMES) && node.args.empty?
|
|
||||||
@current_scope.arguments.each do |arg|
|
|
||||||
variable = arg.variable
|
|
||||||
|
|
||||||
ref = variable.reference(variable.node, @current_scope)
|
case
|
||||||
ref.explicit = false
|
when scope.top_level? && record_macro?(node) then return false
|
||||||
end
|
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
|
end
|
||||||
true
|
|
||||||
when @current_scope.top_level? && record_macro?(node)
|
|
||||||
false
|
|
||||||
else
|
|
||||||
true
|
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
private def record_macro?(node)
|
private def record_macro?(node)
|
||||||
|
|
|
@ -24,10 +24,12 @@ module Ameba::Rule::Lint
|
||||||
# ```
|
# ```
|
||||||
# Lint/UselessAssign:
|
# Lint/UselessAssign:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
|
# ExcludeTypeDeclarations: false
|
||||||
# ```
|
# ```
|
||||||
class UselessAssign < Base
|
class UselessAssign < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows useless variable assignments"
|
description "Disallows useless variable assignments"
|
||||||
|
exclude_type_declarations false
|
||||||
end
|
end
|
||||||
|
|
||||||
MSG = "Useless assignment to variable `%s`"
|
MSG = "Useless assignment to variable `%s`"
|
||||||
|
@ -39,7 +41,7 @@ module Ameba::Rule::Lint
|
||||||
def test(source, node, scope : AST::Scope)
|
def test(source, node, scope : AST::Scope)
|
||||||
scope.variables.each do |var|
|
scope.variables.each do |var|
|
||||||
next if var.ignored? || var.used_in_macro? || var.captured_by_block?
|
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|
|
var.assignments.each do |assign|
|
||||||
next if assign.referenced?
|
next if assign.referenced?
|
||||||
|
|
Loading…
Reference in a new issue