class Gitlab::Styles::Rubocop::Cop::Style::HashTransformation

This cop identifies places where `map { … }.to_h` or `Hash[map { … }]` can be replaced with `to_h { … }`, saving an intermediate array allocation.

@example

# bad
hash.map { |k, v| [v.upcase, k.downcase] }.to_h
hash.collect { |k, v| [v.upcase, k.downcase] }.to_h
Hash[hash.map { |k, v| [v.upcase, k.downcase] }]
Hash[hash.collect { |k, v| [v.upcase, k.downcase] }]
array.map { |x| [x, x + 1] }.to_h

# good
hash.to_h { |k, v| [v.upcase, k.downcase] }
array.to_h { |x| [x, x + 1] }

Full credit: github.com/eugeneius/rubocop-performance/blob/hash_transformation/lib/rubocop/cop/performance/hash_transformation.rb

Constants

MSG

Public Instance Methods

autocorrect(node) click to toggle source
# File lib/gitlab/styles/rubocop/cop/style/hash_transformation.rb, line 47
def autocorrect(node)
  block, call = to_h_candidate?(node)

  lambda do |corrector|
    corrector.remove(after_block(node, block))
    corrector.replace(call.loc.selector, 'to_h')
    corrector.remove(before_block(node, block))
  end
end
on_send(node) click to toggle source
# File lib/gitlab/styles/rubocop/cop/style/hash_transformation.rb, line 39
def on_send(node)
  to_h_candidate?(node) do |_block, call|
    range = offense_range(node, call)
    message = message(node, call)
    add_offense(node, location: range, message: message)
  end
end

Private Instance Methods

after_block(node, block) click to toggle source
# File lib/gitlab/styles/rubocop/cop/style/hash_transformation.rb, line 75
def after_block(node, block)
  block.source_range.end.join(node.source_range.end)
end
before_block(node, block) click to toggle source
# File lib/gitlab/styles/rubocop/cop/style/hash_transformation.rb, line 79
def before_block(node, block)
  node.source_range.begin.join(block.source_range.begin)
end
message(node, call) click to toggle source
# File lib/gitlab/styles/rubocop/cop/style/hash_transformation.rb, line 65
def message(node, call)
  current = if node.children.first.const_type?
              "Hash[#{call.method_name} { ... }]"
            else
              "#{call.method_name} { ... }.to_h"
            end

  format(MSG, current: current)
end
offense_range(node, call) click to toggle source
# File lib/gitlab/styles/rubocop/cop/style/hash_transformation.rb, line 59
def offense_range(node, call)
  return node.source_range if node.children.first.const_type?

  range_between(call.loc.selector.begin_pos, node.loc.selector.end_pos)
end