rubocop 1.75.5 → 1.75.7

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9421b54201da724554271e44969dd9b78ea86635ba622fd5d3f1807d9e3e3530
4
- data.tar.gz: 6f76b18333faee3119a32957b72a5906a9a99cde620b95dc88014b1ebdbfa4f7
3
+ metadata.gz: ef87f85272e845ecc9477a7c890be9f5d8daa78ef1c9625c3252ca8bee58ee40
4
+ data.tar.gz: aeb5a1576ba984944521e10cd92933cbf37080d492a25ed8e51bf46926dc0c4a
5
5
  SHA512:
6
- metadata.gz: bfbad1a5c263aa4de3704954e0835a71d4d6b56bbf564dfec23dc1cc7b75913ae064ddf70a01c942a1ebfb3502fe881d840826a306ce24ed450747058f59541e
7
- data.tar.gz: 88be3812e81036e0e8dde18c38548052f447ae76cf3195fc1b16189eb4c5d7e5b460f8425ecee663d96bfcb4c543f592f8471b7306906262426894fa76301da1
6
+ metadata.gz: 7f668097cd95658c24f521bed8e11b43c3b5ff01bdb49bc2e1cc5a71af630cb751a402bf8026f90cb95907fea56ff2cabe5ea0139329fa3e7fc31a46ca615fc4
7
+ data.tar.gz: cb542cf88e2de605a086e69009dcb8ae2afa4d0b7a713671e6c134cf8b77e5ccd4f6e408c6566be62d57809552e7ef0de30b849b619b0192c358a1441d4060a8
data/config/default.yml CHANGED
@@ -3702,7 +3702,9 @@ Style/CommentedKeyword:
3702
3702
  Style/ComparableBetween:
3703
3703
  Description: 'Enforces the use of `Comparable#between?` instead of logical comparison.'
3704
3704
  Enabled: pending
3705
+ Safe: false
3705
3706
  VersionAdded: '1.74'
3707
+ VersionChanged: '1.75'
3706
3708
  StyleGuide: '#ranges-or-between'
3707
3709
 
3708
3710
  Style/ComparableClamp:
@@ -6,10 +6,11 @@ module RuboCop
6
6
  # An attribute assignment method calls should be listed only once
7
7
  # in a gemspec.
8
8
  #
9
- # Assigning to an attribute with the same name using `spec.foo =` will be
10
- # an unintended usage. On the other hand, duplication of methods such
11
- # as `spec.requirements`, `spec.add_runtime_dependency`, and others are
12
- # permitted because it is the intended use of appending values.
9
+ # Assigning to an attribute with the same name using `spec.foo =` or
10
+ # `spec.attribute#[]=` will be an unintended usage. On the other hand,
11
+ # duplication of methods such # as `spec.requirements`,
12
+ # `spec.add_runtime_dependency`, and others are permitted because it is
13
+ # the intended use of appending values.
13
14
  #
14
15
  # @example
15
16
  # # bad
@@ -34,6 +35,18 @@ module RuboCop
34
35
  # spec.add_dependency('parallel', '~> 1.10')
35
36
  # spec.add_dependency('parser', '>= 2.3.3.1', '< 3.0')
36
37
  # end
38
+ #
39
+ # # bad
40
+ # Gem::Specification.new do |spec|
41
+ # spec.metadata["key"] = "value"
42
+ # spec.metadata["key"] = "value"
43
+ # end
44
+ #
45
+ # # good
46
+ # Gem::Specification.new do |spec|
47
+ # spec.metadata["key"] = "value"
48
+ # end
49
+ #
37
50
  class DuplicatedAssignment < Base
38
51
  include RangeHelp
39
52
  include GemspecHelp
