Skip to content

Commit

Permalink
[Fix #421] Fix false positives for Performance/TimesMap
Browse files Browse the repository at this point in the history
Fixes #421.

This PR fixes false positives for `Performance/TimesMap`
with a block with safe navigation call for nil literal.

It does not have a changelog entry because it is a patch to
a feature that has not been released yet.
  • Loading branch information
koic committed Dec 13, 2023
1 parent 8834ff4 commit 68632dd
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
9 changes: 9 additions & 0 deletions lib/rubocop/cop/performance/times_map.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ def on_block(node)

def check(node)
times_map_call(node) do |map_or_collect, count|
next unless handleable_receiver?(node)

add_offense(node, message: message(map_or_collect, count)) do |corrector|
replacement = "Array.new(#{count.source}#{map_or_collect.arguments.map { |arg| ", #{arg.source}" }.join})"

Expand All @@ -58,6 +60,13 @@ def check(node)
end
end

def handleable_receiver?(node)
receiver = node.receiver.receiver
return true if receiver.literal? && (receiver.int_type? || receiver.float_type?)

node.receiver.dot?
end

def message(map_or_collect, count)
template = if count.literal?
"#{MESSAGE}."
Expand Down
42 changes: 42 additions & 0 deletions spec/rubocop/cop/performance/times_map_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,48 @@
end
end

context 'with a block with safe navigation call for integer literal' do
it 'registers an offense and corrects' do
expect_offense(<<~RUBY, method: method)
42&.times&.#{method} { |i| i.to_s }
^^^^^^^^^^^^{method}^^^^^^^^^^^^^^^ Use `Array.new(42)` with a block instead of `.times.#{method}`.
RUBY
end
end

context 'with a block with safe navigation call for float literal' do
it 'registers an offense and corrects' do
expect_offense(<<~RUBY, method: method)
4.2&.times&.#{method} { |i| i.to_s }
^^^^^^^^^^^^^{method}^^^^^^^^^^^^^^^ Use `Array.new(4.2)` with a block instead of `.times.#{method}`.
RUBY
end
end

context 'with a block with safe navigation call for nil literal' do
it 'does not register an offense' do
expect_no_offenses(<<~RUBY, method: method)
nil&.times&.#{method} { |i| i.to_s }
RUBY
end
end

context 'with a block with safe navigation call for local variable' do
it 'does not register an offense' do
expect_no_offenses(<<~RUBY, method: method)
nullable&.times&.#{method} { |i| i.to_s }
RUBY
end
end

context 'with a block with safe navigation call for instance variable' do
it 'does not register an offense' do
expect_no_offenses(<<~RUBY, method: method)
@nullable&.times&.#{method} { |i| i.to_s }
RUBY
end
end

context 'for non-literal receiver' do
it 'registers an offense' do
expect_offense(<<~RUBY, method: method)
Expand Down

0 comments on commit 68632dd

Please sign in to comment.