rubocop-performance 1.16.0 → 1.19.0

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