@@ -47,9 +60,26 @@ module RuboCop
47
60
  (lvar #match_block_variable_name?) _ ...)
48
61
  PATTERN
49
62
 
63
+ # @!method indexed_assignment_method_declarations(node)
64
+ def_node_search :indexed_assignment_method_declarations, <<~PATTERN
65
+ (send
66
+ (send (lvar #match_block_variable_name?) _)
67
+ :[]=
68
+ literal?
69
+ _
70
+ )
71
+ PATTERN
72
+
50
73
  def on_new_investigation
51
74
  return if processed_source.blank?
52
75
 
76
+ process_assignment_method_nodes
77
+ process_indexed_assignment_method_nodes
78
+ end
79
+
80
+ private
81
+
82
+ def process_assignment_method_nodes
53
83
  duplicated_assignment_method_nodes.each do |nodes|
54
84
  nodes[1..].each do |node|
55
85
  register_offense(node, node.method_name, nodes.first.first_line)
@@ -57,7 +87,14 @@ module RuboCop
57
87
  end
58
88
  end
59
89
 
60
- private
90
+ def process_indexed_assignment_method_nodes
91
+ duplicated_indexed_assignment_method_nodes.each do |nodes|
92
+ nodes[1..].each do |node|
93
+ assignment = "#{node.children.first.method_name}[#{node.first_argument.source}]="
94
+ register_offense(node, assignment, nodes.first.first_line)
95
+ end
96
+ end
97
+ end
61
98
 
62
99
  def match_block_variable_name?(receiver_name)
63
100
  gem_specification(processed_source.ast) do |block_variable_name|
@@ -73,6 +110,13 @@ module RuboCop
73
110
  .select { |nodes| nodes.size > 1 }
74
111
  end
75
112
 
113
+ def duplicated_indexed_assignment_method_nodes
114
+ indexed_assignment_method_declarations(processed_source.ast)
115
+ .group_by { |node| [node.children.first.method_name, node.first_argument] }
116
+ .values
117
+ .select { |nodes| nodes.size > 1 }
118
+ end
119
+
76
120
  def register_offense(node, assignment, line_of_first_occurrence)
77
121
  line_range = node.loc.column...node.loc.last_column
78
122
  offense_location = source_range(processed_source.buffer, node.first_line, line_range)
@@ -22,51 +22,25 @@ module RuboCop
22
22
  RESTRICT_ON_SEND = %i[[] []=].freeze
23
23
 
24
24
  def on_send(node)
25
- return unless (first_argument = node.first_argument)
26
-
27
- begin_pos = first_argument.source_range.begin_pos
28
- return unless (range = offense_range(node, begin_pos))
29
-
30
- register_offense(range)
31
- end
32
-
33
- private
34
-
35
- def offense_range(node, begin_pos)
36
25
  receiver_end_pos = node.receiver.source_range.end_pos
37
26
  selector_begin_pos = node.loc.selector.begin_pos
38
27
  return if receiver_end_pos >= selector_begin_pos
39
28
  return if dot_before_brackets?(node, receiver_end_pos, selector_begin_pos)
40
29
 
41
- if reference_variable_with_brackets?(node)
42
- range_between(receiver_end_pos, selector_begin_pos)
43
- elsif node.method?(:[]=)
44
- offense_range_for_assignment(node, begin_pos)
30
+ range = range_between(receiver_end_pos, selector_begin_pos)
31
+
32
+ add_offense(range) do |corrector|
33
+ corrector.remove(range)
45
34
  end
46
35
  end
47
36
 
37
+ private
38
+
48
39
  def dot_before_brackets?(node, receiver_end_pos, selector_begin_pos)
49
40
  return false unless node.loc.respond_to?(:dot) && (dot = node.loc.dot)
50
41
 
51
42
  dot.begin_pos == receiver_end_pos && dot.end_pos == selector_begin_pos
52
43
  end
53
-
54
- def offense_range_for_assignment(node, begin_pos)
55
- end_pos = node.receiver.source_range.end_pos
56
-
57
- return if begin_pos - end_pos == 1 ||
58
- (range = range_between(end_pos, begin_pos - 1)).source.start_with?('[')
59
-
60
- range
61
- end
62
-
63
- def register_offense(range)
64
- add_offense(range) { |corrector| corrector.remove(range) }
65
- end
66
-
67
- def reference_variable_with_brackets?(node)
68
- node.receiver&.variable? && node.method?(:[]) && node.arguments.size == 1
69
- end
70
44
  end
71
45
  end
72
46
  end
@@ -87,6 +87,7 @@ module RuboCop
87
87
  return if node.array_type? && !node.square_brackets?
88
88
 
89
89
  tokens, left, right = array_brackets(node)
90
+ return unless left && right
90
91
 
91
92
  if empty_brackets?(left, right, tokens: tokens)
92
93
  return empty_offenses(node, left, right, EMPTY_MSG)
@@ -43,7 +43,7 @@ module RuboCop
43
43
  dup: 'to_h',
44
44
  exists?: 'exist?',
45
45
  gethostbyaddr: 'Addrinfo#getnameinfo',
46
- gethostbyname: 'Addrinfo#getaddrinfo',
46
+ gethostbyname: 'Addrinfo.getaddrinfo',
47
47
  iterator?: 'block_given?'
48
48
  }.freeze
49
49
 
@@ -39,9 +39,52 @@ module RuboCop
39
39
  # end
40
40
  #
41
41
  # alias bar foo
42
+ #
43
+ # @example AllCops:ActiveSupportExtensionsEnabled: false (default)
44
+ #
45
+ # # good
46
+ # def foo
47
+ # 1
48
+ # end
49
+ #
50
+ # delegate :foo, to: :bar
51
+ #
52
+ # @example AllCops:ActiveSupportExtensionsEnabled: true
53
+ #
54
+ # # bad
55
+ # def foo
56
+ # 1
57
+ # end
58
+ #
59
+ # delegate :foo, to: :bar
60
+ #
61
+ # # good
62
+ # def foo
63
+ # 1
64
+ # end
65
+ #
66
+ # delegate :baz, to: :bar
67
+ #
68
+ # # good - delegate with splat arguments is ignored
69
+ # def foo
70
+ # 1
71
+ # end
72
+ #
73
+ # delegate :foo, **options
74
+ #
75
+ # # good - delegate inside a condition is ignored
76
+ # def foo
77
+ # 1
78
+ # end
79
+ #
80
+ # if cond
81
+ # delegate :foo, to: :bar
82
+ # end
83
+ #
42
84
  class DuplicateMethods < Base
43
85
  MSG = 'Method `%<method>s` is defined at both %<defined>s and %<current>s.'
44
- RESTRICT_ON_SEND = %i[alias_method attr_reader attr_writer attr_accessor attr].freeze
86
+ RESTRICT_ON_SEND = %i[alias_method attr_reader attr_writer attr_accessor attr
87
+ delegate].freeze
45
88
 
46
89
  def initialize(config = nil, options = nil)
47
90
  super
@@ -85,15 +128,28 @@ module RuboCop
85
128
  (send nil? :alias_method (sym $_name) _)
86
129
  PATTERN
87
130
 
131
+ # @!method delegate_method?(node)
132
+ def_node_matcher :delegate_method?, <<~PATTERN
133
+ (send nil? :delegate
134
+ ({sym str} $_)+
135
+ (hash <(pair (sym :to) _) ...>)
136
+ )
137
+ PATTERN
138
+
88
139
  # @!method sym_name(node)
89
140
  def_node_matcher :sym_name, '(sym $_name)'
90
- def on_send(node)
141
+
142
+ def on_send(node) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
91
143
  if (name = alias_method?(node))
92
144
  return if node.ancestors.any?(&:if_type?)
93
145
 
94
146
  found_instance_method(node, name)
95
147
  elsif (attr = node.attribute_accessor?)
96
148
  on_attr(node, *attr)
149
+ elsif active_support_extensions_enabled? && (names = delegate_method?(node))
150
+ return if node.ancestors.any?(&:if_type?)
151
+
152
+ on_delegate(node, names)
97
153
  end
98
154
  end
99
155
 
@@ -118,6 +174,32 @@ module RuboCop
118
174
  current: source_location(node))
119
175
  end
120
176
 
177
+ def on_delegate(node, method_names)
178
+ name_prefix = delegate_prefix(node)
179
+
180
+ method_names.each do |name|
181
+ name = "#{name_prefix}_#{name}" if name_prefix
182
+
183
+ found_instance_method(node, name)
184
+ end
185
+ end
186
+
187
+ def delegate_prefix(node)
188
+ kwargs_node = node.last_argument
189
+
190
+ return unless (prefix = hash_value(kwargs_node, :prefix))
191
+
192
+ if prefix.true_type?
193
+ hash_value(kwargs_node, :to).value
194
+ elsif prefix.type?(:sym, :str)
195
+ prefix.value
196
+ end
197
+ end
198
+
199
+ def hash_value(node, key)
200
+ node.pairs.find { |pair| pair.key.value == key }&.value
201
+ end
202
+
121
203
  def found_instance_method(node, name)
122
204
  return found_sclass_method(node, name) unless (scope = node.parent_module_name)
123
205
 
@@ -104,6 +104,8 @@ module RuboCop
104
104
  end
105
105
 
106
106
  def chained_assignment?(node)
107
+ return true if node.lvasgn_type? && node.expression&.send_type?
108
+
107
109
  node.respond_to?(:expression) && node.expression&.lvasgn_type?
108
110
  end
109
111
 
@@ -39,7 +39,7 @@ module RuboCop
39
39
  class AbcSize < Base
40
40
  include MethodComplexity
41
41
 
42
- MSG = 'Assignment Branch Condition size for %<method>s is too high. ' \
42
+ MSG = 'Assignment Branch Condition size for `%<method>s` is too high. ' \
43
43
  '[%<abc_vector>s %<complexity>.4g/%<max>.4g]'
44
44
 
45
45
  private
@@ -195,15 +195,27 @@ module RuboCop
195
195
  def autocorrect(corrector, node)
196
196
  case style
197
197
  when :group
198
- def_nodes = find_corresponding_def_nodes(node)
199
- return unless def_nodes.any?
200
-
201
- replace_defs(corrector, node, def_nodes)
198
+ autocorrect_group_style(corrector, node)
202
199
  when :inline
200
+ autocorrect_inline_style(corrector, node)
201
+ end
202
+ end
203
+
204
+ def autocorrect_group_style(corrector, node)
205
+ def_nodes = find_corresponding_def_nodes(node)
206
+ return unless def_nodes.any?
207
+
208
+ replace_defs(corrector, node, def_nodes)
209
+ end
210
+
211
+ def autocorrect_inline_style(corrector, node)
212
+ if node.parent&.begin_type?
213
+ remove_modifier_node_within_begin(corrector, node, node.parent)
214
+ else
203
215
  remove_nodes(corrector, node)
204
- select_grouped_def_nodes(node).each do |grouped_def_node|
205
- insert_inline_modifier(corrector, grouped_def_node, node.method_name)
206
- end
216
+ end
217
+ select_grouped_def_nodes(node).each do |grouped_def_node|
218
+ insert_inline_modifier(corrector, grouped_def_node, node.method_name)
207
219
  end
208
220
  end
209
221
 
@@ -224,9 +236,13 @@ module RuboCop
224
236
  end
225
237
 
226
238
  def offense?(node)
227
- (group_style? && access_modifier_is_inlined?(node) &&
228
- !node.parent&.if_type? && !right_siblings_same_inline_method?(node)) ||
229
- (inline_style? && access_modifier_is_not_inlined?(node))
239
+ if group_style?
240
+ return false if node.parent ? node.parent.if_type? : access_modifier_with_symbol?(node)
241
+
242
+ access_modifier_is_inlined?(node) && !right_siblings_same_inline_method?(node)
243
+ else
244
+ access_modifier_is_not_inlined?(node) && select_grouped_def_nodes(node).any?
245
+ end
230
246
  end
231
247
 
232
248
  def correctable_group_offense?(node)
@@ -331,6 +347,12 @@ module RuboCop
331
347
  end
332
348
  end
333
349
 
350
+ def remove_modifier_node_within_begin(corrector, modifier_node, begin_node)
351
+ def_node = begin_node.children[1]
352
+ range = modifier_node.source_range.begin.join(def_node.source_range.begin)
353
+ corrector.remove(range)
354
+ end
355
+
334
356
  def def_source(node, def_nodes)
335
357
  [
336
358
  *processed_source.ast_with_comments[node].map(&:text),
@@ -173,7 +173,7 @@ module RuboCop
173
173
  end
174
174
 
175
175
  def preferred_delimiters_config
176
- config.for_cop('Style/PercentLiteralDelimiters') ['PreferredDelimiters']
176
+ config.for_cop('Style/PercentLiteralDelimiters')['PreferredDelimiters']
177
177
  end
178
178
  end
179
179
  end
@@ -9,6 +9,9 @@ module RuboCop
9
9
  # although the difference generally isn't observable. If you require maximum
10
10
  # performance, consider using logical comparison.
11
11
  #
12
+ # @safety
13
+ # This cop is unsafe because the receiver may not respond to `between?`.
14
+ #
12
15
  # @example
13
16
  #
14
17
  # # bad
@@ -4,6 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # Checks for inheritance from `Data.define` to avoid creating the anonymous parent class.
7
+ # Inheriting from `Data.define` adds a superfluous level in inheritance tree.
7
8
  #
8
9
  # @safety
9
10
  # Autocorrection is unsafe because it will change the inheritance
@@ -17,12 +18,18 @@ module RuboCop
17
18
  # end
18
19
  # end
19
20
  #
21
+ # Person.ancestors
22
+ # # => [Person, #<Class:0x000000010b4e14a0>, Data, (...)]
23
+ #
20
24
  # # good
21
25
  # Person = Data.define(:first_name, :last_name) do
22
26
  # def age
23
27
  # 42
24
28
  # end
25
29
  # end
30
+ #
31
+ # Person.ancestors
32
+ # # => [Person, Data, (...)]
26
33
  class DataInheritance < Base
27
34
  include RangeHelp
28
35
  extend AutoCorrector
@@ -23,6 +23,17 @@ module RuboCop
23
23
  # end
24
24
  # ----
25
25
  #
26
+ # The code `def method_name = body if condition` is considered a bad case by
27
+ # `Style/AmbiguousEndlessMethodDefinition` cop. So, to respect the user's intention to use
28
+ # an endless method definition in the `if` body, the following code is allowed:
29
+ #
30
+ # [source,ruby]
31
+ # ----
32
+ # if condition
33
+ # def method_name = body
34
+ # end
35
+ # ----
36
+ #
26
37
  # NOTE: It is allowed when `defined?` argument has an undefined value,
27
38
  # because using the modifier form causes the following incompatibility:
28
39
  #
@@ -77,10 +88,14 @@ module RuboCop
77
88
  [Style::SoleNestedConditional]
78
89
  end
79
90
 
91
+ # rubocop:disable Metrics/AbcSize
80
92
  def on_if(node)
93
+ return if endless_method?(node.body)
94
+
81
95
  condition = node.condition
82
96
  return if defined_nodes(condition).any? { |n| defined_argument_is_undefined?(node, n) } ||
83
97
  pattern_matching_nodes(condition).any?
98
+
84
99
  return unless (msg = message(node))
85
100
 
86
101
  add_offense(node.loc.keyword, message: format(msg, keyword: node.keyword)) do |corrector|
@@ -90,9 +105,14 @@ module RuboCop
90
105
  ignore_node(node)
91
106
  end
92
107
  end
108
+ # rubocop:enable Metrics/AbcSize
93
109
 
94
110
  private
95
111
 
112
+ def endless_method?(body)
113
+ body&.any_def_type? && body.endless?
114
+ end
115
+
96
116
  def defined_nodes(condition)
97
117
  if condition.defined_type?
98
118
  [condition]
@@ -28,19 +28,16 @@ module RuboCop
28
28
 
29
29
  MSG = 'Avoid modifier `%<keyword>s` after another conditional.'
30
30
 
31
+ # rubocop:disable Metrics/AbcSize
31
32
  def on_if(node)
32
33
  return unless node.modifier_form? && node.body.if_type?
33
34
 
34
35
  add_offense(node.loc.keyword, message: format(MSG, keyword: node.keyword)) do |corrector|
35
- keyword = node.if? ? 'if' : 'unless'
36
-
37
- corrector.replace(node, <<~RUBY.chop)
38
- #{keyword} #{node.condition.source}
39
- #{node.if_branch.source}
40
- end
41
- RUBY
36
+ corrector.wrap(node.if_branch, "#{node.keyword} #{node.condition.source}\n", "\nend")
37
+ corrector.remove(node.if_branch.source_range.end.join(node.condition.source_range.end))
42
38
  end
43
39
  end
40
+ # rubocop:enable Metrics/AbcSize
44
41
  end
45
42
  end
46
43
  end
@@ -23,11 +23,13 @@ module RuboCop
23
23
  'clause in a multiline statement.'
24
24
 
25
25
  def on_if(node)
26
+ return if part_of_ignored_node?(node)
26
27
  return unless node.modifier_form? && node.body.multiline?
27
28
 
28
29
  add_offense(node, message: format(MSG, keyword: node.keyword)) do |corrector|
29
30
  corrector.replace(node, to_normal_if(node))
30
31
  end
32
+ ignore_node(node)
31
33
  end
32
34
 
33
35
  private
@@ -45,7 +45,7 @@ module RuboCop
45
45
  # Report offense only if changing case doesn't change semantics,
46
46
  # i.e., if the string would become dynamic or has special characters.
47
47
  ast = parse(corrected(node.source)).ast
48
- return if node.children != ast.children
48
+ return if node.children != ast&.children
49
49
 
50
50
  add_offense(node.loc.begin) do |corrector|
51
51
  corrector.replace(node, corrected(node.source))
@@ -155,7 +155,7 @@ module RuboCop
155
155
  end
156
156
 
157
157
  def preferred_delimiters
158
- config.for_cop('Style/PercentLiteralDelimiters') ['PreferredDelimiters']['%r'].chars
158
+ config.for_cop('Style/PercentLiteralDelimiters')['PreferredDelimiters']['%r'].chars
159
159
  end
160
160
 
161
161
  def allowed_omit_parentheses_with_percent_r_literal?(node)
@@ -185,8 +185,10 @@ module RuboCop
185
185
  end
186
186
 
187
187
  def add_parentheses?(node)
188
- node.assignment? || (node.operator_keyword? && !node.and_type?) ||
189
- (node.call_type? && node.arguments.any? && !node.parenthesized?)
188
+ return true if node.assignment? || (node.operator_keyword? && !node.and_type?)
189
+ return false unless node.call_type?
190
+
191
+ (node.arguments.any? && !node.parenthesized?) || node.prefix_not?
190
192
  end
191
193
 
192
194
  def parenthesized_method_arguments(node)
@@ -51,7 +51,6 @@ module RuboCop
51
51
  # Pathname.new('/') + 'test'
52
52
  #
53
53
  class StringConcatenation < Base
54
- include RangeHelp
55
54
  extend AutoCorrector
56
55
 
57
56
  MSG = 'Prefer string interpolation to string concatenation.'
@@ -147,7 +146,7 @@ module RuboCop
147
146
  when :str
148
147
  adjust_str(part)
149
148
  when :dstr
150
- part.children.all?(&:str_type?) ? adjust_str(part) : contents_range(part).source
149
+ part.children.all?(&:str_type?) ? adjust_str(part) : part.value
151
150
  else
152
151
  "\#{#{part.source}}"
153
152
  end
@@ -3,7 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for inheritance from Struct.new.
6
+ # Checks for inheritance from `Struct.new`. Inheriting from `Struct.new`
7
+ # adds a superfluous level in inheritance tree.
7
8
  #
8
9
  # @safety
9
10
  # Autocorrection is unsafe because it will change the inheritance
@@ -17,12 +18,18 @@ module RuboCop
17
18
  # end
18
19
  # end
19
20
  #
21
+ # Person.ancestors
22
+ # # => [Person, #<Class:0x000000010b4e14a0>, Struct, (...)]
23
+ #
20
24
  # # good
21
25
  # Person = Struct.new(:first_name, :last_name) do
22
26
  # def age
23
27
  # 42
24
28
  # end
25
29
  # end
30
+ #
31
+ # Person.ancestors
32
+ # # => [Person, Struct, (...)]
26
33
  class StructInheritance < Base
27
34
  include RangeHelp
28
35
  extend AutoCorrector
@@ -110,8 +110,13 @@ module RuboCop
110
110
  end
111
111
 
112
112
  def multiple_assignment_node
113
- return nil unless node.parent&.mlhs_type?
114
- return nil unless (grandparent_node = node.parent&.parent)
113
+ return nil unless (candidate_mlhs_node = node.parent)
114
+
115
+ # In `(foo, bar), *baz`, the splat node must be traversed as well.
116
+ candidate_mlhs_node = candidate_mlhs_node.parent if candidate_mlhs_node.splat_type?
117
+
118
+ return nil unless candidate_mlhs_node.mlhs_type?
119
+ return nil unless (grandparent_node = node.parent.parent)
115
120
  if (node = find_multiple_assignment_node(grandparent_node))
116
121
  return node
117
122
  end
@@ -139,7 +144,6 @@ module RuboCop
139
144
 
140
145
  def find_multiple_assignment_node(grandparent_node)
141
146
  return unless grandparent_node.type == MULTIPLE_LEFT_HAND_SIDE_TYPE
142
- return if grandparent_node.children.any?(&:splat_type?)
143
147
 
144
148
  parent = grandparent_node.parent
145
149
  return parent if parent.type == MULTIPLE_ASSIGNMENT_TYPE
@@ -178,6 +178,7 @@ module RuboCop
178
178
  next unless value.is_a?(Array)
179
179
  next if value.empty?
180
180
 
181
+ value.map! { |v| v.nil? ? '~' : v } # Change nil back to ~ as in the YAML file.
181
182
  output_buffer.puts "# #{param}: #{value.uniq.join(', ')}"
182
183
  end
183
184
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'cgi'
3
+ require 'cgi/escape'
4
4
  require 'erb'
5
5
 
6
6
  module RuboCop
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.75.5'
6
+ STRING = '1.75.7'
7
7
 
8
8
  MSG = '%<version>s (using %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
metadata CHANGED
@@ -1,16 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.75.5
4
+ version: 1.75.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
8
8
  - Jonas Arvidsson
9
9
  - Yuji Nakayama
10
- autorequire:
11
10
  bindir: exe
12
11
  cert_chain: []
13
- date: 2025-05-05 00:00:00.000000000 Z
12
+ date: 2025-05-21 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: json
@@ -1081,12 +1080,11 @@ licenses:
1081
1080
  - MIT
1082
1081
  metadata:
1083
1082
  homepage_uri: https://rubocop.org/
1084
- changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.75.5
1083
+ changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.75.7
1085
1084
  source_code_uri: https://github.com/rubocop/rubocop/
1086
1085
  documentation_uri: https://docs.rubocop.org/rubocop/1.75/
1087
1086
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
1088
1087
  rubygems_mfa_required: 'true'
1089
- post_install_message:
1090
1088
  rdoc_options: []
1091
1089
  require_paths:
1092
1090
  - lib
@@ -1101,8 +1099,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1101
1099
  - !ruby/object:Gem::Version
1102
1100
  version: '0'
1103
1101
  requirements: []
1104
- rubygems_version: 3.3.7
1105
- signing_key:
1102
+ rubygems_version: 3.6.2
1106
1103
  specification_version: 4
1107
1104
  summary: Automatic Ruby code style checking tool.
1108
1105
  test_files: []