rubocop 1.70.0 → 1.71.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 (195) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +17 -0
  4. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  5. data/lib/rubocop/comment_config.rb +1 -1
  6. data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
  7. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  8. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  9. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  10. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  11. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  12. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  13. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +229 -0
  14. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  15. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  16. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  17. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  18. data/lib/rubocop/cop/internal_affairs.rb +3 -0
  19. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  20. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  21. data/lib/rubocop/cop/layout/block_alignment.rb +1 -1
  22. data/lib/rubocop/cop/layout/class_structure.rb +9 -9
  23. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  24. data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
  25. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  26. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
  27. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  28. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
  29. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
  30. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  31. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  32. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +1 -1
  33. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  34. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +1 -0
  35. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
  36. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
  37. data/lib/rubocop/cop/layout/redundant_line_break.rb +6 -5
  38. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
  39. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  40. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  41. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  42. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  43. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -0
  44. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  45. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  46. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  47. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
  48. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  49. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +1 -1
  50. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  51. data/lib/rubocop/cop/lint/constant_reassignment.rb +2 -6
  52. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  53. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  54. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  55. data/lib/rubocop/cop/lint/duplicate_set_element.rb +1 -1
  56. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  57. data/lib/rubocop/cop/lint/float_comparison.rb +5 -2
  58. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  59. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  60. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  61. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +13 -3
  62. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  63. data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
  64. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  65. data/lib/rubocop/cop/lint/nested_method_definition.rb +3 -3
  66. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  67. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  68. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +13 -18
  69. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
  70. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  71. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  72. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  73. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  74. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -1
  75. data/lib/rubocop/cop/lint/shared_mutable_default.rb +3 -3
  76. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  77. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  78. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +1 -1
  79. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  80. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
  81. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
  82. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -4
  83. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  84. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  85. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  86. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  87. data/lib/rubocop/cop/lint/void.rb +2 -7
  88. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  89. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  90. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  91. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  92. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  93. data/lib/rubocop/cop/mixin/check_line_breakable.rb +5 -5
  94. data/lib/rubocop/cop/mixin/comments_help.rb +1 -1
  95. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  96. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +4 -4
  97. data/lib/rubocop/cop/mixin/hash_subset.rb +188 -0
  98. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  99. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +22 -8
  100. data/lib/rubocop/cop/mixin/statement_modifier.rb +7 -2
  101. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  102. data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
  103. data/lib/rubocop/cop/naming/block_forwarding.rb +18 -14
  104. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -3
  105. data/lib/rubocop/cop/security/compound_hash.rb +1 -0
  106. data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -4
  107. data/lib/rubocop/cop/style/arguments_forwarding.rb +38 -19
  108. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  109. data/lib/rubocop/cop/style/block_delimiters.rb +7 -20
  110. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  111. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  112. data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
  113. data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
  114. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  115. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
  116. data/lib/rubocop/cop/style/documentation.rb +1 -1
  117. data/lib/rubocop/cop/style/double_negation.rb +3 -3
  118. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  119. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  120. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  121. data/lib/rubocop/cop/style/exact_regexp_match.rb +1 -1
  122. data/lib/rubocop/cop/style/explicit_block_argument.rb +15 -2
  123. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  124. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  125. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -6
  126. data/lib/rubocop/cop/style/hash_except.rb +20 -131
  127. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  128. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  129. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  130. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  131. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
  132. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  133. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  134. data/lib/rubocop/cop/style/inverse_methods.rb +6 -6
  135. data/lib/rubocop/cop/style/it_assignment.rb +1 -1
  136. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  137. data/lib/rubocop/cop/style/map_into_array.rb +1 -1
  138. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  139. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  140. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +10 -13
  141. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
  142. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -4
  143. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  144. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  145. data/lib/rubocop/cop/style/mutable_constant.rb +2 -2
  146. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
  147. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  148. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  149. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -5
  150. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  151. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  152. data/lib/rubocop/cop/style/proc.rb +1 -2
  153. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  154. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  155. data/lib/rubocop/cop/style/redundant_condition.rb +2 -2
  156. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  157. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  158. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  159. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
  160. data/lib/rubocop/cop/style/redundant_line_continuation.rb +27 -10
  161. data/lib/rubocop/cop/style/redundant_parentheses.rb +9 -6
  162. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  163. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  164. data/lib/rubocop/cop/style/redundant_self_assignment.rb +12 -27
  165. data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
  166. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  167. data/lib/rubocop/cop/style/return_nil.rb +1 -1
  168. data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
  169. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  170. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  171. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  172. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
  173. data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
  174. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  175. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  176. data/lib/rubocop/cop/style/super_arguments.rb +4 -4
  177. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  178. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  179. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
  180. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  181. data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
  182. data/lib/rubocop/cop/util.rb +2 -2
  183. data/lib/rubocop/cop/variable_force/variable.rb +14 -2
  184. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  185. data/lib/rubocop/cops_documentation_generator.rb +13 -13
  186. data/lib/rubocop/directive_comment.rb +9 -8
  187. data/lib/rubocop/options.rb +2 -1
  188. data/lib/rubocop/result_cache.rb +13 -13
  189. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  190. data/lib/rubocop/rspec/support.rb +1 -2
  191. data/lib/rubocop/target_finder.rb +1 -0
  192. data/lib/rubocop/version.rb +1 -1
  193. data/lib/rubocop.rb +3 -0
  194. metadata +15 -11
  195. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -13,6 +13,20 @@ module RuboCop
