rubocop 1.73.2 → 1.75.2

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 (141) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +63 -8
  4. data/config/obsoletion.yml +3 -1
  5. data/lib/rubocop/cli.rb +1 -1
  6. data/lib/rubocop/config.rb +35 -6
  7. data/lib/rubocop/config_loader.rb +4 -0
  8. data/lib/rubocop/config_loader_resolver.rb +2 -1
  9. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -3
  10. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  11. data/lib/rubocop/config_obsoletion.rb +46 -2
  12. data/lib/rubocop/config_validator.rb +1 -0
  13. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +2 -1
  14. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  15. data/lib/rubocop/cop/layout/block_alignment.rb +2 -2
  16. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  17. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  18. data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
  19. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +3 -3
  20. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
  21. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
  22. data/lib/rubocop/cop/layout/indentation_width.rb +1 -0
  23. data/lib/rubocop/cop/layout/line_length.rb +5 -1
  24. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
  25. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  26. data/lib/rubocop/cop/layout/redundant_line_break.rb +9 -5
  27. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -5
  28. data/lib/rubocop/cop/layout/space_around_operators.rb +4 -1
  29. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
  30. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -0
  31. data/lib/rubocop/cop/lint/debugger.rb +2 -2
  32. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  33. data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -3
  34. data/lib/rubocop/cop/lint/literal_as_condition.rb +4 -0
  35. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  36. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
  37. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  38. data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
  39. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +16 -7
  40. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  41. data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
  42. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  43. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +8 -1
  44. data/lib/rubocop/cop/lint/shared_mutable_default.rb +12 -1
  45. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  46. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
  47. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  48. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +2 -0
  49. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -0
  50. data/lib/rubocop/cop/lint/unreachable_loop.rb +5 -5
  51. data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -0
  52. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +2 -11
  53. data/lib/rubocop/cop/lint/void.rb +1 -0
  54. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  55. data/lib/rubocop/cop/metrics/method_length.rb +1 -0
  56. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  57. data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
  58. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -2
  59. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  60. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  61. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  62. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
  63. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +0 -1
  64. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -0
  65. data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
  66. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  67. data/lib/rubocop/cop/naming/method_name.rb +64 -8
  68. data/lib/rubocop/cop/naming/variable_name.rb +6 -19
  69. data/lib/rubocop/cop/registry.rb +9 -6
  70. data/lib/rubocop/cop/style/array_intersect.rb +39 -28
  71. data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
  72. data/lib/rubocop/cop/style/class_and_module_children.rb +29 -7
  73. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  74. data/lib/rubocop/cop/style/collection_methods.rb +1 -0
  75. data/lib/rubocop/cop/style/combinable_loops.rb +1 -0
  76. data/lib/rubocop/cop/style/commented_keyword.rb +9 -2
  77. data/lib/rubocop/cop/style/comparable_between.rb +75 -0
  78. data/lib/rubocop/cop/style/conditional_assignment.rb +3 -0
  79. data/lib/rubocop/cop/style/double_negation.rb +2 -2
  80. data/lib/rubocop/cop/style/empty_literal.rb +4 -0
  81. data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
  82. data/lib/rubocop/cop/style/exponential_notation.rb +2 -2
  83. data/lib/rubocop/cop/style/for.rb +1 -0
  84. data/lib/rubocop/cop/style/format_string_token.rb +38 -11
  85. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  86. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  87. data/lib/rubocop/cop/style/guard_clause.rb +2 -1
  88. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -2
  89. data/lib/rubocop/cop/style/hash_fetch_chain.rb +105 -0
  90. data/lib/rubocop/cop/style/hash_syntax.rb +3 -0
  91. data/lib/rubocop/cop/style/if_inside_else.rb +10 -13
  92. data/lib/rubocop/cop/style/if_unless_modifier.rb +2 -2
  93. data/lib/rubocop/cop/style/inverse_methods.rb +1 -0
  94. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  95. data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
  96. data/lib/rubocop/cop/style/it_block_parameter.rb +100 -0
  97. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  98. data/lib/rubocop/cop/style/lambda.rb +1 -0
  99. data/lib/rubocop/cop/style/map_into_array.rb +1 -0
  100. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +4 -4
  101. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +1 -0
  102. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -0
  103. data/lib/rubocop/cop/style/next.rb +44 -0
  104. data/lib/rubocop/cop/style/object_then.rb +1 -0
  105. data/lib/rubocop/cop/style/proc.rb +1 -0
  106. data/lib/rubocop/cop/style/raise_args.rb +8 -8
  107. data/lib/rubocop/cop/style/redundant_begin.rb +1 -0
  108. data/lib/rubocop/cop/style/redundant_condition.rb +13 -1
  109. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +14 -4
  110. data/lib/rubocop/cop/style/redundant_format.rb +10 -3
  111. data/lib/rubocop/cop/style/redundant_parentheses.rb +2 -1
  112. data/lib/rubocop/cop/style/redundant_self.rb +1 -0
  113. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  114. data/lib/rubocop/cop/style/rescue_modifier.rb +3 -0
  115. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  116. data/lib/rubocop/cop/style/select_by_regexp.rb +4 -1
  117. data/lib/rubocop/cop/style/single_line_do_end_block.rb +3 -1
  118. data/lib/rubocop/cop/style/sole_nested_conditional.rb +41 -100
  119. data/lib/rubocop/cop/style/super_arguments.rb +1 -2
  120. data/lib/rubocop/cop/style/symbol_proc.rb +2 -0
  121. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -0
  122. data/lib/rubocop/cop/util.rb +1 -1
  123. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  124. data/lib/rubocop/cop/variable_force/variable.rb +2 -7
  125. data/lib/rubocop/cop/variable_force.rb +1 -1
  126. data/lib/rubocop/directive_comment.rb +1 -1
  127. data/lib/rubocop/ext/regexp_node.rb +0 -1
  128. data/lib/rubocop/lsp/runtime.rb +4 -4
  129. data/lib/rubocop/lsp/stdin_runner.rb +3 -1
  130. data/lib/rubocop/magic_comment.rb +8 -0
  131. data/lib/rubocop/rspec/cop_helper.rb +4 -1
  132. data/lib/rubocop/rspec/shared_contexts.rb +20 -0
  133. data/lib/rubocop/rspec/support.rb +2 -0
  134. data/lib/rubocop/runner.rb +5 -1
  135. data/lib/rubocop/server/cache.rb +13 -10
  136. data/lib/rubocop/target_finder.rb +1 -1
  137. data/lib/rubocop/target_ruby.rb +1 -1
  138. data/lib/rubocop/version.rb +14 -7
  139. data/lib/rubocop.rb +5 -0
  140. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +20 -2
  141. metadata +11 -6
