rubocop 1.84.2 → 1.88.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 (357) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +183 -87
  3. data/config/obsoletion.yml +26 -1
  4. data/lib/rubocop/cache_config.rb +1 -1
  5. data/lib/rubocop/cli/command/auto_generate_config.rb +34 -2
  6. data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
  7. data/lib/rubocop/cli/command/mcp.rb +19 -0
  8. data/lib/rubocop/cli/command/show_cops.rb +2 -2
  9. data/lib/rubocop/cli/command/show_docs_url.rb +4 -8
  10. data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
  11. data/lib/rubocop/cli.rb +9 -7
  12. data/lib/rubocop/comment_config.rb +12 -15
  13. data/lib/rubocop/config.rb +14 -10
  14. data/lib/rubocop/config_finder.rb +1 -1
  15. data/lib/rubocop/config_loader.rb +17 -2
  16. data/lib/rubocop/config_loader_resolver.rb +13 -4
  17. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -2
  18. data/lib/rubocop/config_store.rb +2 -2
  19. data/lib/rubocop/config_validator.rb +1 -1
  20. data/lib/rubocop/cop/autocorrect_logic.rb +2 -1
  21. data/lib/rubocop/cop/base.rb +25 -4
  22. data/lib/rubocop/cop/bundler/gem_comment.rb +5 -3
  23. data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
  24. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +1 -1
  25. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -1
  26. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -5
  27. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +8 -1
  28. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +33 -2
  29. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  30. data/lib/rubocop/cop/correctors.rb +28 -0
  31. data/lib/rubocop/cop/documentation.rb +2 -3
  32. data/lib/rubocop/cop/exclude_limit.rb +31 -5
  33. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  34. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
  35. data/lib/rubocop/cop/gemspec/require_mfa.rb +9 -6
  36. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -3
  37. data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
  38. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
  39. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +5 -3
  40. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  41. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -2
  42. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  43. data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
  44. data/lib/rubocop/cop/layout/block_alignment.rb +58 -4
  45. data/lib/rubocop/cop/layout/class_structure.rb +8 -4
  46. data/lib/rubocop/cop/layout/condition_position.rb +13 -3
  47. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  48. data/lib/rubocop/cop/layout/empty_comment.rb +8 -10
  49. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +23 -7
  50. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +15 -2
  51. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
  52. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +12 -2
  53. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +16 -2
  54. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
  55. data/lib/rubocop/cop/layout/end_alignment.rb +8 -5
  56. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +20 -15
  57. data/lib/rubocop/cop/layout/hash_alignment.rb +1 -1
  58. data/lib/rubocop/cop/layout/indentation_width.rb +40 -0
  59. data/lib/rubocop/cop/layout/line_length.rb +5 -3
  60. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +9 -2
  61. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
  62. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +53 -3
  63. data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
  64. data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -1
  65. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  66. data/lib/rubocop/cop/layout/space_around_keyword.rb +3 -1
  67. data/lib/rubocop/cop/layout/space_around_operators.rb +6 -2
  68. data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -1
  69. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +1 -0
  70. data/lib/rubocop/cop/lint/ambiguous_assignment.rb +1 -11
  71. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  72. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +1 -10
  73. data/lib/rubocop/cop/lint/assignment_in_condition.rb +13 -1
  74. data/lib/rubocop/cop/lint/circular_argument_reference.rb +1 -3
  75. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
  76. data/lib/rubocop/cop/lint/constant_reassignment.rb +93 -11
  77. data/lib/rubocop/cop/lint/constant_resolution.rb +6 -6
  78. data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
  79. data/lib/rubocop/cop/lint/debugger.rb +0 -1
  80. data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
  81. data/lib/rubocop/cop/lint/duplicate_methods.rb +55 -8
  82. data/lib/rubocop/cop/lint/empty_block.rb +4 -4
  83. data/lib/rubocop/cop/lint/empty_conditional_body.rb +6 -1
  84. data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
  85. data/lib/rubocop/cop/lint/empty_when.rb +8 -1
  86. data/lib/rubocop/cop/lint/ensure_return.rb +19 -1
  87. data/lib/rubocop/cop/lint/erb_new_arguments.rb +4 -2
  88. data/lib/rubocop/cop/lint/float_comparison.rb +1 -0
  89. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -1
  90. data/lib/rubocop/cop/lint/interpolation_check.rb +25 -5
  91. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  92. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
  93. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +8 -11
  94. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +5 -5
  95. data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
  96. data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
  97. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +16 -0
  98. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +4 -2
  99. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  100. data/lib/rubocop/cop/lint/number_conversion.rb +19 -10
  101. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  102. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +3 -0
  103. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +7 -7
  104. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +3 -13
  105. data/lib/rubocop/cop/lint/raise_exception.rb +1 -1
  106. data/lib/rubocop/cop/lint/rand_one.rb +1 -1
  107. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +4 -1
  108. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +6 -12
  109. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +15 -4
  110. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +36 -12
  111. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +4 -0
  112. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +10 -3
  113. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
  114. data/lib/rubocop/cop/lint/redundant_with_object.rb +5 -0
  115. data/lib/rubocop/cop/lint/refinement_import_methods.rb +8 -1
  116. data/lib/rubocop/cop/lint/regexp_as_condition.rb +9 -1
  117. data/lib/rubocop/cop/lint/require_parentheses.rb +13 -4
  118. data/lib/rubocop/cop/lint/require_range_parentheses.rb +2 -1
  119. data/lib/rubocop/cop/lint/require_relative_self_path.rb +7 -5
  120. data/lib/rubocop/cop/lint/rescue_type.rb +1 -1
  121. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +18 -0
  122. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +7 -1
  123. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
  124. data/lib/rubocop/cop/lint/script_permission.rb +5 -1
  125. data/lib/rubocop/cop/lint/self_assignment.rb +24 -1
  126. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -1
  127. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  128. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +14 -0
  129. data/lib/rubocop/cop/lint/shared_mutable_default.rb +3 -1
  130. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +12 -0
  131. data/lib/rubocop/cop/lint/symbol_conversion.rb +21 -4
  132. data/lib/rubocop/cop/lint/syntax.rb +25 -1
  133. data/lib/rubocop/cop/lint/to_enum_arguments.rb +35 -2
  134. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  135. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +5 -1
  136. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +36 -10
  137. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
  138. data/lib/rubocop/cop/lint/unreachable_code.rb +2 -2
  139. data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
  140. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  141. data/lib/rubocop/cop/lint/useless_assignment.rb +14 -14
  142. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +4 -4
  143. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +2 -0
  144. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +8 -4
  145. data/lib/rubocop/cop/lint/useless_setter_call.rb +4 -1
  146. data/lib/rubocop/cop/lint/useless_times.rb +22 -1
  147. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +35 -9
  148. data/lib/rubocop/cop/lint/void.rb +32 -12
  149. data/lib/rubocop/cop/metrics/block_length.rb +1 -1
  150. data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
  151. data/lib/rubocop/cop/metrics/collection_literal_length.rb +1 -1
  152. data/lib/rubocop/cop/metrics/method_length.rb +2 -2
  153. data/lib/rubocop/cop/metrics/perceived_complexity.rb +38 -7
  154. data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
  155. data/lib/rubocop/cop/migration/department_name.rb +12 -1
  156. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  157. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -2
  158. data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
  159. data/lib/rubocop/cop/mixin/hash_subset.rb +8 -0
  160. data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
  161. data/lib/rubocop/cop/mixin/hash_transform_method.rb +14 -60
  162. data/lib/rubocop/cop/mixin/project_index_help.rb +48 -0
  163. data/lib/rubocop/cop/mixin.rb +86 -0
  164. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
  165. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  166. data/lib/rubocop/cop/naming/file_name.rb +4 -3
  167. data/lib/rubocop/cop/naming/inclusive_language.rb +8 -2
  168. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +10 -1
  169. data/lib/rubocop/cop/naming/predicate_method.rb +2 -2
  170. data/lib/rubocop/cop/naming/predicate_prefix.rb +1 -1
  171. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -4
  172. data/lib/rubocop/cop/offense.rb +8 -0
  173. data/lib/rubocop/cop/registry.rb +62 -38
  174. data/lib/rubocop/cop/security/eval.rb +15 -2
  175. data/lib/rubocop/cop/security/io_methods.rb +2 -2
  176. data/lib/rubocop/cop/security/marshal_load.rb +1 -1
  177. data/lib/rubocop/cop/style/access_modifier_declarations.rb +14 -2
  178. data/lib/rubocop/cop/style/accessor_grouping.rb +15 -3
  179. data/lib/rubocop/cop/style/alias.rb +15 -3
  180. data/lib/rubocop/cop/style/and_or.rb +2 -1
  181. data/lib/rubocop/cop/style/arguments_forwarding.rb +25 -7
  182. data/lib/rubocop/cop/style/array_first_last.rb +12 -1
  183. data/lib/rubocop/cop/style/array_intersect.rb +4 -0
  184. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +3 -0
  185. data/lib/rubocop/cop/style/array_join.rb +4 -2
  186. data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
  187. data/lib/rubocop/cop/style/attr.rb +5 -2
  188. data/lib/rubocop/cop/style/bare_percent_literals.rb +3 -1
  189. data/lib/rubocop/cop/style/begin_block.rb +3 -1
  190. data/lib/rubocop/cop/style/block_delimiters.rb +37 -31
  191. data/lib/rubocop/cop/style/case_equality.rb +18 -2
  192. data/lib/rubocop/cop/style/character_literal.rb +2 -2
  193. data/lib/rubocop/cop/style/class_and_module_children.rb +18 -2
  194. data/lib/rubocop/cop/style/class_equality_comparison.rb +21 -13
  195. data/lib/rubocop/cop/style/class_methods_definitions.rb +11 -5
  196. data/lib/rubocop/cop/style/collection_compact.rb +36 -16
  197. data/lib/rubocop/cop/style/colon_method_call.rb +16 -7
  198. data/lib/rubocop/cop/style/combinable_loops.rb +5 -0
  199. data/lib/rubocop/cop/style/comparable_clamp.rb +12 -1
  200. data/lib/rubocop/cop/style/concat_array_literals.rb +7 -1
  201. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -5
  202. data/lib/rubocop/cop/style/constant_visibility.rb +4 -1
  203. data/lib/rubocop/cop/style/copyright.rb +22 -11
  204. data/lib/rubocop/cop/style/data_inheritance.rb +4 -0
  205. data/lib/rubocop/cop/style/date_time.rb +4 -4
  206. data/lib/rubocop/cop/style/dig_chain.rb +5 -0
  207. data/lib/rubocop/cop/style/dir_empty.rb +4 -0
  208. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +1 -1
  209. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
  210. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  211. data/lib/rubocop/cop/style/each_with_object.rb +2 -0
  212. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  213. data/lib/rubocop/cop/style/empty_case_condition.rb +12 -2
  214. data/lib/rubocop/cop/style/empty_class_definition.rb +51 -21
  215. data/lib/rubocop/cop/style/empty_heredoc.rb +4 -0
  216. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  217. data/lib/rubocop/cop/style/empty_literal.rb +7 -2
  218. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +30 -20
  219. data/lib/rubocop/cop/style/encoding.rb +7 -1
  220. data/lib/rubocop/cop/style/end_block.rb +3 -1
  221. data/lib/rubocop/cop/style/endless_method.rb +8 -3
  222. data/lib/rubocop/cop/style/env_home.rb +4 -0
  223. data/lib/rubocop/cop/style/even_odd.rb +11 -1
  224. data/lib/rubocop/cop/style/exact_regexp_match.rb +8 -1
  225. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  226. data/lib/rubocop/cop/style/file_null.rb +4 -2
  227. data/lib/rubocop/cop/style/file_open.rb +84 -0
  228. data/lib/rubocop/cop/style/file_write.rb +21 -16
  229. data/lib/rubocop/cop/style/for.rb +3 -0
  230. data/lib/rubocop/cop/style/format_string.rb +17 -4
  231. data/lib/rubocop/cop/style/format_string_token.rb +29 -2
  232. data/lib/rubocop/cop/style/global_vars.rb +5 -2
  233. data/lib/rubocop/cop/style/guard_clause.rb +9 -6
  234. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +21 -5
  235. data/lib/rubocop/cop/style/hash_conversion.rb +1 -1
  236. data/lib/rubocop/cop/style/hash_lookup_method.rb +19 -7
  237. data/lib/rubocop/cop/style/hash_slice.rb +16 -0
  238. data/lib/rubocop/cop/style/hash_syntax.rb +2 -0
  239. data/lib/rubocop/cop/style/hash_transform_keys.rb +17 -7
  240. data/lib/rubocop/cop/style/hash_transform_values.rb +17 -7
  241. data/lib/rubocop/cop/style/if_inside_else.rb +16 -7
  242. data/lib/rubocop/cop/style/if_unless_modifier.rb +15 -4
  243. data/lib/rubocop/cop/style/if_with_semicolon.rb +16 -6
  244. data/lib/rubocop/cop/style/inline_comment.rb +5 -2
  245. data/lib/rubocop/cop/style/ip_addresses.rb +1 -2
  246. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +4 -0
  247. data/lib/rubocop/cop/style/keyword_parameters_order.rb +7 -3
  248. data/lib/rubocop/cop/style/lambda.rb +7 -1
  249. data/lib/rubocop/cop/style/magic_comment_format.rb +3 -3
  250. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +11 -0
  251. data/lib/rubocop/cop/style/map_into_array.rb +1 -1
  252. data/lib/rubocop/cop/style/map_join.rb +123 -0
  253. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -3
  254. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +6 -2
  255. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  256. data/lib/rubocop/cop/style/min_max_comparison.rb +4 -1
  257. data/lib/rubocop/cop/style/module_member_existence_check.rb +7 -14
  258. data/lib/rubocop/cop/style/multiline_if_then.rb +4 -2
  259. data/lib/rubocop/cop/style/multiline_memoization.rb +7 -1
  260. data/lib/rubocop/cop/style/multiline_method_signature.rb +11 -4
  261. data/lib/rubocop/cop/style/mutable_constant.rb +106 -12
  262. data/lib/rubocop/cop/style/nil_comparison.rb +2 -3
  263. data/lib/rubocop/cop/style/nil_lambda.rb +9 -1
  264. data/lib/rubocop/cop/style/non_nil_check.rb +5 -11
  265. data/lib/rubocop/cop/style/not.rb +2 -0
  266. data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
  267. data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
  268. data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
  269. data/lib/rubocop/cop/style/one_line_conditional.rb +4 -3
  270. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  271. data/lib/rubocop/cop/style/option_hash.rb +1 -1
  272. data/lib/rubocop/cop/style/optional_arguments.rb +1 -0
  273. data/lib/rubocop/cop/style/parallel_assignment.rb +23 -3
  274. data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
  275. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +4 -0
  276. data/lib/rubocop/cop/style/perl_backrefs.rb +5 -3
  277. data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
  278. data/lib/rubocop/cop/style/proc.rb +3 -2
  279. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  280. data/lib/rubocop/cop/style/reduce_to_hash.rb +200 -0
  281. data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
  282. data/lib/rubocop/cop/style/redundant_begin.rb +3 -3
  283. data/lib/rubocop/cop/style/redundant_constant_base.rb +5 -5
  284. data/lib/rubocop/cop/style/redundant_each.rb +3 -3
  285. data/lib/rubocop/cop/style/redundant_exception.rb +6 -0
  286. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
  287. data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
  288. data/lib/rubocop/cop/style/redundant_format.rb +29 -0
  289. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
  290. data/lib/rubocop/cop/style/redundant_line_continuation.rb +27 -3
  291. data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
  292. data/lib/rubocop/cop/style/redundant_parentheses.rb +25 -22
  293. data/lib/rubocop/cop/style/redundant_percent_q.rb +4 -1
  294. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +2 -2
  295. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -4
  296. data/lib/rubocop/cop/style/redundant_return.rb +3 -1
  297. data/lib/rubocop/cop/style/redundant_self.rb +11 -2
  298. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
  299. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +133 -0
  300. data/lib/rubocop/cop/style/regexp_literal.rb +31 -2
  301. data/lib/rubocop/cop/style/rescue_modifier.rb +3 -3
  302. data/lib/rubocop/cop/style/safe_navigation.rb +7 -7
  303. data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
  304. data/lib/rubocop/cop/style/select_by_range.rb +197 -0
  305. data/lib/rubocop/cop/style/select_by_regexp.rb +51 -21
  306. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  307. data/lib/rubocop/cop/style/semicolon.rb +22 -5
  308. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  309. data/lib/rubocop/cop/style/single_line_do_end_block.rb +18 -5
  310. data/lib/rubocop/cop/style/single_line_methods.rb +3 -1
  311. data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -2
  312. data/lib/rubocop/cop/style/special_global_vars.rb +6 -1
  313. data/lib/rubocop/cop/style/string_hash_keys.rb +1 -0
  314. data/lib/rubocop/cop/style/struct_inheritance.rb +13 -0
  315. data/lib/rubocop/cop/style/symbol_proc.rb +7 -6
  316. data/lib/rubocop/cop/style/tally_method.rb +181 -0
  317. data/lib/rubocop/cop/style/ternary_parentheses.rb +11 -0
  318. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -2
  319. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  320. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
  321. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +7 -8
  322. data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
  323. data/lib/rubocop/cop/style/while_until_do.rb +7 -0
  324. data/lib/rubocop/cop/style/while_until_modifier.rb +16 -0
  325. data/lib/rubocop/cop/style/word_array.rb +1 -0
  326. data/lib/rubocop/cop/style/yoda_condition.rb +1 -1
  327. data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
  328. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -3
  329. data/lib/rubocop/cop/team.rb +86 -35
  330. data/lib/rubocop/cop/variable_force/branch.rb +2 -2
  331. data/lib/rubocop/directive_comment.rb +2 -1
  332. data/lib/rubocop/file_patterns.rb +9 -1
  333. data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -9
  334. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  335. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  336. data/lib/rubocop/formatter/simple_text_formatter.rb +0 -2
  337. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
  338. data/lib/rubocop/formatter.rb +22 -21
  339. data/lib/rubocop/lsp/diagnostic.rb +1 -0
  340. data/lib/rubocop/lsp/routes.rb +10 -3
  341. data/lib/rubocop/lsp/runtime.rb +1 -2
  342. data/lib/rubocop/mcp/server.rb +200 -0
  343. data/lib/rubocop/options.rb +35 -4
  344. data/lib/rubocop/path_util.rb +14 -2
  345. data/lib/rubocop/plugin/loader.rb +1 -1
  346. data/lib/rubocop/project_index_loader.rb +66 -0
  347. data/lib/rubocop/result_cache.rb +22 -10
  348. data/lib/rubocop/rspec/cop_helper.rb +8 -0
  349. data/lib/rubocop/rspec/shared_contexts.rb +32 -2
  350. data/lib/rubocop/runner.rb +126 -53
  351. data/lib/rubocop/server/cache.rb +5 -7
  352. data/lib/rubocop/server/core.rb +8 -0
  353. data/lib/rubocop/target_finder.rb +14 -7
  354. data/lib/rubocop/target_ruby.rb +18 -12
  355. data/lib/rubocop/version.rb +21 -3
  356. data/lib/rubocop.rb +22 -96
  357. metadata +27 -5