13
13
  # The default variable name is `block`. If the name is already in use, it will not be
14
14
  # autocorrected.
15
15
  #
16
+ # [NOTE]
17
+ # --
18
+ # Because of a bug in Ruby 3.3.0, when a block is referenced inside of another block,
19
+ # no offense will be registered until Ruby 3.4:
20
+
21
+ # [source,ruby]
22
+ # ----
23
+ # def foo(&block)
24
+ # # Using an anonymous block would be a syntax error on Ruby 3.3.0
25
+ # block_method { bar(&block) }
26
+ # end
27
+ # ----
28
+ # --
29
+ #
16
30
  # @example EnforcedStyle: anonymous (default)
17
31
  #
18
32
  # # bad
@@ -90,21 +104,11 @@ module RuboCop
90
104
  last_argument.source == block_pass_node.source
91
105
  end
92
106
 
93
- # Prevents the following syntax error:
94
- #
95
- # # foo.rb
96
- # def foo(&)
97
- # block_method do
98
- # bar(&)
99
- # end
100
- # end
101
- #
102
- # $ ruby -vc foo.rb
103
- # ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22]
104
- # foo.rb: foo.rb:4: anonymous block parameter is also used within block (SyntaxError)
105
- #
107
+ # Ruby 3.3.0 had a bug where accessing an anonymous block argument inside of a block
108
+ # was a syntax error in unambiguous cases: https://bugs.ruby-lang.org/issues/20090
109
+ # We disallow this also for earlier Ruby versions so that code is forwards compatible.
106
110
  def invalidates_syntax?(block_pass_node)
107
- block_pass_node.each_ancestor(:block, :numblock).any?
111
+ target_ruby_version <= 3.3 && block_pass_node.each_ancestor(:any_block).any?
108
112
  end
109
113
 
110
114
  def use_kwarg_in_method_definition?(node)
@@ -113,7 +113,7 @@ module RuboCop
113
113
  end
114
114
  end
115
115
 
116
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
116
+ # rubocop:disable Metrics/MethodLength
117
117
  def correct_node(corrector, node, offending_name, preferred_name)
118
118
  return unless node
119
119
 
@@ -129,13 +129,13 @@ module RuboCop
129
129
  end
130
130
  end
131
131
 
132
- if child_node.masgn_type? || child_node.lvasgn_type?
132
+ if child_node.type?(:masgn, :lvasgn)
133
133
  correct_reassignment(corrector, child_node, offending_name, preferred_name)
