rubocop 1.71.1 → 1.92.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (705) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +23 -19
  4. data/config/default.yml +885 -168
  5. data/config/internal_affairs.yml +20 -0
  6. data/config/obsoletion.yml +47 -4
  7. data/exe/rubocop +2 -9
  8. data/lib/rubocop/cache_config.rb +29 -0
  9. data/lib/rubocop/cached_data.rb +50 -5
  10. data/lib/rubocop/changed_files.rb +134 -0
  11. data/lib/rubocop/cli/command/auto_generate_config.rb +36 -4
  12. data/lib/rubocop/cli/command/cop_names.rb +57 -0
  13. data/lib/rubocop/cli/command/execute_runner.rb +54 -3
  14. data/lib/rubocop/cli/command/explain.rb +34 -0
  15. data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
  16. data/lib/rubocop/cli/command/lsp.rb +1 -1
  17. data/lib/rubocop/cli/command/mcp.rb +19 -0
  18. data/lib/rubocop/cli/command/show_cops.rb +8 -2
  19. data/lib/rubocop/cli/command/show_docs_url.rb +8 -10
  20. data/lib/rubocop/cli/command/suggest_extensions.rb +8 -2
  21. data/lib/rubocop/cli.rb +59 -17
  22. data/lib/rubocop/comment_config/directive_range.rb +34 -0
  23. data/lib/rubocop/comment_config/disable_next.rb +143 -0
  24. data/lib/rubocop/comment_config/push_pop.rb +55 -0
  25. data/lib/rubocop/comment_config.rb +98 -45
  26. data/lib/rubocop/config.rb +137 -19
  27. data/lib/rubocop/config_finder.rb +1 -1
  28. data/lib/rubocop/config_loader.rb +75 -49
  29. data/lib/rubocop/config_loader_resolver.rb +124 -33
  30. data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
  31. data/lib/rubocop/config_obsoletion/extracted_cop.rb +6 -3
  32. data/lib/rubocop/config_obsoletion/removed_cop.rb +9 -1
  33. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  34. data/lib/rubocop/config_obsoletion.rb +47 -3
  35. data/lib/rubocop/config_store.rb +7 -2
  36. data/lib/rubocop/config_validator.rb +75 -12
  37. data/lib/rubocop/cop/autocorrect_logic.rb +43 -17
  38. data/lib/rubocop/cop/badge.rb +9 -1
  39. data/lib/rubocop/cop/base.rb +128 -35
  40. data/lib/rubocop/cop/bundler/gem_comment.rb +5 -4
  41. data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
  42. data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -11
  43. data/lib/rubocop/cop/bundler.rb +19 -0
  44. data/lib/rubocop/cop/commissioner.rb +13 -11
  45. data/lib/rubocop/cop/cop_documentation.rb +81 -0
  46. data/lib/rubocop/cop/cop_explanation.rb +140 -0
  47. data/lib/rubocop/cop/corrector.rb +4 -4
  48. data/lib/rubocop/cop/correctors/alignment_corrector.rb +92 -11
  49. data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
  50. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +22 -7
  51. data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
  52. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
  53. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +29 -2
  54. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -5
  55. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +8 -1
  56. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +73 -2
  57. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  58. data/lib/rubocop/cop/correctors.rb +28 -0
  59. data/lib/rubocop/cop/documentation.rb +3 -4
  60. data/lib/rubocop/cop/exclude_limit.rb +31 -5
  61. data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
  62. data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
  63. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  64. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +49 -17
  65. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +2 -9
  66. data/lib/rubocop/cop/gemspec/require_mfa.rb +22 -5
  67. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +12 -7
  68. data/lib/rubocop/cop/gemspec.rb +22 -0
  69. data/lib/rubocop/cop/generator/registration_injector.rb +188 -0
  70. data/lib/rubocop/cop/generator.rb +5 -1
  71. data/lib/rubocop/cop/internal_affairs/example_description.rb +9 -5
  72. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
  73. data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
  74. data/lib/rubocop/cop/internal_affairs/location_exists.rb +142 -0
  75. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
  76. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +16 -20
  77. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  78. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -2
  79. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +6 -2
  80. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +85 -0
  81. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +2 -2
  82. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  83. data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +1 -7
  84. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  85. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +5 -3
  86. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +1 -7
  87. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +13 -2
  88. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
  89. data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
  90. data/lib/rubocop/cop/internal_affairs.rb +3 -16
  91. data/lib/rubocop/cop/layout/argument_alignment.rb +4 -2
  92. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  93. data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
  94. data/lib/rubocop/cop/layout/block_alignment.rb +86 -4
  95. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  96. data/lib/rubocop/cop/layout/case_indentation.rb +28 -10
  97. data/lib/rubocop/cop/layout/class_structure.rb +172 -36
  98. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
  99. data/lib/rubocop/cop/layout/comment_indentation.rb +17 -7
  100. data/lib/rubocop/cop/layout/condition_position.rb +13 -3
  101. data/lib/rubocop/cop/layout/def_end_alignment.rb +5 -1
  102. data/lib/rubocop/cop/layout/dot_position.rb +2 -2
  103. data/lib/rubocop/cop/layout/else_alignment.rb +3 -15
  104. data/lib/rubocop/cop/layout/empty_comment.rb +8 -10
  105. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +27 -9
  106. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +63 -5
  107. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +14 -5
  108. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +46 -21
  109. data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
  110. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +101 -0
  111. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +34 -4
  112. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +8 -29
  113. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +2 -0
  114. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +14 -3
  115. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +17 -3
  116. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
  117. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
  118. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
  119. data/lib/rubocop/cop/layout/end_alignment.rb +20 -8
  120. data/lib/rubocop/cop/layout/extra_spacing.rb +109 -3
  121. data/lib/rubocop/cop/layout/first_argument_indentation.rb +57 -3
  122. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +18 -5
  123. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +26 -0
  124. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +25 -18
  125. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
  126. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +6 -0
  127. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
  128. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +11 -0
  129. data/lib/rubocop/cop/layout/hash_alignment.rb +20 -18
  130. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +5 -3
  131. data/lib/rubocop/cop/layout/heredoc_indentation.rb +48 -3
  132. data/lib/rubocop/cop/layout/indentation_style.rb +5 -2
  133. data/lib/rubocop/cop/layout/indentation_width.rb +159 -12
  134. data/lib/rubocop/cop/layout/leading_comment_space.rb +40 -1
  135. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +10 -4
  136. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
  137. data/lib/rubocop/cop/layout/line_length.rb +201 -30
  138. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +69 -57
  139. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +8 -2
  140. data/lib/rubocop/cop/layout/multiline_block_layout.rb +11 -1
  141. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +63 -56
  142. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +7 -1
  143. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +259 -40
  144. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
  145. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  146. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +9 -5
  147. data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
  148. data/lib/rubocop/cop/layout/redundant_line_break.rb +111 -7
  149. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +29 -9
  150. data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
  151. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  152. data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
  153. data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
  154. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +10 -4
  155. data/lib/rubocop/cop/layout/space_around_keyword.rb +20 -3
  156. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  157. data/lib/rubocop/cop/layout/space_around_operators.rb +30 -4
  158. data/lib/rubocop/cop/layout/space_before_block_braces.rb +5 -1
  159. data/lib/rubocop/cop/layout/space_before_brackets.rb +6 -39
  160. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
  161. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +55 -36
  162. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +32 -8
  163. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
  164. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  165. data/lib/rubocop/cop/layout.rb +114 -0
  166. data/lib/rubocop/cop/lazy_loader.rb +41 -0
  167. data/lib/rubocop/cop/lint/ambiguous_assignment.rb +9 -17
  168. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +72 -1
  169. data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
  170. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +3 -11
  171. data/lib/rubocop/cop/lint/ambiguous_range.rb +6 -2
  172. data/lib/rubocop/cop/lint/argument_mismatch.rb +99 -0
  173. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
  174. data/lib/rubocop/cop/lint/assignment_in_condition.rb +15 -1
  175. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  176. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -8
  177. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +4 -3
  178. data/lib/rubocop/cop/lint/constant_reassignment.rb +94 -15
  179. data/lib/rubocop/cop/lint/constant_resolution.rb +31 -6
  180. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +240 -0
  181. data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
  182. data/lib/rubocop/cop/lint/debugger.rb +13 -4
  183. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  184. data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
  185. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +5 -2
  186. data/lib/rubocop/cop/lint/deprecated_reference.rb +194 -0
  187. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  188. data/lib/rubocop/cop/lint/duplicate_methods.rb +506 -41
  189. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
  190. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  191. data/lib/rubocop/cop/lint/empty_block.rb +4 -4
  192. data/lib/rubocop/cop/lint/empty_conditional_body.rb +22 -65
  193. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  194. data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
  195. data/lib/rubocop/cop/lint/empty_interpolation.rb +14 -1
  196. data/lib/rubocop/cop/lint/empty_when.rb +8 -1
  197. data/lib/rubocop/cop/lint/ensure_return.rb +19 -1
  198. data/lib/rubocop/cop/lint/erb_new_arguments.rb +4 -8
  199. data/lib/rubocop/cop/lint/float_comparison.rb +33 -10
  200. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  201. data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
  202. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -2
  203. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -1
  204. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -2
  205. data/lib/rubocop/cop/lint/inherit_exception.rb +53 -7
  206. data/lib/rubocop/cop/lint/interpolation_check.rb +25 -6
  207. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  208. data/lib/rubocop/cop/lint/literal_as_condition.rb +152 -11
  209. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
  210. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +75 -37
  211. data/lib/rubocop/cop/lint/loop.rb +24 -2
  212. data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +245 -0
  213. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +60 -23
  214. data/lib/rubocop/cop/lint/missing_super.rb +31 -1
  215. data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -2
  216. data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
  217. data/lib/rubocop/cop/lint/name_typo.rb +270 -0
  218. data/lib/rubocop/cop/lint/nested_method_definition.rb +2 -2
  219. data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
  220. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +20 -0
  221. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +4 -2
  222. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +4 -4
  223. data/lib/rubocop/cop/lint/number_conversion.rb +20 -11
  224. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  225. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +11 -0
  226. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  227. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +7 -7
  228. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +15 -4
  229. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +20 -14
  230. data/lib/rubocop/cop/lint/raise_exception.rb +30 -11
  231. data/lib/rubocop/cop/lint/rand_one.rb +1 -1
  232. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +160 -39
  233. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +53 -19
  234. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +28 -6
  235. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  236. data/lib/rubocop/cop/lint/redundant_require_statement.rb +5 -25
  237. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +134 -12
  238. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +13 -4
  239. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +267 -0
  240. data/lib/rubocop/cop/lint/redundant_with_index.rb +5 -3
  241. data/lib/rubocop/cop/lint/redundant_with_object.rb +8 -0
  242. data/lib/rubocop/cop/lint/refinement_import_methods.rb +8 -1
  243. data/lib/rubocop/cop/lint/regexp_as_condition.rb +9 -1
  244. data/lib/rubocop/cop/lint/require_parentheses.rb +13 -4
  245. data/lib/rubocop/cop/lint/require_range_parentheses.rb +3 -2
  246. data/lib/rubocop/cop/lint/require_relative_self_path.rb +7 -5
  247. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  248. data/lib/rubocop/cop/lint/rescue_type.rb +2 -2
  249. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  250. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +28 -4
  251. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +9 -5
  252. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
  253. data/lib/rubocop/cop/lint/script_permission.rb +5 -1
  254. data/lib/rubocop/cop/lint/self_assignment.rb +63 -6
  255. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -1
  256. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  257. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  258. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +27 -1
  259. data/lib/rubocop/cop/lint/shared_mutable_default.rb +14 -1
  260. data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
  261. data/lib/rubocop/cop/lint/super_argument_mismatch.rb +179 -0
  262. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  263. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +122 -0
  264. data/lib/rubocop/cop/lint/symbol_conversion.rb +21 -4
  265. data/lib/rubocop/cop/lint/syntax.rb +25 -1
  266. data/lib/rubocop/cop/lint/to_enum_arguments.rb +73 -5
  267. data/lib/rubocop/cop/lint/to_json.rb +20 -17
  268. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  269. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +5 -1
  270. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +54 -11
  271. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +2 -0
  272. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -1
  273. data/lib/rubocop/cop/lint/unreachable_code.rb +16 -9
  274. data/lib/rubocop/cop/lint/unreachable_loop.rb +5 -5
  275. data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
  276. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  277. data/lib/rubocop/cop/lint/unused_private_method.rb +234 -0
  278. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
  279. data/lib/rubocop/cop/lint/useless_access_modifier.rb +31 -6
  280. data/lib/rubocop/cop/lint/useless_assignment.rb +63 -27
  281. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +107 -0
  282. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +92 -0
  283. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  284. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +11 -10
  285. data/lib/rubocop/cop/lint/useless_or.rb +111 -0
  286. data/lib/rubocop/cop/lint/useless_rescue.rb +2 -3
  287. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +13 -7
  288. data/lib/rubocop/cop/lint/useless_setter_call.rb +4 -1
  289. data/lib/rubocop/cop/lint/useless_times.rb +22 -1
  290. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +201 -0
  291. data/lib/rubocop/cop/lint/void.rb +68 -22
  292. data/lib/rubocop/cop/lint.rb +179 -0
  293. data/lib/rubocop/cop/message_annotator.rb +7 -3
  294. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  295. data/lib/rubocop/cop/metrics/block_length.rb +2 -1
  296. data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
  297. data/lib/rubocop/cop/metrics/class_length.rb +4 -2
  298. data/lib/rubocop/cop/metrics/collection_literal_length.rb +1 -1
  299. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
  300. data/lib/rubocop/cop/metrics/method_length.rb +3 -2
  301. data/lib/rubocop/cop/metrics/module_length.rb +4 -2
  302. data/lib/rubocop/cop/metrics/perceived_complexity.rb +37 -7
  303. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  304. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
  305. data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
  306. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  307. data/lib/rubocop/cop/metrics.rb +31 -0
  308. data/lib/rubocop/cop/migration/department_name.rb +11 -5
  309. data/lib/rubocop/cop/migration.rb +13 -0
  310. data/lib/rubocop/cop/mixin/alignment.rb +7 -3
  311. data/lib/rubocop/cop/mixin/allowed_methods.rb +5 -5
  312. data/lib/rubocop/cop/mixin/allowed_pattern.rb +9 -5
  313. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  314. data/lib/rubocop/cop/mixin/check_line_breakable.rb +44 -23
  315. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +10 -8
  316. data/lib/rubocop/cop/mixin/code_length.rb +10 -2
  317. data/lib/rubocop/cop/mixin/comments_help.rb +2 -3
  318. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -2
  319. data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
  320. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  321. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +13 -2
  322. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
  323. data/lib/rubocop/cop/mixin/endless_method_body_help.rb +69 -0
  324. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +13 -5
  325. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  326. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +20 -0
  327. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -2
  328. data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
  329. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +59 -17
  330. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +52 -25
  331. data/lib/rubocop/cop/mixin/hash_subset.rb +28 -6
  332. data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
  333. data/lib/rubocop/cop/mixin/hash_transform_method.rb +32 -78
  334. data/lib/rubocop/cop/mixin/indexed_method_arity.rb +94 -0
  335. data/lib/rubocop/cop/mixin/line_length_help.rb +52 -11
  336. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  337. data/lib/rubocop/cop/mixin/min_branches_count.rb +3 -1
  338. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
  339. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -1
  340. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +10 -1
  341. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +2 -2
  342. data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
  343. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  344. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +79 -8
  345. data/lib/rubocop/cop/mixin/project_index_help.rb +203 -0
  346. data/lib/rubocop/cop/mixin/range_help.rb +16 -5
  347. data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +181 -0
  348. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  349. data/lib/rubocop/cop/mixin/statement_modifier.rb +66 -10
  350. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  351. data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
  352. data/lib/rubocop/cop/mixin/trailing_comma.rb +23 -6
  353. data/lib/rubocop/cop/mixin.rb +93 -0
  354. data/lib/rubocop/cop/naming/accessor_method_name.rb +8 -0
  355. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +17 -1
  356. data/lib/rubocop/cop/naming/block_forwarding.rb +7 -4
  357. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  358. data/lib/rubocop/cop/naming/file_name.rb +6 -5
  359. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +9 -2
  360. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
  361. data/lib/rubocop/cop/naming/inclusive_language.rb +8 -2
  362. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +13 -6
  363. data/lib/rubocop/cop/naming/method_name.rb +190 -15
  364. data/lib/rubocop/cop/naming/predicate_method.rb +330 -0
  365. data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +65 -8
  366. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -6
  367. data/lib/rubocop/cop/naming/variable_name.rb +51 -6
  368. data/lib/rubocop/cop/naming/variable_number.rb +3 -1
  369. data/lib/rubocop/cop/naming.rb +31 -0
  370. data/lib/rubocop/cop/offense.rb +108 -9
  371. data/lib/rubocop/cop/registry.rb +234 -65
  372. data/lib/rubocop/cop/security/eval.rb +17 -3
  373. data/lib/rubocop/cop/security/io_methods.rb +2 -2
  374. data/lib/rubocop/cop/security/json_load.rb +45 -11
  375. data/lib/rubocop/cop/security/marshal_load.rb +1 -1
  376. data/lib/rubocop/cop/security/open.rb +1 -0
  377. data/lib/rubocop/cop/security.rb +19 -0
  378. data/lib/rubocop/cop/severity.rb +12 -0
  379. data/lib/rubocop/cop/style/access_modifier_declarations.rb +54 -13
  380. data/lib/rubocop/cop/style/accessor_grouping.rb +47 -10
  381. data/lib/rubocop/cop/style/alias.rb +33 -8
  382. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
  383. data/lib/rubocop/cop/style/and_or.rb +6 -1
  384. data/lib/rubocop/cop/style/arguments_forwarding.rb +52 -37
  385. data/lib/rubocop/cop/style/array_first_last.rb +13 -3
  386. data/lib/rubocop/cop/style/array_intersect.rb +136 -38
  387. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +50 -0
  388. data/lib/rubocop/cop/style/array_join.rb +4 -2
  389. data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
  390. data/lib/rubocop/cop/style/attr.rb +8 -6
  391. data/lib/rubocop/cop/style/bare_percent_literals.rb +4 -3
  392. data/lib/rubocop/cop/style/begin_block.rb +3 -1
  393. data/lib/rubocop/cop/style/bitwise_predicate.rb +13 -5
  394. data/lib/rubocop/cop/style/block_delimiters.rb +71 -40
  395. data/lib/rubocop/cop/style/case_equality.rb +29 -15
  396. data/lib/rubocop/cop/style/case_like_if.rb +12 -11
  397. data/lib/rubocop/cop/style/character_literal.rb +2 -2
  398. data/lib/rubocop/cop/style/class_and_module_children.rb +179 -27
  399. data/lib/rubocop/cop/style/class_equality_comparison.rb +22 -14
  400. data/lib/rubocop/cop/style/class_methods_definitions.rb +19 -5
  401. data/lib/rubocop/cop/style/collection_compact.rb +37 -17
  402. data/lib/rubocop/cop/style/collection_methods.rb +1 -0
  403. data/lib/rubocop/cop/style/collection_querying.rb +167 -0
  404. data/lib/rubocop/cop/style/colon_method_call.rb +16 -7
  405. data/lib/rubocop/cop/style/combinable_loops.rb +88 -9
  406. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  407. data/lib/rubocop/cop/style/commented_keyword.rb +12 -5
  408. data/lib/rubocop/cop/style/comparable_between.rb +78 -0
  409. data/lib/rubocop/cop/style/comparable_clamp.rb +12 -1
  410. data/lib/rubocop/cop/style/concat_array_literals.rb +53 -9
  411. data/lib/rubocop/cop/style/conditional_assignment.rb +58 -24
  412. data/lib/rubocop/cop/style/constant_visibility.rb +23 -12
  413. data/lib/rubocop/cop/style/copyright.rb +27 -12
  414. data/lib/rubocop/cop/style/data_inheritance.rb +25 -0
  415. data/lib/rubocop/cop/style/date_time.rb +4 -4
  416. data/lib/rubocop/cop/style/def_with_parentheses.rb +22 -5
  417. data/lib/rubocop/cop/style/dig_chain.rb +6 -1
  418. data/lib/rubocop/cop/style/dir_empty.rb +4 -0
  419. data/lib/rubocop/cop/style/directive_scope.rb +304 -0
  420. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +184 -20
  421. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
  422. data/lib/rubocop/cop/style/documentation.rb +53 -6
  423. data/lib/rubocop/cop/style/documentation_method.rb +8 -12
  424. data/lib/rubocop/cop/style/double_negation.rb +14 -3
  425. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  426. data/lib/rubocop/cop/style/each_with_object.rb +4 -3
  427. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  428. data/lib/rubocop/cop/style/empty_case_condition.rb +13 -4
  429. data/lib/rubocop/cop/style/empty_class_definition.rb +126 -0
  430. data/lib/rubocop/cop/style/empty_heredoc.rb +4 -0
  431. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  432. data/lib/rubocop/cop/style/empty_literal.rb +12 -3
  433. data/lib/rubocop/cop/style/empty_method.rb +15 -9
  434. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +110 -0
  435. data/lib/rubocop/cop/style/encoding.rb +7 -1
  436. data/lib/rubocop/cop/style/end_block.rb +3 -1
  437. data/lib/rubocop/cop/style/endless_method.rb +252 -19
  438. data/lib/rubocop/cop/style/env_home.rb +4 -0
  439. data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
  440. data/lib/rubocop/cop/style/even_odd.rb +11 -1
  441. data/lib/rubocop/cop/style/exact_regexp_match.rb +52 -8
  442. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  443. data/lib/rubocop/cop/style/explicit_block_argument.rb +62 -9
  444. data/lib/rubocop/cop/style/exponential_notation.rb +5 -4
  445. data/lib/rubocop/cop/style/fetch_env_var.rb +33 -7
  446. data/lib/rubocop/cop/style/file_null.rb +6 -4
  447. data/lib/rubocop/cop/style/file_open.rb +84 -0
  448. data/lib/rubocop/cop/style/file_write.rb +21 -16
  449. data/lib/rubocop/cop/style/float_division.rb +43 -15
  450. data/lib/rubocop/cop/style/for.rb +48 -1
  451. data/lib/rubocop/cop/style/format_string.rb +44 -9
  452. data/lib/rubocop/cop/style/format_string_token.rb +86 -16
  453. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +5 -3
  454. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  455. data/lib/rubocop/cop/style/global_vars.rb +5 -2
  456. data/lib/rubocop/cop/style/guard_clause.rb +41 -24
  457. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +27 -9
  458. data/lib/rubocop/cop/style/hash_conversion.rb +52 -16
  459. data/lib/rubocop/cop/style/hash_each_methods.rb +4 -4
  460. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  461. data/lib/rubocop/cop/style/hash_lookup_method.rb +128 -0
  462. data/lib/rubocop/cop/style/hash_slice.rb +16 -0
  463. data/lib/rubocop/cop/style/hash_syntax.rb +23 -6
  464. data/lib/rubocop/cop/style/hash_transform_keys.rb +19 -9
  465. data/lib/rubocop/cop/style/hash_transform_values.rb +19 -9
  466. data/lib/rubocop/cop/style/identical_conditional_branches.rb +39 -11
  467. data/lib/rubocop/cop/style/if_inside_else.rb +46 -21
  468. data/lib/rubocop/cop/style/if_unless_modifier.rb +90 -66
  469. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +19 -19
  470. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -2
  471. data/lib/rubocop/cop/style/if_with_semicolon.rb +61 -8
  472. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  473. data/lib/rubocop/cop/style/inline_comment.rb +5 -2
  474. data/lib/rubocop/cop/style/inverse_methods.rb +34 -8
  475. data/lib/rubocop/cop/style/invertible_unless_condition.rb +27 -7
  476. data/lib/rubocop/cop/style/ip_addresses.rb +3 -4
  477. data/lib/rubocop/cop/style/it_assignment.rb +69 -12
  478. data/lib/rubocop/cop/style/it_block_parameter.rb +150 -0
  479. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +4 -0
  480. data/lib/rubocop/cop/style/keyword_parameters_order.rb +23 -11
  481. data/lib/rubocop/cop/style/lambda.rb +30 -1
  482. data/lib/rubocop/cop/style/lambda_call.rb +31 -10
  483. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  484. data/lib/rubocop/cop/style/magic_comment_format.rb +4 -4
  485. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +11 -0
  486. data/lib/rubocop/cop/style/map_into_array.rb +6 -4
  487. data/lib/rubocop/cop/style/map_join.rb +123 -0
  488. data/lib/rubocop/cop/style/map_to_hash.rb +13 -5
  489. data/lib/rubocop/cop/style/map_to_set.rb +1 -3
  490. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +75 -24
  491. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
  492. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +58 -6
  493. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +36 -8
  494. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -1
  495. data/lib/rubocop/cop/style/method_def_parentheses.rb +36 -8
  496. data/lib/rubocop/cop/style/min_max_comparison.rb +17 -6
  497. data/lib/rubocop/cop/style/missing_else.rb +7 -1
  498. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +40 -7
  499. data/lib/rubocop/cop/style/mixin_usage.rb +1 -1
  500. data/lib/rubocop/cop/style/module_function.rb +4 -2
  501. data/lib/rubocop/cop/style/module_member_existence_check.rb +110 -0
  502. data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -1
  503. data/lib/rubocop/cop/style/multiline_if_modifier.rb +47 -5
  504. data/lib/rubocop/cop/style/multiline_if_then.rb +10 -4
  505. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
  506. data/lib/rubocop/cop/style/multiline_memoization.rb +7 -1
  507. data/lib/rubocop/cop/style/multiline_method_signature.rb +15 -22
  508. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
  509. data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
  510. data/lib/rubocop/cop/style/multiple_comparison.rb +33 -22
  511. data/lib/rubocop/cop/style/mutable_constant.rb +139 -13
  512. data/lib/rubocop/cop/style/negated_if_else_condition.rb +3 -3
  513. data/lib/rubocop/cop/style/negative_array_index.rb +228 -0
  514. data/lib/rubocop/cop/style/nested_modifier.rb +36 -12
  515. data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
  516. data/lib/rubocop/cop/style/next.rb +68 -10
  517. data/lib/rubocop/cop/style/nil_comparison.rb +53 -13
  518. data/lib/rubocop/cop/style/nil_lambda.rb +9 -1
  519. data/lib/rubocop/cop/style/non_nil_check.rb +21 -11
  520. data/lib/rubocop/cop/style/not.rb +12 -3
  521. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
  522. data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
  523. data/lib/rubocop/cop/style/numeric_predicate.rb +22 -6
  524. data/lib/rubocop/cop/style/object_then.rb +1 -0
  525. data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
  526. data/lib/rubocop/cop/style/one_line_conditional.rb +35 -15
  527. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  528. data/lib/rubocop/cop/style/operator_method_call.rb +10 -2
  529. data/lib/rubocop/cop/style/option_hash.rb +1 -1
  530. data/lib/rubocop/cop/style/optional_arguments.rb +1 -0
  531. data/lib/rubocop/cop/style/parallel_assignment.rb +58 -27
  532. data/lib/rubocop/cop/style/parentheses_around_condition.rb +6 -1
  533. data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
  534. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +18 -3
  535. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  536. data/lib/rubocop/cop/style/perl_backrefs.rb +5 -3
  537. data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
  538. data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
  539. data/lib/rubocop/cop/style/proc.rb +4 -2
  540. data/lib/rubocop/cop/style/raise_args.rb +9 -9
  541. data/lib/rubocop/cop/style/reduce_to_hash.rb +216 -0
  542. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  543. data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
  544. data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
  545. data/lib/rubocop/cop/style/redundant_assignment.rb +12 -2
  546. data/lib/rubocop/cop/style/redundant_begin.rb +58 -6
  547. data/lib/rubocop/cop/style/redundant_condition.rb +93 -18
  548. data/lib/rubocop/cop/style/redundant_constant_base.rb +42 -6
  549. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +26 -4
  550. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +17 -3
  551. data/lib/rubocop/cop/style/redundant_each.rb +4 -5
  552. data/lib/rubocop/cop/style/redundant_exception.rb +22 -4
  553. data/lib/rubocop/cop/style/redundant_fetch_block.rb +11 -11
  554. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +9 -0
  555. data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
  556. data/lib/rubocop/cop/style/redundant_format.rb +319 -0
  557. data/lib/rubocop/cop/style/redundant_freeze.rb +12 -3
  558. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +6 -1
  559. data/lib/rubocop/cop/style/redundant_interpolation.rb +12 -3
  560. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
  561. data/lib/rubocop/cop/style/redundant_line_continuation.rb +83 -119
  562. data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
  563. data/lib/rubocop/cop/style/redundant_parentheses.rb +176 -83
  564. data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
  565. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +15 -0
  566. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
  567. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +27 -7
  568. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +16 -0
  569. data/lib/rubocop/cop/style/redundant_return.rb +4 -3
  570. data/lib/rubocop/cop/style/redundant_self.rb +20 -7
  571. data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -3
  572. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
  573. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  574. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  575. data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -2
  576. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +133 -0
  577. data/lib/rubocop/cop/style/regexp_literal.rb +107 -29
  578. data/lib/rubocop/cop/style/require_order.rb +9 -0
  579. data/lib/rubocop/cop/style/rescue_modifier.rb +10 -12
  580. data/lib/rubocop/cop/style/return_nil.rb +19 -4
  581. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
  582. data/lib/rubocop/cop/style/reverse_find.rb +51 -0
  583. data/lib/rubocop/cop/style/safe_navigation.rb +76 -20
  584. data/lib/rubocop/cop/style/sample.rb +19 -13
  585. data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
  586. data/lib/rubocop/cop/style/select_by_range.rb +197 -0
  587. data/lib/rubocop/cop/style/select_by_regexp.rb +54 -22
  588. data/lib/rubocop/cop/style/self_assignment.rb +13 -16
  589. data/lib/rubocop/cop/style/semicolon.rb +56 -14
  590. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  591. data/lib/rubocop/cop/style/single_line_do_end_block.rb +22 -8
  592. data/lib/rubocop/cop/style/single_line_methods.rb +28 -11
  593. data/lib/rubocop/cop/style/sole_nested_conditional.rb +96 -104
  594. data/lib/rubocop/cop/style/special_global_vars.rb +7 -2
  595. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +32 -6
  596. data/lib/rubocop/cop/style/static_class.rb +21 -0
  597. data/lib/rubocop/cop/style/string_concatenation.rb +38 -16
  598. data/lib/rubocop/cop/style/string_hash_keys.rb +1 -0
  599. data/lib/rubocop/cop/style/struct_inheritance.rb +38 -2
  600. data/lib/rubocop/cop/style/super_arguments.rb +7 -6
  601. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  602. data/lib/rubocop/cop/style/symbol_proc.rb +34 -14
  603. data/lib/rubocop/cop/style/tally_method.rb +181 -0
  604. data/lib/rubocop/cop/style/ternary_parentheses.rb +34 -1
  605. data/lib/rubocop/cop/style/time_now.rb +41 -0
  606. data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -2
  607. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +52 -1
  608. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  609. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +2 -2
  610. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  611. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
  612. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +35 -32
  613. data/lib/rubocop/cop/style/trivial_accessors.rb +2 -2
  614. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  615. data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
  616. data/lib/rubocop/cop/style/while_until_do.rb +7 -0
  617. data/lib/rubocop/cop/style/while_until_modifier.rb +16 -1
  618. data/lib/rubocop/cop/style/word_array.rb +1 -0
  619. data/lib/rubocop/cop/style/yoda_condition.rb +26 -12
  620. data/lib/rubocop/cop/style/yoda_expression.rb +11 -2
  621. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -3
  622. data/lib/rubocop/cop/style.rb +311 -0
  623. data/lib/rubocop/cop/team.rb +172 -49
  624. data/lib/rubocop/cop/util.rb +7 -10
  625. data/lib/rubocop/cop/utils/format_string.rb +20 -5
  626. data/lib/rubocop/cop/variable_force/assignment.rb +8 -4
  627. data/lib/rubocop/cop/variable_force/branch.rb +30 -6
  628. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  629. data/lib/rubocop/cop/variable_force/variable.rb +42 -11
  630. data/lib/rubocop/cop/variable_force.rb +26 -9
  631. data/lib/rubocop/cops_documentation_generator.rb +49 -15
  632. data/lib/rubocop/directive_comment.rb +147 -5
  633. data/lib/rubocop/ext/regexp_node.rb +0 -1
  634. data/lib/rubocop/feature_loader.rb +0 -6
  635. data/lib/rubocop/file_patterns.rb +9 -1
  636. data/lib/rubocop/formatter/base_formatter.rb +22 -0
  637. data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
  638. data/lib/rubocop/formatter/disabled_config_formatter.rb +57 -14
  639. data/lib/rubocop/formatter/emacs_style_formatter.rb +3 -1
  640. data/lib/rubocop/formatter/formatter_set.rb +7 -2
  641. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  642. data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
  643. data/lib/rubocop/formatter/html_formatter.rb +3 -5
  644. data/lib/rubocop/formatter/json_formatter.rb +82 -7
  645. data/lib/rubocop/formatter/junit_formatter.rb +27 -10
  646. data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
  647. data/lib/rubocop/formatter/offense_count_formatter.rb +5 -4
  648. data/lib/rubocop/formatter/pacman_formatter.rb +5 -2
  649. data/lib/rubocop/formatter/sarif_formatter.rb +186 -0
  650. data/lib/rubocop/formatter/simple_text_formatter.rb +4 -5
  651. data/lib/rubocop/formatter/tap_formatter.rb +8 -3
  652. data/lib/rubocop/formatter/worst_offenders_formatter.rb +5 -4
  653. data/lib/rubocop/formatter.rb +23 -21
  654. data/lib/rubocop/lockfile.rb +18 -0
  655. data/lib/rubocop/lsp/diagnostic.rb +22 -41
  656. data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
  657. data/lib/rubocop/lsp/routes.rb +136 -33
  658. data/lib/rubocop/lsp/runtime.rb +66 -15
  659. data/lib/rubocop/lsp/server.rb +4 -2
  660. data/lib/rubocop/lsp/stdin_runner.rb +38 -19
  661. data/lib/rubocop/lsp.rb +5 -2
  662. data/lib/rubocop/magic_comment.rb +55 -0
  663. data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
  664. data/lib/rubocop/mcp/explain_tool.rb +68 -0
  665. data/lib/rubocop/mcp/scope.rb +65 -0
  666. data/lib/rubocop/mcp/server.rb +307 -0
  667. data/lib/rubocop/mcp/source_files.rb +35 -0
  668. data/lib/rubocop/offense_limit.rb +30 -0
  669. data/lib/rubocop/options.rb +166 -23
  670. data/lib/rubocop/path_util.rb +20 -5
  671. data/lib/rubocop/pending_cops_reporter.rb +51 -0
  672. data/lib/rubocop/plugin/configuration_integrator.rb +153 -0
  673. data/lib/rubocop/plugin/load_error.rb +26 -0
  674. data/lib/rubocop/plugin/loader.rb +100 -0
  675. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  676. data/lib/rubocop/plugin.rb +46 -0
  677. data/lib/rubocop/project_index_loader.rb +82 -0
  678. data/lib/rubocop/rake_task.rb +6 -4
  679. data/lib/rubocop/remote_config.rb +18 -13
  680. data/lib/rubocop/result_cache.rb +110 -65
  681. data/lib/rubocop/rspec/cop_helper.rb +21 -1
  682. data/lib/rubocop/rspec/expect_offense.rb +11 -7
  683. data/lib/rubocop/rspec/shared_contexts.rb +85 -3
  684. data/lib/rubocop/rspec/support.rb +4 -0
  685. data/lib/rubocop/runner.rb +368 -106
  686. data/lib/rubocop/server/cache.rb +67 -48
  687. data/lib/rubocop/server/cli.rb +2 -4
  688. data/lib/rubocop/server/client_command/base.rb +10 -0
  689. data/lib/rubocop/server/client_command/exec.rb +2 -1
  690. data/lib/rubocop/server/client_command/start.rb +11 -1
  691. data/lib/rubocop/server/core.rb +8 -0
  692. data/lib/rubocop/server.rb +14 -0
  693. data/lib/rubocop/target_finder.rb +25 -11
  694. data/lib/rubocop/target_ruby.rb +31 -14
  695. data/lib/rubocop/todo_audit.rb +111 -0
  696. data/lib/rubocop/unified_diff.rb +257 -0
  697. data/lib/rubocop/util.rb +69 -0
  698. data/lib/rubocop/version.rb +48 -10
  699. data/lib/rubocop.rb +35 -682
  700. data/lib/ruby_lsp/rubocop/addon.rb +28 -17
  701. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +99 -0
  702. metadata +129 -21
  703. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
  704. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  705. data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +0 -50
