rubocop 1.71.1 → 1.91.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 (661) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +23 -19
  4. data/config/default.yml +883 -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 +7 -2
  10. data/lib/rubocop/changed_files.rb +112 -0
  11. data/lib/rubocop/cli/command/auto_generate_config.rb +36 -4
  12. data/lib/rubocop/cli/command/execute_runner.rb +52 -1
  13. data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
  14. data/lib/rubocop/cli/command/lsp.rb +1 -1
  15. data/lib/rubocop/cli/command/mcp.rb +19 -0
  16. data/lib/rubocop/cli/command/show_cops.rb +2 -2
  17. data/lib/rubocop/cli/command/show_docs_url.rb +4 -8
  18. data/lib/rubocop/cli/command/suggest_extensions.rb +8 -2
  19. data/lib/rubocop/cli.rb +58 -17
  20. data/lib/rubocop/comment_config/directive_range.rb +34 -0
  21. data/lib/rubocop/comment_config/disable_next.rb +143 -0
  22. data/lib/rubocop/comment_config/push_pop.rb +55 -0
  23. data/lib/rubocop/comment_config.rb +92 -48
  24. data/lib/rubocop/config.rb +137 -19
  25. data/lib/rubocop/config_finder.rb +1 -1
  26. data/lib/rubocop/config_loader.rb +72 -49
  27. data/lib/rubocop/config_loader_resolver.rb +94 -28
  28. data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
  29. data/lib/rubocop/config_obsoletion/extracted_cop.rb +6 -3
  30. data/lib/rubocop/config_obsoletion/removed_cop.rb +8 -0
  31. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  32. data/lib/rubocop/config_obsoletion.rb +47 -3
  33. data/lib/rubocop/config_store.rb +7 -2
  34. data/lib/rubocop/config_validator.rb +64 -12
  35. data/lib/rubocop/cop/autocorrect_logic.rb +35 -14
  36. data/lib/rubocop/cop/badge.rb +9 -1
  37. data/lib/rubocop/cop/base.rb +93 -21
  38. data/lib/rubocop/cop/bundler/gem_comment.rb +5 -3
  39. data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
  40. data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -3
  41. data/lib/rubocop/cop/bundler.rb +19 -0
  42. data/lib/rubocop/cop/commissioner.rb +13 -11
  43. data/lib/rubocop/cop/corrector.rb +4 -4
  44. data/lib/rubocop/cop/correctors/alignment_corrector.rb +79 -10
  45. data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
  46. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +1 -1
  47. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
  48. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -1
  49. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -5
  50. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +8 -1
  51. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +36 -2
  52. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  53. data/lib/rubocop/cop/correctors.rb +28 -0
  54. data/lib/rubocop/cop/documentation.rb +2 -3
  55. data/lib/rubocop/cop/exclude_limit.rb +31 -5
  56. data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
  57. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  58. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +49 -17
  59. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +2 -3
  60. data/lib/rubocop/cop/gemspec/require_mfa.rb +22 -5
  61. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +12 -7
  62. data/lib/rubocop/cop/gemspec.rb +22 -0
  63. data/lib/rubocop/cop/generator/registration_injector.rb +188 -0
  64. data/lib/rubocop/cop/generator.rb +5 -1
  65. data/lib/rubocop/cop/internal_affairs/example_description.rb +9 -5
  66. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
  67. data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
  68. data/lib/rubocop/cop/internal_affairs/location_exists.rb +142 -0
  69. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
  70. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +14 -15
  71. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  72. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -2
  73. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +6 -2
  74. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +92 -0
  75. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +2 -2
  76. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  77. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  78. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +5 -3
  79. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +13 -2
  80. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
  81. data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
  82. data/lib/rubocop/cop/internal_affairs.rb +3 -16
  83. data/lib/rubocop/cop/layout/argument_alignment.rb +4 -2
  84. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  85. data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
  86. data/lib/rubocop/cop/layout/block_alignment.rb +59 -4
  87. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  88. data/lib/rubocop/cop/layout/case_indentation.rb +3 -1
  89. data/lib/rubocop/cop/layout/class_structure.rb +163 -35
  90. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
  91. data/lib/rubocop/cop/layout/comment_indentation.rb +17 -7
  92. data/lib/rubocop/cop/layout/condition_position.rb +13 -3
  93. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  94. data/lib/rubocop/cop/layout/dot_position.rb +2 -2
  95. data/lib/rubocop/cop/layout/else_alignment.rb +3 -15
  96. data/lib/rubocop/cop/layout/empty_comment.rb +8 -10
  97. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +27 -9
  98. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +63 -5
  99. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +46 -21
  100. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +101 -0
  101. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +34 -4
  102. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +8 -29
  103. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
  104. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +13 -2
  105. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +17 -3
  106. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
  107. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
  108. data/lib/rubocop/cop/layout/end_alignment.rb +9 -3
  109. data/lib/rubocop/cop/layout/extra_spacing.rb +105 -3
  110. data/lib/rubocop/cop/layout/first_argument_indentation.rb +56 -3
  111. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +18 -5
  112. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +26 -0
  113. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +20 -15
  114. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
  115. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +11 -0
  116. data/lib/rubocop/cop/layout/hash_alignment.rb +11 -13
  117. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +3 -3
  118. data/lib/rubocop/cop/layout/heredoc_indentation.rb +33 -3
  119. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  120. data/lib/rubocop/cop/layout/indentation_width.rb +157 -10
  121. data/lib/rubocop/cop/layout/leading_comment_space.rb +40 -1
  122. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +2 -3
  123. data/lib/rubocop/cop/layout/line_length.rb +160 -23
  124. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +57 -57
  125. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +8 -2
  126. data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -0
  127. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +56 -56
  128. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
  129. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +245 -40
  130. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  131. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +9 -5
  132. data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
  133. data/lib/rubocop/cop/layout/redundant_line_break.rb +89 -6
  134. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +14 -7
  135. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  136. data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
  137. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +14 -3
  138. data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -3
  139. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  140. data/lib/rubocop/cop/layout/space_around_operators.rb +30 -4
  141. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
  142. data/lib/rubocop/cop/layout/space_before_brackets.rb +6 -39
  143. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
  144. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +42 -36
  145. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -0
  146. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
  147. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  148. data/lib/rubocop/cop/layout.rb +114 -0
  149. data/lib/rubocop/cop/lazy_loader.rb +41 -0
  150. data/lib/rubocop/cop/lint/ambiguous_assignment.rb +9 -17
  151. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +72 -1
  152. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +1 -10
  153. data/lib/rubocop/cop/lint/ambiguous_range.rb +6 -2
  154. data/lib/rubocop/cop/lint/argument_mismatch.rb +99 -0
  155. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
  156. data/lib/rubocop/cop/lint/assignment_in_condition.rb +15 -1
  157. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  158. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -8
  159. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +4 -3
  160. data/lib/rubocop/cop/lint/constant_reassignment.rb +94 -15
  161. data/lib/rubocop/cop/lint/constant_resolution.rb +31 -6
  162. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +240 -0
  163. data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
  164. data/lib/rubocop/cop/lint/debugger.rb +13 -4
  165. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  166. data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
  167. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +5 -2
  168. data/lib/rubocop/cop/lint/deprecated_reference.rb +194 -0
  169. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  170. data/lib/rubocop/cop/lint/duplicate_methods.rb +506 -41
  171. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
  172. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  173. data/lib/rubocop/cop/lint/empty_block.rb +4 -4
  174. data/lib/rubocop/cop/lint/empty_conditional_body.rb +20 -65
  175. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  176. data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
  177. data/lib/rubocop/cop/lint/empty_interpolation.rb +14 -1
  178. data/lib/rubocop/cop/lint/empty_when.rb +8 -1
  179. data/lib/rubocop/cop/lint/ensure_return.rb +19 -1
  180. data/lib/rubocop/cop/lint/erb_new_arguments.rb +4 -8
  181. data/lib/rubocop/cop/lint/float_comparison.rb +33 -10
  182. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  183. data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
  184. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -2
  185. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -1
  186. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -2
  187. data/lib/rubocop/cop/lint/inherit_exception.rb +53 -7
  188. data/lib/rubocop/cop/lint/interpolation_check.rb +25 -6
  189. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  190. data/lib/rubocop/cop/lint/literal_as_condition.rb +137 -11
  191. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
  192. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +13 -19
  193. data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +185 -0
  194. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +44 -22
  195. data/lib/rubocop/cop/lint/missing_super.rb +31 -1
  196. data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -2
  197. data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
  198. data/lib/rubocop/cop/lint/name_typo.rb +270 -0
  199. data/lib/rubocop/cop/lint/nested_method_definition.rb +2 -2
  200. data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
  201. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +20 -0
  202. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +4 -2
  203. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +4 -4
  204. data/lib/rubocop/cop/lint/number_conversion.rb +19 -10
  205. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  206. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +11 -0
  207. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  208. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +7 -7
  209. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +15 -4
  210. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +20 -14
  211. data/lib/rubocop/cop/lint/raise_exception.rb +30 -11
  212. data/lib/rubocop/cop/lint/rand_one.rb +1 -1
  213. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +149 -39
  214. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +53 -19
  215. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +15 -4
  216. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  217. data/lib/rubocop/cop/lint/redundant_require_statement.rb +5 -25
  218. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +134 -12
  219. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +13 -4
  220. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +267 -0
  221. data/lib/rubocop/cop/lint/redundant_with_index.rb +5 -3
  222. data/lib/rubocop/cop/lint/redundant_with_object.rb +8 -0
  223. data/lib/rubocop/cop/lint/refinement_import_methods.rb +8 -1
  224. data/lib/rubocop/cop/lint/regexp_as_condition.rb +9 -1
  225. data/lib/rubocop/cop/lint/require_parentheses.rb +13 -4
  226. data/lib/rubocop/cop/lint/require_range_parentheses.rb +3 -2
  227. data/lib/rubocop/cop/lint/require_relative_self_path.rb +7 -5
  228. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  229. data/lib/rubocop/cop/lint/rescue_type.rb +2 -2
  230. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  231. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +28 -4
  232. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +9 -5
  233. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
  234. data/lib/rubocop/cop/lint/script_permission.rb +5 -1
  235. data/lib/rubocop/cop/lint/self_assignment.rb +63 -6
  236. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -1
  237. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  238. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  239. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +27 -1
  240. data/lib/rubocop/cop/lint/shared_mutable_default.rb +14 -1
  241. data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
  242. data/lib/rubocop/cop/lint/super_argument_mismatch.rb +179 -0
  243. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  244. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +122 -0
  245. data/lib/rubocop/cop/lint/symbol_conversion.rb +21 -4
  246. data/lib/rubocop/cop/lint/syntax.rb +25 -1
  247. data/lib/rubocop/cop/lint/to_enum_arguments.rb +73 -5
  248. data/lib/rubocop/cop/lint/to_json.rb +20 -17
  249. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  250. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +5 -1
  251. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +36 -10
  252. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +2 -0
  253. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -1
  254. data/lib/rubocop/cop/lint/unreachable_code.rb +16 -9
  255. data/lib/rubocop/cop/lint/unreachable_loop.rb +5 -5
  256. data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
  257. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  258. data/lib/rubocop/cop/lint/unused_private_method.rb +234 -0
  259. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
  260. data/lib/rubocop/cop/lint/useless_access_modifier.rb +31 -6
  261. data/lib/rubocop/cop/lint/useless_assignment.rb +56 -27
  262. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +107 -0
  263. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +92 -0
  264. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  265. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +11 -10
  266. data/lib/rubocop/cop/lint/useless_or.rb +111 -0
  267. data/lib/rubocop/cop/lint/useless_rescue.rb +2 -3
  268. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +13 -7
  269. data/lib/rubocop/cop/lint/useless_setter_call.rb +4 -1
  270. data/lib/rubocop/cop/lint/useless_times.rb +22 -1
  271. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +201 -0
  272. data/lib/rubocop/cop/lint/void.rb +60 -21
  273. data/lib/rubocop/cop/lint.rb +179 -0
  274. data/lib/rubocop/cop/message_annotator.rb +7 -3
  275. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  276. data/lib/rubocop/cop/metrics/block_length.rb +2 -1
  277. data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
  278. data/lib/rubocop/cop/metrics/collection_literal_length.rb +1 -1
  279. data/lib/rubocop/cop/metrics/method_length.rb +3 -2
  280. data/lib/rubocop/cop/metrics/perceived_complexity.rb +37 -7
  281. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  282. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
  283. data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
  284. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  285. data/lib/rubocop/cop/metrics.rb +31 -0
  286. data/lib/rubocop/cop/migration/department_name.rb +11 -5
  287. data/lib/rubocop/cop/migration.rb +13 -0
  288. data/lib/rubocop/cop/mixin/alignment.rb +3 -3
  289. data/lib/rubocop/cop/mixin/allowed_methods.rb +5 -5
  290. data/lib/rubocop/cop/mixin/allowed_pattern.rb +9 -5
  291. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  292. data/lib/rubocop/cop/mixin/check_line_breakable.rb +27 -9
  293. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +5 -7
  294. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  295. data/lib/rubocop/cop/mixin/comments_help.rb +2 -3
  296. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -2
  297. data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
  298. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  299. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  300. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
  301. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +13 -5
  302. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  303. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +20 -0
  304. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -2
  305. data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
  306. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +44 -16
  307. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +29 -26
  308. data/lib/rubocop/cop/mixin/hash_subset.rb +28 -6
  309. data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
  310. data/lib/rubocop/cop/mixin/hash_transform_method.rb +32 -78
  311. data/lib/rubocop/cop/mixin/indexed_method_arity.rb +94 -0
  312. data/lib/rubocop/cop/mixin/line_length_help.rb +52 -11
  313. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  314. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -1
  315. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  316. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  317. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  318. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +62 -6
  319. data/lib/rubocop/cop/mixin/project_index_help.rb +188 -0
  320. data/lib/rubocop/cop/mixin/range_help.rb +16 -5
  321. data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +171 -0
  322. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  323. data/lib/rubocop/cop/mixin/statement_modifier.rb +47 -11
  324. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  325. data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
  326. data/lib/rubocop/cop/mixin/trailing_comma.rb +23 -6
  327. data/lib/rubocop/cop/mixin.rb +91 -0
  328. data/lib/rubocop/cop/naming/accessor_method_name.rb +24 -0
  329. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +17 -1
  330. data/lib/rubocop/cop/naming/block_forwarding.rb +7 -4
  331. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  332. data/lib/rubocop/cop/naming/file_name.rb +6 -5
  333. data/lib/rubocop/cop/naming/inclusive_language.rb +8 -2
  334. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +13 -6
  335. data/lib/rubocop/cop/naming/method_name.rb +190 -15
  336. data/lib/rubocop/cop/naming/predicate_method.rb +330 -0
  337. data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +80 -8
  338. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -6
  339. data/lib/rubocop/cop/naming/variable_name.rb +51 -6
  340. data/lib/rubocop/cop/naming/variable_number.rb +3 -1
  341. data/lib/rubocop/cop/naming.rb +31 -0
  342. data/lib/rubocop/cop/offense.rb +52 -9
  343. data/lib/rubocop/cop/registry.rb +233 -64
  344. data/lib/rubocop/cop/security/eval.rb +17 -3
  345. data/lib/rubocop/cop/security/io_methods.rb +2 -2
  346. data/lib/rubocop/cop/security/json_load.rb +33 -11
  347. data/lib/rubocop/cop/security/marshal_load.rb +1 -1
  348. data/lib/rubocop/cop/security/open.rb +1 -0
  349. data/lib/rubocop/cop/security.rb +19 -0
  350. data/lib/rubocop/cop/severity.rb +12 -0
  351. data/lib/rubocop/cop/style/access_modifier_declarations.rb +47 -13
  352. data/lib/rubocop/cop/style/accessor_grouping.rb +47 -10
  353. data/lib/rubocop/cop/style/alias.rb +15 -3
  354. data/lib/rubocop/cop/style/and_or.rb +2 -1
  355. data/lib/rubocop/cop/style/arguments_forwarding.rb +49 -37
  356. data/lib/rubocop/cop/style/array_first_last.rb +13 -3
  357. data/lib/rubocop/cop/style/array_intersect.rb +136 -38
  358. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +50 -0
  359. data/lib/rubocop/cop/style/array_join.rb +4 -2
  360. data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
  361. data/lib/rubocop/cop/style/attr.rb +5 -2
  362. data/lib/rubocop/cop/style/bare_percent_literals.rb +4 -3
  363. data/lib/rubocop/cop/style/begin_block.rb +3 -1
  364. data/lib/rubocop/cop/style/bitwise_predicate.rb +7 -1
  365. data/lib/rubocop/cop/style/block_delimiters.rb +43 -38
  366. data/lib/rubocop/cop/style/case_equality.rb +29 -15
  367. data/lib/rubocop/cop/style/case_like_if.rb +6 -8
  368. data/lib/rubocop/cop/style/character_literal.rb +2 -2
  369. data/lib/rubocop/cop/style/class_and_module_children.rb +135 -21
  370. data/lib/rubocop/cop/style/class_equality_comparison.rb +22 -14
  371. data/lib/rubocop/cop/style/class_methods_definitions.rb +11 -5
  372. data/lib/rubocop/cop/style/collection_compact.rb +37 -17
  373. data/lib/rubocop/cop/style/collection_methods.rb +1 -0
  374. data/lib/rubocop/cop/style/collection_querying.rb +167 -0
  375. data/lib/rubocop/cop/style/colon_method_call.rb +16 -7
  376. data/lib/rubocop/cop/style/combinable_loops.rb +7 -2
  377. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  378. data/lib/rubocop/cop/style/commented_keyword.rb +12 -5
  379. data/lib/rubocop/cop/style/comparable_between.rb +78 -0
  380. data/lib/rubocop/cop/style/comparable_clamp.rb +12 -1
  381. data/lib/rubocop/cop/style/concat_array_literals.rb +8 -3
  382. data/lib/rubocop/cop/style/conditional_assignment.rb +54 -24
  383. data/lib/rubocop/cop/style/constant_visibility.rb +23 -12
  384. data/lib/rubocop/cop/style/copyright.rb +27 -12
  385. data/lib/rubocop/cop/style/data_inheritance.rb +25 -0
  386. data/lib/rubocop/cop/style/date_time.rb +4 -4
  387. data/lib/rubocop/cop/style/def_with_parentheses.rb +22 -5
  388. data/lib/rubocop/cop/style/dig_chain.rb +6 -1
  389. data/lib/rubocop/cop/style/dir_empty.rb +4 -0
  390. data/lib/rubocop/cop/style/directive_scope.rb +304 -0
  391. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +122 -14
  392. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
  393. data/lib/rubocop/cop/style/documentation.rb +53 -6
  394. data/lib/rubocop/cop/style/documentation_method.rb +8 -12
  395. data/lib/rubocop/cop/style/double_negation.rb +3 -3
  396. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  397. data/lib/rubocop/cop/style/each_with_object.rb +4 -3
  398. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  399. data/lib/rubocop/cop/style/empty_case_condition.rb +13 -4
  400. data/lib/rubocop/cop/style/empty_class_definition.rb +126 -0
  401. data/lib/rubocop/cop/style/empty_heredoc.rb +4 -0
  402. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  403. data/lib/rubocop/cop/style/empty_literal.rb +11 -2
  404. data/lib/rubocop/cop/style/empty_method.rb +12 -8
  405. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +110 -0
  406. data/lib/rubocop/cop/style/encoding.rb +7 -1
  407. data/lib/rubocop/cop/style/end_block.rb +3 -1
  408. data/lib/rubocop/cop/style/endless_method.rb +191 -19
  409. data/lib/rubocop/cop/style/env_home.rb +4 -0
  410. data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
  411. data/lib/rubocop/cop/style/even_odd.rb +11 -1
  412. data/lib/rubocop/cop/style/exact_regexp_match.rb +8 -1
  413. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  414. data/lib/rubocop/cop/style/explicit_block_argument.rb +16 -3
  415. data/lib/rubocop/cop/style/exponential_notation.rb +5 -4
  416. data/lib/rubocop/cop/style/fetch_env_var.rb +33 -7
  417. data/lib/rubocop/cop/style/file_null.rb +6 -4
  418. data/lib/rubocop/cop/style/file_open.rb +84 -0
  419. data/lib/rubocop/cop/style/file_write.rb +21 -16
  420. data/lib/rubocop/cop/style/float_division.rb +25 -17
  421. data/lib/rubocop/cop/style/for.rb +9 -0
  422. data/lib/rubocop/cop/style/format_string.rb +17 -4
  423. data/lib/rubocop/cop/style/format_string_token.rb +86 -16
  424. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  425. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  426. data/lib/rubocop/cop/style/global_vars.rb +5 -2
  427. data/lib/rubocop/cop/style/guard_clause.rb +32 -23
  428. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +27 -9
  429. data/lib/rubocop/cop/style/hash_conversion.rb +28 -12
  430. data/lib/rubocop/cop/style/hash_each_methods.rb +4 -4
  431. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  432. data/lib/rubocop/cop/style/hash_lookup_method.rb +105 -0
  433. data/lib/rubocop/cop/style/hash_slice.rb +16 -0
  434. data/lib/rubocop/cop/style/hash_syntax.rb +7 -3
  435. data/lib/rubocop/cop/style/hash_transform_keys.rb +19 -9
  436. data/lib/rubocop/cop/style/hash_transform_values.rb +19 -9
  437. data/lib/rubocop/cop/style/identical_conditional_branches.rb +18 -9
  438. data/lib/rubocop/cop/style/if_inside_else.rb +25 -20
  439. data/lib/rubocop/cop/style/if_unless_modifier.rb +71 -46
  440. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +15 -19
  441. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -2
  442. data/lib/rubocop/cop/style/if_with_semicolon.rb +16 -6
  443. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  444. data/lib/rubocop/cop/style/inline_comment.rb +5 -2
  445. data/lib/rubocop/cop/style/inverse_methods.rb +10 -6
  446. data/lib/rubocop/cop/style/invertible_unless_condition.rb +27 -7
  447. data/lib/rubocop/cop/style/ip_addresses.rb +3 -4
  448. data/lib/rubocop/cop/style/it_assignment.rb +69 -12
  449. data/lib/rubocop/cop/style/it_block_parameter.rb +121 -0
  450. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +4 -0
  451. data/lib/rubocop/cop/style/keyword_parameters_order.rb +20 -10
  452. data/lib/rubocop/cop/style/lambda.rb +12 -1
  453. data/lib/rubocop/cop/style/lambda_call.rb +26 -10
  454. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  455. data/lib/rubocop/cop/style/magic_comment_format.rb +4 -4
  456. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +11 -0
  457. data/lib/rubocop/cop/style/map_into_array.rb +5 -2
  458. data/lib/rubocop/cop/style/map_join.rb +123 -0
  459. data/lib/rubocop/cop/style/map_to_hash.rb +13 -5
  460. data/lib/rubocop/cop/style/map_to_set.rb +1 -3
  461. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +31 -15
  462. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
  463. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +34 -5
  464. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +12 -7
  465. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -1
  466. data/lib/rubocop/cop/style/method_def_parentheses.rb +7 -5
  467. data/lib/rubocop/cop/style/min_max_comparison.rb +17 -6
  468. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +40 -7
  469. data/lib/rubocop/cop/style/mixin_usage.rb +1 -1
  470. data/lib/rubocop/cop/style/module_function.rb +4 -2
  471. data/lib/rubocop/cop/style/module_member_existence_check.rb +110 -0
  472. data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -1
  473. data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
  474. data/lib/rubocop/cop/style/multiline_if_then.rb +10 -4
  475. data/lib/rubocop/cop/style/multiline_memoization.rb +7 -1
  476. data/lib/rubocop/cop/style/multiline_method_signature.rb +14 -18
  477. data/lib/rubocop/cop/style/multiple_comparison.rb +33 -22
  478. data/lib/rubocop/cop/style/mutable_constant.rb +111 -12
  479. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -2
  480. data/lib/rubocop/cop/style/negative_array_index.rb +220 -0
  481. data/lib/rubocop/cop/style/nested_modifier.rb +9 -4
  482. data/lib/rubocop/cop/style/next.rb +44 -0
  483. data/lib/rubocop/cop/style/nil_comparison.rb +41 -13
  484. data/lib/rubocop/cop/style/nil_lambda.rb +9 -1
  485. data/lib/rubocop/cop/style/non_nil_check.rb +21 -11
  486. data/lib/rubocop/cop/style/not.rb +5 -1
  487. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
  488. data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
  489. data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
  490. data/lib/rubocop/cop/style/object_then.rb +1 -0
  491. data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
  492. data/lib/rubocop/cop/style/one_line_conditional.rb +22 -13
  493. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  494. data/lib/rubocop/cop/style/operator_method_call.rb +10 -2
  495. data/lib/rubocop/cop/style/option_hash.rb +1 -1
  496. data/lib/rubocop/cop/style/optional_arguments.rb +1 -0
  497. data/lib/rubocop/cop/style/parallel_assignment.rb +58 -27
  498. data/lib/rubocop/cop/style/parentheses_around_condition.rb +6 -1
  499. data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
  500. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +4 -0
  501. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  502. data/lib/rubocop/cop/style/perl_backrefs.rb +5 -3
  503. data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
  504. data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
  505. data/lib/rubocop/cop/style/proc.rb +4 -2
  506. data/lib/rubocop/cop/style/raise_args.rb +9 -9
  507. data/lib/rubocop/cop/style/reduce_to_hash.rb +200 -0
  508. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  509. data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
  510. data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
  511. data/lib/rubocop/cop/style/redundant_assignment.rb +12 -2
  512. data/lib/rubocop/cop/style/redundant_begin.rb +38 -3
  513. data/lib/rubocop/cop/style/redundant_condition.rb +63 -5
  514. data/lib/rubocop/cop/style/redundant_constant_base.rb +42 -6
  515. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +26 -4
  516. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +11 -3
  517. data/lib/rubocop/cop/style/redundant_each.rb +4 -5
  518. data/lib/rubocop/cop/style/redundant_exception.rb +7 -1
  519. data/lib/rubocop/cop/style/redundant_fetch_block.rb +2 -10
  520. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +9 -0
  521. data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
  522. data/lib/rubocop/cop/style/redundant_format.rb +319 -0
  523. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
  524. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +6 -1
  525. data/lib/rubocop/cop/style/redundant_interpolation.rb +12 -3
  526. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
  527. data/lib/rubocop/cop/style/redundant_line_continuation.rb +83 -119
  528. data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
  529. data/lib/rubocop/cop/style/redundant_parentheses.rb +164 -82
  530. data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
  531. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +8 -0
  532. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
  533. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +8 -8
  534. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +12 -0
  535. data/lib/rubocop/cop/style/redundant_return.rb +4 -3
  536. data/lib/rubocop/cop/style/redundant_self.rb +20 -7
  537. data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -3
  538. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
  539. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  540. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  541. data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -2
  542. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +133 -0
  543. data/lib/rubocop/cop/style/regexp_literal.rb +32 -3
  544. data/lib/rubocop/cop/style/rescue_modifier.rb +5 -3
  545. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  546. data/lib/rubocop/cop/style/reverse_find.rb +51 -0
  547. data/lib/rubocop/cop/style/safe_navigation.rb +76 -20
  548. data/lib/rubocop/cop/style/sample.rb +11 -6
  549. data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
  550. data/lib/rubocop/cop/style/select_by_range.rb +197 -0
  551. data/lib/rubocop/cop/style/select_by_regexp.rb +54 -22
  552. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  553. data/lib/rubocop/cop/style/semicolon.rb +45 -14
  554. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  555. data/lib/rubocop/cop/style/single_line_do_end_block.rb +22 -8
  556. data/lib/rubocop/cop/style/single_line_methods.rb +13 -8
  557. data/lib/rubocop/cop/style/sole_nested_conditional.rb +96 -104
  558. data/lib/rubocop/cop/style/special_global_vars.rb +7 -2
  559. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +3 -1
  560. data/lib/rubocop/cop/style/static_class.rb +21 -0
  561. data/lib/rubocop/cop/style/string_concatenation.rb +31 -15
  562. data/lib/rubocop/cop/style/string_hash_keys.rb +1 -0
  563. data/lib/rubocop/cop/style/struct_inheritance.rb +38 -2
  564. data/lib/rubocop/cop/style/super_arguments.rb +4 -6
  565. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  566. data/lib/rubocop/cop/style/symbol_proc.rb +11 -9
  567. data/lib/rubocop/cop/style/tally_method.rb +181 -0
  568. data/lib/rubocop/cop/style/ternary_parentheses.rb +11 -0
  569. data/lib/rubocop/cop/style/time_now.rb +41 -0
  570. data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -2
  571. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +52 -1
  572. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  573. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +2 -2
  574. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  575. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
  576. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +18 -19
  577. data/lib/rubocop/cop/style/trivial_accessors.rb +2 -2
  578. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  579. data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
  580. data/lib/rubocop/cop/style/while_until_do.rb +7 -0
  581. data/lib/rubocop/cop/style/while_until_modifier.rb +16 -1
  582. data/lib/rubocop/cop/style/word_array.rb +1 -0
  583. data/lib/rubocop/cop/style/yoda_condition.rb +2 -3
  584. data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
  585. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -3
  586. data/lib/rubocop/cop/style.rb +311 -0
  587. data/lib/rubocop/cop/team.rb +163 -45
  588. data/lib/rubocop/cop/util.rb +7 -10
  589. data/lib/rubocop/cop/utils/format_string.rb +20 -5
  590. data/lib/rubocop/cop/variable_force/assignment.rb +7 -3
  591. data/lib/rubocop/cop/variable_force/branch.rb +30 -6
  592. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  593. data/lib/rubocop/cop/variable_force/variable.rb +28 -10
  594. data/lib/rubocop/cop/variable_force.rb +26 -9
  595. data/lib/rubocop/cops_documentation_generator.rb +49 -15
  596. data/lib/rubocop/directive_comment.rb +147 -5
  597. data/lib/rubocop/ext/regexp_node.rb +0 -1
  598. data/lib/rubocop/feature_loader.rb +0 -6
  599. data/lib/rubocop/file_patterns.rb +9 -1
  600. data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
  601. data/lib/rubocop/formatter/disabled_config_formatter.rb +57 -14
  602. data/lib/rubocop/formatter/emacs_style_formatter.rb +3 -1
  603. data/lib/rubocop/formatter/formatter_set.rb +3 -2
  604. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  605. data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
  606. data/lib/rubocop/formatter/html_formatter.rb +3 -5
  607. data/lib/rubocop/formatter/json_formatter.rb +11 -6
  608. data/lib/rubocop/formatter/junit_formatter.rb +27 -10
  609. data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
  610. data/lib/rubocop/formatter/offense_count_formatter.rb +2 -3
  611. data/lib/rubocop/formatter/pacman_formatter.rb +2 -1
  612. data/lib/rubocop/formatter/sarif_formatter.rb +181 -0
  613. data/lib/rubocop/formatter/simple_text_formatter.rb +4 -5
  614. data/lib/rubocop/formatter/tap_formatter.rb +8 -3
  615. data/lib/rubocop/formatter/worst_offenders_formatter.rb +2 -3
  616. data/lib/rubocop/formatter.rb +23 -21
  617. data/lib/rubocop/lockfile.rb +18 -0
  618. data/lib/rubocop/lsp/diagnostic.rb +22 -41
  619. data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
  620. data/lib/rubocop/lsp/routes.rb +136 -33
  621. data/lib/rubocop/lsp/runtime.rb +23 -8
  622. data/lib/rubocop/lsp/server.rb +4 -2
  623. data/lib/rubocop/lsp/stdin_runner.rb +31 -18
  624. data/lib/rubocop/magic_comment.rb +55 -0
  625. data/lib/rubocop/mcp/server.rb +199 -0
  626. data/lib/rubocop/options.rb +129 -21
  627. data/lib/rubocop/path_util.rb +20 -5
  628. data/lib/rubocop/pending_cops_reporter.rb +51 -0
  629. data/lib/rubocop/plugin/configuration_integrator.rb +146 -0
  630. data/lib/rubocop/plugin/load_error.rb +26 -0
  631. data/lib/rubocop/plugin/loader.rb +100 -0
  632. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  633. data/lib/rubocop/plugin.rb +46 -0
  634. data/lib/rubocop/project_index_loader.rb +82 -0
  635. data/lib/rubocop/rake_task.rb +6 -4
  636. data/lib/rubocop/remote_config.rb +14 -12
  637. data/lib/rubocop/result_cache.rb +90 -52
  638. data/lib/rubocop/rspec/cop_helper.rb +21 -1
  639. data/lib/rubocop/rspec/expect_offense.rb +11 -7
  640. data/lib/rubocop/rspec/shared_contexts.rb +85 -3
  641. data/lib/rubocop/rspec/support.rb +4 -0
  642. data/lib/rubocop/runner.rb +294 -100
  643. data/lib/rubocop/server/cache.rb +67 -48
  644. data/lib/rubocop/server/cli.rb +2 -4
  645. data/lib/rubocop/server/client_command/base.rb +10 -0
  646. data/lib/rubocop/server/client_command/exec.rb +2 -1
  647. data/lib/rubocop/server/client_command/start.rb +11 -1
  648. data/lib/rubocop/server/core.rb +8 -0
  649. data/lib/rubocop/server.rb +14 -0
  650. data/lib/rubocop/target_finder.rb +25 -11
  651. data/lib/rubocop/target_ruby.rb +31 -14
  652. data/lib/rubocop/todo_audit.rb +111 -0
  653. data/lib/rubocop/unified_diff.rb +257 -0
  654. data/lib/rubocop/version.rb +48 -10
  655. data/lib/rubocop.rb +30 -682
  656. data/lib/ruby_lsp/rubocop/addon.rb +28 -17
  657. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +99 -0
  658. metadata +116 -19
  659. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
  660. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  661. data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +0 -50