134
134
  break
135
135
  end
136
136
  end
137
137
  end
138
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
138
+ # rubocop:enable Metrics/MethodLength
139
139
 
140
140
  # If the exception variable is reassigned, that assignment needs to be corrected.
141
141
  # Further `lvar` nodes will not be corrected though since they now refer to a
@@ -100,6 +100,7 @@ module RuboCop
100
100
  add_offense(node, message: REDUNDANT_HASH_MSG)
101
101
  end
102
102
  end
103
+ alias on_csend on_send
103
104
  alias on_op_asgn on_send
104
105
  end
105
106
  end
@@ -150,8 +150,6 @@ module RuboCop
150
150
 
151
151
  RESTRICT_ON_SEND = %i[private protected public module_function].freeze
152
152
 
153
- ALLOWED_NODE_TYPES = %i[pair block].freeze
154
-
155
153
  # @!method access_modifier_with_symbol?(node)
156
154
  def_node_matcher :access_modifier_with_symbol?, <<~PATTERN
157
155
  (send nil? {:private :protected :public :module_function}
@@ -188,7 +186,7 @@ module RuboCop
188
186
 
189
187
  def allowed?(node)
190
188
  !node.access_modifier? ||
191
- ALLOWED_NODE_TYPES.include?(node.parent&.type) ||
189
+ node.parent&.type?(:pair, :any_block) ||
192
190
  allow_modifiers_on_symbols?(node) ||
193
191
  allow_modifiers_on_attrs?(node) ||
194
192
  allow_modifiers_on_alias_method?(node)
@@ -312,7 +310,7 @@ module RuboCop
312
310
  argument_less_modifier_node = find_argument_less_modifier_node(node)
313
311
  if argument_less_modifier_node
314
312
  corrector.insert_after(argument_less_modifier_node, "\n\n#{source}")
315
- elsif (ancestor = node.each_ancestor(:block, :class, :module).first)
313
+ elsif (ancestor = node.each_ancestor(:class, :module).first)
316
314
 
317
315
  corrector.insert_before(ancestor.loc.end, "#{node.method_name}\n\n#{source}\n")
318
316
  else
@@ -31,6 +31,20 @@ module RuboCop
31
31
  #
32
32
  # This cop handles not only method forwarding but also forwarding to `super`.
33
33
  #
34
+ # [NOTE]
35
+ # --
36
+ # Because of a bug in Ruby 3.3.0, when a block is referenced inside of another block,
37
+ # no offense will be registered until Ruby 3.4:
38
+
39
+ # [source,ruby]
40
+ # ----
41
+ # def foo(&block)
42
+ # # Using an anonymous block would be a syntax error on Ruby 3.3.0
43
+ # block_method { bar(&block) }
44
+ # end
45
+ # ----
46
+ # --
47
+ #
34
48
  # @example
35
49
  # # bad
36
50
  # def foo(*args, &block)
@@ -148,7 +162,7 @@ module RuboCop
148
162
 
149
163
  restarg, kwrestarg, blockarg = extract_forwardable_args(node.arguments)
150
164
  forwardable_args = redundant_forwardable_named_args(restarg, kwrestarg, blockarg)
151
- send_nodes = node.each_descendant(:send, :csend, :super, :yield).to_a
165
+ send_nodes = node.each_descendant(:call, :super, :yield).to_a
152
166
 
153
167
  send_classifications = classify_send_nodes(
154
168
  node, send_nodes, non_splat_or_block_pass_lvar_references(node.body), forwardable_args
@@ -191,9 +205,7 @@ module RuboCop
191
205
 
192
206
  send_classifications.each do |send_node, c, forward_rest, forward_kwrest, forward_block_arg| # rubocop:disable Layout/LineLength
193
207
  if !forward_rest && !forward_kwrest && c != :all_anonymous
194
- # Prevents `anonymous block parameter is also used within block (SyntaxError)` occurs
195
- # in Ruby 3.3.0.
196
- if outside_block?(forward_block_arg)
208
+ if allow_anonymous_forwarding_in_block?(forward_block_arg)
197
209
  register_forward_block_arg_offense(!forward_rest, node.arguments, block_arg)
198
210
  register_forward_block_arg_offense(!forward_rest, send_node, forward_block_arg)
199
211
  end
@@ -214,24 +226,22 @@ module RuboCop
214
226
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
215
227
  def add_post_ruby_32_offenses(def_node, send_classifications, forwardable_args)
216
228
  return unless use_anonymous_forwarding?
217
- return if send_inside_block?(send_classifications)
229
+ return unless all_forwarding_offenses_correctable?(send_classifications)
218
230
 
219
231
  rest_arg, kwrest_arg, block_arg = *forwardable_args
220
232
 
221
233
  send_classifications.each do |send_node, _c, forward_rest, forward_kwrest, forward_block_arg| # rubocop:disable Layout/LineLength
222
- if outside_block?(forward_rest)
234
+ if allow_anonymous_forwarding_in_block?(forward_rest)
223
235
  register_forward_args_offense(def_node.arguments, rest_arg)
224
236
  register_forward_args_offense(send_node, forward_rest)
225
237
  end
226
238
 
227
- if outside_block?(forward_kwrest)
239
+ if allow_anonymous_forwarding_in_block?(forward_kwrest)
228
240
  register_forward_kwargs_offense(!forward_rest, def_node.arguments, kwrest_arg)
229
241
  register_forward_kwargs_offense(!forward_rest, send_node, forward_kwrest)
230
242
  end
231
243
 
232
- # Prevents `anonymous block parameter is also used within block (SyntaxError)` occurs
233
- # in Ruby 3.3.0.
234
- if outside_block?(forward_block_arg)
244
+ if allow_anonymous_forwarding_in_block?(forward_block_arg)
235
245
  register_forward_block_arg_offense(!forward_rest, def_node.arguments, block_arg)
236
246
  register_forward_block_arg_offense(!forward_rest, send_node, forward_block_arg)
237
247
  end
@@ -293,10 +303,25 @@ module RuboCop
293
303
  redundant_arg_names.include?(arg.source) ? arg : nil
294
304
  end
295
305
 
296
- def outside_block?(node)
306
+ # Checks if forwarding is uses both in blocks and outside of blocks.
307
+ # On Ruby 3.3.0, anonymous block forwarding in blocks can be is a syntax
308
+ # error, so we only want to register an offense if we can change all occurrences.
309
+ def all_forwarding_offenses_correctable?(send_classifications)
310
+ return true if target_ruby_version >= 3.4
311
+
312
+ send_classifications.none? do |send_node, *|
313
+ send_node.each_ancestor(:any_block).any?
314
+ end
315
+ end
316
+
317
+ # Ruby 3.3.0 had a bug where accessing an anonymous block argument inside of a block
318
+ # was a syntax error in unambiguous cases: https://bugs.ruby-lang.org/issues/20090
319
+ # We disallow this also for earlier Ruby versions so that code is forwards compatible.
320
+ def allow_anonymous_forwarding_in_block?(node)
297
321
  return false unless node
322
+ return true if target_ruby_version >= 3.4
298
323
 
299
- node.each_ancestor(:block, :numblock).none?
324
+ node.each_ancestor(:any_block).none?
300
325
  end
301
326
 
302
327
  def register_forward_args_offense(def_arguments_or_send, rest_arg_or_splat)
@@ -357,12 +382,6 @@ module RuboCop
357
382
  cop_config.fetch('UseAnonymousForwarding', false)
358
383
  end
359
384
 
360
- def send_inside_block?(send_classifications)
361
- send_classifications.any? do |send_node, *|
362
- send_node.each_ancestor(:block, :numblock).any?
363
- end
364
- end
365
-
366
385
  def add_parens_if_missing(node, corrector)
367
386
  return if parentheses?(node)
368
387
  return if node.send_type? && node.method?(:[])
@@ -511,7 +530,7 @@ module RuboCop
511
530
  end
512
531
 
513
532
  def additional_kwargs?
514
- @def_node.arguments.any? { |a| a.kwarg_type? || a.kwoptarg_type? }
533
+ @def_node.arguments.any? { |a| a.type?(:kwarg, :kwoptarg) }
515
534
  end
516
535
 
517
536
  def forward_additional_kwargs?
@@ -42,14 +42,30 @@ module RuboCop
42
42
  return if node.parent && brace_method?(node.parent)
43
43
 
44
44
  preferred = (value.zero? ? 'first' : 'last')
45
- add_offense(node.loc.selector, message: format(MSG, preferred: preferred)) do |corrector|
46
- corrector.replace(node.loc.selector, ".#{preferred}")
45
+ offense_range = find_offense_range(node)
46
+
47
+ add_offense(offense_range, message: format(MSG, preferred: preferred)) do |corrector|
48
+ corrector.replace(offense_range, preferred_value(node, preferred))
47
49
  end
48
50
  end
49
51
  # rubocop:enable Metrics/AbcSize
52
+ alias on_csend on_send
50
53
 
51
54
  private
52
55
 
56
+ def preferred_value(node, value)
57
+ value = ".#{value}" unless node.loc.dot
58
+ value
59
+ end
60
+
61
+ def find_offense_range(node)
62
+ if node.loc.dot
63
+ node.loc.selector.join(node.source_range.end)
64
+ else
65
+ node.loc.selector
66
+ end
67
+ end
68
+
53
69
  def innermost_braces_node(node)
54
70
  node = node.receiver while node.receiver.send_type? && node.receiver.method?(:[])
55
71
  node
@@ -195,6 +195,7 @@ module RuboCop
195
195
  end
196
196
  end
197
197
  end
198
+ alias on_csend on_send
198
199
 
199
200
  def on_block(node)
200
201
  return if ignored_node?(node)
@@ -348,7 +349,7 @@ module RuboCop
348
349
  case node.type
349
350
  when :block, :numblock
350
351
  yield node
351
- when :send
352
+ when :send, :csend
352
353
  # When a method has an argument which is another method with a block,
353
354
  # that block needs braces, otherwise a syntax error will be introduced
354
355
  # for subsequent arguments.
@@ -369,9 +370,8 @@ module RuboCop
369
370
  end
370
371
  # rubocop:enable Metrics/CyclomaticComplexity
371
372
 
372
- # rubocop:disable Metrics/CyclomaticComplexity
373
373
  def proper_block_style?(node)
374
- return true if require_braces?(node) || require_do_end?(node)
374
+ return true if require_do_end?(node)
375
375
  return special_method_proper_block_style?(node) if special_method?(node.method_name)
376
376
 
377
377
  case style
@@ -381,15 +381,6 @@ module RuboCop
381
381
  when :always_braces then braces_style?(node)
382
382
  end
383
383
  end
384
- # rubocop:enable Metrics/CyclomaticComplexity
385
-
386
- def require_braces?(node)
387
- return false unless node.braces?
388
-
389
- node.each_ancestor(:send).any? do |send|
390
- send.arithmetic_operation? && node.source_range.end_pos < send.loc.selector.begin_pos
391
- end
392
- end
393
384
 
394
385
  def require_do_end?(node)
395
386
  return false if node.braces? || node.multiline?
@@ -483,18 +474,14 @@ module RuboCop
483
474
  end
484
475
 
485
476
  def return_value_of_scope?(node)
486
- return false unless node.parent
487
-
488
- conditional?(node.parent) || array_or_range?(node.parent) ||
489
- node.parent.children.last == node
490
- end
477
+ return false unless (parent = node.parent)
491
478
 
492
- def conditional?(node)
493
- node.if_type? || node.operator_keyword?
479
+ parent.conditional? || parent.operator_keyword? || array_or_range?(parent) ||
480
+ parent.children.last == node
494
481
  end
495
482
 
496
483
  def array_or_range?(node)
497
- node.array_type? || node.range_type?
484
+ node.type?(:array, :range)
498
485
  end
499
486
 
500
487
  def begin_required?(block_node)
@@ -161,7 +161,7 @@ module RuboCop
161
161
 
162
162
  def check_compact_style(node, body)
163
163
  parent = node.parent
164
- return if parent&.class_type? || parent&.module_type?
164
+ return if parent&.type?(:class, :module)
165
165
 
166
166
  return unless needs_compacting?(body)
167
167
 
@@ -49,7 +49,6 @@ module RuboCop
49
49
  def on_block(node)
50
50
  check_method_node(node.send_node)
51
51
  end
52
-
53
52
  alias on_numblock on_block
54
53
 
55
54
  def on_send(node)
@@ -57,6 +56,7 @@ module RuboCop
57
56
 
58
57
  check_method_node(node)
59
58
  end
59
+ alias on_csend on_send
60
60
 
61
61
  private
62
62
 
@@ -55,7 +55,7 @@ module RuboCop
55
55
  def defined_calls(nodes)
56
56
  nodes.filter_map do |defined_node|
57
57
  subject = defined_node.first_argument
58
- subject if subject.const_type? || subject.call_type?
58
+ subject if subject.type?(:const, :call)
59
59
  end
60
60
  end
61
61
 
@@ -98,7 +98,7 @@ module RuboCop
98
98
  end
99
99
 
100
100
  def same_collection_looping_block?(node, sibling)
101
- return false if sibling.nil? || (!sibling.block_type? && !sibling.numblock_type?)
101
+ return false if sibling.nil? || !sibling.any_block_type?
102
102
 
103
103
  sibling.method?(node.method_name) &&
104
104
  sibling.receiver == node.receiver &&
@@ -118,7 +118,7 @@ module RuboCop
118
118
 
119
119
  def correct_end_of_block(corrector, node)
120
120
  return unless node.left_sibling.respond_to?(:braces?)
121
- return if node.right_sibling&.block_type? || node.right_sibling&.numblock_type?
121
+ return if node.right_sibling&.any_block_type?
122
122
 
123
123
  end_of_block = node.left_sibling.braces? ? '}' : ' end'
124
124
  corrector.remove(node.loc.end)
@@ -86,7 +86,7 @@ module RuboCop
86
86
 
87
87
  def percent_literals_includes_only_basic_literals?(node)
88
88
  node.arguments.select(&:percent_literal?).all? do |arg|
89
- arg.children.all? { |child| child.str_type? || child.sym_type? }
89
+ arg.children.all? { |child| child.type?(:str, :sym) }
90
90
  end
91
91
  end
92
92
  end
@@ -107,7 +107,7 @@ module RuboCop
107
107
  parent = node.parent
108
108
  return true unless parent
109
109
 
110
- !(parent.mlhs_type? || parent.resbody_type?)
110
+ !parent.type?(:mlhs, :resbody)
111
111
  end
112
112
  end
113
113
 
@@ -309,7 +309,7 @@ module RuboCop
309
309
  end
310
310
 
311
311
  def allowed_single_line?(branches)
312
- single_line_conditions_only? && branches.any?(&:begin_type?)
312
+ single_line_conditions_only? && branches.compact.any?(&:begin_type?)
313
313
  end
314
314
 
315
315
  def assignment_node(node)
@@ -326,7 +326,7 @@ module RuboCop
326
326
  end
327
327
 
328
328
  def move_assignment_outside_condition(corrector, node)
329
- if node.case_type? || node.case_match_type?
329
+ if node.type?(:case, :case_match)
330
330
  CaseCorrector.correct(corrector, self, node)
331
331
  elsif node.ternary?
332
332
  TernaryCorrector.correct(corrector, node)
@@ -340,7 +340,7 @@ module RuboCop
340
340
 
341
341
  if ternary_condition?(condition)
342
342
  TernaryCorrector.move_assignment_inside_condition(corrector, node)
343
- elsif condition.case_type? || condition.case_match_type?
343
+ elsif condition.type?(:case, :case_match)
344
344
  CaseCorrector.move_assignment_inside_condition(corrector, node)
345
345
  elsif condition.if_type?
346
346
  IfCorrector.move_assignment_inside_condition(corrector, node)
@@ -445,6 +445,8 @@ module RuboCop
445
445
  end
446
446
 
447
447
  [condition.loc.else, condition.loc.end].each do |loc|
448
+ next unless loc
449
+
448
450
  corrector.remove_preceding(loc, loc.column - column)
449
451
  end
450
452
  end
@@ -186,7 +186,7 @@ module RuboCop
186
186
  def qualify_const(node)
187
187
  return if node.nil?
188
188
 
189
- if node.cbase_type? || node.self_type? || node.call_type? || node.variable?
189
+ if node.type?(:cbase, :self, :call) || node.variable?
190
190
  node.source
191
191
  else
192
192
  [qualify_const(node.namespace), node.short_name].compact
@@ -93,7 +93,7 @@ module RuboCop
93
93
 
94
94
  if conditional_node
95
95
  double_negative_condition_return_value?(node, last_child, conditional_node)
96
- elsif last_child.pair_type? || last_child.hash_type? || last_child.parent.array_type?
96
+ elsif last_child.type?(:pair, :hash) || last_child.parent.array_type?
97
97
  false
98
98
  else
99
99
  last_child.last_line <= node.last_line
@@ -102,7 +102,7 @@ module RuboCop
102
102
 
103
103
  def find_def_node_from_ascendant(node)
104
104
  return unless (parent = node.parent)
105
- return parent if parent.def_type? || parent.defs_type?
105
+ return parent if parent.type?(:def, :defs)
106
106
  return node.parent.child_nodes.first if define_method?(parent)
107
107
 
108
108
  find_def_node_from_ascendant(node.parent)
@@ -147,7 +147,7 @@ module RuboCop
147
147
  def find_parent_not_enumerable(node)
148
148
  return unless (parent = node.parent)
149
149
 
150
- if parent.pair_type? || parent.hash_type? || parent.array_type?
150
+ if parent.type?(:pair, :hash, :array)
151
151
  find_parent_not_enumerable(parent)
152
152
  else
153
153
  parent
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # Checks for loops which iterate a constant number of times,
7
- # using a Range literal and `#each`. This can be done more readably using
7
+ # using a `Range` literal and `#each`. This can be done more readably using
8
8
  # `Integer#times`.
9
9
  #
10
10
  # This check only applies if the block takes no parameters.
@@ -58,7 +58,7 @@ module RuboCop
58
58
 
59
59
  # @!method each_with_object_block_candidate?(node)
60
60
  def_node_matcher :each_with_object_block_candidate?, <<~PATTERN
61
- (block $(call _ {:inject :reduce} _) $_ $_)
61
+ (block $(call _ {:inject :reduce} _) $(args _ _) $_)
62
62
  PATTERN
63
63
 
64
64
  # @!method each_with_object_numblock_candidate?(node)
@@ -71,8 +71,7 @@ module RuboCop
71
71
 
72
72
  first_arg, second_arg = *node.arguments
73
73
 
74
- corrector.replace(first_arg, second_arg.source)
75
- corrector.replace(second_arg, first_arg.source)
74
+ corrector.swap(first_arg, second_arg)
76
75
 
77
76
  if return_value_occupies_whole_line?(return_value)
78
77
  corrector.remove(whole_line_expression(return_value))
@@ -86,7 +86,7 @@ module RuboCop
86
86
  return if node.method?(:eval) && !valid_eval_receiver?(node.receiver)
87
87
 
88
88
  code = node.first_argument
89
- return unless code && (code.str_type? || code.dstr_type?)
89
+ return unless code&.type?(:str, :dstr)
90
90
 
91
91
  check_location(node, code)
92
92
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for exact regexp match inside Regexp literals.
6
+ # Checks for exact regexp match inside `Regexp` literals.
7
7
  #
8
8
  # @example
9
9
  #
@@ -123,7 +123,7 @@ module RuboCop
123
123
  end
124
124
 
125
125
  def call_like?(node)
126
- node.call_type? || node.zsuper_type? || node.super_type?
126
+ node.type?(:call, :zsuper, :super)
127
127
  end
128
128
 
129
129
  def insert_argument(node, corrector, block_name)
@@ -135,7 +135,13 @@ module RuboCop
135
135
  end
136
136
 
137
137
  def correct_call_node(node, corrector, block_name)
138
- corrector.insert_after(node, "(&#{block_name})")
138
+ new_arguments = if node.zsuper_type?
139
+ args = build_new_arguments_for_zsuper(node) << "&#{block_name}"
140
+ args.join(', ')
141
+ else
142
+ "&#{block_name}"
143
+ end
144
+ corrector.insert_after(node, "(#{new_arguments})")
139
145
  return unless node.parenthesized?
140
146
 
141
147
  args_begin = Util.args_begin(node)
@@ -144,6 +150,13 @@ module RuboCop
144
150
  corrector.remove(range)
145
151
  end
146
152
 
153
+ def build_new_arguments_for_zsuper(node)
154
+ def_node = node.each_ancestor(:def, :defs).first
155
+ def_node.arguments.map do |arg|
156
+ arg.optarg_type? ? arg.node_parts[0] : arg.source
157
+ end
158
+ end
159
+
147
160
  def block_body_range(block_node, send_node)
148
161
  range_between(send_node.source_range.end_pos, block_node.loc.end.end_pos)
149
162
  end
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # Suggests `ENV.fetch` for the replacement of `ENV[]`.
7
7
  # `ENV[]` silently fails and returns `nil` when the environment variable is unset,
8
8
  # which may cause unexpected behaviors when the developer forgets to set it.
9
- # On the other hand, `ENV.fetch` raises KeyError or returns the explicitly
9
+ # On the other hand, `ENV.fetch` raises `KeyError` or returns the explicitly
10
10
  # specified default value.
11
11
  #
12
12
  # @example
@@ -151,7 +151,7 @@ module RuboCop
151
151
 
152
152
  def frozen_string_literal_comment(processed_source)
153
153
  processed_source.tokens.find do |token|
154
- token.text.start_with?(FROZEN_STRING_LITERAL)
154
+ token.text.start_with?(FROZEN_STRING_LITERAL_REGEXP)
155
155
  end
156
156
  end
157
157
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for uses of `each_key` and `each_value` Hash methods.
6
+ # Checks for uses of `each_key` and `each_value` `Hash` methods.
7
7
  #
8
8
  # NOTE: If you have an array of two-element arrays, you can put
9
9
  # parentheses around the block arguments to indicate that you're not
@@ -44,7 +44,7 @@ module RuboCop
44
44
 
45
45
  # @!method kv_each(node)
46
46
  def_node_matcher :kv_each, <<~PATTERN
47
- ({block numblock} $(call (call _ ${:keys :values}) :each) ...)
47
+ (any_block $(call (call _ ${:keys :values}) :each) ...)
48
48
  PATTERN
49
49
 
50
50
  # @!method each_arguments(node)
@@ -162,10 +162,7 @@ module RuboCop
162
162
 
163
163
  def use_array_converter_method_as_preceding?(node)
164
164
  return false unless (preceding_method = node.children.first.children.first)
165
- unless preceding_method.call_type? ||
166
- preceding_method.block_type? || preceding_method.numblock_type?
167
- return false
168
- end
165
+ return false unless preceding_method.type?(:call, :any_block)
169
166
 
170
167
  ARRAY_CONVERTER_METHODS.include?(preceding_method.method_name)
171
168
  end