mirror of
https://gitea.invidious.io/iv-org/shard-ameba.git
synced 2024-08-15 00:53:29 +00:00
Followup to #185
This commit is contained in:
parent
fd4b2f309c
commit
af5d825015
21 changed files with 32 additions and 31 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]?
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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'"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue