-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new
Style/SingleLineDoEndBlock
cop
This PR adds new `Style/SingleLineDoEndBlock` cop that checks for single-line `do`...`end` blocks. ```ruby # bad foo do |arg| bar(arg) end # good foo do |arg| bar(arg) end # bad ->(arg) do bar(arg) end # good ->(arg) { bar(arg) } ``` In practice a single line `do`...`end` is autocorrected when `EnforcedStyle: semantic` in `Style/BlockDelimiters`. It can also be detected by this cop if it is written by handcraft. So I decided to introduce this new cop instead of an autocorrect extension of `Style/BlockDelimiters`.
- Loading branch information
Showing
6 changed files
with
172 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* [#12227](https://github.com/rubocop/rubocop/pull/12227): Add new `Style/SingleLineDoEndBlock` cop. ([@koic][]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Style | ||
# Checks for single-line `do`...`end` block. | ||
# | ||
# In practice a single line `do`...`end` is autocorrected when `EnforcedStyle: semantic` | ||
# in `Style/BlockDelimiters`. The autocorrection maintains the `do` ... `end` syntax to | ||
# preserve semantics and does not change it to `{`...`}` block. | ||
# | ||
# @example | ||
# | ||
# # bad | ||
# foo do |arg| bar(arg) end | ||
# | ||
# # good | ||
# foo do |arg| | ||
# bar(arg) | ||
# end | ||
# | ||
# # bad | ||
# ->(arg) do bar(arg) end | ||
# | ||
# # good | ||
# ->(arg) { bar(arg) } | ||
# | ||
class SingleLineDoEndBlock < Base | ||
extend AutoCorrector | ||
|
||
MSG = 'Prefer multiline `do`...`end` block.' | ||
|
||
def on_block(node) | ||
return if !node.single_line? || node.braces? | ||
|
||
add_offense(node) do |corrector| | ||
corrector.insert_after(do_line(node), "\n") | ||
|
||
node_body = node.body | ||
|
||
if node_body.respond_to?(:heredoc?) && node_body.heredoc? | ||
corrector.remove(node.loc.end) | ||
corrector.insert_after(node_body.loc.heredoc_end, "\nend") | ||
else | ||
corrector.insert_after(node_body, "\n") | ||
end | ||
end | ||
end | ||
alias on_numblock on_block | ||
|
||
private | ||
|
||
def do_line(node) | ||
if node.numblock_type? || node.arguments.children.empty? || node.send_node.lambda_literal? | ||
node.loc.begin | ||
else | ||
node.arguments | ||
end | ||
end | ||
|
||
def x(corrector, node); end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Style::SingleLineDoEndBlock, :config do | ||
it 'registers an offense when using single line `do`...`end`' do | ||
expect_offense(<<~RUBY) | ||
foo do bar end | ||
^^^^^^^^^^^^^^ Prefer multiline `do`...`end` block. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
foo do | ||
bar | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when using single line `do`...`end` with block argument' do | ||
expect_offense(<<~RUBY) | ||
foo do |arg| bar(arg) end | ||
^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer multiline `do`...`end` block. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
foo do |arg| | ||
bar(arg) | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when using single line `do`...`end` with numbered block argument' do | ||
expect_offense(<<~RUBY) | ||
foo do bar(_1) end | ||
^^^^^^^^^^^^^^^^^^ Prefer multiline `do`...`end` block. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
foo do | ||
bar(_1) | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when using single line `do`...`end` with heredoc body' do | ||
expect_offense(<<~RUBY) | ||
foo do <<~EOS end | ||
^^^^^^^^^^^^^^^^^ Prefer multiline `do`...`end` block. | ||
text | ||
EOS | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
foo do | ||
<<~EOS#{' '} | ||
text | ||
EOS | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when using single line `do`...`end` with `->` block' do | ||
expect_offense(<<~RUBY) | ||
->(arg) do foo arg end | ||
^^^^^^^^^^^^^^^^^^^^^^ Prefer multiline `do`...`end` block. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
->(arg) do | ||
foo arg | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when using single line `do`...`end` with `lambda` block' do | ||
expect_offense(<<~RUBY) | ||
lambda do |arg| foo(arg) end | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer multiline `do`...`end` block. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
lambda do |arg| | ||
foo(arg) | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when using multiline `do`...`end`' do | ||
expect_no_offenses(<<~RUBY) | ||
foo do | ||
bar | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when using single line `{`...`}`' do | ||
expect_no_offenses(<<~RUBY) | ||
foo { bar } | ||
RUBY | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters