Skip to content

Commit

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

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 12, 2023
1 parent 8834ff4 commit 5ad1265
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
10 changes: 10 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,14 @@ def check(node)
end
end

def handleable_receiver?(node)
receiver = node.receiver.receiver

return true unless receiver.literal?

receiver.int_type? || receiver.float_type?
end

def message(map_or_collect, count)
template = if count.literal?
"#{MESSAGE}."
Expand Down
26 changes: 26 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,32 @@
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 and corrects' do
expect_no_offenses(<<~RUBY, method: method)
nil&.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 5ad1265

Please sign in to comment.