From 7ac5b60825b09f4d0bd8f02a267150f780046b81 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Wed, 6 Dec 2023 13:19:26 +0900 Subject: [PATCH] [Fix #384] Support optimized `String#dup` for `Performance/UnfreezeString` Resolves #384. This PR supports optimized `String#dup` for `Performance/UnfreezeString` when Ruby 3.3+. To incorporate https://github.com/rubocop/rubocop/commit/d11e25f the RuboCop dependency will be updated to 1.48.1+ from 1.30.0+, but the supported runtime Ruby version will keep at Ruby 2.6+. - https://rubygems.org/gems/rubocop/versions/1.30.0 - https://rubygems.org/gems/rubocop/versions/1.48.1 --- .github/workflows/test.yml | 2 +- ...ing_dup_for_performance_unfreeze_string.md | 1 + .../cop/performance/unfreeze_string.rb | 6 ++--- rubocop-performance.gemspec | 2 +- .../cop/performance/unfreeze_string_spec.rb | 26 +++++++++++++------ 5 files changed, 24 insertions(+), 13 deletions(-) create mode 100644 changelog/new_optimized_string_dup_for_performance_unfreeze_string.md diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 90252d2969..be79dc047f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -76,7 +76,7 @@ jobs: sed -e "/gem 'rubocop', github: 'rubocop\/rubocop'/d" \ -e "/gem 'rubocop-rspec',/d" -i Gemfile cat << EOF > Gemfile.local - gem 'rubocop', '1.30.0' # Specify the oldest supported RuboCop version + gem 'rubocop', '1.48.1' # Specify the oldest supported RuboCop version EOF - name: set up Ruby uses: ruby/setup-ruby@v1 diff --git a/changelog/new_optimized_string_dup_for_performance_unfreeze_string.md b/changelog/new_optimized_string_dup_for_performance_unfreeze_string.md new file mode 100644 index 0000000000..120cb7695a --- /dev/null +++ b/changelog/new_optimized_string_dup_for_performance_unfreeze_string.md @@ -0,0 +1 @@ +* [#384](https://github.com/rubocop/rubocop-performance/issues/384): Support optimized `String#dup` for `Performance/UnfreezeString` when Ruby 3.3+. ([@koic][]) diff --git a/lib/rubocop/cop/performance/unfreeze_string.rb b/lib/rubocop/cop/performance/unfreeze_string.rb index 1b101dc8c8..7f4ef6bd67 100644 --- a/lib/rubocop/cop/performance/unfreeze_string.rb +++ b/lib/rubocop/cop/performance/unfreeze_string.rb @@ -15,8 +15,8 @@ module Performance # # @example # # bad - # ''.dup - # "something".dup + # ''.dup # when Ruby 3.2 or lower + # "something".dup # when Ruby 3.2 or lower # String.new # String.new('') # String.new('something') @@ -45,7 +45,7 @@ class UnfreezeString < Base PATTERN def on_send(node) - return unless dup_string?(node) || string_new?(node) + return unless (dup_string?(node) && target_ruby_version <= 3.2) || string_new?(node) add_offense(node) do |corrector| string_value = "+#{string_value(node)}" diff --git a/rubocop-performance.gemspec b/rubocop-performance.gemspec index 833b605601..2ac1768b58 100644 --- a/rubocop-performance.gemspec +++ b/rubocop-performance.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |s| 'rubygems_mfa_required' => 'true' } - s.add_runtime_dependency('rubocop', '>= 1.30.0', '< 2.0') + s.add_runtime_dependency('rubocop', '>= 1.48.1', '< 2.0') s.add_runtime_dependency('rubocop-ast', '>= 1.30.0', '< 2.0') end diff --git a/spec/rubocop/cop/performance/unfreeze_string_spec.rb b/spec/rubocop/cop/performance/unfreeze_string_spec.rb index d8e27b6151..c782e78966 100644 --- a/spec/rubocop/cop/performance/unfreeze_string_spec.rb +++ b/spec/rubocop/cop/performance/unfreeze_string_spec.rb @@ -1,15 +1,25 @@ # frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::UnfreezeString, :config do - it 'registers an offense and corrects for an empty string with `.dup`' do - expect_offense(<<~RUBY) - "".dup - ^^^^^^ Use unary plus to get an unfrozen string literal. - RUBY + context 'when Ruby <= 3.2', :ruby32 do + it 'registers an offense and corrects for an empty string with `.dup`' do + expect_offense(<<~RUBY) + "".dup + ^^^^^^ Use unary plus to get an unfrozen string literal. + RUBY - expect_correction(<<~RUBY) - +"" - RUBY + expect_correction(<<~RUBY) + +"" + RUBY + end + end + + context 'when Ruby >= 3.3', :ruby33 do + it 'does not register an offense and corrects for an empty string with `.dup`' do + expect_no_offenses(<<~RUBY) + "".dup + RUBY + end end it 'registers an offense and corrects for a string with `.dup`' do