rubocop 1.79.2 → 1.82.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 (142) 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/exe/rubocop +1 -8
  6. data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
  7. data/lib/rubocop/cli.rb +8 -3
  8. data/lib/rubocop/comment_config.rb +62 -17
  9. data/lib/rubocop/config_loader.rb +5 -2
  10. data/lib/rubocop/config_loader_resolver.rb +7 -6
  11. data/lib/rubocop/config_store.rb +5 -0
  12. data/lib/rubocop/cop/autocorrect_logic.rb +6 -4
  13. data/lib/rubocop/cop/correctors/alignment_corrector.rb +8 -7
  14. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -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/empty_lines_after_module_inclusion.rb +1 -1
  25. data/lib/rubocop/cop/layout/end_alignment.rb +4 -0
  26. data/lib/rubocop/cop/layout/hash_alignment.rb +2 -5
  27. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  28. data/lib/rubocop/cop/layout/heredoc_indentation.rb +0 -4
  29. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  30. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  31. data/lib/rubocop/cop/layout/line_length.rb +16 -5
  32. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +8 -4
  33. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
  34. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  35. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  36. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
  37. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
  38. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
  39. data/lib/rubocop/cop/lint/debugger.rb +0 -2
  40. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
  41. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
  42. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  43. data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
  44. data/lib/rubocop/cop/lint/literal_as_condition.rb +4 -0
  45. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  46. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +17 -8
  47. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
  48. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
  49. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
  50. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +7 -1
  51. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  52. data/lib/rubocop/cop/lint/self_assignment.rb +15 -6
  53. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  54. data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
  55. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
  56. data/lib/rubocop/cop/lint/useless_or.rb +15 -2
  57. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +1 -1
  58. data/lib/rubocop/cop/lint/void.rb +7 -0
  59. data/lib/rubocop/cop/message_annotator.rb +1 -1
  60. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  61. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  62. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +0 -4
  63. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  64. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
  65. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +1 -1
  66. data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
  67. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  68. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  69. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  70. data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
  71. data/lib/rubocop/cop/mixin/trailing_comma.rb +5 -6
  72. data/lib/rubocop/cop/naming/method_name.rb +5 -3
  73. data/lib/rubocop/cop/naming/predicate_method.rb +19 -6
  74. data/lib/rubocop/cop/security/json_load.rb +33 -11
  75. data/lib/rubocop/cop/style/array_intersect.rb +46 -12
  76. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
  77. data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -2
  78. data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
  79. data/lib/rubocop/cop/style/case_equality.rb +11 -13
  80. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -0
  81. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -14
  82. data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
  83. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  84. data/lib/rubocop/cop/style/empty_method.rb +0 -6
  85. data/lib/rubocop/cop/style/endless_method.rb +15 -2
  86. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  87. data/lib/rubocop/cop/style/float_division.rb +15 -1
  88. data/lib/rubocop/cop/style/guard_clause.rb +0 -11
  89. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  90. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  91. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  92. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +12 -1
  93. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
  94. data/lib/rubocop/cop/style/module_member_existence_check.rb +74 -0
  95. data/lib/rubocop/cop/style/multiline_method_signature.rb +0 -4
  96. data/lib/rubocop/cop/style/nil_comparison.rb +9 -7
  97. data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
  98. data/lib/rubocop/cop/style/parallel_assignment.rb +2 -2
  99. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  100. data/lib/rubocop/cop/style/redundant_begin.rb +34 -0
  101. data/lib/rubocop/cop/style/redundant_condition.rb +1 -1
  102. data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
  103. data/lib/rubocop/cop/style/redundant_format.rb +26 -5
  104. data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
  105. data/lib/rubocop/cop/style/redundant_parentheses.rb +14 -11
  106. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -2
  107. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
  108. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
  109. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  110. data/lib/rubocop/cop/style/safe_navigation.rb +18 -1
  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/string_concatenation.rb +17 -13
  114. data/lib/rubocop/cop/style/super_arguments.rb +2 -2
  115. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  116. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
  117. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
  118. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  119. data/lib/rubocop/cop/util.rb +2 -3
  120. data/lib/rubocop/cop/utils/format_string.rb +10 -0
  121. data/lib/rubocop/cop/variable_force/variable.rb +1 -1
  122. data/lib/rubocop/cop/variable_force.rb +9 -7
  123. data/lib/rubocop/cops_documentation_generator.rb +4 -4
  124. data/lib/rubocop/directive_comment.rb +46 -3
  125. data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -5
  126. data/lib/rubocop/lsp/diagnostic.rb +10 -14
  127. data/lib/rubocop/lsp/routes.rb +31 -2
  128. data/lib/rubocop/lsp/stdin_runner.rb +0 -16
  129. data/lib/rubocop/magic_comment.rb +20 -0
  130. data/lib/rubocop/rake_task.rb +1 -1
  131. data/lib/rubocop/remote_config.rb +7 -8
  132. data/lib/rubocop/result_cache.rb +1 -1
  133. data/lib/rubocop/rspec/shared_contexts.rb +2 -2
  134. data/lib/rubocop/rspec/support.rb +1 -1
  135. data/lib/rubocop/runner.rb +6 -4
  136. data/lib/rubocop/target_finder.rb +9 -9
  137. data/lib/rubocop/target_ruby.rb +11 -2
  138. data/lib/rubocop/version.rb +1 -1
  139. data/lib/rubocop.rb +2 -0
  140. data/lib/ruby_lsp/rubocop/addon.rb +23 -8
  141. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
  142. metadata +8 -6
