rubocop-performance 1.5.2 → 1.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +5 -1
- data/config/default.yml +96 -13
- data/lib/rubocop/cop/mixin/regexp_metacharacter.rb +76 -0
- data/lib/rubocop/cop/mixin/sort_block.rb +28 -0
- data/lib/rubocop/cop/performance/ancestors_include.rb +48 -0
- data/lib/rubocop/cop/performance/big_decimal_with_numeric_argument.rb +45 -0
- data/lib/rubocop/cop/performance/bind_call.rb +77 -0
- data/lib/rubocop/cop/performance/caller.rb +5 -4
- data/lib/rubocop/cop/performance/case_when_splat.rb +18 -11
- data/lib/rubocop/cop/performance/casecmp.rb +17 -23
- data/lib/rubocop/cop/performance/chain_array_allocation.rb +5 -11
- data/lib/rubocop/cop/performance/collection_literal_in_loop.rb +140 -0
- data/lib/rubocop/cop/performance/compare_with_block.rb +12 -23
- data/lib/rubocop/cop/performance/count.rb +14 -17
- data/lib/rubocop/cop/performance/delete_prefix.rb +87 -0
- data/lib/rubocop/cop/performance/delete_suffix.rb +87 -0
- data/lib/rubocop/cop/performance/detect.rb +64 -32
- data/lib/rubocop/cop/performance/double_start_end_with.rb +18 -26
- data/lib/rubocop/cop/performance/end_with.rb +38 -25
- data/lib/rubocop/cop/performance/fixed_size.rb +2 -2
- data/lib/rubocop/cop/performance/flat_map.rb +21 -23
- data/lib/rubocop/cop/performance/inefficient_hash_search.rb +14 -15
- data/lib/rubocop/cop/performance/io_readlines.rb +116 -0
- data/lib/rubocop/cop/performance/open_struct.rb +3 -3
- data/lib/rubocop/cop/performance/range_include.rb +15 -12
- data/lib/rubocop/cop/performance/redundant_block_call.rb +14 -9
- data/lib/rubocop/cop/performance/redundant_match.rb +13 -8
- data/lib/rubocop/cop/performance/redundant_merge.rb +36 -23
- data/lib/rubocop/cop/performance/redundant_sort_block.rb +43 -0
- data/lib/rubocop/cop/performance/redundant_string_chars.rb +133 -0
- data/lib/rubocop/cop/performance/regexp_match.rb +32 -32
- data/lib/rubocop/cop/performance/reverse_each.rb +10 -5
- data/lib/rubocop/cop/performance/reverse_first.rb +72 -0
- data/lib/rubocop/cop/performance/size.rb +41 -43
- data/lib/rubocop/cop/performance/sort_reverse.rb +45 -0
- data/lib/rubocop/cop/performance/squeeze.rb +66 -0
- data/lib/rubocop/cop/performance/start_with.rb +38 -28
- data/lib/rubocop/cop/performance/string_include.rb +55 -0
- data/lib/rubocop/cop/performance/string_replacement.rb +25 -36
- data/lib/rubocop/cop/performance/sum.rb +134 -0
- data/lib/rubocop/cop/performance/times_map.rb +12 -19
- data/lib/rubocop/cop/performance/unfreeze_string.rb +4 -8
- data/lib/rubocop/cop/performance/uri_default_parser.rb +7 -13
- data/lib/rubocop/cop/performance_cops.rb +17 -0
- data/lib/rubocop/performance/inject.rb +1 -1
- data/lib/rubocop/performance/version.rb +1 -1
- metadata +41 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f1f4841e8542a1f77f21d30ffe7c26019b9f2fb7308a985780506f1920146045
|
4
|
+
data.tar.gz: ed95379cd20af662ce6ce9ce4e64721ca156a6d7b62e511774df9d6abe3c9bae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10a1e89448abd75234807bbdd9be67b10e4b9a837d2d2d711adeb0a0d105b921d722dfcac0c46e30f55f278afc2960f888407959543097d81df4f1aa3667fac6
|
7
|
+
data.tar.gz: 668784bfe08775a1e8917806ef9f34d7dcb3f7581a9080ea14a44a54b43cf7e6516db4f5c4e015718824c32a8b045f43b429c8e1d3864960f41ead8684fbb5f5
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -16,7 +16,7 @@ gem install rubocop-performance
|
|
16
16
|
or if you use bundler put this in your `Gemfile`
|
17
17
|
|
18
18
|
```ruby
|
19
|
-
gem 'rubocop-performance'
|
19
|
+
gem 'rubocop-performance', require: false
|
20
20
|
```
|
21
21
|
|
22
22
|
## Usage
|
@@ -72,6 +72,10 @@ Performance/Size:
|
|
72
72
|
- lib/example.rb
|
73
73
|
```
|
74
74
|
|
75
|
+
## Documentation
|
76
|
+
|
77
|
+
You can read a lot more about RuboCop Performance in its [official docs](https://docs.rubocop.org/rubocop-performance/).
|
78
|
+
|
75
79
|
## Contributing
|
76
80
|
|
77
81
|
Checkout the [contribution guidelines](CONTRIBUTING.md).
|
data/config/default.yml
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
# This is the default configuration file.
|
2
2
|
|
3
|
+
Performance/AncestorsInclude:
|
4
|
+
Description: 'Use `A <= B` instead of `A.ancestors.include?(B)`.'
|
5
|
+
Reference: 'https://github.com/JuanitoFatas/fast-ruby#ancestorsinclude-vs--code'
|
6
|
+
Enabled: 'pending'
|
7
|
+
Safe: false
|
8
|
+
VersionAdded: '1.7'
|
9
|
+
|
10
|
+
Performance/BigDecimalWithNumericArgument:
|
11
|
+
Description: 'Convert numeric argument to string before passing to BigDecimal.'
|
12
|
+
Enabled: 'pending'
|
13
|
+
VersionAdded: '1.7'
|
14
|
+
|
15
|
+
Performance/BindCall:
|
16
|
+
Description: 'Use `bind_call(obj, args, ...)` instead of `bind(obj).call(args, ...)`.'
|
17
|
+
Enabled: true
|
18
|
+
VersionAdded: '1.6'
|
19
|
+
|
3
20
|
Performance/Caller:
|
4
21
|
Description: >-
|
5
22
|
Use `caller(n..n)` instead of `caller`.
|
@@ -21,6 +38,7 @@ Performance/Casecmp:
|
|
21
38
|
Use `casecmp` rather than `downcase ==`, `upcase ==`, `== downcase`, or `== upcase`..
|
22
39
|
Reference: 'https://github.com/JuanitoFatas/fast-ruby#stringcasecmp-vs-stringdowncase---code'
|
23
40
|
Enabled: true
|
41
|
+
Safe: false
|
24
42
|
VersionAdded: '0.36'
|
25
43
|
|
26
44
|
Performance/ChainArrayAllocation:
|
@@ -31,6 +49,13 @@ Performance/ChainArrayAllocation:
|
|
31
49
|
Enabled: false
|
32
50
|
VersionAdded: '0.59'
|
33
51
|
|
52
|
+
Performance/CollectionLiteralInLoop:
|
53
|
+
Description: 'Extract Array and Hash literals outside of loops into local variables or constants.'
|
54
|
+
Enabled: true
|
55
|
+
VersionAdded: '1.8'
|
56
|
+
# Min number of elements to consider an offense
|
57
|
+
MinSize: 1
|
58
|
+
|
34
59
|
Performance/CompareWithBlock:
|
35
60
|
Description: 'Use `sort_by(&:foo)` instead of `sort { |a, b| a.foo <=> b.foo }`.'
|
36
61
|
Enabled: true
|
@@ -38,21 +63,31 @@ Performance/CompareWithBlock:
|
|
38
63
|
|
39
64
|
Performance/Count:
|
40
65
|
Description: >-
|
41
|
-
Use `count` instead of `select
|
42
|
-
`select...count`, `reject...count`, `select...length`,
|
43
|
-
and `reject...length`.
|
66
|
+
Use `count` instead of `{select,find_all,filter,reject}...{size,count,length}`.
|
44
67
|
# This cop has known compatibility issues with `ActiveRecord` and other
|
45
68
|
# frameworks. ActiveRecord's `count` ignores the block that is passed to it.
|
46
69
|
# For more information, see the documentation in the cop itself.
|
47
70
|
SafeAutoCorrect: false
|
48
71
|
Enabled: true
|
49
72
|
VersionAdded: '0.31'
|
50
|
-
VersionChanged: '1.
|
73
|
+
VersionChanged: '1.8'
|
74
|
+
|
75
|
+
Performance/DeletePrefix:
|
76
|
+
Description: 'Use `delete_prefix` instead of `gsub`.'
|
77
|
+
Enabled: true
|
78
|
+
SafeMultiline: true
|
79
|
+
VersionAdded: '1.6'
|
80
|
+
|
81
|
+
Performance/DeleteSuffix:
|
82
|
+
Description: 'Use `delete_suffix` instead of `gsub`.'
|
83
|
+
Enabled: true
|
84
|
+
SafeMultiline: true
|
85
|
+
VersionAdded: '1.6'
|
51
86
|
|
52
87
|
Performance/Detect:
|
53
88
|
Description: >-
|
54
|
-
Use `detect` instead of `select.first`, `find_all.first`,
|
55
|
-
`select.last`, and `
|
89
|
+
Use `detect` instead of `select.first`, `find_all.first`, `filter.first`,
|
90
|
+
`select.last`, `find_all.last`, and `filter.last`.
|
56
91
|
Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerabledetect-vs-enumerableselectfirst-code'
|
57
92
|
# This cop has known compatibility issues with `ActiveRecord` and other
|
58
93
|
# frameworks. `ActiveRecord` does not implement a `detect` method and `find`
|
@@ -61,7 +96,7 @@ Performance/Detect:
|
|
61
96
|
SafeAutoCorrect: false
|
62
97
|
Enabled: true
|
63
98
|
VersionAdded: '0.30'
|
64
|
-
VersionChanged: '1.
|
99
|
+
VersionChanged: '1.8'
|
65
100
|
|
66
101
|
Performance/DoubleStartEndWith:
|
67
102
|
Description: >-
|
@@ -83,11 +118,12 @@ Performance/EndWith:
|
|
83
118
|
SafeAutoCorrect: false
|
84
119
|
AutoCorrect: false
|
85
120
|
Enabled: true
|
121
|
+
SafeMultiline: true
|
86
122
|
VersionAdded: '0.36'
|
87
|
-
VersionChanged: '
|
123
|
+
VersionChanged: '1.6'
|
88
124
|
|
89
125
|
Performance/FixedSize:
|
90
|
-
Description: 'Do not compute the size of statically sized objects except in constants'
|
126
|
+
Description: 'Do not compute the size of statically sized objects except in constants.'
|
91
127
|
Enabled: true
|
92
128
|
VersionAdded: '0.35'
|
93
129
|
|
@@ -95,7 +131,7 @@ Performance/FlatMap:
|
|
95
131
|
Description: >-
|
96
132
|
Use `Enumerable#flat_map`
|
97
133
|
instead of `Enumerable#map...Array#flatten(1)`
|
98
|
-
or `Enumberable#collect..Array#flatten(1)
|
134
|
+
or `Enumberable#collect..Array#flatten(1)`.
|
99
135
|
Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerablemaparrayflatten-vs-enumerableflat_map-code'
|
100
136
|
Enabled: true
|
101
137
|
VersionAdded: '0.30'
|
@@ -106,12 +142,18 @@ Performance/FlatMap:
|
|
106
142
|
# `flatten` without any parameters can flatten multiple levels.
|
107
143
|
|
108
144
|
Performance/InefficientHashSearch:
|
109
|
-
Description: 'Use `key?` or `value?` instead of `keys.include?` or `values.include
|
145
|
+
Description: 'Use `key?` or `value?` instead of `keys.include?` or `values.include?`.'
|
110
146
|
Reference: 'https://github.com/JuanitoFatas/fast-ruby#hashkey-instead-of-hashkeysinclude-code'
|
111
147
|
Enabled: true
|
112
148
|
VersionAdded: '0.56'
|
113
149
|
Safe: false
|
114
150
|
|
151
|
+
Performance/IoReadlines:
|
152
|
+
Description: 'Use `IO.each_line` (`IO#each_line`) instead of `IO.readlines` (`IO#readlines`).'
|
153
|
+
Reference: 'https://docs.gitlab.com/ee/development/performance.html#reading-from-files-and-other-data-sources'
|
154
|
+
Enabled: false
|
155
|
+
VersionAdded: '1.7'
|
156
|
+
|
115
157
|
Performance/OpenStruct:
|
116
158
|
Description: 'Use `Struct` instead of `OpenStruct`.'
|
117
159
|
Enabled: false
|
@@ -119,10 +161,11 @@ Performance/OpenStruct:
|
|
119
161
|
Safe: false
|
120
162
|
|
121
163
|
Performance/RangeInclude:
|
122
|
-
Description: 'Use `Range#cover?` instead of `Range#include
|
164
|
+
Description: 'Use `Range#cover?` instead of `Range#include?` (or `Range#member?`).'
|
123
165
|
Reference: 'https://github.com/JuanitoFatas/fast-ruby#cover-vs-include-code'
|
124
166
|
Enabled: true
|
125
167
|
VersionAdded: '0.36'
|
168
|
+
VersionChanged: '1.7'
|
126
169
|
Safe: false
|
127
170
|
|
128
171
|
Performance/RedundantBlockCall:
|
@@ -146,6 +189,16 @@ Performance/RedundantMerge:
|
|
146
189
|
# Max number of key-value pairs to consider an offense
|
147
190
|
MaxKeyValuePairs: 2
|
148
191
|
|
192
|
+
Performance/RedundantSortBlock:
|
193
|
+
Description: 'Use `sort` instead of `sort { |a, b| a <=> b }`.'
|
194
|
+
Enabled: 'pending'
|
195
|
+
VersionAdded: '1.7'
|
196
|
+
|
197
|
+
Performance/RedundantStringChars:
|
198
|
+
Description: 'Checks for redundant `String#chars`.'
|
199
|
+
Enabled: 'pending'
|
200
|
+
VersionAdded: '1.7'
|
201
|
+
|
149
202
|
Performance/RegexpMatch:
|
150
203
|
Description: >-
|
151
204
|
Use `match?` instead of `Regexp#match`, `String#match`, `Symbol#match`,
|
@@ -160,6 +213,11 @@ Performance/ReverseEach:
|
|
160
213
|
Enabled: true
|
161
214
|
VersionAdded: '0.30'
|
162
215
|
|
216
|
+
Performance/ReverseFirst:
|
217
|
+
Description: 'Use `last(n).reverse` instead of `reverse.first(n)`.'
|
218
|
+
Enabled: 'pending'
|
219
|
+
VersionAdded: '1.7'
|
220
|
+
|
163
221
|
Performance/Size:
|
164
222
|
Description: >-
|
165
223
|
Use `size` instead of `count` for counting
|
@@ -168,6 +226,17 @@ Performance/Size:
|
|
168
226
|
Enabled: true
|
169
227
|
VersionAdded: '0.30'
|
170
228
|
|
229
|
+
Performance/SortReverse:
|
230
|
+
Description: 'Use `sort.reverse` instead of `sort { |a, b| b <=> a }`.'
|
231
|
+
Enabled: 'pending'
|
232
|
+
VersionAdded: '1.7'
|
233
|
+
|
234
|
+
Performance/Squeeze:
|
235
|
+
Description: "Use `squeeze('a')` instead of `gsub(/a+/, 'a')`."
|
236
|
+
Reference: 'https://github.com/JuanitoFatas/fast-ruby#remove-extra-spaces-or-other-contiguous-characters-code'
|
237
|
+
Enabled: 'pending'
|
238
|
+
VersionAdded: '1.7'
|
239
|
+
|
171
240
|
Performance/StartWith:
|
172
241
|
Description: 'Use `start_with?` instead of a regex match anchored to the beginning of a string.'
|
173
242
|
Reference: 'https://github.com/JuanitoFatas/fast-ruby#stringmatch-vs-stringstart_withstringend_with-code-start-code-end'
|
@@ -177,8 +246,16 @@ Performance/StartWith:
|
|
177
246
|
SafeAutoCorrect: false
|
178
247
|
AutoCorrect: false
|
179
248
|
Enabled: true
|
249
|
+
SafeMultiline: true
|
180
250
|
VersionAdded: '0.36'
|
181
|
-
VersionChanged: '
|
251
|
+
VersionChanged: '1.6'
|
252
|
+
|
253
|
+
Performance/StringInclude:
|
254
|
+
Description: 'Use `String#include?` instead of a regex match with literal-only pattern.'
|
255
|
+
Enabled: 'pending'
|
256
|
+
AutoCorrect: false
|
257
|
+
SafeAutoCorrect: false
|
258
|
+
VersionAdded: '1.7'
|
182
259
|
|
183
260
|
Performance/StringReplacement:
|
184
261
|
Description: >-
|
@@ -189,6 +266,12 @@ Performance/StringReplacement:
|
|
189
266
|
Enabled: true
|
190
267
|
VersionAdded: '0.33'
|
191
268
|
|
269
|
+
Performance/Sum:
|
270
|
+
Description: 'Use `sum` instead of a custom array summation.'
|
271
|
+
Reference: 'https://blog.bigbinary.com/2016/11/02/ruby-2-4-introduces-enumerable-sum.html'
|
272
|
+
Enabled: 'pending'
|
273
|
+
VersionAdded: '1.8'
|
274
|
+
|
192
275
|
Performance/TimesMap:
|
193
276
|
Description: 'Checks for .times.map calls.'
|
194
277
|
AutoCorrect: false
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Common functionality for handling regexp metacharacters.
|
6
|
+
module RegexpMetacharacter
|
7
|
+
private
|
8
|
+
|
9
|
+
def literal_at_start?(regexp)
|
10
|
+
return true if literal_at_start_with_backslash_a?(regexp)
|
11
|
+
|
12
|
+
!safe_multiline? && literal_at_start_with_caret?(regexp)
|
13
|
+
end
|
14
|
+
|
15
|
+
def literal_at_end?(regexp)
|
16
|
+
return true if literal_at_end_with_backslash_z?(regexp)
|
17
|
+
|
18
|
+
!safe_multiline? && literal_at_end_with_dollar?(regexp)
|
19
|
+
end
|
20
|
+
|
21
|
+
def literal_at_start_with_backslash_a?(regex_str)
|
22
|
+
# is this regexp 'literal' in the sense of only matching literal
|
23
|
+
# chars, rather than using metachars like `.` and `*` and so on?
|
24
|
+
# also, is it anchored at the start of the string?
|
25
|
+
# (tricky: \s, \d, and so on are metacharacters, but other characters
|
26
|
+
# escaped with a slash are just literals. LITERAL_REGEX takes all
|
27
|
+
# that into account.)
|
28
|
+
/\A\\A(?:#{Util::LITERAL_REGEX})+\z/.match?(regex_str)
|
29
|
+
end
|
30
|
+
|
31
|
+
def literal_at_start_with_caret?(regex_str)
|
32
|
+
# is this regexp 'literal' in the sense of only matching literal
|
33
|
+
# chars, rather than using metachars like `.` and `*` and so on?
|
34
|
+
# also, is it anchored at the start of the string?
|
35
|
+
# (tricky: \s, \d, and so on are metacharacters, but other characters
|
36
|
+
# escaped with a slash are just literals. LITERAL_REGEX takes all
|
37
|
+
# that into account.)
|
38
|
+
/\A\^(?:#{Util::LITERAL_REGEX})+\z/.match?(regex_str)
|
39
|
+
end
|
40
|
+
|
41
|
+
def literal_at_end_with_backslash_z?(regex_str)
|
42
|
+
# is this regexp 'literal' in the sense of only matching literal
|
43
|
+
# chars, rather than using metachars like . and * and so on?
|
44
|
+
# also, is it anchored at the end of the string?
|
45
|
+
/\A(?:#{Util::LITERAL_REGEX})+\\z\z/.match?(regex_str)
|
46
|
+
end
|
47
|
+
|
48
|
+
def literal_at_end_with_dollar?(regex_str)
|
49
|
+
# is this regexp 'literal' in the sense of only matching literal
|
50
|
+
# chars, rather than using metachars like . and * and so on?
|
51
|
+
# also, is it anchored at the end of the string?
|
52
|
+
/\A(?:#{Util::LITERAL_REGEX})+\$\z/.match?(regex_str)
|
53
|
+
end
|
54
|
+
|
55
|
+
def drop_start_metacharacter(regexp_string)
|
56
|
+
if regexp_string.start_with?('\\A')
|
57
|
+
regexp_string[2..-1] # drop `\A` anchor
|
58
|
+
else
|
59
|
+
regexp_string[1..-1] # drop `^` anchor
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def drop_end_metacharacter(regexp_string)
|
64
|
+
if regexp_string.end_with?('\\z')
|
65
|
+
regexp_string.chomp('\z') # drop `\z` anchor
|
66
|
+
else
|
67
|
+
regexp_string.chop # drop `$` anchor
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def safe_multiline?
|
72
|
+
cop_config.fetch('SafeMultiline', true)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Common functionality for cops checking `Enumerable#sort` blocks.
|
6
|
+
module SortBlock
|
7
|
+
extend NodePattern::Macros
|
8
|
+
include RangeHelp
|
9
|
+
|
10
|
+
def_node_matcher :sort_with_block?, <<~PATTERN
|
11
|
+
(block
|
12
|
+
$(send _ :sort)
|
13
|
+
(args (arg $_a) (arg $_b))
|
14
|
+
$send)
|
15
|
+
PATTERN
|
16
|
+
|
17
|
+
def_node_matcher :replaceable_body?, <<~PATTERN
|
18
|
+
(send (lvar %1) :<=> (lvar %2))
|
19
|
+
PATTERN
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def sort_range(send, node)
|
24
|
+
range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Performance
|
6
|
+
# This cop is used to identify usages of `ancestors.include?` and
|
7
|
+
# change them to use `<=` instead.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# A.ancestors.include?(B)
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# A <= B
|
15
|
+
#
|
16
|
+
class AncestorsInclude < Base
|
17
|
+
include RangeHelp
|
18
|
+
extend AutoCorrector
|
19
|
+
|
20
|
+
MSG = 'Use `<=` instead of `ancestors.include?`.'
|
21
|
+
|
22
|
+
def_node_matcher :ancestors_include_candidate?, <<~PATTERN
|
23
|
+
(send (send $_subclass :ancestors) :include? $_superclass)
|
24
|
+
PATTERN
|
25
|
+
|
26
|
+
def on_send(node)
|
27
|
+
return unless (subclass, superclass = ancestors_include_candidate?(node))
|
28
|
+
return if subclass && !subclass.const_type?
|
29
|
+
|
30
|
+
add_offense(range(node)) do |corrector|
|
31
|
+
subclass_source = subclass ? subclass.source : 'self'
|
32
|
+
|
33
|
+
corrector.replace(node, "#{subclass_source} <= #{superclass.source}")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def range(node)
|
40
|
+
location_of_ancestors = node.children[0].loc.selector.begin_pos
|
41
|
+
end_location = node.loc.selector.end_pos
|
42
|
+
|
43
|
+
range_between(location_of_ancestors, end_location)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Performance
|
6
|
+
# This cop identifies places where numeric argument to BigDecimal should be
|
7
|
+
# converted to string. Initializing from String is faster
|
8
|
+
# than from Numeric for BigDecimal.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # bad
|
12
|
+
# BigDecimal(1, 2)
|
13
|
+
# BigDecimal(1.2, 3, exception: true)
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# BigDecimal('1', 2)
|
17
|
+
# BigDecimal('1.2', 3, exception: true)
|
18
|
+
#
|
19
|
+
class BigDecimalWithNumericArgument < Base
|
20
|
+
extend AutoCorrector
|
21
|
+
|
22
|
+
MSG = 'Convert numeric argument to string before passing to `BigDecimal`.'
|
23
|
+
|
24
|
+
def_node_matcher :big_decimal_with_numeric_argument?, <<~PATTERN
|
25
|
+
(send nil? :BigDecimal $numeric_type? ...)
|
26
|
+
PATTERN
|
27
|
+
|
28
|
+
def on_send(node)
|
29
|
+
return unless (numeric = big_decimal_with_numeric_argument?(node))
|
30
|
+
return if numeric.float_type? && specifies_precision?(node)
|
31
|
+
|
32
|
+
add_offense(numeric.source_range) do |corrector|
|
33
|
+
corrector.wrap(numeric, "'", "'")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def specifies_precision?(node)
|
40
|
+
node.arguments.size > 1 && !node.arguments[1].hash_type?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|