rubocop 1.92.0 → 1.92.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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +1 -0
  3. data/lib/rubocop/cop/badge.rb +1 -1
  4. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +16 -1
  5. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +2 -2
  6. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +34 -0
  7. data/lib/rubocop/cop/layout/argument_alignment.rb +5 -1
  8. data/lib/rubocop/cop/layout/class_structure.rb +21 -7
  9. data/lib/rubocop/cop/layout/dot_position.rb +25 -15
  10. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +11 -7
  11. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +9 -3
  12. data/lib/rubocop/cop/layout/end_alignment.rb +3 -7
  13. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  14. data/lib/rubocop/cop/layout/first_argument_indentation.rb +26 -1
  15. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +15 -0
  16. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +11 -5
  17. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +5 -3
  18. data/lib/rubocop/cop/layout/indentation_consistency.rb +22 -5
  19. data/lib/rubocop/cop/layout/line_length.rb +104 -6
  20. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +6 -4
  21. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +16 -5
  22. data/lib/rubocop/cop/layout/single_line_block_chain.rb +3 -3
  23. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +2 -12
  24. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +6 -1
  25. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +4 -0
  26. data/lib/rubocop/cop/lint/number_conversion.rb +2 -0
  27. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +47 -1
  28. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -0
  29. data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
  30. data/lib/rubocop/cop/mixin/check_line_breakable.rb +7 -6
  31. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +3 -1
  32. data/lib/rubocop/cop/mixin/endless_method_body_help.rb +36 -0
  33. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +9 -4
  34. data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -2
  35. data/lib/rubocop/cop/mixin/visibility_help.rb +2 -1
  36. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
  37. data/lib/rubocop/cop/style/access_modifier_declarations.rb +30 -2
  38. data/lib/rubocop/cop/style/and_or.rb +3 -3
  39. data/lib/rubocop/cop/style/arguments_forwarding.rb +28 -2
  40. data/lib/rubocop/cop/style/block_delimiters.rb +6 -0
  41. data/lib/rubocop/cop/style/class_and_module_children.rb +2 -0
  42. data/lib/rubocop/cop/style/class_methods_definitions.rb +7 -0
  43. data/lib/rubocop/cop/style/collection_querying.rb +79 -46
  44. data/lib/rubocop/cop/style/combinable_loops.rb +4 -0
  45. data/lib/rubocop/cop/style/concat_array_literals.rb +13 -1
  46. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +53 -11
  47. data/lib/rubocop/cop/style/endless_method.rb +5 -1
  48. data/lib/rubocop/cop/style/for.rb +14 -1
  49. data/lib/rubocop/cop/style/guard_clause.rb +22 -21
  50. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +4 -0
  51. data/lib/rubocop/cop/style/if_unless_modifier.rb +19 -12
  52. data/lib/rubocop/cop/style/it_block_parameter.rb +63 -2
  53. data/lib/rubocop/cop/style/lambda.rb +16 -1
  54. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +36 -4
  55. data/lib/rubocop/cop/style/mixin_grouping.rb +12 -3
  56. data/lib/rubocop/cop/style/mutable_constant.rb +25 -7
  57. data/lib/rubocop/cop/style/parentheses_around_condition.rb +1 -1
  58. data/lib/rubocop/cop/style/raise_args.rb +19 -9
  59. data/lib/rubocop/cop/style/redundant_begin.rb +2 -1
  60. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -2
  61. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +24 -1
  62. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +28 -0
  63. data/lib/rubocop/cop/style/redundant_sort.rb +38 -4
  64. data/lib/rubocop/cop/style/require_order.rb +16 -8
  65. data/lib/rubocop/cop/style/rescue_modifier.rb +6 -0
  66. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +4 -0
  67. data/lib/rubocop/cop/style/single_line_methods.rb +5 -0
  68. data/lib/rubocop/cop/style/struct_inheritance.rb +6 -0
  69. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  70. data/lib/rubocop/lsp/routes.rb +23 -23
  71. data/lib/rubocop/server/cache.rb +4 -4
  72. data/lib/rubocop/target_ruby.rb +21 -9
  73. data/lib/rubocop/version.rb +1 -1
  74. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82ffd9b6c03e12d770357a074e5f04f30536c85ce4afb9eff74987f03951d756
