rubocop 1.72.1 → 1.81.7

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 (316) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +22 -18
  3. data/config/default.yml +240 -65
  4. data/config/internal_affairs.yml +20 -0
  5. data/config/obsoletion.yml +8 -3
  6. data/exe/rubocop +1 -8
  7. data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
  8. data/lib/rubocop/cli.rb +19 -4
  9. data/lib/rubocop/config.rb +35 -6
  10. data/lib/rubocop/config_loader.rb +8 -40
  11. data/lib/rubocop/config_loader_resolver.rb +9 -7
  12. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -3
  13. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  14. data/lib/rubocop/config_obsoletion.rb +46 -2
  15. data/lib/rubocop/config_store.rb +5 -0
  16. data/lib/rubocop/config_validator.rb +7 -6
  17. data/lib/rubocop/cop/autocorrect_logic.rb +22 -14
  18. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
  19. data/lib/rubocop/cop/correctors/alignment_corrector.rb +7 -4
  20. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
  21. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +5 -2
  22. data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
  23. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +37 -15
  24. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  25. data/lib/rubocop/cop/gemspec/require_mfa.rb +15 -1
  26. data/lib/rubocop/cop/internal_affairs/example_description.rb +9 -5
  27. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +4 -4
  28. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +6 -2
  29. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +92 -0
  30. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  31. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  32. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +6 -1
  33. data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
  34. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  35. data/lib/rubocop/cop/layout/block_alignment.rb +2 -2
  36. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  37. data/lib/rubocop/cop/layout/class_structure.rb +36 -1
  38. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
  39. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  40. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  41. data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
  42. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  43. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +32 -14
  44. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +101 -0
  45. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +34 -4
  46. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +8 -29
  47. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
  48. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +1 -1
  49. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
  50. data/lib/rubocop/cop/layout/hash_alignment.rb +4 -7
  51. data/lib/rubocop/cop/layout/indentation_width.rb +1 -0
  52. data/lib/rubocop/cop/layout/leading_comment_space.rb +13 -1
  53. data/lib/rubocop/cop/layout/line_length.rb +43 -10
  54. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
  55. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  56. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +9 -5
  57. data/lib/rubocop/cop/layout/redundant_line_break.rb +9 -5
  58. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +11 -5
  59. data/lib/rubocop/cop/layout/space_after_semicolon.rb +10 -0
  60. data/lib/rubocop/cop/layout/space_around_keyword.rb +6 -1
  61. data/lib/rubocop/cop/layout/space_around_operators.rb +12 -1
  62. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
  63. data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -38
  64. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +12 -3
  65. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -0
  66. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
  67. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  68. data/lib/rubocop/cop/lint/ambiguous_range.rb +5 -0
  69. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
  70. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  71. data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -5
  72. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
  73. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +13 -7
  74. data/lib/rubocop/cop/lint/debugger.rb +2 -4
  75. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  76. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +5 -2
  77. data/lib/rubocop/cop/lint/duplicate_methods.rb +111 -23
  78. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
  79. data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
  80. data/lib/rubocop/cop/lint/empty_interpolation.rb +14 -1
  81. data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
  82. data/lib/rubocop/cop/lint/float_comparison.rb +32 -10
  83. data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
  84. data/lib/rubocop/cop/lint/literal_as_condition.rb +124 -10
  85. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +17 -8
  86. data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -2
  87. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  88. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
  89. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +1 -0
  90. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  91. data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
  92. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  93. data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
  94. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +101 -2
  95. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +43 -13
  96. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  97. data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
  98. data/lib/rubocop/cop/lint/require_range_parentheses.rb +1 -1
  99. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  100. data/lib/rubocop/cop/lint/rescue_type.rb +1 -1
  101. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  102. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +4 -4
  103. data/lib/rubocop/cop/lint/self_assignment.rb +31 -5
  104. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  105. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +13 -1
  106. data/lib/rubocop/cop/lint/shared_mutable_default.rb +12 -1
  107. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  108. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
  109. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  110. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +2 -0
  111. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -0
  112. data/lib/rubocop/cop/lint/unreachable_loop.rb +5 -5
  113. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
  114. data/lib/rubocop/cop/lint/useless_access_modifier.rb +30 -4
  115. data/lib/rubocop/cop/lint/useless_assignment.rb +2 -0
  116. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +9 -12
  117. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +90 -0
  118. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +1 -0
  119. data/lib/rubocop/cop/lint/useless_or.rb +98 -0
  120. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
  121. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +3 -3
  122. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +121 -0
  123. data/lib/rubocop/cop/lint/void.rb +16 -2
  124. data/lib/rubocop/cop/message_annotator.rb +7 -3
  125. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  126. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  127. data/lib/rubocop/cop/metrics/method_length.rb +1 -0
  128. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  129. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  130. data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
  131. data/lib/rubocop/cop/mixin/check_line_breakable.rb +3 -3
  132. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -2
  133. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  134. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  135. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
  136. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  137. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
  138. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -2
  139. data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
  140. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
  141. data/lib/rubocop/cop/mixin/hash_subset.rb +19 -4
  142. data/lib/rubocop/cop/mixin/line_length_help.rb +24 -8
  143. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -0
  144. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -0
  145. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  146. data/lib/rubocop/cop/mixin/range_help.rb +12 -0
  147. data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
  148. data/lib/rubocop/cop/mixin/trailing_comma.rb +18 -2
  149. data/lib/rubocop/cop/naming/block_forwarding.rb +3 -3
  150. data/lib/rubocop/cop/naming/file_name.rb +2 -2
  151. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  152. data/lib/rubocop/cop/naming/method_name.rb +187 -15
  153. data/lib/rubocop/cop/naming/predicate_method.rb +319 -0
  154. data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +4 -4
  155. data/lib/rubocop/cop/naming/variable_name.rb +51 -6
  156. data/lib/rubocop/cop/registry.rb +9 -6
  157. data/lib/rubocop/cop/security/eval.rb +2 -1
  158. data/lib/rubocop/cop/security/json_load.rb +33 -11
  159. data/lib/rubocop/cop/security/open.rb +1 -0
  160. data/lib/rubocop/cop/style/access_modifier_declarations.rb +32 -10
  161. data/lib/rubocop/cop/style/accessor_grouping.rb +32 -6
  162. data/lib/rubocop/cop/style/arguments_forwarding.rb +21 -24
  163. data/lib/rubocop/cop/style/array_intersect.rb +113 -38
  164. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
  165. data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
  166. data/lib/rubocop/cop/style/block_delimiters.rb +3 -2
  167. data/lib/rubocop/cop/style/case_like_if.rb +1 -1
  168. data/lib/rubocop/cop/style/class_and_module_children.rb +48 -10
  169. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  170. data/lib/rubocop/cop/style/collection_methods.rb +1 -0
  171. data/lib/rubocop/cop/style/collection_querying.rb +167 -0
  172. data/lib/rubocop/cop/style/combinable_loops.rb +1 -0
  173. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  174. data/lib/rubocop/cop/style/commented_keyword.rb +12 -5
  175. data/lib/rubocop/cop/style/comparable_between.rb +78 -0
  176. data/lib/rubocop/cop/style/conditional_assignment.rb +26 -8
  177. data/lib/rubocop/cop/style/constant_visibility.rb +14 -9
  178. data/lib/rubocop/cop/style/data_inheritance.rb +7 -0
  179. data/lib/rubocop/cop/style/def_with_parentheses.rb +18 -5
  180. data/lib/rubocop/cop/style/dig_chain.rb +1 -1
  181. data/lib/rubocop/cop/style/double_negation.rb +3 -3
  182. data/lib/rubocop/cop/style/empty_literal.rb +4 -0
  183. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +100 -0
  184. data/lib/rubocop/cop/style/endless_method.rb +176 -18
  185. data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
  186. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  187. data/lib/rubocop/cop/style/explicit_block_argument.rb +3 -3
  188. data/lib/rubocop/cop/style/exponential_notation.rb +5 -4
  189. data/lib/rubocop/cop/style/fetch_env_var.rb +32 -6
  190. data/lib/rubocop/cop/style/float_division.rb +15 -1
  191. data/lib/rubocop/cop/style/for.rb +1 -0
  192. data/lib/rubocop/cop/style/format_string_token.rb +38 -11
  193. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  194. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  195. data/lib/rubocop/cop/style/guard_clause.rb +2 -1
  196. data/lib/rubocop/cop/style/hash_conversion.rb +16 -8
  197. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -2
  198. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  199. data/lib/rubocop/cop/style/hash_syntax.rb +4 -1
  200. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  201. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  202. data/lib/rubocop/cop/style/identical_conditional_branches.rb +3 -3
  203. data/lib/rubocop/cop/style/if_inside_else.rb +10 -13
  204. data/lib/rubocop/cop/style/if_unless_modifier.rb +35 -8
  205. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -7
  206. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
  207. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  208. data/lib/rubocop/cop/style/inverse_methods.rb +10 -6
  209. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  210. data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
  211. data/lib/rubocop/cop/style/it_assignment.rb +69 -12
  212. data/lib/rubocop/cop/style/it_block_parameter.rb +121 -0
  213. data/lib/rubocop/cop/style/keyword_parameters_order.rb +13 -7
  214. data/lib/rubocop/cop/style/lambda.rb +1 -0
  215. data/lib/rubocop/cop/style/lambda_call.rb +7 -2
  216. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  217. data/lib/rubocop/cop/style/map_into_array.rb +4 -1
  218. data/lib/rubocop/cop/style/map_to_hash.rb +12 -3
  219. data/lib/rubocop/cop/style/map_to_set.rb +1 -3
  220. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +9 -8
  221. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +16 -0
  222. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -1
  223. data/lib/rubocop/cop/style/min_max_comparison.rb +13 -5
  224. data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -1
  225. data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
  226. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
  227. data/lib/rubocop/cop/style/next.rb +44 -0
  228. data/lib/rubocop/cop/style/nil_comparison.rb +9 -7
  229. data/lib/rubocop/cop/style/object_then.rb +1 -0
  230. data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
  231. data/lib/rubocop/cop/style/parallel_assignment.rb +32 -20
  232. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  233. data/lib/rubocop/cop/style/proc.rb +1 -0
  234. data/lib/rubocop/cop/style/raise_args.rb +8 -8
  235. data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
  236. data/lib/rubocop/cop/style/redundant_begin.rb +35 -0
  237. data/lib/rubocop/cop/style/redundant_condition.rb +57 -0
  238. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +14 -4
  239. data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
  240. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -9
  241. data/lib/rubocop/cop/style/redundant_format.rb +79 -18
  242. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
  243. data/lib/rubocop/cop/style/redundant_interpolation.rb +12 -3
  244. data/lib/rubocop/cop/style/redundant_line_continuation.rb +1 -4
  245. data/lib/rubocop/cop/style/redundant_parentheses.rb +73 -18
  246. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -0
  247. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
  248. data/lib/rubocop/cop/style/redundant_self.rb +9 -5
  249. data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -1
  250. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  251. data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
  252. data/lib/rubocop/cop/style/rescue_modifier.rb +3 -0
  253. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  254. data/lib/rubocop/cop/style/safe_navigation.rb +61 -14
  255. data/lib/rubocop/cop/style/select_by_regexp.rb +4 -1
  256. data/lib/rubocop/cop/style/semicolon.rb +23 -7
  257. data/lib/rubocop/cop/style/single_line_do_end_block.rb +3 -1
  258. data/lib/rubocop/cop/style/single_line_methods.rb +10 -7
  259. data/lib/rubocop/cop/style/sole_nested_conditional.rb +75 -101
  260. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -1
  261. data/lib/rubocop/cop/style/string_concatenation.rb +18 -15
  262. data/lib/rubocop/cop/style/struct_inheritance.rb +8 -1
  263. data/lib/rubocop/cop/style/super_arguments.rb +1 -2
  264. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  265. data/lib/rubocop/cop/style/symbol_proc.rb +3 -1
  266. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -0
  267. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +52 -1
  268. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  269. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  270. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  271. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  272. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  273. data/lib/rubocop/cop/team.rb +1 -1
  274. data/lib/rubocop/cop/util.rb +1 -1
  275. data/lib/rubocop/cop/utils/format_string.rb +15 -2
  276. data/lib/rubocop/cop/variable_force/assignment.rb +7 -3
  277. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  278. data/lib/rubocop/cop/variable_force/variable.rb +3 -8
  279. data/lib/rubocop/cop/variable_force.rb +26 -9
  280. data/lib/rubocop/cops_documentation_generator.rb +23 -7
  281. data/lib/rubocop/directive_comment.rb +1 -1
  282. data/lib/rubocop/ext/regexp_node.rb +0 -1
  283. data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -5
  284. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  285. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  286. data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
  287. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  288. data/lib/rubocop/formatter/pacman_formatter.rb +2 -1
  289. data/lib/rubocop/lsp/diagnostic.rb +25 -24
  290. data/lib/rubocop/lsp/routes.rb +65 -9
  291. data/lib/rubocop/lsp/runtime.rb +5 -5
  292. data/lib/rubocop/lsp/server.rb +2 -2
  293. data/lib/rubocop/lsp/stdin_runner.rb +3 -17
  294. data/lib/rubocop/magic_comment.rb +8 -0
  295. data/lib/rubocop/pending_cops_reporter.rb +56 -0
  296. data/lib/rubocop/plugin/configuration_integrator.rb +2 -0
  297. data/lib/rubocop/plugin/load_error.rb +1 -1
  298. data/lib/rubocop/plugin.rb +9 -2
  299. data/lib/rubocop/result_cache.rb +14 -12
  300. data/lib/rubocop/rspec/cop_helper.rb +6 -1
  301. data/lib/rubocop/rspec/expect_offense.rb +9 -3
  302. data/lib/rubocop/rspec/shared_contexts.rb +34 -0
  303. data/lib/rubocop/rspec/support.rb +3 -0
  304. data/lib/rubocop/runner.rb +10 -4
  305. data/lib/rubocop/server/cache.rb +17 -12
  306. data/lib/rubocop/server/client_command/base.rb +10 -0
  307. data/lib/rubocop/server/client_command/exec.rb +2 -1
  308. data/lib/rubocop/server/client_command/start.rb +11 -1
  309. data/lib/rubocop/target_finder.rb +13 -9
  310. data/lib/rubocop/target_ruby.rb +11 -2
  311. data/lib/rubocop/version.rb +14 -7
  312. data/lib/rubocop.rb +17 -2
  313. data/lib/ruby_lsp/rubocop/addon.rb +25 -10
  314. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +57 -5
  315. metadata +24 -8
  316. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