@@ -46,6 +46,38 @@ module RuboCop
46
46
  # next unless a == 1
47
47
  # puts a
48
48
  # end
49
+ #
50
+ # @example AllowConsecutiveConditionals: false (default)
51
+ # # bad
52
+ # [1, 2].each do |a|
53
+ # if a == 1
54
+ # puts a
55
+ # end
56
+ # if a == 2
57
+ # puts a
58
+ # end
59
+ # end
60
+ #
61
+ # # good
62
+ # [1, 2].each do |a|
63
+ # if a == 1
64
+ # puts a
65
+ # end
66
+ # next unless a == 2
67
+ # puts a
68
+ # end
69
+ #
70
+ # @example AllowConsecutiveConditionals: true
71
+ # # good
72
+ # [1, 2].each do |a|
73
+ # if a == 1
74
+ # puts a
75
+ # end
76
+ # if a == 2
77
+ # puts a
78
+ # end
79
+ # end
80
+ #
49
81
  class Next < Base
50
82
  include ConfigurableEnforcedStyle
51
83
  include MinBodyLength
@@ -72,6 +104,7 @@ module RuboCop
72
104
  end
73
105
 
74
106
  alias on_numblock on_block
107
+ alias on_itblock on_block
75
108
 
76
109
  def on_while(node)
77
110
  check(node)
@@ -86,6 +119,9 @@ module RuboCop
86
119
 
87
120
  offending_node = offense_node(node.body)
88
121
 
122
+ return if allowed_consecutive_conditionals? &&
123
+ consecutive_conditionals?(offending_node)
124
+
89
125
  add_offense(offense_location(offending_node)) do |corrector|
90
126
  if offending_node.modifier_form?
91
127
  autocorrect_modifier(corrector, offending_node)
@@ -227,6 +263,14 @@ module RuboCop
227
263
 
