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
@@ -49,10 +49,16 @@ module RuboCop
49
49
  class RedundantLineBreak < Base
50
50
  include CheckAssignment
51
51
  include CheckSingleLineSuitability
52
+ include ReparsedEquivalence
52
53
  extend AutoCorrector
53
54
 
54
55
  MSG = 'Redundant line break detected.'
55
56
 
57
+ def on_new_investigation
58
+ super
59
+ @offense_line_ranges = []
60
+ end
61
+
56
62
  def on_lvasgn(node)
57
63
  super unless end_with_percent_blank_string?(processed_source)
58
64
  end
@@ -76,16 +82,108 @@ module RuboCop
76
82
  end
77
83
 
78
84
  def check_assignment(node, _rhs)
79
- return unless offense?(node)
85
+ return unless offense?(node) && !part_of_ignored_node?(node)
80
86
 
81
87
  register_offense(node)
82
88
  end
83
89
 
84
90
  def register_offense(node)
91
+ line_range = joined_line_range(node)
92
+ return if too_long_as_single_line?(line_range)
93
+
94
+ # The exact single-line correction is verified to parse equivalently
95
+ # before the offense is registered, so a join that would change how
96
+ # the code parses is never reported or offered.
97
+ return if verified_by_reparse([node], oversized: :verify).empty?
98
+
85
99
  add_offense(node) do |corrector|
86
100
  corrector.replace(node, to_single_line(node.source).strip)
87
101
  end
88
102
  ignore_node(node)
103
+ @offense_line_ranges.reject! { |range| line_range.cover?(range) }
104
+ @offense_line_ranges << line_range
105
+ end
106
+
107
+ # Offenses registered in the same pass that share a line with `node`
108
+ # get joined onto that line too, so the combined line has to fit.
109
+ def joined_line_range(node)
110
+ sharing_ranges = @offense_line_ranges.select do |range|
111
+ range.begin <= node.last_line && node.first_line <= range.end
112
+ end
113
+ lines = [node.first_line, node.last_line, *sharing_ranges.flat_map(&:minmax)]
114
+
115
+ lines.min..lines.max
116
+ end
117
+
118
+ def apply_reparse_correction(corrector, node)
119
+ corrector.replace(node, to_single_line(node.source).strip)
120
+ end
121
+
122
+ # Joining lines shifts the value of any later `__LINE__`, exactly as
123
+ # any other line-removing correction does; neutralize it on both sides
124
+ # with an identifier, which stays valid in every position the keyword
125
+ # can appear in.
126
+ def preprocess_reparsed_source(source)
127
+ source.gsub(/\b__LINE__\b/, '__LINE0__')
128
+ end
129
+
130
+ def normalize_reparsed_ast(node)
131
+ fold_string_concatenation(node)
132
+ end
133
+
134
+ # Joining lines merges split string literals (`"a" \<newline> "b"` into
135
+ # `"ab"`) and turns mixed-quote pairs into `+` concatenation, which
136
+ # changes the tree but not the resulting string. Normalize all string
137
+ # concatenation to a canonical form before comparing: nested
138
+ # concatenations are flattened and adjacent literal parts merged.
139
+ def fold_string_concatenation(node)
140
+ return node unless node.is_a?(::Parser::AST::Node)
141
+
142
+ children = node.children.map { |child| fold_string_concatenation(child) }
143
+ node = node.updated(nil, children)
144
+
145
+ parts = string_concatenation_parts(node)
146
+ return node unless parts
147
+
148
+ merged = merge_string_parts(parts)
149
+ if merged.one? && merged.first.str_type?
150
+ node.updated(:str, merged.first.children)
151
+ else
152
+ node.updated(:dstr, merged)
153
+ end
154
+ end
155
+
156
+ def string_concatenation_parts(node)
157
+ case node.type
158
+ when :dstr
159
+ node.children
160
+ when :send
161
+ parts = [node.receiver, *node.arguments]
162
+ parts if node.method?(:+) && parts.all? { |part| stringish?(part) }
163
+ end
164
+ end
165
+
166
+ def merge_string_parts(parts)
167
+ flattened = parts.flat_map do |part|
168
+ part.is_a?(::Parser::AST::Node) && part.dstr_type? ? part.children : [part]
169
+ end
170
+
171
+ flattened.chunk_while { |left, right| plain_string?(left) && plain_string?(right) }
172
+ .map { |chunk| merge_plain_strings(chunk) }
173
+ end
174
+
175
+ def merge_plain_strings(chunk)
176
+ return chunk.first if chunk.one?
177
+
178
+ chunk.first.updated(:str, [chunk.map { |part| part.children.first }.join])
179
+ end
180
+
181
+ def stringish?(node)
182
+ node.is_a?(::Parser::AST::Node) && %i[str dstr].include?(node.type)
183
+ end
184
+
185
+ def plain_string?(node)
186
+ node.is_a?(::Parser::AST::Node) && node.str_type? && node.children.one?
89
187
  end
