rubocop-performance 1.8.1 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -0
  3. data/config/default.yml +25 -1
  4. data/lib/rubocop/cop/mixin/regexp_metacharacter.rb +4 -4
  5. data/lib/rubocop/cop/performance/ancestors_include.rb +1 -0
  6. data/lib/rubocop/cop/performance/array_semi_infinite_range_slice.rb +74 -0
  7. data/lib/rubocop/cop/performance/big_decimal_with_numeric_argument.rb +1 -0
  8. data/lib/rubocop/cop/performance/bind_call.rb +1 -0
  9. data/lib/rubocop/cop/performance/block_given_with_explicit_block.rb +52 -0
  10. data/lib/rubocop/cop/performance/caller.rb +13 -15
  11. data/lib/rubocop/cop/performance/casecmp.rb +1 -0
  12. data/lib/rubocop/cop/performance/constant_regexp.rb +68 -0
  13. data/lib/rubocop/cop/performance/count.rb +1 -0
  14. data/lib/rubocop/cop/performance/delete_prefix.rb +1 -0
  15. data/lib/rubocop/cop/performance/delete_suffix.rb +1 -0
  16. data/lib/rubocop/cop/performance/detect.rb +3 -2
  17. data/lib/rubocop/cop/performance/end_with.rb +1 -0
  18. data/lib/rubocop/cop/performance/fixed_size.rb +1 -0
  19. data/lib/rubocop/cop/performance/flat_map.rb +1 -0
  20. data/lib/rubocop/cop/performance/inefficient_hash_search.rb +2 -0
  21. data/lib/rubocop/cop/performance/io_readlines.rb +3 -7
  22. data/lib/rubocop/cop/performance/method_object_as_block.rb +32 -0
  23. data/lib/rubocop/cop/performance/open_struct.rb +1 -0
  24. data/lib/rubocop/cop/performance/range_include.rb +1 -0
  25. data/lib/rubocop/cop/performance/redundant_block_call.rb +4 -4
  26. data/lib/rubocop/cop/performance/redundant_match.rb +1 -0
  27. data/lib/rubocop/cop/performance/redundant_merge.rb +1 -0
  28. data/lib/rubocop/cop/performance/redundant_string_chars.rb +2 -6
  29. data/lib/rubocop/cop/performance/reverse_each.rb +1 -0
  30. data/lib/rubocop/cop/performance/reverse_first.rb +1 -0
  31. data/lib/rubocop/cop/performance/size.rb +1 -0
  32. data/lib/rubocop/cop/performance/squeeze.rb +2 -1
  33. data/lib/rubocop/cop/performance/start_with.rb +1 -0
  34. data/lib/rubocop/cop/performance/string_include.rb +2 -1
  35. data/lib/rubocop/cop/performance/string_replacement.rb +1 -0
  36. data/lib/rubocop/cop/performance/sum.rb +117 -15
  37. data/lib/rubocop/cop/performance/times_map.rb +1 -0
  38. data/lib/rubocop/cop/performance/unfreeze_string.rb +19 -1
  39. data/lib/rubocop/cop/performance/uri_default_parser.rb +1 -0
  40. data/lib/rubocop/cop/performance_cops.rb +4 -0
  41. data/lib/rubocop/performance/version.rb +6 -1
  42. metadata +19 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1f4841e8542a1f77f21d30ffe7c26019b9f2fb7308a985780506f1920146045
4
- data.tar.gz: ed95379cd20af662ce6ce9ce4e64721ca156a6d7b62e511774df9d6abe3c9bae
3
+ metadata.gz: 9b44c147120a9f64f16a0bf21782f1dbe0a51c64170c3a5c217e548eded4e106
4
+ data.tar.gz: 7b4e6e464ee3631071f3bd3f447acde2a59763d326a86658412f4ec9527850a6
5
5
  SHA512:
6
- metadata.gz: 10a1e89448abd75234807bbdd9be67b10e4b9a837d2d2d711adeb0a0d105b921d722dfcac0c46e30f55f278afc2960f888407959543097d81df4f1aa3667fac6
7
- data.tar.gz: 668784bfe08775a1e8917806ef9f34d7dcb3f7581a9080ea14a44a54b43cf7e6516db4f5c4e015718824c32a8b045f43b429c8e1d3864960f41ead8684fbb5f5
6
+ metadata.gz: e450740a348bd17e276af8393f4e8225521afc4c9fac5816c9a3bbd9883d16a15f28a1044e24b89c9037593f4d2931cf3dc900385d42d7ad035dbb1dd461a306
7
+ data.tar.gz: feef1ae1d9735d3abadf17799ecfb4840ce359fa932902387633e67dc15e1eeb62573ae0a2832c050a8722e004f614c109483a9d8857143f28c866dbd65bc5bf
data/README.md CHANGED
@@ -76,6 +76,14 @@ Performance/Size:
76
76
 
