Skip to content

Commit

Permalink
Fix Performance/Squeeze cop error on frozen AST string node value
Browse files Browse the repository at this point in the history
Since sometimes AST string nodes might have their values frozen,
we should call `dup` explicitly to make sure `to_string_literal`
(which does not work with frozen strings) does not raise. Maybe
we should also apply a patch on RuboCop's core side to fix the
`to_string_literal` itself (it now uses `force_encoding` on its argument).

See [1] and [2] for details.

[1] ruby/prism#3309
[2] rubocop/rubocop-ast#342
  • Loading branch information
viralpraxis committed Dec 21, 2024
1 parent ad9fd62 commit 9fdbe4e
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#480](https://github.com/rubocop/rubocop-performance/pull/480): Fix `Performance/Squeeze` cop error on frozen AST string node value. ([@viralpraxis][])
6 changes: 5 additions & 1 deletion lib/rubocop/cop/performance/squeeze.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ def on_send(node)
message = format(MSG, current: bad_method, prefer: good_method)

add_offense(node.loc.selector, message: message) do |corrector|
string_literal = to_string_literal(replace_str)
# FIXME: When requiring only RuboCop 1.70.0 and above,
# `dup` in `replace_str.dup` becomes unnecessary, as
# frozen strings are handled in the `to_string_literal`
# implementation. Please remove it.
string_literal = to_string_literal(replace_str.dup)
new_code = "#{receiver.source}#{node.loc.dot.source}#{good_method}(#{string_literal})"

corrector.replace(node, new_code)
Expand Down
11 changes: 11 additions & 0 deletions spec/rubocop/cop/performance/squeeze_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,15 @@
str.gsub(/a+/, 'b')
RUBY
end

it 'registers an offense when AST string literal might be frozen' do
expect_offense(<<~'RUBY')
str.gsub(/\n+/, ?\n)
^^^^ Use `squeeze` instead of `gsub`.
RUBY

expect_correction(<<~'RUBY')
str.squeeze("\n")
RUBY
end
end

0 comments on commit 9fdbe4e

Please sign in to comment.