@@ -76,7 +76,7 @@ module RuboCop
76
76
  end
77
77
 
78
78
  def on_send(node) # rubocop:disable InternalAffairs/OnSendWithoutOnCSend
79
- new_identifier = node.first_argument
79
+ return unless (new_identifier = node.first_argument)
80
80
  return unless new_identifier.basic_literal?
81
81
 
82
82
  new_identifier = new_identifier.value
@@ -357,7 +357,7 @@ module RuboCop
357
357
  end
358
358
 
359
359
  def find_heredoc(node)
360
- node.each_node(:str, :dstr, :xstr).find(&:heredoc?)
360
+ node.each_node(:any_str).find(&:heredoc?)
361
361
  end
362
362
 
363
363
  def buffer
@@ -120,7 +120,7 @@ module RuboCop
120
120
  end
121
121
 
122
122
  def heredoc?(node)
123
- node.type?(:str, :dstr) && node.heredoc?
123
+ node.any_str_type? && node.heredoc?
124
124
  end
125
125
 
126
126
  def end_range(node)
@@ -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)
@@ -38,7 +38,7 @@ module RuboCop
38
38
  RESTRICT_ON_SEND = MODULE_INCLUSION_METHODS
39
39
 
40
40
  def on_send(node)
41
- return if node.receiver
41
+ return if node.receiver || node.arguments.empty?
42
42
  return if node.parent&.type?(:send, :any_block)
43
43
 
44
44
  return if next_line_empty_or_enable_directive_comment?(node.last_line)
@@ -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
 
@@ -108,10 +108,6 @@ module RuboCop
108
108
  config.for_cop('Layout/LineLength')['AllowHeredoc']
109
109
  end
110
110
 
111
- def max_line_length
112
- config.for_cop('Layout/LineLength')['Max']
113
- end
114
-
115
111
  def adjust_squiggly(corrector, node)
116
112
  corrector.replace(node.loc.heredoc_body, indented_body(node))
117
113
  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
@@ -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) ||
@@ -321,7 +327,7 @@ module RuboCop
321
327
  def extract_heredocs(ast)
322
328
  return [] unless ast
323
329
 
324
- ast.each_node(:str, :dstr, :xstr).select(&:heredoc?).map do |node|
330
+ ast.each_node(:any_str).select(&:heredoc?).map do |node|
325
331
  body = node.location.heredoc_body
326
332
  delimiter = node.location.heredoc_end.source.strip
327
333
  [body.first_line...body.last_line, delimiter]
@@ -341,6 +347,13 @@ module RuboCop
341
347
  heredocs.any? { |range, _delimiter| range.cover?(line_number) }
342
348
  end
343
349
 
350
+ def receiver_contains_heredoc?(node)
351
+ return false unless (receiver = node.receiver)
352
+ return true if receiver.any_str_type? && receiver.heredoc?
353
+
354
+ receiver.each_descendant(:any_str).any?(&:heredoc?)
355
+ end
356
+
344
357
  def check_directive_line(line, line_index)
345
358
  length_without_directive = line_length_without_directive(line)
