diff --git a/CHANGELOG.md b/CHANGELOG.md index 93e834e0ce3..334bc2fbc29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### New features + +* [#8111](https://github.com/rubocop-hq/rubocop/pull/8111): Add auto-correct for `Style/StructInheritance`. ([@tejasbubane][]) + ## 0.85.1 (2020-06-07) ### Bug fixes diff --git a/config/default.yml b/config/default.yml index 7ba5e2cd2ef..462c00e481b 100644 --- a/config/default.yml +++ b/config/default.yml @@ -3875,6 +3875,7 @@ Style/StructInheritance: StyleGuide: '#no-extend-struct-new' Enabled: true VersionAdded: '0.29' + VersionChanged: '0.86' Style/SymbolArray: Description: 'Use %i or %I for arrays of symbols.' diff --git a/docs/modules/ROOT/pages/cops_style.adoc b/docs/modules/ROOT/pages/cops_style.adoc index 771ffe684e0..aefaa80e5b1 100644 --- a/docs/modules/ROOT/pages/cops_style.adoc +++ b/docs/modules/ROOT/pages/cops_style.adoc @@ -8693,9 +8693,9 @@ This cop identifies places where `lstrip.rstrip` can be replaced by | Enabled | Yes -| No +| Yes | 0.29 -| - +| 0.86 |=== This cop checks for inheritance from Struct.new. diff --git a/lib/rubocop/cop/style/struct_inheritance.rb b/lib/rubocop/cop/style/struct_inheritance.rb index f7ff18c886a..31a66b60c34 100644 --- a/lib/rubocop/cop/style/struct_inheritance.rb +++ b/lib/rubocop/cop/style/struct_inheritance.rb @@ -20,6 +20,8 @@ module Style # end # end class StructInheritance < Cop + include RangeHelp + MSG = "Don't extend an instance initialized by `Struct.new`. " \ 'Use a block to customize the struct.' @@ -29,10 +31,29 @@ def on_class(node) add_offense(node, location: node.parent_class.source_range) end + def autocorrect(node) + lambda do |corrector| + corrector.remove(range_with_surrounding_space(range: node.loc.keyword)) + corrector.replace(node.loc.operator, '=') + + correct_parent(node.parent_class, corrector) + end + end + def_node_matcher :struct_constructor?, <<~PATTERN {(send (const nil? :Struct) :new ...) (block (send (const nil? :Struct) :new ...) ...)} PATTERN + + private + + def correct_parent(parent, corrector) + if parent.block_type? + corrector.remove(range_with_surrounding_space(range: parent.loc.end, newlines: false)) + else + corrector.insert_after(parent.loc.expression, ' do') + end + end end end end diff --git a/spec/rubocop/cop/style/struct_inheritance_spec.rb b/spec/rubocop/cop/style/struct_inheritance_spec.rb index 81656563c9c..6ab38ca1c41 100644 --- a/spec/rubocop/cop/style/struct_inheritance_spec.rb +++ b/spec/rubocop/cop/style/struct_inheritance_spec.rb @@ -7,6 +7,13 @@ expect_offense(<<~RUBY) class Person < Struct.new(:first_name, :last_name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't extend an instance initialized by `Struct.new`. Use a block to customize the struct. + def foo; end + end + RUBY + + expect_correction(<<~RUBY) + Person = Struct.new(:first_name, :last_name) do + def foo; end end RUBY end @@ -17,6 +24,11 @@ class Person < Struct.new(:first_name, :last_name) do end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't extend an instance initialized by `Struct.new`. Use a block to customize the struct. end RUBY + + expect_correction(<<~RUBY) + Person = Struct.new(:first_name, :last_name) do + end + RUBY end it 'accepts plain class' do