@@ -16,8 +16,8 @@ module RuboCop
16
16
  # Diagnostic for Language Server Protocol of RuboCop.
17
17
  # @api private
18
18
  class Diagnostic
19
- def initialize(document_encoding, offense, uri, cop_class)
20
- @document_encoding = document_encoding
19
+ def initialize(position_encoding, offense, uri, cop_class)
20
+ @position_encoding = position_encoding
21
21
  @offense = offense
22
22
  @uri = uri
23
23
  @cop_class = cop_class
@@ -45,11 +45,11 @@ module RuboCop
45
45
  range: LanguageServer::Protocol::Interface::Range.new(
46
46
  start: LanguageServer::Protocol::Interface::Position.new(
47
47
  line: @offense.line - 1,
48
- character: highlighted.begin_pos
48
+ character: to_position_character(highlighted.begin_pos)
49
49
  ),
50
50
  end: LanguageServer::Protocol::Interface::Position.new(
51
51
  line: @offense.line - 1,
52
- character: highlighted.end_pos
52
+ character: to_position_character(highlighted.end_pos)
53
53
  )
54
54
  ),
55
55
  data: {
@@ -79,7 +79,7 @@ module RuboCop
79
79
  LanguageServer::Protocol::Interface::CodeDescription.new(href: doc_url)
80
80
  end
81
81
 
82
- # rubocop:disable Layout/LineLength, Metrics/MethodLength
82
+ # rubocop:disable Metrics/MethodLength
83
83
  def autocorrect_action
84
84
  LanguageServer::Protocol::Interface::CodeAction.new(
85
85
  title: "Autocorrect #{@offense.cop_name}",
@@ -98,7 +98,7 @@ module RuboCop
98
98
  is_preferred: true
99
99
  )
100
100
  end
101
- # rubocop:enable Layout/LineLength, Metrics/MethodLength
101
+ # rubocop:enable Metrics/MethodLength
102
102
 
103
103
  # rubocop:disable Metrics/MethodLength
104
104
  def offense_replacements
@@ -107,11 +107,11 @@ module RuboCop
107
107
  range: LanguageServer::Protocol::Interface::Range.new(
108
108
  start: LanguageServer::Protocol::Interface::Position.new(
109
109
  line: range.line - 1,
110
- character: range.column
110
+ character: to_position_character(range.column)
111
111
  ),
112
112
  end: LanguageServer::Protocol::Interface::Position.new(
113
113
  line: range.last_line - 1,
114
- character: range.last_column
114
+ character: to_position_character(range.last_column)
115
115
  )
116
116
  ),
117
117
  new_text: replacement
@@ -120,7 +120,7 @@ module RuboCop
120
120
  end
121
121
  # rubocop:enable Metrics/MethodLength
122
122
 
123
- # rubocop:disable Layout/LineLength, Metrics/MethodLength
123
+ # rubocop:disable Metrics/MethodLength
124
124
  def disable_line_action
125
125
  LanguageServer::Protocol::Interface::CodeAction.new(
126
126
  title: "Disable #{@offense.cop_name} for this line",
@@ -138,7 +138,7 @@ module RuboCop
138
138
  )
139
139
  )