90
188
 
91
189
  def offense?(node)
@@ -114,7 +212,9 @@ module RuboCop
114
212
 
115
213
  def other_cop_takes_precedence?(node)
116
214
  single_line_block_chain_enabled? && any_descendant?(node, :any_block) do |block_node|
117
- block_node.parent.send_type? && block_node.parent.loc.dot && !block_node.multiline?
215
+ next unless (parent = block_node.parent)
216
+
217
+ parent.call_type? && parent.loc.dot && block_node.single_line?
118
218
  end
119
219
  end
120
220
 
@@ -22,6 +22,7 @@ module RuboCop
22
22
  # puts 'error'
23
23
  # end
24
24
  class RescueEnsureAlignment < Base
25
+ include Alignment
25
26
  include RangeHelp
26
27
  include EndKeywordAlignment
27
28
  extend AutoCorrector
@@ -29,7 +30,7 @@ module RuboCop
29
30
  MSG = '`%<kw_loc>s` at %<kw_loc_line>d, %<kw_loc_column>d is not ' \
30
31
  'aligned with `%<beginning>s` at ' \
31
32
  '%<begin_loc_line>d, %<begin_loc_column>d.'
32
- ANCESTOR_TYPES = %i[kwbegin any_def class module any_block].freeze
33
+ ANCESTOR_TYPES = %i[kwbegin any_def class module sclass any_block].freeze
33
34
  ALTERNATIVE_ACCESS_MODIFIERS = %i[public_class_method private_class_method].freeze
34
35
 
35
36
  def on_resbody(node)
@@ -74,9 +75,10 @@ module RuboCop
74
75
  # Some inline node is sitting before current node.
75
76
  return nil unless whitespace.source.strip.empty?
76
77
 
77
- new_column = alignment_location.column
78
+ indentation = alignment_indentation(alignment_location)
79
+ return nil if indentation.nil?
78
80
 
79
- corrector.replace(whitespace, ' ' * new_column)
81
+ corrector.replace(whitespace, indentation)
80
82
  end
81
83
 
82
84
  def format_message(alignment_node, alignment_loc, kw_loc)
@@ -91,7 +93,18 @@ module RuboCop
91
93
  )
92
94
  end
93
95
 
94
- # rubocop:disable Metrics/AbcSize
96
+ # A run of spaces sized to the target column would be turned back into tabs by
97
+ # `Layout/IndentationStyle`, generally landing on a different column, so under
98
+ # tabs the target line's own indentation is reused. There is nothing to reuse
99
+ # when the target does not start its line.
100
+ def alignment_indentation(location)
101
+ return ' ' * location.column unless using_tabs?
102
+ return unless begins_its_line?(location)
103
+
104
+ location.source_line[/\A\s*/]
105
+ end
106
+
107
+ # rubocop:disable-next Metrics/AbcSize, Metrics/MethodLength
95
108
  def alignment_source(node, starting_loc)
96
109
  ending_loc =
97
110
  case node.type
