Skip to content

Commit

Permalink
Fix an infinite loop for Style/MultilineMethodSignature when line b…
Browse files Browse the repository at this point in the history
…reak after def

This commit removes this exit condition from `expect_correction`. It is now only considered done when there are no correctors anymore.
This has hidden the infinite loop this commit fixes.
  • Loading branch information
Earlopain authored and bbatsov committed Mar 10, 2024
1 parent ca8b38c commit 55cbc7f
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#12763](https://github.com/rubocop/rubocop/pull/12763): Fix an infinite loop for `Style/MultilineMethodSignature` when there is a newline directly after the def keyword. ([@earlopain][])
11 changes: 10 additions & 1 deletion lib/rubocop/cop/style/multiline_method_signature.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def on_def(node)

private

# rubocop:disable Metrics/AbcSize
def autocorrect(corrector, node, begin_of_arguments)
arguments = node.arguments
joined_arguments = arguments.map(&:source).join(', ')
Expand All @@ -49,9 +50,17 @@ def autocorrect(corrector, node, begin_of_arguments)
corrector.remove(range_by_whole_lines(arguments.loc.end, include_final_newline: true))
end

corrector.remove(arguments_range(node))
arguments_range = arguments_range(node)
# If the method name isn't on the same line as def, move it directly after def
if arguments_range.first_line != opening_line(node)
corrector.remove(node.loc.name)
corrector.insert_after(node.loc.keyword, " #{node.loc.name.source}")
end

corrector.remove(arguments_range)
corrector.insert_after(begin_of_arguments, joined_arguments)
end
# rubocop:enable Metrics/AbcSize

def last_line_source_of_arguments(arguments)
processed_source[arguments.last_line - 1].strip
Expand Down
5 changes: 2 additions & 3 deletions lib/rubocop/rspec/expect_offense.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def expect_offense(source, file = nil, severity: nil, chomp: false, **replacemen
@offenses
end

# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
def expect_correction(correction, loop: true, source: nil)
if source
expected_annotations = parse_annotations(source, raise_error: false)
Expand All @@ -148,7 +148,6 @@ def expect_correction(correction, loop: true, source: nil)

break corrected_source unless loop
break corrected_source if @last_corrector.empty?
break corrected_source if corrected_source == @processed_source.buffer.source

if iteration > RuboCop::Runner::MAX_ITERATIONS
raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [@offenses])
Expand All @@ -163,7 +162,7 @@ def expect_correction(correction, loop: true, source: nil)

expect(new_source).to eq(correction)
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity

def expect_no_corrections
raise '`expect_no_corrections` must follow `expect_offense`' unless @processed_source
Expand Down
23 changes: 22 additions & 1 deletion spec/rubocop/cop/style/multiline_method_signature_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,29 @@ def foo(arg)
RUBY

expect_correction(<<~RUBY)
def foo
(bar)
end
RUBY
end

it 'registers an offense and corrects when closing paren is on the following line' \
'and multiple line breaks after `def` keyword' do
expect_offense(<<~RUBY)
def
foo(bar)
^^^ Avoid multi-line method signatures.
foo(bar
)
end
RUBY

expect_correction(<<~RUBY)
def foo
(bar)
end
RUBY
end
Expand Down

0 comments on commit 55cbc7f

Please sign in to comment.