Skip to content

Commit e41543d

Browse files
fatkodimabbatsov
authored andcommitted
Fix Lint/SafeNavigationChain to correctly handle [] operator followed by save navigation and method chain
1 parent 2dc325c commit e41543d

File tree

3 files changed

+28
-27
lines changed

3 files changed

+28
-27
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#11298](https://github.com/rubocop/rubocop/issues/11298): Fix `Lint/SafeNavigationChain` to correctly handle `[]` operator followed by save navigation and method chain. ([@fatkodima][])

lib/rubocop/cop/lint/safe_navigation_chain.rb

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,12 @@ def on_send(node)
4545
bad_method?(node) do |safe_nav, method|
4646
return if nil_methods.include?(method) || PLUS_MINUS_METHODS.include?(node.method_name)
4747

48-
method_chain = method_chain(node)
4948
location =
5049
Parser::Source::Range.new(node.source_range.source_buffer,
5150
safe_nav.source_range.end_pos,
52-
method_chain.source_range.end_pos)
51+
node.source_range.end_pos)
5352
add_offense(location) do |corrector|
54-
autocorrect(corrector, offense_range: location, send_node: method_chain)
53+
autocorrect(corrector, offense_range: location, send_node: node)
5554
end
5655
end
5756
end
@@ -63,12 +62,12 @@ def on_send(node)
6362
# @return [String]
6463
def add_safe_navigation_operator(offense_range:, send_node:)
6564
source =
66-
if (brackets = find_brackets(send_node))
65+
if brackets?(send_node)
6766
format(
6867
'%<method_name>s(%<arguments>s)%<method_chain>s',
69-
arguments: brackets.arguments.map(&:source).join(', '),
70-
method_name: brackets.method_name,
71-
method_chain: brackets.source_range.end.join(send_node.source_range.end).source
68+
arguments: send_node.arguments.map(&:source).join(', '),
69+
method_name: send_node.method_name,
70+
method_chain: send_node.source_range.end.join(send_node.source_range.end).source
7271
)
7372
else
7473
offense_range.source
@@ -90,18 +89,8 @@ def autocorrect(corrector, offense_range:, send_node:)
9089
)
9190
end
9291

93-
def method_chain(node)
94-
chain = node
95-
chain = chain.parent if chain.send_type? && chain.parent&.call_type?
96-
chain
97-
end
98-
99-
def find_brackets(send_node)
100-
return send_node if send_node.method?(:[]) || send_node.method?(:[]=)
101-
102-
send_node.descendants.detect do |node|
103-
node.send_type? && (node.method?(:[]) || node.method?(:[]=))
104-
end
92+
def brackets?(send_node)
93+
send_node.method?(:[]) || send_node.method?(:[]=)
10594
end
10695
end
10796
end

spec/rubocop/cop/lint/safe_navigation_chain_spec.rb

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
expect_offense(<<~RUBY)
6464
something
6565
x&.foo.bar.baz
66-
^^^^^^^^ Do not chain ordinary method call after safe navigation operator.
66+
^^^^ Do not chain ordinary method call after safe navigation operator.
6767
RUBY
6868

6969
expect_correction(<<~RUBY)
@@ -76,7 +76,7 @@
7676
'safe navigation method call with an argument' do
7777
expect_offense(<<~RUBY)
7878
x&.foo(x).bar(y).baz(z)
79-
^^^^^^^^^^^^^^ Do not chain ordinary method call after safe navigation operator.
79+
^^^^^^^ Do not chain ordinary method call after safe navigation operator.
8080
RUBY
8181

8282
expect_correction(<<~RUBY)
@@ -181,7 +181,7 @@
181181
it 'registers an offense for safe navigation with [] operator followed by method chain' do
182182
expect_offense(<<~RUBY)
183183
x&.foo[bar].to_s
184-
^^^^^^^^^^ Do not chain ordinary method call after safe navigation operator.
184+
^^^^^ Do not chain ordinary method call after safe navigation operator.
185185
RUBY
186186

187187
expect_correction(<<~RUBY)
@@ -200,6 +200,17 @@
200200
RUBY
201201
end
202202

203+
it 'registers an offense for [] operator followed by a safe navigation and method chain' do
204+
expect_offense(<<~RUBY)
205+
foo[bar]&.x.y
206+
^^ Do not chain ordinary method call after safe navigation operator.
207+
RUBY
208+
209+
expect_correction(<<~RUBY)
210+
foo[bar]&.x&.y
211+
RUBY
212+
end
213+
203214
it 'registers an offense for safe navigation on the right-hand side of the `+`' do
204215
expect_offense(<<~RUBY)
205216
x + foo&.bar.baz
@@ -249,7 +260,7 @@
249260
expect_offense(<<~RUBY)
250261
something
251262
x&.foo.bar.baz
252-
^^^^^^^^ Do not chain ordinary method call after safe navigation operator.
263+
^^^^ Do not chain ordinary method call after safe navigation operator.
253264
RUBY
254265

255266
expect_correction(<<~RUBY)
@@ -261,7 +272,7 @@
261272
it 'when there are methods after' do
262273
expect_offense(<<~RUBY)
263274
x&.foo.bar.baz
264-
^^^^^^^^ Do not chain ordinary method call after safe navigation operator.
275+
^^^^ Do not chain ordinary method call after safe navigation operator.
265276
something
266277
RUBY
267278

@@ -275,7 +286,7 @@
275286
expect_offense(<<~RUBY)
276287
def something
277288
x&.foo.bar.baz
278-
^^^^^^^^ Do not chain ordinary method call after safe navigation operator.
289+
^^^^ Do not chain ordinary method call after safe navigation operator.
279290
end
280291
RUBY
281292

@@ -290,7 +301,7 @@ def something
290301
expect_offense(<<~RUBY)
291302
begin
292303
x&.foo.bar.baz
293-
^^^^^^^^ Do not chain ordinary method call after safe navigation operator.
304+
^^^^ Do not chain ordinary method call after safe navigation operator.
294305
end
295306
RUBY
296307

@@ -304,7 +315,7 @@ def something
304315
it 'when used with a modifier if' do
305316
expect_offense(<<~RUBY)
306317
x&.foo.bar.baz if something
307-
^^^^^^^^ Do not chain ordinary method call after safe navigation operator.
318+
^^^^ Do not chain ordinary method call after safe navigation operator.
308319
RUBY
309320

310321
expect_correction(<<~RUBY)

0 commit comments

Comments
 (0)