rubocop 1.82.1 → 1.84.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +1 -1
  4. data/config/default.yml +44 -0
  5. data/lib/rubocop/cli/command/lsp.rb +1 -1
  6. data/lib/rubocop/cli.rb +2 -1
  7. data/lib/rubocop/comment_config.rb +1 -0
  8. data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
  9. data/lib/rubocop/cop/correctors/alignment_corrector.rb +20 -2
  10. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
  11. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +9 -9
  12. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
  13. data/lib/rubocop/cop/layout/case_indentation.rb +3 -1
  14. data/lib/rubocop/cop/layout/class_structure.rb +12 -5
  15. data/lib/rubocop/cop/layout/first_argument_indentation.rb +32 -1
  16. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +26 -0
  17. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
  18. data/lib/rubocop/cop/layout/heredoc_indentation.rb +34 -1
  19. data/lib/rubocop/cop/layout/indentation_width.rb +102 -9
  20. data/lib/rubocop/cop/layout/line_length.rb +5 -2
  21. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +57 -57
  22. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +56 -56
  23. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +8 -8
  24. data/lib/rubocop/cop/lint/duplicate_methods.rb +57 -5
  25. data/lib/rubocop/cop/lint/float_comparison.rb +1 -1
  26. data/lib/rubocop/cop/lint/literal_as_condition.rb +1 -1
  27. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  28. data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
  29. data/lib/rubocop/cop/lint/to_json.rb +12 -16
  30. data/lib/rubocop/cop/lint/useless_or.rb +1 -1
  31. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +1 -1
  32. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +4 -4
  33. data/lib/rubocop/cop/naming/predicate_prefix.rb +11 -11
  34. data/lib/rubocop/cop/offense.rb +2 -1
  35. data/lib/rubocop/cop/security/json_load.rb +1 -1
  36. data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -2
  37. data/lib/rubocop/cop/style/documentation.rb +6 -6
  38. data/lib/rubocop/cop/style/documentation_method.rb +8 -8
  39. data/lib/rubocop/cop/style/empty_class_definition.rb +144 -0
  40. data/lib/rubocop/cop/style/guard_clause.rb +7 -4
  41. data/lib/rubocop/cop/style/hash_lookup_method.rb +94 -0
  42. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +12 -12
  43. data/lib/rubocop/cop/style/lambda_call.rb +8 -8
  44. data/lib/rubocop/cop/style/module_member_existence_check.rb +56 -13
  45. data/lib/rubocop/cop/style/negative_array_index.rb +218 -0
  46. data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
  47. data/lib/rubocop/cop/style/redundant_condition.rb +1 -1
  48. data/lib/rubocop/cop/style/reverse_find.rb +51 -0
  49. data/lib/rubocop/cop/team.rb +3 -3
  50. data/lib/rubocop/cop/variable_force/branch.rb +28 -4
  51. data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
  52. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  53. data/lib/rubocop/formatter/tap_formatter.rb +5 -2
  54. data/lib/rubocop/remote_config.rb +5 -2
  55. data/lib/rubocop/rspec/shared_contexts.rb +4 -0
  56. data/lib/rubocop/rspec/support.rb +1 -0
  57. data/lib/rubocop/target_ruby.rb +3 -1
  58. data/lib/rubocop/version.rb +1 -1
  59. data/lib/rubocop.rb +4 -0
  60. metadata +9 -5
@@ -11,7 +11,7 @@ module RuboCop
11
11
  #
12
12
  # @safety
13
13
  # As shown in the examples below, there are generally two possible ways to correct the
14
- # offense, but this cops autocorrection always chooses the option that preserves the
14
+ # offense, but this cop's autocorrection always chooses the option that preserves the
15
15
  # current behavior. While this does not change how the code behaves, that option is not
16
16
  # necessarily the appropriate fix in every situation. For this reason, the autocorrection
17
17
  # provided by this cop is considered unsafe.
@@ -53,7 +53,7 @@ module RuboCop
53
53
  return true
54
54
  end
55
55
  when :when
