rubocop 1.42.0 → 1.64.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (498) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +7 -6
  4. data/assets/output.css.erb +159 -0
  5. data/assets/output.html.erb +1 -160
  6. data/config/default.yml +342 -64
  7. data/config/obsoletion.yml +5 -0
  8. data/lib/rubocop/cached_data.rb +11 -3
  9. data/lib/rubocop/cli/command/auto_generate_config.rb +27 -6
  10. data/lib/rubocop/cli/command/execute_runner.rb +7 -2
  11. data/lib/rubocop/cli/command/lsp.rb +19 -0
  12. data/lib/rubocop/cli/command/show_docs_url.rb +2 -2
  13. data/lib/rubocop/cli.rb +68 -10
  14. data/lib/rubocop/comment_config.rb +19 -0
  15. data/lib/rubocop/config.rb +43 -15
  16. data/lib/rubocop/config_finder.rb +14 -4
  17. data/lib/rubocop/config_loader.rb +20 -24
  18. data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
  19. data/lib/rubocop/config_obsoletion.rb +13 -10
  20. data/lib/rubocop/config_validator.rb +14 -7
  21. data/lib/rubocop/cop/autocorrect_logic.rb +37 -14
  22. data/lib/rubocop/cop/base.rb +97 -28
  23. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -0
  24. data/lib/rubocop/cop/bundler/duplicated_group.rb +127 -0
  25. data/lib/rubocop/cop/bundler/gem_comment.rb +4 -4
  26. data/lib/rubocop/cop/bundler/gem_version.rb +5 -7
  27. data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
  28. data/lib/rubocop/cop/commissioner.rb +8 -2
  29. data/lib/rubocop/cop/cop.rb +25 -5
  30. data/lib/rubocop/cop/corrector.rb +11 -3
  31. data/lib/rubocop/cop/correctors/alignment_corrector.rb +3 -3
  32. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
  33. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +6 -14
  34. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
  35. data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
  36. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +2 -2
  37. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +2 -7
  38. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
  39. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  40. data/lib/rubocop/cop/documentation.rb +16 -6
  41. data/lib/rubocop/cop/exclude_limit.rb +1 -1
  42. data/lib/rubocop/cop/force.rb +12 -0
  43. data/lib/rubocop/cop/gemspec/dependency_version.rb +6 -8
  44. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +3 -3
  45. data/lib/rubocop/cop/gemspec/development_dependencies.rb +107 -0
  46. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
  47. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +5 -1
  48. data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
  49. data/lib/rubocop/cop/internal_affairs/cop_description.rb +37 -13
  50. data/lib/rubocop/cop/internal_affairs/example_description.rb +46 -24
  51. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +3 -3
  52. data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +1 -1
  53. data/lib/rubocop/cop/internal_affairs/location_expression.rb +37 -0
  54. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -1
  55. data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
  56. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +19 -20
  57. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
  58. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +128 -34
  59. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -1
  60. data/lib/rubocop/cop/internal_affairs/processed_source_buffer_name.rb +42 -0
  61. data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
  62. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +11 -3
  63. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  64. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
  65. data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
  66. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +66 -0
  67. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
  68. data/lib/rubocop/cop/internal_affairs.rb +5 -0
  69. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  70. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  71. data/lib/rubocop/cop/layout/block_end_newline.rb +7 -15
  72. data/lib/rubocop/cop/layout/class_structure.rb +15 -19
  73. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +2 -3
  74. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +2 -6
  75. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  76. data/lib/rubocop/cop/layout/dot_position.rb +1 -5
  77. data/lib/rubocop/cop/layout/empty_comment.rb +6 -4
  78. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +42 -9
  79. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +14 -7
  80. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +28 -5
  81. data/lib/rubocop/cop/layout/empty_lines.rb +1 -1
  82. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +2 -0
  83. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
  84. data/lib/rubocop/cop/layout/end_alignment.rb +23 -3
  85. data/lib/rubocop/cop/layout/extra_spacing.rb +3 -4
  86. data/lib/rubocop/cop/layout/first_argument_indentation.rb +8 -3
  87. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +24 -7
  88. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +25 -34
  89. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +7 -19
  90. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +42 -52
  91. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +38 -55
  92. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  93. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +12 -6
  94. data/lib/rubocop/cop/layout/heredoc_indentation.rb +12 -12
  95. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  96. data/lib/rubocop/cop/layout/indentation_width.rb +3 -3
  97. data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
  98. data/lib/rubocop/cop/layout/leading_comment_space.rb +2 -2
  99. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +18 -12
  100. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +12 -8
  101. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -0
  102. data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +8 -27
  103. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +7 -26
  104. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +4 -21
  105. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
  106. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +6 -30
  107. data/lib/rubocop/cop/layout/redundant_line_break.rb +33 -11
  108. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +6 -6
  109. data/lib/rubocop/cop/layout/single_line_block_chain.rb +5 -0
  110. data/lib/rubocop/cop/layout/space_after_comma.rb +9 -1
  111. data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
  112. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  113. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +2 -2
  114. data/lib/rubocop/cop/layout/space_around_operators.rb +53 -21
  115. data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
  116. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
  117. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +2 -2
  118. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +11 -13
  119. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +3 -1
  120. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
  121. data/lib/rubocop/cop/layout/space_inside_parens.rb +3 -3
  122. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +1 -1
  123. data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
  124. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +4 -4
  125. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +6 -6
  126. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +5 -0
  127. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  128. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +13 -1
  129. data/lib/rubocop/cop/lint/ambiguous_operator.rb +4 -0
  130. data/lib/rubocop/cop/lint/assignment_in_condition.rb +6 -6
  131. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
  132. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
  133. data/lib/rubocop/cop/lint/constant_resolution.rb +1 -1
  134. data/lib/rubocop/cop/lint/debugger.rb +49 -26
  135. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +62 -112
  136. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  137. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +2 -1
  138. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +122 -0
  139. data/lib/rubocop/cop/lint/duplicate_methods.rb +3 -3
  140. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +47 -22
  141. data/lib/rubocop/cop/lint/else_layout.rb +3 -7
  142. data/lib/rubocop/cop/lint/empty_block.rb +2 -2
  143. data/lib/rubocop/cop/lint/empty_conditional_body.rb +6 -4
  144. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  145. data/lib/rubocop/cop/lint/erb_new_arguments.rb +27 -21
  146. data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
  147. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +14 -7
  148. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
  149. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +16 -18
  150. data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
  151. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  152. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -3
  153. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  154. data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
  155. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
  156. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  157. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +85 -0
  158. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +47 -5
  159. data/lib/rubocop/cop/lint/missing_super.rb +63 -5
  160. data/lib/rubocop/cop/lint/mixed_case_range.rb +116 -0
  161. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
  162. data/lib/rubocop/cop/lint/nested_method_definition.rb +4 -9
  163. data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
  164. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -7
  165. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -5
  166. data/lib/rubocop/cop/lint/number_conversion.rb +14 -4
  167. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
  168. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -0
  169. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
  170. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +8 -12
  171. data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
  172. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  173. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +11 -5
  174. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +5 -5
  175. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +130 -0
  176. data/lib/rubocop/cop/lint/redundant_require_statement.rb +21 -2
  177. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +72 -8
  178. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  179. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +35 -15
  180. data/lib/rubocop/cop/lint/redundant_with_index.rb +7 -3
  181. data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -3
  182. data/lib/rubocop/cop/lint/refinement_import_methods.rb +2 -1
  183. data/lib/rubocop/cop/lint/rescue_type.rb +2 -4
  184. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +14 -8
  185. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +1 -1
  186. data/lib/rubocop/cop/lint/script_permission.rb +3 -3
  187. data/lib/rubocop/cop/lint/self_assignment.rb +38 -0
  188. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -2
  189. data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
  190. data/lib/rubocop/cop/lint/shadowed_exception.rb +6 -12
  191. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +7 -1
  192. data/lib/rubocop/cop/lint/struct_new_override.rb +12 -12
  193. data/lib/rubocop/cop/lint/suppressed_exception.rb +2 -2
  194. data/lib/rubocop/cop/lint/symbol_conversion.rb +8 -3
  195. data/lib/rubocop/cop/lint/syntax.rb +10 -3
  196. data/lib/rubocop/cop/lint/to_enum_arguments.rb +23 -6
  197. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
  198. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
  199. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
  200. data/lib/rubocop/cop/lint/unreachable_code.rb +4 -2
  201. data/lib/rubocop/cop/lint/unreachable_loop.rb +11 -5
  202. data/lib/rubocop/cop/lint/useless_access_modifier.rb +12 -9
  203. data/lib/rubocop/cop/lint/useless_assignment.rb +94 -10
  204. data/lib/rubocop/cop/lint/useless_method_definition.rb +12 -4
  205. data/lib/rubocop/cop/lint/useless_rescue.rb +89 -0
  206. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +9 -1
  207. data/lib/rubocop/cop/lint/useless_times.rb +3 -3
  208. data/lib/rubocop/cop/lint/void.rb +119 -20
  209. data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
  210. data/lib/rubocop/cop/metrics/block_length.rb +2 -2
  211. data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
  212. data/lib/rubocop/cop/metrics/class_length.rb +8 -2
  213. data/lib/rubocop/cop/metrics/collection_literal_length.rb +76 -0
  214. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  215. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  216. data/lib/rubocop/cop/metrics/parameter_lists.rb +27 -0
  217. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +3 -7
  218. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +38 -10
  219. data/lib/rubocop/cop/migration/department_name.rb +3 -3
  220. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  221. data/lib/rubocop/cop/mixin/allowed_methods.rb +3 -1
  222. data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
  223. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  224. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  225. data/lib/rubocop/cop/mixin/code_length.rb +12 -1
  226. data/lib/rubocop/cop/mixin/comments_help.rb +21 -11
  227. data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -0
  228. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  229. data/lib/rubocop/cop/mixin/documentation_comment.rb +1 -1
  230. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
  231. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +1 -1
  232. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +78 -29
  233. data/lib/rubocop/cop/mixin/hash_transform_method.rb +3 -3
  234. data/lib/rubocop/cop/mixin/heredoc.rb +6 -2
  235. data/lib/rubocop/cop/mixin/line_length_help.rb +3 -1
  236. data/lib/rubocop/cop/mixin/method_complexity.rb +15 -6
  237. data/lib/rubocop/cop/mixin/min_branches_count.rb +40 -0
  238. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +0 -3
  239. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +4 -3
  240. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  241. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  242. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -8
  243. data/lib/rubocop/cop/mixin/range_help.rb +1 -6
  244. data/lib/rubocop/cop/mixin/safe_assignment.rb +1 -1
  245. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  246. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  247. data/lib/rubocop/cop/mixin/statement_modifier.rb +4 -3
  248. data/lib/rubocop/cop/mixin/string_help.rb +4 -2
  249. data/lib/rubocop/cop/mixin/surrounding_space.rb +3 -3
  250. data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
  251. data/lib/rubocop/cop/naming/ascii_identifiers.rb +1 -1
  252. data/lib/rubocop/cop/naming/block_forwarding.rb +38 -7
  253. data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +1 -1
  254. data/lib/rubocop/cop/naming/constant_name.rb +2 -3
  255. data/lib/rubocop/cop/naming/file_name.rb +3 -3
  256. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +1 -1
  257. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +3 -1
  258. data/lib/rubocop/cop/naming/inclusive_language.rb +24 -6
  259. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +26 -11
  260. data/lib/rubocop/cop/naming/method_name.rb +3 -3
  261. data/lib/rubocop/cop/naming/predicate_name.rb +3 -3
  262. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +12 -4
  263. data/lib/rubocop/cop/naming/variable_name.rb +6 -1
  264. data/lib/rubocop/cop/registry.rb +16 -9
  265. data/lib/rubocop/cop/security/compound_hash.rb +2 -2
  266. data/lib/rubocop/cop/security/open.rb +2 -2
  267. data/lib/rubocop/cop/style/access_modifier_declarations.rb +78 -13
  268. data/lib/rubocop/cop/style/accessor_grouping.rb +44 -18
  269. data/lib/rubocop/cop/style/alias.rb +10 -8
  270. data/lib/rubocop/cop/style/arguments_forwarding.rb +414 -62
  271. data/lib/rubocop/cop/style/array_first_last.rb +64 -0
  272. data/lib/rubocop/cop/style/array_intersect.rb +14 -6
  273. data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
  274. data/lib/rubocop/cop/style/attr.rb +11 -1
  275. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
  276. data/lib/rubocop/cop/style/begin_block.rb +1 -2
  277. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +3 -3
  278. data/lib/rubocop/cop/style/block_comments.rb +2 -2
  279. data/lib/rubocop/cop/style/block_delimiters.rb +22 -6
  280. data/lib/rubocop/cop/style/case_like_if.rb +25 -8
  281. data/lib/rubocop/cop/style/class_and_module_children.rb +5 -12
  282. data/lib/rubocop/cop/style/class_check.rb +1 -0
  283. data/lib/rubocop/cop/style/class_equality_comparison.rb +58 -40
  284. data/lib/rubocop/cop/style/class_vars.rb +3 -3
  285. data/lib/rubocop/cop/style/collection_compact.rb +37 -14
  286. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  287. data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
  288. data/lib/rubocop/cop/style/combinable_loops.rb +36 -8
  289. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  290. data/lib/rubocop/cop/style/comment_annotation.rb +1 -1
  291. data/lib/rubocop/cop/style/commented_keyword.rb +7 -4
  292. data/lib/rubocop/cop/style/comparable_clamp.rb +125 -0
  293. data/lib/rubocop/cop/style/concat_array_literals.rb +12 -3
  294. data/lib/rubocop/cop/style/conditional_assignment.rb +15 -20
  295. data/lib/rubocop/cop/style/copyright.rb +37 -24
  296. data/lib/rubocop/cop/style/data_inheritance.rb +75 -0
  297. data/lib/rubocop/cop/style/date_time.rb +5 -4
  298. data/lib/rubocop/cop/style/dir.rb +1 -1
  299. data/lib/rubocop/cop/style/dir_empty.rb +54 -0
  300. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +2 -2
  301. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +3 -3
  302. data/lib/rubocop/cop/style/documentation.rb +36 -30
  303. data/lib/rubocop/cop/style/documentation_method.rb +30 -4
  304. data/lib/rubocop/cop/style/double_negation.rb +2 -2
  305. data/lib/rubocop/cop/style/each_for_simple_loop.rb +7 -7
  306. data/lib/rubocop/cop/style/each_with_object.rb +3 -3
  307. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  308. data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
  309. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  310. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  311. data/lib/rubocop/cop/style/eval_with_location.rb +14 -23
  312. data/lib/rubocop/cop/style/exact_regexp_match.rb +70 -0
  313. data/lib/rubocop/cop/style/explicit_block_argument.rb +3 -3
  314. data/lib/rubocop/cop/style/file_empty.rb +71 -0
  315. data/lib/rubocop/cop/style/file_read.rb +3 -3
  316. data/lib/rubocop/cop/style/file_write.rb +1 -1
  317. data/lib/rubocop/cop/style/for.rb +3 -1
  318. data/lib/rubocop/cop/style/format_string.rb +33 -12
  319. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +4 -2
  320. data/lib/rubocop/cop/style/guard_clause.rb +29 -1
  321. data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
  322. data/lib/rubocop/cop/style/hash_each_methods.rb +106 -21
  323. data/lib/rubocop/cop/style/hash_except.rb +25 -13
  324. data/lib/rubocop/cop/style/hash_like_case.rb +3 -9
  325. data/lib/rubocop/cop/style/hash_syntax.rb +29 -3
  326. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  327. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  328. data/lib/rubocop/cop/style/identical_conditional_branches.rb +34 -5
  329. data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
  330. data/lib/rubocop/cop/style/if_unless_modifier.rb +111 -15
  331. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +7 -3
  332. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  333. data/lib/rubocop/cop/style/infinite_loop.rb +2 -5
  334. data/lib/rubocop/cop/style/inverse_methods.rb +14 -13
  335. data/lib/rubocop/cop/style/invertible_unless_condition.rb +160 -0
  336. data/lib/rubocop/cop/style/lambda.rb +3 -3
  337. data/lib/rubocop/cop/style/lambda_call.rb +5 -0
  338. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +8 -10
  339. data/lib/rubocop/cop/style/map_into_array.rb +175 -0
  340. data/lib/rubocop/cop/style/map_to_hash.rb +20 -7
  341. data/lib/rubocop/cop/style/map_to_set.rb +5 -2
  342. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +48 -28
  343. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +46 -41
  344. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +22 -0
  345. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  346. data/lib/rubocop/cop/style/min_max.rb +3 -3
  347. data/lib/rubocop/cop/style/min_max_comparison.rb +11 -1
  348. data/lib/rubocop/cop/style/missing_else.rb +13 -1
  349. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
  350. data/lib/rubocop/cop/style/mixin_grouping.rb +5 -5
  351. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  352. data/lib/rubocop/cop/style/multiline_if_modifier.rb +0 -4
  353. data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
  354. data/lib/rubocop/cop/style/multiline_method_signature.rb +17 -5
  355. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +21 -4
  356. data/lib/rubocop/cop/style/multiple_comparison.rb +14 -0
  357. data/lib/rubocop/cop/style/negated_if_else_condition.rb +13 -12
  358. data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
  359. data/lib/rubocop/cop/style/next.rb +1 -1
  360. data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
  361. data/lib/rubocop/cop/style/nil_lambda.rb +2 -2
  362. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +11 -3
  363. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +1 -1
  364. data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
  365. data/lib/rubocop/cop/style/numeric_predicate.rb +10 -2
  366. data/lib/rubocop/cop/style/object_then.rb +5 -3
  367. data/lib/rubocop/cop/style/one_line_conditional.rb +4 -7
  368. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  369. data/lib/rubocop/cop/style/operator_method_call.rb +24 -4
  370. data/lib/rubocop/cop/style/parallel_assignment.rb +32 -24
  371. data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -0
  372. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -3
  373. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  374. data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
  375. data/lib/rubocop/cop/style/raise_args.rb +4 -1
  376. data/lib/rubocop/cop/style/redundant_argument.rb +33 -4
  377. data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
  378. data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
  379. data/lib/rubocop/cop/style/redundant_begin.rb +10 -2
  380. data/lib/rubocop/cop/style/redundant_condition.rb +18 -3
  381. data/lib/rubocop/cop/style/redundant_conditional.rb +2 -14
  382. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +39 -0
  383. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +103 -9
  384. data/lib/rubocop/cop/style/redundant_each.rb +7 -4
  385. data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
  386. data/lib/rubocop/cop/style/redundant_fetch_block.rb +9 -7
  387. data/lib/rubocop/cop/style/redundant_filter_chain.rb +118 -0
  388. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +58 -0
  389. data/lib/rubocop/cop/style/redundant_interpolation.rb +2 -2
  390. data/lib/rubocop/cop/style/redundant_line_continuation.rb +200 -0
  391. data/lib/rubocop/cop/style/redundant_parentheses.rb +73 -24
  392. data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -2
  393. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +100 -0
  394. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +7 -8
  395. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
  396. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +13 -4
  397. data/lib/rubocop/cop/style/redundant_return.rb +14 -3
  398. data/lib/rubocop/cop/style/redundant_self.rb +17 -2
  399. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +8 -1
  400. data/lib/rubocop/cop/style/redundant_sort.rb +13 -12
  401. data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
  402. data/lib/rubocop/cop/style/redundant_string_escape.rb +6 -5
  403. data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
  404. data/lib/rubocop/cop/style/require_order.rb +12 -15
  405. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
  406. data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -2
  407. data/lib/rubocop/cop/style/return_nil.rb +6 -2
  408. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +95 -0
  409. data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
  410. data/lib/rubocop/cop/style/sample.rb +3 -4
  411. data/lib/rubocop/cop/style/select_by_regexp.rb +22 -11
  412. data/lib/rubocop/cop/style/self_assignment.rb +3 -3
  413. data/lib/rubocop/cop/style/semicolon.rb +43 -5
  414. data/lib/rubocop/cop/style/send.rb +4 -4
  415. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +90 -0
  416. data/lib/rubocop/cop/style/signal_exception.rb +1 -1
  417. data/lib/rubocop/cop/style/single_argument_dig.rb +7 -3
  418. data/lib/rubocop/cop/style/single_line_do_end_block.rb +67 -0
  419. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  420. data/lib/rubocop/cop/style/slicing_with_range.rb +77 -11
  421. data/lib/rubocop/cop/style/sole_nested_conditional.rb +9 -5
  422. data/lib/rubocop/cop/style/special_global_vars.rb +4 -6
  423. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  424. data/lib/rubocop/cop/style/string_chars.rb +1 -0
  425. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -1
  426. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
  427. data/lib/rubocop/cop/style/strip.rb +7 -4
  428. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  429. data/lib/rubocop/cop/style/super_arguments.rb +156 -0
  430. data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
  431. data/lib/rubocop/cop/style/symbol_array.rb +35 -15
  432. data/lib/rubocop/cop/style/symbol_proc.rb +68 -5
  433. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  434. data/lib/rubocop/cop/style/trailing_body_on_class.rb +1 -0
  435. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +1 -1
  436. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  437. data/lib/rubocop/cop/style/unless_logical_operators.rb +1 -0
  438. data/lib/rubocop/cop/style/unpack_first.rb +11 -14
  439. data/lib/rubocop/cop/style/word_array.rb +18 -6
  440. data/lib/rubocop/cop/style/yaml_file_read.rb +66 -0
  441. data/lib/rubocop/cop/style/yoda_condition.rb +17 -8
  442. data/lib/rubocop/cop/style/yoda_expression.rb +26 -9
  443. data/lib/rubocop/cop/style/zero_length_predicate.rb +9 -5
  444. data/lib/rubocop/cop/team.rb +36 -23
  445. data/lib/rubocop/cop/util.rb +14 -5
  446. data/lib/rubocop/cop/utils/regexp_ranges.rb +113 -0
  447. data/lib/rubocop/cop/variable_force/assignment.rb +45 -4
  448. data/lib/rubocop/cop/variable_force/scope.rb +3 -3
  449. data/lib/rubocop/cop/variable_force/variable.rb +5 -3
  450. data/lib/rubocop/cop/variable_force/variable_table.rb +5 -3
  451. data/lib/rubocop/cop/variable_force.rb +2 -1
  452. data/lib/rubocop/cops_documentation_generator.rb +26 -7
  453. data/lib/rubocop/directive_comment.rb +13 -11
  454. data/lib/rubocop/ext/comment.rb +18 -0
  455. data/lib/rubocop/ext/regexp_node.rb +10 -5
  456. data/lib/rubocop/ext/regexp_parser.rb +5 -2
  457. data/lib/rubocop/file_finder.rb +4 -7
  458. data/lib/rubocop/formatter/clang_style_formatter.rb +3 -7
  459. data/lib/rubocop/formatter/disabled_config_formatter.rb +23 -8
  460. data/lib/rubocop/formatter/formatter_set.rb +7 -1
  461. data/lib/rubocop/formatter/html_formatter.rb +35 -14
  462. data/lib/rubocop/formatter/json_formatter.rb +0 -1
  463. data/lib/rubocop/formatter/junit_formatter.rb +4 -1
  464. data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
  465. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
  466. data/lib/rubocop/formatter/tap_formatter.rb +3 -7
  467. data/lib/rubocop/formatter.rb +1 -2
  468. data/lib/rubocop/lockfile.rb +56 -7
  469. data/lib/rubocop/lsp/logger.rb +22 -0
  470. data/lib/rubocop/lsp/routes.rb +243 -0
  471. data/lib/rubocop/lsp/runtime.rb +99 -0
  472. data/lib/rubocop/lsp/server.rb +73 -0
  473. data/lib/rubocop/lsp/severity.rb +27 -0
  474. data/lib/rubocop/lsp.rb +36 -0
  475. data/lib/rubocop/magic_comment.rb +13 -11
  476. data/lib/rubocop/options.rb +49 -12
  477. data/lib/rubocop/path_util.rb +17 -8
  478. data/lib/rubocop/rake_task.rb +1 -1
  479. data/lib/rubocop/result_cache.rb +6 -3
  480. data/lib/rubocop/rspec/cop_helper.rb +9 -3
  481. data/lib/rubocop/rspec/expect_offense.rb +18 -8
  482. data/lib/rubocop/rspec/shared_contexts.rb +59 -19
  483. data/lib/rubocop/rspec/support.rb +3 -0
  484. data/lib/rubocop/runner.rb +59 -10
  485. data/lib/rubocop/server/cache.rb +11 -4
  486. data/lib/rubocop/server/cli.rb +37 -18
  487. data/lib/rubocop/server/client_command/exec.rb +4 -4
  488. data/lib/rubocop/server/client_command/start.rb +6 -1
  489. data/lib/rubocop/server/core.rb +24 -9
  490. data/lib/rubocop/server/helper.rb +1 -1
  491. data/lib/rubocop/server/server_command/exec.rb +1 -2
  492. data/lib/rubocop/string_interpreter.rb +3 -3
  493. data/lib/rubocop/target_finder.rb +91 -81
  494. data/lib/rubocop/target_ruby.rb +85 -78
  495. data/lib/rubocop/version.rb +27 -8
  496. data/lib/rubocop.rb +35 -0
  497. metadata +76 -35
  498. /data/lib/rubocop/formatter/{git_hub_actions_formatter.rb → github_actions_formatter.rb} +0 -0
