rubocop 1.71.1 → 1.88.2

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 (590) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +23 -19
  4. data/config/default.yml +513 -149
  5. data/config/internal_affairs.yml +20 -0
  6. data/config/obsoletion.yml +38 -4
  7. data/exe/rubocop +1 -8
  8. data/lib/rubocop/cache_config.rb +29 -0
  9. data/lib/rubocop/cli/command/auto_generate_config.rb +36 -4
  10. data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
  11. data/lib/rubocop/cli/command/lsp.rb +1 -1
  12. data/lib/rubocop/cli/command/mcp.rb +19 -0
  13. data/lib/rubocop/cli/command/show_cops.rb +2 -2
  14. data/lib/rubocop/cli/command/show_docs_url.rb +4 -8
  15. data/lib/rubocop/cli/command/suggest_extensions.rb +8 -2
  16. data/lib/rubocop/cli.rb +48 -11
  17. data/lib/rubocop/comment_config.rb +60 -18
  18. data/lib/rubocop/config.rb +53 -16
  19. data/lib/rubocop/config_finder.rb +1 -1
  20. data/lib/rubocop/config_loader.rb +65 -49
  21. data/lib/rubocop/config_loader_resolver.rb +44 -19
  22. data/lib/rubocop/config_obsoletion/extracted_cop.rb +6 -3
  23. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  24. data/lib/rubocop/config_obsoletion.rb +46 -2
  25. data/lib/rubocop/config_store.rb +7 -2
  26. data/lib/rubocop/config_validator.rb +7 -6
  27. data/lib/rubocop/cop/autocorrect_logic.rb +27 -14
  28. data/lib/rubocop/cop/base.rb +38 -12
  29. data/lib/rubocop/cop/bundler/gem_comment.rb +5 -3
  30. data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
  31. data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -3
  32. data/lib/rubocop/cop/commissioner.rb +13 -11
  33. data/lib/rubocop/cop/correctors/alignment_corrector.rb +26 -7
  34. data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
  35. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +1 -1
  36. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
  37. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -1
  38. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -5
  39. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +8 -1
  40. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +36 -2
  41. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  42. data/lib/rubocop/cop/correctors.rb +28 -0
  43. data/lib/rubocop/cop/documentation.rb +2 -3
  44. data/lib/rubocop/cop/exclude_limit.rb +31 -5
  45. data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
  46. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  47. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +49 -17
  48. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +2 -3
  49. data/lib/rubocop/cop/gemspec/require_mfa.rb +22 -5
  50. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +12 -7
  51. data/lib/rubocop/cop/internal_affairs/example_description.rb +9 -5
  52. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
  53. data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
  54. data/lib/rubocop/cop/internal_affairs/location_exists.rb +142 -0
  55. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
  56. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +13 -13
  57. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  58. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -1
  59. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +6 -2
  60. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +92 -0
  61. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  62. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  63. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  64. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +5 -3
  65. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +13 -2
  66. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
  67. data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
  68. data/lib/rubocop/cop/internal_affairs.rb +3 -16
  69. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -2
  70. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  71. data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
  72. data/lib/rubocop/cop/layout/block_alignment.rb +60 -4
  73. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  74. data/lib/rubocop/cop/layout/case_indentation.rb +3 -1
  75. data/lib/rubocop/cop/layout/class_structure.rb +56 -10
  76. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
  77. data/lib/rubocop/cop/layout/comment_indentation.rb +9 -2
  78. data/lib/rubocop/cop/layout/condition_position.rb +13 -3
  79. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  80. data/lib/rubocop/cop/layout/dot_position.rb +2 -2
  81. data/lib/rubocop/cop/layout/else_alignment.rb +2 -15
  82. data/lib/rubocop/cop/layout/empty_comment.rb +8 -10
  83. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +28 -9
  84. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +46 -21
  85. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +101 -0
  86. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +34 -4
  87. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +8 -29
  88. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
  89. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +13 -2
  90. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +17 -3
  91. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
  92. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
  93. data/lib/rubocop/cop/layout/end_alignment.rb +10 -3
  94. data/lib/rubocop/cop/layout/first_argument_indentation.rb +35 -2
  95. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +26 -0
  96. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +20 -15
  97. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
  98. data/lib/rubocop/cop/layout/hash_alignment.rb +5 -8
  99. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +3 -3
  100. data/lib/rubocop/cop/layout/heredoc_indentation.rb +33 -3
  101. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  102. data/lib/rubocop/cop/layout/indentation_width.rb +152 -7
  103. data/lib/rubocop/cop/layout/leading_comment_space.rb +13 -1
  104. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  105. data/lib/rubocop/cop/layout/line_length.rb +62 -15
  106. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +57 -57
  107. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +9 -2
  108. data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -0
  109. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +56 -56
  110. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
  111. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +236 -41
  112. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  113. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +9 -5
  114. data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
  115. data/lib/rubocop/cop/layout/redundant_line_break.rb +12 -6
  116. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +15 -7
  117. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  118. data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
  119. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  120. data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -3
  121. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  122. data/lib/rubocop/cop/layout/space_around_operators.rb +18 -3
  123. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
  124. data/lib/rubocop/cop/layout/space_before_brackets.rb +6 -39
  125. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
  126. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +12 -3
  127. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -0
  128. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
  129. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  130. data/lib/rubocop/cop/lint/ambiguous_assignment.rb +1 -11
  131. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  132. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +1 -10
  133. data/lib/rubocop/cop/lint/ambiguous_range.rb +5 -0
  134. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
  135. data/lib/rubocop/cop/lint/assignment_in_condition.rb +13 -1
  136. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  137. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -8
  138. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +4 -3
  139. data/lib/rubocop/cop/lint/constant_reassignment.rb +93 -11
  140. data/lib/rubocop/cop/lint/constant_resolution.rb +6 -6
  141. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +90 -0
  142. data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
  143. data/lib/rubocop/cop/lint/debugger.rb +13 -4
  144. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  145. data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
  146. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +5 -2
  147. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  148. data/lib/rubocop/cop/lint/duplicate_methods.rb +219 -32
  149. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
  150. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  151. data/lib/rubocop/cop/lint/empty_block.rb +4 -4
  152. data/lib/rubocop/cop/lint/empty_conditional_body.rb +20 -65
  153. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  154. data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
  155. data/lib/rubocop/cop/lint/empty_interpolation.rb +14 -1
  156. data/lib/rubocop/cop/lint/empty_when.rb +8 -1
  157. data/lib/rubocop/cop/lint/ensure_return.rb +19 -1
  158. data/lib/rubocop/cop/lint/erb_new_arguments.rb +4 -8
  159. data/lib/rubocop/cop/lint/float_comparison.rb +33 -10
  160. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  161. data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
  162. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -1
  163. data/lib/rubocop/cop/lint/interpolation_check.rb +25 -5
  164. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  165. data/lib/rubocop/cop/lint/literal_as_condition.rb +129 -11
  166. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
  167. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +9 -12
  168. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +19 -10
  169. data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -2
  170. data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
  171. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  172. data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
  173. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +20 -0
  174. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +4 -2
  175. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +4 -4
  176. data/lib/rubocop/cop/lint/number_conversion.rb +19 -10
  177. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  178. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +11 -0
  179. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  180. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +7 -7
  181. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +3 -13
  182. data/lib/rubocop/cop/lint/raise_exception.rb +30 -11
  183. data/lib/rubocop/cop/lint/rand_one.rb +1 -1
  184. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +27 -10
  185. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +6 -12
  186. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +15 -4
  187. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  188. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -23
  189. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +134 -11
  190. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +12 -2
  191. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +268 -0
  192. data/lib/rubocop/cop/lint/redundant_with_index.rb +4 -1
  193. data/lib/rubocop/cop/lint/redundant_with_object.rb +8 -0
  194. data/lib/rubocop/cop/lint/refinement_import_methods.rb +8 -1
  195. data/lib/rubocop/cop/lint/regexp_as_condition.rb +9 -1
  196. data/lib/rubocop/cop/lint/require_parentheses.rb +13 -4
  197. data/lib/rubocop/cop/lint/require_range_parentheses.rb +3 -2
  198. data/lib/rubocop/cop/lint/require_relative_self_path.rb +7 -5
  199. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  200. data/lib/rubocop/cop/lint/rescue_type.rb +2 -2
  201. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  202. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +22 -4
  203. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +7 -1
  204. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
  205. data/lib/rubocop/cop/lint/script_permission.rb +5 -1
  206. data/lib/rubocop/cop/lint/self_assignment.rb +63 -6
  207. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -1
  208. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  209. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  210. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +27 -1
  211. data/lib/rubocop/cop/lint/shared_mutable_default.rb +14 -1
  212. data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
  213. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  214. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +123 -0
  215. data/lib/rubocop/cop/lint/symbol_conversion.rb +21 -4
  216. data/lib/rubocop/cop/lint/syntax.rb +25 -1
  217. data/lib/rubocop/cop/lint/to_enum_arguments.rb +36 -3
  218. data/lib/rubocop/cop/lint/to_json.rb +20 -17
  219. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  220. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +5 -1
  221. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +36 -10
  222. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +2 -0
  223. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -1
  224. data/lib/rubocop/cop/lint/unreachable_code.rb +17 -9
  225. data/lib/rubocop/cop/lint/unreachable_loop.rb +5 -5
  226. data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
  227. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  228. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
  229. data/lib/rubocop/cop/lint/useless_access_modifier.rb +30 -4
  230. data/lib/rubocop/cop/lint/useless_assignment.rb +55 -25
  231. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +71 -0
  232. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +92 -0
  233. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +11 -10
  234. data/lib/rubocop/cop/lint/useless_or.rb +111 -0
  235. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
  236. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +11 -7
  237. data/lib/rubocop/cop/lint/useless_setter_call.rb +4 -1
  238. data/lib/rubocop/cop/lint/useless_times.rb +22 -1
  239. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +147 -0
  240. data/lib/rubocop/cop/lint/void.rb +50 -21
  241. data/lib/rubocop/cop/message_annotator.rb +7 -3
  242. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  243. data/lib/rubocop/cop/metrics/block_length.rb +2 -1
  244. data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
  245. data/lib/rubocop/cop/metrics/collection_literal_length.rb +1 -1
  246. data/lib/rubocop/cop/metrics/method_length.rb +3 -2
  247. data/lib/rubocop/cop/metrics/perceived_complexity.rb +38 -7
  248. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  249. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  250. data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
  251. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  252. data/lib/rubocop/cop/migration/department_name.rb +12 -1
  253. data/lib/rubocop/cop/mixin/alignment.rb +3 -3
  254. data/lib/rubocop/cop/mixin/allowed_methods.rb +5 -5
  255. data/lib/rubocop/cop/mixin/allowed_pattern.rb +9 -5
  256. data/lib/rubocop/cop/mixin/check_line_breakable.rb +4 -4
  257. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +5 -7
  258. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  259. data/lib/rubocop/cop/mixin/comments_help.rb +1 -1
  260. data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
  261. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  262. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  263. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
  264. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  265. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +20 -0
  266. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -2
  267. data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
  268. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
  269. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
  270. data/lib/rubocop/cop/mixin/hash_subset.rb +27 -4
  271. data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
  272. data/lib/rubocop/cop/mixin/hash_transform_method.rb +32 -78
  273. data/lib/rubocop/cop/mixin/line_length_help.rb +45 -10
  274. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  275. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -1
  276. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  277. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  278. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  279. data/lib/rubocop/cop/mixin/project_index_help.rb +48 -0
  280. data/lib/rubocop/cop/mixin/range_help.rb +15 -3
  281. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  282. data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -7
  283. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  284. data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
  285. data/lib/rubocop/cop/mixin/trailing_comma.rb +25 -6
  286. data/lib/rubocop/cop/mixin.rb +86 -0
  287. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
  288. data/lib/rubocop/cop/naming/block_forwarding.rb +3 -3
  289. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  290. data/lib/rubocop/cop/naming/file_name.rb +6 -5
  291. data/lib/rubocop/cop/naming/inclusive_language.rb +8 -2
  292. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +11 -2
  293. data/lib/rubocop/cop/naming/method_name.rb +187 -15
  294. data/lib/rubocop/cop/naming/predicate_method.rb +330 -0
  295. data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +48 -4
  296. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -4
  297. data/lib/rubocop/cop/naming/variable_name.rb +51 -6
  298. data/lib/rubocop/cop/offense.rb +17 -1
  299. data/lib/rubocop/cop/registry.rb +66 -39
  300. data/lib/rubocop/cop/security/eval.rb +17 -3
  301. data/lib/rubocop/cop/security/io_methods.rb +2 -2
  302. data/lib/rubocop/cop/security/json_load.rb +33 -11
  303. data/lib/rubocop/cop/security/marshal_load.rb +1 -1
  304. data/lib/rubocop/cop/security/open.rb +1 -0
  305. data/lib/rubocop/cop/style/access_modifier_declarations.rb +45 -12
  306. data/lib/rubocop/cop/style/accessor_grouping.rb +46 -8
  307. data/lib/rubocop/cop/style/alias.rb +15 -3
  308. data/lib/rubocop/cop/style/and_or.rb +2 -1
  309. data/lib/rubocop/cop/style/arguments_forwarding.rb +46 -31
  310. data/lib/rubocop/cop/style/array_first_last.rb +12 -1
  311. data/lib/rubocop/cop/style/array_intersect.rb +117 -38
  312. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +50 -0
  313. data/lib/rubocop/cop/style/array_join.rb +4 -2
  314. data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
  315. data/lib/rubocop/cop/style/attr.rb +5 -2
  316. data/lib/rubocop/cop/style/bare_percent_literals.rb +4 -3
  317. data/lib/rubocop/cop/style/begin_block.rb +3 -1
  318. data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
  319. data/lib/rubocop/cop/style/block_delimiters.rb +42 -34
  320. data/lib/rubocop/cop/style/case_equality.rb +29 -15
  321. data/lib/rubocop/cop/style/case_like_if.rb +1 -1
  322. data/lib/rubocop/cop/style/character_literal.rb +2 -2
  323. data/lib/rubocop/cop/style/class_and_module_children.rb +67 -12
  324. data/lib/rubocop/cop/style/class_equality_comparison.rb +22 -14
  325. data/lib/rubocop/cop/style/class_methods_definitions.rb +11 -5
  326. data/lib/rubocop/cop/style/collection_compact.rb +37 -17
  327. data/lib/rubocop/cop/style/collection_methods.rb +1 -0
  328. data/lib/rubocop/cop/style/collection_querying.rb +167 -0
  329. data/lib/rubocop/cop/style/colon_method_call.rb +16 -7
  330. data/lib/rubocop/cop/style/combinable_loops.rb +6 -0
  331. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  332. data/lib/rubocop/cop/style/commented_keyword.rb +12 -5
  333. data/lib/rubocop/cop/style/comparable_between.rb +78 -0
  334. data/lib/rubocop/cop/style/comparable_clamp.rb +12 -1
  335. data/lib/rubocop/cop/style/concat_array_literals.rb +7 -1
  336. data/lib/rubocop/cop/style/conditional_assignment.rb +33 -24
  337. data/lib/rubocop/cop/style/constant_visibility.rb +20 -12
  338. data/lib/rubocop/cop/style/copyright.rb +22 -11
  339. data/lib/rubocop/cop/style/data_inheritance.rb +11 -0
  340. data/lib/rubocop/cop/style/date_time.rb +4 -4
  341. data/lib/rubocop/cop/style/def_with_parentheses.rb +22 -5
  342. data/lib/rubocop/cop/style/dig_chain.rb +6 -1
  343. data/lib/rubocop/cop/style/dir_empty.rb +4 -0
  344. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +1 -1
  345. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
  346. data/lib/rubocop/cop/style/documentation.rb +6 -6
  347. data/lib/rubocop/cop/style/documentation_method.rb +12 -8
  348. data/lib/rubocop/cop/style/double_negation.rb +3 -3
  349. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  350. data/lib/rubocop/cop/style/each_with_object.rb +4 -3
  351. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  352. data/lib/rubocop/cop/style/empty_case_condition.rb +12 -2
  353. data/lib/rubocop/cop/style/empty_class_definition.rb +126 -0
  354. data/lib/rubocop/cop/style/empty_heredoc.rb +4 -0
  355. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  356. data/lib/rubocop/cop/style/empty_literal.rb +11 -2
  357. data/lib/rubocop/cop/style/empty_method.rb +0 -6
  358. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +110 -0
  359. data/lib/rubocop/cop/style/encoding.rb +7 -1
  360. data/lib/rubocop/cop/style/end_block.rb +3 -1
  361. data/lib/rubocop/cop/style/endless_method.rb +181 -18
  362. data/lib/rubocop/cop/style/env_home.rb +4 -0
  363. data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
  364. data/lib/rubocop/cop/style/even_odd.rb +11 -1
  365. data/lib/rubocop/cop/style/exact_regexp_match.rb +8 -1
  366. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  367. data/lib/rubocop/cop/style/explicit_block_argument.rb +16 -3
  368. data/lib/rubocop/cop/style/exponential_notation.rb +5 -4
  369. data/lib/rubocop/cop/style/fetch_env_var.rb +33 -7
  370. data/lib/rubocop/cop/style/file_null.rb +4 -2
  371. data/lib/rubocop/cop/style/file_open.rb +84 -0
  372. data/lib/rubocop/cop/style/file_write.rb +21 -16
  373. data/lib/rubocop/cop/style/float_division.rb +15 -1
  374. data/lib/rubocop/cop/style/for.rb +4 -0
  375. data/lib/rubocop/cop/style/format_string.rb +17 -4
  376. data/lib/rubocop/cop/style/format_string_token.rb +85 -14
  377. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  378. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  379. data/lib/rubocop/cop/style/global_vars.rb +5 -2
  380. data/lib/rubocop/cop/style/guard_clause.rb +29 -23
  381. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +27 -9
  382. data/lib/rubocop/cop/style/hash_conversion.rb +28 -12
  383. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -2
  384. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  385. data/lib/rubocop/cop/style/hash_lookup_method.rb +102 -0
  386. data/lib/rubocop/cop/style/hash_slice.rb +16 -0
  387. data/lib/rubocop/cop/style/hash_syntax.rb +6 -1
  388. data/lib/rubocop/cop/style/hash_transform_keys.rb +19 -9
  389. data/lib/rubocop/cop/style/hash_transform_values.rb +19 -9
  390. data/lib/rubocop/cop/style/identical_conditional_branches.rb +18 -7
  391. data/lib/rubocop/cop/style/if_inside_else.rb +26 -20
  392. data/lib/rubocop/cop/style/if_unless_modifier.rb +83 -16
  393. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +16 -19
  394. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -2
  395. data/lib/rubocop/cop/style/if_with_semicolon.rb +16 -6
  396. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  397. data/lib/rubocop/cop/style/inline_comment.rb +5 -2
  398. data/lib/rubocop/cop/style/inverse_methods.rb +10 -6
  399. data/lib/rubocop/cop/style/invertible_unless_condition.rb +27 -7
  400. data/lib/rubocop/cop/style/ip_addresses.rb +3 -4
  401. data/lib/rubocop/cop/style/it_assignment.rb +69 -12
  402. data/lib/rubocop/cop/style/it_block_parameter.rb +121 -0
  403. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +4 -0
  404. data/lib/rubocop/cop/style/keyword_parameters_order.rb +20 -10
  405. data/lib/rubocop/cop/style/lambda.rb +8 -1
  406. data/lib/rubocop/cop/style/lambda_call.rb +26 -10
  407. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  408. data/lib/rubocop/cop/style/magic_comment_format.rb +3 -3
  409. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +11 -0
  410. data/lib/rubocop/cop/style/map_into_array.rb +5 -2
  411. data/lib/rubocop/cop/style/map_join.rb +123 -0
  412. data/lib/rubocop/cop/style/map_to_hash.rb +12 -3
  413. data/lib/rubocop/cop/style/map_to_set.rb +1 -3
  414. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +9 -8
  415. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
  416. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +33 -4
  417. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -5
  418. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -1
  419. data/lib/rubocop/cop/style/method_def_parentheses.rb +7 -5
  420. data/lib/rubocop/cop/style/min_max_comparison.rb +17 -6
  421. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +10 -7
  422. data/lib/rubocop/cop/style/mixin_usage.rb +1 -1
  423. data/lib/rubocop/cop/style/module_function.rb +4 -2
  424. data/lib/rubocop/cop/style/module_member_existence_check.rb +110 -0
  425. data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -1
  426. data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
  427. data/lib/rubocop/cop/style/multiline_if_then.rb +4 -4
  428. data/lib/rubocop/cop/style/multiline_memoization.rb +7 -1
  429. data/lib/rubocop/cop/style/multiline_method_signature.rb +13 -16
  430. data/lib/rubocop/cop/style/mutable_constant.rb +106 -12
  431. data/lib/rubocop/cop/style/negative_array_index.rb +220 -0
  432. data/lib/rubocop/cop/style/next.rb +44 -0
  433. data/lib/rubocop/cop/style/nil_comparison.rb +11 -10
  434. data/lib/rubocop/cop/style/nil_lambda.rb +9 -1
  435. data/lib/rubocop/cop/style/non_nil_check.rb +5 -11
  436. data/lib/rubocop/cop/style/not.rb +2 -0
  437. data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
  438. data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
  439. data/lib/rubocop/cop/style/object_then.rb +1 -0
  440. data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
  441. data/lib/rubocop/cop/style/one_line_conditional.rb +21 -12
  442. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  443. data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
  444. data/lib/rubocop/cop/style/option_hash.rb +1 -1
  445. data/lib/rubocop/cop/style/optional_arguments.rb +1 -0
  446. data/lib/rubocop/cop/style/parallel_assignment.rb +57 -25
  447. data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
  448. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +4 -0
  449. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  450. data/lib/rubocop/cop/style/perl_backrefs.rb +5 -3
  451. data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
  452. data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
  453. data/lib/rubocop/cop/style/proc.rb +4 -2
  454. data/lib/rubocop/cop/style/raise_args.rb +9 -9
  455. data/lib/rubocop/cop/style/reduce_to_hash.rb +200 -0
  456. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  457. data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
  458. data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
  459. data/lib/rubocop/cop/style/redundant_begin.rb +38 -3
  460. data/lib/rubocop/cop/style/redundant_condition.rb +61 -1
  461. data/lib/rubocop/cop/style/redundant_constant_base.rb +5 -5
  462. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +26 -4
  463. data/lib/rubocop/cop/style/redundant_each.rb +3 -3
  464. data/lib/rubocop/cop/style/redundant_exception.rb +7 -1
  465. data/lib/rubocop/cop/style/redundant_fetch_block.rb +2 -10
  466. data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
  467. data/lib/rubocop/cop/style/redundant_format.rb +312 -0
  468. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
  469. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +6 -1
  470. data/lib/rubocop/cop/style/redundant_interpolation.rb +12 -3
  471. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
  472. data/lib/rubocop/cop/style/redundant_line_continuation.rb +28 -7
  473. data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
  474. data/lib/rubocop/cop/style/redundant_parentheses.rb +111 -37
  475. data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
  476. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
  477. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +2 -2
  478. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +12 -0
  479. data/lib/rubocop/cop/style/redundant_return.rb +3 -1
  480. data/lib/rubocop/cop/style/redundant_self.rb +20 -7
  481. data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -1
  482. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
  483. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  484. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  485. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +133 -0
  486. data/lib/rubocop/cop/style/regexp_literal.rb +32 -3
  487. data/lib/rubocop/cop/style/rescue_modifier.rb +6 -3
  488. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  489. data/lib/rubocop/cop/style/reverse_find.rb +51 -0
  490. data/lib/rubocop/cop/style/safe_navigation.rb +67 -20
  491. data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
  492. data/lib/rubocop/cop/style/select_by_range.rb +197 -0
  493. data/lib/rubocop/cop/style/select_by_regexp.rb +53 -20
  494. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  495. data/lib/rubocop/cop/style/semicolon.rb +45 -12
  496. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  497. data/lib/rubocop/cop/style/single_line_do_end_block.rb +21 -6
  498. data/lib/rubocop/cop/style/single_line_methods.rb +13 -8
  499. data/lib/rubocop/cop/style/sole_nested_conditional.rb +77 -101
  500. data/lib/rubocop/cop/style/special_global_vars.rb +6 -1
  501. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -1
  502. data/lib/rubocop/cop/style/string_concatenation.rb +18 -15
  503. data/lib/rubocop/cop/style/string_hash_keys.rb +1 -0
  504. data/lib/rubocop/cop/style/struct_inheritance.rb +24 -2
  505. data/lib/rubocop/cop/style/super_arguments.rb +3 -4
  506. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  507. data/lib/rubocop/cop/style/symbol_proc.rb +10 -7
  508. data/lib/rubocop/cop/style/tally_method.rb +181 -0
  509. data/lib/rubocop/cop/style/ternary_parentheses.rb +11 -0
  510. data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -2
  511. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +52 -1
  512. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  513. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +2 -2
  514. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  515. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
  516. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +18 -19
  517. data/lib/rubocop/cop/style/trivial_accessors.rb +2 -2
  518. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  519. data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
  520. data/lib/rubocop/cop/style/while_until_do.rb +7 -0
  521. data/lib/rubocop/cop/style/while_until_modifier.rb +16 -1
  522. data/lib/rubocop/cop/style/word_array.rb +1 -0
  523. data/lib/rubocop/cop/style/yoda_condition.rb +1 -1
  524. data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
  525. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -3
  526. data/lib/rubocop/cop/team.rb +105 -40
  527. data/lib/rubocop/cop/util.rb +4 -5
  528. data/lib/rubocop/cop/utils/format_string.rb +20 -5
  529. data/lib/rubocop/cop/variable_force/assignment.rb +7 -3
  530. data/lib/rubocop/cop/variable_force/branch.rb +30 -6
  531. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  532. data/lib/rubocop/cop/variable_force/variable.rb +10 -3
  533. data/lib/rubocop/cop/variable_force.rb +26 -9
  534. data/lib/rubocop/cops_documentation_generator.rb +23 -7
  535. data/lib/rubocop/directive_comment.rb +80 -3
  536. data/lib/rubocop/ext/regexp_node.rb +0 -1
  537. data/lib/rubocop/file_patterns.rb +9 -1
  538. data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
  539. data/lib/rubocop/formatter/disabled_config_formatter.rb +38 -13
  540. data/lib/rubocop/formatter/formatter_set.rb +2 -2
  541. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  542. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  543. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  544. data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
  545. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  546. data/lib/rubocop/formatter/pacman_formatter.rb +2 -1
  547. data/lib/rubocop/formatter/simple_text_formatter.rb +0 -2
  548. data/lib/rubocop/formatter/tap_formatter.rb +5 -2
  549. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
  550. data/lib/rubocop/formatter.rb +22 -21
  551. data/lib/rubocop/lsp/diagnostic.rb +22 -37
  552. data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
  553. data/lib/rubocop/lsp/routes.rb +47 -11
  554. data/lib/rubocop/lsp/runtime.rb +19 -8
  555. data/lib/rubocop/lsp/server.rb +0 -2
  556. data/lib/rubocop/lsp/stdin_runner.rb +11 -18
  557. data/lib/rubocop/magic_comment.rb +28 -0
  558. data/lib/rubocop/mcp/server.rb +200 -0
  559. data/lib/rubocop/options.rb +60 -14
  560. data/lib/rubocop/path_util.rb +18 -2
  561. data/lib/rubocop/pending_cops_reporter.rb +56 -0
  562. data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
  563. data/lib/rubocop/plugin/load_error.rb +26 -0
  564. data/lib/rubocop/plugin/loader.rb +100 -0
  565. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  566. data/lib/rubocop/plugin.rb +46 -0
  567. data/lib/rubocop/project_index_loader.rb +66 -0
  568. data/lib/rubocop/rake_task.rb +5 -2
  569. data/lib/rubocop/remote_config.rb +10 -8
  570. data/lib/rubocop/result_cache.rb +72 -47
  571. data/lib/rubocop/rspec/cop_helper.rb +21 -1
  572. data/lib/rubocop/rspec/expect_offense.rb +9 -3
  573. data/lib/rubocop/rspec/shared_contexts.rb +71 -3
  574. data/lib/rubocop/rspec/support.rb +4 -0
  575. data/lib/rubocop/runner.rb +188 -65
  576. data/lib/rubocop/server/cache.rb +56 -41
  577. data/lib/rubocop/server/cli.rb +2 -2
  578. data/lib/rubocop/server/client_command/base.rb +10 -0
  579. data/lib/rubocop/server/client_command/exec.rb +2 -1
  580. data/lib/rubocop/server/client_command/start.rb +11 -1
  581. data/lib/rubocop/server/core.rb +8 -0
  582. data/lib/rubocop/target_finder.rb +21 -10
  583. data/lib/rubocop/target_ruby.rb +31 -14
  584. data/lib/rubocop/version.rb +50 -10
  585. data/lib/rubocop.rb +47 -96
  586. data/lib/ruby_lsp/rubocop/addon.rb +29 -17
  587. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +99 -0
  588. metadata +86 -16
  589. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  590. data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +0 -50
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module LSP
5
+ # Builds LSP text edits for rubocop:disable comments.
6
+ # @api private
7
+ class DisableCommentEdits
8
+ def initialize(offense:, document_encoding:, processed_source:)
9
+ @offense = offense
10
+ @document_encoding = document_encoding
11
+ @processed_source = processed_source
12
+ end
13
+
14
+ def edits
15
+ literal_range = multiline_literal_range
16
+ return block_disable_comments(literal_range) if literal_range
17
+
18
+ inline_disable_comment
19
+ end
20
+
21
+ private
22
+
23
+ def inline_disable_comment
24
+ eol = position(@offense.line - 1, @offense.source_line.length, @offense.source_line)
25
+ [text_edit(eol, inline_comment_text)]
26
+ end
27
+
28
+ def inline_comment_text
29
+ if @offense.source_line.include?(' # rubocop:disable ')
30
+ ",#{@offense.cop_name}"
31
+ else
32
+ " # rubocop:disable #{@offense.cop_name}"
33
+ end
34
+ end
35
+
36
+ def block_disable_comments(range)
37
+ full_line_range = range_by_lines(range)
38
+ leading_whitespace = full_line_range.source_line[/^\s*/].to_s
39
+ [
40
+ disable_edit(full_line_range.first_line, leading_whitespace),
41
+ enable_edit(full_line_range, leading_whitespace)
42
+ ]
43
+ end
44
+
45
+ def disable_edit(first_line, leading_whitespace)
46
+ position = position(first_line - 1, 0, '')
47
+ text_edit(position, "#{leading_whitespace}# rubocop:disable #{@offense.cop_name}\n")
48
+ end
49
+
50
+ def enable_edit(full_line_range, leading_whitespace)
51
+ last_line = full_line_range.last_line
52
+ last_line_text = full_line_range.source_buffer.source_line(last_line)
53
+ position = position(last_line - 1, last_line_text.length, last_line_text)
54
+ text_edit(position, "\n#{leading_whitespace}# rubocop:enable #{@offense.cop_name}")
55
+ end
56
+
57
+ def text_edit(position, new_text)
58
+ range = LanguageServer::Protocol::Interface::Range.new(start: position, end: position)
59
+ LanguageServer::Protocol::Interface::TextEdit.new(range: range, new_text: new_text)
60
+ end
61
+
62
+ def position(line, utf8_index, line_text)
63
+ LanguageServer::Protocol::Interface::Position.new(
64
+ line: line,
65
+ character: position_character(utf8_index, line_text)
66
+ )
67
+ end
68
+
69
+ def position_character(utf8_index, line_text)
70
+ str = line_text[0, utf8_index]
71
+ if @document_encoding == Encoding::UTF_16LE || @document_encoding.nil?
72
+ str.length + str.b.count("\xf0-\xff".b)
73
+ else
74
+ str.length
75
+ end
76
+ end
77
+
78
+ def multiline_literal_range
79
+ return unless @processed_source&.ast
80
+
81
+ offense_range = @offense.location
82
+ multiline_ranges&.find do |range|
83
+ eol_comment_would_be_inside_literal?(offense_range, range)
84
+ end
85
+ end
86
+
87
+ def multiline_ranges
88
+ @processed_source.ast.each_node.filter_map do |node|
89
+ if surrounding_heredoc?(node)
90
+ heredoc_range(node)
91
+ elsif string_continuation?(node)
92
+ range_by_lines(node.source_range)
93
+ elsif surrounding_percent_array?(node) || multiline_string?(node)
94
+ node.source_range
95
+ end
96
+ end
97
+ end
98
+
99
+ def eol_comment_would_be_inside_literal?(offense_range, literal_range)
100
+ offense_line = offense_range.line
101
+ offense_line >= literal_range.first_line && offense_line < literal_range.last_line
102
+ end
103
+
104
+ def surrounding_heredoc?(node)
105
+ node.any_str_type? && node.heredoc?
106
+ end
107
+
108
+ def heredoc_range(node)
109
+ node.source_range.join(node.loc.heredoc_end)
110
+ end
111
+
112
+ def surrounding_percent_array?(node)
113
+ node.array_type? && node.percent_literal?
114
+ end
115
+
116
+ def string_continuation?(node)
117
+ node.any_str_type? && node.source.match?(/\\\s*$/)
118
+ end
119
+
120
+ def multiline_string?(node)
121
+ node.dstr_type? && node.multiline?
122
+ end
123
+
124
+ def range_by_lines(range)
125
+ begin_of_first_line = range.begin_pos - range.column
126
+
127
+ last_line = range.source_buffer.source_line(range.last_line)
128
+ last_line_offset = last_line.length - range.last_column
129
+ end_of_last_line = range.end_pos + last_line_offset
130
+
131
+ Parser::Source::Range.new(range.source_buffer, begin_of_first_line, end_of_last_line)
132
+ end
133
+ end
134
+ end
135
+ end
@@ -51,7 +51,7 @@ module RuboCop
51
51
  capabilities: LanguageServer::Protocol::Interface::ServerCapabilities.new(
52
52
  document_formatting_provider: true,
53
53
  text_document_sync: LanguageServer::Protocol::Interface::TextDocumentSyncOptions.new(
54
- change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::FULL,
54
+ change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::INCREMENTAL,
55
55
  open_close: true
56
56
  )
57
57
  )
