diff --git a/changelog/fix_a_false_positive_for_style_redundant_parentheses.md b/changelog/fix_a_false_positive_for_style_redundant_parentheses.md new file mode 100644 index 00000000000..b97ea35dfe7 --- /dev/null +++ b/changelog/fix_a_false_positive_for_style_redundant_parentheses.md @@ -0,0 +1 @@ +* [#10979](https://github.com/rubocop/rubocop/issues/10979): Fix a false positive for `Style/RedundantParentheses` when using parentheses with pin operator except for variables. ([@Tietew][]) diff --git a/lib/rubocop/cop/style/redundant_parentheses.rb b/lib/rubocop/cop/style/redundant_parentheses.rb index 184b3ab6eaf..e4f7a3b7b50 100644 --- a/lib/rubocop/cop/style/redundant_parentheses.rb +++ b/lib/rubocop/cop/style/redundant_parentheses.rb @@ -29,6 +29,9 @@ class RedundantParentheses < Base # @!method rescue?(node) def_node_matcher :rescue?, '{^resbody ^^resbody}' + # @!method allowed_pin_operator?(node) + def_node_matcher :allowed_pin_operator?, '^(pin (begin !{lvar ivar cvar gvar}))' + # @!method arg_in_call_with_block?(node) def_node_matcher :arg_in_call_with_block?, '^^(block (send _ _ equal?(%0) ...) ...)' @@ -44,6 +47,7 @@ def parens_allowed?(node) empty_parentheses?(node) || first_arg_begins_with_hash_literal?(node) || rescue?(node) || + allowed_pin_operator?(node) || allowed_expression?(node) end diff --git a/spec/rubocop/cop/style/redundant_parentheses_spec.rb b/spec/rubocop/cop/style/redundant_parentheses_spec.rb index 34332aa5b4d..24b8445091c 100644 --- a/spec/rubocop/cop/style/redundant_parentheses_spec.rb +++ b/spec/rubocop/cop/style/redundant_parentheses_spec.rb @@ -626,4 +626,49 @@ def x ] RUBY end + + context 'pin operator', :ruby31 do + let(:target_ruby_version) { 3.1 } + + shared_examples 'redundant parentheses' do |variable, description| + it "registers an offense and corrects #{description}" do + expect_offense(<<~RUBY, variable: variable) + var = 0 + foo in { bar: ^(%{variable}) } + ^^{variable}^ Don\x27t use parentheses around a variable. + RUBY + + expect_correction(<<~RUBY) + var = 0 + foo in { bar: ^#{variable} } + RUBY + end + end + + it_behaves_like 'redundant parentheses', 'var', 'a local variable' + it_behaves_like 'redundant parentheses', '@var', 'an instance variable' + it_behaves_like 'redundant parentheses', '@@var', 'a class variable' + it_behaves_like 'redundant parentheses', '$var', 'a global variable' + + shared_examples 'allowed parentheses' do |expression, description| + it "accepts parentheses on #{description}" do + expect_no_offenses(<<~RUBY) + var = 0 + foo in { bar: ^(#{expression}) } + RUBY + end + end + + it_behaves_like 'allowed parentheses', 'meth', 'a function call with no arguments' + it_behaves_like 'allowed parentheses', 'meth(true)', 'a function call with arguments' + it_behaves_like 'allowed parentheses', 'var.to_i', 'a method call on a local variable' + it_behaves_like 'allowed parentheses', '@var.to_i', 'a method call on an instance variable' + it_behaves_like 'allowed parentheses', '@@var.to_i', 'a method call on a class variable' + it_behaves_like 'allowed parentheses', '$var.to_i', 'a method call on a global variable' + it_behaves_like 'allowed parentheses', 'var + 1', 'an expression' + it_behaves_like 'allowed parentheses', '[1, 2]', 'an array literal' + it_behaves_like 'allowed parentheses', '{ baz: 2 }', 'a hash literal' + it_behaves_like 'allowed parentheses', '1..2', 'a range literal' + it_behaves_like 'allowed parentheses', '1', 'an int literal' + end end