@@ -27,6 +27,7 @@ module RuboCop
27
27
  # there's parallel execution and the cache is shared.
28
28
  def self.cleanup(config_store, verbose, cache_root_override = nil)
29
29
  return if inhibit_cleanup # OPTIMIZE: For faster testing
30
+ return unless config_store.for_pwd.for_all_cops['MaxFilesInCache']
30
31
 
31
32
  rubocop_cache_dir = cache_root(config_store, cache_root_override)
32
33
  return unless File.exist?(rubocop_cache_dir)
@@ -85,15 +86,23 @@ module RuboCop
85
86
  end
86
87
 
87
88
  def self.cache_root(config_store, cache_root_override = nil)
88
- CacheConfig.root_dir do
89
+ return @cache_root if @cache_root && !cache_root_override
90
+
91
+ result = CacheConfig.root_dir do
89
92
  cache_root_override || config_store.for_pwd.for_all_cops['CacheRootDirectory']
90
93
  end
94
+ @cache_root = result unless cache_root_override
95
+ result
91
96
  end
92
97
 
93
98
  def self.allow_symlinks_in_cache_location?(config_store)
94
99
  config_store.for_pwd.for_all_cops['AllowSymlinksInCacheRootDirectory']
95
100
  end
96
101
 
102
+ def self.reset_config_cache
103
+ @cache_root = nil
104
+ end
105
+
97
106
  attr_reader :path
98
107
 
99
108
  def initialize(file, team, options, config_store, cache_root_override = nil)
@@ -196,6 +205,17 @@ module RuboCop
196
205
  end
197
206
  end
198
207
 
208
+ # Return a hash of the options given at invocation, minus the ones that have
209
+ # no effect on which offenses and disabled line ranges are found, and thus
210
+ # don't affect caching.
211
+ def relevant_options_digest(options)
212
+ @relevant_options_digest ||= {}
213
+ @relevant_options_digest[options] ||= begin
214
+ options = options.reject { |key, _| NON_CHANGING.include?(key) }
215
+ options.to_s.gsub(/[^a-z]+/i, '_')
216
+ end
217
+ end
218
+
199
219
  private
200
220
 
201
221
  def digest(path)
@@ -227,20 +247,12 @@ module RuboCop
227
247
  end
228
248
  end
229
249
 
230
- # Return a hash of the options given at invocation, minus the ones that have
231
- # no effect on which offenses and disabled line ranges are found, and thus
232
- # don't affect caching.
233
- def relevant_options_digest(options)
234
- options = options.reject { |key, _| NON_CHANGING.include?(key) }
235
- options.to_s.gsub(/[^a-z]+/i, '_')
236
- end
237
-
238
250
  # We combine team and options into a single "context" checksum to avoid
