From 2319c31326bb6111b6e8fd5ee1a179e518d41e70 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Tue, 17 May 2022 00:02:31 +0900 Subject: [PATCH] Recover Ruby 2.1 code analysis using `TargetRubyVersion: 2.1` Follow up https://github.com/rubocop/rubocop/pull/10632#issuecomment-1125909580. Reverts part of #5990 and #6101. Only the Ruby version (2.1) to runtime should have been dropped, not code analysis. This PR makes Ruby 2.1 code analysis with `TargetRubyVersion: 2.1`. It aims to solve essentially the same problem as #10626, #10632, #10640, and #10644. --- .../fix_recover_ruby_21_code_analysis.md | 1 + .../cop/lint/redundant_require_statement.rb | 3 + lib/rubocop/rspec/shared_contexts.rb | 4 + lib/rubocop/target_ruby.rb | 2 +- spec/rubocop/cli_spec.rb | 4 +- spec/rubocop/config_loader_spec.rb | 4 +- .../lint/redundant_require_statement_spec.rb | 28 +++++-- .../cop/lint/unused_method_argument_spec.rb | 20 +++-- spec/rubocop/cop/style/hash_syntax_spec.rb | 82 +++++++++++++++++++ 9 files changed, 125 insertions(+), 23 deletions(-) create mode 100644 changelog/fix_recover_ruby_21_code_analysis.md diff --git a/changelog/fix_recover_ruby_21_code_analysis.md b/changelog/fix_recover_ruby_21_code_analysis.md new file mode 100644 index 00000000000..b1d42a1bffc --- /dev/null +++ b/changelog/fix_recover_ruby_21_code_analysis.md @@ -0,0 +1 @@ +* [#10662](https://github.com/rubocop/rubocop/pull/10662): Recover Ruby 2.1 code analysis using `TargetRubyVersion: 2.1`. ([@koic][]) diff --git a/lib/rubocop/cop/lint/redundant_require_statement.rb b/lib/rubocop/cop/lint/redundant_require_statement.rb index 142c812f741..3b2af97310c 100644 --- a/lib/rubocop/cop/lint/redundant_require_statement.rb +++ b/lib/rubocop/cop/lint/redundant_require_statement.rb @@ -24,6 +24,9 @@ module Lint class RedundantRequireStatement < Base include RangeHelp extend AutoCorrector + extend TargetRubyVersion + + minimum_target_ruby_version 2.2 MSG = 'Remove unnecessary `require` statement.' RESTRICT_ON_SEND = %i[require].freeze diff --git a/lib/rubocop/rspec/shared_contexts.rb b/lib/rubocop/rspec/shared_contexts.rb index 7c3c2a419a2..5046de6b058 100644 --- a/lib/rubocop/rspec/shared_contexts.rb +++ b/lib/rubocop/rspec/shared_contexts.rb @@ -116,6 +116,10 @@ def source_range(range, buffer: source_buffer) end end +RSpec.shared_context 'ruby 2.1', :ruby21 do + let(:ruby_version) { 2.1 } +end + RSpec.shared_context 'ruby 2.2', :ruby22 do let(:ruby_version) { 2.2 } end diff --git a/lib/rubocop/target_ruby.rb b/lib/rubocop/target_ruby.rb index 05d93efa3cf..0ae7a8f52ea 100644 --- a/lib/rubocop/target_ruby.rb +++ b/lib/rubocop/target_ruby.rb @@ -4,7 +4,7 @@ module RuboCop # The kind of Ruby that code inspected by RuboCop is written in. # @api private class TargetRuby - KNOWN_RUBIES = [2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2].freeze + KNOWN_RUBIES = [2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2].freeze DEFAULT_VERSION = 2.6 OBSOLETE_RUBIES = { diff --git a/spec/rubocop/cli_spec.rb b/spec/rubocop/cli_spec.rb index 5caab7aefb5..af36786db94 100644 --- a/spec/rubocop/cli_spec.rb +++ b/spec/rubocop/cli_spec.rb @@ -1724,7 +1724,7 @@ def method(foo, bar, qux, fred, arg5, f) end #{'#' * 85} 'Error: RuboCop found unknown Ruby version 4.0 in `TargetRubyVersion`' ) expect($stderr.string.strip).to match( - /Supported versions: 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2/ + /Supported versions: 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2/ ) end end @@ -1746,7 +1746,7 @@ def method(foo, bar, qux, fred, arg5, f) end #{'#' * 85} /2\.0-compatible analysis was dropped after version 0\.50/ ) - expect($stderr.string.strip).to match(/Supported versions: 2.2/) + expect($stderr.string.strip).to match(/Supported versions: 2.1/) end end end diff --git a/spec/rubocop/config_loader_spec.rb b/spec/rubocop/config_loader_spec.rb index c4cd1b00e20..77e7fe77a37 100644 --- a/spec/rubocop/config_loader_spec.rb +++ b/spec/rubocop/config_loader_spec.rb @@ -1188,7 +1188,7 @@ class Loop < Base end context 'when the specified version is obsolete' do - let(:inherited_version) { '2.1' } + let(:inherited_version) { '2.0' } context 'and it is not overridden' do before do @@ -1199,7 +1199,7 @@ class Loop < Base it 'raises a validation error' do expect { configuration_from_file }.to raise_error(RuboCop::ValidationError) do |error| - expect(error.message).to start_with('RuboCop found unsupported Ruby version 2.1') + expect(error.message).to start_with('RuboCop found unsupported Ruby version 2.0') end end end diff --git a/spec/rubocop/cop/lint/redundant_require_statement_spec.rb b/spec/rubocop/cop/lint/redundant_require_statement_spec.rb index 4629392468a..71e457dfabb 100644 --- a/spec/rubocop/cop/lint/redundant_require_statement_spec.rb +++ b/spec/rubocop/cop/lint/redundant_require_statement_spec.rb @@ -1,15 +1,25 @@ # frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::RedundantRequireStatement, :config do - it "registers an offense and corrects when using `require 'enumerator'`" do - expect_offense(<<~RUBY) - require 'enumerator' - ^^^^^^^^^^^^^^^^^^^^ Remove unnecessary `require` statement. - require 'uri' - RUBY + context 'target ruby version < 2.2', :ruby21 do + it "does not registers an offense when using `require 'enumerator'`" do + expect_no_offenses(<<~RUBY) + require 'enumerator' + RUBY + end + end + + context 'target ruby version >= 2.2', :ruby22 do + it "registers an offense and corrects when using `require 'enumerator'`" do + expect_offense(<<~RUBY) + require 'enumerator' + ^^^^^^^^^^^^^^^^^^^^ Remove unnecessary `require` statement. + require 'uri' + RUBY - expect_correction(<<~RUBY) - require 'uri' - RUBY + expect_correction(<<~RUBY) + require 'uri' + RUBY + end end end diff --git a/spec/rubocop/cop/lint/unused_method_argument_spec.rb b/spec/rubocop/cop/lint/unused_method_argument_spec.rb index df776748e2d..b17d242d740 100644 --- a/spec/rubocop/cop/lint/unused_method_argument_spec.rb +++ b/spec/rubocop/cop/lint/unused_method_argument_spec.rb @@ -154,16 +154,18 @@ def some_method(foo, _bar = 1) end end - context 'when a required keyword argument is unused' do - it 'registers an offense but does not suggest underscore-prefix' do - expect_offense(<<~RUBY) - def self.some_method(foo, bar:) - ^^^ Unused method argument - `bar`. - puts foo - end - RUBY + context 'when a required keyword argument is unused', ruby: 2.1 do + context 'when a required keyword argument is unused' do + it 'registers an offense but does not suggest underscore-prefix' do + expect_offense(<<~RUBY) + def self.some_method(foo, bar:) + ^^^ Unused method argument - `bar`. + puts foo + end + RUBY - expect_no_corrections + expect_no_corrections + end end end diff --git a/spec/rubocop/cop/style/hash_syntax_spec.rb b/spec/rubocop/cop/style/hash_syntax_spec.rb index 12851726295..0c1f32d05fc 100644 --- a/spec/rubocop/cop/style/hash_syntax_spec.rb +++ b/spec/rubocop/cop/style/hash_syntax_spec.rb @@ -68,6 +68,12 @@ expect_no_offenses('{}') end + context 'ruby < 2.2', :ruby21 do + it 'accepts hash rockets when symbol keys have string in them' do + expect_no_offenses('x = { :"string" => 0 }') + end + end + it 'registers an offense when symbol keys have strings in them' do expect_offense(<<~RUBY) x = { :"string" => 0 } @@ -472,6 +478,44 @@ RUBY end + context 'ruby < 2.2', :ruby21 do + it 'accepts hash rockets when keys have whitespaces in them' do + expect_no_offenses('x = { :"t o" => 0, :b => 1 }') + end + + it 'registers an offense when keys have whitespaces and mix styles' do + expect_offense(<<~RUBY) + x = { :"t o" => 0, b: 1 } + ^^ Don't mix styles in the same hash. + RUBY + expect(cop.config_to_allow_offenses).to eq('Enabled' => false) + end + + it 'accepts hash rockets when keys have special symbols in them' do + expect_no_offenses('x = { :"\\tab" => 1, :b => 1 }') + end + + it 'registers an offense when keys have special symbols and mix styles' do + expect_offense(<<~RUBY) + x = { :"\tab" => 1, b: 1 } + ^^ Don't mix styles in the same hash. + RUBY + expect(cop.config_to_allow_offenses).to eq('Enabled' => false) + end + + it 'accepts hash rockets when keys start with a digit' do + expect_no_offenses('x = { :"1" => 1, :b => 1 }') + end + + it 'registers an offense when keys start with a digit and mix styles' do + expect_offense(<<~RUBY) + x = { :"1" => 1, b: 1 } + ^^ Don't mix styles in the same hash. + RUBY + expect(cop.config_to_allow_offenses).to eq('Enabled' => false) + end + end + it 'registers an offense when keys have whitespaces in them' do expect_offense(<<~RUBY) x = { :"t o" => 0 } @@ -614,6 +658,44 @@ RUBY end + context 'ruby < 2.2', :ruby21 do + it 'accepts hash rockets when keys have whitespaces in them' do + expect_no_offenses('x = { :"t o" => 0, :b => 1 }') + end + + it 'registers an offense when keys have whitespaces and mix styles' do + expect_offense(<<~RUBY) + x = { :"t o" => 0, b: 1 } + ^^ Don't mix styles in the same hash. + RUBY + expect(cop.config_to_allow_offenses).to eq('Enabled' => false) + end + + it 'accepts hash rockets when keys have special symbols in them' do + expect_no_offenses('x = { :"\\tab" => 1, :b => 1 }') + end + + it 'registers an offense when keys have special symbols and mix styles' do + expect_offense(<<~RUBY) + x = { :"\tab" => 1, b: 1 } + ^^ Don't mix styles in the same hash. + RUBY + expect(cop.config_to_allow_offenses).to eq('Enabled' => false) + end + + it 'accepts hash rockets when keys start with a digit' do + expect_no_offenses('x = { :"1" => 1, :b => 1 }') + end + + it 'registers an offense when keys start with a digit and mix styles' do + expect_offense(<<~RUBY) + x = { :"1" => 1, b: 1 } + ^^ Don't mix styles in the same hash. + RUBY + expect(cop.config_to_allow_offenses).to eq('Enabled' => false) + end + end + it 'registers an offense when keys have whitespaces in them' do expect_offense(<<~RUBY) x = { :"t o" => 0 }