rubocop 1.54.1 → 1.64.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (297) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +5 -4
  4. data/assets/output.css.erb +159 -0
  5. data/assets/output.html.erb +1 -160
  6. data/config/default.yml +155 -26
  7. data/config/obsoletion.yml +5 -0
  8. data/lib/rubocop/cached_data.rb +11 -3
  9. data/lib/rubocop/cli/command/auto_generate_config.rb +22 -8
  10. data/lib/rubocop/cli/command/lsp.rb +2 -2
  11. data/lib/rubocop/cli/command/show_docs_url.rb +2 -2
  12. data/lib/rubocop/cli.rb +11 -2
  13. data/lib/rubocop/config.rb +36 -12
  14. data/lib/rubocop/config_finder.rb +14 -4
  15. data/lib/rubocop/config_loader.rb +0 -1
  16. data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
  17. data/lib/rubocop/config_obsoletion.rb +11 -8
  18. data/lib/rubocop/config_validator.rb +14 -7
  19. data/lib/rubocop/cop/autocorrect_logic.rb +9 -2
  20. data/lib/rubocop/cop/base.rb +64 -17
  21. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -0
  22. data/lib/rubocop/cop/bundler/duplicated_group.rb +127 -0
  23. data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
  24. data/lib/rubocop/cop/bundler/gem_version.rb +3 -5
  25. data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
  26. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
  27. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +5 -13
  28. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
  29. data/lib/rubocop/cop/documentation.rb +16 -6
  30. data/lib/rubocop/cop/exclude_limit.rb +1 -1
  31. data/lib/rubocop/cop/force.rb +12 -0
  32. data/lib/rubocop/cop/gemspec/dependency_version.rb +3 -5
  33. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +2 -2
  34. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
  35. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +5 -1
  36. data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
  37. data/lib/rubocop/cop/internal_affairs/example_description.rb +46 -24
  38. data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
  39. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +19 -20
  40. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
  41. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +123 -29
  42. data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
  43. data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
  44. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
  45. data/lib/rubocop/cop/internal_affairs.rb +2 -0
  46. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  47. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  48. data/lib/rubocop/cop/layout/dot_position.rb +1 -5
  49. data/lib/rubocop/cop/layout/empty_comment.rb +3 -1
  50. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +42 -9
  51. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +14 -7
  52. data/lib/rubocop/cop/layout/end_alignment.rb +15 -3
  53. data/lib/rubocop/cop/layout/extra_spacing.rb +4 -10
  54. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +24 -7
  55. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  56. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  57. data/lib/rubocop/cop/layout/heredoc_indentation.rb +4 -1
  58. data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
  59. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  60. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +17 -9
  61. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  62. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
  63. data/lib/rubocop/cop/layout/redundant_line_break.rb +29 -6
  64. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -4
  65. data/lib/rubocop/cop/layout/single_line_block_chain.rb +5 -0
  66. data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
  67. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +2 -2
  68. data/lib/rubocop/cop/layout/space_around_operators.rb +50 -20
  69. data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
  70. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
  71. data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
  72. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +3 -4
  73. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +5 -0
  74. data/lib/rubocop/cop/lint/assignment_in_condition.rb +6 -6
  75. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
  76. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
  77. data/lib/rubocop/cop/lint/debugger.rb +38 -3
  78. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  79. data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
  80. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  81. data/lib/rubocop/cop/lint/empty_conditional_body.rb +2 -2
  82. data/lib/rubocop/cop/lint/erb_new_arguments.rb +24 -17
  83. data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
  84. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
  85. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
  86. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +85 -0
  87. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  88. data/lib/rubocop/cop/lint/mixed_case_range.rb +10 -5
  89. data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
  90. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -7
  91. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -5
  92. data/lib/rubocop/cop/lint/number_conversion.rb +9 -4
  93. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -0
  94. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +72 -8
  95. data/lib/rubocop/cop/lint/redundant_with_index.rb +6 -2
  96. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  97. data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
  98. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +14 -8
  99. data/lib/rubocop/cop/lint/script_permission.rb +3 -3
  100. data/lib/rubocop/cop/lint/self_assignment.rb +38 -0
  101. data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
  102. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +7 -1
  103. data/lib/rubocop/cop/lint/struct_new_override.rb +12 -12
  104. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  105. data/lib/rubocop/cop/lint/symbol_conversion.rb +7 -2
  106. data/lib/rubocop/cop/lint/syntax.rb +6 -3
  107. data/lib/rubocop/cop/lint/to_enum_arguments.rb +12 -5
  108. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
  109. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
  110. data/lib/rubocop/cop/lint/unreachable_code.rb +4 -2
  111. data/lib/rubocop/cop/lint/unreachable_loop.rb +8 -2
  112. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  113. data/lib/rubocop/cop/lint/useless_assignment.rb +38 -12
  114. data/lib/rubocop/cop/lint/useless_times.rb +2 -2
  115. data/lib/rubocop/cop/lint/void.rb +48 -12
  116. data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
  117. data/lib/rubocop/cop/metrics/block_length.rb +1 -1
  118. data/lib/rubocop/cop/metrics/class_length.rb +8 -3
  119. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  120. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +7 -7
  121. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  122. data/lib/rubocop/cop/mixin/code_length.rb +12 -1
  123. data/lib/rubocop/cop/mixin/comments_help.rb +16 -12
  124. data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -0
  125. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  126. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +23 -13
  127. data/lib/rubocop/cop/mixin/method_complexity.rb +15 -6
  128. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +4 -3
  129. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -8
  130. data/lib/rubocop/cop/mixin/safe_assignment.rb +1 -1
  131. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  132. data/lib/rubocop/cop/mixin/string_help.rb +4 -2
  133. data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
  134. data/lib/rubocop/cop/naming/block_forwarding.rb +34 -7
  135. data/lib/rubocop/cop/naming/constant_name.rb +1 -2
  136. data/lib/rubocop/cop/naming/file_name.rb +3 -3
  137. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +3 -1
  138. data/lib/rubocop/cop/naming/inclusive_language.rb +1 -2
  139. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  140. data/lib/rubocop/cop/naming/predicate_name.rb +2 -2
  141. data/lib/rubocop/cop/registry.rb +1 -1
  142. data/lib/rubocop/cop/security/compound_hash.rb +2 -2
  143. data/lib/rubocop/cop/security/open.rb +2 -2
  144. data/lib/rubocop/cop/style/access_modifier_declarations.rb +52 -2
  145. data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
  146. data/lib/rubocop/cop/style/alias.rb +10 -8
  147. data/lib/rubocop/cop/style/arguments_forwarding.rb +414 -63
  148. data/lib/rubocop/cop/style/array_first_last.rb +64 -0
  149. data/lib/rubocop/cop/style/array_intersect.rb +13 -5
  150. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
  151. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
  152. data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
  153. data/lib/rubocop/cop/style/case_like_if.rb +5 -5
  154. data/lib/rubocop/cop/style/class_check.rb +1 -0
  155. data/lib/rubocop/cop/style/class_equality_comparison.rb +7 -0
  156. data/lib/rubocop/cop/style/class_vars.rb +3 -3
  157. data/lib/rubocop/cop/style/collection_compact.rb +21 -11
  158. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  159. data/lib/rubocop/cop/style/combinable_loops.rb +17 -9
  160. data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
  161. data/lib/rubocop/cop/style/concat_array_literals.rb +2 -1
  162. data/lib/rubocop/cop/style/conditional_assignment.rb +7 -8
  163. data/lib/rubocop/cop/style/copyright.rb +31 -21
  164. data/lib/rubocop/cop/style/date_time.rb +5 -4
  165. data/lib/rubocop/cop/style/documentation.rb +24 -24
  166. data/lib/rubocop/cop/style/documentation_method.rb +20 -0
  167. data/lib/rubocop/cop/style/each_for_simple_loop.rb +7 -7
  168. data/lib/rubocop/cop/style/each_with_object.rb +2 -2
  169. data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
  170. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  171. data/lib/rubocop/cop/style/eval_with_location.rb +6 -15
  172. data/lib/rubocop/cop/style/exact_regexp_match.rb +4 -2
  173. data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
  174. data/lib/rubocop/cop/style/for.rb +3 -1
  175. data/lib/rubocop/cop/style/format_string.rb +33 -12
  176. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -1
  177. data/lib/rubocop/cop/style/guard_clause.rb +26 -0
  178. data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
  179. data/lib/rubocop/cop/style/hash_each_methods.rb +105 -11
  180. data/lib/rubocop/cop/style/hash_except.rb +2 -1
  181. data/lib/rubocop/cop/style/hash_syntax.rb +24 -2
  182. data/lib/rubocop/cop/style/identical_conditional_branches.rb +28 -3
  183. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -3
  184. data/lib/rubocop/cop/style/inverse_methods.rb +14 -13
  185. data/lib/rubocop/cop/style/invertible_unless_condition.rb +44 -2
  186. data/lib/rubocop/cop/style/lambda_call.rb +5 -0
  187. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +8 -10
  188. data/lib/rubocop/cop/style/map_into_array.rb +175 -0
  189. data/lib/rubocop/cop/style/map_to_hash.rb +18 -8
  190. data/lib/rubocop/cop/style/map_to_set.rb +1 -1
  191. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +22 -6
  192. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -4
  193. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +20 -0
  194. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  195. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
  196. data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
  197. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  198. data/lib/rubocop/cop/style/multiline_method_signature.rb +10 -1
  199. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +6 -4
  200. data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
  201. data/lib/rubocop/cop/style/next.rb +1 -1
  202. data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
  203. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +1 -1
  204. data/lib/rubocop/cop/style/numeric_predicate.rb +10 -2
  205. data/lib/rubocop/cop/style/object_then.rb +5 -3
  206. data/lib/rubocop/cop/style/one_line_conditional.rb +1 -1
  207. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  208. data/lib/rubocop/cop/style/operator_method_call.rb +8 -2
  209. data/lib/rubocop/cop/style/parallel_assignment.rb +3 -5
  210. data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -0
  211. data/lib/rubocop/cop/style/raise_args.rb +4 -1
  212. data/lib/rubocop/cop/style/redundant_argument.rb +33 -4
  213. data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
  214. data/lib/rubocop/cop/style/redundant_begin.rb +9 -1
  215. data/lib/rubocop/cop/style/redundant_conditional.rb +1 -9
  216. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +5 -4
  217. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +93 -5
  218. data/lib/rubocop/cop/style/redundant_each.rb +7 -4
  219. data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
  220. data/lib/rubocop/cop/style/redundant_fetch_block.rb +3 -3
  221. data/lib/rubocop/cop/style/redundant_filter_chain.rb +23 -6
  222. data/lib/rubocop/cop/style/redundant_line_continuation.rb +19 -2
  223. data/lib/rubocop/cop/style/redundant_parentheses.rb +71 -22
  224. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  225. data/lib/rubocop/cop/style/redundant_return.rb +14 -3
  226. data/lib/rubocop/cop/style/redundant_self.rb +17 -2
  227. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +5 -0
  228. data/lib/rubocop/cop/style/redundant_sort.rb +9 -8
  229. data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
  230. data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -1
  231. data/lib/rubocop/cop/style/require_order.rb +1 -1
  232. data/lib/rubocop/cop/style/return_nil.rb +6 -2
  233. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +23 -9
  234. data/lib/rubocop/cop/style/sample.rb +3 -4
  235. data/lib/rubocop/cop/style/select_by_regexp.rb +7 -6
  236. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  237. data/lib/rubocop/cop/style/semicolon.rb +8 -3
  238. data/lib/rubocop/cop/style/send.rb +4 -4
  239. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +90 -0
  240. data/lib/rubocop/cop/style/single_argument_dig.rb +7 -3
  241. data/lib/rubocop/cop/style/single_line_do_end_block.rb +67 -0
  242. data/lib/rubocop/cop/style/slicing_with_range.rb +76 -10
  243. data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
  244. data/lib/rubocop/cop/style/special_global_vars.rb +1 -2
  245. data/lib/rubocop/cop/style/string_chars.rb +1 -0
  246. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
  247. data/lib/rubocop/cop/style/strip.rb +7 -4
  248. data/lib/rubocop/cop/style/super_arguments.rb +156 -0
  249. data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
  250. data/lib/rubocop/cop/style/symbol_array.rb +35 -15
  251. data/lib/rubocop/cop/style/symbol_proc.rb +68 -5
  252. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  253. data/lib/rubocop/cop/style/unpack_first.rb +11 -14
  254. data/lib/rubocop/cop/style/yoda_expression.rb +8 -7
  255. data/lib/rubocop/cop/team.rb +5 -0
  256. data/lib/rubocop/cop/utils/regexp_ranges.rb +27 -14
  257. data/lib/rubocop/cop/variable_force/assignment.rb +1 -3
  258. data/lib/rubocop/cops_documentation_generator.rb +15 -3
  259. data/lib/rubocop/directive_comment.rb +10 -8
  260. data/lib/rubocop/ext/regexp_node.rb +9 -4
  261. data/lib/rubocop/file_finder.rb +4 -7
  262. data/lib/rubocop/formatter/clang_style_formatter.rb +3 -7
  263. data/lib/rubocop/formatter/disabled_config_formatter.rb +23 -8
  264. data/lib/rubocop/formatter/formatter_set.rb +7 -1
  265. data/lib/rubocop/formatter/html_formatter.rb +35 -14
  266. data/lib/rubocop/formatter/json_formatter.rb +0 -1
  267. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  268. data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
  269. data/lib/rubocop/formatter/tap_formatter.rb +3 -7
  270. data/lib/rubocop/formatter.rb +1 -1
  271. data/lib/rubocop/lockfile.rb +56 -7
  272. data/lib/rubocop/lsp/logger.rb +1 -1
  273. data/lib/rubocop/lsp/routes.rb +43 -31
  274. data/lib/rubocop/lsp/runtime.rb +21 -4
  275. data/lib/rubocop/lsp/server.rb +13 -6
  276. data/lib/rubocop/lsp/severity.rb +1 -1
  277. data/lib/rubocop/lsp.rb +36 -0
  278. data/lib/rubocop/magic_comment.rb +13 -11
  279. data/lib/rubocop/options.rb +14 -11
  280. data/lib/rubocop/path_util.rb +6 -2
  281. data/lib/rubocop/rake_task.rb +1 -1
  282. data/lib/rubocop/result_cache.rb +4 -1
  283. data/lib/rubocop/rspec/cop_helper.rb +8 -2
  284. data/lib/rubocop/rspec/expect_offense.rb +16 -8
  285. data/lib/rubocop/rspec/shared_contexts.rb +55 -19
  286. data/lib/rubocop/rspec/support.rb +2 -0
  287. data/lib/rubocop/runner.rb +19 -6
  288. data/lib/rubocop/server/cache.rb +1 -1
  289. data/lib/rubocop/server/client_command/exec.rb +1 -2
  290. data/lib/rubocop/server/server_command/exec.rb +0 -1
  291. data/lib/rubocop/string_interpreter.rb +3 -3
  292. data/lib/rubocop/target_finder.rb +91 -81
  293. data/lib/rubocop/target_ruby.rb +82 -76
  294. data/lib/rubocop/version.rb +19 -4
  295. data/lib/rubocop.rb +9 -0
  296. metadata +29 -16
  297. /data/lib/rubocop/formatter/{git_hub_actions_formatter.rb → github_actions_formatter.rb} +0 -0
