Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix a false positive for Layout/SingleLineBlockChain #10063

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1 @@
* [#10063](https://github.com/rubocop/rubocop/pull/10063): Fix a false positive for `Layout/SingleLineBlockChain` when method call chained on a new line after a single line block with trailing dot. ([@koic][])
19 changes: 15 additions & 4 deletions lib/rubocop/cop/layout/single_line_block_chain.rb
Expand Up @@ -37,15 +37,26 @@ def offending_range(node)
return unless receiver&.block_type?

receiver_location = receiver.loc
closing_block_delimiter_line_number = receiver_location.end.line
return if receiver_location.begin.line < closing_block_delimiter_line_number
closing_block_delimiter_line_num = receiver_location.end.line
return if receiver_location.begin.line < closing_block_delimiter_line_num

node_location = node.loc
dot_range = node_location.dot
return unless dot_range
return if dot_range.line > closing_block_delimiter_line_number
return unless call_method_after_block?(node, dot_range, closing_block_delimiter_line_num)

range_between(dot_range.begin_pos, node_location.selector.end_pos)
range_between(dot_range.begin_pos, selector_range(node).end_pos)
end

def call_method_after_block?(node, dot_range, closing_block_delimiter_line_num)
return false if dot_range.line > closing_block_delimiter_line_num

dot_range.column < selector_range(node).column
end

def selector_range(node)
# l.(1) has no selector, so we use the opening parenthesis instead
node.loc.selector || node.loc.begin
end
end
end
Expand Down
15 changes: 15 additions & 0 deletions spec/rubocop/cli/autocorrect_spec.rb
Expand Up @@ -2070,6 +2070,21 @@ def do_even_more_stuff
RUBY
end

it 'corrects `Layout/DotPosition` and `Layout/SingleLineBlockChain` offenses' do
source_file = Pathname('example.rb')
create_file(source_file, <<~RUBY)
example.select { |item| item.cond? }.
join('-')
RUBY

expect(cli.run(['-a', '--only', 'Layout/DotPosition,Layout/SingleLineBlockChain'])).to eq(0)

expect(source_file.read).to eq(<<~RUBY)
example.select { |item| item.cond? }
.join('-')
RUBY
end

it 'does not correct Style/IfUnlessModifier offense disabled by a comment directive and ' \
'does not fire Lint/RedundantCopDisableDirective offense even though that directive ' \
'would make the modifier form too long' do
Expand Down
19 changes: 19 additions & 0 deletions spec/rubocop/cop/layout/single_line_block_chain_spec.rb
Expand Up @@ -13,13 +13,32 @@
RUBY
end

it 'registers an offense for no selector method call chained on the same line as a block' do
expect_offense(<<~RUBY)
example.select { |item| item.cond? }.(42)
^^ Put method call on a separate line if chained to a single line block.
RUBY

expect_correction(<<~RUBY)
example.select { |item| item.cond? }
.(42)
RUBY
end

it 'does not register an offense for method call chained on a new line after a single line block' do
expect_no_offenses(<<~RUBY)
example.select { |item| item.cond? }
.join('-')
RUBY
end

it 'does not register an offense for method call chained on a new line after a single line block with trailing dot' do
expect_no_offenses(<<~RUBY)
example.select { |item| item.cond? }.
join('-')
RUBY
end

it 'does not register an offense for method call chained without a dot' do
expect_no_offenses(<<~RUBY)
example.select { |item| item.cond? } + 2
Expand Down