239
251
  # making file names that are too long for some filesystems to handle.
240
252
  # This context is for anything that's not (1) the RuboCop executable
241
253
  # checksum or (2) the inspected file checksum.
242
254
  def context_checksum(team, options)
243
- keys = [team.external_dependency_checksum, relevant_options_digest(options)]
255
+ keys = [team.external_dependency_checksum, self.class.relevant_options_digest(options)]
244
256
  Digest::SHA1.hexdigest(keys.join)
245
257
  end
246
258
  end
@@ -6,6 +6,12 @@ require 'tempfile'
6
6
  module CopHelper
7
7
  extend RSpec::SharedContext
8
8
 
9
+ @integrated_plugins = false
10
+
11
+ class << self
12
+ attr_accessor :integrated_plugins
13
+ end
14
+
9
15
  let(:ruby_version) do
10
16
  # The minimum version Prism can parse is 3.3.
11
17
  ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : RuboCop::TargetRuby::DEFAULT_VERSION
@@ -18,11 +24,13 @@ module CopHelper
18
24
 
19
25
  before(:all) do
20
26
  next if ENV['RUBOCOP_CORE_DEVELOPMENT']
27
+ next if CopHelper.integrated_plugins
21
28
 
22
29
  plugins = Gem.loaded_specs.filter_map do |feature_name, feature_specification|
23
30
  feature_name if feature_specification.metadata['default_lint_roller_plugin']
24
31
  end
25
32
  RuboCop::Plugin.integrate_plugins(RuboCop::Config.new, plugins)
33
+ CopHelper.integrated_plugins = true
26
34
  end
27
35
 
28
36
  def inspect_source(source, file = nil)
@@ -2,8 +2,12 @@
2
2
 
3
3
  require 'tmpdir'
4
4
 
5
+ # Reset cached PathUtil.pwd before each example so that tests using Dir.chdir
6
+ # or stubbing Dir.pwd get a fresh value.
7
+ RSpec.configure { |c| c.before { RuboCop::PathUtil.reset_pwd } }
8
+
5
9
  RSpec.shared_context 'isolated environment' do # rubocop:disable Metrics/BlockLength
6
- around do |example|
10
+ around do |example| # rubocop:disable Metrics/BlockLength
7
11
  Dir.mktmpdir do |tmpdir|
8
12
  original_home = Dir.home
9
13
  original_xdg_config_home = ENV.fetch('XDG_CONFIG_HOME', nil)
@@ -26,11 +30,16 @@ RSpec.shared_context 'isolated environment' do # rubocop:disable Metrics/BlockLe
26
30
  begin
27
31
  FileUtils.mkdir_p(working_dir)
28
32
 
29
- Dir.chdir(working_dir) { example.run }
33
+ Dir.chdir(working_dir) do
34
+ RuboCop::PathUtil.reset_pwd
35
+ RuboCop::ResultCache.reset_config_cache
36
+ example.run
37
+ end
30
38
  ensure
31
39
  ENV['HOME'] = original_home
32
40
  ENV['XDG_CONFIG_HOME'] = original_xdg_config_home
33
41
 
42
+ RuboCop::ResultCache.reset_config_cache
34
43
  RuboCop::ConfigLoader.clear_options # This also resets RuboCop::FileFinder.root_level
35
44
  end
36
45
  end
@@ -203,6 +212,27 @@ RSpec.shared_context 'lsp' do
203
212
  end
204
213
  end
205
214
 
215
+ RSpec.shared_context 'with exclude limit tracking' do
216
+ around do |example|
217
+ Dir.mktmpdir('rubocop-exclude-limit') do |dir|
218
+ RuboCop::ExcludeLimit.tmp_dir = Pathname.new(dir)
219
+ example.run
220
+ ensure
221
+ RuboCop::ExcludeLimit.tmp_dir = nil
222
+ end
223
+ end
224
+
225
+ # Reads exclude_limit values from the tmp files written by ExcludeLimit.
226
+ # Returns a hash like { 'Max' => 81 } or nil if no values were written.
227
+ def read_exclude_limit(cop, parameter_name = nil)
228
+ if parameter_name
229
+ read_exclude_limit(cop)[parameter_name]
230
+ else
231
+ RuboCop::ExcludeLimit.read_limits(cop.class.badge.to_s)
232
+ end
233
+ end
234
+ end
235
+
206
236
  RSpec.shared_context 'ruby 2.0' do
207
237
  # Prism supports parsing Ruby 3.3+.
208
238
  let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.0 }
@@ -62,6 +62,8 @@ module RuboCop
62
62
  @errors = []
63
63
  @warnings = []
64
64
  @aborting = false
65
+ @inspected_files = []
66
+ @report_queue = {}
65
67
  end
66
68
 
67
69
  def run(paths)
@@ -70,10 +72,11 @@ module RuboCop
70
72
  ResultCache.source_checksum
71
73
 
72
74
  target_files = find_target_files(paths)
75
+ @project_index = ProjectIndexLoader.build_index(target_files) if project_index_enabled?
76
+
73
77
  if @options[:list_target_files]
74
78
  list_files(target_files)
75
79
  else
76
- warm_cache(target_files) if @options[:parallel]
77
80
  inspect_files(target_files)
78
81
  end
79
82
  rescue Interrupt
@@ -90,21 +93,6 @@ module RuboCop
90
93
 
91
94
  private
92
95
 
93
- # Warms up the RuboCop cache by forking a suitable number of RuboCop
94
- # instances that each inspects its allotted group of files.
95
- def warm_cache(target_files)
96
- saved_options = @options.dup
97
- if target_files.length <= 1
98
- puts 'Skipping parallel inspection: only a single file needs inspection' if @options[:debug]
99
- return
100
- end
101
- puts 'Running parallel inspection' if @options[:debug]
102
- %i[autocorrect safe_autocorrect].each { |opt| @options[opt] = false }
103
- Parallel.each(target_files) { |target_file| file_offenses(target_file) }
104
- ensure
105
- @options = saved_options
106
- end
107
-
108
96
  def find_target_files(paths)
109
97
  target_finder = TargetFinder.new(@config_store, @options)
110
98
  mode = if @options[:only_recognized_file_types]
@@ -116,12 +104,25 @@ module RuboCop
116
104
  target_files.each(&:freeze).freeze
117
105
  end
118
106
 
119
- def inspect_files(files)
120
- inspected_files = []
107
+ def project_index_enabled?
108
+ return false unless @config_store.for_pwd.for_all_cops['UseProjectIndex']
121
109
 
110
+ unless ProjectIndexLoader.available?
111
+ ProjectIndexLoader.warn_unavailable
112
+ return false
113
+ end
114
+
115
+ true
116
+ end
117
+
118
+ def inspect_files(files) # rubocop:disable Metrics/AbcSize
122
119
  formatter_set.started(files)
