58 lines
1.6 KiB
Ruby
58 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
|