4
- data.tar.gz: f9032e319d69366079bd51472893ef0e780e8405b2d3892ccde21c23deaf3fe0
3
+ metadata.gz: 0f289b93d86b59bdf80728f8130f7daeb1b6b6f940d6144cc425b627efe00061
4
+ data.tar.gz: c87922f68ef6b6fb2d1cdf8ac29998908f6be8f7d39d8ed14b7a0772d33a6b69
5
5
  SHA512:
6
- metadata.gz: c00f0dac21282c6d8727c74ef585bab1d21f2818e29003b99e05d740ab2a142160d8cbfc9030e0654dbc6d08f83e811333d02bf41d4ea7bca3a033f03783efcc
7
- data.tar.gz: 88f197ff630a6531ac0f702c46f68ccbe3d78315aa3f4ec57d0155b854d421bd0ef0abed6dcc7835cd90a869da14909ca99c606dd8d463a641c901a223dc6092
6
+ metadata.gz: cc6d21f74027a289aa14bf41cacbf840a0d156c93a33fa3526ee75607cb6d85ca3a6e219f4117c4d70462ef80fd8ae81d62ffd74cc8451c89c67754c4c719c87
7
+ data.tar.gz: 8a0a4af9e4cbba6b0c242461cacba0ef1fe5ba6049e5d5814eeac5db118f73a18142927ea33ea43a9ffd7b751f340893abd861eeb7fcc502506897d09c74e860
data/config/default.yml CHANGED
@@ -3943,6 +3943,7 @@ Style/CollectionQuerying:
3943
3943
  StyleGuide: '#collection-querying'
3944
3944
  Enabled: pending
3945
3945
  VersionAdded: '1.77'
3946
+ VersionChanged: '1.92'
3946
3947
  Safe: false
3947
3948
 
3948
3949
  Style/ColonMethodCall:
@@ -39,7 +39,7 @@ module RuboCop
39
39
  end
40
40
 
41
41
  def ==(other)
42
- hash == other.hash
42
+ other.is_a?(Badge) && department == other.department && cop_name == other.cop_name
43
43
  end
44
44
  alias eql? ==
45
45
 
@@ -29,7 +29,7 @@ module RuboCop
29
29
  format(
30
30
  CORRECTION_WITH_ARGUMENTS,
31
31
  collection: collection_node.source,
32
- variables: argument_node.children.map(&:source).join(', ')
32
+ variables: loop_variables
33
33
  )
34
34
  else
35
35
  format(CORRECTION_WITHOUT_ARGUMENTS, enumerable: collection_node.source)
@@ -38,6 +38,21 @@ module RuboCop
38
38
  padding_needed?(offending_range.end_pos) ? "#{keyword} " : keyword
39
39
  end
40
40
 
41
+ def loop_variables
42
+ variables = argument_node.children.map { |argument| loop_variable(argument) }.join(', ')
43
+
44
+ argument_node.source.match?(/,\s*\|\z/) ? "#{variables}," : variables
45
+ end
46
+
47
+ def loop_variable(argument)
48
+ return argument.source unless argument.mlhs_type?
49
+
50
+ variables = argument.children.map { |child| loop_variable(child) }.join(', ')
51
+ lone_target = argument.children.one? && !argument.children.first.restarg_type?
52
+
53
+ lone_target ? "(#{variables},)" : "(#{variables})"
54
+ end
55
+
41
56
  def closing_keyword
42
57
  padding_needed?(block_node.loc.end.begin_pos - 1) ? ' end' : 'end'
43
58
  end
@@ -76,8 +76,8 @@ module RuboCop
76
76
  end
77
77
 
