rubocop 1.80.2 → 1.82.1

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 (136) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +35 -7
  4. data/config/obsoletion.yml +4 -0
  5. data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
  6. data/lib/rubocop/cli.rb +3 -3
  7. data/lib/rubocop/comment_config.rb +62 -17
  8. data/lib/rubocop/config_loader.rb +5 -2
  9. data/lib/rubocop/config_loader_resolver.rb +7 -6
  10. data/lib/rubocop/config_store.rb +5 -0
  11. data/lib/rubocop/cop/autocorrect_logic.rb +8 -4
  12. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -2
  13. data/lib/rubocop/cop/correctors/alignment_corrector.rb +2 -4
  14. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -2
  15. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +10 -5
  16. data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
  17. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  18. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
  19. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  20. data/lib/rubocop/cop/layout/class_structure.rb +1 -1
  21. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  22. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -0
  23. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +30 -12
  24. data/lib/rubocop/cop/layout/end_alignment.rb +4 -0
  25. data/lib/rubocop/cop/layout/hash_alignment.rb +2 -5
  26. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  27. data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -4
  28. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  29. data/lib/rubocop/cop/layout/indentation_width.rb +12 -1
  30. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  31. data/lib/rubocop/cop/layout/line_length.rb +17 -5
  32. data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
  33. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +5 -1
  34. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +6 -4
  35. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
  36. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  37. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  38. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  39. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  40. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
  41. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
  42. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
  43. data/lib/rubocop/cop/lint/debugger.rb +0 -2
  44. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
  45. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  46. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  47. data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
  48. data/lib/rubocop/cop/lint/literal_as_condition.rb +4 -0
  49. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  50. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +16 -6
  51. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
  52. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
  53. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
  54. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +7 -1
  55. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  56. data/lib/rubocop/cop/lint/self_assignment.rb +10 -2
  57. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  58. data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
  59. data/lib/rubocop/cop/lint/useless_assignment.rb +44 -16
  60. data/lib/rubocop/cop/lint/useless_or.rb +15 -2
  61. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +1 -1
  62. data/lib/rubocop/cop/lint/void.rb +7 -0
  63. data/lib/rubocop/cop/message_annotator.rb +1 -1
  64. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  65. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  66. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -4
  67. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  68. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +1 -1
  69. data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
  70. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  71. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  72. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  73. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  74. data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
  75. data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -5
  76. data/lib/rubocop/cop/naming/method_name.rb +4 -2
  77. data/lib/rubocop/cop/naming/predicate_method.rb +16 -4
  78. data/lib/rubocop/cop/security/json_load.rb +33 -11
  79. data/lib/rubocop/cop/style/array_intersect.rb +2 -2
  80. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
  81. data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -2
  82. data/lib/rubocop/cop/style/case_equality.rb +11 -13
  83. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -0
  84. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -14
  85. data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
  86. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  87. data/lib/rubocop/cop/style/empty_method.rb +0 -6
  88. data/lib/rubocop/cop/style/endless_method.rb +15 -2
  89. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  90. data/lib/rubocop/cop/style/float_division.rb +15 -1
  91. data/lib/rubocop/cop/style/guard_clause.rb +0 -11
  92. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  93. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  94. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +12 -1
  95. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
  96. data/lib/rubocop/cop/style/module_member_existence_check.rb +74 -0
  97. data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -4
  98. data/lib/rubocop/cop/style/nil_comparison.rb +9 -7
  99. data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
  100. data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
  101. data/lib/rubocop/cop/style/parallel_assignment.rb +2 -2
  102. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  103. data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
  104. data/lib/rubocop/cop/style/redundant_format.rb +26 -5
  105. data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
  106. data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -0
  107. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -2
  108. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
  109. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
  110. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  111. data/lib/rubocop/cop/style/semicolon.rb +23 -7
  112. data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -1
  113. data/lib/rubocop/cop/style/super_arguments.rb +2 -2
  114. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
  115. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
  116. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  117. data/lib/rubocop/cop/util.rb +2 -3
  118. data/lib/rubocop/cop/utils/format_string.rb +10 -0
  119. data/lib/rubocop/cops_documentation_generator.rb +4 -4
  120. data/lib/rubocop/directive_comment.rb +46 -3
  121. data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -0
  122. data/lib/rubocop/lsp/diagnostic.rb +10 -14
  123. data/lib/rubocop/lsp/stdin_runner.rb +0 -16
  124. data/lib/rubocop/magic_comment.rb +20 -0
  125. data/lib/rubocop/rake_task.rb +1 -1
  126. data/lib/rubocop/remote_config.rb +7 -8
  127. data/lib/rubocop/result_cache.rb +38 -27
  128. data/lib/rubocop/rspec/shared_contexts.rb +2 -2
  129. data/lib/rubocop/rspec/support.rb +1 -1
  130. data/lib/rubocop/runner.rb +4 -0
  131. data/lib/rubocop/target_ruby.rb +11 -2
  132. data/lib/rubocop/version.rb +1 -1
  133. data/lib/rubocop.rb +2 -0
  134. data/lib/ruby_lsp/rubocop/addon.rb +23 -8
  135. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
  136. metadata +9 -7
@@ -145,8 +145,10 @@ module RuboCop
145
145
  next_sibling.if_type? && contains_guard_clause?(next_sibling)
146
146
  end
147
147
 
148
+ # rubocop:disable Metrics/CyclomaticComplexity
148
149
  def last_heredoc_argument(node)
149
150
  n = last_heredoc_argument_node(node)
151
+ n = n.children.first while n.respond_to?(:begin_type?) && n.begin_type?
150
152
 
151
153
  return n if heredoc?(n)
152
154
  return unless n.respond_to?(:arguments)
@@ -158,6 +160,7 @@ module RuboCop
158
160
 
159
161
  last_heredoc_argument(n.receiver) if n.respond_to?(:receiver)
160
162
  end
163
+ # rubocop:enable Metrics/CyclomaticComplexity
161
164
 
162
165
  def last_heredoc_argument_node(node)
163
166
  return node unless node.respond_to?(:if_branch)
@@ -76,28 +76,40 @@ module RuboCop
76
76
  # # good
77
77
  # class ErrorA < BaseError; end
78
78
  # class ErrorB < BaseError; end
79
- # class ErrorC < BaseError; end
80
79
  #
81
80
  # # good
82
81
  # class ErrorA < BaseError; end
83
82
  #
84
83
  # class ErrorB < BaseError; end
85
84
  #
86
- # class ErrorC < BaseError; end
85
+ # # good - DefLikeMacros: [memoize]
86
+ # memoize :attribute_a
87
+ # memoize :attribute_b
88
+ #
89
+ # # good
90
+ # memoize :attribute_a
91
+ #
92
+ # memoize :attribute_b
87
93
  #
88
94
  # @example AllowAdjacentOneLineDefs: false
89
95
  #
90
96
  # # bad
91
97
  # class ErrorA < BaseError; end
92
98
  # class ErrorB < BaseError; end
93
- # class ErrorC < BaseError; end
94
99
  #
95
100
  # # good
96
101
  # class ErrorA < BaseError; end
97
102
  #
98
103
  # class ErrorB < BaseError; end
99
104
  #
100
- # class ErrorC < BaseError; end
105
+ # # bad - DefLikeMacros: [memoize]
106
+ # memoize :attribute_a
107
+ # memoize :attribute_b
108
+ #
109
+ # # good
110
+ # memoize :attribute_a
111
+ #
112
+ # memoize :attribute_b
101
113
  #
102
114
  class EmptyLineBetweenDefs < Base
103
115
  include RangeHelp
@@ -158,6 +170,8 @@ module RuboCop
158
170
  def def_location(correction_node)
159
171
  if correction_node.any_block_type?
