forked from rubocop/rubocop
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR adds new `Style/InPatternThen` cop. It checks for `in;` uses in `case` expressions. ```ruby # bad case expression in pattern_a; foo in pattern_b; bar end # good case expression in pattern_a then foo in pattern_b then bar end ``` This cop is similar to `Style/WhenThen`, but with different supported syntax and Ruby version (requires 2.7 or higher). And this PR use rubocop/rubocop-ast#186 feature, so it requires RuboCop AST 1.7.0 or higher.
- Loading branch information
Showing
6 changed files
with
153 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 @@ | ||
* [#9833](https://github.com/rubocop/rubocop/pull/9833): Add new `Style/InPatternThen` 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,56 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Style | ||
# This cop checks for `in;` uses in `case` expressions. | ||
# | ||
# @example | ||
# # bad | ||
# case expression | ||
# in pattern_a; foo | ||
# in pattern_b; bar | ||
# end | ||
# | ||
# # good | ||
# case expression | ||
# in pattern_a then foo | ||
# in pattern_b then bar | ||
# end | ||
# | ||
class InPatternThen < Base | ||
extend AutoCorrector | ||
extend TargetRubyVersion | ||
|
||
minimum_target_ruby_version 2.7 | ||
|
||
MSG = 'Do not use `in %<pattern>s;`. Use `in %<pattern>s then` instead.' | ||
|
||
def on_in_pattern(node) | ||
return if node.multiline? || node.then? || !node.body | ||
|
||
pattern = node.pattern | ||
pattern_source = if pattern.match_alt_type? | ||
alternative_pattern_source(pattern) | ||
else | ||
pattern.source | ||
end | ||
|
||
add_offense(node.loc.begin, message: format(MSG, pattern: pattern_source)) do |corrector| | ||
corrector.replace(node.loc.begin, ' then') | ||
end | ||
end | ||
|
||
private | ||
|
||
def alternative_pattern_source(pattern) | ||
return pattern.children.map(&:source) unless pattern.children.first.match_alt_type? | ||
|
||
pattern_sources = alternative_pattern_source(pattern.children.first) | ||
|
||
(pattern_sources << pattern.children[1].source).join(' | ') | ||
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
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,88 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Style::InPatternThen, :config do | ||
context '>= Ruby 2.7', :ruby27 do | ||
it 'registers an offense for `in b;`' do | ||
expect_offense(<<~RUBY) | ||
case a | ||
in b; c | ||
^ Do not use `in b;`. Use `in b then` instead. | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
case a | ||
in b then c | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense for `in b, c, d;` (array pattern)' do | ||
expect_offense(<<~RUBY) | ||
case a | ||
in b, c, d; e | ||
^ Do not use `in b, c, d;`. Use `in b, c, d then` instead. | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
case a | ||
in b, c, d then e | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense for `in b | c | d;` (alternative pattern)' do | ||
expect_offense(<<~RUBY) | ||
case a | ||
in b | c | d; e | ||
^ Do not use `in b | c | d;`. Use `in b | c | d then` instead. | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
case a | ||
in b | c | d then e | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense for `in b, c | d;`' do | ||
expect_offense(<<~RUBY) | ||
case a | ||
in b, c | d; e | ||
^ Do not use `in b, c | d;`. Use `in b, c | d then` instead. | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
case a | ||
in b, c | d then e | ||
end | ||
RUBY | ||
end | ||
|
||
it 'accepts `;` separating statements in the body of `in`' do | ||
expect_no_offenses(<<~RUBY) | ||
case a | ||
in b then c; d | ||
end | ||
case e | ||
in f | ||
g; h | ||
end | ||
RUBY | ||
end | ||
|
||
context 'when inspecting a case statement with an empty branch' do | ||
it 'does not register an offense' do | ||
expect_no_offenses(<<~RUBY) | ||
case condition | ||
in pattern | ||
end | ||
RUBY | ||
end | ||
end | ||
end | ||
end |