78
78
  def remove_trailing_whitespace(corrector)
79
- size = block_begin.begin_pos - arguments.source_range.end_pos - 1
80
- corrector.remove_preceding(block_begin, size) if size.positive?
79
+ whitespace = arguments.source_range.end.join(block_begin.begin)
80
+ corrector.replace(whitespace, ' ') if whitespace.size > 1
81
81
  end
82
82
 
83
83
  def replace_delimiters(corrector)
@@ -27,6 +27,7 @@ module RuboCop
27
27
  # corrected. The user must handle the delicate decision of where to
28
28
  # put the comment.
29
29
  return if new_line_needed_before_closing_brace?(node)
30
+ return if nested_closing_bracket_moved_before_comment?
30
31
 
31
32
  end_range = last_element_range_with_trailing_comma(node).end
32
33
 
@@ -43,6 +44,39 @@ module RuboCop
43
44
  corrector.insert_before(node.loc.end, "\n")
44
45
  end
45
46
 
47
+ def nested_closing_bracket_moved_before_comment?
48
+ last_element = children(node).last
49
+ return false unless (comment = processed_source.comment_at_line(last_element.last_line - 1))
50
+ return false unless (nested = nested_literal_with_closing_bracket_on_own_line(last_element))
51
+
52
+ own_line_comment?(comment) || !(nested.chained? || nested.argument?)
53
+ end
54
+
55
+ def nested_literal_with_closing_bracket_on_own_line(last_element)
56
+ last_line = last_element.last_line
57
+
58
+ last_element.each_node.find do |descendant|
59
+ same_kind_as_node?(descendant) && closing_bracket_on_own_line?(descendant, last_line)
60
+ end
61
+ end
62
+
63
+ def same_kind_as_node?(descendant)
64
+ descendant.type == node.type || (descendant.call_type? && node.call_type?)
65
+ end
66
+
67
+ def closing_bracket_on_own_line?(descendant, line)
68
+ return false unless descendant.loc?(:end) && descendant.loc.end.is?('}', ']', ')')
69
+
70
+ closing_bracket = descendant.loc.end
71
+ return false if closing_bracket.line != line
72
+
73
+ closing_bracket.source_line[0...closing_bracket.column].strip.empty?
74
+ end
75
+
76
+ def own_line_comment?(comment)
77
+ comment.source_range.source_line.lstrip.start_with?('#')
78
+ end
79
+
46
80
  def correct_next_line_brace(corrector, end_range)
47
81
  corrector.remove(range_with_surrounding_space(node.loc.end, side: :left))
48
82
  corrector.insert_before(end_range, content_if_comment_present(corrector, node))
@@ -53,7 +53,7 @@ module RuboCop
53
53
 
54
54
  def on_send(node)
55
55
  return if !multiple_arguments?(node) || (node.call_type? && node.method?(:[]=)) ||
56
- autocorrect_incompatible_with_other_cops?
56
+ binary_operator_call?(node) || autocorrect_incompatible_with_other_cops?
57
57
 
58
58
  items = flattened_arguments(node)
59
59
 
@@ -64,6 +64,10 @@ module RuboCop
64
64
 
65
65
  private
66
66
 
67
+ def binary_operator_call?(node)
68
+ node.binary_operation? && !node.method?(:[]) && !node.loc.dot
69
+ end
70
+
67
71
  def autocorrect_incompatible_with_other_cops?
68
72
  with_first_argument_style? && enforce_hash_argument_with_separator?
69
73
  end
@@ -341,9 +341,26 @@ module RuboCop
341
341
 
342
342
  return "#{node_visibility(node)}_methods"
343
343
  end
344
+ return class_method_category(node) if node.defs_type?
345
+
344
346
  HUMANIZED_NODE_TYPE[node.type] || node.type
345
347
  end
346
348
 
