Skip to content

Commit

Permalink
Add option to allow case equality when the receiver is a constant
Browse files Browse the repository at this point in the history
For some constant, specially direct subclasses of `BasicObject`, using
`is_a?` is not an option since `BasicObject` doesn't respond to that
method.

In those cases it would be interesting to allow this config so apps can
opt-out that cop only when the receiver is a constant.
  • Loading branch information
rafaelfranca authored and bbatsov committed Apr 10, 2020
1 parent a065802 commit ae73ae7
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -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

Expand Down Expand Up @@ -4439,3 +4440,4 @@
[@dmolesUC]: https://github.com/dmolesUC
[@yuritomanek]: https://github.com/yuritomanek
[@egze]: https://github.com/egze
[@rafaelfranca]: https://github.com/rafaelfranca
9 changes: 9 additions & 0 deletions config/default.yml
Expand Up @@ -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.'
Expand Down
25 changes: 24 additions & 1 deletion lib/rubocop/cop/style/case_equality.rb
Expand Up @@ -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
Expand Down
21 changes: 21 additions & 0 deletions manual/cops_style.md
Expand Up @@ -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

Expand Down
27 changes: 26 additions & 1 deletion spec/rubocop/cop/style/case_equality_spec.rb
@@ -1,12 +1,37 @@
# 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)
Array === var
^^^ 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

0 comments on commit ae73ae7

Please sign in to comment.