Skip to content

Commit 810c790

Browse files
koicbbatsov
authored andcommitted
Fix incorrect autocorrect for Style/StructInheritance cop
This fixes a syntax error caused by `Style/StructInheritance` when the inherited `Struct.new` is called without parentheses. Previously the cop inserted ` do` at the end of the parent send's source range. When `Style/MethodCallWithArgsParentheses` ran in the same iteration, it inserted a closing paren at the same position, producing invalid `Struct.new(:a, :b do)` with `do` inside the argument list. The cop now wraps the unparenthesized argument list in parentheses and appends ` do` as a single combined edit, eliminating the position conflict.
1 parent 1ec0554 commit 810c790

3 files changed

Lines changed: 29 additions & 0 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#15192](https://github.com/rubocop/rubocop/pull/15192): Fix incorrect autocorrect for `Style/StructInheritance` causing a syntax error when the inherited `Struct.new` is called without parentheses. ([@koic][])

lib/rubocop/cop/style/struct_inheritance.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ def correct_parent(parent, corrector)
6161
corrector.remove(range_with_surrounding_space(parent.loc.end, newlines: false))
6262
elsif (class_node = parent.parent).body.nil?
6363
corrector.remove(range_for_empty_class_body(class_node, parent))
64+
elsif unparenthesized_struct_new?(parent)
65+
wrap_unparenthesized_call_with_do(corrector, parent)
6466
else
6567
corrector.insert_after(parent, ' do')
6668
end
@@ -73,6 +75,17 @@ def range_for_empty_class_body(class_node, struct_new)
7375
range_by_whole_lines(class_node.loc.end, include_final_newline: true)
7476
end
7577
end
78+
79+
def unparenthesized_struct_new?(parent)
80+
parent.send_type? && parent.arguments.any? && !parent.parenthesized?
81+
end
82+
83+
def wrap_unparenthesized_call_with_do(corrector, parent)
84+
args_source = parent.arguments.map(&:source).join(', ')
85+
range = parent.loc.selector.end.join(parent.source_range.end)
86+
87+
corrector.replace(range, "(#{args_source}) do")
88+
end
7689
end
7790
end
7891
end

spec/rubocop/cop/style/struct_inheritance_spec.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,21 @@ def foo; end
1616
RUBY
1717
end
1818

19+
it 'registers an offense and adds parentheses when extending instance of Struct without parentheses' do
20+
expect_offense(<<~RUBY)
21+
class Person < Struct.new :first_name, :last_name
22+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't extend an instance initialized by `Struct.new`. Use a block to customize the struct.
23+
def foo; end
24+
end
25+
RUBY
26+
27+
expect_correction(<<~RUBY)
28+
Person = Struct.new(:first_name, :last_name) do
29+
def foo; end
30+
end
31+
RUBY
32+
end
33+
1934
it 'registers an offense when extending instance of ::Struct' do
2035
expect_offense(<<~RUBY)
2136
class Person < ::Struct.new(:first_name, :last_name)

0 commit comments

Comments
 (0)