349
+ # Only `private_class_method` reaches a singleton method; a bare `private` does not.
350
+ # Such a call follows the definition it names, so only right siblings are searched.
351
+ def class_method_category(node)
352
+ modifier = node.right_siblings.reverse.find do |sibling|
353
+ class_method_visibility_modifier?(sibling, method_name: node.method_name)
354
+ end
355
+
356
+ modifier ? :"#{modifier.method_name}s" : HUMANIZED_NODE_TYPE[node.type]
357
+ end
358
+
359
+ # @!method class_method_visibility_modifier?(node, method_name:)
360
+ def_node_matcher :class_method_visibility_modifier?, <<~PATTERN
361
+ (send nil? {:private_class_method :public_class_method} <(sym %method_name) ...>)
362
+ PATTERN
363
+
347
364
  def dynamic_constant?(node)
348
365
  return false unless node.casgn_type? && node.namespace.nil?
349
366
 
@@ -429,12 +446,9 @@ module RuboCop
429
446
  end
430
447
 
431
448
  def end_position_for(node)
432
- if node.casgn_type?
433
- heredoc = find_heredoc(node)
434
- return heredoc.location.heredoc_end.end_pos if heredoc
435
- end
449
+ heredoc_end_lines = heredocs(node).map { |heredoc| heredoc.loc.heredoc_end.line }
450
+ end_line = [node.last_line, *heredoc_end_lines].max
436
451
 
437
- end_line = buffer.line_for_position(node.source_range.end_pos)
438
452
  buffer.line_range(end_line).end_pos
439
453
  end
440
454
 
@@ -457,8 +471,8 @@ module RuboCop
457
471
  buffer.line_range(node.loc.line).begin_pos - 1
458
472
  end
459
473
 
460
- def find_heredoc(node)
461
- node.each_node(:any_str).find(&:heredoc?)
474
+ def heredocs(node)
475
+ node.each_node(:any_str).select(&:heredoc?)
462
476
  end
463
477
 
464
478
  def buffer
@@ -27,10 +27,6 @@ module RuboCop
27
27
  include RangeHelp
28
28
  extend AutoCorrector
29
29
 
30
- def self.autocorrect_incompatible_with
31
- [Style::RedundantSelf]
32
- end
33
-
34
30
  def on_send(node)
35
31
  return unless node.dot? || node.safe_navigation?
36
32
 
@@ -46,21 +42,35 @@ module RuboCop
46
42
 
47
43
  private
48
44
 
45
+ # The dot and the gap it moves across are replaced in one action, so that another
46
+ # correction that rewrites a range spanning the dot clashes with this one instead of
47
+ # leaving the moved dot behind.
49
48
  def autocorrect(corrector, dot, node)
50
- dot_range = if processed_source[dot.line - 1].strip == '.'
51
- range_by_whole_lines(dot, include_final_newline: true)
52
- else
53
- dot
54
- end
55
- corrector.remove(dot_range)
56
- case style
57
- when :leading
58
- corrector.insert_before(selector_range(node), dot.source)
59
- when :trailing
60
- corrector.insert_after(node.receiver, dot.source)
49
+ dot_range = removed_dot_range(dot)
50
+
51
+ if style == :leading
52
+ move_dot_before_selector(corrector, dot, dot_range, selector_range(node))
53
+ else
54
+ move_dot_after_receiver(corrector, dot, dot_range, node.receiver)
61
55
  end
62
56
  end
63
57
 
58
+ def removed_dot_range(dot)
59
+ return dot unless processed_source[dot.line - 1].strip == '.'
60
+
61
+ range_by_whole_lines(dot, include_final_newline: true)
62
+ end
63
+
64
+ def move_dot_before_selector(corrector, dot, dot_range, selector)
65
+ gap = range_between(dot_range.end_pos, selector.begin_pos)
66
+ corrector.replace(dot_range.join(gap), "#{gap.source}#{dot.source}")
67
+ end
68
+
69
+ def move_dot_after_receiver(corrector, dot, dot_range, receiver)
70
+ gap = range_between(receiver.source_range.end_pos, dot_range.begin_pos)
71
+ corrector.replace(gap.join(dot_range), "#{dot.source}#{gap.source}")
72
+ end
73
+
64
74
  def message(dot)
