Skip to content

Commit

Permalink
Fix an infinite loop for Style/RaiseArgs with `EnforcedStyle: compa…
Browse files Browse the repository at this point in the history
…ct` when passing than 2 arguments to `raise`

The following test caused the loop: https://github.com/rubocop/rubocop/blob/5ee786dcadfa3c91096d9e81dcd16e4776ca6186/spec/rubocop/cop/style/raise_args_spec.rb#L130-L140

This changes `expect_no_corrections`  to always raise if there are correctors. In this case, the corrector replaced nothing, resulting in the same cop
being invocted again for the same reason.

The source assertion is left in because it produces nice diffs if there are actually changes.
  • Loading branch information
Earlopain authored and bbatsov committed Mar 11, 2024
1 parent bb0dd97 commit 8d2ef48
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 5 deletions.
1 change: 1 addition & 0 deletions changelog/fix_infinite_loop_for_style_raise_args.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#12774](https://github.com/rubocop/rubocop/pull/12774): Fix an infinite loop for `Style/RaiseArgs` with `EnforcedStyle: compact` when passing more than 2 arguments to `raise`. ([@earlopain][])
2 changes: 1 addition & 1 deletion lib/rubocop/cop/style/raise_args.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def correction_compact_to_exploded(node)

def correction_exploded_to_compact(node)
exception_node, *message_nodes = *node.arguments
return node.source if message_nodes.size > 1
return if message_nodes.size > 1

argument = message_nodes.first.source
exception_class = exception_node.receiver&.source || exception_node.source
Expand Down
9 changes: 5 additions & 4 deletions lib/rubocop/rspec/expect_offense.rb
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,13 @@ def expect_no_corrections

return if @last_corrector.empty?

# In order to print a nice diff, e.g. what source got corrected to,
# we need to run the actual corrections

# This is just here for a pretty diff if the source actually got changed
new_source = @last_corrector.rewrite

expect(new_source).to eq(@processed_source.buffer.source)

# There is an infinite loop if a corrector is present that did not make
# any changes. It will cause the same offense/correction on the next loop.
raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [@offenses])
end

def expect_no_offenses(source, file = nil)
Expand Down

0 comments on commit 8d2ef48

Please sign in to comment.