rubocop-performance 1.18.0 → 1.23.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 +3 -1
- data/config/default.yml +34 -18
- data/lib/rubocop/cop/mixin/sort_block.rb +2 -2
- data/lib/rubocop/cop/performance/array_semi_infinite_range_slice.rb +2 -1
- data/lib/rubocop/cop/performance/big_decimal_with_numeric_argument.rb +43 -19
- data/lib/rubocop/cop/performance/block_given_with_explicit_block.rb +7 -0
- data/lib/rubocop/cop/performance/casecmp.rb +6 -0
- data/lib/rubocop/cop/performance/chain_array_allocation.rb +11 -4
- data/lib/rubocop/cop/performance/count.rb +7 -7
- data/lib/rubocop/cop/performance/delete_prefix.rb +5 -2
- data/lib/rubocop/cop/performance/delete_suffix.rb +5 -2
- data/lib/rubocop/cop/performance/detect.rb +3 -2
- data/lib/rubocop/cop/performance/double_start_end_with.rb +10 -10
- data/lib/rubocop/cop/performance/end_with.rb +6 -3
- data/lib/rubocop/cop/performance/fixed_size.rb +4 -3
- data/lib/rubocop/cop/performance/flat_map.rb +4 -3
- data/lib/rubocop/cop/performance/inefficient_hash_search.rb +16 -10
- data/lib/rubocop/cop/performance/map_compact.rb +8 -6
- data/lib/rubocop/cop/performance/map_method_chain.rb +89 -0
- data/lib/rubocop/cop/performance/range_include.rb +8 -6
- data/lib/rubocop/cop/performance/redundant_block_call.rb +2 -0
- data/lib/rubocop/cop/performance/redundant_equality_comparison_block.rb +2 -2
- data/lib/rubocop/cop/performance/redundant_match.rb +30 -1
- data/lib/rubocop/cop/performance/redundant_merge.rb +2 -2
- data/lib/rubocop/cop/performance/redundant_split_regexp_argument.rb +2 -1
- data/lib/rubocop/cop/performance/redundant_string_chars.rb +1 -1
- data/lib/rubocop/cop/performance/regexp_match.rb +1 -8
- data/lib/rubocop/cop/performance/reverse_each.rb +2 -1
- data/lib/rubocop/cop/performance/reverse_first.rb +6 -13
- data/lib/rubocop/cop/performance/select_map.rb +3 -6
- data/lib/rubocop/cop/performance/size.rb +4 -3
- data/lib/rubocop/cop/performance/sort_reverse.rb +5 -4
- data/lib/rubocop/cop/performance/squeeze.rb +10 -3
- data/lib/rubocop/cop/performance/start_with.rb +6 -3
- data/lib/rubocop/cop/performance/string_bytesize.rb +45 -0
- data/lib/rubocop/cop/performance/string_identifier_argument.rb +58 -10
- data/lib/rubocop/cop/performance/string_include.rb +11 -5
- data/lib/rubocop/cop/performance/string_replacement.rb +2 -1
- data/lib/rubocop/cop/performance/sum.rb +12 -10
- data/lib/rubocop/cop/performance/times_map.rb +14 -2
- data/lib/rubocop/cop/performance/unfreeze_string.rb +6 -3
- data/lib/rubocop/cop/performance/uri_default_parser.rb +1 -1
- data/lib/rubocop/cop/performance_cops.rb +2 -0
- data/lib/rubocop/performance/version.rb +1 -1
- data/lib/rubocop-performance.rb +8 -0
- metadata +16 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 332ca643753a81ff66c4a6050117f7a479bd3aaa3f186c361a596d06b16aa9b5
|
|
4
|
+
data.tar.gz: 2fb149f85f986d9d0302e6fbe4c7389f312bb93a15a93cec49ffd74495853c78
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e03b8e178f4cde75ef5d82aa7483da512f2816afd82c97b414a4bfcd7afacf589ebb033d6bed40d0968217ec0ff24cb69e2a6c4f28a52ecbdb31cef5599e5386
|
|
7
|
+
data.tar.gz: 410a72e5e85fe6cdc8002b51c8b185dc4d2a1dea5f3a5889c146364c2a20b5b50256c2a90fef59604137dd75d83f20c17ec65991eac6b8dab15e046184e1f006
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# RuboCop Performance
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/rb/rubocop-performance)
|
|
4
|
-
[](https://github.com/rubocop/rubocop-performance/actions/workflows/test.yml)
|
|
5
5
|
[](https://discord.gg/wJjWvGRDmm)
|
|
6
6
|
|
|
7
7
|
Performance optimization analysis for your projects, as an extension to [RuboCop](https://github.com/rubocop/rubocop).
|
|
@@ -53,6 +53,8 @@ $ rubocop --require rubocop-performance
|
|
|
53
53
|
### Rake task
|
|
54
54
|
|
|
55
55
|
```ruby
|
|
56
|
+
require 'rubocop/rake_task'
|
|
57
|
+
|
|
56
58
|
RuboCop::RakeTask.new do |task|
|
|
57
59
|
task.requires << 'rubocop-performance'
|
|
58
60
|
end
|
data/config/default.yml
CHANGED
|
@@ -6,7 +6,7 @@ Performance:
|
|
|
6
6
|
|
|
7
7
|
Performance/AncestorsInclude:
|
|
8
8
|
Description: 'Use `A <= B` instead of `A.ancestors.include?(B)`.'
|
|
9
|
-
Reference: 'https://github.com/
|
|
9
|
+
Reference: 'https://github.com/fastruby/fast-ruby#ancestorsinclude-vs--code'
|
|
10
10
|
Enabled: 'pending'
|
|
11
11
|
Safe: false
|
|
12
12
|
VersionAdded: '1.7'
|
|
@@ -32,8 +32,11 @@ Performance/BindCall:
|
|
|
32
32
|
|
|
33
33
|
Performance/BlockGivenWithExplicitBlock:
|
|
34
34
|
Description: 'Check block argument explicitly instead of using `block_given?`.'
|
|
35
|
-
|
|
35
|
+
# This cop was created due to a mistake in microbenchmark.
|
|
36
|
+
# https://github.com/rubocop/rubocop-performance/issues/385
|
|
37
|
+
Enabled: false
|
|
36
38
|
VersionAdded: '1.9'
|
|
39
|
+
VersionChanged: '1.22'
|
|
37
40
|
|
|
38
41
|
Performance/Caller:
|
|
39
42
|
Description: >-
|
|
@@ -54,10 +57,11 @@ Performance/CaseWhenSplat:
|
|
|
54
57
|
Performance/Casecmp:
|
|
55
58
|
Description: >-
|
|
56
59
|
Use `casecmp` rather than `downcase ==`, `upcase ==`, `== downcase`, or `== upcase`..
|
|
57
|
-
Reference: 'https://github.com/
|
|
58
|
-
Enabled:
|
|
60
|
+
Reference: 'https://github.com/fastruby/fast-ruby#stringcasecmp-vs--stringcasecmp-vs-stringdowncase---code'
|
|
61
|
+
Enabled: false
|
|
59
62
|
Safe: false
|
|
60
63
|
VersionAdded: '0.36'
|
|
64
|
+
VersionChanged: '1.21'
|
|
61
65
|
|
|
62
66
|
Performance/ChainArrayAllocation:
|
|
63
67
|
Description: >-
|
|
@@ -122,7 +126,7 @@ Performance/Detect:
|
|
|
122
126
|
Description: >-
|
|
123
127
|
Use `detect` instead of `select.first`, `find_all.first`, `filter.first`,
|
|
124
128
|
`select.last`, `find_all.last`, and `filter.last`.
|
|
125
|
-
Reference: 'https://github.com/
|
|
129
|
+
Reference: 'https://github.com/fastruby/fast-ruby#enumerabledetect-vs-enumerableselectfirst-code'
|
|
126
130
|
# This cop has known compatibility issues with `ActiveRecord` and other
|
|
127
131
|
# frameworks. `ActiveRecord` does not implement a `detect` method and `find`
|
|
128
132
|
# has its own meaning. Correcting `ActiveRecord` methods with this cop
|
|
@@ -145,7 +149,7 @@ Performance/DoubleStartEndWith:
|
|
|
145
149
|
|
|
146
150
|
Performance/EndWith:
|
|
147
151
|
Description: 'Use `end_with?` instead of a regex match anchored to the end of a string.'
|
|
148
|
-
Reference: 'https://github.com/
|
|
152
|
+
Reference: 'https://github.com/fastruby/fast-ruby#stringmatch-vs-stringmatch-vs-stringstart_withstringend_with-code-start-code-end'
|
|
149
153
|
# This will change to a new method call which isn't guaranteed to be on the
|
|
150
154
|
# object. Switching these methods has to be done with knowledge of the types
|
|
151
155
|
# of the variables which rubocop doesn't have.
|
|
@@ -165,7 +169,7 @@ Performance/FlatMap:
|
|
|
165
169
|
Use `Enumerable#flat_map`
|
|
166
170
|
instead of `Enumerable#map...Array#flatten(1)`
|
|
167
171
|
or `Enumerable#collect..Array#flatten(1)`.
|
|
168
|
-
Reference: 'https://github.com/
|
|
172
|
+
Reference: 'https://github.com/fastruby/fast-ruby#enumerablemaparrayflatten-vs-enumerableflat_map-code'
|
|
169
173
|
Enabled: true
|
|
170
174
|
VersionAdded: '0.30'
|
|
171
175
|
EnabledForFlattenWithoutParams: false
|
|
@@ -176,7 +180,7 @@ Performance/FlatMap:
|
|
|
176
180
|
|
|
177
181
|
Performance/InefficientHashSearch:
|
|
178
182
|
Description: 'Use `key?` or `value?` instead of `keys.include?` or `values.include?`.'
|
|
179
|
-
Reference: 'https://github.com/
|
|
183
|
+
Reference: 'https://github.com/fastruby/fast-ruby#hashkey-instead-of-hashkeysinclude-code'
|
|
180
184
|
Enabled: true
|
|
181
185
|
VersionAdded: '0.56'
|
|
182
186
|
Safe: false
|
|
@@ -193,9 +197,15 @@ Performance/MapCompact:
|
|
|
193
197
|
SafeAutoCorrect: false
|
|
194
198
|
VersionAdded: '1.11'
|
|
195
199
|
|
|
200
|
+
Performance/MapMethodChain:
|
|
201
|
+
Description: 'Checks if the `map` method is used in a chain.'
|
|
202
|
+
Enabled: pending
|
|
203
|
+
Safe: false
|
|
204
|
+
VersionAdded: '1.19'
|
|
205
|
+
|
|
196
206
|
Performance/MethodObjectAsBlock:
|
|
197
207
|
Description: 'Use block explicitly instead of block-passing a method object.'
|
|
198
|
-
Reference: 'https://github.com/
|
|
208
|
+
Reference: 'https://github.com/fastruby/fast-ruby#normal-way-to-apply-method-vs-method-code'
|
|
199
209
|
Enabled: pending
|
|
200
210
|
VersionAdded: '1.9'
|
|
201
211
|
|
|
@@ -207,7 +217,7 @@ Performance/OpenStruct:
|
|
|
207
217
|
|
|
208
218
|
Performance/RangeInclude:
|
|
209
219
|
Description: 'Use `Range#cover?` instead of `Range#include?` (or `Range#member?`).'
|
|
210
|
-
Reference: 'https://github.com/
|
|
220
|
+
Reference: 'https://github.com/fastruby/fast-ruby#cover-vs-include-code'
|
|
211
221
|
Enabled: true
|
|
212
222
|
VersionAdded: '0.36'
|
|
213
223
|
VersionChanged: '1.7'
|
|
@@ -215,7 +225,7 @@ Performance/RangeInclude:
|
|
|
215
225
|
|
|
216
226
|
Performance/RedundantBlockCall:
|
|
217
227
|
Description: 'Use `yield` instead of `block.call`.'
|
|
218
|
-
Reference: 'https://github.com/
|
|
228
|
+
Reference: 'https://github.com/fastruby/fast-ruby#proccall-and-block-arguments-vs-yieldcode'
|
|
219
229
|
Enabled: true
|
|
220
230
|
VersionAdded: '0.36'
|
|
221
231
|
|
|
@@ -238,7 +248,7 @@ Performance/RedundantMatch:
|
|
|
238
248
|
|
|
239
249
|
Performance/RedundantMerge:
|
|
240
250
|
Description: 'Use Hash#[]=, rather than Hash#merge! with a single key-value pair.'
|
|
241
|
-
Reference: 'https://github.com/
|
|
251
|
+
Reference: 'https://github.com/fastruby/fast-ruby#hashmerge-vs-hash-code'
|
|
242
252
|
Enabled: true
|
|
243
253
|
Safe: false
|
|
244
254
|
VersionAdded: '0.36'
|
|
@@ -265,13 +275,13 @@ Performance/RegexpMatch:
|
|
|
265
275
|
Description: >-
|
|
266
276
|
Use `match?` instead of `Regexp#match`, `String#match`, `Symbol#match`,
|
|
267
277
|
`Regexp#===`, or `=~` when `MatchData` is not used.
|
|
268
|
-
Reference: 'https://github.com/
|
|
278
|
+
Reference: 'https://github.com/fastruby/fast-ruby#regexp-vs-regexpmatch-vs-regexpmatch-vs-stringmatch-vs-string-vs-stringmatch-code-'
|
|
269
279
|
Enabled: true
|
|
270
280
|
VersionAdded: '0.47'
|
|
271
281
|
|
|
272
282
|
Performance/ReverseEach:
|
|
273
283
|
Description: 'Use `reverse_each` instead of `reverse.each`.'
|
|
274
|
-
Reference: 'https://github.com/
|
|
284
|
+
Reference: 'https://github.com/fastruby/fast-ruby#enumerablereverseeach-vs-enumerablereverse_each-code'
|
|
275
285
|
Enabled: true
|
|
276
286
|
VersionAdded: '0.30'
|
|
277
287
|
|
|
@@ -289,7 +299,7 @@ Performance/Size:
|
|
|
289
299
|
Description: >-
|
|
290
300
|
Use `size` instead of `count` for counting
|
|
291
301
|
the number of elements in `Array` and `Hash`.
|
|
292
|
-
Reference: 'https://github.com/
|
|
302
|
+
Reference: 'https://github.com/fastruby/fast-ruby#arraylength-vs-arraysize-vs-arraycount-code'
|
|
293
303
|
Enabled: true
|
|
294
304
|
VersionAdded: '0.30'
|
|
295
305
|
|
|
@@ -300,13 +310,13 @@ Performance/SortReverse:
|
|
|
300
310
|
|
|
301
311
|
Performance/Squeeze:
|
|
302
312
|
Description: "Use `squeeze('a')` instead of `gsub(/a+/, 'a')`."
|
|
303
|
-
Reference: 'https://github.com/
|
|
313
|
+
Reference: 'https://github.com/fastruby/fast-ruby#remove-extra-spaces-or-other-contiguous-characters-code'
|
|
304
314
|
Enabled: 'pending'
|
|
305
315
|
VersionAdded: '1.7'
|
|
306
316
|
|
|
307
317
|
Performance/StartWith:
|
|
308
318
|
Description: 'Use `start_with?` instead of a regex match anchored to the beginning of a string.'
|
|
309
|
-
Reference: 'https://github.com/
|
|
319
|
+
Reference: 'https://github.com/fastruby/fast-ruby#stringmatch-vs-stringmatch-vs-stringstart_withstringend_with-code-start-code-end'
|
|
310
320
|
# This will change to a new method call which isn't guaranteed to be on the
|
|
311
321
|
# object. Switching these methods has to be done with knowledge of the types
|
|
312
322
|
# of the variables which rubocop doesn't have.
|
|
@@ -316,6 +326,12 @@ Performance/StartWith:
|
|
|
316
326
|
VersionAdded: '0.36'
|
|
317
327
|
VersionChanged: '1.10'
|
|
318
328
|
|
|
329
|
+
Performance/StringBytesize:
|
|
330
|
+
Description: "Use `String#bytesize` instead of calculating the size of the bytes array."
|
|
331
|
+
Safe: false
|
|
332
|
+
Enabled: 'pending'
|
|
333
|
+
VersionAdded: '1.23'
|
|
334
|
+
|
|
319
335
|
Performance/StringIdentifierArgument:
|
|
320
336
|
Description: 'Use symbol identifier argument instead of string identifier argument.'
|
|
321
337
|
Enabled: pending
|
|
@@ -333,7 +349,7 @@ Performance/StringReplacement:
|
|
|
333
349
|
Use `tr` instead of `gsub` when you are replacing the same
|
|
334
350
|
number of characters. Use `delete` instead of `gsub` when
|
|
335
351
|
you are deleting characters.
|
|
336
|
-
Reference: 'https://github.com/
|
|
352
|
+
Reference: 'https://github.com/fastruby/fast-ruby#stringgsub-vs-stringtr-code'
|
|
337
353
|
Enabled: true
|
|
338
354
|
VersionAdded: '0.33'
|
|
339
355
|
|
|
@@ -9,14 +9,14 @@ module RuboCop
|
|
|
9
9
|
|
|
10
10
|
def_node_matcher :sort_with_block?, <<~PATTERN
|
|
11
11
|
(block
|
|
12
|
-
$(
|
|
12
|
+
$(call _ :sort)
|
|
13
13
|
(args (arg $_a) (arg $_b))
|
|
14
14
|
$send)
|
|
15
15
|
PATTERN
|
|
16
16
|
|
|
17
17
|
def_node_matcher :sort_with_numblock?, <<~PATTERN
|
|
18
18
|
(numblock
|
|
19
|
-
$(
|
|
19
|
+
$(call _ :sort)
|
|
20
20
|
$_arg_count
|
|
21
21
|
$send)
|
|
22
22
|
PATTERN
|
|
@@ -39,7 +39,7 @@ module RuboCop
|
|
|
39
39
|
RESTRICT_ON_SEND = SLICE_METHODS
|
|
40
40
|
|
|
41
41
|
def_node_matcher :endless_range_slice?, <<~PATTERN
|
|
42
|
-
(
|
|
42
|
+
(call $!{str dstr xstr} $%SLICE_METHODS $#endless_range?)
|
|
43
43
|
PATTERN
|
|
44
44
|
|
|
45
45
|
def_node_matcher :endless_range?, <<~PATTERN
|
|
@@ -59,6 +59,7 @@ module RuboCop
|
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
|
+
alias on_csend on_send
|
|
62
63
|
|
|
63
64
|
private
|
|
64
65
|
|
|
@@ -3,50 +3,74 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Performance
|
|
6
|
-
# Identifies places where
|
|
7
|
-
#
|
|
8
|
-
#
|
|
6
|
+
# Identifies places where a float argument to BigDecimal should be converted to a string.
|
|
7
|
+
# Initializing from String is faster than from Float for BigDecimal.
|
|
8
|
+
#
|
|
9
|
+
# Also identifies places where an integer string argument to BigDecimal should be converted to
|
|
10
|
+
# an integer. Initializing from Integer is faster than from String for BigDecimal.
|
|
9
11
|
#
|
|
10
12
|
# @example
|
|
11
13
|
# # bad
|
|
12
|
-
# BigDecimal(1, 2)
|
|
13
|
-
# 4.to_d(6)
|
|
14
14
|
# BigDecimal(1.2, 3, exception: true)
|
|
15
15
|
# 4.5.to_d(6, exception: true)
|
|
16
16
|
#
|
|
17
17
|
# # good
|
|
18
|
-
# BigDecimal('1', 2)
|
|
19
|
-
# BigDecimal('4', 6)
|
|
20
18
|
# BigDecimal('1.2', 3, exception: true)
|
|
21
19
|
# BigDecimal('4.5', 6, exception: true)
|
|
22
20
|
#
|
|
21
|
+
# # bad
|
|
22
|
+
# BigDecimal('1', 2)
|
|
23
|
+
# BigDecimal('4', 6)
|
|
24
|
+
#
|
|
25
|
+
# # good
|
|
26
|
+
# BigDecimal(1, 2)
|
|
27
|
+
# 4.to_d(6)
|
|
28
|
+
#
|
|
23
29
|
class BigDecimalWithNumericArgument < Base
|
|
24
30
|
extend AutoCorrector
|
|
31
|
+
extend TargetRubyVersion
|
|
32
|
+
|
|
33
|
+
minimum_target_ruby_version 3.1
|
|
25
34
|
|
|
26
|
-
|
|
35
|
+
MSG_FROM_FLOAT_TO_STRING = 'Convert float literal to string and pass it to `BigDecimal`.'
|
|
36
|
+
MSG_FROM_INTEGER_TO_STRING = 'Convert string literal to integer and pass it to `BigDecimal`.'
|
|
27
37
|
RESTRICT_ON_SEND = %i[BigDecimal to_d].freeze
|
|
28
38
|
|
|
29
|
-
def_node_matcher :big_decimal_with_numeric_argument
|
|
30
|
-
(send nil? :BigDecimal $
|
|
39
|
+
def_node_matcher :big_decimal_with_numeric_argument, <<~PATTERN
|
|
40
|
+
(send nil? :BigDecimal ${float_type? str_type?} ...)
|
|
31
41
|
PATTERN
|
|
32
42
|
|
|
33
|
-
def_node_matcher :to_d
|
|
34
|
-
(send [!nil? $
|
|
43
|
+
def_node_matcher :to_d, <<~PATTERN
|
|
44
|
+
(send [!nil? ${float_type? str_type?}] :to_d ...)
|
|
35
45
|
PATTERN
|
|
36
46
|
|
|
47
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
|
|
37
48
|
def on_send(node)
|
|
38
|
-
if (numeric = big_decimal_with_numeric_argument
|
|
39
|
-
|
|
40
|
-
|
|
49
|
+
if (numeric = big_decimal_with_numeric_argument(node))
|
|
50
|
+
if numeric.numeric_type?
|
|
51
|
+
add_offense(numeric, message: MSG_FROM_FLOAT_TO_STRING) do |corrector|
|
|
52
|
+
corrector.wrap(numeric, "'", "'")
|
|
53
|
+
end
|
|
54
|
+
elsif numeric.value.match?(/\A\d+\z/)
|
|
55
|
+
add_offense(numeric, message: MSG_FROM_INTEGER_TO_STRING) do |corrector|
|
|
56
|
+
corrector.replace(numeric, numeric.value)
|
|
57
|
+
end
|
|
41
58
|
end
|
|
42
|
-
elsif (numeric_to_d = to_d
|
|
43
|
-
|
|
44
|
-
|
|
59
|
+
elsif (numeric_to_d = to_d(node))
|
|
60
|
+
if numeric_to_d.numeric_type?
|
|
61
|
+
add_offense(numeric_to_d, message: MSG_FROM_FLOAT_TO_STRING) do |corrector|
|
|
62
|
+
big_decimal_args = node.arguments.map(&:source).unshift("'#{numeric_to_d.source}'").join(', ')
|
|
45
63
|
|
|
46
|
-
|
|
64
|
+
corrector.replace(node, "BigDecimal(#{big_decimal_args})")
|
|
65
|
+
end
|
|
66
|
+
elsif numeric_to_d.value.match?(/\A\d+\z/)
|
|
67
|
+
add_offense(numeric_to_d, message: MSG_FROM_INTEGER_TO_STRING) do |corrector|
|
|
68
|
+
corrector.replace(node, "#{numeric_to_d.value}.to_d")
|
|
69
|
+
end
|
|
47
70
|
end
|
|
48
71
|
end
|
|
49
72
|
end
|
|
73
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
|
|
50
74
|
end
|
|
51
75
|
end
|
|
52
76
|
end
|
|
@@ -6,6 +6,9 @@ module RuboCop
|
|
|
6
6
|
# Identifies unnecessary use of a `block_given?` where explicit check
|
|
7
7
|
# of block argument would suffice.
|
|
8
8
|
#
|
|
9
|
+
# NOTE: This cop produces code with significantly worse performance when a
|
|
10
|
+
# block is being passed to the method and as such should not be enabled.
|
|
11
|
+
#
|
|
9
12
|
# @example
|
|
10
13
|
# # bad
|
|
11
14
|
# def method(&block)
|
|
@@ -47,6 +50,10 @@ module RuboCop
|
|
|
47
50
|
corrector.replace(node, block_arg_name)
|
|
48
51
|
end
|
|
49
52
|
end
|
|
53
|
+
|
|
54
|
+
def self.autocorrect_incompatible_with
|
|
55
|
+
[Lint::UnusedMethodArgument]
|
|
56
|
+
end
|
|
50
57
|
end
|
|
51
58
|
end
|
|
52
59
|
end
|
|
@@ -6,6 +6,12 @@ module RuboCop
|
|
|
6
6
|
# Identifies places where a case-insensitive string comparison
|
|
7
7
|
# can better be implemented using `casecmp`.
|
|
8
8
|
#
|
|
9
|
+
# This cop is disabled by default because `String#casecmp` only works with
|
|
10
|
+
# ASCII characters. See https://github.com/rubocop/rubocop/issues/9753.
|
|
11
|
+
#
|
|
12
|
+
# If you are working only with ASCII characters, then this cop can be
|
|
13
|
+
# safely enabled.
|
|
14
|
+
#
|
|
9
15
|
# @safety
|
|
10
16
|
# This cop is unsafe because `String#casecmp` and `String#casecmp?` behave
|
|
11
17
|
# differently when using Non-ASCII characters.
|
|
@@ -19,8 +19,6 @@ module RuboCop
|
|
|
19
19
|
# array.map! { |x| x.downcase }
|
|
20
20
|
# array
|
|
21
21
|
class ChainArrayAllocation < Base
|
|
22
|
-
include RangeHelp
|
|
23
|
-
|
|
24
22
|
# These methods return a new array but only sometimes. They must be
|
|
25
23
|
# called with an argument. For example:
|
|
26
24
|
#
|
|
@@ -54,7 +52,7 @@ module RuboCop
|
|
|
54
52
|
def_node_matcher :chain_array_allocation?, <<~PATTERN
|
|
55
53
|
(send {
|
|
56
54
|
(send _ $%RETURN_NEW_ARRAY_WHEN_ARGS {int lvar ivar cvar gvar send})
|
|
57
|
-
(block (send _ $%ALWAYS_RETURNS_NEW_ARRAY) ...)
|
|
55
|
+
({block numblock} (send _ $%ALWAYS_RETURNS_NEW_ARRAY) ...)
|
|
58
56
|
(send _ $%RETURNS_NEW_ARRAY ...)
|
|
59
57
|
} $%HAS_MUTATION_ALTERNATIVE ...)
|
|
60
58
|
PATTERN
|
|
@@ -62,12 +60,21 @@ module RuboCop
|
|
|
62
60
|
def on_send(node)
|
|
63
61
|
chain_array_allocation?(node) do |fm, sm|
|
|
64
62
|
return if node.each_descendant(:send).any? { |descendant| descendant.method?(:lazy) }
|
|
63
|
+
return if node.method?(:select) && !enumerable_select_method?(node.receiver)
|
|
65
64
|
|
|
66
|
-
range =
|
|
65
|
+
range = node.loc.selector.begin.join(node.source_range.end)
|
|
67
66
|
|
|
68
67
|
add_offense(range, message: format(MSG, method: fm, second_method: sm))
|
|
69
68
|
end
|
|
70
69
|
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def enumerable_select_method?(node)
|
|
74
|
+
# NOTE: `QueryMethods#select` in Rails accepts positional arguments, whereas `Enumerable#select` does not.
|
|
75
|
+
# This difference can be utilized to reduce the knowledge requirements related to `select`.
|
|
76
|
+
(node.block_type? || node.numblock_type?) && node.send_node.arguments.empty?
|
|
77
|
+
end
|
|
71
78
|
end
|
|
72
79
|
end
|
|
73
80
|
end
|
|
@@ -9,8 +9,7 @@ module RuboCop
|
|
|
9
9
|
#
|
|
10
10
|
# @safety
|
|
11
11
|
# This cop is unsafe because it has known compatibility issues with `ActiveRecord` and other
|
|
12
|
-
# frameworks.
|
|
13
|
-
# `ActiveRecord` will ignore the block that is passed to `count`.
|
|
12
|
+
# frameworks. Before Rails 5.1, `ActiveRecord` will ignore the block that is passed to `count`.
|
|
14
13
|
# Other methods, such as `select`, will convert the association to an
|
|
15
14
|
# array and then run the block on the array. A simple work around to
|
|
16
15
|
# make `count` work with a block is to call `to_a.count {...}`.
|
|
@@ -19,14 +18,14 @@ module RuboCop
|
|
|
19
18
|
#
|
|
20
19
|
# [source,ruby]
|
|
21
20
|
# ----
|
|
22
|
-
#
|
|
21
|
+
# Model.where(id: [1, 2, 3]).select { |m| m.method == true }.size
|
|
23
22
|
# ----
|
|
24
23
|
#
|
|
25
24
|
# becomes:
|
|
26
25
|
#
|
|
27
26
|
# [source,ruby]
|
|
28
27
|
# ----
|
|
29
|
-
#
|
|
28
|
+
# Model.where(id: [1, 2, 3]).to_a.count { |m| m.method == true }
|
|
30
29
|
# ----
|
|
31
30
|
#
|
|
32
31
|
# @example
|
|
@@ -55,8 +54,8 @@ module RuboCop
|
|
|
55
54
|
|
|
56
55
|
def_node_matcher :count_candidate?, <<~PATTERN
|
|
57
56
|
{
|
|
58
|
-
(
|
|
59
|
-
(
|
|
57
|
+
(call (block $(call _ ${:select :filter :find_all :reject}) ...) ${:count :length :size})
|
|
58
|
+
(call $(call _ ${:select :filter :find_all :reject} (:block_pass _)) ${:count :length :size})
|
|
60
59
|
}
|
|
61
60
|
PATTERN
|
|
62
61
|
|
|
@@ -73,6 +72,7 @@ module RuboCop
|
|
|
73
72
|
end
|
|
74
73
|
end
|
|
75
74
|
end
|
|
75
|
+
alias on_csend on_send
|
|
76
76
|
|
|
77
77
|
private
|
|
78
78
|
|
|
@@ -101,7 +101,7 @@ module RuboCop
|
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
def negate_reject(corrector, node)
|
|
104
|
-
if node.receiver.
|
|
104
|
+
if node.receiver.call_type?
|
|
105
105
|
negate_block_pass_reject(corrector, node)
|
|
106
106
|
else
|
|
107
107
|
negate_block_reject(corrector, node)
|
|
@@ -64,9 +64,10 @@ module RuboCop
|
|
|
64
64
|
}.freeze
|
|
65
65
|
|
|
66
66
|
def_node_matcher :delete_prefix_candidate?, <<~PATTERN
|
|
67
|
-
(
|
|
67
|
+
(call $!nil? ${:gsub :gsub! :sub :sub!} (regexp (str $#literal_at_start?) (regopt)) (str $_))
|
|
68
68
|
PATTERN
|
|
69
69
|
|
|
70
|
+
# rubocop:disable Metrics/AbcSize
|
|
70
71
|
def on_send(node)
|
|
71
72
|
return unless (receiver, bad_method, regexp_str, replace_string = delete_prefix_candidate?(node))
|
|
72
73
|
return unless replace_string.empty?
|
|
@@ -80,11 +81,13 @@ module RuboCop
|
|
|
80
81
|
regexp_str = interpret_string_escapes(regexp_str)
|
|
81
82
|
string_literal = to_string_literal(regexp_str)
|
|
82
83
|
|
|
83
|
-
new_code = "#{receiver.source}
|
|
84
|
+
new_code = "#{receiver.source}#{node.loc.dot.source}#{good_method}(#{string_literal})"
|
|
84
85
|
|
|
85
86
|
corrector.replace(node, new_code)
|
|
86
87
|
end
|
|
87
88
|
end
|
|
89
|
+
# rubocop:enable Metrics/AbcSize
|
|
90
|
+
alias on_csend on_send
|
|
88
91
|
end
|
|
89
92
|
end
|
|
90
93
|
end
|
|
@@ -64,9 +64,10 @@ module RuboCop
|
|
|
64
64
|
}.freeze
|
|
65
65
|
|
|
66
66
|
def_node_matcher :delete_suffix_candidate?, <<~PATTERN
|
|
67
|
-
(
|
|
67
|
+
(call $!nil? ${:gsub :gsub! :sub :sub!} (regexp (str $#literal_at_end?) (regopt)) (str $_))
|
|
68
68
|
PATTERN
|
|
69
69
|
|
|
70
|
+
# rubocop:disable Metrics/AbcSize
|
|
70
71
|
def on_send(node)
|
|
71
72
|
return unless (receiver, bad_method, regexp_str, replace_string = delete_suffix_candidate?(node))
|
|
72
73
|
return unless replace_string.empty?
|
|
@@ -80,11 +81,13 @@ module RuboCop
|
|
|
80
81
|
regexp_str = interpret_string_escapes(regexp_str)
|
|
81
82
|
string_literal = to_string_literal(regexp_str)
|
|
82
83
|
|
|
83
|
-
new_code = "#{receiver.source}
|
|
84
|
+
new_code = "#{receiver.source}#{node.loc.dot.source}#{good_method}(#{string_literal})"
|
|
84
85
|
|
|
85
86
|
corrector.replace(node, new_code)
|
|
86
87
|
end
|
|
87
88
|
end
|
|
89
|
+
# rubocop:enable Metrics/AbcSize
|
|
90
|
+
alias on_csend on_send
|
|
88
91
|
end
|
|
89
92
|
end
|
|
90
93
|
end
|
|
@@ -40,9 +40,9 @@ module RuboCop
|
|
|
40
40
|
|
|
41
41
|
def_node_matcher :detect_candidate?, <<~PATTERN
|
|
42
42
|
{
|
|
43
|
-
(send $(block (
|
|
43
|
+
(send $(block (call _ %CANDIDATE_METHODS) ...) ${:first :last} $...)
|
|
44
44
|
(send $(block (send _ %CANDIDATE_METHODS) ...) $:[] (int ${0 -1}))
|
|
45
|
-
(send $(
|
|
45
|
+
(send $(call _ %CANDIDATE_METHODS ...) ${:first :last} $...)
|
|
46
46
|
(send $(send _ %CANDIDATE_METHODS ...) $:[] (int ${0 -1}))
|
|
47
47
|
}
|
|
48
48
|
PATTERN
|
|
@@ -63,6 +63,7 @@ module RuboCop
|
|
|
63
63
|
register_offense(node, receiver, second_method, index)
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
|
+
alias on_csend on_send
|
|
66
67
|
|
|
67
68
|
private
|
|
68
69
|
|
|
@@ -41,7 +41,7 @@ module RuboCop
|
|
|
41
41
|
class DoubleStartEndWith < Base
|
|
42
42
|
extend AutoCorrector
|
|
43
43
|
|
|
44
|
-
MSG = 'Use `%<
|
|
44
|
+
MSG = 'Use `%<replacement>s` instead of `%<original_code>s`.'
|
|
45
45
|
|
|
46
46
|
def on_or(node)
|
|
47
47
|
receiver, method, first_call_args, second_call_args = process_source(node)
|
|
@@ -50,7 +50,7 @@ module RuboCop
|
|
|
50
50
|
|
|
51
51
|
combined_args = combine_args(first_call_args, second_call_args)
|
|
52
52
|
|
|
53
|
-
add_offense(node, message: message(node, receiver, method, combined_args)) do |corrector|
|
|
53
|
+
add_offense(node, message: message(node, receiver, first_call_args, method, combined_args)) do |corrector|
|
|
54
54
|
autocorrect(corrector, first_call_args, second_call_args, combined_args)
|
|
55
55
|
end
|
|
56
56
|
end
|
|
@@ -73,10 +73,10 @@ module RuboCop
|
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
def message(node, receiver, method, combined_args)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
)
|
|
76
|
+
def message(node, receiver, first_call_args, method, combined_args)
|
|
77
|
+
dot = first_call_args.first.parent.send_type? ? '.' : '&.'
|
|
78
|
+
replacement = "#{receiver.source}#{dot}#{method}(#{combined_args})"
|
|
79
|
+
format(MSG, replacement: replacement, original_code: node.source)
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
def combine_args(first_call_args, second_call_args)
|
|
@@ -89,16 +89,16 @@ module RuboCop
|
|
|
89
89
|
|
|
90
90
|
def_node_matcher :two_start_end_with_calls, <<~PATTERN
|
|
91
91
|
(or
|
|
92
|
-
(
|
|
93
|
-
(
|
|
92
|
+
(call $_recv [{:start_with? :end_with?} $_method] $...)
|
|
93
|
+
(call _recv _method $...))
|
|
94
94
|
PATTERN
|
|
95
95
|
|
|
96
96
|
def_node_matcher :check_with_active_support_aliases, <<~PATTERN
|
|
97
97
|
(or
|
|
98
|
-
(
|
|
98
|
+
(call $_recv
|
|
99
99
|
[{:start_with? :starts_with? :end_with? :ends_with?} $_method]
|
|
100
100
|
$...)
|
|
101
|
-
(
|
|
101
|
+
(call _recv _method $...))
|
|
102
102
|
PATTERN
|
|
103
103
|
end
|
|
104
104
|
end
|
|
@@ -54,9 +54,10 @@ module RuboCop
|
|
|
54
54
|
RESTRICT_ON_SEND = %i[match =~ match?].freeze
|
|
55
55
|
|
|
56
56
|
def_node_matcher :redundant_regex?, <<~PATTERN
|
|
57
|
-
{(
|
|
57
|
+
{(call $!nil? {:match :=~ :match?} (regexp (str $#literal_at_end?) (regopt)))
|
|
58
58
|
(send (regexp (str $#literal_at_end?) (regopt)) {:match :match?} $_)
|
|
59
|
-
(match-with-lvasgn (regexp (str $#literal_at_end?) (regopt)) $_)
|
|
59
|
+
({send match-with-lvasgn} (regexp (str $#literal_at_end?) (regopt)) $_)
|
|
60
|
+
(send (regexp (str $#literal_at_end?) (regopt)) :=~ $_)}
|
|
60
61
|
PATTERN
|
|
61
62
|
|
|
62
63
|
def on_send(node)
|
|
@@ -66,12 +67,14 @@ module RuboCop
|
|
|
66
67
|
receiver, regex_str = regex_str, receiver if receiver.is_a?(String)
|
|
67
68
|
regex_str = drop_end_metacharacter(regex_str)
|
|
68
69
|
regex_str = interpret_string_escapes(regex_str)
|
|
70
|
+
dot = node.loc.dot ? node.loc.dot.source : '.'
|
|
69
71
|
|
|
70
|
-
new_source = "#{receiver.source}
|
|
72
|
+
new_source = "#{receiver.source}#{dot}end_with?(#{to_string_literal(regex_str)})"
|
|
71
73
|
|
|
72
74
|
corrector.replace(node, new_source)
|
|
73
75
|
end
|
|
74
76
|
end
|
|
77
|
+
alias on_csend on_send
|
|
75
78
|
alias on_match_with_lvasgn on_send
|
|
76
79
|
end
|
|
77
80
|
end
|