65
75
  "Place the #{dot.source} on the " +
66
76
  case style
@@ -61,23 +61,23 @@ module RuboCop
61
61
  return if node.ternary?
62
62
 
63
63
  if node.modifier_form?
64
- check_condition(node.condition) if node.right_sibling
64
+ check_condition(node.condition, node.right_sibling) if followed_by_statement?(node)
65
65
  else
66
66
  check_condition(node.condition, node.if_branch)
67
67
  end
68
68
  end
69
69
 
70
70
  def on_while(node)
71
- return if node.modifier_form? && !node.right_sibling
71
+ return if node.modifier_form? && !followed_by_statement?(node)
72
72
 
73
- check_condition(node.condition, node.modifier_form? ? nil : node.body)
73
+ check_condition(node.condition, node.modifier_form? ? node.right_sibling : node.body)
74
74
  end
75
75
  alias on_until on_while
76
76
 
77
77
  def on_while_post(node)
78
- return unless node.right_sibling
78
+ return unless followed_by_statement?(node)
79
79
 
80
- check_condition(node.condition)
80
+ check_condition(node.condition, node.right_sibling)
81
81
  end
82
82
  alias on_until_post on_while_post
83
83
 
@@ -106,10 +106,14 @@ module RuboCop
106
106
 
107
107
  private
108
108
 
109
- def check_condition(condition, body = nil)
109
+ def followed_by_statement?(node)
110
+ node.parent&.type?(:begin, :kwbegin) && node.right_sibling
111
+ end
112
+
113
+ def check_condition(condition, following_node)
110
114
  return unless condition.multiline?
111
115
  return if next_line_empty?(condition.last_line)
112
- return if body_on_line?(body, condition.last_line)
116
+ return if body_on_line?(following_node, condition.last_line)
113
117
 
114
118
  add_offense(condition, &autocorrect(condition))
115
119
  end
@@ -38,13 +38,19 @@ module RuboCop
38
38
  KIND = 'block'
39
39
 
40
40
  def on_block(node)
41
- first_line = node.loc.begin.line
42
-
43
- check(node, node.body, adjusted_first_line: first_line)
41
+ check(node, node.body, adjusted_first_line: body_start_line(node))
44
42
  end
45
43
 
46
44
  alias on_numblock on_block
47
45
  alias on_itblock on_block
46
+
47
+ private
48
+
49
+ def body_start_line(node)
50
+ return node.loc.begin.line unless node.arguments?
51
+
52
+ [node.loc.begin.line, node.arguments.last_line].max
53
+ end
48
54
  end
49
55
  end
50
56
  end
@@ -177,13 +177,7 @@ module RuboCop
177
177
  when :keyword
178
178
  node
179
179
  when :variable
180
- align_to = alignment_node_for_variable_style(node)
181
-
182
- while (parent = align_to.parent) && parent.send_type? && same_line?(align_to, parent)
183
- align_to = parent
184
- end
185
-
186
- align_to
180
+ alignment_node_for_variable_style(node)
187
181
  else
188
182
  start_line_range(node)
189
183
  end
@@ -213,6 +207,8 @@ module RuboCop
213
207
  leading_node(extract_rhs(ancestor)).equal?(node)
214
208
  elsif ancestor.send_type? && ancestor.operator_method?
215
209
  !leading_node(ancestor).equal?(node)
210
+ elsif ancestor.send_type?
211
+ leading_node(ancestor.last_argument).equal?(node)
216
212
  end
217
213
  end
218
214
  end
@@ -37,7 +37,7 @@ module RuboCop
37
37
  MSG_UNALIGNED_ASGN = '`=` is not aligned with the %<location>s assignment.'
38
38
 
39
39
  def self.autocorrect_incompatible_with
40
- [Style::SelfAssignment]
40
+ [Layout::RedundantLineBreak, Style::SelfAssignment]
41
41
  end