@@ -19,7 +19,7 @@ module RuboCop
19
19
 
20
20
  # @!method non_public_modifier?(node)
21
21
  def_node_matcher :non_public_modifier?, <<~PATTERN
22
- (send nil? {:private :protected :private_class_method} ({def defs} ...))
22
+ (send nil? {:private :protected :private_class_method} (any_def ...))
23
23
  PATTERN
24
24
  end
25
25
  end
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Layout
6
6
  # Common functionality for checking if presence/absence of empty lines
7
7
  # around some kind of body matches the configuration.
8
- module EmptyLinesAroundBody
8
+ module EmptyLinesAroundBody # rubocop:disable Metrics/ModuleLength
9
9
  extend NodePattern::Macros
10
10
  include ConfigurableEnforcedStyle
11
11
  include RangeHelp
@@ -14,6 +14,8 @@ module RuboCop
14
14
  MSG_MISSING = 'Empty line missing at %<kind>s body %<location>s.'
15
15
  MSG_DEFERRED = 'Empty line missing before first %<type>s definition'
16
16
 
17
+ LEADING_DOT_TYPES = %i[tDOT tANDDOT].to_set.freeze
18
+
17
19
  private
18
20
 
19
21
  # @!method constant_definition?(node)
@@ -21,7 +23,7 @@ module RuboCop
21
23
 
