rubocop 1.79.2 → 1.88.0

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 (421) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +259 -90
  5. data/config/obsoletion.yml +30 -1
  6. data/exe/rubocop +1 -8
  7. data/lib/rubocop/cache_config.rb +29 -0
  8. data/lib/rubocop/cli/command/auto_generate_config.rb +36 -4
  9. data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
  10. data/lib/rubocop/cli/command/lsp.rb +1 -1
  11. data/lib/rubocop/cli/command/mcp.rb +19 -0
  12. data/lib/rubocop/cli/command/show_cops.rb +2 -2
  13. data/lib/rubocop/cli/command/show_docs_url.rb +4 -8
  14. data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
  15. data/lib/rubocop/cli.rb +35 -9
  16. data/lib/rubocop/comment_config.rb +59 -17
  17. data/lib/rubocop/config.rb +14 -10
  18. data/lib/rubocop/config_finder.rb +1 -1
  19. data/lib/rubocop/config_loader.rb +37 -23
  20. data/lib/rubocop/config_loader_resolver.rb +20 -10
  21. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -2
  22. data/lib/rubocop/config_store.rb +7 -2
  23. data/lib/rubocop/config_validator.rb +1 -1
  24. data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
  25. data/lib/rubocop/cop/base.rb +25 -4
  26. data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
  27. data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
  28. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -2
  29. data/lib/rubocop/cop/correctors/alignment_corrector.rb +26 -7
  30. data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
  31. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
  32. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -5
  33. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +33 -2
  34. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  35. data/lib/rubocop/cop/correctors.rb +28 -0
  36. data/lib/rubocop/cop/documentation.rb +2 -3
  37. data/lib/rubocop/cop/exclude_limit.rb +31 -5
  38. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
  39. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -2
  40. data/lib/rubocop/cop/gemspec/require_mfa.rb +5 -5
  41. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +12 -7
  42. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
  43. data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
  44. data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
  45. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
  46. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +9 -9
  47. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  48. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
  49. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  50. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +5 -3
  51. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
  52. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  53. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -2
  54. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  55. data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
  56. data/lib/rubocop/cop/layout/block_alignment.rb +41 -4
  57. data/lib/rubocop/cop/layout/case_indentation.rb +3 -1
  58. data/lib/rubocop/cop/layout/class_structure.rb +14 -7
  59. data/lib/rubocop/cop/layout/dot_position.rb +2 -2
  60. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +26 -7
  61. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +31 -13
  62. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +2 -2
  63. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
  64. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +12 -2
  65. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +16 -2
  66. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
  67. data/lib/rubocop/cop/layout/end_alignment.rb +10 -3
  68. data/lib/rubocop/cop/layout/first_argument_indentation.rb +34 -1
  69. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +26 -0
  70. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +7 -1
  71. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
  72. data/lib/rubocop/cop/layout/hash_alignment.rb +3 -6
  73. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  74. data/lib/rubocop/cop/layout/heredoc_indentation.rb +33 -3
  75. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  76. data/lib/rubocop/cop/layout/indentation_width.rb +123 -7
  77. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  78. data/lib/rubocop/cop/layout/line_length.rb +26 -9
  79. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +57 -57
  80. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +9 -2
  81. data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
  82. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +56 -56
  83. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
  84. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +229 -39
  85. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +8 -4
  86. data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
  87. data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -1
  88. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
  89. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  90. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  91. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  92. data/lib/rubocop/cop/layout/space_around_keyword.rb +4 -2
  93. data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -1
  94. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
  95. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  96. data/lib/rubocop/cop/lint/ambiguous_assignment.rb +1 -11
  97. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  98. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +1 -10
  99. data/lib/rubocop/cop/lint/circular_argument_reference.rb +45 -3
  100. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +4 -3
  101. data/lib/rubocop/cop/lint/constant_reassignment.rb +93 -11
  102. data/lib/rubocop/cop/lint/constant_resolution.rb +6 -6
  103. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
  104. data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
  105. data/lib/rubocop/cop/lint/debugger.rb +0 -3
  106. data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
  107. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
  108. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  109. data/lib/rubocop/cop/lint/duplicate_methods.rb +111 -12
  110. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
  111. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  112. data/lib/rubocop/cop/lint/empty_block.rb +4 -4
  113. data/lib/rubocop/cop/lint/empty_conditional_body.rb +6 -1
  114. data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
  115. data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
  116. data/lib/rubocop/cop/lint/empty_when.rb +8 -1
  117. data/lib/rubocop/cop/lint/ensure_return.rb +19 -1
  118. data/lib/rubocop/cop/lint/erb_new_arguments.rb +4 -2
  119. data/lib/rubocop/cop/lint/float_comparison.rb +2 -1
  120. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -1
  121. data/lib/rubocop/cop/lint/interpolation_check.rb +25 -5
  122. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  123. data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -1
  124. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
  125. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +9 -12
  126. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +19 -10
  127. data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
  128. data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
  129. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +20 -0
  130. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +4 -2
  131. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  132. data/lib/rubocop/cop/lint/number_conversion.rb +19 -10
  133. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  134. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +3 -0
  135. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +7 -7
  136. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +3 -13
  137. data/lib/rubocop/cop/lint/raise_exception.rb +1 -1
  138. data/lib/rubocop/cop/lint/rand_one.rb +1 -1
  139. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +27 -10
  140. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +6 -12
  141. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +15 -4
  142. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
  143. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +36 -12
  144. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +12 -2
  145. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +10 -3
  146. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
  147. data/lib/rubocop/cop/lint/redundant_with_object.rb +5 -0
  148. data/lib/rubocop/cop/lint/refinement_import_methods.rb +8 -1
  149. data/lib/rubocop/cop/lint/regexp_as_condition.rb +9 -1
  150. data/lib/rubocop/cop/lint/require_parentheses.rb +13 -4
  151. data/lib/rubocop/cop/lint/require_range_parentheses.rb +2 -1
  152. data/lib/rubocop/cop/lint/require_relative_self_path.rb +7 -5
  153. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  154. data/lib/rubocop/cop/lint/rescue_type.rb +1 -1
  155. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +18 -0
  156. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +7 -1
  157. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
  158. data/lib/rubocop/cop/lint/script_permission.rb +5 -1
  159. data/lib/rubocop/cop/lint/self_assignment.rb +39 -7
  160. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -1
  161. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  162. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  163. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +14 -0
  164. data/lib/rubocop/cop/lint/shared_mutable_default.rb +3 -1
  165. data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
  166. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +12 -0
  167. data/lib/rubocop/cop/lint/symbol_conversion.rb +21 -4
  168. data/lib/rubocop/cop/lint/syntax.rb +25 -1
  169. data/lib/rubocop/cop/lint/to_enum_arguments.rb +28 -1
  170. data/lib/rubocop/cop/lint/to_json.rb +12 -16
  171. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  172. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +5 -1
  173. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +4 -2
  174. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
  175. data/lib/rubocop/cop/lint/unreachable_code.rb +7 -5
  176. data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
  177. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  178. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
  179. data/lib/rubocop/cop/lint/useless_assignment.rb +53 -25
  180. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +4 -4
  181. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +2 -0
  182. data/lib/rubocop/cop/lint/useless_or.rb +15 -2
  183. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +8 -4
  184. data/lib/rubocop/cop/lint/useless_setter_call.rb +4 -1
  185. data/lib/rubocop/cop/lint/useless_times.rb +22 -1
  186. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +37 -11
  187. data/lib/rubocop/cop/lint/void.rb +39 -12
  188. data/lib/rubocop/cop/message_annotator.rb +1 -1
  189. data/lib/rubocop/cop/metrics/block_length.rb +1 -1
  190. data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
  191. data/lib/rubocop/cop/metrics/collection_literal_length.rb +1 -1
  192. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  193. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  194. data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
  195. data/lib/rubocop/cop/migration/department_name.rb +12 -1
  196. data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
  197. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +4 -6
  198. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  199. data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
  200. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
  201. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +5 -5
  202. data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
  203. data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -60
  204. data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
  205. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  206. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  207. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  208. data/lib/rubocop/cop/mixin/project_index_help.rb +48 -0
  209. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  210. data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
  211. data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -5
  212. data/lib/rubocop/cop/mixin.rb +86 -0
  213. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
  214. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  215. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  216. data/lib/rubocop/cop/naming/method_name.rb +5 -3
  217. data/lib/rubocop/cop/naming/predicate_method.rb +32 -8
  218. data/lib/rubocop/cop/naming/predicate_prefix.rb +12 -12
  219. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
  220. data/lib/rubocop/cop/offense.rb +17 -1
  221. data/lib/rubocop/cop/registry.rb +62 -38
  222. data/lib/rubocop/cop/security/eval.rb +15 -2
  223. data/lib/rubocop/cop/security/io_methods.rb +1 -1
  224. data/lib/rubocop/cop/security/json_load.rb +33 -11
  225. data/lib/rubocop/cop/style/access_modifier_declarations.rb +15 -4
  226. data/lib/rubocop/cop/style/accessor_grouping.rb +4 -2
  227. data/lib/rubocop/cop/style/alias.rb +15 -3
  228. data/lib/rubocop/cop/style/and_or.rb +2 -1
  229. data/lib/rubocop/cop/style/arguments_forwarding.rb +25 -7
  230. data/lib/rubocop/cop/style/array_first_last.rb +12 -1
  231. data/lib/rubocop/cop/style/array_intersect.rb +50 -12
  232. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +50 -0
  233. data/lib/rubocop/cop/style/array_join.rb +4 -2
  234. data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
  235. data/lib/rubocop/cop/style/attr.rb +5 -2
  236. data/lib/rubocop/cop/style/bare_percent_literals.rb +4 -3
  237. data/lib/rubocop/cop/style/begin_block.rb +3 -1
  238. data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
  239. data/lib/rubocop/cop/style/block_delimiters.rb +39 -32
  240. data/lib/rubocop/cop/style/case_equality.rb +29 -15
  241. data/lib/rubocop/cop/style/character_literal.rb +2 -2
  242. data/lib/rubocop/cop/style/class_and_module_children.rb +19 -2
  243. data/lib/rubocop/cop/style/class_equality_comparison.rb +21 -13
  244. data/lib/rubocop/cop/style/class_methods_definitions.rb +11 -5
  245. data/lib/rubocop/cop/style/collection_compact.rb +36 -16
  246. data/lib/rubocop/cop/style/colon_method_call.rb +16 -7
  247. data/lib/rubocop/cop/style/combinable_loops.rb +5 -0
  248. data/lib/rubocop/cop/style/comparable_clamp.rb +12 -1
  249. data/lib/rubocop/cop/style/concat_array_literals.rb +7 -1
  250. data/lib/rubocop/cop/style/conditional_assignment.rb +14 -19
  251. data/lib/rubocop/cop/style/constant_visibility.rb +20 -12
  252. data/lib/rubocop/cop/style/copyright.rb +22 -11
  253. data/lib/rubocop/cop/style/date_time.rb +4 -4
  254. data/lib/rubocop/cop/style/dig_chain.rb +5 -0
  255. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +1 -1
  256. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
  257. data/lib/rubocop/cop/style/documentation.rb +6 -6
  258. data/lib/rubocop/cop/style/documentation_method.rb +8 -8
  259. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  260. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  261. data/lib/rubocop/cop/style/each_with_object.rb +2 -0
  262. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  263. data/lib/rubocop/cop/style/empty_class_definition.rb +119 -0
  264. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  265. data/lib/rubocop/cop/style/empty_method.rb +0 -6
  266. data/lib/rubocop/cop/style/encoding.rb +7 -1
  267. data/lib/rubocop/cop/style/end_block.rb +3 -1
  268. data/lib/rubocop/cop/style/endless_method.rb +23 -5
  269. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  270. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  271. data/lib/rubocop/cop/style/file_open.rb +84 -0
  272. data/lib/rubocop/cop/style/file_write.rb +21 -16
  273. data/lib/rubocop/cop/style/float_division.rb +15 -1
  274. data/lib/rubocop/cop/style/for.rb +3 -0
  275. data/lib/rubocop/cop/style/format_string.rb +4 -3
  276. data/lib/rubocop/cop/style/format_string_token.rb +49 -5
  277. data/lib/rubocop/cop/style/global_vars.rb +5 -2
  278. data/lib/rubocop/cop/style/guard_clause.rb +27 -22
  279. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +27 -9
  280. data/lib/rubocop/cop/style/hash_conversion.rb +1 -1
  281. data/lib/rubocop/cop/style/hash_lookup_method.rb +106 -0
  282. data/lib/rubocop/cop/style/hash_slice.rb +16 -0
  283. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  284. data/lib/rubocop/cop/style/hash_transform_keys.rb +17 -7
  285. data/lib/rubocop/cop/style/hash_transform_values.rb +17 -7
  286. data/lib/rubocop/cop/style/if_inside_else.rb +16 -7
  287. data/lib/rubocop/cop/style/if_unless_modifier.rb +58 -18
  288. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +12 -12
  289. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +4 -1
  290. data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -5
  291. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  292. data/lib/rubocop/cop/style/inline_comment.rb +4 -1
  293. data/lib/rubocop/cop/style/ip_addresses.rb +1 -2
  294. data/lib/rubocop/cop/style/lambda_call.rb +8 -8
  295. data/lib/rubocop/cop/style/magic_comment_format.rb +3 -3
  296. data/lib/rubocop/cop/style/map_join.rb +123 -0
  297. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
  298. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
  299. data/lib/rubocop/cop/style/method_def_parentheses.rb +2 -4
  300. data/lib/rubocop/cop/style/min_max_comparison.rb +1 -1
  301. data/lib/rubocop/cop/style/module_member_existence_check.rb +110 -0
  302. data/lib/rubocop/cop/style/multiline_if_then.rb +4 -4
  303. data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -4
  304. data/lib/rubocop/cop/style/mutable_constant.rb +106 -12
  305. data/lib/rubocop/cop/style/negative_array_index.rb +220 -0
  306. data/lib/rubocop/cop/style/nil_comparison.rb +11 -10
  307. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  308. data/lib/rubocop/cop/style/non_nil_check.rb +5 -11
  309. data/lib/rubocop/cop/style/not.rb +2 -0
  310. data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
  311. data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
  312. data/lib/rubocop/cop/style/one_line_conditional.rb +21 -12
  313. data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
  314. data/lib/rubocop/cop/style/parallel_assignment.rb +14 -3
  315. data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
  316. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -0
  317. data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
  318. data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
  319. data/lib/rubocop/cop/style/proc.rb +3 -2
  320. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  321. data/lib/rubocop/cop/style/reduce_to_hash.rb +200 -0
  322. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  323. data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
  324. data/lib/rubocop/cop/style/redundant_begin.rb +37 -3
  325. data/lib/rubocop/cop/style/redundant_condition.rb +6 -3
  326. data/lib/rubocop/cop/style/redundant_constant_base.rb +5 -5
  327. data/lib/rubocop/cop/style/redundant_each.rb +3 -3
  328. data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
  329. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
  330. data/lib/rubocop/cop/style/redundant_format.rb +27 -5
  331. data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
  332. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
  333. data/lib/rubocop/cop/style/redundant_line_continuation.rb +16 -0
  334. data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
  335. data/lib/rubocop/cop/style/redundant_parentheses.rb +36 -30
  336. data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
  337. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
  338. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +2 -2
  339. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
  340. data/lib/rubocop/cop/style/redundant_return.rb +3 -1
  341. data/lib/rubocop/cop/style/redundant_self.rb +2 -2
  342. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
  343. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  344. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +114 -0
  345. data/lib/rubocop/cop/style/regexp_literal.rb +31 -2
  346. data/lib/rubocop/cop/style/rescue_modifier.rb +3 -3
  347. data/lib/rubocop/cop/style/reverse_find.rb +51 -0
  348. data/lib/rubocop/cop/style/safe_navigation.rb +25 -8
  349. data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
  350. data/lib/rubocop/cop/style/select_by_range.rb +197 -0
  351. data/lib/rubocop/cop/style/select_by_regexp.rb +51 -21
  352. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  353. data/lib/rubocop/cop/style/semicolon.rb +41 -8
  354. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  355. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -1
  356. data/lib/rubocop/cop/style/single_line_methods.rb +3 -1
  357. data/lib/rubocop/cop/style/sole_nested_conditional.rb +12 -3
  358. data/lib/rubocop/cop/style/special_global_vars.rb +6 -1
  359. data/lib/rubocop/cop/style/string_concatenation.rb +17 -13
  360. data/lib/rubocop/cop/style/struct_inheritance.rb +13 -0
  361. data/lib/rubocop/cop/style/super_arguments.rb +2 -2
  362. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  363. data/lib/rubocop/cop/style/symbol_proc.rb +7 -6
  364. data/lib/rubocop/cop/style/tally_method.rb +181 -0
  365. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -2
  366. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
  367. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  368. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
  369. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
  370. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  371. data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
  372. data/lib/rubocop/cop/style/while_until_do.rb +7 -0
  373. data/lib/rubocop/cop/style/while_until_modifier.rb +16 -0
  374. data/lib/rubocop/cop/style/word_array.rb +1 -0
  375. data/lib/rubocop/cop/style/yoda_condition.rb +1 -1
  376. data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
  377. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -3
  378. data/lib/rubocop/cop/team.rb +87 -36
  379. data/lib/rubocop/cop/util.rb +2 -3
  380. data/lib/rubocop/cop/utils/format_string.rb +10 -0
  381. data/lib/rubocop/cop/variable_force/branch.rb +30 -6
  382. data/lib/rubocop/cop/variable_force/variable.rb +1 -1
  383. data/lib/rubocop/cop/variable_force.rb +9 -7
  384. data/lib/rubocop/cops_documentation_generator.rb +4 -4
  385. data/lib/rubocop/directive_comment.rb +48 -4
  386. data/lib/rubocop/file_patterns.rb +9 -1
  387. data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
  388. data/lib/rubocop/formatter/disabled_config_formatter.rb +38 -14
  389. data/lib/rubocop/formatter/formatter_set.rb +2 -2
  390. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  391. data/lib/rubocop/formatter/simple_text_formatter.rb +0 -2
  392. data/lib/rubocop/formatter/tap_formatter.rb +5 -2
  393. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
  394. data/lib/rubocop/formatter.rb +22 -21
  395. data/lib/rubocop/lsp/diagnostic.rb +18 -33
  396. data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
  397. data/lib/rubocop/lsp/routes.rb +43 -7
  398. data/lib/rubocop/lsp/runtime.rb +13 -4
  399. data/lib/rubocop/lsp/stdin_runner.rb +8 -17
  400. data/lib/rubocop/magic_comment.rb +20 -0
  401. data/lib/rubocop/mcp/server.rb +200 -0
  402. data/lib/rubocop/options.rb +35 -4
  403. data/lib/rubocop/path_util.rb +14 -2
  404. data/lib/rubocop/plugin/loader.rb +1 -1
  405. data/lib/rubocop/project_index_loader.rb +66 -0
  406. data/lib/rubocop/rake_task.rb +1 -1
  407. data/lib/rubocop/remote_config.rb +10 -8
  408. data/lib/rubocop/result_cache.rb +61 -38
  409. data/lib/rubocop/rspec/cop_helper.rb +8 -0
  410. data/lib/rubocop/rspec/shared_contexts.rb +39 -5
  411. data/lib/rubocop/rspec/support.rb +2 -1
  412. data/lib/rubocop/runner.rb +134 -57
  413. data/lib/rubocop/server/cache.rb +6 -29
  414. data/lib/rubocop/server/core.rb +8 -0
  415. data/lib/rubocop/target_finder.rb +17 -10
  416. data/lib/rubocop/target_ruby.rb +31 -14
  417. data/lib/rubocop/version.rb +21 -3
  418. data/lib/rubocop.rb +28 -96
  419. data/lib/ruby_lsp/rubocop/addon.rb +23 -8
  420. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
  421. metadata +38 -9
