rubocop 1.81.7 → 1.92.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (621) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +626 -111
  5. data/config/obsoletion.yml +39 -1
  6. data/exe/rubocop +1 -1
  7. data/lib/rubocop/cache_config.rb +29 -0
  8. data/lib/rubocop/cached_data.rb +50 -5
  9. data/lib/rubocop/changed_files.rb +134 -0
  10. data/lib/rubocop/cli/command/auto_generate_config.rb +34 -2
  11. data/lib/rubocop/cli/command/cop_names.rb +57 -0
  12. data/lib/rubocop/cli/command/execute_runner.rb +54 -3
  13. data/lib/rubocop/cli/command/explain.rb +34 -0
  14. data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
  15. data/lib/rubocop/cli/command/lsp.rb +1 -1
  16. data/lib/rubocop/cli/command/mcp.rb +19 -0
  17. data/lib/rubocop/cli/command/show_cops.rb +8 -2
  18. data/lib/rubocop/cli/command/show_docs_url.rb +8 -10
  19. data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
  20. data/lib/rubocop/cli.rb +41 -14
  21. data/lib/rubocop/comment_config/directive_range.rb +34 -0
  22. data/lib/rubocop/comment_config/disable_next.rb +143 -0
  23. data/lib/rubocop/comment_config/push_pop.rb +55 -0
  24. data/lib/rubocop/comment_config.rb +97 -44
  25. data/lib/rubocop/config.rb +100 -15
  26. data/lib/rubocop/config_finder.rb +1 -1
  27. data/lib/rubocop/config_loader.rb +49 -27
  28. data/lib/rubocop/config_loader_resolver.rb +95 -20
  29. data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
  30. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -2
  31. data/lib/rubocop/config_obsoletion/removed_cop.rb +9 -1
  32. data/lib/rubocop/config_obsoletion.rb +1 -1
  33. data/lib/rubocop/config_store.rb +2 -2
  34. data/lib/rubocop/config_validator.rb +69 -7
  35. data/lib/rubocop/cop/autocorrect_logic.rb +24 -6
  36. data/lib/rubocop/cop/badge.rb +10 -2
  37. data/lib/rubocop/cop/base.rb +128 -35
  38. data/lib/rubocop/cop/bundler/gem_comment.rb +5 -4
  39. data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
  40. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -10
  41. data/lib/rubocop/cop/bundler.rb +19 -0
  42. data/lib/rubocop/cop/commissioner.rb +13 -11
  43. data/lib/rubocop/cop/cop_documentation.rb +81 -0
  44. data/lib/rubocop/cop/cop_explanation.rb +140 -0
  45. data/lib/rubocop/cop/corrector.rb +4 -4
  46. data/lib/rubocop/cop/correctors/alignment_corrector.rb +87 -9
  47. data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
  48. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +37 -7
  49. data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
  50. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +31 -4
  51. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +35 -5
  52. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +8 -1
  53. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +70 -2
  54. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  55. data/lib/rubocop/cop/correctors.rb +28 -0
  56. data/lib/rubocop/cop/documentation.rb +3 -4
  57. data/lib/rubocop/cop/exclude_limit.rb +31 -5
  58. data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
  59. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  60. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +14 -4
  61. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -8
  62. data/lib/rubocop/cop/gemspec/require_mfa.rb +9 -6
  63. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +12 -7
  64. data/lib/rubocop/cop/gemspec.rb +22 -0
  65. data/lib/rubocop/cop/generator/registration_injector.rb +188 -0
  66. data/lib/rubocop/cop/generator.rb +5 -1
  67. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
  68. data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
  69. data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
  70. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
  71. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +12 -16
  72. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  73. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -2
  74. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +0 -7
  75. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  76. data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +1 -7
  77. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +5 -3
  78. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +1 -7
  79. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
  80. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  81. data/lib/rubocop/cop/layout/argument_alignment.rb +9 -3
  82. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  83. data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
  84. data/lib/rubocop/cop/layout/block_alignment.rb +84 -4
  85. data/lib/rubocop/cop/layout/case_indentation.rb +28 -10
  86. data/lib/rubocop/cop/layout/class_structure.rb +156 -41
  87. data/lib/rubocop/cop/layout/comment_indentation.rb +17 -7
  88. data/lib/rubocop/cop/layout/condition_position.rb +13 -3
  89. data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
  90. data/lib/rubocop/cop/layout/dot_position.rb +26 -16
  91. data/lib/rubocop/cop/layout/else_alignment.rb +2 -14
  92. data/lib/rubocop/cop/layout/empty_comment.rb +8 -10
  93. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +25 -7
  94. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +63 -5
  95. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +21 -8
  96. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +15 -2
  97. data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
  98. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +2 -2
  99. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +2 -0
  100. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +21 -5
  101. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +16 -2
  102. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
  103. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
  104. data/lib/rubocop/cop/layout/end_alignment.rb +23 -15
  105. data/lib/rubocop/cop/layout/extra_spacing.rb +109 -3
  106. data/lib/rubocop/cop/layout/first_argument_indentation.rb +81 -2
  107. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +18 -5
  108. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +41 -0
  109. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +36 -23
  110. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
  111. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +6 -0
  112. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
  113. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +11 -0
  114. data/lib/rubocop/cop/layout/hash_alignment.rb +16 -11
  115. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +8 -4
  116. data/lib/rubocop/cop/layout/heredoc_indentation.rb +48 -3
  117. data/lib/rubocop/cop/layout/indentation_consistency.rb +22 -5
  118. data/lib/rubocop/cop/layout/indentation_style.rb +5 -2
  119. data/lib/rubocop/cop/layout/indentation_width.rb +158 -12
  120. data/lib/rubocop/cop/layout/leading_comment_space.rb +27 -0
  121. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +10 -4
  122. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
  123. data/lib/rubocop/cop/layout/line_length.rb +265 -29
  124. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +69 -57
  125. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +8 -2
  126. data/lib/rubocop/cop/layout/multiline_block_layout.rb +10 -1
  127. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +65 -56
  128. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +7 -1
  129. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +268 -38
  130. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
  131. data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
  132. data/lib/rubocop/cop/layout/redundant_line_break.rb +102 -2
  133. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +19 -5
  134. data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
  135. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  136. data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
  137. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  138. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +10 -4
  139. data/lib/rubocop/cop/layout/space_around_keyword.rb +14 -2
  140. data/lib/rubocop/cop/layout/space_around_operators.rb +18 -3
  141. data/lib/rubocop/cop/layout/space_before_block_braces.rb +4 -1
  142. data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -1
  143. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
  144. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +44 -34
  145. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +31 -8
  146. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +2 -12
  147. data/lib/rubocop/cop/layout.rb +114 -0
  148. data/lib/rubocop/cop/lazy_loader.rb +41 -0
  149. data/lib/rubocop/cop/lint/ambiguous_assignment.rb +9 -17
  150. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +72 -1
  151. data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
  152. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +3 -11
  153. data/lib/rubocop/cop/lint/ambiguous_range.rb +1 -2
  154. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +6 -1
  155. data/lib/rubocop/cop/lint/argument_mismatch.rb +99 -0
  156. data/lib/rubocop/cop/lint/assignment_in_condition.rb +15 -1
  157. data/lib/rubocop/cop/lint/circular_argument_reference.rb +45 -3
  158. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
  159. data/lib/rubocop/cop/lint/constant_reassignment.rb +94 -15
  160. data/lib/rubocop/cop/lint/constant_resolution.rb +31 -6
  161. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +165 -15
  162. data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
  163. data/lib/rubocop/cop/lint/debugger.rb +13 -2
  164. data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
  165. data/lib/rubocop/cop/lint/deprecated_reference.rb +194 -0
  166. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  167. data/lib/rubocop/cop/lint/duplicate_methods.rb +405 -28
  168. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  169. data/lib/rubocop/cop/lint/empty_block.rb +4 -4
  170. data/lib/rubocop/cop/lint/empty_conditional_body.rb +9 -2
  171. data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
  172. data/lib/rubocop/cop/lint/empty_when.rb +8 -1
  173. data/lib/rubocop/cop/lint/ensure_return.rb +19 -1
  174. data/lib/rubocop/cop/lint/erb_new_arguments.rb +4 -2
  175. data/lib/rubocop/cop/lint/float_comparison.rb +2 -1
  176. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +4 -0
  177. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -2
  178. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -1
  179. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -2
  180. data/lib/rubocop/cop/lint/inherit_exception.rb +53 -7
  181. data/lib/rubocop/cop/lint/interpolation_check.rb +25 -6
  182. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  183. data/lib/rubocop/cop/lint/literal_as_condition.rb +36 -9
  184. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
  185. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +75 -37
  186. data/lib/rubocop/cop/lint/loop.rb +24 -2
  187. data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +245 -0
  188. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +46 -18
  189. data/lib/rubocop/cop/lint/missing_super.rb +31 -1
  190. data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
  191. data/lib/rubocop/cop/lint/name_typo.rb +270 -0
  192. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  193. data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
  194. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +20 -0
  195. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +4 -2
  196. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  197. data/lib/rubocop/cop/lint/number_conversion.rb +22 -11
  198. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  199. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +10 -0
  200. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +7 -7
  201. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +15 -4
  202. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +20 -14
  203. data/lib/rubocop/cop/lint/raise_exception.rb +1 -1
  204. data/lib/rubocop/cop/lint/rand_one.rb +1 -1
  205. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +160 -39
  206. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +53 -19
  207. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +28 -6
  208. data/lib/rubocop/cop/lint/redundant_require_statement.rb +5 -4
  209. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +37 -14
  210. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +13 -4
  211. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +11 -5
  212. data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -3
  213. data/lib/rubocop/cop/lint/redundant_with_object.rb +5 -0
  214. data/lib/rubocop/cop/lint/refinement_import_methods.rb +8 -1
  215. data/lib/rubocop/cop/lint/regexp_as_condition.rb +9 -1
  216. data/lib/rubocop/cop/lint/require_parentheses.rb +13 -4
  217. data/lib/rubocop/cop/lint/require_range_parentheses.rb +2 -1
  218. data/lib/rubocop/cop/lint/require_relative_self_path.rb +7 -5
  219. data/lib/rubocop/cop/lint/rescue_type.rb +1 -1
  220. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +24 -0
  221. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +56 -6
  222. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
  223. data/lib/rubocop/cop/lint/script_permission.rb +5 -1
  224. data/lib/rubocop/cop/lint/self_assignment.rb +33 -2
  225. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -1
  226. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  227. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +14 -0
  228. data/lib/rubocop/cop/lint/shared_mutable_default.rb +3 -1
  229. data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
  230. data/lib/rubocop/cop/lint/super_argument_mismatch.rb +179 -0
  231. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +13 -2
  232. data/lib/rubocop/cop/lint/symbol_conversion.rb +22 -4
  233. data/lib/rubocop/cop/lint/syntax.rb +25 -1
  234. data/lib/rubocop/cop/lint/to_enum_arguments.rb +72 -4
  235. data/lib/rubocop/cop/lint/to_json.rb +20 -17
  236. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  237. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +5 -1
  238. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +54 -11
  239. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
  240. data/lib/rubocop/cop/lint/unreachable_code.rb +15 -9
  241. data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
  242. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  243. data/lib/rubocop/cop/lint/unused_private_method.rb +234 -0
  244. data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -2
  245. data/lib/rubocop/cop/lint/useless_assignment.rb +61 -27
  246. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +40 -4
  247. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +2 -0
  248. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  249. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +10 -10
  250. data/lib/rubocop/cop/lint/useless_or.rb +15 -2
  251. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -2
  252. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +10 -4
  253. data/lib/rubocop/cop/lint/useless_setter_call.rb +11 -5
  254. data/lib/rubocop/cop/lint/useless_times.rb +22 -1
  255. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +94 -14
  256. data/lib/rubocop/cop/lint/void.rb +59 -22
  257. data/lib/rubocop/cop/lint.rb +179 -0
  258. data/lib/rubocop/cop/metrics/block_length.rb +1 -1
  259. data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
  260. data/lib/rubocop/cop/metrics/class_length.rb +4 -2
  261. data/lib/rubocop/cop/metrics/collection_literal_length.rb +1 -1
  262. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
  263. data/lib/rubocop/cop/metrics/method_length.rb +2 -2
  264. data/lib/rubocop/cop/metrics/module_length.rb +4 -2
  265. data/lib/rubocop/cop/metrics/perceived_complexity.rb +37 -7
  266. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  267. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  268. data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
  269. data/lib/rubocop/cop/metrics.rb +31 -0
  270. data/lib/rubocop/cop/migration/department_name.rb +11 -5
  271. data/lib/rubocop/cop/migration.rb +13 -0
  272. data/lib/rubocop/cop/mixin/alignment.rb +5 -1
  273. data/lib/rubocop/cop/mixin/allowed_methods.rb +5 -5
  274. data/lib/rubocop/cop/mixin/allowed_pattern.rb +5 -1
  275. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  276. data/lib/rubocop/cop/mixin/check_line_breakable.rb +47 -25
  277. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +12 -8
  278. data/lib/rubocop/cop/mixin/code_length.rb +10 -2
  279. data/lib/rubocop/cop/mixin/comments_help.rb +1 -2
  280. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -2
  281. data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
  282. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -1
  283. data/lib/rubocop/cop/mixin/endless_method_body_help.rb +105 -0
  284. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +13 -5
  285. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +2 -2
  286. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +5 -1
  287. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +58 -12
  288. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +37 -10
  289. data/lib/rubocop/cop/mixin/hash_subset.rb +9 -2
  290. data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
  291. data/lib/rubocop/cop/mixin/hash_transform_method.rb +14 -60
  292. data/lib/rubocop/cop/mixin/indexed_method_arity.rb +94 -0
  293. data/lib/rubocop/cop/mixin/line_length_help.rb +28 -3
  294. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  295. data/lib/rubocop/cop/mixin/min_branches_count.rb +3 -1
  296. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
  297. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  298. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +10 -1
  299. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  300. data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
  301. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +79 -8
  302. data/lib/rubocop/cop/mixin/project_index_help.rb +203 -0
  303. data/lib/rubocop/cop/mixin/range_help.rb +1 -2
  304. data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +181 -0
  305. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  306. data/lib/rubocop/cop/mixin/statement_modifier.rb +69 -12
  307. data/lib/rubocop/cop/mixin/trailing_comma.rb +7 -6
  308. data/lib/rubocop/cop/mixin/visibility_help.rb +2 -1
  309. data/lib/rubocop/cop/mixin.rb +93 -0
  310. data/lib/rubocop/cop/naming/accessor_method_name.rb +8 -0
  311. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +17 -1
  312. data/lib/rubocop/cop/naming/block_forwarding.rb +4 -1
  313. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  314. data/lib/rubocop/cop/naming/file_name.rb +4 -3
  315. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +9 -2
  316. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
  317. data/lib/rubocop/cop/naming/inclusive_language.rb +8 -2
  318. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +12 -5
  319. data/lib/rubocop/cop/naming/method_name.rb +6 -3
  320. data/lib/rubocop/cop/naming/predicate_method.rb +13 -2
  321. data/lib/rubocop/cop/naming/predicate_prefix.rb +30 -17
  322. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +12 -7
  323. data/lib/rubocop/cop/naming/variable_number.rb +3 -1
  324. data/lib/rubocop/cop/naming.rb +31 -0
  325. data/lib/rubocop/cop/offense.rb +108 -9
  326. data/lib/rubocop/cop/registry.rb +232 -66
  327. data/lib/rubocop/cop/security/eval.rb +15 -2
  328. data/lib/rubocop/cop/security/io_methods.rb +2 -2
  329. data/lib/rubocop/cop/security/json_load.rb +16 -4
  330. data/lib/rubocop/cop/security/marshal_load.rb +1 -1
  331. data/lib/rubocop/cop/security.rb +19 -0
  332. data/lib/rubocop/cop/severity.rb +12 -0
  333. data/lib/rubocop/cop/style/access_modifier_declarations.rb +55 -8
  334. data/lib/rubocop/cop/style/accessor_grouping.rb +16 -5
  335. data/lib/rubocop/cop/style/alias.rb +33 -8
  336. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
  337. data/lib/rubocop/cop/style/and_or.rb +8 -3
  338. data/lib/rubocop/cop/style/arguments_forwarding.rb +61 -17
  339. data/lib/rubocop/cop/style/array_first_last.rb +13 -3
  340. data/lib/rubocop/cop/style/array_intersect.rb +28 -5
  341. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +3 -0
  342. data/lib/rubocop/cop/style/array_join.rb +4 -2
  343. data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
  344. data/lib/rubocop/cop/style/attr.rb +8 -6
  345. data/lib/rubocop/cop/style/bare_percent_literals.rb +4 -3
  346. data/lib/rubocop/cop/style/begin_block.rb +3 -1
  347. data/lib/rubocop/cop/style/bitwise_predicate.rb +7 -6
  348. data/lib/rubocop/cop/style/block_delimiters.rb +74 -38
  349. data/lib/rubocop/cop/style/case_equality.rb +29 -15
  350. data/lib/rubocop/cop/style/case_like_if.rb +11 -10
  351. data/lib/rubocop/cop/style/character_literal.rb +2 -2
  352. data/lib/rubocop/cop/style/class_and_module_children.rb +151 -35
  353. data/lib/rubocop/cop/style/class_equality_comparison.rb +21 -13
  354. data/lib/rubocop/cop/style/class_methods_definitions.rb +26 -5
  355. data/lib/rubocop/cop/style/collection_compact.rb +37 -17
  356. data/lib/rubocop/cop/style/collection_querying.rb +79 -46
  357. data/lib/rubocop/cop/style/colon_method_call.rb +16 -7
  358. data/lib/rubocop/cop/style/combinable_loops.rb +91 -9
  359. data/lib/rubocop/cop/style/comparable_clamp.rb +12 -1
  360. data/lib/rubocop/cop/style/concat_array_literals.rb +65 -9
  361. data/lib/rubocop/cop/style/conditional_assignment.rb +34 -18
  362. data/lib/rubocop/cop/style/constant_visibility.rb +13 -7
  363. data/lib/rubocop/cop/style/copyright.rb +27 -12
  364. data/lib/rubocop/cop/style/data_inheritance.rb +18 -0
  365. data/lib/rubocop/cop/style/date_time.rb +4 -4
  366. data/lib/rubocop/cop/style/def_with_parentheses.rb +6 -2
  367. data/lib/rubocop/cop/style/dig_chain.rb +5 -0
  368. data/lib/rubocop/cop/style/dir_empty.rb +4 -0
  369. data/lib/rubocop/cop/style/directive_scope.rb +304 -0
  370. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +184 -20
  371. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
  372. data/lib/rubocop/cop/style/documentation.rb +53 -6
  373. data/lib/rubocop/cop/style/documentation_method.rb +8 -12
  374. data/lib/rubocop/cop/style/double_negation.rb +11 -0
  375. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  376. data/lib/rubocop/cop/style/each_with_object.rb +2 -0
  377. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  378. data/lib/rubocop/cop/style/empty_case_condition.rb +13 -4
  379. data/lib/rubocop/cop/style/empty_class_definition.rb +126 -0
  380. data/lib/rubocop/cop/style/empty_heredoc.rb +4 -0
  381. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  382. data/lib/rubocop/cop/style/empty_literal.rb +8 -3
  383. data/lib/rubocop/cop/style/empty_method.rb +15 -9
  384. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +74 -22
  385. data/lib/rubocop/cop/style/encoding.rb +7 -1
  386. data/lib/rubocop/cop/style/end_block.rb +3 -1
  387. data/lib/rubocop/cop/style/endless_method.rb +100 -21
  388. data/lib/rubocop/cop/style/env_home.rb +4 -0
  389. data/lib/rubocop/cop/style/even_odd.rb +11 -1
  390. data/lib/rubocop/cop/style/exact_regexp_match.rb +52 -8
  391. data/lib/rubocop/cop/style/explicit_block_argument.rb +50 -10
  392. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  393. data/lib/rubocop/cop/style/file_null.rb +6 -4
  394. data/lib/rubocop/cop/style/file_open.rb +84 -0
  395. data/lib/rubocop/cop/style/file_write.rb +21 -16
  396. data/lib/rubocop/cop/style/float_division.rb +28 -14
  397. data/lib/rubocop/cop/style/for.rb +60 -1
  398. data/lib/rubocop/cop/style/format_string.rb +44 -9
  399. data/lib/rubocop/cop/style/format_string_token.rb +50 -7
  400. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
  401. data/lib/rubocop/cop/style/global_vars.rb +5 -2
  402. data/lib/rubocop/cop/style/guard_clause.rb +57 -40
  403. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +31 -9
  404. data/lib/rubocop/cop/style/hash_conversion.rb +39 -11
  405. data/lib/rubocop/cop/style/hash_each_methods.rb +1 -2
  406. data/lib/rubocop/cop/style/hash_lookup_method.rb +128 -0
  407. data/lib/rubocop/cop/style/hash_slice.rb +16 -0
  408. data/lib/rubocop/cop/style/hash_syntax.rb +19 -5
  409. data/lib/rubocop/cop/style/hash_transform_keys.rb +17 -7
  410. data/lib/rubocop/cop/style/hash_transform_values.rb +17 -7
  411. data/lib/rubocop/cop/style/identical_conditional_branches.rb +38 -10
  412. data/lib/rubocop/cop/style/if_inside_else.rb +36 -8
  413. data/lib/rubocop/cop/style/if_unless_modifier.rb +80 -76
  414. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +17 -14
  415. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +4 -1
  416. data/lib/rubocop/cop/style/if_with_semicolon.rb +61 -8
  417. data/lib/rubocop/cop/style/inline_comment.rb +5 -2
  418. data/lib/rubocop/cop/style/inverse_methods.rb +24 -2
  419. data/lib/rubocop/cop/style/invertible_unless_condition.rb +25 -5
  420. data/lib/rubocop/cop/style/ip_addresses.rb +1 -2
  421. data/lib/rubocop/cop/style/it_block_parameter.rb +94 -4
  422. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +4 -0
  423. data/lib/rubocop/cop/style/keyword_parameters_order.rb +10 -4
  424. data/lib/rubocop/cop/style/lambda.rb +45 -2
  425. data/lib/rubocop/cop/style/lambda_call.rb +24 -8
  426. data/lib/rubocop/cop/style/magic_comment_format.rb +4 -4
  427. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +11 -0
  428. data/lib/rubocop/cop/style/map_into_array.rb +2 -3
  429. data/lib/rubocop/cop/style/map_join.rb +123 -0
  430. data/lib/rubocop/cop/style/map_to_hash.rb +1 -2
  431. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +102 -20
  432. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
  433. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +42 -6
  434. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +36 -8
  435. data/lib/rubocop/cop/style/method_def_parentheses.rb +36 -8
  436. data/lib/rubocop/cop/style/min_max_comparison.rb +4 -1
  437. data/lib/rubocop/cop/style/missing_else.rb +7 -1
  438. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +40 -7
  439. data/lib/rubocop/cop/style/mixin_grouping.rb +12 -3
  440. data/lib/rubocop/cop/style/mixin_usage.rb +1 -1
  441. data/lib/rubocop/cop/style/module_function.rb +4 -2
  442. data/lib/rubocop/cop/style/module_member_existence_check.rb +110 -0
  443. data/lib/rubocop/cop/style/multiline_if_modifier.rb +45 -5
  444. data/lib/rubocop/cop/style/multiline_if_then.rb +10 -4
  445. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
  446. data/lib/rubocop/cop/style/multiline_memoization.rb +7 -1
  447. data/lib/rubocop/cop/style/multiline_method_signature.rb +14 -13
  448. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
  449. data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
  450. data/lib/rubocop/cop/style/multiple_comparison.rb +33 -22
  451. data/lib/rubocop/cop/style/mutable_constant.rb +158 -14
  452. data/lib/rubocop/cop/style/negated_if_else_condition.rb +3 -3
  453. data/lib/rubocop/cop/style/negative_array_index.rb +228 -0
  454. data/lib/rubocop/cop/style/nested_modifier.rb +36 -12
  455. data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
  456. data/lib/rubocop/cop/style/next.rb +24 -10
  457. data/lib/rubocop/cop/style/nil_comparison.rb +50 -12
  458. data/lib/rubocop/cop/style/nil_lambda.rb +9 -1
  459. data/lib/rubocop/cop/style/non_nil_check.rb +21 -11
  460. data/lib/rubocop/cop/style/not.rb +12 -3
  461. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
  462. data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
  463. data/lib/rubocop/cop/style/numeric_predicate.rb +22 -6
  464. data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
  465. data/lib/rubocop/cop/style/one_line_conditional.rb +18 -6
  466. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  467. data/lib/rubocop/cop/style/operator_method_call.rb +10 -2
  468. data/lib/rubocop/cop/style/option_hash.rb +1 -1
  469. data/lib/rubocop/cop/style/optional_arguments.rb +1 -0
  470. data/lib/rubocop/cop/style/parallel_assignment.rb +26 -7
  471. data/lib/rubocop/cop/style/parentheses_around_condition.rb +7 -2
  472. data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
  473. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +18 -3
  474. data/lib/rubocop/cop/style/perl_backrefs.rb +5 -3
  475. data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
  476. data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
  477. data/lib/rubocop/cop/style/proc.rb +3 -2
  478. data/lib/rubocop/cop/style/raise_args.rb +20 -10
  479. data/lib/rubocop/cop/style/reduce_to_hash.rb +216 -0
  480. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  481. data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
  482. data/lib/rubocop/cop/style/redundant_assignment.rb +12 -2
  483. data/lib/rubocop/cop/style/redundant_begin.rb +25 -7
  484. data/lib/rubocop/cop/style/redundant_condition.rb +41 -23
  485. data/lib/rubocop/cop/style/redundant_constant_base.rb +42 -6
  486. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +13 -1
  487. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +17 -3
  488. data/lib/rubocop/cop/style/redundant_each.rb +4 -5
  489. data/lib/rubocop/cop/style/redundant_exception.rb +21 -3
  490. data/lib/rubocop/cop/style/redundant_fetch_block.rb +10 -2
  491. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +9 -0
  492. data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
  493. data/lib/rubocop/cop/style/redundant_format.rb +43 -7
  494. data/lib/rubocop/cop/style/redundant_freeze.rb +11 -3
  495. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +6 -1
  496. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +49 -10
  497. data/lib/rubocop/cop/style/redundant_line_continuation.rb +82 -115
  498. data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
  499. data/lib/rubocop/cop/style/redundant_parentheses.rb +105 -83
  500. data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
  501. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +13 -2
  502. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
  503. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +27 -7
  504. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +12 -4
  505. data/lib/rubocop/cop/style/redundant_return.rb +4 -3
  506. data/lib/rubocop/cop/style/redundant_self.rb +11 -2
  507. data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -2
  508. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +27 -4
  509. data/lib/rubocop/cop/style/redundant_sort.rb +45 -11
  510. data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -2
  511. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +133 -0
  512. data/lib/rubocop/cop/style/regexp_literal.rb +106 -28
  513. data/lib/rubocop/cop/style/require_order.rb +25 -8
  514. data/lib/rubocop/cop/style/rescue_modifier.rb +15 -14
  515. data/lib/rubocop/cop/style/return_nil.rb +17 -2
  516. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
  517. data/lib/rubocop/cop/style/reverse_find.rb +51 -0
  518. data/lib/rubocop/cop/style/safe_navigation.rb +18 -9
  519. data/lib/rubocop/cop/style/sample.rb +19 -13
  520. data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
  521. data/lib/rubocop/cop/style/select_by_range.rb +197 -0
  522. data/lib/rubocop/cop/style/select_by_regexp.rb +52 -23
  523. data/lib/rubocop/cop/style/self_assignment.rb +13 -16
  524. data/lib/rubocop/cop/style/semicolon.rb +39 -13
  525. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +4 -0
  526. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  527. data/lib/rubocop/cop/style/single_line_do_end_block.rb +19 -7
  528. data/lib/rubocop/cop/style/single_line_methods.rb +24 -5
  529. data/lib/rubocop/cop/style/sole_nested_conditional.rb +25 -7
  530. data/lib/rubocop/cop/style/special_global_vars.rb +7 -2
  531. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +31 -5
  532. data/lib/rubocop/cop/style/static_class.rb +21 -0
  533. data/lib/rubocop/cop/style/string_concatenation.rb +25 -6
  534. data/lib/rubocop/cop/style/string_hash_keys.rb +1 -0
  535. data/lib/rubocop/cop/style/struct_inheritance.rb +36 -1
  536. data/lib/rubocop/cop/style/super_arguments.rb +6 -4
  537. data/lib/rubocop/cop/style/symbol_proc.rb +32 -14
  538. data/lib/rubocop/cop/style/tally_method.rb +181 -0
  539. data/lib/rubocop/cop/style/ternary_parentheses.rb +34 -1
  540. data/lib/rubocop/cop/style/time_now.rb +41 -0
  541. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -2
  542. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  543. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
  544. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +35 -32
  545. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  546. data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
  547. data/lib/rubocop/cop/style/while_until_do.rb +7 -0
  548. data/lib/rubocop/cop/style/while_until_modifier.rb +16 -0
  549. data/lib/rubocop/cop/style/word_array.rb +1 -0
  550. data/lib/rubocop/cop/style/yoda_condition.rb +26 -12
  551. data/lib/rubocop/cop/style/yoda_expression.rb +11 -2
  552. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -3
  553. data/lib/rubocop/cop/style.rb +311 -0
  554. data/lib/rubocop/cop/team.rb +171 -48
  555. data/lib/rubocop/cop/util.rb +5 -8
  556. data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
  557. data/lib/rubocop/cop/variable_force/branch.rb +30 -6
  558. data/lib/rubocop/cop/variable_force/variable.rb +33 -9
  559. data/lib/rubocop/cops_documentation_generator.rb +27 -9
  560. data/lib/rubocop/directive_comment.rb +116 -7
  561. data/lib/rubocop/feature_loader.rb +0 -6
  562. data/lib/rubocop/file_patterns.rb +9 -1
  563. data/lib/rubocop/formatter/base_formatter.rb +22 -0
  564. data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
  565. data/lib/rubocop/formatter/disabled_config_formatter.rb +39 -10
  566. data/lib/rubocop/formatter/emacs_style_formatter.rb +3 -1
  567. data/lib/rubocop/formatter/formatter_set.rb +7 -2
  568. data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
  569. data/lib/rubocop/formatter/html_formatter.rb +2 -4
  570. data/lib/rubocop/formatter/json_formatter.rb +82 -7
  571. data/lib/rubocop/formatter/junit_formatter.rb +27 -10
  572. data/lib/rubocop/formatter/offense_count_formatter.rb +4 -3
  573. data/lib/rubocop/formatter/pacman_formatter.rb +3 -1
  574. data/lib/rubocop/formatter/sarif_formatter.rb +186 -0
  575. data/lib/rubocop/formatter/simple_text_formatter.rb +4 -5
  576. data/lib/rubocop/formatter/tap_formatter.rb +8 -3
  577. data/lib/rubocop/formatter/worst_offenders_formatter.rb +5 -4
  578. data/lib/rubocop/formatter.rb +23 -21
  579. data/lib/rubocop/lockfile.rb +18 -0
  580. data/lib/rubocop/lsp/diagnostic.rb +22 -42
  581. data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
  582. data/lib/rubocop/lsp/routes.rb +130 -83
  583. data/lib/rubocop/lsp/runtime.rb +64 -15
  584. data/lib/rubocop/lsp/server.rb +6 -2
  585. data/lib/rubocop/lsp/stdin_runner.rb +35 -2
  586. data/lib/rubocop/lsp.rb +5 -2
  587. data/lib/rubocop/magic_comment.rb +47 -0
  588. data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
  589. data/lib/rubocop/mcp/explain_tool.rb +68 -0
  590. data/lib/rubocop/mcp/scope.rb +65 -0
  591. data/lib/rubocop/mcp/server.rb +307 -0
  592. data/lib/rubocop/mcp/source_files.rb +35 -0
  593. data/lib/rubocop/offense_limit.rb +30 -0
  594. data/lib/rubocop/options.rb +141 -13
  595. data/lib/rubocop/path_util.rb +16 -5
  596. data/lib/rubocop/pending_cops_reporter.rb +1 -6
  597. data/lib/rubocop/plugin/configuration_integrator.rb +13 -3
  598. data/lib/rubocop/plugin/loader.rb +2 -2
  599. data/lib/rubocop/project_index_loader.rb +82 -0
  600. data/lib/rubocop/rake_task.rb +2 -3
  601. data/lib/rubocop/remote_config.rb +18 -13
  602. data/lib/rubocop/result_cache.rb +102 -59
  603. data/lib/rubocop/rspec/cop_helper.rb +8 -0
  604. data/lib/rubocop/rspec/expect_offense.rb +2 -4
  605. data/lib/rubocop/rspec/shared_contexts.rb +53 -5
  606. data/lib/rubocop/rspec/support.rb +2 -1
  607. data/lib/rubocop/runner.rb +362 -106
  608. data/lib/rubocop/server/cache.rb +21 -40
  609. data/lib/rubocop/server/cli.rb +2 -4
  610. data/lib/rubocop/server/core.rb +8 -0
  611. data/lib/rubocop/server.rb +14 -0
  612. data/lib/rubocop/target_finder.rb +18 -8
  613. data/lib/rubocop/target_ruby.rb +42 -22
  614. data/lib/rubocop/todo_audit.rb +111 -0
  615. data/lib/rubocop/unified_diff.rb +257 -0
  616. data/lib/rubocop/util.rb +69 -0
  617. data/lib/rubocop/version.rb +23 -7
  618. data/lib/rubocop.rb +34 -701
  619. data/lib/ruby_lsp/rubocop/addon.rb +1 -2
  620. metadata +80 -14
  621. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
