Skip to content

Commit

Permalink
Caller: use lonely operator to safely call #first
Browse files Browse the repository at this point in the history
  • Loading branch information
chastell committed Nov 2, 2024
1 parent 3806fc4 commit f874d1d
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 20 deletions.
1 change: 1 addition & 0 deletions changelog/fix_caller_use_lonely_operator_to_safely.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#476](https://github.com/rubocop/rubocop-performance/pull/476): Caller: use lonely operator to safely call `#first`. ([@chastell][])
8 changes: 4 additions & 4 deletions lib/rubocop/cop/performance/caller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module RuboCop
module Cop
module Performance
# Identifies places where `caller[n]` can be replaced by `caller(n..n).first`.
# Identifies places where `caller[n]` can be replaced by `caller(n..n)&.first`.
#
# @example
# # bad
Expand All @@ -13,9 +13,9 @@ module Performance
# caller_locations.first
#
# # good
# caller(2..2).first
# caller(2..2)&.first
# caller(1..1).first
# caller_locations(2..2).first
# caller_locations(2..2)&.first
# caller_locations(1..1).first
class Caller < Base
extend AutoCorrector
Expand Down Expand Up @@ -48,7 +48,7 @@ def on_send(node)
n += m
end

preferred_method = "#{method_name}(#{n}..#{n}).first"
preferred_method = "#{method_name}(#{n}..#{n})&.first"

message = format(MSG, preferred_method: preferred_method, current_method: node.source)
add_offense(node, message: message) do |corrector|
Expand Down
32 changes: 16 additions & 16 deletions spec/rubocop/cop/performance/caller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,95 +17,95 @@
expect(caller.first).to eq(caller(1..1).first)
expect_offense(<<~RUBY)
caller.first
^^^^^^^^^^^^ Use `caller(1..1).first` instead of `caller.first`.
^^^^^^^^^^^^ Use `caller(1..1)&.first` instead of `caller.first`.
RUBY

expect_correction(<<~RUBY)
caller(1..1).first
caller(1..1)&.first
RUBY
end

it 'registers an offense and corrects when :first is called on caller with 1' do
expect(caller(1).first).to eq(caller(1..1).first)
expect_offense(<<~RUBY)
caller(1).first
^^^^^^^^^^^^^^^ Use `caller(1..1).first` instead of `caller(1).first`.
^^^^^^^^^^^^^^^ Use `caller(1..1)&.first` instead of `caller(1).first`.
RUBY

expect_correction(<<~RUBY)
caller(1..1).first
caller(1..1)&.first
RUBY
end

it 'registers an offense and corrects when :first is called on caller with 2' do
expect(caller(2).first).to eq(caller(2..2).first)
expect_offense(<<~RUBY)
caller(2).first
^^^^^^^^^^^^^^^ Use `caller(2..2).first` instead of `caller(2).first`.
^^^^^^^^^^^^^^^ Use `caller(2..2)&.first` instead of `caller(2).first`.
RUBY

expect_correction(<<~RUBY)
caller(2..2).first
caller(2..2)&.first
RUBY
end

it 'registers an offense and corrects when :[] is called on caller' do
expect(caller[1]).to eq(caller(2..2).first)
expect_offense(<<~RUBY)
caller[1]
^^^^^^^^^ Use `caller(2..2).first` instead of `caller[1]`.
^^^^^^^^^ Use `caller(2..2)&.first` instead of `caller[1]`.
RUBY

expect_correction(<<~RUBY)
caller(2..2).first
caller(2..2)&.first
RUBY
end

it 'registers an offense and corrects when :[] is called on caller with 1' do
expect(caller(1)[1]).to eq(caller(2..2).first)
expect_offense(<<~RUBY)
caller(1)[1]
^^^^^^^^^^^^ Use `caller(2..2).first` instead of `caller(1)[1]`.
^^^^^^^^^^^^ Use `caller(2..2)&.first` instead of `caller(1)[1]`.
RUBY

expect_correction(<<~RUBY)
caller(2..2).first
caller(2..2)&.first
RUBY
end

it 'registers an offense and corrects when :[] is called on caller with 2' do
expect(caller(2)[1]).to eq(caller(3..3).first)
expect_offense(<<~RUBY)
caller(2)[1]
^^^^^^^^^^^^ Use `caller(3..3).first` instead of `caller(2)[1]`.
^^^^^^^^^^^^ Use `caller(3..3)&.first` instead of `caller(2)[1]`.
RUBY

expect_correction(<<~RUBY)
caller(3..3).first
caller(3..3)&.first
RUBY
end

it 'registers an offense and corrects when :first is called on caller_locations also' do
expect(caller_locations.first.to_s).to eq(caller_locations(1..1).first.to_s)
expect_offense(<<~RUBY)
caller_locations.first
^^^^^^^^^^^^^^^^^^^^^^ Use `caller_locations(1..1).first` instead of `caller_locations.first`.
^^^^^^^^^^^^^^^^^^^^^^ Use `caller_locations(1..1)&.first` instead of `caller_locations.first`.
RUBY

expect_correction(<<~RUBY)
caller_locations(1..1).first
caller_locations(1..1)&.first
RUBY
end

it 'registers an offense and corrects when :[] is called on caller_locations also' do
expect(caller_locations[1].to_s).to eq(caller_locations(2..2).first.to_s)
expect_offense(<<~RUBY)
caller_locations[1]
^^^^^^^^^^^^^^^^^^^ Use `caller_locations(2..2).first` instead of `caller_locations[1]`.
^^^^^^^^^^^^^^^^^^^ Use `caller_locations(2..2)&.first` instead of `caller_locations[1]`.
RUBY

expect_correction(<<~RUBY)
caller_locations(2..2).first
caller_locations(2..2)&.first
RUBY
end
end

0 comments on commit f874d1d

Please sign in to comment.