140
140
  end
141
- # rubocop:enable Layout/LineLength, Metrics/MethodLength
141
+ # rubocop:enable Metrics/MethodLength
142
142
 
143
143
  def line_disable_comment
144
144
  new_text = if @offense.source_line.include?(' # rubocop:disable ')
@@ -149,7 +149,7 @@ module RuboCop
149
149
 
150
150
  eol = LanguageServer::Protocol::Interface::Position.new(
151
151
  line: @offense.line - 1,
152
- character: length_of_line(@offense.source_line)
152
+ character: to_position_character
153
153
  )
154
154
 
155
155
  # TODO: fails for multiline strings - may be preferable to use block
@@ -162,19 +162,6 @@ module RuboCop
162
162
  [inline_comment]
163
163
  end
164
164
 
165
- def length_of_line(line)
166
- if @document_encoding == Encoding::UTF_16LE
167
- line_length = 0
168
- line.codepoints.each do |codepoint|
169
- line_length += 1
170
- line_length += 1 if codepoint > RubyLsp::Document::Scanner::SURROGATE_PAIR_START
171
- end
172
- line_length
173
- else
174
- line.length
175
- end
176
- end
177
-
178
165
  def correctable?
179
166
  !@offense.corrector.nil?
180
167
  end
@@ -184,6 +171,20 @@ module RuboCop
184
171
  uri.scheme = 'file' if uri.scheme.nil?