160
172
  correction_node.source_range.join(correction_node.children.first.source_range)
173
+ elsif correction_node.send_type?
174
+ correction_node.source_range
161
175
  else
162
176
  correction_node.loc.keyword.join(correction_node.loc.name)
163
177
  end
@@ -175,8 +189,14 @@ module RuboCop
175
189
  end
176
190
 
177
191
  def macro_candidate?(node)
178
- node.any_block_type? && node.children.first.macro? &&
179
- empty_line_between_macros.include?(node.children.first.method_name)
192
+ macro_candidate = if node.any_block_type?
193
+ node.send_node
194
+ elsif node.send_type?
195
+ node
196
+ end
197
+ return false unless macro_candidate
198
+
199
+ macro_candidate.macro? && empty_line_between_macros.include?(macro_candidate.method_name)
180
200
  end
181
201
 
182
202
  def method_candidate?(node)
@@ -240,7 +260,9 @@ module RuboCop
240
260
  end
241
261
 
242
262
  def def_start(node)
243
- if node.any_block_type? && node.children.first.send_type?
263
+ node = node.send_node if node.any_block_type?
264
+
265
+ if node.send_type?
244
266
  node.source_range.line
245
267
  else
246
268
  node.loc.keyword.line
@@ -252,11 +274,7 @@ module RuboCop
252
274
  end
253
275
 
254
276
  def end_loc(node)
255
- if node.any_def_type? && node.endless?
256
- node.source_range.end
257
- else
258
- node.loc.end
259
- end
277
+ node.source_range.end
260
278
  end
261
279
 
262
280
  def autocorrect_remove_lines(corrector, newline_pos, count)
@@ -128,6 +128,10 @@ module RuboCop
128
128
  # assignment, we let rhs be the receiver of those method calls before
129
129
  # we check if it's an if/unless/while/until.
130
130
  return unless (rhs = first_part_of_call_chain(rhs))
131
+
132
+ # If `rhs` is a `begin` node, find the first non-`begin` child.
133
+ rhs = rhs.child_nodes.first while rhs.begin_type?
134
+
131
135
  return unless rhs.conditional?
132
136
  return if rhs.if_type? && rhs.ternary?
133
137
 
@@ -193,7 +193,6 @@ module RuboCop
193
193
  SEPARATOR_ALIGNMENT_STYLES = %w[EnforcedColonStyle EnforcedHashRocketStyle].freeze
194
194
 
195
195
  def on_send(node)
196
- return if double_splat?(node)
197
196
  return unless node.arguments?
198
197
 
199
198
  last_argument = node.last_argument
@@ -233,6 +232,8 @@ module RuboCop
233
232
  end
234
233
 
235
234
  def argument_before_hash(hash_node)
235
+ return hash_node.children.first.children.first if hash_node.children.first.kwsplat_type?
236
+
236
237
  hash_node.left_sibling.respond_to?(:loc) ? hash_node.left_sibling : nil
237
238
  end
238
239
 
@@ -241,10 +242,6 @@ module RuboCop
241
242
  self.column_deltas = Hash.new { |hash, key| hash[key] = {} }
242
243
  end
243
244
 
244
- def double_splat?(node)
245
- node.children.last.is_a?(Symbol)
246
- end
247
-
248
245
  def check_pairs(node)
249
246
  first_pair = node.pairs.first
250
247
  reset!
@@ -168,7 +168,7 @@ module RuboCop
168
168
 
169
169
  def subsequent_closing_parentheses_in_same_line?(outermost_send)
170
170
  last_arg_of_outer_send = outermost_send.last_argument
171
- return false unless last_arg_of_outer_send&.loc.respond_to?(:end) &&
171
+ return false unless last_arg_of_outer_send&.loc?(:end) &&
172
172
  (end_of_last_arg_of_outer_send = last_arg_of_outer_send.loc.end)
173
173
 
174
174
  end_of_outer_send = outermost_send.loc.end