@@ -76,6 +76,9 @@ module RuboCop
76
76
 
77
77
  def on_super(super_node)
78
78
  return unless (def_node = find_def_node(super_node))
79
+ # Zsuper passes a destructured argument as the original value, while
80
+ # `argument_list` flattens it into its parts.
81
+ return if def_node.arguments.any?(&:mlhs_type?)
79
82
 
80
83
  def_node_args = def_node.arguments.argument_list
81
84
  super_args = preprocess_super_args(super_node.arguments)
@@ -103,13 +106,13 @@ module RuboCop
103
106
  end
104
107
  end
105
108
 
106
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
109
+ # rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
107
110
  def arguments_identical?(def_node, super_node, def_args, super_args)
108
111
  return false if argument_list_size_differs?(def_args, super_args, super_node)
109
112
 
110
113
  def_args.zip(super_args).each do |def_arg, super_arg|
111
114
  next if positional_arg_same?(def_arg, super_arg)
112
- next if positional_rest_arg_same(def_arg, super_arg)
115
+ next if positional_rest_arg_same?(def_arg, super_arg)
113
116
  next if keyword_arg_same?(def_arg, super_arg)
114
117
  next if keyword_rest_arg_same?(def_arg, super_arg)
115
118
  next if block_arg_same?(def_node, super_node, def_arg, super_arg)
@@ -120,7 +123,6 @@ module RuboCop
120
123
 
121
124
  true
122
125
  end
123
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
124
126
 
125
127
  def argument_list_size_differs?(def_args, super_args, super_node)
126
128
  # If the def node has a block argument and the super node has an explicit block,
@@ -147,7 +149,7 @@ module RuboCop
147
149
  def_arg.name == super_arg.children.first
148
150
  end
149
151
 
150
- def positional_rest_arg_same(def_arg, super_arg)
152
+ def positional_rest_arg_same?(def_arg, super_arg)
151
153
  return false unless def_arg.restarg_type?
152
154
  # anonymous forwarding
153
155
  return true if def_arg.name.nil? && super_arg.forwarded_restarg_type?
@@ -142,9 +142,11 @@ module RuboCop
142
142
  include RangeHelp
143
143
  include AllowedMethods
144
144
  include AllowedPattern
145
+ include PatternMatchingHelp
145
146
  extend AutoCorrector
146
147
 
147
148
  MSG = 'Pass `&:%<method>s` as an argument to `%<block_method>s` instead of a block.'
149
+ MSG_LAMBDA_LITERAL = 'Use `lambda(&:%<method>s)` instead of %<original>s.'
148
150
  SUPER_TYPES = %i[super zsuper].freeze