@@ -8,6 +8,29 @@ module RuboCop
8
8
  # This cop identifies places where `do_something(*args, &block)`
9
9
  # can be replaced by `do_something(...)`.
10
10
  #
11
+ # In Ruby 3.1, anonymous block forwarding has been added.
12
+ #
13
+ # This cop identifies places where `do_something(&block)` can be replaced
14
+ # by `do_something(&)`; if desired, this functionality can be disabled
15
+ # by setting `UseAnonymousForwarding: false`.
16
+ #
17
+ # In Ruby 3.2, anonymous args/kwargs forwarding has been added.
18
+ #
19
+ # This cop also identifies places where `use_args(*args)`/`use_kwargs(**kwargs)` can be
20
+ # replaced by `use_args(*)`/`use_kwargs(**)`; if desired, this functionality can be disabled
21
+ # by setting `UseAnonymousForwarding: false`.
22
+ #
23
+ # And this cop has `RedundantRestArgumentNames`, `RedundantKeywordRestArgumentNames`,
24
+ # and `RedundantBlockArgumentNames` options. This configuration is a list of redundant names
25
+ # that are sufficient for anonymizing meaningless naming.
26
+ #
27
+ # Meaningless names that are commonly used can be anonymized by default:
28
+ # e.g., `*args`, `**options`, `&block`, and so on.
29
+ #
30
+ # Names not on this list are likely to be meaningful and are allowed by default.
31
+ #
32
+ # This cop handles not only method forwarding but also forwarding to `super`.
33
+ #
11
34
  # @example
12
35
  # # bad
13
36
  # def foo(*args, &block)
@@ -24,7 +47,30 @@ module RuboCop
24
47
  # bar(...)
25
48
  # end
26
49
  #
27
- # @example AllowOnlyRestArgument: true (default)
50
+ # @example UseAnonymousForwarding: true (default, only relevant for Ruby >= 3.2)
51
+ # # bad
52
+ # def foo(*args, **kwargs, &block)
53
+ # args_only(*args)
54
+ # kwargs_only(**kwargs)
55
+ # block_only(&block)
56
+ # end
57
+ #
58
+ # # good
59
+ # def foo(*, **, &)
60
+ # args_only(*)
61
+ # kwargs_only(**)
62
+ # block_only(&)
63
+ # end
64
+ #
65
+ # @example UseAnonymousForwarding: false (only relevant for Ruby >= 3.2)
66
+ # # good
67
+ # def foo(*args, **kwargs, &block)
68
+ # args_only(*args)
69
+ # kwargs_only(**kwargs)
70
+ # block_only(&block)
71
+ # end
72
+ #
73
+ # @example AllowOnlyRestArgument: true (default, only relevant for Ruby < 3.2)
28
74
  # # good
29
75
  # def foo(*args)
30
76
  # bar(*args)
@@ -34,7 +80,7 @@ module RuboCop
34
80
  # bar(**kwargs)
35
81
  # end
36
82
  #
37
- # @example AllowOnlyRestArgument: false
83
+ # @example AllowOnlyRestArgument: false (only relevant for Ruby < 3.2)
38
84
  # # bad
39
85
  # # The following code can replace the arguments with `...`,
40
86
  # # but it will change the behavior. Because `...` forwards block also.
@@ -46,6 +92,38 @@ module RuboCop
46
92
  # bar(**kwargs)
47
93
  # end
48
94
  #
95
+ # @example RedundantRestArgumentNames: ['args', 'arguments'] (default)
96
+ # # bad
97
+ # def foo(*args)
98
+ # bar(*args)
99
+ # end
100
+ #
101
+ # # good
102
+ # def foo(*)
103
+ # bar(*)
104
+ # end
105
+ #
106
+ # @example RedundantKeywordRestArgumentNames: ['kwargs', 'options', 'opts'] (default)
107
+ # # bad
108
+ # def foo(**kwargs)
109
+ # bar(**kwargs)
110
+ # end
111
+ #
112
+ # # good
113
+ # def foo(**)
114
+ # bar(**)
115
+ # end
116
+ #
117
+ # @example RedundantBlockArgumentNames: ['blk', 'block', 'proc'] (default)
118
+ # # bad - But it is good with `EnforcedStyle: explicit` set for `Naming/BlockForwarding`.
119
+ # def foo(&block)
120
+ # bar(&block)
121
+ # end
122
+ #
123
+ # # good
124
+ # def foo(&)
125
+ # bar(&)
126
+ # end
49
127
  class ArgumentsForwarding < Base
50
128
  include RangeHelp
51
129
  extend AutoCorrector
@@ -53,101 +131,375 @@ module RuboCop
53
131
 
54
132
  minimum_target_ruby_version 2.7
55
133
 
56
- MSG = 'Use arguments forwarding.'
57
-
58
- # @!method use_rest_arguments?(node)
59
- def_node_matcher :use_rest_arguments?, <<~PATTERN
60
- (args ({restarg kwrestarg} $_) $...)
61
- PATTERN
62
-
63
- # @!method only_rest_arguments?(node, name)
64
- def_node_matcher :only_rest_arguments?, <<~PATTERN
65
- {
66
- (send _ _ (splat (lvar %1)))
67
- (send _ _ (hash (kwsplat (lvar %1))))
68
- }
69
- PATTERN
70
-
71
- # @!method forwarding_method_arguments?(node, rest_name, block_name, kwargs_name)
72
- def_node_matcher :forwarding_method_arguments?, <<~PATTERN
73
- {
74
- (send _ _
75
- (splat (lvar %1))
76
- (block-pass {(lvar %2) nil?}))
77
- (send _ _
78
- (splat (lvar %1))
79
- (hash (kwsplat (lvar %3)))
80
- (block-pass {(lvar %2) nil?}))
81
- }
82
- PATTERN
134
+ FORWARDING_LVAR_TYPES = %i[splat kwsplat block_pass].freeze
135
+ ADDITIONAL_ARG_TYPES = %i[lvar arg].freeze
136
+
137
+ FORWARDING_MSG = 'Use shorthand syntax `...` for arguments forwarding.'
138
+ ARGS_MSG = 'Use anonymous positional arguments forwarding (`*`).'
139
+ KWARGS_MSG = 'Use anonymous keyword arguments forwarding (`**`).'
140
+ BLOCK_MSG = 'Use anonymous block arguments forwarding (`&`).'
141
+
142
+ def self.autocorrect_incompatible_with
143
+ [Naming::BlockForwarding]
144
+ end
83
145
 
84
146
  def on_def(node)
85
147
  return unless node.body
86
- return unless (rest_args_name, args = use_rest_arguments?(node.arguments))
87
148
 
88
- node.each_descendant(:send) do |send_node|
89
- kwargs_name, block_name = extract_argument_names_from(args)
149
+ restarg, kwrestarg, blockarg = extract_forwardable_args(node.arguments)
150
+ forwardable_args = redundant_forwardable_named_args(restarg, kwrestarg, blockarg)
151
+ send_nodes = node.each_descendant(:send, :csend, :super).to_a
90
152
 
91
- next unless forwarding_method?(send_node, rest_args_name, kwargs_name, block_name) &&
92
- all_lvars_as_forwarding_method_arguments?(node, send_node)
153
+ send_classifications = classify_send_nodes(
154
+ node, send_nodes, non_splat_or_block_pass_lvar_references(node.body), forwardable_args
155
+ )
93
156
 
94
- register_offense_to_forwarding_method_arguments(send_node)
95
- register_offense_to_method_definition_arguments(node)
157
+ return if send_classifications.empty?
158
+
159
+ if only_forwards_all?(send_classifications)
160
+ add_forward_all_offenses(node, send_classifications, forwardable_args)
161
+ elsif target_ruby_version >= 3.2
162
+ add_post_ruby_32_offenses(node, send_classifications, forwardable_args)
96
163
  end
97
164
  end
165
+
98
166
  alias on_defs on_def
99
167
 
100
168
  private
101
169
 