@@ -230,7 +230,7 @@ module RuboCop
230
230
 
231
231
  def find_most_bottom_of_heredoc_end(arguments)
232
232
  arguments.filter_map do |argument|
233
- argument.loc.heredoc_end.end_pos if argument.loc.respond_to?(:heredoc_end)
233
+ argument.loc.heredoc_end.end_pos if argument.loc?(:heredoc_end)
234
234
  end.max
235
235
  end
236
236
 
@@ -89,6 +89,7 @@ module RuboCop
89
89
  end
90
90
 
91
91
  def line_too_long?(node)
92
+ return false unless max_line_length
92
93
  return false if unlimited_heredoc_length?
93
94
 
94
95
  body = heredoc_body(node)
@@ -108,10 +109,6 @@ module RuboCop
108
109
  config.for_cop('Layout/LineLength')['AllowHeredoc']
109
110
  end
110
111
 
111
- def max_line_length
112
- config.for_cop('Layout/LineLength')['Max']
113
- end
114
-
115
112
  def adjust_squiggly(corrector, node)
116
113
  corrector.replace(node.loc.heredoc_body, indented_body(node))
117
114
  corrector.replace(node.loc.heredoc_end, indented_end(node))
@@ -99,7 +99,7 @@ module RuboCop
99
99
 
100
100
  if str.heredoc?
101
101
  ranges << loc.heredoc_body
102
- elsif loc.respond_to?(:begin) && loc.begin
102
+ elsif str.loc?(:begin)
103
103
  ranges << loc.expression
104
104
  end
105
105
  end
@@ -83,7 +83,10 @@ module RuboCop
83
83
 
84
84
  return unless begins_its_line?(end_loc)
85
85
 
86
- check_indentation(end_loc, node.body)
86
+ # For blocks where the dot is on a new line, use the dot position as the base.
87
+ # Otherwise, use the end keyword position as the base.
88
+ base_loc = dot_on_new_line?(node) ? node.send_node.loc.dot : end_loc
89
+ check_indentation(base_loc, node.body)
87
90
 
88
91
  return unless indented_internal_methods_style?
89
92
 
@@ -383,6 +386,14 @@ module RuboCop
383
386
 
384
387
  leftmost_modifier_of(node.parent)
385
388
  end
389
+
390
+ def dot_on_new_line?(node)
391
+ send_node = node.send_node
392
+ return false unless send_node.loc?(:dot)
393
+
394
+ receiver = send_node.receiver
395
+ receiver && receiver.last_line < send_node.loc.dot.line
396
+ end
386
397
  end
387
398
  end
388
399
  end
@@ -101,7 +101,7 @@ module RuboCop
101
101
  ranges << loc.expression
102
102
  elsif literal.heredoc?
103
103
  ranges << loc.heredoc_body
104
- elsif (loc.respond_to?(:begin) && loc.begin) || ignored_parent?(literal)
104
+ elsif literal.loc?(:begin) || ignored_parent?(literal)
105
105
  ranges << loc.expression
106
106
  end
107
107
  end
@@ -134,6 +134,7 @@ module RuboCop
134
134
 
135
135
  def check_for_breakable_block(block_node)
136
136
  return unless block_node.single_line?
137
+ return if receiver_contains_heredoc?(block_node)
137
138
 
138
139
  line_index = block_node.loc.line - 1
139
140
  range = breakable_block_range(block_node)
@@ -251,17 +252,22 @@ module RuboCop
251
252
  [max - indentation_difference(line), 0].max
252
253
  end
253
254
 
255
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
254
256
  def check_line(line, line_index)
255
257
  return if line_length(line) <= max
256
258
  return if allowed_line?(line, line_index)
259
+ if allow_rbs_inline_annotation? && rbs_inline_annotation_on_source_line?(line_index)
260
+ return
261
+ end
257
262
 