@@ -11,6 +11,9 @@ module RuboCop
11
11
  # (unless autocorrections happened).
12
12
  # rubocop:disable Metrics/ClassLength
13
13
  class Team
14
+ InvestigationResult = Struct.new(:report, :corrector)
15
+ private_constant :InvestigationResult
16
+
14
17
  # @return [Team]
15
18
  def self.new(cop_or_classes, config, options = {})
16
19
  # Support v0 api:
@@ -89,31 +92,25 @@ module RuboCop
89
92
 
90
93
  # @return [Commissioner::InvestigationReport]
91
94
  def investigate(processed_source, offset: 0, original: processed_source)
92
- be_ready
93
-
94
- # The autocorrection process may have to be repeated multiple times
95
- # until there are no corrections left to perform
96
- # To speed things up, run autocorrecting cops by themselves, and only
97
- # run the other cops when no corrections are left
98
- on_duty = roundup_relevant_cops(processed_source)
95
+ result = investigate_with_corrector(processed_source, offset: offset, original: original)
96
+ autocorrect(processed_source, result.corrector)
97
+ result.report
98
+ end
99
99
 
100
- autocorrect_cops, other_cops = on_duty.partition(&:autocorrect?)
101
- report = investigate_partial(autocorrect_cops, processed_source,
102
- offset: offset, original: original)
100
+ # @return [Array<Offense>]
101
+ def investigate_fragments(fragments, original:)
102
+ @updated_source_file = false
103
103
 