102
- def extract_argument_names_from(args)
103
- kwargs_name = args.first.source.delete('**') if args.first&.kwrestarg_type?
104
- block_arg_name = args.last.source.delete('&') if args.last&.blockarg_type?
170
+ def extract_forwardable_args(args)
171
+ [args.find(&:restarg_type?), args.find(&:kwrestarg_type?), args.find(&:blockarg_type?)]
172
+ end
173
+
174
+ def redundant_forwardable_named_args(restarg, kwrestarg, blockarg)
175
+ restarg_node = redundant_named_arg(restarg, 'RedundantRestArgumentNames', '*')
176
+ kwrestarg_node = redundant_named_arg(kwrestarg, 'RedundantKeywordRestArgumentNames', '**')
177
+ blockarg_node = redundant_named_arg(blockarg, 'RedundantBlockArgumentNames', '&')
178
+
179
+ [restarg_node, kwrestarg_node, blockarg_node]
180
+ end
181
+
182
+ def only_forwards_all?(send_classifications)
183
+ send_classifications.all? { |_, c, _, _| c == :all }
184
+ end
185
+
186
+ # rubocop:disable Metrics/MethodLength
187
+ def add_forward_all_offenses(node, send_classifications, forwardable_args)
188
+ _rest_arg, _kwrest_arg, block_arg = *forwardable_args
189
+ registered_block_arg_offense = false
190
+
191
+ send_classifications.each do |send_node, _c, forward_rest, forward_kwrest, forward_block_arg| # rubocop:disable Layout/LineLength
192
+ if !forward_rest && !forward_kwrest
193
+ # Prevents `anonymous block parameter is also used within block (SyntaxError)` occurs
194
+ # in Ruby 3.3.0.
195
+ if outside_block?(forward_block_arg)
196
+ register_forward_block_arg_offense(!forward_rest, node.arguments, block_arg)
197
+ register_forward_block_arg_offense(!forward_rest, send_node, forward_block_arg)
198
+ end
199
+ registered_block_arg_offense = true
200
+ break
201
+ else
202
+ register_forward_all_offense(send_node, send_node, forward_rest)
203
+ end
204
+ end
205
+
206
+ return if registered_block_arg_offense
105
207
 
106
- [kwargs_name, block_arg_name].map { |name| name&.to_sym }
208
+ rest_arg, _kwrest_arg, _block_arg = *forwardable_args
209
+ register_forward_all_offense(node, node.arguments, rest_arg)
107
210
  end
211
+ # rubocop:enable Metrics/MethodLength
108
212
 
109
- def forwarding_method?(node, rest_arg, kwargs, block_arg)
110
- return only_rest_arguments?(node, rest_arg) unless allow_only_rest_arguments?
213
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
214
+ def add_post_ruby_32_offenses(def_node, send_classifications, forwardable_args)
215
+ return unless use_anonymous_forwarding?
111
216
 
112
- forwarding_method_arguments?(node, rest_arg, block_arg, kwargs)
217
+ rest_arg, kwrest_arg, block_arg = *forwardable_args
218
+
219
+ send_classifications.each do |send_node, _c, forward_rest, forward_kwrest, forward_block_arg| # rubocop:disable Layout/LineLength
220
+ if outside_block?(forward_rest)
221
+ register_forward_args_offense(def_node.arguments, rest_arg)
222
+ register_forward_args_offense(send_node, forward_rest)
223
+ end
224
+
225
+ if outside_block?(forward_kwrest)
226
+ register_forward_kwargs_offense(!forward_rest, def_node.arguments, kwrest_arg)
227
+ register_forward_kwargs_offense(!forward_rest, send_node, forward_kwrest)
228
+ end
229
+
230
+ # Prevents `anonymous block parameter is also used within block (SyntaxError)` occurs
231
+ # in Ruby 3.3.0.
232
+ if outside_block?(forward_block_arg)
233
+ register_forward_block_arg_offense(!forward_rest, def_node.arguments, block_arg)
234
+ register_forward_block_arg_offense(!forward_rest, send_node, forward_block_arg)
235
+ end
236
+ end
113
237
  end
238
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
114
239
 
115
- def all_lvars_as_forwarding_method_arguments?(def_node, forwarding_method)
116
- lvars = def_node.body.each_descendant(:lvar, :lvasgn)
240
+ def non_splat_or_block_pass_lvar_references(body)
241
+ body.each_descendant(:lvar, :lvasgn).filter_map do |lvar|
242
+ parent = lvar.parent
117
243
 
118
- begin_pos = forwarding_method.source_range.begin_pos
119
- end_pos = forwarding_method.source_range.end_pos
244
+ next if lvar.lvar_type? && FORWARDING_LVAR_TYPES.include?(parent.type)
120
245
 
121
- lvars.all? { |lvar| lvar.source_range.begin_pos.between?(begin_pos, end_pos) }
246
+ lvar.children.first
247
+ end.uniq
122
248
  end
123
249
 
