diff --git a/changelog/fix_recover_ruby_24_code_analysis.md b/changelog/fix_recover_ruby_24_code_analysis.md new file mode 100644 index 00000000000..d7ff16cc3a5 --- /dev/null +++ b/changelog/fix_recover_ruby_24_code_analysis.md @@ -0,0 +1 @@ +* [#10258](https://github.com/rubocop/rubocop/issues/10258): Recover Ruby 2.4 code analysis using `TargetRubyVersion: 2.4`. ([@koic][]) diff --git a/lib/rubocop/cop/style/hash_transform_keys.rb b/lib/rubocop/cop/style/hash_transform_keys.rb index 0cac133ca44..1dcd8826c56 100644 --- a/lib/rubocop/cop/style/hash_transform_keys.rb +++ b/lib/rubocop/cop/style/hash_transform_keys.rb @@ -7,6 +7,8 @@ module Style # `_.map {...}.to_h`, and `Hash[_.map {...}]` that are actually just # transforming the keys of a hash, and tries to use a simpler & faster # call to `transform_keys` instead. + # It should only be enabled on Ruby version 2.5 or newer. + # (`transform_keys` was added in Ruby 2.5.) # # @safety # This cop is unsafe, as it can produce false positives if we are @@ -26,6 +28,9 @@ module Style class HashTransformKeys < Base include HashTransformMethod extend AutoCorrector + extend TargetRubyVersion + + minimum_target_ruby_version 2.5 # @!method on_bad_each_with_object(node) def_node_matcher :on_bad_each_with_object, <<~PATTERN diff --git a/lib/rubocop/cop/style/redundant_begin.rb b/lib/rubocop/cop/style/redundant_begin.rb index 87834c7788d..eb33faefe0a 100644 --- a/lib/rubocop/cop/style/redundant_begin.rb +++ b/lib/rubocop/cop/style/redundant_begin.rb @@ -36,6 +36,7 @@ module Style # do_something # # # bad + # # When using Ruby 2.5 or later. # do_something do # begin # something @@ -75,6 +76,7 @@ def on_def(node) alias on_defs on_def def on_block(node) + return if target_ruby_version < 2.5 return if node.send_node.lambda_literal? return if node.braces? return unless node.body&.kwbegin_type? diff --git a/lib/rubocop/rspec/shared_contexts.rb b/lib/rubocop/rspec/shared_contexts.rb index 984146ca1b0..d72630ddf1d 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.4', :ruby24 do + let(:ruby_version) { 2.4 } +end + RSpec.shared_context 'ruby 2.5', :ruby25 do let(:ruby_version) { 2.5 } end diff --git a/lib/rubocop/target_ruby.rb b/lib/rubocop/target_ruby.rb index 741eecd55f0..5569a05cc47 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.5, 2.6, 2.7, 3.0, 3.1, 3.2].freeze + KNOWN_RUBIES = [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 3ebc19a85b9..96c868c6017 100644 --- a/spec/rubocop/cli_spec.rb +++ b/spec/rubocop/cli_spec.rb @@ -1693,7 +1693,9 @@ def method(foo, bar, qux, fred, arg5, f) end #{'#' * 85} expect($stderr.string.strip).to start_with( 'Error: RuboCop found unknown Ruby version 4.0 in `TargetRubyVersion`' ) - expect($stderr.string.strip).to match(/Supported versions: 2.5, 2.6, 2.7, 3.0, 3.1, 3.2/) + expect($stderr.string.strip).to match( + /Supported versions: 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2/ + ) end end @@ -1714,7 +1716,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.5/) + expect($stderr.string.strip).to match(/Supported versions: 2.4/) end end end diff --git a/spec/rubocop/config_loader_spec.rb b/spec/rubocop/config_loader_spec.rb index 399169cea61..aeafcc13b28 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.4' } + let(:inherited_version) { '2.3' } 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.4') + expect(error.message).to start_with('RuboCop found unsupported Ruby version 2.3') end end end diff --git a/spec/rubocop/cop/lint/suppressed_exception_spec.rb b/spec/rubocop/cop/lint/suppressed_exception_spec.rb index cd5a5c7aac4..b4360f54a0f 100644 --- a/spec/rubocop/cop/lint/suppressed_exception_spec.rb +++ b/spec/rubocop/cop/lint/suppressed_exception_spec.rb @@ -114,25 +114,27 @@ def self.foo end end - context 'when empty rescue for `do` block' do - it 'registers an offense for empty rescue without comment' do - expect_offense(<<~RUBY) - foo do - do_something - rescue - ^^^^^^ Do not suppress exceptions. - end - RUBY - end + context 'Ruby 2.5 or higher', :ruby25 do + context 'when empty rescue for `do` block' do + it 'registers an offense for empty rescue without comment' do + expect_offense(<<~RUBY) + foo do + do_something + rescue + ^^^^^^ Do not suppress exceptions. + end + RUBY + end - it 'registers an offense for empty rescue with comment' do - expect_offense(<<~RUBY) - foo do - rescue - ^^^^^^ Do not suppress exceptions. - # do nothing - end - RUBY + it 'registers an offense for empty rescue with comment' do + expect_offense(<<~RUBY) + foo do + rescue + ^^^^^^ Do not suppress exceptions. + # do nothing + end + RUBY + end end end end @@ -195,24 +197,26 @@ def self.foo end end - context 'when empty rescue for `do` block' do - it 'registers an offense for empty rescue without comment' do - expect_offense(<<~RUBY) - foo do - do_something - rescue - ^^^^^^ Do not suppress exceptions. - end - RUBY - end + context 'Ruby 2.5 or higher', :ruby25 do + context 'when empty rescue for `do` block' do + it 'registers an offense for empty rescue without comment' do + expect_offense(<<~RUBY) + foo do + do_something + rescue + ^^^^^^ Do not suppress exceptions. + end + RUBY + end - it 'does not register an offense for empty rescue with comment' do - expect_no_offenses(<<~RUBY) - foo do - rescue - # do nothing - end - RUBY + it 'does not register an offense for empty rescue with comment' do + expect_no_offenses(<<~RUBY) + foo do + rescue + # do nothing + end + RUBY + end end end diff --git a/spec/rubocop/cop/style/hash_transform_keys_spec.rb b/spec/rubocop/cop/style/hash_transform_keys_spec.rb index 6a538e56807..31424f1d6c4 100644 --- a/spec/rubocop/cop/style/hash_transform_keys_spec.rb +++ b/spec/rubocop/cop/style/hash_transform_keys_spec.rb @@ -1,251 +1,259 @@ # frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::HashTransformKeys, :config do - context 'with inline block' do - it 'flags each_with_object when transform_keys could be used' do - expect_offense(<<~RUBY) - x.each_with_object({}) {|(k, v), h| h[foo(k)] = v} - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `each_with_object`. + context 'when using Ruby 2.5 or newer', :ruby25 do + context 'with inline block' do + it 'flags each_with_object when transform_keys could be used' do + expect_offense(<<~RUBY) + x.each_with_object({}) {|(k, v), h| h[foo(k)] = v} + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `each_with_object`. + RUBY + + expect_correction(<<~RUBY) + x.transform_keys {|k| foo(k)} + RUBY + end + end + + context 'with multiline block' do + it 'flags each_with_object when transform_keys could be used' do + expect_offense(<<~RUBY) + some_hash.each_with_object({}) do |(key, val), memo| + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `each_with_object`. + memo[key.to_sym] = val + end + RUBY + + expect_correction(<<~RUBY) + some_hash.transform_keys do |key| + key.to_sym + end + RUBY + end + end + + context 'with safe navigation operator' do + it 'flags each_with_object when transform_keys could be used' do + expect_offense(<<~RUBY) + x&.each_with_object({}) {|(k, v), h| h[foo(k)] = v} + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `each_with_object`. + RUBY + + expect_correction(<<~RUBY) + x&.transform_keys {|k| foo(k)} + RUBY + end + end + + it 'does not flag each_with_object when both key & value are transformed' do + expect_no_offenses(<<~RUBY) + x.each_with_object({}) {|(k, v), h| h[k.to_sym] = foo(v)} RUBY + end - expect_correction(<<~RUBY) - x.transform_keys {|k| foo(k)} + it 'does not flag each_with_object when key transformation uses value' do + expect_no_offenses('x.each_with_object({}) {|(k, v), h| h[foo(v)] = v}') + end + + it 'does not flag each_with_object when no transformation occurs' do + expect_no_offenses('x.each_with_object({}) {|(k, v), h| h[k] = v}') + end + + it 'does not flag each_with_object when its argument is not modified' do + expect_no_offenses(<<~RUBY) + x.each_with_object({}) {|(k, v), h| other_h[k.to_sym] = v} RUBY end - end - context 'with multiline block' do - it 'flags each_with_object when transform_keys could be used' do - expect_offense(<<~RUBY) - some_hash.each_with_object({}) do |(key, val), memo| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `each_with_object`. - memo[key.to_sym] = val - end + it 'does not flag `each_with_object` when its argument is used in the key' do + expect_no_offenses(<<~RUBY) + x.each_with_object({}) { |(k, v), h| h[h[k.to_sym]] = v } RUBY + end - expect_correction(<<~RUBY) - some_hash.transform_keys do |key| - key.to_sym - end + it 'does not flag each_with_object when its receiver is array literal' do + expect_no_offenses(<<~RUBY) + [1, 2, 3].each_with_object({}) {|(k, v), h| h[foo(k)] = v} + RUBY + end + + it 'does not flag `each_with_object` when its receiver is `each_with_index`' do + expect_no_offenses(<<~RUBY) + [1, 2, 3].each_with_index.each_with_object({}) { |(k, v), h| h[k.to_sym] = v } + RUBY + end + + it 'does not flag `each_with_object` when its receiver is `with_index`' do + expect_no_offenses(<<~RUBY) + [1, 2, 3].each.with_index.each_with_object({}) { |(k, v), h| h[k.to_sym] = v } RUBY end - end - context 'with safe navigation operator' do - it 'flags each_with_object when transform_keys could be used' do + it 'does not flag `each_with_object` when its receiver is `zip`' do + expect_no_offenses(<<~RUBY) + %i[a b c].zip([1, 2, 3]).each_with_object({}) { |(k, v), h| h[k.to_sym] = v } + RUBY + end + + it 'flags _.map{...}.to_h when transform_keys could be used' do expect_offense(<<~RUBY) - x&.each_with_object({}) {|(k, v), h| h[foo(k)] = v} - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `each_with_object`. + x.map {|k, v| [k.to_sym, v]}.to_h + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `map {...}.to_h`. RUBY expect_correction(<<~RUBY) - x&.transform_keys {|k| foo(k)} + x.transform_keys {|k| k.to_sym} RUBY end - end - it 'does not flag each_with_object when both key & value are transformed' do - expect_no_offenses(<<~RUBY) - x.each_with_object({}) {|(k, v), h| h[k.to_sym] = foo(v)} - RUBY - end + it 'flags _.map{...}.to_h when transform_keys could be used when line break before `to_h`' do + expect_offense(<<~RUBY) + x.map {|k, v| [k.to_sym, v]}. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `map {...}.to_h`. + to_h + RUBY - it 'does not flag each_with_object when key transformation uses value' do - expect_no_offenses('x.each_with_object({}) {|(k, v), h| h[foo(v)] = v}') - end + expect_correction(<<~RUBY) + x.transform_keys {|k| k.to_sym} + RUBY + end - it 'does not flag each_with_object when no transformation occurs' do - expect_no_offenses('x.each_with_object({}) {|(k, v), h| h[k] = v}') - end + it 'flags _.map {...}.to_h when transform_keys could be used when wrapped in another block' do + expect_offense(<<~RUBY) + wrapping do + x.map do |k, v| + ^^^^^^^^^^^^^^^ Prefer `transform_keys` over `map {...}.to_h`. + [k.to_sym, v] + end.to_h + end + RUBY - it 'does not flag each_with_object when its argument is not modified' do - expect_no_offenses(<<~RUBY) - x.each_with_object({}) {|(k, v), h| other_h[k.to_sym] = v} - RUBY - end + expect_correction(<<~RUBY) + wrapping do + x.transform_keys do |k| + k.to_sym + end + end + RUBY + end - it 'does not flag `each_with_object` when its argument is used in the key' do - expect_no_offenses(<<~RUBY) - x.each_with_object({}) { |(k, v), h| h[h[k.to_sym]] = v } - RUBY - end + it 'does not flag _.map{...}.to_h when both key & value are transformed' do + expect_no_offenses('x.map {|k, v| [k.to_sym, foo(v)]}.to_h') + end - it 'does not flag each_with_object when its receiver is array literal' do - expect_no_offenses(<<~RUBY) - [1, 2, 3].each_with_object({}) {|(k, v), h| h[foo(k)] = v} - RUBY - end + it 'flags Hash[_.map{...}] when transform_keys could be used' do + expect_offense(<<~RUBY) + Hash[x.map {|k, v| [k.to_sym, v]}] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `Hash[_.map {...}]`. + RUBY - it 'does not flag `each_with_object` when its receiver is `each_with_index`' do - expect_no_offenses(<<~RUBY) - [1, 2, 3].each_with_index.each_with_object({}) { |(k, v), h| h[k.to_sym] = v } - RUBY - end + expect_correction(<<~RUBY) + x.transform_keys {|k| k.to_sym} + RUBY + end - it 'does not flag `each_with_object` when its receiver is `with_index`' do - expect_no_offenses(<<~RUBY) - [1, 2, 3].each.with_index.each_with_object({}) { |(k, v), h| h[k.to_sym] = v } - RUBY - end + it 'does not flag Hash[_.map{...}] when both key & value are transformed' do + expect_no_offenses('Hash[x.map {|k, v| [k.to_sym, foo(v)]}]') + end - it 'does not flag `each_with_object` when its receiver is `zip`' do - expect_no_offenses(<<~RUBY) - %i[a b c].zip([1, 2, 3]).each_with_object({}) { |(k, v), h| h[k.to_sym] = v } - RUBY - end + it 'does not flag key transformation in the absence of to_h' do + expect_no_offenses('x.map {|k, v| [k.to_sym, v]}') + end - it 'flags _.map{...}.to_h when transform_keys could be used' do - expect_offense(<<~RUBY) - x.map {|k, v| [k.to_sym, v]}.to_h - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `map {...}.to_h`. - RUBY + it 'does not flag key transformation when receiver is array literal' do + expect_no_offenses(<<~RUBY) + [1, 2, 3].map {|k, v| [k.to_sym, v]}.to_h + RUBY + end - expect_correction(<<~RUBY) - x.transform_keys {|k| k.to_sym} - RUBY - end + it 'does not flag `_.map{...}.to_h` when its receiver is `each_with_index`' do + expect_no_offenses(<<~RUBY) + [1, 2, 3].each_with_index.map { |k, v| [k.to_sym, v] }.to_h + RUBY + end - it 'flags _.map{...}.to_h when transform_keys could be used when line break before `to_h`' do - expect_offense(<<~RUBY) - x.map {|k, v| [k.to_sym, v]}. - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `map {...}.to_h`. - to_h - RUBY + it 'does not flag `_.map{...}.to_h` when its receiver is `with_index`' do + expect_no_offenses(<<~RUBY) + [1, 2, 3].each.with_index.map { |k, v| [k.to_sym, v] }.to_h + RUBY + end - expect_correction(<<~RUBY) - x.transform_keys {|k| k.to_sym} - RUBY - end + it 'does not flag `_.map{...}.to_h` when its receiver is `zip`' do + expect_no_offenses(<<~RUBY) + %i[a b c].zip([1, 2, 3]).map { |k, v| [k.to_sym, v] }.to_h + RUBY + end - it 'flags _.map {...}.to_h when transform_keys could be used when wrapped in another block' do - expect_offense(<<~RUBY) - wrapping do - x.map do |k, v| - ^^^^^^^^^^^^^^^ Prefer `transform_keys` over `map {...}.to_h`. - [k.to_sym, v] + it 'correctly autocorrects _.map{...}.to_h without block' do + expect_offense(<<~RUBY) + {a: 1, b: 2}.map do |k, v| + ^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `map {...}.to_h`. + [k.to_s, v] end.to_h - end - RUBY + RUBY - expect_correction(<<~RUBY) - wrapping do - x.transform_keys do |k| - k.to_sym + expect_correction(<<~RUBY) + {a: 1, b: 2}.transform_keys do |k| + k.to_s end - end - RUBY - end - - it 'does not flag _.map{...}.to_h when both key & value are transformed' do - expect_no_offenses('x.map {|k, v| [k.to_sym, foo(v)]}.to_h') - end - - it 'flags Hash[_.map{...}] when transform_keys could be used' do - expect_offense(<<~RUBY) - Hash[x.map {|k, v| [k.to_sym, v]}] - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `Hash[_.map {...}]`. - RUBY - - expect_correction(<<~RUBY) - x.transform_keys {|k| k.to_sym} - RUBY - end - - it 'does not flag Hash[_.map{...}] when both key & value are transformed' do - expect_no_offenses('Hash[x.map {|k, v| [k.to_sym, foo(v)]}]') - end - - it 'does not flag key transformation in the absence of to_h' do - expect_no_offenses('x.map {|k, v| [k.to_sym, v]}') - end - - it 'does not flag key transformation when receiver is array literal' do - expect_no_offenses(<<~RUBY) - [1, 2, 3].map {|k, v| [k.to_sym, v]}.to_h - RUBY - end - - it 'does not flag `_.map{...}.to_h` when its receiver is `each_with_index`' do - expect_no_offenses(<<~RUBY) - [1, 2, 3].each_with_index.map { |k, v| [k.to_sym, v] }.to_h - RUBY - end - - it 'does not flag `_.map{...}.to_h` when its receiver is `with_index`' do - expect_no_offenses(<<~RUBY) - [1, 2, 3].each.with_index.map { |k, v| [k.to_sym, v] }.to_h - RUBY - end + RUBY + end - it 'does not flag `_.map{...}.to_h` when its receiver is `zip`' do - expect_no_offenses(<<~RUBY) - %i[a b c].zip([1, 2, 3]).map { |k, v| [k.to_sym, v] }.to_h - RUBY - end + it 'correctly autocorrects _.map{...}.to_h with block' do + expect_offense(<<~RUBY) + {a: 1, b: 2}.map {|k, v| [k.to_s, v]}.to_h {|k, v| [v, k]} + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `map {...}.to_h`. + RUBY - it 'correctly autocorrects _.map{...}.to_h without block' do - expect_offense(<<~RUBY) - {a: 1, b: 2}.map do |k, v| - ^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `map {...}.to_h`. - [k.to_s, v] - end.to_h - RUBY - - expect_correction(<<~RUBY) - {a: 1, b: 2}.transform_keys do |k| - k.to_s - end - RUBY - end + expect_correction(<<~RUBY) + {a: 1, b: 2}.transform_keys {|k| k.to_s}.to_h {|k, v| [v, k]} + RUBY + end - it 'correctly autocorrects _.map{...}.to_h with block' do - expect_offense(<<~RUBY) - {a: 1, b: 2}.map {|k, v| [k.to_s, v]}.to_h {|k, v| [v, k]} - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `map {...}.to_h`. - RUBY + it 'correctly autocorrects Hash[_.map{...}]' do + expect_offense(<<~RUBY) + Hash[{a: 1, b: 2}.map do |k, v| + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `Hash[_.map {...}]`. + [k.to_s, v] + end] + RUBY - expect_correction(<<~RUBY) - {a: 1, b: 2}.transform_keys {|k| k.to_s}.to_h {|k, v| [v, k]} - RUBY - end + expect_correction(<<~RUBY) + {a: 1, b: 2}.transform_keys do |k| + k.to_s + end + RUBY + end - it 'correctly autocorrects Hash[_.map{...}]' do - expect_offense(<<~RUBY) - Hash[{a: 1, b: 2}.map do |k, v| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_keys` over `Hash[_.map {...}]`. - [k.to_s, v] - end] - RUBY - - expect_correction(<<~RUBY) - {a: 1, b: 2}.transform_keys do |k| - k.to_s - end - RUBY - end + it 'does not flag `Hash[_.map{...}]` when its receiver is an array literal' do + expect_no_offenses(<<~RUBY) + Hash[[1, 2, 3].map { |k, v| [k.to_sym, v] }] + RUBY + end - it 'does not flag `Hash[_.map{...}]` when its receiver is an array literal' do - expect_no_offenses(<<~RUBY) - Hash[[1, 2, 3].map { |k, v| [k.to_sym, v] }] - RUBY - end + it 'does not flag `Hash[_.map{...}]` when its receiver is `each_with_index`' do + expect_no_offenses(<<~RUBY) + Hash[[1, 2, 3].each_with_index.map { |k, v| [k.to_sym, v] }] + RUBY + end - it 'does not flag `Hash[_.map{...}]` when its receiver is `each_with_index`' do - expect_no_offenses(<<~RUBY) - Hash[[1, 2, 3].each_with_index.map { |k, v| [k.to_sym, v] }] - RUBY - end + it 'does not flag `Hash[_.map{...}]` when its receiver is `with_index`' do + expect_no_offenses(<<~RUBY) + Hash[[1, 2, 3].each.with_index.map { |k, v| [k.to_sym, v] }] + RUBY + end - it 'does not flag `Hash[_.map{...}]` when its receiver is `with_index`' do - expect_no_offenses(<<~RUBY) - Hash[[1, 2, 3].each.with_index.map { |k, v| [k.to_sym, v] }] - RUBY + it 'does not flag `Hash[_.map{...}]` when its receiver is `zip`' do + expect_no_offenses(<<~RUBY) + Hash[%i[a b c].zip([1, 2, 3]).map { |k, v| [k.to_sym, v] }] + RUBY + end end - it 'does not flag `Hash[_.map{...}]` when its receiver is `zip`' do - expect_no_offenses(<<~RUBY) - Hash[%i[a b c].zip([1, 2, 3]).map { |k, v| [k.to_sym, v] }] - RUBY + context 'below Ruby 2.5', :ruby24 do + it 'does not flag even if transform_keys could be used' do + expect_no_offenses('x.each_with_object({}) {|(k, v), h| h[foo(k)] = v}') + end end context 'when using Ruby 2.6 or newer', :ruby26 do diff --git a/spec/rubocop/cop/style/redundant_begin_spec.rb b/spec/rubocop/cop/style/redundant_begin_spec.rb index 30efadf83eb..6e16cf89ece 100644 --- a/spec/rubocop/cop/style/redundant_begin_spec.rb +++ b/spec/rubocop/cop/style/redundant_begin_spec.rb @@ -344,76 +344,92 @@ def method RUBY end - it 'registers an offense for a do-end block with redundant begin-end' do - expect_offense(<<~RUBY) - do_something do - begin - ^^^^^ Redundant `begin` block detected. - foo - rescue => e - bar + context '< Ruby 2.5', :ruby24 do + it 'accepts a do-end block with a begin-end' do + expect_no_offenses(<<~RUBY) + do_something do + begin + foo + rescue => e + bar + end end - end - RUBY - - expect_correction(<<~RUBY) - do_something do - #{trailing_whitespace} - foo - rescue => e - bar - #{trailing_whitespace} - end - RUBY + RUBY + end end - it 'accepts a {} block with a begin-end' do - expect_no_offenses(<<~RUBY) - do_something { - begin - foo - rescue => e - bar + context '>= ruby 2.5', :ruby25 do + it 'registers an offense for a do-end block with redundant begin-end' do + expect_offense(<<~RUBY) + do_something do + begin + ^^^^^ Redundant `begin` block detected. + foo + rescue => e + bar + end end - } - RUBY - end + RUBY - it 'accepts a block with a begin block after a statement' do - expect_no_offenses(<<~RUBY) - do_something do - something - begin - ala - rescue => e - bala + expect_correction(<<~RUBY) + do_something do + #{trailing_whitespace} + foo + rescue => e + bar + #{trailing_whitespace} end - end - RUBY - end + RUBY + end - it 'accepts a stabby lambda with a begin-end' do - expect_no_offenses(<<~RUBY) - -> do - begin - foo - rescue => e - bar + it 'accepts a {} block with a begin-end' do + expect_no_offenses(<<~RUBY) + do_something { + begin + foo + rescue => e + bar + end + } + RUBY + end + + it 'accepts a block with a begin block after a statement' do + expect_no_offenses(<<~RUBY) + do_something do + something + begin + ala + rescue => e + bala + end end - end - RUBY - end + RUBY + end - it 'accepts super with block' do - expect_no_offenses(<<~RUBY) - def a_method - super do |arg| - foo - rescue => e - bar + it 'accepts a stabby lambda with a begin-end' do + expect_no_offenses(<<~RUBY) + -> do + begin + foo + rescue => e + bar + end end - end - RUBY + RUBY + end + + it 'accepts super with block' do + expect_no_offenses(<<~RUBY) + def a_method + super do |arg| + foo + rescue => e + bar + end + end + RUBY + end end it 'accepts when one-liner `begin` block has multiple statements with modifier condition' do