rubocop 1.80.2 → 1.86.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 (310) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +170 -19
  5. data/config/obsoletion.yml +9 -0
  6. data/lib/rubocop/cache_config.rb +29 -0
  7. data/lib/rubocop/cli/command/auto_generate_config.rb +3 -3
  8. data/lib/rubocop/cli/command/lsp.rb +1 -1
  9. data/lib/rubocop/cli/command/mcp.rb +19 -0
  10. data/lib/rubocop/cli/command/show_cops.rb +2 -2
  11. data/lib/rubocop/cli/command/show_docs_url.rb +1 -1
  12. data/lib/rubocop/cli.rb +28 -6
  13. data/lib/rubocop/comment_config.rb +62 -17
  14. data/lib/rubocop/config.rb +14 -10
  15. data/lib/rubocop/config_finder.rb +1 -1
  16. data/lib/rubocop/config_loader.rb +20 -21
  17. data/lib/rubocop/config_loader_resolver.rb +9 -7
  18. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -2
  19. data/lib/rubocop/config_store.rb +6 -1
  20. data/lib/rubocop/config_validator.rb +1 -1
  21. data/lib/rubocop/cop/autocorrect_logic.rb +8 -4
  22. data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
  23. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -2
  24. data/lib/rubocop/cop/correctors/alignment_corrector.rb +22 -6
  25. data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
  26. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  27. data/lib/rubocop/cop/documentation.rb +2 -3
  28. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -2
  29. data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
  30. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +10 -5
  31. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
  32. data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
  33. data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
  34. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +9 -9
  35. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  36. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
  37. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  38. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
  39. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  40. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -2
  41. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  42. data/lib/rubocop/cop/layout/case_indentation.rb +3 -1
  43. data/lib/rubocop/cop/layout/class_structure.rb +13 -6
  44. data/lib/rubocop/cop/layout/dot_position.rb +2 -2
  45. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +12 -2
  46. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +31 -13
  47. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
  48. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
  49. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +12 -2
  50. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +16 -2
  51. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
  52. data/lib/rubocop/cop/layout/end_alignment.rb +8 -1
  53. data/lib/rubocop/cop/layout/first_argument_indentation.rb +34 -1
  54. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +26 -0
  55. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +7 -1
  56. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
  57. data/lib/rubocop/cop/layout/hash_alignment.rb +3 -6
  58. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  59. data/lib/rubocop/cop/layout/heredoc_indentation.rb +33 -3
  60. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  61. data/lib/rubocop/cop/layout/indentation_width.rb +111 -7
  62. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  63. data/lib/rubocop/cop/layout/line_length.rb +26 -9
  64. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +57 -57
  65. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +9 -2
  66. data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
  67. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +56 -56
  68. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +204 -39
  69. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +6 -4
  70. data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
  71. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
  72. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
  73. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  74. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  75. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  76. data/lib/rubocop/cop/layout/space_around_keyword.rb +4 -2
  77. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
  78. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  79. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
  80. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
  81. data/lib/rubocop/cop/lint/constant_reassignment.rb +59 -9
  82. data/lib/rubocop/cop/lint/constant_resolution.rb +1 -1
  83. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
  84. data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
  85. data/lib/rubocop/cop/lint/debugger.rb +0 -2
  86. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
  87. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  88. data/lib/rubocop/cop/lint/duplicate_methods.rb +111 -12
  89. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  90. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  91. data/lib/rubocop/cop/lint/empty_conditional_body.rb +6 -1
  92. data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
  93. data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
  94. data/lib/rubocop/cop/lint/empty_when.rb +8 -1
  95. data/lib/rubocop/cop/lint/float_comparison.rb +1 -1
  96. data/lib/rubocop/cop/lint/interpolation_check.rb +7 -2
  97. data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -1
  98. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  99. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +16 -6
  100. data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
  101. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
  102. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -1
  103. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  104. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
  105. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +0 -9
  106. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
  107. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +23 -6
  108. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -2
  109. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  110. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -0
  111. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +7 -1
  112. data/lib/rubocop/cop/lint/self_assignment.rb +10 -2
  113. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  114. data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
  115. data/lib/rubocop/cop/lint/syntax.rb +25 -1
  116. data/lib/rubocop/cop/lint/to_json.rb +12 -16
  117. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -0
  118. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
  119. data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
  120. data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
  121. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  122. data/lib/rubocop/cop/lint/useless_assignment.rb +45 -17
  123. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +4 -4
  124. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +2 -0
  125. data/lib/rubocop/cop/lint/useless_or.rb +15 -2
  126. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +24 -9
  127. data/lib/rubocop/cop/lint/void.rb +39 -12
  128. data/lib/rubocop/cop/message_annotator.rb +1 -1
  129. data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
  130. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  131. data/lib/rubocop/cop/migration/department_name.rb +12 -1
  132. data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
  133. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +4 -6
  134. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  135. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +5 -5
  136. data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
  137. data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -60
  138. data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
  139. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  140. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  141. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  142. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  143. data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
  144. data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -5
  145. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  146. data/lib/rubocop/cop/naming/method_name.rb +4 -2
  147. data/lib/rubocop/cop/naming/predicate_method.rb +27 -4
  148. data/lib/rubocop/cop/naming/predicate_prefix.rb +11 -11
  149. data/lib/rubocop/cop/offense.rb +9 -1
  150. data/lib/rubocop/cop/registry.rb +20 -13
  151. data/lib/rubocop/cop/security/eval.rb +15 -2
  152. data/lib/rubocop/cop/security/json_load.rb +33 -11
  153. data/lib/rubocop/cop/style/access_modifier_declarations.rb +15 -4
  154. data/lib/rubocop/cop/style/accessor_grouping.rb +4 -2
  155. data/lib/rubocop/cop/style/alias.rb +4 -1
  156. data/lib/rubocop/cop/style/and_or.rb +1 -0
  157. data/lib/rubocop/cop/style/arguments_forwarding.rb +25 -7
  158. data/lib/rubocop/cop/style/array_intersect.rb +2 -2
  159. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
  160. data/lib/rubocop/cop/style/array_join.rb +4 -2
  161. data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
  162. data/lib/rubocop/cop/style/attr.rb +5 -2
  163. data/lib/rubocop/cop/style/bare_percent_literals.rb +4 -3
  164. data/lib/rubocop/cop/style/begin_block.rb +3 -1
  165. data/lib/rubocop/cop/style/block_delimiters.rb +27 -34
  166. data/lib/rubocop/cop/style/case_equality.rb +15 -13
  167. data/lib/rubocop/cop/style/class_and_module_children.rb +11 -2
  168. data/lib/rubocop/cop/style/collection_compact.rb +36 -16
  169. data/lib/rubocop/cop/style/colon_method_call.rb +3 -1
  170. data/lib/rubocop/cop/style/concat_array_literals.rb +2 -0
  171. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -18
  172. data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
  173. data/lib/rubocop/cop/style/copyright.rb +1 -1
  174. data/lib/rubocop/cop/style/documentation.rb +6 -6
  175. data/lib/rubocop/cop/style/documentation_method.rb +8 -8
  176. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  177. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  178. data/lib/rubocop/cop/style/each_with_object.rb +2 -0
  179. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  180. data/lib/rubocop/cop/style/empty_class_definition.rb +119 -0
  181. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  182. data/lib/rubocop/cop/style/empty_method.rb +0 -6
  183. data/lib/rubocop/cop/style/encoding.rb +7 -1
  184. data/lib/rubocop/cop/style/end_block.rb +3 -1
  185. data/lib/rubocop/cop/style/endless_method.rb +23 -5
  186. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  187. data/lib/rubocop/cop/style/file_open.rb +84 -0
  188. data/lib/rubocop/cop/style/float_division.rb +15 -1
  189. data/lib/rubocop/cop/style/for.rb +3 -0
  190. data/lib/rubocop/cop/style/format_string_token.rb +49 -5
  191. data/lib/rubocop/cop/style/global_vars.rb +5 -2
  192. data/lib/rubocop/cop/style/guard_clause.rb +27 -22
  193. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +27 -9
  194. data/lib/rubocop/cop/style/hash_lookup_method.rb +101 -0
  195. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  196. data/lib/rubocop/cop/style/hash_transform_keys.rb +17 -7
  197. data/lib/rubocop/cop/style/hash_transform_values.rb +17 -7
  198. data/lib/rubocop/cop/style/if_inside_else.rb +1 -5
  199. data/lib/rubocop/cop/style/if_unless_modifier.rb +57 -17
  200. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +12 -12
  201. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +4 -1
  202. data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -5
  203. data/lib/rubocop/cop/style/inline_comment.rb +4 -1
  204. data/lib/rubocop/cop/style/ip_addresses.rb +1 -2
  205. data/lib/rubocop/cop/style/lambda_call.rb +8 -8
  206. data/lib/rubocop/cop/style/magic_comment_format.rb +2 -2
  207. data/lib/rubocop/cop/style/map_join.rb +123 -0
  208. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
  209. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
  210. data/lib/rubocop/cop/style/method_def_parentheses.rb +2 -4
  211. data/lib/rubocop/cop/style/module_member_existence_check.rb +107 -0
  212. data/lib/rubocop/cop/style/multiline_if_then.rb +4 -4
  213. data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -4
  214. data/lib/rubocop/cop/style/mutable_constant.rb +1 -1
  215. data/lib/rubocop/cop/style/negative_array_index.rb +220 -0
  216. data/lib/rubocop/cop/style/nil_comparison.rb +11 -10
  217. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  218. data/lib/rubocop/cop/style/non_nil_check.rb +5 -11
  219. data/lib/rubocop/cop/style/not.rb +2 -0
  220. data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
  221. data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
  222. data/lib/rubocop/cop/style/one_line_conditional.rb +21 -12
  223. data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
  224. data/lib/rubocop/cop/style/parallel_assignment.rb +6 -2
  225. data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
  226. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -0
  227. data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
  228. data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
  229. data/lib/rubocop/cop/style/proc.rb +3 -2
  230. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  231. data/lib/rubocop/cop/style/reduce_to_hash.rb +184 -0
  232. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  233. data/lib/rubocop/cop/style/redundant_begin.rb +3 -3
  234. data/lib/rubocop/cop/style/redundant_condition.rb +5 -2
  235. data/lib/rubocop/cop/style/redundant_each.rb +3 -3
  236. data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
  237. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
  238. data/lib/rubocop/cop/style/redundant_format.rb +26 -5
  239. data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
  240. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
  241. data/lib/rubocop/cop/style/redundant_line_continuation.rb +16 -0
  242. data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
  243. data/lib/rubocop/cop/style/redundant_parentheses.rb +26 -22
  244. data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
  245. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
  246. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
  247. data/lib/rubocop/cop/style/redundant_return.rb +3 -1
  248. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
  249. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  250. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +114 -0
  251. data/lib/rubocop/cop/style/reverse_find.rb +51 -0
  252. data/lib/rubocop/cop/style/safe_navigation.rb +7 -7
  253. data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
  254. data/lib/rubocop/cop/style/select_by_range.rb +197 -0
  255. data/lib/rubocop/cop/style/select_by_regexp.rb +51 -21
  256. data/lib/rubocop/cop/style/semicolon.rb +25 -7
  257. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  258. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -1
  259. data/lib/rubocop/cop/style/single_line_methods.rb +3 -1
  260. data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -1
  261. data/lib/rubocop/cop/style/special_global_vars.rb +6 -1
  262. data/lib/rubocop/cop/style/super_arguments.rb +2 -2
  263. data/lib/rubocop/cop/style/symbol_proc.rb +4 -3
  264. data/lib/rubocop/cop/style/tally_method.rb +181 -0
  265. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
  266. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  267. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
  268. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
  269. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  270. data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
  271. data/lib/rubocop/cop/team.rb +4 -4
  272. data/lib/rubocop/cop/util.rb +2 -3
  273. data/lib/rubocop/cop/utils/format_string.rb +10 -0
  274. data/lib/rubocop/cop/variable_force/branch.rb +30 -6
  275. data/lib/rubocop/cops_documentation_generator.rb +4 -4
  276. data/lib/rubocop/directive_comment.rb +48 -4
  277. data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
  278. data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -1
  279. data/lib/rubocop/formatter/formatter_set.rb +2 -2
  280. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  281. data/lib/rubocop/formatter/simple_text_formatter.rb +0 -2
  282. data/lib/rubocop/formatter/tap_formatter.rb +5 -2
  283. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
  284. data/lib/rubocop/formatter.rb +22 -21
  285. data/lib/rubocop/lsp/diagnostic.rb +18 -33
  286. data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
  287. data/lib/rubocop/lsp/routes.rb +12 -5
  288. data/lib/rubocop/lsp/runtime.rb +13 -3
  289. data/lib/rubocop/lsp/stdin_runner.rb +8 -17
  290. data/lib/rubocop/magic_comment.rb +20 -0
  291. data/lib/rubocop/mcp/server.rb +200 -0
  292. data/lib/rubocop/options.rb +10 -1
  293. data/lib/rubocop/path_util.rb +14 -2
  294. data/lib/rubocop/plugin/loader.rb +1 -1
  295. data/lib/rubocop/rake_task.rb +1 -1
  296. data/lib/rubocop/remote_config.rb +10 -8
  297. data/lib/rubocop/result_cache.rb +60 -37
  298. data/lib/rubocop/rspec/cop_helper.rb +8 -0
  299. data/lib/rubocop/rspec/shared_contexts.rb +18 -5
  300. data/lib/rubocop/rspec/support.rb +2 -1
  301. data/lib/rubocop/runner.rb +12 -3
  302. data/lib/rubocop/server/cache.rb +6 -29
  303. data/lib/rubocop/server/core.rb +2 -0
  304. data/lib/rubocop/target_finder.rb +1 -1
  305. data/lib/rubocop/target_ruby.rb +31 -14
  306. data/lib/rubocop/version.rb +2 -2
  307. data/lib/rubocop.rb +20 -0
  308. data/lib/ruby_lsp/rubocop/addon.rb +23 -8
  309. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
  310. metadata +33 -9