228
264
  corrector.remove_leading(buffer.line_range(lineno), adjustment) if adjustment.positive?
229
265
  end
266
+
267
+ def consecutive_conditionals?(if_node)
268
+ if_node.parent&.begin_type? && if_node.left_sibling&.if_type?
269
+ end
270
+
271
+ def allowed_consecutive_conditionals?
272
+ cop_config.fetch('AllowConsecutiveConditionals', false)
273
+ end
230
274
  end
231
275
  end
232
276
  end
@@ -38,6 +38,7 @@ module RuboCop
38
38
  check_method_node(node.send_node)
39
39
  end
40
40
  alias on_numblock on_block
41
+ alias on_itblock on_block
41
42
 
42
43
  def on_send(node)
43
44
  return unless node.arguments.one? && node.first_argument.block_pass_type?
@@ -30,6 +30,7 @@ module RuboCop
30
30
  end
31
31
 
32
32
  alias on_numblock on_block
33
+ alias on_itblock on_block
33
34
  end
34
35
  end
35
36
  end
@@ -3,15 +3,15 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks the args passed to `fail` and `raise`. For exploded
7
- # style (default), it recommends passing the exception class and message
8
- # to `raise`, rather than construct an instance of the error. It will
9
- # still allow passing just a message, or the construction of an error
10
- # with more than one argument.
6
+ # Checks the args passed to `fail` and `raise`.
11
7
  #
12
- # The exploded style works identically, but with the addition that it
13
- # will also suggest constructing error objects when the exception is
14
- # passed multiple arguments.
8
+ # Exploded style (default) enforces passing the exception class and message
9
+ # arguments separately, rather than constructing an instance of the error.
10
+ #
11
+ # Compact style enforces constructing an error instance.
12
+ #
13
+ # Both styles allow passing just a message, or an error instance when there is more
14
+ # than one argument.
15
15
  #
16
16
  # The exploded style has an `AllowedCompactTypes` configuration
17
17
  # option that takes an `Array` of exception name Strings.
@@ -95,6 +95,7 @@ module RuboCop
95
95
  end
96
96
 
97
97
  alias on_numblock on_block
98
+ alias on_itblock on_block
98
99
 
99
100
  def on_kwbegin(node)
100
101
  return unless (target_node = offensive_kwbegins(node).to_a.last)
@@ -230,6 +230,14 @@ module RuboCop
230
230
  node.type?(:kwsplat, :forwarded_kwrestarg)
231
231
  end
232
232
 
233
+ def wrap_arguments_with_parens(condition)
234
+ method = condition.source_range.begin.join(condition.loc.selector.end)
235
+ arguments = condition.first_argument.source_range.begin.join(condition.source_range.end)
236
+
237
+ "#{method.source}(#{arguments.source})"
238
+ end
239
+
240
+ # rubocop:disable Metrics/AbcSize
233
241
  def if_source(if_branch, arithmetic_operation)
234
242
  if branches_have_method?(if_branch.parent) && if_branch.parenthesized?
235
243
  if_branch.source.delete_suffix(')')
@@ -238,11 +246,15 @@ module RuboCop
238
246
 
239
247
  "#{if_branch.receiver.source} #{if_branch.method_name} (#{argument_source}"
240
248
  elsif if_branch.true_type?
241
- if_branch.parent.condition.source
249
+ condition = if_branch.parent.condition
250
+ return condition.source if condition.arguments.empty?
251
+
252
+ wrap_arguments_with_parens(condition)
242
253
  else
243
254
  if_branch.source
244
255
  end
245
256
  end
257
+ # rubocop:enable Metrics/AbcSize
246
258
 
247
259
  def else_source(else_branch, arithmetic_operation) # rubocop:disable Metrics/AbcSize
248
260
  if arithmetic_operation
@@ -20,20 +20,30 @@ module RuboCop
20
20
 
21
21
  MSG = 'Remove the redundant current directory path.'
22
22
  RESTRICT_ON_SEND = %i[require_relative].freeze
23
- CURRENT_DIRECTORY_PATH = './'
23
+ CURRENT_DIRECTORY_PREFIX = %r{./+}.freeze
24
+ REDUNDANT_CURRENT_DIRECTORY_PREFIX = /\A#{CURRENT_DIRECTORY_PREFIX}/.freeze
24
25
 
25
26
  def on_send(node)
