diff --git a/changelog/fix_fix_infinite_loop_between.md b/changelog/fix_fix_infinite_loop_between.md new file mode 100644 index 00000000000..0b0ea3f01de --- /dev/null +++ b/changelog/fix_fix_infinite_loop_between.md @@ -0,0 +1 @@ +* [#9619](https://github.com/rubocop/rubocop/pull/9619): Fix infinite loop between `Layout/IndentationWidth` and `Layout/RescueEnsureAlignment` autocorrection. ([@dvandersluis][]) diff --git a/lib/rubocop/cop/layout/indentation_width.rb b/lib/rubocop/cop/layout/indentation_width.rb index 705c65a4da1..73ff3e482fb 100644 --- a/lib/rubocop/cop/layout/indentation_width.rb +++ b/lib/rubocop/cop/layout/indentation_width.rb @@ -310,12 +310,20 @@ def other_offense_in_same_range?(node) def indentation_to_check?(base_loc, body_node) return false if skip_check?(base_loc, body_node) - if %i[rescue ensure].include?(body_node.type) + if body_node.rescue_type? + check_rescue?(body_node) + elsif body_node.ensure_type? block_body, = *body_node return unless block_body + + check_rescue?(block_body) if block_body.rescue_type? + else + true end + end - true + def check_rescue?(rescue_node) + rescue_node.body end def skip_check?(base_loc, body_node) diff --git a/spec/rubocop/cli/autocorrect_spec.rb b/spec/rubocop/cli/autocorrect_spec.rb index a8da92c6594..cf864d8b8f6 100644 --- a/spec/rubocop/cli/autocorrect_spec.rb +++ b/spec/rubocop/cli/autocorrect_spec.rb @@ -1885,4 +1885,49 @@ def do_even_more_stuff expect(status).to eq(0) expect(source_file.read).to eq(source) end + + it 'corrects indentation for a begin/rescue/else/ensure/end block properly' do + source_file = Pathname('example.rb') + create_file(source_file, <<~RUBY) + def my_func + puts 'do something outside block' + begin + puts 'do something error prone' + rescue SomeException, SomeOther + puts 'wrongly indented error handling' + rescue StandardError + puts 'another wrongly indented error handling' + else + puts 'wrongly indented normal case handling' + ensure + puts 'wrongly indented common handling' + end + end + RUBY + + status = cli.run( + [ + '--auto-correct', + '--only', + 'Layout/IndentationWidth,Layout/RescueEnsureAlignment,Layout/ElseAlignment' + ] + ) + expect(status).to eq(0) + expect(source_file.read).to eq(<<~RUBY) + def my_func + puts 'do something outside block' + begin + puts 'do something error prone' + rescue SomeException, SomeOther + puts 'wrongly indented error handling' + rescue StandardError + puts 'another wrongly indented error handling' + else + puts 'wrongly indented normal case handling' + ensure + puts 'wrongly indented common handling' + end + end + RUBY + end end diff --git a/spec/rubocop/cop/layout/indentation_width_spec.rb b/spec/rubocop/cop/layout/indentation_width_spec.rb index bca2f261f0a..a265b9ddda4 100644 --- a/spec/rubocop/cop/layout/indentation_width_spec.rb +++ b/spec/rubocop/cop/layout/indentation_width_spec.rb @@ -213,6 +213,46 @@ class Test RUBY end + it 'accepts `rescue`/`ensure` after an empty body' do + expect_no_offenses(<<~RUBY) + begin + rescue + handle_error + ensure + something + end + RUBY + end + + it 'accepts `rescue` after an empty def' do + expect_no_offenses(<<~RUBY) + def foo + rescue + handle_error + end + RUBY + end + + it 'accepts `ensure` after an empty def' do + expect_no_offenses(<<~RUBY) + def foo + ensure + something + end + RUBY + end + + it 'accepts `rescue`/`ensure` after an empty def' do + expect_no_offenses(<<~RUBY) + def foo + rescue + handle_error + ensure + something + end + RUBY + end + it 'does not raise any error with empty braces' do expect_no_offenses(<<~RUBY) if cond @@ -1294,16 +1334,16 @@ def my_func puts 'do something error prone' ^{} Use 2 (not 0) spaces for indentation. rescue SomeException, SomeOther => e - puts 'wrongly intended error handling' + puts 'wrongly indented error handling' ^ Use 2 (not 1) spaces for indentation. rescue - puts 'wrongly intended error handling' + puts 'wrongly indented error handling' ^ Use 2 (not 1) spaces for indentation. else - puts 'wrongly intended normal case handling' + puts 'wrongly indented normal case handling' ^^^ Use 2 (not 3) spaces for indentation. ensure - puts 'wrongly intended common handling' + puts 'wrongly indented common handling' ^^^^ Use 2 (not 4) spaces for indentation. end end @@ -1317,13 +1357,23 @@ def my_func def my_func puts 'do something error prone' rescue SomeException - puts 'wrongly intended error handling' + puts 'wrongly indented error handling' ^ Use 2 (not 1) spaces for indentation. rescue - puts 'wrongly intended error handling' + puts 'wrongly indented error handling' ^ Use 2 (not 1) spaces for indentation. end RUBY + + expect_correction(<<~RUBY) + def my_func + puts 'do something error prone' + rescue SomeException + puts 'wrongly indented error handling' + rescue + puts 'wrongly indented error handling' + end + RUBY end it 'registers an offense for bad indent of defs bodies with a modifier' do @@ -1331,10 +1381,10 @@ def my_func foo def self.my_func puts 'do something error prone' rescue SomeException - puts 'wrongly intended error handling' + puts 'wrongly indented error handling' ^ Use 2 (not 1) spaces for indentation. rescue - puts 'wrongly intended error handling' + puts 'wrongly indented error handling' ^ Use 2 (not 1) spaces for indentation. end RUBY diff --git a/spec/rubocop/cop/layout/rescue_ensure_alignment_spec.rb b/spec/rubocop/cop/layout/rescue_ensure_alignment_spec.rb index c7a8059b69a..59b9b068583 100644 --- a/spec/rubocop/cop/layout/rescue_ensure_alignment_spec.rb +++ b/spec/rubocop/cop/layout/rescue_ensure_alignment_spec.rb @@ -408,6 +408,29 @@ def method2 RUBY end + it 'accepts correctly aligned rescue/ensure with def' do + expect_no_offenses(<<~RUBY) + def foo + something + rescue StandardError + handle_error + ensure + error + end + RUBY + end + + it 'accepts correctly aligned rescue/ensure with def with no body' do + expect_no_offenses(<<~RUBY) + def foo + rescue StandardError + handle_error + ensure + error + end + RUBY + end + it 'accepts correctly aligned rescue in assigned begin-end block' do expect_no_offenses(<<-RUBY) foo = begin