rubocop-performance 1.16.0 → 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/README.md +2 -2
- data/config/default.yml +7 -0
- data/lib/rubocop/cop/performance/array_semi_infinite_range_slice.rb +2 -1
- data/lib/rubocop/cop/performance/case_when_splat.rb +2 -2
- data/lib/rubocop/cop/performance/compare_with_block.rb +19 -10
- data/lib/rubocop/cop/performance/constant_regexp.rb +4 -0
- data/lib/rubocop/cop/performance/count.rb +1 -1
- 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 +6 -8
- data/lib/rubocop/cop/performance/double_start_end_with.rb +2 -2
- data/lib/rubocop/cop/performance/end_with.rb +5 -3
- data/lib/rubocop/cop/performance/fixed_size.rb +2 -2
- data/lib/rubocop/cop/performance/flat_map.rb +6 -4
- data/lib/rubocop/cop/performance/inefficient_hash_search.rb +15 -9
- data/lib/rubocop/cop/performance/io_readlines.rb +1 -1
- data/lib/rubocop/cop/performance/map_compact.rb +3 -2
- data/lib/rubocop/cop/performance/map_method_chain.rb +87 -0
- data/lib/rubocop/cop/performance/redundant_block_call.rb +1 -1
- data/lib/rubocop/cop/performance/redundant_equality_comparison_block.rb +34 -2
- data/lib/rubocop/cop/performance/redundant_match.rb +1 -1
- data/lib/rubocop/cop/performance/redundant_merge.rb +4 -4
- data/lib/rubocop/cop/performance/redundant_split_regexp_argument.rb +2 -1
- data/lib/rubocop/cop/performance/redundant_string_chars.rb +2 -2
- data/lib/rubocop/cop/performance/regexp_match.rb +16 -12
- data/lib/rubocop/cop/performance/reverse_each.rb +2 -1
- data/lib/rubocop/cop/performance/reverse_first.rb +3 -2
- data/lib/rubocop/cop/performance/select_map.rb +2 -1
- data/lib/rubocop/cop/performance/squeeze.rb +6 -3
- data/lib/rubocop/cop/performance/start_with.rb +5 -3
- data/lib/rubocop/cop/performance/string_identifier_argument.rb +15 -10
- data/lib/rubocop/cop/performance/string_include.rb +7 -3
- data/lib/rubocop/cop/performance/string_replacement.rb +3 -2
- data/lib/rubocop/cop/performance/sum.rb +1 -1
- data/lib/rubocop/cop/performance/times_map.rb +1 -1
- data/lib/rubocop/cop/performance/uri_default_parser.rb +2 -2
- data/lib/rubocop/cop/performance_cops.rb +1 -0
- data/lib/rubocop/performance/version.rb +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06f3e8346dc7f9be72a1f18c62a25dc02aeac41debcfe3c58df68e2a6904df43
|
4
|
+
data.tar.gz: f01facdb92a3056d05990e2ed2b6b1920de0501edf53a08e95e08620651c8557
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 07eb541698b6ccf2985ef62392bd78703bf6607e2877ef3865ab1762d62910c4c346fbb7e9bc48af7b7d98b0e1ad22e8c79ea2425555fbe75c2a5e614837eaa7
|
7
|
+
data.tar.gz: 60fc9f900906cca518d0da62170f71ae6e5f5ffd44f4c1cbe75af83f9a1fef252b6bab95d3af4f49f328d4a856cd17c7f47621ee62575ab282eacfd26dc09841
|
data/README.md
CHANGED
@@ -11,7 +11,7 @@ Performance optimization analysis for your projects, as an extension to [RuboCop
|
|
11
11
|
Just install the `rubocop-performance` gem
|
12
12
|
|
13
13
|
```sh
|
14
|
-
gem install rubocop-performance
|
14
|
+
$ gem install rubocop-performance
|
15
15
|
```
|
16
16
|
|
17
17
|
or if you use bundler put this in your `Gemfile`
|
@@ -47,7 +47,7 @@ cops together with the standard cops.
|
|
47
47
|
### Command line
|
48
48
|
|
49
49
|
```sh
|
50
|
-
rubocop --require rubocop-performance
|
50
|
+
$ rubocop --require rubocop-performance
|
51
51
|
```
|
52
52
|
|
53
53
|
### Rake task
|
data/config/default.yml
CHANGED
@@ -193,6 +193,12 @@ Performance/MapCompact:
|
|
193
193
|
SafeAutoCorrect: false
|
194
194
|
VersionAdded: '1.11'
|
195
195
|
|
196
|
+
Performance/MapMethodChain:
|
197
|
+
Description: 'Checks if the `map` method is used in a chain.'
|
198
|
+
Enabled: pending
|
199
|
+
Safe: false
|
200
|
+
VersionAdded: '1.19'
|
201
|
+
|
196
202
|
Performance/MethodObjectAsBlock:
|
197
203
|
Description: 'Use block explicitly instead of block-passing a method object.'
|
198
204
|
Reference: 'https://github.com/JuanitoFatas/fast-ruby#normal-way-to-apply-method-vs-method-code'
|
@@ -226,6 +232,7 @@ Performance/RedundantEqualityComparisonBlock:
|
|
226
232
|
Reference: 'https://github.com/rails/rails/pull/41363'
|
227
233
|
Enabled: pending
|
228
234
|
Safe: false
|
235
|
+
AllowRegexpMatch: true
|
229
236
|
VersionAdded: '1.10'
|
230
237
|
|
231
238
|
Performance/RedundantMatch:
|
@@ -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 $_ $%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
|
|
@@ -99,7 +99,7 @@ module RuboCop
|
|
99
99
|
|
100
100
|
def inline_fix_branch(corrector, when_node)
|
101
101
|
conditions = when_node.conditions
|
102
|
-
range = range_between(conditions[0].
|
102
|
+
range = range_between(conditions[0].source_range.begin_pos, conditions[-1].source_range.end_pos)
|
103
103
|
|
104
104
|
corrector.replace(range, replacement(conditions))
|
105
105
|
end
|
@@ -110,7 +110,7 @@ module RuboCop
|
|
110
110
|
return if when_branches.one?
|
111
111
|
|
112
112
|
corrector.remove(when_branch_range(when_node))
|
113
|
-
corrector.insert_after(when_branches.last
|
113
|
+
corrector.insert_after(when_branches.last, reordering_correction(when_node))
|
114
114
|
end
|
115
115
|
|
116
116
|
def reordering_correction(when_node)
|
@@ -5,35 +5,42 @@ module RuboCop
|
|
5
5
|
module Performance
|
6
6
|
# Identifies places where `sort { |a, b| a.foo <=> b.foo }`
|
7
7
|
# can be replaced by `sort_by(&:foo)`.
|
8
|
-
# This cop also checks `max` and `
|
8
|
+
# This cop also checks `sort!`, `min`, `max` and `minmax` methods.
|
9
9
|
#
|
10
10
|
# @example
|
11
11
|
# # bad
|
12
|
-
# array.sort
|
13
|
-
# array.
|
14
|
-
# array.
|
15
|
-
# array.
|
12
|
+
# array.sort { |a, b| a.foo <=> b.foo }
|
13
|
+
# array.sort! { |a, b| a.foo <=> b.foo }
|
14
|
+
# array.max { |a, b| a.foo <=> b.foo }
|
15
|
+
# array.min { |a, b| a.foo <=> b.foo }
|
16
|
+
# array.minmax { |a, b| a.foo <=> b.foo }
|
17
|
+
# array.sort { |a, b| a[:foo] <=> b[:foo] }
|
16
18
|
#
|
17
19
|
# # good
|
18
20
|
# array.sort_by(&:foo)
|
21
|
+
# array.sort_by!(&:foo)
|
19
22
|
# array.sort_by { |v| v.foo }
|
20
23
|
# array.sort_by do |var|
|
21
24
|
# var.foo
|
22
25
|
# end
|
23
26
|
# array.max_by(&:foo)
|
24
27
|
# array.min_by(&:foo)
|
28
|
+
# array.minmax_by(&:foo)
|
25
29
|
# array.sort_by { |a| a[:foo] }
|
26
30
|
class CompareWithBlock < Base
|
27
31
|
include RangeHelp
|
28
32
|
extend AutoCorrector
|
29
33
|
|
30
|
-
MSG = 'Use `%<
|
34
|
+
MSG = 'Use `%<replacement_method>s%<instead>s` instead of ' \
|
31
35
|
'`%<compare_method>s { |%<var_a>s, %<var_b>s| %<str_a>s ' \
|
32
36
|
'<=> %<str_b>s }`.'
|
33
37
|
|
38
|
+
REPLACEMENT = { sort: :sort_by, sort!: :sort_by!, min: :min_by, max: :max_by, minmax: :minmax_by }.freeze
|
39
|
+
private_constant :REPLACEMENT
|
40
|
+
|
34
41
|
def_node_matcher :compare?, <<~PATTERN
|
35
42
|
(block
|
36
|
-
$(send _ {:sort :min :max})
|
43
|
+
$(send _ {:sort :sort! :min :max :minmax})
|
37
44
|
(args (arg $_a) (arg $_b))
|
38
45
|
$send)
|
39
46
|
PATTERN
|
@@ -54,9 +61,9 @@ module RuboCop
|
|
54
61
|
|
55
62
|
add_offense(range, message: message(send, method, var_a, var_b, args_a)) do |corrector|
|
56
63
|
replacement = if method == :[]
|
57
|
-
"#{send.method_name}
|
64
|
+
"#{REPLACEMENT[send.method_name]} { |a| a[#{args_a.first.source}] }"
|
58
65
|
else
|
59
|
-
"#{send.method_name}
|
66
|
+
"#{REPLACEMENT[send.method_name]}(&:#{method})"
|
60
67
|
end
|
61
68
|
corrector.replace(range, replacement)
|
62
69
|
end
|
@@ -82,7 +89,8 @@ module RuboCop
|
|
82
89
|
|
83
90
|
# rubocop:disable Metrics/MethodLength
|
84
91
|
def message(send, method, var_a, var_b, args)
|
85
|
-
compare_method
|
92
|
+
compare_method = send.method_name
|
93
|
+
replacement_method = REPLACEMENT[compare_method]
|
86
94
|
if method == :[]
|
87
95
|
key = args.first
|
88
96
|
instead = " { |a| a[#{key.source}] }"
|
@@ -94,6 +102,7 @@ module RuboCop
|
|
94
102
|
str_b = "#{var_b}.#{method}"
|
95
103
|
end
|
96
104
|
format(MSG, compare_method: compare_method,
|
105
|
+
replacement_method: replacement_method,
|
97
106
|
instead: instead,
|
98
107
|
var_a: var_a,
|
99
108
|
var_b: var_b,
|
@@ -38,6 +38,10 @@ module RuboCop
|
|
38
38
|
|
39
39
|
MSG = 'Extract this regexp into a constant, memoize it, or append an `/o` option to its options.'
|
40
40
|
|
41
|
+
def self.autocorrect_incompatible_with
|
42
|
+
[RegexpMatch]
|
43
|
+
end
|
44
|
+
|
41
45
|
def on_regexp(node)
|
42
46
|
return if within_allowed_assignment?(node) || !include_interpolated_const?(node) || node.single_interpolation?
|
43
47
|
|
@@ -110,7 +110,7 @@ module RuboCop
|
|
110
110
|
|
111
111
|
def negate_block_pass_reject(corrector, node)
|
112
112
|
corrector.replace(
|
113
|
-
node.receiver.
|
113
|
+
node.receiver.source_range.with(begin_pos: node.receiver.loc.begin.begin_pos),
|
114
114
|
negate_block_pass_as_inline_block(node.receiver)
|
115
115
|
)
|
116
116
|
end
|
@@ -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
|
@@ -8,12 +8,9 @@ module RuboCop
|
|
8
8
|
# `detect` instead.
|
9
9
|
#
|
10
10
|
# @safety
|
11
|
-
# This cop is unsafe because
|
12
|
-
# `
|
13
|
-
#
|
14
|
-
# frameworks. `Hash` and `ActiveRecord` do not implement a `detect`
|
15
|
-
# method and `find` has its own meaning. Correcting `Hash` and
|
16
|
-
# `ActiveRecord` methods with this cop should be considered unsafe.
|
11
|
+
# This cop is unsafe because it assumes that the receiver is an
|
12
|
+
# `Array` or equivalent, but can't reliably detect it. For example,
|
13
|
+
# if the receiver is a `Hash`, it may report a false positive.
|
17
14
|
#
|
18
15
|
# @example
|
19
16
|
# # bad
|
@@ -43,9 +40,9 @@ module RuboCop
|
|
43
40
|
|
44
41
|
def_node_matcher :detect_candidate?, <<~PATTERN
|
45
42
|
{
|
46
|
-
(send $(block (
|
43
|
+
(send $(block (call _ %CANDIDATE_METHODS) ...) ${:first :last} $...)
|
47
44
|
(send $(block (send _ %CANDIDATE_METHODS) ...) $:[] (int ${0 -1}))
|
48
|
-
(send $(
|
45
|
+
(send $(call _ %CANDIDATE_METHODS ...) ${:first :last} $...)
|
49
46
|
(send $(send _ %CANDIDATE_METHODS ...) $:[] (int ${0 -1}))
|
50
47
|
}
|
51
48
|
PATTERN
|
@@ -66,6 +63,7 @@ module RuboCop
|
|
66
63
|
register_offense(node, receiver, second_method, index)
|
67
64
|
end
|
68
65
|
end
|
66
|
+
alias on_csend on_send
|
69
67
|
|
70
68
|
private
|
71
69
|
|
@@ -58,8 +58,8 @@ module RuboCop
|
|
58
58
|
private
|
59
59
|
|
60
60
|
def autocorrect(corrector, first_call_args, second_call_args, combined_args)
|
61
|
-
first_argument = first_call_args.first.
|
62
|
-
last_argument = second_call_args.last.
|
61
|
+
first_argument = first_call_args.first.source_range
|
62
|
+
last_argument = second_call_args.last.source_range
|
63
63
|
range = first_argument.join(last_argument)
|
64
64
|
|
65
65
|
corrector.replace(range, combined_args)
|
@@ -54,7 +54,7 @@ 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
59
|
(match-with-lvasgn (regexp (str $#literal_at_end?) (regopt)) $_)}
|
60
60
|
PATTERN
|
@@ -66,12 +66,14 @@ module RuboCop
|
|
66
66
|
receiver, regex_str = regex_str, receiver if receiver.is_a?(String)
|
67
67
|
regex_str = drop_end_metacharacter(regex_str)
|
68
68
|
regex_str = interpret_string_escapes(regex_str)
|
69
|
+
dot = node.loc.dot ? node.loc.dot.source : '.'
|
69
70
|
|
70
|
-
new_source = "#{receiver.source}
|
71
|
+
new_source = "#{receiver.source}#{dot}end_with?(#{to_string_literal(regex_str)})"
|
71
72
|
|
72
|
-
corrector.replace(node
|
73
|
+
corrector.replace(node, new_source)
|
73
74
|
end
|
74
75
|
end
|
76
|
+
alias on_csend on_send
|
75
77
|
alias on_match_with_lvasgn on_send
|
76
78
|
end
|
77
79
|
end
|
@@ -78,13 +78,13 @@ module RuboCop
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def contains_splat?(node)
|
81
|
-
return unless node.array_type?
|
81
|
+
return false unless node.array_type?
|
82
82
|
|
83
83
|
node.each_child_node(:splat).any?
|
84
84
|
end
|
85
85
|
|
86
86
|
def contains_double_splat?(node)
|
87
|
-
return unless node.hash_type?
|
87
|
+
return false unless node.hash_type?
|
88
88
|
|
89
89
|
node.each_child_node(:kwsplat).any?
|
90
90
|
end
|
@@ -28,7 +28,7 @@ module RuboCop
|
|
28
28
|
def_node_matcher :flat_map_candidate?, <<~PATTERN
|
29
29
|
(send
|
30
30
|
{
|
31
|
-
(block
|
31
|
+
$(block (send _ ${:collect :map}) ...)
|
32
32
|
$(send _ ${:collect :map} (block_pass _))
|
33
33
|
}
|
34
34
|
${:flatten :flatten!}
|
@@ -60,7 +60,8 @@ module RuboCop
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def register_offense(node, map_node, first_method, flatten, message)
|
63
|
-
|
63
|
+
map_send_node = map_node.block_type? ? map_node.send_node : map_node
|
64
|
+
range = range_between(map_send_node.loc.selector.begin_pos, node.source_range.end_pos)
|
64
65
|
message = format(message, method: first_method, flatten: flatten)
|
65
66
|
|
66
67
|
add_offense(range, message: message) do |corrector|
|
@@ -74,10 +75,11 @@ module RuboCop
|
|
74
75
|
|
75
76
|
return unless flatten_level
|
76
77
|
|
77
|
-
|
78
|
+
map_send_node = map_node.block_type? ? map_node.send_node : map_node
|
79
|
+
range = range_between(map_node.source_range.end_pos, node.source_range.end_pos)
|
78
80
|
|
79
81
|
corrector.remove(range)
|
80
|
-
corrector.replace(
|
82
|
+
corrector.replace(map_send_node.loc.selector, 'flat_map')
|
81
83
|
end
|
82
84
|
end
|
83
85
|
end
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
45
45
|
RESTRICT_ON_SEND = %i[include?].freeze
|
46
46
|
|
47
47
|
def_node_matcher :inefficient_include?, <<~PATTERN
|
48
|
-
(send (
|
48
|
+
(send (call $_ {:keys :values}) :include? _)
|
49
49
|
PATTERN
|
50
50
|
|
51
51
|
def on_send(node)
|
@@ -56,21 +56,23 @@ module RuboCop
|
|
56
56
|
add_offense(node, message: message) do |corrector|
|
57
57
|
# Replace `keys.include?` or `values.include?` with the appropriate
|
58
58
|
# `key?`/`value?` method.
|
59
|
-
corrector.replace(
|
60
|
-
node.loc.expression,
|
61
|
-
"#{autocorrect_hash_expression(node)}.#{autocorrect_method(node)}(#{autocorrect_argument(node)})"
|
62
|
-
)
|
59
|
+
corrector.replace(node, replacement(node))
|
63
60
|
end
|
64
61
|
end
|
65
62
|
end
|
63
|
+
alias on_csend on_send
|
66
64
|
|
67
65
|
private
|
68
66
|
|
69
67
|
def message(node)
|
70
|
-
"Use `##{
|
68
|
+
"Use `##{correct_method(node)}` instead of `##{current_method(node)}.include?`."
|
71
69
|
end
|
72
70
|
|
73
|
-
def
|
71
|
+
def replacement(node)
|
72
|
+
"#{correct_hash_expression(node)}#{correct_dot(node)}#{correct_method(node)}(#{correct_argument(node)})"
|
73
|
+
end
|
74
|
+
|
75
|
+
def correct_method(node)
|
74
76
|
case current_method(node)
|
75
77
|
when :keys then use_long_method ? 'has_key?' : 'key?'
|
76
78
|
when :values then use_long_method ? 'has_value?' : 'value?'
|
@@ -86,13 +88,17 @@ module RuboCop
|
|
86
88
|
preferred_config && preferred_config['EnforcedStyle'] == 'long' && preferred_config['Enabled']
|
87
89
|
end
|
88
90
|
|
89
|
-
def
|
91
|
+
def correct_argument(node)
|
90
92
|
node.arguments.first.source
|
91
93
|
end
|
92
94
|
|
93
|
-
def
|
95
|
+
def correct_hash_expression(node)
|
94
96
|
node.receiver.receiver.source
|
95
97
|
end
|
98
|
+
|
99
|
+
def correct_dot(node)
|
100
|
+
node.receiver.loc.dot.source
|
101
|
+
end
|
96
102
|
end
|
97
103
|
end
|
98
104
|
end
|
@@ -40,12 +40,12 @@ module RuboCop
|
|
40
40
|
def_node_matcher :map_compact, <<~PATTERN
|
41
41
|
{
|
42
42
|
(send
|
43
|
-
$(
|
43
|
+
$(call _ {:map :collect}
|
44
44
|
(block_pass
|
45
45
|
(sym _))) _)
|
46
46
|
(send
|
47
47
|
(block
|
48
|
-
$(
|
48
|
+
$(call _ {:map :collect})
|
49
49
|
(args ...) _) _)
|
50
50
|
}
|
51
51
|
PATTERN
|
@@ -61,6 +61,7 @@ module RuboCop
|
|
61
61
|
remove_compact_method(corrector, map_node, node, node.parent)
|
62
62
|
end
|
63
63
|
end
|
64
|
+
alias on_csend on_send
|
64
65
|
|
65
66
|
private
|
66
67
|
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Performance
|
6
|
+
# Checks if the map method is used in a chain.
|
7
|
+
#
|
8
|
+
# Autocorrection is not supported because an appropriate block variable name cannot be determined automatically.
|
9
|
+
#
|
10
|
+
# @safety
|
11
|
+
# This cop is unsafe because false positives occur if the number of times the first method is executed
|
12
|
+
# affects the return value of subsequent methods.
|
13
|
+
#
|
14
|
+
# [source,ruby]
|
15
|
+
# ----
|
16
|
+
# class X
|
17
|
+
# def initialize
|
18
|
+
# @@num = 0
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# def foo
|
22
|
+
# @@num += 1
|
23
|
+
# self
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# def bar
|
27
|
+
# @@num * 2
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# [X.new, X.new].map(&:foo).map(&:bar) # => [4, 4]
|
32
|
+
# [X.new, X.new].map { |x| x.foo.bar } # => [2, 4]
|
33
|
+
# ----
|
34
|
+
#
|
35
|
+
# @example
|
36
|
+
#
|
37
|
+
# # bad
|
38
|
+
# array.map(&:foo).map(&:bar)
|
39
|
+
#
|
40
|
+
# # good
|
41
|
+
# array.map { |item| item.foo.bar }
|
42
|
+
#
|
43
|
+
class MapMethodChain < Base
|
44
|
+
include IgnoredNode
|
45
|
+
|
46
|
+
MSG = 'Use `%<method_name>s { |x| x.%<map_args>s }` instead of `%<method_name>s` method chain.'
|
47
|
+
RESTRICT_ON_SEND = %i[map collect].freeze
|
48
|
+
|
49
|
+
def_node_matcher :block_pass_with_symbol_arg?, <<~PATTERN
|
50
|
+
(:block_pass (:sym $_))
|
51
|
+
PATTERN
|
52
|
+
|
53
|
+
def on_send(node)
|
54
|
+
return if part_of_ignored_node?(node)
|
55
|
+
return unless (map_arg = block_pass_with_symbol_arg?(node.first_argument))
|
56
|
+
|
57
|
+
map_args = [map_arg]
|
58
|
+
|
59
|
+
return unless (begin_of_chained_map_method = find_begin_of_chained_map_method(node, map_args))
|
60
|
+
|
61
|
+
range = begin_of_chained_map_method.loc.selector.begin.join(node.source_range.end)
|
62
|
+
message = format(MSG, method_name: begin_of_chained_map_method.method_name, map_args: map_args.join('.'))
|
63
|
+
|
64
|
+
add_offense(range, message: message)
|
65
|
+
|
66
|
+
ignore_node(node)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def find_begin_of_chained_map_method(node, map_args)
|
72
|
+
return unless (chained_map_method = node.receiver)
|
73
|
+
return if !chained_map_method.call_type? || !RESTRICT_ON_SEND.include?(chained_map_method.method_name)
|
74
|
+
return unless (map_arg = block_pass_with_symbol_arg?(chained_map_method.first_argument))
|
75
|
+
|
76
|
+
map_args.unshift(map_arg)
|
77
|
+
|
78
|
+
receiver = chained_map_method.receiver
|
79
|
+
|
80
|
+
return chained_map_method unless receiver.call_type? && block_pass_with_symbol_arg?(receiver.first_argument)
|
81
|
+
|
82
|
+
find_begin_of_chained_map_method(chained_map_method, map_args)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -10,6 +10,16 @@ module RuboCop
|
|
10
10
|
# behavior is appropriately overridden in subclass. For example,
|
11
11
|
# `Range#===` returns `true` when argument is within the range.
|
12
12
|
#
|
13
|
+
# This cop has `AllowRegexpMatch` option and it is true by default because
|
14
|
+
# `regexp.match?('string')` often used in block changes to the opposite result:
|
15
|
+
#
|
16
|
+
# [source,ruby]
|
17
|
+
# ----
|
18
|
+
# [/pattern/].all? { |regexp| regexp.match?('pattern') } # => true
|
19
|
+
# [/pattern/].all? { |regexp| regexp =~ 'pattern' } # => true
|
20
|
+
# [/pattern/].all?('pattern') # => false
|
21
|
+
# ----
|
22
|
+
#
|
13
23
|
# @safety
|
14
24
|
# This cop is unsafe because `===` and `==` do not always behave the same.
|
15
25
|
#
|
@@ -22,6 +32,19 @@ module RuboCop
|
|
22
32
|
#
|
23
33
|
# # good
|
24
34
|
# items.all?(pattern)
|
35
|
+
# items.all?(Klass)
|
36
|
+
#
|
37
|
+
# @example AllowRegexpMatch: true (default)
|
38
|
+
#
|
39
|
+
# # good
|
40
|
+
# items.all? { |item| item =~ pattern }
|
41
|
+
# items.all? { |item| item.match?(pattern) }
|
42
|
+
#
|
43
|
+
# @example AllowRegexpMatch: false
|
44
|
+
#
|
45
|
+
# # bad
|
46
|
+
# items.all? { |item| item =~ pattern }
|
47
|
+
# items.all? { |item| item.match?(pattern) }
|
25
48
|
#
|
26
49
|
class RedundantEqualityComparisonBlock < Base
|
27
50
|
extend AutoCorrector
|
@@ -33,6 +56,7 @@ module RuboCop
|
|
33
56
|
|
34
57
|
TARGET_METHODS = %i[all? any? one? none?].freeze
|
35
58
|
COMPARISON_METHODS = %i[== === is_a? kind_of?].freeze
|
59
|
+
REGEXP_METHODS = %i[=~ match?].freeze
|
36
60
|
IS_A_METHODS = %i[is_a? kind_of?].freeze
|
37
61
|
|
38
62
|
def on_block(node)
|
@@ -60,7 +84,11 @@ module RuboCop
|
|
60
84
|
end
|
61
85
|
|
62
86
|
def use_equality_comparison_block?(block_body)
|
63
|
-
block_body.send_type?
|
87
|
+
return false unless block_body.send_type?
|
88
|
+
|
89
|
+
method_name = block_body.method_name
|
90
|
+
|
91
|
+
COMPARISON_METHODS.include?(method_name) || (!allow_regexp_match? && REGEXP_METHODS.include?(method_name))
|
64
92
|
end
|
65
93
|
|
66
94
|
def same_block_argument_and_is_a_argument?(block_body, block_argument)
|
@@ -69,7 +97,7 @@ module RuboCop
|
|
69
97
|
elsif IS_A_METHODS.include?(block_body.method_name)
|
70
98
|
block_argument.source == block_body.first_argument.source
|
71
99
|
else
|
72
|
-
|
100
|
+
block_body.receiver.source == block_body.first_argument.receiver&.source
|
73
101
|
end
|
74
102
|
end
|
75
103
|
|
@@ -99,6 +127,10 @@ module RuboCop
|
|
99
127
|
def offense_range(node)
|
100
128
|
node.send_node.loc.selector.join(node.source_range.end)
|
101
129
|
end
|
130
|
+
|
131
|
+
def allow_regexp_match?
|
132
|
+
cop_config.fetch('AllowRegexpMatch', true)
|
133
|
+
end
|
102
134
|
end
|
103
135
|
end
|
104
136
|
end
|
@@ -109,14 +109,14 @@ module RuboCop
|
|
109
109
|
node = parent
|
110
110
|
else
|
111
111
|
padding = "\n#{leading_spaces(node)}"
|
112
|
-
new_source.gsub!(
|
112
|
+
new_source.gsub!("\n", padding)
|
113
113
|
end
|
114
114
|
|
115
|
-
corrector.replace(node
|
115
|
+
corrector.replace(node, new_source)
|
116
116
|
end
|
117
117
|
|
118
118
|
def correct_single_element(corrector, node, new_source)
|
119
|
-
corrector.replace(node
|
119
|
+
corrector.replace(node, new_source)
|
120
120
|
end
|
121
121
|
|
122
122
|
def to_assignments(receiver, pairs)
|
@@ -132,7 +132,7 @@ module RuboCop
|
|
132
132
|
def rewrite_with_modifier(node, parent, new_source)
|
133
133
|
indent = ' ' * configured_indentation_width
|
134
134
|
padding = "\n#{indent + leading_spaces(node)}"
|
135
|
-
new_source.gsub!(
|
135
|
+
new_source.gsub!("\n", padding)
|
136
136
|
|
137
137
|
format(WITH_MODIFIER_CORRECTION, keyword: parent.loc.keyword.source,
|
138
138
|
condition: parent.condition.source,
|
@@ -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
|
|
@@ -69,11 +69,11 @@ module RuboCop
|
|
69
69
|
private
|
70
70
|
|
71
71
|
def offense_range(receiver, node)
|
72
|
-
range_between(receiver.loc.selector.begin_pos, node.
|
72
|
+
range_between(receiver.loc.selector.begin_pos, node.source_range.end_pos)
|
73
73
|
end
|
74
74
|
|
75
75
|
def correction_range(receiver, node)
|
76
|
-
range_between(receiver.loc.dot.begin_pos, node.
|
76
|
+
range_between(receiver.loc.dot.begin_pos, node.source_range.end_pos)
|
77
77
|
end
|
78
78
|
|
79
79
|
def build_message(method, args)
|
@@ -131,6 +131,10 @@ module RuboCop
|
|
131
131
|
}
|
132
132
|
PATTERN
|
133
133
|
|
134
|
+
def self.autocorrect_incompatible_with
|
135
|
+
[ConstantRegexp]
|
136
|
+
end
|
137
|
+
|
134
138
|
def on_if(node)
|
135
139
|
check_condition(node.condition)
|
136
140
|
end
|
@@ -185,9 +189,9 @@ module RuboCop
|
|
185
189
|
|
186
190
|
def range_to_search_for_last_matches(match_node, body, scope_root)
|
187
191
|
expression = if modifier_form?(match_node)
|
188
|
-
match_node.parent.if_branch.
|
192
|
+
match_node.parent.if_branch.source_range
|
189
193
|
else
|
190
|
-
match_node.
|
194
|
+
match_node.source_range
|
191
195
|
end
|
192
196
|
|
193
197
|
match_node_pos = expression.begin_pos
|
@@ -199,15 +203,15 @@ module RuboCop
|
|
199
203
|
def next_match_pos(body, match_node_pos, scope_root)
|
200
204
|
node = search_match_nodes(body).find do |match|
|
201
205
|
begin_pos = if modifier_form?(match)
|
202
|
-
match.parent.if_branch.
|
206
|
+
match.parent.if_branch.source_range.begin_pos
|
203
207
|
else
|
204
|
-
match.
|
208
|
+
match.source_range.begin_pos
|
205
209
|
end
|
206
210
|
|
207
211
|
begin_pos > match_node_pos && scope_root(match) == scope_root
|
208
212
|
end
|
209
213
|
|
210
|
-
node ? node.
|
214
|
+
node ? node.source_range.begin_pos : Float::INFINITY
|
211
215
|
end
|
212
216
|
|
213
217
|
def modifier_form?(match_node)
|
@@ -216,7 +220,7 @@ module RuboCop
|
|
216
220
|
|
217
221
|
def find_last_match(body, range, scope_root)
|
218
222
|
last_matches(body).find do |ref|
|
219
|
-
ref_pos = ref.
|
223
|
+
ref_pos = ref.source_range.begin_pos
|
220
224
|
range.cover?(ref_pos) && scope_root(ref) == scope_root
|
221
225
|
end
|
222
226
|
end
|
@@ -248,8 +252,8 @@ module RuboCop
|
|
248
252
|
|
249
253
|
replace_with_match_predicate_method(corrector, recv, arg, op_range)
|
250
254
|
|
251
|
-
corrector.insert_after(arg
|
252
|
-
corrector.insert_before(recv
|
255
|
+
corrector.insert_after(arg, ')') unless op_range.source.end_with?('(')
|
256
|
+
corrector.insert_before(recv, '!') if oper == :!~
|
253
257
|
end
|
254
258
|
|
255
259
|
def replace_with_match_predicate_method(corrector, recv, arg, op_range)
|
@@ -264,14 +268,14 @@ module RuboCop
|
|
264
268
|
end
|
265
269
|
|
266
270
|
def swap_receiver_and_arg(corrector, recv, arg)
|
267
|
-
corrector.replace(recv
|
268
|
-
corrector.replace(arg
|
271
|
+
corrector.replace(recv, arg.source)
|
272
|
+
corrector.replace(arg, recv.source)
|
269
273
|
end
|
270
274
|
|
271
275
|
def correction_range(recv, arg)
|
272
276
|
buffer = processed_source.buffer
|
273
|
-
op_begin_pos = recv.
|
274
|
-
op_end_pos = arg.
|
277
|
+
op_begin_pos = recv.source_range.end_pos
|
278
|
+
op_end_pos = arg.source_range.begin_pos
|
275
279
|
Parser::Source::Range.new(buffer, op_begin_pos, op_end_pos)
|
276
280
|
end
|
277
281
|
end
|
@@ -27,7 +27,7 @@ module RuboCop
|
|
27
27
|
RESTRICT_ON_SEND = %i[each].freeze
|
28
28
|
|
29
29
|
def_node_matcher :reverse_each?, <<~MATCHER
|
30
|
-
(send (
|
30
|
+
(send (call _ :reverse) :each)
|
31
31
|
MATCHER
|
32
32
|
|
33
33
|
def on_send(node)
|
@@ -41,6 +41,7 @@ module RuboCop
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
44
|
+
alias on_csend on_send
|
44
45
|
|
45
46
|
private
|
46
47
|
|
@@ -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
|
@@ -27,7 +27,7 @@ module RuboCop
|
|
27
27
|
PREFERRED_METHODS = { gsub: :squeeze, gsub!: :squeeze! }.freeze
|
28
28
|
|
29
29
|
def_node_matcher :squeeze_candidate?, <<~PATTERN
|
30
|
-
(
|
30
|
+
(call
|
31
31
|
$!nil? ${:gsub :gsub!}
|
32
32
|
(regexp
|
33
33
|
(str $#repeating_literal?)
|
@@ -35,6 +35,7 @@ module RuboCop
|
|
35
35
|
(str $_))
|
36
36
|
PATTERN
|
37
37
|
|
38
|
+
# rubocop:disable Metrics/AbcSize
|
38
39
|
def on_send(node)
|
39
40
|
squeeze_candidate?(node) do |receiver, bad_method, regexp_str, replace_str|
|
40
41
|
regexp_str = regexp_str[0..-2] # delete '+' from the end
|
@@ -46,12 +47,14 @@ module RuboCop
|
|
46
47
|
|
47
48
|
add_offense(node.loc.selector, message: message) do |corrector|
|
48
49
|
string_literal = to_string_literal(replace_str)
|
49
|
-
new_code = "#{receiver.source}
|
50
|
+
new_code = "#{receiver.source}#{node.loc.dot.source}#{good_method}(#{string_literal})"
|
50
51
|
|
51
|
-
corrector.replace(node
|
52
|
+
corrector.replace(node, new_code)
|
52
53
|
end
|
53
54
|
end
|
54
55
|
end
|
56
|
+
# rubocop:enable Metrics/AbcSize
|
57
|
+
alias on_csend on_send
|
55
58
|
|
56
59
|
private
|
57
60
|
|
@@ -54,7 +54,7 @@ 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_start?) (regopt)))
|
58
58
|
(send (regexp (str $#literal_at_start?) (regopt)) {:match :match?} $_)
|
59
59
|
(match-with-lvasgn (regexp (str $#literal_at_start?) (regopt)) $_)}
|
60
60
|
PATTERN
|
@@ -66,12 +66,14 @@ module RuboCop
|
|
66
66
|
receiver, regex_str = regex_str, receiver if receiver.is_a?(String)
|
67
67
|
regex_str = drop_start_metacharacter(regex_str)
|
68
68
|
regex_str = interpret_string_escapes(regex_str)
|
69
|
+
dot = node.loc.dot ? node.loc.dot.source : '.'
|
69
70
|
|
70
|
-
new_source = "#{receiver.source}
|
71
|
+
new_source = "#{receiver.source}#{dot}start_with?(#{to_string_literal(regex_str)})"
|
71
72
|
|
72
|
-
corrector.replace(node
|
73
|
+
corrector.replace(node, new_source)
|
73
74
|
end
|
74
75
|
end
|
76
|
+
alias on_csend on_send
|
75
77
|
alias on_match_with_lvasgn on_send
|
76
78
|
end
|
77
79
|
end
|
@@ -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?(' ') || 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
|
|
@@ -26,11 +26,12 @@ module RuboCop
|
|
26
26
|
RESTRICT_ON_SEND = %i[match =~ !~ match?].freeze
|
27
27
|
|
28
28
|
def_node_matcher :redundant_regex?, <<~PATTERN
|
29
|
-
{(
|
29
|
+
{(call $!nil? {:match :=~ :!~ :match?} (regexp (str $#literal?) (regopt)))
|
30
30
|
(send (regexp (str $#literal?) (regopt)) {:match :match?} $_)
|
31
31
|
(match-with-lvasgn (regexp (str $#literal?) (regopt)) $_)}
|
32
32
|
PATTERN
|
33
33
|
|
34
|
+
# rubocop:disable Metrics/AbcSize
|
34
35
|
def on_send(node)
|
35
36
|
return unless (receiver, regex_str = redundant_regex?(node))
|
36
37
|
|
@@ -40,12 +41,15 @@ module RuboCop
|
|
40
41
|
add_offense(node, message: message) do |corrector|
|
41
42
|
receiver, regex_str = regex_str, receiver if receiver.is_a?(String)
|
42
43
|
regex_str = interpret_string_escapes(regex_str)
|
44
|
+
dot = node.loc.dot ? node.loc.dot.source : '.'
|
43
45
|
|
44
|
-
new_source = "#{'!' if negation}#{receiver.source}
|
46
|
+
new_source = "#{'!' if negation}#{receiver.source}#{dot}include?(#{to_string_literal(regex_str)})"
|
45
47
|
|
46
|
-
corrector.replace(node
|
48
|
+
corrector.replace(node, new_source)
|
47
49
|
end
|
48
50
|
end
|
51
|
+
# rubocop:enable Metrics/AbcSize
|
52
|
+
alias on_csend on_send
|
49
53
|
alias on_match_with_lvasgn on_send
|
50
54
|
|
51
55
|
private
|
@@ -29,7 +29,7 @@ module RuboCop
|
|
29
29
|
BANG = '!'
|
30
30
|
|
31
31
|
def_node_matcher :string_replacement?, <<~PATTERN
|
32
|
-
(
|
32
|
+
(call _ {:gsub :gsub!}
|
33
33
|
${regexp str (send (const nil? :Regexp) {:new :compile} _)}
|
34
34
|
$str)
|
35
35
|
PATTERN
|
@@ -42,6 +42,7 @@ module RuboCop
|
|
42
42
|
offense(node, first_param, second_param)
|
43
43
|
end
|
44
44
|
end
|
45
|
+
alias on_csend on_send
|
45
46
|
|
46
47
|
private
|
47
48
|
|
@@ -70,7 +71,7 @@ module RuboCop
|
|
70
71
|
replacement_method = replacement_method(node, first_source, second_source)
|
71
72
|
|
72
73
|
corrector.replace(node.loc.selector, replacement_method)
|
73
|
-
corrector.replace(first_param
|
74
|
+
corrector.replace(first_param, to_string_literal(first_source)) unless first_param.str_type?
|
74
75
|
|
75
76
|
remove_second_param(corrector, node, first_param) if second_source.empty? && first_source.length == 1
|
76
77
|
end
|
@@ -52,7 +52,7 @@ module RuboCop
|
|
52
52
|
add_offense(node, message: message(map_or_collect, count)) do |corrector|
|
53
53
|
replacement = "Array.new(#{count.source}#{map_or_collect.arguments.map { |arg| ", #{arg.source}" }.join})"
|
54
54
|
|
55
|
-
corrector.replace(map_or_collect
|
55
|
+
corrector.replace(map_or_collect, replacement)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -25,12 +25,12 @@ module RuboCop
|
|
25
25
|
PATTERN
|
26
26
|
|
27
27
|
def on_send(node)
|
28
|
-
|
28
|
+
uri_parser_new?(node) do |captured_value|
|
29
29
|
double_colon = captured_value ? '::' : ''
|
30
30
|
message = format(MSG, double_colon: double_colon)
|
31
31
|
|
32
32
|
add_offense(node, message: message) do |corrector|
|
33
|
-
corrector.replace(node
|
33
|
+
corrector.replace(node, "#{double_colon}URI::DEFAULT_PARSER")
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -25,6 +25,7 @@ require_relative 'performance/fixed_size'
|
|
25
25
|
require_relative 'performance/flat_map'
|
26
26
|
require_relative 'performance/inefficient_hash_search'
|
27
27
|
require_relative 'performance/map_compact'
|
28
|
+
require_relative 'performance/map_method_chain'
|
28
29
|
require_relative 'performance/method_object_as_block'
|
29
30
|
require_relative 'performance/open_struct'
|
30
31
|
require_relative 'performance/range_include'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-performance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.19.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-
|
13
|
+
date: 2023-08-13 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rubocop
|
@@ -87,6 +87,7 @@ files:
|
|
87
87
|
- lib/rubocop/cop/performance/inefficient_hash_search.rb
|
88
88
|
- lib/rubocop/cop/performance/io_readlines.rb
|
89
89
|
- lib/rubocop/cop/performance/map_compact.rb
|
90
|
+
- lib/rubocop/cop/performance/map_method_chain.rb
|
90
91
|
- lib/rubocop/cop/performance/method_object_as_block.rb
|
91
92
|
- lib/rubocop/cop/performance/open_struct.rb
|
92
93
|
- lib/rubocop/cop/performance/range_include.rb
|
@@ -123,7 +124,7 @@ metadata:
|
|
123
124
|
homepage_uri: https://docs.rubocop.org/rubocop-performance/
|
124
125
|
changelog_uri: https://github.com/rubocop/rubocop-performance/blob/master/CHANGELOG.md
|
125
126
|
source_code_uri: https://github.com/rubocop/rubocop-performance/
|
126
|
-
documentation_uri: https://docs.rubocop.org/rubocop-performance/1.
|
127
|
+
documentation_uri: https://docs.rubocop.org/rubocop-performance/1.19/
|
127
128
|
bug_tracker_uri: https://github.com/rubocop/rubocop-performance/issues
|
128
129
|
rubygems_mfa_required: 'true'
|
129
130
|
post_install_message:
|
@@ -134,14 +135,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
134
135
|
requirements:
|
135
136
|
- - ">="
|
136
137
|
- !ruby/object:Gem::Version
|
137
|
-
version: 2.
|
138
|
+
version: 2.7.0
|
138
139
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
140
|
requirements:
|
140
141
|
- - ">="
|
141
142
|
- !ruby/object:Gem::Version
|
142
143
|
version: '0'
|
143
144
|
requirements: []
|
144
|
-
rubygems_version: 3.
|
145
|
+
rubygems_version: 3.5.0.dev
|
145
146
|
signing_key:
|
146
147
|
specification_version: 4
|
147
148
|
summary: Automatic performance checking tool for Ruby code.
|