rubocop 1.71.1 → 1.92.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 (705) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +23 -19
  4. data/config/default.yml +885 -168
  5. data/config/internal_affairs.yml +20 -0
  6. data/config/obsoletion.yml +47 -4
  7. data/exe/rubocop +2 -9
  8. data/lib/rubocop/cache_config.rb +29 -0
  9. data/lib/rubocop/cached_data.rb +50 -5
  10. data/lib/rubocop/changed_files.rb +134 -0
  11. data/lib/rubocop/cli/command/auto_generate_config.rb +36 -4
  12. data/lib/rubocop/cli/command/cop_names.rb +57 -0
  13. data/lib/rubocop/cli/command/execute_runner.rb +54 -3
  14. data/lib/rubocop/cli/command/explain.rb +34 -0
  15. data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
  16. data/lib/rubocop/cli/command/lsp.rb +1 -1
  17. data/lib/rubocop/cli/command/mcp.rb +19 -0
  18. data/lib/rubocop/cli/command/show_cops.rb +8 -2
  19. data/lib/rubocop/cli/command/show_docs_url.rb +8 -10
  20. data/lib/rubocop/cli/command/suggest_extensions.rb +8 -2
  21. data/lib/rubocop/cli.rb +59 -17
  22. data/lib/rubocop/comment_config/directive_range.rb +34 -0
  23. data/lib/rubocop/comment_config/disable_next.rb +143 -0
  24. data/lib/rubocop/comment_config/push_pop.rb +55 -0
  25. data/lib/rubocop/comment_config.rb +98 -45
  26. data/lib/rubocop/config.rb +137 -19
  27. data/lib/rubocop/config_finder.rb +1 -1
  28. data/lib/rubocop/config_loader.rb +75 -49
  29. data/lib/rubocop/config_loader_resolver.rb +124 -33
  30. data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
  31. data/lib/rubocop/config_obsoletion/extracted_cop.rb +6 -3
  32. data/lib/rubocop/config_obsoletion/removed_cop.rb +9 -1
  33. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  34. data/lib/rubocop/config_obsoletion.rb +47 -3
  35. data/lib/rubocop/config_store.rb +7 -2
  36. data/lib/rubocop/config_validator.rb +75 -12
  37. data/lib/rubocop/cop/autocorrect_logic.rb +43 -17
  38. data/lib/rubocop/cop/badge.rb +9 -1
  39. data/lib/rubocop/cop/base.rb +128 -35
  40. data/lib/rubocop/cop/bundler/gem_comment.rb +5 -4
  41. data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
  42. data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -11
  43. data/lib/rubocop/cop/bundler.rb +19 -0
  44. data/lib/rubocop/cop/commissioner.rb +13 -11
  45. data/lib/rubocop/cop/cop_documentation.rb +81 -0
  46. data/lib/rubocop/cop/cop_explanation.rb +140 -0
  47. data/lib/rubocop/cop/corrector.rb +4 -4
  48. data/lib/rubocop/cop/correctors/alignment_corrector.rb +92 -11
  49. data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
  50. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +22 -7
  51. data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
  52. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
  53. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +29 -2
  54. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -5
  55. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +8 -1
  56. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +73 -2
  57. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  58. data/lib/rubocop/cop/correctors.rb +28 -0
  59. data/lib/rubocop/cop/documentation.rb +3 -4
  60. data/lib/rubocop/cop/exclude_limit.rb +31 -5
  61. data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
  62. data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
  63. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  64. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +49 -17
  65. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +2 -9
  66. data/lib/rubocop/cop/gemspec/require_mfa.rb +22 -5
  67. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +12 -7
  68. data/lib/rubocop/cop/gemspec.rb +22 -0
  69. data/lib/rubocop/cop/generator/registration_injector.rb +188 -0
  70. data/lib/rubocop/cop/generator.rb +5 -1
  71. data/lib/rubocop/cop/internal_affairs/example_description.rb +9 -5
  72. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
  73. data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
  74. data/lib/rubocop/cop/internal_affairs/location_exists.rb +142 -0
  75. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
  76. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +16 -20
  77. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  78. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -2
  79. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +6 -2
  80. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +85 -0
  81. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +2 -2
  82. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  83. data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +1 -7
  84. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  85. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +5 -3
  86. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +1 -7
  87. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +13 -2
  88. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
  89. data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
  90. data/lib/rubocop/cop/internal_affairs.rb +3 -16
  91. data/lib/rubocop/cop/layout/argument_alignment.rb +4 -2
  92. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  93. data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
  94. data/lib/rubocop/cop/layout/block_alignment.rb +86 -4
  95. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  96. data/lib/rubocop/cop/layout/case_indentation.rb +28 -10
  97. data/lib/rubocop/cop/layout/class_structure.rb +172 -36
  98. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
  99. data/lib/rubocop/cop/layout/comment_indentation.rb +17 -7
  100. data/lib/rubocop/cop/layout/condition_position.rb +13 -3
  101. data/lib/rubocop/cop/layout/def_end_alignment.rb +5 -1
  102. data/lib/rubocop/cop/layout/dot_position.rb +2 -2
  103. data/lib/rubocop/cop/layout/else_alignment.rb +3 -15
  104. data/lib/rubocop/cop/layout/empty_comment.rb +8 -10
  105. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +27 -9
  106. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +63 -5
  107. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +14 -5
  108. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +46 -21
  109. data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
  110. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +101 -0
  111. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +34 -4
  112. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +8 -29
  113. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +2 -0
  114. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +14 -3
  115. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +17 -3
  116. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
  117. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
  118. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
  119. data/lib/rubocop/cop/layout/end_alignment.rb +20 -8
  120. data/lib/rubocop/cop/layout/extra_spacing.rb +109 -3
  121. data/lib/rubocop/cop/layout/first_argument_indentation.rb +57 -3
  122. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +18 -5
  123. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +26 -0
  124. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +25 -18
  125. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
  126. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +6 -0
  127. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
  128. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +11 -0
  129. data/lib/rubocop/cop/layout/hash_alignment.rb +20 -18
  130. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +5 -3
  131. data/lib/rubocop/cop/layout/heredoc_indentation.rb +48 -3
  132. data/lib/rubocop/cop/layout/indentation_style.rb +5 -2
  133. data/lib/rubocop/cop/layout/indentation_width.rb +159 -12
  134. data/lib/rubocop/cop/layout/leading_comment_space.rb +40 -1
  135. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +10 -4
  136. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
  137. data/lib/rubocop/cop/layout/line_length.rb +201 -30
  138. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +69 -57
  139. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +8 -2
  140. data/lib/rubocop/cop/layout/multiline_block_layout.rb +11 -1
  141. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +63 -56
  142. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +7 -1
  143. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +259 -40
  144. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
  145. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  146. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +9 -5
  147. data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
  148. data/lib/rubocop/cop/layout/redundant_line_break.rb +111 -7
  149. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +29 -9
  150. data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
  151. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  152. data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
  153. data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
  154. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +10 -4
  155. data/lib/rubocop/cop/layout/space_around_keyword.rb +20 -3
  156. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  157. data/lib/rubocop/cop/layout/space_around_operators.rb +30 -4
  158. data/lib/rubocop/cop/layout/space_before_block_braces.rb +5 -1
  159. data/lib/rubocop/cop/layout/space_before_brackets.rb +6 -39
  160. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
  161. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +55 -36
  162. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +32 -8
  163. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
  164. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  165. data/lib/rubocop/cop/layout.rb +114 -0
  166. data/lib/rubocop/cop/lazy_loader.rb +41 -0
  167. data/lib/rubocop/cop/lint/ambiguous_assignment.rb +9 -17
  168. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +72 -1
  169. data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
  170. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +3 -11
  171. data/lib/rubocop/cop/lint/ambiguous_range.rb +6 -2
  172. data/lib/rubocop/cop/lint/argument_mismatch.rb +99 -0
  173. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
  174. data/lib/rubocop/cop/lint/assignment_in_condition.rb +15 -1
  175. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  176. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -8
  177. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +4 -3
  178. data/lib/rubocop/cop/lint/constant_reassignment.rb +94 -15
  179. data/lib/rubocop/cop/lint/constant_resolution.rb +31 -6
  180. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +240 -0
  181. data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
  182. data/lib/rubocop/cop/lint/debugger.rb +13 -4
  183. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  184. data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
  185. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +5 -2
  186. data/lib/rubocop/cop/lint/deprecated_reference.rb +194 -0
  187. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  188. data/lib/rubocop/cop/lint/duplicate_methods.rb +506 -41
  189. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
  190. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  191. data/lib/rubocop/cop/lint/empty_block.rb +4 -4
  192. data/lib/rubocop/cop/lint/empty_conditional_body.rb +22 -65
  193. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  194. data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
  195. data/lib/rubocop/cop/lint/empty_interpolation.rb +14 -1
  196. data/lib/rubocop/cop/lint/empty_when.rb +8 -1
  197. data/lib/rubocop/cop/lint/ensure_return.rb +19 -1
  198. data/lib/rubocop/cop/lint/erb_new_arguments.rb +4 -8
  199. data/lib/rubocop/cop/lint/float_comparison.rb +33 -10
  200. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  201. data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
  202. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -2
  203. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -1
  204. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -2
  205. data/lib/rubocop/cop/lint/inherit_exception.rb +53 -7
  206. data/lib/rubocop/cop/lint/interpolation_check.rb +25 -6
  207. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  208. data/lib/rubocop/cop/lint/literal_as_condition.rb +152 -11
  209. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
  210. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +75 -37
  211. data/lib/rubocop/cop/lint/loop.rb +24 -2
  212. data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +245 -0
  213. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +60 -23
  214. data/lib/rubocop/cop/lint/missing_super.rb +31 -1
  215. data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -2
  216. data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
  217. data/lib/rubocop/cop/lint/name_typo.rb +270 -0
  218. data/lib/rubocop/cop/lint/nested_method_definition.rb +2 -2
  219. data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
  220. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +20 -0
  221. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +4 -2
  222. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +4 -4
  223. data/lib/rubocop/cop/lint/number_conversion.rb +20 -11
  224. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  225. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +11 -0
  226. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  227. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +7 -7
  228. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +15 -4
  229. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +20 -14
  230. data/lib/rubocop/cop/lint/raise_exception.rb +30 -11
  231. data/lib/rubocop/cop/lint/rand_one.rb +1 -1
  232. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +160 -39
  233. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +53 -19
  234. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +28 -6
  235. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  236. data/lib/rubocop/cop/lint/redundant_require_statement.rb +5 -25
  237. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +134 -12
  238. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +13 -4
  239. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +267 -0
  240. data/lib/rubocop/cop/lint/redundant_with_index.rb +5 -3
  241. data/lib/rubocop/cop/lint/redundant_with_object.rb +8 -0
  242. data/lib/rubocop/cop/lint/refinement_import_methods.rb +8 -1
  243. data/lib/rubocop/cop/lint/regexp_as_condition.rb +9 -1
  244. data/lib/rubocop/cop/lint/require_parentheses.rb +13 -4
  245. data/lib/rubocop/cop/lint/require_range_parentheses.rb +3 -2
  246. data/lib/rubocop/cop/lint/require_relative_self_path.rb +7 -5
  247. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  248. data/lib/rubocop/cop/lint/rescue_type.rb +2 -2
  249. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  250. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +28 -4
  251. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +9 -5
  252. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
  253. data/lib/rubocop/cop/lint/script_permission.rb +5 -1
  254. data/lib/rubocop/cop/lint/self_assignment.rb +63 -6
  255. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -1
  256. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  257. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  258. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +27 -1
  259. data/lib/rubocop/cop/lint/shared_mutable_default.rb +14 -1
  260. data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
  261. data/lib/rubocop/cop/lint/super_argument_mismatch.rb +179 -0
  262. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  263. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +122 -0
  264. data/lib/rubocop/cop/lint/symbol_conversion.rb +21 -4
  265. data/lib/rubocop/cop/lint/syntax.rb +25 -1
  266. data/lib/rubocop/cop/lint/to_enum_arguments.rb +73 -5
  267. data/lib/rubocop/cop/lint/to_json.rb +20 -17
  268. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  269. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +5 -1
  270. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +54 -11
  271. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +2 -0
  272. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -1
  273. data/lib/rubocop/cop/lint/unreachable_code.rb +16 -9
  274. data/lib/rubocop/cop/lint/unreachable_loop.rb +5 -5
  275. data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
  276. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  277. data/lib/rubocop/cop/lint/unused_private_method.rb +234 -0
  278. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
  279. data/lib/rubocop/cop/lint/useless_access_modifier.rb +31 -6
  280. data/lib/rubocop/cop/lint/useless_assignment.rb +63 -27
  281. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +107 -0
  282. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +92 -0
  283. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  284. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +11 -10
  285. data/lib/rubocop/cop/lint/useless_or.rb +111 -0
  286. data/lib/rubocop/cop/lint/useless_rescue.rb +2 -3
  287. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +13 -7
  288. data/lib/rubocop/cop/lint/useless_setter_call.rb +4 -1
  289. data/lib/rubocop/cop/lint/useless_times.rb +22 -1
  290. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +201 -0
  291. data/lib/rubocop/cop/lint/void.rb +68 -22
  292. data/lib/rubocop/cop/lint.rb +179 -0
  293. data/lib/rubocop/cop/message_annotator.rb +7 -3
  294. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  295. data/lib/rubocop/cop/metrics/block_length.rb +2 -1
  296. data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
  297. data/lib/rubocop/cop/metrics/class_length.rb +4 -2
  298. data/lib/rubocop/cop/metrics/collection_literal_length.rb +1 -1
  299. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
  300. data/lib/rubocop/cop/metrics/method_length.rb +3 -2
  301. data/lib/rubocop/cop/metrics/module_length.rb +4 -2
  302. data/lib/rubocop/cop/metrics/perceived_complexity.rb +37 -7
  303. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  304. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
  305. data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
  306. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  307. data/lib/rubocop/cop/metrics.rb +31 -0
  308. data/lib/rubocop/cop/migration/department_name.rb +11 -5
  309. data/lib/rubocop/cop/migration.rb +13 -0
  310. data/lib/rubocop/cop/mixin/alignment.rb +7 -3
  311. data/lib/rubocop/cop/mixin/allowed_methods.rb +5 -5
  312. data/lib/rubocop/cop/mixin/allowed_pattern.rb +9 -5
  313. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  314. data/lib/rubocop/cop/mixin/check_line_breakable.rb +44 -23
  315. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +10 -8
  316. data/lib/rubocop/cop/mixin/code_length.rb +10 -2
  317. data/lib/rubocop/cop/mixin/comments_help.rb +2 -3
  318. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -2
  319. data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
  320. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  321. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +13 -2
  322. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
  323. data/lib/rubocop/cop/mixin/endless_method_body_help.rb +69 -0
  324. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +13 -5
  325. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  326. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +20 -0
  327. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -2
  328. data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
  329. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +59 -17
  330. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +52 -25
  331. data/lib/rubocop/cop/mixin/hash_subset.rb +28 -6
  332. data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
  333. data/lib/rubocop/cop/mixin/hash_transform_method.rb +32 -78
  334. data/lib/rubocop/cop/mixin/indexed_method_arity.rb +94 -0
  335. data/lib/rubocop/cop/mixin/line_length_help.rb +52 -11
  336. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  337. data/lib/rubocop/cop/mixin/min_branches_count.rb +3 -1
  338. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
  339. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -1
  340. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +10 -1
  341. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +2 -2
  342. data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
  343. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  344. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +79 -8
  345. data/lib/rubocop/cop/mixin/project_index_help.rb +203 -0
  346. data/lib/rubocop/cop/mixin/range_help.rb +16 -5
  347. data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +181 -0
  348. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  349. data/lib/rubocop/cop/mixin/statement_modifier.rb +66 -10
  350. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  351. data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
  352. data/lib/rubocop/cop/mixin/trailing_comma.rb +23 -6
  353. data/lib/rubocop/cop/mixin.rb +93 -0
  354. data/lib/rubocop/cop/naming/accessor_method_name.rb +8 -0
  355. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +17 -1
  356. data/lib/rubocop/cop/naming/block_forwarding.rb +7 -4
  357. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  358. data/lib/rubocop/cop/naming/file_name.rb +6 -5
  359. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +9 -2
  360. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
  361. data/lib/rubocop/cop/naming/inclusive_language.rb +8 -2
  362. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +13 -6
  363. data/lib/rubocop/cop/naming/method_name.rb +190 -15
  364. data/lib/rubocop/cop/naming/predicate_method.rb +330 -0
  365. data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +65 -8
  366. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -6
  367. data/lib/rubocop/cop/naming/variable_name.rb +51 -6
  368. data/lib/rubocop/cop/naming/variable_number.rb +3 -1
  369. data/lib/rubocop/cop/naming.rb +31 -0
  370. data/lib/rubocop/cop/offense.rb +108 -9
  371. data/lib/rubocop/cop/registry.rb +234 -65
  372. data/lib/rubocop/cop/security/eval.rb +17 -3
  373. data/lib/rubocop/cop/security/io_methods.rb +2 -2
  374. data/lib/rubocop/cop/security/json_load.rb +45 -11
  375. data/lib/rubocop/cop/security/marshal_load.rb +1 -1
  376. data/lib/rubocop/cop/security/open.rb +1 -0
  377. data/lib/rubocop/cop/security.rb +19 -0
  378. data/lib/rubocop/cop/severity.rb +12 -0
  379. data/lib/rubocop/cop/style/access_modifier_declarations.rb +54 -13
  380. data/lib/rubocop/cop/style/accessor_grouping.rb +47 -10
  381. data/lib/rubocop/cop/style/alias.rb +33 -8
  382. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
  383. data/lib/rubocop/cop/style/and_or.rb +6 -1
  384. data/lib/rubocop/cop/style/arguments_forwarding.rb +52 -37
  385. data/lib/rubocop/cop/style/array_first_last.rb +13 -3
  386. data/lib/rubocop/cop/style/array_intersect.rb +136 -38
  387. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +50 -0
  388. data/lib/rubocop/cop/style/array_join.rb +4 -2
  389. data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
  390. data/lib/rubocop/cop/style/attr.rb +8 -6
  391. data/lib/rubocop/cop/style/bare_percent_literals.rb +4 -3
  392. data/lib/rubocop/cop/style/begin_block.rb +3 -1
  393. data/lib/rubocop/cop/style/bitwise_predicate.rb +13 -5
  394. data/lib/rubocop/cop/style/block_delimiters.rb +71 -40
  395. data/lib/rubocop/cop/style/case_equality.rb +29 -15
  396. data/lib/rubocop/cop/style/case_like_if.rb +12 -11
  397. data/lib/rubocop/cop/style/character_literal.rb +2 -2
  398. data/lib/rubocop/cop/style/class_and_module_children.rb +179 -27
  399. data/lib/rubocop/cop/style/class_equality_comparison.rb +22 -14
  400. data/lib/rubocop/cop/style/class_methods_definitions.rb +19 -5
  401. data/lib/rubocop/cop/style/collection_compact.rb +37 -17
  402. data/lib/rubocop/cop/style/collection_methods.rb +1 -0
  403. data/lib/rubocop/cop/style/collection_querying.rb +167 -0
  404. data/lib/rubocop/cop/style/colon_method_call.rb +16 -7
  405. data/lib/rubocop/cop/style/combinable_loops.rb +88 -9
  406. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  407. data/lib/rubocop/cop/style/commented_keyword.rb +12 -5
  408. data/lib/rubocop/cop/style/comparable_between.rb +78 -0
  409. data/lib/rubocop/cop/style/comparable_clamp.rb +12 -1
  410. data/lib/rubocop/cop/style/concat_array_literals.rb +53 -9
  411. data/lib/rubocop/cop/style/conditional_assignment.rb +58 -24
  412. data/lib/rubocop/cop/style/constant_visibility.rb +23 -12
  413. data/lib/rubocop/cop/style/copyright.rb +27 -12
  414. data/lib/rubocop/cop/style/data_inheritance.rb +25 -0
  415. data/lib/rubocop/cop/style/date_time.rb +4 -4
  416. data/lib/rubocop/cop/style/def_with_parentheses.rb +22 -5
  417. data/lib/rubocop/cop/style/dig_chain.rb +6 -1
  418. data/lib/rubocop/cop/style/dir_empty.rb +4 -0
  419. data/lib/rubocop/cop/style/directive_scope.rb +304 -0
  420. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +184 -20
  421. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
  422. data/lib/rubocop/cop/style/documentation.rb +53 -6
  423. data/lib/rubocop/cop/style/documentation_method.rb +8 -12
  424. data/lib/rubocop/cop/style/double_negation.rb +14 -3
  425. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  426. data/lib/rubocop/cop/style/each_with_object.rb +4 -3
  427. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  428. data/lib/rubocop/cop/style/empty_case_condition.rb +13 -4
  429. data/lib/rubocop/cop/style/empty_class_definition.rb +126 -0
  430. data/lib/rubocop/cop/style/empty_heredoc.rb +4 -0
  431. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  432. data/lib/rubocop/cop/style/empty_literal.rb +12 -3
  433. data/lib/rubocop/cop/style/empty_method.rb +15 -9
  434. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +110 -0
  435. data/lib/rubocop/cop/style/encoding.rb +7 -1
  436. data/lib/rubocop/cop/style/end_block.rb +3 -1
  437. data/lib/rubocop/cop/style/endless_method.rb +252 -19
  438. data/lib/rubocop/cop/style/env_home.rb +4 -0
  439. data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
  440. data/lib/rubocop/cop/style/even_odd.rb +11 -1
  441. data/lib/rubocop/cop/style/exact_regexp_match.rb +52 -8
  442. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  443. data/lib/rubocop/cop/style/explicit_block_argument.rb +62 -9
  444. data/lib/rubocop/cop/style/exponential_notation.rb +5 -4
  445. data/lib/rubocop/cop/style/fetch_env_var.rb +33 -7
  446. data/lib/rubocop/cop/style/file_null.rb +6 -4
  447. data/lib/rubocop/cop/style/file_open.rb +84 -0
  448. data/lib/rubocop/cop/style/file_write.rb +21 -16
  449. data/lib/rubocop/cop/style/float_division.rb +43 -15
  450. data/lib/rubocop/cop/style/for.rb +48 -1
  451. data/lib/rubocop/cop/style/format_string.rb +44 -9
  452. data/lib/rubocop/cop/style/format_string_token.rb +86 -16
  453. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +5 -3
  454. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  455. data/lib/rubocop/cop/style/global_vars.rb +5 -2
  456. data/lib/rubocop/cop/style/guard_clause.rb +41 -24
  457. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +27 -9
  458. data/lib/rubocop/cop/style/hash_conversion.rb +52 -16
  459. data/lib/rubocop/cop/style/hash_each_methods.rb +4 -4
  460. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  461. data/lib/rubocop/cop/style/hash_lookup_method.rb +128 -0
  462. data/lib/rubocop/cop/style/hash_slice.rb +16 -0
  463. data/lib/rubocop/cop/style/hash_syntax.rb +23 -6
  464. data/lib/rubocop/cop/style/hash_transform_keys.rb +19 -9
  465. data/lib/rubocop/cop/style/hash_transform_values.rb +19 -9
  466. data/lib/rubocop/cop/style/identical_conditional_branches.rb +39 -11
  467. data/lib/rubocop/cop/style/if_inside_else.rb +46 -21
  468. data/lib/rubocop/cop/style/if_unless_modifier.rb +90 -66
  469. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +19 -19
  470. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -2
  471. data/lib/rubocop/cop/style/if_with_semicolon.rb +61 -8
  472. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  473. data/lib/rubocop/cop/style/inline_comment.rb +5 -2
  474. data/lib/rubocop/cop/style/inverse_methods.rb +34 -8
  475. data/lib/rubocop/cop/style/invertible_unless_condition.rb +27 -7
  476. data/lib/rubocop/cop/style/ip_addresses.rb +3 -4
  477. data/lib/rubocop/cop/style/it_assignment.rb +69 -12
  478. data/lib/rubocop/cop/style/it_block_parameter.rb +150 -0
  479. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +4 -0
  480. data/lib/rubocop/cop/style/keyword_parameters_order.rb +23 -11
  481. data/lib/rubocop/cop/style/lambda.rb +30 -1
  482. data/lib/rubocop/cop/style/lambda_call.rb +31 -10
  483. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  484. data/lib/rubocop/cop/style/magic_comment_format.rb +4 -4
  485. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +11 -0
  486. data/lib/rubocop/cop/style/map_into_array.rb +6 -4
  487. data/lib/rubocop/cop/style/map_join.rb +123 -0
  488. data/lib/rubocop/cop/style/map_to_hash.rb +13 -5
  489. data/lib/rubocop/cop/style/map_to_set.rb +1 -3
  490. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +75 -24
  491. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
  492. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +58 -6
  493. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +36 -8
  494. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -1
  495. data/lib/rubocop/cop/style/method_def_parentheses.rb +36 -8
  496. data/lib/rubocop/cop/style/min_max_comparison.rb +17 -6
  497. data/lib/rubocop/cop/style/missing_else.rb +7 -1
  498. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +40 -7
  499. data/lib/rubocop/cop/style/mixin_usage.rb +1 -1
  500. data/lib/rubocop/cop/style/module_function.rb +4 -2
  501. data/lib/rubocop/cop/style/module_member_existence_check.rb +110 -0
  502. data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -1
  503. data/lib/rubocop/cop/style/multiline_if_modifier.rb +47 -5
  504. data/lib/rubocop/cop/style/multiline_if_then.rb +10 -4
  505. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
  506. data/lib/rubocop/cop/style/multiline_memoization.rb +7 -1
  507. data/lib/rubocop/cop/style/multiline_method_signature.rb +15 -22
  508. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
  509. data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
  510. data/lib/rubocop/cop/style/multiple_comparison.rb +33 -22
  511. data/lib/rubocop/cop/style/mutable_constant.rb +139 -13
  512. data/lib/rubocop/cop/style/negated_if_else_condition.rb +3 -3
  513. data/lib/rubocop/cop/style/negative_array_index.rb +228 -0
  514. data/lib/rubocop/cop/style/nested_modifier.rb +36 -12
  515. data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
  516. data/lib/rubocop/cop/style/next.rb +68 -10
  517. data/lib/rubocop/cop/style/nil_comparison.rb +53 -13
  518. data/lib/rubocop/cop/style/nil_lambda.rb +9 -1
  519. data/lib/rubocop/cop/style/non_nil_check.rb +21 -11
  520. data/lib/rubocop/cop/style/not.rb +12 -3
  521. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
  522. data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
  523. data/lib/rubocop/cop/style/numeric_predicate.rb +22 -6
  524. data/lib/rubocop/cop/style/object_then.rb +1 -0
  525. data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
  526. data/lib/rubocop/cop/style/one_line_conditional.rb +35 -15
  527. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  528. data/lib/rubocop/cop/style/operator_method_call.rb +10 -2
  529. data/lib/rubocop/cop/style/option_hash.rb +1 -1
  530. data/lib/rubocop/cop/style/optional_arguments.rb +1 -0
  531. data/lib/rubocop/cop/style/parallel_assignment.rb +58 -27
  532. data/lib/rubocop/cop/style/parentheses_around_condition.rb +6 -1
  533. data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
  534. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +18 -3
  535. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  536. data/lib/rubocop/cop/style/perl_backrefs.rb +5 -3
  537. data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
  538. data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
  539. data/lib/rubocop/cop/style/proc.rb +4 -2
  540. data/lib/rubocop/cop/style/raise_args.rb +9 -9
  541. data/lib/rubocop/cop/style/reduce_to_hash.rb +216 -0
  542. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  543. data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
  544. data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
  545. data/lib/rubocop/cop/style/redundant_assignment.rb +12 -2
  546. data/lib/rubocop/cop/style/redundant_begin.rb +58 -6
  547. data/lib/rubocop/cop/style/redundant_condition.rb +93 -18
  548. data/lib/rubocop/cop/style/redundant_constant_base.rb +42 -6
  549. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +26 -4
  550. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +17 -3
  551. data/lib/rubocop/cop/style/redundant_each.rb +4 -5
  552. data/lib/rubocop/cop/style/redundant_exception.rb +22 -4
  553. data/lib/rubocop/cop/style/redundant_fetch_block.rb +11 -11
  554. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +9 -0
  555. data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
  556. data/lib/rubocop/cop/style/redundant_format.rb +319 -0
  557. data/lib/rubocop/cop/style/redundant_freeze.rb +12 -3
  558. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +6 -1
  559. data/lib/rubocop/cop/style/redundant_interpolation.rb +12 -3
  560. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
  561. data/lib/rubocop/cop/style/redundant_line_continuation.rb +83 -119
  562. data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
  563. data/lib/rubocop/cop/style/redundant_parentheses.rb +176 -83
  564. data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
  565. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +15 -0
  566. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
  567. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +27 -7
  568. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +16 -0
  569. data/lib/rubocop/cop/style/redundant_return.rb +4 -3
  570. data/lib/rubocop/cop/style/redundant_self.rb +20 -7
  571. data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -3
  572. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
  573. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  574. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  575. data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -2
  576. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +133 -0
  577. data/lib/rubocop/cop/style/regexp_literal.rb +107 -29
  578. data/lib/rubocop/cop/style/require_order.rb +9 -0
  579. data/lib/rubocop/cop/style/rescue_modifier.rb +10 -12
  580. data/lib/rubocop/cop/style/return_nil.rb +19 -4
  581. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
  582. data/lib/rubocop/cop/style/reverse_find.rb +51 -0
  583. data/lib/rubocop/cop/style/safe_navigation.rb +76 -20
  584. data/lib/rubocop/cop/style/sample.rb +19 -13
  585. data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
  586. data/lib/rubocop/cop/style/select_by_range.rb +197 -0
  587. data/lib/rubocop/cop/style/select_by_regexp.rb +54 -22
  588. data/lib/rubocop/cop/style/self_assignment.rb +13 -16
  589. data/lib/rubocop/cop/style/semicolon.rb +56 -14
  590. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  591. data/lib/rubocop/cop/style/single_line_do_end_block.rb +22 -8
  592. data/lib/rubocop/cop/style/single_line_methods.rb +28 -11
  593. data/lib/rubocop/cop/style/sole_nested_conditional.rb +96 -104
  594. data/lib/rubocop/cop/style/special_global_vars.rb +7 -2
  595. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +32 -6
  596. data/lib/rubocop/cop/style/static_class.rb +21 -0
  597. data/lib/rubocop/cop/style/string_concatenation.rb +38 -16
  598. data/lib/rubocop/cop/style/string_hash_keys.rb +1 -0
  599. data/lib/rubocop/cop/style/struct_inheritance.rb +38 -2
  600. data/lib/rubocop/cop/style/super_arguments.rb +7 -6
  601. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  602. data/lib/rubocop/cop/style/symbol_proc.rb +34 -14
  603. data/lib/rubocop/cop/style/tally_method.rb +181 -0
  604. data/lib/rubocop/cop/style/ternary_parentheses.rb +34 -1
  605. data/lib/rubocop/cop/style/time_now.rb +41 -0
  606. data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -2
  607. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +52 -1
  608. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  609. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +2 -2
  610. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  611. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
  612. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +35 -32
  613. data/lib/rubocop/cop/style/trivial_accessors.rb +2 -2
  614. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  615. data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
  616. data/lib/rubocop/cop/style/while_until_do.rb +7 -0
  617. data/lib/rubocop/cop/style/while_until_modifier.rb +16 -1
  618. data/lib/rubocop/cop/style/word_array.rb +1 -0
  619. data/lib/rubocop/cop/style/yoda_condition.rb +26 -12
  620. data/lib/rubocop/cop/style/yoda_expression.rb +11 -2
  621. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -3
  622. data/lib/rubocop/cop/style.rb +311 -0
  623. data/lib/rubocop/cop/team.rb +172 -49
  624. data/lib/rubocop/cop/util.rb +7 -10
  625. data/lib/rubocop/cop/utils/format_string.rb +20 -5
  626. data/lib/rubocop/cop/variable_force/assignment.rb +8 -4
  627. data/lib/rubocop/cop/variable_force/branch.rb +30 -6
  628. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  629. data/lib/rubocop/cop/variable_force/variable.rb +42 -11
  630. data/lib/rubocop/cop/variable_force.rb +26 -9
  631. data/lib/rubocop/cops_documentation_generator.rb +49 -15
  632. data/lib/rubocop/directive_comment.rb +147 -5
  633. data/lib/rubocop/ext/regexp_node.rb +0 -1
  634. data/lib/rubocop/feature_loader.rb +0 -6
  635. data/lib/rubocop/file_patterns.rb +9 -1
  636. data/lib/rubocop/formatter/base_formatter.rb +22 -0
  637. data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
  638. data/lib/rubocop/formatter/disabled_config_formatter.rb +57 -14
  639. data/lib/rubocop/formatter/emacs_style_formatter.rb +3 -1
  640. data/lib/rubocop/formatter/formatter_set.rb +7 -2
  641. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  642. data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
  643. data/lib/rubocop/formatter/html_formatter.rb +3 -5
  644. data/lib/rubocop/formatter/json_formatter.rb +82 -7
  645. data/lib/rubocop/formatter/junit_formatter.rb +27 -10
  646. data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
  647. data/lib/rubocop/formatter/offense_count_formatter.rb +5 -4
  648. data/lib/rubocop/formatter/pacman_formatter.rb +5 -2
  649. data/lib/rubocop/formatter/sarif_formatter.rb +186 -0
  650. data/lib/rubocop/formatter/simple_text_formatter.rb +4 -5
  651. data/lib/rubocop/formatter/tap_formatter.rb +8 -3
  652. data/lib/rubocop/formatter/worst_offenders_formatter.rb +5 -4
  653. data/lib/rubocop/formatter.rb +23 -21
  654. data/lib/rubocop/lockfile.rb +18 -0
  655. data/lib/rubocop/lsp/diagnostic.rb +22 -41
  656. data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
  657. data/lib/rubocop/lsp/routes.rb +136 -33
  658. data/lib/rubocop/lsp/runtime.rb +66 -15
  659. data/lib/rubocop/lsp/server.rb +4 -2
  660. data/lib/rubocop/lsp/stdin_runner.rb +38 -19
  661. data/lib/rubocop/lsp.rb +5 -2
  662. data/lib/rubocop/magic_comment.rb +55 -0
  663. data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
  664. data/lib/rubocop/mcp/explain_tool.rb +68 -0
  665. data/lib/rubocop/mcp/scope.rb +65 -0
  666. data/lib/rubocop/mcp/server.rb +307 -0
  667. data/lib/rubocop/mcp/source_files.rb +35 -0
  668. data/lib/rubocop/offense_limit.rb +30 -0
  669. data/lib/rubocop/options.rb +166 -23
  670. data/lib/rubocop/path_util.rb +20 -5
  671. data/lib/rubocop/pending_cops_reporter.rb +51 -0
  672. data/lib/rubocop/plugin/configuration_integrator.rb +153 -0
  673. data/lib/rubocop/plugin/load_error.rb +26 -0
  674. data/lib/rubocop/plugin/loader.rb +100 -0
  675. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  676. data/lib/rubocop/plugin.rb +46 -0
  677. data/lib/rubocop/project_index_loader.rb +82 -0
  678. data/lib/rubocop/rake_task.rb +6 -4
  679. data/lib/rubocop/remote_config.rb +18 -13
  680. data/lib/rubocop/result_cache.rb +110 -65
  681. data/lib/rubocop/rspec/cop_helper.rb +21 -1
  682. data/lib/rubocop/rspec/expect_offense.rb +11 -7
  683. data/lib/rubocop/rspec/shared_contexts.rb +85 -3
  684. data/lib/rubocop/rspec/support.rb +4 -0
  685. data/lib/rubocop/runner.rb +368 -106
  686. data/lib/rubocop/server/cache.rb +67 -48
  687. data/lib/rubocop/server/cli.rb +2 -4
  688. data/lib/rubocop/server/client_command/base.rb +10 -0
  689. data/lib/rubocop/server/client_command/exec.rb +2 -1
  690. data/lib/rubocop/server/client_command/start.rb +11 -1
  691. data/lib/rubocop/server/core.rb +8 -0
  692. data/lib/rubocop/server.rb +14 -0
  693. data/lib/rubocop/target_finder.rb +25 -11
  694. data/lib/rubocop/target_ruby.rb +31 -14
  695. data/lib/rubocop/todo_audit.rb +111 -0
  696. data/lib/rubocop/unified_diff.rb +257 -0
  697. data/lib/rubocop/util.rb +69 -0
  698. data/lib/rubocop/version.rb +48 -10
  699. data/lib/rubocop.rb +35 -682
  700. data/lib/ruby_lsp/rubocop/addon.rb +28 -17
  701. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +99 -0
  702. metadata +129 -21
  703. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
  704. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  705. data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +0 -50
