rubocop-performance 1.5.2 → 1.8.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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +5 -1
  4. data/config/default.yml +96 -13
  5. data/lib/rubocop/cop/mixin/regexp_metacharacter.rb +76 -0
  6. data/lib/rubocop/cop/mixin/sort_block.rb +28 -0
  7. data/lib/rubocop/cop/performance/ancestors_include.rb +48 -0
  8. data/lib/rubocop/cop/performance/big_decimal_with_numeric_argument.rb +45 -0
  9. data/lib/rubocop/cop/performance/bind_call.rb +77 -0
  10. data/lib/rubocop/cop/performance/caller.rb +5 -4
  11. data/lib/rubocop/cop/performance/case_when_splat.rb +18 -11
  12. data/lib/rubocop/cop/performance/casecmp.rb +17 -23
  13. data/lib/rubocop/cop/performance/chain_array_allocation.rb +5 -11
  14. data/lib/rubocop/cop/performance/collection_literal_in_loop.rb +140 -0
  15. data/lib/rubocop/cop/performance/compare_with_block.rb +12 -23
  16. data/lib/rubocop/cop/performance/count.rb +14 -17
  17. data/lib/rubocop/cop/performance/delete_prefix.rb +87 -0
  18. data/lib/rubocop/cop/performance/delete_suffix.rb +87 -0
  19. data/lib/rubocop/cop/performance/detect.rb +30 -27
  20. data/lib/rubocop/cop/performance/double_start_end_with.rb +18 -26
  21. data/lib/rubocop/cop/performance/end_with.rb +38 -25
  22. data/lib/rubocop/cop/performance/fixed_size.rb +2 -2
  23. data/lib/rubocop/cop/performance/flat_map.rb +21 -23
  24. data/lib/rubocop/cop/performance/inefficient_hash_search.rb +14 -15
  25. data/lib/rubocop/cop/performance/io_readlines.rb +116 -0
  26. data/lib/rubocop/cop/performance/open_struct.rb +3 -3
  27. data/lib/rubocop/cop/performance/range_include.rb +15 -12
  28. data/lib/rubocop/cop/performance/redundant_block_call.rb +14 -9
  29. data/lib/rubocop/cop/performance/redundant_match.rb +13 -8
  30. data/lib/rubocop/cop/performance/redundant_merge.rb +36 -23
  31. data/lib/rubocop/cop/performance/redundant_sort_block.rb +43 -0
  32. data/lib/rubocop/cop/performance/redundant_string_chars.rb +133 -0
  33. data/lib/rubocop/cop/performance/regexp_match.rb +32 -32
  34. data/lib/rubocop/cop/performance/reverse_each.rb +10 -5
  35. data/lib/rubocop/cop/performance/reverse_first.rb +72 -0
  36. data/lib/rubocop/cop/performance/size.rb +41 -43
  37. data/lib/rubocop/cop/performance/sort_reverse.rb +45 -0
  38. data/lib/rubocop/cop/performance/squeeze.rb +66 -0
  39. data/lib/rubocop/cop/performance/start_with.rb +38 -28
  40. data/lib/rubocop/cop/performance/string_include.rb +55 -0
  41. data/lib/rubocop/cop/performance/string_replacement.rb +25 -36
  42. data/lib/rubocop/cop/performance/sum.rb +129 -0
  43. data/lib/rubocop/cop/performance/times_map.rb +12 -19
  44. data/lib/rubocop/cop/performance/unfreeze_string.rb +4 -8
  45. data/lib/rubocop/cop/performance/uri_default_parser.rb +7 -13
  46. data/lib/rubocop/cop/performance_cops.rb +17 -0
  47. data/lib/rubocop/performance/inject.rb +1 -1
  48. data/lib/rubocop/performance/version.rb +1 -1
  49. metadata +27 -11
@@ -45,10 +45,10 @@ module RuboCop
45
45
  # waldo = { a: corge, b: grault }
46
46
  # waldo.size
47
47
  #
48
- class FixedSize < Cop
48
+ class FixedSize < Base
49
49
  MSG = 'Do not compute the size of statically sized objects.'
50
50
 
51
- def_node_matcher :counter, <<-MATCHER
51
+ def_node_matcher :counter, <<~MATCHER
52
52
  (send ${array hash str sym} {:count :length :size} $...)
53
53
  MATCHER
54
54
 
