gitlab-org--gitlab-foss/rubocop/cop/gitlab/keys_first_and_values_first.rb

59 lines
1.6 KiB
Ruby

# frozen_string_literal: true
module RuboCop
module Cop
module Gitlab
# Detects the use of `.keys.first` or `.values.first` and suggests a
# change to `.each_key.first` or `.each_value.first`. This reduces
# memory usage and execution time.
#
# @example
#
# # bad
#
# hash.keys.first
# hash.values.first
#
# # good
#
# hash.each_key.first
# hash.each_value.first
#
class KeysFirstAndValuesFirst < RuboCop::Cop::Base
extend RuboCop::Cop::AutoCorrector
MSG = 'Prefer `.%{autocorrect_method}.first` over `.%{current_method}.first`. ' \
'This reduces memory usage and execution time.'
AUTOCORRECT_METHOD = {
keys: 'each_key',
values: 'each_value'
}.freeze
def_node_matcher :keys_or_values_first, <<~PATTERN
(send (send ({send const hash lvar} ...) ${:keys :values}) :first)
PATTERN
def on_send(node)
current_method = keys_or_values_first(node)
return unless current_method
autocorrect_method = AUTOCORRECT_METHOD.fetch(current_method)
msg = format(MSG, autocorrect_method: autocorrect_method, current_method: current_method)
add_offense(node.loc.selector, message: msg) do |corrector|
replacement = "#{autocorrect_expression(node)}.#{autocorrect_method}.first"
corrector.replace(node, replacement)
end
end
private
def autocorrect_expression(node)
node.receiver.receiver.source
end
end
end
end
end