diff --git a/lib/rubocop/cop/performance/times_map.rb b/lib/rubocop/cop/performance/times_map.rb index 9b9c120638..7b37959479 100644 --- a/lib/rubocop/cop/performance/times_map.rb +++ b/lib/rubocop/cop/performance/times_map.rb @@ -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})" @@ -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}." diff --git a/spec/rubocop/cop/performance/times_map_spec.rb b/spec/rubocop/cop/performance/times_map_spec.rb index 71b7ef59f4..9d393fcf41 100644 --- a/spec/rubocop/cop/performance/times_map_spec.rb +++ b/spec/rubocop/cop/performance/times_map_spec.rb @@ -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)