149
151
  LAMBDA_OR_PROC = %i[lambda proc].freeze
150
152
 
@@ -164,27 +166,28 @@ module RuboCop
164
166
  PATTERN
165
167
 
166
168
  def self.autocorrect_incompatible_with
167
- [Layout::SpaceBeforeBlockBraces]
169
+ [Layout::SpaceBeforeBlockBraces, Style::TrailingCommaInArguments]
168
170
  end
169
171
 
170
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
172
+ # rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
171
173
  def on_block(node)
172
174
  symbol_proc?(node) do |dispatch_node, arguments_node, method_name|
173
175
  if active_support_extensions_enabled?
174
176
  return if proc_node?(dispatch_node)
175
177
  return if LAMBDA_OR_PROC.include?(dispatch_node.method_name)
176
178
  end
179
+ # A pattern accepts a lambda literal, but not `lambda(&:foo)`.
180
+ return if in_pattern?(node)
177
181
  return if unsafe_hash_usage?(dispatch_node)
178
182
  return if unsafe_array_usage?(dispatch_node)
179
183
  return if allowed_method_name?(dispatch_node.method_name)
180
184
  return if allow_if_method_has_argument?(node.send_node)
181
185
  return if node.block_type? && destructuring_block_argument?(arguments_node)
182
- return if allow_comments? && contains_comments?(node)
186
+ return if allow_comments?(node)
183
187
 
184
188
  register_offense(node, method_name, dispatch_node.method_name)
185
189
  end
186
190
  end
187
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
188
191
  alias on_numblock on_block
189
192
  alias on_itblock on_block
190
193
 
@@ -208,12 +211,26 @@ module RuboCop
208
211
  end
209
212
 
210
213
  def register_offense(node, method_name, block_method_name)
211
- block_start = node.loc.begin.begin_pos
212
- block_end = node.loc.end.end_pos
213
- range = range_between(block_start, block_end)
214
- message = format(MSG, method: method_name, block_method: block_method_name)
214
+ range = if node.send_node.lambda_literal?
215
+ node.source_range
216
+ else
217
+ node.loc.begin.begin.join(node.loc.end.end)
218
+ end
219
+ message = message(node, method_name, block_method_name)
215
220
 
216
- add_offense(range, message: message) { |corrector| autocorrect(corrector, node) }
221
+ add_offense(range, message: message) do |corrector|
222
+ autocorrect(corrector, node)
223
+ end
224
+ end
225
+
226
+ def message(node, method_name, block_method_name)
227
+ if node.send_node.lambda_literal?
228
+ original = node.single_line? ? "`#{node.source}`" : 'a lambda literal with a block'
229
+
230
+ format(MSG_LAMBDA_LITERAL, method: method_name, original: original)
231
+ else
232
+ format(MSG, method: method_name, block_method: block_method_name)
233
+ end
217
234
  end
218
235
 
219
236
  def autocorrect(corrector, node)
@@ -260,10 +277,10 @@ module RuboCop
260
277
  end
261
278
 
262
279
  def begin_pos_for_replacement(node)
263
- expr = node.send_node.source_range
280
+ send_node = node.send_node
264
281
 
265
- if (paren_pos = (expr.source =~ /\(\s*\)$/))
266
- expr.begin_pos + paren_pos
282
+ if send_node.parenthesized? && send_node.arguments.empty?
283
+ send_node.loc.begin.begin_pos
267
284
  else
268
285
  node.loc.begin.begin_pos
269
286
  end
@@ -273,8 +290,9 @@ module RuboCop
273
290
  !!cop_config.fetch('AllowMethodsWithArguments', false) && send_node.arguments.any?
274
291
  end
275
292
 
276
- def allow_comments?
277
- cop_config.fetch('AllowComments', false)
293
+ def allow_comments?(node)
294
+ cop_config.fetch('AllowComments', false) && contains_comments?(node) &&
295
+ !comments_contain_disables?(node, name)
278
296
  end
279
297
  end
280
298
  end
@@ -0,0 +1,181 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for manual counting patterns that can be replaced by `Enumerable#tally`.
7
+ #
8
+ # The cop detects the following patterns:
9
+ #
10
+ # - `each_with_object(Hash.new(0)) { |item, counts| counts[item] += 1 }`
11
+ # - `group_by(&:itself).transform_values(&:count)`
12
+ # - `group_by { |x| x }.transform_values(&:size)`
13
+ # - `group_by { |x| x }.transform_values { |v| v.length }`
14
+ #
15
+ # @safety
16
+ # This cop is unsafe because it cannot guarantee that the receiver
17
+ # is an `Enumerable` by static analysis, so the correction may
18
+ # not be actually equivalent.
19
+ #
20
+ # @example
21
+ # # bad
22
+ # array.each_with_object(Hash.new(0)) { |item, counts| counts[item] += 1 }
23
+ #
24
+ # # bad
25
+ # array.group_by(&:itself).transform_values(&:count)
26
+ #
27
+ # # bad
28
+ # array.group_by { |item| item }.transform_values(&:size)
29
+ #
30
+ # # bad
31
+ # array.group_by { |item| item }.transform_values { |v| v.length }
32
+ #
33
+ # # good
34
+ # array.tally
35
+ #
36
+ class TallyMethod < Base
37
+ extend AutoCorrector
38
+ extend TargetRubyVersion
39
+ include RangeHelp
40
+
41
+ minimum_target_ruby_version 2.7
42
+
43
+ MSG_EACH_WITH_OBJECT = 'Use `tally` instead of `each_with_object`.'
44
+ MSG_GROUP_BY = 'Use `tally` instead of `group_by` and `transform_values`.'
45
+ RESTRICT_ON_SEND = %i[each_with_object transform_values].freeze
46
+ COUNTING_METHODS = %i[count size length].to_set.freeze
47
+
48
+ # Pattern 1: collection.each_with_object(Hash.new(0)) { |elem, hash| hash[elem] += 1 }
49
+ # @!method tally_each_with_object?(node)
50
+ def_node_matcher :tally_each_with_object?, <<~PATTERN
51
+ {
52
+ (block
53
+ (call _ :each_with_object
54
+ (send (const {nil? cbase} :Hash) :new (int 0)))
55
+ (args (arg _elem) (arg _hash))
56
+ (op_asgn
57
+ (send (lvar _hash) :[] (lvar _elem)) :+ (int 1)))
58
+ (numblock
59
+ (call _ :each_with_object
60
+ (send (const {nil? cbase} :Hash) :new (int 0)))
61
+ 2
62
+ (op_asgn
63
+ (send (lvar :_2) :[] (lvar :_1)) :+ (int 1)))
64
+ }
65
+ PATTERN
66
+
67
+ # Pattern 2: collection.group_by(&:itself).transform_values(&:count/size/length)
68
+ # @!method tally_group_by_symbol?(node)
69
+ def_node_matcher :tally_group_by_symbol?, <<~PATTERN
70
+ (call
71
+ (call _ :group_by (block_pass (sym :itself)))
72
+ :transform_values
73
+ (block_pass (sym %COUNTING_METHODS)))
74
+ PATTERN
75
+
76
+ # Pattern 3: collection.group_by { |x| x }.transform_values(&:count/size/length)
77
+ # @!method tally_group_by_identity_block?(node)
78
+ def_node_matcher :tally_group_by_identity_block?, <<~PATTERN
79
+ (call
80
+ {
81
+ (block (call _ :group_by) (args (arg _x)) (lvar _x))
82
+ (numblock (call _ :group_by) 1 (lvar :_1))
83
+ (itblock (call _ :group_by) :it (lvar :it))
84
+ }
85
+ :transform_values
86
+ (block_pass (sym %COUNTING_METHODS)))
87
+ PATTERN
88
+
89
+ # Pattern 4: collection.group_by(&:itself).transform_values { |v| v.count/size/length }
90
+ # collection.group_by { |x| x }.transform_values { |v| v.count/size/length }
91
+ # @!method tally_group_by_transform_block?(node)
92
+ def_node_matcher :tally_group_by_transform_block?, <<~PATTERN
93
+ {
94
+ (block
95
+ (call
96
+ {
97
+ (call _ :group_by (block_pass (sym :itself)))
98
+ (block (call _ :group_by) (args (arg _x)) (lvar _x))
99
+ (numblock (call _ :group_by) 1 (lvar :_1))
100
+ (itblock (call _ :group_by) :it (lvar :it))
101
+ }
102
+ :transform_values)
103
+ (args (arg _v))
104
+ (send (lvar _v) %COUNTING_METHODS))
105
+ (numblock
106
+ (call
107
+ {
108
+ (call _ :group_by (block_pass (sym :itself)))
109
+ (block (call _ :group_by) (args (arg _x)) (lvar _x))
110
+ (numblock (call _ :group_by) 1 (lvar :_1))
111
+ (itblock (call _ :group_by) :it (lvar :it))
112
+ }
113
+ :transform_values)
114
+ 1
115
+ (send (lvar :_1) %COUNTING_METHODS))
116
+ (itblock
117
+ (call
118
+ {
119
+ (call _ :group_by (block_pass (sym :itself)))
120
+ (block (call _ :group_by) (args (arg _x)) (lvar _x))
121
+ (numblock (call _ :group_by) 1 (lvar :_1))
122
+ (itblock (call _ :group_by) :it (lvar :it))
123
+ }
124
+ :transform_values)
125
+ :it
126
+ (send (lvar :it) %COUNTING_METHODS))
127
+ }
128
+ PATTERN
129
+ def on_send(node)
130
+ if node.method?(:each_with_object)
131
+ check_each_with_object(node)
132
+ elsif node.method?(:transform_values)
133
+ check_transform_values(node)
134
+ end
135
+ end
136
+ alias on_csend on_send
137
+
138
+ private
139
+
140
+ def check_each_with_object(node)
141
+ block_node = node.block_node
142
+ return unless block_node
143
+ return unless tally_each_with_object?(block_node)
144
+
145
+ add_offense(node.loc.selector, message: MSG_EACH_WITH_OBJECT) do |corrector|
146
+ corrector.replace(replacement_range(node, block_node), 'tally')
147
+ end
148
+ end
149
+
150
+ def check_transform_values(node)
151
+ if tally_group_by_symbol?(node) || tally_group_by_identity_block?(node)
152
+ register_group_by_offense(node, node)
153
+ elsif (block_node = node.block_node) && tally_group_by_transform_block?(block_node)
154
+ register_group_by_offense(node, block_node)
155
+ end
156
+ end
157
+
158
+ def register_group_by_offense(transform_node, end_node)
159
+ group_by_node = group_by_send_node(transform_node)
160
+
161
+ add_offense(group_by_node.loc.selector, message: MSG_GROUP_BY) do |corrector|
162
+ corrector.replace(replacement_range(group_by_node, end_node), 'tally')
163
+ end
164
+ end
165
+
166
+ def group_by_send_node(transform_node)
167
+ receiver = transform_node.receiver
168
+ if receiver.type?(:any_block)
169
+ receiver.send_node
170
+ else
171
+ receiver
172
+ end
173
+ end
174
+
175
+ def replacement_range(start_node, end_node)
176
+ range_between(start_node.loc.selector.begin_pos, end_node.source_range.end_pos)
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end
@@ -58,6 +58,7 @@ module RuboCop
58
58
  include SafeAssignment
59
59
  include ConfigurableEnforcedStyle
60
60
  include SurroundingSpace
61
+ include ReparsedEquivalence
61
62
  extend AutoCorrector
62
63
 
63
64
  VARIABLE_TYPES = AST::Node::VARIABLES
@@ -101,7 +102,8 @@ module RuboCop
101
102
  condition = node.condition
102
103
 
103
104
  return nil if parenthesized?(condition) &&
104
- (safe_assignment?(condition) || unsafe_autocorrect?(condition))
105
+ (safe_assignment?(condition) || unsafe_autocorrect?(condition) ||
106
+ verified_by_reparse([condition]).empty?)
105
107
 
106
108
  if parenthesized?(condition)
107
109
  correct_parenthesized(corrector, condition)
@@ -113,6 +115,10 @@ module RuboCop
113
115
  def offense?(node)
114
116
  condition = node.condition
115
117
 
118
+ # A modifier `if`/`unless` requires the parentheses, e.g. `(a if b) ? x : y`,
119
+ # so removing them would change the meaning. Don't flag it.
120
+ return false if parenthesized_modifier_condition?(condition)
121
+
116
122
  if safe_assignment?(condition)
117
123
  !safe_assignment_allowed?
118
124
  else
@@ -174,6 +180,13 @@ module RuboCop
174
180
  condition.children.any? { |child| below_ternary_precedence?(child) }
175
181
  end
176
182
 
183
+ def parenthesized_modifier_condition?(condition)
184
+ return false unless condition.begin_type?
185
+
186
+ inner = condition.children.first
187
+ inner&.if_type? && inner.modifier_form?
188
+ end
189
+
177
190
  def unparenthesized_method_call?(child)
178
191
  /^[a-z]/i.match?(method_name(child)) && !child.parenthesized?
179
192
  end
@@ -207,6 +220,26 @@ module RuboCop
207
220
  end
208
221
  end
209
222
 
223
+ # Whatever binds looser than the ternary operator (`n += 1`, `a rescue b`,
224
+ # a nested ternary, `yield a`, several statements, ...) changes
225
+ # meaning without the parentheses, so their removal is verified by
226
+ # reparsing.
227
+ def apply_reparse_correction(corrector, condition)
228
+ correct_parenthesized(corrector, condition)
229
+ end
230
+
231
+ # The removed parentheses are the only expected difference.
232
+ def normalize_reparsed_ast(node)
233
+ return node unless node.is_a?(::Parser::AST::Node)
234
+
235
+ children = node.children.map { |child| normalize_reparsed_ast(child) }
236
+ if node.begin_type? && children.one? && children.first.is_a?(::Parser::AST::Node)
237
+ children.first
238
+ else
239
+ node.updated(nil, children)
240
+ end
241
+ end
242
+
210
243
  def correct_unparenthesized(corrector, condition)
211
244
  corrector.wrap(condition, '(', ')')
212
245
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for `Time.new` without arguments, which is an implicit way
7
+ # to retrieve the current system time. Prefer the more explicit `Time.now`.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # Time.new
12
+ #
13
+ # # good
14
+ # Time.now
15
+ #
16
+ # # good - `Time.new` with arguments constructs a specific time
17
+ # Time.new(2026, 8, 19)
18
+ #
19
+ class TimeNow < Base
20
+ extend AutoCorrector
21
+
22
+ MSG = 'Prefer `Time.now` over `Time.new` to retrieve the current time.'
23
+ RESTRICT_ON_SEND = %i[new].freeze
24
+
25
+ # @!method time_new?(node)
26
+ def_node_matcher :time_new?, <<~PATTERN
27
+ (call (const {nil? cbase} :Time) :new)
28
+ PATTERN
29
+
30
+ def on_send(node)
31
+ return unless time_new?(node)
32
+
33
+ add_offense(node) do |corrector|
34
+ corrector.replace(node.loc.selector.join(node.source_range.end), 'now')
35
+ end
36
+ end
37
+ alias on_csend on_send
38
+ end
39
+ end
40
+ end
41
+ end
@@ -3,11 +3,11 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Newcomers to ruby applications may write top-level methods,
6
+ # Newcomers to Ruby applications may write top-level methods,
7
7
  # when ideally they should be organized in appropriate classes or modules.
8
8
  # This cop looks for definitions of top-level methods and warns about them.
9
9
  #
10
- # However for ruby scripts it is perfectly fine to use top-level methods.
10
+ # However, for Ruby scripts it is perfectly fine to use top-level methods.
11
11
  # Hence this cop is disabled by default.
12
12
  #
13
13
  # @example
@@ -64,7 +64,7 @@ module RuboCop
64
64
 
65
65
  MSG = 'Useless trailing comma present in block arguments.'
66
66
 
67
- def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
67
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler -- a trailing comma needs an explicit parameter list
68
68
  # lambda literal (`->`) never has block arguments.
69
69
  return if node.send_node.lambda_literal?
70
70
  return unless useless_trailing_comma?(node)
@@ -45,6 +45,7 @@ module RuboCop
45
45
  corrector.insert_before(node.loc.end, "\n#{' ' * node.loc.keyword.column}")
46
46
  end
47
47
  end
48
+ alias on_defs on_def
48
49
 
49
50
  private
50
51
 
@@ -7,26 +7,26 @@ module RuboCop
7
7
  #
8
8
  # @example
9
9
  # # bad
10
- # a, b, _ = foo()
11
- # a, b, _, = foo()
12
- # a, _, _ = foo()
13
- # a, _, _, = foo()
10
+ # a, b, _ = foo
11
+ # a, b, _, = foo
12
+ # a, _, _ = foo
13
+ # a, _, _, = foo
14
14
  #
15
15
  # # good