@@ -9,7 +9,7 @@ module RuboCop
9
9
  self.command_name = :lsp
10
10
 
11
11
  def run
12
- # Load on demand, `languge-server-protocol` is heavy to require.
12
+ # Load on demand, `language-server-protocol` is heavy to require.
13
13
  require_relative '../../lsp/server'
14
14
  RuboCop::LSP::Server.new(@config_store).start
15
15
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ class CLI
5
+ module Command
6
+ # Start Model Context Protocol of RuboCop.
7
+ # @api private
8
+ class MCP < Base
9
+ self.command_name = :mcp
10
+
11
+ def run
12
+ require_relative '../../mcp/server'
13
+
14
+ RuboCop::MCP::Server.new(@config_store).start
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -7,6 +7,8 @@ module RuboCop
7
7
  # for the current directory.
8
8
  # @api private
9
9
  class ShowCops < Base
10
+ include CopNames
11
+
10
12
  self.command_name = :show_cops
11
13
 
12
14
  ExactMatcher = Struct.new(:pattern) do
@@ -25,7 +27,7 @@ module RuboCop
25
27
  super
26
28
 
27
29
  # Load the configs so the require()s are done for custom cops
28
- @config = @config_store.for(Dir.pwd)
30
+ @config = @config_store.for(PathUtil.pwd)
29
31
 