22
24
  # @!method empty_line_required?(node)
23
25
  def_node_matcher :empty_line_required?,
24
- '{def defs class module (send nil? {:private :protected :public})}'
26
+ '{any_def class module (send nil? {:private :protected :public})}'
25
27
 
26
28
  def check(node, body, adjusted_first_line: nil)
27
29
  return if valid_body_style?(body)
@@ -29,6 +31,7 @@ module RuboCop
29
31
 
30
32
  first_line = adjusted_first_line || node.source_range.first_line
31
33
  last_line = node.source_range.last_line
34
+ return if first_line >= last_line
32
35
 
33
36
  case style
34
37
  when :empty_lines_except_namespace
@@ -99,12 +102,20 @@ module RuboCop
99
102
  return unless yield(processed_source.lines[line])
100
103
 
101
104
  offset = style == :empty_lines && msg.include?('end.') ? 2 : 1
105
+ return if style == :empty_lines && leading_dot_line?(line + offset)
106
+
102
107
  range = source_range(processed_source.buffer, line + offset, 0)
103
108
  add_offense(range, message: msg) do |corrector|
104
109
  EmptyLineCorrector.correct(corrector, [style, range])
105
110
  end
106
111
  end
107
112
 
113
+ def leading_dot_line?(line)
114
+ first_token = processed_source.sorted_tokens.find { |token| token.line == line }
115
+
116
+ LEADING_DOT_TYPES.include?(first_token&.type)
117
+ end
118
+
108
119
  def check_deferred_empty_line(body)
