forked from rubocop/rubocop-rails
/
hash_enum.rb
59 lines (51 loc) · 1.55 KB
/
hash_enum.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# frozen_string_literal: true
module RuboCop
module Cop
module Rails
# This cop looks for enums written with array syntax
#
# @example
# # bad
# enum status: [:active, :archived]
#
# # good
# enum status: { active: 0, archived: 1 }
#
class HashEnum < Cop
MSG = 'Enum defined as an array found in `%<enum>s` enum declaration. '\
'Use hash syntax instead.'
def_node_matcher :enum_with_array?, <<~PATTERN
(send nil? :enum (hash (pair (_ $_) array)))
PATTERN
def on_send(node)
enum_with_array?(node) do |name, _args|
add_offense(node, message: format(MSG, enum: name))
end
end
def autocorrect(node)
enum_values = node.children[2].children.first.children[1]
to_replace = enum_values.loc.expression
values_hash = "{ #{converted_values(enum_values)} }"
->(corrector) { corrector.replace(to_replace, values_hash) }
end
private
def converted_values(enum_values)
enum_values.children.each_with_index.map do |child, index|
hash_entry_as_string(child, index)
end.join(', ')
end
def hash_entry_as_string(child, index)
value = child.children.first
case value
when String
"'#{value}' => #{index}"
when Symbol
"#{value}: #{index}"
else
"#{child.source} => #{index}"
end
end
end
end
end
end