30
32
  @cop_matchers = @options[:show_cops].map do |pattern|
31
33
  if pattern.include?('*')
@@ -38,6 +40,10 @@ module RuboCop
38
40
 
39
41
  def run
40
42
  print_available_cops
43
+ # Checked after printing, so a typo alongside good names still shows
44
+ # what was asked for. Wildcards are patterns, not names, so a pattern
45
+ # that matches nothing is not an error.
46
+ validate_cop_names!(@options[:show_cops].grep_v(/\*/))
41
47
  end
42
48
 
43
49
  private
@@ -46,7 +52,7 @@ module RuboCop
46
52
  registry = Cop::Registry.global
47
53
  show_all = @cop_matchers.empty?
48
54
 
49
- puts "# Available cops (#{registry.length}) + config for #{Dir.pwd}: " if show_all
55
+ puts "# Available cops (#{registry.length}) + config for #{PathUtil.pwd}: " if show_all
50
56
 
51
57
  registry.departments.sort!.each do |department|
52
58
  print_cops_of_department(registry, department, show_all)
@@ -7,16 +7,21 @@ module RuboCop
7
7
  # or documentation base url by default.
8
8
  # @api private
9
9
  class ShowDocsUrl < Base
10
+ include CopNames
11
+
10
12
  self.command_name = :show_docs_url
