Class: RuboCop::Cop::Performance::Sum
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
TargetRubyVersion,
AutoCorrector,
Base
|
|
Instance Chain:
self,
RangeHelp,
Base
|
|
Inherits: |
Base
|
Defined in: | lib/rubocop/cop/performance/sum.rb |
Overview
Identifies places where custom code finding the sum of elements
in some Enumerable object can be replaced by Enumerable#sum
method.
Constant Summary
-
MSG =
# File 'lib/rubocop/cop/performance/sum.rb', line 77'Use `%<good_method>s` instead of `%<bad_method>s`.'
-
MSG_IF_NO_INIT_VALUE =
# File 'lib/rubocop/cop/performance/sum.rb', line 78'Use `%<good_method>s` instead of `%<bad_method>s`, unless calling `%<bad_method>s` on an empty array.'
-
RESTRICT_ON_SEND =
# File 'lib/rubocop/cop/performance/sum.rb', line 80%i[inject reduce sum].freeze
Instance Method Summary
- #elem_plus_acc?
- #on_block(node)
-
#on_csend(node)
Alias for #on_send.
- #on_send(node) (also: #on_csend)
- #array_literal?(node) ⇒ Boolean private
- #autocorrect(corrector, init, range) private
- #autocorrect_sum_map(corrector, sum, map, init) private
- #build_block_bad_method(method, init, var_acc, var_elem, body) private
- #build_block_message(send, init, var_acc, var_elem, body) private
- #build_good_method(init, block_pass = nil) private
- #build_method_bad_method(init, method, operation) private
- #build_method_message(node, method, init, operation) private
- #build_sum_map_message(send_node, init) private
- #empty_array_literal?(node) ⇒ Boolean private
- #handle_sum_candidate(node) private
- #handle_sum_map_candidate(node) private
- #method_call_with_args_range(node) private
- #sum_block_range(send, node) private
- #sum_map_range(map, sum) private
- #sum_method_range(node) private
Instance Method Details
#array_literal?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/performance/sum.rb', line 160
def array_literal?(node) receiver = node.children.first receiver&.literal? && receiver.array_type? end
#autocorrect(corrector, init, range) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 165
def autocorrect(corrector, init, range) return if init.empty? && safe_autocorrect? replacement = build_good_method(init) corrector.replace(range, replacement) end
#autocorrect_sum_map(corrector, sum, map, init) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 173
def autocorrect_sum_map(corrector, sum, map, init) sum_range = method_call_with_args_range(sum) map_range = method_call_with_args_range(map) block_pass = map.last_argument if map.last_argument&.block_pass_type? replacement = build_good_method(init, block_pass) corrector.remove(sum_range) dot = map.loc.dot&.source || '' corrector.replace(map_range, "#{dot}#{replacement}") end
#build_block_bad_method(method, init, var_acc, var_elem, body) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 250
def build_block_bad_method(method, init, var_acc, var_elem, body) bad_method = method.to_s unless init.empty? init = init.first bad_method += "(#{init.source})" end bad_method += " { |#{var_acc}, #{var_elem}| #{body.source} }" bad_method end
#build_block_message(send, init, var_acc, var_elem, body) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 217
def (send, init, var_acc, var_elem, body) good_method = build_good_method(init) bad_method = build_block_bad_method(send.method_name, init, var_acc, var_elem, body) format(MSG, good_method: good_method, bad_method: bad_method) end
#build_good_method(init, block_pass = nil) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 223
def build_good_method(init, block_pass = nil) good_method = 'sum' args = [] unless init.empty? init = init.first args << init.source unless init.int_type? && init.value.zero? end args << block_pass.source if block_pass good_method += "(#{args.join(', ')})" unless args.empty? good_method end
#build_method_bad_method(init, method, operation) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 236
def build_method_bad_method(init, method, operation) bad_method = "#{method}(" unless init.empty? init = init.first bad_method += "#{init.source}, " end bad_method += if operation.block_pass_type? '&:+)' else ':+)' end bad_method end
#build_method_message(node, method, init, operation) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 198
def (node, method, init, operation) good_method = build_good_method(init) bad_method = build_method_bad_method(init, method, operation) msg = if init.empty? && !array_literal?(node) MSG_IF_NO_INIT_VALUE else MSG end format(msg, good_method: good_method, bad_method: bad_method) end
#build_sum_map_message(send_node, init) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 209
def (send_node, init) sum_method = build_good_method(init) good_method = "#{sum_method} { ... }" dot = send_node.loc.dot&.source || '.' bad_method = "#{send_node.method_name} { ... }#{dot}#{sum_method}" format(MSG, good_method: good_method, bad_method: bad_method) end
#elem_plus_acc?
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 105
alias elem_plus_acc? acc_plus_elem?
#empty_array_literal?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/performance/sum.rb', line 155
def empty_array_literal?(node) receiver = node.children.first array_literal?(node) && receiver && receiver.children.empty? end
#handle_sum_candidate(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 130
def handle_sum_candidate(node) sum_candidate?(node) do |method, init, operation| next if cop_config['OnlySumOrWithInitialValue'] && init.empty? range = sum_method_range(node) = (node, method, init, operation) add_offense(range, message: ) do |corrector| autocorrect(corrector, init, range) end end end
#handle_sum_map_candidate(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 143
def handle_sum_map_candidate(node) sum_map_candidate?(node) do |map, init| next if node.block_literal? || node.block_argument? = (map, init) add_offense(sum_map_range(map, node), message: ) do |corrector| autocorrect_sum_map(corrector, node, map, init) end end end
#method_call_with_args_range(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 261
def method_call_with_args_range(node) if (receiver = node.receiver) receiver.source_range.end.join(node.source_range.end) else node.source_range end end
#on_block(node)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 115
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) = (send, init, var_acc, var_elem, body) add_offense(range, message: ) do |corrector| autocorrect(corrector, init, range) end end end end
#on_csend(node)
Alias for #on_send.
# File 'lib/rubocop/cop/performance/sum.rb', line 113
alias on_csend on_send
#on_send(node) Also known as: #on_csend
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 107
def on_send(node) return if empty_array_literal?(node) handle_sum_candidate(node) handle_sum_map_candidate(node) end
#sum_block_range(send, node) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 194
def sum_block_range(send, node) range_between(send.loc.selector.begin_pos, node.loc.end.end_pos) end
#sum_map_range(map, sum) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 190
def sum_map_range(map, sum) range_between(map.loc.selector.begin_pos, sum.source_range.end.end_pos) end
#sum_method_range(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/sum.rb', line 186
def sum_method_range(node) range_between(node.loc.selector.begin_pos, node.source_range.end_pos) end