rubocop-performance 1.8.1 → 1.9.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.
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: []