11
13
 
12
14
  def initialize(env)
13
15
  super
14
16
 
15
- @config = @config_store.for(Dir.pwd)
17
+ @config = @config_store.for(PathUtil.pwd)
16
18
  end
17
19
 
18
20
  def run
19
21
  print_documentation_url
22
+ # Checked after printing, so a typo alongside good names still gives
23
+ # you the urls you asked for.
24
+ validate_cop_names!(cops_array)
20
25
  end
21
26
 
22
27
  private
@@ -24,11 +29,8 @@ module RuboCop
24
29
  def print_documentation_url
25
30
  puts Cop::Documentation.default_base_url if cops_array.empty?
26
31
 
27
- cops_array.each do |cop_name|
28
- cop = registry_hash[cop_name]
29
- next if cop.empty?
30
-
31
- url = Cop::Documentation.url_for(cop.first, @config)
32
+ known_cop_classes(cops_array).each do |cop|
33
+ url = Cop::Documentation.url_for(cop, @config)
32
34
  puts url if url
33
35
  end
34
36
 
@@ -38,10 +40,6 @@ module RuboCop
38
40
  def cops_array
39
41
  @cops_array ||= @options[:show_docs_url]
40
42
  end
41
-
42
- def registry_hash
43
- @registry_hash ||= Cop::Registry.global.to_h
44
- end
45
43
  end