@@ -61,9 +61,16 @@ module RuboCop
61
61
 
62
62
  handle 'initialized' do |_request|
63
63
  version = RuboCop::Version::STRING
64
- yjit = Object.const_defined?('RubyVM::YJIT') && RubyVM::YJIT.enabled? ? ' +YJIT' : ''
65
-
66
- Logger.log("RuboCop #{version} language server#{yjit} initialized, PID #{Process.pid}")
64
+ # Only one JIT can be enabled at the same time, since YJIT and ZJIT are mutually exclusive.
65
+ jit = if Object.const_defined?('RubyVM::YJIT') && RubyVM::YJIT.enabled?
66
+ '+YJIT'
67
+ elsif Object.const_defined?('RubyVM::ZJIT') && RubyVM::ZJIT.enabled?
68
+ '+ZJIT'
69
+ else
70
+ ''
71
+ end
72
+
73
+ Logger.log("RuboCop #{version} language server#{jit} initialized, PID #{Process.pid}")
67
74
  end
68
75
 
69
76
  handle 'shutdown' do |request|
@@ -76,7 +83,12 @@ module RuboCop
76
83
 
77
84
  handle 'textDocument/didChange' do |request|
78
85
  params = request[:params]
79
- result = diagnostic(params[:textDocument][:uri], params[:contentChanges][0][:text])
86
+ file_uri = params[:textDocument][:uri]
87
+ text = @text_cache[file_uri]
88
+ params[:contentChanges].each do |content|
89
+ text = change_text(text, content[:text], content[:range])
90
+ end
91
+ result = diagnostic(file_uri, text)
80
92
  @server.write(result)
