Skip to content

Commit

Permalink
Extend Performance/StringInclude to handle !~
Browse files Browse the repository at this point in the history
  • Loading branch information
fatkodima committed Dec 1, 2022
1 parent 9d2ac69 commit a88d9ef
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 5 deletions.
1 change: 1 addition & 0 deletions changelog/change_string_include_handle_not_match.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#318](https://github.com/rubocop/rubocop-performance/issues/318): Extend `Performance/StringInclude` to handle `!~`. ([@fatkodima][])
13 changes: 8 additions & 5 deletions lib/rubocop/cop/performance/string_include.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,26 @@ module Performance
class StringInclude < Base
extend AutoCorrector

MSG = 'Use `String#include?` instead of a regex match with literal-only pattern.'
RESTRICT_ON_SEND = %i[match =~ match?].freeze
MSG = 'Use `%<negation>sString#include?` instead of a regex match with literal-only pattern.'
RESTRICT_ON_SEND = %i[match =~ !~ match?].freeze

def_node_matcher :redundant_regex?, <<~PATTERN
{(send $!nil? {:match :=~ :match?} (regexp (str $#literal?) (regopt)))
{(send $!nil? {:match :=~ :!~ :match?} (regexp (str $#literal?) (regopt)))
(send (regexp (str $#literal?) (regopt)) {:match :match?} $str)
(match-with-lvasgn (regexp (str $#literal?) (regopt)) $_)}
PATTERN

def on_send(node)
return unless (receiver, regex_str = redundant_regex?(node))

add_offense(node) do |corrector|
negation = node.send_type? && node.method?(:!~)
message = format(MSG, negation: ('!' if negation))

add_offense(node, message: message) do |corrector|
receiver, regex_str = regex_str, receiver if receiver.is_a?(String)
regex_str = interpret_string_escapes(regex_str)

new_source = "#{receiver.source}.include?(#{to_string_literal(regex_str)})"
new_source = "#{'!' if negation}#{receiver.source}.include?(#{to_string_literal(regex_str)})"

corrector.replace(node.source_range, new_source)
end
Expand Down
11 changes: 11 additions & 0 deletions spec/rubocop/cop/performance/string_include_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,15 @@
it 'allows argument of `match?` is not a string literal' do
expect_no_offenses('/ /.match?(content_as_symbol)')
end

it 'registers an offense and corrects when using `!~`' do
expect_offense(<<~RUBY)
str !~ /abc/
^^^^^^^^^^^^ Use `!String#include?` instead of a regex match with literal-only pattern.
RUBY

expect_correction(<<~RUBY)
!str.include?('abc')
RUBY
end
end

0 comments on commit a88d9ef

Please sign in to comment.