@@ -100,6 +113,8 @@ module RuboCop
100
113
  when :def, :defs, :class, :module,
101
114
  :lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn
102
115
  node.loc.name
116
+ when :sclass
117
+ node.identifier.source_range
103
118
  when :masgn
104
119
  node.lhs.source_range
105
120
  else
@@ -109,7 +124,6 @@ module RuboCop
109
124
 
110
125
  range_between(starting_loc.begin_pos, ending_loc.end_pos).source
111
126
  end
112
- # rubocop:enable Metrics/AbcSize
113
127
 
114
128
  # We will use ancestor or wrapper with access modifier.
115
129
 
@@ -25,13 +25,17 @@ module RuboCop
25
25
 
26
26
  MSG = 'Put method call on a separate line if chained to a single line block.'
27
27
 
28
+ # These cops rewrite a method chained to the block in the same pass,
29
+ # which must not start a line of its own.
28
30
  def self.autocorrect_incompatible_with
29
- [Style::MapToHash]
31
+ [Style::FloatDivision, Style::MapToHash, Style::NilComparison, Style::RedundantSort]
30
32
  end
31
33
 
32
34
  def on_send(node)
33
35
  range = offending_range(node)
34
- add_offense(range) { |corrector| corrector.insert_before(range, "\n") } if range
36
+ return if !range || heredoc_opened_before?(node.receiver, range)
37
+
38
+ add_offense(range) { |corrector| corrector.insert_before(range, "\n") }
35
39
  end
36
40
  alias on_csend on_send
37
41
 
@@ -63,6 +67,10 @@ module RuboCop
63
67
  # l.(1) has no selector, so we use the opening parenthesis instead
64
68
  node.loc.selector || node.loc.begin
65
69
  end
70
+
71
+ def heredoc_opened_before?(receiver, range)
72
+ receiver.each_node(:any_str).any? { |str| str.heredoc? && str.first_line == range.line }
73
+ end
66
74
  end
67
75
  end
68
76
  end
@@ -23,16 +23,8 @@ module RuboCop
23
23
  cfg['EnforcedStyle'] || 'space'
24
24
  end
25
25
 
26
- def kind(token)
27
- 'comma' if token.comma? && !before_semicolon?(token)
28
- end
29
-
30
- private
31
-
32
- def before_semicolon?(token)
33
- tokens = processed_source.tokens
34
-
35
- tokens[tokens.index(token) + 1].semicolon?
26
+ def kind(token, next_token)
27
+ 'comma' if token.comma? && !next_token.semicolon?
36
28
  end
37
29
  end
38
30
  end
@@ -20,6 +20,7 @@ module RuboCop
20
20
 
21
21
  def on_send(node)
22
22
  return unless node.prefix_bang? && whitespace_after_operator?(node)
23
+ return if unary_tilde?(node.receiver)
23
24
 
24
25
  add_offense(node) do |corrector|