124
- def register_offense_to_forwarding_method_arguments(forwarding_method)
125
- add_offense(arguments_range(forwarding_method)) do |corrector|
126
- range = range_between(
127
- forwarding_method.loc.selector.end_pos, forwarding_method.source_range.end_pos
250
+ def classify_send_nodes(def_node, send_nodes, referenced_lvars, forwardable_args)
251
+ send_nodes.filter_map do |send_node|
252
+ classification_and_forwards = classification_and_forwards(
253
+ def_node,
254
+ send_node,
255
+ referenced_lvars,
256
+ forwardable_args
128
257
  )
129
- corrector.replace(range, '(...)')
258
+
259
+ next unless classification_and_forwards
260
+
261
+ [send_node, *classification_and_forwards]
130
262
  end
131
263
  end
132
264
 
133
- def register_offense_to_method_definition_arguments(method_definition)
134
- add_offense(arguments_range(method_definition)) do |corrector|
135
- arguments_range = range_with_surrounding_space(
136
- method_definition.arguments.source_range, side: :left
137
- )
138
- corrector.replace(arguments_range, '(...)')
265
+ def classification_and_forwards(def_node, send_node, referenced_lvars, forwardable_args)
266
+ classifier = SendNodeClassifier.new(
267
+ def_node, send_node, referenced_lvars, forwardable_args,
268
+ target_ruby_version: target_ruby_version,
269
+ allow_only_rest_arguments: allow_only_rest_arguments?
270
+ )
271
+
272
+ classification = classifier.classification
273
+
274
+ return unless classification
275
+
276
+ [
277
+ classification,
278
+ classifier.forwarded_rest_arg,
279
+ classifier.forwarded_kwrest_arg,
280
+ classifier.forwarded_block_arg
281
+ ]
282
+ end
283
+
284
+ def redundant_named_arg(arg, config_name, keyword)
285
+ return nil unless arg
286
+
287
+ redundant_arg_names = cop_config.fetch(config_name, []).map do |redundant_arg_name|
288
+ "#{keyword}#{redundant_arg_name}"
289
+ end << keyword
290
+
291
+ redundant_arg_names.include?(arg.source) ? arg : nil
292
+ end
293
+
294
+ def outside_block?(node)
295
+ return false unless node
296
+
297
+ node.each_ancestor(:block, :numblock).none?
298
+ end
299
+
300
+ def register_forward_args_offense(def_arguments_or_send, rest_arg_or_splat)
301
+ add_offense(rest_arg_or_splat, message: ARGS_MSG) do |corrector|
302
+ add_parens_if_missing(def_arguments_or_send, corrector)
303
+
304
+ corrector.replace(rest_arg_or_splat, '*')
305
+ end
306
+ end
307
+
308
+ def register_forward_kwargs_offense(add_parens, def_arguments_or_send, kwrest_arg_or_splat)
309
+ add_offense(kwrest_arg_or_splat, message: KWARGS_MSG) do |corrector|
310
+ add_parens_if_missing(def_arguments_or_send, corrector) if add_parens
311
+
312
+ corrector.replace(kwrest_arg_or_splat, '**')
139
313
  end
140
314
  end
141
315
 
142
- def arguments_range(node)
143
- arguments = node.arguments
316
+ def register_forward_block_arg_offense(add_parens, def_arguments_or_send, block_arg)
317
+ return if target_ruby_version <= 3.0 ||
318
+ block_arg.nil? || block_arg.source == '&' || explicit_block_name?
144
319
 
145
- range_between(arguments.first.source_range.begin_pos, arguments.last.source_range.end_pos)
320
+ add_offense(block_arg, message: BLOCK_MSG) do |corrector|
321
+ add_parens_if_missing(def_arguments_or_send, corrector) if add_parens
322
+
323
+ corrector.replace(block_arg, '&')
324
+ end
325
+ end
326
+
327
+ def register_forward_all_offense(def_or_send, send_or_arguments, rest_or_splat)
328
+ arg_range = arguments_range(def_or_send, rest_or_splat)
329
+
330
+ add_offense(arg_range, message: FORWARDING_MSG) do |corrector|
331
+ add_parens_if_missing(send_or_arguments, corrector)
332
+
333
+ corrector.replace(arg_range, '...')
334
+ end
335
+ end
336
+
337
+ def arguments_range(node, first_node)
338
+ arguments = node.arguments.reject { |arg| ADDITIONAL_ARG_TYPES.include?(arg.type) }
339
+
340
+ start_node = first_node || arguments.first
341
+
342
+ range_between(start_node.source_range.begin_pos, arguments.last.source_range.end_pos)
146
343
  end
147
344
 
148
345
  def allow_only_rest_arguments?
149
346
  cop_config.fetch('AllowOnlyRestArgument', true)
150
347
  end
348
+
349
+ def use_anonymous_forwarding?
350
+ cop_config.fetch('UseAnonymousForwarding', false)
351
+ end
352
+
353
+ def add_parens_if_missing(node, corrector)
354
+ return if parentheses?(node)
355
+
356
+ add_parentheses(node, corrector)
357
+ end
358
+
359
+ # Classifies send nodes for possible rest/kwrest/all (including block) forwarding.
360
+ class SendNodeClassifier
361
+ extend NodePattern::Macros
362
+
363
+ # @!method forwarded_rest_arg?(node, rest_name)
364
+ def_node_matcher :forwarded_rest_arg?, '(splat (lvar %1))'
365
+
366
+ # @!method extract_forwarded_kwrest_arg(node, kwrest_name)
367
+ def_node_matcher :extract_forwarded_kwrest_arg, '(hash <$(kwsplat (lvar %1)) ...>)'
368
+
369
+ # @!method forwarded_block_arg?(node, block_name)
370
+ def_node_matcher :forwarded_block_arg?, '(block_pass {(lvar %1) nil?})'
371
+
372
+ def initialize(def_node, send_node, referenced_lvars, forwardable_args, **config)
373
+ @def_node = def_node
374
+ @send_node = send_node
375
+ @referenced_lvars = referenced_lvars
376
+ @rest_arg, @kwrest_arg, @block_arg = *forwardable_args
377
+ @rest_arg_name, @kwrest_arg_name, @block_arg_name =
378
+ *forwardable_args.map { |a| a&.name }
379
+ @config = config
380
+ end
381
+
382
+ def forwarded_rest_arg
383
+ return nil if referenced_rest_arg?
384
+
385
+ arguments.find { |arg| forwarded_rest_arg?(arg, @rest_arg_name) }
386
+ end
387
+
388
+ def forwarded_kwrest_arg
389
+ return nil if referenced_kwrest_arg?
390
+
391
+ arguments.filter_map { |arg| extract_forwarded_kwrest_arg(arg, @kwrest_arg_name) }.first
392
+ end
393
+
394
+ def forwarded_block_arg
395
+ return nil if referenced_block_arg?
396
+
397
+ arguments.find { |arg| forwarded_block_arg?(arg, @block_arg_name) }
398
+ end
399
+
400
+ def classification
401
+ return nil unless forwarded_rest_arg || forwarded_kwrest_arg || forwarded_block_arg
402
+
403
+ if can_forward_all?
404
+ :all
405
+ else
406
+ :rest_or_kwrest
407
+ end
408
+ end
409
+
410
+ private
411
+
412
+ def can_forward_all?
413
+ return false if any_arg_referenced?
414
+ return false if ruby_32_missing_rest_or_kwest?
415
+ return false unless offensive_block_forwarding?
416
+ return false if additional_kwargs_or_forwarded_kwargs?
417
+
418
+ no_additional_args? || (target_ruby_version >= 3.0 && no_post_splat_args?)
419
+ end
420
+
421
+ def ruby_32_missing_rest_or_kwest?
422
+ target_ruby_version >= 3.2 && !forwarded_rest_and_kwrest_args
423
+ end
424
+
425
+ def offensive_block_forwarding?
426
+ @block_arg ? forwarded_block_arg : allow_offense_for_no_block?
427
+ end
428
+
429
+ def forwarded_rest_and_kwrest_args
430
+ forwarded_rest_arg && forwarded_kwrest_arg
431
+ end
432
+
433
+ def arguments
434
+ @send_node.arguments
435
+ end
436
+
437
+ def referenced_rest_arg?
438
+ @referenced_lvars.include?(@rest_arg_name)
439
+ end
440
+
441
+ def referenced_kwrest_arg?
442
+ @referenced_lvars.include?(@kwrest_arg_name)
443
+ end
444
+
445
+ def referenced_block_arg?
446
+ @referenced_lvars.include?(@block_arg_name)
447
+ end
448
+
449
+ def any_arg_referenced?
450
+ referenced_rest_arg? || referenced_kwrest_arg? || referenced_block_arg?
451
+ end
452
+
453
+ def target_ruby_version
454
+ @config.fetch(:target_ruby_version)
455
+ end
456
+
457
+ def no_post_splat_args?
458
+ return true unless (splat_index = arguments.index(forwarded_rest_arg))
459
+
460
+ arg_after_splat = arguments[splat_index + 1]
461
+ [nil, :hash, :block_pass].include?(arg_after_splat&.type)
462
+ end
463
+
464
+ def additional_kwargs_or_forwarded_kwargs?
465
+ additional_kwargs? || forward_additional_kwargs?
466
+ end
467
+
468
+ def additional_kwargs?
469
+ @def_node.arguments.any? { |a| a.kwarg_type? || a.kwoptarg_type? }
470
+ end
471
+
472
+ def forward_additional_kwargs?
473
+ return false unless forwarded_kwrest_arg
474
+
475
+ !forwarded_kwrest_arg.parent.children.one?
476
+ end
477
+
478
+ def allow_offense_for_no_block?
479
+ !@config.fetch(:allow_only_rest_arguments)
480
+ end
481
+
482
+ def no_additional_args?
483
+ forwardable_count = [@rest_arg, @kwrest_arg, @block_arg].compact.size
484
+
485
+ return false if missing_rest_arg_or_kwrest_arg?
486
+
487
+ @def_node.arguments.size == forwardable_count &&
488
+ @send_node.arguments.size == forwardable_count
489
+ end
490
+
491
+ def missing_rest_arg_or_kwrest_arg?
492
+ (@rest_arg_name && !forwarded_rest_arg) ||
493
+ (@kwrest_arg_name && !forwarded_kwrest_arg)
494
+ end
495
+ end
496
+
497
+ def explicit_block_name?
498
+ block_forwarding_config = config.for_cop('Naming/BlockForwarding')
499
+ return false unless block_forwarding_config['Enabled']
500
+
501
+ block_forwarding_config['EnforcedStyle'] == 'explicit'
502
+ end
151
503
  end
152
504
  end
153
505
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Identifies usages of `arr[0]` and `arr[-1]` and suggests to change
7
+ # them to use `arr.first` and `arr.last` instead.
8
+ #
9
+ # The cop is disabled by default due to safety concerns.
10
+ #
11
+ # @safety
12
+ # This cop is unsafe because `[0]` or `[-1]` can be called on a Hash,
13
+ # which returns a value for `0` or `-1` key, but changing these to use
14
+ # `.first` or `.last` will return first/last tuple instead. Also, String
15
+ # does not implement `first`/`last` methods.
16
+ #
17
+ # @example
18
+ # # bad
19
+ # arr[0]
20
+ # arr[-1]
21
+ #
22
+ # # good
23
+ # arr.first
24
+ # arr.last
25
+ # arr[0] = 2
26
+ # arr[0][-2]
27
+ #
28
+ class ArrayFirstLast < Base
29
+ extend AutoCorrector
30
+
31
+ MSG = 'Use `%<preferred>s`.'
32
+ RESTRICT_ON_SEND = %i[[]].freeze
33
+
34
+ # rubocop:disable Metrics/AbcSize
35
+ def on_send(node)
36
+ return unless node.arguments.size == 1 && node.first_argument.int_type?
37
+
38
+ value = node.first_argument.value
39
+ return unless [0, -1].include?(value)
40
+
41
+ node = innermost_braces_node(node)
42
+ return if node.parent && brace_method?(node.parent)
43
+
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}")
47
+ end
48
+ end
49
+ # rubocop:enable Metrics/AbcSize
50
+
51
+ private
52
+
53
+ def innermost_braces_node(node)
54
+ node = node.receiver while node.receiver.send_type? && node.receiver.method?(:[])
55
+ node
56
+ end
57
+
58
+ def brace_method?(node)
59
+ node.send_type? && (node.method?(:[]) || node.method?(:[]=))
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -11,8 +11,17 @@ module RuboCop
11
11
  # The `array1.intersect?(array2)` method is faster than