46
44
  end
47
45
  end
@@ -60,7 +60,7 @@ module RuboCop
60
60
  def print_opt_out_instruction
61
61
  puts
62
62
  puts 'You can opt out of this message by adding the following to your config ' \
63
- '(see https://docs.rubocop.org/rubocop/extensions.html#extension-suggestions ' \
63
+ '(see https://docs.rubocop.org/rubocop/plugins.html#plugin-suggestions ' \
64
64
  'for more options):'
65
65
  puts ' AllCops:'
66
66
  puts ' SuggestExtensions: false'
@@ -97,7 +97,13 @@ module RuboCop
97
97
  end
98
98
 
99
99
  def loaded_extensions
100
- @config_store.for_pwd.loaded_features.to_a
100
+ rubocop_config = @config_store.for_pwd
101
+
102
+ plugin_names = rubocop_config.loaded_plugins.map do |plugin|
103
+ plugin.about.name
104
+ end
105
+
106
+ plugin_names + rubocop_config.loaded_features.to_a
101
107
  end
102
108
 
103
109
  def installed_and_not_loaded_extensions
data/lib/rubocop/cli.rb CHANGED
@@ -12,8 +12,9 @@ module RuboCop
12
12
  STATUS_INTERRUPTED = Signal.list['INT'] + 128