81
93
  end
82
94
 
@@ -194,17 +206,17 @@ module RuboCop
194
206
  return []
195
207
  end
196
208
 
197
- new_text = @server.format(remove_file_protocol_from(file_uri), text, command: command)
209
+ new_text = @server.format(convert_file_uri_to_path(file_uri), text, command: command)
198
210
 
199
211
  return [] if new_text == text
200
212
 
201
- [
213
+ [{
202
214
  newText: new_text,
203
215
  range: {
204
216
  start: { line: 0, character: 0 },
205
217
  end: { line: text.count("\n") + 1, character: 0 }
206
218
  }
207
- ]
219
+ }]
208
220
  end
209
221
 
210
222
  def diagnostic(file_uri, text)
@@ -214,13 +226,37 @@ module RuboCop
214
226
  method: 'textDocument/publishDiagnostics',
215
227
  params: {
216
228
  uri: file_uri,
217
- diagnostics: @server.offenses(remove_file_protocol_from(file_uri), text)
229
+ diagnostics: @server.offenses(convert_file_uri_to_path(file_uri), text)
218
230
  }
219
231
  }
220
232
  end
221
233
 
222
- def remove_file_protocol_from(uri)
223
- uri.delete_prefix('file://')
234
+ def change_text(orig_text, text, range)
235
+ return text unless range
236
+
237
+ start_pos = text_pos(orig_text, range[:start])
238
+ end_pos = text_pos(orig_text, range[:end])
239
+ text_bin = orig_text.b
240
+ text_bin[start_pos...end_pos] = text.b
241
+ text_bin.force_encoding(orig_text.encoding)
242
+ end
243
+
244
+ def text_pos(text, range)
245
+ line = range[:line]
246
+ char = range[:character]
247
+ pos = 0
248
+ text.each_line.with_index do |l, i|
249
+ if i == line
250
+ pos += l.encode('utf-16be').b[0, char * 2].encode('utf-8', 'utf-16be').bytesize
251
+ return pos
252
+ end
253
+ pos += l.bytesize
254
+ end
255
+ pos
256
+ end
257
+
258
+ def convert_file_uri_to_path(uri)
259
+ URI.decode_www_form_component(uri.delete_prefix('file://'))
224
260
  end