@@ -7,8 +7,16 @@ module RuboCop
7
7
  # the configuration.
8
8
  #
9
9
  # @example EnforcedStyle: no_empty_lines (default)
10
- # # good
10
+ # # bad
11
+ # class Foo
12
+ #
13
+ # def bar
14
+ # # ...
15
+ # end
16
+ #
17
+ # end
11
18
  #
19
+ # # good
12
20
  # class Foo
13
21
  # def bar
14
22
  # # ...
@@ -16,8 +24,14 @@ module RuboCop
16
24
  # end
17
25
  #
18
26
  # @example EnforcedStyle: empty_lines
19
- # # good
27
+ # # bad
28
+ # class Foo
29
+ # def bar
30
+ # # ...
31
+ # end
32
+ # end
20
33
  #
34
+ # # good
21
35
  # class Foo
22
36
  #
23
37
  # def bar
@@ -7,8 +7,16 @@ module RuboCop
7
7
  # the configuration.
8
8
  #
9
9
  # @example EnforcedStyle: no_empty_lines (default)
10
- # # good
10
+ # # bad
11
+ # module Foo
12
+ #
13
+ # def bar
14
+ # # ...
15
+ # end
16
+ #
17
+ # end
11
18
  #
19
+ # # good
12
20
  # module Foo
