From 7cf773ee9461811834977f46b82bf8bed0e8e540 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Tue, 15 Jun 2021 09:50:58 +0900 Subject: [PATCH] [Fix #9874] Fix a false positive for `Style/RegexpLiteral` Fixes #9874. This PR fixes a false positive for `Style/RegexpLiteral` when using `%r` regexp literal with `EnforcedStyle: omit_parentheses` of `Style/MethodCallWithArgsParentheses`. --- ...false_positive_for_style_regexp_literal.md | 1 + lib/rubocop/cop/style/regexp_literal.rb | 10 +- spec/rubocop/cop/style/regexp_literal_spec.rb | 107 ++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 changelog/fix_false_positive_for_style_regexp_literal.md diff --git a/changelog/fix_false_positive_for_style_regexp_literal.md b/changelog/fix_false_positive_for_style_regexp_literal.md new file mode 100644 index 00000000000..688e22c5214 --- /dev/null +++ b/changelog/fix_false_positive_for_style_regexp_literal.md @@ -0,0 +1 @@ +* [#9874](https://github.com/rubocop/rubocop/issues/9874): Fix a false positive for `Style/RegexpLiteral` when using `%r` regexp literal with `EnforcedStyle: omit_parentheses` of `Style/MethodCallWithArgsParentheses`. ([@koic][]) diff --git a/lib/rubocop/cop/style/regexp_literal.rb b/lib/rubocop/cop/style/regexp_literal.rb index 5cb8855a5e1..cffea6d3561 100644 --- a/lib/rubocop/cop/style/regexp_literal.rb +++ b/lib/rubocop/cop/style/regexp_literal.rb @@ -117,7 +117,7 @@ def allowed_mixed_slash?(node) def allowed_percent_r_literal?(node) style == :slashes && contains_disallowed_slash?(node) || style == :percent_r || - allowed_mixed_percent_r?(node) + allowed_mixed_percent_r?(node) || omit_parentheses_style?(node) end def allowed_mixed_percent_r?(node) @@ -149,6 +149,14 @@ def preferred_delimiters config.for_cop('Style/PercentLiteralDelimiters') ['PreferredDelimiters']['%r'].chars end + def omit_parentheses_style?(node) + return false unless node.parent&.call_type? + + enforced_style = config.for_cop('Style/MethodCallWithArgsParentheses')['EnforcedStyle'] + + enforced_style == 'omit_parentheses' + end + def correct_delimiters(node, corrector) replacement = calculate_replacement(node) corrector.replace(node.loc.begin, replacement.first) diff --git a/spec/rubocop/cop/style/regexp_literal_spec.rb b/spec/rubocop/cop/style/regexp_literal_spec.rb index 5d214344a24..5c4affe6c34 100644 --- a/spec/rubocop/cop/style/regexp_literal_spec.rb +++ b/spec/rubocop/cop/style/regexp_literal_spec.rb @@ -5,10 +5,13 @@ supported_styles = { 'SupportedStyles' => %w[slashes percent_r mixed] } RuboCop::Config.new('Style/PercentLiteralDelimiters' => percent_literal_delimiters_config, + 'Style/MethodCallWithArgsParentheses' => + method_call_with_args_parentheses_config, 'Style/RegexpLiteral' => cop_config.merge(supported_styles)) end let(:percent_literal_delimiters_config) { { 'PreferredDelimiters' => { '%r' => '{}' } } } + let(:method_call_with_args_parentheses_config) { { 'EnforcedStyle' => 'require_parentheses' } } describe 'when regex contains slashes in interpolation' do let(:cop_config) { { 'EnforcedStyle' => 'slashes' } } @@ -488,4 +491,108 @@ end end end + + context 'when `EnforcedStyle: require_parentheses` of `Style/MethodCallWithArgsParentheses` cop' do + let(:method_call_with_args_parentheses_config) { { 'EnforcedStyle' => 'require_parentheses' } } + + context 'when using `%r` regexp with `EnforcedStyle: slashes`' do + let(:cop_config) { { 'EnforcedStyle' => 'slashes' } } + + it 'registers an offense when used as a method argument' do + expect_offense(<<~RUBY) + do_something %r/regexp/ + ^^^^^^^^^^ Use `//` around regular expression. + RUBY + end + + it 'registers an offense when used as a safe navigation method argument' do + expect_offense(<<~RUBY) + foo&.do_something %r/regexp/ + ^^^^^^^^^^ Use `//` around regular expression. + RUBY + end + + it 'registers an offense when not used as a method argument' do + expect_offense(<<~RUBY) + %r/regexp/ + ^^^^^^^^^^ Use `//` around regular expression. + RUBY + end + end + + context 'when using `%r` regexp with `EnforcedStyle: mixed`' do + let(:cop_config) { { 'EnforcedStyle' => 'mixed' } } + + it 'registers an offense when used as a method argument' do + expect_offense(<<~RUBY) + do_something %r/regexp/ + ^^^^^^^^^^ Use `//` around regular expression. + RUBY + end + + it 'registers an offense when used as a safe navigation method argument' do + expect_offense(<<~RUBY) + foo&.do_something %r/regexp/ + ^^^^^^^^^^ Use `//` around regular expression. + RUBY + end + + it 'registers an offense when not used as a method argument' do + expect_offense(<<~RUBY) + %r/regexp/ + ^^^^^^^^^^ Use `//` around regular expression. + RUBY + end + end + end + + context 'when `EnforcedStyle: omit_parentheses` of `Style/MethodCallWithArgsParentheses` cop' do + let(:method_call_with_args_parentheses_config) { { 'EnforcedStyle' => 'omit_parentheses' } } + + context 'when using `%r` regexp with `EnforcedStyle: slashes`' do + let(:cop_config) { { 'EnforcedStyle' => 'slashes' } } + + it 'does not register an offense when used as a method argument' do + expect_no_offenses(<<~RUBY) + do_something %r/regexp/ + RUBY + end + + it 'does not register an offense when used as a safe navigation method argument' do + expect_no_offenses(<<~RUBY) + foo&.do_something %r/regexp/ + RUBY + end + + it 'registers an offense when not used as a method argument' do + expect_offense(<<~RUBY) + %r/regexp/ + ^^^^^^^^^^ Use `//` around regular expression. + RUBY + end + end + + context 'when using `%r` regexp with `EnforcedStyle: mixed`' do + let(:cop_config) { { 'EnforcedStyle' => 'mixed' } } + + it 'does not register an offense when used as a method argument' do + expect_no_offenses(<<~RUBY) + do_something %r/regexp/ + RUBY + end + + it 'does not register an offense when used as a safe navigation method argument' do + expect_no_offenses(<<~RUBY) + foo&.do_something %r/regexp/ + RUBY + end + + it 'registers an offense when not used as a method argument' do + expect_offense(<<~RUBY) + %r/regexp/ + ^^^^^^^^^^ Use `//` around regular expression. + RUBY + end + end + end end