@@ -10,16 +10,18 @@
10
10
  # https://github.com/standardrb/standard/blob/main/LICENSE.txt
11
11
  #
12
12
  module RuboCop
13
- module Lsp
13
+ module LSP
14
14
  # Runtime for Language Server Protocol of RuboCop.
15
15
  # @api private
16
16
  class Runtime
17
- attr_writer :safe_autocorrect
17
+ attr_writer :safe_autocorrect, :lint_mode, :layout_mode
18
18
 
19
19
  def initialize(config_store)
20
20
  @config_store = config_store
21
21
  @logged_paths = []
22
22
  @safe_autocorrect = true
23
+ @lint_mode = false
24
+ @layout_mode = false
23
25
  end
24
26
 
25
27
  # This abuses the `--stdin` option of rubocop and reads the formatted text
@@ -33,10 +35,17 @@ module RuboCop
33
35
  # https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cli/command/execute_runner.rb#L95
34
36
  # Setting `parallel: true` would break this here:
35
37
  # https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/runner.rb#L72
36
- def format(path, text)
38
+ def format(path, text, command:)
39
+ safe_autocorrect = if command
40
+ command == 'rubocop.formatAutocorrects'
41
+ else
42
+ @safe_autocorrect
43
+ end
44
+
37
45
  formatting_options = {
38
- stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect: @safe_autocorrect
46
+ stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect: safe_autocorrect
39
47
  }