56
- node.each_condition do |condition|
56
+ node.conditions.each do |condition|
57
57
  return true if _cant_be_nil?(condition, receiver)
58
58
  end
59
59
  when :lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn
@@ -125,7 +125,7 @@ module RuboCop
125
125
  return if dispatch_node.assignment_method?
126
126
  return if dispatch_node.parenthesized?
127
127
  return if dispatch_node.parent && parentheses?(dispatch_node.parent)
128
- return if last_expression?(dispatch_node) && !method_dispatch_as_argument?(dispatch_node)
128
+ return if last_expression?(dispatch_node) && !requires_parentheses_context?(dispatch_node)
129
129
 
130
130
  def_node = node.each_ancestor(:call, :super, :yield).first
131
131
 
@@ -164,11 +164,11 @@ module RuboCop
164
164
  !assignment_node.right_sibling
165
165
  end
166
166
 
167
- def method_dispatch_as_argument?(method_dispatch_node)
168
- parent = method_dispatch_node.parent
167
+ def requires_parentheses_context?(node)
168
+ parent = node.parent
169
169
  return false unless parent
170
170
 
171
- parent.type?(:call, :super, :yield)
171
+ parent.type?(:call, :if, :super, :until, :while, :yield)
172
172
  end
173
173
 
174
174
  def breakdown_value_types_of_hash(hash_node)
@@ -63,17 +63,17 @@ module RuboCop
63
63
  # end
64
64
  #
65
65
  # @example UseSorbetSigs: false (default)
66
- # # bad
67
- # sig { returns(String) }
68
- # def is_this_thing_on
69
- # "yes"
70
- # end
71
- #
72
- # # good - Sorbet signature is not evaluated
73
- # sig { returns(String) }
74
- # def is_this_thing_on?
75
- # "yes"
76
- # end
66
+ # # bad
67
+ # sig { returns(String) }
68
+ # def is_this_thing_on
69
+ # "yes"
70
+ # end
71
+ #
72
+ # # good - Sorbet signature is not evaluated
73
+ # sig { returns(String) }
74
+ # def is_this_thing_on?
75
+ # "yes"
76
+ # end
77
77
  #
78
78
  # @example UseSorbetSigs: true
79
79
  # # bad
@@ -139,7 +139,8 @@ module RuboCop
139
139
  # @return [Parser::Source::Range]
140
140
  # the range of the code that is highlighted
141
141
  def highlighted_area
142
- Parser::Source::Range.new(source_line, column, column + column_length)
142
+ source_buffer = Parser::Source::Buffer.new(location.source_buffer.name, source: source_line)
143
+ Parser::Source::Range.new(source_buffer, column, column + column_length)
143
144
  end
144
145
 
145
146
  # @api private
