From e437bc6155138cf1c97f5ce9185e83725bf28f32 Mon Sep 17 00:00:00 2001 From: Santiago Bartesaghi Date: Wed, 24 Jul 2019 18:51:52 -0300 Subject: [PATCH 1/2] [Fix #78] Autocorrect EnumHash Cop --- lib/rubocop/cop/rails/enum_hash.rb | 29 ++++++++++++++++++++++++ manual/cops_rails.md | 2 +- spec/rubocop/cop/rails/enum_hash_spec.rb | 10 ++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/lib/rubocop/cop/rails/enum_hash.rb b/lib/rubocop/cop/rails/enum_hash.rb index 639b96f887..560ceddd02 100644 --- a/lib/rubocop/cop/rails/enum_hash.rb +++ b/lib/rubocop/cop/rails/enum_hash.rb @@ -50,6 +50,35 @@ def enum_name(key) key.source 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 = "'#{value}'" if value =~ /\s/ + "#{value}: #{index}" + else + "#{child.source} => #{index}" + end + end end end end diff --git a/manual/cops_rails.md b/manual/cops_rails.md index 2b12dae89e..017184d3c2 100644 --- a/manual/cops_rails.md +++ b/manual/cops_rails.md @@ -646,7 +646,7 @@ Whitelist | `find_by_sql` | Array Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged --- | --- | --- | --- | --- -Enabled | Yes | No | 2.3 | - +Enabled | Yes | Yes | 2.3 | - This cop looks for enums written with array syntax. diff --git a/spec/rubocop/cop/rails/enum_hash_spec.rb b/spec/rubocop/cop/rails/enum_hash_spec.rb index cd1201ca64..a371941d5c 100644 --- a/spec/rubocop/cop/rails/enum_hash_spec.rb +++ b/spec/rubocop/cop/rails/enum_hash_spec.rb @@ -79,6 +79,16 @@ RUBY end end + + it 'autocorrects' do + expect( + autocorrect_source( + 'enum status: [:old, :"very active", "is archived", 42]' + ) + ).to eq( + "enum status: { old: 0, 'very active': 1, 'is archived' => 2, 42 => 3 }" + ) + end end context 'when hash syntax is used' do From 9d54e36ddae9a2b966aaa509adb47ebaa84e59bc Mon Sep 17 00:00:00 2001 From: Santiago Bartesaghi Date: Fri, 26 Jul 2019 20:40:36 -0300 Subject: [PATCH 2/2] [Fix #78] Improvements --- lib/rubocop/cop/rails/enum_hash.rb | 39 ++++++------------------ spec/rubocop/cop/rails/enum_hash_spec.rb | 15 ++++----- 2 files changed, 18 insertions(+), 36 deletions(-) diff --git a/lib/rubocop/cop/rails/enum_hash.rb b/lib/rubocop/cop/rails/enum_hash.rb index 560ceddd02..c1c39e1a66 100644 --- a/lib/rubocop/cop/rails/enum_hash.rb +++ b/lib/rubocop/cop/rails/enum_hash.rb @@ -40,6 +40,16 @@ def on_send(node) end end + def autocorrect(node) + range = node.loc.expression + hash = node + .children + .each_with_index + .map { |elem, index| [elem.children.first, index] }.to_h + + ->(corrector) { corrector.replace(range, hash.to_s) } + end + private def enum_name(key) @@ -50,35 +60,6 @@ def enum_name(key) key.source 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 = "'#{value}'" if value =~ /\s/ - "#{value}: #{index}" - else - "#{child.source} => #{index}" - end - end end end end diff --git a/spec/rubocop/cop/rails/enum_hash_spec.rb b/spec/rubocop/cop/rails/enum_hash_spec.rb index a371941d5c..43016f853c 100644 --- a/spec/rubocop/cop/rails/enum_hash_spec.rb +++ b/spec/rubocop/cop/rails/enum_hash_spec.rb @@ -81,13 +81,14 @@ end it 'autocorrects' do - expect( - autocorrect_source( - 'enum status: [:old, :"very active", "is archived", 42]' - ) - ).to eq( - "enum status: { old: 0, 'very active': 1, 'is archived' => 2, 42 => 3 }" - ) + expect_offense(<<~RUBY) + enum status: [:old, :"very active", "is archived", 42] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead. + RUBY + + expect_correction(<<~RUBY) + enum status: {:old=>0, :"very active"=>1, "is archived"=>2, 42=>3} + RUBY end end