mirror of
https://gitea.invidious.io/iv-org/shard-ameba.git
synced 2024-08-15 00:53:29 +00:00
Use NodeVisitor by default and remove the boilerplace code
This commit is contained in:
parent
1d827b4969
commit
1a0468c653
26 changed files with 6 additions and 101 deletions
|
@ -32,7 +32,12 @@ module Ameba::Rule
|
||||||
|
|
||||||
# This method is designed to test the source passed in. If source has issues
|
# This method is designed to test the source passed in. If source has issues
|
||||||
# that are tested by this rule, it should add an issue.
|
# that are tested by this rule, it should add an issue.
|
||||||
abstract def test(source : Source)
|
#
|
||||||
|
# Be default it uses a node visitor to traverse all the nodes in the source.
|
||||||
|
# Must be overriten for other type of rules.
|
||||||
|
def test(source : Source)
|
||||||
|
AST::NodeVisitor.new self, source
|
||||||
|
end
|
||||||
|
|
||||||
def test(source : Source, node : Crystal::ASTNode, *opts)
|
def test(source : Source, node : Crystal::ASTNode, *opts)
|
||||||
# can't be abstract
|
# can't be abstract
|
||||||
|
|
|
@ -28,10 +28,6 @@ module Ameba::Rule::Lint
|
||||||
|
|
||||||
MSG = "Comparison to a boolean is pointless"
|
MSG = "Comparison to a boolean is pointless"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Call)
|
def test(source, node : Crystal::Call)
|
||||||
comparison = %w(== != ===).includes?(node.name)
|
comparison = %w(== != ===).includes?(node.name)
|
||||||
to_boolean = node.args.first?.try &.is_a?(Crystal::BoolLiteral) ||
|
to_boolean = node.args.first?.try &.is_a?(Crystal::BoolLiteral) ||
|
||||||
|
|
|
@ -18,10 +18,6 @@ module Ameba::Rule::Lint
|
||||||
|
|
||||||
MSG = "Possible forgotten debugger statement detected"
|
MSG = "Possible forgotten debugger statement detected"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Call)
|
def test(source, node : Crystal::Call)
|
||||||
return unless node.name == "debugger" &&
|
return unless node.name == "debugger" &&
|
||||||
node.args.empty? &&
|
node.args.empty? &&
|
||||||
|
|
|
@ -46,10 +46,6 @@ module Ameba::Rule::Lint
|
||||||
|
|
||||||
MSG = "Empty `ensure` block detected"
|
MSG = "Empty `ensure` block detected"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::ExceptionHandler)
|
def test(source, node : Crystal::ExceptionHandler)
|
||||||
node_ensure = node.ensure
|
node_ensure = node.ensure
|
||||||
return if node_ensure.nil? || !node_ensure.nop?
|
return if node_ensure.nil? || !node_ensure.nop?
|
||||||
|
|
|
@ -38,10 +38,6 @@ module Ameba::Rule::Lint
|
||||||
MSG = "Avoid empty expression %s"
|
MSG = "Avoid empty expression %s"
|
||||||
MSG_EXRS = "Avoid empty expressions"
|
MSG_EXRS = "Avoid empty expressions"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::NilLiteral)
|
def test(source, node : Crystal::NilLiteral)
|
||||||
exp = node_source(node, source.lines).try &.join
|
exp = node_source(node, source.lines).try &.join
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,6 @@ module Ameba::Rule::Lint
|
||||||
|
|
||||||
MSG = "Duplicated keys in hash literal: %s"
|
MSG = "Duplicated keys in hash literal: %s"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::HashLiteral)
|
def test(source, node : Crystal::HashLiteral)
|
||||||
return unless (keys = duplicated_keys(node.entries)).any?
|
return unless (keys = duplicated_keys(node.entries)).any?
|
||||||
|
|
||||||
|
|
|
@ -30,10 +30,6 @@ module Ameba::Rule::Lint
|
||||||
|
|
||||||
MSG = "Literal value found in conditional"
|
MSG = "Literal value found in conditional"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_node(source, node)
|
def check_node(source, node)
|
||||||
return unless literal?(node.cond)
|
return unless literal?(node.cond)
|
||||||
issue_for node, MSG
|
issue_for node, MSG
|
||||||
|
|
|
@ -25,10 +25,6 @@ module Ameba::Rule::Lint
|
||||||
|
|
||||||
MSG = "Literal value found in interpolation"
|
MSG = "Literal value found in interpolation"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::StringInterpolation)
|
def test(source, node : Crystal::StringInterpolation)
|
||||||
found = node.expressions.any? { |e| !e.is_a?(Crystal::StringLiteral) && literal?(e) }
|
found = node.expressions.any? { |e| !e.is_a?(Crystal::StringLiteral) && literal?(e) }
|
||||||
return unless found
|
return unless found
|
||||||
|
|
|
@ -30,10 +30,6 @@ module Ameba::Rule::Lint
|
||||||
|
|
||||||
MSG = "%s always returns 0"
|
MSG = "%s always returns 0"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Call)
|
def test(source, node : Crystal::Call)
|
||||||
return unless node.name == "rand" &&
|
return unless node.name == "rand" &&
|
||||||
node.args.size == 1 &&
|
node.args.size == 1 &&
|
||||||
|
|
|
@ -32,10 +32,6 @@ module Ameba::Rule::Lint
|
||||||
description "Disallows redundant `with_index` calls"
|
description "Disallows redundant `with_index` calls"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Call)
|
def test(source, node : Crystal::Call)
|
||||||
args, block = node.args, node.block
|
args, block = node.args, node.block
|
||||||
|
|
||||||
|
|
|
@ -33,10 +33,6 @@ module Ameba::Rule::Lint
|
||||||
description "Disallows redundant `with_object` calls"
|
description "Disallows redundant `with_object` calls"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Call)
|
def test(source, node : Crystal::Call)
|
||||||
return if node.name != "each_with_object" ||
|
return if node.name != "each_with_object" ||
|
||||||
node.args.size != 1 ||
|
node.args.size != 1 ||
|
||||||
|
|
|
@ -41,10 +41,6 @@ module Ameba::Rule::Lint
|
||||||
|
|
||||||
MSG = "Exception handler has shadowed exceptions: %s"
|
MSG = "Exception handler has shadowed exceptions: %s"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::ExceptionHandler)
|
def test(source, node : Crystal::ExceptionHandler)
|
||||||
return unless excs = node.rescues
|
return unless excs = node.rescues
|
||||||
|
|
||||||
|
|
|
@ -51,10 +51,6 @@ module Ameba::Rule::Lint
|
||||||
issue_for cond, MSG
|
issue_for cond, MSG
|
||||||
end
|
end
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::When)
|
def test(source, node : Crystal::When)
|
||||||
ConditionInWhenVisitor.new self, source, node
|
ConditionInWhenVisitor.new self, source, node
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,10 +17,6 @@ module Ameba::Rule::Metrics
|
||||||
|
|
||||||
MSG = "Cyclomatic complexity too high [%d/%d]"
|
MSG = "Cyclomatic complexity too high [%d/%d]"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Def)
|
def test(source, node : Crystal::Def)
|
||||||
complexity = AST::CountingVisitor.new(node).count
|
complexity = AST::CountingVisitor.new(node).count
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,6 @@ module Ameba::Rule::Performance
|
||||||
description "Identifies usage of `any?` calls that follow filters."
|
description "Identifies usage of `any?` calls that follow filters."
|
||||||
end
|
end
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Call)
|
def test(source, node : Crystal::Call)
|
||||||
return unless node.name == ANY_NAME && (obj = node.obj)
|
return unless node.name == ANY_NAME && (obj = node.obj)
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,6 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
MSG = "Constant name should be screaming-cased: %s, not %s"
|
MSG = "Constant name should be screaming-cased: %s, not %s"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Assign)
|
def test(source, node : Crystal::Assign)
|
||||||
if (target = node.target).is_a? Crystal::Path
|
if (target = node.target).is_a? Crystal::Path
|
||||||
name = target.names.first
|
name = target.names.first
|
||||||
|
|
|
@ -45,10 +45,6 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
MSG = "Method name should be underscore-cased: %s, not %s"
|
MSG = "Method name should be underscore-cased: %s, not %s"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Def)
|
def test(source, node : Crystal::Def)
|
||||||
return if (expected = node.name.underscore) == node.name
|
return if (expected = node.name.underscore) == node.name
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,6 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
MSG = "Avoid negated conditions in unless blocks"
|
MSG = "Avoid negated conditions in unless blocks"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Unless)
|
def test(source, node : Crystal::Unless)
|
||||||
return unless negated_condition? node.cond
|
return unless negated_condition? node.cond
|
||||||
issue_for node, MSG
|
issue_for node, MSG
|
||||||
|
|
|
@ -37,10 +37,6 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
MSG = "Favour method name '%s?' over '%s'"
|
MSG = "Favour method name '%s?' over '%s'"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Def)
|
def test(source, node : Crystal::Def)
|
||||||
if node.name =~ /^(is|has)_(\w+)\?/
|
if node.name =~ /^(is|has)_(\w+)\?/
|
||||||
alternative = $2
|
alternative = $2
|
||||||
|
|
|
@ -64,10 +64,6 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
MSG = "Redundant `begin` block detected"
|
MSG = "Redundant `begin` block detected"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Def)
|
def test(source, node : Crystal::Def)
|
||||||
return unless redundant_begin?(source, node)
|
return unless redundant_begin?(source, node)
|
||||||
|
|
||||||
|
|
|
@ -105,10 +105,6 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
MSG = "Redundant `next` detected"
|
MSG = "Redundant `next` detected"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Block)
|
def test(source, node : Crystal::Block)
|
||||||
AST::RedundantControlExpressionVisitor.new(self, source, node.body)
|
AST::RedundantControlExpressionVisitor.new(self, source, node.body)
|
||||||
end
|
end
|
||||||
|
|
|
@ -102,10 +102,6 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
MSG = "Redundant `return` detected"
|
MSG = "Redundant `return` detected"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Def)
|
def test(source, node : Crystal::Def)
|
||||||
AST::RedundantControlExpressionVisitor.new(self, source, node.body)
|
AST::RedundantControlExpressionVisitor.new(self, source, node.body)
|
||||||
end
|
end
|
||||||
|
|
|
@ -59,10 +59,6 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
MSG = "Type name should be camelcased: %s, but it was %s"
|
MSG = "Type name should be camelcased: %s, but it was %s"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
private def check_node(source, node)
|
private def check_node(source, node)
|
||||||
name = node.name.to_s
|
name = node.name.to_s
|
||||||
expected = name.camelcase
|
expected = name.camelcase
|
||||||
|
|
|
@ -50,10 +50,6 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
MSG = "Favour if over unless with else"
|
MSG = "Favour if over unless with else"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::Unless)
|
def test(source, node : Crystal::Unless)
|
||||||
return if node.else.nop?
|
return if node.else.nop?
|
||||||
issue_for node, MSG
|
issue_for node, MSG
|
||||||
|
|
|
@ -30,10 +30,6 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
MSG = "Var name should be underscore-cased: %s, not %s"
|
MSG = "Var name should be underscore-cased: %s, not %s"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
private def check_node(source, node)
|
private def check_node(source, node)
|
||||||
return if (expected = node.name.underscore) == node.name
|
return if (expected = node.name.underscore) == node.name
|
||||||
|
|
||||||
|
|
|
@ -33,10 +33,6 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
MSG = "While statement using true literal as condition"
|
MSG = "While statement using true literal as condition"
|
||||||
|
|
||||||
def test(source)
|
|
||||||
AST::NodeVisitor.new self, source
|
|
||||||
end
|
|
||||||
|
|
||||||
def test(source, node : Crystal::While)
|
def test(source, node : Crystal::While)
|
||||||
return unless node.cond.true_literal?
|
return unless node.cond.true_literal?
|
||||||
issue_for node, MSG
|
issue_for node, MSG
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue