class RuboCop::Cop::Performance::RedundantMerge
This cop identifies places where `Hash#merge!` can be replaced by `Hash#[]=`. You can set the maximum number of key-value pairs to consider an offense with `MaxKeyValuePairs`.
This cop is marked as unsafe because RuboCop
cannot determine if the receiver of `merge!` is actually a hash or not.
@example
# bad hash.merge!(a: 1) hash.merge!({'key' => 'value'}) # good hash[:a] = 1 hash['key'] = 'value'
@example MaxKeyValuePairs: 2 (default)
# bad hash.merge!(a: 1, b: 2) # good hash[:a] = 1 hash[:b] = 2
Constants
- AREF_ASGN
- MSG
- RESTRICT_ON_SEND
- WITH_MODIFIER_CORRECTION
Public Instance Methods
on_send(node)
click to toggle source
# File lib/rubocop/cop/performance/redundant_merge.rb, line 51 def on_send(node) each_redundant_merge(node) do |redundant_merge_node| message = message(node) add_offense(redundant_merge_node, message: message) do |corrector| redundant_merge_candidate(node) do |receiver, pairs| new_source = to_assignments(receiver, pairs).join("\n") if node.parent && pairs.size > 1 correct_multiple_elements(corrector, node, node.parent, new_source) else correct_single_element(corrector, node, new_source) end end end end end
Private Instance Methods
correct_multiple_elements(corrector, node, parent, new_source)
click to toggle source
# File lib/rubocop/cop/performance/redundant_merge.rb, line 106 def correct_multiple_elements(corrector, node, parent, new_source) if modifier_flow_control?(parent) new_source = rewrite_with_modifier(node, parent, new_source) node = parent else padding = "\n#{leading_spaces(node)}" new_source.gsub!(/\n/, padding) end corrector.replace(node.source_range, new_source) end
correct_single_element(corrector, node, new_source)
click to toggle source
# File lib/rubocop/cop/performance/redundant_merge.rb, line 118 def correct_single_element(corrector, node, new_source) corrector.replace(node.source_range, new_source) end
each_redundant_merge(node) { |node| ... }
click to toggle source
# File lib/rubocop/cop/performance/redundant_merge.rb, line 78 def each_redundant_merge(node) redundant_merge_candidate(node) do |receiver, pairs| next if non_redundant_merge?(node, receiver, pairs) yield node end end
indent_width()
click to toggle source
# File lib/rubocop/cop/performance/redundant_merge.rb, line 150 def indent_width @config.for_cop('Layout/IndentationWidth')['Width'] || 2 end
kwsplat_used?(pairs)
click to toggle source
# File lib/rubocop/cop/performance/redundant_merge.rb, line 97 def kwsplat_used?(pairs) pairs.any?(&:kwsplat_type?) end
leading_spaces(node)
click to toggle source
# File lib/rubocop/cop/performance/redundant_merge.rb, line 146 def leading_spaces(node) node.source_range.source_line[/\A\s*/] end
max_key_value_pairs()
click to toggle source
# File lib/rubocop/cop/performance/redundant_merge.rb, line 154 def max_key_value_pairs Integer(cop_config['MaxKeyValuePairs'] || 2) end
message(node)
click to toggle source
# File lib/rubocop/cop/performance/redundant_merge.rb, line 70 def message(node) redundant_merge_candidate(node) do |receiver, pairs| assignments = to_assignments(receiver, pairs).join('; ') format(MSG, prefer: assignments, current: node.source) end end
non_redundant_merge?(node, receiver, pairs)
click to toggle source
# File lib/rubocop/cop/performance/redundant_merge.rb, line 86 def non_redundant_merge?(node, receiver, pairs) pairs.empty? || non_redundant_pairs?(receiver, pairs) || kwsplat_used?(pairs) || non_redundant_value_used?(receiver, node) end
non_redundant_pairs?(receiver, pairs)
click to toggle source
# File lib/rubocop/cop/performance/redundant_merge.rb, line 93 def non_redundant_pairs?(receiver, pairs) pairs.size > 1 && !receiver.pure? || pairs.size > max_key_value_pairs end
non_redundant_value_used?(receiver, node)
click to toggle source
# File lib/rubocop/cop/performance/redundant_merge.rb, line 101 def non_redundant_value_used?(receiver, node) node.value_used? && !EachWithObjectInspector.new(node, receiver).value_used? end
rewrite_with_modifier(node, parent, new_source)
click to toggle source
# File lib/rubocop/cop/performance/redundant_merge.rb, line 134 def rewrite_with_modifier(node, parent, new_source) indent = ' ' * indent_width padding = "\n#{indent + leading_spaces(node)}" new_source.gsub!(/\n/, padding) format(WITH_MODIFIER_CORRECTION, keyword: parent.loc.keyword.source, condition: parent.condition.source, leading_space: leading_spaces(node), indent: indent, body: new_source).chomp end
to_assignments(receiver, pairs)
click to toggle source
# File lib/rubocop/cop/performance/redundant_merge.rb, line 122 def to_assignments(receiver, pairs) pairs.map do |pair| key, value = *pair key = key.sym_type? && pair.colon? ? ":#{key.source}" : key.source format(AREF_ASGN, receiver: receiver.source, key: key, value: value.source) end end