26
27
  return unless (first_argument = node.first_argument)
27
- return unless first_argument.str_content&.start_with?(CURRENT_DIRECTORY_PATH)
28
- return unless (index = first_argument.source.index(CURRENT_DIRECTORY_PATH))
28
+ return unless (index = first_argument.source.index(CURRENT_DIRECTORY_PREFIX))
29
+ return unless (redundant_length = redundant_path_length(first_argument.str_content))
29
30
 
30
31
  begin_pos = first_argument.source_range.begin.begin_pos + index
31
- range = range_between(begin_pos, begin_pos + 2)
32
+ end_pos = begin_pos + redundant_length
33
+ range = range_between(begin_pos, end_pos)
32
34
 
33
35
  add_offense(range) do |corrector|
34
36
  corrector.remove(range)
35
37
  end
36
38
  end
39
+
40
+ private
41
+
42
+ def redundant_path_length(path)
43
+ return unless (match = path&.match(REDUNDANT_CURRENT_DIRECTORY_PREFIX))
44
+
45
+ match[0].length
46
+ end
37
47
  end
38
48
  end
39
49
  end
@@ -5,8 +5,8 @@ module RuboCop
5
5
  module Style
6
6
  # Checks for calls to `Kernel#format` or `Kernel#sprintf` that are redundant.
7
7
  #
8
- # Calling `format` with only a single string argument is redundant, as it can be
9
- # replaced by the string itself.
8
+ # Calling `format` with only a single string or constant argument is redundant,
9
+ # as it can be replaced by the string or constant itself.
10
10
  #
11
11
  # Also looks for `format` calls where the arguments are literals that can be
12
12
  # inlined into a string easily. This applies to the `%s`, `%d`, `%i`, `%u`, and
@@ -38,6 +38,13 @@ module RuboCop
38
38
  # 'the quick brown fox jumps over the lazy dog.'
39
39
  #
40
40
  # # bad
41
+ # format(MESSAGE)
42
+ # sprintf(MESSAGE)
43
+ #
44
+ # # good
45
+ # MESSAGE
46
+ #
47
+ # # bad
41
48
  # format('%s %s', 'foo', 'bar')
42
49
  # sprintf('%s %s', 'foo', 'bar')
43
50
  #
@@ -54,7 +61,7 @@ module RuboCop
54
61
 
55
62
  # @!method format_without_additional_args?(node)
56
63
  def_node_matcher :format_without_additional_args?, <<~PATTERN
57
- (send {(const {nil? cbase} :Kernel) nil?} %RESTRICT_ON_SEND ${str dstr})
64
+ (send {(const {nil? cbase} :Kernel) nil?} %RESTRICT_ON_SEND ${str dstr const})
58
65
  PATTERN
59
66
 
60
67
  # @!method rational_number?(node)
@@ -17,7 +17,7 @@ module RuboCop
17
17
  include Parentheses
18
18
  extend AutoCorrector
19
19
 
20
- ALLOWED_NODE_TYPES = %i[and or send splat kwsplat].freeze
20
+ ALLOWED_NODE_TYPES = %i[or send splat kwsplat].freeze
21
21
 
22
22
  # @!method square_brackets?(node)
23
23
  def_node_matcher :square_brackets?, <<~PATTERN
@@ -162,6 +162,7 @@ module RuboCop
162
162
  return if node.semantic_operator? && begin_node.parent
163
163
  return if node.multiline? && allow_in_multiline_conditions?
164
164
  return if ALLOWED_NODE_TYPES.include?(begin_node.parent&.type)
165
+ return if !node.and_type? && begin_node.parent&.and_type?
165
166
  return if begin_node.parent&.if_type? && begin_node.parent.ternary?
166
167
 
167
168
  'a logical expression'
@@ -118,6 +118,7 @@ module RuboCop
118
118
  end
119
119
 
120
120
  alias on_numblock on_block
121
+ alias on_itblock on_block
121
122
 
122
123
  def on_if(node)
123
124
  # Allow conditional nodes to use `self` in the condition if that variable
@@ -21,6 +21,7 @@ module RuboCop
21
21
 
22
22
  MSG_BLOCK = 'Use `sort` instead of `sort_by { |%<var>s| %<var>s }`.'
23
23
  MSG_NUMBLOCK = 'Use `sort` instead of `sort_by { _1 }`.'
