Skip to content

Commit

Permalink
[Fix rubocop#11672] Fix an error for Layout/BlockEndNewline
Browse files Browse the repository at this point in the history
Fixes rubocop#11672.

This PR fixes an error for `Layout/BlockEndNewline` when multiline block `}`
is not on its own line and it is used as multiple arguments.

And the following case is handled by `Style/Semicolon`:

```ruby
test do
  foo
; end
```

So make it out of the responsibility of `Layout/BlockEndNewline`.
  • Loading branch information
koic committed Mar 7, 2023
1 parent 1f7094d commit efdb100
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 30 deletions.
1 change: 1 addition & 0 deletions changelog/fix_an_error_for_layout_block_end_newline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#11672](https://github.com/rubocop/rubocop/issues/11672): Fix an error for `Layout/BlockEndNewline` when multiline block `}` is not on its own line and it is used as multiple arguments. ([@koic][])
28 changes: 7 additions & 21 deletions lib/rubocop/cop/layout/block_end_newline.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,19 @@ def on_block(node)
# If the end is on its own line, there is no offense
return if begins_its_line?(node.loc.end)

register_offense(node)
offense_range = offense_range(node)
return if offense_range.source.lstrip.start_with?(';')

register_offense(node, offense_range)
end

alias on_numblock on_block

private

def register_offense(node)
def register_offense(node, offense_range)
add_offense(node.loc.end, message: message(node)) do |corrector|
offense_range = offense_range(node)
replacement = replacement(node)
replacement = "\n#{offense_range.source.lstrip}"

if (heredoc = last_heredoc_argument(node.body))
corrector.remove(offense_range)
Expand All @@ -72,23 +74,7 @@ def last_heredoc_argument(node)
end

def offense_range(node)
Parser::Source::Range.new(
node.source_range.source_buffer,
node.children.compact.last.source_range.end_pos,
end_of_method_chain(node).source_range.end_pos
)
end

def replacement(node)
end_with_method_chain = node.loc.end.join(end_of_method_chain(node).source_range.end)

"\n#{end_with_method_chain.source.strip}"
end

def end_of_method_chain(node)
return node unless node.parent&.call_type?

end_of_method_chain(node.parent)
node.children.compact.last.source_range.end.join(node.loc.end)
end
end
end
Expand Down
30 changes: 21 additions & 9 deletions spec/rubocop/cop/layout/block_end_newline_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,11 @@
RUBY
end

it 'registers an offense when multiline blocks with newlines before the `; end`' do
expect_offense(<<~RUBY)
it 'does not register an offense when multiline blocks with newlines before the `; end`' do
expect_no_offenses(<<~RUBY)
test do
foo
; end
^^^ Expression at 3, 3 should be on its own line.
RUBY

expect_correction(<<~RUBY)
test do
foo
end
RUBY
end

Expand Down Expand Up @@ -86,6 +79,25 @@
RUBY
end

it 'registers an offense and corrects when multiline block `}` is not on its own line ' \
'and it is used as multiple arguments' do
expect_offense(<<~RUBY)
foo(one {
x }, two {
^ Expression at 2, 5 should be on its own line.
y })
^ Expression at 3, 5 should be on its own line.
RUBY

expect_correction(<<~RUBY)
foo(one {
x
}, two {
y
})
RUBY
end

it 'registers an offense and corrects when multiline block `}` is not on its own line ' \
'and using heredoc argument' do
expect_offense(<<~RUBY)
Expand Down

0 comments on commit efdb100

Please sign in to comment.