258
- if ignore_cop_directives? && directive_on_source_line?(line_index)
263
+ if allow_cop_directives? && directive_on_source_line?(line_index)
259
264
  return check_directive_line(line, line_index)
260
265
  end
261
266
  return check_line_for_exemptions(line, line_index) if allow_uri? || allow_qualified_name?
262
267
 
263
268
  register_offense(excess_range(nil, line, line_index), line, line_index)
264
269
  end
270
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
265
271
 
266
272
  def allowed_line?(line, line_index)
267
273
  matches_allowed_pattern?(line) ||
@@ -305,6 +311,7 @@ module RuboCop
305
311
  def max
306
312
  cop_config['Max']
307
313
  end
314
+ alias max_line_length max
308
315
 
309
316
  def allow_heredoc?
310
317
  allowed_heredoc
@@ -321,7 +328,7 @@ module RuboCop
321
328
  def extract_heredocs(ast)
322
329
  return [] unless ast
323
330
 
324
- ast.each_node(:str, :dstr, :xstr).select(&:heredoc?).map do |node|
331
+ ast.each_node(:any_str).select(&:heredoc?).map do |node|
325
332
  body = node.location.heredoc_body
326
333
  delimiter = node.location.heredoc_end.source.strip
327
334
  [body.first_line...body.last_line, delimiter]
@@ -341,6 +348,13 @@ module RuboCop
341
348
  heredocs.any? { |range, _delimiter| range.cover?(line_number) }
342
349
  end
343
350
 
351
+ def receiver_contains_heredoc?(node)
352
+ return false unless (receiver = node.receiver)
353
+ return true if receiver.any_str_type? && receiver.heredoc?
354
+
355
+ receiver.each_descendant(:any_str).any?(&:heredoc?)
356
+ end
357
+
344
358
  def check_directive_line(line, line_index)
345
359
  length_without_directive = line_length_without_directive(line)
346
360
  return if length_without_directive <= max
@@ -393,9 +407,7 @@ module RuboCop
393
407
 
394
408
  def string_delimiter(node)
395
409
  delimiter = node.loc.begin
396
- if node.parent&.dstr_type? && node.parent.loc.respond_to?(:begin)
397
- delimiter ||= node.parent.loc.begin
398
- end
410
+ delimiter ||= node.parent.loc.begin if node.parent&.dstr_type? && node.parent.loc?(:begin)
399
411
  delimiter = delimiter&.source
400
412
 
401
413
  delimiter if %w[' "].include?(delimiter)
@@ -78,6 +78,8 @@ module RuboCop
78
78
  end
79
79
 
80
80
  def line_break_necessary_in_args?(node)
81
+ return false unless max_line_length
82
+
81
83
  needed_length_for_args(node) > max_line_length
82
84
  end
83
85
 
@@ -84,19 +84,23 @@ module RuboCop
84
84
  end
85
85
  end
86
86
 
87
+ # rubocop:disable Metrics/AbcSize
87
88
  def offending_range(node, lhs, rhs, given_style)
88
89
  return false unless begins_its_line?(rhs)
89
90
  return false if not_for_this_cop?(node)
90
91
 
91
92
  @base = alignment_base(node, rhs, given_style)
92
93
  correct_column = if @base
93
- @base.column + extra_indentation(given_style, node.parent)
94
+ parent = node.parent
95
+ parent = parent.parent if parent&.any_block_type?
96
+ @base.column + extra_indentation(given_style, parent)
94
97
  else
95
98
  indentation(lhs) + correct_indentation(node)
96
99
  end
97
100
  @column_delta = correct_column - rhs.column
98
101
  rhs if @column_delta.nonzero?
99
102
  end
103
+ # rubocop:enable Metrics/AbcSize
100
104
 
101
105
  def extra_indentation(given_style, parent)
102
106
  if given_style == :indented_relative_to_receiver
@@ -102,10 +102,12 @@ module RuboCop
102
102
  return true if begins_its_line?(assignment_rhs.source_range)
103
103
  end
104
104
 
105
- given_style == :aligned &&
106
- (kw_node_with_special_indentation(node) ||
107
- assignment_node ||
108
- argument_in_method_call(node, :with_or_without_parentheses))
105
+ return false unless given_style == :aligned
106
+ return true if kw_node_with_special_indentation(node) || assignment_node
107
+
108
+ node = argument_in_method_call(node, :with_or_without_parentheses)
109
+
110
+ node.respond_to?(:def_modifier?) && !node.def_modifier?
109
111
  end
110
112
 
111
113
  def message(node, lhs, rhs)
@@ -29,7 +29,7 @@ module RuboCop
29
29
  MSG = '`%<kw_loc>s` at %<kw_loc_line>d, %<kw_loc_column>d is not ' \
30
30
  'aligned with `%<beginning>s` at ' \
31
31
  '%<begin_loc_line>d, %<begin_loc_column>d.'
32
- ANCESTOR_TYPES = %i[kwbegin any_def class module any_block].freeze
32
+ ANCESTOR_TYPES = %i[kwbegin any_def class module sclass any_block].freeze
33
33
  ALTERNATIVE_ACCESS_MODIFIERS = %i[public_class_method private_class_method].freeze
34
34
 
35
35
  def on_resbody(node)
@@ -91,7 +91,7 @@ module RuboCop
91
91
  )