@@ -3,9 +3,10 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for uses of if/then/else/end constructs on a single line.
7
- # `AlwaysCorrectToMultiline` config option can be set to true to autocorrect all offenses to
8
- # multi-line constructs. When `AlwaysCorrectToMultiline` is false (default case) the
6
+ # Checks for uses of `if/then/else/end` constructs on a single line.
7
+ # A ternary operator (`?:`) or multi-line `if` is more readable.
8
+ # `AlwaysCorrectToMultiline` config option can be set to `true` to autocorrect all offenses to
9
+ # multi-line constructs. When `AlwaysCorrectToMultiline` is `false` (default case) the
9
10
  # autocorrect will first try converting them to ternary operators.
10
11
  #
11
12
  # @example
@@ -55,19 +56,21 @@ module RuboCop
55
56
  include OnNormalIfUnless
56
57
  extend AutoCorrector
57
58
 
58
- MSG = 'Favor the ternary operator (`?:`) or multi-line constructs ' \
59
- 'over single-line `%<keyword>s/then/else/end` constructs.'
59
+ MSG_SUFFIX = 'over single-line `%<keyword>s/then/else/end` constructs.'
60
+ MSG_TERNARY = "Favor the ternary operator (`?:`) #{MSG_SUFFIX}"
61
+ MSG_MULTILINE = "Favor multi-line `%<keyword>s` #{MSG_SUFFIX}"
60
62
 
