rubocop 1.62.1 → 1.67.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 (276) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +67 -68
  3. data/config/default.yml +82 -12
  4. data/config/internal_affairs.yml +11 -0
  5. data/exe/rubocop +4 -3
  6. data/lib/rubocop/cached_data.rb +11 -3
  7. data/lib/rubocop/cli/command/auto_generate_config.rb +6 -7
  8. data/lib/rubocop/cli/command/lsp.rb +2 -2
  9. data/lib/rubocop/cli/command/show_docs_url.rb +2 -2
  10. data/lib/rubocop/cli.rb +4 -0
  11. data/lib/rubocop/comment_config.rb +1 -1
  12. data/lib/rubocop/config.rb +37 -11
  13. data/lib/rubocop/config_loader.rb +15 -9
  14. data/lib/rubocop/config_loader_resolver.rb +13 -8
  15. data/lib/rubocop/config_obsoletion.rb +1 -1
  16. data/lib/rubocop/config_validator.rb +3 -2
  17. data/lib/rubocop/cop/base.rb +56 -16
  18. data/lib/rubocop/cop/bundler/gem_version.rb +4 -5
  19. data/lib/rubocop/cop/cop.rb +30 -4
  20. data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -0
  21. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
  22. data/lib/rubocop/cop/documentation.rb +32 -5
  23. data/lib/rubocop/cop/force.rb +12 -0
  24. data/lib/rubocop/cop/gemspec/add_runtime_dependency.rb +38 -0
  25. data/lib/rubocop/cop/gemspec/dependency_version.rb +3 -5
  26. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
  27. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -3
  28. data/lib/rubocop/cop/internal_affairs/cop_description.rb +0 -4
  29. data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +2 -1
  30. data/lib/rubocop/cop/internal_affairs/example_description.rb +2 -1
  31. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  32. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +6 -21
  33. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +8 -1
  34. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +11 -1
  35. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +0 -5
  36. data/lib/rubocop/cop/internal_affairs.rb +16 -0
  37. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +5 -1
  38. data/lib/rubocop/cop/layout/assignment_indentation.rb +3 -2
  39. data/lib/rubocop/cop/layout/block_alignment.rb +30 -12
  40. data/lib/rubocop/cop/layout/case_indentation.rb +1 -1
  41. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  42. data/lib/rubocop/cop/layout/condition_position.rb +0 -4
  43. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  44. data/lib/rubocop/cop/layout/empty_comment.rb +3 -1
  45. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  46. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +1 -1
  47. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -1
  48. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +8 -3
  49. data/lib/rubocop/cop/layout/first_argument_indentation.rb +2 -2
  50. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -3
  51. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +8 -0
  52. data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -1
  53. data/lib/rubocop/cop/layout/indentation_width.rb +5 -6
  54. data/lib/rubocop/cop/layout/leading_comment_space.rb +28 -1
  55. data/lib/rubocop/cop/layout/line_length.rb +20 -20
  56. data/lib/rubocop/cop/layout/space_around_operators.rb +3 -0
  57. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +3 -4
  58. data/lib/rubocop/cop/legacy/corrector.rb +12 -2
  59. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +0 -2
  60. data/lib/rubocop/cop/lint/ambiguous_operator.rb +0 -2
  61. data/lib/rubocop/cop/lint/ambiguous_range.rb +4 -1
  62. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +0 -2
  63. data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -2
  64. data/lib/rubocop/cop/lint/big_decimal_new.rb +4 -7
  65. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -3
  66. data/lib/rubocop/cop/lint/circular_argument_reference.rb +0 -13
  67. data/lib/rubocop/cop/lint/debugger.rb +27 -6
  68. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  69. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +0 -10
  70. data/lib/rubocop/cop/lint/duplicate_case_condition.rb +1 -5
  71. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +0 -4
  72. data/lib/rubocop/cop/lint/duplicate_methods.rb +0 -10
  73. data/lib/rubocop/cop/lint/duplicate_set_element.rb +74 -0
  74. data/lib/rubocop/cop/lint/each_with_object_argument.rb +0 -4
  75. data/lib/rubocop/cop/lint/else_layout.rb +0 -2
  76. data/lib/rubocop/cop/lint/empty_conditional_body.rb +28 -7
  77. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -11
  78. data/lib/rubocop/cop/lint/empty_interpolation.rb +0 -4
  79. data/lib/rubocop/cop/lint/empty_when.rb +1 -3
  80. data/lib/rubocop/cop/lint/ensure_return.rb +1 -9
  81. data/lib/rubocop/cop/lint/erb_new_arguments.rb +21 -14
  82. data/lib/rubocop/cop/lint/float_comparison.rb +1 -1
  83. data/lib/rubocop/cop/lint/float_out_of_range.rb +0 -4
  84. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +0 -10
  85. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +23 -12
  86. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +0 -7
  87. data/lib/rubocop/cop/lint/interpolation_check.rb +0 -4
  88. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +5 -14
  89. data/lib/rubocop/cop/lint/literal_as_condition.rb +1 -1
  90. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  91. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +25 -6
  92. data/lib/rubocop/cop/lint/loop.rb +6 -12
  93. data/lib/rubocop/cop/lint/mixed_case_range.rb +9 -4
  94. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -7
  95. data/lib/rubocop/cop/lint/next_without_accumulator.rb +0 -4
  96. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +0 -5
  97. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
  98. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -6
  99. data/lib/rubocop/cop/lint/percent_string_array.rb +0 -4
  100. data/lib/rubocop/cop/lint/percent_symbol_array.rb +0 -4
  101. data/lib/rubocop/cop/lint/rand_one.rb +0 -4
  102. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +3 -1
  103. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +1 -1
  104. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  105. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +0 -4
  106. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  107. data/lib/rubocop/cop/lint/require_parentheses.rb +0 -4
  108. data/lib/rubocop/cop/lint/rescue_exception.rb +0 -4
  109. data/lib/rubocop/cop/lint/return_in_void_context.rb +0 -2
  110. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +0 -4
  111. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +105 -41
  112. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +6 -10
  113. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  114. data/lib/rubocop/cop/lint/to_enum_arguments.rb +2 -9
  115. data/lib/rubocop/cop/lint/unified_integer.rb +0 -4
  116. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
  117. data/lib/rubocop/cop/lint/unreachable_code.rb +4 -7
  118. data/lib/rubocop/cop/lint/unreachable_loop.rb +8 -2
  119. data/lib/rubocop/cop/lint/uri_regexp.rb +25 -7
  120. data/lib/rubocop/cop/lint/useless_assignment.rb +19 -16
  121. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +0 -4
  122. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +77 -0
  123. data/lib/rubocop/cop/lint/useless_setter_call.rb +0 -4
  124. data/lib/rubocop/cop/lint/void.rb +35 -8
  125. data/lib/rubocop/cop/metrics/block_length.rb +6 -5
  126. data/lib/rubocop/cop/metrics/block_nesting.rb +19 -7
  127. data/lib/rubocop/cop/metrics/class_length.rb +6 -5
  128. data/lib/rubocop/cop/metrics/method_length.rb +6 -5
  129. data/lib/rubocop/cop/metrics/module_length.rb +6 -5
  130. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +5 -5
  131. data/lib/rubocop/cop/mixin/alignment.rb +5 -1
  132. data/lib/rubocop/cop/mixin/allowed_methods.rb +7 -1
  133. data/lib/rubocop/cop/mixin/allowed_pattern.rb +15 -3
  134. data/lib/rubocop/cop/mixin/annotation_comment.rb +0 -2
  135. data/lib/rubocop/cop/mixin/code_length.rb +12 -1
  136. data/lib/rubocop/cop/mixin/configurable_max.rb +5 -1
  137. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +19 -9
  138. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +9 -2
  139. data/lib/rubocop/cop/mixin/line_length_help.rb +7 -2
  140. data/lib/rubocop/cop/mixin/method_complexity.rb +15 -6
  141. data/lib/rubocop/cop/mixin/percent_array.rb +1 -1
  142. data/lib/rubocop/cop/mixin/rescue_node.rb +4 -0
  143. data/lib/rubocop/cop/mixin/safe_assignment.rb +1 -1
  144. data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -2
  145. data/lib/rubocop/cop/mixin/string_literals_help.rb +12 -0
  146. data/lib/rubocop/cop/naming/accessor_method_name.rb +5 -0
  147. data/lib/rubocop/cop/naming/block_forwarding.rb +31 -12
  148. data/lib/rubocop/cop/naming/file_name.rb +2 -2
  149. data/lib/rubocop/cop/naming/inclusive_language.rb +13 -5
  150. data/lib/rubocop/cop/naming/predicate_name.rb +53 -27
  151. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -1
  152. data/lib/rubocop/cop/offense.rb +2 -2
  153. data/lib/rubocop/cop/security/compound_hash.rb +2 -2
  154. data/lib/rubocop/cop/style/access_modifier_declarations.rb +62 -2
  155. data/lib/rubocop/cop/style/accessor_grouping.rb +10 -2
  156. data/lib/rubocop/cop/style/alias.rb +2 -1
  157. data/lib/rubocop/cop/style/arguments_forwarding.rb +59 -11
  158. data/lib/rubocop/cop/style/block_delimiters.rb +14 -1
  159. data/lib/rubocop/cop/style/collection_compact.rb +9 -9
  160. data/lib/rubocop/cop/style/combinable_loops.rb +7 -0
  161. data/lib/rubocop/cop/style/commented_keyword.rb +7 -1
  162. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -2
  163. data/lib/rubocop/cop/style/copyright.rb +31 -21
  164. data/lib/rubocop/cop/style/data_inheritance.rb +1 -1
  165. data/lib/rubocop/cop/style/def_with_parentheses.rb +0 -2
  166. data/lib/rubocop/cop/style/documentation.rb +24 -24
  167. data/lib/rubocop/cop/style/documentation_method.rb +20 -0
  168. data/lib/rubocop/cop/style/each_for_simple_loop.rb +0 -1
  169. data/lib/rubocop/cop/style/empty_else.rb +6 -5
  170. data/lib/rubocop/cop/style/empty_heredoc.rb +1 -14
  171. data/lib/rubocop/cop/style/empty_literal.rb +31 -22
  172. data/lib/rubocop/cop/style/eval_with_location.rb +16 -13
  173. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -1
  174. data/lib/rubocop/cop/style/file_read.rb +2 -5
  175. data/lib/rubocop/cop/style/file_write.rb +2 -5
  176. data/lib/rubocop/cop/style/format_string.rb +9 -9
  177. data/lib/rubocop/cop/style/format_string_token.rb +2 -2
  178. data/lib/rubocop/cop/style/global_std_stream.rb +7 -1
  179. data/lib/rubocop/cop/style/guard_clause.rb +3 -1
  180. data/lib/rubocop/cop/style/hash_each_methods.rb +6 -0
  181. data/lib/rubocop/cop/style/hash_except.rb +8 -5
  182. data/lib/rubocop/cop/style/hash_syntax.rb +20 -2
  183. data/lib/rubocop/cop/style/identical_conditional_branches.rb +1 -1
  184. data/lib/rubocop/cop/style/if_inside_else.rb +1 -1
  185. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -4
  186. data/lib/rubocop/cop/style/if_with_semicolon.rb +49 -6
  187. data/lib/rubocop/cop/style/in_pattern_then.rb +6 -2
  188. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  189. data/lib/rubocop/cop/style/lambda.rb +1 -1
  190. data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
  191. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +77 -43
  192. data/lib/rubocop/cop/style/map_into_array.rb +228 -0
  193. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  194. data/lib/rubocop/cop/style/map_to_set.rb +1 -1
  195. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +17 -7
  196. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
  197. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -2
  198. data/lib/rubocop/cop/style/missing_else.rb +0 -4
  199. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  200. data/lib/rubocop/cop/style/multiline_when_then.rb +0 -4
  201. data/lib/rubocop/cop/style/multiple_comparison.rb +3 -11
  202. data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
  203. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  204. data/lib/rubocop/cop/style/numeric_predicate.rb +12 -4
  205. data/lib/rubocop/cop/style/one_line_conditional.rb +6 -2
  206. data/lib/rubocop/cop/style/operator_method_call.rb +25 -6
  207. data/lib/rubocop/cop/style/parallel_assignment.rb +5 -4
  208. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -3
  209. data/lib/rubocop/cop/style/redundant_argument.rb +24 -1
  210. data/lib/rubocop/cop/style/redundant_begin.rb +5 -1
  211. data/lib/rubocop/cop/style/redundant_condition.rb +4 -4
  212. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +1 -1
  213. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  214. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -1
  215. data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
  216. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +46 -0
  217. data/lib/rubocop/cop/style/redundant_line_continuation.rb +15 -18
  218. data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
  219. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  220. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -1
  221. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -24
  222. data/lib/rubocop/cop/style/require_order.rb +2 -2
  223. data/lib/rubocop/cop/style/rescue_modifier.rb +13 -1
  224. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +54 -12
  225. data/lib/rubocop/cop/style/safe_navigation.rb +94 -52
  226. data/lib/rubocop/cop/style/select_by_regexp.rb +9 -6
  227. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  228. data/lib/rubocop/cop/style/send.rb +4 -4
  229. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +104 -0
  230. data/lib/rubocop/cop/style/sole_nested_conditional.rb +21 -2
  231. data/lib/rubocop/cop/style/special_global_vars.rb +1 -2
  232. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  233. data/lib/rubocop/cop/style/super_arguments.rb +174 -0
  234. data/lib/rubocop/cop/style/symbol_proc.rb +39 -5
  235. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  236. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  237. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  238. data/lib/rubocop/cop/style/while_until_do.rb +0 -2
  239. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  240. data/lib/rubocop/cop/style/zero_length_predicate.rb +32 -24
  241. data/lib/rubocop/cop/team.rb +27 -3
  242. data/lib/rubocop/cop/util.rb +8 -2
  243. data/lib/rubocop/cop/variable_force.rb +13 -1
  244. data/lib/rubocop/cops_documentation_generator.rb +73 -34
  245. data/lib/rubocop/core_ext/string.rb +2 -6
  246. data/lib/rubocop/ext/regexp_node.rb +9 -31
  247. data/lib/rubocop/ext/regexp_parser.rb +4 -21
  248. data/lib/rubocop/file_finder.rb +9 -4
  249. data/lib/rubocop/formatter/clang_style_formatter.rb +3 -7
  250. data/lib/rubocop/formatter/disabled_config_formatter.rb +13 -9
  251. data/lib/rubocop/formatter/formatter_set.rb +7 -1
  252. data/lib/rubocop/formatter/html_formatter.rb +3 -1
  253. data/lib/rubocop/formatter/junit_formatter.rb +70 -23
  254. data/lib/rubocop/formatter/tap_formatter.rb +3 -7
  255. data/lib/rubocop/lockfile.rb +58 -7
  256. data/lib/rubocop/lsp/routes.rb +10 -13
  257. data/lib/rubocop/lsp/runtime.rb +2 -0
  258. data/lib/rubocop/lsp/server.rb +2 -1
  259. data/lib/rubocop/lsp.rb +9 -2
  260. data/lib/rubocop/options.rb +6 -4
  261. data/lib/rubocop/rake_task.rb +1 -1
  262. data/lib/rubocop/remote_config.rb +5 -1
  263. data/lib/rubocop/result_cache.rb +2 -8
  264. data/lib/rubocop/rspec/expect_offense.rb +9 -0
  265. data/lib/rubocop/rspec/shared_contexts.rb +35 -3
  266. data/lib/rubocop/rspec/support.rb +1 -0
  267. data/lib/rubocop/runner.rb +8 -1
  268. data/lib/rubocop/server/cache.rb +16 -1
  269. data/lib/rubocop/server/client_command/exec.rb +2 -2
  270. data/lib/rubocop/server/client_command/start.rb +1 -1
  271. data/lib/rubocop/server/core.rb +5 -0
  272. data/lib/rubocop/target_ruby.rb +19 -15
  273. data/lib/rubocop/version.rb +7 -5
  274. data/lib/rubocop/yaml_duplication_checker.rb +20 -26
  275. data/lib/rubocop.rb +13 -1
  276. metadata +20 -32
