Skip to content

Commit

Permalink
Support pattern matching for Lint/OutOfRangeRegexpRef cop
Browse files Browse the repository at this point in the history
  • Loading branch information
fatkodima authored and bbatsov committed Dec 31, 2022
1 parent 422cdea commit 2d0589a
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#10976](https://github.com/rubocop/rubocop/issues/10976): Support pattern matching for `Lint/OutOfRangeRegexpRef` cop. ([@fatkodima][])
19 changes: 19 additions & 0 deletions lib/rubocop/cop/lint/out_of_range_regexp_ref.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ def on_when(node)
@valid_ref = regexp_conditions.map { |condition| check_regexp(condition) }.compact.max
end

def on_in_pattern(node)
regexp_patterns = patterns(node).select(&:regexp_type?)

@valid_ref = regexp_patterns.map { |pattern| check_regexp(pattern) }.compact.max
end

def on_nth_ref(node)
backref, = *node
return if @valid_ref.nil? || backref <= @valid_ref
Expand All @@ -84,6 +90,19 @@ def on_nth_ref(node)

private

def patterns(pattern_node)
pattern = pattern_node.node_parts[0]

case pattern.type
when :array_pattern, :match_alt
pattern.children
when :match_as
patterns(pattern)
else
[pattern]
end
end

def check_regexp(node)
return if node.interpolation?

Expand Down
148 changes: 148 additions & 0 deletions spec/rubocop/cop/lint/out_of_range_regexp_ref_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,154 @@
RUBY
end

context 'pattern matching', :ruby27 do
context 'matching variable' do
it 'does not register an offense when in range references are used' do
expect_no_offenses(<<~RUBY)
case "foobar"
in /(foo)(bar)/
$2
end
RUBY
end

it 'registers an offense when out of range references are used' do
expect_offense(<<~RUBY)
case "foobar"
in /(foo)(bar)/
$3
^^ $3 is out of range (2 regexp capture groups detected).
end
RUBY
end
end

context 'matching arrays' do
it 'uses the maximum number of captures with multiple patterns' do
expect_no_offenses(<<~RUBY)
case array
in [/(foo)(bar)/, /(bar)baz/]
$2
end
RUBY

expect_offense(<<~RUBY)
case array
in [/(foo)(bar)/, /(bar)baz/]
$3
^^ $3 is out of range (2 regexp capture groups detected).
end
RUBY
end
end

context 'matching with aliases' do
context 'variable aliases' do
it 'does not register an offense when in range references are used' do
expect_no_offenses(<<~RUBY)
case "foobar"
in /(foo)(bar)/ => x
$2
end
RUBY
end

it 'registers an offense when out of range references are used' do
expect_offense(<<~RUBY)
case "foobar"
in /(foo)(bar)/ => x
$3
^^ $3 is out of range (2 regexp capture groups detected).
end
RUBY
end
end

context 'array aliases' do
it 'uses the maximum number of captures with multiple patterns' do
expect_no_offenses(<<~RUBY)
case array
in [/(foo)(bar)/, /(bar)baz/] => x
$2
end
RUBY

expect_offense(<<~RUBY)
case array
in [/(foo)(bar)/, /(bar)baz/] => x
$3
^^ $3 is out of range (2 regexp capture groups detected).
end
RUBY
end
end
end

context 'matching alternatives' do
it 'does not register an offense when in range references are used' do
expect_no_offenses(<<~RUBY)
case "foobar"
in /(foo)(bar)/ | "foo"
$2
end
RUBY

expect_no_offenses(<<~RUBY)
case "foobar"
in /(foo)(bar)/ | "foo" => x
$2
end
RUBY
end

it 'registers an offense when out of range references are used' do
expect_offense(<<~RUBY)
case "foobar"
in /(foo)(bar)/ | "foo"
$3
^^ $3 is out of range (2 regexp capture groups detected).
end
RUBY
end

it 'uses the maximum number of captures with multiple patterns' do
expect_no_offenses(<<~RUBY)
case "foobar"
in /(foo)baz/ | /(foo)(bar)/
$2
end
RUBY

expect_offense(<<~RUBY)
case "foobar"
in /(foo)baz/ | /(foo)(bar)/
$3
^^ $3 is out of range (2 regexp capture groups detected).
end
RUBY
end
end

it 'only registers an offense when the regexp is matched as a literal' do
expect_no_offenses(<<~RUBY)
case some_string
in some_regexp
$2
end
RUBY
end

it 'ignores regexp when clause conditions contain interpolations' do
expect_offense(<<~'RUBY')
case array
in [/(foo)(bar)/, /#{var}/]
$3
^^ $3 is out of range (2 regexp capture groups detected).
end
RUBY
end
end

context 'matching with `grep`' do
it 'does not register an offense when in range references are used' do
expect_no_offenses(<<~RUBY)
Expand Down

0 comments on commit 2d0589a

Please sign in to comment.