61
63
  def on_normal_if_unless(node)
62
64
  return unless node.single_line?
63
65
  return unless node.else_branch
64
66
  return if node.elsif? || node.if_branch&.begin_type?
65
67
 
66
- message = message(node)
67
- add_offense(node, message: message) do |corrector|
68
+ multiline = multiline?(node)
69
+
70
+ add_offense(node, message: message(node, multiline)) do |corrector|
68
71
  next if part_of_ignored_node?(node)
69
72
 
70
- autocorrect(corrector, node)
73
+ autocorrect(corrector, node, multiline)
71
74
 
72
75
  ignore_node(node)
73
76
  end
@@ -75,12 +78,18 @@ module RuboCop
75
78
 
76
79
  private
77
80
 
78
- def message(node)
79
- format(MSG, keyword: node.keyword)
81
+ def multiline?(node)
82
+ always_multiline? || cannot_replace_to_ternary?(node)
83
+ end
84
+
85
+ def message(node, multiline)
86
+ template = multiline ? MSG_MULTILINE : MSG_TERNARY
87
+
88
+ format(template, keyword: node.keyword)
80
89
  end
81
90
 
82
- def autocorrect(corrector, node)
83
- if always_multiline? || cannot_replace_to_ternary?(node)
91
+ def autocorrect(corrector, node, multiline)
92
+ if multiline
84
93
  IfThenCorrector.new(node, indentation: configured_indentation_width).call(corrector)
85
94
  else
86
95
  corrector.replace(node, ternary_correction(node))
@@ -108,7 +117,7 @@ module RuboCop
108
117
  end
109
118
 
110
119
  def ternary_replacement(node)
111
- condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring
120
+ condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring -- takes all three branches in one step
112
121
 
113
122
  "#{expr_replacement(condition)} ? " \
114
123
  "#{expr_replacement(if_branch)} : " \
@@ -61,7 +61,7 @@ module RuboCop
61
61
  def custom_class_or_module_definition?(node)
62
62
  parent = node.parent
63
63
 
64
- parent.type?(:class, :module) && node.left_siblings.empty?
64
+ parent&.type?(:class, :module) && node.left_siblings.empty?
65
65
  end
66
66
  end
67
67
  end
@@ -26,9 +26,10 @@ module RuboCop
26
26
  splat kwsplat forwarded_args forwarded_restarg forwarded_kwrestarg block_pass
27
27
  ].freeze
28
28
 
29
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
29
+ # rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
30
30
  def on_send(node)
31
31
  return unless (dot = node.loc.dot)
32
+ return if unary_method_no_operator?(node)
32
33
  return if node.receiver.const_type? || !node.arguments.one?
33
34
 
34
35
  return unless (rhs = node.first_argument)
@@ -43,10 +44,17 @@ module RuboCop
43
44
  corrector.insert_after(selector, ' ') if insert_space_after?(node)
44
45
  end
45
46
  end
46
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
47
47
 
48
48
  private
49
49
 
50
+ # `foo.~@` and `foo.!@` call the method `~` and `!` respectively. While those
51
+ # are operator methods, we don't want to actually consider them as such.
52
+ def unary_method_no_operator?(node)
53
+ return false unless node.nonmutating_unary_operator_method?
54
+
55
+ node.method_name.to_s != node.selector.source
56
+ end
57
+
50
58
  # Checks for an acceptable case of `foo.+(bar).baz`.
51
59
  def method_call_with_parenthesized_arg?(argument)
52
60
  return false unless argument.parent.parent&.send_type?
@@ -46,7 +46,7 @@ module RuboCop
46
46
  end
47
47
 
48
48
  def super_used?(node)
49
- node.parent.each_node(:zsuper).any?
49
+ node.parent.each_node(:zsuper, :super).any?
50
50
  end
51
51
  end
52
52
  end
@@ -27,6 +27,7 @@ module RuboCop
27
27
  def on_def(node)
28
28
  each_misplaced_optional_arg(node.arguments) { |argument| add_offense(argument) }
29
29
  end
30
+ alias on_defs on_def
30
31
 
31
32
  private
32
33
 
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'tsort'
4
-
5
3
  module RuboCop
6
4
  module Cop
7
5
  module Style
8
6
  # Checks for simple usages of parallel assignment.
7
+ # Parallel assignment is less readable than individual
8
+ # assignments and makes it harder to follow what each
9
+ # variable is being set to.
10
+ #
9
11
  # This will only complain when the number of variables
10
12
  # being assigned matched the number of assigning variables.
11
13
  #
@@ -16,7 +18,7 @@ module RuboCop
16
18
  #
17
19
  # # good
18
20
  # one, two = *foo
19
- # a, b = foo()
21
+ # a, b = foo
20
22
  # a, b = b, a
21
23
  #
22
24
  # a = 1
@@ -29,18 +31,21 @@ module RuboCop
29
31
  MSG = 'Do not use parallel assignment.'
30
32
 
31
33
  def on_masgn(node) # rubocop:disable Metrics/AbcSize
34
+ return if part_of_ignored_node?(node)
35
+
32
36
  rhs = node.rhs
33
37
  rhs = rhs.body if rhs.rescue_type?
34
38
  rhs_elements = Array(rhs).compact # edge case for one constant
35
39
 
36
40
  return if allowed_lhs?(node.assignments) || allowed_rhs?(rhs) ||
37
- allowed_masign?(node.assignments, rhs_elements)
41
+ allowed_masign?(node.assignments, rhs_elements) || contains_heredoc?(rhs)
38
42
 
39
43
  range = node.source_range.begin.join(rhs.source_range.end)
40
44
 
41
45
  add_offense(range) do |corrector|
42
46
  autocorrect(corrector, node, rhs)
43
47
  end
48
+ ignore_node(node)
44
49
  end
45
50
 
46
51
  private
@@ -72,6 +77,13 @@ module RuboCop
72
77
  !node.array_type? || elements.any?(&:splat_type?)
73
78
  end
74
79
 
80
+ # Autocorrection splits the assignment into single assignments on
81
+ # consecutive lines, which would put following assignments into the
82
+ # heredoc body unless the heredoc bodies were moved along.
83
+ def contains_heredoc?(node)
84
+ node.each_descendant(:any_str).any?(&:heredoc?)
85
+ end
86
+
75
87
  def assignment_corrector(node, rhs, order)
76
88
  if node.parent&.rescue_type?
77
89
  _assignment, modifier = *node.parent
@@ -91,15 +103,9 @@ module RuboCop
91
103
  def find_valid_order(left_elements, right_elements)
92
104
  # arrange left_elements in an order such that no corresponding right
93
105
  # element refers to a left element earlier in the sequence
94
- # this can be done using an algorithm called a "topological sort"
95
- # fortunately for us, Ruby's stdlib contains an implementation
96
106
  assignments = left_elements.zip(right_elements)
97
107
 
98
- begin
99
- AssignmentSorter.new(assignments).tsort
100
- rescue TSort::Cyclic
101
- nil
102
- end
108
+ AssignmentSorter.new(assignments).tsort
103
109
  end
104
110
 
105
111
  # Converts (send nil :something) nodes to (send (:self) :something).
@@ -114,10 +120,9 @@ module RuboCop
114
120
  # @!method implicit_self_getter?(node)
115
121
  def_node_matcher :implicit_self_getter?, '(send nil? $_)'
116
122
 
117
- # Helper class necessitated by silly design of TSort prior to Ruby 2.1
118
- # Newer versions have a better API, but that doesn't help us
123
+ # Topologically sorts the assignments with Kahn's algorithm.
124
+ # https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm
119
125
  class AssignmentSorter
120
- include TSort
121
126
  extend RuboCop::NodePattern::Macros
122
127
 
123
128
  # @!method var_name(node)
@@ -133,21 +138,39 @@ module RuboCop
133
138
  @assignments = assignments
134
139
  end
135
140
 
136
- def tsort_each_node(...)
137
- @assignments.each(...)
141
+ def tsort
142
+ dependencies = @assignments.to_h do |assignment|
143
+ [assignment, dependencies_for_assignment(assignment)]
144
+ end
145
+ result = []
146
+
147
+ while (matched_node, = dependencies.find { |_node, edges| edges.empty? })
148
+ dependencies.delete(matched_node)
149
+ result.push(matched_node)
150
+
151
+ dependencies.each do |node, edges|
152
+ dependencies[node].delete(matched_node) if edges.include?(matched_node)
153
+ end
154
+ end
155
+ # Cyclic dependency
156
+ return nil if dependencies.any?
157
+
158
+ result
138
159
  end
139
160
 
140
- def tsort_each_child(assignment)
141
- # yield all the assignments which must come after `assignment`
142
- # (due to dependencies on the previous value of the assigned var)
161
+ # Returns all the assignments which must come after `assignment`
162
+ # (due to dependencies on the previous value of the assigned var)
163
+ def dependencies_for_assignment(assignment)
143
164
  my_lhs, _my_rhs = *assignment
144
165
 
145
- @assignments.each do |other|
146
- _other_lhs, other_rhs = *other
166
+ @assignments.filter_map do |other|
167
+ # Exclude self, there are no dependencies in cases such as `a, b = a, b`.
168
+ next if other == assignment
147
169
 
170
+ _other_lhs, other_rhs = *other
148
171
  next unless dependency?(my_lhs, other_rhs)
149
172
 
150
- yield other
173
+ other
151
174
  end
152
175
  end
153
176
 
@@ -161,9 +184,8 @@ module RuboCop
161
184
  def accesses?(rhs, lhs)
162
185
  if lhs.method?(:[]=)
163
186
  # FIXME: Workaround `rubocop:disable` comment for JRuby.
164
- # rubocop:disable Performance/RedundantEqualityComparisonBlock
187
+ # rubocop:disable-next Performance/RedundantEqualityComparisonBlock -- a JRuby workaround, as the comment above says
165
188
  matching_calls(rhs, lhs.receiver, :[]).any? { |args| args == lhs.arguments }
166
- # rubocop:enable Performance/RedundantEqualityComparisonBlock
167
189
  else
168
190
  access_method = lhs.method_name.to_s.chop.to_sym
169
191
  matching_calls(rhs, lhs.receiver, access_method).any?
@@ -210,14 +232,23 @@ module RuboCop
210
232
  def source(node, loc)
211
233
  # __FILE__ is treated as a StrNode but has no begin
212
234
  if node.str_type? && loc.respond_to?(:begin) && loc.begin.nil?
213
- "'#{node.source}'"
214
- elsif node.sym_type? && loc.begin.nil?
215
- ":#{node.source}"
235
+ # `%w` elements have no per-element delimiter, so the value must be
236
+ # quoted and escaped to stay valid (e.g. `%w(it's)` -> `'it\'s'`).
237
+ quote(node.value)
238
+ elsif node.sym_type? && !node.loc?(:begin)
239
+ # `%i` elements have no per-element delimiter, so a symbol that needs
240
+ # quoting must be emitted as `:"..."` (e.g. `%i(foo-bar)` -> `:"foo-bar"`),
241
+ # otherwise `:foo-bar` would parse as `:foo.-(bar)`.
242
+ node.value.inspect
216
243
  else
217
244
  node.source
218
245
  end
219
246
  end
220
247
 
248
+ def quote(string)
249
+ "'#{string.gsub(/[\\']/) { |char| "\\#{char}" }}'"
250
+ end
251
+
221
252
  def extract_sources(node)
222
253
  node.children.map(&:source)
223
254
  end
@@ -123,10 +123,15 @@ module RuboCop
123
123
 
124
124
  def parens_allowed?(node)
125
125
  parens_required?(node) ||
126
- (safe_assignment?(node) && safe_assignment_allowed?) ||
126
+ (safe_assignment?(node) && safe_assignment_kept?) ||
127
127
  (node.multiline? && allow_multiline_conditions?)
128
128
  end
129
129
 
130
+ def safe_assignment_kept?
131
+ safe_assignment_allowed? ||
132
+ config.for_enabled_cop('Lint/AssignmentInCondition')['AllowSafeAssignment']
133
+ end
134
+
130
135
  def allow_multiline_conditions?
131
136
  cop_config['AllowInMultilineConditions']
132
137
  end
@@ -0,0 +1,270 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for consecutive calls to `select`/`filter`/`find_all` and `reject`
7
+ # on the same receiver with the same block body, where `partition` could be
8
+ # used instead. Also detects two `select` or two `reject` calls where one
9
+ # block negates the other with `!`. Using `partition` reduces two collection
10
+ # traversals to one.
11
+ #
12
+ # @safety
13
+ # This cop is unsafe because:
14
+ #
15
+ # * `Hash#select` and `Hash#reject` return hashes, but `Hash#partition`
16
+ # returns nested arrays.
17
+ # * When the receiver has side effects, calling it once (with `partition`)
18
+ # versus twice (with `select` + `reject`) may produce different results.
19
+ # * Custom classes may override `select`/`reject` without providing a
20
+ # compatible `partition` method.
21
+ #
22
+ # @example
23
+ # # bad
24
+ # positives = array.select { |x| x > 0 }
25
+ # negatives = array.reject { |x| x > 0 }
26
+ #
27
+ # # bad
28
+ # positives = array.filter { |x| x > 0 }
29
+ # negatives = array.reject { |x| x > 0 }
30
+ #
31
+ # # bad
32
+ # negatives = array.reject { |x| x > 0 }
33
+ # positives = array.select { |x| x > 0 }
34
+ #
35
+ # # bad
36
+ # positives = array.select(&:positive?)
37
+ # negatives = array.reject(&:positive?)
38
+ #
39
+ # # bad
40
+ # positives = array.select(&:positive?)
41
+ # negatives = array.reject { |x| x.positive? }
42
+ #
43
+ # # bad
44
+ # positives = array.select { |x| x.positive? }
45
+ # non_positives = array.select { |x| !x.positive? }
46
+ #
47
+ # # good
48
+ # positives, negatives = array.partition { |x| x > 0 }
49
+ #
50
+ # # good
51
+ # positives, non_positives = array.partition { |x| x.positive? }
52
+ #
53
+ # # good
54
+ # positives, negatives = array.partition(&:positive?)
55
+ #
56
+ class PartitionInsteadOfDoubleSelect < Base
57
+ include RangeHelp
58
+ extend AutoCorrector
59
+
60
+ MSG = 'Use `partition` instead of consecutive `%<first>s` and `%<second>s` calls.'
61
+
62
+ SELECT_METHODS = %i[select filter find_all].freeze
63
+ CANDIDATE_METHODS = (SELECT_METHODS + %i[reject]).to_set.freeze
64
+ RESTRICT_ON_SEND = (SELECT_METHODS + %i[reject]).freeze
65
+
66
+ # @!method symbol_proc_method?(node)
67
+ def_node_matcher :symbol_proc_method?, <<~PATTERN
68
+ (block _ (args (arg _name)) (send (lvar _name) $_method_name))
69
+ PATTERN
70
+
71
+ def on_block(node)
72
+ return unless CANDIDATE_METHODS.include?(node.method_name)
73
+
74
+ find_and_register_offense(node)
75
+ end
76
+ alias on_numblock on_block
77
+ alias on_itblock on_block
78
+
79
+ def on_send(node)
80
+ return unless node.last_argument&.block_pass_type?
81
+
82
+ find_and_register_offense(node)
83
+ end
84
+ alias on_csend on_send
85
+
86
+ private
87
+
88
+ def find_and_register_offense(node)
89
+ container = node_container(node)
90
+ return unless container
91
+
92
+ sibling_container = container.left_sibling
93
+ sibling = find_matching_candidate(node, sibling_container)
94
+ return unless sibling
95
+
96
+ register_offense(node, sibling, container, sibling_container)
97
+ end
98
+
99
+ def node_container(node)
100
+ parent = node.parent
101
+ if parent&.begin_type?
102
+ node
103
+ elsif parent&.assignment? && parent.parent&.begin_type?
104
+ parent
105
+ end
106
+ end
107
+
108
+ def find_matching_candidate(node, sibling_container)
109
+ return unless sibling_container
110
+
111
+ sibling = extract_candidate(sibling_container)
112
+ return unless sibling
113
+ return unless node.receiver == sibling.receiver
114
+ return unless matching_pair?(node, sibling)
115
+
116
+ sibling
117
+ end
118
+
119
+ def matching_pair?(node, sibling)
120
+ (complementary_pair?(node, sibling) && equivalent_predicate?(node, sibling)) ||
121
+ (node.method?(sibling.method_name) && negated_predicate?(node, sibling))
122
+ end
123
+
124
+ def extract_candidate(container)
125
+ extract_block(container) || extract_block_pass_send(container)
126
+ end
127
+
128
+ def extract_block(container)
129
+ if container.any_block_type?
130
+ container
131
+ elsif container.assignment?
132
+ rhs = container.children.last
133
+ rhs if rhs&.any_block_type?
134
+ end
135
+ end
136
+
137
+ def extract_block_pass_send(container)
138
+ node = container.assignment? ? container.children.last : container
139
+ return unless node&.type?(:call)
140
+ return unless node.last_argument&.block_pass_type?
141
+
142
+ node
143
+ end
144
+
145
+ def complementary_pair?(node1, node2)
146
+ m1 = node1.method_name
147
+ m2 = node2.method_name
148
+ (SELECT_METHODS.include?(m1) && m2 == :reject) ||
149
+ (m1 == :reject && SELECT_METHODS.include?(m2))
150
+ end
151
+
152
+ def equivalent_predicate?(node1, node2)
153
+ if node1.any_block_type? && node2.any_block_type?
154
+ same_block_contents?(node1, node2)
155
+ elsif node1.any_block_type?
156
+ block_matches_block_pass?(node1, node2)
157
+ elsif node2.any_block_type?
158
+ block_matches_block_pass?(node2, node1)
159
+ else
160
+ node1.last_argument == node2.last_argument
161
+ end
162
+ end
163
+
164
+ def same_block_contents?(block1, block2)
165
+ return false unless block1.type == block2.type
166
+
167
+ if block1.block_type?
168
+ block1.arguments == block2.arguments &&
169
+ block1.body == block2.body
170
+ else
171
+ block1.body == block2.body
172
+ end
173
+ end
174
+
175
+ def block_matches_block_pass?(block_node, send_node)
176
+ method_name = symbol_proc_method?(block_node)
177
+ return false unless method_name
178
+
179
+ sym_node = send_node.last_argument.children.first
180
+ sym_node.sym_type? && sym_node.children.first == method_name
181
+ end
182
+
183
+ def negated_predicate?(node1, node2)
184
+ return false unless node1.any_block_type? && node2.any_block_type?
185
+ return false unless node1.type == node2.type
186
+ return false if node1.block_type? && node1.arguments != node2.arguments
187
+
188
+ negated_body?(node1.body, node2.body) || negated_body?(node2.body, node1.body)
189
+ end
190
+
191
+ def negated_body?(body1, body2)
192
+ body1&.send_type? && body1.method?(:!) && body1.receiver == body2
193
+ end
194
+
195
+ def register_offense(node, sibling, container, sibling_container)
196
+ message = format(MSG, first: sibling.method_name, second: node.method_name)
197
+
198
+ add_offense(container, message: message) do |corrector|
199
+ next unless both_lvasgn?(container, sibling_container)
200
+
201
+ autocorrect(corrector, node, sibling, container, sibling_container)
202
+ end
203
+ end
204
+
205
+ def both_lvasgn?(container, sibling_container)
206
+ container.lvasgn_type? && sibling_container.lvasgn_type?
207
+ end
208
+
209
+ def autocorrect(corrector, node, sibling, container, sibling_container)
210
+ if complementary_pair?(node, sibling)
211
+ select_var, reject_var =
212
+ complementary_variable_order(sibling, container, sibling_container)
213
+ partition_node = select_node_for(sibling, container)
214
+ else
215
+ select_var, reject_var, partition_node =
216
+ negation_partition_args(node, sibling, container, sibling_container)
217
+ end
218
+
219
+ partition_call = build_partition_call(partition_node)
220
+ replacement = "#{select_var}, #{reject_var} = #{partition_call}"
221
+
222
+ corrector.replace(sibling_container, replacement)
223
+ range = range_by_whole_lines(container.source_range, include_final_newline: true)
224
+ corrector.remove(range)
225
+ end
226
+
227
+ def complementary_variable_order(sibling, container, sibling_container)
228
+ if SELECT_METHODS.include?(sibling.method_name)
229
+ [sibling_container.children.first, container.children.first]
230
+ else
231
+ [container.children.first, sibling_container.children.first]
232
+ end
233
+ end
234
+
235
+ def negation_partition_args(node, sibling, container, sibling_container)
236
+ node_is_negated = negated_body?(node.body, sibling.body)
237
+ is_select = SELECT_METHODS.include?(node.method_name)
238
+ # For select: non-negated is truthy (first). For reject: negated is truthy (first).
239
+ node_is_truthy = is_select != node_is_negated
240
+ partition_node = node_is_negated ? sibling : node
241
+
242
+ if node_is_truthy
243
+ [container.children.first, sibling_container.children.first, partition_node]
244
+ else
245
+ [sibling_container.children.first, container.children.first, partition_node]
246
+ end
247
+ end
248
+
249
+ def select_node_for(sibling, container)
250
+ if SELECT_METHODS.include?(sibling.method_name)
251
+ sibling
252
+ else
253
+ container.children.last
254
+ end
255
+ end
256
+
257
+ def build_partition_call(node)
258
+ source = node.source
259
+ send_node = node.any_block_type? ? node.send_node : node
260
+ selector = send_node.loc.selector
261
+ offset = node.source_range.begin_pos
262
+ method_start = selector.begin_pos - offset
263
+ method_end = selector.end_pos - offset
264
+
265
+ "#{source[0...method_start]}partition#{source[method_end..]}"
266
+ end
267
+ end
268
+ end
269
+ end
270
+ end
@@ -4,6 +4,8 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # Enforces the consistent usage of `%`-literal delimiters.
7
+ # Using consistent delimiters across the codebase reduces
8
+ # cognitive load when reading `%`-literals.
7
9
  #
8
10
  # Specify the 'default' key to set all preferred delimiters at once. You
9
11
  # can continue to specify individual preferred delimiters to override the
@@ -99,6 +101,8 @@ module RuboCop
99
101
  def string_source(node)
100
102
  if node.is_a?(String)
101
103
  node.scrub
104
+ elsif node.is_a?(Symbol)
105
+ node.to_s
102
106
  elsif node.respond_to?(:type) && node.type?(:str, :sym)
103
107
  node.source
104
108
  end
@@ -45,7 +45,7 @@ module RuboCop
45
45
  # Report offense only if changing case doesn't change semantics,
46
46
  # i.e., if the string would become dynamic or has special characters.
47
47
  ast = parse(corrected(node.source)).ast
48
- return if node.children != ast.children
48
+ return if node.children != ast&.children
49
49
 
50
50
  add_offense(node.loc.begin) do |corrector|
51
51
  corrector.replace(node, corrected(node.source))
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Style
6
6
  # Looks for uses of Perl-style regexp match
7
7
  # backreferences and their English versions like
8
- # $1, $2, $&, &+, $MATCH, $PREMATCH, etc.
8
+ # $1, $2, $&, $MATCH, $PREMATCH, etc.
9
9
  #
10
10
  # @example
11
11
  # # bad
@@ -69,6 +69,10 @@ module RuboCop
69
69
  # @return [String, nil]
70
70
  def preferred_expression_to(node)
71
71
  first = node.to_a.first
72
+ # NOTE: `$+` / `$LAST_PAREN_MATCH` is deliberately not converted. It
73
+ # refers to the last group that actually matched, which has no concise
74
+ # `Regexp.last_match` equivalent (`Regexp.last_match(-1)` is the last
75
+ # group in the pattern, which may be `nil`).
72
76
  case first
73
77
  when ::Integer
74
78
  "Regexp.last_match(#{first})"
@@ -78,8 +82,6 @@ module RuboCop
78
82
  'Regexp.last_match.pre_match'
79
83
  when :$', :$POSTMATCH
80
84
  'Regexp.last_match.post_match'
81
- when :$+, :$LAST_PAREN_MATCH
82
- 'Regexp.last_match(-1)'
83
85
  end
84
86
  end
85
87