120
+ file_iterator(files) do |file|
121
+ offenses = process_file(file)
122
+ succeeded = offenses.none? { |o| considered_failure?(o) && offense_displayed?(o) }
123
123
 
124
- each_inspected_file(files) { |file| inspected_files << file }
124
+ [offenses, succeeded]
125
+ end
125
126
  ensure
126
127
  # OPTIMIZE: Calling `ResultCache.cleanup` takes time. This optimization
127
128
  # mainly targets editors that integrates RuboCop. When RuboCop is run
@@ -129,23 +130,91 @@ module RuboCop
129
130
  if files.size > 1 && cached_run?
130
131
  ResultCache.cleanup(@config_store, @options[:debug], @options[:cache_root])
131
132
  end
132
-
133
- formatter_set.finished(inspected_files.freeze)
133
+ formatter_set.finished(@inspected_files.freeze)
134
134
  formatter_set.close_output_files
135
135
  end
136
136
 
137
- def each_inspected_file(files)
138
- files.reduce(true) do |all_passed, file|
139
- offenses = process_file(file)
140
- yield file
137
+ def file_iterator(files, &block)
138
+ all_passed = true
141
139
 
142
- if offenses.any? { |o| considered_failure?(o) && offense_displayed?(o) }
143
- break false if @options[:fail_fast]
140
+ on_start = ->(file, _index) { file_started(file) }
141
+ on_finish = lambda do |file, index, (offenses, passed)|
142
+ all_passed &&= passed
143
+ finished_report(file, index, offenses)
144
+ end
144
145
 
145
- next false
146
- end
146
+ if run_in_parallel?(files)
147
+ parallel_file_iterator(files, on_start, on_finish, &block)
148
+ else
149
+ serial_file_iterator(files, on_start, on_finish, &block)
150
+ end
151
+
152
+ process_remaining_report_queue
153
+
154
+ all_passed
155
+ end
156
+
157
+ def finished_report(file, index, offenses)
158
+ @report_queue[index] = [file, offenses]
159
+ @next_index_to_report ||= 0
160
+ while @report_queue.key?(@next_index_to_report)
161
+ process_report_queue_entry(@next_index_to_report)
162
+ @next_index_to_report += 1
163
+ end
164
+ end
165
+
166
+ def process_report_queue_entry(index)
167
+ file, offenses = @report_queue.delete(index)
168
+ file_finished(file, offenses)
169
+ end
170
+
171
+ def process_remaining_report_queue
172
+ @report_queue.keys.sort.each do |index|
173
+ process_report_queue_entry(index)
174
+ end
175
+ end
176
+
177
+ def run_in_parallel?(files)
178
+ return false if @options[:auto_gen_config]
179
+ return false unless @options[:parallel]
147
180
 
148
- all_passed
181
+ if files.size <= 1
182
+ puts 'Skipping parallel inspection: only a single file needs inspection' if @options[:debug]
183
+ return false
184
+ end
185
+
186
+ return false if project_index_disables_parallel?
187
+
188
+ puts 'Running parallel inspection' if @options[:debug]
189
+
190
+ true
191
+ end
192
+
193
+ def project_index_disables_parallel?
194
+ return false if @project_index.nil? || !Gem.win_platform?
195
+
196
+ if @options[:debug]
197
+ puts 'Skipping parallel inspection: the project index is enabled and parallel ' \
198
+ 'inspection is not yet supported on Windows.'
199
+ end
200
+
201
+ true
202
+ end
203
+
204
+ def parallel_file_iterator(files, on_start, on_finish, &block)
205
+ Parallel.each(files, start: on_start, finish: on_finish, &block)
206
+ end
207
+
208
+ def serial_file_iterator(files, on_start, on_finish, &block)
209
+ files.each_with_index do |file, index|
210
+ on_start.call(file, index)
211
+ result = yield file
212
+ on_finish.call(file, index, result)
213
+
214
+ # Report and count the offending file before stopping so `--fail-fast`
215
+ # still shows its offenses and exits with a failing status.
216
+ _offenses, succeeded = result
217
+ break if @options[:fail_fast] && !succeeded
149
218
  end
150
219
  end
151
220
 
@@ -154,16 +223,13 @@ module RuboCop
154
223
  end
155
224
 
156
225
  def process_file(file)
157
- file_started(file)
158
- offenses = file_offenses(file)
226
+ file_offenses(file)
159
227
  rescue InfiniteCorrectionLoop => e
160
228
  raise e if @options[:raise_cop_error]
161
229
 
162
230
  errors << e
163
231
  warn Rainbow(e.message).red
164
- offenses = e.offenses.compact.sort.freeze
165
- ensure
166
- file_finished(file, offenses || [])
232
+ e.offenses.compact.sort.freeze
167
233
  end
168
234
 
169
235
  def file_offenses(file)
@@ -194,7 +260,7 @@ module RuboCop
194
260
 
195
261
  if real_run_needed
196
262
  offenses = yield
197
- save_in_cache(cache, offenses)
263
+ save_in_cache(cache, offenses) unless Cop::Registry.global.warnings?(file)
198
264
  end
199
265
 
200
266
  offenses
@@ -250,6 +316,7 @@ module RuboCop
250
316
  end
251
317
 
252
318
  def file_finished(file, offenses)
319
+ @inspected_files << file
253
320
  offenses = offenses_to_report(offenses)
254
321
  formatter_set.file_finished(file, offenses)
255
322
  end
@@ -258,10 +325,6 @@ module RuboCop
258
325
  @cached_run ||=
259
326
  (@options[:cache] == 'true' ||
260
327
  (@options[:cache] != 'false' && @config_store.for_pwd.for_all_cops['UseCache'])) &&