@@ -40,6 +40,7 @@ module RuboCop
40
40
  MSG_WRITER = 'Do not prefix writer method names with `set_`.'
41
41
 
42
42
  def on_def(node)
43
+ return unless proper_attribute_name?(node)
43
44
  return unless bad_reader_name?(node) || bad_writer_name?(node)
44
45
 
45
46
  message = message(node)
@@ -58,6 +59,10 @@ module RuboCop
58
59
  end
59
60
  end
60
61
 
62
+ def proper_attribute_name?(node)
63
+ !node.method_name.to_s.end_with?('!', '?', '=')
64
+ end
65
+
61
66
  def bad_reader_name?(node)
62
67
  node.method_name.to_s.start_with?('get_') && !node.arguments?
63
68
  end
@@ -51,29 +51,25 @@ module RuboCop
51
51
  [Lint::AmbiguousOperator, Style::ArgumentsForwarding]
52
52
  end
53
53
 
54
- # rubocop:disable Metrics/CyclomaticComplexity
55
54
  def on_def(node)
56
55
  return if node.arguments.empty?
57
56
 
58
57
  last_argument = node.last_argument
59
58
  return if expected_block_forwarding_style?(node, last_argument)
60
59
 
61
- invalid_syntax = false
62
- node.each_descendant(:block_pass) do |block_pass_node|
63
- next if block_pass_node.children.first&.sym_type? ||
64
- last_argument.source != block_pass_node.source
60
+ forwarded_args = node.each_descendant(:block_pass).with_object([]) do |block_pass, result|
61
+ return nil if invalidates_syntax?(block_pass)
62
+ next unless block_argument_name_matched?(block_pass, last_argument)
65
63
 