185
172
  uri
186
173
  end
174
+
175
+ def to_position_character(utf8_index = nil)
176
+ str = utf8_index ? @offense.source_line[0, utf8_index] : @offense.source_line
177
+ case @position_encoding
178
+ when 'utf-8', Encoding::UTF_8
179
+ str.bytesize
180
+ when 'utf-32', Encoding::UTF_32
181
+ str.size
182
+ else # 'utf-16'
183
+ # utf-16 is default position encoding on LSP
184
+ # https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/
185
+ str.size + str.count("\u{10000}-\u{10FFFF}")
186
+ end
187
+ end
187
188
  end
188
189
  end
189
190
  end
@@ -15,7 +15,7 @@ module RuboCop
15
15
  module LSP
16
16
  # Routes for Language Server Protocol of RuboCop.
17
17
  # @api private
18
- class Routes
18
+ class Routes # rubocop:disable Metrics/ClassLength
19
19
  CONFIGURATION_FILE_PATTERNS = [
20
20
  RuboCop::ConfigFinder::DOTFILE,
21
21
  RuboCop::CLI::Command::AutoGenerateConfig::AUTO_GENERATED_FILE
@@ -42,6 +42,7 @@ module RuboCop
42
42
 
43
43
  handle 'initialize' do |request|
44
44
  initialization_options = extract_initialization_options_from(request)
45
+ @position_encoding = initialization_options[:position_encoding]
45
46
 
46
47
  @server.configure(initialization_options)
47
48
 
@@ -51,9 +52,10 @@ module RuboCop
51
52
  capabilities: LanguageServer::Protocol::Interface::ServerCapabilities.new(
52
53
  document_formatting_provider: true,
53
54
  text_document_sync: LanguageServer::Protocol::Interface::TextDocumentSyncOptions.new(
54
- change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::FULL,
55
+ change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::INCREMENTAL,
55
56
  open_close: true
56
- )
57
+ ),
58
+ position_encoding: @position_encoding
57
59
  )