24
+ MSG_ITBLOCK = 'Use `sort` instead of `sort_by { it }`.'
24
25
 
25
26
  def on_block(node)
26
27
  redundant_sort_by_block(node) do |send, var_name|
@@ -36,7 +37,17 @@ module RuboCop
36
37
  redundant_sort_by_numblock(node) do |send|
37
38
  range = sort_by_range(send, node)
38
39
 
39
- add_offense(range, message: format(MSG_NUMBLOCK)) do |corrector|
40
+ add_offense(range, message: MSG_NUMBLOCK) do |corrector|
41
+ corrector.replace(range, 'sort')
42
+ end
43
+ end
44
+ end
45
+
46
+ def on_itblock(node)
47
+ redundant_sort_by_itblock(node) do |send|
48
+ range = sort_by_range(send, node)
49
+
50
+ add_offense(range, message: MSG_ITBLOCK) do |corrector|
40
51
  corrector.replace(range, 'sort')
41
52
  end
42
53
  end
@@ -54,6 +65,11 @@ module RuboCop
54
65
  (numblock $(call _ :sort_by) 1 (lvar :_1))
55
66
  PATTERN
56
67
 
68
+ # @!method redundant_sort_by_itblock(node)
69
+ def_node_matcher :redundant_sort_by_itblock, <<~PATTERN
70
+ (itblock $(call _ :sort_by) _ (lvar :it))
71
+ PATTERN
72
+
57
73
  def sort_by_range(send, node)
58
74
  range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
59
75
  end
@@ -67,11 +67,13 @@ module RuboCop
67
67
  node.parent && parentheses?(node.parent)
68
68
  end
69
69
 
70
+ # rubocop:disable Metrics/AbcSize
70
71
  def correct_rescue_block(corrector, node, parenthesized)
71
72
  operation = node.body
72
73
 
73
74
  node_indentation, node_offset = indentation_and_offset(node, parenthesized)
74
75
 
76
+ corrector.wrap(operation, '[', ']') if operation.array_type? && !operation.bracketed?
75
77
  corrector.remove(range_between(operation.source_range.end_pos, node.source_range.end_pos))
76
78
  corrector.insert_before(operation, "begin\n#{node_indentation}")
77
79
  corrector.insert_after(heredoc_end(operation) || operation, <<~RESCUE_CLAUSE.chop)
@@ -81,6 +83,7 @@ module RuboCop
81
83
  #{node_offset}end
82
84
  RESCUE_CLAUSE
83
85
  end
86
+ # rubocop:enable Metrics/AbcSize
84
87
 
85
88
  def indentation_and_offset(node, parenthesized)
86
89
  node_indentation = indentation(node)
@@ -47,7 +47,7 @@ module RuboCop
47
47
 
48
48
  def on_return(node)
49
49
  # Check Lint/NonLocalExitFromIterator first before this cop
50
- node.each_ancestor(:block, :def, :defs) do |n|
50
+ node.each_ancestor(:block, :any_def) do |n|
51
51
  break if scoped_node?(n)
52
52
 
53
53
  send_node, args_node, _body_node = *n
@@ -83,7 +83,7 @@ module RuboCop
83
83
  end
84
84
 
85
85
  def scoped_node?(node)
86
- node.type?(:def, :defs) || node.lambda?
86
+ node.any_def_type? || node.lambda?
87
87
  end
88
88
 
89
89
  # @!method chained_send?(node)
@@ -59,6 +59,7 @@ module RuboCop
59
59
  {
60
60
  (block call (args (arg $_)) ${(send _ %REGEXP_METHODS _) match-with-lvasgn})
61
61
  (numblock call $1 ${(send _ %REGEXP_METHODS _) match-with-lvasgn})
62
+ (itblock call $_ ${(send _ %REGEXP_METHODS _) match-with-lvasgn})
62
63
  }
63
64
  PATTERN
64
65
 
@@ -137,6 +138,7 @@ module RuboCop
137
138
  return unless (block_arg_name, regexp_method_send_node = regexp_match?(block_node))
138
139
 
139
140
  block_arg_name = :"_#{block_arg_name}" if block_node.numblock_type?
141
+
140
142
  return unless calls_lvar?(regexp_method_send_node, block_arg_name)
141
143
 
142
144
  regexp_method_send_node