48
+ formatting_options[:only] = config_only_options if @lint_mode || @layout_mode
40
49
 
41
50
  redirect_stdout { run_rubocop(formatting_options, path) }
42
51
 
@@ -47,6 +56,7 @@ module RuboCop
47
56
  diagnostic_options = {
48
57
  stdin: text, force_exclusion: true, formatters: ['json'], format: 'json'
49
58
  }
59
+ diagnostic_options[:only] = config_only_options if @lint_mode || @layout_mode
50
60
 
51
61
  json = redirect_stdout { run_rubocop(diagnostic_options, path) }
52
62
  results = JSON.parse(json, symbolize_names: true)
@@ -64,6 +74,13 @@ module RuboCop
64
74
 
65
75
  private
66
76
 
77
+ def config_only_options
78
+ only_options = []
79
+ only_options << 'Lint' if @lint_mode
80
+ only_options << 'Layout' if @layout_mode
81
+ only_options
82
+ end
83
+
67
84
  def redirect_stdout(&block)
68
85
  stdout = StringIO.new
69
86
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'language_server-protocol'
4
+ require_relative '../lsp'
4
5
  require_relative 'logger'
5
6
  require_relative 'routes'
6
7
  require_relative 'runtime'
@@ -15,14 +16,18 @@ require_relative 'runtime'
15
16
  # https://github.com/standardrb/standard/blob/main/LICENSE.txt