77
77
  You can read a lot more about RuboCop Performance in its [official docs](https://docs.rubocop.org/rubocop-performance/).
78
78
 
79
+ ## Compatibility
80
+
81
+ RuboCop Performance complies with the RuboCop core compatibility.
82
+
83
+ See the [compatibility documentation](https://docs.rubocop.org/rubocop/compatibility.html) for further details.
84
+
85
+ **Note:** Performance cops are all MRI focused and are highly dependent of the version of MRI you're using.
86
+
79
87
  ## Contributing
80
88
 
81
89
  Checkout the [contribution guidelines](CONTRIBUTING.md).
@@ -7,6 +7,11 @@ Performance/AncestorsInclude:
7
7
  Safe: false
8
8
  VersionAdded: '1.7'
9
9
 
10
+ Performance/ArraySemiInfiniteRangeSlice:
11
+ Description: 'Identifies places where slicing arrays with semi-infinite ranges can be replaced by `Array#take` and `Array#drop`.'
12
+ Enabled: pending
13
+ VersionAdded: '1.9'
14
+
10
15
  Performance/BigDecimalWithNumericArgument:
11
16
  Description: 'Convert numeric argument to string before passing to BigDecimal.'
12
17
  Enabled: 'pending'
@@ -17,11 +22,17 @@ Performance/BindCall:
17
22
  Enabled: true
18
23
  VersionAdded: '1.6'
19
24
 
25
+ Performance/BlockGivenWithExplicitBlock:
26
+ Description: 'Check block argument explicitly instead of using `block_given?`.'
27
+ Enabled: pending
28
+ VersionAdded: '1.9'
29
+
20
30
  Performance/Caller:
21
31
  Description: >-
22
32
  Use `caller(n..n)` instead of `caller`.
23
33
  Enabled: true
24
34
  VersionAdded: '0.49'
35
+ VersionChanged: '1.9'
25
36
 
26
37
  Performance/CaseWhenSplat:
27
38
  Description: >-
@@ -51,7 +62,7 @@ Performance/ChainArrayAllocation:
51
62
 
52
63
  Performance/CollectionLiteralInLoop:
53
64
  Description: 'Extract Array and Hash literals outside of loops into local variables or constants.'
54
- Enabled: true
65
+ Enabled: 'pending'
55
66
  VersionAdded: '1.8'
56
67
  # Min number of elements to consider an offense
57
68
  MinSize: 1
@@ -61,6 +72,11 @@ Performance/CompareWithBlock:
61
72
  Enabled: true
62
73
  VersionAdded: '0.46'
63
74
 
75
+ Performance/ConstantRegexp:
76
+ Description: 'Finds regular expressions with dynamic components that are all constants.'
77
+ Enabled: pending
78
+ VersionAdded: '1.9'
79
+
64
80
  Performance/Count:
65
81
  Description: >-
66
82
  Use `count` instead of `{select,find_all,filter,reject}...{size,count,length}`.
@@ -154,6 +170,12 @@ Performance/IoReadlines:
154
170
  Enabled: false
155
171
  VersionAdded: '1.7'
156
172
 
173
+ Performance/MethodObjectAsBlock:
174
+ Description: 'Use block explicitly instead of block-passing a method object.'
175
+ Reference: 'https://github.com/JuanitoFatas/fast-ruby#normal-way-to-apply-method-vs-method-code'
176
+ Enabled: pending
177
+ VersionAdded: '1.9'
178
+
157
179
  Performance/OpenStruct:
158
180
  Description: 'Use `Struct` instead of `OpenStruct`.'
159
181
  Enabled: false
@@ -283,7 +305,9 @@ Performance/TimesMap:
283
305
  Performance/UnfreezeString:
284
306
  Description: 'Use unary plus to get an unfrozen string literal.'
285
307
  Enabled: true
308
+ SafeAutoCorrect: false
286
309
  VersionAdded: '0.50'
310
+ VersionChanged: '1.9'
287
311
 
288
312
  Performance/UriDefaultParser:
289
313
  Description: 'Use `URI::DEFAULT_PARSER` instead of `URI::Parser.new`.'
@@ -25,7 +25,7 @@ module RuboCop
25
25
  # (tricky: \s, \d, and so on are metacharacters, but other characters
26
26
  # escaped with a slash are just literals. LITERAL_REGEX takes all
27
27
  # that into account.)
28
- /\A\\A(?:#{Util::LITERAL_REGEX})+\z/.match?(regex_str)
28
+ /\A\\A(?:#{Util::LITERAL_REGEX})+\z/o.match?(regex_str)
29
29
  end
30
30
 
31
31
  def literal_at_start_with_caret?(regex_str)
@@ -35,21 +35,21 @@ module RuboCop
35
35
  # (tricky: \s, \d, and so on are metacharacters, but other characters
36
36
  # escaped with a slash are just literals. LITERAL_REGEX takes all
37
37
  # that into account.)
38
- /\A\^(?:#{Util::LITERAL_REGEX})+\z/.match?(regex_str)
38
+ /\A\^(?:#{Util::LITERAL_REGEX})+\z/o.match?(regex_str)
39
39
  end
40
40
 
41
41
  def literal_at_end_with_backslash_z?(regex_str)
42
42
  # is this regexp 'literal' in the sense of only matching literal
43
43
  # chars, rather than using metachars like . and * and so on?
44
44
  # also, is it anchored at the end of the string?
45
- /\A(?:#{Util::LITERAL_REGEX})+\\z\z/.match?(regex_str)
45
+ /\A(?:#{Util::LITERAL_REGEX})+\\z\z/o.match?(regex_str)
46
46
  end
47
47
 
48
48
  def literal_at_end_with_dollar?(regex_str)
49
49
  # is this regexp 'literal' in the sense of only matching literal
50
50
  # chars, rather than using metachars like . and * and so on?
51
51
  # also, is it anchored at the end of the string?
52
- /\A(?:#{Util::LITERAL_REGEX})+\$\z/.match?(regex_str)
52
+ /\A(?:#{Util::LITERAL_REGEX})+\$\z/o.match?(regex_str)
53
53
  end
54
54
 
55
55
  def drop_start_metacharacter(regexp_string)
@@ -18,6 +18,7 @@ module RuboCop
18
18
  extend AutoCorrector
19
19
 
20
20
  MSG = 'Use `<=` instead of `ancestors.include?`.'
21
+ RESTRICT_ON_SEND = %i[include?].freeze
21
22
 
22
23
  def_node_matcher :ancestors_include_candidate?, <<~PATTERN
23
24
  (send (send $_subclass :ancestors) :include? $_superclass)
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Performance
6
+ # This cop identifies places where slicing arrays with semi-infinite ranges
7
+ # can be replaced by `Array#take` and `Array#drop`.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # # array[..2]
12
+ # # array[...2]
13
+ # # array[2..]
14
+ # # array[2...]
15
+ # # array.slice(..2)
16
+ #
17
+ # # good
18
+ # array.take(3)
19
+ # array.take(2)
20
+ # array.drop(2)
21
+ # array.drop(2)
22
+ # array.take(3)
23
+ #
24
+ class ArraySemiInfiniteRangeSlice < Base
25
+ include RangeHelp
26
+ extend AutoCorrector
27
+ extend TargetRubyVersion
28
+
29
+ minimum_target_ruby_version 2.7
30
+
31
+ MSG = 'Use `%<prefer>s` instead of `%<current>s` with semi-infinite range.'
32
+
33
+ SLICE_METHODS = Set[:[], :slice].freeze
34
+ RESTRICT_ON_SEND = SLICE_METHODS
35
+
36
+ def_node_matcher :endless_range_slice?, <<~PATTERN
37
+ (send $_ $%SLICE_METHODS $#endless_range?)
38
+ PATTERN
39
+
40
+ def_node_matcher :endless_range?, <<~PATTERN
41
+ {
42
+ ({irange erange} nil? (int positive?))
43
+ ({irange erange} (int positive?) nil?)
44
+ }
45
+ PATTERN
46
+
47
+ def on_send(node)
48
+ endless_range_slice?(node) do |receiver, method_name, range_node|
49
+ prefer = range_node.begin ? :drop : :take
50
+ message = format(MSG, prefer: prefer, current: method_name)
51
+
52
+ add_offense(node, message: message) do |corrector|
53
+ corrector.replace(node, correction(receiver, range_node))
54
+ end
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def correction(receiver, range_node)
61
+ method_call = if range_node.begin
62
+ "drop(#{range_node.begin.value})"
63
+ elsif range_node.irange_type?
64
+ "take(#{range_node.end.value + 1})"
65
+ else
66
+ "take(#{range_node.end.value})"
67
+ end
68
+
69
+ "#{receiver.source}.#{method_call}"
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -20,6 +20,7 @@ module RuboCop
20
20
  extend AutoCorrector
21
21
 
22
22
  MSG = 'Convert numeric argument to string before passing to `BigDecimal`.'
23
+ RESTRICT_ON_SEND = %i[BigDecimal].freeze
23
24
 
24
25
  def_node_matcher :big_decimal_with_numeric_argument?, <<~PATTERN
25
26
  (send nil? :BigDecimal $numeric_type? ...)
@@ -28,6 +28,7 @@ module RuboCop
28
28
 
29
29
  MSG = 'Use `bind_call(%<bind_arg>s%<comma>s%<call_args>s)` ' \
30
30
  'instead of `bind(%<bind_arg>s).call(%<call_args>s)`.'
31
+ RESTRICT_ON_SEND = %i[call].freeze
31
32
 
32
33
  def_node_matcher :bind_with_call_method?, <<~PATTERN
33
34
  (send
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Performance
6
+ # This cop identifies unnecessary use of a `block_given?` where explicit check
7
+ # of block argument would suffice.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # def method(&block)
12
+ # do_something if block_given?
13
+ # end
14
+ #
15
+ # # good
16
+ # def method(&block)
17
+ # do_something if block
18
+ # end
19
+ #
20
+ # # good - block is reassigned
21
+ # def method(&block)
22
+ # block ||= -> { do_something }
23
+ # warn "Using default ..." unless block_given?
24
+ # # ...
25
+ # end
26
+ #
27
+ class BlockGivenWithExplicitBlock < Base
28
+ extend AutoCorrector
29
+
30
+ RESTRICT_ON_SEND = %i[block_given?].freeze
31
+ MSG = 'Check block argument explicitly instead of using `block_given?`.'
32
+
33
+ def_node_matcher :reassigns_block_arg?, '`(lvasgn %1 ...)'
34
+
35
+ def on_send(node)
36
+ def_node = node.each_ancestor(:def, :defs).first
37
+ return unless def_node
38
+
39
+ block_arg = def_node.arguments.find(&:blockarg_type?)
40
+ return unless block_arg
41
+
42
+ block_arg_name = block_arg.loc.name.source.to_sym
43
+ return if reassigns_block_arg?(def_node, block_arg_name)
44
+
45
+ add_offense(node) do |corrector|
46
+ corrector.replace(node, block_arg_name)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -19,10 +19,10 @@ module RuboCop
19
19
  # caller_locations(2..2).first
20
20
  # caller_locations(1..1).first
21
21
  class Caller < Base
22
- MSG_BRACE = 'Use `%<method>s(%<n>d..%<n>d).first`' \
23
- ' instead of `%<method>s[%<m>d]`.'
24
- MSG_FIRST = 'Use `%<method>s(%<n>d..%<n>d).first`' \
25
- ' instead of `%<method>s.first`.'
22
+ extend AutoCorrector
23
+
24
+ MSG = 'Use `%<preferred_method>s` instead of `%<current_method>s`.'
25
+ RESTRICT_ON_SEND = %i[first []].freeze
26
26
 
27
27
  def_node_matcher :slow_caller?, <<~PATTERN
28
28
  {
@@ -41,26 +41,24 @@ module RuboCop
41
41
  def on_send(node)
42
42
  return unless caller_with_scope_method?(node)
43
43
 
44
- message = message(node)
45
- add_offense(node, message: message)
46
- end
47
-
48
- private
49
-
50
- def message(node)
51
44
  method_name = node.receiver.method_name
52
45
  caller_arg = node.receiver.first_argument
53
46
  n = caller_arg ? int_value(caller_arg) : 1
54
-
55
47
  if node.method?(:[])
56
48
  m = int_value(node.first_argument)
57
49
  n += m
58
- format(MSG_BRACE, n: n, m: m, method: method_name)
59
- else
60
- format(MSG_FIRST, n: n, method: method_name)
50
+ end
51
+
52
+ preferred_method = "#{method_name}(#{n}..#{n}).first"
53
+
54
+ message = format(MSG, preferred_method: preferred_method, current_method: node.source)
55
+ add_offense(node, message: message) do |corrector|
56
+ corrector.replace(node, preferred_method)
61
57
  end
62
58
  end
63
59
 
60
+ private
61
+
64
62
  def int_value(node)
65
63
  node.children[0]
66
64
  end
@@ -23,6 +23,7 @@ module RuboCop
23
23
  extend AutoCorrector
24
24
 
25
25
  MSG = 'Use `%<good>s` instead of `%<bad>s`.'
26
+ RESTRICT_ON_SEND = %i[== eql? !=].freeze
26
27
  CASE_METHODS = %i[downcase upcase].freeze
27
28
 
28
29
  def_node_matcher :downcase_eq, <<~PATTERN
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Performance
6
+ # This cop finds regular expressions with dynamic components that are all constants.
7
+ #
8
+ # Ruby allocates a new Regexp object every time it executes a code containing such
9
+ # a regular expression. It is more efficient to extract it into a constant
10
+ # or add an `/o` option to perform `#{}` interpolation only once and reuse that
11
+ # Regexp object.
12
+ #
13
+ # @example
14
+ #
15
+ # # bad
16
+ # def tokens(pattern)
17
+ # pattern.scan(TOKEN).reject { |token| token.match?(/\A#{SEPARATORS}\Z/) }
18
+ # end
19
+ #
20
+ # # good
21
+ # ALL_SEPARATORS = /\A#{SEPARATORS}\Z/
22
+ # def tokens(pattern)
23
+ # pattern.scan(TOKEN).reject { |token| token.match?(ALL_SEPARATORS) }
24
+ # end
25
+ #
26
+ # # good
27
+ # def tokens(pattern)
28
+ # pattern.scan(TOKEN).reject { |token| token.match?(/\A#{SEPARATORS}\Z/o) }
29
+ # end
30
+ #
31
+ class ConstantRegexp < Base
32
+ extend AutoCorrector
33
+
34
+ MSG = 'Extract this regexp into a constant or append an `/o` option to its options.'
35
+
36
+ def on_regexp(node)
37
+ return if within_const_assignment?(node) ||
38
+ !include_interpolated_const?(node) ||
39
+ node.single_interpolation?
40
+
41
+ add_offense(node) do |corrector|
42
+ corrector.insert_after(node, 'o')
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def within_const_assignment?(node)
49
+ node.each_ancestor(:casgn).any?
50
+ end
51
+
52
+ def_node_matcher :regexp_escape?, <<~PATTERN
53
+ (send
54
+ (const nil? :Regexp) :escape const_type?)
55
+ PATTERN
56
+
57
+ def include_interpolated_const?(node)
58
+ return false unless node.interpolation?
59
+
60
+ node.each_child_node(:begin).all? do |begin_node|
61
+ inner_node = begin_node.children.first
62
+ inner_node && (inner_node.const_type? || regexp_escape?(inner_node))
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -42,6 +42,7 @@ module RuboCop
42
42
  extend AutoCorrector
43
43
 
44
44
  MSG = 'Use `count` instead of `%<selector>s...%<counter>s`.'
45
+ RESTRICT_ON_SEND = %i[count length size].freeze
45
46
 
46
47
  def_node_matcher :count_candidate?, <<~PATTERN
47
48
  {
@@ -51,6 +51,7 @@ module RuboCop
51
51
  minimum_target_ruby_version 2.5
52
52
 
53
53
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
54
+ RESTRICT_ON_SEND = %i[gsub gsub! sub sub!].freeze
54
55
 
55
56
  PREFERRED_METHODS = {
56
57
  gsub: :delete_prefix,
@@ -51,6 +51,7 @@ module RuboCop
51
51
  minimum_target_ruby_version 2.5
52
52
 
53
53
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
54
+ RESTRICT_ON_SEND = %i[gsub gsub! sub sub!].freeze
54
55
 
55
56
  PREFERRED_METHODS = {
56
57
  gsub: :delete_suffix,
@@ -4,8 +4,8 @@ module RuboCop
4
4
  module Cop
5
5
  module Performance
6
6
  # This cop is used to identify usages of `first`, `last`, `[0]` or `[-1]`
7
- # chained to `select`, `find_all`, or `find_all`
8
- # and change them to use `detect` instead.
7
+ # chained to `select`, `find_all` or `filter` and change them to use
8
+ # `detect` instead.
9
9
  #
10
10
  # @example
11
11
  # # bad
@@ -39,6 +39,7 @@ module RuboCop
39
39
  '`%<first_method>s[%<index>i]`.'
40
40
  INDEX_REVERSE_MSG = 'Use `reverse.%<prefer>s` instead of ' \
41
41
  '`%<first_method>s[%<index>i]`.'
42
+ RESTRICT_ON_SEND = %i[first last []].freeze
42
43
 
43
44
  def_node_matcher :detect_candidate?, <<~PATTERN
44
45
  {
@@ -47,6 +47,7 @@ module RuboCop
47
47
 
48
48
  MSG = 'Use `String#end_with?` instead of a regex match anchored to ' \
49
49
  'the end of the string.'
50
+ RESTRICT_ON_SEND = %i[match =~ match?].freeze
50
51
 
51
52
  def_node_matcher :redundant_regex?, <<~PATTERN
52
53
  {(send $!nil? {:match :=~ :match?} (regexp (str $#literal_at_end?) (regopt)))
@@ -47,6 +47,7 @@ module RuboCop
47
47
  #
48
48
  class FixedSize < Base
49
49
  MSG = 'Do not compute the size of statically sized objects.'
50
+ RESTRICT_ON_SEND = %i[count length size].freeze
50
51
 
51
52
  def_node_matcher :counter, <<~MATCHER
52
53
  (send ${array hash str sym} {:count :length :size} $...)
@@ -19,6 +19,7 @@ module RuboCop
19
19
  extend AutoCorrector
20
20
 
21
21
  MSG = 'Use `flat_map` instead of `%<method>s...%<flatten>s`.'
22
+ RESTRICT_ON_SEND = %i[flatten flatten!].freeze
22
23
  FLATTEN_MULTIPLE_LEVELS = ' Beware, `flat_map` only flattens 1 level ' \
23
24
  'and `flatten` can be used to flatten ' \
24
25
  'multiple levels.'
@@ -39,6 +39,8 @@ module RuboCop
39
39
  class InefficientHashSearch < Base
40
40
  extend AutoCorrector
41
41
 
42
+ RESTRICT_ON_SEND = %i[include?].freeze
43
+
42
44
  def_node_matcher :inefficient_include?, <<~PATTERN
43
45
  (send (send $_ {:keys :values}) :include? _)
44
46
  PATTERN
@@ -29,14 +29,14 @@ module RuboCop
29
29
  extend AutoCorrector
30
30
 
31
31
  MSG = 'Use `%<good>s` instead of `%<bad>s`.'
32
- ENUMERABLE_METHODS = (Enumerable.instance_methods + [:each]).freeze
32
+ RESTRICT_ON_SEND = (Enumerable.instance_methods + [:each]).freeze
33
33
 
34
34
  def_node_matcher :readlines_on_class?, <<~PATTERN
35
- $(send $(send (const nil? {:IO :File}) :readlines ...) #enumerable_method?)
35
+ $(send $(send (const nil? {:IO :File}) :readlines ...) _)
36
36
  PATTERN
37
37
 
38
38
  def_node_matcher :readlines_on_instance?, <<~PATTERN
39
- $(send $(send ${nil? !const_type?} :readlines ...) #enumerable_method? ...)
39
+ $(send $(send ${nil? !const_type?} :readlines ...) _ ...)
40
40
  PATTERN
41
41
 
42
42
  def on_send(node)
@@ -55,10 +55,6 @@ module RuboCop
55
55
 
56
56
  private
57
57
 
58
- def enumerable_method?(node)
59
- ENUMERABLE_METHODS.include?(node.to_sym)
60
- end
61
-
62
58
  def autocorrect(corrector, enumerable_call, readlines_call, receiver)
63
59
  # We cannot safely correct `.readlines` method called on IO/File classes
64
60
  # due to its signature and we are not sure with implicit receiver
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Performance
6
+ # This cop identifies places where methods are converted to blocks, with the
7
+ # use of `&method`, and passed as arguments to method calls.
8
+ # It is faster to replace those with explicit blocks, calling those methods inside.
9
+ #
10
+ # @example
11
+ # # bad
12
+ # array.map(&method(:do_something))
13
+ # [1, 2, 3].each(&out.method(:puts))
14
+ #
15
+ # # good
16
+ # array.map { |x| do_something(x) }
17
+ # [1, 2, 3].each { |x| out.puts(x) }
18
+ #
19
+ class MethodObjectAsBlock < Base
20
+ MSG = 'Use block explicitly instead of block-passing a method object.'
21
+
22
+ def_node_matcher :method_object_as_argument?, <<~PATTERN
23
+ (^send (send _ :method sym))
24
+ PATTERN
25
+
26
+ def on_block_pass(node)
27
+ add_offense(node) if method_object_as_argument?(node)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -30,6 +30,7 @@ module RuboCop
30
30
  class OpenStruct < Base
31
31
  MSG = 'Consider using `Struct` over `OpenStruct` ' \
32
32
  'to optimize the performance.'
33
+ RESTRICT_ON_SEND = %i[new].freeze
33
34
 
34
35
  def_node_matcher :open_struct, <<~PATTERN
35
36
  (send (const {nil? cbase} :OpenStruct) :new ...)
@@ -28,6 +28,7 @@ module RuboCop
28
28
  extend AutoCorrector
29
29
 
30
30
  MSG = 'Use `Range#cover?` instead of `Range#%<bad_method>s`.'
31
+ RESTRICT_ON_SEND = %i[include? member?].freeze
31
32
 
32
33
  # TODO: If we traced out assignments of variables to their uses, we
33
34
  # might pick up on a few more instances of this issue
@@ -80,11 +80,11 @@ module RuboCop
80
80
  def calls_to_report(argname, body)
81
81
  return [] if blockarg_assigned?(body, argname)
82
82
 
83
- calls = to_enum(:blockarg_calls, body, argname)
83
+ blockarg_calls(body, argname).map do |call|
84
+ return [] if args_include_block_pass?(call)
84
85
 
85
- return [] if calls.any? { |call| args_include_block_pass?(call) }
86
-
87
- calls
86
+ call
87
+ end
88
88
  end
89
89
 
90
90
  def args_include_block_pass?(blockcall)
@@ -22,6 +22,7 @@ module RuboCop
22
22
 
23
23
  MSG = 'Use `=~` in places where the `MatchData` returned by ' \
24
24
  '`#match` will not be used.'
25
+ RESTRICT_ON_SEND = %i[match].freeze
25
26
 
26
27
  # 'match' is a fairly generic name, so we don't flag it unless we see
27
28
  # a string or regexp literal on one side or the other
@@ -29,6 +29,7 @@ module RuboCop
29
29
 
30
30
  AREF_ASGN = '%<receiver>s[%<key>s] = %<value>s'
31
31
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
32
+ RESTRICT_ON_SEND = %i[merge!].freeze
32
33
 
33
34
  WITH_MODIFIER_CORRECTION = <<~RUBY
34
35
  %<keyword>s %<condition>s
@@ -44,10 +44,10 @@ module RuboCop
44
44
  extend AutoCorrector
45
45
 
46
46
  MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
47
- REPLACEABLE_METHODS = %i[[] slice first last take drop length size empty?].freeze
47
+ RESTRICT_ON_SEND = %i[[] slice first last take drop length size empty?].freeze
48
48
 
49
49
  def_node_matcher :redundant_chars_call?, <<~PATTERN
50
- (send $(send _ :chars) $#replaceable_method? $...)
50
+ (send $(send _ :chars) $_ $...)
51
51
  PATTERN
52
52
 
53
53
  def on_send(node)
@@ -66,10 +66,6 @@ module RuboCop
66
66
 
67
67
  private
68
68
 
69
- def replaceable_method?(method_name)
70
- REPLACEABLE_METHODS.include?(method_name)
71
- end
72
-
73
69
  def offense_range(receiver, node)
74
70
  range_between(receiver.loc.selector.begin_pos, node.loc.expression.end_pos)
75
71
  end
@@ -17,6 +17,7 @@ module RuboCop
17
17
  extend AutoCorrector
18
18
 
19
19
  MSG = 'Use `reverse_each` instead of `reverse.each`.'
20
+ RESTRICT_ON_SEND = %i[each].freeze
20
21
  UNDERSCORE = '_'
21
22
 
22
23
  def_node_matcher :reverse_each?, <<~MATCHER
@@ -21,6 +21,7 @@ module RuboCop
21
21
  extend AutoCorrector
22
22
 
23
23
  MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
24
+ RESTRICT_ON_SEND = %i[first].freeze
24
25
 
25
26
  def_node_matcher :reverse_first_candidate?, <<~PATTERN
26
27
  (send $(send _ :reverse) :first (int _)?)
@@ -39,6 +39,7 @@ module RuboCop
39
39
  extend AutoCorrector
40
40
 
41
41
  MSG = 'Use `size` instead of `count`.'
42
+ RESTRICT_ON_SEND = %i[count].freeze
42
43
 
43
44
  def_node_matcher :array?, <<~PATTERN
44
45
  {
@@ -22,6 +22,7 @@ module RuboCop
22
22
  extend AutoCorrector
23
23
 
24
24
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
25
+ RESTRICT_ON_SEND = %i[gsub gsub!].freeze
25
26
 
26
27
  PREFERRED_METHODS = {
27
28
  gsub: :squeeze,
@@ -58,7 +59,7 @@ module RuboCop
58
59
  private
59
60
 
60
61
  def repeating_literal?(regex_str)
61
- regex_str.match?(/\A(?:#{Util::LITERAL_REGEX})\+\z/)
62
+ regex_str.match?(/\A(?:#{Util::LITERAL_REGEX})\+\z/o)
62
63
  end
63
64
  end
64
65
  end
@@ -47,6 +47,7 @@ module RuboCop
47
47
 
48
48
  MSG = 'Use `String#start_with?` instead of a regex match anchored to ' \
49
49
  'the beginning of the string.'
50
+ RESTRICT_ON_SEND = %i[match =~ match?].freeze
50
51
 
51
52
  def_node_matcher :redundant_regex?, <<~PATTERN
52
53
  {(send $!nil? {:match :=~ :match?} (regexp (str $#literal_at_start?) (regopt)))
@@ -23,6 +23,7 @@ module RuboCop
23
23
  extend AutoCorrector
24
24
 
25
25
  MSG = 'Use `String#include?` instead of a regex match with literal-only pattern.'
26
+ RESTRICT_ON_SEND = %i[match =~ match?].freeze
26
27
 
27
28
  def_node_matcher :redundant_regex?, <<~PATTERN
28
29
  {(send $!nil? {:match :=~ :match?} (regexp (str $#literal?) (regopt)))
@@ -47,7 +48,7 @@ module RuboCop
47
48
  private
48
49
 
49
50
  def literal?(regex_str)
50
- regex_str.match?(/\A#{Util::LITERAL_REGEX}+\z/)
51
+ regex_str.match?(/\A#{Util::LITERAL_REGEX}+\z/o)
51
52
  end
52
53
  end
53
54
  end
@@ -23,6 +23,7 @@ module RuboCop
23
23
  extend AutoCorrector
24
24
 
25
25
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
26
+ RESTRICT_ON_SEND = %i[gsub gsub!].freeze
26
27
  DETERMINISTIC_REGEX = /\A(?:#{LITERAL_REGEX})+\Z/.freeze
27
28
  DELETE = 'delete'
28
29
  TR = 'tr'
@@ -6,28 +6,67 @@ module RuboCop
6
6
  # This cop identifies places where custom code finding the sum of elements
7
7
  # in some Enumerable object can be replaced by `Enumerable#sum` method.
8
8
  #
9
+ # This cop can change auto-correction scope depending on the value of
10
+ # `SafeAutoCorrect`.
11
+ # Its auto-correction is marked as safe by default (`SafeAutoCorrect: true`)
12
+ # to prevent `TypeError` in auto-correced code when initial value is not
13
+ # specified as shown below:
14
+ #
15
+ # [source,ruby]
16
+ # ----
17
+ # ['a', 'b'].sum # => (String can't be coerced into Integer)
18
+ # ----
19
+ #
20
+ # Therefore if initial value is not specified, unsafe auto-corrected will not occur.
21
+ #
22
+ # If you always want to enable auto-correction, you can set `SafeAutoCorrect: false`.
23
+ #
24
+ # [source,yaml]
25
+ # ----
26
+ # Performance/Sum:
27
+ # SafeAutoCorrect: false
28
+ # ----
29
+ #
30
+ # Please note that the auto-correction command line option will be changed from
31
+ # `rubocop -a` to `rubocop -A`, which includes unsafe auto-correction.
32
+ #
9
33
  # @example
10
34
  # # bad
11
- # [1, 2, 3].inject(:+)
35
+ # [1, 2, 3].inject(:+) # These bad cases with no initial value are unsafe and
36
+ # [1, 2, 3].inject(&:+) # will not be auto-correced by default. If you want to
37
+ # [1, 2, 3].reduce { |acc, elem| acc + elem } # auto-corrected, you can set `SafeAutoCorrect: false`.
12
38
  # [1, 2, 3].reduce(10, :+)
13
- # [1, 2, 3].inject(&:+)
14
- # [1, 2, 3].reduce { |acc, elem| acc + elem }
39
+ # [1, 2, 3].map { |elem| elem ** 2 }.sum
40
+ # [1, 2, 3].collect(&:count).sum(10)
15
41
  #
16
42
  # # good
17
43
  # [1, 2, 3].sum
18
44
  # [1, 2, 3].sum(10)
19
- # [1, 2, 3].sum
45
+ # [1, 2, 3].sum { |elem| elem ** 2 }
46
+ # [1, 2, 3].sum(10, &:count)
20
47
  #
21
48
  class Sum < Base
22
49
  include RangeHelp
23
50
  extend AutoCorrector
24
51
 
25
52
  MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
53
+ MSG_IF_NO_INIT_VALUE =
54
+ 'Use `%<good_method>s` instead of `%<bad_method>s`, unless calling `%<bad_method>s` on an empty array.'
55
+ RESTRICT_ON_SEND = %i[inject reduce sum].freeze
26
56
 
27
57
  def_node_matcher :sum_candidate?, <<~PATTERN
28
58
  (send _ ${:inject :reduce} $_init ? ${(sym :+) (block_pass (sym :+))})
29
59
  PATTERN
30
60
 
61
+ def_node_matcher :sum_map_candidate?, <<~PATTERN
62
+ (send
63
+ {
64
+ (block $(send _ {:map :collect}) ...)
65
+ $(send _ {:map :collect} (block_pass _))
66
+ }
67
+ :sum $_init ?)
68
+ PATTERN
69
+
31
70
  def_node_matcher :sum_with_block_candidate?, <<~PATTERN
32
71
  (block
33
72
  $(send _ {:inject :reduce} $_init ?)
@@ -41,14 +80,10 @@ module RuboCop
41
80
  alias elem_plus_acc? acc_plus_elem?
42
81
 
43
82
  def on_send(node)
44
- sum_candidate?(node) do |method, init, operation|
45
- range = sum_method_range(node)
46
- message = build_method_message(method, init, operation)
83
+ return if empty_array_literal?(node)
47
84
 
48
- add_offense(range, message: message) do |corrector|
49
- autocorrect(corrector, init, range)
50
- end
51
- end
85
+ handle_sum_candidate(node)
86
+ handle_sum_map_candidate(node)
52
87
  end
53
88
 
54
89
  def on_block(node)
@@ -66,25 +101,85 @@ module RuboCop
66
101
 
67
102
  private
68
103
 
104
+ def handle_sum_candidate(node)
105
+ sum_candidate?(node) do |method, init, operation|
106
+ range = sum_method_range(node)
107
+ message = build_method_message(node, method, init, operation)
108
+
109
+ add_offense(range, message: message) do |corrector|
110
+ autocorrect(corrector, init, range)
111
+ end
112
+ end
113
+ end
114
+
115
+ def handle_sum_map_candidate(node)
116
+ sum_map_candidate?(node) do |map, init|
117
+ next if node.block_literal? || node.block_argument?
118
+
119
+ message = build_sum_map_message(map.method_name, init)
120
+
121
+ add_offense(sum_map_range(map, node), message: message) do |corrector|
122
+ autocorrect_sum_map(corrector, node, map, init)
123
+ end
124
+ end
125
+ end
126
+
127
+ def empty_array_literal?(node)
128
+ receiver = node.children.first
129
+ array_literal?(node) && receiver && receiver.children.empty?
130
+ end
131
+
132
+ def array_literal?(node)
133
+ receiver = node.children.first
134
+ receiver&.literal? && receiver&.array_type?
135
+ end
136
+
69
137
  def autocorrect(corrector, init, range)
70
- return if init.empty?
138
+ return if init.empty? && safe_autocorrect?
71
139
 
72
140
  replacement = build_good_method(init)
73
141
 
74
142
  corrector.replace(range, replacement)
75
143
  end
76
144
 
145
+ def autocorrect_sum_map(corrector, sum, map, init)
146
+ sum_range = method_call_with_args_range(sum)
147
+ map_range = method_call_with_args_range(map)
148
+
149
+ block_pass = map.last_argument if map.last_argument&.block_pass_type?
150
+ replacement = build_good_method(init, block_pass)
151
+
152
+ corrector.remove(sum_range)
153
+ corrector.replace(map_range, ".#{replacement}")
154
+ end
155
+
77
156
  def sum_method_range(node)
78
157
  range_between(node.loc.selector.begin_pos, node.loc.end.end_pos)
79
158
  end
80
159
 
160
+ def sum_map_range(map, sum)
161
+ range_between(map.loc.selector.begin_pos, sum.source_range.end.end_pos)
162
+ end
163
+
81
164
  def sum_block_range(send, node)
82
165
  range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
83
166
  end
84
167
 
85
- def build_method_message(method, init, operation)
168
+ def build_method_message(node, method, init, operation)
86
169
  good_method = build_good_method(init)
87
170
  bad_method = build_method_bad_method(init, method, operation)
171
+ msg = if init.empty? && !array_literal?(node)
172
+ MSG_IF_NO_INIT_VALUE
173
+ else
174
+ MSG
175
+ end
176
+ format(msg, good_method: good_method, bad_method: bad_method)
177
+ end
178
+
179
+ def build_sum_map_message(method, init)
180
+ sum_method = build_good_method(init)
181
+ good_method = "#{sum_method} { ... }"
182
+ bad_method = "#{method} { ... }.#{sum_method}"
88
183
  format(MSG, good_method: good_method, bad_method: bad_method)
89
184
  end
90
185
 
@@ -94,13 +189,16 @@ module RuboCop
94
189
  format(MSG, good_method: good_method, bad_method: bad_method)
95
190
  end
96
191
 
97
- def build_good_method(init)
192
+ def build_good_method(init, block_pass = nil)
98
193
  good_method = 'sum'
99
194
 
195
+ args = []
100
196
  unless init.empty?
101
197
  init = init.first
102
- good_method += "(#{init.source})" unless init.int_type? && init.value.zero?
198
+ args << init.source unless init.int_type? && init.value.zero?
103
199
  end
200
+ args << block_pass.source if block_pass
201
+ good_method += "(#{args.join(', ')})" unless args.empty?
104
202
  good_method
105
203
  end
106
204
 
@@ -128,6 +226,10 @@ module RuboCop
128
226
  bad_method += " { |#{var_acc}, #{var_elem}| #{body.source} }"
129
227
  bad_method
130
228
  end
229
+
230
+ def method_call_with_args_range(node)
231
+ node.receiver.source_range.end.join(node.source_range.end)
232
+ end
131
233
  end
132
234
  end
133
235
  end
@@ -23,6 +23,7 @@ module RuboCop
23
23
  MESSAGE = 'Use `Array.new(%<count>s)` with a block ' \
24
24
  'instead of `.times.%<map_or_collect>s`'
25
25
  MESSAGE_ONLY_IF = 'only if `%<count>s` is always 0 or more'
26
+ RESTRICT_ON_SEND = %i[map collect].freeze
26
27
 
27
28
  def on_send(node)
28
29
  check(node)
@@ -10,6 +10,7 @@ module RuboCop
10
10
  # NOTE: `String.new` (without operator) is not exactly the same as `+''`.
11
11
  # These differ in encoding. `String.new.encoding` is always `ASCII-8BIT`.
12
12
  # However, `(+'').encoding` is the same as script encoding(e.g. `UTF-8`).
13
+ # Therefore, auto-correction is unsafe.
13
14
  # So, if you expect `ASCII-8BIT` encoding, disable this cop.
14
15
  #
15
16
  # @example
@@ -24,7 +25,10 @@ module RuboCop
24
25
  # +'something'
25
26
  # +''
26
27
  class UnfreezeString < Base
28
+ extend AutoCorrector
29
+
27
30
  MSG = 'Use unary plus to get an unfrozen string literal.'
31
+ RESTRICT_ON_SEND = %i[dup new].freeze
28
32
 
29
33
  def_node_matcher :dup_string?, <<~PATTERN
30
34
  (send {str dstr} :dup)
@@ -38,7 +42,21 @@ module RuboCop
38
42
  PATTERN
39
43
 
40
44
  def on_send(node)
41
- add_offense(node) if dup_string?(node) || string_new?(node)
45
+ return unless dup_string?(node) || string_new?(node)
46
+
47
+ add_offense(node) do |corrector|
48
+ corrector.replace(node, "+#{string_value(node)}")
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def string_value(node)
55
+ if node.receiver.source == 'String' && node.method?(:new)
56
+ node.arguments.empty? ? "''" : node.first_argument.source
57
+ else
58
+ node.receiver.source
59
+ end
42
60
  end
43
61
  end
44
62
  end
@@ -18,6 +18,7 @@ module RuboCop
18
18
 
19
19
  MSG = 'Use `%<double_colon>sURI::DEFAULT_PARSER` instead of ' \
20
20
  '`%<double_colon>sURI::Parser.new`.'
21
+ RESTRICT_ON_SEND = %i[new].freeze
21
22
 
22
23
  def_node_matcher :uri_parser_new?, <<~PATTERN
23
24
  (send
@@ -4,13 +4,16 @@ require_relative 'mixin/regexp_metacharacter'
4
4
  require_relative 'mixin/sort_block'
5
5
 
6
6
  require_relative 'performance/ancestors_include'
7
+ require_relative 'performance/array_semi_infinite_range_slice'
7
8
  require_relative 'performance/big_decimal_with_numeric_argument'
8
9
  require_relative 'performance/bind_call'
10
+ require_relative 'performance/block_given_with_explicit_block'
9
11
  require_relative 'performance/caller'
10
12
  require_relative 'performance/case_when_splat'
11
13
  require_relative 'performance/casecmp'
12
14
  require_relative 'performance/collection_literal_in_loop'
13
15
  require_relative 'performance/compare_with_block'
16
+ require_relative 'performance/constant_regexp'
14
17
  require_relative 'performance/count'
15
18
  require_relative 'performance/delete_prefix'
16
19
  require_relative 'performance/delete_suffix'
@@ -20,6 +23,7 @@ require_relative 'performance/end_with'
20
23
  require_relative 'performance/fixed_size'
21
24
  require_relative 'performance/flat_map'
22
25
  require_relative 'performance/inefficient_hash_search'
26
+ require_relative 'performance/method_object_as_block'
23
27
  require_relative 'performance/open_struct'
24
28
  require_relative 'performance/range_include'
25
29
  require_relative 'performance/io_readlines'
@@ -2,8 +2,13 @@
2
2
 
3
3
  module RuboCop
4
4
  module Performance
5
+ # This module holds the RuboCop Performance version information.
5
6
  module Version
6
- STRING = '1.8.1'
7
+ STRING = '1.9.0'
8
+
9
+ def self.document_version
10
+ STRING.match('\d+\.\d+').to_s
11
+ end
7
12
  end
8
13
  end
9
14
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-performance
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.1
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
8
8
  - Jonas Arvidsson
9
9
  - Yuji Nakayama
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-09-18 00:00:00.000000000 Z
13
+ date: 2020-11-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rubocop
@@ -18,14 +18,20 @@ dependencies:
18
18
  requirements:
19
19
  - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: 0.87.0
21
+ version: 0.90.0
22
+ - - "<"
23
+ - !ruby/object:Gem::Version
24
+ version: '2.0'
22
25
  type: :runtime
23
26
  prerelease: false
24
27
  version_requirements: !ruby/object:Gem::Requirement
25
28
  requirements:
26
29
  - - ">="
27
30
  - !ruby/object:Gem::Version
28
- version: 0.87.0
31
+ version: 0.90.0
32
+ - - "<"
33
+ - !ruby/object:Gem::Version
34
+ version: '2.0'
29
35
  - !ruby/object:Gem::Dependency
30
36
  name: rubocop-ast
31
37
  requirement: !ruby/object:Gem::Requirement
@@ -40,20 +46,6 @@ dependencies:
40
46
  - - ">="
41
47
  - !ruby/object:Gem::Version
42
48
  version: 0.4.0
43
- - !ruby/object:Gem::Dependency
44
- name: simplecov
45
- requirement: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: '0'
50
- type: :development
51
- prerelease: false
52
- version_requirements: !ruby/object:Gem::Requirement
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: '0'
57
49
  description: |
58
50
  A collection of RuboCop cops to check for performance optimizations
59
51
  in Ruby code.
@@ -71,14 +63,17 @@ files:
71
63
  - lib/rubocop/cop/mixin/regexp_metacharacter.rb
72
64
  - lib/rubocop/cop/mixin/sort_block.rb
73
65
  - lib/rubocop/cop/performance/ancestors_include.rb
66
+ - lib/rubocop/cop/performance/array_semi_infinite_range_slice.rb
74
67
  - lib/rubocop/cop/performance/big_decimal_with_numeric_argument.rb
75
68
  - lib/rubocop/cop/performance/bind_call.rb
69
+ - lib/rubocop/cop/performance/block_given_with_explicit_block.rb
76
70
  - lib/rubocop/cop/performance/caller.rb
77
71
  - lib/rubocop/cop/performance/case_when_splat.rb
78
72
  - lib/rubocop/cop/performance/casecmp.rb
79
73
  - lib/rubocop/cop/performance/chain_array_allocation.rb
80
74
  - lib/rubocop/cop/performance/collection_literal_in_loop.rb
81
75
  - lib/rubocop/cop/performance/compare_with_block.rb
76
+ - lib/rubocop/cop/performance/constant_regexp.rb
82
77
  - lib/rubocop/cop/performance/count.rb
83
78
  - lib/rubocop/cop/performance/delete_prefix.rb
84
79
  - lib/rubocop/cop/performance/delete_suffix.rb
@@ -89,6 +84,7 @@ files:
89
84
  - lib/rubocop/cop/performance/flat_map.rb
90
85
  - lib/rubocop/cop/performance/inefficient_hash_search.rb
91
86
  - lib/rubocop/cop/performance/io_readlines.rb
87
+ - lib/rubocop/cop/performance/method_object_as_block.rb
92
88
  - lib/rubocop/cop/performance/open_struct.rb
93
89
  - lib/rubocop/cop/performance/range_include.rb
94
90
  - lib/rubocop/cop/performance/redundant_block_call.rb
@@ -120,9 +116,9 @@ metadata:
120
116
  homepage_uri: https://docs.rubocop.org/rubocop-performance/
121
117
  changelog_uri: https://github.com/rubocop-hq/rubocop-performance/blob/master/CHANGELOG.md
122
118
  source_code_uri: https://github.com/rubocop-hq/rubocop-performance/
123
- documentation_uri: https://docs.rubocop.org/rubocop-performance/
119
+ documentation_uri: https://docs.rubocop.org/rubocop-performance/1.9/
124
120
  bug_tracker_uri: https://github.com/rubocop-hq/rubocop-performance/issues
125
- post_install_message:
121
+ post_install_message:
126
122
  rdoc_options: []
127
123
  require_paths:
128
124
  - lib
@@ -137,8 +133,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
133
  - !ruby/object:Gem::Version
138
134
  version: '0'
139
135
  requirements: []
140
- rubygems_version: 3.1.4
141
- signing_key:
136
+ rubygems_version: 3.2.0.rc.2
137
+ signing_key:
142
138
  specification_version: 4
143
139
  summary: Automatic performance checking tool for Ruby code.
144
140
  test_files: []