66
- if block_pass_node.each_ancestor(:block, :numblock).any?
67
- invalid_syntax = true
68
- next
69
- end
64
+ result << block_pass
65
+ end
70
66
 
71
- register_offense(block_pass_node, node)
67
+ forwarded_args.each do |forwarded_arg|
68
+ register_offense(forwarded_arg, node)
72
69
  end
73
70
 
74
- register_offense(last_argument, node) unless invalid_syntax
71
+ register_offense(last_argument, node)
75
72
  end
76
- # rubocop:enable Metrics/CyclomaticComplexity
77
73
  alias on_defs on_def
78
74
 
79
75
  private
@@ -88,6 +84,29 @@ module RuboCop
88
84
  end
89
85
  end
90
86
 
87
+ def block_argument_name_matched?(block_pass_node, last_argument)
88
+ return false if block_pass_node.children.first&.sym_type?
89
+
90
+ last_argument.source == block_pass_node.source
91
+ end
92
+
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
+ #
106
+ def invalidates_syntax?(block_pass_node)
107
+ block_pass_node.each_ancestor(:block, :numblock).any?
108
+ end
109
+
91
110
  def use_kwarg_in_method_definition?(node)
92
111
  node.arguments.each_descendant(:kwarg, :kwoptarg).any?
93
112
  end
