Skip to content

Commit

Permalink
Support one-line pattern matching syntax
Browse files Browse the repository at this point in the history
This PR supports one-line pattern matching syntax for `Layout/SpaceAroundKeyword`
and `Layout/SpaceAroundOperators`.

`match-pattern` node changes differently in Ruby 2.7 and Ruby 3.0.

## Ruby 2.7 (`Parser::Ruby27`)

```console
% ruby-parse -e '42 in foo'
(match-pattern
  (int 42)
  (match-var :foo))
```

## Ruby 3.0 (`Parser::Ruby30`)

```console
% ruby-parse -e '42 => foo'
(match-pattern
  (int 42)
  (match-var :foo))
```

And one-line `in` syntax that represents one-line pattern maching changes
from `match-pattern` node to `match-pattern-p` in Ruby 3.0.

```console
% ruby-parse -e '42 in foo'
(match-pattern-p
(int 42)
  (match-var :foo))
```
  • Loading branch information
koic authored and bbatsov committed Jun 13, 2021
1 parent 40ecfcf commit 4fed3f7
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 0 deletions.
1 change: 1 addition & 0 deletions changelog/new_support_one_line_pattern_matching.md
@@ -0,0 +1 @@
* [#9873](https://github.com/rubocop/rubocop/pull/9873): Support one-line pattern matching syntax for `Layout/SpaceAroundKeyword` and `Layout/SpaceAroundOperators`. ([@koic][])
12 changes: 12 additions & 0 deletions lib/rubocop/cop/layout/space_around_keyword.rb
Expand Up @@ -81,6 +81,18 @@ def on_kwbegin(node)
check(node, %i[begin end].freeze, nil)
end

# Handle one-line pattern matching syntax (`in`) with `Parser::Ruby27`.
def on_match_pattern(node)
return if target_ruby_version >= 3.0

check(node, [:operator].freeze)
end

# Handle one-line pattern matching syntax (`in`) with `Parser::Ruby30`.
def on_match_pattern_p(node)
check(node, [:operator].freeze)
end

def on_next(node)
check(node, [:keyword].freeze)
end
Expand Down
6 changes: 6 additions & 0 deletions lib/rubocop/cop/layout/space_around_operators.rb
Expand Up @@ -120,6 +120,12 @@ def on_special_asgn(node)
check_operator(:special_asgn, node.loc.operator, right.source_range)
end

def on_match_pattern(node)
return if target_ruby_version < 3.0

check_operator(:match_pattern, node.loc.operator, node.source_range)
end

alias on_or on_binary
alias on_and on_binary
alias on_lvasgn on_assignment
Expand Down
8 changes: 8 additions & 0 deletions spec/rubocop/cop/layout/space_around_keyword_spec.rb
Expand Up @@ -133,6 +133,14 @@
# The answer will determine whether to enable or discard the test in the future.
# it_behaves_like 'missing before', 'in', 'case ""in a; end', 'case "" in a; end'
it_behaves_like 'missing after', 'in', 'case a; in""; end', 'case a; in ""; end'

it_behaves_like 'missing before', 'in', '""in a', '"" in a'
it_behaves_like 'missing after', 'in', 'a in""', 'a in ""'
end

context '>= Ruby 3.0', :ruby30 do
it_behaves_like 'accept before', '=>', '""=> a'
it_behaves_like 'accept after', '=>', 'a =>""'
end

it_behaves_like 'missing before', 'while', '1while ""', '1 while ""'
Expand Down
28 changes: 28 additions & 0 deletions spec/rubocop/cop/layout/space_around_operators_spec.rb
Expand Up @@ -4,13 +4,15 @@
let(:config) do
RuboCop::Config
.new(
'AllCops' => { 'TargetRubyVersion' => target_ruby_version },
'Layout/HashAlignment' => { 'EnforcedHashRocketStyle' => hash_style },
'Layout/SpaceAroundOperators' => {
'AllowForAlignment' => allow_for_alignment,
'EnforcedStyleForExponentOperator' => exponent_operator_style
}
)
end
let(:target_ruby_version) { 2.5 }
let(:hash_style) { 'key' }
let(:allow_for_alignment) { true }
let(:exponent_operator_style) { nil }
Expand Down Expand Up @@ -204,6 +206,32 @@ def self.===(other); end
expect_no_offenses('x = a * b**2')
end

context '>= Ruby 2.7', :ruby27 do
let(:target_ruby_version) { 2.7 }

# NOTE: It is `Layout/SpaceAroundKeyword` cop's role to detect this offense.
it 'does not register an offenses for one-line pattern matching syntax (`in`)' do
expect_no_offenses(<<~RUBY)
""in foo
RUBY
end
end

context '>= Ruby 3.0', :ruby30 do
let(:target_ruby_version) { 3.0 }

it 'registers an offenses for one-line pattern matching syntax (`=>`)' do
expect_offense(<<~RUBY)
""=>foo
^^ Surrounding space missing for operator `=>`.
RUBY

expect_correction(<<~RUBY)
"" => foo
RUBY
end
end

context 'when EnforcedStyleForExponentOperator is space' do
let(:exponent_operator_style) { 'space' }

Expand Down

0 comments on commit 4fed3f7

Please sign in to comment.