Followup to #185

This commit is contained in:
Sijawusz Pur Rahnama 2021-01-17 18:12:10 +01:00
parent fd4b2f309c
commit af5d825015
21 changed files with 32 additions and 31 deletions

View file

@ -175,7 +175,7 @@ module Ameba::AST
end end
def references?(node : Crystal::Var) def references?(node : Crystal::Var)
@macro_literals.any? { |literal| literal.value.includes? node.name } @macro_literals.any?(&.value.includes?(node.name))
end end
def visit(node : Crystal::ASTNode) def visit(node : Crystal::ASTNode)
@ -190,7 +190,7 @@ module Ameba::AST
private def update_assign_reference! private def update_assign_reference!
if @assign_before_reference.nil? && if @assign_before_reference.nil? &&
references.size <= assignments.size && references.size <= assignments.size &&
assignments.none? { |ass| ass.op_assign? } assignments.none?(&.op_assign?)
@assign_before_reference = assignments.find { |ass| !ass.in_branch? }.try &.node @assign_before_reference = assignments.find { |ass| !ass.in_branch? }.try &.node
end end
end end

View file

@ -18,7 +18,6 @@ module Ameba::AST
if flow_expression?(node, in_loop?) if flow_expression?(node, in_loop?)
@rule.test @source, node, FlowExpression.new(node, in_loop?) @rule.test @source, node, FlowExpression.new(node, in_loop?)
end end
true true
end end

View file

@ -40,7 +40,7 @@ module Ameba::AST
@skip : Array(Crystal::ASTNode.class)? @skip : Array(Crystal::ASTNode.class)?
def initialize(@rule, @source, skip = nil) def initialize(@rule, @source, skip = nil)
@skip = skip.try &.map { |el| el.as(Crystal::ASTNode.class) } @skip = skip.try &.map(&.as(Crystal::ASTNode.class))
super @rule, @source super @rule, @source
end end
@ -54,7 +54,7 @@ module Ameba::AST
{% end %} {% end %}
def visit(node) def visit(node)
return true unless (skip = @skip) return true unless skip = @skip
!skip.includes?(node.class) !skip.includes?(node.class)
end end
end end

View file

@ -28,8 +28,6 @@ module Ameba::AST
when Crystal::Case then traverse_case node when Crystal::Case then traverse_case node
when Crystal::BinaryOp then traverse_binary_op node when Crystal::BinaryOp then traverse_binary_op node
when Crystal::ExceptionHandler then traverse_exception_handler node when Crystal::ExceptionHandler then traverse_exception_handler node
else
# ok
end end
end end

View file

@ -7,7 +7,6 @@ module Ameba::AST
RECORD_NODE_NAME = "record" RECORD_NODE_NAME = "record"
@scope_queue = [] of Scope @scope_queue = [] of Scope
@current_scope : Scope @current_scope : Scope
def initialize(@rule, @source) def initialize(@rule, @source)
@ -169,7 +168,6 @@ module Ameba::AST
variable.reference(variable.node, @current_scope).explicit = false variable.reference(variable.node, @current_scope).explicit = false
end end
end end
true true
when @current_scope.top_level? && record_macro?(node) when @current_scope.top_level? && record_macro?(node)
false false

View file

@ -89,11 +89,11 @@ module Ameba::Formatter
private def final_message(sources, failed_sources) private def final_message(sources, failed_sources)
total = sources.size total = sources.size
failures = failed_sources.map { |f| f.issues.size }.sum failures = failed_sources.sum(&.issues.size)
color = failures == 0 ? :green : :red color = failures == 0 ? :green : :red
s = failures != 1 ? "s" : "" s = failures != 1 ? "s" : ""
"#{total} inspected, #{failures} failure#{s}.\n".colorize color "#{total} inspected, #{failures} failure#{s}.\n".colorize(color)
end end
end end
end end

View file

@ -38,7 +38,7 @@ module Ameba
# ``` # ```
# #
def location_disabled?(location, rule) def location_disabled?(location, rule)
return false if Rule::SPECIAL.includes?(rule.name) return false if rule.name.in?(Rule::SPECIAL)
return false unless line_number = location.try &.line_number.try &.- 1 return false unless line_number = location.try &.line_number.try &.- 1
return false unless line = lines[line_number]? return false unless line = lines[line_number]?