13
21
  # def bar
14
22
  # # ...
@@ -16,8 +24,14 @@ module RuboCop
16
24
  # end
17
25
  #
18
26
  # @example EnforcedStyle: empty_lines
19
- # # good
27
+ # # bad
28
+ # module Foo
29
+ # def bar
30
+ # # ...
31
+ # end
32
+ # end
20
33
  #
34
+ # # good
21
35
  # module Foo
22
36
  #
23
37
  # def bar
@@ -123,16 +123,23 @@ module RuboCop
123
123
  AlignmentCorrector.align_end(corrector, processed_source, node, alignment_node(node))
124
124
  end
125
125
 
126
+ # rubocop:disable Metrics/CyclomaticComplexity
126
127
  def check_assignment(node, rhs)
127
128
  # If there are method calls chained to the right hand side of the
128
129
  # assignment, we let rhs be the receiver of those method calls before
129
130
  # we check if it's an if/unless/while/until.
130
131
  return unless (rhs = first_part_of_call_chain(rhs))
131
- return unless rhs.conditional?
132
+
133
+ # If `rhs` is a `begin` node or a logical operator,
134
+ # unwrap to find the leading conditional.
135
+ rhs = rhs.child_nodes.first while rhs&.type?(:begin, :or, :and)
136
+
137
+ return unless rhs&.conditional?
132
138
  return if rhs.if_type? && rhs.ternary?