104
- unless autocorrect(processed_source, report, offset: offset, original: original)
105
- # If we corrected some errors, another round of inspection will be
106
- # done, and any other offenses will be caught then, so only need
107
- # to check other_cops if no correction was done
108
- report = report.merge(investigate_partial(other_cops, processed_source,
109
- offset: offset, original: original))
110
- end
104
+ offenses, errors, warnings, corrector =
105
+ fragments.each_with_object([[], [], [], nil]) do |fragment, data|
106
+ investigate_fragment(fragment, original, data)
107
+ end
111
108
 
112
- process_errors(processed_source.path, report.errors)
109
+ autocorrect(original, corrector)
110
+ @errors = errors
111
+ @warnings = warnings
113
112
 
114
- report
115
- ensure
116
- @ready = false
113
+ offenses
117
114
  end
118
115
 
119
116
  # @deprecated
@@ -136,14 +133,13 @@ module RuboCop
136
133
 
137
134
  private
138
135
 
139
- def autocorrect(processed_source, report, original:, offset:)
136
+ def autocorrect(processed_source, corrector)
140
137
  @updated_source_file = false
141
138
  return unless autocorrect?
142
- return if report.processed_source.parser_error
143
-
144
- new_source = autocorrect_report(report, original: original, offset: offset)
139
+ return unless corrector
140
+ return if corrector.empty?
145
141
 
146
- return unless new_source
142
+ new_source = corrector.rewrite
147
143
 
148
144
  if @options[:stdin]
149
145
  # holds source read in from stdin, when --stdin option is used
@@ -174,11 +170,59 @@ module RuboCop
174
170
  commissioner.investigate(processed_source, offset: offset, original: original)
175
171
  end
176
172
 
173
+ def investigate_with_corrector(processed_source, offset:, original:)
174
+ be_ready
175
+
176
+ # The autocorrection process may have to be repeated multiple times
177
+ # until there are no corrections left to perform
178
+ # To speed things up, run autocorrecting cops by themselves, and only
179
+ # run the other cops when no corrections are left
180
+ on_duty = roundup_relevant_cops(processed_source)
181
+
182
+ autocorrect_cops, other_cops = on_duty.partition(&:autocorrect?)
183
+ report = investigate_partial(autocorrect_cops, processed_source,
184
+ offset: offset, original: original)
185
+
186
+ corrector = collated_corrector(report, offset: offset, original: original)
187
+
188
+ unless corrector
189
+ # If we corrected some errors, another round of inspection will be
190
+ # done, and any other offenses will be caught then, so only need
191
+ # to check other_cops if no correction was done
192
+ report = report.merge(investigate_partial(other_cops, processed_source,
193
+ offset: offset, original: original))
194
+ end
195
+
196
+ process_errors(processed_source.path, report.errors)
197
+
198
+ InvestigationResult.new(report, corrector)
199
+ ensure
200
+ @ready = false
201
+ end
202
+
203
+ def investigate_fragment(fragment, original, data)
204
+ offenses, errors, warnings, corrector = data
205
+ result = investigate_with_corrector(
206
+ fragment[:processed_source],
207
+ offset: fragment[:offset],
208
+ original: original
209
+ )
210
+
211
+ offenses.concat(result.report.offenses)
212
+ if result.corrector
213
+ corrector ||= Corrector.new(original)
214
+ merge_corrector!(corrector, result.corrector, offset: 0)
215
+ data[3] = corrector
216
+ end
217
+ errors.concat(@errors)
218
+ warnings.concat(@warnings)
219
+ end
220
+
177
221
  # @return [Array<cop>]