109
120
  node = first_empty_line_required_child(body)
110
121
  return unless node
@@ -19,8 +19,7 @@ module RuboCop
19
19
  def check_end_kw_alignment(node, align_ranges)
20
20
  return if ignored_node?(node)
21
21
 
22
- end_loc = node.loc.end
23
- return if accept_end_kw_alignment?(end_loc)
22
+ return unless (end_loc = node.loc.end)
24
23
 
25
24
  matching = matching_ranges(end_loc, align_ranges)
26
25
 
@@ -57,11 +56,6 @@ module RuboCop
57
56
  add_offense(end_loc, message: msg) { |corrector| autocorrect(corrector, node) }
58
57
  end
59
58
 
60
- def accept_end_kw_alignment?(end_loc)
61
- end_loc.nil? || # Discard modifier forms of if/while/until.
62
- !/\A[ \t]*end/.match?(processed_source.lines[end_loc.line - 1])
63
- end
64
-
65
59
  def style_parameter_name
66
60
  'EnforcedStyleAlignWith'
67
61
  end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Common functionality for checking whether a method body can become the
6
+ # body of an endless method definition without changing its meaning.
7
+ module EndlessMethodBodyHelp
8
+ private
9
+
10
+ def endless_method_body?(body)
11
+ return false if body.type?(:begin, :kwbegin, :rescue, :ensure, :masgn)
12
+ return false if low_precedence_body?(body)
13
+ return false if ends_with_omitted_hash_value?(body) || ends_with_anonymous_argument?(body)
14
+ return false if body.assignment? && multiple_values?(assigned_value(body))
15
+
16
+ !command_disallowed_in_endless_body?(body)
17
+ end
18
+
19
+ # `def foo = bar and baz` parses as `(def foo = bar) and baz`.
20
+ def low_precedence_body?(body)
21
+ body.type?(:any_match_pattern, :while_post, :until_post) ||
22
+ (body.type?(:and, :or) && body.semantic_operator?) ||
23
+ (body.type?(:if, :while, :until) && body.modifier_form?)
24
+ end
25
+
26
+ # `foo = 1, 2` and `foo = *bar` assign an array without brackets.
27
+ def multiple_values?(node)
28
+ node.array_type? && !node.bracketed?
29
+ end
30
+
31
+ def ends_with_omitted_hash_value?(body)
32
+ body.each_descendant(:pair).any? do |pair|
33
+ pair.value_omission? && pair.source_range.end_pos == body.source_range.end_pos
34
+ end
35
+ end
36
+
37
+ def ends_with_anonymous_argument?(body)
38
+ forwarding = %i[forwarded_restarg forwarded_kwrestarg block_pass]
39
+
40
+ body.each_descendant(*forwarding).any? do |argument|
41
+ argument.source_range.end_pos == body.source_range.end_pos &&
42
+ (!argument.block_pass_type? || argument.children.first.nil?)
43
+ end
44
+ end
45
+
46
+ def command_disallowed_in_endless_body?(body)
47
+ return true if body.assignment? && command_call?(assigned_value(body))
48
+
49
+ body.each_node(:any_block).any? do |block|
50
+ block.keywords? && command_call?(block.send_node)
51
+ end
52
+ end
53
+
54
+ def assigned_value(node)
55
+ while node.assignment? || node.rescue_type?
56
+ node = node.rescue_type? ? node.body : node.children.last
57
+ end
58
+ node
59
+ end
60
+
61
+ def command_call?(node)
62
+ node = node.send_node if node.any_block_type?
63
+ return false unless node.type?(:call, :super, :yield)
64
+
65
+ node.arguments? && !node.parenthesized? && !node.operator_method? && !node.setter_method?
66
+ end
67
+ end
68
+ end
69
+ end
@@ -5,20 +5,28 @@ module RuboCop
5
5
  # Common functionality for rewriting endless methods to normal method definitions