View file

@ -107,11 +107,11 @@ module Ameba::Rule
# ``` # ```
# #
def special? def special?
SPECIAL.includes? name name.in?(SPECIAL)
end end
def ==(other) def ==(other)
name == other.try &.name name == other.try(&.name)
end end
def hash def hash

View file

@ -23,9 +23,9 @@ module Ameba::Rule::Layout
source_lines_size = source_lines.size source_lines_size = source_lines.size
return if source_lines_size == 1 && last_source_line.empty? return if source_lines_size == 1 && last_source_line.empty?
last_line_not_empty = !last_source_line.empty? last_line_empty = last_source_line.empty?
if source_lines_size >= 1 && (source_lines.last(2).join.strip.empty? || last_line_not_empty) if source_lines_size >= 1 && (source_lines.last(2).join.blank? || !last_line_empty)
issue_for({source_lines_size - 1, 1}, last_line_not_empty ? MSG_FINAL_NEWLINE : MSG) issue_for({source_lines_size - 1, 1}, last_line_empty ? MSG : MSG_FINAL_NEWLINE)
end end
end end
end end

View file

@ -30,7 +30,7 @@ module Ameba::Rule::Lint
def test(source, node : Crystal::Call) def test(source, node : Crystal::Call)
comparison = node.name.in?(OP_NAMES) comparison = node.name.in?(OP_NAMES)
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)
issue_for node, MSG if comparison && to_boolean issue_for node, MSG if comparison && to_boolean

View file

@ -31,8 +31,8 @@ module Ameba::Rule::Lint
include AST::Util include AST::Util
properties do properties do
description "Disallows empty expressions"
enabled false enabled false
description "Disallows empty expressions"
end end
MSG = "Avoid empty expression %s" MSG = "Avoid empty expression %s"

View file

@ -26,6 +26,7 @@ module Ameba::Rule::Lint
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"
string_array_unwanted_symbols %(,") string_array_unwanted_symbols %(,")
symbol_array_unwanted_symbols %(,:) symbol_array_unwanted_symbols %(,:)
end end

View file

@ -51,7 +51,7 @@ module Ameba::Rule::Lint
previous_exceptions = [] of String previous_exceptions = [] of String
exceptions.reduce([] of String) do |shadowed, excs| exceptions.reduce([] of String) do |shadowed, excs|
excs = excs ? excs.map(&.to_s) : ["Exception"] excs = excs.try(&.map(&.to_s)) || %w[Exception]
if exception_found if exception_found
shadowed.concat excs shadowed.concat excs

View file

@ -26,8 +26,8 @@ module Ameba::Rule::Performance
# ``` # ```
struct AnyAfterFilter < Base struct AnyAfterFilter < Base
properties do properties do
filter_names : Array(String) = %w(select reject)
description "Identifies usage of `any?` calls that follow filters." description "Identifies usage of `any?` calls that follow filters."
filter_names : Array(String) = %w(select reject)
end end
ANY_NAME = "any?" ANY_NAME = "any?"
@ -36,7 +36,7 @@ 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) && obj.block && node.block.nil? return unless obj.is_a?(Crystal::Call) && obj.block && node.block.nil?
return unless filter_names.includes?(obj.name) return unless obj.name.in?(filter_names)
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

View file

@ -25,8 +25,8 @@ module Ameba::Rule::Performance
# ``` # ```
struct FirstLastAfterFilter < Base struct FirstLastAfterFilter < Base
properties do properties do
filter_names : Array(String) = %w(select)
description "Identifies usage of `first/last/first?/last?` calls that follow filters." description "Identifies usage of `first/last/first?/last?` calls that follow filters."
filter_names : Array(String) = %w(select)
end end
CALL_NAMES = %w(first last first? last?) CALL_NAMES = %w(first last first? last?)
@ -43,10 +43,10 @@ module Ameba::Rule::Performance
end end
def test(source, node : Crystal::Call) def test(source, node : Crystal::Call)
return unless CALL_NAMES.includes?(node.name) && (obj = node.obj) return unless node.name.in?(CALL_NAMES) && (obj = node.obj)
return unless obj.is_a?(Crystal::Call) && obj.block return unless obj.is_a?(Crystal::Call) && obj.block
return if !node.block.nil? || node.args.any? return if !node.block.nil? || node.args.any?
return unless filter_names.includes?(obj.name) return unless obj.name.in?(filter_names)
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}