13
13
  DEFAULT_PARALLEL_OPTIONS = %i[
14
14
  color config debug display_style_guide display_time display_only_fail_level_offenses
15
- display_only_failed editor_mode except extra_details fail_level fix_layout format
16
- ignore_disable_comments lint only only_guide_cops require safe
15
+ display_only_failed editor_mode except extra_details fail_level fix_layout format formatters
16
+ ignore_disable_comments lint max_offenses_per_cop only only_guide_cops out preview require
17
+ safe
17
18
  autocorrect safe_autocorrect autocorrect_all
18
19
  ].freeze
19
20
 
@@ -35,8 +36,10 @@ module RuboCop
35
36
  # @param args [Array<String>] command line arguments
36
37
  # @return [Integer] UNIX exit code
37
38
  #
38
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
39
+ # rubocop:disable-next Metrics/MethodLength, Metrics/AbcSize
39
40
  def run(args = ARGV)
41
+ time_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
42
+
40
43
  @options, paths = Options.new.parse(args)
41
44
  @env = Environment.new(@options, @config_store, paths)
42
45
 
@@ -48,11 +51,12 @@ module RuboCop
48
51
  validate_options_vs_config
49
52
  parallel_by_default!
50
53
  apply_default_formatter
54
+ report_pending_cops
51
55
  execute_runners