225
261
  end
226
262
  end
@@ -20,15 +20,16 @@ module RuboCop
20
20
  attr_writer :safe_autocorrect, :lint_mode, :layout_mode
21
21
 
22
22
  def initialize(config_store)
23
+ RuboCop::LSP.enable
24
+
23
25
  @runner = RuboCop::Lsp::StdinRunner.new(config_store)
24
- @cop_registry = RuboCop::Cop::Registry.global.to_h
25
26
 
26
27
  @safe_autocorrect = true
27
28
  @lint_mode = false
28
29
  @layout_mode = false
29
30
  end
30
31
 
31
- def format(path, text, command:)
32
+ def format(path, text, command:, prism_result: nil)
32
33
  safe_autocorrect = if command
33
34
  command == 'rubocop.formatAutocorrects'
34
35
  else
@@ -38,24 +39,34 @@ module RuboCop
38
39
  formatting_options = { autocorrect: true, safe_autocorrect: safe_autocorrect }
39
40
  formatting_options[:only] = config_only_options if @lint_mode || @layout_mode
40
41
 
41
- @runner.run(path, text, formatting_options)
42
+ @runner.run(path, text, formatting_options, prism_result: prism_result)
42
43
  @runner.formatted_source
43
44
  end
44
45
 
45
- def offenses(path, text, document_encoding = nil)
46
+ def offenses(path, text, document_encoding = nil, prism_result: nil)
46
47
  diagnostic_options = {}