261
- # When running --auto-gen-config, there's some processing done in the
262
- # cops related to calculating the Max parameters for Metrics cops. We
263
- # need to do that processing and cannot use caching.
264
- !@options[:auto_gen_config] &&
265
328
  # We can't cache results from code which is piped in to stdin
266
329
  !@options[:stdin]
267
330
  end
@@ -350,16 +413,9 @@ module RuboCop
350
413
 
351
414
  def inspect_file(processed_source, team = mobilize_team(processed_source))
352
415
  extracted_ruby_sources = extract_ruby_sources(processed_source)
353
- offenses = extracted_ruby_sources.flat_map do |extracted_ruby_source|
354
- report = team.investigate(
355
- extracted_ruby_source[:processed_source],
356
- offset: extracted_ruby_source[:offset],
357
- original: processed_source
358
- )
359
- @errors.concat(team.errors)
360
- @warnings.concat(team.warnings)
361
- report.offenses
362
- end
416
+ offenses = team.investigate_fragments(extracted_ruby_sources, original: processed_source)
417
+ @errors.concat(team.errors)
418
+ @warnings.concat(team.warnings)
363
419
  [offenses, team.updated_source_file?]
364
420
  end
365
421
 
@@ -379,7 +435,15 @@ module RuboCop
379
435
 
380
436
  def mobilize_team(processed_source)
381
437
  config = @config_store.for_file(processed_source.path)
382
- Cop::Team.mobilize(mobilized_cop_classes(config), config, @options)
438
+ team = Cop::Team.mobilize(mobilized_cop_classes(config), config, @options)
439
+
440
+ if @project_index
441
+ team.cops.each do |cop|
442
+ cop.project_index = @project_index
443
+ end
444
+ end
445
+
446
+ team
383
447
  end
384
448
 
385
449
  def mobilized_cop_classes(config) # rubocop:disable Metrics/AbcSize
@@ -522,8 +586,17 @@ module RuboCop
522
586
  # level caching in ResultCache.
523
587
  def standby_team(config)
524
588
  @team_by_config ||= {}.compare_by_identity
525
- @team_by_config[config] ||=
526
- Cop::Team.mobilize(mobilized_cop_classes(config), config, @options)
589
+ @team_by_config[config] ||= begin
590
+ team = Cop::Team.mobilize(mobilized_cop_classes(config), config, @options)
591
+
592
+ if @project_index
593
+ team.cops.each do |cop|
594
+ cop.project_index = @project_index
595
+ end
596
+ end
597
+
598
+ team
599
+ end
527
600
  end
528
601
  end
529
602
  end
@@ -114,13 +114,11 @@ module RuboCop
114
114
  end
115
115
 
116
116
  def acquire_lock
117
- lock_file = File.open(lock_path, File::CREAT)
118
- # flock returns 0 if successful, and false if not.
119
- flock_result = lock_file.flock(File::LOCK_EX | File::LOCK_NB)
120
- yield flock_result != false
121
- ensure
122
- lock_file.flock(File::LOCK_UN)
123
- lock_file.close
117
+ File.open(lock_path, File::CREAT) do |lock_file|
118
+ # flock returns 0 if successful, and false if not.
119
+ flock_result = lock_file.flock(File::LOCK_EX | File::LOCK_NB)
120
+ yield flock_result != false
121
+ end
124
122
  end
125
123
 
126
124
  def write_port_and_token_files(port:, token:)
@@ -45,6 +45,8 @@ module RuboCop
45
45
  write_port_and_token_files
46
46
 
47
47
  pid = fork do
48
+ # NOTE: As of Ruby 4.0.0, ZJIT is still under development, while YJIT is production-ready,
49
+ # so support for ZJIT is deferred.
48
50
  if defined?(RubyVM::YJIT.enable)
49
51
  RubyVM::YJIT.enable
50
52
  end
@@ -55,6 +57,12 @@ module RuboCop
55
57
  end
56
58
 
57
59
  Process.waitpid(pid)
60
+
61
+ # The daemon writes its pid file asynchronously after forking, so wait until
62
+ # the server is actually running before returning. This prevents a race where
63
+ # a subsequent command (e.g. `--restart-server`) observes an inconsistent
64
+ # state right after `--start-server` returns.
65
+ Server.wait_for_running_status!(true)
58
66
  end
59
67
 
60
68
  def write_port_and_token_files
@@ -38,16 +38,16 @@ module RuboCop
38
38
  # @param base_dir Root directory under which to search for
39
39
  # ruby source files
40
40
  # @return [Array] Array of filenames
41
- def target_files_in_dir(base_dir = Dir.pwd)
41
+ def target_files_in_dir(base_dir = PathUtil.pwd)
42
42
  # Support Windows: Backslashes from command-line -> forward slashes
43
43
  base_dir = base_dir.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
44
44
  all_files = find_files(base_dir, File::FNM_DOTMATCH)
45
45
  base_dir_config = @config_store.for(base_dir)
46
46
 
47
- target_files = if hidden_path?(base_dir)
47
+ target_files = if hidden_dir?(base_dir)
48
48
  all_files.select { |file| ruby_file?(file) }
49
49
  else
50
- all_files.select { |file| to_inspect?(file, base_dir_config) }
50
+ all_files.select { |file| to_inspect?(file, base_dir, base_dir_config) }
51
51
  end
52
52
 
53
53
  target_files.sort_by!(&order)
@@ -72,15 +72,22 @@ module RuboCop
72
72
 
73
73
  private
74
74
 
75
- def to_inspect?(file, base_dir_config)
75
+ def to_inspect?(file, base_dir, base_dir_config)
76
76
  return false if base_dir_config.file_to_exclude?(file)
77
- return true if !hidden_path?(file) && ruby_file?(file)
77
+ return true if !hidden_file_in_dir?(file, base_dir) && ruby_file?(file)
78
78
 
79
79
  base_dir_config.file_to_include?(file)
80
80
  end
81
81
 
