From a14ff0f57548eedbbf9ee6c449673c2b63352b51 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Mon, 16 May 2022 09:49:26 +0900 Subject: [PATCH] Recover Ruby 2.2 code analysis using `TargetRubyVersion: 2.2` Follow up https://github.com/rubocop/rubocop/pull/10632#issuecomment-1125909580. Reverts part of #6766, #7026, and #7030. Only the Ruby version (2.2) to runtime should have been dropped, not code analysis. This PR makes Ruby 2.2 code analysis with `TargetRubyVersion: 2.2`. It aims to solve essentially the same problem as #10626, #10632, and #10640. Previously, there was the following default enforced style `when_needed` for `Style/FrozenStringLiteralComment` cop. ```ruby # @example EnforcedStyle: when_needed (default) # # The `when_needed` style will add the frozen string literal # # to files only when the `TargetRubyVersion` is set to 2.3+. # # bad # module Foo # # ... # end # # # good # # frozen_string_literal: true # # module Foo # # ... # end ``` This PR does not restore that option, but sets the `minimum_target_ruby_version 2.3` to make `always (default)` apply by default. It is a simple solution that does not handle frozen literal magic comment added in Ruby 2.3 when `TargetRubyVersion` is Ruby 2.2 or lower. --- .../fix_recover_ruby_22_code_analysis.md | 1 + lib/rubocop/cop/lint/safe_navigation_chain.rb | 3 + .../style/frozen_string_literal_comment.rb | 5 +- lib/rubocop/cop/style/numeric_predicate.rb | 10 +- lib/rubocop/cop/util.rb | 2 +- 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 +- .../cop/lint/safe_navigation_chain_spec.rb | 284 +++++++++--------- spec/rubocop/cop/style/empty_literal_spec.rb | 2 +- spec/rubocop/cop/style/for_spec.rb | 2 +- .../frozen_string_literal_comment_spec.rb | 18 ++ spec/rubocop/cop/style/lambda_spec.rb | 2 +- .../cop/style/numeric_predicate_spec.rb | 180 ++++++----- 15 files changed, 299 insertions(+), 224 deletions(-) create mode 100644 changelog/changelog/fix_recover_ruby_22_code_analysis.md diff --git a/changelog/changelog/fix_recover_ruby_22_code_analysis.md b/changelog/changelog/fix_recover_ruby_22_code_analysis.md new file mode 100644 index 00000000000..a283fbf2c04 --- /dev/null +++ b/changelog/changelog/fix_recover_ruby_22_code_analysis.md @@ -0,0 +1 @@ +* [#10644](https://github.com/rubocop/rubocop/pull/10644): Recover Ruby 2.2 code analysis using `TargetRubyVersion: 2.2`. ([@koic][]) diff --git a/lib/rubocop/cop/lint/safe_navigation_chain.rb b/lib/rubocop/cop/lint/safe_navigation_chain.rb index 1c66793f172..232caba3c28 100644 --- a/lib/rubocop/cop/lint/safe_navigation_chain.rb +++ b/lib/rubocop/cop/lint/safe_navigation_chain.rb @@ -25,6 +25,9 @@ module Lint # x&.foo || bar class SafeNavigationChain < Base include NilMethods + extend TargetRubyVersion + + minimum_target_ruby_version 2.3 MSG = 'Do not chain ordinary method call after safe navigation operator.' diff --git a/lib/rubocop/cop/style/frozen_string_literal_comment.rb b/lib/rubocop/cop/style/frozen_string_literal_comment.rb index 62a9b76e42c..e0c2eeac6f7 100644 --- a/lib/rubocop/cop/style/frozen_string_literal_comment.rb +++ b/lib/rubocop/cop/style/frozen_string_literal_comment.rb @@ -8,7 +8,7 @@ module Style # It will add the `# frozen_string_literal: true` magic comment to the top # of files to enable frozen string literals. Frozen string literals may be # default in future Ruby. The comment will be added below a shebang and - # encoding comment. + # encoding comment. The frozen string literal comment is only valid in Ruby 2.3+. # # Note that the cop will accept files where the comment exists but is set # to `false` instead of `true`. @@ -86,6 +86,9 @@ class FrozenStringLiteralComment < Base include FrozenStringLiteral include RangeHelp extend AutoCorrector + extend TargetRubyVersion + + minimum_target_ruby_version 2.3 MSG_MISSING_TRUE = 'Missing magic comment `# frozen_string_literal: true`.' MSG_MISSING = 'Missing frozen string literal comment.' diff --git a/lib/rubocop/cop/style/numeric_predicate.rb b/lib/rubocop/cop/style/numeric_predicate.rb index 38949a2d720..30cdc03b2c0 100644 --- a/lib/rubocop/cop/style/numeric_predicate.rb +++ b/lib/rubocop/cop/style/numeric_predicate.rb @@ -82,7 +82,7 @@ def check(node) predicate(node) end - return unless numeric && operator + return unless numeric && operator && replacement_supported?(operator) [numeric, replacement(numeric, operator)] end @@ -107,6 +107,14 @@ def require_parentheses?(node) node.send_type? && node.binary_operation? && !node.parenthesized? end + def replacement_supported?(operator) + if %i[> <].include?(operator) + target_ruby_version >= 2.3 + else + true + end + end + def invert lambda do |comparison, numeric| comparison = { :> => :<, :< => :> }[comparison] || comparison diff --git a/lib/rubocop/cop/util.rb b/lib/rubocop/cop/util.rb index 8f67f429140..32543a872d4 100644 --- a/lib/rubocop/cop/util.rb +++ b/lib/rubocop/cop/util.rb @@ -159,7 +159,7 @@ def to_supported_styles(enforced_style) private def compatible_external_encoding_for?(src) - src = src.dup if RUBY_ENGINE == 'jruby' + src = src.dup if RUBY_VERSION < '2.3' || RUBY_ENGINE == 'jruby' src.force_encoding(Encoding.default_external).valid_encoding? end end diff --git a/lib/rubocop/rspec/shared_contexts.rb b/lib/rubocop/rspec/shared_contexts.rb index 39a4093a3ba..7c3c2a419a2 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.2', :ruby22 do + let(:ruby_version) { 2.2 } +end + RSpec.shared_context 'ruby 2.3', :ruby23 do let(:ruby_version) { 2.3 } end diff --git a/lib/rubocop/target_ruby.rb b/lib/rubocop/target_ruby.rb index 64cf4e88fb4..05d93efa3cf 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.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2].freeze + KNOWN_RUBIES = [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 50c8770331d..5caab7aefb5 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.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2/ + /Supported versions: 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.3/) + expect($stderr.string.strip).to match(/Supported versions: 2.2/) end end end diff --git a/spec/rubocop/config_loader_spec.rb b/spec/rubocop/config_loader_spec.rb index 7b696d632b9..c4cd1b00e20 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.2' } + let(:inherited_version) { '2.1' } 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.2') + expect(error.message).to start_with('RuboCop found unsupported Ruby version 2.1') end end end diff --git a/spec/rubocop/cop/lint/safe_navigation_chain_spec.rb b/spec/rubocop/cop/lint/safe_navigation_chain_spec.rb index 2b322e31254..f729f6ccb93 100644 --- a/spec/rubocop/cop/lint/safe_navigation_chain_spec.rb +++ b/spec/rubocop/cop/lint/safe_navigation_chain_spec.rb @@ -7,180 +7,182 @@ end end - [ - ['ordinary method chain', 'x.foo.bar.baz'], - ['ordinary method chain with argument', 'x.foo(x).bar(y).baz(z)'], - ['method chain with safe navigation only', 'x&.foo&.bar&.baz'], - ['method chain with safe navigation only with argument', - 'x&.foo(x)&.bar(y)&.baz(z)'], - ['safe navigation at last only', 'x.foo.bar&.baz'], - ['safe navigation at last only with argument', 'x.foo(x).bar(y)&.baz(z)'], - ['safe navigation with == operator', 'x&.foo == bar'], - ['safe navigation with === operator', 'x&.foo === bar'], - ['safe navigation with || operator', 'x&.foo || bar'], - ['safe navigation with && operator', 'x&.foo && bar'], - ['safe navigation with | operator', 'x&.foo | bar'], - ['safe navigation with & operator', 'x&.foo & bar'], - ['safe navigation with `nil?` method', 'x&.foo.nil?'], - ['safe navigation with `present?` method', 'x&.foo.present?'], - ['safe navigation with `blank?` method', 'x&.foo.blank?'], - ['safe navigation with `try` method', 'a&.b.try(:c)'], - ['safe navigation with assignment method', 'x&.foo = bar'], - ['safe navigation with self assignment method', 'x&.foo += bar'], - ['safe navigation with `to_d` method', 'x&.foo.to_d'], - ['safe navigation with `in?` method', 'x&.foo.in?([:baz, :qux])'] - ].each do |name, code| - include_examples 'accepts', name, code - end - - it 'registers an offense for ordinary method call exists after safe navigation method call' do - expect_offense(<<~RUBY) - x&.foo.bar - ^^^^ Do not chain ordinary method call after safe navigation operator. - RUBY - end - - it 'registers an offense for ordinary method call exists after ' \ - 'safe navigation method call with an argument' do - expect_offense(<<~RUBY) - x&.foo(x).bar(y) - ^^^^^^^ Do not chain ordinary method call after safe navigation operator. - RUBY - end + context 'TargetRubyVersion >= 2.3', :ruby23 do + [ + ['ordinary method chain', 'x.foo.bar.baz'], + ['ordinary method chain with argument', 'x.foo(x).bar(y).baz(z)'], + ['method chain with safe navigation only', 'x&.foo&.bar&.baz'], + ['method chain with safe navigation only with argument', + 'x&.foo(x)&.bar(y)&.baz(z)'], + ['safe navigation at last only', 'x.foo.bar&.baz'], + ['safe navigation at last only with argument', 'x.foo(x).bar(y)&.baz(z)'], + ['safe navigation with == operator', 'x&.foo == bar'], + ['safe navigation with === operator', 'x&.foo === bar'], + ['safe navigation with || operator', 'x&.foo || bar'], + ['safe navigation with && operator', 'x&.foo && bar'], + ['safe navigation with | operator', 'x&.foo | bar'], + ['safe navigation with & operator', 'x&.foo & bar'], + ['safe navigation with `nil?` method', 'x&.foo.nil?'], + ['safe navigation with `present?` method', 'x&.foo.present?'], + ['safe navigation with `blank?` method', 'x&.foo.blank?'], + ['safe navigation with `try` method', 'a&.b.try(:c)'], + ['safe navigation with assignment method', 'x&.foo = bar'], + ['safe navigation with self assignment method', 'x&.foo += bar'], + ['safe navigation with `to_d` method', 'x&.foo.to_d'], + ['safe navigation with `in?` method', 'x&.foo.in?([:baz, :qux])'] + ].each do |name, code| + include_examples 'accepts', name, code + end - it 'registers an offense for ordinary method chain exists after safe navigation method call' do - expect_offense(<<~RUBY) - something - x&.foo.bar.baz - ^^^^^^^^ Do not chain ordinary method call after safe navigation operator. - RUBY - end + it 'registers an offense for ordinary method call exists after safe navigation method call' do + expect_offense(<<~RUBY) + x&.foo.bar + ^^^^ Do not chain ordinary method call after safe navigation operator. + RUBY + end - it 'registers an offense for ordinary method chain exists after ' \ - 'safe navigation method call with an argument' do - expect_offense(<<~RUBY) - x&.foo(x).bar(y).baz(z) - ^^^^^^^^^^^^^^ Do not chain ordinary method call after safe navigation operator. - RUBY - end + it 'registers an offense for ordinary method call exists after ' \ + 'safe navigation method call with an argument' do + expect_offense(<<~RUBY) + x&.foo(x).bar(y) + ^^^^^^^ Do not chain ordinary method call after safe navigation operator. + RUBY + end - it 'registers an offense for ordinary method chain exists after ' \ - 'safe navigation method call with a block-pass' do - expect_offense(<<~RUBY) - something - x&.select(&:foo).bar - ^^^^ Do not chain ordinary method call after safe navigation operator. - RUBY - end + it 'registers an offense for ordinary method chain exists after safe navigation method call' do + expect_offense(<<~RUBY) + something + x&.foo.bar.baz + ^^^^^^^^ Do not chain ordinary method call after safe navigation operator. + RUBY + end - it 'registers an offense for ordinary method chain exists after ' \ - 'safe navigation method call with a block' do - expect_offense(<<~RUBY) - something - x&.select { |x| foo(x) }.bar - ^^^^ Do not chain ordinary method call after safe navigation operator. - RUBY - end + it 'registers an offense for ordinary method chain exists after ' \ + 'safe navigation method call with an argument' do + expect_offense(<<~RUBY) + x&.foo(x).bar(y).baz(z) + ^^^^^^^^^^^^^^ Do not chain ordinary method call after safe navigation operator. + RUBY + end - context '>= Ruby 2.7', :ruby27 do it 'registers an offense for ordinary method chain exists after ' \ - 'safe navigation method call with a block using numbered parameter' do + 'safe navigation method call with a block-pass' do expect_offense(<<~RUBY) something - x&.select { foo(_1) }.bar - ^^^^ Do not chain ordinary method call after safe navigation operator. + x&.select(&:foo).bar + ^^^^ Do not chain ordinary method call after safe navigation operator. RUBY end - end - - it 'registers an offense for safe navigation with < operator' do - expect_offense(<<~RUBY) - x&.foo < bar - ^^^^^^ Do not chain ordinary method call after safe navigation operator. - RUBY - end - - it 'registers an offense for safe navigation with > operator' do - expect_offense(<<~RUBY) - x&.foo > bar - ^^^^^^ Do not chain ordinary method call after safe navigation operator. - RUBY - end - it 'registers an offense for safe navigation with <= operator' do - expect_offense(<<~RUBY) - x&.foo <= bar - ^^^^^^^ Do not chain ordinary method call after safe navigation operator. - RUBY - end - - it 'registers an offense for safe navigation with >= operator' do - expect_offense(<<~RUBY) - x&.foo >= bar - ^^^^^^^ Do not chain ordinary method call after safe navigation operator. - RUBY - end + it 'registers an offense for ordinary method chain exists after ' \ + 'safe navigation method call with a block' do + expect_offense(<<~RUBY) + something + x&.select { |x| foo(x) }.bar + ^^^^ Do not chain ordinary method call after safe navigation operator. + RUBY + end - it 'registers an offense for safe navigation with + operator' do - expect_offense(<<~RUBY) - x&.foo + bar - ^^^^^^ Do not chain ordinary method call after safe navigation operator. - RUBY - end + it 'registers an offense for safe navigation with < operator' do + expect_offense(<<~RUBY) + x&.foo < bar + ^^^^^^ Do not chain ordinary method call after safe navigation operator. + RUBY + end - it 'registers an offense for safe navigation with [] operator' do - expect_offense(<<~RUBY) - x&.foo[bar] - ^^^^^ Do not chain ordinary method call after safe navigation operator. - RUBY - end + it 'registers an offense for safe navigation with > operator' do + expect_offense(<<~RUBY) + x&.foo > bar + ^^^^^^ Do not chain ordinary method call after safe navigation operator. + RUBY + end - it 'registers an offense for safe navigation with []= operator' do - expect_offense(<<~RUBY) - x&.foo[bar] = baz - ^^^^^^^^^^^ Do not chain ordinary method call after safe navigation operator. - RUBY - end + it 'registers an offense for safe navigation with <= operator' do + expect_offense(<<~RUBY) + x&.foo <= bar + ^^^^^^^ Do not chain ordinary method call after safe navigation operator. + RUBY + end - context 'proper highlighting' do - it 'when there are methods before' do + it 'registers an offense for safe navigation with >= operator' do expect_offense(<<~RUBY) - something - x&.foo.bar.baz - ^^^^^^^^ Do not chain ordinary method call after safe navigation operator. + x&.foo >= bar + ^^^^^^^ Do not chain ordinary method call after safe navigation operator. RUBY end - it 'when there are methods after' do + it 'registers an offense for safe navigation with + operator' do expect_offense(<<~RUBY) - x&.foo.bar.baz - ^^^^^^^^ Do not chain ordinary method call after safe navigation operator. - something + x&.foo + bar + ^^^^^^ Do not chain ordinary method call after safe navigation operator. RUBY end - it 'when in a method' do + it 'registers an offense for safe navigation with [] operator' do expect_offense(<<~RUBY) - def something - x&.foo.bar.baz - ^^^^^^^^ Do not chain ordinary method call after safe navigation operator. - end + x&.foo[bar] + ^^^^^ Do not chain ordinary method call after safe navigation operator. RUBY end - it 'when in a begin' do + it 'registers an offense for safe navigation with []= operator' do expect_offense(<<~RUBY) - begin + x&.foo[bar] = baz + ^^^^^^^^^^^ Do not chain ordinary method call after safe navigation operator. + RUBY + end + + context 'proper highlighting' do + it 'when there are methods before' do + expect_offense(<<~RUBY) + something x&.foo.bar.baz ^^^^^^^^ Do not chain ordinary method call after safe navigation operator. - end - RUBY + RUBY + end + + it 'when there are methods after' do + expect_offense(<<~RUBY) + x&.foo.bar.baz + ^^^^^^^^ Do not chain ordinary method call after safe navigation operator. + something + RUBY + end + + it 'when in a method' do + expect_offense(<<~RUBY) + def something + x&.foo.bar.baz + ^^^^^^^^ Do not chain ordinary method call after safe navigation operator. + end + RUBY + end + + it 'when in a begin' do + expect_offense(<<~RUBY) + begin + x&.foo.bar.baz + ^^^^^^^^ Do not chain ordinary method call after safe navigation operator. + end + RUBY + end + + it 'when used with a modifier if' do + expect_offense(<<~RUBY) + x&.foo.bar.baz if something + ^^^^^^^^ Do not chain ordinary method call after safe navigation operator. + RUBY + end end + end - it 'when used with a modifier if' do + context '>= Ruby 2.7', :ruby27 do + it 'registers an offense for ordinary method chain exists after ' \ + 'safe navigation method call with a block using numbered parameter' do expect_offense(<<~RUBY) - x&.foo.bar.baz if something - ^^^^^^^^ Do not chain ordinary method call after safe navigation operator. + something + x&.select { foo(_1) }.bar + ^^^^ Do not chain ordinary method call after safe navigation operator. RUBY end end diff --git a/spec/rubocop/cop/style/empty_literal_spec.rb b/spec/rubocop/cop/style/empty_literal_spec.rb index 16084192d3d..add628e33c6 100644 --- a/spec/rubocop/cop/style/empty_literal_spec.rb +++ b/spec/rubocop/cop/style/empty_literal_spec.rb @@ -278,7 +278,7 @@ def foo end end - context 'when frozen string literals is enabled' do + context 'when frozen string literals is enabled', :ruby23 do it 'does not register an offense for String.new' do expect_no_offenses(<<~RUBY) # frozen_string_literal: true diff --git a/spec/rubocop/cop/style/for_spec.rb b/spec/rubocop/cop/style/for_spec.rb index e9e9342f735..46dd04dc730 100644 --- a/spec/rubocop/cop/style/for_spec.rb +++ b/spec/rubocop/cop/style/for_spec.rb @@ -332,7 +332,7 @@ def func RUBY end - context 'when using safe navigation operator' do + context 'when using safe navigation operator', :ruby23 do it 'does not break' do expect_no_offenses(<<~RUBY) def func diff --git a/spec/rubocop/cop/style/frozen_string_literal_comment_spec.rb b/spec/rubocop/cop/style/frozen_string_literal_comment_spec.rb index dfbd4a9d526..f857ab014e6 100644 --- a/spec/rubocop/cop/style/frozen_string_literal_comment_spec.rb +++ b/spec/rubocop/cop/style/frozen_string_literal_comment_spec.rb @@ -1042,4 +1042,22 @@ RUBY end end + + context 'target_ruby_version < 2.3', :ruby22 do + it 'accepts freezing a string' do + expect_no_offenses('"x".freeze') + end + + it 'accepts calling << on a string' do + expect_no_offenses('"x" << "y"') + end + + it 'accepts freezing a string with interpolation' do + expect_no_offenses('"#{foo}bar".freeze') + end + + it 'accepts calling << on a string with interpolation' do + expect_no_offenses('"#{foo}bar" << "baz"') + end + end end diff --git a/spec/rubocop/cop/style/lambda_spec.rb b/spec/rubocop/cop/style/lambda_spec.rb index 79ff1674c87..fd83081c65d 100644 --- a/spec/rubocop/cop/style/lambda_spec.rb +++ b/spec/rubocop/cop/style/lambda_spec.rb @@ -513,7 +513,7 @@ end end - context 'when using safe navigation operator' do + context 'when using safe navigation operator', :ruby23 do it 'does not break' do expect_no_offenses(<<~RUBY) foo&.bar do |_| diff --git a/spec/rubocop/cop/style/numeric_predicate_spec.rb b/spec/rubocop/cop/style/numeric_predicate_spec.rb index 17b79278d46..eabc977fbd7 100644 --- a/spec/rubocop/cop/style/numeric_predicate_spec.rb +++ b/spec/rubocop/cop/style/numeric_predicate_spec.rb @@ -89,98 +89,114 @@ def m(foo) end context 'when checking if a number is positive' do - it 'registers an offense' do - expect_offense(<<~RUBY) - number > 0 - ^^^^^^^^^^ Use `number.positive?` instead of `number > 0`. - RUBY - - expect_correction(<<~RUBY) - number.positive? - RUBY - end - - it 'registers an offense in yoda condition' do - expect_offense(<<~RUBY) - 0 < number - ^^^^^^^^^^ Use `number.positive?` instead of `0 < number`. - RUBY - - expect_correction(<<~RUBY) - number.positive? - RUBY - end - - context 'with a complex expression' do + context 'when target ruby version is 2.3 or higher', :ruby23 do it 'registers an offense' do expect_offense(<<~RUBY) - foo - 1 > 0 - ^^^^^^^^^^^ Use `(foo - 1).positive?` instead of `foo - 1 > 0`. + number > 0 + ^^^^^^^^^^ Use `number.positive?` instead of `number > 0`. RUBY expect_correction(<<~RUBY) - (foo - 1).positive? + number.positive? RUBY end it 'registers an offense in yoda condition' do expect_offense(<<~RUBY) - 0 < foo - 1 - ^^^^^^^^^^^ Use `(foo - 1).positive?` instead of `0 < foo - 1`. + 0 < number + ^^^^^^^^^^ Use `number.positive?` instead of `0 < number`. RUBY expect_correction(<<~RUBY) - (foo - 1).positive? + number.positive? RUBY end - end - end - context 'when checking if a number is negative' do - it 'registers an offense' do - expect_offense(<<~RUBY) - number < 0 - ^^^^^^^^^^ Use `number.negative?` instead of `number < 0`. - RUBY + context 'with a complex expression' do + it 'registers an offense' do + expect_offense(<<~RUBY) + foo - 1 > 0 + ^^^^^^^^^^^ Use `(foo - 1).positive?` instead of `foo - 1 > 0`. + RUBY - expect_correction(<<~RUBY) - number.negative? - RUBY - end + expect_correction(<<~RUBY) + (foo - 1).positive? + RUBY + end - it 'registers an offense in yoda condition' do - expect_offense(<<~RUBY) - 0 > number - ^^^^^^^^^^ Use `number.negative?` instead of `0 > number`. - RUBY + it 'registers an offense in yoda condition' do + expect_offense(<<~RUBY) + 0 < foo - 1 + ^^^^^^^^^^^ Use `(foo - 1).positive?` instead of `0 < foo - 1`. + RUBY - expect_correction(<<~RUBY) - number.negative? - RUBY + expect_correction(<<~RUBY) + (foo - 1).positive? + RUBY + end + end + end + + context 'when target ruby version is 2.2 or lower', :ruby22 do + it 'does not register an offense' do + expect_no_offenses('number > 0') + end end + end - context 'with a complex expression' do + context 'when checking if a number is negative' do + context 'when target ruby version is 2.3 or higher', :ruby23 do it 'registers an offense' do expect_offense(<<~RUBY) - foo - 1 < 0 - ^^^^^^^^^^^ Use `(foo - 1).negative?` instead of `foo - 1 < 0`. + number < 0 + ^^^^^^^^^^ Use `number.negative?` instead of `number < 0`. RUBY expect_correction(<<~RUBY) - (foo - 1).negative? + number.negative? RUBY end it 'registers an offense in yoda condition' do expect_offense(<<~RUBY) - 0 > foo - 1 - ^^^^^^^^^^^ Use `(foo - 1).negative?` instead of `0 > foo - 1`. + 0 > number + ^^^^^^^^^^ Use `number.negative?` instead of `0 > number`. RUBY expect_correction(<<~RUBY) - (foo - 1).negative? + number.negative? RUBY end + + context 'with a complex expression' do + it 'registers an offense' do + expect_offense(<<~RUBY) + foo - 1 < 0 + ^^^^^^^^^^^ Use `(foo - 1).negative?` instead of `foo - 1 < 0`. + RUBY + + expect_correction(<<~RUBY) + (foo - 1).negative? + RUBY + end + + it 'registers an offense in yoda condition' do + expect_offense(<<~RUBY) + 0 > foo - 1 + ^^^^^^^^^^^ Use `(foo - 1).negative?` instead of `0 > foo - 1`. + RUBY + + expect_correction(<<~RUBY) + (foo - 1).negative? + RUBY + end + end + end + + context 'when target ruby version is 2.2 or lower', :ruby22 do + it 'does not register an offense' do + expect_no_offenses('number < 0') + end end end end @@ -285,26 +301,46 @@ def m(foo) end context 'not ignored method' do - it 'registers an offense for checking if a number is positive' do - expect_offense(<<~RUBY) - exclude(number > 0) - ^^^^^^^^^^ Use `number.positive?` instead of `number > 0`. - RUBY + context 'when checking if a number is positive' do + context 'when target ruby version is 2.3 or higher', :ruby23 do + it 'registers an offense' do + expect_offense(<<~RUBY) + exclude(number > 0) + ^^^^^^^^^^ Use `number.positive?` instead of `number > 0`. + RUBY + + expect_correction(<<~RUBY) + exclude(number.positive?) + RUBY + end + end - expect_correction(<<~RUBY) - exclude(number.positive?) - RUBY + context 'when target ruby version is 2.2 or lower', :ruby22 do + it 'does not register an offense' do + expect_no_offenses('exclude { number > 0 }') + end + end end - it 'registers an offense for checking if a number is negative' do - expect_offense(<<~RUBY) - exclude(number < 0) - ^^^^^^^^^^ Use `number.negative?` instead of `number < 0`. - RUBY + context 'when checking if a number is negative' do + context 'when target ruby version is 2.3 or higher', :ruby23 do + it 'registers an offense' do + expect_offense(<<~RUBY) + exclude(number < 0) + ^^^^^^^^^^ Use `number.negative?` instead of `number < 0`. + RUBY + + expect_correction(<<~RUBY) + exclude(number.negative?) + RUBY + end + end - expect_correction(<<~RUBY) - exclude(number.negative?) - RUBY + context 'when target ruby version is 2.2 or lower', :ruby22 do + it 'does not register an offense' do + expect_no_offenses('exclude { number > 0 }') + end + end end end end