47
48
  diagnostic_options[:only] = config_only_options if @lint_mode || @layout_mode
48
49
 
49
- @runner.run(path, text, diagnostic_options)
50
+ @runner.run(path, text, diagnostic_options, prism_result: prism_result)
51
+ processed_source = @runner.processed_source
52
+ config = @runner.config_for_working_directory
50
53
  @runner.offenses.map do |offense|
51
- Diagnostic.new(
52
- document_encoding, offense, path, @cop_registry[offense.cop_name]&.first
53
- ).to_lsp_diagnostic(@runner.config_for_working_directory)
54
+ build_diagnostic(offense, path, document_encoding, processed_source, config)
54
55
  end
55
56
  end
56
57
 
57
58
  private
58
59
 
60
+ def build_diagnostic(offense, path, document_encoding, processed_source, config)
61
+ Diagnostic.new(
62
+ document_encoding,
63
+ offense,
64
+ path,
65
+ RuboCop::Cop::Registry.global.find_by_cop_name(offense.cop_name),
66
+ processed_source
67
+ ).to_lsp_diagnostic(config)
68
+ end
69
+
59
70
  def config_only_options
60
71
  only_options = []
61
72
  only_options << 'Lint' if @lint_mode
@@ -22,8 +22,6 @@ module RuboCop
22
22
  def initialize(config_store)
