Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix an infinite loop for Style/MultilineMethodSignature when line break after def #12763

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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