-
-
Notifications
You must be signed in to change notification settings - Fork 79
/
redundant_match.rb
62 lines (52 loc) · 1.92 KB
/
redundant_match.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# frozen_string_literal: true
module RuboCop
module Cop
module Performance
# This cop identifies the use of `Regexp#match` or `String#match`, which
# returns `#<MatchData>`/`nil`. The return value of `=~` is an integral
# index/`nil` and is more performant.
#
# @example
# # bad
# do_something if str.match(/regex/)
# while regex.match('str')
# do_something
# end
#
# # good
# method(str =~ /regex/)
# return value unless regex =~ 'str'
class RedundantMatch < Base
extend AutoCorrector
MSG = 'Use `=~` in places where the `MatchData` returned by ' \
'`#match` will not be used.'
RESTRICT_ON_SEND = %i[match].freeze
# 'match' is a fairly generic name, so we don't flag it unless we see
# a string or regexp literal on one side or the other
def_node_matcher :match_call?, <<~PATTERN
{(send {str regexp} :match _)
(send !nil? :match {str regexp})}
PATTERN
def_node_matcher :only_truthiness_matters?, <<~PATTERN
^({if while until case while_post until_post} equal?(%0) ...)
PATTERN
def on_send(node)
return unless match_call?(node) &&
(!node.value_used? || only_truthiness_matters?(node)) &&
!(node.parent && node.parent.block_type?)
add_offense(node) do |corrector|
autocorrect(corrector, node)
end
end
private
def autocorrect(corrector, node)
# Regexp#match can take a second argument, but this cop doesn't
# register an offense in that case
return unless node.first_argument.regexp_type?
new_source = "#{node.receiver.source} =~ #{node.first_argument.source}"
corrector.replace(node.source_range, new_source)
end
end
end
end
end