6
6
  module EndlessMethodRewriter
7
7
  def correct_to_multiline(corrector, node)
8
- replacement = <<~RUBY.strip
9
- def #{node.method_name}#{arguments(node)}
10
- #{node.body.source}
11
- end
12
- RUBY
8
+ replacement = [
9
+ "def #{receiver(node)}#{node.method_name}#{arguments(node)}",
10
+ "#{indent(node, offset: configured_indentation_width)}#{node.body.source}",
11
+ "#{indent(node)}end"
12
+ ].join("\n")
13
13
 
14
14
  corrector.replace(node, replacement)
15
15
  end
16
16
 
17
17
  private
18
18
 
19
+ def receiver(node)
20
+ node.receiver ? "#{node.receiver.source}#{node.loc.operator.source}" : ''
21
+ end
22
+
19
23
  def arguments(node, missing = '')
20
24
  node.arguments.any? ? node.arguments.source : missing
21
25
  end
26
+
27
+ def configured_indentation_width
28
+ cop_config['IndentationWidth'] || config.for_cop('Layout/IndentationWidth')['Width'] || 2
29
+ end
22
30
  end
23
31
  end
24
32
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This module encapsulates the ability to forbid certain identifiers in a cop.
6
+ module ForbiddenIdentifiers
7
+ SIGILS = '@$' # if a variable starts with a sigil it will be removed
8
+
9
+ def forbidden_identifier?(name)
10
+ return false if forbidden_identifiers.empty?
11
+
12
+ forbidden_identifiers.include?(name.to_s.delete(SIGILS))
13
+ end
14
+
15
+ def forbidden_identifiers
16
+ cop_config.fetch('ForbiddenIdentifiers', [])
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This module encapsulates the ability to forbid certain patterns in a cop.
6
+ module ForbiddenPattern
7
+ def forbidden_pattern?(name)
8
+ forbidden_pattern_regexps.any? { |pattern| pattern.match?(name) }
9
+ end
10
+
11
+ def forbidden_patterns
12
+ cop_config.fetch('ForbiddenPatterns', [])
13
+ end
14
+
15
+ def forbidden_pattern_regexps
16
+ @forbidden_pattern_regexps ||= forbidden_patterns.map { |pattern| Regexp.new(pattern) }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -6,7 +6,6 @@ module RuboCop
6
6
  module FrozenStringLiteral
7
7
  module_function
8
8
 
9
- FROZEN_STRING_LITERAL_REGEXP = /#\s*frozen[-_]?string[-_]?literal:/i.freeze
10
9
  FROZEN_STRING_LITERAL_ENABLED = '# frozen_string_literal: true'
11
10
  FROZEN_STRING_LITERAL_TYPES_RUBY27 = %i[str dstr].freeze
12
11
 
@@ -90,7 +89,7 @@ module RuboCop
90
89
 
91
90
  if first_non_comment_token
92
91
  # `line` is 1-indexed so we need to subtract 1 to get the array index
93
- processed_source.lines[0...first_non_comment_token.line - 1]
92
+ processed_source.lines[0...(first_non_comment_token.line - 1)]
94
93
  else
95
94
  processed_source.lines
96
95
  end
@@ -25,6 +25,28 @@ module RuboCop
25
25
  (args
26
26
  (arg $_)) ...)
27
27
  PATTERN
28
+
29
+ # @!method assignment_method_declarations(node)
30
+ def_node_search :assignment_method_declarations, <<~PATTERN
31
+ (send
32
+ (lvar {#match_block_variable_name? :_1 :it}) _ ...)
33
+ PATTERN
34
+
35
+ # @!method indexed_assignment_method_declarations(node)
36
+ def_node_search :indexed_assignment_method_declarations, <<~PATTERN
37
+ (send
38
+ (send (lvar {#match_block_variable_name? :_1 :it}) _)
39
+ :[]=
40
+ literal?
41
+ _
42
+ )
43
+ PATTERN
44
+
45
+ def match_block_variable_name?(receiver_name)
46
+ gem_specification(processed_source.ast) do |block_variable_name|
47
+ return block_variable_name == receiver_name
48
+ end
49
+ end
28
50
  end
29
51
  end
30
52
  end
@@ -10,7 +10,7 @@ module RuboCop
10
10
  true
11
11
  end
12
12
 
13
- def deltas_for_first_pair(first_pair, _node)
13
+ def deltas_for_first_pair(first_pair)
14
14
  {
15
15
  separator: separator_delta(first_pair),
16
16
  value: value_delta(first_pair)
@@ -55,7 +55,7 @@ module RuboCop
55
55
  # Common functionality for checking alignment of hash values.
56
56
  module ValueAlignment
57
57
  def checkable_layout?(node)
58
- !node.pairs_on_same_line? && !node.mixed_delimiters?
58
+ !node.pairs_on_same_line? && !node.mixed_delimiters? && alignable_values?(node)
59
59
  end
60
60
 
61
61
  def deltas(first_pair, current_pair)
@@ -68,6 +68,16 @@ module RuboCop
68
68
 
69
69
  private
70
70
 
71
+ def alignable_values?(node)
72
+ return false if node.pairs.first.value_omission?
73
+
74
+ node.pairs.none? { |pair| value_on_later_line?(pair) }
75
+ end
76
+
77
+ def value_on_later_line?(pair)
78
+ pair.value && pair.key.last_line != pair.value.first_line
79
+ end
80
+
71
81
  def separator_delta(first_pair, current_pair, key_delta)
72
82
  if current_pair.hash_rocket?
73
83
  hash_rocket_delta(first_pair, current_pair) - key_delta
@@ -81,13 +91,7 @@ module RuboCop
81
91
  class TableAlignment
82
92
  include ValueAlignment
83
93
 
84
- def initialize
85
- self.max_key_width = 0
86
- end
87
-
88
- def deltas_for_first_pair(first_pair, node)
89
- self.max_key_width = node.keys.map { |key| key.source.length }.max
90
-
94
+ def deltas_for_first_pair(first_pair)
91
95
  separator_delta = separator_delta(first_pair, first_pair, 0)
92
96
  {
93
97
  separator: separator_delta,
@@ -97,33 +101,68 @@ module RuboCop
97
101
 
98
102
  private
99
103
 
100
- attr_accessor :max_key_width
101
-
102
104
  def key_delta(first_pair, current_pair)
103
105
  first_pair.key_delta(current_pair)
104
106
  end
105
107
 
106
108
  def hash_rocket_delta(first_pair, current_pair)
107
- first_pair.loc.column + max_key_width + 1 - current_pair.loc.operator.column
109
+ target_operator_column(first_pair) - current_pair.loc.operator.column
108
110
  end
109
111
 
110
112
  def value_delta(first_pair, current_pair)
111
- correct_value_column = first_pair.key.loc.column +
112
- current_pair.delimiter(true).length +
113
- max_key_width
113
+ correct_value_column = target_operator_column(first_pair) +
114
+ max_delimiter_width(first_pair.parent) - 1
114
115
 
115
116
  current_pair.value_omission? ? 0 : correct_value_column - current_pair.value.loc.column
116
117
  end
118
+
119
+ # The column the separator should land on: the shared key margin
120
+ # plus the widest single-line key, or, if larger, a multiline key's
121
+ # own last-line end column. The latter can't be measured from a
122
+ # multiline key's (newline-including) source length, so it's a
123
+ # separate candidate rather than folded into `max_key_width`.
124
+ def target_operator_column(first_pair)
125
+ hash_node = first_pair.parent
126
+ candidates = multiline_key_end_columns(hash_node)
127
+
128
+ key_width = max_key_width(hash_node)
129
+ candidates << (first_pair.loc.column + key_width + 1) if key_width.positive?
130
+
131
+ candidates.max
132
+ end
133
+
134
+ def multiline_key_end_columns(hash_node)
135
+ hash_node.keys.reject(&:single_line?).map { |key| key.source_range.end.column + 1 }
136
+ end
137
+
138
+ def max_key_width(hash_node)
139
+ hash_node.keys.select(&:single_line?).map { |key| key.source.length }.max || 0
140
+ end
141
+
142
+ def max_delimiter_width(hash_node)
143
+ hash_node.pairs.map { |pair| pair.delimiter(true).length }.max
144
+ end
117
145
  end
118
146
 
119
147
  # Handles calculation of deltas when the enforced style is 'separator'.
120
148
  class SeparatorAlignment
121
149
  include ValueAlignment
122
150
 
123
- def deltas_for_first_pair(*_nodes)
151
+ def deltas_for_first_pair(_first_pair)
124
152
  {}
125
153
  end
126
154
 
155
+ # Keys are right-aligned by the column their last line ends on.
156
+ # A key spanning several lines ends on a line other than the one it starts on,
157
+ # so moving its first line would never change that column and the correction
158
+ # would be repeated on every pass. Such pairs are left alone, and so is every pair
159
+ # when the first key spans several lines, since there is then no column to right-align to.
160
+ def deltas(first_pair, current_pair)
161
+ return {} if first_pair.key.multiline? || current_pair.key.multiline?
162
+
163
+ super
164
+ end
165
+
127
166
  private
128
167
 
129
168
  def key_delta(first_pair, current_pair)
@@ -135,7 +174,10 @@ module RuboCop
135
174
  end
136
175
 
137
176
  def value_delta(first_pair, current_pair)
138
- current_pair.value_omission? ? 0 : first_pair.value_delta(current_pair)
177
+ return 0 if first_pair.equal?(current_pair) || current_pair.value_omission?
178
+
179
+ expected_value_column = first_pair.loc.operator.end.column + 1
180
+ expected_value_column - current_pair.value.loc.column
139
181
  end
140
182
  end
141
183
 
@@ -11,6 +11,33 @@ module RuboCop
11
11
  DO_NOT_MIX_OMIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{OMIT_HASH_VALUE_MSG}"
12
12
  DO_NOT_MIX_EXPLICIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{EXPLICIT_HASH_VALUE_MSG}"
13
13
 
14
+ # A keyword parameter can be named after a keyword, as in `def foo(if:)`,
15
+ # but the parameter can only be referenced by an omitted hash value,
16
+ # so `{ if: }` has no explicit form: `{ if: if }` is invalid Ruby.
17
+ KEYWORDS = %i[
18
+ __ENCODING__ __FILE__ __LINE__ BEGIN END alias and begin break case class def do
19
+ else elsif end ensure false for if in module next nil not or redo rescue retry
20
+ return self super then true undef unless until when while yield
21
+ ].to_set.freeze
22
+
23
+ DefNode = Struct.new(:node) do
24
+ def selector
25
+ if node.loc?(:selector)
26
+ node.loc.selector
27
+ else
28
+ node.loc.keyword
29
+ end
30
+ end
31
+
32
+ def first_argument
33
+ node.first_argument
34
+ end
35
+
36
+ def last_argument
37
+ node.last_argument
38
+ end
39
+ end
40
+
14
41
  def on_hash_for_mixed_shorthand(hash_node)
15
42
  return if ignore_mixed_hash_shorthand_syntax?(hash_node)
16
43
 
@@ -35,7 +62,7 @@ module RuboCop
35
62
  replacement = "#{hash_key_source}:"
36
63
  self.config_to_allow_offenses = { 'Enabled' => false }
37
64
  else
38
- return unless node.value_omission?
65
+ return if !node.value_omission? || keyword_value?(node)
39
66
 
40
67
  message = EXPLICIT_HASH_VALUE_MSG
41
68
  replacement = "#{hash_key_source}: #{hash_key_source}"
@@ -69,13 +96,26 @@ module RuboCop
69
96
  def ignore_mixed_hash_shorthand_syntax?(hash_node)
70
97
  target_ruby_version <= 3.0 ||
71
98
  !%w[consistent either_consistent].include?(enforced_shorthand_syntax) ||
72
- !hash_node.hash_type?
99
+ !hash_node.hash_type? || hash_rockets_enforced?(hash_node)
73
100
  end
74
101
 
75
102
  def ignore_hash_shorthand_syntax?(pair_node)
76
103
  target_ruby_version <= 3.0 || enforced_shorthand_syntax == 'either' ||
77
104
  %w[consistent either_consistent].include?(enforced_shorthand_syntax) ||
78
- !pair_node.parent.hash_type?
105
+ !pair_node.parent.hash_type? || hash_rockets_enforced?(pair_node.parent)
106
+ end
107
+
108
+ def hash_rockets_enforced?(hash_node)
109
+ style == :hash_rockets || force_hash_rockets?(hash_node.pairs) ||
110
+ no_mixed_keys_enforces_hash_rockets?(hash_node.pairs)
111
+ end
112
+
113
+ def no_mixed_keys_enforces_hash_rockets?(pairs)
114
+ case style
115
+ when :no_mixed_keys then !sym_indices?(pairs) || pairs.first.delimiter == '=>'
116
+ when :ruby19_no_mixed_keys then !sym_indices?(pairs)
117
+ else false
118
+ end
79
119
  end
80
120
 
81
121
  def enforced_shorthand_syntax
@@ -99,7 +139,7 @@ module RuboCop
99
139
  use_modifier_form_without_parenthesized_method_call?(method_dispatch_node)
100
140
  end
101
141
 
102
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
142
+ # rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
103
143
  def def_node_that_require_parentheses(node)
104
144
  last_pair = node.parent.pairs.last
105
145
  return unless last_pair.key.source == last_pair.value.source
@@ -107,13 +147,12 @@ module RuboCop
107
147
  return if dispatch_node.assignment_method?
108
148
  return if dispatch_node.parenthesized?
109
149
  return if dispatch_node.parent && parentheses?(dispatch_node.parent)
110
- return if last_expression?(dispatch_node) && !method_dispatch_as_argument?(dispatch_node)
150
+ return if last_expression?(dispatch_node) && !requires_parentheses_context?(dispatch_node)
111
151
 
112
152
  def_node = node.each_ancestor(:call, :super, :yield).first
113
153
 
114
154
  DefNode.new(def_node) unless def_node && def_node.arguments.empty?
115
155
  end
116
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
117
156
 
118
157
  def find_ancestor_method_dispatch_node(node)
119
158
  return unless (ancestor = node.parent.parent)
@@ -146,11 +185,11 @@ module RuboCop
146
185
  !assignment_node.right_sibling
147
186
  end
148
187
 
149
- def method_dispatch_as_argument?(method_dispatch_node)
150
- parent = method_dispatch_node.parent
188
+ def requires_parentheses_context?(node)
189
+ parent = node.parent
151
190
  return false unless parent
152
191
 
153
- parent.type?(:call, :super, :yield)
192
+ parent.type?(:call, :if, :super, :until, :while, :yield)
154
193
  end
155
194
 
156
195
  def breakdown_value_types_of_hash(hash_node)
@@ -189,6 +228,8 @@ module RuboCop
189
228
  def mixed_shorthand_syntax_check(hash_value_type_breakdown)
190
229
  if hash_with_values_that_cant_be_omitted?(hash_value_type_breakdown)
191
230
  each_omitted_value_pair(hash_value_type_breakdown) do |pair_node|
231
+ next if keyword_value?(pair_node)
232
+
192
233
  hash_key_source = pair_node.key.source
193
234
  replacement = "#{hash_key_source}: #{hash_key_source}"
194
235
  register_offense(pair_node, DO_NOT_MIX_EXPLICIT_VALUE_MSG, replacement)
@@ -213,22 +254,8 @@ module RuboCop
213
254
  end
214
255
  end
215
256
 
216
- DefNode = Struct.new(:node) do
217
- def selector
218
- if node.loc.respond_to?(:selector)
219
- node.loc.selector
220
- else
221
- node.loc.keyword
222
- end
223
- end
224
-
225
- def first_argument
226
- node.first_argument
227
- end
228
-
229
- def last_argument
230
- node.last_argument
231
- end
257
+ def keyword_value?(pair_node)
258
+ KEYWORDS.include?(pair_node.key.value)
232
259
  end
233
260
  end
234
261
  end
@@ -5,7 +5,7 @@ module RuboCop
5
5
  # Common functionality for Style/HashExcept and Style/HashSlice cops.
6
6
  # It registers an offense on methods with blocks that are equivalent
7
7
  # to Hash#except or Hash#slice.
8
- # rubocop:disable Metrics/ModuleLength
8
+ # rubocop:disable-next Metrics/ModuleLength
9
9
  module HashSubset
10
10
  include RangeHelp
11
11
  extend NodePattern::Macros
@@ -23,7 +23,7 @@ module RuboCop
23
23
  (call _ _)
24
24
  (args
25
25
  $(arg _key)
26
- (arg _))
26
+ $(arg _))
27
27
  {
28
28
  $(send
29
29
  {(lvar _key) $_ _ | _ $_ (lvar _key)})
@@ -67,7 +67,7 @@ module RuboCop
67
67
  end
68
68
 
69
69
  def extracts_hash_subset?(block)
70
- block_with_first_arg_check?(block) do |key_arg, send_node, method|
70
+ block_with_first_arg_check?(block) do |key_arg, value_arg, send_node, method|
71
71
  # Only consider methods that have one argument
72
72
  return false unless send_node.arguments.one?
73
73
 
@@ -76,15 +76,22 @@ module RuboCop
76
76
 
77
77
  case method
78
78
  when :include?, :exclude?
79
- send_node.first_argument.source == key_arg.source
79
+ slices_key?(send_node, :first_argument, key_arg, value_arg)
80
80
  when :in?
81
- send_node.receiver.source == key_arg.source
81
+ slices_key?(send_node, :receiver, key_arg, value_arg)
82
82
  else
83
83
  true
84
84
  end
85
85
  end
86
86
  end
87
87
 
88
+ def slices_key?(send_node, method, key_arg, value_arg)
89
+ return false if using_value_variable?(send_node, value_arg)
90
+
91
+ node = method == :receiver ? send_node.receiver : send_node.first_argument
92
+ node.source == key_arg.source
93
+ end
94
+
88
95
  def range_include?(send_node)
89
96
  # When checking `include?`, `exclude?` and `in?` for offenses, if the receiver
90
97
  # or first argument is a range, an offense should not be registered.
@@ -97,6 +104,14 @@ module RuboCop
97
104
  receiver.range_type?
98
105
  end
99
106
 
107
+ def using_value_variable?(send_node, value_arg)
108
+ # If the receiver of `include?` or `exclude?`, or the first argument of `in?` is the
109
+ # hash value block argument, an offense should not be registered.
110
+ # ie. `v.include?(k)` or `k.in?(v)`
111
+ (send_node.receiver.lvar_type? && send_node.receiver.name == value_arg.name) ||
112
+ (send_node.first_argument.lvar_type? && send_node.first_argument.name == value_arg.name)
113
+ end
114
+
100
115
  def supported_subset_method?(method)
101
116
  if active_support_extensions_enabled?
102
117
  ACTIVE_SUPPORT_SUBSET_METHODS.include?(method)
@@ -167,10 +182,18 @@ module RuboCop
167
182
  return ":\"#{value.source}\"" if value.dsym_type?
168
183
  return "\"#{value.source}\"" if value.dstr_type?
169
184
  return ":#{value.source}" if value.sym_type?
185
+ # The element of a `%w` array can contain characters that are special
186
+ # inside a single-quoted string (e.g. a `'`), so escape them rather than
187
+ # wrapping the raw source.
188
+ return to_single_quoted(value.value) if value.str_type?
170
189
 
171
190
  "'#{value.source}'"
172
191
  end
173
192
 
193
+ def to_single_quoted(string)
194
+ "'#{string.gsub(/['\\]/) { |character| "\\#{character}" }}'"
195
+ end
196
+
174
197
  def except_key(node)
175
198
  key_arg = node.argument_list.first.source
176
199
  body, = extract_body_if_negated(node.body)
@@ -183,6 +206,5 @@ module RuboCop
183
206
  range_between(node.loc.selector.begin_pos, node.parent.loc.end.end_pos)
184
207
  end
185
208
  end
186
- # rubocop:enable Metrics/ModuleLength
187
209
  end
188
210
  end