42
42
 
43
43
  def on_new_investigation
@@ -152,6 +152,10 @@ module RuboCop
152
152
 
153
153
  MSG = 'Indent the first argument one step more than %<base>s.'
154
154
 
155
+ def self.autocorrect_incompatible_with
156
+ [Layout::ArgumentAlignment, Layout::HashAlignment]
157
+ end
158
+
155
159
  def on_send(node)
156
160
  return unless should_check?(node)
157
161
  return if same_line?(node, node.first_argument)
@@ -180,7 +184,13 @@ module RuboCop
180
184
 
181
185
  top_level_send = find_top_level_send(send_node)
182
186
  node_to_correct =
183
- should_correct_entire_chain?(send_node, top_level_send) ? top_level_send : node
187
+ if should_correct_entire_chain?(send_node, top_level_send)
188
+ top_level_send
189
+ elsif hash_elements_aligned_by_argument_alignment?(node)
190
+ node.children.first
191
+ else
192
+ node
193
+ end
184
194
 
185
195
  AlignmentCorrector.correct(corrector, processed_source, node_to_correct, column_delta)
186
196
  end
@@ -210,6 +220,21 @@ module RuboCop
210
220
  top_level_send
211
221
  end
212
222
 
223
+ # `Layout/ArgumentAlignment` with `with_fixed_indentation` indents the pairs of an
224
+ # unbraced hash to a fixed column, so they must not move along with the first element.
225
+ def hash_elements_aligned_by_argument_alignment?(node)
226
+ return false if !node.hash_type? || node.braces?
227
+ return false unless enforce_first_argument_with_fixed_indentation?
228
+
229
+ argument_alignment_applies?(node.parent) && !enforce_hash_argument_with_separator?
230
+ end
231
+
232
+ def enforce_hash_argument_with_separator?
233
+ HashAlignment::SEPARATOR_ALIGNMENT_STYLES.any? do |style|
234
+ config.for_enabled_cop('Layout/HashAlignment')[style]&.include?('separator')
235
+ end
236
+ end
237
+
213
238
  def bare_operator?(node)
214
239
  node.operator_method? && !node.dot?
215
240
  end
@@ -6,6 +6,10 @@ module RuboCop
6
6
  # Checks for a line break before the first element in a
7
7
  # multi-line array.
8
8
  #
9
+ # NOTE: An array whose first element is an array literal is not checked when
10
+ # `Layout/SpaceInsideArrayLiteralBrackets` is enabled with `EnforcedStyle: compact`,
11
+ # since that style joins the two opening brackets.
12
+ #
9
13
  # @example
10
14
  #
11
15
  # # bad
@@ -70,6 +74,7 @@ module RuboCop
70
74
  def on_array(node)
71
75
  return if !node.loc.begin && !assignment_on_same_line?(node)
72
76
  return if allow_implicit_array_brackets? && !node.bracketed?
77
+ return if compact_nested_array?(node)
73
78
 
74
79
  check_children_line_break(node, node.children, ignore_last: ignore_last_element?)
75
80
  end
@@ -85,6 +90,16 @@ module RuboCop
85
90
  !!cop_config['AllowImplicitArrayLiterals']
86
91
  end
87
92
 
93
+ def compact_nested_array?(node)
94
+ node.square_brackets? && node.children.first&.source&.start_with?('[') &&
95
+ compact_array_brackets_enforced?
96
+ end
97
+
98
+ def compact_array_brackets_enforced?
99
+ config.cop_enabled?('Layout/SpaceInsideArrayLiteralBrackets') &&
100
+ config.for_cop('Layout/SpaceInsideArrayLiteralBrackets')['EnforcedStyle'] == 'compact'
101
+ end
102
+
88
103
  def ignore_last_element?
89
104
  !!cop_config['AllowMultilineFinalElement']
90
105
  end
@@ -156,16 +156,22 @@ module RuboCop
156
156
  if first_pair