25
26
  corrector.remove(
@@ -33,6 +34,10 @@ module RuboCop
33
34
  def whitespace_after_operator?(node)
34
35
  node.receiver.source_range.begin_pos - node.source_range.begin_pos > 1
35
36
  end
37
+
38
+ def unary_tilde?(receiver)
39
+ receiver.send_type? && receiver.unary_operation? && receiver.method?(:~)
40
+ end
36
41
  end
37
42
  end
38
43
  end
@@ -20,7 +20,7 @@ module RuboCop
20
20
  cfg['EnforcedStyle'] || 'space'
21
21
  end
22
22
 
23
- def kind(token)
23
+ def kind(token, _next_token)
24
24
  'semicolon' if token.semicolon?
25
25
  end
26
26
 
@@ -5,7 +5,9 @@ module RuboCop
5
5
  module Layout
6
6
  # Checks the spacing inside and after block parameters pipes. Line breaks
7
7
  # inside parameter pipes are checked by `Layout/MultilineBlockLayout` and
8
- # not by this cop.
8
+ # not by this cop. Spaces inside a lambda's parameter parentheses are left
9
+ # to `Layout/SpaceInsideParens` when that cop is enabled, so the examples
10
+ # below apply to a lambda only when it is not.
9
11
  #
10
12
  # @example EnforcedStyleInsidePipes: no_space (default)
11
13
  # # bad
@@ -29,12 +31,12 @@ module RuboCop
29
31
  include RangeHelp
30
32
  extend AutoCorrector
31
33
 
32
- def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
34
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler -- checks spacing inside a block parameter list
33
35
  arguments = node.arguments
34
36
 
35
37
  return unless node.arguments? && pipes?(arguments)
36
38
 
37
- check_inside_pipes(arguments)
39
+ check_inside_pipes(arguments) unless checked_by_space_inside_parens?(arguments)
38
40
  check_after_closing_pipe(arguments) if node.body
39
41
  check_each_arg(arguments)
40
42
  end
@@ -53,6 +55,10 @@ module RuboCop
53
55
  'EnforcedStyleInsidePipes'
54
56
  end
55
57
 
58
+ def checked_by_space_inside_parens?(arguments)
59
+ arguments.loc.begin.source == '(' && config.cop_enabled?('Layout/SpaceInsideParens')
60
+ end
61
+
56
62
  def check_inside_pipes(arguments)
57
63
  case style
58
64
  when :no_space
@@ -142,7 +148,7 @@ module RuboCop
142
148
  if node
143
149
  corrector.insert_before(node, ' ')
144
150
  else
145
- corrector.insert_after(target, ' ')
151
+ corrector.insert_after(range_between(space_begin_pos, space_begin_pos), ' ')
146
152
  end
147
153
  end
148
154
  end
@@ -47,9 +47,11 @@ module RuboCop
47
47
  check(node, [:operator].freeze) if node.keyword?
48
48
  end
49
49
 
50
- def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
50
+ def on_block(node)
51
51
  check(node, %i[begin end].freeze)
52
52
  end
53
+ alias on_numblock on_block
54
+ alias on_itblock on_block
53
55
 
54
56
  def on_break(node)
55
57
  check(node, [:keyword].freeze)
@@ -167,7 +169,7 @@ module RuboCop
167
169
 
168
170
  def check(node, locations, begin_keyword = DO)
169
171
  locations.each do |loc|
170
- next unless node.loc.respond_to?(loc)
172
+ next unless node.loc?(loc)
171
173
 
172
174
  range = node.loc.public_send(loc)
173
175
  next unless range
@@ -207,6 +209,7 @@ module RuboCop
207
209
  end
208
210
 
209
211
  return unless space_after_missing?(range)
212
+ return if block_brace_with_no_space_style?(node, range)
210
213
 
211
214
  add_offense(range, message: format(MSG_AFTER, range: range.source)) do |corrector|
212
215
  corrector.insert_after(range, ' ')
@@ -231,6 +234,15 @@ module RuboCop
231
234
  !/[\s;,#\\)}\].]/.match?(char)
232
235
  end
233
236
 
237
+ def block_brace_with_no_space_style?(node, range)
238
+ return false unless (parent = node.parent)
239
+ return false unless parent.any_block_type? && parent.loc.begin&.begin_pos == range.end_pos
240
+
241
+ space_before_block_braces_config = config.for_cop('Layout/SpaceBeforeBlockBraces')
242
+ space_before_block_braces_config.fetch('Enabled', true) &&
243
+ space_before_block_braces_config['EnforcedStyle'] == 'no_space'
244
+ end
245
+
234
246
  def accepted_opening_delimiter?(range, char)
235
247
  return true unless char
236
248
 
@@ -129,6 +129,12 @@ module RuboCop
129
129
  check_operator(:class, node.loc.operator, rhs)
130
130
  end
131
131
 
132
+ def on_def(node)
133
+ return unless node.endless?
134
+
135
+ check_operator(:assignment, node.loc.assignment, node.body)
136
+ end
137
+
132
138
  def on_binary(node)
133
139
  rhs = node.rhs
134
140
 
@@ -170,6 +176,7 @@ module RuboCop
170
176
  alias on_or_asgn on_assignment
171
177
  alias on_and_asgn on_assignment
172
178
  alias on_op_asgn on_assignment
179
+ alias on_defs on_def
173
180
 
174
181
  private
175
182
 
@@ -204,10 +211,14 @@ module RuboCop
204
211
 
205
212
  def autocorrect(corrector, range, right_operand)
206
213
  range_source = range.source
214
+ # Match the operator exactly, not by substring, so compound assignments
215
+ # like `**=` and `/=` are not mistaken for `**` and `/` (which would drop
216
+ # the `=` and silently change the program's behavior).
217
+ operator = range_source.strip
207
218
 
208
- if range_source.include?('**') && !space_around_exponent_operator?
219
+ if operator == '**' && !space_around_exponent_operator?
209
220
  corrector.replace(range, '**')
210
- elsif range_source.include?('/') && !space_around_slash_operator?(right_operand)
221
+ elsif operator == '/' && !space_around_slash_operator?(right_operand)
211
222
  corrector.replace(range, '/')
212
223
  elsif range_source.end_with?("\n")
213
224
  corrector.replace(range, " #{range_source.strip}\n")
@@ -247,7 +258,7 @@ module RuboCop
247
258
  return false unless allow_for_alignment?
248
259
  return false unless with_space.source.start_with?(EXCESSIVE_SPACE)
249
260
 
250
- return !aligned_with_operator?(operator) unless type == :assignment
261
+ return !aligned_with_operator?(operator) unless grouped_alignment_type?(type)
251
262
 
252
263
  token = Token.new(operator, nil, operator.source)
253
264
  align_preceding = aligned_with_preceding_equals_operator(token)
@@ -258,6 +269,10 @@ module RuboCop
258
269
  aligned_with_subsequent_equals_operator(token) != :yes
259
270
  end
260
271
 
272
+ def grouped_alignment_type?(type)
273
+ type == :assignment || (type == :special_asgn && force_equal_sign_alignment?)
274
+ end
275
+
261
276
  def excess_trailing_space?(right_operand, with_space)
262
277
  with_space.source.end_with?(EXCESSIVE_SPACE) &&
263
278
  (!allow_for_alignment? || !aligned_with_something?(right_operand))
@@ -49,8 +49,11 @@ module RuboCop
49
49
  MISSING_MSG = 'Space missing to the left of {.'
50
50
  DETECTED_MSG = 'Space detected to the left of {.'
51
51
 
52
+ # `Style/BlockDelimiters` decides whether to put a space before the `do`
53
+ # it writes by looking at the source before this cop removed the space,
54
+ # so the two corrections cannot be applied in the same pass.
52
55
  def self.autocorrect_incompatible_with
53
- [Style::SymbolProc]
56
+ [Style::BlockDelimiters, Style::SymbolProc]
54
57
  end
55
58
 
56
59
  def on_block(node)
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Layout
6
6
  # Checks for space between the name of a receiver and a left
7
- # brackets.
7
+ # bracket.
8
8
  #
9
9
  # @example
10
10
  #
@@ -7,18 +7,18 @@ module RuboCop
7
7
  # parenthesis (`(`) in lambda literals.
8
8
  #
9
9
  # @example EnforcedStyle: require_no_space (default)
10
- # # bad
11
- # a = -> (x, y) { x + y }
10
+ # # bad
11
+ # a = -> (x, y) { x + y }
12
12
  #
13
- # # good
14
- # a = ->(x, y) { x + y }
13
+ # # good
14
+ # a = ->(x, y) { x + y }
15
15
  #
16
16
  # @example EnforcedStyle: require_space
17
- # # bad
18
- # a = ->(x, y) { x + y }
17
+ # # bad
18
+ # a = ->(x, y) { x + y }
19
19
  #
20
- # # good
21
- # a = -> (x, y) { x + y }
20
+ # # good
21
+ # a = -> (x, y) { x + y }
22
22
  class SpaceInLambdaLiteral < Base
23
23
  include ConfigurableEnforcedStyle
24
24
  include RangeHelp
@@ -26,6 +26,7 @@ module RuboCop
26
26
 
27
27
  MSG_REQUIRE_SPACE = 'Use a space between `->` and `(` in lambda literals.'
28
28
  MSG_REQUIRE_NO_SPACE = 'Do not use spaces between `->` and `(` in lambda literals.'
29
+ RESTRICT_ON_SEND = %i[lambda].freeze
29
30
 
30
31
  def on_send(node)
31
32
  return unless arrow_lambda_with_args?(node)
@@ -94,10 +94,10 @@ module RuboCop
94
94
  return empty_offenses(node, left, right, EMPTY_MSG)
95
95
  end
96
96
 
97
- start_ok = next_to_newline?(node, left)
97
+ start_ok = next_to_newline?(tokens, left)
98
98
  end_ok = node.single_line? ? false : end_has_own_line?(right)
99
99
 
100
- issue_offenses(node, left, right, start_ok, end_ok)
100
+ issue_offenses(node, tokens, left, right, start_ok, end_ok)
101
101
  end
102
102
  alias on_array_pattern on_array
103
103
 
@@ -117,7 +117,7 @@ module RuboCop
117
117
  elsif style == :space
118
118
  SpaceCorrector.add_space(processed_source, corrector, left, right)
119
119
  else
120
- compact_corrections(corrector, node, left, right)
120
+ compact_corrections(corrector, node, tokens, left, right)
121
121
  end
122
122
  end
123
123
 
@@ -134,8 +134,8 @@ module RuboCop
134
134
  cop_config['EnforcedStyleForEmptyBrackets']
135
135
  end
136
136
 
137
- def next_to_newline?(node, token)
138
- processed_source.tokens_within(node)[index_for(node, token) + 1].line != token.line
137
+ def next_to_newline?(tokens, token)
138
+ tokens[index_for(tokens, token) + 1].line != token.line
139
139
  end
140
140
 
141
141
  def end_has_own_line?(token)
@@ -145,68 +145,67 @@ module RuboCop
145
145
  !/\S/.match?(processed_source.lines[line][0..col])
146
146
  end
147
147
 
148
- def index_for(node, token)
149
- processed_source.tokens_within(node).index(token)
148
+ def index_for(tokens, token)
149
+ tokens.index(token)
150
150
  end
151
151
 
152
152
  def line_and_column_for(token)
153
153
  [token.line - 1, token.column - 1]
154
154
  end
155
155
 
156
- def issue_offenses(node, left, right, start_ok, end_ok)
156
+ # rubocop:disable-next Metrics/ParameterLists
157
+ def issue_offenses(node, tokens, left, right, start_ok, end_ok)
157
158
  case style
158
159
  when :no_space
159
- start_ok = next_to_comment?(node, left)
160
+ start_ok = next_to_comment?(tokens, left)
160
161
  no_space_offenses(node, left, right, MSG, start_ok: start_ok, end_ok: end_ok)
161
162
  when :space
162
163
  space_offenses(node, left, right, MSG, start_ok: start_ok, end_ok: end_ok)
163
164
  else
164
- compact_offenses(node, left, right, start_ok, end_ok)
165
+ compact_offenses(node, tokens, left, right, start_ok, end_ok)
165
166
  end
166
167
  end
167
168
 
168
- def next_to_comment?(node, token)
169
- processed_source.tokens_within(node)[index_for(node, token) + 1].comment?
169
+ def next_to_comment?(tokens, token)
170
+ tokens[index_for(tokens, token) + 1].comment?
170
171
  end
171
172
 
172
- def compact_offenses(node, left, right, start_ok, end_ok)
173
- if qualifies_for_compact?(node, left, side: :left)
173
+ # rubocop:disable-next Metrics/ParameterLists
174
+ def compact_offenses(node, tokens, left, right, start_ok, end_ok)
175
+ if qualifies_for_compact?(tokens, left, side: :left)
174
176
  compact_offense(node, left, side: :left)
175
- elsif !multi_dimensional_array?(node, left, side: :left)
177
+ elsif !multi_dimensional_array?(tokens, left, side: :left)
176
178
  space_offenses(node, left, nil, MSG, start_ok: start_ok, end_ok: true)
177
179
  end
178
- if qualifies_for_compact?(node, right)
180
+
181
+ return if closing_bracket_kept_apart?(node, tokens, left, right)
182
+
183
+ if qualifies_for_compact?(tokens, right)
179
184
  compact_offense(node, right)
180
- elsif !multi_dimensional_array?(node, right)
185
+ elsif !multi_dimensional_array?(tokens, right)
181
186
  space_offenses(node, nil, right, MSG, start_ok: true, end_ok: end_ok)
182
187
  end
183
188
  end
184
189
 
185
- def qualifies_for_compact?(node, token, side: :right)
190
+ def qualifies_for_compact?(tokens, token, side: :right)
186
191
  if side == :right
187
- multi_dimensional_array?(node, token) && token.space_before?
192
+ multi_dimensional_array?(tokens, token) && token.space_before?
188
193
  else
189
- multi_dimensional_array?(node, token, side: :left) && token.space_after?
194
+ multi_dimensional_array?(tokens, token, side: :left) && token.space_after?
190
195
  end
191
196
  end
192
197
 
193
- def multi_dimensional_array?(node, token, side: :right)
198
+ def multi_dimensional_array?(tokens, token, side: :right)
194
199
  offset = side == :right ? -1 : +1
195
- i = index_for(node, token) + offset
196
- i += offset while processed_source.tokens_within(node)[i].new_line?
200
+ i = index_for(tokens, token) + offset
201
+ i += offset while tokens[i].new_line?
197
202
  if side == :right
198
- processed_source.tokens_within(node)[i].right_bracket?
203
+ tokens[i].right_bracket?
199
204
  else
200
- processed_source.tokens_within(node)[i].left_bracket?
205
+ tokens[i].left_bracket?
201
206
  end
202
207
  end
203
208
 
204
- def next_to_bracket?(token, side: :right)
205
- line_index, col = line_and_column_for(token)
206
- line = processed_source.lines[line_index]
207
- side == :right ? line[col] == ']' : line[col + 2] == '['
208
- end
209
-
210
209
  def compact_offense(node, token, side: :right)
211
210
  if side == :right
212
211
  space_offense(node, token, :left, MSG, NO_SPACE_COMMAND)
@@ -215,14 +214,25 @@ module RuboCop
215
214
  end
216
215
  end
217
216
 
218
- def compact_corrections(corrector, node, left, right)
219
- if multi_dimensional_array?(node, left, side: :left)
217
+ # A closing bracket on its own line is only collapsed when the opening
218
+ # bracket ends up on the first element's line, so that the brackets
219
+ # stay symmetrical (see `Layout/MultilineArrayBraceLayout`).
220
+ def closing_bracket_kept_apart?(node, tokens, left, right)
221
+ end_has_own_line?(right) &&
222
+ !multi_dimensional_array?(tokens, left, side: :left) &&
223
+ !same_line?(left, node.children.first)
224
+ end
225
+
226
+ def compact_corrections(corrector, node, tokens, left, right)
227
+ if multi_dimensional_array?(tokens, left, side: :left)
220
228
  compact(corrector, left, :right)
221
229
  elsif !left.space_after?
222
230
  corrector.insert_after(left.pos, ' ')
223
231
  end
224
232
 
225
- if multi_dimensional_array?(node, right)
233
+ return if closing_bracket_kept_apart?(node, tokens, left, right)
234
+
235
+ if multi_dimensional_array?(tokens, right)
226
236
  compact(corrector, right, :left)
227
237
  elsif !right.space_before?
228
238
  corrector.insert_before(right.pos, ' ')