@@ -57,7 +57,7 @@ module RuboCop
57
57
  file_path = processed_source.file_path
58
58
  return if config.file_to_exclude?(file_path) || config.allowed_camel_case_file?(file_path)
59
59
 
60
- for_bad_filename(file_path) { |range, msg| add_offense(range, message: msg) }
60
+ for_bad_filename(file_path)
61
61
  end
62
62
 
63
63
  private
@@ -71,7 +71,7 @@ module RuboCop
71
71
  msg = other_message(basename) unless bad_filename_allowed?
72
72
  end
73
73
 
74
- yield source_range(processed_source.buffer, 1, 0), msg if msg
74
+ add_global_offense(msg) if msg
75
75
  end
76
76
 
77
77
  def perform_class_and_module_naming_checks(file_path, basename)
@@ -116,9 +116,9 @@ module RuboCop
116
116
  add_offense(range, message: create_message(word)) do |corrector|
117
117
  suggestions = find_flagged_term(word)['Suggestions']
118
118
 
119
- next unless suggestions.is_a?(String)
120
-
121
- corrector.replace(range, suggestions)
119
+ if (preferred_term = preferred_sole_term(suggestions))
120
+ corrector.replace(range, preferred_term)
121
+ end
122
122
  end
123
123
  end
124
124
  end
@@ -157,6 +157,15 @@ module RuboCop
157
157
  set_regexes(flagged_term_strings, allowed_strings)
158
158
  end
159
159
 
160
+ def preferred_sole_term(suggestions)
161
+ case suggestions
162
+ when Array
163
+ suggestions.one? && preferred_sole_term(suggestions.first)
164
+ when String
165
+ suggestions
166
+ end
167
+ end
168
+
160
169
  def extract_regexp(term, term_definition)
161
170
  return term_definition['Regex'] if term_definition['Regex']
162
171
  return /(?:\b|(?<=[\W_]))#{term}(?:\b|(?=[\W_]))/ if term_definition['WholeWord']
@@ -207,8 +216,7 @@ module RuboCop
207
216
  message = create_multiple_word_message_for_file(words)
208
217
  end
209
218
 
210
- range = source_range(processed_source.buffer, 1, 0)
211
- add_offense(range, message: message)
219
+ add_global_offense(message)
212
220
  end
213
221
 
214
222
  def create_single_word_message_for_file(word)
@@ -3,59 +3,75 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Naming
6
- # Checks that predicate methods names end with a question mark and
6
+ # Checks that predicate method names end with a question mark and
7
7
  # do not start with a forbidden prefix.
8
8
  #