@@ -150,7 +152,8 @@ module RuboCop
150
152
  return node.child_nodes.first if node.match_with_lvasgn_type?
151
153
 
152
154
  if node.receiver.lvar_type? &&
153
- (block.numblock_type? || node.receiver.source == block.first_argument.source)
155
+ (block.type?(:numblock, :itblock) ||
156
+ node.receiver.source == block.first_argument.source)
154
157
  node.first_argument
155
158
  elsif node.first_argument.lvar_type?
156
159
  node.receiver
@@ -56,11 +56,13 @@ module RuboCop
56
56
  end
57
57
  # rubocop:enable Metrics/AbcSize
58
58
  alias on_numblock on_block
59
+ alias on_itblock on_block
59
60
 
60
61
  private
61
62
 
62
63
  def do_line(node)
63
- if node.numblock_type? || node.arguments.children.empty? || node.send_node.lambda_literal?
64
+ if node.type?(:numblock, :itblock) ||
65
+ node.arguments.children.empty? || node.send_node.lambda_literal?
64
66
  node.loc.begin
65
67
  else
66
68
  node.arguments
@@ -96,11 +96,7 @@ module RuboCop
96
96
  end
97
97
 
98
98
  def autocorrect(corrector, node, if_branch)
99
- if node.condition.or_type? || node.condition.assignment?
100
- corrector.wrap(node.condition, '(', ')')
101
- end
102
-
103
- if outer_condition_modify_form?(node, if_branch)
99
+ if node.modifier_form?
104
100
  autocorrect_outer_condition_modify_form(corrector, node, if_branch)
105
101
  else
106
102
  autocorrect_outer_condition_basic(corrector, node, if_branch)
@@ -108,74 +104,48 @@ module RuboCop
108
104
  end
109
105
 
110
106
  def autocorrect_outer_condition_basic(corrector, node, if_branch)
111
- correct_from_unless_to_if(corrector, node) if node.unless?
112
-
113
- outer_condition = node.condition
114
- correct_outer_condition(corrector, outer_condition)
107
+ correct_node(corrector, node)
115
108
 
116
- and_operator = if_branch.unless? ? ' && !' : ' && '
117
109
  if if_branch.modifier_form?
118
- correct_for_guard_condition_style(corrector, outer_condition, if_branch, and_operator)
110
+ correct_for_guard_condition_style(corrector, node, if_branch)
119
111
  else
120
- correct_for_basic_condition_style(corrector, node, if_branch, and_operator)
112
+ correct_for_basic_condition_style(corrector, node, if_branch)
121
113
  correct_for_comment(corrector, node, if_branch)
122
114
  end
123
115
  end
124
116
 
125
- def autocorrect_outer_condition_modify_form(corrector, node, if_branch)
126
- correct_from_unless_to_if(corrector, if_branch, is_modify_form: true) if if_branch.unless?
127
- correct_for_outer_condition_modify_form_style(corrector, node, if_branch)
117
+ def correct_node(corrector, node)
118
+ corrector.replace(node.loc.keyword, 'if') if node.unless?
119
+ corrector.replace(node.condition, chainable_condition(node))
128
120
  end
129
121
 
130
- def correct_from_unless_to_if(corrector, node, is_modify_form: false)
131
- corrector.replace(node.loc.keyword, 'if')
132
-
133
- insert_bang(corrector, node, is_modify_form)
134
- end
122
+ def correct_for_guard_condition_style(corrector, node, if_branch)
123
+ corrector.insert_after(node.condition, " && #{chainable_condition(if_branch)}")
135
124
 
136
- def correct_for_guard_condition_style(corrector, outer_condition, if_branch, and_operator)
137
- condition = if_branch.condition
138
- corrector.insert_after(outer_condition, "#{and_operator}#{replace_condition(condition)}")
139
-
140
- range = range_between(if_branch.loc.keyword.begin_pos, condition.source_range.end_pos)
125
+ range = range_between(
126
+ if_branch.loc.keyword.begin_pos, if_branch.condition.source_range.end_pos
127
+ )
141
128
  corrector.remove(range_with_surrounding_space(range, newlines: false))
142
- corrector.remove(if_branch.loc.keyword)
143
129
  end
144
130
 
