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/MultilineInPatternThen
cop
Follow rubocop/ruby-style-guide#873. This PR adds new `Style/MultilineInPatternThen` cop. It checks uses of the `then` keyword in multi-line `in` statement. ```ruby # bad case expression in pattern then end # good case expression in pattern end ``` This cop is similar to `Style/MultilineWhenThen` (and `Style/MultilineIfThen`) but with different supported syntax and Ruby version (requires 2.7 or higher).
- Loading branch information
Showing
6 changed files
with
231 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 @@ | ||
* [#9834](https://github.com/rubocop/rubocop/pull/9834): Add new `Style/MultilineInPatternThen` 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,62 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Style | ||
# This cop checks uses of the `then` keyword in multi-line `in` statement. | ||
# | ||
# @example | ||
# # bad | ||
# case expression | ||
# in pattern then | ||
# end | ||
# | ||
# # good | ||
# case expression | ||
# in pattern | ||
# end | ||
# | ||
# # good | ||
# case expression | ||
# in pattern then do_something | ||
# end | ||
# | ||
# # good | ||
# case expression | ||
# in pattern then do_something(arg1, | ||
# arg2) | ||
# end | ||
# | ||
class MultilineInPatternThen < Base | ||
include RangeHelp | ||
extend AutoCorrector | ||
extend TargetRubyVersion | ||
|
||
minimum_target_ruby_version 2.7 | ||
|
||
MSG = 'Do not use `then` for multiline `in` statement.' | ||
|
||
def on_in_pattern(node) | ||
return if !node.then? || require_then?(node) | ||
|
||
range = node.loc.begin | ||
add_offense(range) do |corrector| | ||
corrector.remove( | ||
range_with_surrounding_space(range: range, side: :left, newlines: false) | ||
) | ||
end | ||
end | ||
|
||
private | ||
|
||
# Requires `then` for write `in` and its body on the same line. | ||
def require_then?(in_pattern_node) | ||
return true if in_pattern_node.pattern.first_line != in_pattern_node.pattern.last_line | ||
return false unless in_pattern_node.body | ||
|
||
in_pattern_node.loc.line == in_pattern_node.body.loc.line | ||
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
160 changes: 160 additions & 0 deletions
160
spec/rubocop/cop/style/multiline_in_pattern_then_spec.rb
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,160 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Style::MultilineInPatternThen, :config do | ||
context '>= Ruby 2.7', :ruby27 do | ||
it 'registers an offense for empty `in` statement with `then`' do | ||
expect_offense(<<~RUBY) | ||
case foo | ||
in bar then | ||
^^^^ Do not use `then` for multiline `in` statement. | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
case foo | ||
in bar | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense for multiline (one line in a body) `in` statement with `then`' do | ||
expect_offense(<<~RUBY) | ||
case foo | ||
in bar then | ||
^^^^ Do not use `then` for multiline `in` statement. | ||
do_something | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
case foo | ||
in bar | ||
do_something | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense for multiline (two lines in a body) `in` statement with `then`' do | ||
expect_offense(<<~RUBY) | ||
case foo | ||
in bar then | ||
^^^^ Do not use `then` for multiline `in` statement. | ||
do_something1 | ||
do_something2 | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
case foo | ||
in bar | ||
do_something1 | ||
do_something2 | ||
end | ||
RUBY | ||
end | ||
|
||
it "doesn't register an offense for singleline `in` statement with `then`" do | ||
expect_no_offenses(<<~RUBY) | ||
case foo | ||
in bar then do_something | ||
end | ||
RUBY | ||
end | ||
|
||
it "doesn't register an offense when `then` required for a body of `in` is used" do | ||
expect_no_offenses(<<~RUBY) | ||
case cond | ||
in foo then do_something(arg1, | ||
arg2) | ||
end | ||
RUBY | ||
end | ||
|
||
it "doesn't register an offense for multiline `in` statement with `then` followed by other lines" do | ||
expect_no_offenses(<<~RUBY) | ||
case foo | ||
in bar then do_something | ||
do_another_thing | ||
end | ||
RUBY | ||
end | ||
|
||
it "doesn't register an offense for empty `in` statement without `then`" do | ||
expect_no_offenses(<<~RUBY) | ||
case foo | ||
in bar | ||
end | ||
RUBY | ||
end | ||
|
||
it "doesn't register an offense for multiline `in` statement without `then`" do | ||
expect_no_offenses(<<~RUBY) | ||
case foo | ||
in bar | ||
do_something | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense for hash `in` statement with `then`' do | ||
expect_no_offenses(<<~RUBY) | ||
case condition | ||
in foo then { | ||
key: 'value' | ||
} | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense for array `when` statement with `then`' do | ||
expect_no_offenses(<<~RUBY) | ||
case condition | ||
in foo then [ | ||
'element' | ||
] | ||
end | ||
RUBY | ||
end | ||
|
||
it 'autocorrects when the body of `in` branch starts with `then`' do | ||
expect_offense(<<~RUBY) | ||
case foo | ||
in bar | ||
then do_something | ||
^^^^ Do not use `then` for multiline `in` statement. | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
case foo | ||
in bar | ||
do_something | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when one line for multiple condidate values of `in`' do | ||
expect_offense(<<~RUBY) | ||
case foo | ||
in bar, baz then | ||
^^^^ Do not use `then` for multiline `in` statement. | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
case foo | ||
in bar, baz | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when line break for multiple condidate values of `in`' do | ||
expect_no_offenses(<<~RUBY) | ||
case foo | ||
in bar, | ||
baz then do_something | ||
end | ||
RUBY | ||
end | ||
end | ||
end |