16
17
  #
17
18
  module RuboCop
18
- module Lsp
19
+ module LSP
19
20
  # Language Server Protocol of RuboCop.
20
21
  # @api private
21
22
  class Server
22
23
  def initialize(config_store)
24
+ $PROGRAM_NAME = "rubocop --lsp #{ConfigFinder.project_root}"
25
+
26
+ RuboCop::LSP.enable
27
+
23
28
  @reader = LanguageServer::Protocol::Transport::Io::Reader.new($stdin)
24
29
  @writer = LanguageServer::Protocol::Transport::Io::Writer.new($stdout)
25
- @runtime = RuboCop::Lsp::Runtime.new(config_store)
30
+ @runtime = RuboCop::LSP::Runtime.new(config_store)
26
31
  @routes = Routes.new(self)
27
32
  end
28
33
 
@@ -45,16 +50,18 @@ module RuboCop
45
50
  @writer.write(response)
46
51
  end
47
52
 
48
- def format(path, text)
49
- @runtime.format(path, text)
53
+ def format(path, text, command:)
54
+ @runtime.format(path, text, command: command)
50
55
  end
51
56
 
52
57
  def offenses(path, text)
53
58
  @runtime.offenses(path, text)
54
59
  end
55
60
 
56
- def configure(safe_autocorrect: true)
57
- @runtime.safe_autocorrect = safe_autocorrect
61
+ def configure(options)
62
+ @runtime.safe_autocorrect = options[:safe_autocorrect]
63
+ @runtime.lint_mode = options[:lint_mode]
64
+ @runtime.layout_mode = options[:layout_mode]
58
65
  end
59
66
 
60
67
  def stop(&block)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RuboCop
4
- module Lsp
4
+ module LSP
5
5
  # Severity for Language Server Protocol of RuboCop.
6
6
  # @api private
7
7
  class Severity
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ # The RuboCop's built-in LSP module.
5
+ module LSP
6
+ module_function
7
+
8
+ # Returns true when LSP is enabled, false when disabled.
9
+ #
10
+ # @return [Boolean]
11
+ def enabled?
12
+ @enabled ||= false
13
+ end
14
+
15
+ # Enable LSP.
16
+ #
17
+ # @return [void]
18
+ def enable
19
+ @enabled = true
20
+ end
21
+
22
+ # Disable LSP.
23
+ #
24
+ # @return [void]
25
+ def disable(&block)
26
+ if block
27
+ original = @enabled
28
+ @enabled = false
29
+ yield
30
+ @enabled = original
31
+ else
32
+ @enabled = false
33
+ end
34
+ end
35
+ end
36
+ end
@@ -7,7 +7,7 @@ module RuboCop
7
7
  class MagicComment
8
8
  # IRB's pattern for matching magic comment tokens.
9
9
  # @see https://github.com/ruby/ruby/blob/b4a55c1/lib/irb/magic-file.rb#L5