133
139
 
134
140
  check_asgn_alignment(node, rhs)
135
141
  end
142
+ # rubocop:enable Metrics/CyclomaticComplexity
136
143
 
137
144
  def check_asgn_alignment(outer_node, inner_node)
138
145
  align_with = {
@@ -172,7 +172,40 @@ module RuboCop
172
172
  end
173
173
 
174
174
  def autocorrect(corrector, node)
175
- AlignmentCorrector.correct(corrector, processed_source, node, column_delta)
175
+ return unless node
176
+
177
+ send_node = node.parent
178
+ return unless send_node
179
+
180
+ top_level_send = find_top_level_send(send_node)
181
+ node_to_correct =
182
+ should_correct_entire_chain?(send_node, top_level_send) ? top_level_send : node
183
+
184
+ AlignmentCorrector.correct(corrector, processed_source, node_to_correct, column_delta)
185
+ end
186
+
187
+ def should_correct_entire_chain?(send_node, top_level_send)
188
+ return false unless style == :special_for_inner_method_call_in_parentheses
189
+ return false unless inner_call?(top_level_send)
190
+ return false unless display_column(send_node.source_range) < column_delta.abs
191
+
192
+ top_level_send != send_node || begins_its_line?(top_level_send.loc.end)
193
+ end
194
+
195
+ def inner_call?(top_level_send)
196
+ outer_call = top_level_send.parent
197
+
198
+ outer_call&.send_type? && outer_call.parenthesized?
199
+ end
200
+
201
+ def find_top_level_send(send_node)
202
+ top_level_send = send_node
203
+ while top_level_send.parent&.send_type? &&
204
+ top_level_send.parent.receiver == top_level_send &&
205
+ top_level_send.parent.loc.dot
206
+ top_level_send = top_level_send.parent
207
+ end
208
+ top_level_send
176
209
  end
177
210
 
178
211
  def bare_operator?(node)
@@ -20,6 +20,27 @@ module RuboCop
20
20
  # # good
21
21
  # [:a, :b]
22
22
  #
23
+ # @example AllowImplicitArrayLiterals: false (default)
24
+ #
25
+ # # bad
26
+ # a = b,
27
+ # c
28
+ #
29
+ # # good
30
+ # a =
31
+ # b,
32
+ # c
33
+ #
34
+ # @example AllowImplicitArrayLiterals: true
35
+ #
36
+ # # good
37
+ # a = b,
38
+ # c
39
+ #
40
+ # a =
41
+ # b,
42
+ # c
43
+ #
23
44
  # @example AllowMultilineFinalElement: false (default)
24
45
  #
25
46
  # # bad
@@ -48,6 +69,7 @@ module RuboCop
48
69
 
49
70
  def on_array(node)
50
71
  return if !node.loc.begin && !assignment_on_same_line?(node)
72
+ return if allow_implicit_array_brackets? && !node.bracketed?
51
73
 
52
74
  check_children_line_break(node, node.children, ignore_last: ignore_last_element?)
53
75
  end
@@ -59,6 +81,10 @@ module RuboCop
59
81
  /\s*=\s*$/.match?(source)
60
82
  end
61
83
 
84
+ def allow_implicit_array_brackets?
85
+ !!cop_config['AllowImplicitArrayLiterals']
86
+ end
87
+
62
88
  def ignore_last_element?
63
89
  !!cop_config['AllowMultilineFinalElement']
64
90
  end
@@ -135,7 +135,13 @@ module RuboCop
135
135
  private
136
136
 
137
137
  def autocorrect(corrector, node)
138
- AlignmentCorrector.correct(corrector, processed_source, node, @column_delta)
138
+ line_range = if !node.is_a?(AST::Node) || node.value.first_line <= node.key.first_line
139
+ node
140
+ else
141
+ processed_source.buffer.line_range(node.loc.line)
142
+ end
143
+
144
+ AlignmentCorrector.correct(corrector, processed_source, line_range, @column_delta)
139
145
  end
140
146
 
141
147
  def brace_alignment_style
@@ -8,40 +8,40 @@ module RuboCop
8
8
  #
9
9
  # @example
10
10
  #
11
- # # bad
12
- # { a: 1,
13
- # b: 2}
11
+ # # bad
12
+ # { a: 1,
13
+ # b: 2}
14
14
  #
15
- # # good
16
- # {
17
- # a: 1,
18
- # b: 2 }
15
+ # # good
16
+ # {
17
+ # a: 1,
18
+ # b: 2 }
19
19
  #
20
- # # good
21
- # {
22
- # a: 1, b: {
23
- # c: 3
24
- # }}
20
+ # # good
21
+ # {
22
+ # a: 1, b: {
23
+ # c: 3
24
+ # }}
25
25
  #
26
26
  # @example AllowMultilineFinalElement: false (default)
27
27
  #
28
- # # bad
29
- # { a: 1, b: {
30
- # c: 3
31
- # }}
28
+ # # bad
29
+ # { a: 1, b: {
30
+ # c: 3
31
+ # }}
32
32
  #
33
33
  # @example AllowMultilineFinalElement: true
34
34
  #
35
- # # bad
36
- # { a: 1,
37
- # b: {
38
- # c: 3
39
- # }}
35
+ # # bad
36
+ # { a: 1,
37
+ # b: {
38
+ # c: 3
39
+ # }}
40
40
  #
41
- # # good
42
- # { a: 1, b: {
43
- # c: 3
44
- # }}
41
+ # # good
42
+ # { a: 1, b: {
43
+ # c: 3
44
+ # }}
45
45
  #
46
46
  class FirstHashElementLineBreak < Base
47
47
  include FirstElementLineBreak
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Check that the keys, separators, and values of a multi-line hash
6
+ # Checks that the keys, separators, and values of a multi-line hash
7
7
  # literal are aligned according to configuration. The configuration
8
8
  # options are:
9
9
  #
@@ -193,7 +193,6 @@ module RuboCop
193
193
  SEPARATOR_ALIGNMENT_STYLES = %w[EnforcedColonStyle EnforcedHashRocketStyle].freeze
194
194
 
195
195
  def on_send(node)
196
- return if double_splat?(node)
197
196
  return unless node.arguments?
198
197
 
199
198
  last_argument = node.last_argument
@@ -233,6 +232,8 @@ module RuboCop
233
232
  end
234
233
 
235
234
  def argument_before_hash(hash_node)
235
+ return hash_node.children.first.children.first if hash_node.children.first.kwsplat_type?
236
+
236
237
  hash_node.left_sibling.respond_to?(:loc) ? hash_node.left_sibling : nil
237
238
  end
238
239
 
@@ -241,10 +242,6 @@ module RuboCop
241
242
  self.column_deltas = Hash.new { |hash, key| hash[key] = {} }
242
243
  end
243
244
 
244
- def double_splat?(node)
245
- node.children.last.is_a?(Symbol)
246
- end
247
-
248
245
  def check_pairs(node)
249
246
  first_pair = node.pairs.first
250
247
  reset!
@@ -168,7 +168,7 @@ module RuboCop
168
168
 
169
169
  def subsequent_closing_parentheses_in_same_line?(outermost_send)
170
170
  last_arg_of_outer_send = outermost_send.last_argument
171
- return false unless last_arg_of_outer_send&.loc.respond_to?(:end) &&
171
+ return false unless last_arg_of_outer_send&.loc?(:end) &&
172
172
  (end_of_last_arg_of_outer_send = last_arg_of_outer_send.loc.end)
173
173
 
174
174
  end_of_outer_send = outermost_send.loc.end
@@ -230,7 +230,7 @@ module RuboCop
230
230
 
231
231
  def find_most_bottom_of_heredoc_end(arguments)
232
232
  arguments.filter_map do |argument|
233
- argument.loc.heredoc_end.end_pos if argument.loc.respond_to?(:heredoc_end)
233
+ argument.loc.heredoc_end.end_pos if argument.loc?(:heredoc_end)
234
234
  end.max
235
235
  end
236
236
 
@@ -21,6 +21,23 @@ module RuboCop
21
21
  # something
22
22
  # RUBY
23
23
  #
24
+ # @example AllCops:ActiveSupportExtensionsEnabled: false (default)
25
+ # # good
26
+ # <<-RUBY.squish
27
+ # something
28
+ # RUBY
29
+ #
30
+ # @example AllCops:ActiveSupportExtensionsEnabled: true
31
+ # # bad
32
+ # <<-RUBY.squish
33
+ # something
34
+ # RUBY
35
+ #
36
+ # # good
37
+ # <<~RUBY.squish
38
+ # something
39
+ # RUBY
40
+ #
24
41
  class HeredocIndentation < Base
25
42
  include Alignment
26
43
  include Heredoc
@@ -33,6 +50,11 @@ module RuboCop
33
50
  'heredoc by using `<<~` instead of `%<current_indent_type>s`.'
34
51
  WIDTH_MSG = 'Use %<indentation_width>d spaces for indentation in a heredoc.'
35
52
 
53
+ # @!method squish_method?(node)
54
+ def_node_matcher :squish_method?, <<~PATTERN
55
+ (send _ {:squish :squish!})
56
+ PATTERN
57
+
36
58
  def on_heredoc(node)
37
59
  body = heredoc_body(node)
38
60
  return if body.strip.empty?
@@ -44,7 +66,7 @@ module RuboCop
44
66
  expected_indent_level = base_indent_level(node) + configured_indentation_width
45
67
  return if expected_indent_level == body_indent_level
46
68
  else
47
- return unless body_indent_level.zero?
69
+ return unless body_indent_level.zero? || heredoc_squish?(node)
48
70
  end
49
71
 
50
72
  return if line_too_long?(node)
@@ -60,6 +82,8 @@ module RuboCop
60
82
  add_offense(node.loc.heredoc_body, message: message) do |corrector|
61
83
  if heredoc_indent_type == '~'
62
84
  adjust_squiggly(corrector, node)
85
+ elsif heredoc_squish?(node)
86
+ adjust_heredoc_squish(corrector, node)
63
87
  else
64
88
  adjust_minus(corrector, node)
65
89
  end
@@ -89,6 +113,7 @@ module RuboCop
89
113
  end
90
114
 
91
115
  def line_too_long?(node)
116
+ return false unless max_line_length
92
117
  return false if unlimited_heredoc_length?
93
118
 
94
119
  body = heredoc_body(node)
@@ -108,8 +133,9 @@ module RuboCop
108
133
  config.for_cop('Layout/LineLength')['AllowHeredoc']
109
134
  end
110
135
 
111
- def max_line_length
112
- config.for_cop('Layout/LineLength')['Max']
136
+ def adjust_heredoc_squish(corrector, node)
137
+ adjust_squiggly(corrector, node)
138
+ adjust_minus(corrector, node)
113
139
  end
114
140
 
115
141
  def adjust_squiggly(corrector, node)
@@ -159,6 +185,10 @@ module RuboCop
159
185
  def heredoc_end(node)
160
186
  node.loc.heredoc_end.source
161
187
  end
188
+
189
+ def heredoc_squish?(node)
190
+ active_support_extensions_enabled? && squish_method?(node.parent)
191
+ end
162
192
  end
163
193
  end
164
194
  end
@@ -99,7 +99,7 @@ module RuboCop
99
99
 
100
100
  if str.heredoc?
101
101
  ranges << loc.heredoc_body
102
- elsif loc.respond_to?(:begin) && loc.begin
102
+ elsif str.loc?(:begin)
103
103
  ranges << loc.expression
104
104
  end
105
105
  end
@@ -5,6 +5,8 @@ module RuboCop
5
5
  module Layout
6
6
  # Checks for indentation that doesn't use the specified number of spaces.
7
7
  # The indentation width can be configured using the `Width` setting. The default width is 2.
8
+ # The block body indentation for method chain blocks can be configured using the
9
+ # `EnforcedStyleAlignWith` setting.
8
10
  #
9
11
  # See also the `Layout/IndentationConsistency` cop which is the companion to this one.
10
12
  #
@@ -41,7 +43,22 @@ module RuboCop
41
43
  # end
42
44
  # end
43
45
  # end
46
+ #
47
+ # @example EnforcedStyleAlignWith: start_of_line (default)
48
+ # # good
49
+ # records.uniq { |el| el[:profile_id] }
50
+ # .map do |message|
51
+ # SomeJob.perform_later(message[:id])
52
+ # end
53
+ #
54
+ # @example EnforcedStyleAlignWith: relative_to_receiver
55
+ # # good
56
+ # records.uniq { |el| el[:profile_id] }
57
+ # .map do |message|
58
+ # SomeJob.perform_later(message[:id])
59
+ # end
44
60
  class IndentationWidth < Base # rubocop:disable Metrics/ClassLength
61
+ include ConfigurableEnforcedStyle
45
62
  include EndKeywordAlignment
46
63
  include Alignment
47
64
  include CheckAssignment
@@ -50,7 +67,7 @@ module RuboCop
50
67
  extend AutoCorrector
51
68
 
52
69
  MSG = 'Use %<configured_indentation_width>d (not %<indentation>d) ' \
53
- 'spaces for%<name>s indentation.'
70
+ '%<indentation_type>s for%<name>s indentation.'
54
71
 
55
72
  # @!method access_modifier?(node)
56
73
  def_node_matcher :access_modifier?, <<~PATTERN
@@ -83,9 +100,11 @@ module RuboCop
83
100
 
84
101
  return unless begins_its_line?(end_loc)
85
102
 
86
- check_indentation(end_loc, node.body)
103
+ base_loc = block_body_indentation_base(node, end_loc)
104
+ check_indentation(base_loc, node.body)
87
105
 
88
106
  return unless indented_internal_methods_style?
107
+ return unless contains_access_modifier?(node.body)
89
108
 
90
109
  check_members(end_loc, [node.body])
91
110
  end
@@ -145,7 +164,7 @@ module RuboCop
145
164
  end
146
165
 
147
166
  def on_case_match(case_match)
148
- case_match.each_in_pattern do |in_pattern_node|
167
+ case_match.in_pattern_branches.each do |in_pattern_node|
149
168
  check_indentation(in_pattern_node.loc.keyword, in_pattern_node.body)
150
169
  end
151
170
 
@@ -164,6 +183,8 @@ module RuboCop
164
183
  private
165
184
 
166
185
  def autocorrect(corrector, node)
186
+ return unless node
187
+
167
188
  AlignmentCorrector.correct(corrector, processed_source, node, @column_delta)
168
189
  end
169
190
 
@@ -172,7 +193,7 @@ module RuboCop
172
193
 
173
194
  return unless members.any? && members.first.begin_type?
174
195
 
175
- if indentation_consistency_style == 'indented_internal_methods'
196
+ if indented_internal_methods_style?
176
197
  check_members_for_indented_internal_methods_style(members)
177
198
  else
178
199
  check_members_for_normal_style(base, members)
@@ -301,10 +322,32 @@ module RuboCop
301
322
  end
302
323
 
303
324
  def message(configured_indentation_width, indentation, name)
325
+ if using_tabs?
326
+ message_for_tabs(configured_indentation_width, indentation, name)
327
+ else
328
+ message_for_spaces(configured_indentation_width, indentation, name)
329
+ end
330
+ end
331
+
332
+ def message_for_tabs(configured_indentation_width, indentation, name)
333
+ configured_tabs = 1
334
+ actual_tabs = indentation / configured_indentation_width
335
+
336
+ format(
337
+ MSG,
338
+ configured_indentation_width: configured_tabs,
339
+ indentation: actual_tabs,
340
+ indentation_type: 'tabs',
341
+ name: name
342
+ )
343
+ end
344
+
345
+ def message_for_spaces(configured_indentation_width, indentation, name)
304
346
  format(
305
347
  MSG,
306
348
  configured_indentation_width: configured_indentation_width,
307
349
  indentation: indentation,
350
+ indentation_type: 'spaces',
308
351
  name: name
309
352
  )
310
353
  end
@@ -360,7 +403,13 @@ module RuboCop
360
403
  def offending_range(body_node, indentation)
361
404
  expr = body_node.source_range
362
405
  begin_pos = expr.begin_pos
363
- ind = expr.begin_pos - indentation
406
+
407
+ ind = if using_tabs?
408
+ begin_pos - line_indentation(expr).length
409
+ else
410
+ begin_pos - indentation
411
+ end
412
+
364
413
  pos = indentation >= 0 ? ind..begin_pos : begin_pos..ind
365
414
  range_between(pos.begin, pos.end)
366
415
  end
@@ -374,8 +423,47 @@ module RuboCop
374
423
  starting_node.send_type? && starting_node.bare_access_modifier?
375
424
  end
376
425
 
377
- def configured_indentation_width
378
- cop_config['Width']
426
+ def contains_access_modifier?(body_node)
427
+ return false unless body_node&.begin_type?
428
+
429
+ body_node.children.any? { |child| child.send_type? && child.bare_access_modifier? }
430
+ end
431
+
432
+ def indentation_style
433
+ config.for_cop('Layout/IndentationStyle')['EnforcedStyle'] || 'spaces'
434
+ end
435
+
436
+ def using_tabs?
437
+ indentation_style == 'tabs'
438
+ end
439
+
440
+ def column_offset_between(base_range, range)
441
+ return super unless using_tabs?
442
+
443
+ base_uses_tabs = line_uses_tabs?(base_range)
444
+ range_uses_tabs = line_uses_tabs?(range)
445
+
446
+ return super unless base_uses_tabs || range_uses_tabs
447
+
448
+ visual_column(base_range) - visual_column(range)
449
+ end
450
+
451
+ def line_indentation(range)
452
+ line = processed_source.lines[range.line - 1]
453
+ line[0...range.column]
454
+ end
455
+
456
+ def line_uses_tabs?(range)
457
+ line_indentation(range).include?("\t")
458
+ end
459
+
460
+ def visual_column(range)
461
+ indentation = line_indentation(range)
462
+
463
+ tab_count = indentation.count("\t")
464
+ space_count = indentation.count(' ')
465
+
466
+ (tab_count * configured_indentation_width) + space_count
379
467
  end
380
468
 
381
469
  def leftmost_modifier_of(node)
@@ -383,6 +471,22 @@ module RuboCop
383
471
 
384
472
  leftmost_modifier_of(node.parent)
385
473
  end
474
+
475
+ def block_body_indentation_base(node, end_loc)
476
+ if style == :relative_to_receiver && dot_on_new_line?(node)
477
+ node.send_node.loc.dot
478
+ else
479
+ end_loc
480
+ end
481
+ end
482
+
483
+ def dot_on_new_line?(node)
484
+ send_node = node.send_node
485
+ return false unless send_node.loc?(:dot)
486
+
487
+ receiver = send_node.receiver
488
+ receiver && receiver.last_line < send_node.loc.dot.line
489
+ end
386
490
  end
387
491
  end
388
492
  end
@@ -101,7 +101,7 @@ module RuboCop
101
101
  ranges << loc.expression
102
102
  elsif literal.heredoc?
103
103
  ranges << loc.heredoc_body
104
- elsif (loc.respond_to?(:begin) && loc.begin) || ignored_parent?(literal)
104
+ elsif literal.loc?(:begin) || ignored_parent?(literal)
105
105
  ranges << loc.expression
106
106
  end
107
107
  end