From 601a5260210e2bb8de45f000603088d49f47ecbc Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Mon, 11 Mar 2024 09:08:15 +0100 Subject: [PATCH] Fix an infinite loop for `Style/RaiseArgs` with `EnforcedStyle: compact` 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. --- changelog/fix_infinite_loop_for_style_raise_args.md | 1 + lib/rubocop/cop/style/raise_args.rb | 2 +- lib/rubocop/rspec/expect_offense.rb | 9 +++++---- 3 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 changelog/fix_infinite_loop_for_style_raise_args.md diff --git a/changelog/fix_infinite_loop_for_style_raise_args.md b/changelog/fix_infinite_loop_for_style_raise_args.md new file mode 100644 index 000000000000..0828dd441316 --- /dev/null +++ b/changelog/fix_infinite_loop_for_style_raise_args.md @@ -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][]) diff --git a/lib/rubocop/cop/style/raise_args.rb b/lib/rubocop/cop/style/raise_args.rb index 6b6180edfc4a..3c5cfa3c76e4 100644 --- a/lib/rubocop/cop/style/raise_args.rb +++ b/lib/rubocop/cop/style/raise_args.rb @@ -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 diff --git a/lib/rubocop/rspec/expect_offense.rb b/lib/rubocop/rspec/expect_offense.rb index 5272dfcd7d2f..bf4d61d80a3d 100644 --- a/lib/rubocop/rspec/expect_offense.rb +++ b/lib/rubocop/rspec/expect_offense.rb @@ -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)