View file

@ -32,8 +32,8 @@ module Ameba::Rule::Performance
# ``` # ```
struct SizeAfterFilter < Base struct SizeAfterFilter < Base
properties do properties do
filter_names : Array(String) = %w(select reject)
description "Identifies usage of `size` calls that follow filter" description "Identifies usage of `size` calls that follow filter"
filter_names : Array(String) = %w(select reject)
end end
SIZE_NAME = "size" SIZE_NAME = "size"
@ -51,7 +51,7 @@ 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) && obj.block return unless obj.is_a?(Crystal::Call) && obj.block
return unless filter_names.includes?(obj.name) return unless obj.name.in?(filter_names)
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

View file

@ -28,9 +28,9 @@ module Ameba::Rule::Style
# ``` # ```
struct LargeNumbers < Base struct LargeNumbers < Base
properties do properties do
enabled false
description "Disallows usage of large numbers without underscore" description "Disallows usage of large numbers without underscore"
int_min_digits 5 int_min_digits 5
enabled false
end end
MSG = "Large numbers should be written with underscores: %s" MSG = "Large numbers should be written with underscores: %s"
@ -82,7 +82,7 @@ module Ameba::Rule::Style
end end
private def parse_sign(value) private def parse_sign(value)
if "+-".includes?(value[0]) if value[0].in?('+', '-')
sign = value[0] sign = value[0]
value = value[1..-1] value = value[1..-1]
end end
@ -90,7 +90,7 @@ module Ameba::Rule::Style
end end
private def parse_suffix(value) private def parse_suffix(value)
if pos = (value =~ /e/ || value =~ /_?(i|u|f)/) if pos = (value =~ /(e|_?(i|u|f))/)
suffix = value[pos..-1] suffix = value[pos..-1]
value = value[0..pos - 1] value = value[0..pos - 1]
end end

View file

@ -30,8 +30,8 @@ module Ameba::Rule::Style
# ``` # ```
struct PredicateName < Base struct PredicateName < Base
properties do properties do
description "Disallows tautological predicate names"
enabled false enabled false
description "Disallows tautological predicate names"
end end
MSG = "Favour method name '%s?' over '%s'" MSG = "Favour method name '%s?' over '%s'"

View file

@ -57,6 +57,7 @@ module Ameba::Rule::Style
# ``` # ```
struct RedundantBegin < Base struct RedundantBegin < Base
include AST::Util include AST::Util
properties do properties do
description "Disallows redundant begin blocks" description "Disallows redundant begin blocks"
end end
@ -102,6 +103,7 @@ module Ameba::Rule::Style
private def def_redundant_begin?(code) private def def_redundant_begin?(code)
lexer = Crystal::Lexer.new code lexer = Crystal::Lexer.new code
in_body = in_argument_list = false in_body = in_argument_list = false
loop do loop do
token = lexer.next_token token = lexer.next_token
@ -117,6 +119,7 @@ module Ameba::Rule::Style
when :NEWLINE when :NEWLINE
in_body = true unless in_argument_list in_body = true unless in_argument_list
when :SPACE when :SPACE
# ignore
else else
return false if in_body return false if in_body
end end

View file

@ -99,6 +99,7 @@ module Ameba::Rule::Style
struct RedundantNext < Base struct RedundantNext < Base
properties do properties do
description "Reports redundant next expressions" description "Reports redundant next expressions"
allow_multi_next true allow_multi_next true
allow_empty_next true allow_empty_next true
end end

View file

@ -96,6 +96,7 @@ module Ameba::Rule::Style
struct RedundantReturn < Base struct RedundantReturn < Base
properties do properties do
description "Reports redundant return expressions" description "Reports redundant return expressions"
allow_multi_return true allow_multi_return true
allow_empty_return true allow_empty_return true
end end