@@ -14,15 +14,16 @@ module RuboCop
14
14
  # [1, 2, 3, 4].flat_map { |e| [e, e] }
15
15
  # [1, 2, 3, 4].map { |e| [e, e] }.flatten
16
16
  # [1, 2, 3, 4].collect { |e| [e, e] }.flatten
17
- class FlatMap < Cop
17
+ class FlatMap < Base
18
18
  include RangeHelp
19
+ extend AutoCorrector
19
20
 
20
21
  MSG = 'Use `flat_map` instead of `%<method>s...%<flatten>s`.'
21
22
  FLATTEN_MULTIPLE_LEVELS = ' Beware, `flat_map` only flattens 1 level ' \
22
23
  'and `flatten` can be used to flatten ' \
23
24
  'multiple levels.'
24
25
 
25
- def_node_matcher :flat_map_candidate?, <<-PATTERN
26
+ def_node_matcher :flat_map_candidate?, <<~PATTERN
26
27
  (send
27
28
  {
28
29
  (block $(send _ ${:collect :map}) ...)
@@ -44,25 +45,11 @@ module RuboCop
44
45
  end
45
46
  end
46
47
 
47
- def autocorrect(node)
48
- map_node, _first_method, _flatten, params = flat_map_candidate?(node)
49
- flatten_level, = *params.first
50
-
51
- return unless flatten_level
52
-
53
- range = range_between(node.loc.dot.begin_pos,
54
- node.source_range.end_pos)
55
-
56
- lambda do |corrector|
57
- corrector.remove(range)
58
- corrector.replace(map_node.loc.selector, 'flat_map')
59
- end
60
- end
61
-
62
48
  private
63
49
 
64
50
  def offense_for_levels(node, map_node, first_method, flatten)
65
51
  message = MSG + FLATTEN_MULTIPLE_LEVELS
52
+
66
53
  register_offense(node, map_node, first_method, flatten, message)
67
54
  end
68
55
 
@@ -71,13 +58,24 @@ module RuboCop
71
58
  end
72
59
 
73
60
  def register_offense(node, map_node, first_method, flatten, message)
74
- range = range_between(map_node.loc.selector.begin_pos,
75
- node.loc.expression.end_pos)
61
+ range = range_between(map_node.loc.selector.begin_pos, node.loc.expression.end_pos)
62
+ message = format(message, method: first_method, flatten: flatten)
63
+
64
+ add_offense(range, message: message) do |corrector|
65
+ autocorrect(corrector, node)
66
+ end
67
+ end
68
+
69
+ def autocorrect(corrector, node)
70
+ map_node, _first_method, _flatten, params = flat_map_candidate?(node)
71
+ flatten_level, = *params.first
72
+
73
+ return unless flatten_level
74
+
75
+ range = range_between(node.loc.dot.begin_pos, node.source_range.end_pos)
76
76
 
77
- add_offense(node,
78
- location: range,
79
- message: format(message, method: first_method,
80
- flatten: flatten))
77
+ corrector.remove(range)
78
+ corrector.replace(map_node.loc.selector, 'flat_map')
81
79
  end
82
80
  end
83
81
  end
@@ -36,8 +36,10 @@ module RuboCop
36
36
  # { a: 1, b: 2 }.has_value?('garbage')
37
37
  # h = { a: 1, b: 2 }; h.value?(nil)
38
38
  #
39
- class InefficientHashSearch < Cop
40
- def_node_matcher :inefficient_include?, <<-PATTERN
39
+ class InefficientHashSearch < Base
40
+ extend AutoCorrector
41
+
42
+ def_node_matcher :inefficient_include?, <<~PATTERN
41
43
  (send (send $_ {:keys :values}) :include? _)
42
44
  PATTERN
43
45
 
@@ -45,19 +47,16 @@ module RuboCop
45
47
  inefficient_include?(node) do |receiver|
46
48
  return if receiver.nil?
47
49
 
48
- add_offense(node)
49
- end
50
- end
51
-
52
- def autocorrect(node)
53
- lambda do |corrector|
54
- # Replace `keys.include?` or `values.include?` with the appropriate
55
- # `key?`/`value?` method.
56
- corrector.replace(
57
- node.loc.expression,
58
- "#{autocorrect_hash_expression(node)}."\
59
- "#{autocorrect_method(node)}(#{autocorrect_argument(node)})"
60
- )
50
+ message = message(node)
51
+ add_offense(node, message: message) do |corrector|
52
+ # Replace `keys.include?` or `values.include?` with the appropriate
53
+ # `key?`/`value?` method.
54
+ corrector.replace(
55
+ node.loc.expression,
56
+ "#{autocorrect_hash_expression(node)}."\
57
+ "#{autocorrect_method(node)}(#{autocorrect_argument(node)})"
58
+ )
59
+ end
61
60
  end
62
61
  end
63
62
 
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Performance
6
+ # This cop identifies places where inefficient `readlines` method
7
+ # can be replaced by `each_line` to avoid fully loading file content into memory.
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # File.readlines('testfile').each { |l| puts l }
13
+ # IO.readlines('testfile', chomp: true).each { |l| puts l }
14
+ #
15
+ # conn.readlines(10).map { |l| l.size }
16
+ # file.readlines.find { |l| l.start_with?('#') }
17
+ # file.readlines.each { |l| puts l }
18
+ #
19
+ # # good
20
+ # File.open('testfile', 'r').each_line { |l| puts l }
21
+ # IO.open('testfile').each_line(chomp: true) { |l| puts l }
22
+ #
23
+ # conn.each_line(10).map { |l| l.size }
24
+ # file.each_line.find { |l| l.start_with?('#') }
25
+ # file.each_line { |l| puts l }
26
+ #
27
+ class IoReadlines < Base
28
+ include RangeHelp
29
+ extend AutoCorrector
30
+
31
+ MSG = 'Use `%<good>s` instead of `%<bad>s`.'
32
+ ENUMERABLE_METHODS = (Enumerable.instance_methods + [:each]).freeze
33
+
34
+ def_node_matcher :readlines_on_class?, <<~PATTERN
35
+ $(send $(send (const nil? {:IO :File}) :readlines ...) #enumerable_method?)
36
+ PATTERN
37
+
38
+ def_node_matcher :readlines_on_instance?, <<~PATTERN
39
+ $(send $(send ${nil? !const_type?} :readlines ...) #enumerable_method? ...)
40
+ PATTERN
41
+
42
+ def on_send(node)
43
+ return unless (captured_values = readlines_on_class?(node) || readlines_on_instance?(node))
44
+
45
+ enumerable_call, readlines_call, receiver = *captured_values
46
+
47
+ range = offense_range(enumerable_call, readlines_call)
48
+ good_method = build_good_method(enumerable_call)
49
+ bad_method = build_bad_method(enumerable_call)
50
+
51
+ add_offense(range, message: format(MSG, good: good_method, bad: bad_method)) do |corrector|
52
+ autocorrect(corrector, enumerable_call, readlines_call, receiver)
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def enumerable_method?(node)
59
+ ENUMERABLE_METHODS.include?(node.to_sym)
60
+ end
61
+
62
+ def autocorrect(corrector, enumerable_call, readlines_call, receiver)
63
+ # We cannot safely correct `.readlines` method called on IO/File classes
64
+ # due to its signature and we are not sure with implicit receiver
65
+ # if it is called in the context of some instance or mentioned class.
66
+ return if receiver.nil?
67
+
68
+ range = correction_range(enumerable_call, readlines_call)
69
+
70
+ if readlines_call.arguments?
71
+ call_args = build_call_args(readlines_call.arguments)
72
+ replacement = "each_line(#{call_args})"
73
+ else
74
+ replacement = 'each_line'
75
+ end
76
+
77
+ corrector.replace(range, replacement)
78
+ end
79
+
80
+ def offense_range(enumerable_call, readlines_call)
81
+ readlines_pos = readlines_call.loc.selector.begin_pos
82
+ enumerable_pos = enumerable_call.loc.selector.end_pos
83
+ range_between(readlines_pos, enumerable_pos)
84
+ end
85
+
86
+ def build_good_method(enumerable_call)
87
+ if enumerable_call.method?(:each)
88
+ 'each_line'
89
+ else
90
+ "each_line.#{enumerable_call.method_name}"
91
+ end
92
+ end
93
+
94
+ def build_bad_method(enumerable_call)
95
+ "readlines.#{enumerable_call.method_name}"
96
+ end
97
+
98
+ def correction_range(enumerable_call, readlines_call)
99
+ begin_pos = readlines_call.loc.selector.begin_pos
100
+
101
+ end_pos = if enumerable_call.method?(:each)
102
+ enumerable_call.loc.expression.end_pos
103
+ else
104
+ enumerable_call.loc.dot.begin_pos
105
+ end
106
+
107
+ range_between(begin_pos, end_pos)
108
+ end
109
+
110
+ def build_call_args(call_args_node)
111
+ call_args_node.map(&:source).join(', ')
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -27,17 +27,17 @@ module RuboCop
27
27
  # end
28
28
  # end
29
29
  #
30
- class OpenStruct < Cop
30
+ class OpenStruct < Base
31
31
  MSG = 'Consider using `Struct` over `OpenStruct` ' \
32
32
  'to optimize the performance.'
33
33
 
34
- def_node_matcher :open_struct, <<-PATTERN
34
+ def_node_matcher :open_struct, <<~PATTERN
35
35
  (send (const {nil? cbase} :OpenStruct) :new ...)
36
36
  PATTERN
37
37
 
38
38
  def on_send(node)
39
39
  open_struct(node) do
40
- add_offense(node, location: :selector)
40
+ add_offense(node.loc.selector)
41
41
  end
42
42
  end
43
43
  end
@@ -3,18 +3,19 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Performance
6
- # This cop identifies uses of `Range#include?`, which iterates over each
6
+ # This cop identifies uses of `Range#include?` and `Range#member?`, which iterates over each
7
7
  # item in a `Range` to see if a specified item is there. In contrast,
8
8
  # `Range#cover?` simply compares the target item with the beginning and
9
9
  # end points of the `Range`. In a great majority of cases, this is what
10
10
  # is wanted.
11
11
  #
12
- # This cop is `Safe: false` by default because `Range#include?` and
12
+ # This cop is `Safe: false` by default because `Range#include?` (or `Range#member?`) and
13
13
  # `Range#cover?` are not equivalent behaviour.
14
14
  #
15
15
  # @example
16
16
  # # bad
17
17
  # ('a'..'z').include?('b') # => true
18
+ # ('a'..'z').member?('b') # => true
18
19
  #
19
20
  # # good
20
21
  # ('a'..'z').cover?('b') # => true
@@ -23,26 +24,28 @@ module RuboCop
23
24
  # # the desired result:
24
25
  #
25
26
  # ('a'..'z').cover?('yellow') # => true
26
- class RangeInclude < Cop
27
- MSG = 'Use `Range#cover?` instead of `Range#include?`.'
27
+ class RangeInclude < Base
28
+ extend AutoCorrector
29
+
30
+ MSG = 'Use `Range#cover?` instead of `Range#%<bad_method>s`.'
28
31
 
29
32
  # TODO: If we traced out assignments of variables to their uses, we
30
33
  # might pick up on a few more instances of this issue
31
34
  # Right now, we only detect direct calls on a Range literal
32
35
  # (We don't even catch it if the Range is in double parens)
33
36
 
34
- def_node_matcher :range_include, <<-PATTERN
35
- (send {irange erange (begin {irange erange})} :include? ...)
37
+ def_node_matcher :range_include, <<~PATTERN
38
+ (send {irange erange (begin {irange erange})} ${:include? :member?} ...)
36
39
  PATTERN
37
40
 
38
41
  def on_send(node)
39
- return unless range_include(node)
40
-
41
- add_offense(node, location: :selector)
42
- end
42
+ range_include(node) do |bad_method|
43
+ message = format(MSG, bad_method: bad_method)
43
44
 
44
- def autocorrect(node)
45
- ->(corrector) { corrector.replace(node.loc.selector, 'cover?') }
45
+ add_offense(node.loc.selector, message: message) do |corrector|
46
+ corrector.replace(node.loc.selector, 'cover?')
47
+ end
48
+ end
46
49
  end
47
50
  end
48
51
  end
@@ -22,23 +22,25 @@ module RuboCop
22
22
  # def another
23
23
  # yield 1, 2, 3
24
24
  # end
25
- class RedundantBlockCall < Cop
25
+ class RedundantBlockCall < Base
26
+ extend AutoCorrector
27
+
26
28
  MSG = 'Use `yield` instead of `%<argname>s.call`.'
27
29
  YIELD = 'yield'
28
30
  OPEN_PAREN = '('
29
31
  CLOSE_PAREN = ')'
30
32
  SPACE = ' '
31
33
 
32
- def_node_matcher :blockarg_def, <<-PATTERN
34
+ def_node_matcher :blockarg_def, <<~PATTERN
33
35
  {(def _ (args ... (blockarg $_)) $_)
34
36
  (defs _ _ (args ... (blockarg $_)) $_)}
35
37
  PATTERN
36
38
 
37
- def_node_search :blockarg_calls, <<-PATTERN
39
+ def_node_search :blockarg_calls, <<~PATTERN
38
40
  (send (lvar %1) :call ...)
39
41
  PATTERN
40
42
 
41
- def_node_search :blockarg_assigned?, <<-PATTERN
43
+ def_node_search :blockarg_assigned?, <<~PATTERN
42
44
  (lvasgn %1 ...)
43
45
  PATTERN
44
46
 
@@ -47,13 +49,17 @@ module RuboCop
47
49
  next unless body
48
50
 
49
51
  calls_to_report(argname, body).each do |blockcall|
50
- add_offense(blockcall, message: format(MSG, argname: argname))
52
+ add_offense(blockcall, message: format(MSG, argname: argname)) do |corrector|
53
+ autocorrect(corrector, blockcall)
54
+ end
51
55
  end
52
56
  end
53
57
  end
54
58
 
59
+ private
60
+
55
61
  # offenses are registered on the `block.call` nodes
56
- def autocorrect(node)
62
+ def autocorrect(corrector, node)
57
63
  _receiver, _method, *args = *node
58
64
  new_source = String.new(YIELD)
59
65
  unless args.empty?
@@ -67,10 +73,9 @@ module RuboCop
67
73
  end
68
74
 
69
75
  new_source << CLOSE_PAREN if parentheses?(node) && !args.empty?
70
- ->(corrector) { corrector.replace(node.source_range, new_source) }
71
- end
72
76
 
73
- private
77
+ corrector.replace(node.source_range, new_source)
78
+ end
74
79
 
75
80
  def calls_to_report(argname, body)
76
81
  return [] if blockarg_assigned?(body, argname)
@@ -17,18 +17,20 @@ module RuboCop
17
17
  # # good
18
18
  # method(str =~ /regex/)
19
19
  # return value unless regex =~ 'str'
20
- class RedundantMatch < Cop
20
+ class RedundantMatch < Base
21
+ extend AutoCorrector
22
+
21
23
  MSG = 'Use `=~` in places where the `MatchData` returned by ' \
22
24
  '`#match` will not be used.'
23
25
 
24
26
  # 'match' is a fairly generic name, so we don't flag it unless we see
25
27
  # a string or regexp literal on one side or the other
26
- def_node_matcher :match_call?, <<-PATTERN
28
+ def_node_matcher :match_call?, <<~PATTERN
27
29
  {(send {str regexp} :match _)
28
30
  (send !nil? :match {str regexp})}
29
31
  PATTERN
30
32
 
31
- def_node_matcher :only_truthiness_matters?, <<-PATTERN
33
+ def_node_matcher :only_truthiness_matters?, <<~PATTERN
32
34
  ^({if while until case while_post until_post} equal?(%0) ...)
33
35
  PATTERN
34
36
 
@@ -37,18 +39,21 @@ module RuboCop
37
39
  (!node.value_used? || only_truthiness_matters?(node)) &&
38
40
  !(node.parent && node.parent.block_type?)
39
41
 
40
- add_offense(node)
42
+ add_offense(node) do |corrector|
43
+ autocorrect(corrector, node)
44
+ end
41
45
  end
42
46
 
43
- def autocorrect(node)
47
+ private
48
+
49
+ def autocorrect(corrector, node)
44
50
  # Regexp#match can take a second argument, but this cop doesn't
45
51
  # register an offense in that case
46
52
  return unless node.first_argument.regexp_type?
47
53
 
48
- new_source =
49
- node.receiver.source + ' =~ ' + node.first_argument.source
54
+ new_source = "#{node.receiver.source} =~ #{node.first_argument.source}"
50
55
 
51
- ->(corrector) { corrector.replace(node.source_range, new_source) }
56
+ corrector.replace(node.source_range, new_source)
52
57
  end
53
58
  end
54
59
  end
@@ -5,12 +5,28 @@ module RuboCop
5
5
  module Performance
6
6
  # This cop identifies places where `Hash#merge!` can be replaced by
7
7
  # `Hash#[]=`.
8
+ # You can set the maximum number of key-value pairs to consider
9
+ # an offense with `MaxKeyValuePairs`.
8
10
  #
9
11
  # @example
12
+ # # bad
10
13
  # hash.merge!(a: 1)
11
14
  # hash.merge!({'key' => 'value'})
15
+ #
16
+ # # good
17
+ # hash[:a] = 1
18
+ # hash['key'] = 'value'
19
+ #
20
+ # @example MaxKeyValuePairs: 2 (default)
21
+ # # bad
12
22
  # hash.merge!(a: 1, b: 2)
13
- class RedundantMerge < Cop
23
+ #
24
+ # # good
25
+ # hash[:a] = 1
26
+ # hash[:b] = 2
27
+ class RedundantMerge < Base
28
+ extend AutoCorrector
29
+
14
30
  AREF_ASGN = '%<receiver>s[%<key>s] = %<value>s'
15
31
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
16
32
 
@@ -20,28 +36,27 @@ module RuboCop
20
36
  %<leading_space>send
21
37
  RUBY
22
38
 
23
- def_node_matcher :redundant_merge_candidate, <<-PATTERN
39
+ def_node_matcher :redundant_merge_candidate, <<~PATTERN
24
40
  (send $!nil? :merge! [(hash $...) !kwsplat_type?])
25
41
  PATTERN
26
42
 
27
- def_node_matcher :modifier_flow_control?, <<-PATTERN
43
+ def_node_matcher :modifier_flow_control?, <<~PATTERN
28
44
  [{if while until} modifier_form?]
29
45
  PATTERN
30
46
 
31
47
  def on_send(node)
32
48
  each_redundant_merge(node) do |redundant_merge_node|
33
- add_offense(redundant_merge_node)
34
- end
35
- end
36
-
37
- def autocorrect(node)
38
- redundant_merge_candidate(node) do |receiver, pairs|
39
- new_source = to_assignments(receiver, pairs).join("\n")
40
-
41
- if node.parent && pairs.size > 1
42
- correct_multiple_elements(node, node.parent, new_source)
43
- else
44
- correct_single_element(node, new_source)
49
+ message = message(node)
50
+ add_offense(redundant_merge_node, message: message) do |corrector|
51
+ redundant_merge_candidate(node) do |receiver, pairs|
52
+ new_source = to_assignments(receiver, pairs).join("\n")
53
+
54
+ if node.parent && pairs.size > 1
55
+ correct_multiple_elements(corrector, node, node.parent, new_source)
56
+ else
57
+ correct_single_element(corrector, node, new_source)
58
+ end
59
+ end
45
60
  end
46
61
  end
47
62
  end
@@ -84,7 +99,7 @@ module RuboCop
84
99
  !EachWithObjectInspector.new(node, receiver).value_used?
85
100
  end
86
101
 
87
- def correct_multiple_elements(node, parent, new_source)
102
+ def correct_multiple_elements(corrector, node, parent, new_source)
88
103
  if modifier_flow_control?(parent)
89
104
  new_source = rewrite_with_modifier(node, parent, new_source)
90
105
  node = parent
@@ -93,11 +108,11 @@ module RuboCop
93
108
  new_source.gsub!(/\n/, padding)
94
109
  end
95
110
 
96
- ->(corrector) { corrector.replace(node.source_range, new_source) }
111
+ corrector.replace(node.source_range, new_source)
97
112
  end
98
113
 
99
- def correct_single_element(node, new_source)
100
- ->(corrector) { corrector.replace(node.source_range, new_source) }
114
+ def correct_single_element(corrector, node, new_source)
115
+ corrector.replace(node.source_range, new_source)
101
116
  end
102
117
 
103
118
  def to_assignments(receiver, pairs)
@@ -168,13 +183,11 @@ module RuboCop
168
183
  end
169
184
 
170
185
  def unwind(receiver)
171
- while receiver.respond_to?(:send_type?) && receiver.send_type?
172
- receiver, = *receiver
173
- end
186
+ receiver, = *receiver while receiver.respond_to?(:send_type?) && receiver.send_type?
174
187
  receiver
175
188
  end
176
189
 
177
- def_node_matcher :each_with_object_node, <<-PATTERN
190
+ def_node_matcher :each_with_object_node, <<~PATTERN
178
191
  (block (send _ :each_with_object _) (args _ $_) ...)
179
192
  PATTERN
180
193
  end