9
- # A method is determined to be a predicate method if its name starts
10
- # with one of the prefixes defined in the `NamePrefix` configuration.
11
- # You can change what prefixes are considered by changing this option.
12
- # Any method name that starts with one of these prefixes is required by
13
- # the cop to end with a `?`. Other methods can be allowed by adding to
14
- # the `AllowedMethods` configuration.
9
+ # A method is determined to be a predicate method if its name starts with
10
+ # one of the prefixes listed in the `NamePrefix` configuration. The list
11
+ # defaults to `is_`, `has_`, and `have_` but may be overridden.
15
12
  #
16
- # NOTE: The `is_a?` method is allowed by default.
13
+ # Predicate methods must end with a question mark.
17
14
  #
18
- # If `ForbiddenPrefixes` is set, methods that start with the configured
19
- # prefixes will not be allowed and will be removed by autocorrection.
15
+ # When `ForbiddenPrefixes` is also set (as it is by default), predicate
16
+ # methods which begin with a forbidden prefix are not allowed, even if
17
+ # they end with a `?`. These methods should be changed to remove the
18
+ # prefix.
20
19
  #
21
- # In other words, if `ForbiddenPrefixes` is empty, a method named `is_foo`
22
- # will register an offense only due to the lack of question mark (and will be
23
- # autocorrected to `is_foo?`). If `ForbiddenPrefixes` contains `is_`,
24
- # `is_foo` will register an offense both because the ? is missing and because of
25
- # the `is_` prefix, and will be corrected to `foo?`.
26
- #
27
- # NOTE: `ForbiddenPrefixes` is only applied to prefixes in `NamePrefix`;
28
- # a prefix in the former but not the latter will not be considered by
29
- # this cop.
30
- #
31
- # @example
20
+ # @example NamePrefix: ['is_', 'has_', 'have_'] (default)
32
21
  # # bad
33
22
  # def is_even(value)
34
23
  # end
35
24
  #
36
- # def is_even?(value)
25
+ # # When ForbiddenPrefixes: ['is_', 'has_', 'have_'] (default)
26
+ # # good
27
+ # def even?(value)
37
28
  # end
38
29
  #
30
+ # # When ForbiddenPrefixes: []
39
31
  # # good
40
- # def even?(value)
32
+ # def is_even?(value)
41
33
  # end
42
34
  #
35
+ # @example NamePrefix: ['seems_to_be_']
43
36
  # # bad
44
- # def has_value
37
+ # def seems_to_be_even(value)
45
38
  # end
46
39
  #
47
- # def has_value?
40
+ # # When ForbiddenPrefixes: ['seems_to_be_']
41
+ # # good
42
+ # def even?(value)
48
43
  # end
49
44
  #
45
+ # # When ForbiddenPrefixes: []
50
46
  # # good
51
- # def value?
47
+ # def seems_to_be_even?(value)
52
48
  # end
53
49
  #
54
50
  # @example AllowedMethods: ['is_a?'] (default)
51
+ # # Despite starting with the `is_` prefix, this method is allowed
55
52
  # # good
56
53
  # def is_a?(value)
57
54
  # end
58
55
  #
56
+ # @example AllowedMethods: ['is_even?']
57
+ # # good
58
+ # def is_even?(value)
59
+ # end
60
+ #
61
+ # @example MethodDefinitionMacros: ['define_method', 'define_singleton_method'] (default)
62
+ # # bad
63
+ # define_method(:is_even) { |value| }
64
+ #
65
+ # # good
66
+ # define_method(:even?) { |value| }
67
+ #
68
+ # @example MethodDefinitionMacros: ['def_node_matcher']
69
+ # # bad
70
+ # def_node_matcher(:is_even) { |value| }
71
+ #
72
+ # # good
73
+ # def_node_matcher(:even?) { |value| }
74
+ #
59
75
  class PredicateName < Base
60
76
  include AllowedMethods
61
77
 
@@ -72,7 +88,7 @@ module RuboCop
72
88
  next if allowed_method_name?(method_name.to_s, prefix)
73
89
 
74
90
  add_offense(
75
- node.first_argument.source_range,
91
+ node.first_argument,
76
92
  message: message(method_name, expected_name(method_name.to_s, prefix))
77
93
  )
78
94
  end
@@ -93,6 +109,16 @@ module RuboCop
93
109
  end
94
110
  alias on_defs on_def
95
111
 
112
+ def validate_config
113
+ forbidden_prefixes.each do |forbidden_prefix|
114
+ next if predicate_prefixes.include?(forbidden_prefix)
115
+
116
+ raise ValidationError, <<~MSG.chomp
117
+ The `Naming/PredicateName` cop is misconfigured. Prefix #{forbidden_prefix} must be included in NamePrefix because it is included in ForbiddenPrefixes.
118
+ MSG
119
+ end
120
+ end
121
+
96
122
  private
97
123
 
98
124
  def allowed_method_name?(method_name, prefix)
@@ -113,13 +113,21 @@ module RuboCop
113
113
  end
114
114
  end
115
115
 
116
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
116
117
  def correct_node(corrector, node, offending_name, preferred_name)
117
118
  return unless node
118
119
 
119
120
  node.each_node(:lvar, :lvasgn, :masgn) do |child_node|
120
121
  next unless variable_name_matches?(child_node, offending_name)
121
122
 
122
- corrector.replace(child_node, preferred_name) if child_node.lvar_type?
123
+ if child_node.lvar_type?
124
+ parent_node = child_node.parent
125
+ if parent_node.respond_to?(:value_omission?) && parent_node.value_omission?
126
+ corrector.insert_after(parent_node.loc.operator, " #{preferred_name}")
127
+ else
128
+ corrector.replace(child_node, preferred_name)
129
+ end
130
+ end
123
131
 