58
60
  )
59
61
  )
@@ -76,7 +78,12 @@ module RuboCop
76
78
 
77
79
  handle 'textDocument/didChange' do |request|
78
80
  params = request[:params]
79
- result = diagnostic(params[:textDocument][:uri], params[:contentChanges][0][:text])
81
+ file_uri = params[:textDocument][:uri]
82
+ text = @text_cache[file_uri]
83
+ params[:contentChanges].each do |content|
84
+ text = change_text(text, content[:text], content[:range])
85
+ end
86
+ result = diagnostic(file_uri, text)
80
87
  @server.write(result)
81
88
  end
82
89
 
@@ -179,14 +186,26 @@ module RuboCop
179
186
 
180
187
  def extract_initialization_options_from(request)
181
188
  safe_autocorrect = request.dig(:params, :initializationOptions, :safeAutocorrect)
189
+ position_encodings = request.dig(:params, :capabilities, :general, :positionEncodings)
182
190
 
183
191
  {
184
192
  safe_autocorrect: safe_autocorrect.nil? || safe_autocorrect == true,
185
193
  lint_mode: request.dig(:params, :initializationOptions, :lintMode) == true,
186
- layout_mode: request.dig(:params, :initializationOptions, :layoutMode) == true
194
+ layout_mode: request.dig(:params, :initializationOptions, :layoutMode) == true,
195
+ position_encoding: position_encoding(position_encodings)
187
196
  }
188
197
  end
189
198
 
199
+ def position_encoding(position_encodings)
200
+ if position_encodings&.include?('utf-8')
201
+ 'utf-8'
202
+ elsif position_encodings&.include?('utf-32')
203
+ 'utf-32'
204
+ else
205
+ 'utf-16'
206
+ end
207
+ end
208
+
190
209
  def format_file(file_uri, command: nil)
191
210
  unless (text = @text_cache[file_uri])
192
211
  Logger.log("Format request arrived before text synchronized; skipping: `#{file_uri}'")
@@ -194,7 +213,7 @@ module RuboCop
194
213
  return []
195
214
  end
196
215
 
197
- new_text = @server.format(remove_file_protocol_from(file_uri), text, command: command)
216
+ new_text = @server.format(convert_file_uri_to_path(file_uri), text, command: command)
198
217
 
199
218
  return [] if new_text == text
200
219
 
@@ -214,13 +233,50 @@ module RuboCop
214
233
  method: 'textDocument/publishDiagnostics',
215
234
  params: {
216
235
  uri: file_uri,
217
- diagnostics: @server.offenses(remove_file_protocol_from(file_uri), text)
236
+ diagnostics: @server.offenses(convert_file_uri_to_path(file_uri),
237
+ text, @position_encoding)
218
238
  }
219
239
  }
220
240
  end
221
241
 
222
- def remove_file_protocol_from(uri)
223
- uri.delete_prefix('file://')
242
+ def change_text(orig_text, text, range)
243
+ return text unless range
244
+
245
+ start_pos = text_pos(orig_text, range[:start])
246
+ end_pos = text_pos(orig_text, range[:end])
247
+ orig_text[start_pos...end_pos] = text
248
+ orig_text
249
+ end
250
+
251
+ def text_pos(text, range)
252
+ line = range[:line]
253
+ char = range[:character]
254
+ pos = 0
255
+ text.each_line.with_index do |l, i|
256
+ if i == line
257
+ pos += line_pos(l, char)
258
+ return pos
259
+ end
260
+ pos += l.size
261
+ end
262
+ pos
263
+ end
264
+
265
+ def line_pos(line, char)
266
+ case @position_encoding
267
+ when 'utf-8'
268
+ line.byteslice(0, char).size
269
+ when 'utf-32'
270
+ char
271
+ else # 'utf-16'
272
+ # utf-16 is default position encoding on LSP
273
+ # https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/
274
+ line.encode('utf-16be').byteslice(0, char * 2).size
275
+ end
276
+ end
277
+
278
+ def convert_file_uri_to_path(uri)
279
+ URI.decode_www_form_component(uri.delete_prefix('file://'))
224
280
  end
225
281
  end
226
282
  end
@@ -30,7 +30,7 @@ module RuboCop
30
30
  @layout_mode = false
31
31
  end
32
32
 
33
- def format(path, text, command:)
33
+ def format(path, text, command:, prism_result: nil)
34
34
  safe_autocorrect = if command
35
35
  command == 'rubocop.formatAutocorrects'
36
36
  else
