rubocop-performance 1.11.1 → 1.11.5
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/config/default.yml +4 -0
- data/lib/rubocop/cop/performance/array_semi_infinite_range_slice.rb +5 -5
- data/lib/rubocop/cop/performance/case_when_splat.rb +4 -8
- data/lib/rubocop/cop/performance/collection_literal_in_loop.rb +1 -1
- data/lib/rubocop/cop/performance/delete_prefix.rb +2 -1
- data/lib/rubocop/cop/performance/delete_suffix.rb +2 -1
- data/lib/rubocop/cop/performance/detect.rb +4 -8
- data/lib/rubocop/cop/performance/map_compact.rb +14 -6
- data/lib/rubocop/cop/performance/redundant_equality_comparison_block.rb +17 -2
- data/lib/rubocop/cop/performance/redundant_string_chars.rb +7 -17
- data/lib/rubocop/cop/performance/regexp_match.rb +1 -2
- data/lib/rubocop/cop/performance/unfreeze_string.rb +4 -1
- data/lib/rubocop/performance/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4fffd38c1ed7da6f4ff4f67b3f1d7d08bc60e8871dc22d4ac266de6facc04fcf
|
4
|
+
data.tar.gz: e0de1a9ec946e37b2654390d4b46a0b9f0e1afbc37fec464c6fd78001ad5e509
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4225a879e2e0421438be5d17bb38d982901709c809ed7ccda3a0095affaf77a707c5fb5657ee61b123546860f1e9f0bcf783ed706b8b17fba9114588a16b4653
|
7
|
+
data.tar.gz: 3af998bbda7046ae5a55f06bb1ecc941dff48901d94a791fd81963cc1d76adf39524600c7ff4633c3dc06f925a2d8ea7f57716f51de2079e971c10b6194e40bb
|
data/config/default.yml
CHANGED
@@ -96,14 +96,18 @@ Performance/Count:
|
|
96
96
|
Performance/DeletePrefix:
|
97
97
|
Description: 'Use `delete_prefix` instead of `gsub`.'
|
98
98
|
Enabled: true
|
99
|
+
Safe: false
|
99
100
|
SafeMultiline: true
|
100
101
|
VersionAdded: '1.6'
|
102
|
+
VersionChanged: '1.11'
|
101
103
|
|
102
104
|
Performance/DeleteSuffix:
|
103
105
|
Description: 'Use `delete_suffix` instead of `gsub`.'
|
104
106
|
Enabled: true
|
107
|
+
Safe: false
|
105
108
|
SafeMultiline: true
|
106
109
|
VersionAdded: '1.6'
|
110
|
+
VersionChanged: '1.11'
|
107
111
|
|
108
112
|
Performance/Detect:
|
109
113
|
Description: >-
|
@@ -11,11 +11,11 @@ module RuboCop
|
|
11
11
|
#
|
12
12
|
# @example
|
13
13
|
# # bad
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
14
|
+
# array[..2]
|
15
|
+
# array[...2]
|
16
|
+
# array[2..]
|
17
|
+
# array[2...]
|
18
|
+
# array.slice(..2)
|
19
19
|
#
|
20
20
|
# # good
|
21
21
|
# array.take(3)
|
@@ -58,10 +58,8 @@ module RuboCop
|
|
58
58
|
include RangeHelp
|
59
59
|
extend AutoCorrector
|
60
60
|
|
61
|
-
MSG = 'Reordering `when` conditions with a splat to the end '
|
62
|
-
|
63
|
-
ARRAY_MSG = 'Pass the contents of array literals ' \
|
64
|
-
'directly to `when` conditions.'
|
61
|
+
MSG = 'Reordering `when` conditions with a splat to the end of the `when` branches can improve performance.'
|
62
|
+
ARRAY_MSG = 'Pass the contents of array literals directly to `when` conditions.'
|
65
63
|
|
66
64
|
def on_case(case_node)
|
67
65
|
when_conditions = case_node.when_branches.flat_map(&:conditions)
|
@@ -134,13 +132,11 @@ module RuboCop
|
|
134
132
|
end
|
135
133
|
|
136
134
|
def new_condition_with_then(node, new_condition)
|
137
|
-
"\n#{indent_for(node)}when "
|
138
|
-
"#{new_condition} then #{node.body.source}"
|
135
|
+
"\n#{indent_for(node)}when #{new_condition} then #{node.body.source}"
|
139
136
|
end
|
140
137
|
|
141
138
|
def new_branch_without_then(node, new_condition)
|
142
|
-
"\n#{indent_for(node)}when #{new_condition}"
|
143
|
-
"\n#{indent_for(node.body)}#{node.body.source}"
|
139
|
+
"\n#{indent_for(node)}when #{new_condition}\n#{indent_for(node.body)}#{node.body.source}"
|
144
140
|
end
|
145
141
|
|
146
142
|
def indent_for(node)
|
@@ -33,7 +33,7 @@ module RuboCop
|
|
33
33
|
#
|
34
34
|
class CollectionLiteralInLoop < Base
|
35
35
|
MSG = 'Avoid immutable %<literal_class>s literals in loops. '\
|
36
|
-
|
36
|
+
'It is better to extract it into a local variable or a constant.'
|
37
37
|
|
38
38
|
POST_CONDITION_LOOP_TYPES = %i[while_post until_post].freeze
|
39
39
|
LOOP_TYPES = (POST_CONDITION_LOOP_TYPES + %i[while until for]).freeze
|
@@ -7,6 +7,7 @@ module RuboCop
|
|
7
7
|
#
|
8
8
|
# This cop identifies places where `gsub(/\Aprefix/, '')` and `sub(/\Aprefix/, '')`
|
9
9
|
# can be replaced by `delete_prefix('prefix')`.
|
10
|
+
# It is marked as unsafe by default because `Pathname` has `sub` but not `delete_prefix`.
|
10
11
|
#
|
11
12
|
# This cop has `SafeMultiline` configuration option that `true` by default because
|
12
13
|
# `^prefix` is unsafe as it will behave incompatible with `delete_prefix`
|
@@ -66,7 +67,7 @@ module RuboCop
|
|
66
67
|
|
67
68
|
def on_send(node)
|
68
69
|
return unless (receiver, bad_method, regexp_str, replace_string = delete_prefix_candidate?(node))
|
69
|
-
return unless replace_string.
|
70
|
+
return unless replace_string.empty?
|
70
71
|
|
71
72
|
good_method = PREFERRED_METHODS[bad_method]
|
72
73
|
|
@@ -7,6 +7,7 @@ module RuboCop
|
|
7
7
|
#
|
8
8
|
# This cop identifies places where `gsub(/suffix\z/, '')` and `sub(/suffix\z/, '')`
|
9
9
|
# can be replaced by `delete_suffix('suffix')`.
|
10
|
+
# It is marked as unsafe by default because `Pathname` has `sub` but not `delete_suffix`.
|
10
11
|
#
|
11
12
|
# This cop has `SafeMultiline` configuration option that `true` by default because
|
12
13
|
# `suffix$` is unsafe as it will behave incompatible with `delete_suffix?`
|
@@ -66,7 +67,7 @@ module RuboCop
|
|
66
67
|
|
67
68
|
def on_send(node)
|
68
69
|
return unless (receiver, bad_method, regexp_str, replace_string = delete_suffix_candidate?(node))
|
69
|
-
return unless replace_string.
|
70
|
+
return unless replace_string.empty?
|
70
71
|
|
71
72
|
good_method = PREFERRED_METHODS[bad_method]
|
72
73
|
|
@@ -31,14 +31,10 @@ module RuboCop
|
|
31
31
|
|
32
32
|
CANDIDATE_METHODS = Set[:select, :find_all, :filter].freeze
|
33
33
|
|
34
|
-
MSG = 'Use `%<prefer>s` instead of '
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
INDEX_MSG = 'Use `%<prefer>s` instead of ' \
|
39
|
-
'`%<first_method>s[%<index>i]`.'
|
40
|
-
INDEX_REVERSE_MSG = 'Use `reverse.%<prefer>s` instead of ' \
|
41
|
-
'`%<first_method>s[%<index>i]`.'
|
34
|
+
MSG = 'Use `%<prefer>s` instead of `%<first_method>s.%<second_method>s`.'
|
35
|
+
REVERSE_MSG = 'Use `reverse.%<prefer>s` instead of `%<first_method>s.%<second_method>s`.'
|
36
|
+
INDEX_MSG = 'Use `%<prefer>s` instead of `%<first_method>s[%<index>i]`.'
|
37
|
+
INDEX_REVERSE_MSG = 'Use `reverse.%<prefer>s` instead of `%<first_method>s[%<index>i]`.'
|
42
38
|
RESTRICT_ON_SEND = %i[first last []].freeze
|
43
39
|
|
44
40
|
def_node_matcher :detect_candidate?, <<~PATTERN
|
@@ -23,6 +23,7 @@ module RuboCop
|
|
23
23
|
# # good
|
24
24
|
# ary.filter_map(&:foo)
|
25
25
|
# ary.map(&:foo).compact!
|
26
|
+
# ary.compact.map(&:foo)
|
26
27
|
#
|
27
28
|
class MapCompact < Base
|
28
29
|
include RangeHelp
|
@@ -55,21 +56,28 @@ module RuboCop
|
|
55
56
|
|
56
57
|
add_offense(range) do |corrector|
|
57
58
|
corrector.replace(map_node.loc.selector, 'filter_map')
|
58
|
-
corrector
|
59
|
-
corrector.remove(compact_method_range(node))
|
59
|
+
remove_compact_method(corrector, node)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
63
|
private
|
64
64
|
|
65
|
-
def
|
65
|
+
def remove_compact_method(corrector, compact_node)
|
66
|
+
chained_method = compact_node.parent
|
66
67
|
compact_method_range = compact_node.loc.selector
|
67
68
|
|
68
|
-
if compact_node.multiline?
|
69
|
-
|
69
|
+
if compact_node.multiline? && chained_method&.loc.respond_to?(:selector) && chained_method.dot? &&
|
70
|
+
!invoke_method_after_map_compact_on_same_line?(compact_node, chained_method)
|
71
|
+
compact_method_range = range_by_whole_lines(compact_method_range, include_final_newline: true)
|
70
72
|
else
|
71
|
-
|
73
|
+
corrector.remove(compact_node.loc.dot)
|
72
74
|
end
|
75
|
+
|
76
|
+
corrector.remove(compact_method_range)
|
77
|
+
end
|
78
|
+
|
79
|
+
def invoke_method_after_map_compact_on_same_line?(compact_node, chained_method)
|
80
|
+
compact_node.loc.selector.line == chained_method.loc.selector.line
|
73
81
|
end
|
74
82
|
end
|
75
83
|
end
|
@@ -74,12 +74,27 @@ module RuboCop
|
|
74
74
|
|
75
75
|
def new_argument(block_argument, block_body)
|
76
76
|
if block_argument.source == block_body.receiver.source
|
77
|
-
block_body.first_argument
|
77
|
+
rhs = block_body.first_argument
|
78
|
+
return if use_block_argument_in_method_argument_of_operand?(block_argument, rhs)
|
79
|
+
|
80
|
+
rhs.source
|
78
81
|
elsif block_argument.source == block_body.first_argument.source
|
79
|
-
block_body.receiver
|
82
|
+
lhs = block_body.receiver
|
83
|
+
return if use_block_argument_in_method_argument_of_operand?(block_argument, lhs)
|
84
|
+
|
85
|
+
lhs.source
|
80
86
|
end
|
81
87
|
end
|
82
88
|
|
89
|
+
def use_block_argument_in_method_argument_of_operand?(block_argument, operand)
|
90
|
+
return false unless operand.send_type?
|
91
|
+
|
92
|
+
arguments = operand.arguments
|
93
|
+
arguments.inject(arguments.map(&:source)) do |operand_sources, argument|
|
94
|
+
operand_sources + argument.each_descendant(:lvar).map(&:source)
|
95
|
+
end.any?(block_argument.source)
|
96
|
+
end
|
97
|
+
|
83
98
|
def offense_range(node)
|
84
99
|
node.send_node.loc.selector.join(node.source_range.end)
|
85
100
|
end
|
@@ -16,35 +16,35 @@ module RuboCop
|
|
16
16
|
# # bad
|
17
17
|
# str.chars.first
|
18
18
|
# str.chars.first(2)
|
19
|
-
# str.chars.last
|
20
|
-
# str.chars.last(2)
|
21
19
|
#
|
22
20
|
# # good
|
23
21
|
# str[0]
|
24
22
|
# str[0...2].chars
|
25
|
-
# str[-1]
|
26
|
-
# str[-2..-1].chars
|
27
23
|
#
|
28
24
|
# # bad
|
29
25
|
# str.chars.take(2)
|
30
|
-
# str.chars.drop(2)
|
31
26
|
# str.chars.length
|
32
27
|
# str.chars.size
|
33
28
|
# str.chars.empty?
|
34
29
|
#
|
35
30
|
# # good
|
36
31
|
# str[0...2].chars
|
37
|
-
# str[2..-1].chars
|
38
32
|
# str.length
|
39
33
|
# str.size
|
40
34
|
# str.empty?
|
41
35
|
#
|
36
|
+
# # For example, if the receiver is a blank string, it will be incompatible.
|
37
|
+
# # If a negative value is specified for the receiver, `nil` is returned.
|
38
|
+
# str.chars.last # Incompatible with `str[-1]`.
|
39
|
+
# str.chars.last(2) # Incompatible with `str[-2..-1].chars`.
|
40
|
+
# str.chars.drop(2) # Incompatible with `str[2..-1].chars`.
|
41
|
+
#
|
42
42
|
class RedundantStringChars < Base
|
43
43
|
include RangeHelp
|
44
44
|
extend AutoCorrector
|
45
45
|
|
46
46
|
MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
|
47
|
-
RESTRICT_ON_SEND = %i[[] slice first
|
47
|
+
RESTRICT_ON_SEND = %i[[] slice first take length size empty?].freeze
|
48
48
|
|
49
49
|
def_node_matcher :redundant_chars_call?, <<~PATTERN
|
50
50
|
(send $(send _ :chars) $_ $...)
|
@@ -80,7 +80,6 @@ module RuboCop
|
|
80
80
|
format(MSG, good_method: good_method, bad_method: bad_method)
|
81
81
|
end
|
82
82
|
|
83
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
84
83
|
def build_good_method(method, args)
|
85
84
|
case method
|
86
85
|
when :[], :slice
|
@@ -91,21 +90,12 @@ module RuboCop
|
|
91
90
|
else
|
92
91
|
'[0]'
|
93
92
|
end
|
94
|
-
when :last
|
95
|
-
if args.any?
|
96
|
-
"[-#{args.first.source}..-1].chars"
|
97
|
-
else
|
98
|
-
'[-1]'
|
99
|
-
end
|
100
93
|
when :take
|
101
94
|
"[0...#{args.first.source}].chars"
|
102
|
-
when :drop
|
103
|
-
"[#{args.first.source}..-1].chars"
|
104
95
|
else
|
105
96
|
".#{method}"
|
106
97
|
end
|
107
98
|
end
|
108
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
109
99
|
|
110
100
|
def build_bad_method(method, args)
|
111
101
|
case method
|
@@ -78,8 +78,7 @@ module RuboCop
|
|
78
78
|
# Constants are included in this list because it is unlikely that
|
79
79
|
# someone will store `nil` as a constant and then use it for comparison
|
80
80
|
TYPES_IMPLEMENTING_MATCH = %i[const regexp str sym].freeze
|
81
|
-
MSG = 'Use `match?` instead of `%<current>s` when `MatchData` '
|
82
|
-
'is not used.'
|
81
|
+
MSG = 'Use `match?` instead of `%<current>s` when `MatchData` is not used.'
|
83
82
|
|
84
83
|
def_node_matcher :match_method?, <<~PATTERN
|
85
84
|
{
|
@@ -45,7 +45,10 @@ module RuboCop
|
|
45
45
|
return unless dup_string?(node) || string_new?(node)
|
46
46
|
|
47
47
|
add_offense(node) do |corrector|
|
48
|
-
|
48
|
+
string_value = "+#{string_value(node)}"
|
49
|
+
string_value = "(#{string_value})" if node.parent&.send_type?
|
50
|
+
|
51
|
+
corrector.replace(node, string_value)
|
49
52
|
end
|
50
53
|
end
|
51
54
|
|
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.11.
|
4
|
+
version: 1.11.5
|
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: 2021-
|
13
|
+
date: 2021-08-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rubocop
|