92
92
  end
93
93
 
94
- # rubocop:disable Metrics/AbcSize
94
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
95
95
  def alignment_source(node, starting_loc)
96
96
  ending_loc =
97
97
  case node.type
@@ -100,6 +100,8 @@ module RuboCop
100
100
  when :def, :defs, :class, :module,
101
101
  :lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn
102
102
  node.loc.name
103
+ when :sclass
104
+ node.identifier.source_range
103
105
  when :masgn
104
106
  node.lhs.source_range
105
107
  else
@@ -109,7 +111,7 @@ module RuboCop
109
111
 
110
112
  range_between(starting_loc.begin_pos, ending_loc.end_pos).source
111
113
  end
112
- # rubocop:enable Metrics/AbcSize
114
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
113
115
 
114
116
  # We will use ancestor or wrapper with access modifier.
115
117
 
@@ -194,6 +196,14 @@ module RuboCop
194
196
  def alignment_location(alignment_node)
195
197
  if begin_end_alignment_style == 'start_of_line'
196
198
  start_line_range(alignment_node)
199
+ elsif alignment_node.any_block_type?
200
+ # If the alignment node is a block, the `rescue`/`ensure` keyword should
201
+ # be aligned to the start of the block. It is possible that the block's
202
+ # `send_node` spans multiple lines, in which case it should align to the
203
+ # start of the last line.
204
+ send_node = alignment_node.send_node
205
+ range = processed_source.buffer.line_range(send_node.last_line)
206
+ range.adjust(begin_pos: range.source =~ /\S/)
197
207
  else
198
208
  alignment_node.source_range
199
209
  end
@@ -23,16 +23,8 @@ module RuboCop
23
23
  cfg['EnforcedStyle'] || 'space'
24
24
  end
25
25
 
26
- def kind(token)
27
- 'comma' if token.comma? && !before_semicolon?(token)
28
- end
29
-
30
- private
31
-
32
- def before_semicolon?(token)
33
- tokens = processed_source.tokens
34
-
35
- tokens[tokens.index(token) + 1].semicolon?
26
+ def kind(token, next_token)
27
+ 'comma' if token.comma? && !next_token.semicolon?
36
28
  end
37
29
  end
38
30
  end
@@ -20,7 +20,7 @@ module RuboCop
20
20
  cfg['EnforcedStyle'] || 'space'
21
21
  end
22
22
 
23
- def kind(token)
23
+ def kind(token, _next_token)
24
24
  'semicolon' if token.semicolon?
25
25
  end
26
26
 