82
- def hidden_path?(path)
83
- path.include?(HIDDEN_PATH_SUBSTRING)
82
+ def hidden_dir?(dir)
83
+ basename = File.basename(dir)
84
+ basename.start_with?('.') && basename != '.' && basename != '..'
85
+ end
86
+
87
+ def hidden_file_in_dir?(file, base_dir)
88
+ base_dir = "#{base_dir}#{File::SEPARATOR}" unless base_dir.end_with?(File::SEPARATOR)
89
+ relative = file.delete_prefix(base_dir)
90
+ relative.start_with?('.') || relative.include?(HIDDEN_PATH_SUBSTRING)
84
91
  end
85
92
 
86
93
  def wanted_dir_patterns(base_dir, exclude_pattern, flags)
@@ -160,21 +160,18 @@ module RuboCop
160
160
  # The target ruby version may be found in a .ruby-version file.
161
161
  # @api private
162
162
  class RubyVersionFile < Source
163
- RUBY_VERSION_FILENAME = '.ruby-version'
164
- RUBY_VERSION_PATTERN = /\A(?:ruby-)?(?<version>\d+\.\d+)/.freeze
165
-
166
163
  def name
167
- "`#{RUBY_VERSION_FILENAME}`"
164
+ "`#{filename}`"
168
165
  end
169
166
 
170
167
  private
171
168
 
172
169
  def filename
173
- RUBY_VERSION_FILENAME
170
+ '.ruby-version'
174
171
  end
175
172
 
176
173
  def pattern
177
- RUBY_VERSION_PATTERN
174
+ /\A(?:ruby-)?(?<version>\d+\.\d+)/.freeze
178
175
  end
179
176
 
180
177
  def find_version
@@ -193,21 +190,29 @@ module RuboCop
193
190
  # starting with `ruby`.
194
191
  # @api private
195
192
  class ToolVersionsFile < RubyVersionFile
196
- TOOL_VERSIONS_FILENAME = '.tool-versions'
197
- TOOL_VERSIONS_PATTERN = /^(?:ruby )(?<version>\d+\.\d+)/.freeze
193
+ private
198
194
 
199
- def name
200
- "`#{TOOL_VERSIONS_FILENAME}`"
195
+ def filename
196
+ '.tool-versions'
201
197
  end
202
198
 
199
+ def pattern
200
+ /^(?:ruby )(?<version>\d+\.\d+)/.freeze
201
+ end
202
+ end
203
+
204
+ # The target ruby version may be found in a mise.toml file, in a line
205
+ # starting with `ruby = "`.
206
+ # @api private
207
+ class MiseTomlFile < RubyVersionFile
203
208
  private
204
209
 
205
210
  def filename
206
- TOOL_VERSIONS_FILENAME
211
+ 'mise.toml'
207
212
  end
208
213
 
209
214
  def pattern
210
- TOOL_VERSIONS_PATTERN
215
+ /^ruby = "(?<version>\d+\.\d+)/.freeze
211
216
  end
212
217
  end
213
218
 
@@ -275,6 +280,7 @@ module RuboCop
275
280
  RuboCopConfig,
276
281
  GemspecFile,
277
282
  RubyVersionFile,
283
+ MiseTomlFile,
278
284
  ToolVersionsFile,
279
285
  BundlerLockFile,
280
286
  Default
@@ -3,12 +3,13 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.84.2'
6
+ STRING = '1.88.1'
7
7
 
8
8
  MSG = '%<version>s (using %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
10
10
  'analyzing as Ruby %<target_ruby_version>s, ' \
11
- 'running on %<ruby_engine>s %<ruby_version>s)%<server_mode>s [%<ruby_platform>s]'
11
+ 'running on %<ruby_engine>s %<ruby_version>s)' \
12
+ '%<rubydex_indicator>s%<server_mode>s [%<ruby_platform>s]'
12
13
 
13
14
  MINIMUM_PARSABLE_PRISM_VERSION = 3.3
14
15
 
@@ -31,6 +32,7 @@ module RuboCop
31
32
  rubocop_ast_version: RuboCop::AST::Version::STRING,
32
33
  target_ruby_version: target_ruby_version,
33
34
  ruby_engine: RUBY_ENGINE, ruby_version: RUBY_VERSION,
35
+ rubydex_indicator: rubydex_indicator(env),
34
36
  server_mode: server_mode,
35
37
  ruby_platform: RUBY_PLATFORM)
36
38
  return verbose_version unless env
@@ -55,7 +57,7 @@ module RuboCop
55
57
 
56
58
  # @api private
57
59
  def self.parser_version(target_ruby_version)
58
- config_path = ConfigFinder.find_config_path(Dir.pwd)
60
+ config_path = ConfigFinder.find_config_path(PathUtil.pwd)
59
61
  yaml = Util.silence_warnings do
60
62
  ConfigLoader.load_yaml_configuration(config_path)
61
63
  end
@@ -152,6 +154,22 @@ module RuboCop
152
154
  STRING.match('\d+\.\d+').to_s
153
155
  end
154
156
 
157
+ # @api private
158
+ def self.rubydex_indicator(env)
159
+ env && rubydex_enabled?(env) && ProjectIndexLoader.available? ? ' +Rubydex' : ''
160
+ end
161
+
162
+ # @api private
163
+ def self.rubydex_enabled?(env)
164
+ config_for_pwd(env).for_all_cops['UseProjectIndex']
165
+ rescue StandardError
166
+ # Keep `rubocop -V` usable when the config cannot be loaded (broken YAML,
167
+ # missing `inherit_from` target, etc). It is the first command users run to
168
+ # diagnose a broken setup, so the indicator just hides rather than letting
169
+ # the version banner crash.
170
+ false
171
+ end
172
+
155
173
  # @api private
156
174
  def self.server_mode
157
175
  RuboCop.const_defined?(:Server) && Server.running? ? ' +server' : ''