16
- # a, b, = foo()
17
- # a, = foo()
18
- # *a, b, _ = foo()
16
+ # a, b, = foo
17
+ # a, = foo
18
+ # *a, b, _ = foo
19
19
  # # => We need to know to not include 2 variables in a
20
- # a, *b, _ = foo()
21
- # # => The correction `a, *b, = foo()` is a syntax error
20
+ # a, *b, _ = foo
21
+ # # => The correction `a, *b, = foo` is a syntax error
22
22
  #
23
23
  # @example AllowNamedUnderscoreVariables: true (default)
24
24
  # # good
25
- # a, b, _something = foo()
25
+ # a, b, _something = foo
26
26
  #
27
27
  # @example AllowNamedUnderscoreVariables: false
28
28
  # # bad
29
- # a, b, _something = foo()
29
+ # a, b, _something = foo
30
30
  #
31
31
  class TrailingUnderscoreVariable < Base
32
32
  include SurroundingSpace
@@ -35,19 +35,20 @@ module RuboCop
35
35
 
36
36
  MSG = 'Do not use trailing `_`s in parallel assignment. Prefer `%<code>s`.'
37
37
  UNDERSCORE = '_'
38
+ ARRAY_OPENING = '['
38
39
  DISALLOW = %i[lvasgn splat].freeze
39
40
  private_constant :DISALLOW
40
41
 
41
42
  def on_masgn(node)
42
- ranges = unneeded_ranges(node)
43
-
44
- ranges.each do |range|
43
+ unneeded_ranges(node).each do |range, replacement|
44
+ closing = replacement == ARRAY_OPENING ? ']' : ''
45
45
  good_code = node.source
46
46
  offset = range.begin_pos - node.source_range.begin_pos
47
- good_code[offset, range.size] = ''
47
+ good_code[offset, range.size] = replacement
48
48
 
49
- add_offense(range, message: format(MSG, code: good_code)) do |corrector|
50
- corrector.remove(range)
49
+ add_offense(range, message: format(MSG, code: "#{good_code}#{closing}")) do |corrector|
50
+ corrector.replace(range, replacement)
51
+ corrector.insert_after(node, closing) unless closing.empty?
51
52
  end
52
53
  end
53
54
  end
@@ -113,13 +114,14 @@ module RuboCop
113
114
 
114
115
  return unless first_offense
115
116
 
116
- if unused_variables_only?(first_offense, variables)
117
- return unused_range(node.type, mlhs_node, node.rhs)
118
- end
119
-
120
- return range_for_parentheses(first_offense, mlhs_node) if Util.parentheses?(mlhs_node)
117
+ return unused_range(node, mlhs_node) if unused_variables_only?(first_offense, variables)
121
118
 
122
- range_between(first_offense.source_range.begin_pos, node.loc.operator.begin_pos)
119
+ range = if Util.parentheses?(mlhs_node)
120
+ range_for_parentheses(first_offense, mlhs_node)
121
+ else
122
+ range_between(first_offense.source_range.begin_pos, node.loc.operator.begin_pos)
123
+ end
124
+ [range, '']
123
125
  end
124
126
 
125
127
  def children_offenses(variables)
@@ -130,17 +132,18 @@ module RuboCop
130
132
  offense.source_range == variables.first.source_range
131
133
  end
132
134
 
133
- def unused_range(node_type, mlhs_node, right)
134
- start_range = mlhs_node.source_range.begin_pos
135
+ def unused_range(node, mlhs_node)
136
+ # `node` can be an `mlhs` when recursing into a nested destructuring
137
+ # group. Removing the group could leave a dangling comma or put
138
+ # something after a splat, so it is collapsed into a single `_`,
139
+ # which the parent group handles in turn.
140
+ return [mlhs_node.source_range, UNDERSCORE] unless node.masgn_type?
135
141
 
136
- end_range = case node_type
137
- when :masgn
138
- right.source_range.begin_pos
139
- when :mlhs
140
- mlhs_node.source_range.end_pos
141
- end
142
+ rhs = node.rhs
143
+ range = range_between(mlhs_node.source_range.begin_pos, rhs.source_range.begin_pos)
142
144
 
143
- range_between(start_range, end_range)
145
+ # `_, _ = 1, 2` cannot become `1, 2`, so the values become an array literal.
146
+ [range, rhs.array_type? && !rhs.bracketed? ? ARRAY_OPENING : '']
144
147
  end
145
148
 
146
149
  def range_for_parentheses(offense, left)
@@ -234,7 +234,7 @@ module RuboCop
234
234
  def autocorrect_class(corrector, node)
235
235
  kind = trivial_accessor_kind(node)
236
236
 
237
- return unless names_match?(node) && kind
237
+ return unless names_match?(node) && !node.predicate_method? && kind
238
238
 
239
239
  indent = ' ' * node.loc.column
240
240
  corrector.replace(
@@ -14,11 +14,11 @@ module RuboCop
14
14
  #
15
15
  # `forbid_mixed_logical_operators` style forbids the use of more than one type
16
16
  # of logical operators. This makes the `unless` condition easier to read
17
- # because either all conditions need to be met or any condition need to be met
17
+ # because either all conditions need to be met or any condition needs to be met
18
18
  # in order for the expression to be truthy or falsey.
19
19
  #
20
- # `forbid_logical_operators` style forbids any use of logical operator.
21
- # This makes it even more easy to read the `unless` condition as
20
+ # `forbid_logical_operators` style forbids any use of logical operators.
21
+ # This makes it even easier to read the `unless` condition as
22
22
  # there is only one condition in the expression.
23
23
  #
24
24
  # @example EnforcedStyle: forbid_mixed_logical_operators (default)
@@ -33,6 +33,7 @@ module RuboCop
33
33
 
34
34
  def on_while(node)
35
35
  return unless node.multiline? && node.do?
36
+ return if same_line_body?(node)
36
37
 
37
38
  add_offense(node.loc.begin, message: format(MSG, keyword: node.keyword)) do |corrector|
38
39
  do_range = node.condition.source_range.end.join(node.loc.begin)
@@ -41,6 +42,12 @@ module RuboCop
41
42
  end
42
43
  end
43
44
  alias on_until on_while
45
+
46
+ private
47
+
48
+ def same_line_body?(node)
49
+ node.body && same_line?(node.loc.begin, node.body)
50
+ end
44
51
  end
45
52
  end
46
53
  end
@@ -16,6 +16,11 @@ module RuboCop
16
16
  # # good
17
17
  # x += 1 while x < 10
18
18
  #
19
+ # # good
20
+ # while x < 10
21
+ # y += 1 if x.odd?
22
+ # end
23
+ #
19
24
  # # bad
20
25
  # until x > 10
21
26
  # x += 1
@@ -24,6 +29,11 @@ module RuboCop
24
29
  # # good
25
30
  # x += 1 until x > 10
26
31
  #
32
+ # # good
33
+ # until x > 10
34
+ # y += 1 unless x.even?
35
+ # end
36
+ #
27
37
  # # bad
28
38
  # x += 100 while x < 500 # a long comment that makes code too long if it were a single line
29
39
  #
@@ -45,6 +55,12 @@ module RuboCop
45
55
  end
46
56
  end
47
57
  alias on_until on_while
58
+
59
+ private
60
+
61
+ def non_eligible_body?(body)
62
+ body&.conditional? || body&.kwbegin_type? || super
63
+ end
48
64
  end
49
65
  end
50
66
  end
@@ -93,6 +93,7 @@ module RuboCop
93
93
 
94
94
  def on_array(node)
95
95
  if bracketed_array_of?(:str, node)
96
+ return if node.values.any?(&:heredoc?)
96
97
  return if complex_content?(node.values)
97
98
  return if within_matrix_of_complex_content?(node)
98
99