178
222
  def roundup_relevant_cops(processed_source)
179
223
  cops.select do |cop|
180
- next true if processed_source.comment_config.cop_opted_in?(cop)
181
224
  next false if cop.excluded_file?(processed_source.file_path)
225
+ next true if processed_source.comment_config.cop_opted_in?(cop)
182
226
  next false unless @registry.enabled?(cop, @config)
183
227
 
184
228
  support_target_ruby_version?(cop) && support_target_rails_version?(cop)
@@ -200,28 +244,35 @@ module RuboCop
200
244
  cop.class.support_target_rails_version?(cop.target_rails_version)
201
245
  end
202
246
 
203
- def autocorrect_report(report, offset:, original:)
247
+ def collated_corrector(report, offset:, original:)
248
+ return unless autocorrect?
249
+ return if report.processed_source.parser_error
250
+
204
251
  corrector = collate_corrections(report, offset: offset, original: original)
205
252
 
206
- corrector.rewrite unless corrector.empty?
253
+ corrector unless corrector.empty?
207
254
  end
208
255
 
209
256
  def collate_corrections(report, offset:, original:)
210
257
  corrector = Corrector.new(original)
211
258
 
212
259
  each_corrector(report) do |to_merge|
213
- suppress_clobbering do
214
- if offset.positive?
215
- corrector.import!(to_merge, offset: offset)
216
- else
217
- corrector.merge!(to_merge)
218
- end
219
- end
260
+ merge_corrector!(corrector, to_merge, offset: offset)
220
261
  end
221
262
 
222
263
  corrector
223
264
  end
224
265
 
266
+ def merge_corrector!(corrector, to_merge, offset:)
267
+ suppress_clobbering do
268
+ if corrector.source_buffer == to_merge.source_buffer
269
+ corrector.merge!(to_merge)
270
+ else
271
+ corrector.import!(to_merge, offset: offset)
272
+ end
273
+ end
274
+ end
275
+
225
276
  def each_corrector(report)
226
277
  skips = Set.new
227
278
  report.cop_reports.each do |cop_report|
@@ -117,10 +117,9 @@ module RuboCop
117
117
  # with calls chained to the end of it.
118
118
  def first_part_of_call_chain(node)
119
119
  while node
120
- case node.type
121
- when :send
120
+ if node.call_type?
122
121
  node = node.receiver
123
- when :block
122
+ elsif node.any_block_type?
124
123
  node = node.send_node
125
124
  else
126
125
  break
@@ -71,6 +71,16 @@ module RuboCop
71
71
  name && @source.include?('{')
72
72
  end
73
73
 
74
+ def variable_width?
75
+ !!width&.start_with?('*')
76
+ end
77
+
78
+ def variable_width_argument_number
79
+ return unless variable_width?
80
+
81
+ width == '*' ? 1 : width.match(DIGIT_DOLLAR)['arg_number'].to_i
82
+ end
83
+
74
84
  # Number of arguments required for the format sequence
75
85
  def arity
76
86
  @source.scan('*').count + 1
@@ -254,8 +254,8 @@ module RuboCop
254
254
  end
255
255
  end
256
256
 
257
- # Mix-in module for logical operator control structures.
258
- module LogicalOperator
257
+ # Mix-in module for operator control structures.
258
+ module Operator
259
259
  def always_run?
260
260
  left_body?
261
261
  end
@@ -263,7 +263,15 @@ module RuboCop
263
263
 
264
264
  # left_body && right_body
265
265
  class And < Base
266
- include LogicalOperator
266
+ include Operator
267
+
268
+ define_predicate :left_body?, child_index: 0
269
+ define_predicate :right_body?, child_index: 1
270
+ end
271
+
272
+ # left_body &&= right_body
273
+ class AndAsgn < Base
274
+ include Operator
267
275
 
268
276
  define_predicate :left_body?, child_index: 0
269
277
  define_predicate :right_body?, child_index: 1
@@ -271,7 +279,23 @@ module RuboCop
271
279
 
272
280
  # left_body || right_body
273
281
  class Or < Base
274
- include LogicalOperator
282
+ include Operator
283
+
284
+ define_predicate :left_body?, child_index: 0
285
+ define_predicate :right_body?, child_index: 1
286
+ end
287
+
288
+ # left_body ||= right_body
289
+ class OrAsgn < Base
290
+ include Operator
291
+
292
+ define_predicate :left_body?, child_index: 0
293
+ define_predicate :right_body?, child_index: 1
294
+ end
295
+
296
+ # e.g. left_body += right_body
297
+ class OpAsgn < Base
298
+ include Operator
275
299
 
276
300
  define_predicate :left_body?, child_index: 0
277
301
  define_predicate :right_body?, child_index: 1
@@ -322,8 +346,8 @@ module RuboCop
322
346
  end
