8000 [Fix #407] Make `Performance/DoubleStartEndWith` aware of safe naviga… · rubocop/rubocop-performance@767f2c9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 767f2c9

Browse files
committed
[Fix #407] Make Performance/DoubleStartEndWith aware of safe 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
1 parent 082d635 commit 767f2c9

File tree

3 files changed

+46
-10
lines changed

3 files changed

+46
-10
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#407](https://github.com/rubocop/rubocop-performance/issues/407): Make `Performance/DoubleStartEndWith` aware of safe navigation. ([@earlopain][])

lib/rubocop/cop/performance/double_start_end_with.rb

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ module Performance
4141
class DoubleStartEndWith < Base
4242
extend AutoCorrector
4343

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

4646
def on_or(node)
4747
receiver, method, first_call_args, second_call_args = process_source(node)
@@ -50,7 +50,7 @@ def on_or(node)
5050

5151
combined_args = combine_args(first_call_args, second_call_args)
5252

53-
add_offense(node, message: message(node, receiver, method, combined_args)) do |corrector|
53+
add_offense(node, message: message(node, receiver, first_call_args, method, combined_args)) do |corrector|
5454
autocorrect(corrector, first_call_args, second_call_args, combined_args)
5555
end
5656
end
@@ -73,10 +73,10 @@ def process_source(node)
7373
end
7474
end
7575

76-
def message(node, receiver, method, combined_args)
77-
format(
78-
MSG, receiver: receiver.source, method: method, combined_args: combined_args, original_code: node.source
79-
)
76+
def message(node, receiver, first_call_args, method, combined_args)
77+
dot = first_call_args.first.parent.send_type? ? '.' : '&.'
78+
replacement = "#{receiver.source}#{dot}#{method}(#{combined_args})"
79+
format(MSG, replacement: replacement, original_code: node.source)
8080
end
8181

8282
def combine_args(first_call_args, second_call_args)
@@ -89,16 +89,16 @@ def check_for_active_support_aliases?
8989

9090
def_node_matcher :two_start_end_with_calls, <<~PATTERN
9191
(or
92-
(send $_recv [{:start_with? :end_with?} $_method] $...)
93-
(send _recv _method $...))
92+
(call $_recv [{:start_with? :end_with?} $_method] $...)
93+
(call _recv _method $...))
9494
PATTERN
9595

9696
def_node_matcher :check_with_active_support_aliases, <<~PATTERN
9797
(or
98-
(send $_recv
98+
(call $_recv
9999
[{:start_with? :starts_with? :end_with? :ends_with?} $_method]
100100
$...)
101-
(send _recv _method $...))
101+
(call _recv _method $...))
102102
PATTERN
103103
end
104104
end

spec/rubocop/cop/performance/double_start_end_with_spec.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,41 @@
2626
expect_no_offenses('x.start_with?(a, "b") || x.start_with?(C, d)')
2727
end
2828
end
29+
30+
context 'with safe navigation' do
31+
it 'registers an offense' do
32+
expect_offense(<<~RUBY)
33+
x&.start_with?(a, b) || x&.start_with?("c", D)
34+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `x&.start_with?(a, b, "c", D)` instead of `x&.start_with?(a, b) || x&.start_with?("c", D)`.
35+
RUBY
36+
37+
expect_correction(<<~RUBY)
38+
x&.start_with?(a, b, "c", D)
39+
RUBY
40+
end
41+
42+
it 'registers an offense when the first start_with uses no safe navigation' do
43+
expect_offense(<<~RUBY)
44+
x.start_with?(a, b) || x&.start_with?("c", D)
45+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `x.start_with?(a, b, "c", D)` instead of `x.start_with?(a, b) || x&.start_with?("c", D)`.
46+
RUBY
47+
48+
expect_correction(<<~RUBY)
49+
x.start_with?(a, b, "c", D)
50+
RUBY
51+
end
52+
53+
it 'registers an offense when the second start_with uses no safe navigation' do
54+
expect_offense(<<~RUBY)
55+
x&.start_with?(a, b) || x.start_with?("c", D)
56+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `x&.start_with?(a, b, "c", D)` instead of `x&.start_with?(a, b) || x.start_with?("c", D)`.
57+
RUBY
58+
59+
expect_correction(<<~RUBY)
60+
x&.start_with?(a, b, "c", D)
61+
RUBY
62+
end
63+
end
2964
end
3065

3166
context 'with different receivers' do

0 commit comments

Comments
 (0)
0