Skip to content

Commit

Permalink
Performance/Sum should avoid empty arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
ghiculescu committed Oct 8, 2020
1 parent 79d11d7 commit 2e91541
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 13 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Changes

* [#170](https://github.com/rubocop-hq/rubocop-performance/pull/170): Extend `Performance/Sum` to register an offense for `map { ... }.sum`. ([@eugeneius][])
* [#179](https://github.com/rubocop-hq/rubocop-performance/pull/179): Change `Performance/Sum` to not error on empty array literals. ([@ghiculescu][])

## 1.8.1 (2020-09-19)

Expand Down Expand Up @@ -174,3 +175,4 @@
[@siegfault]: https://github.com/siegfault
[@fatkodima]: https://github.com/fatkodima
[@dvandersluis]: https://github.com/dvandersluis
[@ghiculescu]: https://github.com/ghiculescu
39 changes: 26 additions & 13 deletions lib/rubocop/cop/performance/sum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,28 @@ class Sum < Base
alias elem_plus_acc? acc_plus_elem?

def on_send(node)
return if empty_array_literal?(node.children.first)

handle_sum_candidate(node)
handle_sum_map_candidate(node)
end

def on_block(node)
sum_with_block_candidate?(node) do |send, init, var_acc, var_elem, body|
if acc_plus_elem?(body, var_acc, var_elem) || elem_plus_acc?(body, var_elem, var_acc)
range = sum_block_range(send, node)
message = build_block_message(send, init, var_acc, var_elem, body)

add_offense(range, message: message) do |corrector|
autocorrect(corrector, init, range)
end
end
end
end

private

def handle_sum_candidate(node)
sum_candidate?(node) do |method, init, operation|
range = sum_method_range(node)
message = build_method_message(method, init, operation)
Expand All @@ -61,7 +83,9 @@ def on_send(node)
autocorrect(corrector, init, range)
end
end
end

def handle_sum_map_candidate(node)
sum_map_candidate?(node) do |map, init|
next if node.block_literal? || node.block_argument?

Expand All @@ -73,21 +97,10 @@ def on_send(node)
end
end

def on_block(node)
sum_with_block_candidate?(node) do |send, init, var_acc, var_elem, body|
if acc_plus_elem?(body, var_acc, var_elem) || elem_plus_acc?(body, var_elem, var_acc)
range = sum_block_range(send, node)
message = build_block_message(send, init, var_acc, var_elem, body)

add_offense(range, message: message) do |corrector|
autocorrect(corrector, init, range)
end
end
end
def empty_array_literal?(node)
!node.nil? && node.literal? && node.array_type? && node.children.empty?
end

private

def autocorrect(corrector, init, range)
return if init.empty?

Expand Down
16 changes: 16 additions & 0 deletions spec/rubocop/cop/performance/sum_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,22 @@
expect_no_corrections
end

# ideally it would autocorrect to `[1, 2, 3].sum`
it 'registers an offense but does not autocorrect on array literals' do
expect_offense(<<~RUBY, method: method)
[1, 2, 3].#{method}(:+)
^{method}^^^^ Use `sum` instead of `#{method}(:+)`.
RUBY

expect_no_corrections
end

it 'does not register an offense when the array is empty' do
expect_no_offenses(<<~RUBY, method: method)
[].#{method}(:+)
RUBY
end

it 'does not register an offense when block does not implement summation' do
expect_no_offenses(<<~RUBY)
array.#{method} { |acc, elem| elem * 2 }
Expand Down

0 comments on commit 2e91541

Please sign in to comment.