23
23
  $PROGRAM_NAME = "rubocop --lsp #{ConfigFinder.project_root}"
24
24
 
25
- RuboCop::LSP.enable
26
-
27
25
  @reader = LanguageServer::Protocol::Transport::Io::Reader.new($stdin)
28
26
  @writer = LanguageServer::Protocol::Transport::Io::Writer.new($stdout)
29
27
  @runtime = RuboCop::LSP::Runtime.new(config_store)
@@ -17,7 +17,7 @@ module RuboCop
17
17
  class StdinRunner < RuboCop::Runner
18
18
  class ConfigurationError < StandardError; end
19
19
 
20
- attr_reader :offenses, :config_for_working_directory
20
+ attr_reader :offenses, :config_for_working_directory, :processed_source
21
21
 
22
22
  DEFAULT_RUBOCOP_OPTIONS = {
23
23
  stderr: true,
@@ -40,11 +40,13 @@ module RuboCop
40
40
  super(@options, config_store)
41
41
  end
42
42
 
43
- # rubocop:disable Metrics/MethodLength
44
- def run(path, contents, options)
43
+ def run(path, contents, options, prism_result: nil)
45
44
  @options = options.merge(DEFAULT_RUBOCOP_OPTIONS)
46
45
  @options[:stdin] = contents
47
46
 
47
+ @prism_result = prism_result
48
+ @processed_source = nil
49
+
48
50
  @offenses = []
49
51
  @warnings = []
50
52
  @errors = []
@@ -52,22 +54,7 @@ module RuboCop
52
54
  super([path])
53
55
 
54
56
  raise Interrupt if aborting?
55
- rescue RuboCop::Runner::InfiniteCorrectionLoop => e
56
- if defined?(::RubyLsp::Requests::Formatting::Error)
57
- raise ::RubyLsp::Requests::Formatting::Error, e.message
58
- end
59
-
60
- raise e
61
- rescue RuboCop::ValidationError => e
62
- raise ConfigurationError, e.message
63
- rescue StandardError => e
64
- if defined?(::RubyLsp::Requests::Formatting::Error)
65
- raise ::RubyLsp::Requests::Support::InternalRuboCopError, e
66
- end
67
-
68
- raise e
69
57
  end
70
- # rubocop:enable Metrics/MethodLength
71
58
 
72
59
  def formatted_source
73
60
  @options[:stdin]
@@ -78,6 +65,12 @@ module RuboCop
78
65
  def file_finished(_file, offenses)
79
66
  @offenses = offenses
80
67
  end
68
+
69
+ def do_inspection_loop(file)
70
+ source, offenses = super
71
+ @processed_source = source
72
+ [source, offenses]
73
+ end
81
74
  end
82
75
  end
83
76
  end
@@ -11,6 +11,7 @@ module RuboCop
11
11
  KEYWORDS = {
12
12
  encoding: '(?:en)?coding',
13
13
  frozen_string_literal: 'frozen[_-]string[_-]literal',
14
+ rbs_inline: 'rbs_inline',
14
15
  shareable_constant_value: 'shareable[_-]constant[_-]value',
15
16
  typed: 'typed'
16
17
  }.freeze
@@ -36,6 +37,7 @@ module RuboCop
36
37
  def any?
37
38
  frozen_string_literal_specified? ||
38
39
  encoding_specified? ||
40
+ rbs_inline_specified? ||
39
41
  shareable_constant_value_specified? ||
40
42
  typed_specified?
41
43
  end
@@ -60,6 +62,10 @@ module RuboCop
60
62
  [true, false].include?(frozen_string_literal)
61
63
  end
62
64
 
65
+ def valid_rbs_inline_value?
66
+ %w[enabled disabled].include?(extract_rbs_inline_value)
67
+ end
68
+
63
69
  def valid_shareable_constant_value?
64
70
  %w[none literal experimental_everything experimental_copy].include?(shareable_constant_value)
65
71
  end
@@ -105,6 +111,10 @@ module RuboCop
105
111
  specified?(encoding)
106
112
  end
107
113
 
114
+ def rbs_inline_specified?
115
+ valid_rbs_inline_value?
116
+ end
117
+
108
118
  # Was the Sorbet `typed` sigil specified?
109
119
  #
110
120
  # @return [Boolean]
@@ -193,12 +203,19 @@ module RuboCop
193
203
  SEPARATOR = ';'
194
204
  OPERATOR = ':'
195
205
 
206
+ def new_frozen_string_literal(value)
207
+ "# -*- frozen_string_literal: #{value} -*-"
208
+ end
209
+
196
210
  private
197
211
 
198
212
  def extract_frozen_string_literal
199
213
  match(KEYWORDS[:frozen_string_literal])
200
214
  end
201
215
 
216
+ # Emacs comments cannot specify RBS::inline behavior.
217
+ def extract_rbs_inline_value; end
218
+
202
219
  def extract_shareable_constant_value
203
220
  match(KEYWORDS[:shareable_constant_value])
204
221
  end
@@ -238,6 +255,9 @@ module RuboCop
238
255
  # Vim comments cannot specify frozen string literal behavior.
239
256
  def frozen_string_literal; end
240
257
 
258
+ # Vim comments cannot specify RBS::inline behavior.
259
+ def extract_rbs_inline_value; end
260
+
241
261
  # Vim comments cannot specify shareable constant values behavior.
242
262
  def shareable_constant_value; end
243
263
 
@@ -275,6 +295,10 @@ module RuboCop
275
295
  end
276
296
  end
277
297
 
298
+ def new_frozen_string_literal(value)
299
+ "# frozen_string_literal: #{value}"
300
+ end
301
+
278
302
  private
279
303
 
280
304
  # Extract `frozen_string_literal`.
@@ -288,6 +312,10 @@ module RuboCop
288
312
  extract(/\A\s*#\s*#{KEYWORDS[:frozen_string_literal]}:\s*#{TOKEN}\s*\z/io)
289
313
  end
290
314
 
315
+ def extract_rbs_inline_value
316
+ extract(/\A\s*#\s*#{KEYWORDS[:rbs_inline]}:\s*#{TOKEN}\s*\z/io)
317
+ end
318
+
291
319
  def extract_shareable_constant_value
292
320
  extract(/\A\s*#\s*#{KEYWORDS[:shareable_constant_value]}:\s*#{TOKEN}\s*\z/io)
293
321
  end
@@ -0,0 +1,200 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'mcp'
5
+
6
+ required_mcp_version = '0.6.0'
7
+
8
+ if Gem::Version.new(required_mcp_version) > Gem::Version.new(MCP::VERSION)
9
+ # While `mcp` is not a runtime dependency, users may have an outdated version installed.
10
+ warn <<~MESSAGE
11
+ Error: `mcp` gem version #{MCP::VERSION} was loaded, but `rubocop --mcp` requires #{required_mcp_version}.
12
+ - If you're using Bundler and don't yet have `gem 'mcp'` as a dependency, add it now.
13
+ - If you're using Bundler and already have `gem 'mcp'` as a dependency, update it to the most recent version.
14
+ - If you don't use Bundler, run `gem update mcp`.
15
+ MESSAGE
16
+ exit!
17
+ end
18
+ rescue LoadError => e
19
+ raise unless e.path == 'mcp'
20
+
21
+ warn <<~MESSAGE
22
+ Error: Unable to load `mcp` gem. Add `gem 'mcp', '~> 0.6'` to your Gemfile, or run `gem install mcp`.
23
+ MESSAGE
24
+
25
+ exit!
26
+ end
27
+
28
+ require_relative '../lsp'
29
+ require_relative '../lsp/runtime'
30
+
31
+ module RuboCop
32
+ module MCP
33
+ # RuboCop MCP Server.
34
+ # @api private
35
+ class Server
36
+ def initialize(config_store)
37
+ @config_store = config_store
38
+ @runtime = RuboCop::LSP::Runtime.new(@config_store)
39
+ @options = {}
40
+ end
41
+
42
+ def start
43
+ # No `protocol_version` is specified because draft feature by default can be used.
44
+ server = ::MCP::Server.new(
45
+ name: 'rubocop_mcp_server',
46
+ version: RuboCop::Version::STRING,
47
+ tools: [inspection_tool, autocorrection_tool]
48
+ )
49
+
50
+ ::MCP::Server::Transports::StdioTransport.new(server).open
51
+ end
52
+
53
+ private
54
+
55
+ def inspection_tool
56
+ build_tool(
57
+ name: 'rubocop_inspection',
58
+ description: 'Inspect Ruby code for offenses. ' \
59
+ 'Provide `source_code` to check inline code or `path` to check files.',
60
+ title: "RuboCop's inspection",
61
+ destructive_hint: false,
62
+ idempotent_hint: true,
63
+ read_only_hint: true,
64
+ safety_required: false
65
+ ) do |path, source_code|
66
+ run_inspection(path, source_code)
67
+ end
68
+ end
69
+
70
+ def autocorrection_tool
71
+ build_tool(
72
+ name: 'rubocop_autocorrection',
73
+ description: 'Autocorrect RuboCop offenses in Ruby code. ' \
74
+ 'Provide `source_code` to correct inline code or `path` to correct files. ' \
75
+ 'Set `safety` to false to include unsafe corrections.',
76
+ title: "RuboCop's autocorrection",
77
+ destructive_hint: true,
78
+ idempotent_hint: false,
79
+ read_only_hint: false,
80
+ safety_required: true
81
+ ) do |path, source_code, safety|
82
+ run_autocorrection(path, source_code, safety)
83
+ end
84
+ end
85
+
86
+ def run_inspection(path, source_code)
87
+ if source_code
88
+ offenses = @runtime.offenses(path || 'example.rb', source_code, source_code.encoding)
89
+ offenses.to_json
90
+ else
91
+ process_files(path, filter_empty: true) do |file, source|
92
+ offenses = @runtime.offenses(file, source, source.encoding)
93
+
94
+ { path: PathUtil.relative_path(file), offenses: offenses }
95
+ end
96
+ end
97
+ end
98
+
99
+ def run_autocorrection(path, source_code, safety)
100
+ command = safety ? 'rubocop.formatAutocorrects' : 'rubocop.formatAutocorrectsAll'
101
+
102
+ if source_code
103
+ @runtime.format(path || 'example.rb', source_code, command: command).tap do |corrected|
104
+ write_file(path, corrected) if path
105
+ end
106
+ else
107
+ process_files(path) do |file, source|
108
+ @runtime.format(file, source, command: command).then do |corrected|
109
+ write_file(file, corrected)
110
+
111
+ { path: PathUtil.relative_path(file), corrected: source != corrected }
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ def process_files(path, filter_empty: false)
118
+ target_finder = RuboCop::TargetFinder.new(@config_store, @options)
119
+ target_files = target_finder.find(path ? [path] : [], :only_recognized_file_types)
120
+ all_files = target_files.map { |file| yield(file, read_file(file)) }
121
+ files = filter_empty ? all_files.reject { |f| f[:offenses]&.empty? } : all_files
122
+
123
+ { files: files, summary: build_summary(target_files, all_files) }.to_json
124
+ end
125
+
126
+ def read_file(file)
127
+ config = @config_store.for_file(file)
128
+ RuboCop::ProcessedSource.from_file(
129
+ file, config.target_ruby_version, parser_engine: config.parser_engine
130
+ ).raw_source
131
+ rescue Errno::ENOENT
132
+ raise RuboCop::Error, "No such file or directory: #{file}"
133
+ end
134
+
135
+ def write_file(file, content)
136
+ File.write(file, content)
137
+ rescue Errno::EACCES
138
+ raise RuboCop::Error, "Permission denied: #{file}"
139
+ rescue Errno::ENOSPC
140
+ raise RuboCop::Error, "No space left on device: #{file}"
141
+ rescue Errno::EROFS
142
+ raise RuboCop::Error, "Read-only file system: #{file}"
143
+ end
144
+
145
+ # NOTE: It is useful for RuboCop's result summary to be shown in the LLM's responses
146
+ # during interactions, so the summary is returned in a form that is easy for the LLM
147
+ # to reason about. Since LLM execution is non-deterministic, it is also sensible to
148
+ # compute the summary deterministically at this stage.
149
+ def build_summary(target_files, files)
150
+ summary = { target_file_count: target_files.count }
151
+ if files.first&.key?(:offenses)
152
+ summary[:offense_count] = files.sum { |f| f[:offenses].size }
153
+ else
154
+ summary[:corrected_file_count] = files.count { |f| f[:corrected] }
155
+ end
156
+ summary
157
+ end
158
+
159
+ # rubocop:disable Metrics/MethodLength, Metrics/ParameterLists
160
+ def build_tool(
161
+ name:, description:,
162
+ title:, destructive_hint:, idempotent_hint:, read_only_hint:, safety_required:
163
+ )
164
+ if safety_required
165
+ safety_property = { safety: { type: 'boolean' } }
166
+ required = ['safety']
167
+ else
168
+ safety_property = {}
169
+ required = nil
170
+ end
171
+
172
+ ::MCP::Tool.define(
173
+ name: name,
174
+ description: description,
175
+ input_schema: {
176
+ properties: {
177
+ path: { type: 'string' },
178
+ source_code: { type: 'string' }
179
+ }.merge(safety_property),
180
+ required: required
181
+ }.compact,
182
+ annotations: {
183
+ title: title,
184
+ destructive_hint: destructive_hint,
185
+ idempotent_hint: idempotent_hint,
186
+ open_world_hint: false,
187
+ read_only_hint: read_only_hint
188
+ }
189
+ ) do |path: nil, source_code: nil, safety: true|
190
+ result = yield(path, source_code, safety)
191
+
192
+ ::MCP::Tool::Response.new([{ type: 'text', text: result }])
193
+ rescue RuboCop::Error => e
194
+ ::MCP::Tool::Response.new([{ type: 'text', text: e.message }], error: true)
195
+ end
196
+ end
197
+ # rubocop:enable Metrics/MethodLength, Metrics/ParameterLists
198
+ end
199
+ end
200
+ end