124
132
  if child_node.masgn_type? || child_node.lvasgn_type?
125
133
  correct_reassignment(corrector, child_node, offending_name, preferred_name)
@@ -127,6 +135,7 @@ module RuboCop
127
135
  end
128
136
  end
129
137
  end
138
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
130
139
 
131
140
  # If the exception variable is reassigned, that assignment needs to be corrected.
132
141
  # Further `lvar` nodes will not be corrected though since they now refer to a
@@ -97,8 +97,8 @@ module RuboCop
97
97
  # @!attribute [r] correctable?
98
98
  #
99
99
  # @return [Boolean]
100
- # whether this offense can be automatically corrected via
101
- # autocorrect or a todo.
100
+ # whether this offense can be automatically corrected via autocorrect.
101
+ # This includes todo comments, for example when requested with `--disable-uncorrectable`.
102
102
  def correctable?
103
103
  @status != :unsupported
104
104
  end
@@ -30,8 +30,8 @@ module RuboCop
30
30
  class CompoundHash < Base
31
31
  COMBINATOR_IN_HASH_MSG = 'Use `[...].hash` instead of combining hash values manually.'
32
32
  MONUPLE_HASH_MSG =
33
- 'Delegate hash directly without wrapping in an array when only using a single value'
34
- REDUNDANT_HASH_MSG = 'Calling .hash on elements of a hashed array is redundant'
33
+ 'Delegate hash directly without wrapping in an array when only using a single value.'
34
+ REDUNDANT_HASH_MSG = 'Calling .hash on elements of a hashed array is redundant.'
35
35
 
36
36
  # @!method hash_method_definition?(node)
37
37
  def_node_matcher :hash_method_definition?, <<~PATTERN
@@ -8,6 +8,17 @@ module RuboCop
8
8
  # EnforcedStyle config covers only method definitions.
9
9
  # Applications of visibility methods to symbols can be controlled
10
10
  # using AllowModifiersOnSymbols config.
11
+ # Also, the visibility of `attr*` methods can be controlled using
12
+ # AllowModifiersOnAttrs config.
13
+ #
14
+ # In Ruby 3.0, `attr*` methods now return an array of defined method names
15
+ # as symbols. So we can write the modifier and `attr*` in inline style.
16
+ # AllowModifiersOnAttrs config allows `attr*` methods to be written in
17
+ # inline style without modifying applications that have been maintained
18
+ # for a long time in group style. Furthermore, developers who are not very
19
+ # familiar with Ruby may know that the modifier applies to `def`, but they
20
+ # may not know that it also applies to `attr*` methods. It would be easier
21
+ # to understand if we could write `attr*` methods in inline style.
11
22
  #
12
23
  # @safety
13
24
  # Autocorrection is not safe, because the visibility of dynamically
@@ -57,6 +68,8 @@ module RuboCop
57
68
  # class Foo
58
69
  #
59
70
  # private :bar, :baz
71
+ # private *%i[qux quux]
72
+ # private *METHOD_NAMES
60
73
  #
61
74
  # end
62
75
  #
@@ -65,6 +78,36 @@ module RuboCop
65
78
  # class Foo
66
79
  #
67
80
  # private :bar, :baz
81
+ # private *%i[qux quux]
82
+ # private *METHOD_NAMES
83
+ #
84
+ # end
85
+ #
86
+ # @example AllowModifiersOnAttrs: true (default)
87
+ # # good
88
+ # class Foo
89
+ #
90
+ # public attr_reader :bar
91
+ # protected attr_writer :baz
92
+ # private attr_accessor :qux
93
+ # private attr :quux
94
+ #
95
+ # def public_method; end
96
+ #
97
+ # private
98
+ #
99
+ # def private_method; end
100
+ #
101
+ # end
102
+ #
103
+ # @example AllowModifiersOnAttrs: false
104
+ # # bad
105
+ # class Foo
106
+ #
107
+ # public attr_reader :bar
108
+ # protected attr_writer :baz
109
+ # private attr_accessor :qux
110
+ # private attr :quux
68
111
  #
69
112
  # end
70
113
  class AccessModifierDeclarations < Base
@@ -89,13 +132,22 @@ module RuboCop
89
132
 
90
133
  # @!method access_modifier_with_symbol?(node)
91
134
  def_node_matcher :access_modifier_with_symbol?, <<~PATTERN
