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 `Lint/EmptyInPattern` cop for Ruby 2.7's pattern matching. It checks for the presence of `in` branches without a body. ```ruby # bad case condition in [a] do_something in [a, b] end # good case condition in [a] do_something in [a, b] nil end # good - AllowComments: true (default) case condition in [a] do_something in [a, b] # noop end # bad - AllowComments: false case condition in [a] do_something in [a, b] # noop end ``` This cop is similar to `Lint/EmptyWhen`, but with different supported syntax and Ruby version (requires 2.7 or higher). And this PR use rubocop/rubocop-ast#183 feature, so it requires RuboCop AST 1.6.0 or higher.
- Loading branch information
Showing
6 changed files
with
235 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 @@ | ||
* [#9825](https://github.com/rubocop/rubocop/pull/9825): Add new `Lint/EmptyInPattern` 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 Lint | ||
# This cop checks for the presence of `in` pattern branches without a body. | ||
# | ||
# @example | ||
# | ||
# # bad | ||
# case condition | ||
# in [a] | ||
# do_something | ||
# in [a, b] | ||
# end | ||
# | ||
# # good | ||
# case condition | ||
# in [a] | ||
# do_something | ||
# in [a, b] | ||
# nil | ||
# end | ||
# | ||
# @example AllowComments: true (default) | ||
# | ||
# # good | ||
# case condition | ||
# in [a] | ||
# do_something | ||
# in [a, b] | ||
# # noop | ||
# end | ||
# | ||
# @example AllowComments: false | ||
# | ||
# # bad | ||
# case condition | ||
# in [a] | ||
# do_something | ||
# in [a, b] | ||
# # noop | ||
# end | ||
# | ||
class EmptyInPattern < Base | ||
extend TargetRubyVersion | ||
|
||
MSG = 'Avoid `in` branches without a body.' | ||
|
||
minimum_target_ruby_version 2.7 | ||
|
||
def on_case_match(node) | ||
node.in_pattern_branches.each do |branch| | ||
next if branch.body || cop_config['AllowComments'] && comment_lines?(node) | ||
|
||
add_offense(branch) | ||
end | ||
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,165 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Lint::EmptyInPattern, :config do | ||
let(:cop_config) { { 'AllowComments' => false } } | ||
|
||
context 'when a `in` body is missing', :ruby27 do | ||
it 'registers an offense for a missing `in` body' do | ||
expect_offense(<<~RUBY) | ||
case foo | ||
in [a] then 1 | ||
in [a, b] # nothing | ||
^^^^^^^^^ Avoid `in` branches without a body. | ||
end | ||
RUBY | ||
|
||
expect_no_corrections | ||
end | ||
|
||
it 'registers an offense for missing `in` body followed by `else`' do | ||
expect_offense(<<~RUBY) | ||
case foo | ||
in [a] then 1 | ||
in [a, b] # nothing | ||
^^^^^^^^^ Avoid `in` branches without a body. | ||
else 3 | ||
end | ||
RUBY | ||
|
||
expect_no_corrections | ||
end | ||
|
||
it 'registers an offense for missing `in` ... `then` body' do | ||
expect_offense(<<~RUBY) | ||
case foo | ||
in [a] then 1 | ||
in [a, b] then # nothing | ||
^^^^^^^^^ Avoid `in` branches without a body. | ||
end | ||
RUBY | ||
|
||
expect_no_corrections | ||
end | ||
|
||
it 'registers an offense for missing `in` ... then `body` followed by `else`' do | ||
expect_offense(<<~RUBY) | ||
case foo | ||
in [a] then 1 | ||
in [a, b] then # nothing | ||
^^^^^^^^^ Avoid `in` branches without a body. | ||
else 3 | ||
end | ||
RUBY | ||
|
||
expect_no_corrections | ||
end | ||
|
||
it 'registers an offense for missing `in` body with a comment' do | ||
expect_offense(<<~RUBY) | ||
case foo | ||
in [a] | ||
1 | ||
in [a, b] | ||
^^^^^^^^^ Avoid `in` branches without a body. | ||
# nothing | ||
end | ||
RUBY | ||
|
||
expect_no_corrections | ||
end | ||
|
||
it 'registers an offense for missing `in` body with a comment followed by `else`' do | ||
expect_offense(<<~RUBY) | ||
case foo | ||
in [a] | ||
1 | ||
in [a, b] | ||
^^^^^^^^^ Avoid `in` branches without a body. | ||
# nothing | ||
else | ||
3 | ||
end | ||
RUBY | ||
|
||
expect_no_corrections | ||
end | ||
end | ||
|
||
context 'when a `in` body is present', :ruby27 do | ||
it 'accepts `case` with `in` ... `then` statements' do | ||
expect_no_offenses(<<~RUBY) | ||
case foo | ||
in [a] then 1 | ||
in [a, b] then 2 | ||
end | ||
RUBY | ||
end | ||
|
||
it 'accepts `case` with `in` ... `then` statements and else clause' do | ||
expect_no_offenses(<<~RUBY) | ||
case foo | ||
in [a] then 1 | ||
in [a, b] then 2 | ||
else 3 | ||
end | ||
RUBY | ||
end | ||
|
||
it 'accepts `case` with `in` bodies' do | ||
expect_no_offenses(<<~RUBY) | ||
case foo | ||
in [a] | ||
1 | ||
in [a, b] | ||
2 | ||
end | ||
RUBY | ||
end | ||
|
||
it 'accepts `case` with `in` bodies and `else` clause' do | ||
expect_no_offenses(<<~RUBY) | ||
case foo | ||
in [a] | ||
1 | ||
in [a, b] | ||
2 | ||
else | ||
3 | ||
end | ||
RUBY | ||
end | ||
end | ||
|
||
context 'when `AllowComments: true`', :ruby27 do | ||
let(:cop_config) { { 'AllowComments' => true } } | ||
|
||
it 'accepts an empty `in` body with a comment' do | ||
expect_no_offenses(<<~RUBY) | ||
case condition | ||
in [a] | ||
do_something | ||
in [a, b] | ||
# do nothing | ||
end | ||
RUBY | ||
end | ||
end | ||
|
||
context 'when `AllowComments: false`', :ruby27 do | ||
let(:cop_config) { { 'AllowComments' => false } } | ||
|
||
it 'registers an offense for empty `in` body with a comment' do | ||
expect_offense(<<~RUBY) | ||
case condition | ||
in [a] | ||
do_something | ||
in [a, b] | ||
^^^^^^^^^ Avoid `in` branches without a body. | ||
# do nothing | ||
end | ||
RUBY | ||
|
||
expect_no_corrections | ||
end | ||
end | ||
end |