Skip to content

Commit

Permalink
Merge pull request #12414 from koic/make_style_inverse_methods_aware_…
Browse files Browse the repository at this point in the history
…of_safe_navigation_operator

[Fix #12413] Make `Style/InverseMethods` aware of safe navigation operator
  • Loading branch information
koic committed Nov 26, 2023
2 parents f466f86 + 7512e8a commit 0c1671f
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#12413](https://github.com/rubocop/rubocop/issues/12413): Make `Style/InverseMethods` aware of safe navigation operator. ([@koic][])
11 changes: 6 additions & 5 deletions lib/rubocop/cop/style/inverse_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,17 @@ def self.autocorrect_incompatible_with
# @!method inverse_candidate?(node)
def_node_matcher :inverse_candidate?, <<~PATTERN
{
(send $(send $(...) $_ $...) :!)
(send ({block numblock} $(send $(...) $_) $...) :!)
(send (begin $(send $(...) $_ $...)) :!)
(send $(call $(...) $_ $...) :!)
(send ({block numblock} $(call $(...) $_) $...) :!)
(send (begin $(call $(...) $_ $...)) :!)
}
PATTERN

# @!method inverse_block?(node)
def_node_matcher :inverse_block?, <<~PATTERN
({block numblock} $(send (...) $_) ... { $(send ... :!)
({block numblock} $(call (...) $_) ... { $(call ... :!)
$(send (...) {:!= :!~} ...)
(begin ... $(send ... :!))
(begin ... $(call ... :!))
(begin ... $(send (...) {:!= :!~} ...))
})
PATTERN
Expand All @@ -87,6 +87,7 @@ def on_send(node)
end
end
end
alias on_csend on_send

def on_block(node)
inverse_block?(node) do |_method_call, method, block|
Expand Down
72 changes: 72 additions & 0 deletions spec/rubocop/cop/style/inverse_methods_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@
RUBY
end

it 'registers an offense for safe navigation calling !.none? with a symbol proc' do
expect_offense(<<~RUBY)
!foo&.none?(&:even?)
^^^^^^^^^^^^^^^^^^^^ Use `any?` instead of inverting `none?`.
RUBY

expect_correction(<<~RUBY)
foo&.any?(&:even?)
RUBY
end

it 'registers an offense for calling !.none? with a block' do
expect_offense(<<~RUBY)
!foo.none? { |f| f.even? }
Expand All @@ -44,6 +55,17 @@
RUBY
end

it 'registers an offense for safe navigation calling !.none? with a block' do
expect_offense(<<~RUBY)
!foo&.none? { |f| f.even? }
^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `any?` instead of inverting `none?`.
RUBY

expect_correction(<<~RUBY)
foo&.any? { |f| f.even? }
RUBY
end

context 'Ruby 2.7', :ruby27 do
it 'registers an offense for calling !.none? with a numblock' do
expect_offense(<<~RUBY)
Expand All @@ -68,6 +90,17 @@
RUBY
end

it 'registers an offense for safe navigation calling !.any? inside parens' do
expect_offense(<<~RUBY)
!(foo&.any? &:working?)
^^^^^^^^^^^^^^^^^^^^^^^ Use `none?` instead of inverting `any?`.
RUBY

expect_correction(<<~RUBY)
foo&.none? &:working?
RUBY
end

it 'allows a method call without a not' do
expect_no_offenses('foo.none?')
end
Expand Down Expand Up @@ -232,6 +265,17 @@ def test_method
RUBY
end

it "registers an offense for foo&.#{method} { |e| !e }" do
expect_offense(<<~RUBY, method: method)
foo&.%{method} { |e| !e }
^^^^^^{method}^^^^^^^^^^^ Use `#{inverse}` instead of inverting `#{method}`.
RUBY

expect_correction(<<~RUBY)
foo&.#{inverse} { |e| e }
RUBY
end

it 'registers an offense for a multiline method call where the last method is inverted' do
expect_offense(<<~RUBY, method: method)
foo.%{method} do |e|
Expand All @@ -249,6 +293,23 @@ def test_method
RUBY
end

it 'registers an offense for a multiline safe navigation method call where the last method is inverted' do
expect_offense(<<~RUBY, method: method)
foo&.%{method} do |e|
^^^^^^{method}^^^^^^^ Use `#{inverse}` instead of inverting `#{method}`.
something
e&.bar&.!
end
RUBY

expect_correction(<<~RUBY)
foo&.#{inverse} do |e|
something
e&.bar
end
RUBY
end

it 'registers an offense for an inverted equality block' do
expect_offense(<<~RUBY, method: method)
foo.%{method} { |e| e != 2 }
Expand Down Expand Up @@ -312,6 +373,17 @@ def test_method
RUBY
end

it 'corrects an inverted safe navigation method call when using `BasicObject#!`' do
expect_offense(<<~RUBY, method: method)
foo&.%{method} { |e| e&.bar?&.! }
^^^^^^{method}^^^^^^^^^^^^^^^^^^^ Use `#{inverse}` instead of inverting `#{method}`.
RUBY

expect_correction(<<~RUBY)
foo&.#{inverse} { |e| e&.bar? }
RUBY
end

it 'corrects an inverted method call when using `BasicObject#!` with spaces before the method call' do
expect_offense(<<~RUBY, method: method)
foo.%{method} { |e| e.bar?. ! }
Expand Down

0 comments on commit 0c1671f

Please sign in to comment.