From 9fdbe4e81be615973d6647d54af1763d98223133 Mon Sep 17 00:00:00 2001 From: viralpraxis Date: Wed, 18 Dec 2024 16:07:06 +0300 Subject: [PATCH] Fix `Performance/Squeeze` cop error on frozen AST string node value 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] /~https://github.com/ruby/prism/issues/3309 [2] /~https://github.com/rubocop/rubocop-ast/issues/342 --- ...ueeze_cop_error_on_frozen_ast_string_node_value.md | 1 + lib/rubocop/cop/performance/squeeze.rb | 6 +++++- spec/rubocop/cop/performance/squeeze_spec.rb | 11 +++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 changelog/fix_performance_squeeze_cop_error_on_frozen_ast_string_node_value.md diff --git a/changelog/fix_performance_squeeze_cop_error_on_frozen_ast_string_node_value.md b/changelog/fix_performance_squeeze_cop_error_on_frozen_ast_string_node_value.md new file mode 100644 index 0000000000..491548f931 --- /dev/null +++ b/changelog/fix_performance_squeeze_cop_error_on_frozen_ast_string_node_value.md @@ -0,0 +1 @@ +* [#480](/~https://github.com/rubocop/rubocop-performance/pull/480): Fix `Performance/Squeeze` cop error on frozen AST string node value. ([@viralpraxis][]) diff --git a/lib/rubocop/cop/performance/squeeze.rb b/lib/rubocop/cop/performance/squeeze.rb index 3176154f88..bf2766a133 100644 --- a/lib/rubocop/cop/performance/squeeze.rb +++ b/lib/rubocop/cop/performance/squeeze.rb @@ -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) diff --git a/spec/rubocop/cop/performance/squeeze_spec.rb b/spec/rubocop/cop/performance/squeeze_spec.rb index 02f73fdc27..8bbdb1b2e5 100644 --- a/spec/rubocop/cop/performance/squeeze_spec.rb +++ b/spec/rubocop/cop/performance/squeeze_spec.rb @@ -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