Skip to content

Commit

Permalink
[Fix #11098] Fix false positive for Style/RedundantStringEscape
Browse files Browse the repository at this point in the history
  • Loading branch information
tdeo authored and bbatsov committed Oct 22, 2022
1 parent 2abcc4a commit 05e4611
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 4 deletions.
1 change: 1 addition & 0 deletions changelog/fix_fix_false_positive_for.md
@@ -0,0 +1 @@
* [#11098](https://github.com/rubocop/rubocop/issues/11098): Fix false positive for Style/RedundantStringEscape. ([@tdeo][])
15 changes: 12 additions & 3 deletions lib/rubocop/cop/style/redundant_string_escape.rb
Expand Up @@ -90,9 +90,7 @@ def allowed_escape?(node, range)

return true if escaped[0] == ' ' && percent_array_literal?(node)

# Allow #{foo}, #$foo, #@foo, and #@@foo for escaping local, global, instance and class
# variable interpolations inside
return true if /\A#[{$@]/.match?(escaped)
return true if disabling_interpolation?(range)
return true if delimiter?(node, escaped[0])

false
Expand Down Expand Up @@ -166,6 +164,17 @@ def delimiter?(node, char)
def literal_in_interpolated_or_multiline_string?(node)
node.str_type? && !begin_loc_present?(node) && node.parent&.dstr_type?
end

def disabling_interpolation?(range)
# Allow \#{foo}, \#$foo, \#@foo, and \#@@foo
# for escaping local, global, instance and class variable interpolations
return true if range.source.match?(/\A\\#[{$@]/)

# Also allow #\{foo}, #\$foo, #\@foo and #\@@foo
return true if range.adjust(begin_pos: -2).source.match?(/\A[^\\]#\\[{$@]/)

false
end
end
end
end
Expand Down
33 changes: 32 additions & 1 deletion spec/rubocop/cop/style/redundant_string_escape_spec.rb
Expand Up @@ -21,22 +21,42 @@ def wrap(contents)
expect_no_offenses(wrap('\#$foo'))
end

it 'does not register an offense for a $-escaped gvar interpolation' do
expect_no_offenses(wrap('#\$foo'))
end

it 'does not register an offense for an escaped ivar interpolation' do
expect_no_offenses(wrap('\#@foo'))
end

it 'does not register an offense for a @-escaped ivar interpolation' do
expect_no_offenses(wrap('#\@foo'))
end

it 'does not register an offense for an escaped cvar interpolation' do
expect_no_offenses(wrap('\#@@foo'))
end

it 'does not register an offense for a @-escaped cvar interpolation' do
expect_no_offenses(wrap('#\@@foo'))
end

it 'does not register an offense for an escaped interpolation' do
expect_no_offenses(wrap('\#{my_var}'))
end

it 'does not register an offense for an escaped # an following {' do
it 'does not register an offense for a bracket-escaped interpolation' do
expect_no_offenses(wrap('#\{my_var}'))
end

it 'does not register an offense for an escaped # followed {' do
expect_no_offenses(wrap('\#{my_lvar}'))
end

it 'does not register a bracket-escaped lvar interpolation' do
expect_no_offenses(wrap('#\{my_lvar}'))
end

it 'does not register an offense for an escaped newline' do
expect_no_offenses(wrap("foo\\\nbar"))
end
Expand Down Expand Up @@ -117,6 +137,17 @@ def wrap(contents)
RUBY
end

it 'registers an offense and corrects an escaped } when escaping both brackets to avoid interpolation' do
expect_offense(<<~'RUBY', l: l, r: r)
%{l}#\{whatever\}%{r}
_{l} ^^ Redundant escape of } inside string literal.
RUBY

expect_correction(<<~RUBY)
#{l}#\\{whatever}#{r}
RUBY
end

it 'registers an offense and corrects an escaped # at end-of-string' do
expect_offense(<<~'RUBY', l: l, r: r)
%{l}\#%{r}
Expand Down

0 comments on commit 05e4611

Please sign in to comment.