145
- def correct_for_basic_condition_style(corrector, node, if_branch, and_operator)
131
+ def correct_for_basic_condition_style(corrector, node, if_branch)
146
132
  range = range_between(
147
133
  node.condition.source_range.end_pos, if_branch.condition.source_range.begin_pos
148
134
  )
149
- corrector.replace(range, and_operator)
150
- corrector.remove(range_by_whole_lines(node.loc.end, include_final_newline: true))
151
-
152
- wrap_condition(corrector, if_branch.condition)
153
- end
154
-
155
- def wrap_condition(corrector, condition)
156
- # Handle `send` and `block` nodes that need to be wrapped in parens
157
- # FIXME: autocorrection prevents syntax errors by wrapping the entire node in parens,
158
- # but wrapping the argument list would be a more ergonomic correction.
159
- node_to_check = condition&.any_block_type? ? condition.send_node : condition
160
- return unless wrap_condition?(node_to_check)
135
+ corrector.replace(range, ' && ')
161
136
 
162
- if condition.call_type?
163
- source = parenthesized_method_arguments(condition)
137
+ corrector.replace(if_branch.condition, chainable_condition(if_branch))
164
138
 
165
- corrector.replace(condition, source)
166
- else
167
- corrector.wrap(condition, '(', ')')
168
- end
139
+ corrector.remove(range_by_whole_lines(node.loc.end, include_final_newline: true))
169
140
  end
170
141
 
171
- def correct_for_outer_condition_modify_form_style(corrector, node, if_branch)
172
- condition = if_branch.condition
173
- corrector.insert_before(condition,
174
- "#{'!' if node.unless?}#{replace_condition(node.condition)} && ")
142
+ def autocorrect_outer_condition_modify_form(corrector, node, if_branch)
143
+ correct_node(corrector, if_branch)
144
+
145
+ corrector.insert_before(if_branch.condition, "#{chainable_condition(node)} && ")
175
146
 
176
- corrector.remove(node.condition)
177
- corrector.remove(range_with_surrounding_space(node.loc.keyword, newlines: false))
178
- corrector.replace(if_branch.loc.keyword, 'if')
147
+ range = range_between(node.loc.keyword.begin_pos, node.condition.source_range.end_pos)
148
+ corrector.remove(range_with_surrounding_space(range, newlines: false))
179
149
  end
180
150
 
181
151
  def correct_for_comment(corrector, node, if_branch)
@@ -187,61 +157,36 @@ module RuboCop
187
157
  corrector.insert_before(node.loc.keyword, comment_text) unless comments.empty?
188
158
  end
189
159
 
190
- def correct_outer_condition(corrector, condition)
191
- return unless require_parentheses?(condition)
192
-
193
- end_pos = condition.loc.selector.end_pos
194
- begin_pos = condition.first_argument.source_range.begin_pos
195
- return if end_pos > begin_pos
196
-
197
- range = range_between(end_pos, begin_pos)
198
- corrector.remove(range)
199
- corrector.insert_after(range, '(')
200
- corrector.insert_after(condition.last_argument, ')')
201
- end
160
+ def chainable_condition(node)
161
+ wrapped_condition = add_parentheses_if_needed(node.condition)
202
162
 
203
- def insert_bang(corrector, node, is_modify_form)
204
- condition = node.condition
163
+ return wrapped_condition if node.if?
205
164
 
206
- if (condition.send_type? && condition.comparison_method? && !condition.parenthesized?) ||
207
- (is_modify_form && wrap_condition?(condition))
208
- corrector.wrap(node.condition, '!(', ')')
209
- elsif condition.and_type?
210
- insert_bang_for_and(corrector, node)
211
- else
212
- corrector.insert_before(condition, '!')
213
- end
165
+ node.condition.and_type? ? "!(#{wrapped_condition})" : "!#{wrapped_condition}"
214
166
  end
215
167
 
216
- def insert_bang_for_and(corrector, node)
217
- lhs, rhs = *node # rubocop:disable InternalAffairs/NodeDestructuring
168
+ def add_parentheses_if_needed(condition)
169
+ # Handle `send` and `block` nodes that need to be wrapped in parens
170
+ # FIXME: autocorrection prevents syntax errors by wrapping the entire node in parens,
171
+ # but wrapping the argument list would be a more ergonomic correction.
172
+ node_to_check = condition&.any_block_type? ? condition.send_node : condition
173
+ return condition.source unless add_parentheses?(node_to_check)
218
174
 