@@ -52,7 +52,7 @@ module RuboCop
52
52
  (
53
53
  send (const {nil? cbase} :JSON) ${:load :restore}
54
54
  ...
55
- !(hash `(sym $:create_additions))
55
+ !`(pair (sym :create_additions) _)
56
56
  )
57
57
  PATTERN
58
58
 
@@ -326,8 +326,7 @@ module RuboCop
326
326
  argument_less_modifier_node = find_argument_less_modifier_node(node)
327
327
  if argument_less_modifier_node
328
328
  corrector.insert_after(argument_less_modifier_node, "\n\n#{source}")
329
- elsif (ancestor = node.each_ancestor(:class, :module).first)
330
-
329
+ elsif (ancestor = node.each_ancestor(:class, :module, :sclass).first)
331
330
  corrector.insert_before(ancestor.loc.end, "#{node.method_name}\n\n#{source}\n")
332
331
  else
333
332
  corrector.replace(node, "#{node.method_name}\n\n#{source}")
@@ -62,12 +62,12 @@ module RuboCop
62
62
  #
63
63
  # @example AllowedConstants: ['ClassMethods']
64
64
  #
65
- # # good
66
- # module A
67
- # module ClassMethods
68
- # # ...
69
- # end
70
- # end
65
+ # # good
66
+ # module A
67
+ # module ClassMethods
68
+ # # ...
69
+ # end
70
+ # end
71
71
  #
72
72
  class Documentation < Base
73
73
  include DocumentationComment
@@ -97,14 +97,14 @@ module RuboCop
97
97
  #
98
98
  # @example AllowedMethods: ['method_missing', 'respond_to_missing?']
99
99
  #
100
- # # good
101
- # class Foo
102
- # def method_missing(name, *args)
103
- # end
104
- #
105
- # def respond_to_missing?(symbol, include_private)
106
- # end
107
- # end
100
+ # # good
101
+ # class Foo
102
+ # def method_missing(name, *args)
103
+ # end
104
+ #
105
+ # def respond_to_missing?(symbol, include_private)
106
+ # end
107
+ # end
108
108
  #
109
109
  class DocumentationMethod < Base
110
110
  include DocumentationComment
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Enforces consistent style for empty class definitions.
7
+ #
8
+ # This cop can enforce either a two-line class definition or `Class.new`
9
+ # for classes with no body.
10
+ #
11
+ # The supported styles are:
12
+ #
13
+ # * class_definition (default) - prefer two-line class definition over `Class.new`
14
+ # * class_new - prefer `Class.new` over class definition
15
+ #
16
+ # @example EnforcedStyle: class_definition (default)
17
+ # # bad
18
+ # FooError = Class.new(StandardError)
19
+ #
20
+ # # okish
21
+ # class FooError < StandardError; end
22
+ #
23
+ # # good
24
+ # class FooError < StandardError
25
+ # end
26
+ #
27
+ # @example EnforcedStyle: class_new
28
+ # # bad
29
+ # class FooError < StandardError
30
+ # end
31
+ #
32
+ # # bad
33
+ # class FooError < StandardError; end
34
+ #
35
+ # # good
36
+ # FooError = Class.new(StandardError)
37
+ #
38
+ class EmptyClassDefinition < Base
39
+ include ConfigurableEnforcedStyle
40
+ include Alignment
41
+ include RangeHelp
42
+ extend AutoCorrector
43
+
44
+ MSG_CLASS_DEFINITION =
45
+ 'Prefer a two-line class definition over `Class.new` for classes with no body.'
46
+ MSG_CLASS_NEW = 'Prefer `Class.new` over class definition for classes with no body.'
47
+
48
+ # @!method class_new_assignment?(node)
49
+ def_node_matcher :class_new_assignment?, <<~PATTERN
50
+ (casgn _ _ (send (const _ :Class) :new ...))
51
+ PATTERN
52
+
53
+ def on_casgn(node)
54
+ return unless style == :class_definition
55
+ return unless node.expression
56
+
57
+ class_new_node = find_class_new_node(node.expression)
58
+ return if chained_with_any_method?(node.expression, class_new_node)
59
+ return if variable_parent_class?(class_new_node)
60
+
61
+ add_offense(node, message: MSG_CLASS_DEFINITION) do |corrector|
62
+ autocorrect_class_new(corrector, node)
63
+ end
64
+ end
65
+
66
+ def on_class(node)
67
+ return unless style == :class_new
68
+ return unless empty_class?(node)
69
+
70
+ add_offense(node, message: MSG_CLASS_NEW) do |corrector|
71
+ autocorrect_class_definition(corrector, node)
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def autocorrect_class_new(corrector, node)
78
+ indent = ' ' * node.loc.column
79
+ class_name = node.name
80
+ class_new_node = find_class_new_node(node.expression)
81
+ parent_class = extract_parent_class(class_new_node)
82
+
83
+ replacement = if parent_class
84
+ "class #{class_name} < #{parent_class}\n#{indent}end"
85
+ else
86
+ "class #{class_name}\n#{indent}end"
87
+ end
88
+
89
+ corrector.replace(node, replacement)
90
+ end
91
+
92
+ def autocorrect_class_definition(corrector, node)
93
+ source_line = processed_source.buffer.source_line(node.loc.line)
94
+ indent = source_line[/\A */]
95
+ class_name = node.identifier.source
96
+ parent_class = node.parent_class&.source
97
+ range = range_by_whole_lines(node.source_range, include_final_newline: true)
98
+
99
+ replacement = if parent_class
100
+ "#{indent}#{class_name} = Class.new(#{parent_class})\n"
101
+ else
102
+ "#{indent}#{class_name} = Class.new\n"
103
+ end
104
+
105
+ corrector.replace(range, replacement)
106
+ end
107
+
108
+ def extract_parent_class(class_new_node)
109
+ first_arg = class_new_node.first_argument
110
+ first_arg&.source
111
+ end
112
+
113
+ def variable_parent_class?(class_new_node)
114
+ first_arg = class_new_node.first_argument
115
+ return false unless first_arg
116
+
117
+ !first_arg.const_type?
118
+ end
119
+
120
+ def find_class_new_node(node)
121
+ return nil unless node.send_type?
122
+ return nil unless node.receiver&.const_type?
123
+
124
+ return node if node.receiver.const_name.to_sym == :Class && node.method?(:new)
125
+
126
+ nil
127
+ end
128
+
129
+ def chained_with_any_method?(expression_node, class_new_node)
130
+ return true unless expression_node == class_new_node
131
+
132
+ false
133
+ end
134
+
135
+ def empty_class?(node)
136
+ body = node.body
137
+ return true unless body
138
+
139
+ body.begin_type? && body.children.empty?
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -227,12 +227,15 @@ module RuboCop
227
227
  remove_whole_lines(corrector, node.loc.end)
228
228
  return unless node.else?
229
229
 
230
- remove_whole_lines(corrector, leave_branch.source_range)
230
+ if leave_branch
231
+ remove_whole_lines(corrector, leave_branch.source_range)
232
+ corrector.insert_after(
233
+ heredoc_branch.last_argument.loc.heredoc_end, "\n#{leave_branch.source}"
234
+ )
235
+ end
236
+
231
237
  remove_whole_lines(corrector, node.loc.else)
232
238
  remove_whole_lines(corrector, range_of_branch_to_remove(node, guard))
233
- corrector.insert_after(
234
- heredoc_branch.last_argument.loc.heredoc_end, "\n#{leave_branch.source}"
235
- )
236
239
  end
237
240
 
238
241
  def range_of_branch_to_remove(node, guard)
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Enforces the use of either `Hash#[]` or `Hash#fetch` for hash lookup.
7
+ #
8
+ # This cop can be configured to prefer either bracket-style (`[]`)
9
+ # or fetch-style lookup. It is disabled by default.
10
+ #
11
+ # When enforcing `fetch` style, only single-argument bracket access is flagged.
12
+ # When enforcing `brackets` style, only `fetch` calls with a single key
13
+ # argument are flagged (not those with default values or blocks).
14
+ #
15
+ # @safety
16
+ # This cop is unsafe because `Hash#[]` and `Hash#fetch` have different
17
+ # semantics. `Hash#[]` returns `nil` for missing keys, while `Hash#fetch`
18
+ # raises a `KeyError`. Replacing one with the other can change program
19
+ # behavior in cases where the key is missing.
20
+ #
21
+ # Additionally, it cannot be guaranteed that the receiver is a `Hash`
22
+ # or responds to the replacement method.
23
+ #
24
+ # @example EnforcedStyle: brackets (default)
25
+ # # bad
26
+ # hash.fetch(key)
27
+ #
28
+ # # good
29
+ # hash[key]
30
+ #
31
+ # # good - fetch with default value is allowed
32
+ # hash.fetch(key, default)
33
+ #
34
+ # # good - fetch with block is allowed
35
+ # hash.fetch(key) { default }
36
+ #
37
+ # @example EnforcedStyle: fetch
38
+ # # bad
39
+ # hash[key]
40
+ #
41
+ # # good
42
+ # hash.fetch(key)
43
+ #
44
+ class HashLookupMethod < Base
45
+ include ConfigurableEnforcedStyle
46
+ extend AutoCorrector
47
+
48
+ BRACKET_MSG = 'Use `Hash#[]` instead of `Hash#fetch`.'
49
+ FETCH_MSG = 'Use `Hash#fetch` instead of `Hash#[]`.'
50
+
51
+ RESTRICT_ON_SEND = %i[[] fetch].freeze
52
+
53
+ def on_send(node)
54
+ if offense_for_brackets?(node)
55
+ add_offense(node.loc.selector, message: BRACKET_MSG) do |corrector|
56
+ correct_fetch_to_brackets(corrector, node)
57
+ end
58
+ elsif offense_for_fetch?(node)
59
+ add_offense(node, message: FETCH_MSG) do |corrector|
60
+ correct_brackets_to_fetch(corrector, node)
61
+ end
62
+ end
63
+ end
64
+ alias on_csend on_send
65
+
66
+ private
67
+
68
+ def offense_for_brackets?(node)
69
+ style == :brackets && node.receiver && node.method?(:fetch) && node.arguments.one? &&
70
+ !node.block_literal?
71
+ end
72
+
73
+ def offense_for_fetch?(node)
74
+ style == :fetch && node.method?(:[]) && node.arguments.one?
75
+ end
76
+
77
+ def correct_fetch_to_brackets(corrector, node)
78
+ receiver = node.receiver.source
79
+ key = node.first_argument.source
80
+ replacement = "#{receiver}[#{key}]"
81
+ replacement = "(#{replacement})" if node.csend_type?
82
+ corrector.replace(node, replacement)
83
+ end
84
+
85
+ def correct_brackets_to_fetch(corrector, node)
86
+ receiver = node.receiver.source
87
+ key = node.first_argument.source
88
+ operator = node.csend_type? ? '&.' : '.'
89
+ corrector.replace(node, "#{receiver}#{operator}fetch(#{key})")
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -8,20 +8,20 @@ module RuboCop
8
8
  #
9
9
  # @example
10
10
  #
11
- # # bad
12
- # tired? ? 'stop' : 'go faster' if running?
11
+ # # bad
12
+ # tired? ? 'stop' : 'go faster' if running?
13
13
  #
14
- # # bad
15
- # if tired?
16
- # "please stop"
17
- # else
18
- # "keep going"
19
- # end if running?
14
+ # # bad
15
+ # if tired?
16
+ # "please stop"
17
+ # else
18
+ # "keep going"
19
+ # end if running?
20
20
  #
21
- # # good
22
- # if running?
23
- # tired? ? 'stop' : 'go faster'
24
- # end
21
+ # # good
22
+ # if running?
23
+ # tired? ? 'stop' : 'go faster'
24
+ # end
25
25
  class IfUnlessModifierOfIfUnless < Base
26
26
  include StatementModifier
27
27
  extend AutoCorrector
@@ -6,18 +6,18 @@ module RuboCop
6
6
  # Checks for use of the lambda.(args) syntax.
7
7
  #
8
8
  # @example EnforcedStyle: call (default)
9
- # # bad
10
- # lambda.(x, y)
9
+ # # bad
10
+ # lambda.(x, y)
11
11
  #
12
- # # good
13
- # lambda.call(x, y)
12
+ # # good
13
+ # lambda.call(x, y)
14
14
  #
15
15
  # @example EnforcedStyle: braces
16
- # # bad
17
- # lambda.call(x, y)
16
+ # # bad
17
+ # lambda.call(x, y)
18
18
  #
19
- # # good
20
- # lambda.(x, y)
19
+ # # good
20
+ # lambda.(x, y)
21
21
  class LambdaCall < Base
22
22
  include ConfigurableEnforcedStyle
23
23
  extend AutoCorrector
@@ -26,33 +26,65 @@ module RuboCop
26
26
  #
27
27
  # Array.method_defined?(:find, false)
28
28
  #
29
+ # # bad
30
+ # Array.class_variables.include?(:foo)
31
+ # Array.constants.include?(:foo)
32
+ # Array.private_instance_methods.include?(:foo)
33
+ # Array.protected_instance_methods.include?(:foo)
34
+ # Array.public_instance_methods.include?(:foo)
35
+ # Array.included_modules.include?(:foo)
36
+ #
37
+ # # good
38
+ # Array.class_variable_defined?(:foo)
39
+ # Array.const_defined?(:foo)
40
+ # Array.private_method_defined?(:foo)
41
+ # Array.protected_method_defined?(:foo)
42
+ # Array.public_method_defined?(:foo)
43
+ # Array.include?(:foo)
44
+ #
45
+ # @example AllowedMethods: [included_modules]
46
+ #
47
+ # # good
48
+ # Array.included_modules.include?(:foo)
49
+ #
29
50
  class ModuleMemberExistenceCheck < Base
51
+ include AllowedMethods
30
52
  extend AutoCorrector
31
53
 
32
54
  MSG = 'Use `%<replacement>s` instead.'
33
55
 
34
- RESTRICT_ON_SEND = %i[instance_methods].freeze
35
-
36
- # @!method instance_methods_inclusion?(node)
37
- def_node_matcher :instance_methods_inclusion?, <<~PATTERN
56
+ # @!method module_member_inclusion?(node)
57
+ def_node_matcher :module_member_inclusion?, <<~PATTERN
38
58
  (call
39
- (call _ :instance_methods _?)
59
+ {(call _ %METHODS_WITH_INHERIT_PARAM _?) (call _ %METHODS_WITHOUT_INHERIT_PARAM)}
40
60
  {:include? :member?}
41
61
  _)
42
62
  PATTERN
43
63
 
44
- def on_send(node) # rubocop:disable Metrics/AbcSize
64
+ METHOD_REPLACEMENTS = {
65
+ class_variables: :class_variable_defined?,
66
+ constants: :const_defined?,
67
+ included_modules: :include?,
68
+ instance_methods: :method_defined?,
69
+ private_instance_methods: :private_method_defined?,
70
+ protected_instance_methods: :protected_method_defined?,
71
+ public_instance_methods: :public_method_defined?
72
+ }.freeze
73
+
74
+ METHODS_WITHOUT_INHERIT_PARAM = Set[:class_variables, :included_modules].freeze
75
+ METHODS_WITH_INHERIT_PARAM =
76
+ (METHOD_REPLACEMENTS.keys.to_set - METHODS_WITHOUT_INHERIT_PARAM).freeze
77
+
78
+ RESTRICT_ON_SEND = METHOD_REPLACEMENTS.keys.freeze
79
+
80
+ def on_send(node)
45
81
  return unless (parent = node.parent)
46
- return unless instance_methods_inclusion?(parent)
82
+ return unless module_member_inclusion?(parent)
47
83
  return unless simple_method_argument?(node) && simple_method_argument?(parent)
84
+ return if allowed_method?(node.method_name)
48
85
 
49
86
  offense_range = node.location.selector.join(parent.source_range.end)
50
- replacement =
51
- if node.first_argument.nil? || node.first_argument.true_type?
52
- "method_defined?(#{parent.first_argument.source})"
53
- else
54
- "method_defined?(#{parent.first_argument.source}, #{node.first_argument.source})"
55
- end
87
+ replacement = replacement_for(node, parent)
56
88
 
57
89
  add_offense(offense_range, message: format(MSG, replacement: replacement)) do |corrector|
58
90
  corrector.replace(offense_range, replacement)
@@ -62,6 +94,17 @@ module RuboCop
62
94
 
63
95
  private
64
96
 
97
+ def replacement_for(node, parent)
98
+ replacement_method = METHOD_REPLACEMENTS.fetch(node.method_name)
99
+ without_inherit_param = METHODS_WITHOUT_INHERIT_PARAM.include?(node.method_name)
100
+
101
+ if without_inherit_param || node.first_argument.nil? || node.first_argument.true_type?
102
+ "#{replacement_method}(#{parent.first_argument.source})"
103
+ else
104
+ "#{replacement_method}(#{parent.first_argument.source}, #{node.first_argument.source})"
105
+ end
106
+ end
107
+
65
108
  def simple_method_argument?(node)
66
109
  return false if node.splat_argument? || node.block_argument?
67
110
  return false if node.first_argument&.hash_type?