Instead of adding the new rule to support enforcing parens around assignments, refactor existing RedundantParentheses rule

This commit is contained in:
Sijawusz Pur Rahnama 2022-11-18 05:27:05 +01:00
parent 94a271b2a1
commit eabe463386
3 changed files with 32 additions and 51 deletions

View file

@ -75,7 +75,7 @@ module Ameba::Rule::Style
end end
end end
context "#exclude_assignments=" do context "#parenthesized_assignments=" do
it "reports assignments by default" do it "reports assignments by default" do
expect_issue subject, <<-CRYSTAL expect_issue subject, <<-CRYSTAL
if (foo = @foo) if (foo = @foo)
@ -83,11 +83,24 @@ module Ameba::Rule::Style
foo foo
end end
CRYSTAL CRYSTAL
expect_no_issues subject, <<-CRYSTAL
if foo = @foo
foo
end
CRYSTAL
end end
it "allows to configure assignments" do it "allows to configure assignments" do
rule = Rule::Style::RedundantParentheses.new rule = Rule::Style::RedundantParentheses.new
rule.exclude_assignments = true rule.parenthesized_assignments = true
expect_issue rule, <<-CRYSTAL
if foo = @foo
# ^^^^^^^^^^ error: Missing parentheses
foo
end
CRYSTAL
expect_no_issues rule, <<-CRYSTAL expect_no_issues rule, <<-CRYSTAL
if (foo = @foo) if (foo = @foo)

View file

@ -1,43 +0,0 @@
module Ameba::Rule::Style
# A rule that disallows assignments without parens in control expressions.
#
# For example, this is considered invalid:
#
# ```
# if foo = @foo
# do_something
# end
# ```
#
# And should be replaced by the following:
#
# ```
# if (foo = @foo)
# do_something
# end
# ```
#
# YAML configuration example:
#
# ```
# Style/ParenthesizedAssignments:
# Enabled: true
# ```
class ParenthesizedAssignments < Base
properties do
enabled false
description "Disallows assignments without parens in control expressions"
end
MSG = "Missing parentheses around assignment"
def test(source, node : Crystal::If | Crystal::Unless | Crystal::Case | Crystal::While | Crystal::Until)
return unless (cond = node.cond).is_a?(Crystal::Assign)
issue_for cond, MSG do |corrector|
corrector.insert_before(cond, '(')
corrector.insert_after(cond, ')')
end
end
end
end

View file

@ -23,17 +23,18 @@ module Ameba::Rule::Style
# Style/RedundantParentheses: # Style/RedundantParentheses:
# Enabled: true # Enabled: true
# ExcludeTernary: false # ExcludeTernary: false
# ExcludeAssignments: false # ParenthesizedAssignments: false
# ``` # ```
class RedundantParentheses < Base class RedundantParentheses < Base
properties do properties do
description "Disallows redundant parentheses around control expressions" description "Disallows redundant parentheses around control expressions"
exclude_ternary false exclude_ternary false
exclude_assignments false parenthesized_assignments false
end end
MSG = "Redundant parentheses" MSG_REDUNDANT = "Redundant parentheses"
MSG_MISSING = "Missing parentheses"
protected def strip_parentheses?(node, in_ternary) : Bool protected def strip_parentheses?(node, in_ternary) : Bool
case node case node
@ -44,24 +45,34 @@ module Ameba::Rule::Style
when Crystal::Yield when Crystal::Yield
!in_ternary || node.has_parentheses? || node.exps.empty? !in_ternary || node.has_parentheses? || node.exps.empty?
when Crystal::Assign, Crystal::OpAssign, Crystal::MultiAssign when Crystal::Assign, Crystal::OpAssign, Crystal::MultiAssign
!in_ternary && !exclude_assignments !in_ternary && !parenthesized_assignments
else else
true true
end end
end end
def test(source, node : Crystal::If | Crystal::Unless | Crystal::Case | Crystal::While | Crystal::Until) def test(source, node : Crystal::If | Crystal::Unless | Crystal::Case | Crystal::While | Crystal::Until)
cond = node.cond
if cond.is_a?(Crystal::Assign) && parenthesized_assignments
issue_for cond, MSG_MISSING do |corrector|
corrector.insert_before(cond, '(')
corrector.insert_after(cond, ')')
end
return
end
is_ternary = node.is_a?(Crystal::If) && node.ternary? is_ternary = node.is_a?(Crystal::If) && node.ternary?
return if is_ternary && exclude_ternary return if is_ternary && exclude_ternary
return unless (cond = node.cond).is_a?(Crystal::Expressions) return unless cond.is_a?(Crystal::Expressions)
return unless cond.keyword.paren? return unless cond.keyword.paren?
return unless exp = cond.single_expression? return unless exp = cond.single_expression?
return unless strip_parentheses?(exp, is_ternary) return unless strip_parentheses?(exp, is_ternary)
issue_for cond, MSG do |corrector| issue_for cond, MSG_REDUNDANT do |corrector|
corrector.remove_trailing(cond, 1) corrector.remove_trailing(cond, 1)
corrector.remove_leading(cond, 1) corrector.remove_leading(cond, 1)
end end