10
- TOKEN = /[[:alnum:]\-_]+/.freeze
10
+ TOKEN = '(?<token>[[:alnum:]\-_]+)'
11
11
  KEYWORDS = {
12
12
  encoding: '(?:en)?coding',
13
13
  frozen_string_literal: 'frozen[_-]string[_-]literal',
@@ -129,7 +129,7 @@ module RuboCop
129
129
  # @return [String] if pattern matched
130
130
  # @return [nil] otherwise
131
131
  def extract(pattern)
132
- @comment[pattern, 1]
132
+ @comment[pattern, :token]
133
133
  end
134
134
 
135
135
  # Parent to Vim and Emacs magic comment handling.
@@ -157,10 +157,10 @@ module RuboCop
157
157
  # @return [String] extracted value if it is found
158
158
  # @return [nil] otherwise
159
159
  def match(keyword)
160
- pattern = /\A#{keyword}\s*#{self.class::OPERATOR}\s*(#{TOKEN})\z/
160
+ pattern = /\A#{keyword}\s*#{self.class::OPERATOR}\s*#{TOKEN}\z/
161
161
 
162
162
  tokens.each do |token|
163
- next unless (value = token[pattern, 1])
163
+ next unless (value = token[pattern, :token])
164
164
 
165
165
  return value.downcase
166
166
  end
@@ -188,7 +188,7 @@ module RuboCop
188
188
  # @see https://www.gnu.org/software/emacs/manual/html_node/emacs/Specify-Coding.html
189
189
  # @see https://github.com/ruby/ruby/blob/3f306dc/parse.y#L6873-L6892 Emacs handling in parse.y
190
190
  class EmacsComment < EditorComment
191
- REGEXP = /-\*-(.+)-\*-/.freeze
191
+ REGEXP = /-\*-(?<token>.+)-\*-/.freeze
192
192
  FORMAT = '# -*- %s -*-'
193
193
  SEPARATOR = ';'
194
194
  OPERATOR = ':'
@@ -216,7 +216,7 @@ module RuboCop
216
216
  #
217
217
  # comment.encoding # => 'ascii-8bit'
218
218
  class VimComment < EditorComment
219
- REGEXP = /#\s*vim:\s*(.+)/.freeze
219
+ REGEXP = /#\s*vim:\s*(?<token>.+)/.freeze
220
220
  FORMAT = '# vim: %s'
221
221
  SEPARATOR = ', '
222
222
  OPERATOR = '='
@@ -259,14 +259,16 @@ module RuboCop
259
259
  # comment2.frozen_string_literal # => nil
260
260
  # comment2.encoding # => 'utf-8'
261
261
  class SimpleComment < MagicComment
262
+ FSTRING_LITERAL_COMMENT = 'frozen_string_literal:\s*(true|false)'
263
+
262
264
  # Match `encoding` or `coding`
263
265
  def encoding
264
- extract(/\A\s*\#.*\b#{KEYWORDS[:encoding]}: (#{TOKEN})/io)
266
+ extract(/\A\s*\#\s*(#{FSTRING_LITERAL_COMMENT})?\s*#{KEYWORDS[:encoding]}: (#{TOKEN})/io)
265
267
  end
266
268
 
267
269
  # Rewrite the comment without a given token type
268
270
  def without(type)
269
- if @comment.match?(/\A#\s*#{self.class::KEYWORDS[type.to_sym]}/)
271
+ if @comment.match?(/\A#\s*#{self.class::KEYWORDS[type.to_sym]}/io)
270
272
  ''
271
273
  else
272
274
  @comment
@@ -283,15 +285,15 @@ module RuboCop
283
285
  # Case-insensitive and dashes/underscores are acceptable.
284
286
  # @see https://github.com/ruby/ruby/blob/78b95b4/parse.y#L7134-L7138
285
287
  def extract_frozen_string_literal
286
- extract(/\A\s*#\s*#{KEYWORDS[:frozen_string_literal]}:\s*(#{TOKEN})\s*\z/io)
288
+ extract(/\A\s*#\s*#{KEYWORDS[:frozen_string_literal]}:\s*#{TOKEN}\s*\z/io)
287
289
  end
288
290
 
289
291
  def extract_shareable_constant_value
290
- extract(/\A\s*#\s*#{KEYWORDS[:shareable_constant_value]}:\s*(#{TOKEN})\s*\z/io)
292
+ extract(/\A\s*#\s*#{KEYWORDS[:shareable_constant_value]}:\s*#{TOKEN}\s*\z/io)
291
293
  end
292
294
 
293
295
  def extract_typed
294
- extract(/\A\s*#\s*#{KEYWORDS[:typed]}:\s*(#{TOKEN})\s*\z/io)
296
+ extract(/\A\s*#\s*#{KEYWORDS[:typed]}:\s*#{TOKEN}\s*\z/io)
295
297
  end
296
298
  end
297
299
  end
@@ -95,6 +95,7 @@ module RuboCop
95
95
  option(opts, '--ignore-unrecognized-cops')
96
96
  option(opts, '--force-default-config')
97
97
  option(opts, '-s', '--stdin FILE')
98
+ option(opts, '--editor-mode')
98
99
  option(opts, '-P', '--[no-]parallel')
99
100
  option(opts, '--raise-cop-error')
100
101
  add_severity_option(opts)
@@ -364,15 +365,12 @@ module RuboCop
364
365
  raise OptionArgumentError, '-C/--cache argument must be true or false'
365
366
  end
366
367
 
367
- if display_only_fail_level_offenses_with_autocorrect?
368
- raise OptionArgumentError, '--autocorrect cannot be used with ' \
369
- '--display-only-fail-level-offenses.'
370
- end
371
368
  validate_auto_gen_config
372
369
  validate_autocorrect
373
370
  validate_display_only_failed
374
371
  validate_display_only_failed_and_display_only_correctable
375
372
  validate_display_only_correctable_and_autocorrect
373
+ validate_lsp_and_editor_mode
376
374
  disable_parallel_when_invalid_option_combo
377
375
 
378
376
  return if incompatible_options.size <= 1
@@ -420,6 +418,13 @@ module RuboCop
420
418
  format('--display-only-failed cannot be used together with other display options.')
421
419
  end
422
420
 
421
+ def validate_lsp_and_editor_mode
422
+ return if !@options.key?(:lsp) || !@options.key?(:editor_mode)
423
+
424
+ raise OptionArgumentError,
425
+ format('Do not specify `--editor-mode` as it is redundant in `--lsp`.')
426
+ end
427
+
423
428
  def validate_autocorrect
424
429
  if @options.key?(:safe_autocorrect) && @options.key?(:autocorrect_all)
425
430
  message = Rainbow(<<~MESSAGE).red
@@ -460,10 +465,6 @@ module RuboCop
460
465
  (@options[:only] & %w[Lint/RedundantCopDisableDirective RedundantCopDisableDirective]).any?
461
466
  end
462
467
 
463
- def display_only_fail_level_offenses_with_autocorrect?
464
- @options.key?(:display_only_fail_level_offenses) && @options.key?(:autocorrect)
465
- end
466
-
467
468
  def except_syntax?
468
469
  @options.key?(:except) && (@options[:except] & %w[Lint/Syntax Syntax]).any?
469
470
  end
@@ -572,7 +573,7 @@ module RuboCop
572
573
  'cops. Only valid for --format junit.'],
573
574
  display_only_fail_level_offenses:
574
575
  ['Only output offense messages at',
575
- 'the specified --fail-level or above'],
576
+ 'the specified --fail-level or above.'],
576
577
  display_only_correctable: ['Only output correctable offense messages.'],
577
578
  display_only_safe_correctable: ['Only output safe-correctable offense messages',
578
579
  'when combined with --display-only-correctable.'],
@@ -617,6 +618,8 @@ module RuboCop
617
618
  'parallel. Default is true.'],
618
619
  stdin: ['Pipe source from STDIN, using FILE in offense',
619
620
  'reports. This is useful for editor integration.'],
621
+ editor_mode: ['Optimize real-time feedback in editors,',
622
+ 'adjusting behaviors for editing experience.'],
620
623
  init: 'Generate a .rubocop.yml file in the current directory.',
621
624
  server: ['If a server process has not been started yet, start',
622
625
  'the server process and execute inspection with server.',
@@ -633,8 +636,8 @@ module RuboCop
633
636
  raise_cop_error: ['Raise cop-related errors with cause and location.',
634
637
  'This is used to prevent cops from failing silently.',
635
638
  'Default is false.'],
636
- profile: 'Profile rubocop',
637
- memory: 'Profile rubocop memory usage'
639
+ profile: 'Profile rubocop.',
640
+ memory: 'Profile rubocop memory usage.'
638
641
  }.freeze
639
642
  end
640
643
  # rubocop:enable Metrics/ModuleLength
@@ -44,7 +44,7 @@ module RuboCop
44
44
  end
45
45
  end
46
46
 
47
- # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
47
+ # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
48
48
  def match_path?(pattern, path)
49
49
  case pattern
50
50
  when String
@@ -52,6 +52,10 @@ module RuboCop
52
52
  if pattern == path
53
53
  true
54
54
  elsif glob?(pattern)
55
+ # File name matching doesn't really work with relative patterns that start with "..". We
56
+ # get around that problem by converting the pattern to an absolute path.
57
+ pattern = File.expand_path(pattern) if pattern.start_with?('..')
58
+
55
59
  File.fnmatch?(pattern, path, File::FNM_PATHNAME | File::FNM_EXTGLOB)
56
60
  end
57
61
 
@@ -66,7 +70,7 @@ module RuboCop
66
70
  end
67
71
  end
68
72
  end
69
- # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity
73
+ # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
70
74
 
71
75
  # Returns true for an absolute Unix or Windows path.
72
76
  def absolute?(path)
@@ -44,7 +44,7 @@ module RuboCop
44
44
  def run_cli(verbose, options)
45
45
  # We lazy-load RuboCop so that the task doesn't dramatically impact the
46
46
  # load time of your Rakefile.
47
- require 'rubocop'
47
+ require_relative '../rubocop'
48
48
 
49
49
  cli = CLI.new
50
50
  puts 'Running RuboCop...' if verbose
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'digest/sha1'
4
- require 'etc'
5
4
  require 'find'
6
5
  require 'zlib'
7
6
  require_relative 'cache_config'
@@ -202,6 +201,10 @@ module RuboCop
202
201
  lib_root = File.join(File.dirname(__FILE__), '..')
203
202
  exe_root = File.join(lib_root, '..', 'exe')
204
203
 
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)
207
+
205
208
  # These are all the files we have `require`d plus everything in the
206
209
  # exe directory. A change to any of them could affect the cop output
207
210
  # so we include them in the cache hash.
@@ -6,7 +6,11 @@ require 'tempfile'
6
6
  module CopHelper
7
7
  extend RSpec::SharedContext
8
8
 
9
- let(:ruby_version) { RuboCop::TargetRuby::DEFAULT_VERSION }
9
+ let(:ruby_version) do
10
+ # The minimum version Prism can parse is 3.3.
11
+ ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : RuboCop::TargetRuby::DEFAULT_VERSION
12
+ end
13
+ let(:parser_engine) { ENV.fetch('PARSER_ENGINE', :parser_whitequark).to_sym }
10
14
  let(:rails_version) { false }
11
15
 
12
16
  def inspect_source(source, file = nil)
@@ -28,7 +32,9 @@ module CopHelper
28
32
  file = file.path
29
33
  end
30
34
 
31
- processed_source = RuboCop::ProcessedSource.new(source, ruby_version, file)
35
+ processed_source = RuboCop::ProcessedSource.new(
36
+ source, ruby_version, file, parser_engine: parser_engine
37
+ )
32
38
  processed_source.config = configuration
33
39
  processed_source.registry = registry
34
40
  processed_source
@@ -111,6 +111,7 @@ module RuboCop
111
111
  source
112
112
  end
113
113
 
114
+ # rubocop:disable Metrics/AbcSize
114
115
  def expect_offense(source, file = nil, severity: nil, chomp: false, **replacements)
115
116
  expected_annotations = parse_annotations(source, **replacements)
116
117
  source = expected_annotations.plain_source
@@ -123,10 +124,17 @@ module RuboCop
123
124
  expect(actual_annotations).to eq(expected_annotations), ''
124
125
  expect(@offenses.map(&:severity).uniq).to eq([severity]) if severity
125
126
 
127
+ # Validate that all offenses have a range that formatters can display
128
+ expect do
129
+ @offenses.each { |offense| offense.location.source_line }
130
+ end.not_to raise_error, 'One of the offenses has a misconstructed range, for ' \
131
+ 'example if the offense is on line 1 and the source is empty'
132
+
126
133
  @offenses
127
134
  end
135
+ # rubocop:enable Metrics/AbcSize
128
136
 
129
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
137
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
130
138
  def expect_correction(correction, loop: true, source: nil)
131
139
  if source
132
140
  expected_annotations = parse_annotations(source, raise_error: false)
@@ -148,7 +156,6 @@ module RuboCop
148
156
 
149
157
  break corrected_source unless loop
150
158
  break corrected_source if @last_corrector.empty?
151
- break corrected_source if corrected_source == @processed_source.buffer.source
152
159
 
153
160
  if iteration > RuboCop::Runner::MAX_ITERATIONS
154
161
  raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [@offenses])
@@ -163,19 +170,20 @@ module RuboCop
163
170
 
164
171
  expect(new_source).to eq(correction)
165
172
  end
166
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
173
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
167
174
 
168
175
  def expect_no_corrections
169
176
  raise '`expect_no_corrections` must follow `expect_offense`' unless @processed_source
170
177
 
171
178
  return if @last_corrector.empty?
172
179
 
173
- # In order to print a nice diff, e.g. what source got corrected to,
174
- # we need to run the actual corrections
175
-
180
+ # This is just here for a pretty diff if the source actually got changed
176
181
  new_source = @last_corrector.rewrite
177
-
178
182
  expect(new_source).to eq(@processed_source.buffer.source)
183
+
184
+ # There is an infinite loop if a corrector is present that did not make
185
+ # any changes. It will cause the same offense/correction on the next loop.
186
+ raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [@offenses])
179
187
  end
180
188
 
181
189
  def expect_no_offenses(source, file = nil)
@@ -212,7 +220,7 @@ module RuboCop
212
220
 
213
221
  # Parsed representation of code annotated with the `^^^ Message` style
214
222
  class AnnotatedSource
215
- ANNOTATION_PATTERN = /\A\s*(\^+|\^{}) /.freeze
223
+ ANNOTATION_PATTERN = /\A\s*(\^+|\^{}) ?/.freeze
216
224
  ABBREV = "[...]\n"
217
225
 
218
226
  # @param annotated_source [String] string passed to the matchers
@@ -11,6 +11,8 @@ RSpec.shared_context 'isolated environment' do # rubocop:disable Metrics/BlockLe
11
11
  # Make sure to expand all symlinks in the path first. Otherwise we may
12
12
  # get mismatched pathnames when loading config files later on.
13
13
  tmpdir = File.realpath(tmpdir)
14
+ # Make upwards search for .rubocop.yml files stop at this directory.
15
+ RuboCop::FileFinder.root_level = tmpdir
14
16
 
15
17
  virtual_home = File.expand_path(File.join(tmpdir, 'home'))
16
18
  Dir.mkdir(virtual_home)
@@ -21,9 +23,6 @@ RSpec.shared_context 'isolated environment' do # rubocop:disable Metrics/BlockLe
21
23
  root = example.metadata[:root]
22
24
  working_dir = root ? File.join(base_dir, 'work', root) : File.join(base_dir, 'work')
23
25
 
24
- # Make upwards search for .rubocop.yml files stop at this directory.
25
- RuboCop::FileFinder.root_level = working_dir
26
-
27
26
  begin
28
27
  FileUtils.mkdir_p(working_dir)
29
28
 
@@ -101,17 +100,29 @@ RSpec.shared_context 'config' do # rubocop:disable Metrics/BlockLength
101
100
  let(:cur_cop_config) do
102
101
  RuboCop::ConfigLoader
103
102
  .default_configuration.for_cop(cop_class)
104
- .merge({
105
- 'Enabled' => true, # in case it is 'pending'
106
- 'AutoCorrect' => true # in case defaults set it to false
107
- })
103
+ .merge(
104
+ 'Enabled' => true, # in case it is 'pending'
105
+ 'AutoCorrect' => 'always' # in case defaults set it to 'disabled' or false
106
+ )
108
107
  .merge(cop_config)
109
108
  end
110
109
 
111
110
  let(:config) do
112
111
  hash = { 'AllCops' => all_cops_config, cop_class.cop_name => cur_cop_config }.merge!(other_cops)
113
112
 
114
- RuboCop::Config.new(hash, "#{Dir.pwd}/.rubocop.yml")
113
+ config = RuboCop::Config.new(hash, "#{Dir.pwd}/.rubocop.yml")
114
+
115
+ rails_version_in_gemfile = Gem::Version.new(
116
+ rails_version || RuboCop::Config::DEFAULT_RAILS_VERSION
117
+ )
118
+
119
+ allow(config).to receive(:gem_versions_in_target).and_return(
120
+ {
121
+ 'railties' => rails_version_in_gemfile
122
+ }
123
+ )
124
+
125
+ config
115
126
  end
116
127
 
117
128
  let(:cop) { cop_class.new(config, cop_options) }
@@ -129,50 +140,75 @@ RSpec.shared_context 'mock console output' do
129
140
  end
130
141
  end
131
142
 
143
+ RSpec.shared_context 'lsp' do
144
+ before do
145
+ RuboCop::LSP.enable
146
+ end
147
+
148
+ after do
149
+ RuboCop::LSP.disable
150
+ end
151
+ end
152
+
132
153
  RSpec.shared_context 'ruby 2.0' do
133
- let(:ruby_version) { 2.0 }
154
+ # Prism supports parsing Ruby 3.3+.
155
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.0 }
134
156
  end
135
157
 
136
158
  RSpec.shared_context 'ruby 2.1' do
137
- let(:ruby_version) { 2.1 }
159
+ # Prism supports parsing Ruby 3.3+.
160
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.1 }
138
161
  end
139
162
 
140
163
  RSpec.shared_context 'ruby 2.2' do
141
- let(:ruby_version) { 2.2 }
164
+ # Prism supports parsing Ruby 3.3+.
165
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.2 }
142
166
  end
143
167
 
144
168
  RSpec.shared_context 'ruby 2.3' do
145
- let(:ruby_version) { 2.3 }
169
+ # Prism supports parsing Ruby 3.3+.
170
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.3 }
146
171
  end
147
172
 
148
173
  RSpec.shared_context 'ruby 2.4' do
149
- let(:ruby_version) { 2.4 }
174
+ # Prism supports parsing Ruby 3.3+.
175
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.4 }
150
176
  end