219
- if lhs.and_type?
220
- insert_bang_for_and(corrector, lhs)
221
- corrector.insert_before(rhs, '!') if rhs
175
+ if parenthesize_method?(condition)
176
+ parenthesized_method_arguments(condition)
222
177
  else
223
- corrector.insert_before(lhs, '!')
224
- corrector.insert_before(rhs, '!')
178
+ "(#{condition.source})"
225
179
  end
226
180
  end
227
181
 
228
- def require_parentheses?(condition)
229
- condition.call_type? && !condition.arguments.empty? && !condition.parenthesized? &&
230
- !condition.comparison_method?
231
- end
232
-
233
- def wrap_condition?(node)
234
- node.operator_keyword? || (node.call_type? && node.arguments.any? && !node.parenthesized?)
182
+ def parenthesize_method?(node)
183
+ node.call_type? && node.arguments.any? && !node.parenthesized? &&
184
+ !node.comparison_method? && !node.operator_method?
235
185
  end
236
186
 
237
- def replace_condition(condition)
238
- return condition.source unless wrap_condition?(condition)
239
-
240
- if condition.call_type? && !condition.comparison_method?
241
- parenthesized_method_arguments(condition)
242
- else
243
- "(#{condition.source})"
244
- end
187
+ def add_parentheses?(node)
188
+ node.assignment? || (node.operator_keyword? && !node.and_type?) ||
189
+ (node.call_type? && node.arguments.any? && !node.parenthesized?)
245
190
  end
246
191
 
247
192
  def parenthesized_method_arguments(node)
@@ -254,10 +199,6 @@ module RuboCop
254
199
  def allow_modifier?
255
200
  cop_config['AllowModifier']
256
201
  end
257
-
258
- def outer_condition_modify_form?(node, if_branch)
259
- node.condition.source_range.begin_pos > if_branch.condition.source_range.begin_pos
260
- end
261
202
  end
262
203
  end
263
204
  end
@@ -68,7 +68,6 @@ module RuboCop
68
68
  class SuperArguments < Base
69
69
  extend AutoCorrector
70
70
 
71
- DEF_TYPES = %i[def defs].freeze
72
71
  ASSIGN_TYPES = %i[or_asgn lvasgn].freeze
73
72
 
74
73
  MSG = 'Call `super` without arguments and parentheses when the signature is identical.'
@@ -100,7 +99,7 @@ module RuboCop
100
99
  # `super` used within the block is always allowed.
101
100
  break if node.any_block_type? && !block_sends_to_super?(super_node, node)
102
101
 
103
- break node if DEF_TYPES.include?(node.type)
102
+ break node if node.any_def_type?
104
103
  end
105
104
  end
106
105
 
@@ -159,6 +159,7 @@ module RuboCop
159
159
  {
160
160
  (block $#symbol_proc_receiver? $(args (arg _var)) (send (lvar _var) $_))
161
161
  (numblock $#symbol_proc_receiver? $1 (send (lvar :_1) $_))
162
+ (itblock $#symbol_proc_receiver? $_ (send (lvar :it) $_))
162
163
  }
163
164
  PATTERN
164
165
 
@@ -185,6 +186,7 @@ module RuboCop
185
186
  end
186
187
  # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
187
188
  alias on_numblock on_block
189
+ alias on_itblock on_block
188
190
 
189
191
  def destructuring_block_argument?(argument_node)
190
192
  argument_node.one? && argument_node.source.include?(',')
@@ -64,6 +64,7 @@ module RuboCop
64
64
  end
65
65
 
66
66
  alias on_numblock on_block
67
+ alias on_itblock on_block
67
68
 
68
69
  private
69
70
 
@@ -76,7 +76,7 @@ module RuboCop
76
76
  loc = node.loc
77
77
  selector = if node.type?(:super, :yield)
78
78
  loc.keyword
79
- elsif node.type?(:def, :defs)
79
+ elsif node.any_def_type?
80
80
  loc.name
81
81
  else
82
82
  loc.selector
@@ -46,7 +46,7 @@ module RuboCop
46
46
  else
47
47
  child_index = case node.type
48
48
  when :module, :sclass then 1
49
- when :def, :class, :block, :numblock then 2
49
+ when :def, :class, :block, :numblock, :itblock then 2
50
50
  when :defs then 3
51
51
  end
52
52