@@ -40,18 +40,18 @@ module RuboCop
40
40
  formatting_options = { autocorrect: true, safe_autocorrect: safe_autocorrect }
41
41
  formatting_options[:only] = config_only_options if @lint_mode || @layout_mode
42
42
 
43
- @runner.run(path, text, formatting_options)
43
+ @runner.run(path, text, formatting_options, prism_result: prism_result)
44
44
  @runner.formatted_source
45
45
  end
46
46
 
47
- def offenses(path, text, document_encoding = nil)
47
+ def offenses(path, text, position_encoding, prism_result: nil)
48
48
  diagnostic_options = {}
49
49
  diagnostic_options[:only] = config_only_options if @lint_mode || @layout_mode
50
50
 
51
- @runner.run(path, text, diagnostic_options)
51
+ @runner.run(path, text, diagnostic_options, prism_result: prism_result)
52
52
  @runner.offenses.map do |offense|
53
53
  Diagnostic.new(
54
- document_encoding, offense, path, @cop_registry[offense.cop_name]&.first
54
+ position_encoding, offense, path, @cop_registry[offense.cop_name]&.first
55
55
  ).to_lsp_diagnostic(@runner.config_for_working_directory)
56
56
  end
57
57
  end
@@ -51,8 +51,8 @@ module RuboCop
51
51
  @runtime.format(path, text, command: command)
52
52
  end
53
53
 
54
- def offenses(path, text)
55
- @runtime.offenses(path, text)
54
+ def offenses(path, text, position_encoding)
55
+ @runtime.offenses(path, text, position_encoding)
56
56
  end
57
57
 
58
58
  def configure(options)
@@ -40,11 +40,12 @@ 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
+
48
49
  @offenses = []
49
50
  @warnings = []
50
51
  @errors = []
@@ -52,22 +53,7 @@ module RuboCop
52
53
  super([path])
53
54
 
54
55
  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
56
  end
70
- # rubocop:enable Metrics/MethodLength
71
57
 
72
58
  def formatted_source
73
59
  @options[:stdin]
@@ -193,6 +193,10 @@ module RuboCop
193
193
  SEPARATOR = ';'
194
194
  OPERATOR = ':'
195
195
 
196
+ def new_frozen_string_literal(value)
197
+ "# -*- frozen_string_literal: #{value} -*-"
198
+ end
199
+
196
200
  private
197
201
 
198
202
  def extract_frozen_string_literal
@@ -275,6 +279,10 @@ module RuboCop
275
279
  end
276
280
  end
277
281
 
282
+ def new_frozen_string_literal(value)
283
+ "# frozen_string_literal: #{value}"
284
+ end
285
+
278
286
  private
279
287
 
280
288
  # Extract `frozen_string_literal`.
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ # Reports information about pending cops that are not explicitly configured.
5
+ #
6
+ # This class is responsible for displaying warnings when new cops have been added to RuboCop
7
+ # but have not yet been enabled or disabled in the user's configuration.
8
+ # It provides a centralized way to determine whether such warnings should be shown,
9
+ # based on global flags or configuration settings.
10
+ class PendingCopsReporter
11
+ class << self
12
+ PENDING_BANNER = <<~BANNER
13
+ The following cops were added to RuboCop, but are not configured. Please set Enabled to either `true` or `false` in your `.rubocop.yml` file.
14
+
15
+ Please also note that you can opt-in to new cops by default by adding this to your config:
16
+ AllCops:
17
+ NewCops: enable
18
+ BANNER
19
+
20
+ attr_accessor :disable_pending_cops, :enable_pending_cops
21
+
22
+ def warn_if_needed(config)
23
+ return if possible_new_cops?(config)
24
+
25
+ pending_cops = pending_cops_only_qualified(config.pending_cops)
26
+ warn_on_pending_cops(pending_cops) unless pending_cops.empty?
27
+ end
28
+
29
+ private
30
+
31
+ def pending_cops_only_qualified(pending_cops)
32
+ pending_cops.select { |cop| Cop::Registry.qualified_cop?(cop.name) }
33
+ end
34
+
35
+ def possible_new_cops?(config)
36
+ disable_pending_cops || enable_pending_cops ||
37
+ config.disabled_new_cops? || config.enabled_new_cops?
38
+ end
39
+
40
+ def warn_on_pending_cops(pending_cops)
41
+ warn Rainbow(PENDING_BANNER).yellow
42
+
43
+ pending_cops.each { |cop| warn_pending_cop cop }
44
+
45
+ warn Rainbow('For more information: https://docs.rubocop.org/rubocop/versioning.html').yellow
46
+ end
47
+
48
+ def warn_pending_cop(cop)
49
+ version = cop.metadata['VersionAdded'] || 'N/A'
50
+
51
+ warn Rainbow("#{cop.name}: # new in #{version}").yellow
52
+ warn Rainbow(' Enabled: true').yellow
53
+ end
54
+ end
55
+ end
56
+ end
@@ -57,6 +57,8 @@ module RuboCop
57
57
  all_cop_keys_configured_by_plugins
58
58
  )
59
59
 
60
+ plugin_config.make_excludes_absolute
61
+
60
62
  ConfigLoader.merge_with_default(plugin_config, plugin_config_path)
61
63
  end
62
64
  end
