mirror of
https://gitea.invidious.io/iv-org/shard-ameba.git
synced 2024-08-15 00:53:29 +00:00
Optimize rules (#185)
* Replace pointless interpolations with actual values * Rules optimizations * Stylistic refactors * Remove extraneous blank lines * Remove some instances of .not_nil! usage
This commit is contained in:
parent
270a003df6
commit
1a091c1f1a
43 changed files with 57 additions and 98 deletions
|
@ -77,7 +77,7 @@ module Ameba::Rule::Lint
|
||||||
issue.rule.should_not be_nil
|
issue.rule.should_not be_nil
|
||||||
issue.location.to_s.should eq "source.cr:2:14"
|
issue.location.to_s.should eq "source.cr:2:14"
|
||||||
issue.end_location.to_s.should eq "source.cr:2:30"
|
issue.end_location.to_s.should eq "source.cr:2:30"
|
||||||
issue.message.should eq "Use each instead of each_with_object"
|
issue.message.should eq "Use `each` instead of `each_with_object`"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,8 +8,13 @@ module Ameba::Cli
|
||||||
def run(args = ARGV)
|
def run(args = ARGV)
|
||||||
opts = parse_args args
|
opts = parse_args args
|
||||||
config = Config.load opts.config, opts.colors?
|
config = Config.load opts.config, opts.colors?
|
||||||
config.globs = opts.globs.not_nil! if opts.globs
|
|
||||||
config.severity = opts.fail_level.not_nil! if opts.fail_level
|
if globs = opts.globs
|
||||||
|
config.globs = globs
|
||||||
|
end
|
||||||
|
if fail_level = opts.fail_level
|
||||||
|
config.severity = fail_level
|
||||||
|
end
|
||||||
|
|
||||||
configure_formatter(config, opts)
|
configure_formatter(config, opts)
|
||||||
configure_rules(config, opts)
|
configure_rules(config, opts)
|
||||||
|
|
|
@ -8,7 +8,6 @@ module Ameba::Rule::Layout
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# MaxLength: 100
|
# MaxLength: 100
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct LineLength < Base
|
struct LineLength < Base
|
||||||
properties do
|
properties do
|
||||||
enabled false
|
enabled false
|
||||||
|
@ -20,9 +19,7 @@ module Ameba::Rule::Layout
|
||||||
|
|
||||||
def test(source)
|
def test(source)
|
||||||
source.lines.each_with_index do |line, index|
|
source.lines.each_with_index do |line, index|
|
||||||
next unless line.size > max_length
|
issue_for({index + 1, max_length + 1}, MSG) if line.size > max_length
|
||||||
|
|
||||||
issue_for({index + 1, max_length + 1}, MSG)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,6 @@ module Ameba::Rule::Layout
|
||||||
# Layout/TrailingBlankLines:
|
# Layout/TrailingBlankLines:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct TrailingBlankLines < Base
|
struct TrailingBlankLines < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows trailing blank lines"
|
description "Disallows trailing blank lines"
|
||||||
|
|
|
@ -7,7 +7,6 @@ module Ameba::Rule::Layout
|
||||||
# Layout/TrailingWhitespace:
|
# Layout/TrailingWhitespace:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct TrailingWhitespace < Base
|
struct TrailingWhitespace < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows trailing whitespaces"
|
description "Disallows trailing whitespaces"
|
||||||
|
@ -17,8 +16,7 @@ module Ameba::Rule::Layout
|
||||||
|
|
||||||
def test(source)
|
def test(source)
|
||||||
source.lines.each_with_index do |line, index|
|
source.lines.each_with_index do |line, index|
|
||||||
next unless line =~ /\s$/
|
issue_for({index + 1, line.size}, MSG) if line =~ /\s$/
|
||||||
issue_for({index + 1, line.size}, MSG)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,7 +17,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/BadDirective:
|
# Lint/BadDirective:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct BadDirective < Base
|
struct BadDirective < Base
|
||||||
properties do
|
properties do
|
||||||
description "Reports bad comment directives"
|
description "Reports bad comment directives"
|
||||||
|
@ -48,7 +47,9 @@ module Ameba::Rule::Lint
|
||||||
|
|
||||||
private def check_rules(source, token, rules)
|
private def check_rules(source, token, rules)
|
||||||
bad_names = rules - ALL_RULE_NAMES - ALL_GROUP_NAMES
|
bad_names = rules - ALL_RULE_NAMES - ALL_GROUP_NAMES
|
||||||
issue_for token, "Such rules do not exist: %s" % bad_names.join(", ") unless bad_names.empty?
|
return if bad_names.empty?
|
||||||
|
|
||||||
|
issue_for token, "Such rules do not exist: %s" % bad_names.join(", ")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,7 +19,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/ComparisonToBoolean:
|
# Lint/ComparisonToBoolean:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct ComparisonToBoolean < Base
|
struct ComparisonToBoolean < Base
|
||||||
properties do
|
properties do
|
||||||
enabled false
|
enabled false
|
||||||
|
@ -33,9 +32,7 @@ module Ameba::Rule::Lint
|
||||||
to_boolean = node.args.first?.try &.is_a?(Crystal::BoolLiteral) ||
|
to_boolean = node.args.first?.try &.is_a?(Crystal::BoolLiteral) ||
|
||||||
node.obj.is_a?(Crystal::BoolLiteral)
|
node.obj.is_a?(Crystal::BoolLiteral)
|
||||||
|
|
||||||
return unless comparison && to_boolean
|
issue_for node, MSG if comparison && to_boolean
|
||||||
|
|
||||||
issue_for node, MSG
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,7 +10,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/DebuggerStatement:
|
# Lint/DebuggerStatement:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct DebuggerStatement < Base
|
struct DebuggerStatement < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows calls to debugger"
|
description "Disallows calls to debugger"
|
||||||
|
|
|
@ -38,7 +38,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/EmptyEnsure
|
# Lint/EmptyEnsure
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct EmptyEnsure < Base
|
struct EmptyEnsure < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows empty ensure statement"
|
description "Disallows empty ensure statement"
|
||||||
|
|
|
@ -27,7 +27,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/EmptyExpression:
|
# Lint/EmptyExpression:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct EmptyExpression < Base
|
struct EmptyExpression < Base
|
||||||
include AST::Util
|
include AST::Util
|
||||||
|
|
||||||
|
@ -41,8 +40,7 @@ module Ameba::Rule::Lint
|
||||||
|
|
||||||
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
|
||||||
|
return if exp.in?(nil, "nil")
|
||||||
return if exp.nil? || exp == "nil"
|
|
||||||
|
|
||||||
issue_for node, MSG % exp
|
issue_for node, MSG % exp
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,7 +19,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/HashDuplicatedKey:
|
# Lint/HashDuplicatedKey:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct HashDuplicatedKey < Base
|
struct HashDuplicatedKey < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows duplicated keys in hash literals"
|
description "Disallows duplicated keys in hash literals"
|
||||||
|
@ -28,7 +27,7 @@ module Ameba::Rule::Lint
|
||||||
MSG = "Duplicated keys in hash literal: %s"
|
MSG = "Duplicated keys in hash literal: %s"
|
||||||
|
|
||||||
def test(source, node : Crystal::HashLiteral)
|
def test(source, node : Crystal::HashLiteral)
|
||||||
return unless (keys = duplicated_keys(node.entries)).any?
|
return if (keys = duplicated_keys(node.entries)).empty?
|
||||||
|
|
||||||
issue_for node, MSG % keys.join(", ")
|
issue_for node, MSG % keys.join(", ")
|
||||||
end
|
end
|
||||||
|
@ -36,7 +35,7 @@ module Ameba::Rule::Lint
|
||||||
private def duplicated_keys(entries)
|
private def duplicated_keys(entries)
|
||||||
entries.map(&.key)
|
entries.map(&.key)
|
||||||
.group_by(&.itself)
|
.group_by(&.itself)
|
||||||
.select { |_, v| v.size > 1 }
|
.tap(&.select! { |_, v| v.size > 1 })
|
||||||
.map { |k, _| k }
|
.map { |k, _| k }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,7 +19,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/LiteralInCondition:
|
# Lint/LiteralInCondition:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct LiteralInCondition < Base
|
struct LiteralInCondition < Base
|
||||||
include AST::Util
|
include AST::Util
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/LiteralInInterpolation
|
# Lint/LiteralInInterpolation
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct LiteralInInterpolation < Base
|
struct LiteralInInterpolation < Base
|
||||||
include AST::Util
|
include AST::Util
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ module Ameba::Rule::Lint
|
||||||
# StringArrayUnwantedSymbols: ',"'
|
# StringArrayUnwantedSymbols: ',"'
|
||||||
# SymbolArrayUnwantedSymbols: ',:'
|
# SymbolArrayUnwantedSymbols: ',:'
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct PercentArrays < Base
|
struct PercentArrays < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows some unwanted symbols in percent array literals"
|
description "Disallows some unwanted symbols in percent array literals"
|
||||||
|
|
|
@ -22,7 +22,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/RandZero:
|
# Lint/RandZero:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct RandZero < Base
|
struct RandZero < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows rand zero calls"
|
description "Disallows rand zero calls"
|
||||||
|
@ -36,7 +35,7 @@ module Ameba::Rule::Lint
|
||||||
(arg = node.args.first) &&
|
(arg = node.args.first) &&
|
||||||
(arg.is_a? Crystal::NumberLiteral) &&
|
(arg.is_a? Crystal::NumberLiteral) &&
|
||||||
(value = arg.value) &&
|
(value = arg.value) &&
|
||||||
(value == "0" || value == "1")
|
value.in?("0", "1")
|
||||||
|
|
||||||
issue_for node, MSG % node
|
issue_for node, MSG % node
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,7 +20,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/RedundantStringCoersion
|
# Lint/RedundantStringCoersion
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct RedundantStringCoercion < Base
|
struct RedundantStringCoercion < Base
|
||||||
include AST::Util
|
include AST::Util
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/RedundantWithIndex:
|
# Lint/RedundantWithIndex:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct RedundantWithIndex < Base
|
struct RedundantWithIndex < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows redundant `with_index` calls"
|
description "Disallows redundant `with_index` calls"
|
||||||
|
@ -35,7 +34,8 @@ module Ameba::Rule::Lint
|
||||||
def test(source, node : Crystal::Call)
|
def test(source, node : Crystal::Call)
|
||||||
args, block = node.args, node.block
|
args, block = node.args, node.block
|
||||||
|
|
||||||
return if args.size > 1 || block.nil? || with_index_arg?(block.not_nil!)
|
return if block.nil? || args.size > 1
|
||||||
|
return if with_index_arg?(block)
|
||||||
|
|
||||||
case node.name
|
case node.name
|
||||||
when "with_index"
|
when "with_index"
|
||||||
|
|
|
@ -27,21 +27,20 @@ module Ameba::Rule::Lint
|
||||||
# Lint/RedundantWithObject:
|
# Lint/RedundantWithObject:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct RedundantWithObject < Base
|
struct RedundantWithObject < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows redundant `with_object` calls"
|
description "Disallows redundant `with_object` calls"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
MSG = "Use `each` instead of `each_with_object`"
|
||||||
|
|
||||||
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 ||
|
||||||
node.block.nil? ||
|
node.block.nil? ||
|
||||||
with_index_arg?(node.block.not_nil!)
|
with_index_arg?(node.block.not_nil!)
|
||||||
|
|
||||||
issue_for node.name_location,
|
issue_for node.name_location, node.name_end_location, MSG
|
||||||
node.name_end_location,
|
|
||||||
"Use each instead of each_with_object"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private def with_index_arg?(block : Crystal::Block)
|
private def with_index_arg?(block : Crystal::Block)
|
||||||
|
|
|
@ -35,7 +35,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/ShadowedArgument:
|
# Lint/ShadowedArgument:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct ShadowedArgument < Base
|
struct ShadowedArgument < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows shadowed arguments"
|
description "Disallows shadowed arguments"
|
||||||
|
|
|
@ -33,7 +33,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/ShadowedException:
|
# Lint/ShadowedException:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct ShadowedException < Base
|
struct ShadowedException < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows rescued exception that get shadowed"
|
description "Disallows rescued exception that get shadowed"
|
||||||
|
|
|
@ -30,7 +30,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/ShadowingOuterLocalVar:
|
# Lint/ShadowingOuterLocalVar:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct ShadowingOuterLocalVar < Base
|
struct ShadowingOuterLocalVar < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows the usage of the same name as outer local variables" \
|
description "Disallows the usage of the same name as outer local variables" \
|
||||||
|
|
|
@ -49,7 +49,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/SharedVarInFiber:
|
# Lint/SharedVarInFiber:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct SharedVarInFiber < Base
|
struct SharedVarInFiber < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows shared variables in fibers."
|
description "Disallows shared variables in fibers."
|
||||||
|
@ -77,7 +76,7 @@ module Ameba::Rule::Lint
|
||||||
declared_in = variable.assignments.first?.try &.branch
|
declared_in = variable.assignments.first?.try &.branch
|
||||||
|
|
||||||
variable.assignments
|
variable.assignments
|
||||||
.reject { |assign| assign.scope.spawn_block? }
|
.reject(&.scope.spawn_block?)
|
||||||
.any? do |assign|
|
.any? do |assign|
|
||||||
assign.branch.try(&.in_loop?) && assign.branch != declared_in
|
assign.branch.try(&.in_loop?) && assign.branch != declared_in
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,7 +18,6 @@ module Ameba::Rule::Lint
|
||||||
# rescue e : Exception
|
# rescue e : Exception
|
||||||
# end
|
# end
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct Syntax < Base
|
struct Syntax < Base
|
||||||
properties do
|
properties do
|
||||||
description "Reports invalid Crystal syntax"
|
description "Reports invalid Crystal syntax"
|
||||||
|
|
|
@ -24,7 +24,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/UnneededDisableDirective
|
# Lint/UnneededDisableDirective
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct UnneededDisableDirective < Base
|
struct UnneededDisableDirective < Base
|
||||||
properties do
|
properties do
|
||||||
description "Reports unneeded disable directives in comments"
|
description "Reports unneeded disable directives in comments"
|
||||||
|
@ -47,11 +46,12 @@ module Ameba::Rule::Lint
|
||||||
return unless directive[:action] == "disable"
|
return unless directive[:action] == "disable"
|
||||||
|
|
||||||
directive[:rules].reject do |rule_name|
|
directive[:rules].reject do |rule_name|
|
||||||
|
next if rule_name == self.name
|
||||||
source.issues.any? do |issue|
|
source.issues.any? do |issue|
|
||||||
issue.rule.name == rule_name &&
|
issue.rule.name == rule_name &&
|
||||||
issue.disabled? &&
|
issue.disabled? &&
|
||||||
issue_at_location?(source, issue, location)
|
issue_at_location?(source, issue, location)
|
||||||
end && rule_name != self.name
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/UnreachableCode:
|
# Lint/UnreachableCode:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct UnreachableCode < Base
|
struct UnreachableCode < Base
|
||||||
include AST::Util
|
include AST::Util
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ module Ameba::Rule::Lint
|
||||||
# IgnoreBlocks: false
|
# IgnoreBlocks: false
|
||||||
# IgnoreProcs: false
|
# IgnoreProcs: false
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct UnusedArgument < Base
|
struct UnusedArgument < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows unused arguments"
|
description "Disallows unused arguments"
|
||||||
|
|
|
@ -25,7 +25,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/UselessAssign:
|
# Lint/UselessAssign:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct UselessAssign < Base
|
struct UselessAssign < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows useless variable assignments"
|
description "Disallows useless variable assignments"
|
||||||
|
|
|
@ -30,7 +30,6 @@ module Ameba::Rule::Lint
|
||||||
# Lint/UselessConditionInWhen:
|
# Lint/UselessConditionInWhen:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct UselessConditionInWhen < Base
|
struct UselessConditionInWhen < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows useless conditions in when"
|
description "Disallows useless conditions in when"
|
||||||
|
@ -43,10 +42,7 @@ module Ameba::Rule::Lint
|
||||||
# simple implementation in future.
|
# simple implementation in future.
|
||||||
protected def check_node(source, when_node, cond)
|
protected def check_node(source, when_node, cond)
|
||||||
cond_s = cond.to_s
|
cond_s = cond.to_s
|
||||||
return if when_node
|
return if when_node.conds.none?(&.to_s.==(cond_s))
|
||||||
.conds
|
|
||||||
.map(&.to_s)
|
|
||||||
.none? { |c| c == cond_s }
|
|
||||||
|
|
||||||
issue_for cond, MSG
|
issue_for cond, MSG
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,6 @@ module Ameba::Rule::Metrics
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# MaxComplexity: 10
|
# MaxComplexity: 10
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct CyclomaticComplexity < Base
|
struct CyclomaticComplexity < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows methods with a cyclomatic complexity higher than `MaxComplexity`"
|
description "Disallows methods with a cyclomatic complexity higher than `MaxComplexity`"
|
||||||
|
@ -21,17 +20,18 @@ module Ameba::Rule::Metrics
|
||||||
complexity = AST::CountingVisitor.new(node).count
|
complexity = AST::CountingVisitor.new(node).count
|
||||||
|
|
||||||
if complexity > max_complexity && (location = node.name_location)
|
if complexity > max_complexity && (location = node.name_location)
|
||||||
issue_for(
|
issue_for location, def_name_end_location(node), MSG % {
|
||||||
location,
|
complexity, max_complexity,
|
||||||
def_name_end_location(node),
|
}
|
||||||
MSG % {complexity, max_complexity}
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private def def_name_end_location(node)
|
private def def_name_end_location(node)
|
||||||
return unless location = node.name_location
|
return unless location = node.name_location
|
||||||
line_number, column_number = location.line_number, location.column_number
|
|
||||||
|
line_number, column_number =
|
||||||
|
location.line_number, location.column_number
|
||||||
|
|
||||||
Crystal::Location.new(location.filename, line_number, column_number + node.name.size)
|
Crystal::Location.new(location.filename, line_number, column_number + node.name.size)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,10 +24,9 @@ module Ameba::Rule::Performance
|
||||||
# - select
|
# - select
|
||||||
# - reject
|
# - reject
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct AnyAfterFilter < Base
|
struct AnyAfterFilter < Base
|
||||||
ANY_NAME = "any?"
|
ANY_NAME = "any?"
|
||||||
MSG = "Use `#{ANY_NAME} {...}` instead of `%s {...}.#{ANY_NAME}`"
|
MSG = "Use `any? {...}` instead of `%s {...}.any?`"
|
||||||
|
|
||||||
properties do
|
properties do
|
||||||
filter_names : Array(String) = %w(select reject)
|
filter_names : Array(String) = %w(select reject)
|
||||||
|
@ -36,9 +35,10 @@ module Ameba::Rule::Performance
|
||||||
|
|
||||||
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)
|
||||||
|
return unless obj.is_a?(Crystal::Call)
|
||||||
|
return if obj.block.nil? || !node.block.nil?
|
||||||
|
|
||||||
if node.block.nil? && obj.is_a?(Crystal::Call) &&
|
if filter_names.includes?(obj.name)
|
||||||
filter_names.includes?(obj.name) && !obj.block.nil?
|
|
||||||
issue_for obj.name_location, node.name_end_location, MSG % obj.name
|
issue_for obj.name_location, node.name_end_location, MSG % obj.name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,7 +23,6 @@ module Ameba::Rule::Performance
|
||||||
# FilterNames:
|
# FilterNames:
|
||||||
# - select
|
# - select
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct FirstLastAfterFilter < Base
|
struct FirstLastAfterFilter < Base
|
||||||
CALL_NAMES = %w(first last first? last?)
|
CALL_NAMES = %w(first last first? last?)
|
||||||
MSG = "Use `find {...}` instead of `%s {...}.%s`"
|
MSG = "Use `find {...}` instead of `%s {...}.%s`"
|
||||||
|
@ -45,10 +44,10 @@ module Ameba::Rule::Performance
|
||||||
|
|
||||||
def test(source, node : Crystal::Call)
|
def test(source, node : Crystal::Call)
|
||||||
return unless CALL_NAMES.includes?(node.name) && (obj = node.obj)
|
return unless CALL_NAMES.includes?(node.name) && (obj = node.obj)
|
||||||
return if node.args.any?
|
return unless obj.is_a?(Crystal::Call)
|
||||||
|
return if obj.block.nil? || !node.block.nil? || node.args.any?
|
||||||
|
|
||||||
if node.block.nil? && obj.is_a?(Crystal::Call) &&
|
if filter_names.includes?(obj.name)
|
||||||
filter_names.includes?(obj.name) && !obj.block.nil?
|
|
||||||
message = node.name.includes?(CALL_NAMES.first) ? MSG : MSG_REVERSE
|
message = node.name.includes?(CALL_NAMES.first) ? MSG : MSG_REVERSE
|
||||||
issue_for obj.name_location, node.name_end_location, message % {obj.name, node.name}
|
issue_for obj.name_location, node.name_end_location, message % {obj.name, node.name}
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,10 +30,9 @@ module Ameba::Rule::Performance
|
||||||
# - select
|
# - select
|
||||||
# - reject
|
# - reject
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct SizeAfterFilter < Base
|
struct SizeAfterFilter < Base
|
||||||
SIZE_NAME = "size"
|
SIZE_NAME = "size"
|
||||||
MSG = "Use `count {...}` instead of `%s {...}.#{SIZE_NAME}`."
|
MSG = "Use `count {...}` instead of `%s {...}.size`."
|
||||||
|
|
||||||
properties do
|
properties do
|
||||||
filter_names : Array(String) = %w(select reject)
|
filter_names : Array(String) = %w(select reject)
|
||||||
|
@ -51,9 +50,10 @@ module Ameba::Rule::Performance
|
||||||
|
|
||||||
def test(source, node : Crystal::Call)
|
def test(source, node : Crystal::Call)
|
||||||
return unless node.name == SIZE_NAME && (obj = node.obj)
|
return unless node.name == SIZE_NAME && (obj = node.obj)
|
||||||
|
return unless obj.is_a?(Crystal::Call)
|
||||||
|
return if obj.block.nil?
|
||||||
|
|
||||||
if obj.is_a?(Crystal::Call) &&
|
if filter_names.includes?(obj.name)
|
||||||
filter_names.includes?(obj.name) && !obj.block.nil?
|
|
||||||
issue_for obj.name_location, node.name_end_location, MSG % obj.name
|
issue_for obj.name_location, node.name_end_location, MSG % obj.name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,7 +21,6 @@ module Ameba::Rule::Style
|
||||||
# Style/ConstantNames:
|
# Style/ConstantNames:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct ConstantNames < Base
|
struct ConstantNames < Base
|
||||||
properties do
|
properties do
|
||||||
description "Enforces constant names to be in screaming case"
|
description "Enforces constant names to be in screaming case"
|
||||||
|
@ -34,7 +33,7 @@ module Ameba::Rule::Style
|
||||||
name = target.names.first
|
name = target.names.first
|
||||||
expected = name.upcase
|
expected = name.upcase
|
||||||
|
|
||||||
return if expected == name || name.camelcase == name
|
return if name.in?(expected, name.camelcase)
|
||||||
|
|
||||||
issue_for target, MSG % {expected, name}
|
issue_for target, MSG % {expected, name}
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,7 +19,6 @@ module Ameba::Rule::Style
|
||||||
# Style/IsANil:
|
# Style/IsANil:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct IsANil < Base
|
struct IsANil < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows calls to `is_a?(Nil)` in favor of `nil?`"
|
description "Disallows calls to `is_a?(Nil)` in favor of `nil?`"
|
||||||
|
@ -32,7 +31,9 @@ module Ameba::Rule::Style
|
||||||
return if node.nil_check?
|
return if node.nil_check?
|
||||||
|
|
||||||
const = node.const
|
const = node.const
|
||||||
issue_for const, MSG if const.is_a?(Crystal::Path) && const.names == PATH_NIL_NAMES
|
return unless const.is_a?(Crystal::Path) && const.names == PATH_NIL_NAMES
|
||||||
|
|
||||||
|
issue_for const, MSG
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -26,7 +26,6 @@ module Ameba::Rule::Style
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# IntMinDigits: 5 # i.e. integers higher than 9999
|
# IntMinDigits: 5 # i.e. integers higher than 9999
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct LargeNumbers < Base
|
struct LargeNumbers < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows usage of large numbers without underscore"
|
description "Disallows usage of large numbers without underscore"
|
||||||
|
@ -53,7 +52,7 @@ module Ameba::Rule::Style
|
||||||
end
|
end
|
||||||
|
|
||||||
private def allowed?(_sign, value, fraction, _suffix)
|
private def allowed?(_sign, value, fraction, _suffix)
|
||||||
return true if !fraction.nil? && fraction.size > 3
|
return true if fraction && fraction.size > 3
|
||||||
|
|
||||||
digits = value.chars.select &.to_s.=~ /[0-9]/
|
digits = value.chars.select &.to_s.=~ /[0-9]/
|
||||||
digits.size >= int_min_digits
|
digits.size >= int_min_digits
|
||||||
|
@ -71,7 +70,7 @@ module Ameba::Rule::Style
|
||||||
value.chars.reject(&.== '_').each_slice(by) do |slice|
|
value.chars.reject(&.== '_').each_slice(by) do |slice|
|
||||||
slices << (yield slice).join
|
slices << (yield slice).join
|
||||||
end
|
end
|
||||||
end.join("_")
|
end.join('_')
|
||||||
end
|
end
|
||||||
|
|
||||||
private def parse_number(value)
|
private def parse_number(value)
|
||||||
|
|
|
@ -37,7 +37,6 @@ module Ameba::Rule::Style
|
||||||
# Style/MethodNames:
|
# Style/MethodNames:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct MethodNames < Base
|
struct MethodNames < Base
|
||||||
properties do
|
properties do
|
||||||
description "Enforces method names to be in underscored case"
|
description "Enforces method names to be in underscored case"
|
||||||
|
@ -51,7 +50,7 @@ module Ameba::Rule::Style
|
||||||
line_number = node.location.try &.line_number
|
line_number = node.location.try &.line_number
|
||||||
column_number = node.name_location.try &.column_number
|
column_number = node.name_location.try &.column_number
|
||||||
|
|
||||||
return if line_number.nil? || column_number.nil?
|
return unless line_number && column_number
|
||||||
|
|
||||||
issue_for(
|
issue_for(
|
||||||
{line_number, column_number},
|
{line_number, column_number},
|
||||||
|
|
|
@ -26,7 +26,6 @@ module Ameba::Rule::Style
|
||||||
# Style/NegatedConditionsInUnless:
|
# Style/NegatedConditionsInUnless:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct NegatedConditionsInUnless < Base
|
struct NegatedConditionsInUnless < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows negated conditions in unless"
|
description "Disallows negated conditions in unless"
|
||||||
|
@ -35,8 +34,7 @@ module Ameba::Rule::Style
|
||||||
MSG = "Avoid negated conditions in unless blocks"
|
MSG = "Avoid negated conditions in unless blocks"
|
||||||
|
|
||||||
def test(source, node : Crystal::Unless)
|
def test(source, node : Crystal::Unless)
|
||||||
return unless negated_condition? node.cond
|
issue_for node, MSG if negated_condition?(node.cond)
|
||||||
issue_for node, MSG
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private def negated_condition?(node)
|
private def negated_condition?(node)
|
||||||
|
|
|
@ -28,7 +28,6 @@ module Ameba::Rule::Style
|
||||||
# Style/PredicateName:
|
# Style/PredicateName:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct PredicateName < Base
|
struct PredicateName < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows tautological predicate names"
|
description "Disallows tautological predicate names"
|
||||||
|
|
|
@ -55,7 +55,6 @@ module Ameba::Rule::Style
|
||||||
# Style/RedundantBegin:
|
# Style/RedundantBegin:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct RedundantBegin < Base
|
struct RedundantBegin < Base
|
||||||
include AST::Util
|
include AST::Util
|
||||||
properties do
|
properties do
|
||||||
|
@ -65,9 +64,7 @@ module Ameba::Rule::Style
|
||||||
MSG = "Redundant `begin` block detected"
|
MSG = "Redundant `begin` block detected"
|
||||||
|
|
||||||
def test(source, node : Crystal::Def)
|
def test(source, node : Crystal::Def)
|
||||||
return unless redundant_begin?(source, node)
|
issue_for node, MSG if redundant_begin?(source, node)
|
||||||
|
|
||||||
issue_for node, MSG
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private def redundant_begin?(source, node)
|
private def redundant_begin?(source, node)
|
||||||
|
|
|
@ -51,7 +51,6 @@ module Ameba::Rule::Style
|
||||||
# Style/TypeNames:
|
# Style/TypeNames:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct TypeNames < Base
|
struct TypeNames < Base
|
||||||
properties do
|
properties do
|
||||||
description "Enforces type names in camelcase manner"
|
description "Enforces type names in camelcase manner"
|
||||||
|
@ -62,7 +61,7 @@ module Ameba::Rule::Style
|
||||||
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
|
||||||
return if expected == name
|
return if name == expected
|
||||||
|
|
||||||
issue_for node, MSG % {expected, name}
|
issue_for node, MSG % {expected, name}
|
||||||
end
|
end
|
||||||
|
|
|
@ -42,7 +42,6 @@ module Ameba::Rule::Style
|
||||||
# Style/UnlessElse:
|
# Style/UnlessElse:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct UnlessElse < Base
|
struct UnlessElse < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows the use of an `else` block with the `unless`"
|
description "Disallows the use of an `else` block with the `unless`"
|
||||||
|
@ -51,8 +50,7 @@ module Ameba::Rule::Style
|
||||||
MSG = "Favour if over unless with else"
|
MSG = "Favour if over unless with else"
|
||||||
|
|
||||||
def test(source, node : Crystal::Unless)
|
def test(source, node : Crystal::Unless)
|
||||||
return if node.else.nop?
|
issue_for node, MSG unless node.else.nop?
|
||||||
issue_for node, MSG
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,7 +22,6 @@ module Ameba::Rule::Style
|
||||||
# Style/VariableNames:
|
# Style/VariableNames:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct VariableNames < Base
|
struct VariableNames < Base
|
||||||
properties do
|
properties do
|
||||||
description "Enforces variable names to be in underscored case"
|
description "Enforces variable names to be in underscored case"
|
||||||
|
|
|
@ -25,7 +25,6 @@ module Ameba::Rule::Style
|
||||||
# Style/WhileTrue:
|
# Style/WhileTrue:
|
||||||
# Enabled: true
|
# Enabled: true
|
||||||
# ```
|
# ```
|
||||||
#
|
|
||||||
struct WhileTrue < Base
|
struct WhileTrue < Base
|
||||||
properties do
|
properties do
|
||||||
description "Disallows while statements with a true literal as condition"
|
description "Disallows while statements with a true literal as condition"
|
||||||
|
@ -34,8 +33,7 @@ module Ameba::Rule::Style
|
||||||
MSG = "While statement using true literal as condition"
|
MSG = "While statement using true literal as condition"
|
||||||
|
|
||||||
def test(source, node : Crystal::While)
|
def test(source, node : Crystal::While)
|
||||||
return unless node.cond.true_literal?
|
issue_for node, MSG if node.cond.true_literal?
|
||||||
issue_for node, MSG
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue