rubocop 1.71.1 → 1.92.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (712) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +23 -19
  4. data/config/default.yml +886 -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 +10 -2
  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 +37 -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 +31 -4
  54. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +35 -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 +9 -3
  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 +191 -41
  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 +27 -17
  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 +21 -8
  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 +22 -5
  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 +23 -15
  120. data/lib/rubocop/cop/layout/extra_spacing.rb +109 -3
  121. data/lib/rubocop/cop/layout/first_argument_indentation.rb +82 -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 +41 -0
  124. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +36 -23
  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 +9 -5
  131. data/lib/rubocop/cop/layout/heredoc_indentation.rb +48 -3
  132. data/lib/rubocop/cop/layout/indentation_consistency.rb +22 -5
  133. data/lib/rubocop/cop/layout/indentation_style.rb +5 -2
  134. data/lib/rubocop/cop/layout/indentation_width.rb +159 -12
  135. data/lib/rubocop/cop/layout/leading_comment_space.rb +40 -1
  136. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +10 -4
  137. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
  138. data/lib/rubocop/cop/layout/line_length.rb +300 -31
  139. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +69 -57
  140. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +8 -2
  141. data/lib/rubocop/cop/layout/multiline_block_layout.rb +11 -1
  142. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +65 -56
  143. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +7 -1
  144. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +270 -40
  145. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
  146. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  147. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +9 -5
  148. data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
  149. data/lib/rubocop/cop/layout/redundant_line_break.rb +111 -7
  150. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +29 -9
  151. data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
  152. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  153. data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
  154. data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
  155. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +10 -4
  156. data/lib/rubocop/cop/layout/space_around_keyword.rb +20 -3
  157. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  158. data/lib/rubocop/cop/layout/space_around_operators.rb +30 -4
  159. data/lib/rubocop/cop/layout/space_before_block_braces.rb +5 -1
  160. data/lib/rubocop/cop/layout/space_before_brackets.rb +6 -39
  161. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
  162. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +55 -36
  163. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +32 -8
  164. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
  165. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +2 -12
  166. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  167. data/lib/rubocop/cop/layout.rb +114 -0
  168. data/lib/rubocop/cop/lazy_loader.rb +41 -0
  169. data/lib/rubocop/cop/lint/ambiguous_assignment.rb +9 -17
  170. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +72 -1
  171. data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
  172. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +3 -11
  173. data/lib/rubocop/cop/lint/ambiguous_range.rb +6 -2
  174. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +6 -1
  175. data/lib/rubocop/cop/lint/argument_mismatch.rb +99 -0
  176. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
  177. data/lib/rubocop/cop/lint/assignment_in_condition.rb +15 -1
  178. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  179. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -8
  180. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +4 -3
  181. data/lib/rubocop/cop/lint/constant_reassignment.rb +94 -15
  182. data/lib/rubocop/cop/lint/constant_resolution.rb +31 -6
  183. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +240 -0
  184. data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
  185. data/lib/rubocop/cop/lint/debugger.rb +13 -4
  186. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  187. data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
  188. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +5 -2
  189. data/lib/rubocop/cop/lint/deprecated_reference.rb +194 -0
  190. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  191. data/lib/rubocop/cop/lint/duplicate_methods.rb +506 -41
  192. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
  193. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  194. data/lib/rubocop/cop/lint/empty_block.rb +4 -4
  195. data/lib/rubocop/cop/lint/empty_conditional_body.rb +22 -65
  196. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  197. data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
  198. data/lib/rubocop/cop/lint/empty_interpolation.rb +14 -1
  199. data/lib/rubocop/cop/lint/empty_when.rb +8 -1
  200. data/lib/rubocop/cop/lint/ensure_return.rb +19 -1
  201. data/lib/rubocop/cop/lint/erb_new_arguments.rb +4 -8
  202. data/lib/rubocop/cop/lint/float_comparison.rb +33 -10
  203. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  204. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +4 -0
  205. data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
  206. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -2
  207. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -1
  208. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -2
  209. data/lib/rubocop/cop/lint/inherit_exception.rb +53 -7
  210. data/lib/rubocop/cop/lint/interpolation_check.rb +25 -6
  211. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  212. data/lib/rubocop/cop/lint/literal_as_condition.rb +152 -11
  213. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
  214. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +75 -37
  215. data/lib/rubocop/cop/lint/loop.rb +24 -2
  216. data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +245 -0
  217. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +60 -23
  218. data/lib/rubocop/cop/lint/missing_super.rb +31 -1
  219. data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -2
  220. data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
  221. data/lib/rubocop/cop/lint/name_typo.rb +270 -0
  222. data/lib/rubocop/cop/lint/nested_method_definition.rb +2 -2
  223. data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
  224. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +20 -0
  225. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +4 -2
  226. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +4 -4
  227. data/lib/rubocop/cop/lint/number_conversion.rb +22 -11
  228. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  229. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +11 -0
  230. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  231. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +7 -7
  232. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +15 -4
  233. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +20 -14
  234. data/lib/rubocop/cop/lint/raise_exception.rb +30 -11
  235. data/lib/rubocop/cop/lint/rand_one.rb +1 -1
  236. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +160 -39
  237. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +53 -19
  238. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +28 -6
  239. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  240. data/lib/rubocop/cop/lint/redundant_require_statement.rb +5 -25
  241. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +134 -12
  242. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +13 -4
  243. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +267 -0
  244. data/lib/rubocop/cop/lint/redundant_with_index.rb +5 -3
  245. data/lib/rubocop/cop/lint/redundant_with_object.rb +8 -0
  246. data/lib/rubocop/cop/lint/refinement_import_methods.rb +8 -1
  247. data/lib/rubocop/cop/lint/regexp_as_condition.rb +9 -1
  248. data/lib/rubocop/cop/lint/require_parentheses.rb +13 -4
  249. data/lib/rubocop/cop/lint/require_range_parentheses.rb +3 -2
  250. data/lib/rubocop/cop/lint/require_relative_self_path.rb +7 -5
  251. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  252. data/lib/rubocop/cop/lint/rescue_type.rb +2 -2
  253. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  254. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +28 -4
  255. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +56 -6
  256. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
  257. data/lib/rubocop/cop/lint/script_permission.rb +5 -1
  258. data/lib/rubocop/cop/lint/self_assignment.rb +63 -6
  259. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -1
  260. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  261. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  262. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +27 -1
  263. data/lib/rubocop/cop/lint/shared_mutable_default.rb +14 -1
  264. data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
  265. data/lib/rubocop/cop/lint/super_argument_mismatch.rb +179 -0
  266. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  267. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +122 -0
  268. data/lib/rubocop/cop/lint/symbol_conversion.rb +22 -4
  269. data/lib/rubocop/cop/lint/syntax.rb +25 -1
  270. data/lib/rubocop/cop/lint/to_enum_arguments.rb +73 -5
  271. data/lib/rubocop/cop/lint/to_json.rb +20 -17
  272. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  273. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +5 -1
  274. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +54 -11
  275. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +2 -0
  276. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -1
  277. data/lib/rubocop/cop/lint/unreachable_code.rb +16 -9
  278. data/lib/rubocop/cop/lint/unreachable_loop.rb +5 -5
  279. data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
  280. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  281. data/lib/rubocop/cop/lint/unused_private_method.rb +234 -0
  282. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
  283. data/lib/rubocop/cop/lint/useless_access_modifier.rb +31 -6
  284. data/lib/rubocop/cop/lint/useless_assignment.rb +63 -27
  285. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +107 -0
  286. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +92 -0
  287. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  288. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +11 -10
  289. data/lib/rubocop/cop/lint/useless_or.rb +111 -0
  290. data/lib/rubocop/cop/lint/useless_rescue.rb +2 -3
  291. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +13 -7
  292. data/lib/rubocop/cop/lint/useless_setter_call.rb +11 -5
  293. data/lib/rubocop/cop/lint/useless_times.rb +22 -1
  294. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +201 -0
  295. data/lib/rubocop/cop/lint/void.rb +68 -22
  296. data/lib/rubocop/cop/lint.rb +179 -0
  297. data/lib/rubocop/cop/message_annotator.rb +7 -3
  298. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  299. data/lib/rubocop/cop/metrics/block_length.rb +2 -1
  300. data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
  301. data/lib/rubocop/cop/metrics/class_length.rb +4 -2
  302. data/lib/rubocop/cop/metrics/collection_literal_length.rb +1 -1
  303. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
  304. data/lib/rubocop/cop/metrics/method_length.rb +3 -2
  305. data/lib/rubocop/cop/metrics/module_length.rb +4 -2
  306. data/lib/rubocop/cop/metrics/perceived_complexity.rb +37 -7
  307. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  308. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
  309. data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
  310. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  311. data/lib/rubocop/cop/metrics.rb +31 -0
  312. data/lib/rubocop/cop/migration/department_name.rb +11 -5
  313. data/lib/rubocop/cop/migration.rb +13 -0
  314. data/lib/rubocop/cop/mixin/alignment.rb +7 -3
  315. data/lib/rubocop/cop/mixin/allowed_methods.rb +5 -5
  316. data/lib/rubocop/cop/mixin/allowed_pattern.rb +9 -5
  317. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  318. data/lib/rubocop/cop/mixin/check_line_breakable.rb +50 -28
  319. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +13 -9
  320. data/lib/rubocop/cop/mixin/code_length.rb +10 -2
  321. data/lib/rubocop/cop/mixin/comments_help.rb +2 -3
  322. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -2
  323. data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
  324. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  325. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +13 -2
  326. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
  327. data/lib/rubocop/cop/mixin/endless_method_body_help.rb +105 -0
  328. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +13 -5
  329. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  330. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +20 -0
  331. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -2
  332. data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
  333. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +68 -21
  334. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +52 -25
  335. data/lib/rubocop/cop/mixin/hash_subset.rb +28 -6
  336. data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
  337. data/lib/rubocop/cop/mixin/hash_transform_method.rb +32 -78
  338. data/lib/rubocop/cop/mixin/indexed_method_arity.rb +94 -0
  339. data/lib/rubocop/cop/mixin/line_length_help.rb +52 -11
  340. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  341. data/lib/rubocop/cop/mixin/min_branches_count.rb +3 -1
  342. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
  343. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -1
  344. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +10 -1
  345. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +2 -2
  346. data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
  347. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  348. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +79 -8
  349. data/lib/rubocop/cop/mixin/project_index_help.rb +203 -0
  350. data/lib/rubocop/cop/mixin/range_help.rb +16 -5
  351. data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +181 -0
  352. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  353. data/lib/rubocop/cop/mixin/statement_modifier.rb +69 -12
  354. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  355. data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
  356. data/lib/rubocop/cop/mixin/trailing_comma.rb +23 -6
  357. data/lib/rubocop/cop/mixin/visibility_help.rb +2 -1
  358. data/lib/rubocop/cop/mixin.rb +93 -0
  359. data/lib/rubocop/cop/naming/accessor_method_name.rb +8 -0
  360. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +17 -1
  361. data/lib/rubocop/cop/naming/block_forwarding.rb +7 -4
  362. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  363. data/lib/rubocop/cop/naming/file_name.rb +6 -5
  364. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +9 -2
  365. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
  366. data/lib/rubocop/cop/naming/inclusive_language.rb +8 -2
  367. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +13 -6
  368. data/lib/rubocop/cop/naming/method_name.rb +190 -15
  369. data/lib/rubocop/cop/naming/predicate_method.rb +330 -0
  370. data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +65 -8
  371. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +12 -7
  372. data/lib/rubocop/cop/naming/variable_name.rb +51 -6
  373. data/lib/rubocop/cop/naming/variable_number.rb +3 -1
  374. data/lib/rubocop/cop/naming.rb +31 -0
  375. data/lib/rubocop/cop/offense.rb +108 -9
  376. data/lib/rubocop/cop/registry.rb +234 -65
  377. data/lib/rubocop/cop/security/eval.rb +17 -3
  378. data/lib/rubocop/cop/security/io_methods.rb +2 -2
  379. data/lib/rubocop/cop/security/json_load.rb +45 -11
  380. data/lib/rubocop/cop/security/marshal_load.rb +1 -1
  381. data/lib/rubocop/cop/security/open.rb +1 -0
  382. data/lib/rubocop/cop/security.rb +19 -0
  383. data/lib/rubocop/cop/severity.rb +12 -0
  384. data/lib/rubocop/cop/style/access_modifier_declarations.rb +83 -14
  385. data/lib/rubocop/cop/style/accessor_grouping.rb +47 -10
  386. data/lib/rubocop/cop/style/alias.rb +33 -8
  387. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
  388. data/lib/rubocop/cop/style/and_or.rb +8 -3
  389. data/lib/rubocop/cop/style/arguments_forwarding.rb +80 -39
  390. data/lib/rubocop/cop/style/array_first_last.rb +13 -3
  391. data/lib/rubocop/cop/style/array_intersect.rb +136 -38
  392. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +50 -0
  393. data/lib/rubocop/cop/style/array_join.rb +4 -2
  394. data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
  395. data/lib/rubocop/cop/style/attr.rb +8 -6
  396. data/lib/rubocop/cop/style/bare_percent_literals.rb +4 -3
  397. data/lib/rubocop/cop/style/begin_block.rb +3 -1
  398. data/lib/rubocop/cop/style/bitwise_predicate.rb +13 -5
  399. data/lib/rubocop/cop/style/block_delimiters.rb +77 -40
  400. data/lib/rubocop/cop/style/case_equality.rb +29 -15
  401. data/lib/rubocop/cop/style/case_like_if.rb +12 -11
  402. data/lib/rubocop/cop/style/character_literal.rb +2 -2
  403. data/lib/rubocop/cop/style/class_and_module_children.rb +181 -27
  404. data/lib/rubocop/cop/style/class_equality_comparison.rb +22 -14
  405. data/lib/rubocop/cop/style/class_methods_definitions.rb +26 -5
  406. data/lib/rubocop/cop/style/collection_compact.rb +37 -17
  407. data/lib/rubocop/cop/style/collection_methods.rb +1 -0
  408. data/lib/rubocop/cop/style/collection_querying.rb +200 -0
  409. data/lib/rubocop/cop/style/colon_method_call.rb +16 -7
  410. data/lib/rubocop/cop/style/combinable_loops.rb +92 -9
  411. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  412. data/lib/rubocop/cop/style/commented_keyword.rb +12 -5
  413. data/lib/rubocop/cop/style/comparable_between.rb +78 -0
  414. data/lib/rubocop/cop/style/comparable_clamp.rb +12 -1
  415. data/lib/rubocop/cop/style/concat_array_literals.rb +65 -9
  416. data/lib/rubocop/cop/style/conditional_assignment.rb +58 -24
  417. data/lib/rubocop/cop/style/constant_visibility.rb +23 -12
  418. data/lib/rubocop/cop/style/copyright.rb +27 -12
  419. data/lib/rubocop/cop/style/data_inheritance.rb +25 -0
  420. data/lib/rubocop/cop/style/date_time.rb +4 -4
  421. data/lib/rubocop/cop/style/def_with_parentheses.rb +22 -5
  422. data/lib/rubocop/cop/style/dig_chain.rb +6 -1
  423. data/lib/rubocop/cop/style/dir_empty.rb +4 -0
  424. data/lib/rubocop/cop/style/directive_scope.rb +304 -0
  425. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +184 -20
  426. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
  427. data/lib/rubocop/cop/style/documentation.rb +53 -6
  428. data/lib/rubocop/cop/style/documentation_method.rb +8 -12
  429. data/lib/rubocop/cop/style/double_negation.rb +14 -3
  430. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  431. data/lib/rubocop/cop/style/each_with_object.rb +4 -3
  432. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  433. data/lib/rubocop/cop/style/empty_case_condition.rb +13 -4
  434. data/lib/rubocop/cop/style/empty_class_definition.rb +126 -0
  435. data/lib/rubocop/cop/style/empty_heredoc.rb +4 -0
  436. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  437. data/lib/rubocop/cop/style/empty_literal.rb +12 -3
  438. data/lib/rubocop/cop/style/empty_method.rb +15 -9
  439. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +152 -0
  440. data/lib/rubocop/cop/style/encoding.rb +7 -1
  441. data/lib/rubocop/cop/style/end_block.rb +3 -1
  442. data/lib/rubocop/cop/style/endless_method.rb +256 -19
  443. data/lib/rubocop/cop/style/env_home.rb +4 -0
  444. data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
  445. data/lib/rubocop/cop/style/even_odd.rb +11 -1
  446. data/lib/rubocop/cop/style/exact_regexp_match.rb +52 -8
  447. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  448. data/lib/rubocop/cop/style/explicit_block_argument.rb +62 -9
  449. data/lib/rubocop/cop/style/exponential_notation.rb +5 -4
  450. data/lib/rubocop/cop/style/fetch_env_var.rb +33 -7
  451. data/lib/rubocop/cop/style/file_null.rb +6 -4
  452. data/lib/rubocop/cop/style/file_open.rb +84 -0
  453. data/lib/rubocop/cop/style/file_write.rb +21 -16
  454. data/lib/rubocop/cop/style/float_division.rb +43 -15
  455. data/lib/rubocop/cop/style/for.rb +61 -1
  456. data/lib/rubocop/cop/style/format_string.rb +44 -9
  457. data/lib/rubocop/cop/style/format_string_token.rb +86 -16
  458. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +5 -3
  459. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  460. data/lib/rubocop/cop/style/global_vars.rb +5 -2
  461. data/lib/rubocop/cop/style/guard_clause.rb +58 -40
  462. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +31 -9
  463. data/lib/rubocop/cop/style/hash_conversion.rb +52 -16
  464. data/lib/rubocop/cop/style/hash_each_methods.rb +4 -4
  465. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  466. data/lib/rubocop/cop/style/hash_lookup_method.rb +128 -0
  467. data/lib/rubocop/cop/style/hash_slice.rb +16 -0
  468. data/lib/rubocop/cop/style/hash_syntax.rb +23 -6
  469. data/lib/rubocop/cop/style/hash_transform_keys.rb +19 -9
  470. data/lib/rubocop/cop/style/hash_transform_values.rb +19 -9
  471. data/lib/rubocop/cop/style/identical_conditional_branches.rb +39 -11
  472. data/lib/rubocop/cop/style/if_inside_else.rb +46 -21
  473. data/lib/rubocop/cop/style/if_unless_modifier.rb +101 -70
  474. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +19 -19
  475. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -2
  476. data/lib/rubocop/cop/style/if_with_semicolon.rb +61 -8
  477. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  478. data/lib/rubocop/cop/style/inline_comment.rb +5 -2
  479. data/lib/rubocop/cop/style/inverse_methods.rb +34 -8
  480. data/lib/rubocop/cop/style/invertible_unless_condition.rb +27 -7
  481. data/lib/rubocop/cop/style/ip_addresses.rb +3 -4
  482. data/lib/rubocop/cop/style/it_assignment.rb +69 -12
  483. data/lib/rubocop/cop/style/it_block_parameter.rb +211 -0
  484. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +4 -0
  485. data/lib/rubocop/cop/style/keyword_parameters_order.rb +23 -11
  486. data/lib/rubocop/cop/style/lambda.rb +46 -2
  487. data/lib/rubocop/cop/style/lambda_call.rb +31 -10
  488. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  489. data/lib/rubocop/cop/style/magic_comment_format.rb +4 -4
  490. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +11 -0
  491. data/lib/rubocop/cop/style/map_into_array.rb +6 -4
  492. data/lib/rubocop/cop/style/map_join.rb +123 -0
  493. data/lib/rubocop/cop/style/map_to_hash.rb +13 -5
  494. data/lib/rubocop/cop/style/map_to_set.rb +1 -3
  495. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +110 -27
  496. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
  497. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +58 -6
  498. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +36 -8
  499. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -1
  500. data/lib/rubocop/cop/style/method_def_parentheses.rb +36 -8
  501. data/lib/rubocop/cop/style/min_max_comparison.rb +17 -6
  502. data/lib/rubocop/cop/style/missing_else.rb +7 -1
  503. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +40 -7
  504. data/lib/rubocop/cop/style/mixin_grouping.rb +12 -3
  505. data/lib/rubocop/cop/style/mixin_usage.rb +1 -1
  506. data/lib/rubocop/cop/style/module_function.rb +4 -2
  507. data/lib/rubocop/cop/style/module_member_existence_check.rb +110 -0
  508. data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -1
  509. data/lib/rubocop/cop/style/multiline_if_modifier.rb +47 -5
  510. data/lib/rubocop/cop/style/multiline_if_then.rb +10 -4
  511. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
  512. data/lib/rubocop/cop/style/multiline_memoization.rb +7 -1
  513. data/lib/rubocop/cop/style/multiline_method_signature.rb +15 -22
  514. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
  515. data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
  516. data/lib/rubocop/cop/style/multiple_comparison.rb +33 -22
  517. data/lib/rubocop/cop/style/mutable_constant.rb +158 -14
  518. data/lib/rubocop/cop/style/negated_if_else_condition.rb +3 -3
  519. data/lib/rubocop/cop/style/negative_array_index.rb +228 -0
  520. data/lib/rubocop/cop/style/nested_modifier.rb +36 -12
  521. data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
  522. data/lib/rubocop/cop/style/next.rb +68 -10
  523. data/lib/rubocop/cop/style/nil_comparison.rb +53 -13
  524. data/lib/rubocop/cop/style/nil_lambda.rb +9 -1
  525. data/lib/rubocop/cop/style/non_nil_check.rb +21 -11
  526. data/lib/rubocop/cop/style/not.rb +12 -3
  527. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
  528. data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
  529. data/lib/rubocop/cop/style/numeric_predicate.rb +22 -6
  530. data/lib/rubocop/cop/style/object_then.rb +1 -0
  531. data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
  532. data/lib/rubocop/cop/style/one_line_conditional.rb +35 -15
  533. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  534. data/lib/rubocop/cop/style/operator_method_call.rb +10 -2
  535. data/lib/rubocop/cop/style/option_hash.rb +1 -1
  536. data/lib/rubocop/cop/style/optional_arguments.rb +1 -0
  537. data/lib/rubocop/cop/style/parallel_assignment.rb +58 -27
  538. data/lib/rubocop/cop/style/parentheses_around_condition.rb +7 -2
  539. data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
  540. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +18 -3
  541. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  542. data/lib/rubocop/cop/style/perl_backrefs.rb +5 -3
  543. data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
  544. data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
  545. data/lib/rubocop/cop/style/proc.rb +4 -2
  546. data/lib/rubocop/cop/style/raise_args.rb +28 -18
  547. data/lib/rubocop/cop/style/reduce_to_hash.rb +216 -0
  548. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  549. data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
  550. data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
  551. data/lib/rubocop/cop/style/redundant_assignment.rb +12 -2
  552. data/lib/rubocop/cop/style/redundant_begin.rb +60 -7
  553. data/lib/rubocop/cop/style/redundant_condition.rb +93 -18
  554. data/lib/rubocop/cop/style/redundant_constant_base.rb +42 -6
  555. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +26 -4
  556. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +17 -3
  557. data/lib/rubocop/cop/style/redundant_each.rb +4 -5
  558. data/lib/rubocop/cop/style/redundant_exception.rb +22 -4
  559. data/lib/rubocop/cop/style/redundant_fetch_block.rb +11 -11
  560. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +9 -0
  561. data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
  562. data/lib/rubocop/cop/style/redundant_format.rb +319 -0
  563. data/lib/rubocop/cop/style/redundant_freeze.rb +13 -5
  564. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +6 -1
  565. data/lib/rubocop/cop/style/redundant_interpolation.rb +12 -3
  566. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +49 -10
  567. data/lib/rubocop/cop/style/redundant_line_continuation.rb +83 -119
  568. data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
  569. data/lib/rubocop/cop/style/redundant_parentheses.rb +176 -83
  570. data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
  571. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +15 -0
  572. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
  573. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +27 -7
  574. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +16 -0
  575. data/lib/rubocop/cop/style/redundant_return.rb +4 -3
  576. data/lib/rubocop/cop/style/redundant_self.rb +20 -7
  577. data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -3
  578. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +27 -4
  579. data/lib/rubocop/cop/style/redundant_sort.rb +45 -11
  580. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  581. data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -2
  582. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +133 -0
  583. data/lib/rubocop/cop/style/regexp_literal.rb +107 -29
  584. data/lib/rubocop/cop/style/require_order.rb +25 -8
  585. data/lib/rubocop/cop/style/rescue_modifier.rb +16 -12
  586. data/lib/rubocop/cop/style/return_nil.rb +19 -4
  587. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
  588. data/lib/rubocop/cop/style/reverse_find.rb +51 -0
  589. data/lib/rubocop/cop/style/safe_navigation.rb +76 -20
  590. data/lib/rubocop/cop/style/sample.rb +19 -13
  591. data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
  592. data/lib/rubocop/cop/style/select_by_range.rb +197 -0
  593. data/lib/rubocop/cop/style/select_by_regexp.rb +54 -22
  594. data/lib/rubocop/cop/style/self_assignment.rb +13 -16
  595. data/lib/rubocop/cop/style/semicolon.rb +56 -14
  596. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +4 -0
  597. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  598. data/lib/rubocop/cop/style/single_line_do_end_block.rb +22 -8
  599. data/lib/rubocop/cop/style/single_line_methods.rb +33 -11
  600. data/lib/rubocop/cop/style/sole_nested_conditional.rb +96 -104
  601. data/lib/rubocop/cop/style/special_global_vars.rb +7 -2
  602. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +32 -6
  603. data/lib/rubocop/cop/style/static_class.rb +21 -0
  604. data/lib/rubocop/cop/style/string_concatenation.rb +38 -16
  605. data/lib/rubocop/cop/style/string_hash_keys.rb +1 -0
  606. data/lib/rubocop/cop/style/struct_inheritance.rb +44 -2
  607. data/lib/rubocop/cop/style/super_arguments.rb +7 -6
  608. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  609. data/lib/rubocop/cop/style/symbol_proc.rb +35 -15
  610. data/lib/rubocop/cop/style/tally_method.rb +181 -0
  611. data/lib/rubocop/cop/style/ternary_parentheses.rb +34 -1
  612. data/lib/rubocop/cop/style/time_now.rb +41 -0
  613. data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -2
  614. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +52 -1
  615. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  616. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +2 -2
  617. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  618. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
  619. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +35 -32
  620. data/lib/rubocop/cop/style/trivial_accessors.rb +2 -2
  621. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  622. data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
  623. data/lib/rubocop/cop/style/while_until_do.rb +7 -0
  624. data/lib/rubocop/cop/style/while_until_modifier.rb +16 -1
  625. data/lib/rubocop/cop/style/word_array.rb +1 -0
  626. data/lib/rubocop/cop/style/yoda_condition.rb +26 -12
  627. data/lib/rubocop/cop/style/yoda_expression.rb +11 -2
  628. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -3
  629. data/lib/rubocop/cop/style.rb +311 -0
  630. data/lib/rubocop/cop/team.rb +172 -49
  631. data/lib/rubocop/cop/util.rb +7 -10
  632. data/lib/rubocop/cop/utils/format_string.rb +20 -5
  633. data/lib/rubocop/cop/variable_force/assignment.rb +8 -4
  634. data/lib/rubocop/cop/variable_force/branch.rb +30 -6
  635. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  636. data/lib/rubocop/cop/variable_force/variable.rb +42 -11
  637. data/lib/rubocop/cop/variable_force.rb +26 -9
  638. data/lib/rubocop/cops_documentation_generator.rb +49 -15
  639. data/lib/rubocop/directive_comment.rb +147 -5
  640. data/lib/rubocop/ext/regexp_node.rb +0 -1
  641. data/lib/rubocop/feature_loader.rb +0 -6
  642. data/lib/rubocop/file_patterns.rb +9 -1
  643. data/lib/rubocop/formatter/base_formatter.rb +22 -0
  644. data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
  645. data/lib/rubocop/formatter/disabled_config_formatter.rb +57 -14
  646. data/lib/rubocop/formatter/emacs_style_formatter.rb +3 -1
  647. data/lib/rubocop/formatter/formatter_set.rb +7 -2
  648. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  649. data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
  650. data/lib/rubocop/formatter/html_formatter.rb +3 -5
  651. data/lib/rubocop/formatter/json_formatter.rb +82 -7
  652. data/lib/rubocop/formatter/junit_formatter.rb +27 -10
  653. data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
  654. data/lib/rubocop/formatter/offense_count_formatter.rb +5 -4
  655. data/lib/rubocop/formatter/pacman_formatter.rb +5 -2
  656. data/lib/rubocop/formatter/sarif_formatter.rb +186 -0
  657. data/lib/rubocop/formatter/simple_text_formatter.rb +4 -5
  658. data/lib/rubocop/formatter/tap_formatter.rb +8 -3
  659. data/lib/rubocop/formatter/worst_offenders_formatter.rb +5 -4
  660. data/lib/rubocop/formatter.rb +23 -21
  661. data/lib/rubocop/lockfile.rb +18 -0
  662. data/lib/rubocop/lsp/diagnostic.rb +22 -41
  663. data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
  664. data/lib/rubocop/lsp/routes.rb +158 -55
  665. data/lib/rubocop/lsp/runtime.rb +66 -15
  666. data/lib/rubocop/lsp/server.rb +4 -2
  667. data/lib/rubocop/lsp/stdin_runner.rb +38 -19
  668. data/lib/rubocop/lsp.rb +5 -2
  669. data/lib/rubocop/magic_comment.rb +55 -0
  670. data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
  671. data/lib/rubocop/mcp/explain_tool.rb +68 -0
  672. data/lib/rubocop/mcp/scope.rb +65 -0
  673. data/lib/rubocop/mcp/server.rb +307 -0
  674. data/lib/rubocop/mcp/source_files.rb +35 -0
  675. data/lib/rubocop/offense_limit.rb +30 -0
  676. data/lib/rubocop/options.rb +166 -23
  677. data/lib/rubocop/path_util.rb +20 -5
  678. data/lib/rubocop/pending_cops_reporter.rb +51 -0
  679. data/lib/rubocop/plugin/configuration_integrator.rb +153 -0
  680. data/lib/rubocop/plugin/load_error.rb +26 -0
  681. data/lib/rubocop/plugin/loader.rb +100 -0
  682. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  683. data/lib/rubocop/plugin.rb +46 -0
  684. data/lib/rubocop/project_index_loader.rb +82 -0
  685. data/lib/rubocop/rake_task.rb +6 -4
  686. data/lib/rubocop/remote_config.rb +18 -13
  687. data/lib/rubocop/result_cache.rb +110 -65
  688. data/lib/rubocop/rspec/cop_helper.rb +21 -1
  689. data/lib/rubocop/rspec/expect_offense.rb +11 -7
  690. data/lib/rubocop/rspec/shared_contexts.rb +85 -3
  691. data/lib/rubocop/rspec/support.rb +4 -0
  692. data/lib/rubocop/runner.rb +368 -106
  693. data/lib/rubocop/server/cache.rb +67 -48
  694. data/lib/rubocop/server/cli.rb +2 -4
  695. data/lib/rubocop/server/client_command/base.rb +10 -0
  696. data/lib/rubocop/server/client_command/exec.rb +2 -1
  697. data/lib/rubocop/server/client_command/start.rb +11 -1
  698. data/lib/rubocop/server/core.rb +8 -0
  699. data/lib/rubocop/server.rb +14 -0
  700. data/lib/rubocop/target_finder.rb +25 -11
  701. data/lib/rubocop/target_ruby.rb +52 -23
  702. data/lib/rubocop/todo_audit.rb +111 -0
  703. data/lib/rubocop/unified_diff.rb +257 -0
  704. data/lib/rubocop/util.rb +69 -0
  705. data/lib/rubocop/version.rb +48 -10
  706. data/lib/rubocop.rb +35 -682
  707. data/lib/ruby_lsp/rubocop/addon.rb +28 -17
  708. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +99 -0
  709. metadata +129 -21
  710. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
  711. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  712. data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +0 -50
@@ -62,14 +62,34 @@ module RuboCop
62
62
  @errors = []
63
63
  @warnings = []
64
64
  @aborting = false
65
+ @inspected_files = []
66
+ @diff_sources = {}
67
+ @report_queue = {}
68
+ end
69
+
70
+ # The `--diff` patches, one per file, from the source on disk (or stdin) to
71
+ # the source once every correction, redundant directive removal included,
72
+ # has been applied.
73
+ def diffs
74
+ @diffs ||= @diff_sources.filter_map do |file, (original_source, corrected_source)|
75
+ diff = UnifiedDiff.new(PathUtil.smart_path(file), original_source, corrected_source).to_s
76
+ diff unless diff.empty?
77
+ end
65
78
  end
66
79
 
67
80
  def run(paths)
68
- target_files = find_target_files(paths)
81
+ @inspection_team_by_config = {}.compare_by_identity
82
+
83
+ # Compute the cache source checksum once to avoid potential
84
+ # inconsistencies between workers.
85
+ ResultCache.source_checksum
86
+
87
+ target_files = only_changed(find_target_files(paths))
88
+ build_project_index(target_files)
89
+
69
90
  if @options[:list_target_files]
70
91
  list_files(target_files)
71
92
  else
72
- warm_cache(target_files) if @options[:parallel]
73
93
  inspect_files(target_files)
74
94
  end
75
95
  rescue Interrupt
@@ -86,19 +106,12 @@ module RuboCop
86
106
 
87
107
  private
88
108
 
89
- # Warms up the RuboCop cache by forking a suitable number of RuboCop
90
- # instances that each inspects its allotted group of files.
91
- def warm_cache(target_files)
92
- saved_options = @options.dup
93
- if target_files.length <= 1
94
- puts 'Skipping parallel inspection: only a single file needs inspection' if @options[:debug]
95
- return
96
- end
97
- puts 'Running parallel inspection' if @options[:debug]
98
- %i[autocorrect safe_autocorrect].each { |opt| @options[opt] = false }
99
- Parallel.each(target_files) { |target_file| file_offenses(target_file) }
100
- ensure
101
- @options = saved_options
109
+ # The project index is deliberately built from the unfiltered file list:
110
+ # cross-file offenses must not depend on which files happen to have changed.
111
+ def only_changed(target_files)
112
+ return target_files unless @options[:changed]
113
+
114
+ ChangedFiles.new(@options[:changed]).filter(target_files).freeze
102
115
  end
103
116
 
104
117
  def find_target_files(paths)
@@ -112,12 +125,54 @@ module RuboCop
112
125
  target_files.each(&:freeze).freeze
113
126
  end
114
127
 
115
- def inspect_files(files)
116
- inspected_files = []
128
+ def build_project_index(target_files)
129
+ return unless project_index_enabled?
130
+
131
+ @project_index = ProjectIndexLoader.build_index(project_index_files(target_files))
132
+ end
133
+
134
+ # The index always covers the whole project, not just the files being
135
+ # inspected: cross-file offenses must not depend on which files a
136
+ # particular run happens to include, or single-file runs (editors, CI
137
+ # sharding) would see different offenses than full runs. The project is
138
+ # rooted at the directory of the configuration that enabled the index.
139
+ def project_index_files(target_files)
140
+ root = @config_store.for_pwd.base_dir_for_path_parameters
141
+ project_files = begin
142
+ find_target_files([root]) | target_files
143
+ rescue Errno::ENOENT
144
+ target_files
145
+ end
146
+
147
+ (project_files | bundled_gem_files).sort
148
+ end
149
+
150
+ def bundled_gem_files
151
+ return [] unless @config_store.for_pwd.for_all_cops['ProjectIndexIncludesGems']
152
+
153
+ ProjectIndexLoader.bundled_gem_source_files
154
+ end
155
+
156
+ def project_index_enabled?
157
+ return false unless @config_store.for_pwd.for_all_cops['UseProjectIndex']
158
+
159
+ unless ProjectIndexLoader.available?
160
+ ProjectIndexLoader.warn_unavailable
161
+ return false
162
+ end
163
+
164
+ true
165
+ end
117
166
 
167
+ def inspect_files(files) # rubocop:disable Metrics/AbcSize
118
168
  formatter_set.started(files)
169
+ formatters_started = true
170
+ file_iterator(files) do |file|
171
+ offenses, problems = collect_problems { process_file(file) }
172
+ succeeded = offenses.none? { |o| considered_failure?(o) && offense_displayed?(o) }
119
173
 
120
- each_inspected_file(files) { |file| inspected_files << file }
174
+ [offenses, succeeded, problems]
175
+ end
121
176
  ensure
122
177
  # OPTIMIZE: Calling `ResultCache.cleanup` takes time. This optimization
123
178
  # mainly targets editors that integrates RuboCop. When RuboCop is run
@@ -125,23 +180,101 @@ module RuboCop
125
180
  if files.size > 1 && cached_run?
126
181
  ResultCache.cleanup(@config_store, @options[:debug], @options[:cache_root])
127
182
  end
128
-
129
- formatter_set.finished(inspected_files.freeze)
183
+ formatter_set.finished(@inspected_files.freeze) if formatters_started
130
184
  formatter_set.close_output_files
185
+ warn_about_elided_offenses
131
186
  end
132
187
 
133
- def each_inspected_file(files)
134
- files.reduce(true) do |all_passed, file|
135
- offenses = process_file(file)
136
- yield file
188
+ def file_iterator(files, &block)
189
+ all_passed = true
137
190
 
138
- if offenses.any? { |o| considered_failure?(o) && offense_displayed?(o) }
139
- break false if @options[:fail_fast]
191
+ on_start = ->(file, _index) { file_started(file) }
192
+ on_finish = lambda do |file, index, (offenses, passed, problems)|
193
+ all_passed &&= passed
194
+ finished_report(file, index, offenses, problems)
195
+ end
140
196
 
141
- next false
142
- end
197
+ if run_in_parallel?(files)
198
+ parallel_file_iterator(files, on_start, on_finish, &block)
199
+ else
200
+ serial_file_iterator(files, on_start, on_finish, &block)
201
+ end
202
+
203
+ process_remaining_report_queue
143
204
 
144
- all_passed
205
+ all_passed
206
+ end
207
+
208
+ def finished_report(file, index, offenses, problems)
209
+ @report_queue[index] = [file, offenses, problems]
210
+ @next_index_to_report ||= 0
211
+ while @report_queue.key?(@next_index_to_report)
212
+ process_report_queue_entry(@next_index_to_report)
213
+ @next_index_to_report += 1
214
+ end
215
+ end
216
+
217
+ def process_report_queue_entry(index)
218
+ file, offenses, (errors, warnings) = @report_queue.delete(index)
219
+ @errors.concat(errors)
220
+ @warnings.concat(warnings)
221
+ file_problems(file, errors, warnings) unless errors.empty? && warnings.empty?
222
+ file_finished(file, offenses)
223
+ end
224
+
225
+ def process_remaining_report_queue
226
+ @report_queue.keys.sort.each do |index|
227
+ process_report_queue_entry(index)
228
+ end
229
+ end
230
+
231
+ def run_in_parallel?(files)
232
+ return false unless parallel_supported_by_options?
233
+
234
+ if files.size <= 1
235
+ puts 'Skipping parallel inspection: only a single file needs inspection' if @options[:debug]
236
+ return false
237
+ end
238
+
239
+ return false if project_index_disables_parallel?
240
+
241
+ puts 'Running parallel inspection' if @options[:debug]
242
+
243
+ true
244
+ end
245
+
246
+ # `--auto-gen-config` needs the offenses of every file in one place, and
247
+ # `--diff` collects the diffs in this process, where a worker's copy of
248
+ # them would be lost.
249
+ def parallel_supported_by_options?
250
+ @options[:parallel] && !@options[:auto_gen_config] && !@options[:diff]
251
+ end
252
+
253
+ def project_index_disables_parallel?
254
+ return false if @project_index.nil? || !Gem.win_platform?
255
+
256
+ if @options[:debug]
257
+ puts 'Skipping parallel inspection: the project index is enabled and parallel ' \
258
+ 'inspection is not yet supported on Windows.'
259
+ end
260
+
261
+ true
262
+ end
263
+
264
+ def parallel_file_iterator(files, on_start, on_finish, &block)
265
+ Parallel.each(files, start: on_start, finish: on_finish, &block)
266
+ end
267
+
268
+ def serial_file_iterator(files, on_start, on_finish, &block)
269
+ files.each_with_index do |file, index|
270
+ on_start.call(file, index)
271
+ result = yield file
272
+ on_finish.call(file, index, result)
273
+
274
+ # Report and count the offending file before stopping so `--fail-fast`
275
+ # still shows its offenses and exits with a failing status.
276
+ _offenses, succeeded = result
277
+ break if @options[:fail_fast] && !succeeded
145
278
  end
146
279
  end
147
280
 
@@ -149,24 +282,37 @@ module RuboCop
149
282
  paths.each { |path| puts PathUtil.relative_path(path) }
150
283
  end
151
284
 
285
+ # Keeps the errors and warnings a file causes apart from the rest of the
286
+ # run's. A parallel worker inspects files in a copy of the runner that is
287
+ # thrown away, so they have to travel back with the file's offenses.
288
+ def collect_problems
289
+ errors = @errors
290
+ warnings = @warnings
291
+ @errors = []
292
+ @warnings = []
293
+
294
+ [yield, [@errors, @warnings]]
295
+ ensure
296
+ @errors = errors
297
+ @warnings = warnings
298
+ end
299
+
152
300
  def process_file(file)
153
- file_started(file)
154
- offenses = file_offenses(file)
301
+ file_offenses(file)
155
302
  rescue InfiniteCorrectionLoop => e
156
303
  raise e if @options[:raise_cop_error]
157
304
 
158
305
  errors << e
159
306
  warn Rainbow(e.message).red
160
- offenses = e.offenses.compact.sort.freeze
161
- ensure
162
- file_finished(file, offenses || [])
307
+ e.offenses.compact.sort.freeze
163
308
  end
164
309
 
165
310
  def file_offenses(file)
166
311
  file_offense_cache(file) do
167
312
  source, offenses = do_inspection_loop(file)
168
313
  offenses = add_redundant_disables(file, offenses.compact.sort, source)
169
- offenses.sort.reject(&:disabled?).freeze
314
+ offenses = offenses.reject(&:disabled?) unless @options[:display_suppressed]
315
+ offenses.sort.freeze
170
316
  end
171
317
  end
172
318
 
@@ -190,7 +336,7 @@ module RuboCop
190
336
 
191
337
  if real_run_needed
192
338
  offenses = yield
193
- save_in_cache(cache, offenses)
339
+ save_in_cache(cache, offenses) unless Cop::Registry.global.warnings?(file)
194
340
  end
195
341
 
196
342
  offenses
@@ -203,9 +349,11 @@ module RuboCop
203
349
  if redundant_updated
204
350
  # Do one extra inspection loop if any redundant disables were
205
351
  # removed. This is done in order to find rubocop:enable directives that
206
- # have now become useless.
207
- _source, new_offenses = do_inspection_loop(file)
208
- offenses |= new_offenses
352
+ # have now become useless. It finds the offenses that are left again,
353
+ # located in the corrected source, so only the corrected ones are kept
354
+ # from before, as `inspect_and_correct` does.
355
+ _source, new_offenses = do_inspection_loop(file, team.updated_source)
356
+ offenses = offenses.select(&:corrected?) | new_offenses
209
357
  end
210
358
  end
211
359
  offenses
@@ -218,12 +366,20 @@ module RuboCop
218
366
  team = Cop::Team.mobilize([Cop::Lint::RedundantCopDisableDirective], config, @options)
219
367
  return if team.cops.empty?
220
368
 
369
+ team.defer_corrections = @options[:diff]
370
+
221
371
  team.cops.first.offenses_to_check = offenses
222
372
  yield team
223
373
  end
224
374
 
225
375
  def check_for_redundant_disables?(source)
226
- return false if source.disabled_line_ranges.empty? || except_redundant_cop_disable_directive?
376
+ return false if except_redundant_cop_disable_directive?
377
+ # Detached `disable-next` directives produce no disabled ranges but must
378
+ # still be reported as redundant.
379
+ if source.disabled_line_ranges.empty? &&
380
+ source.comment_config.detached_next_directives.empty?
381
+ return false
382
+ end
227
383
 
228
384
  !@options[:only]
229
385
  end
@@ -245,7 +401,17 @@ module RuboCop
245
401
  formatter_set.file_started(file, cli_options: @options, config_store: @config_store)
246
402
  end
247
403
 
404
+ # Formatters get the messages without the colors added for the terminal.
405
+ def file_problems(file, errors, warnings)
406
+ formatter_set.file_problems(file, plain_messages(errors), plain_messages(warnings))
407
+ end
408
+
409
+ def plain_messages(problems)
410
+ problems.map { |problem| Rainbow::StringUtils.uncolor(problem.to_s) }
411
+ end
412
+
248
413
  def file_finished(file, offenses)
414
+ @inspected_files << file
249
415
  offenses = offenses_to_report(offenses)
250
416
  formatter_set.file_finished(file, offenses)
251
417
  end
@@ -254,10 +420,6 @@ module RuboCop
254
420
  @cached_run ||=
255
421
  (@options[:cache] == 'true' ||
256
422
  (@options[:cache] != 'false' && @config_store.for_pwd.for_all_cops['UseCache'])) &&
257
- # When running --auto-gen-config, there's some processing done in the
258
- # cops related to calculating the Max parameters for Metrics cops. We
259
- # need to do that processing and cannot use caching.
260
- !@options[:auto_gen_config] &&
261
423
  # We can't cache results from code which is piped in to stdin
262
424
  !@options[:stdin]
263
425
  end
@@ -266,41 +428,107 @@ module RuboCop
266
428
  return unless cache
267
429
  # Caching results when a cop has crashed would prevent the crash in the
268
430
  # next run, since the cop would not be called then. We want crashes to
269
- # show up the same in each run.
431
+ # show up the same in each run. Only this file's errors and warnings are
432
+ # visible here, see `collect_problems`.
270
433
  return if errors.any? || warnings.any?
271
434
 
272
435
  cache.save(offenses)
273
436
  end
274
437
 
275
- def do_inspection_loop(file)
276
- processed_source = get_processed_source(file)
438
+ def do_inspection_loop(file, source = nil)
439
+ processed_source = initial_processed_source(file, source)
440
+ original_source = processed_source.raw_source
277
441
  # This variable is 2d array used to track corrected offenses after each
278
442
  # inspection iteration. This is used to output meaningful infinite loop
279
443
  # error message.
280
444
  offenses_by_iteration = []
445
+ corrected_source = nil
281
446
 
282
- # When running with --autocorrect, we need to inspect the file (which
283
- # includes writing a corrected version of it) until no more corrections
284
- # are made. This is because automatic corrections can introduce new
285
- # offenses. In the normal case the loop is only executed once.
447
+ # When running with --autocorrect, we need to inspect the file until no
448
+ # more corrections are made. This is because automatic corrections can
449
+ # introduce new offenses. In the normal case the loop is only executed
450
+ # once. The corrections are kept in memory while iterating and written
451
+ # back to the file when the loop is done.
286
452
  iterate_until_no_changes(processed_source, offenses_by_iteration) do
287
- # The offenses that couldn't be corrected will be found again so we
288
- # only keep the corrected ones in order to avoid duplicate reporting.
289
- !offenses_by_iteration.empty? && offenses_by_iteration.last.select!(&:corrected?)
290
- new_offenses, updated_source_file = inspect_file(processed_source)
291
- offenses_by_iteration.push(new_offenses)
453
+ team, updated_source_file = inspect_and_correct(processed_source, offenses_by_iteration)
292
454
 
293
455
  # We have to reprocess the source to pickup the changes. Since the
294
456
  # change could (theoretically) introduce parsing errors, we break the
295
457
  # loop if we find any.
296
458
  break unless updated_source_file
297
459
 
298
- processed_source = get_processed_source(file)
460
+ # Autocorrect has happened, don't use the prism result since it is stale.
461
+ # With --stdin the corrected source is kept in @options[:stdin] instead.
462
+ corrected_source = team.updated_source
463
+ processed_source = get_processed_source(file, nil, source: corrected_source)
299
464
  end
300
465
 
301
466
  # Return summary of corrected offenses after all iterations
302
- offenses = offenses_by_iteration.flatten.uniq
303
- [processed_source, offenses]
467
+ [processed_source, offenses_by_iteration.flatten.uniq]
468
+ ensure
469
+ finalize_corrections(file, original_source, corrected_source)
470
+ end
471
+
472
+ # `source` is the corrected source to continue from when the corrections
473
+ # are kept in memory rather than written to the file (`--diff`).
474
+ def initial_processed_source(file, source)
475
+ return get_processed_source(file, nil, source: source) if source
476
+
477
+ # We can reuse the prism result since the source did not change yet.
478
+ get_processed_source(file, @prism_result)
479
+ end
480
+
481
+ def inspect_and_correct(processed_source, offenses_by_iteration)
482
+ # The offenses that couldn't be corrected will be found again so we
483
+ # only keep the corrected ones in order to avoid duplicate reporting.
484
+ !offenses_by_iteration.empty? && offenses_by_iteration.last.select!(&:corrected?)
485
+ team, new_offenses, updated_source_file = inspect_iteration(processed_source)
486
+ offenses_by_iteration.push(new_offenses)
487
+
488
+ [team, updated_source_file]
489
+ end
490
+
491
+ # Write the file once, even when the loop was left through an exception
492
+ # (e.g. an infinite correction loop), like the per-iteration writes used
493
+ # to be. Under `--diff` nothing is written at all.
494
+ def finalize_corrections(file, original_source, corrected_source)
495
+ if @options[:diff]
496
+ record_diff(file, original_source, corrected_source)
497
+ elsif corrected_source
498
+ Util.replace_file_contents(file, corrected_source)
499
+ end
500
+ end
501
+
502
+ # `--diff` reports what autocorrection would do instead of doing it. With
503
+ # `--stdin` the corrected source is handed back through the options rather
504
+ # than deferred, so that is where the new source comes from. A file can go
505
+ # through more than one inspection loop, so the diff runs from the source
506
+ # the first loop started with to the one the last loop ended with.
507
+ def record_diff(file, original_source, corrected_source)
508
+ return unless original_source
509
+
510
+ new_source = @options[:stdin] || corrected_source
511
+ # The original source is the file as it is on disk, so the corrected one
512
+ # has to go through the same line ending conversion `File.write` would
513
+ # apply, or on Windows every single line reads as changed.
514
+ new_source = new_source ? Util.emulate_write_read_cycle(new_source) : original_source
515
+
516
+ sources = (@diff_sources[file] ||= [original_source])
517
+ sources[1] = new_source
518
+ end
519
+
520
+ def inspect_iteration(processed_source)
521
+ team = mobilize_team(processed_source)
522
+ team.defer_corrections = @options[:diff] || in_memory_corrections_possible?
523
+ offenses, updated_source_file = inspect_file(processed_source, team)
524
+ [team, offenses, updated_source_file]
525
+ end
526
+
527
+ # Custom ruby extractors may derive their fragments from the file on
528
+ # disk rather than from the passed processed source, so corrections can
529
+ # only be kept in memory when the default extractor is used.
530
+ def in_memory_corrections_possible?
531
+ self.class.ruby_extractors.one?
304
532
  end
305
533
 
306
534
  def iterate_until_no_changes(source, offenses_by_iteration)
@@ -344,16 +572,9 @@ module RuboCop
344
572
 
345
573
  def inspect_file(processed_source, team = mobilize_team(processed_source))
346
574
  extracted_ruby_sources = extract_ruby_sources(processed_source)
347
- offenses = extracted_ruby_sources.flat_map do |extracted_ruby_source|
348
- report = team.investigate(
349
- extracted_ruby_source[:processed_source],
350
- offset: extracted_ruby_source[:offset],
351
- original: processed_source
352
- )
353
- @errors.concat(team.errors)
354
- @warnings.concat(team.warnings)
355
- report.offenses
356
- end
575
+ offenses = team.investigate_fragments(extracted_ruby_sources, original: processed_source)
576
+ @errors.concat(team.errors)
577
+ @warnings.concat(team.warnings)
357
578
  [offenses, team.updated_source_file?]
358
579
  end
359
580
 
@@ -373,30 +594,41 @@ module RuboCop
373
594
 
374
595
  def mobilize_team(processed_source)
375
596
  config = @config_store.for_file(processed_source.path)
376
- Cop::Team.mobilize(mobilized_cop_classes(config), config, @options)
597
+ @inspection_team_by_config ||= {}.compare_by_identity
598
+ @inspection_team_by_config[config] ||= assemble_team(config)
377
599
  end
378
600
 
379
- def mobilized_cop_classes(config) # rubocop:disable Metrics/AbcSize
601
+ def mobilized_cop_classes(config)
380
602
  @mobilized_cop_classes ||= {}.compare_by_identity
381
603
  @mobilized_cop_classes[config] ||= begin
382
- cop_classes = Cop::Registry.all
383
-
384
604
  # `@options[:only]` and `@options[:except]` are not qualified until
385
- # needed so that the Registry can be fully loaded, including any
386
- # cops added by `require`s.
605
+ # needed so that the registry contains any cops added by `require`s,
606
+ # which register eagerly when their files are loaded.
387
607
  qualify_option_cop_names
388
608
 
389
609
  OptionsValidator.new(@options).validate_cop_options
390
610
 
391
- if @options[:only]
392
- cop_classes.select! { |c| c.match?(@options[:only]) }
393
- else
394
- filter_cop_classes(cop_classes, config)
395
- end
611
+ # Filtering by badge keeps lazy-loaded cops unloaded; only the cops
612
+ # that survive the filter and are enabled will be loaded.
613
+ Cop::Registry.global.filter_by_badge(@options) { |badge| mobilize_cop_badge?(badge, config) }
614
+ end
615
+ end
616
+
617
+ # Lets a runner that is reused from run to run pick up a different `--only`
618
+ # or `--except`.
619
+ def forget_mobilized_cops
620
+ @mobilized_cop_classes = nil
621
+ end
396
622
 
397
- cop_classes.reject! { |c| c.match?(@options[:except]) }
623
+ def mobilize_cop_badge?(badge, config)
624
+ return false if badge.department == :Test
625
+ return false if badge.match_name?(@options[:except])
398
626
 
399
- Cop::Registry.new(cop_classes, @options)
627
+ if @options[:only]
628
+ badge.match_name?(@options[:only])
629
+ else
630
+ # use only cops that link to a style guide if requested.
631
+ !style_guide_cops_only?(config) || config.for_cop(badge.to_s)['StyleGuide']
400
632
  end
401
633
  end
402
634
 
@@ -404,19 +636,12 @@ module RuboCop
404
636
  %i[only except].each do |option|
405
637
  next unless @options[option]
406
638
 
407
- @options[option].map! do |cop_name|
639
+ @options[option] = @options[option].map do |cop_name|
408
640
  Cop::Registry.qualified_cop_name(cop_name, "--#{option} option")
409
641
  end
410
642
  end
411
643
  end
412
644
 
413
- def filter_cop_classes(cop_classes, config)
414
- # use only cops that link to a style guide if requested
415
- return unless style_guide_cops_only?(config)
416
-
417
- cop_classes.select! { |cop| config.for_cop(cop)['StyleGuide'] }
418
- end
419
-
420
645
  def style_guide_cops_only?(config)
421
646
  @options[:only_guide_cops] || config.for_all_cops['StyleGuideCopsOnly']
422
647
  end
@@ -452,7 +677,28 @@ module RuboCop
452
677
  end
453
678
 
454
679
  def offenses_to_report(offenses)
455
- offenses.select { |o| offense_displayed?(o) }
680
+ offenses = offenses.select { |o| offense_displayed?(o) }
681
+ offenses = offense_limit.filter(offenses) if offense_limit
682
+ offenses
683
+ end
684
+
685
+ # Files are reported in order, so which offenses survive the limit does not
686
+ # depend on how the run was parallelized.
687
+ def offense_limit
688
+ return @offense_limit if defined?(@offense_limit)
689
+
690
+ max = @options[:max_offenses_per_cop]
691
+ @offense_limit = (OffenseLimit.new(max.to_i) if max)
692
+ end
693
+
694
+ def warn_about_elided_offenses
695
+ elided = offense_limit&.elided_per_cop
696
+ return unless elided&.any?
697
+
698
+ warn Rainbow(
699
+ "#{elided.values.sum} more offenses were not reported because of " \
700
+ "--max-offenses-per-cop=#{offense_limit.max} (#{elided.keys.join(', ')})."
701
+ ).yellow
456
702
  end
457
703
 
458
704
  def supports_safe_autocorrect?(offense)
@@ -472,24 +718,30 @@ module RuboCop
472
718
  end
473
719
 
474
720
  def minimum_severity_to_fail
475
- @minimum_severity_to_fail ||= begin
476
- # Unless given explicitly as `fail_level`, `:info` severity offenses do not fail
477
- name = @options[:fail_level] || :refactor
478
-
479
- # autocorrect is a fake level - use the default
480
- RuboCop::Cop::Severity.new(name == :autocorrect ? :refactor : name)
481
- end
721
+ @minimum_severity_to_fail ||=
722
+ RuboCop::Cop::Severity.minimum_to_fail(@options, @config_store.for_pwd)
482
723
  end
483
724
 
484
- # rubocop:disable Metrics/MethodLength
485
- def get_processed_source(file)
725
+ # rubocop:disable-next Metrics/MethodLength
726
+ def get_processed_source(file, prism_result, source: nil)
486
727
  config = @config_store.for_file(file)
487
728
  ruby_version = config.target_ruby_version
488
729
  parser_engine = config.parser_engine
489
730
 
490
- processed_source = if @options[:stdin]
731
+ processed_source = if source
732
+ ProcessedSource.new(
733
+ Util.emulate_write_read_cycle(source),
734
+ ruby_version,
735
+ file,
736
+ parser_engine: parser_engine
737
+ )
738
+ elsif @options[:stdin]
491
739
  ProcessedSource.new(
492
- @options[:stdin], ruby_version, file, parser_engine: parser_engine
740
+ @options[:stdin],
741
+ ruby_version,
742
+ file,
743
+ parser_engine: parser_engine,
744
+ prism_result: prism_result
493
745
  )
494
746
  else
495
747
  begin
@@ -504,16 +756,26 @@ module RuboCop
504
756
  processed_source.registry = mobilized_cop_classes(config)
505
757
  processed_source
506
758
  end
507
- # rubocop:enable Metrics/MethodLength
508
759
 
509
760
  # A Cop::Team instance is stateful and may change when inspecting.
510
761
  # The "standby" team for a given config is an initialized but
511
762
  # otherwise dormant team that can be used for config- and option-
512
763
  # level caching in ResultCache.
513
764
  def standby_team(config)
514
- @team_by_config ||= {}.compare_by_identity
515
- @team_by_config[config] ||=
516
- Cop::Team.mobilize(mobilized_cop_classes(config), config, @options)
765
+ @standby_team_by_config ||= {}.compare_by_identity
766
+ @standby_team_by_config[config] ||= assemble_team(config)
767
+ end
768
+
769
+ def assemble_team(config)
770
+ team = Cop::Team.mobilize(mobilized_cop_classes(config), config, @options)
771
+
772
+ if @project_index
773
+ team.cops.each do |cop|
774
+ cop.project_index = @project_index
775
+ end
776
+ end
777
+
778
+ team
517
779
  end
518
780
  end
519
781
  end