323
347
  end
324
348
 
325
- CLASSES_BY_TYPE = Base.classes.each_with_object({}) do |klass, classes|
326
- classes[klass.type] = klass
349
+ CLASSES_BY_TYPE = Base.classes.to_h do |klass|
350
+ [klass.type, klass]
327
351
  end
328
352
  end
329
353
  end
@@ -79,7 +79,7 @@ module RuboCop
79
79
  parent = parent.parent if parent&.begin_type?
80
80
  return false if parent.nil?
81
81
 
82
- parent.type?(:if, :while, :until) && parent.modifier_form?
82
+ parent.basic_conditional? && parent.modifier_form?
83
83
  end
84
84
 
85
85
  def capture_with_block!
@@ -238,11 +238,16 @@ module RuboCop
238
238
  end
239
239
 
240
240
  def process_loop(node)
241
- if POST_CONDITION_LOOP_TYPES.include?(node.type)
241
+ if node.post_condition_loop?
242
242
  # See the comment at the end of file for this behavior.
243
243
  condition_node, body_node = *node
244
244
  process_node(body_node)
245
245
  process_node(condition_node)
246
+ elsif node.for_type?
247
+ # In `for item in items` the rightmost expression is evaluated first.
248
+ process_node(node.collection)
249
+ process_node(node.variable)
250
+ process_node(node.body) if node.body
246
251
  else
247
252
  process_children(node)
248
253
  end
@@ -356,17 +361,14 @@ module RuboCop
356
361
  end
357
362
 
358
363
  def reference_assignments(loop_assignments, loop_node)
359
- node = loop_assignments.first.node
360
-
361
364
  # If inside a branching statement, mark all as referenced.
362
365
  # Otherwise, mark only the last assignment as referenced.
363
366
  # Note that `rescue` must be considered as branching because of
364
367
  # the `retry` keyword.
365
- if node.each_ancestor(*BRANCH_NODES).any? || node.parent.each_descendant(*BRANCH_NODES).any?
366
- loop_assignments.each { |assignment| assignment.reference!(loop_node) }
367
- else
368
- loop_assignments.last&.reference!(loop_node)
368
+ loop_assignments.each do |assignment|
369
+ assignment.reference!(loop_node) if assignment.node.each_ancestor(*BRANCH_NODES).any?
369
370
  end
371
+ loop_assignments.last&.reference!(loop_node)
370
372
  end
371
373
 
372
374
  def scanned_node?(node)
@@ -194,10 +194,10 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
194
194
 
195
195
  def configurations(department, cop, cop_config)
196
196
  header = ['Name', 'Default value', 'Configurable values']
197
- configs = cop_config
198
- .each_key
199
- .reject { |key| key.start_with?('Supported') }
200
- .reject { |key| key.start_with?('AllowMultipleStyles') }
197
+ configs = cop_config.each_key.reject do |key|
198
+ key == 'AllowMultipleStyles' ||
199
+ (key != 'SupportedTypes' && key.start_with?('Supported'))
200
+ end
201
201
  return '' if configs.empty?
202
202
 
203
203
  content = configs.map do |name|
@@ -14,11 +14,17 @@ module RuboCop
14
14
  # @api private
15
15
  COP_NAME_PATTERN = '([A-Za-z]\w+/)*(?:[A-Za-z]\w+)'
16
16
  # @api private
17
+ COP_NAME_PATTERN_NC = '(?:[A-Za-z]\w+/)*[A-Za-z]\w+'
18
+ # @api private
19
+ COP_NAMES_PATTERN_NC = "(?:#{COP_NAME_PATTERN_NC} , )*#{COP_NAME_PATTERN_NC}"
20
+ # @api private
17
21
  COP_NAMES_PATTERN = "(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}"
18
22
  # @api private
19
23
  COPS_PATTERN = "(all|#{COP_NAMES_PATTERN})"
20
24
  # @api private
21
- AVAILABLE_MODES = %w[disable enable todo].freeze
25
+ PUSH_POP_ARGS_PATTERN = "([+\\-]#{COP_NAME_PATTERN_NC}(?:\\s+[+\\-]#{COP_NAME_PATTERN_NC})*)"
26
+ # @api private
27
+ AVAILABLE_MODES = %w[disable enable todo push pop].freeze
22
28
  # @api private
23
29
  DIRECTIVE_MARKER_PATTERN = '# rubocop : '
24
30
  # @api private
@@ -27,7 +33,7 @@ module RuboCop
27
33
  DIRECTIVE_HEADER_PATTERN = "#{DIRECTIVE_MARKER_PATTERN}((?:#{AVAILABLE_MODES.join('|')}))\\b"
28
34
  # @api private
29
35
  DIRECTIVE_COMMENT_REGEXP = Regexp.new(
30
- "#{DIRECTIVE_HEADER_PATTERN} #{COPS_PATTERN}"
36
+ "#{DIRECTIVE_HEADER_PATTERN}(?:\\s+#{COPS_PATTERN}|\\s+#{PUSH_POP_ARGS_PATTERN})?"
31
37
  .gsub(' ', '\s*')
32
38
  )
33
39
  # @api private
@@ -46,7 +52,8 @@ module RuboCop
46
52
  def initialize(comment, cop_registry = Cop::Registry.global)
47
53
  @comment = comment
48
54
  @cop_registry = cop_registry