52
56
  end
53
57
  end
54
58
  rescue ConfigNotFoundError, IncorrectCopNameError, OptionArgumentError => e
55
- warn e.message
59
+ warn Rainbow(e.message).red
56
60
  STATUS_ERROR
57
61
  rescue RuboCop::Error => e
58
62
  warn Rainbow("Error: #{e.message}").red
@@ -63,7 +67,7 @@ module RuboCop
63
67
  STATUS_INTERRUPTED
64
68
  rescue Finished
65
69
  STATUS_SUCCESS
66
- rescue OptionParser::InvalidOption => e
70
+ rescue OptionParser::ParseError => e
67
71
  warn e.message
68
72
  warn 'For usage information, use --help'
69
73
  STATUS_ERROR
@@ -71,12 +75,16 @@ module RuboCop
71
75
  warn e.message
72
76
  warn e.backtrace
73
77
  STATUS_ERROR
78
+ ensure
79
+ elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - time_start
80
+ if @options[:debug] || @options[:display_time]
81
+ puts "Finished in #{elapsed_time.round(5)} seconds"
82
+ end
74
83
  end
75
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
76
84
 
77
85
  private
78
86
 
79
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
87
+ # rubocop:disable-next Metrics/MethodLength, Metrics/AbcSize
80
88
  def profile_if_needed
81
89
  return yield unless @options[:profile]
82
90
 
@@ -108,7 +116,6 @@ module RuboCop
108
116
  end
109
117
  status
110
118
  end
111
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
112
119
 
113
120
  def require_gem(name)
114
121
  require name
@@ -155,10 +162,14 @@ module RuboCop
155
162
 
156
163
  def act_on_options
157
164
  set_options_to_config_loader
165
+ set_options_to_pending_cops_reporter
158
166
  handle_editor_mode
159
167
 
160
- @config_store.options_config = @options[:config] if @options[:config]
161
- @config_store.force_default_config! if @options[:force_default_config]
168
+ @config_store.apply_options!(@options)
169
+ # Set cache root after apply_options! to ensure force_default_config is applied first.
170
+ early_cache_root = ConfigLoader.cache_root(@options[:cache_root])
171
+ ConfigLoader.cache_root = ResultCache.cache_root(@config_store, @options[:cache_root])
172
+ warn_if_cache_root_changed(early_cache_root, ConfigLoader.cache_root)
162
173
 
163
174
  handle_exiting_options
164
175
 
@@ -173,27 +184,38 @@ module RuboCop
173
184
 
174
185
  def set_options_to_config_loader
175
186
  ConfigLoader.debug = @options[:debug]
176
- ConfigLoader.disable_pending_cops = @options[:disable_pending_cops]
177
- ConfigLoader.enable_pending_cops = @options[:enable_pending_cops]
178
187
  ConfigLoader.ignore_parent_exclusion = @options[:ignore_parent_exclusion]
179
188
  ConfigLoader.ignore_unrecognized_cops = @options[:ignore_unrecognized_cops]
189
+ set_cop_selection_options_to_config_loader
190
+ end
191
+
192
+ # Options that decide which cops run, as opposed to how configuration is loaded.
193
+ def set_cop_selection_options_to_config_loader
194
+ ConfigLoader.disable_pending_cops = @options[:disable_pending_cops]
195
+ ConfigLoader.enable_pending_cops = @options[:enable_pending_cops]
196
+ ConfigLoader.enabled_by_default = @options[:enable_all_cops]
197
+ ConfigLoader.disabled_by_default = @options[:disable_all_cops]
198
+ ConfigLoader.preview = @options[:preview]
199
+ end
200
+
201
+ def set_options_to_pending_cops_reporter
202
+ PendingCopsReporter.disable_pending_cops = @options[:disable_pending_cops]
203
+ PendingCopsReporter.enable_pending_cops = @options[:enable_pending_cops]
180
204
  end
181
205
 
182
206
  def handle_editor_mode
183
207
  RuboCop::LSP.enable if @options[:editor_mode]
184
208
  end
185
209
 
186
- # rubocop:disable Metrics/CyclomaticComplexity
187
210
  def handle_exiting_options
188
211
  return unless Options::EXITING_OPTIONS.any? { |o| @options.key? o }
189
212
 
190
213
  run_command(:version) if @options[:version] || @options[:verbose_version]
191
- run_command(:show_cops) if @options[:show_cops]
192
- run_command(:show_docs_url) if @options[:show_docs_url]
193
- run_command(:lsp) if @options[:lsp]
214
+ %i[show_cops list_enabled_cops_for show_docs_url explain lsp mcp].each do |name|
215
+ run_command(name) if @options[name]
216
+ end
194
217
  raise Finished
195
218
  end
196
- # rubocop:enable Metrics/CyclomaticComplexity
197
219
 
198
220
  def apply_default_formatter
199
221
  # This must be done after the options have already been processed,
@@ -208,5 +230,25 @@ module RuboCop
208
230
  [[formatter, @options[:output_path]]]
209
231
  end
210
232
  end
233
+
234
+ def report_pending_cops
235
+ PendingCopsReporter.warn_if_needed(@config_store.for_pwd)
236
+ end
237
+
238
+ def warn_if_cache_root_changed(early, desired)
239
+ return if early == desired
240
+ # Normalize paths to avoid false positives from symlink resolution differences
241
+ if File.exist?(early) && File.exist?(desired) &&
242
+ File.realpath(early) == File.realpath(desired)
243
+ return
244
+ end
245
+
246
+ warn Rainbow(
247
+ "Warning: Remote configuration cache files were stored in `#{early}` " \
248
+ "because a desired cache root (`#{desired}`) was not set at the top level. " \
249
+ 'Consider setting `AllCops: CacheRootDirectory` in your toplevel configuration file, ' \
250
+ 'using the `RUBOCOP_CACHE_ROOT` environment variable, or using CLI options.'
251
+ ).yellow
252
+ end
211
253
  end