@@ -15,7 +15,7 @@ module RuboCop
15
15
  <<~MESSAGE
16
16
  Failed to load plugin `#{@plugin_name}` because the corresponding plugin class could not be determined for instantiation.
17
17
  Try upgrading it first (e.g., `bundle update #{@plugin_name}`).
18
- If `#{@plugin_name}` is not yet a plugin, use `require: #{@plugin_name}` instead of `plugins: `#{@plugin_name}` in your configuration.
18
+ If `#{@plugin_name}` is not yet a plugin, use `require: #{@plugin_name}` instead of `plugins: #{@plugin_name}` in your configuration.
19
19
 
20
20
  For further assistance, check with the developer regarding the following points:
21
21
  https://docs.rubocop.org/rubocop/plugin_migration_guide.html
@@ -22,9 +22,16 @@ module RuboCop
22
22
  def plugin_capable?(feature_name)
23
23
  return true if BUILTIN_INTERNAL_PLUGINS.key?(feature_name)
24
24
  return true if feature_name == OBSOLETE_INTERNAL_AFFAIRS_PLUGIN_NAME
25
- return false unless (gem = Gem.loaded_specs[feature_name])
26
25
 
27
- !!gem.metadata['default_lint_roller_plugin']
26
+ begin
27
+ # When not using Bundler. Makes the spec available but does not require it.
28
+ gem feature_name
29
+ rescue Gem::LoadError
30
+ # The user requested a gem that they do not have installed
31
+ end
32
+ return false unless (spec = Gem.loaded_specs[feature_name])
33
+
34
+ !!spec.metadata['default_lint_roller_plugin']
28
35
  end
29
36
 
30
37
  def integrate_plugins(rubocop_config, plugins)
@@ -9,7 +9,7 @@ module RuboCop
9
9
  # Provides functionality for caching RuboCop runs.
10
10
  # @api private
11
11
  class ResultCache
