rubocop-performance 1.13.3 → 1.19.0
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 +2 -2
- data/config/default.yml +13 -2
- data/lib/rubocop/cop/mixin/regexp_metacharacter.rb +2 -2
- data/lib/rubocop/cop/mixin/sort_block.rb +7 -0
- data/lib/rubocop/cop/performance/ancestors_include.rb +1 -2
- data/lib/rubocop/cop/performance/array_semi_infinite_range_slice.rb +3 -2
- data/lib/rubocop/cop/performance/big_decimal_with_numeric_argument.rb +2 -6
- data/lib/rubocop/cop/performance/bind_call.rb +1 -2
- data/lib/rubocop/cop/performance/block_given_with_explicit_block.rb +1 -1
- data/lib/rubocop/cop/performance/caller.rb +1 -2
- data/lib/rubocop/cop/performance/case_when_splat.rb +7 -13
- data/lib/rubocop/cop/performance/casecmp.rb +10 -12
- data/lib/rubocop/cop/performance/chain_array_allocation.rb +5 -5
- data/lib/rubocop/cop/performance/collection_literal_in_loop.rb +4 -6
- data/lib/rubocop/cop/performance/compare_with_block.rb +20 -11
- data/lib/rubocop/cop/performance/concurrent_monotonic_time.rb +1 -1
- data/lib/rubocop/cop/performance/constant_regexp.rb +6 -4
- data/lib/rubocop/cop/performance/count.rb +39 -3
- data/lib/rubocop/cop/performance/delete_prefix.rb +8 -2
- data/lib/rubocop/cop/performance/delete_suffix.rb +8 -2
- data/lib/rubocop/cop/performance/detect.rb +7 -6
- data/lib/rubocop/cop/performance/double_start_end_with.rb +4 -5
- data/lib/rubocop/cop/performance/end_with.rb +7 -6
- data/lib/rubocop/cop/performance/fixed_size.rb +2 -2
- data/lib/rubocop/cop/performance/flat_map.rb +7 -5
- data/lib/rubocop/cop/performance/inefficient_hash_search.rb +17 -15
- data/lib/rubocop/cop/performance/io_readlines.rb +2 -2
- data/lib/rubocop/cop/performance/map_compact.rb +9 -4
- data/lib/rubocop/cop/performance/map_method_chain.rb +87 -0
- data/lib/rubocop/cop/performance/method_object_as_block.rb +1 -1
- data/lib/rubocop/cop/performance/open_struct.rb +2 -3
- data/lib/rubocop/cop/performance/range_include.rb +2 -2
- data/lib/rubocop/cop/performance/redundant_block_call.rb +2 -2
- data/lib/rubocop/cop/performance/redundant_equality_comparison_block.rb +38 -3
- data/lib/rubocop/cop/performance/redundant_match.rb +10 -9
- data/lib/rubocop/cop/performance/redundant_merge.rb +9 -16
- data/lib/rubocop/cop/performance/redundant_sort_block.rb +17 -10
- data/lib/rubocop/cop/performance/redundant_split_regexp_argument.rb +3 -2
- data/lib/rubocop/cop/performance/redundant_string_chars.rb +10 -6
- data/lib/rubocop/cop/performance/regexp_match.rb +23 -24
- data/lib/rubocop/cop/performance/reverse_each.rb +3 -3
- data/lib/rubocop/cop/performance/reverse_first.rb +4 -3
- data/lib/rubocop/cop/performance/select_map.rb +2 -1
- data/lib/rubocop/cop/performance/size.rb +1 -2
- data/lib/rubocop/cop/performance/sort_reverse.rb +19 -10
- data/lib/rubocop/cop/performance/squeeze.rb +8 -8
- data/lib/rubocop/cop/performance/start_with.rb +7 -6
- data/lib/rubocop/cop/performance/string_identifier_argument.rb +16 -11
- data/lib/rubocop/cop/performance/string_include.rb +23 -17
- data/lib/rubocop/cop/performance/string_replacement.rb +7 -10
- data/lib/rubocop/cop/performance/sum.rb +7 -4
- data/lib/rubocop/cop/performance/times_map.rb +6 -7
- data/lib/rubocop/cop/performance/uri_default_parser.rb +4 -6
- data/lib/rubocop/cop/performance_cops.rb +1 -0
- data/lib/rubocop/performance/version.rb +1 -1
- metadata +6 -5
@@ -3,8 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Performance
|
6
|
-
#
|
7
|
-
# `Hash#[]=`.
|
6
|
+
# Identifies places where `Hash#merge!` can be replaced by `Hash#[]=`.
|
8
7
|
# You can set the maximum number of key-value pairs to consider
|
9
8
|
# an offense with `MaxKeyValuePairs`.
|
10
9
|
#
|
@@ -29,6 +28,7 @@ module RuboCop
|
|
29
28
|
# hash[:a] = 1
|
30
29
|
# hash[:b] = 2
|
31
30
|
class RedundantMerge < Base
|
31
|
+
include Alignment
|
32
32
|
extend AutoCorrector
|
33
33
|
|
34
34
|
AREF_ASGN = '%<receiver>s[%<key>s] = %<value>s'
|
@@ -100,8 +100,7 @@ module RuboCop
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def non_redundant_value_used?(receiver, node)
|
103
|
-
node.value_used? &&
|
104
|
-
!EachWithObjectInspector.new(node, receiver).value_used?
|
103
|
+
node.value_used? && !EachWithObjectInspector.new(node, receiver).value_used?
|
105
104
|
end
|
106
105
|
|
107
106
|
def correct_multiple_elements(corrector, node, parent, new_source)
|
@@ -110,14 +109,14 @@ module RuboCop
|
|
110
109
|
node = parent
|
111
110
|
else
|
112
111
|
padding = "\n#{leading_spaces(node)}"
|
113
|
-
new_source.gsub!(
|
112
|
+
new_source.gsub!("\n", padding)
|
114
113
|
end
|
115
114
|
|
116
|
-
corrector.replace(node
|
115
|
+
corrector.replace(node, new_source)
|
117
116
|
end
|
118
117
|
|
119
118
|
def correct_single_element(corrector, node, new_source)
|
120
|
-
corrector.replace(node
|
119
|
+
corrector.replace(node, new_source)
|
121
120
|
end
|
122
121
|
|
123
122
|
def to_assignments(receiver, pairs)
|
@@ -126,16 +125,14 @@ module RuboCop
|
|
126
125
|
|
127
126
|
key = key.sym_type? && pair.colon? ? ":#{key.source}" : key.source
|
128
127
|
|
129
|
-
format(AREF_ASGN, receiver: receiver.source,
|
130
|
-
key: key,
|
131
|
-
value: value.source)
|
128
|
+
format(AREF_ASGN, receiver: receiver.source, key: key, value: value.source)
|
132
129
|
end
|
133
130
|
end
|
134
131
|
|
135
132
|
def rewrite_with_modifier(node, parent, new_source)
|
136
|
-
indent = ' ' *
|
133
|
+
indent = ' ' * configured_indentation_width
|
137
134
|
padding = "\n#{indent + leading_spaces(node)}"
|
138
|
-
new_source.gsub!(
|
135
|
+
new_source.gsub!("\n", padding)
|
139
136
|
|
140
137
|
format(WITH_MODIFIER_CORRECTION, keyword: parent.loc.keyword.source,
|
141
138
|
condition: parent.condition.source,
|
@@ -148,10 +145,6 @@ module RuboCop
|
|
148
145
|
node.source_range.source_line[/\A\s*/]
|
149
146
|
end
|
150
147
|
|
151
|
-
def indent_width
|
152
|
-
@config.for_cop('Layout/IndentationWidth')['Width'] || 2
|
153
|
-
end
|
154
|
-
|
155
148
|
def max_key_value_pairs
|
156
149
|
Integer(cop_config['MaxKeyValuePairs'] || 2)
|
157
150
|
end
|
@@ -3,8 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Performance
|
6
|
-
#
|
7
|
-
# can be replaced with `sort`.
|
6
|
+
# Identifies places where `sort { |a, b| a <=> b }` can be replaced with `sort`.
|
8
7
|
#
|
9
8
|
# @example
|
10
9
|
# # bad
|
@@ -17,25 +16,33 @@ module RuboCop
|
|
17
16
|
include SortBlock
|
18
17
|
extend AutoCorrector
|
19
18
|
|
20
|
-
MSG = 'Use `sort`
|
19
|
+
MSG = 'Use `sort` without block.'
|
21
20
|
|
22
21
|
def on_block(node)
|
23
22
|
return unless (send, var_a, var_b, body = sort_with_block?(node))
|
24
23
|
|
25
24
|
replaceable_body?(body, var_a, var_b) do
|
26
|
-
|
25
|
+
register_offense(send, node)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def on_numblock(node)
|
30
|
+
return unless (send, arg_count, body = sort_with_numblock?(node))
|
31
|
+
return unless arg_count == 2
|
27
32
|
|
28
|
-
|
29
|
-
|
30
|
-
end
|
33
|
+
replaceable_body?(body, :_1, :_2) do
|
34
|
+
register_offense(send, node)
|
31
35
|
end
|
32
36
|
end
|
33
37
|
|
34
38
|
private
|
35
39
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
40
|
+
def register_offense(send, node)
|
41
|
+
range = sort_range(send, node)
|
42
|
+
|
43
|
+
add_offense(range) do |corrector|
|
44
|
+
corrector.replace(range, 'sort')
|
45
|
+
end
|
39
46
|
end
|
40
47
|
end
|
41
48
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Performance
|
6
|
-
#
|
6
|
+
# Identifies places where `split` argument can be replaced from
|
7
7
|
# a deterministic regexp to a string.
|
8
8
|
#
|
9
9
|
# @example
|
@@ -21,7 +21,7 @@ module RuboCop
|
|
21
21
|
STR_SPECIAL_CHARS = %w[\n \" \' \\\\ \t \b \f \r].freeze
|
22
22
|
|
23
23
|
def_node_matcher :split_call_with_regexp?, <<~PATTERN
|
24
|
-
{(
|
24
|
+
{(call !nil? :split $regexp)}
|
25
25
|
PATTERN
|
26
26
|
|
27
27
|
def on_send(node)
|
@@ -35,6 +35,7 @@ module RuboCop
|
|
35
35
|
corrector.replace(regexp_node, "\"#{new_argument}\"")
|
36
36
|
end
|
37
37
|
end
|
38
|
+
alias on_csend on_send
|
38
39
|
|
39
40
|
private
|
40
41
|
|
@@ -3,12 +3,13 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Performance
|
6
|
-
#
|
6
|
+
# Checks for redundant `String#chars`.
|
7
7
|
#
|
8
8
|
# @example
|
9
9
|
# # bad
|
10
10
|
# str.chars[0..2]
|
11
11
|
# str.chars.slice(0..2)
|
12
|
+
# str.chars.last
|
12
13
|
#
|
13
14
|
# # good
|
14
15
|
# str[0..2].chars
|
@@ -20,6 +21,7 @@ module RuboCop
|
|
20
21
|
# # good
|
21
22
|
# str[0]
|
22
23
|
# str[0...2].chars
|
24
|
+
# str[-1]
|
23
25
|
#
|
24
26
|
# # bad
|
25
27
|
# str.chars.take(2)
|
@@ -33,9 +35,8 @@ module RuboCop
|
|
33
35
|
# str.size
|
34
36
|
# str.empty?
|
35
37
|
#
|
36
|
-
# # For example, if the receiver is
|
38
|
+
# # For example, if the receiver is an empty string, it will be incompatible.
|
37
39
|
# # If a negative value is specified for the receiver, `nil` is returned.
|
38
|
-
# str.chars.last # Incompatible with `str[-1]`.
|
39
40
|
# str.chars.last(2) # Incompatible with `str[-2..-1].chars`.
|
40
41
|
# str.chars.drop(2) # Incompatible with `str[2..-1].chars`.
|
41
42
|
#
|
@@ -44,7 +45,7 @@ module RuboCop
|
|
44
45
|
extend AutoCorrector
|
45
46
|
|
46
47
|
MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
|
47
|
-
RESTRICT_ON_SEND = %i[[] slice first take length size empty?].freeze
|
48
|
+
RESTRICT_ON_SEND = %i[[] slice first last take length size empty?].freeze
|
48
49
|
|
49
50
|
def_node_matcher :redundant_chars_call?, <<~PATTERN
|
50
51
|
(send $(send _ :chars) $_ $...)
|
@@ -52,6 +53,7 @@ module RuboCop
|
|
52
53
|
|
53
54
|
def on_send(node)
|
54
55
|
return unless (receiver, method, args = redundant_chars_call?(node))
|
56
|
+
return if method == :last && !args.empty?
|
55
57
|
|
56
58
|
range = offense_range(receiver, node)
|
57
59
|
message = build_message(method, args)
|
@@ -67,11 +69,11 @@ module RuboCop
|
|
67
69
|
private
|
68
70
|
|
69
71
|
def offense_range(receiver, node)
|
70
|
-
range_between(receiver.loc.selector.begin_pos, node.
|
72
|
+
range_between(receiver.loc.selector.begin_pos, node.source_range.end_pos)
|
71
73
|
end
|
72
74
|
|
73
75
|
def correction_range(receiver, node)
|
74
|
-
range_between(receiver.loc.dot.begin_pos, node.
|
76
|
+
range_between(receiver.loc.dot.begin_pos, node.source_range.end_pos)
|
75
77
|
end
|
76
78
|
|
77
79
|
def build_message(method, args)
|
@@ -86,6 +88,8 @@ module RuboCop
|
|
86
88
|
"[#{build_call_args(args)}].chars"
|
87
89
|
when :[], :first
|
88
90
|
build_good_method_for_brackets_or_first_method(method, args)
|
91
|
+
when :last
|
92
|
+
'[-1]'
|
89
93
|
when :take
|
90
94
|
"[0...#{args.first.source}].chars"
|
91
95
|
else
|
@@ -74,6 +74,9 @@ module RuboCop
|
|
74
74
|
# end
|
75
75
|
class RegexpMatch < Base
|
76
76
|
extend AutoCorrector
|
77
|
+
extend TargetRubyVersion
|
78
|
+
|
79
|
+
minimum_target_ruby_version 2.4
|
77
80
|
|
78
81
|
# Constants are included in this list because it is unlikely that
|
79
82
|
# someone will store `nil` as a constant and then use it for comparison
|
@@ -121,13 +124,17 @@ module RuboCop
|
|
121
124
|
|
122
125
|
def_node_search :last_matches, <<~PATTERN
|
123
126
|
{
|
124
|
-
(send (const nil? :Regexp) :last_match)
|
125
|
-
(send (const nil? :Regexp) :last_match _)
|
127
|
+
(send (const {nil? cbase} :Regexp) :last_match)
|
128
|
+
(send (const {nil? cbase} :Regexp) :last_match _)
|
126
129
|
({back_ref nth_ref} _)
|
127
130
|
(gvar #match_gvar?)
|
128
131
|
}
|
129
132
|
PATTERN
|
130
133
|
|
134
|
+
def self.autocorrect_incompatible_with
|
135
|
+
[ConstantRegexp]
|
136
|
+
end
|
137
|
+
|
131
138
|
def on_if(node)
|
132
139
|
check_condition(node.condition)
|
133
140
|
end
|
@@ -182,9 +189,9 @@ module RuboCop
|
|
182
189
|
|
183
190
|
def range_to_search_for_last_matches(match_node, body, scope_root)
|
184
191
|
expression = if modifier_form?(match_node)
|
185
|
-
match_node.parent.if_branch.
|
192
|
+
match_node.parent.if_branch.source_range
|
186
193
|
else
|
187
|
-
match_node.
|
194
|
+
match_node.source_range
|
188
195
|
end
|
189
196
|
|
190
197
|
match_node_pos = expression.begin_pos
|
@@ -196,15 +203,15 @@ module RuboCop
|
|
196
203
|
def next_match_pos(body, match_node_pos, scope_root)
|
197
204
|
node = search_match_nodes(body).find do |match|
|
198
205
|
begin_pos = if modifier_form?(match)
|
199
|
-
match.parent.if_branch.
|
206
|
+
match.parent.if_branch.source_range.begin_pos
|
200
207
|
else
|
201
|
-
match.
|
208
|
+
match.source_range.begin_pos
|
202
209
|
end
|
203
210
|
|
204
211
|
begin_pos > match_node_pos && scope_root(match) == scope_root
|
205
212
|
end
|
206
213
|
|
207
|
-
node ? node.
|
214
|
+
node ? node.source_range.begin_pos : Float::INFINITY
|
208
215
|
end
|
209
216
|
|
210
217
|
def modifier_form?(match_node)
|
@@ -213,9 +220,8 @@ module RuboCop
|
|
213
220
|
|
214
221
|
def find_last_match(body, range, scope_root)
|
215
222
|
last_matches(body).find do |ref|
|
216
|
-
ref_pos = ref.
|
217
|
-
range.cover?(ref_pos) &&
|
218
|
-
scope_root(ref) == scope_root
|
223
|
+
ref_pos = ref.source_range.begin_pos
|
224
|
+
range.cover?(ref_pos) && scope_root(ref) == scope_root
|
219
225
|
end
|
220
226
|
end
|
221
227
|
|
@@ -238,14 +244,7 @@ module RuboCop
|
|
238
244
|
end
|
239
245
|
|
240
246
|
def match_gvar?(sym)
|
241
|
-
%i[
|
242
|
-
$~
|
243
|
-
$MATCH
|
244
|
-
$PREMATCH
|
245
|
-
$POSTMATCH
|
246
|
-
$LAST_PAREN_MATCH
|
247
|
-
$LAST_MATCH_INFO
|
248
|
-
].include?(sym)
|
247
|
+
%i[$~ $MATCH $PREMATCH $POSTMATCH $LAST_PAREN_MATCH $LAST_MATCH_INFO].include?(sym)
|
249
248
|
end
|
250
249
|
|
251
250
|
def correct_operator(corrector, recv, arg, oper = nil)
|
@@ -253,8 +252,8 @@ module RuboCop
|
|
253
252
|
|
254
253
|
replace_with_match_predicate_method(corrector, recv, arg, op_range)
|
255
254
|
|
256
|
-
corrector.insert_after(arg
|
257
|
-
corrector.insert_before(recv
|
255
|
+
corrector.insert_after(arg, ')') unless op_range.source.end_with?('(')
|
256
|
+
corrector.insert_before(recv, '!') if oper == :!~
|
258
257
|
end
|
259
258
|
|
260
259
|
def replace_with_match_predicate_method(corrector, recv, arg, op_range)
|
@@ -269,14 +268,14 @@ module RuboCop
|
|
269
268
|
end
|
270
269
|
|
271
270
|
def swap_receiver_and_arg(corrector, recv, arg)
|
272
|
-
corrector.replace(recv
|
273
|
-
corrector.replace(arg
|
271
|
+
corrector.replace(recv, arg.source)
|
272
|
+
corrector.replace(arg, recv.source)
|
274
273
|
end
|
275
274
|
|
276
275
|
def correction_range(recv, arg)
|
277
276
|
buffer = processed_source.buffer
|
278
|
-
op_begin_pos = recv.
|
279
|
-
op_end_pos = arg.
|
277
|
+
op_begin_pos = recv.source_range.end_pos
|
278
|
+
op_end_pos = arg.source_range.begin_pos
|
280
279
|
Parser::Source::Range.new(buffer, op_begin_pos, op_end_pos)
|
281
280
|
end
|
282
281
|
end
|
@@ -3,8 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Performance
|
6
|
-
#
|
7
|
-
# change them to use `reverse_each` instead.
|
6
|
+
# Identifies usages of `reverse.each` and change them to use `reverse_each` instead.
|
8
7
|
#
|
9
8
|
# If the return value is used, it will not be detected because the result will be different.
|
10
9
|
#
|
@@ -28,7 +27,7 @@ module RuboCop
|
|
28
27
|
RESTRICT_ON_SEND = %i[each].freeze
|
29
28
|
|
30
29
|
def_node_matcher :reverse_each?, <<~MATCHER
|
31
|
-
(send (
|
30
|
+
(send (call _ :reverse) :each)
|
32
31
|
MATCHER
|
33
32
|
|
34
33
|
def on_send(node)
|
@@ -42,6 +41,7 @@ module RuboCop
|
|
42
41
|
end
|
43
42
|
end
|
44
43
|
end
|
44
|
+
alias on_csend on_send
|
45
45
|
|
46
46
|
private
|
47
47
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Performance
|
6
|
-
#
|
6
|
+
# Identifies places where `reverse.first(n)` and `reverse.first`
|
7
7
|
# can be replaced by `last(n).reverse` and `last`.
|
8
8
|
#
|
9
9
|
# @example
|
@@ -24,7 +24,7 @@ module RuboCop
|
|
24
24
|
RESTRICT_ON_SEND = %i[first].freeze
|
25
25
|
|
26
26
|
def_node_matcher :reverse_first_candidate?, <<~PATTERN
|
27
|
-
(send $(
|
27
|
+
(send $(call _ :reverse) :first (int _)?)
|
28
28
|
PATTERN
|
29
29
|
|
30
30
|
def on_send(node)
|
@@ -39,11 +39,12 @@ module RuboCop
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
42
|
+
alias on_csend on_send
|
42
43
|
|
43
44
|
private
|
44
45
|
|
45
46
|
def correction_range(receiver, node)
|
46
|
-
range_between(receiver.loc.selector.begin_pos, node.
|
47
|
+
range_between(receiver.loc.selector.begin_pos, node.source_range.end_pos)
|
47
48
|
end
|
48
49
|
|
49
50
|
def build_message(node)
|
@@ -38,6 +38,7 @@ module RuboCop
|
|
38
38
|
range = offense_range(node, map_method)
|
39
39
|
add_offense(range, message: format(MSG, method_name: node.method_name))
|
40
40
|
end
|
41
|
+
alias on_csend on_send
|
41
42
|
|
42
43
|
private
|
43
44
|
|
@@ -52,7 +53,7 @@ module RuboCop
|
|
52
53
|
end
|
53
54
|
|
54
55
|
def offense_range(node, map_method)
|
55
|
-
range_between(node.loc.selector.begin_pos, map_method.
|
56
|
+
range_between(node.loc.selector.begin_pos, map_method.source_range.end_pos)
|
56
57
|
end
|
57
58
|
end
|
58
59
|
end
|
@@ -3,8 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Performance
|
6
|
-
#
|
7
|
-
# `Array` and `Hash` and change them to `size`.
|
6
|
+
# Identifies usages of `count` on an `Array` and `Hash` and change them to `size`.
|
8
7
|
#
|
9
8
|
# @example
|
10
9
|
# # bad
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Performance
|
6
|
-
#
|
6
|
+
# Identifies places where `sort { |a, b| b <=> a }`
|
7
7
|
# can be replaced by a faster `sort.reverse`.
|
8
8
|
#
|
9
9
|
# @example
|
@@ -17,27 +17,36 @@ module RuboCop
|
|
17
17
|
include SortBlock
|
18
18
|
extend AutoCorrector
|
19
19
|
|
20
|
-
MSG = 'Use `sort.reverse` instead
|
20
|
+
MSG = 'Use `sort.reverse` instead.'
|
21
21
|
|
22
22
|
def on_block(node)
|
23
23
|
sort_with_block?(node) do |send, var_a, var_b, body|
|
24
24
|
replaceable_body?(body, var_b, var_a) do
|
25
|
-
|
25
|
+
register_offense(send, node)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
26
29
|
|
27
|
-
|
28
|
-
|
30
|
+
def on_numblock(node)
|
31
|
+
sort_with_numblock?(node) do |send, arg_count, body|
|
32
|
+
next unless arg_count == 2
|
29
33
|
|
30
|
-
|
31
|
-
|
34
|
+
replaceable_body?(body, :_2, :_1) do
|
35
|
+
register_offense(send, node)
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
35
39
|
|
36
40
|
private
|
37
41
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
42
|
+
def register_offense(send, node)
|
43
|
+
range = sort_range(send, node)
|
44
|
+
|
45
|
+
add_offense(range) do |corrector|
|
46
|
+
replacement = 'sort.reverse'
|
47
|
+
|
48
|
+
corrector.replace(range, replacement)
|
49
|
+
end
|
41
50
|
end
|
42
51
|
end
|
43
52
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Performance
|
6
|
-
#
|
6
|
+
# Identifies places where `gsub(/a+/, 'a')` and `gsub!(/a+/, 'a')`
|
7
7
|
# can be replaced by `squeeze('a')` and `squeeze!('a')`.
|
8
8
|
#
|
9
9
|
# The `squeeze('a')` method is faster than `gsub(/a+/, 'a')`.
|
@@ -24,13 +24,10 @@ module RuboCop
|
|
24
24
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
25
25
|
RESTRICT_ON_SEND = %i[gsub gsub!].freeze
|
26
26
|
|
27
|
-
PREFERRED_METHODS = {
|
28
|
-
gsub: :squeeze,
|
29
|
-
gsub!: :squeeze!
|
30
|
-
}.freeze
|
27
|
+
PREFERRED_METHODS = { gsub: :squeeze, gsub!: :squeeze! }.freeze
|
31
28
|
|
32
29
|
def_node_matcher :squeeze_candidate?, <<~PATTERN
|
33
|
-
(
|
30
|
+
(call
|
34
31
|
$!nil? ${:gsub :gsub!}
|
35
32
|
(regexp
|
36
33
|
(str $#repeating_literal?)
|
@@ -38,6 +35,7 @@ module RuboCop
|
|
38
35
|
(str $_))
|
39
36
|
PATTERN
|
40
37
|
|
38
|
+
# rubocop:disable Metrics/AbcSize
|
41
39
|
def on_send(node)
|
42
40
|
squeeze_candidate?(node) do |receiver, bad_method, regexp_str, replace_str|
|
43
41
|
regexp_str = regexp_str[0..-2] # delete '+' from the end
|
@@ -49,12 +47,14 @@ module RuboCop
|
|
49
47
|
|
50
48
|
add_offense(node.loc.selector, message: message) do |corrector|
|
51
49
|
string_literal = to_string_literal(replace_str)
|
52
|
-
new_code = "#{receiver.source}
|
50
|
+
new_code = "#{receiver.source}#{node.loc.dot.source}#{good_method}(#{string_literal})"
|
53
51
|
|
54
|
-
corrector.replace(node
|
52
|
+
corrector.replace(node, new_code)
|
55
53
|
end
|
56
54
|
end
|
57
55
|
end
|
56
|
+
# rubocop:enable Metrics/AbcSize
|
57
|
+
alias on_csend on_send
|
58
58
|
|
59
59
|
private
|
60
60
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Performance
|
6
|
-
#
|
6
|
+
# Identifies unnecessary use of a regex where `String#start_with?` would suffice.
|
7
7
|
#
|
8
8
|
# This cop has `SafeMultiline` configuration option that `true` by default because
|
9
9
|
# `^start` is unsafe as it will behave incompatible with `start_with?`
|
@@ -50,12 +50,11 @@ module RuboCop
|
|
50
50
|
include RegexpMetacharacter
|
51
51
|
extend AutoCorrector
|
52
52
|
|
53
|
-
MSG = 'Use `String#start_with?` instead of a regex match anchored to '
|
54
|
-
'the beginning of the string.'
|
53
|
+
MSG = 'Use `String#start_with?` instead of a regex match anchored to the beginning of the string.'
|
55
54
|
RESTRICT_ON_SEND = %i[match =~ match?].freeze
|
56
55
|
|
57
56
|
def_node_matcher :redundant_regex?, <<~PATTERN
|
58
|
-
{(
|
57
|
+
{(call $!nil? {:match :=~ :match?} (regexp (str $#literal_at_start?) (regopt)))
|
59
58
|
(send (regexp (str $#literal_at_start?) (regopt)) {:match :match?} $_)
|
60
59
|
(match-with-lvasgn (regexp (str $#literal_at_start?) (regopt)) $_)}
|
61
60
|
PATTERN
|
@@ -67,12 +66,14 @@ module RuboCop
|
|
67
66
|
receiver, regex_str = regex_str, receiver if receiver.is_a?(String)
|
68
67
|
regex_str = drop_start_metacharacter(regex_str)
|
69
68
|
regex_str = interpret_string_escapes(regex_str)
|
69
|
+
dot = node.loc.dot ? node.loc.dot.source : '.'
|
70
70
|
|
71
|
-
new_source = "#{receiver.source}
|
71
|
+
new_source = "#{receiver.source}#{dot}start_with?(#{to_string_literal(regex_str)})"
|
72
72
|
|
73
|
-
corrector.replace(node
|
73
|
+
corrector.replace(node, new_source)
|
74
74
|
end
|
75
75
|
end
|
76
|
+
alias on_csend on_send
|
76
77
|
alias on_match_with_lvasgn on_send
|
77
78
|
end
|
78
79
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Performance
|
6
|
-
#
|
6
|
+
# Identifies places where string identifier argument can be replaced
|
7
7
|
# by symbol identifier argument.
|
8
8
|
# It prevents the redundancy of the internal string-to-symbol conversion.
|
9
9
|
#
|
@@ -27,28 +27,33 @@ module RuboCop
|
|
27
27
|
|
28
28
|
MSG = 'Use `%<symbol_arg>s` instead of `%<string_arg>s`.'
|
29
29
|
|
30
|
+
COMMAND_METHODS = %i[
|
31
|
+
alias_method attr_accessor attr_reader attr_writer autoload autoload? private private_constant
|
32
|
+
protected public public_constant module_function
|
33
|
+
].freeze
|
34
|
+
|
30
35
|
# NOTE: `attr` method is not included in this list as it can cause false positives in Nokogiri API.
|
31
36
|
# And `attr` may not be used because `Style/Attr` registers an offense.
|
32
37
|
# https://github.com/rubocop/rubocop-performance/issues/278
|
33
|
-
RESTRICT_ON_SEND = %i[
|
34
|
-
alias_method attr_accessor attr_reader attr_writer autoload autoload?
|
38
|
+
RESTRICT_ON_SEND = (%i[
|
35
39
|
class_variable_defined? const_defined? const_get const_set const_source_location
|
36
40
|
define_method instance_method method_defined? private_class_method? private_method_defined?
|
37
41
|
protected_method_defined? public_class_method public_instance_method public_method_defined?
|
38
42
|
remove_class_variable remove_method undef_method class_variable_get class_variable_set
|
39
|
-
deprecate_constant
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
__send__
|
44
|
-
].freeze
|
43
|
+
deprecate_constant remove_const ruby2_keywords define_singleton_method instance_variable_defined?
|
44
|
+
instance_variable_get instance_variable_set method public_method public_send remove_instance_variable
|
45
|
+
respond_to? send singleton_method __send__
|
46
|
+
] + COMMAND_METHODS).freeze
|
45
47
|
|
46
48
|
def on_send(node)
|
49
|
+
return if COMMAND_METHODS.include?(node.method_name) && node.receiver
|
47
50
|
return unless (first_argument = node.first_argument)
|
48
51
|
return unless first_argument.str_type?
|
49
|
-
return if first_argument.value.include?(' ')
|
50
52
|
|
51
|
-
|
53
|
+
first_argument_value = first_argument.value
|
54
|
+
return if first_argument_value.include?(' ') || first_argument_value.include?('::')
|
55
|
+
|
56
|
+
replacement = first_argument_value.to_sym.inspect
|
52
57
|
|
53
58
|
message = format(MSG, symbol_arg: replacement, string_arg: first_argument.source)
|
54
59
|
|