212
254
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ class CommentConfig
5
+ # A disabled line range that remembers the directive comment that opened
6
+ # it. Value-equal to a plain `Range`, so consumers comparing or hashing
7
+ # ranges are unaffected.
8
+ # @api private
9
+ class DirectiveRange < Range
10
+ attr_reader :directive
11
+
12
+ def initialize(first_line, last_line, directive)
13
+ super(first_line, last_line)
14
+ @directive = directive
15
+ end
16
+ end
17
+
18
+ # The per-cop state accumulated while analyzing directives: the disabled
19
+ # ranges so far, plus the line and directive of the currently open
20
+ # disable, if any.
21
+ # @api private
22
+ CopAnalysis = Struct.new(:line_ranges, :start_line_number, :start_directive) do
23
+ # The open range (if any) closed at the given line, appended to the
24
+ # accumulated ranges, each remembering the directive that opened it.
25
+ # Closing above the opening line (e.g. a `pop` directly below a
26
+ # statement whose disable a `next +Cop` suspended) yields no range.
27
+ def close(line)
28
+ return line_ranges if !start_line_number || line < start_line_number
29
+
30
+ line_ranges + [DirectiveRange.new(start_line_number, line, start_directive)]
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ class CommentConfig
5
+ # Handling of next-statement directives (`disable-next`, `todo-next` and
6
+ # `next`): computing the statement scope they apply to and tracking
7
+ # directives that attached to nothing.
8
+ # The scope is the whole statement starting on the next line bearing
9
+ # code. Comment-only lines between the directive and the code chain (so
10
+ # several directives can stack), while a blank line breaks the attachment.
11
+ # @api private
12
+ module DisableNext
13
+ # Next-statement directives that affect nothing: nothing follows
14
+ # them, or they sit at the end of a code line.
15
+ def detached_next_directives
16
+ cop_disabled_line_ranges # ensure the analysis that collects them ran
17
+ @detached_next_directives
18
+ end
19
+
20
+ # The line range of the statement a `disable-next` directive on the
21
+ # given line scopes to (or would scope to), or `nil` when no statement
22
+ # is attached. A directive is only honored on a comment-only line.
23
+ # Stacked directives share the target, so the computation is memoized.
24
+ # @api private
25
+ def statement_scope_after(line)
26
+ return nil unless comment_only_line?(line)
27
+
28
+ code_line = attached_code_line(line)
29
+ return nil unless code_line
30
+
31
+ (@statement_bounds ||= {})[code_line] ||= statement_bounds_at(code_line)
32
+ end
33
+
34
+ private
35
+
36
+ def apply_disable_next(analyses, directive)
37
+ bounds = statement_scope_after(directive.line_number)
38
+ return @detached_next_directives << directive unless bounds
39
+
40
+ range = DirectiveRange.new(bounds.begin, bounds.end, directive)
41
+ directive.cop_names.each do |cop_name|
42
+ add_next_range(analyses, qualified_cop_name(cop_name), range)
43
+ end
44
+ end
45
+
46
+ def add_next_range(analyses, cop_name, range)
47
+ analysis = analyses[cop_name]
48
+ analyses[cop_name] = CopAnalysis.new(analysis.line_ranges + [range],
49
+ analysis.start_line_number, analysis.start_directive)
50
+ end
51
+
52
+ # Applies a `next` directive: `-` cops are disabled for the attached
53
+ # statement (exactly like `disable-next`), `+` cops have any open
54
+ # disable suspended for it. The `resolved_cops` come pre-expanded and
55
+ # qualified, mirroring `push`.
56
+ def apply_next_directive(analyses, resolved_cops, directive)
57
+ bounds = statement_scope_after(directive.line_number)
58
+ return @detached_next_directives << directive unless bounds
59
+
60
+ range = DirectiveRange.new(bounds.begin, bounds.end, directive)
61
+ resolved_cops.each do |op, cops|
62
+ cops.each do |cop|
63
+ if op == '-'
64
+ add_next_range(analyses, cop, range)
65
+ else
66
+ suspend_disable(analyses, cop, bounds)
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ # Applies an `enable-next` directive: every listed cop (departments
73
+ # and `all` included) has any open disable suspended for the attached
74
+ # statement.
75
+ def apply_enable_next(analyses, directive)
76
+ bounds = statement_scope_after(directive.line_number)
77
+ return @detached_next_directives << directive unless bounds
78
+
79
+ directive.cop_names.each do |cop_name|
80
+ suspend_disable(analyses, qualified_cop_name(cop_name), bounds)
81
+ end
82
+ end
83
+
84
+ # Punches a statement-sized hole into the currently open disable of the
85
+ # cop (whether opened by a directive or injected for a config-disabled
86
+ # cop): the open range closes just above the statement and reopens
87
+ # right below it, still attributed to its opening directive. Aligned
88
+ # with `push`, a `+` for a cop that is not disabled is a no-op.
89
+ def suspend_disable(analyses, cop, bounds)
90
+ analysis = analyses[cop]
91
+ return unless analysis.start_line_number
92
+
93
+ analyses[cop] = CopAnalysis.new(analysis.close(bounds.begin - 1),
94
+ bounds.end + 1, analysis.start_directive)
95
+ end
96
+
97
+ def attached_code_line(directive_line)
98
+ ((directive_line + 1)..processed_source.lines.size).each do |line|
99
+ return line unless comment_only_line?(line)
100
+ return nil if processed_source[line - 1].blank?
101
+ end
102
+
103
+ nil
104
+ end
105
+
106
+ def statement_bounds_at(line)
107
+ statement = statement_starting_at(line)
108
+ # A code line where no statement starts (e.g. a lone `end`) scopes
109
+ # the directive to that line alone.
110
+ return (line..line) unless statement
111
+
112
+ (line..statement_end_line(statement))
113
+ end
114
+
115
+ def statement_start_line?(node, line)
116
+ # Synthetic nodes (e.g. parentheses-less argument lists) have no
117
+ # source range. `begin` nodes are sequences of statements, not
118
+ # statements themselves - taking one would scope the directive to
119
+ # everything up to the last statement of the sequence.
120
+ node.source_range && node.first_line == line && !node.begin_type?
121
+ end
122
+
123
+ def statement_starting_at(line)
124
+ ast = processed_source.ast
125
+ return nil unless ast
126
+
127
+ ast.each_node.select { |node| statement_start_line?(node, line) }.max_by(&:last_line)
128
+ end
129
+
130
+ def statement_end_line(statement)
131
+ statement.each_node.filter_map do |node|
132
+ next unless node.source_range
133
+
134
+ heredoc?(node) ? node.loc.heredoc_end.line : node.last_line
135
+ end.max
136
+ end
137
+
138
+ def heredoc?(node)
139
+ node.respond_to?(:heredoc?) && node.heredoc?
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ class CommentConfig
5
+ # Handling of `push`/`pop` directives and their signed cop arguments:
6
+ # saving and restoring the per-cop analysis state, and resolving the
7
+ # `+`/`-` argument lists (shared with the `next` directive).
8
+ # @api private
9
+ module PushPop
10
+ private
11
+
12
+ def resolve_push_cops(directive)
13
+ directive.push_args.transform_values do |names|
14
+ names.flat_map { |name| expand_cop_name(name) }
15
+ end
16
+ end
17
+
18
+ def expand_cop_name(name)
19
+ registry = Cop::Registry.global
20
+ cops = registry.department?(name) ? registry.names_for_department(name) : [name]
21
+ cops.map { |c| qualified_cop_name(c) }
22
+ end
23
+
24
+ def apply_push(analyses, resolved_cops, directive)
25
+ resolved_cops.each do |op, cops|
26
+ cops.each { |cop| apply_cop_op(analyses, op, cop, directive) }
27
+ end
28
+ end
29
+
30
+ def apply_cop_op(analyses, operation, cop, directive)
31
+ analysis = analyses[cop]
32
+ line = directive.line_number
33
+ if operation == '-' && !analysis.start_line_number
34
+ analyses[cop] = CopAnalysis.new(analysis.line_ranges, line, directive)
35
+ elsif operation == '+' && analysis.start_line_number
36
+ analyses[cop] = CopAnalysis.new(analysis.close(line), nil)
37
+ end
38
+ end
39
+
40
+ def pop_state(analyses, line)
41
+ restore_point = @stack.pop
42
+ (restore_point.keys | analyses.keys).each do |cop|
43
+ analyses[cop] = popped_analysis(analyses[cop], restore_point[cop], line)
44
+ end
45
+ end
46
+
47
+ def popped_analysis(current, restored, line)
48
+ ranges = current.close(line - 1)
49
+ return CopAnalysis.new(ranges, nil) unless restored&.start_line_number
50
+
51
+ CopAnalysis.new(ranges, line, restored.start_directive)
52
+ end
53
+ end
54
+ end
55
+ end