diff --git a/changelog/change_update_lintelselayout_to_be_able_to.md b/changelog/change_update_lintelselayout_to_be_able_to.md new file mode 100644 index 00000000000..3d42c2b86b4 --- /dev/null +++ b/changelog/change_update_lintelselayout_to_be_able_to.md @@ -0,0 +1 @@ +* [#10130](https://github.com/rubocop/rubocop/issues/10130): Update `Lint/ElseLayout` to be able to handle an `else` with only a single line. ([@dvandersluis][]) diff --git a/lib/rubocop/cop/lint/else_layout.rb b/lib/rubocop/cop/lint/else_layout.rb index 6043cc5630a..f41caab5928 100644 --- a/lib/rubocop/cop/lint/else_layout.rb +++ b/lib/rubocop/cop/lint/else_layout.rb @@ -49,6 +49,9 @@ class ElseLayout < Base def on_if(node) return if node.ternary? + # If the if is on a single line, it'll be handled by `Style/OneLineConditional` + return if node.single_line? + check(node) end @@ -66,10 +69,7 @@ def check(node) def check_else(node) else_branch = node.else_branch - - return unless else_branch.begin_type? - - first_else = else_branch.children.first + first_else = else_branch.begin_type? ? else_branch.children.first : else_branch return unless first_else return unless first_else.source_range.line == node.loc.else.line @@ -81,9 +81,13 @@ def autocorrect(corrector, node, first_else) corrector.insert_after(node.loc.else, "\n") blank_range = range_between(node.loc.else.end_pos, first_else.loc.expression.begin_pos) - indentation = indent(node.else_branch.children[1]) + indentation = indent(node, offset: indentation_width) corrector.replace(blank_range, indentation) end + + def indentation_width + @config.for_cop('Layout/IndentationWidth')['Width'] || 2 + end end end end diff --git a/lib/rubocop/cop/util.rb b/lib/rubocop/cop/util.rb index 8ef3a276082..d5db3193675 100644 --- a/lib/rubocop/cop/util.rb +++ b/lib/rubocop/cop/util.rb @@ -129,8 +129,8 @@ def same_line?(node1, node2) node1.respond_to?(:loc) && node2.respond_to?(:loc) && node1.loc.line == node2.loc.line end - def indent(node) - ' ' * node.loc.column + def indent(node, offset: 0) + ' ' * (node.loc.column + offset) end def to_supported_styles(enforced_style) diff --git a/spec/rubocop/cop/lint/else_layout_spec.rb b/spec/rubocop/cop/lint/else_layout_spec.rb index 098da490faa..9369f456951 100644 --- a/spec/rubocop/cop/lint/else_layout_spec.rb +++ b/spec/rubocop/cop/lint/else_layout_spec.rb @@ -23,22 +23,31 @@ RUBY end - it 'accepts proper else' do - expect_no_offenses(<<~RUBY) + it 'registers an offense and corrects for the entire else body being on the same line' do + expect_offense(<<~RUBY) if something test - else - something + else something_else + ^^^^^^^^^^^^^^ Odd `else` layout detected. Did you mean to use `elsif`? + end + RUBY + + expect_correction(<<~RUBY) + if something test + else + something_else end RUBY end - it 'accepts single-expr else regardless of layout' do + it 'accepts proper else' do expect_no_offenses(<<~RUBY) if something test - else bala + else + something + test end RUBY end @@ -116,4 +125,19 @@ end RUBY end + + it 'does not register an offense for an elsif with no body' do + expect_no_offenses(<<~RUBY) + if something + foo + elsif something_else + end + RUBY + end + + it 'does not register an offense if the entire if is on a single line' do + expect_no_offenses(<<~RUBY) + if a then b else c end + RUBY + end end