lib/rubocop/cop/performance/start_with.rb in rubocop-performance-1.5.2 vs lib/rubocop/cop/performance/start_with.rb in rubocop-performance-1.6.0
- old
+ new
@@ -13,43 +13,41 @@
# 'abc' =~ /\Aab/
# /\Aab/ =~ 'abc'
# 'abc'.match(/\Aab/)
# /\Aab/.match('abc')
#
+ # 'abc'.match?(/^ab/)
+ # /^ab/.match?('abc')
+ # 'abc' =~ /^ab/
+ # /^ab/ =~ 'abc'
+ # 'abc'.match(/^ab/)
+ # /^ab/.match('abc')
+ #
# # good
# 'abc'.start_with?('ab')
class StartWith < Cop
+ include RegexpMetacharacter
+
MSG = 'Use `String#start_with?` instead of a regex match anchored to ' \
'the beginning of the string.'
- SINGLE_QUOTE = "'"
- def_node_matcher :redundant_regex?, <<-PATTERN
+ def_node_matcher :redundant_regex?, <<~PATTERN
{(send $!nil? {:match :=~ :match?} (regexp (str $#literal_at_start?) (regopt)))
(send (regexp (str $#literal_at_start?) (regopt)) {:match :match?} $_)
(match-with-lvasgn (regexp (str $#literal_at_start?) (regopt)) $_)}
PATTERN
- def literal_at_start?(regex_str)
- # is this regexp 'literal' in the sense of only matching literal
- # chars, rather than using metachars like `.` and `*` and so on?
- # also, is it anchored at the start of the string?
- # (tricky: \s, \d, and so on are metacharacters, but other characters
- # escaped with a slash are just literals. LITERAL_REGEX takes all
- # that into account.)
- regex_str =~ /\A\\A(?:#{LITERAL_REGEX})+\z/
- end
-
def on_send(node)
return unless redundant_regex?(node)
add_offense(node)
end
alias on_match_with_lvasgn on_send
def autocorrect(node)
redundant_regex?(node) do |receiver, regex_str|
receiver, regex_str = regex_str, receiver if receiver.is_a?(String)
- regex_str = regex_str[2..-1] # drop \A anchor
+ regex_str = drop_start_metacharacter(regex_str)
regex_str = interpret_string_escapes(regex_str)
lambda do |corrector|
new_source = receiver.source + '.start_with?(' +
to_string_literal(regex_str) + ')'