rubocop-performance 1.10.1 → 1.11.3
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 +1 -0
- data/config/default.yml +13 -0
- data/config/obsoletion.yml +7 -0
- data/lib/rubocop/cop/performance/chain_array_allocation.rb +2 -0
- data/lib/rubocop/cop/performance/flat_map.rb +2 -1
- data/lib/rubocop/cop/performance/map_compact.rb +84 -0
- data/lib/rubocop/cop/performance/redundant_block_call.rb +7 -1
- data/lib/rubocop/cop/performance/redundant_equality_comparison_block.rb +13 -4
- data/lib/rubocop/cop/performance/redundant_merge.rb +3 -0
- data/lib/rubocop/cop/performance/redundant_split_regexp_argument.rb +1 -1
- data/lib/rubocop/cop/performance/reverse_each.rb +18 -2
- data/lib/rubocop/cop/performance/select_map.rb +60 -0
- data/lib/rubocop/cop/performance_cops.rb +2 -0
- data/lib/rubocop/performance.rb +2 -0
- data/lib/rubocop/performance/version.rb +1 -1
- metadata +9 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 341ace76835db65803b9c7ef7d54f67dbb053c86c9e31b0a80b80f1514e96c29
|
4
|
+
data.tar.gz: 031bda91d5c5d1e66716f218472621c115cf247e364c25596c6fd9f470261aca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c324e059ffa5f0f98789d6336a41ab0135bdf1dcc8e3b45df83ac8bf75e7bae53fe1e40fb7ae0039d83567bd226709b47cd9cc09184819d16ce8c558d56d85e
|
7
|
+
data.tar.gz: a7c1698db1e6c9c16150f46df944c3f275c38c0f39bca1bc5f0961bdde6a1d14aa9acb9b19823b9f62f352a11120596559fd9cdef6e3343fd8e01bf71b816f96
|
data/README.md
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/rubocop-performance)
|
4
4
|
[](https://circleci.com/gh/rubocop/rubocop-performance)
|
5
|
+
[](https://discord.gg/wJjWvGRDmm)
|
5
6
|
|
6
7
|
Performance optimization analysis for your projects, as an extension to [RuboCop](https://github.com/rubocop/rubocop).
|
7
8
|
|
data/config/default.yml
CHANGED
@@ -174,6 +174,12 @@ Performance/IoReadlines:
|
|
174
174
|
Enabled: false
|
175
175
|
VersionAdded: '1.7'
|
176
176
|
|
177
|
+
Performance/MapCompact:
|
178
|
+
Description: 'Use `filter_map` instead of `collection.map(&:do_something).compact`.'
|
179
|
+
Enabled: pending
|
180
|
+
SafeAutoCorrect: false
|
181
|
+
VersionAdded: '1.11'
|
182
|
+
|
177
183
|
Performance/MethodObjectAsBlock:
|
178
184
|
Description: 'Use block explicitly instead of block-passing a method object.'
|
179
185
|
Reference: 'https://github.com/JuanitoFatas/fast-ruby#normal-way-to-apply-method-vs-method-code'
|
@@ -220,7 +226,9 @@ Performance/RedundantMerge:
|
|
220
226
|
Description: 'Use Hash#[]=, rather than Hash#merge! with a single key-value pair.'
|
221
227
|
Reference: 'https://github.com/JuanitoFatas/fast-ruby#hashmerge-vs-hash-code'
|
222
228
|
Enabled: true
|
229
|
+
Safe: false
|
223
230
|
VersionAdded: '0.36'
|
231
|
+
VersionChanged: '1.11'
|
224
232
|
# Max number of key-value pairs to consider an offense
|
225
233
|
MaxKeyValuePairs: 2
|
226
234
|
|
@@ -258,6 +266,11 @@ Performance/ReverseFirst:
|
|
258
266
|
Enabled: 'pending'
|
259
267
|
VersionAdded: '1.7'
|
260
268
|
|
269
|
+
Performance/SelectMap:
|
270
|
+
Description: 'Use `filter_map` instead of `ary.select(&:foo).map(&:bar)`.'
|
271
|
+
Enabled: false
|
272
|
+
VersionAdded: '1.11'
|
273
|
+
|
261
274
|
Performance/Size:
|
262
275
|
Description: >-
|
263
276
|
Use `size` instead of `count` for counting
|
@@ -63,6 +63,8 @@ module RuboCop
|
|
63
63
|
|
64
64
|
def on_send(node)
|
65
65
|
chain_array_allocation?(node) do |fm, sm|
|
66
|
+
return if node.each_descendant(:send).any? { |descendant| descendant.method?(:lazy) }
|
67
|
+
|
66
68
|
range = range_between(node.loc.dot.begin_pos, node.source_range.end_pos)
|
67
69
|
|
68
70
|
add_offense(range, message: format(MSG, method: fm, second_method: sm))
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Performance
|
6
|
+
# In Ruby 2.7, `Enumerable#filter_map` has been added.
|
7
|
+
#
|
8
|
+
# This cop identifies places where `map { ... }.compact` can be replaced by `filter_map`.
|
9
|
+
# It is marked as unsafe auto-correction by default because `map { ... }.compact`
|
10
|
+
# that is not compatible with `filter_map`.
|
11
|
+
#
|
12
|
+
# [source,ruby]
|
13
|
+
# ----
|
14
|
+
# [true, false, nil].compact #=> [true, false]
|
15
|
+
# [true, false, nil].filter_map(&:itself) #=> [true]
|
16
|
+
# ----
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# # bad
|
20
|
+
# ary.map(&:foo).compact
|
21
|
+
# ary.collect(&:foo).compact
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# ary.filter_map(&:foo)
|
25
|
+
# ary.map(&:foo).compact!
|
26
|
+
# ary.compact.map(&:foo)
|
27
|
+
#
|
28
|
+
class MapCompact < Base
|
29
|
+
include RangeHelp
|
30
|
+
extend AutoCorrector
|
31
|
+
extend TargetRubyVersion
|
32
|
+
|
33
|
+
MSG = 'Use `filter_map` instead.'
|
34
|
+
RESTRICT_ON_SEND = %i[compact].freeze
|
35
|
+
|
36
|
+
minimum_target_ruby_version 2.7
|
37
|
+
|
38
|
+
def_node_matcher :map_compact, <<~PATTERN
|
39
|
+
{
|
40
|
+
(send
|
41
|
+
$(send _ {:map :collect}
|
42
|
+
(block_pass
|
43
|
+
(sym _))) _)
|
44
|
+
(send
|
45
|
+
(block
|
46
|
+
$(send _ {:map :collect})
|
47
|
+
(args ...) _) _)
|
48
|
+
}
|
49
|
+
PATTERN
|
50
|
+
|
51
|
+
def on_send(node)
|
52
|
+
return unless (map_node = map_compact(node))
|
53
|
+
|
54
|
+
compact_loc = node.loc
|
55
|
+
range = range_between(map_node.loc.selector.begin_pos, compact_loc.selector.end_pos)
|
56
|
+
|
57
|
+
add_offense(range) do |corrector|
|
58
|
+
corrector.replace(map_node.loc.selector, 'filter_map')
|
59
|
+
corrector.remove(compact_loc.dot)
|
60
|
+
corrector.remove(compact_method_range(node))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def compact_method_range(compact_node)
|
67
|
+
chained_method = compact_node.parent
|
68
|
+
compact_method_range = compact_node.loc.selector
|
69
|
+
|
70
|
+
if compact_node.multiline? && chained_method&.loc.respond_to?(:selector) &&
|
71
|
+
!invoke_method_after_map_compact_on_same_line?(compact_node, chained_method)
|
72
|
+
range_by_whole_lines(compact_method_range, include_final_newline: true)
|
73
|
+
else
|
74
|
+
compact_method_range
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def invoke_method_after_map_compact_on_same_line?(compact_node, chained_method)
|
79
|
+
compact_node.loc.selector.line == chained_method.loc.selector.line
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -78,7 +78,7 @@ module RuboCop
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def calls_to_report(argname, body)
|
81
|
-
return [] if blockarg_assigned?(body, argname)
|
81
|
+
return [] if blockarg_assigned?(body, argname) || shadowed_block_argument?(body, argname)
|
82
82
|
|
83
83
|
blockarg_calls(body, argname).map do |call|
|
84
84
|
return [] if args_include_block_pass?(call)
|
@@ -87,6 +87,12 @@ module RuboCop
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
+
def shadowed_block_argument?(body, block_argument_of_method_signature)
|
91
|
+
return false unless body.block_type?
|
92
|
+
|
93
|
+
body.arguments.map(&:source).include?(block_argument_of_method_signature.to_s)
|
94
|
+
end
|
95
|
+
|
90
96
|
def args_include_block_pass?(blockcall)
|
91
97
|
_receiver, _call, *args = *blockcall
|
92
98
|
|
@@ -35,7 +35,8 @@ module RuboCop
|
|
35
35
|
IS_A_METHODS = %i[is_a? kind_of?].freeze
|
36
36
|
|
37
37
|
def on_block(node)
|
38
|
-
return unless TARGET_METHODS.include?(node.method_name)
|
38
|
+
return unless TARGET_METHODS.include?(node.method_name)
|
39
|
+
return unless one_block_argument?(node.arguments)
|
39
40
|
|
40
41
|
block_argument = node.arguments.first
|
41
42
|
block_body = node.body
|
@@ -53,14 +54,22 @@ module RuboCop
|
|
53
54
|
|
54
55
|
private
|
55
56
|
|
57
|
+
def one_block_argument?(block_arguments)
|
58
|
+
block_arguments.one? && !block_arguments.source.include?(',')
|
59
|
+
end
|
60
|
+
|
56
61
|
def use_equality_comparison_block?(block_body)
|
57
62
|
block_body.send_type? && COMPARISON_METHODS.include?(block_body.method_name)
|
58
63
|
end
|
59
64
|
|
60
65
|
def same_block_argument_and_is_a_argument?(block_body, block_argument)
|
61
|
-
|
62
|
-
|
63
|
-
|
66
|
+
if block_body.method?(:===)
|
67
|
+
block_argument.source != block_body.children[2].source
|
68
|
+
elsif IS_A_METHODS.include?(block_body.method_name)
|
69
|
+
block_argument.source == block_body.first_argument.source
|
70
|
+
else
|
71
|
+
false
|
72
|
+
end
|
64
73
|
end
|
65
74
|
|
66
75
|
def new_argument(block_argument, block_body)
|
@@ -8,6 +8,9 @@ module RuboCop
|
|
8
8
|
# You can set the maximum number of key-value pairs to consider
|
9
9
|
# an offense with `MaxKeyValuePairs`.
|
10
10
|
#
|
11
|
+
# This cop is marked as unsafe because RuboCop cannot determine if the
|
12
|
+
# receiver of `merge!` is actually a hash or not.
|
13
|
+
#
|
11
14
|
# @example
|
12
15
|
# # bad
|
13
16
|
# hash.merge!(a: 1)
|
@@ -26,7 +26,7 @@ module RuboCop
|
|
26
26
|
|
27
27
|
def on_send(node)
|
28
28
|
return unless (regexp_node = split_call_with_regexp?(node))
|
29
|
-
return if regexp_node.ignore_case?
|
29
|
+
return if regexp_node.ignore_case? || regexp_node.content == ' '
|
30
30
|
return unless determinist_regexp?(regexp_node)
|
31
31
|
|
32
32
|
add_offense(regexp_node) do |corrector|
|
@@ -6,12 +6,20 @@ module RuboCop
|
|
6
6
|
# This cop is used to identify usages of `reverse.each` and
|
7
7
|
# change them to use `reverse_each` instead.
|
8
8
|
#
|
9
|
+
# If the return value is used, it will not be detected because the result will be different.
|
10
|
+
#
|
11
|
+
# [source,ruby]
|
12
|
+
# ----
|
13
|
+
# [1, 2, 3].reverse.each {} #=> [3, 2, 1]
|
14
|
+
# [1, 2, 3].reverse_each {} #=> [1, 2, 3]
|
15
|
+
# ----
|
16
|
+
#
|
9
17
|
# @example
|
10
18
|
# # bad
|
11
|
-
#
|
19
|
+
# items.reverse.each
|
12
20
|
#
|
13
21
|
# # good
|
14
|
-
#
|
22
|
+
# items.reverse_each
|
15
23
|
class ReverseEach < Base
|
16
24
|
include RangeHelp
|
17
25
|
extend AutoCorrector
|
@@ -24,6 +32,8 @@ module RuboCop
|
|
24
32
|
MATCHER
|
25
33
|
|
26
34
|
def on_send(node)
|
35
|
+
return if use_return_value?(node)
|
36
|
+
|
27
37
|
reverse_each?(node) do
|
28
38
|
range = offense_range(node)
|
29
39
|
|
@@ -35,6 +45,12 @@ module RuboCop
|
|
35
45
|
|
36
46
|
private
|
37
47
|
|
48
|
+
def use_return_value?(node)
|
49
|
+
!!node.ancestors.detect do |ancestor|
|
50
|
+
ancestor.assignment? || ancestor.send_type? || ancestor.return_type?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
38
54
|
def offense_range(node)
|
39
55
|
range_between(node.children.first.loc.selector.begin_pos, node.loc.selector.end_pos)
|
40
56
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Performance
|
6
|
+
# In Ruby 2.7, `Enumerable#filter_map` has been added.
|
7
|
+
#
|
8
|
+
# This cop identifies places where `select.map` can be replaced by `filter_map`.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # bad
|
12
|
+
# ary.select(&:foo).map(&:bar)
|
13
|
+
# ary.filter(&:foo).map(&:bar)
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# ary.filter_map { |o| o.bar if o.foo }
|
17
|
+
#
|
18
|
+
class SelectMap < Base
|
19
|
+
include RangeHelp
|
20
|
+
extend TargetRubyVersion
|
21
|
+
|
22
|
+
minimum_target_ruby_version 2.7
|
23
|
+
|
24
|
+
MSG = 'Use `filter_map` instead of `%<method_name>s.map`.'
|
25
|
+
RESTRICT_ON_SEND = %i[select filter].freeze
|
26
|
+
|
27
|
+
def_node_matcher :bad_method?, <<~PATTERN
|
28
|
+
(send nil? :bad_method ...)
|
29
|
+
PATTERN
|
30
|
+
|
31
|
+
def on_send(node)
|
32
|
+
return if (first_argument = node.first_argument) && !first_argument.block_pass_type?
|
33
|
+
return unless (send_node = map_method_candidate(node))
|
34
|
+
return unless send_node.method?(:map)
|
35
|
+
|
36
|
+
map_method = send_node.parent&.block_type? ? send_node.parent : send_node
|
37
|
+
|
38
|
+
range = offense_range(node, map_method)
|
39
|
+
add_offense(range, message: format(MSG, method_name: node.method_name))
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def map_method_candidate(node)
|
45
|
+
return unless (parent = node.parent)
|
46
|
+
|
47
|
+
if parent.block_type? && parent.parent&.send_type?
|
48
|
+
parent.parent
|
49
|
+
elsif parent.send_type?
|
50
|
+
parent
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def offense_range(node, map_method)
|
55
|
+
range_between(node.loc.selector.begin_pos, map_method.loc.expression.end_pos)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -23,6 +23,7 @@ require_relative 'performance/end_with'
|
|
23
23
|
require_relative 'performance/fixed_size'
|
24
24
|
require_relative 'performance/flat_map'
|
25
25
|
require_relative 'performance/inefficient_hash_search'
|
26
|
+
require_relative 'performance/map_compact'
|
26
27
|
require_relative 'performance/method_object_as_block'
|
27
28
|
require_relative 'performance/open_struct'
|
28
29
|
require_relative 'performance/range_include'
|
@@ -37,6 +38,7 @@ require_relative 'performance/redundant_string_chars'
|
|
37
38
|
require_relative 'performance/regexp_match'
|
38
39
|
require_relative 'performance/reverse_each'
|
39
40
|
require_relative 'performance/reverse_first'
|
41
|
+
require_relative 'performance/select_map'
|
40
42
|
require_relative 'performance/size'
|
41
43
|
require_relative 'performance/sort_reverse'
|
42
44
|
require_relative 'performance/squeeze'
|
data/lib/rubocop/performance.rb
CHANGED
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.11.3
|
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-05-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rubocop
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ">="
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 1.7.0
|
22
22
|
- - "<"
|
23
23
|
- !ruby/object:Gem::Version
|
24
24
|
version: '2.0'
|
@@ -28,7 +28,7 @@ dependencies:
|
|
28
28
|
requirements:
|
29
29
|
- - ">="
|
30
30
|
- !ruby/object:Gem::Version
|
31
|
-
version:
|
31
|
+
version: 1.7.0
|
32
32
|
- - "<"
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: '2.0'
|
@@ -59,6 +59,7 @@ files:
|
|
59
59
|
- LICENSE.txt
|
60
60
|
- README.md
|
61
61
|
- config/default.yml
|
62
|
+
- config/obsoletion.yml
|
62
63
|
- lib/rubocop-performance.rb
|
63
64
|
- lib/rubocop/cop/mixin/regexp_metacharacter.rb
|
64
65
|
- lib/rubocop/cop/mixin/sort_block.rb
|
@@ -84,6 +85,7 @@ files:
|
|
84
85
|
- lib/rubocop/cop/performance/flat_map.rb
|
85
86
|
- lib/rubocop/cop/performance/inefficient_hash_search.rb
|
86
87
|
- lib/rubocop/cop/performance/io_readlines.rb
|
88
|
+
- lib/rubocop/cop/performance/map_compact.rb
|
87
89
|
- lib/rubocop/cop/performance/method_object_as_block.rb
|
88
90
|
- lib/rubocop/cop/performance/open_struct.rb
|
89
91
|
- lib/rubocop/cop/performance/range_include.rb
|
@@ -97,6 +99,7 @@ files:
|
|
97
99
|
- lib/rubocop/cop/performance/regexp_match.rb
|
98
100
|
- lib/rubocop/cop/performance/reverse_each.rb
|
99
101
|
- lib/rubocop/cop/performance/reverse_first.rb
|
102
|
+
- lib/rubocop/cop/performance/select_map.rb
|
100
103
|
- lib/rubocop/cop/performance/size.rb
|
101
104
|
- lib/rubocop/cop/performance/sort_reverse.rb
|
102
105
|
- lib/rubocop/cop/performance/squeeze.rb
|
@@ -118,7 +121,7 @@ metadata:
|
|
118
121
|
homepage_uri: https://docs.rubocop.org/rubocop-performance/
|
119
122
|
changelog_uri: https://github.com/rubocop/rubocop-performance/blob/master/CHANGELOG.md
|
120
123
|
source_code_uri: https://github.com/rubocop/rubocop-performance/
|
121
|
-
documentation_uri: https://docs.rubocop.org/rubocop-performance/1.
|
124
|
+
documentation_uri: https://docs.rubocop.org/rubocop-performance/1.11/
|
122
125
|
bug_tracker_uri: https://github.com/rubocop/rubocop-performance/issues
|
123
126
|
post_install_message:
|
124
127
|
rdoc_options: []
|
@@ -128,7 +131,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
128
131
|
requirements:
|
129
132
|
- - ">="
|
130
133
|
- !ruby/object:Gem::Version
|
131
|
-
version: 2.
|
134
|
+
version: 2.5.0
|
132
135
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
136
|
requirements:
|
134
137
|
- - ">="
|