@@ -167,7 +167,7 @@ module RuboCop
167
167
 
168
168
  def check(node, locations, begin_keyword = DO)
169
169
  locations.each do |loc|
170
- next unless node.loc.respond_to?(loc)
170
+ next unless node.loc?(loc)
171
171
 
172
172
  range = node.loc.public_send(loc)
173
173
  next unless range
@@ -113,7 +113,7 @@ module RuboCop
113
113
  return [] unless ast
114
114
 
115
115
  heredocs = []
116
- ast.each_node(:str, :dstr, :xstr) do |node|
116
+ ast.each_node(:any_str) do |node|
117
117
  next unless node.heredoc?
118
118
 
119
119
  body = node.location.heredoc_body
@@ -35,6 +35,26 @@ module RuboCop
35
35
  # def cook(dry_ingredients = self.dry_ingredients)
36
36
  # dry_ingredients.combine
37
37
  # end
38
+ #
39
+ # # bad
40
+ # def foo(pie = pie = pie)
41
+ # pie.heat_up
42
+ # end
43
+ #
44
+ # # good
45
+ # def foo(pie)
46
+ # pie.heat_up
47
+ # end
48
+ #
49
+ # # bad
50
+ # def foo(pie = cake = pie)
51
+ # [pie, cake].each(&:heat_up)
52
+ # end
53
+ #
54
+ # # good
55
+ # def foo(cake = pie)
56
+ # [pie, cake].each(&:heat_up)
57
+ # end
38
58
  class CircularArgumentReference < Base
39
59
  extend TargetRubyVersion
40
60
 
@@ -51,11 +71,35 @@ module RuboCop
51
71
  private
52
72
 
53
73
  def check_for_circular_argument_references(arg_name, arg_value)
54
- return unless arg_value.lvar_type?
55
- return unless arg_value.to_a == [arg_name]
74
+ if arg_value.lvar_type? && arg_value.to_a == [arg_name]
75
+ add_offense(arg_value, message: format(MSG, arg_name: arg_name))
76
+
77
+ return
78
+ end
79
+
80
+ check_assignment_chain(arg_name, arg_value)
81
+ end
82
+
83
+ # rubocop:disable Metrics/AbcSize
84
+ def check_assignment_chain(arg_name, node)
85
+ return unless node.lvasgn_type?
86
+
87
+ seen_variables = Set[]
88
+ current_node = node
89
+
90
+ while current_node.lvasgn_type?
91
+ seen_variables << current_node.children.first if current_node.lvasgn_type?
92
+ current_node = current_node.children.last
93
+ end
94
+
95
+ return unless current_node.lvar_type?
96
+
97
+ variable_node = current_node.children.first
98
+ return unless seen_variables.include?(variable_node) || variable_node == arg_name
56
99
 
57
- add_offense(arg_value, message: format(MSG, arg_name: arg_name))
100
+ add_offense(current_node, message: format(MSG, arg_name: arg_name))
58
101
  end
102
+ # rubocop:enable Metrics/AbcSize
59
103
  end
60
104
  end
61
105
  end
@@ -31,7 +31,7 @@ module RuboCop
31
31
 
32
32
  # @!method overwritten_constant(node)
33
33
  def_node_matcher :overwritten_constant, <<~PATTERN
34
- (resbody nil? (casgn nil? $_) nil?)
34
+ (resbody nil? $(casgn _ _) nil?)
35
35
  PATTERN
36
36
 
37
37
  def self.autocorrect_incompatible_with
@@ -41,7 +41,8 @@ module RuboCop
41
41
  def on_resbody(node)
42
42
  return unless (constant = overwritten_constant(node))
43
43
 
44
- add_offense(node.loc.assoc, message: format(MSG, constant: constant)) do |corrector|
44
+ message = format(MSG, constant: constant.source)
45
+ add_offense(node.loc.assoc, message: message) do |corrector|
45
46
  corrector.remove(range_between(node.loc.keyword.end_pos, node.loc.assoc.end_pos))
