diff --git a/CHANGELOG.md b/CHANGELOG.md index bc65b70ba03..b2617369153 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * [#7862](https://github.com/rubocop-hq/rubocop/issues/7862): Corrector now has a `wrap` method. ([@marcandre][]) * [#7850](https://github.com/rubocop-hq/rubocop/issues/7850): Make it possible to enable/disable pending cops. ([@koic][]) +* [#7861](https://github.com/rubocop-hq/rubocop/issues/7861): Make it to allow `Style/CaseEquality` when the receiver is a constant. ([@rafaelfranca][]) ### Bug fixes @@ -4439,3 +4440,4 @@ [@dmolesUC]: https://github.com/dmolesUC [@yuritomanek]: https://github.com/yuritomanek [@egze]: https://github.com/egze +[@rafaelfranca]: https://github.com/rafaelfranca diff --git a/config/default.yml b/config/default.yml index a4559adc8fb..a8a81e721cf 100644 --- a/config/default.yml +++ b/config/default.yml @@ -2417,6 +2417,15 @@ Style/CaseEquality: StyleGuide: '#no-case-equality' Enabled: true VersionAdded: '0.9' + # If AllowOnConstant is enabled, the cop will ignore violations when the receiver of + # the case equality operator is a constant. + # + # # bad + # /string/ === "string" + # + # # good + # String === "string" + AllowOnConstant: false Style/CharacterLiteral: Description: 'Checks for uses of character literals.' diff --git a/lib/rubocop/cop/style/case_equality.rb b/lib/rubocop/cop/style/case_equality.rb index 93c29e9ef14..5069e948eda 100644 --- a/lib/rubocop/cop/style/case_equality.rb +++ b/lib/rubocop/cop/style/case_equality.rb @@ -16,14 +16,37 @@ module Style # (1..100).include?(7) # some_string =~ /something/ # + # @example AllowOnConstant + # # Style/CaseEquality: + # # AllowOnConstant: true + # + # # bad + # (1..100) === 7 + # /something/ === some_string + # + # # good + # Array === something + # (1..100).include?(7) + # some_string =~ /something/ + # class CaseEquality < Cop MSG = 'Avoid the use of the case equality operator `===`.' - def_node_matcher :case_equality?, '(send _ :=== _)' + def_node_matcher :case_equality?, '(send #const? :=== _)' def on_send(node) case_equality?(node) { add_offense(node, location: :selector) } end + + private + + def const?(node) + if cop_config.fetch('AllowOnConstant', false) + !node.const_type? + else + true + end + end end end end diff --git a/manual/cops_style.md b/manual/cops_style.md index 856d78d29c8..e654fd2443d 100644 --- a/manual/cops_style.md +++ b/manual/cops_style.md @@ -557,6 +557,27 @@ something.is_a?(Array) (1..100).include?(7) some_string =~ /something/ ``` +#### AllowOnConstant + +```ruby +# Style/CaseEquality: +# AllowOnConstant: true + +# bad +(1..100) === 7 +/something/ === some_string + +# good +Array === something +(1..100).include?(7) +some_string =~ /something/ +``` + +### Configurable attributes + +Name | Default value | Configurable values +--- | --- | --- +AllowOnConstant | `false` | Boolean ### References diff --git a/spec/rubocop/cop/style/case_equality_spec.rb b/spec/rubocop/cop/style/case_equality_spec.rb index f7741eb5703..cd65cdbfe24 100644 --- a/spec/rubocop/cop/style/case_equality_spec.rb +++ b/spec/rubocop/cop/style/case_equality_spec.rb @@ -1,7 +1,9 @@ # frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::CaseEquality do - subject(:cop) { described_class.new } + subject(:cop) { described_class.new(config) } + + let(:config) { RuboCop::Config.new } it 'registers an offense for ===' do expect_offense(<<~RUBY) @@ -9,4 +11,27 @@ ^^^ Avoid the use of the case equality operator `===`. RUBY end + + context 'when constant checks are allowed' do + let(:config) do + RuboCop::Config.new( + 'Style/CaseEquality' => { + 'AllowOnConstant' => true + } + ) + end + + it 'does not register an offense for === when the receiver is a constant' do + expect_no_offenses(<<~RUBY) + Array === var + RUBY + end + + it 'registers an offense for === when the receiver is not a constant' do + expect_offense(<<~RUBY) + /OMG/ === "OMG" + ^^^ Avoid the use of the case equality operator `===`. + RUBY + end + end end