12
12
  # `(array1 & array2).any?` and is more readable.
13
13
  #
14
+ # In cases like the following, compatibility is not ensured,
15
+ # so it will not be detected when using block argument.
16
+ #
17
+ # [source,ruby]
18
+ # ----
19
+ # ([1] & [1,2]).any? { |x| false } # => false
20
+ # [1].intersect?([1,2]) { |x| false } # => true
21
+ # ----
22
+ #
14
23
  # @safety
15
- # This cop cannot guarantee that array1 and array2 are
24
+ # This cop cannot guarantee that `array1` and `array2` are
16
25
  # actually arrays while method `intersect?` is for arrays only.
17
26
  #
18
27
  # @example
@@ -68,16 +77,15 @@ module RuboCop
68
77
  RESTRICT_ON_SEND = (STRAIGHT_METHODS + NEGATED_METHODS).freeze
69
78
 
70
79
  def on_send(node)
80
+ return if (parent = node.parent) && (parent.block_type? || parent.numblock_type?)
71
81
  return unless (receiver, argument, method_name = bad_intersection_check?(node))
72
82
 
73
83
  message = message(receiver.source, argument.source, method_name)
74
84
 
75
85
  add_offense(node, message: message) do |corrector|
76
- if straight?(method_name)
77
- corrector.replace(node, "#{receiver.source}.intersect?(#{argument.source})")
78
- else
79
- corrector.replace(node, "!#{receiver.source}.intersect?(#{argument.source})")
80
- end
86
+ bang = straight?(method_name) ? '' : '!'
87
+
88
+ corrector.replace(node, "#{bang}#{receiver.source}.intersect?(#{argument.source})")
81
89
  end
82
90
  end
83
91
 
@@ -30,7 +30,7 @@ module RuboCop
30
30
  private
31
31
 
32
32
  def first_offense_range(comment)
33
- expression = comment.loc.expression
33
+ expression = comment.source_range
34
34
  first_offense = first_non_ascii_chars(comment.text)
35
35
 
36
36
  start_position = expression.begin_pos + comment.text.index(first_offense)
@@ -24,7 +24,7 @@ module RuboCop
24
24
  def on_send(node)
25
25
  return unless node.command?(:attr) && node.arguments?
26
26
  # check only for method definitions in class/module body
27
- return if node.parent && !node.parent.class_type? && !class_eval?(node.parent)
27
+ return if allowed_context?(node)
28
28
 
29
29
  message = message(node)
30
30
  add_offense(node.loc.selector, message: message) do |corrector|
@@ -34,6 +34,16 @@ module RuboCop
34
34
 
35
35
  private
36
36
 
37
+ def allowed_context?(node)
38
+ return false unless (class_node = node.each_ancestor(:class, :block).first)
39
+
40
+ (!class_node.class_type? && !class_eval?(class_node)) || define_attr_method?(class_node)
41
+ end
42
+
43
+ def define_attr_method?(node)
44
+ node.each_descendant(:def).any? { |def_node| def_node.method?(:attr) }
45
+ end
46
+
37
47
  def autocorrect(corrector, node)
38
48
  attr_name, setter = *node.arguments
39
49