46
47
  end
47
48
  end
@@ -13,34 +13,40 @@ module RuboCop
13
13
  # @example
14
14
  # # bad
15
15
  # # rubocop:disable Layout/LineLength Style/Encoding
16
- # # ^ missing comma
16
+ #
17
+ # # good
18
+ # # rubocop:disable Layout/LineLength, Style/Encoding
17
19
  #
18
20
  # # bad
19
21
  # # rubocop:disable
20
22
  #
23
+ # # good
24
+ # # rubocop:disable all
25
+ #
21
26
  # # bad
22
27
  # # rubocop:disable Layout/LineLength # rubocop:disable Style/Encoding
23
28
  #
29
+ # # good
30
+ # # rubocop:disable Layout/LineLength
31
+ # # rubocop:disable Style/Encoding
32
+ #
24
33
  # # bad
25
34
  # # rubocop:wrongmode Layout/LineLength
26
35
  #
27
36
  # # good
28
37
  # # rubocop:disable Layout/LineLength
29
38
  #
30
- # # good
31
- # # rubocop:disable Layout/LineLength, Style/Encoding
32
- #
33
- # # good
34
- # # rubocop:disable all
39
+ # # bad
40
+ # # rubocop:disable Layout/LineLength comment
35
41
  #
36
42
  # # good
37
- # # rubocop:disable Layout/LineLength -- This is a good comment.
43
+ # # rubocop:disable Layout/LineLength -- comment
38
44
  #
39
45
  class CopDirectiveSyntax < Base
40
46
  COMMON_MSG = 'Malformed directive comment detected.'
41
47
 
42
48
  MISSING_MODE_NAME_MSG = 'The mode name is missing.'
43
- INVALID_MODE_NAME_MSG = 'The mode name must be one of `enable`, `disable`, or `todo`.'
49
+ INVALID_MODE_NAME_MSG = 'The mode name must be one of `enable`, `disable`, `todo`, `push`, or `pop`.' # rubocop:disable Layout/LineLength
44
50
  MISSING_COP_NAME_MSG = 'The cop name is missing.'
45
51
  MALFORMED_COP_NAMES_MSG = 'Cop names must be separated by commas. ' \
46
52
  'Comment in the directive must start with `--`.'
@@ -102,8 +102,6 @@ module RuboCop
102
102
  end
103
103
 
104
104
  def debugger_method?(send_node)
105
- return false if send_node.parent&.send_type? && send_node.parent.receiver == send_node
106
-
107
105
  debugger_methods.include?(chained_method_name(send_node))
108
106
  end
109
107
 
@@ -118,8 +118,11 @@ module RuboCop
118
118
 
119
119
  def replacement_args(node)
120
120
  algorithm_constant, = algorithm_const(node)
121
- algorithm_name = algorithm_name(algorithm_constant)
121
+ if algorithm_constant.source == 'OpenSSL::Cipher::Cipher'
122
+ return node.first_argument.source
123
+ end
122
124
 
125
+ algorithm_name = algorithm_name(algorithm_constant)
123
126
  if openssl_class(algorithm_constant) == 'OpenSSL::Cipher'
124
127
  build_cipher_arguments(node, algorithm_name, node.arguments.empty?)
125
128
  else
@@ -25,17 +25,17 @@ module RuboCop
25
25
  #
26
26
  # # bad - repeated alternate patterns with the same conditions don't depend on the order
27
27
  # case x
28
- # in foo | bar
28
+ # in 0 | 1
29
29
  # first_method
30
- # in bar | foo
30
+ # in 1 | 0
31
31
  # second_method
32
32
  # end
33
33
  #
34
34
  # # good
35
35
  # case x
36
- # in foo | bar
36
+ # in 0 | 1
37
37
  # first_method
38
- # in bar | baz
38
+ # in 2 | 3
39
39
  # second_method
40
40
  # end
41
41
  #