From 2c0b6aff4fdbf858882d3c359833ef76e50e0ed9 Mon Sep 17 00:00:00 2001 From: Masataka Pocke Kuwabara Date: Fri, 26 Jul 2019 12:02:51 +0900 Subject: [PATCH] Fix false negatives for Rails/EnumHash cop --- lib/rubocop/cop/rails/enum_hash.rb | 28 ++++++++++++++--- spec/rubocop/cop/rails/enum_hash_spec.rb | 39 +++++++++++++++++++++--- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/lib/rubocop/cop/rails/enum_hash.rb b/lib/rubocop/cop/rails/enum_hash.rb index cff550baf6..639b96f887 100644 --- a/lib/rubocop/cop/rails/enum_hash.rb +++ b/lib/rubocop/cop/rails/enum_hash.rb @@ -21,13 +21,33 @@ class EnumHash < Cop MSG = 'Enum defined as an array found in `%s` enum declaration. '\ 'Use hash syntax instead.' - def_node_matcher :enum_with_array?, <<~PATTERN - (send nil? :enum (hash (pair (_ $_) array))) + def_node_matcher :enum?, <<~PATTERN + (send nil? :enum (hash $...)) + PATTERN + + def_node_matcher :array_pair?, <<~PATTERN + (pair $_ $array) PATTERN def on_send(node) - enum_with_array?(node) do |name| - add_offense(node, message: format(MSG, enum: name)) + enum?(node) do |pairs| + pairs.each do |pair| + key, array = array_pair?(pair) + next unless key + + add_offense(array, message: format(MSG, enum: enum_name(key))) + end + end + end + + private + + def enum_name(key) + case key.type + when :sym, :str + key.value + else + key.source end end end diff --git a/spec/rubocop/cop/rails/enum_hash_spec.rb b/spec/rubocop/cop/rails/enum_hash_spec.rb index a803c85a85..cd1201ca64 100644 --- a/spec/rubocop/cop/rails/enum_hash_spec.rb +++ b/spec/rubocop/cop/rails/enum_hash_spec.rb @@ -10,7 +10,7 @@ it 'registers an offense' do expect_offense(<<~RUBY) enum status: %i[active archived] - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead. + ^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead. RUBY end end @@ -19,7 +19,7 @@ it 'registers an offense' do expect_offense(<<~RUBY) enum status: %w[active archived] - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead. + ^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead. RUBY end end @@ -28,7 +28,7 @@ it 'registers an offense' do expect_offense(<<~RUBY) enum status: %i(active archived) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead. + ^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead. RUBY end end @@ -37,7 +37,7 @@ it 'registers an offense' do expect_offense(<<~RUBY) enum status: %w(active archived) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead. + ^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead. RUBY end end @@ -46,7 +46,36 @@ it 'registers an offense' do expect_offense(<<~RUBY) enum status: [:active, :archived] - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead. + ^^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead. + RUBY + end + end + + context 'when the enum name is a string' do + it 'registers an offense' do + expect_offense(<<~RUBY) + enum "status" => %i[active archived] + ^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead. + RUBY + end + end + + context 'when the enum name is not a literal' do + it 'registers an offense' do + expect_offense(<<~RUBY) + enum KEY => %i[active archived] + ^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `KEY` enum declaration. Use hash syntax instead. + RUBY + end + end + + context 'with multiple enum definition for a `enum` method call' do + it 'registers an offense' do + expect_offense(<<~RUBY) + enum status: %i[active archived], + ^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead. + role: %i[owner member guest] + ^^^^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `role` enum declaration. Use hash syntax instead. RUBY end end