Skip to content

Commit

Permalink
Fix [rubocop#407] Make Performance/DoubleStartEndWith aware of safe…
Browse files Browse the repository at this point in the history
… navigation

In case of inconsistent safe navigation, it keeps the dot from the first receiver.

This shouldn't change anything:
Depending on the order, it was either not needed or it will continue raising.

`Lint/SafeNavigationConsistency``takes care of this anyways
  • Loading branch information
Earlopain committed Sep 13, 2024
1 parent 082d635 commit ca4f322
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#407](https://github.com/rubocop/rubocop-performance/issues/407): Make `Performance/DoubleStartEndWith` aware of safe navigation. ([@earlopain][])
20 changes: 10 additions & 10 deletions lib/rubocop/cop/performance/double_start_end_with.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ module Performance
class DoubleStartEndWith < Base
extend AutoCorrector

MSG = 'Use `%<receiver>s.%<method>s(%<combined_args>s)` instead of `%<original_code>s`.'
MSG = 'Use `%<replacement>s` instead of `%<original_code>s`.'

def on_or(node)
receiver, method, first_call_args, second_call_args = process_source(node)
Expand All @@ -50,7 +50,7 @@ def on_or(node)

combined_args = combine_args(first_call_args, second_call_args)

add_offense(node, message: message(node, receiver, method, combined_args)) do |corrector|
add_offense(node, message: message(node, receiver, first_call_args, method, combined_args)) do |corrector|
autocorrect(corrector, first_call_args, second_call_args, combined_args)
end
end
Expand All @@ -73,10 +73,10 @@ def process_source(node)
end
end

def message(node, receiver, method, combined_args)
format(
MSG, receiver: receiver.source, method: method, combined_args: combined_args, original_code: node.source
)
def message(node, receiver, first_call_args, method, combined_args)
dot = first_call_args.first.parent.send_type? ? '.' : '&.'
replacement = "#{receiver.source}#{dot}#{method}(#{combined_args})"
format(MSG, replacement: replacement, original_code: node.source)
end

def combine_args(first_call_args, second_call_args)
Expand All @@ -89,16 +89,16 @@ def check_for_active_support_aliases?

def_node_matcher :two_start_end_with_calls, <<~PATTERN
(or
(send $_recv [{:start_with? :end_with?} $_method] $...)
(send _recv _method $...))
(call $_recv [{:start_with? :end_with?} $_method] $...)
(call _recv _method $...))
PATTERN

def_node_matcher :check_with_active_support_aliases, <<~PATTERN
(or
(send $_recv
(call $_recv
[{:start_with? :starts_with? :end_with? :ends_with?} $_method]
$...)
(send _recv _method $...))
(call _recv _method $...))
PATTERN
end
end
Expand Down
35 changes: 35 additions & 0 deletions spec/rubocop/cop/performance/double_start_end_with_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,41 @@
expect_no_offenses('x.start_with?(a, "b") || x.start_with?(C, d)')
end
end

context 'with safe navigation' do
it 'registers an offense' do
expect_offense(<<~RUBY)
x&.start_with?(a, b) || x&.start_with?("c", D)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `x&.start_with?(a, b, "c", D)` instead of `x&.start_with?(a, b) || x&.start_with?("c", D)`.
RUBY

expect_correction(<<~RUBY)
x&.start_with?(a, b, "c", D)
RUBY
end

it 'registers an offense when the first start_with uses no safe navigation' do
expect_offense(<<~RUBY)
x.start_with?(a, b) || x&.start_with?("c", D)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `x.start_with?(a, b, "c", D)` instead of `x.start_with?(a, b) || x&.start_with?("c", D)`.
RUBY

expect_correction(<<~RUBY)
x.start_with?(a, b, "c", D)
RUBY
end

it 'registers an offense when the second start_with uses no safe navigation' do
expect_offense(<<~RUBY)
x&.start_with?(a, b) || x.start_with?("c", D)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `x&.start_with?(a, b, "c", D)` instead of `x&.start_with?(a, b) || x.start_with?("c", D)`.
RUBY

expect_correction(<<~RUBY)
x&.start_with?(a, b, "c", D)
RUBY
end
end
end

context 'with different receivers' do
Expand Down

0 comments on commit ca4f322

Please sign in to comment.