346
359
  return if length_without_directive <= max
@@ -393,9 +406,7 @@ module RuboCop
393
406
 
394
407
  def string_delimiter(node)
395
408
  delimiter = node.loc.begin
396
- if node.parent&.dstr_type? && node.parent.loc.respond_to?(:begin)
397
- delimiter ||= node.parent.loc.begin
398
- end
409
+ delimiter ||= node.parent.loc.begin if node.parent&.dstr_type? && node.parent.loc?(:begin)
399
410
  delimiter = delimiter&.source
400
411
 
401
412
  delimiter if %w[' "].include?(delimiter)
@@ -10,6 +10,8 @@ module RuboCop
10
10
  # condition, an explicit `return` statement, etc. In other contexts, the second operand should
11
11
  # be indented regardless of enforced style.
12
12
  #
13
+ # In both styles, operators should be aligned when an assignment begins on the next line.
14
+ #
13
15
  # @example EnforcedStyle: aligned (default)
14
16
  # # bad
15
17
  # if a +
@@ -100,10 +102,12 @@ module RuboCop
100
102
  return true if begins_its_line?(assignment_rhs.source_range)
101
103
  end
102
104
 
103
- given_style == :aligned &&
104
- (kw_node_with_special_indentation(node) ||
105
- assignment_node ||
106
- 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?
107
111
  end
108
112
 
109
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
@@ -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
@@ -24,8 +24,6 @@ module RuboCop
24
24
 
25
25
  MSG_REPEATED_ELEMENT = 'Duplicate element inside regexp character class'
26
26
 
27
- OCTAL_DIGITS_AFTER_ESCAPE = 2
28
-
29
27
  def on_regexp(node)
30
28
  each_repeated_character_class_element_loc(node) do |loc|
31
29
  add_offense(loc, message: MSG_REPEATED_ELEMENT) do |corrector|
@@ -40,9 +38,9 @@ module RuboCop
40
38
 
41
39
  seen = Set.new
42
40
  group_expressions(node, expr.expressions) do |group|
43
- group_source = group.map(&:to_s).join
41
+ group_source = group.to_s
44
42
 
45
- yield source_range(group) if seen.include?(group_source)
43
+ yield group.expression if seen.include?(group_source)
46
44
 
47
45
  seen << group_source
48
46
  end
@@ -52,40 +50,13 @@ module RuboCop
52
50
  private
53
51
 
54
52
  def group_expressions(node, expressions)
55
- # Create a mutable list to simplify state tracking while we iterate.
56
- expressions = expressions.to_a
57
-
58
- until expressions.empty?
59
- # With we may need to compose a group of multiple expressions.
60
- group = [expressions.shift]
61
- next if within_interpolation?(node, group.first)
62
-
63
- # With regexp_parser < 2.7 escaped octal sequences may be up to 3
64
- # separate expressions ("\\0", "0", "1").
65
- pop_octal_digits(group, expressions) if escaped_octal?(group.first.to_s)
66
-
67
- yield(group)
68
- end
69
- end
70
-
71
- def pop_octal_digits(current_child, expressions)
72
- OCTAL_DIGITS_AFTER_ESCAPE.times do
73
- next_child = expressions.first
74
- break unless octal?(next_child.to_s)
53
+ expressions.each do |expression|
54
+ next if within_interpolation?(node, expression)
75
55
 
76
- current_child << expressions.shift
56
+ yield(expression)
77
57
  end
78
58
  end
79
59
 
80
- def source_range(children)
81
- return children.first.expression if children.size == 1
82
-
83
- range_between(
84
- children.first.expression.begin_pos,
85
- children.last.expression.begin_pos + children.last.to_s.length
86
- )
87
- end
88
-
89
60
  def skip_expression?(expr)
90
61
  expr.type != :set || expr.token == :intersection
91
62
  end
@@ -99,14 +70,6 @@ module RuboCop
99
70
  interpolation_locs(node).any? { |il| il.overlaps?(parse_tree_child_loc) }
100
71
  end
101
72
 
102
- def escaped_octal?(string)
103
- string.length == 2 && string[0] == '\\' && octal?(string[1])
104
- end
105
-
106
- def octal?(char)
107
- ('0'..'7').cover?(char)
108
- end
109
-
110
73
  def interpolation_locs(node)
111
74
  @interpolation_locs ||= {}
112
75