157
157
  return if same_line?(first_pair, left_brace)
158
158
 
159
- if separator_style?(first_pair)
160
- check_based_on_longest_key(hash_node, left_brace, left_parenthesis)
161
- else
162
- check_first(first_pair, left_brace, left_parenthesis, 0)
163
- end
159
+ check_first_pair(hash_node, first_pair, left_brace, left_parenthesis)
164
160
  end
165
161
 
166
162
  check_right_brace(hash_node.loc.end, first_pair, left_brace, left_parenthesis)
167
163
  end
168
164
 
165
+ def check_first_pair(hash_node, first_pair, left_brace, left_parenthesis)
166
+ return unless begins_its_line?(first_pair.source_range)
167
+
168
+ if separator_style?(first_pair)
169
+ check_based_on_longest_key(hash_node, left_brace, left_parenthesis)
170
+ else
171
+ check_first(first_pair, left_brace, left_parenthesis, 0)
172
+ end
173
+ end
174
+
169
175
  def check_right_brace(right_brace, first_pair, left_brace, left_parenthesis)
170
176
  # if the right brace is on the same line as the last value, accept
171
177
  return if /\S/.match?(right_brace.source_line[0...right_brace.column])
@@ -57,8 +57,10 @@ module RuboCop
57
57
  MSG = 'Put the closing parenthesis for a method call with a ' \
58
58
  'HEREDOC parameter on the same line as the HEREDOC opening.'
59
59
 
60
+ # `Layout/MultilineMethodCallBraceLayout` can move the same closing parenthesis after
61
+ # the last argument in the same pass, and both insertions are kept.
60
62
  def self.autocorrect_incompatible_with
61
- [Style::TrailingCommaInArguments]
63
+ [Layout::MultilineMethodCallBraceLayout, Style::TrailingCommaInArguments]
62
64
  end
63
65
 
64
66
  def on_send(node)
@@ -231,8 +233,8 @@ module RuboCop
231
233
  end
232
234
 
233
235
  def find_most_bottom_of_heredoc_end(arguments)
234
- arguments.filter_map do |argument|
235
- argument.loc.heredoc_end.end_pos if argument.loc?(:heredoc_end)
236
+ arguments.flat_map { |argument| argument.each_node(:any_str).to_a }.filter_map do |node|
237
+ node.loc.heredoc_end.end_pos if node.loc?(:heredoc_end)
236
238
  end.max
237
239
  end
238
240
 
@@ -178,10 +178,24 @@ module RuboCop
178
178
  end
179
179
 
180
180
  def check_normal_style(node)
181
- check_alignment(
182
- node.children.reject { |child| bare_access_modifier?(child) },
183
- base_column_for_normal_style(node)
184
- )
181
+ items = node.children.reject { |child| bare_access_modifier?(child) }
182
+
183
+ check_alignment(items, base_column_for_normal_style(node) || governed_base_column(items))
184
+ end
185
+
186
+ def governed_base_column(items)
187
+ return unless config.cop_enabled?('Layout/IndentationWidth')
188
+ return if items.empty? || indentation_width_enabled_at?(items.first)
189
+
190
+ governed_item = items.find { |item| indentation_width_enabled_at?(item) }
191
+
192
+ display_column(governed_item.source_range) if governed_item
193
+ end
194
+
195
+ def indentation_width_enabled_at?(node)
196
+ comment_config = processed_source.comment_config
197
+
198
+ comment_config.cop_enabled_at_line?('Layout/IndentationWidth', node.first_line)
185
199
  end
186
200
 
187
201
  def check_indented_internal_methods_style(node)
@@ -197,7 +211,10 @@ module RuboCop
197
211
  children_to_check.last << child
198
212
  end
199
213
  end
200
- children_to_check.each { |group| check_alignment(group) }
214
+
215
+ children_to_check.each do |group|
216
+ check_alignment(group, governed_base_column(group))
217
+ end
201
218
  end
202
219
  end
203
220
  end