92
- (send nil? {:private :protected :public :module_function} (sym _))
135
+ (send nil? {:private :protected :public :module_function}
136
+ {(sym _) (splat {#percent_symbol_array? const})}
137
+ )
138
+ PATTERN
139
+
140
+ # @!method access_modifier_with_attr?(node)
141
+ def_node_matcher :access_modifier_with_attr?, <<~PATTERN
142
+ (send nil? {:private :protected :public :module_function}
143
+ (send nil? {:attr :attr_reader :attr_writer :attr_accessor} _))
93
144
  PATTERN
94
145
 
95
146
  def on_send(node)
96
147
  return unless node.access_modifier?
97
148
  return if ALLOWED_NODE_TYPES.include?(node.parent&.type)
98
149
  return if allow_modifiers_on_symbols?(node)
150
+ return if allow_modifiers_on_attrs?(node)
99
151
 
100
152
  if offense?(node)
101
153
  add_offense(node.loc.selector) do |corrector|
@@ -124,10 +176,18 @@ module RuboCop
124
176
  end
125
177
  end
126
178
 
179
+ def percent_symbol_array?(node)
180
+ node.array_type? && node.percent_literal?(:symbol)
181
+ end
182
+
127
183
  def allow_modifiers_on_symbols?(node)
128
184
  cop_config['AllowModifiersOnSymbols'] && access_modifier_with_symbol?(node)
129
185
  end
130
186
 
187
+ def allow_modifiers_on_attrs?(node)
188
+ cop_config['AllowModifiersOnAttrs'] && access_modifier_with_attr?(node)
189
+ end
190
+
131
191
  def offense?(node)
132
192
  (group_style? && access_modifier_is_inlined?(node) &&
133
193
  !right_siblings_same_inline_method?(node)) ||
@@ -168,7 +228,7 @@ module RuboCop
168
228
 
169
229
  def find_corresponding_def_node(node)
170
230
  if access_modifier_with_symbol?(node)
171
- method_name = node.first_argument.value
231
+ method_name = node.first_argument.respond_to?(:value) && node.first_argument.value
172
232
  node.parent.each_child_node(:def).find do |child|
173
233
  child.method?(method_name)
174
234
  end
@@ -10,6 +10,9 @@ module RuboCop
10
10
  # NOTE: If there is a method call before the accessor method it is always allowed
11
11
  # as it might be intended like Sorbet.
12
12
  #
13
+ # NOTE: If there is a RBS::Inline annotation comment just after the accessor method
14
+ # it is always allowed.
15
+ #
13
16
  # @example EnforcedStyle: grouped (default)
14
17
  # # bad
15
18
  # class Foo
@@ -92,7 +95,7 @@ module RuboCop
92
95
  comment_line?(processed_source[node.first_line - 2])
93
96
  end
94
97
 
95
- # rubocop:disable Metrics/CyclomaticComplexity
98
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
96
99
  def groupable_accessor?(node)
97
100
  return true unless (previous_expression = node.left_siblings.last)
98
101
 
@@ -105,11 +108,16 @@ module RuboCop
105
108
 
106
109
  return true unless previous_expression.send_type?
107
110
 
111
+ # Accessors with RBS::Inline annotations shouldn't be groupable.
112
+ return false if processed_source.comments.any? do |c|
113
+ same_line?(c, previous_expression) && c.text.start_with?('#:')
114
+ end
115
+
108
116
  previous_expression.attribute_accessor? ||
109
117
  previous_expression.access_modifier? ||
110
118
  node.first_line - previous_expression.last_line > 1 # there is a space between nodes
111
119
  end
112
- # rubocop:enable Metrics/CyclomaticComplexity
120
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
113
121
 
114
122
  def class_send_elements(class_node)
115
123
  class_def = class_node.body
@@ -41,6 +41,7 @@ module RuboCop
41
41
  def on_send(node)
42
42
  return unless node.command?(:alias_method)
43
43
  return unless style == :prefer_alias && alias_keyword_possible?(node)
44
+ return unless node.arguments.count == 2
44
45
 
45
46
  msg = format(MSG_ALIAS_METHOD, current: lexical_scope_type(node))
46
47
  add_offense(node.loc.selector, message: msg) do |corrector|
@@ -79,7 +80,7 @@ module RuboCop
79
80
  def alias_method_possible?(node)
80
81
  scope_type(node) != :instance_eval &&
81
82
  node.children.none?(&:gvar_type?) &&
82
- node&.parent&.type != :def
83
+ node.each_ancestor(:def).none?
83
84
  end
84
85
 
85
86
  def add_offense_for_args(node, &block)
@@ -29,6 +29,8 @@ module RuboCop
29
29
  #
30
30
  # Names not on this list are likely to be meaningful and are allowed by default.
31
31
  #
32
+ # This cop handles not only method forwarding but also forwarding to `super`.
33
+ #
32
34
  # @example
33
35
  # # bad
34
36
  # def foo(*args, &block)
@@ -146,7 +148,7 @@ module RuboCop
146
148
 
147
149
  restarg, kwrestarg, blockarg = extract_forwardable_args(node.arguments)
148
150
  forwardable_args = redundant_forwardable_named_args(restarg, kwrestarg, blockarg)
149
- send_nodes = node.each_descendant(:send).to_a
151
+ send_nodes = node.each_descendant(:send, :csend, :super, :yield).to_a
150
152
 
151
153
  send_classifications = classify_send_nodes(
152
154
  node, send_nodes, non_splat_or_block_pass_lvar_references(node.body), forwardable_args
@@ -178,7 +180,8 @@ module RuboCop
178
180
  end
179
181
 
180
182
  def only_forwards_all?(send_classifications)
181
- send_classifications.all? { |_, c, _, _| c == :all }
183
+ all_classifications = %i[all all_anonymous].freeze
184
+ send_classifications.all? { |_, c, _, _| all_classifications.include?(c) }
182
185
  end
183
186
 
184
187
  # rubocop:disable Metrics/MethodLength
@@ -186,8 +189,8 @@ module RuboCop
186
189
  _rest_arg, _kwrest_arg, block_arg = *forwardable_args
187
190
  registered_block_arg_offense = false
188
191
 
189
- send_classifications.each do |send_node, _c, forward_rest, forward_kwrest, forward_block_arg| # rubocop:disable Layout/LineLength
190
- if !forward_rest && !forward_kwrest
192
+ send_classifications.each do |send_node, c, forward_rest, forward_kwrest, forward_block_arg| # rubocop:disable Layout/LineLength
193
+ if !forward_rest && !forward_kwrest && c != :all_anonymous
191
194
  # Prevents `anonymous block parameter is also used within block (SyntaxError)` occurs
192
195
  # in Ruby 3.3.0.
193
196
  if outside_block?(forward_block_arg)
@@ -211,6 +214,7 @@ module RuboCop
211
214
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
212
215
  def add_post_ruby_32_offenses(def_node, send_classifications, forwardable_args)
213
216
  return unless use_anonymous_forwarding?
217
+ return if send_inside_block?(send_classifications)
214
218
 
215
219
  rest_arg, kwrest_arg, block_arg = *forwardable_args
216
220
 
@@ -312,7 +316,8 @@ module RuboCop
312
316
  end
313
317
 
314
318
  def register_forward_block_arg_offense(add_parens, def_arguments_or_send, block_arg)
315
- return if target_ruby_version <= 3.0 || block_arg.source == '&' || explicit_block_name?
319
+ return if target_ruby_version <= 3.0 ||
320
+ block_arg.nil? || block_arg.source == '&' || explicit_block_name?
316
321
 
317
322
  add_offense(block_arg, message: BLOCK_MSG) do |corrector|
318
323
  add_parens_if_missing(def_arguments_or_send, corrector) if add_parens
@@ -331,13 +336,18 @@ module RuboCop
331
336
  end
332
337
  end
333
338
 
339
+ # rubocop:disable Metrics/AbcSize
334
340
  def arguments_range(node, first_node)
335
- arguments = node.arguments.reject { |arg| ADDITIONAL_ARG_TYPES.include?(arg.type) }
341
+ arguments = node.arguments.reject do |arg|
342
+ next true if ADDITIONAL_ARG_TYPES.include?(arg.type) || arg.variable? || arg.call_type?
336
343
 
337
- start_node = first_node || arguments.first
344
+ arg.literal? && arg.each_descendant(:kwsplat).none?
345
+ end
338
346
 
339
- range_between(start_node.source_range.begin_pos, arguments.last.source_range.end_pos)
347
+ start_node = first_node || arguments.first
348
+ start_node.source_range.begin.join(arguments.last.source_range.end)
340
349
  end
350
+ # rubocop:enable Metrics/AbcSize
341
351
 
342
352
  def allow_only_rest_arguments?
343
353
  cop_config.fetch('AllowOnlyRestArgument', true)
@@ -347,8 +357,15 @@ module RuboCop
347
357
  cop_config.fetch('UseAnonymousForwarding', false)
348
358
  end
349
359
 
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
+
350
366
  def add_parens_if_missing(node, corrector)
351
367
  return if parentheses?(node)
368
+ return if node.send_type? && node.method?(:[])
352
369
 
353
370
  add_parentheses(node, corrector)
354
371
  end
@@ -366,6 +383,23 @@ module RuboCop
366
383
  # @!method forwarded_block_arg?(node, block_name)
367
384
  def_node_matcher :forwarded_block_arg?, '(block_pass {(lvar %1) nil?})'
368
385
 
386
+ # @!method def_all_anonymous_args?(node)
387
+ def_node_matcher :def_all_anonymous_args?, <<~PATTERN
388
+ (
389
+ def _
390
+ (args ... (restarg) (kwrestarg) (blockarg nil?))
391
+ _
392
+ )
393
+ PATTERN
394
+
395
+ # @!method send_all_anonymous_args?(node)
396
+ def_node_matcher :send_all_anonymous_args?, <<~PATTERN
397
+ (
398
+ send _ _
399
+ ... (forwarded_restarg) (hash (forwarded_kwrestarg)) (block_pass nil?)
400
+ )
401
+ PATTERN
402
+
369
403
  def initialize(def_node, send_node, referenced_lvars, forwardable_args, **config)
370
404
  @def_node = def_node
371
405
  @send_node = send_node
@@ -397,7 +431,9 @@ module RuboCop
397
431
  def classification
398
432
  return nil unless forwarded_rest_arg || forwarded_kwrest_arg || forwarded_block_arg
399
433
 
400
- if can_forward_all?
434
+ if ruby_32_only_anonymous_forwarding?
435
+ :all_anonymous
436
+ elsif can_forward_all?
401
437
  :all
402
438
  else
403
439
  :rest_or_kwrest
@@ -406,16 +442,28 @@ module RuboCop
406
442
 
407
443
  private
408
444
 
445
+ # rubocop:disable Metrics/CyclomaticComplexity
409
446
  def can_forward_all?
410
447
  return false if any_arg_referenced?
411
- return false if ruby_32_missing_rest_or_kwest?
448
+ return false if ruby_30_or_lower_optarg?
449
+ return false if ruby_32_or_higher_missing_rest_or_kwest?
412
450
  return false unless offensive_block_forwarding?
413
451
  return false if additional_kwargs_or_forwarded_kwargs?
414
452
 
415
453
  no_additional_args? || (target_ruby_version >= 3.0 && no_post_splat_args?)
416
454
  end
455
+ # rubocop:enable Metrics/CyclomaticComplexity
456
+
457
+ # def foo(a = 41, ...) is a syntax error in 3.0.
458
+ def ruby_30_or_lower_optarg?
459
+ target_ruby_version <= 3.0 && @def_node.arguments.any?(&:optarg_type?)
460
+ end
461
+
462
+ def ruby_32_only_anonymous_forwarding?
463
+ def_all_anonymous_args?(@def_node) && send_all_anonymous_args?(@send_node)
464
+ end
417
465
 
418
- def ruby_32_missing_rest_or_kwest?
466
+ def ruby_32_or_higher_missing_rest_or_kwest?
419
467
  target_ruby_version >= 3.2 && !forwarded_rest_and_kwrest_args
420
468
  end
421
469