12
- NON_CHANGING = %i[color format formatters out debug fail_level
12
+ NON_CHANGING = %i[color format formatters out debug display_time fail_level
13
13
  fix_layout autocorrect safe_autocorrect autocorrect_all
14
14
  cache fail_fast stdin parallel].freeze
15
15
 
@@ -198,20 +198,22 @@ module RuboCop
198
198
  end
199
199
 
200
200
  def rubocop_extra_features
201
- lib_root = File.join(File.dirname(__FILE__), '..')
202
- exe_root = File.join(lib_root, '..', 'exe')
201
+ @rubocop_extra_features ||= begin
202
+ lib_root = File.join(File.dirname(__FILE__), '..')
203
+ exe_root = File.join(lib_root, '..', 'exe')
203
204
 
204
- # Make sure to use an absolute path to prevent errors on Windows
205
- # when traversing the relative paths with symlinks.
206
- exe_root = File.absolute_path(exe_root)
205
+ # Make sure to use an absolute path to prevent errors on Windows
206
+ # when traversing the relative paths with symlinks.
207
+ exe_root = File.absolute_path(exe_root)
207
208
 
208
- # These are all the files we have `require`d plus everything in the
209
- # exe directory. A change to any of them could affect the cop output
210
- # so we include them in the cache hash.
211
- source_files = $LOADED_FEATURES + Find.find(exe_root).to_a
212
- source_files -= ResultCache.rubocop_required_features # Rely on gem versions
209
+ # These are all the files we have `require`d plus everything in the
210
+ # exe directory. A change to any of them could affect the cop output
211
+ # so we include them in the cache hash.
212
+ source_files = $LOADED_FEATURES + Find.find(exe_root).to_a
213
+ source_files -= ResultCache.rubocop_required_features # Rely on gem versions
213
214
 
214
- source_files
215
+ source_files
216
+ end
215
217
  end
216
218
 
217
219
  # Return a hash of the options given at invocation, minus the ones that have
@@ -10,10 +10,15 @@ module CopHelper
10
10
  # The minimum version Prism can parse is 3.3.
11
11
  ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : RuboCop::TargetRuby::DEFAULT_VERSION
12
12
  end
13
- let(:parser_engine) { ENV.fetch('PARSER_ENGINE', :parser_whitequark).to_sym }
13
+ let(:parser_engine) do
14
+ # The maximum version Parser can correctly parse is 3.3.
15
+ ruby_version >= 3.4 ? :parser_prism : ENV.fetch('PARSER_ENGINE', :parser_whitequark).to_sym
16
+ end
14
17
  let(:rails_version) { false }
15
18
 
16
19
  before(:all) do
20
+ next if ENV['RUBOCOP_CORE_DEVELOPMENT']
21
+
17
22
  plugins = Gem.loaded_specs.filter_map do |feature_name, feature_specification|
18
23
  feature_name if feature_specification.metadata['default_lint_roller_plugin']
19
24
  end
@@ -72,9 +72,15 @@ module RuboCop
72
72
  #
73
73
  # expect_no_corrections
74
74
  #
75
- # If your code has variables of different lengths, you can use `%{foo}`,
76
- # `^{foo}`, and `_{foo}` to format your template; you can also abbreviate
77
- # offense messages with `[...]`:
75
+ # If your code has variables of different lengths, you can use the
76
+ # following markers to format your template by passing the variables as a
77
+ # keyword arguments:
78
+ #
79
+ # - `%{foo}`: Interpolates `foo`
80
+ # - `^{foo}`: Inserts `'^' * foo.size` for dynamic offense range length
81
+ # - `_{foo}`: Inserts `' ' * foo.size` for dynamic offense range indentation
82
+ #
83
+ # You can also abbreviate offense messages with `[...]`.
78
84
  #
79
85
  # %w[raise fail].each do |keyword|
80
86
  # expect_offense(<<~RUBY, keyword: keyword)
@@ -80,6 +80,21 @@ RSpec.shared_context 'maintain registry' do
80
80
  end
81
81
  end
82
82
 
83
+ RSpec.shared_context 'maintain default configuration' do
84
+ around(:each) do |example|
85
+ # Make a copy of the current configuration that will not change when source hash changes
86
+ default_configuration = RuboCop::ConfigLoader.default_configuration
87
+ config = RuboCop::Config.create(
88
+ default_configuration.to_h.clone,
89
+ default_configuration.loaded_path
90
+ )
91
+
92
+ example.run
93
+
94
+ RuboCop::ConfigLoader.instance_variable_set(:@default_configuration, config)
95
+ end
96
+ end
97
+
83
98
  # This context assumes nothing and defines `cop`, among others.
84
99
  RSpec.shared_context 'config' do # rubocop:disable Metrics/BlockLength
85
100
  ### Meant to be overridden at will
@@ -163,6 +178,21 @@ RSpec.shared_context 'mock console output' do
163
178
  end
164
179
  end
165
180
 
181
+ RSpec.shared_context 'mock obsoletion' do
182
+ include_context 'mock console output'
183
+
184
+ let(:obsoletion_configuration_path) { 'obsoletions.yml' }
185
+
186
+ before do
187
+ RuboCop::ConfigObsoletion.reset!
188
+ allow(RuboCop::ConfigObsoletion).to receive(:files).and_return([obsoletion_configuration_path])
189
+ end
190
+
191
+ after do
192
+ RuboCop::ConfigObsoletion.reset!
193
+ end
194
+ end
195
+
166
196
  RSpec.shared_context 'lsp' do
167
197
  before do
168
198
  RuboCop::LSP.enable
@@ -235,3 +265,7 @@ end
235
265
  RSpec.shared_context 'ruby 3.4' do
236
266
  let(:ruby_version) { 3.4 }
237
267
  end
268
+
269
+ RSpec.shared_context 'ruby 3.5' do
270
+ let(:ruby_version) { 3.5 }
271
+ end
@@ -15,6 +15,8 @@ RSpec.configure do |config|
15
15
  config.include_context 'isolated bundler', :isolated_bundler
16
16
  config.include_context 'lsp', :lsp
17
17
  config.include_context 'maintain registry', :restore_registry
18
+ config.include_context 'maintain default configuration', :restore_configuration
19
+ config.include_context 'mock obsoletion', :mock_obsoletion
18
20
  config.include_context 'ruby 2.0', :ruby20
19
21
  config.include_context 'ruby 2.1', :ruby21
20
22
  config.include_context 'ruby 2.2', :ruby22
@@ -28,4 +30,5 @@ RSpec.configure do |config|
28
30
  config.include_context 'ruby 3.2', :ruby32
29
31
  config.include_context 'ruby 3.3', :ruby33
30
32
  config.include_context 'ruby 3.4', :ruby34
33
+ config.include_context 'ruby 3.5', :ruby35
31
34
  end
@@ -273,7 +273,8 @@ module RuboCop
273
273
  end
274
274
 
275
275
  def do_inspection_loop(file)
276
- processed_source = get_processed_source(file)
276
+ # We can reuse the prism result since the source did not change yet.
277
+ processed_source = get_processed_source(file, @prism_result)
277
278
  # This variable is 2d array used to track corrected offenses after each
278
279
  # inspection iteration. This is used to output meaningful infinite loop
279
280
  # error message.
@@ -295,7 +296,8 @@ module RuboCop
295
296
  # loop if we find any.
296
297
  break unless updated_source_file
297
298
 
298
- processed_source = get_processed_source(file)
299
+ # Autocorrect has happened, don't use the prism result since it is stale.
300
+ processed_source = get_processed_source(file, nil)
299
301
  end
300
302
 
301
303
  # Return summary of corrected offenses after all iterations
@@ -482,14 +484,18 @@ module RuboCop
482
484
  end
483
485
 
484
486
  # rubocop:disable Metrics/MethodLength
485
- def get_processed_source(file)
487
+ def get_processed_source(file, prism_result)
486
488
  config = @config_store.for_file(file)
487
489
  ruby_version = config.target_ruby_version
488
490
  parser_engine = config.parser_engine
489
491
 
490
492
  processed_source = if @options[:stdin]
491
493
  ProcessedSource.new(
492
- @options[:stdin], ruby_version, file, parser_engine: parser_engine
494
+ @options[:stdin],
495
+ ruby_version,
496
+ file,
497
+ parser_engine: parser_engine,
498
+ prism_result: prism_result
493
499
  )
494
500
  else
495
501
  begin