rubocop-performance 1.4.1 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +5 -1
- data/config/default.yml +29 -10
- data/lib/rubocop/cop/mixin/regexp_metacharacter.rb +76 -0
- data/lib/rubocop/cop/performance/bind_call.rb +87 -0
- data/lib/rubocop/cop/performance/caller.rb +3 -3
- data/lib/rubocop/cop/performance/casecmp.rb +5 -3
- data/lib/rubocop/cop/performance/chain_array_allocation.rb +1 -1
- data/lib/rubocop/cop/performance/compare_with_block.rb +2 -2
- data/lib/rubocop/cop/performance/count.rb +3 -6
- data/lib/rubocop/cop/performance/delete_prefix.rb +96 -0
- data/lib/rubocop/cop/performance/delete_suffix.rb +96 -0
- data/lib/rubocop/cop/performance/detect.rb +1 -5
- data/lib/rubocop/cop/performance/double_start_end_with.rb +2 -2
- data/lib/rubocop/cop/performance/end_with.rb +36 -13
- data/lib/rubocop/cop/performance/fixed_size.rb +1 -1
- data/lib/rubocop/cop/performance/flat_map.rb +9 -2
- data/lib/rubocop/cop/performance/inefficient_hash_search.rb +1 -1
- data/lib/rubocop/cop/performance/open_struct.rb +1 -1
- data/lib/rubocop/cop/performance/range_include.rb +1 -1
- data/lib/rubocop/cop/performance/redundant_block_call.rb +3 -3
- data/lib/rubocop/cop/performance/redundant_match.rb +2 -2
- data/lib/rubocop/cop/performance/redundant_merge.rb +22 -9
- data/lib/rubocop/cop/performance/regexp_match.rb +13 -13
- data/lib/rubocop/cop/performance/reverse_each.rb +3 -2
- data/lib/rubocop/cop/performance/size.rb +2 -2
- data/lib/rubocop/cop/performance/start_with.rb +36 -16
- data/lib/rubocop/cop/performance/string_replacement.rb +4 -11
- data/lib/rubocop/cop/performance/times_map.rb +1 -1
- data/lib/rubocop/cop/performance/unfreeze_string.rb +3 -7
- data/lib/rubocop/cop/performance/uri_default_parser.rb +1 -1
- data/lib/rubocop/cop/performance_cops.rb +5 -0
- data/lib/rubocop/performance/inject.rb +1 -1
- data/lib/rubocop/performance/version.rb +1 -1
- metadata +13 -9
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Performance
|
6
|
+
# In Ruby 2.5, `String#delete_suffix` has been added.
|
7
|
+
#
|
8
|
+
# This cop identifies places where `gsub(/suffix\z/, '')` and `sub(/suffix\z/, '')`
|
9
|
+
# can be replaced by `delete_suffix('suffix')`.
|
10
|
+
#
|
11
|
+
# This cop has `SafeMultiline` configuration option that `true` by default because
|
12
|
+
# `suffix$` is unsafe as it will behave incompatible with `delete_suffix?`
|
13
|
+
# for receiver is multiline string.
|
14
|
+
#
|
15
|
+
# The `delete_suffix('suffix')` method is faster than `gsub(/suffix\z/, '')`.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
#
|
19
|
+
# # bad
|
20
|
+
# str.gsub(/suffix\z/, '')
|
21
|
+
# str.gsub!(/suffix\z/, '')
|
22
|
+
#
|
23
|
+
# str.sub(/suffix\z/, '')
|
24
|
+
# str.sub!(/suffix\z/, '')
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# str.delete_suffix('suffix')
|
28
|
+
# str.delete_suffix!('suffix')
|
29
|
+
#
|
30
|
+
# @example SafeMultiline: true (default)
|
31
|
+
#
|
32
|
+
# # good
|
33
|
+
# str.gsub(/suffix$/, '')
|
34
|
+
# str.gsub!(/suffix$/, '')
|
35
|
+
# str.sub(/suffix$/, '')
|
36
|
+
# str.sub!(/suffix$/, '')
|
37
|
+
#
|
38
|
+
# @example SafeMultiline: false
|
39
|
+
#
|
40
|
+
# # bad
|
41
|
+
# str.gsub(/suffix$/, '')
|
42
|
+
# str.gsub!(/suffix$/, '')
|
43
|
+
# str.sub(/suffix$/, '')
|
44
|
+
# str.sub!(/suffix$/, '')
|
45
|
+
#
|
46
|
+
class DeleteSuffix < Cop
|
47
|
+
extend TargetRubyVersion
|
48
|
+
include RegexpMetacharacter
|
49
|
+
|
50
|
+
minimum_target_ruby_version 2.5
|
51
|
+
|
52
|
+
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
53
|
+
|
54
|
+
PREFERRED_METHODS = {
|
55
|
+
gsub: :delete_suffix,
|
56
|
+
gsub!: :delete_suffix!,
|
57
|
+
sub: :delete_suffix,
|
58
|
+
sub!: :delete_suffix!
|
59
|
+
}.freeze
|
60
|
+
|
61
|
+
def_node_matcher :delete_suffix_candidate?, <<~PATTERN
|
62
|
+
(send $!nil? ${:gsub :gsub! :sub :sub!} (regexp (str $#literal_at_end?) (regopt)) (str $_))
|
63
|
+
PATTERN
|
64
|
+
|
65
|
+
def on_send(node)
|
66
|
+
delete_suffix_candidate?(node) do |_, bad_method, _, replace_string|
|
67
|
+
return unless replace_string.blank?
|
68
|
+
|
69
|
+
good_method = PREFERRED_METHODS[bad_method]
|
70
|
+
|
71
|
+
message = format(MSG, current: bad_method, prefer: good_method)
|
72
|
+
|
73
|
+
add_offense(node, location: :selector, message: message)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def autocorrect(node)
|
78
|
+
delete_suffix_candidate?(node) do |receiver, bad_method, regexp_str, _|
|
79
|
+
lambda do |corrector|
|
80
|
+
good_method = PREFERRED_METHODS[bad_method]
|
81
|
+
regexp_str = drop_end_metacharacter(regexp_str)
|
82
|
+
regexp_str = interpret_string_escapes(regexp_str)
|
83
|
+
string_literal = to_string_literal(regexp_str)
|
84
|
+
|
85
|
+
new_code = "#{receiver.source}.#{good_method}(#{string_literal})"
|
86
|
+
|
87
|
+
# TODO: `source_range` is no longer required when RuboCop 0.81 or lower support will be dropped.
|
88
|
+
# https://github.com/rubocop-hq/rubocop/commit/82eb350d2cba16
|
89
|
+
corrector.replace(node.source_range, new_code)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -23,14 +23,12 @@ module RuboCop
|
|
23
23
|
# own meaning. Correcting ActiveRecord methods with this cop should be
|
24
24
|
# considered unsafe.
|
25
25
|
class Detect < Cop
|
26
|
-
include SafeMode
|
27
|
-
|
28
26
|
MSG = 'Use `%<prefer>s` instead of ' \
|
29
27
|
'`%<first_method>s.%<second_method>s`.'
|
30
28
|
REVERSE_MSG = 'Use `reverse.%<prefer>s` instead of ' \
|
31
29
|
'`%<first_method>s.%<second_method>s`.'
|
32
30
|
|
33
|
-
def_node_matcher :detect_candidate?,
|
31
|
+
def_node_matcher :detect_candidate?, <<~PATTERN
|
34
32
|
{
|
35
33
|
(send $(block (send _ {:select :find_all}) ...) ${:first :last} $...)
|
36
34
|
(send $(send _ {:select :find_all} ...) ${:first :last} $...)
|
@@ -38,8 +36,6 @@ module RuboCop
|
|
38
36
|
PATTERN
|
39
37
|
|
40
38
|
def on_send(node)
|
41
|
-
return if rails_safe_mode?
|
42
|
-
|
43
39
|
detect_candidate?(node) do |receiver, second_method, args|
|
44
40
|
return unless args.empty?
|
45
41
|
return unless receiver
|
@@ -75,13 +75,13 @@ module RuboCop
|
|
75
75
|
cop_config['IncludeActiveSupportAliases']
|
76
76
|
end
|
77
77
|
|
78
|
-
def_node_matcher :two_start_end_with_calls,
|
78
|
+
def_node_matcher :two_start_end_with_calls, <<~PATTERN
|
79
79
|
(or
|
80
80
|
(send $_recv [{:start_with? :end_with?} $_method] $...)
|
81
81
|
(send _recv _method $...))
|
82
82
|
PATTERN
|
83
83
|
|
84
|
-
def_node_matcher :check_with_active_support_aliases,
|
84
|
+
def_node_matcher :check_with_active_support_aliases, <<~PATTERN
|
85
85
|
(or
|
86
86
|
(send $_recv
|
87
87
|
[{:start_with? :starts_with? :end_with? :ends_with?} $_method]
|
@@ -3,44 +3,67 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Performance
|
6
|
-
# This cop identifies unnecessary use of a regex where `String#end_with?`
|
7
|
-
#
|
6
|
+
# This cop identifies unnecessary use of a regex where `String#end_with?` would suffice.
|
7
|
+
#
|
8
|
+
# This cop has `SafeMultiline` configuration option that `true` by default because
|
9
|
+
# `end$` is unsafe as it will behave incompatible with `end_with?`
|
10
|
+
# for receiver is multiline string.
|
8
11
|
#
|
9
12
|
# @example
|
10
13
|
# # bad
|
11
14
|
# 'abc'.match?(/bc\Z/)
|
15
|
+
# /bc\Z/.match?('abc')
|
12
16
|
# 'abc' =~ /bc\Z/
|
17
|
+
# /bc\Z/ =~ 'abc'
|
13
18
|
# 'abc'.match(/bc\Z/)
|
19
|
+
# /bc\Z/.match('abc')
|
14
20
|
#
|
15
21
|
# # good
|
16
22
|
# 'abc'.end_with?('bc')
|
23
|
+
#
|
24
|
+
# @example SafeMultiline: true (default)
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# 'abc'.match?(/bc$/)
|
28
|
+
# /bc$/.match?('abc')
|
29
|
+
# 'abc' =~ /bc$/
|
30
|
+
# /bc$/ =~ 'abc'
|
31
|
+
# 'abc'.match(/bc$/)
|
32
|
+
# /bc$/.match('abc')
|
33
|
+
#
|
34
|
+
# @example SafeMultiline: false
|
35
|
+
#
|
36
|
+
# # bad
|
37
|
+
# 'abc'.match?(/bc$/)
|
38
|
+
# /bc$/.match?('abc')
|
39
|
+
# 'abc' =~ /bc$/
|
40
|
+
# /bc$/ =~ 'abc'
|
41
|
+
# 'abc'.match(/bc$/)
|
42
|
+
# /bc$/.match('abc')
|
43
|
+
#
|
17
44
|
class EndWith < Cop
|
45
|
+
include RegexpMetacharacter
|
46
|
+
|
18
47
|
MSG = 'Use `String#end_with?` instead of a regex match anchored to ' \
|
19
48
|
'the end of the string.'
|
20
|
-
SINGLE_QUOTE = "'"
|
21
49
|
|
22
|
-
def_node_matcher :redundant_regex?,
|
50
|
+
def_node_matcher :redundant_regex?, <<~PATTERN
|
23
51
|
{(send $!nil? {:match :=~ :match?} (regexp (str $#literal_at_end?) (regopt)))
|
24
|
-
(send (regexp (str $#literal_at_end?) (regopt)) {:match
|
52
|
+
(send (regexp (str $#literal_at_end?) (regopt)) {:match :match?} $_)
|
53
|
+
(match-with-lvasgn (regexp (str $#literal_at_end?) (regopt)) $_)}
|
25
54
|
PATTERN
|
26
55
|
|
27
|
-
def literal_at_end?(regex_str)
|
28
|
-
# is this regexp 'literal' in the sense of only matching literal
|
29
|
-
# chars, rather than using metachars like . and * and so on?
|
30
|
-
# also, is it anchored at the end of the string?
|
31
|
-
regex_str =~ /\A(?:#{LITERAL_REGEX})+\\z\z/
|
32
|
-
end
|
33
|
-
|
34
56
|
def on_send(node)
|
35
57
|
return unless redundant_regex?(node)
|
36
58
|
|
37
59
|
add_offense(node)
|
38
60
|
end
|
61
|
+
alias on_match_with_lvasgn on_send
|
39
62
|
|
40
63
|
def autocorrect(node)
|
41
64
|
redundant_regex?(node) do |receiver, regex_str|
|
42
65
|
receiver, regex_str = regex_str, receiver if receiver.is_a?(String)
|
43
|
-
regex_str = regex_str
|
66
|
+
regex_str = drop_end_metacharacter(regex_str)
|
44
67
|
regex_str = interpret_string_escapes(regex_str)
|
45
68
|
|
46
69
|
lambda do |corrector|
|
@@ -48,7 +48,7 @@ module RuboCop
|
|
48
48
|
class FixedSize < Cop
|
49
49
|
MSG = 'Do not compute the size of statically sized objects.'
|
50
50
|
|
51
|
-
def_node_matcher :counter,
|
51
|
+
def_node_matcher :counter, <<~MATCHER
|
52
52
|
(send ${array hash str sym} {:count :length :size} $...)
|
53
53
|
MATCHER
|
54
54
|
|
@@ -22,8 +22,15 @@ module RuboCop
|
|
22
22
|
'and `flatten` can be used to flatten ' \
|
23
23
|
'multiple levels.'
|
24
24
|
|
25
|
-
def_node_matcher :flat_map_candidate?,
|
26
|
-
(send
|
25
|
+
def_node_matcher :flat_map_candidate?, <<~PATTERN
|
26
|
+
(send
|
27
|
+
{
|
28
|
+
(block $(send _ ${:collect :map}) ...)
|
29
|
+
$(send _ ${:collect :map} (block_pass _))
|
30
|
+
}
|
31
|
+
${:flatten :flatten!}
|
32
|
+
$...
|
33
|
+
)
|
27
34
|
PATTERN
|
28
35
|
|
29
36
|
def on_send(node)
|
@@ -37,7 +37,7 @@ module RuboCop
|
|
37
37
|
# h = { a: 1, b: 2 }; h.value?(nil)
|
38
38
|
#
|
39
39
|
class InefficientHashSearch < Cop
|
40
|
-
def_node_matcher :inefficient_include?,
|
40
|
+
def_node_matcher :inefficient_include?, <<~PATTERN
|
41
41
|
(send (send $_ {:keys :values}) :include? _)
|
42
42
|
PATTERN
|
43
43
|
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
31
31
|
MSG = 'Consider using `Struct` over `OpenStruct` ' \
|
32
32
|
'to optimize the performance.'
|
33
33
|
|
34
|
-
def_node_matcher :open_struct,
|
34
|
+
def_node_matcher :open_struct, <<~PATTERN
|
35
35
|
(send (const {nil? cbase} :OpenStruct) :new ...)
|
36
36
|
PATTERN
|
37
37
|
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
31
31
|
# Right now, we only detect direct calls on a Range literal
|
32
32
|
# (We don't even catch it if the Range is in double parens)
|
33
33
|
|
34
|
-
def_node_matcher :range_include,
|
34
|
+
def_node_matcher :range_include, <<~PATTERN
|
35
35
|
(send {irange erange (begin {irange erange})} :include? ...)
|
36
36
|
PATTERN
|
37
37
|
|
@@ -29,16 +29,16 @@ module RuboCop
|
|
29
29
|
CLOSE_PAREN = ')'
|
30
30
|
SPACE = ' '
|
31
31
|
|
32
|
-
def_node_matcher :blockarg_def,
|
32
|
+
def_node_matcher :blockarg_def, <<~PATTERN
|
33
33
|
{(def _ (args ... (blockarg $_)) $_)
|
34
34
|
(defs _ _ (args ... (blockarg $_)) $_)}
|
35
35
|
PATTERN
|
36
36
|
|
37
|
-
def_node_search :blockarg_calls,
|
37
|
+
def_node_search :blockarg_calls, <<~PATTERN
|
38
38
|
(send (lvar %1) :call ...)
|
39
39
|
PATTERN
|
40
40
|
|
41
|
-
def_node_search :blockarg_assigned?,
|
41
|
+
def_node_search :blockarg_assigned?, <<~PATTERN
|
42
42
|
(lvasgn %1 ...)
|
43
43
|
PATTERN
|
44
44
|
|
@@ -23,12 +23,12 @@ module RuboCop
|
|
23
23
|
|
24
24
|
# 'match' is a fairly generic name, so we don't flag it unless we see
|
25
25
|
# a string or regexp literal on one side or the other
|
26
|
-
def_node_matcher :match_call?,
|
26
|
+
def_node_matcher :match_call?, <<~PATTERN
|
27
27
|
{(send {str regexp} :match _)
|
28
28
|
(send !nil? :match {str regexp})}
|
29
29
|
PATTERN
|
30
30
|
|
31
|
-
def_node_matcher :only_truthiness_matters?,
|
31
|
+
def_node_matcher :only_truthiness_matters?, <<~PATTERN
|
32
32
|
^({if while until case while_post until_post} equal?(%0) ...)
|
33
33
|
PATTERN
|
34
34
|
|
@@ -5,11 +5,25 @@ module RuboCop
|
|
5
5
|
module Performance
|
6
6
|
# This cop identifies places where `Hash#merge!` can be replaced by
|
7
7
|
# `Hash#[]=`.
|
8
|
+
# You can set the maximum number of key-value pairs to consider
|
9
|
+
# an offense with `MaxKeyValuePairs`.
|
8
10
|
#
|
9
11
|
# @example
|
12
|
+
# # bad
|
10
13
|
# hash.merge!(a: 1)
|
11
14
|
# hash.merge!({'key' => 'value'})
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# hash[:a] = 1
|
18
|
+
# hash['key'] = 'value'
|
19
|
+
#
|
20
|
+
# @example MaxKeyValuePairs: 2 (default)
|
21
|
+
# # bad
|
12
22
|
# hash.merge!(a: 1, b: 2)
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# hash[:a] = 1
|
26
|
+
# hash[:b] = 2
|
13
27
|
class RedundantMerge < Cop
|
14
28
|
AREF_ASGN = '%<receiver>s[%<key>s] = %<value>s'
|
15
29
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
@@ -20,11 +34,11 @@ module RuboCop
|
|
20
34
|
%<leading_space>send
|
21
35
|
RUBY
|
22
36
|
|
23
|
-
def_node_matcher :redundant_merge_candidate,
|
37
|
+
def_node_matcher :redundant_merge_candidate, <<~PATTERN
|
24
38
|
(send $!nil? :merge! [(hash $...) !kwsplat_type?])
|
25
39
|
PATTERN
|
26
40
|
|
27
|
-
def_node_matcher :modifier_flow_control?,
|
41
|
+
def_node_matcher :modifier_flow_control?, <<~PATTERN
|
28
42
|
[{if while until} modifier_form?]
|
29
43
|
PATTERN
|
30
44
|
|
@@ -65,7 +79,8 @@ module RuboCop
|
|
65
79
|
end
|
66
80
|
|
67
81
|
def non_redundant_merge?(node, receiver, pairs)
|
68
|
-
|
82
|
+
pairs.empty? ||
|
83
|
+
non_redundant_pairs?(receiver, pairs) ||
|
69
84
|
kwsplat_used?(pairs) ||
|
70
85
|
non_redundant_value_used?(receiver, node)
|
71
86
|
end
|
@@ -128,11 +143,11 @@ module RuboCop
|
|
128
143
|
end
|
129
144
|
|
130
145
|
def indent_width
|
131
|
-
@config.for_cop('IndentationWidth')['Width'] || 2
|
146
|
+
@config.for_cop('Layout/IndentationWidth')['Width'] || 2
|
132
147
|
end
|
133
148
|
|
134
149
|
def max_key_value_pairs
|
135
|
-
Integer(cop_config['MaxKeyValuePairs']
|
150
|
+
Integer(cop_config['MaxKeyValuePairs'] || 2)
|
136
151
|
end
|
137
152
|
|
138
153
|
# A utility class for checking the use of values within an
|
@@ -167,13 +182,11 @@ module RuboCop
|
|
167
182
|
end
|
168
183
|
|
169
184
|
def unwind(receiver)
|
170
|
-
while receiver.respond_to?(:send_type?) && receiver.send_type?
|
171
|
-
receiver, = *receiver
|
172
|
-
end
|
185
|
+
receiver, = *receiver while receiver.respond_to?(:send_type?) && receiver.send_type?
|
173
186
|
receiver
|
174
187
|
end
|
175
188
|
|
176
|
-
def_node_matcher :each_with_object_node,
|
189
|
+
def_node_matcher :each_with_object_node, <<~PATTERN
|
177
190
|
(block (send _ :each_with_object _) (args _ $_) ...)
|
178
191
|
PATTERN
|
179
192
|
end
|
@@ -73,32 +73,28 @@ module RuboCop
|
|
73
73
|
# end
|
74
74
|
# end
|
75
75
|
class RegexpMatch < Cop
|
76
|
-
extend TargetRubyVersion
|
77
|
-
|
78
|
-
minimum_target_ruby_version 2.4
|
79
|
-
|
80
76
|
# Constants are included in this list because it is unlikely that
|
81
77
|
# someone will store `nil` as a constant and then use it for comparison
|
82
78
|
TYPES_IMPLEMENTING_MATCH = %i[const regexp str sym].freeze
|
83
79
|
MSG = 'Use `match?` instead of `%<current>s` when `MatchData` ' \
|
84
80
|
'is not used.'
|
85
81
|
|
86
|
-
def_node_matcher :match_method?,
|
82
|
+
def_node_matcher :match_method?, <<~PATTERN
|
87
83
|
{
|
88
84
|
(send _recv :match {regexp str sym})
|
89
85
|
(send {regexp str sym} :match _)
|
90
86
|
}
|
91
87
|
PATTERN
|
92
88
|
|
93
|
-
def_node_matcher :match_with_int_arg_method?,
|
89
|
+
def_node_matcher :match_with_int_arg_method?, <<~PATTERN
|
94
90
|
(send _recv :match _ (int ...))
|
95
91
|
PATTERN
|
96
92
|
|
97
|
-
def_node_matcher :match_operator?,
|
93
|
+
def_node_matcher :match_operator?, <<~PATTERN
|
98
94
|
(send !nil? {:=~ :!~} !nil?)
|
99
95
|
PATTERN
|
100
96
|
|
101
|
-
def_node_matcher :match_threequals?,
|
97
|
+
def_node_matcher :match_threequals?, <<~PATTERN
|
102
98
|
(send (regexp (str _) {(regopt) (regopt _)}) :=== !nil?)
|
103
99
|
PATTERN
|
104
100
|
|
@@ -109,7 +105,7 @@ module RuboCop
|
|
109
105
|
regexp.to_regexp.named_captures.empty?
|
110
106
|
end
|
111
107
|
|
112
|
-
MATCH_NODE_PATTERN =
|
108
|
+
MATCH_NODE_PATTERN = <<~PATTERN
|
113
109
|
{
|
114
110
|
#match_method?
|
115
111
|
#match_with_int_arg_method?
|
@@ -122,7 +118,7 @@ module RuboCop
|
|
122
118
|
def_node_matcher :match_node?, MATCH_NODE_PATTERN
|
123
119
|
def_node_search :search_match_nodes, MATCH_NODE_PATTERN
|
124
120
|
|
125
|
-
def_node_search :last_matches,
|
121
|
+
def_node_search :last_matches, <<~PATTERN
|
126
122
|
{
|
127
123
|
(send (const nil? :Regexp) :last_match)
|
128
124
|
(send (const nil? :Regexp) :last_match _)
|
@@ -256,6 +252,13 @@ module RuboCop
|
|
256
252
|
def correct_operator(corrector, recv, arg, oper = nil)
|
257
253
|
op_range = correction_range(recv, arg)
|
258
254
|
|
255
|
+
replace_with_match_predicate_method(corrector, recv, arg, op_range)
|
256
|
+
|
257
|
+
corrector.insert_after(arg.loc.expression, ')') unless op_range.source.end_with?('(')
|
258
|
+
corrector.insert_before(recv.loc.expression, '!') if oper == :!~
|
259
|
+
end
|
260
|
+
|
261
|
+
def replace_with_match_predicate_method(corrector, recv, arg, op_range)
|
259
262
|
if TYPES_IMPLEMENTING_MATCH.include?(recv.type)
|
260
263
|
corrector.replace(op_range, '.match?(')
|
261
264
|
elsif TYPES_IMPLEMENTING_MATCH.include?(arg.type)
|
@@ -264,9 +267,6 @@ module RuboCop
|
|
264
267
|
else
|
265
268
|
corrector.replace(op_range, '&.match?(')
|
266
269
|
end
|
267
|
-
|
268
|
-
corrector.insert_after(arg.loc.expression, ')')
|
269
|
-
corrector.insert_before(recv.loc.expression, '!') if oper == :!~
|
270
270
|
end
|
271
271
|
|
272
272
|
def swap_receiver_and_arg(corrector, recv, arg)
|