151
177
 
152
178
  RSpec.shared_context 'ruby 2.5' do
153
- let(:ruby_version) { 2.5 }
179
+ # Prism supports parsing Ruby 3.3+.
180
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.5 }
154
181
  end
155
182
 
156
183
  RSpec.shared_context 'ruby 2.6' do
157
- let(:ruby_version) { 2.6 }
184
+ # Prism supports parsing Ruby 3.3+.
185
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.6 }
158
186
  end
159
187
 
160
188
  RSpec.shared_context 'ruby 2.7' do
161
- let(:ruby_version) { 2.7 }
189
+ # Prism supports parsing Ruby 3.3+.
190
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.7 }
162
191
  end
163
192
 
164
193
  RSpec.shared_context 'ruby 3.0' do
165
- let(:ruby_version) { 3.0 }
194
+ # Prism supports parsing Ruby 3.3+.
195
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 3.0 }
166
196
  end
167
197
 
168
198
  RSpec.shared_context 'ruby 3.1' do
169
- let(:ruby_version) { 3.1 }
199
+ # Prism supports parsing Ruby 3.3+.
200
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 3.1 }
170
201
  end
171
202
 
172
203
  RSpec.shared_context 'ruby 3.2' do
173
- let(:ruby_version) { 3.2 }
204
+ # Prism supports parsing Ruby 3.3+.
205
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 3.2 }
174
206
  end
175
207
 
176
208
  RSpec.shared_context 'ruby 3.3' do
177
209
  let(:ruby_version) { 3.3 }
178
210
  end
211
+
212
+ RSpec.shared_context 'ruby 3.4' do
213
+ let(:ruby_version) { 3.4 }
214
+ end
@@ -13,6 +13,7 @@ RSpec.configure do |config|
13
13
  config.include HostEnvironmentSimulatorHelper
14
14
  config.include_context 'config', :config
15
15
  config.include_context 'isolated environment', :isolated_environment
16
+ config.include_context 'lsp', :lsp
16
17
  config.include_context 'maintain registry', :restore_registry
17
18
  config.include_context 'ruby 2.0', :ruby20
18
19
  config.include_context 'ruby 2.1', :ruby21
@@ -26,4 +27,5 @@ RSpec.configure do |config|
26
27
  config.include_context 'ruby 3.1', :ruby31
27
28
  config.include_context 'ruby 3.2', :ruby32
28
29
  config.include_context 'ruby 3.3', :ruby33
30
+ config.include_context 'ruby 3.4', :ruby34
29
31
  end