49
- @match_data = comment.text.match(DIRECTIVE_COMMENT_REGEXP)
55
+ match_data = comment.text.match(DIRECTIVE_COMMENT_REGEXP)
56
+ @match_data = match_data&.pre_match&.match?(/\A#\s*\z/) ? nil : match_data
50
57
  @mode, @cops = match_captures
51
58
  end
52
59
 
@@ -58,6 +65,7 @@ module RuboCop
58
65
  # Checks if the comment is malformed as a `# rubocop:` directive
59
66
  def malformed?
60
67
  return true if !start_with_marker? || @match_data.nil?
68
+ return true if missing_cop_name?
61
69
 
62
70
  tail = @match_data.post_match.lstrip
63
71
  !(tail.empty? || tail.start_with?(TRAILING_COMMENT_MARKER))
@@ -65,6 +73,8 @@ module RuboCop
65
73
 
66
74
  # Checks if the directive comment is missing a cop name
67
75
  def missing_cop_name?
76
+ return false if push? || pop?
77
+
68
78
  MALFORMED_DIRECTIVE_WITHOUT_COP_NAME_REGEXP.match?(comment.text)
69
79
  end
70
80
 
@@ -88,7 +98,13 @@ module RuboCop
88
98
 
89
99
  # Returns match captures to directive comment pattern
90
100
  def match_captures
91
- @match_captures ||= @match_data&.captures
101
+ @match_captures ||= @match_data && begin
102
+ captures = @match_data.captures
103
+ mode = captures[0]
104
+ # COPS_PATTERN is at captures[1], PUSH_POP_ARGS_PATTERN is at captures[4]
105
+ cops = captures[1] || captures[4]
106
+ [mode, cops]
107
+ end
92
108
  end
93
109
 
94
110
  # Checks if this directive disables cops
@@ -101,6 +117,21 @@ module RuboCop
101
117
  mode == 'enable'
102
118
  end
103
119
 
120
+ # Checks if this directive is a push
121
+ def push?
122
+ mode == 'push'
123
+ end
124
+
125
+ # Checks if this directive is a pop
126
+ def pop?
127
+ mode == 'pop'
128
+ end
129
+
130
+ # Returns the push arguments as a hash of cop names with their operations
131
+ def push_args
132
+ @push_args ||= parse_push_args
133
+ end
134
+
104
135
  # Checks if this directive enables all cops
105
136
  def enabled_all?
106
137
  !disabled? && all_cops?
@@ -176,5 +207,18 @@ module RuboCop
176
207
  def exclude_lint_department_cops(cops)
177
208
  cops - [LINT_REDUNDANT_DIRECTIVE_COP, LINT_SYNTAX_COP]
178
209
  end
210
+
211
+ def parse_push_args
212
+ return {} unless push? && cops
213
+
214
+ args = {}
215
+ cops.split.each do |cop_spec|
216
+ op = cop_spec[0]
217
+ cop_name = cop_spec[1..]
218
+ args[op] ||= []
219
+ args[op] << cop_name
220
+ end
221
+ args
222
+ end
179
223
  end
180
224
  end
@@ -21,11 +21,19 @@ module RuboCop
21
21
  def initialize(patterns)
22
22
  @strings = Set.new
23
23
  @patterns = []
24
+ @match_cache = {}
24
25
  partition_patterns(patterns)
25
26
  end
26
27
 
27
28
  def match?(path)
28
- @strings.include?(path) || @patterns.any? { |pattern| PathUtil.match_path?(pattern, path) }
29
+ # `FilePatterns.from` memoizes one instance per pattern array (by identity),
30
+ # so this cache is shared across every cop using the same Include/Exclude
31
+ # list. Patterns are immutable within a run, so caching by path is safe.
32
+ cached = @match_cache[path]
33
+ return cached unless cached.nil?
34
+
35
+ @match_cache[path] =
36
+ @strings.include?(path) || @patterns.any? { |pattern| PathUtil.match_path?(pattern, path) }
29
37
  end
30
38
 
31
39
  private
@@ -47,8 +47,11 @@ module RuboCop
47
47
  def report_highlighted_area(highlighted_area)
48
48
  space_area = highlighted_area.source_buffer.slice(0...highlighted_area.begin_pos)
49
49
  source_area = highlighted_area.source
50
- output.puts("#{' ' * Unicode::DisplayWidth.of(space_area)}" \
51
- "#{'^' * Unicode::DisplayWidth.of(source_area)}")
50
+ output.puts("#{to_whitespace(space_area)}#{'^' * Unicode::DisplayWidth.of(source_area)}")
51
+ end
52
+
53
+ def to_whitespace(string)
54
+ "#{string.delete("^\t")}#{' ' * Unicode::DisplayWidth.of(string.delete("\t"))}"
52
55
  end
53
56
  end
54
57
  end
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Formatter
5
5
  # This formatter displays a YAML configuration file where all cops that
6
6
  # detected any offenses are configured to not detect the offense.
7
- class DisabledConfigFormatter < BaseFormatter
7
+ class DisabledConfigFormatter < BaseFormatter # rubocop:disable Metrics/ClassLength
8
8
  include PathUtil
9
9
 
10
10
  HEADING = <<~COMMENTS
@@ -17,6 +17,23 @@ module RuboCop
17
17
  # versions of RuboCop, may require this file to be generated again.
18
18
  COMMENTS
19
19
 
20
+ EXCLUDED_CONFIG_KEYS = %w[
21
+ AutoCorrect
22
+ Description
23
+ Enabled
24
+ Exclude
25
+ Include
26
+ Reference
27
+ References
28
+ Safe
29
+ SafeAutoCorrect
30
+ Severity
31
+ StyleGuide
32
+ VersionAdded
33
+ VersionChanged
34
+ VersionRemoved
35
+ ].freeze
36
+
20
37
  @config_to_allow_offenses = {}
21
38
  @detected_styles = {}
22
39
 
@@ -74,12 +91,9 @@ module RuboCop
74
91
  command = 'rubocop --auto-gen-config'
75
92
 
76
93
  command += ' --auto-gen-only-exclude' if @options[:auto_gen_only_exclude]
77
-
78
- if no_exclude_limit?
79
- command += ' --no-exclude-limit'
80
- elsif @exclude_limit_option
81
- command += format(' --exclude-limit %<limit>d', limit: Integer(@exclude_limit_option))
82
- end
94
+ command += ' --disable-pending-cops' if @options[:disable_pending_cops]
95
+ command += ' --enable-pending-cops' if @options[:enable_pending_cops]
96
+ command += exclude_limit_option
83
97
  command += ' --no-offense-counts' unless show_offense_counts?
84
98
 
85
99
  command += ' --no-auto-gen-timestamp' unless show_timestamp?
@@ -89,6 +103,16 @@ module RuboCop
89
103
  command
90
104
  end
91
105
 
106
+ def exclude_limit_option
107
+ if no_exclude_limit?
108
+ ' --no-exclude-limit'
109
+ elsif @exclude_limit_option
110
+ format(' --exclude-limit %<limit>d', limit: Integer(@exclude_limit_option))
111
+ else
112
+ ''
113
+ end
114
+ end
115
+
92
116
  def timestamp
93
117
  show_timestamp? ? "on #{Time.now.utc} " : ''
94
118
  end
@@ -114,6 +138,9 @@ module RuboCop
114
138
  end
115
139
 
116
140
  def set_max(cfg, cop_name)
141
+ exclude_limits = RuboCop::ExcludeLimit.read_limits(cop_name)
142
+ cfg[:exclude_limit] = exclude_limits unless exclude_limits.empty?
143
+
117
144
  return unless cfg[:exclude_limit]
118
145
 
119
146
  cfg.merge!(cfg[:exclude_limit]) if should_set_max?(cop_name)
@@ -138,7 +165,7 @@ module RuboCop
138
165
  output_buffer.puts "# Offense count: #{offense_count}" if show_offense_counts?
139
166
 
140
167
  cop_class = Cop::Registry.global.find_by_cop_name(cop_name)
141
- default_cfg = default_config(cop_name)
168
+ default_cfg = default_config(cop_name) || @config_for_pwd[cop_name]
142
169
 
143
170
  if supports_safe_autocorrect?(cop_class, default_cfg)
144
171
  output_buffer.puts '# This cop supports safe autocorrection (--autocorrect).'
@@ -163,10 +190,7 @@ module RuboCop
163
190
  end
164
191
 
165
192
  def cop_config_params(default_cfg, cfg)
166
- default_cfg.keys -
167
- %w[Description StyleGuide Reference References Enabled Exclude Safe
168
- SafeAutoCorrect VersionAdded VersionChanged VersionRemoved] -
169
- cfg.keys
193
+ default_cfg.keys - EXCLUDED_CONFIG_KEYS - cfg.keys
170
194
  end
171
195
 
172
196
  def output_cop_param_comments(output_buffer, params, default_cfg)
@@ -178,7 +202,7 @@ module RuboCop
178
202
  next unless value.is_a?(Array)
179
203
  next if value.empty?
180
204
 
181
- value.map! { |v| v.nil? ? '~' : v } # Change nil back to ~ as in the YAML file.
205
+ value = value.map { |v| v.nil? ? '~' : v } # Change nil back to ~ as in the YAML file.
182
206
  output_buffer.puts "# #{param}: #{value.uniq.join(', ')}"
183
207
  end
184
208
  end
@@ -219,7 +243,7 @@ module RuboCop
219
243
 
220
244
  def output_exclude_list(output_buffer, offending_files, cop_name)
221
245
  require 'pathname'
222
- parent = Pathname.new(Dir.pwd)
246
+ parent = Pathname.new(PathUtil.pwd)
223
247
 
224
248
  output_buffer.puts ' Exclude:'
225
249
  excludes(offending_files, cop_name, parent).each do |exclude_path|
@@ -57,7 +57,7 @@ module RuboCop
57
57
  if output_path
58
58
  dir_path = File.dirname(output_path)
59
59
  FileUtils.mkdir_p(dir_path)
60
- output = File.open(output_path, 'w')
60
+ output = File.open(output_path, 'w') # rubocop:disable Style/FileOpen
61
61
  else
62
62
  output = $stdout
63
63
  end
@@ -86,7 +86,7 @@ module RuboCop
86
86
 
87
87
  def builtin_formatter_class(specified_key)
88
88
  matching_keys = BUILTIN_FORMATTERS_FOR_KEYS.keys.select do |key|
89
- /^\[#{specified_key}\]/.match?(key) || specified_key == key.delete('[]')
89
+ key.start_with?("[#{specified_key}]") || specified_key == key.delete('[]')
90
90
  end
91
91
 
92
92
  if matching_keys.empty?
@@ -93,7 +93,7 @@ module RuboCop
93
93
 
94
94
  def classname_attribute_value(file)
95
95
  @classname_attribute_value_cache ||= Hash.new do |hash, key|
96
- hash[key] = key.delete_suffix('.rb').gsub("#{Dir.pwd}/", '').tr('/', '.')
96
+ hash[key] = key.delete_suffix('.rb').gsub("#{PathUtil.pwd}/", '').tr('/', '.')
97
97
  end
98
98
  @classname_attribute_value_cache[file]
99
99
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'colorizable'
4
-
5
3
  module RuboCop
6
4
  module Formatter
7
5
  # A basic formatter that displays only files with offenses.
@@ -39,8 +39,11 @@ module RuboCop
39
39
  def report_highlighted_area(highlighted_area)
40
40
  space_area = highlighted_area.source_buffer.slice(0...highlighted_area.begin_pos)
41
41
  source_area = highlighted_area.source
42
- output.puts("# #{' ' * Unicode::DisplayWidth.of(space_area)}" \
43
- "#{'^' * Unicode::DisplayWidth.of(source_area)}")
42
+ output.puts("# #{to_whitespace(space_area)}#{'^' * Unicode::DisplayWidth.of(source_area)}")
43
+ end
44
+
45
+ def to_whitespace(string)
46
+ "#{string.delete("^\t")}#{' ' * Unicode::DisplayWidth.of(string.delete("\t"))}"
44
47
  end
45
48
 
46
49
  def report_offense(file, offense)
@@ -24,7 +24,7 @@ module RuboCop
24
24
  def file_finished(file, offenses)
25
25
  return if offenses.empty?
26
26
 
27
- path = Pathname.new(file).relative_path_from(Pathname.new(Dir.pwd))
27
+ path = Pathname.new(file).relative_path_from(Pathname.new(PathUtil.pwd))
28
28
  @offense_counts[path] = offenses.size
29
29
  end
30
30