rubocop 1.69.2 → 1.73.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +4 -4
  4. data/config/default.yml +90 -13
  5. data/config/internal_affairs.yml +16 -0
  6. data/lib/rubocop/cli/command/execute_runner.rb +3 -3
  7. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  8. data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
  9. data/lib/rubocop/comment_config.rb +2 -2
  10. data/lib/rubocop/config.rb +17 -4
  11. data/lib/rubocop/config_loader.rb +48 -8
  12. data/lib/rubocop/config_loader_resolver.rb +35 -10
  13. data/lib/rubocop/config_validator.rb +19 -9
  14. data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
  15. data/lib/rubocop/cop/base.rb +6 -0
  16. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  17. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  18. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  19. data/lib/rubocop/cop/internal_affairs/example_description.rb +4 -2
  20. data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
  21. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  22. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  23. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  24. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  25. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  26. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +229 -0
  27. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  28. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  29. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  30. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  31. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  32. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  33. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +7 -1
  34. data/lib/rubocop/cop/internal_affairs.rb +5 -16
  35. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  36. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -8
  37. data/lib/rubocop/cop/layout/block_alignment.rb +3 -1
  38. data/lib/rubocop/cop/layout/class_structure.rb +9 -9
  39. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +4 -4
  40. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  41. data/lib/rubocop/cop/layout/else_alignment.rb +2 -2
  42. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  43. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  44. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +27 -1
  45. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
  46. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
  47. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  48. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  49. data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
  50. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  51. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  52. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  53. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  54. data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
  55. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
  56. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  57. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  58. data/lib/rubocop/cop/layout/line_length.rb +4 -3
  59. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  60. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  61. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
  62. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
  63. data/lib/rubocop/cop/layout/redundant_line_break.rb +7 -6
  64. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
  65. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  66. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  67. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  68. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  69. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  70. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -0
  71. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  72. data/lib/rubocop/cop/layout/space_around_operators.rb +3 -3
  73. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  74. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  75. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  76. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  77. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
  78. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  79. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +1 -1
  80. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  81. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  82. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
  83. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  84. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  85. data/lib/rubocop/cop/lint/duplicate_methods.rb +0 -14
  86. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  87. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  88. data/lib/rubocop/cop/lint/empty_conditional_body.rb +10 -5
  89. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  90. data/lib/rubocop/cop/lint/float_comparison.rb +6 -8
  91. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  92. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  93. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  94. data/lib/rubocop/cop/lint/literal_as_condition.rb +99 -9
  95. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
  96. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  97. data/lib/rubocop/cop/lint/mixed_case_range.rb +3 -3
  98. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  99. data/lib/rubocop/cop/lint/nested_method_definition.rb +8 -4
  100. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  101. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -3
  102. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  103. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +18 -31
  104. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
  105. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  106. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  107. data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
  108. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  109. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +252 -0
  110. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  111. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -1
  112. data/lib/rubocop/cop/lint/shared_mutable_default.rb +65 -0
  113. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  114. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
  115. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  116. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  117. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -4
  118. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +1 -1
  119. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  120. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
  121. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
  122. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -4
  123. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  124. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +80 -0
  125. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  126. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  127. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  128. data/lib/rubocop/cop/lint/void.rb +11 -9
  129. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  130. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  131. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  132. data/lib/rubocop/cop/metrics/method_length.rb +8 -1
  133. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  134. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  135. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  136. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  137. data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
  138. data/lib/rubocop/cop/mixin/check_line_breakable.rb +11 -11
  139. data/lib/rubocop/cop/mixin/comments_help.rb +4 -2
  140. data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
  141. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  142. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
  143. data/lib/rubocop/cop/mixin/hash_subset.rb +203 -0
  144. data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
  145. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  146. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  147. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +48 -24
  148. data/lib/rubocop/cop/mixin/range_help.rb +3 -3
  149. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  150. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
  151. data/lib/rubocop/cop/mixin/string_help.rb +2 -2
  152. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  153. data/lib/rubocop/cop/mixin/trailing_comma.rb +15 -3
  154. data/lib/rubocop/cop/naming/block_forwarding.rb +19 -15
  155. data/lib/rubocop/cop/naming/predicate_name.rb +44 -0
  156. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -3
  157. data/lib/rubocop/cop/naming/variable_name.rb +64 -6
  158. data/lib/rubocop/cop/security/compound_hash.rb +1 -0
  159. data/lib/rubocop/cop/style/access_modifier_declarations.rb +34 -5
  160. data/lib/rubocop/cop/style/accessor_grouping.rb +19 -5
  161. data/lib/rubocop/cop/style/and_or.rb +1 -1
  162. data/lib/rubocop/cop/style/arguments_forwarding.rb +39 -23
  163. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  164. data/lib/rubocop/cop/style/block_delimiters.rb +7 -20
  165. data/lib/rubocop/cop/style/class_and_module_children.rb +6 -3
  166. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  167. data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
  168. data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
  169. data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
  170. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  171. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
  172. data/lib/rubocop/cop/style/documentation.rb +1 -1
  173. data/lib/rubocop/cop/style/double_negation.rb +3 -3
  174. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  175. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  176. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  177. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  178. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  179. data/lib/rubocop/cop/style/endless_method.rb +163 -18
  180. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  181. data/lib/rubocop/cop/style/exact_regexp_match.rb +3 -10
  182. data/lib/rubocop/cop/style/explicit_block_argument.rb +15 -2
  183. data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
  184. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  185. data/lib/rubocop/cop/style/float_division.rb +8 -4
  186. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  187. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -6
  188. data/lib/rubocop/cop/style/hash_except.rb +24 -148
  189. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  190. data/lib/rubocop/cop/style/hash_syntax.rb +6 -3
  191. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  192. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  193. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
  194. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  195. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  196. data/lib/rubocop/cop/style/inverse_methods.rb +6 -6
  197. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  198. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  199. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  200. data/lib/rubocop/cop/style/map_into_array.rb +1 -1
  201. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  202. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  203. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +19 -12
  204. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  205. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
  206. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -4
  207. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  208. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  209. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  210. data/lib/rubocop/cop/style/multiple_comparison.rb +26 -20
  211. data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
  212. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
  213. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  214. data/lib/rubocop/cop/style/object_then.rb +13 -15
  215. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  216. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -5
  217. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  218. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  219. data/lib/rubocop/cop/style/proc.rb +1 -2
  220. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  221. data/lib/rubocop/cop/style/raise_args.rb +6 -4
  222. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  223. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  224. data/lib/rubocop/cop/style/redundant_condition.rb +48 -2
  225. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
  226. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  227. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  228. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  229. data/lib/rubocop/cop/style/redundant_format.rb +250 -0
  230. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
  231. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  232. data/lib/rubocop/cop/style/redundant_line_continuation.rb +34 -13
  233. data/lib/rubocop/cop/style/redundant_parentheses.rb +28 -14
  234. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
  235. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  236. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  237. data/lib/rubocop/cop/style/redundant_self_assignment.rb +14 -28
  238. data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
  239. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  240. data/lib/rubocop/cop/style/return_nil.rb +1 -1
  241. data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
  242. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  243. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  244. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  245. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
  246. data/lib/rubocop/cop/style/single_line_methods.rb +6 -7
  247. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  248. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
  249. data/lib/rubocop/cop/style/string_concatenation.rb +2 -2
  250. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  251. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  252. data/lib/rubocop/cop/style/super_arguments.rb +65 -17
  253. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  254. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  255. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
  256. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  257. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  258. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  259. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  260. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  261. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  262. data/lib/rubocop/cop/util.rb +12 -5
  263. data/lib/rubocop/cop/utils/format_string.rb +7 -5
  264. data/lib/rubocop/cop/variable_force/variable.rb +14 -2
  265. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  266. data/lib/rubocop/cops_documentation_generator.rb +25 -14
  267. data/lib/rubocop/directive_comment.rb +44 -10
  268. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  269. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  270. data/lib/rubocop/lsp/logger.rb +2 -2
  271. data/lib/rubocop/lsp/routes.rb +7 -23
  272. data/lib/rubocop/lsp/runtime.rb +17 -49
  273. data/lib/rubocop/lsp/server.rb +0 -2
  274. data/lib/rubocop/lsp/stdin_runner.rb +83 -0
  275. data/lib/rubocop/options.rb +28 -12
  276. data/lib/rubocop/path_util.rb +15 -8
  277. data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
  278. data/lib/rubocop/plugin/load_error.rb +26 -0
  279. data/lib/rubocop/plugin/loader.rb +100 -0
  280. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  281. data/lib/rubocop/plugin.rb +46 -0
  282. data/lib/rubocop/rake_task.rb +4 -1
  283. data/lib/rubocop/result_cache.rb +13 -13
  284. data/lib/rubocop/rspec/cop_helper.rb +9 -0
  285. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  286. data/lib/rubocop/rspec/shared_contexts.rb +19 -1
  287. data/lib/rubocop/rspec/support.rb +2 -2
  288. data/lib/rubocop/runner.rb +5 -6
  289. data/lib/rubocop/server/cache.rb +35 -2
  290. data/lib/rubocop/server/cli.rb +2 -2
  291. data/lib/rubocop/target_finder.rb +1 -0
  292. data/lib/rubocop/target_ruby.rb +15 -0
  293. data/lib/rubocop/version.rb +17 -2
  294. data/lib/rubocop.rb +11 -1
  295. data/lib/ruby_lsp/rubocop/addon.rb +75 -0
  296. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +47 -0
  297. metadata +53 -16
  298. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  299. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -5,8 +5,11 @@ module RuboCop
5
5
  module Style
6
6
  # Checks for endless methods.
7
7
  #
8
- # It can enforce either the use of endless methods definitions
9
- # for single-lined method bodies, or disallow endless methods.
8
+ # It can enforce endless method definitions whenever possible or with single line methods.
9
+ # It can also disallow multiline endless method definitions or all endless definitions.
10
+ #
11
+ # `require_single_line` style enforces endless method definitions for single line methods.
12
+ # `require_always` style enforces endless method definitions for single statement methods.
10
13
  #
11
14
  # Other method definition types are not considered by this cop.
12
15
  #
@@ -15,36 +18,116 @@ module RuboCop
15
18
  # * allow_single_line (default) - only single line endless method definitions are allowed.
16
19
  # * allow_always - all endless method definitions are allowed.
17
20
  # * disallow - all endless method definitions are disallowed.
21
+ # * require_single_line - endless method definitions are required for single line methods.
22
+ # * require_always - all endless method definitions are required.
18
23
  #
19
24
  # NOTE: Incorrect endless method definitions will always be
20
25
  # corrected to a multi-line definition.
21
26
  #
22
27
  # @example EnforcedStyle: allow_single_line (default)
28
+ # # bad, multi-line endless method
29
+ # def my_method = x.foo
30
+ # .bar
31
+ # .baz
32
+ #
23
33
  # # good
24
- # def my_method() = x
34
+ # def my_method
35
+ # x
36
+ # end
25
37
  #
26
- # # bad, multi-line endless method
27
- # def my_method() = x.foo
28
- # .bar
29
- # .baz
38
+ # # good
39
+ # def my_method = x
40
+ #
41
+ # # good
42
+ # def my_method
43
+ # x.foo
44
+ # .bar
45
+ # .baz
46
+ # end
30
47
  #
31
48
  # @example EnforcedStyle: allow_always
32
49
  # # good
33
- # def my_method() = x
50
+ # def my_method
51
+ # x
52
+ # end
34
53
  #
35
54
  # # good
36
- # def my_method() = x.foo
37
- # .bar
38
- # .baz
55
+ # def my_method = x
56
+ #
57
+ # # good
58
+ # def my_method = x.foo
59
+ # .bar
60
+ # .baz
61
+ #
62
+ # # good
63
+ # def my_method
64
+ # x.foo
65
+ # .bar
66
+ # .baz
67
+ # end
39
68
  #
40
69
  # @example EnforcedStyle: disallow
41
70
  # # bad
42
- # def my_method() = x
71
+ # def my_method = x
72
+ #
73
+ # # bad
74
+ # def my_method = x.foo
75
+ # .bar
76
+ # .baz
77
+ #
78
+ # # good
79
+ # def my_method
80
+ # x
81
+ # end
82
+ #
83
+ # # good
84
+ # def my_method
85
+ # x.foo
86
+ # .bar
87
+ # .baz
88
+ # end
89
+ #
90
+ # @example EnforcedStyle: require_single_line
91
+ # # bad
92
+ # def my_method
93
+ # x
94
+ # end
95
+ #
96
+ # # bad
97
+ # def my_method = x.foo
98
+ # .bar
99
+ # .baz
100
+ #
101
+ # # good
102
+ # def my_method = x
103
+ #
104
+ # # good
105
+ # def my_method
106
+ # x.foo
107
+ # .bar
108
+ # .baz
109
+ # end
110
+ #
111
+ # @example EnforcedStyle: require_always
112
+ # # bad
113
+ # def my_method
114
+ # x
115
+ # end
43
116
  #
44
117
  # # bad
45
- # def my_method() = x.foo
46
- # .bar
47
- # .baz
118
+ # def my_method
119
+ # x.foo
120
+ # .bar
121
+ # .baz
122
+ # end
123
+ #
124
+ # # good
125
+ # def my_method = x
126
+ #
127
+ # # good
128
+ # def my_method = x.foo
129
+ # .bar
130
+ # .baz
48
131
  #
49
132
  class EndlessMethod < Base
50
133
  include ConfigurableEnforcedStyle
@@ -57,12 +140,21 @@ module RuboCop
57
140
  CORRECTION_STYLES = %w[multiline single_line].freeze
58
141
  MSG = 'Avoid endless method definitions.'
59
142
  MSG_MULTI_LINE = 'Avoid endless method definitions with multiple lines.'
143
+ MSG_REQUIRE_SINGLE = 'Use endless method definitions for single line methods.'
144
+ MSG_REQUIRE_ALWAYS = 'Use endless method definitions.'
60
145
 
61
146
  def on_def(node)
62
- if style == :disallow
63
- handle_disallow_style(node)
64
- else
147
+ return if node.assignment_method?
148
+
149
+ case style
150
+ when :allow_single_line, :allow_always
65
151
  handle_allow_style(node)
152
+ when :disallow
153
+ handle_disallow_style(node)
154
+ when :require_single_line
155
+ handle_require_single_line_style(node)
156
+ when :require_always
157
+ handle_require_always_style(node)
66
158
  end
67
159
  end
68
160
 
@@ -77,11 +169,64 @@ module RuboCop
77
169
  end
78
170
  end
79
171
 
172
+ def handle_require_single_line_style(node)
173
+ if node.endless? && !node.single_line?
174
+ add_offense(node, message: MSG_MULTI_LINE) do |corrector|
175
+ correct_to_multiline(corrector, node)
176
+ end
177
+ elsif !node.endless? && can_be_made_endless?(node) && node.body.single_line?
178
+ return if too_long_when_made_endless?(node)
179
+
180
+ add_offense(node, message: MSG_REQUIRE_SINGLE) do |corrector|
181
+ corrector.replace(node, endless_replacement(node))
182
+ end
183
+ end
184
+ end
185
+
186
+ def handle_require_always_style(node)
187
+ return if node.endless? || !can_be_made_endless?(node)
188
+ return if too_long_when_made_endless?(node)
189
+
190
+ add_offense(node, message: MSG_REQUIRE_ALWAYS) do |corrector|
191
+ corrector.replace(node, endless_replacement(node))
192
+ end
193
+ end
194
+
80
195
  def handle_disallow_style(node)
81
196
  return unless node.endless?
82
197
 
83
198
  add_offense(node) { |corrector| correct_to_multiline(corrector, node) }
84
199
  end
200
+
201
+ def correct_to_multiline(corrector, node)
202
+ replacement = <<~RUBY.strip
203
+ def #{node.method_name}#{arguments(node)}
204
+ #{node.body.source}
205
+ end
206
+ RUBY
207
+
208
+ corrector.replace(node, replacement)
209
+ end
210
+
211
+ def endless_replacement(node)
212
+ <<~RUBY.strip
213
+ def #{node.method_name}#{arguments(node)} = #{node.body.source}
214
+ RUBY
215
+ end
216
+
217
+ def arguments(node, missing = '')
218
+ node.arguments.any? ? node.arguments.source : missing
219
+ end
220
+
221
+ def can_be_made_endless?(node)
222
+ node.body && !node.body.begin_type? && !node.body.kwbegin_type?
223
+ end
224
+
225
+ def too_long_when_made_endless?(node)
226
+ return false unless config.cop_enabled?('Layout/LineLength')
227
+
228
+ endless_replacement(node).length > config.for_cop('Layout/LineLength')['Max']
229
+ end
85
230
  end
86
231
  end
87
232
  end
@@ -86,7 +86,7 @@ module RuboCop
86
86
  return if node.method?(:eval) && !valid_eval_receiver?(node.receiver)
87
87
 
88
88
  code = node.first_argument
89
- return unless code && (code.str_type? || code.dstr_type?)
89
+ return unless code&.type?(:str, :dstr)
90
90
 
91
91
  check_location(node, code)
92
92
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for exact regexp match inside Regexp literals.
6
+ # Checks for exact regexp match inside `Regexp` literals.
7
7
  #
8
8
  # @example
9
9
  #
@@ -40,15 +40,8 @@ module RuboCop
40
40
  def on_send(node)
41
41
  return unless (receiver = node.receiver)
42
42
  return unless (regexp = exact_regexp_match(node))
43
-
44
- parsed_regexp = begin
45
- Regexp::Parser.parse(regexp)
46
- rescue Regexp::Parser::Error
47
- # Upon encountering an invalid regular expression,
48
- # we aim to proceed and identify any remaining potential offenses.
49
- end
50
-
51
- return unless parsed_regexp && exact_match_pattern?(parsed_regexp)
43
+ return unless (parsed_regexp = parse_regexp(regexp))
44
+ return unless exact_match_pattern?(parsed_regexp)
52
45
 
53
46
  prefer = "#{receiver.source} #{new_method(node)} '#{parsed_regexp[1].text}'"
54
47
 
@@ -123,7 +123,7 @@ module RuboCop
123
123
  end
124
124
 
125
125
  def call_like?(node)
126
- node.call_type? || node.zsuper_type? || node.super_type?
126
+ node.type?(:call, :zsuper, :super)
127
127
  end
128
128
 
129
129
  def insert_argument(node, corrector, block_name)
@@ -135,7 +135,13 @@ module RuboCop
135
135
  end
136
136
 
137
137
  def correct_call_node(node, corrector, block_name)
138
- corrector.insert_after(node, "(&#{block_name})")
138
+ new_arguments = if node.zsuper_type?
139
+ args = build_new_arguments_for_zsuper(node) << "&#{block_name}"
140
+ args.join(', ')
141
+ else
142
+ "&#{block_name}"
143
+ end
144
+ corrector.insert_after(node, "(#{new_arguments})")
139
145
  return unless node.parenthesized?
140
146
 
141
147
  args_begin = Util.args_begin(node)
@@ -144,6 +150,13 @@ module RuboCop
144
150
  corrector.remove(range)
145
151
  end
146
152
 
153
+ def build_new_arguments_for_zsuper(node)
154
+ def_node = node.each_ancestor(:def, :defs).first
155
+ def_node.arguments.map do |arg|
156
+ arg.optarg_type? ? arg.node_parts[0] : arg.source
157
+ end
158
+ end
159
+
147
160
  def block_body_range(block_node, send_node)
148
161
  range_between(send_node.source_range.end_pos, block_node.loc.end.end_pos)
149
162
  end
@@ -8,7 +8,7 @@ module RuboCop
8
8
  #
9
9
  # * `scientific` which enforces a mantissa between 1 (inclusive) and 10 (exclusive).
10
10
  # * `engineering` which enforces the exponent to be a multiple of 3 and the mantissa
11
- # to be between 0.1 (inclusive) and 10 (exclusive).
11
+ # to be between 0.1 (inclusive) and 1000 (exclusive).
12
12
  # * `integral` which enforces the mantissa to always be a whole number without
13
13
  # trailing zeroes.
14
14
  #
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # Suggests `ENV.fetch` for the replacement of `ENV[]`.
7
7
  # `ENV[]` silently fails and returns `nil` when the environment variable is unset,
8
8
  # which may cause unexpected behaviors when the developer forgets to set it.
9
- # On the other hand, `ENV.fetch` raises KeyError or returns the explicitly
9
+ # On the other hand, `ENV.fetch` raises `KeyError` or returns the explicitly
10
10
  # specified default value.
11
11
  #
12
12
  # @example
@@ -65,19 +65,23 @@ module RuboCop
65
65
 
66
66
  # @!method right_coerce?(node)
67
67
  def_node_matcher :right_coerce?, <<~PATTERN
68
- (send _ :/ (send _ :to_f))
68
+ (send _ :/ #to_f_method?)
69
69
  PATTERN
70
70
  # @!method left_coerce?(node)
71
71
  def_node_matcher :left_coerce?, <<~PATTERN
72
- (send (send _ :to_f) :/ _)
72
+ (send #to_f_method? :/ _)
73
73
  PATTERN
74
74
  # @!method both_coerce?(node)
75
75
  def_node_matcher :both_coerce?, <<~PATTERN
76
- (send (send _ :to_f) :/ (send _ :to_f))
76
+ (send #to_f_method? :/ #to_f_method?)
77
77
  PATTERN
78
78
  # @!method any_coerce?(node)
79
79
  def_node_matcher :any_coerce?, <<~PATTERN
80
- {(send _ :/ (send _ :to_f)) (send (send _ :to_f) :/ _)}
80
+ {(send _ :/ #to_f_method?) (send #to_f_method? :/ _)}
81
+ PATTERN
82
+ # @!method to_f_method?(node)
83
+ def_node_matcher :to_f_method?, <<~PATTERN
84
+ (send !nil? :to_f)
81
85
  PATTERN
82
86
 
83
87
  def on_send(node)
@@ -151,7 +151,7 @@ module RuboCop
151
151
 
152
152
  def frozen_string_literal_comment(processed_source)
153
153
  processed_source.tokens.find do |token|
154
- token.text.start_with?(FROZEN_STRING_LITERAL)
154
+ token.text.start_with?(FROZEN_STRING_LITERAL_REGEXP)
155
155
  end
156
156
  end
157
157
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for uses of `each_key` and `each_value` Hash methods.
6
+ # Checks for uses of `each_key` and `each_value` `Hash` methods.
7
7
  #
8
8
  # NOTE: If you have an array of two-element arrays, you can put
9
9
  # parentheses around the block arguments to indicate that you're not
@@ -44,7 +44,7 @@ module RuboCop
44
44
 
45
45
  # @!method kv_each(node)
46
46
  def_node_matcher :kv_each, <<~PATTERN
47
- ({block numblock} $(call (call _ ${:keys :values}) :each) ...)
47
+ (any_block $(call (call _ ${:keys :values}) :each) ...)
48
48
  PATTERN
49
49
 
50
50
  # @!method each_arguments(node)
@@ -162,10 +162,7 @@ module RuboCop
162
162
 
163
163
  def use_array_converter_method_as_preceding?(node)
164
164
  return false unless (preceding_method = node.children.first.children.first)
165
- unless preceding_method.call_type? ||
166
- preceding_method.block_type? || preceding_method.numblock_type?
167
- return false
168
- end
165
+ return false unless preceding_method.type?(:call, :any_block)
169
166
 
170
167
  ARRAY_CONVERTER_METHODS.include?(preceding_method.method_name)
171
168
  end
@@ -10,8 +10,10 @@ module RuboCop
10
10
  # (`Hash#except` was added in Ruby 3.0.)
11
11
  #
12
12
  # For safe detection, it is limited to commonly used string and symbol comparisons
13
- # when used `==`.
14
- # And do not check `Hash#delete_if` and `Hash#keep_if` to change receiver object.
13
+ # when using `==` or `!=`.
14
+ #
15
+ # This cop doesn't check for `Hash#delete_if` and `Hash#keep_if` because they
16
+ # modify the receiver.
15
17
  #
16
18
  # @safety
17
19
  # This cop is unsafe because it cannot be guaranteed that the receiver
@@ -30,6 +32,21 @@ module RuboCop
30
32
  # {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].include?(k) }
31
33
  # {foo: 1, bar: 2, baz: 3}.filter {|k, v| !%i[bar].include?(k) }
32
34
  #
35
+ # # good
36
+ # {foo: 1, bar: 2, baz: 3}.except(:bar)
37
+ #
38
+ # @example AllCops:ActiveSupportExtensionsEnabled: false (default)
39
+ #
40
+ # # good
41
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].exclude?(k) }
42
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].exclude?(k) }
43
+ #
44
+ # # good
45
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| k.in?(%i[bar]) }
46
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| !k.in?(%i[bar]) }
47
+ #
48
+ # @example AllCops:ActiveSupportExtensionsEnabled: true
49
+ #
33
50
  # # bad
34
51
  # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].exclude?(k) }
35
52
  # {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].exclude?(k) }
@@ -42,161 +59,20 @@ module RuboCop
42
59
  # {foo: 1, bar: 2, baz: 3}.except(:bar)
43
60
  #
44
61
  class HashExcept < Base
45
- include RangeHelp
62
+ include HashSubset
46
63
  extend TargetRubyVersion
47
64
  extend AutoCorrector
48
65
 
49
66
  minimum_target_ruby_version 3.0
50
67
 
51
- MSG = 'Use `%<prefer>s` instead.'
52
- RESTRICT_ON_SEND = %i[reject select filter].freeze
53
-
54
- # @!method bad_method_with_poro?(node)
55
- def_node_matcher :bad_method_with_poro?, <<~PATTERN
56
- (block
57
- (call _ _)
58
- (args
59
- $(arg _)
60
- (arg _))
61
- {
62
- $(send
63
- _ {:== :!= :eql? :include?} _)
64
- (send
65
- $(send
66
- _ {:== :!= :eql? :include?} _) :!)
67
- })
68
- PATTERN
69
-
70
- # @!method bad_method_with_active_support?(node)
71
- def_node_matcher :bad_method_with_active_support?, <<~PATTERN
72
- (block
73
- (send _ _)
74
- (args
75
- $(arg _)
76
- (arg _))
77
- {
78
- $(send
79
- _ {:== :!= :eql? :in? :include? :exclude?} _)
80
- (send
81
- $(send
82
- _ {:== :!= :eql? :in? :include? :exclude?} _) :!)
83
- })
84
- PATTERN
85
-
86
- def on_send(node)
87
- block = node.parent
88
- return unless bad_method?(block) && semantically_except_method?(node, block)
89
-
90
- except_key = except_key(block)
91
- return if except_key.nil? || !safe_to_register_offense?(block, except_key)
92
-
93
- range = offense_range(node)
94
- preferred_method = "except(#{except_key_source(except_key)})"
95
-
96
- add_offense(range, message: format(MSG, prefer: preferred_method)) do |corrector|
97
- corrector.replace(range, preferred_method)
98
- end
99
- end
100
- alias on_csend on_send
101
-
102
68
  private
103
69
 
104
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
105
- def bad_method?(block)
106
- if active_support_extensions_enabled?
107
- bad_method_with_active_support?(block) do |key_arg, send_node|
108
- if send_node.method?(:in?) && send_node.receiver&.source != key_arg.source
109
- return false
110
- end
111
- return true if !send_node.method?(:include?) && !send_node.method?(:exclude?)
112
-
113
- send_node.first_argument&.source == key_arg.source
114
- end
115
- else
116
- bad_method_with_poro?(block) do |key_arg, send_node|
117
- !send_node.method?(:include?) || send_node.first_argument&.source == key_arg.source
118
- end
119
- end
120
- end
121
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
122
-
123
- def semantically_except_method?(send, block)
124
- body = block.body
125
-
126
- negated = body.method?('!')
127
- body = body.receiver if negated
128
-
129
- case send.method_name
130
- when :reject
131
- body.method?('==') || body.method?('eql?') || included?(negated, body)
132
- when :select, :filter
133
- body.method?('!=') || not_included?(negated, body)
134
- else
135
- false
136
- end
137
- end
138
-
139
- def included?(negated, body)
140
- if negated
141
- body.method?('exclude?')
142
- else
143
- body.method?('include?') || body.method?('in?')
144
- end
145
- end
146
-
147
- def not_included?(negated, body)
148
- included?(!negated, body)
149
- end
150
-
151
- def safe_to_register_offense?(block, except_key)
152
- extracted = extract_body_if_negated(block.body)
153
- if extracted.method?('in?') || extracted.method?('include?') ||
154
- extracted.method?('exclude?')
155
- return true
156
- end
157
- return true if block.body.method?('eql?')
158
-
159
- except_key.sym_type? || except_key.str_type?
160
- end
161
-
162
- def extract_body_if_negated(body)
163
- return body unless body.method?('!')
164
-
165
- body.receiver
166
- end
167
-
168
- def except_key_source(key)
169
- if key.array_type?
170
- key = if key.percent_literal?
171
- key.each_value.map { |v| decorate_source(v) }
172
- else
173
- key.each_value.map(&:source)
174
- end
175
- return key.join(', ')
176
- end
177
-
178
- key.literal? ? key.source : "*#{key.source}"
179
- end
180
-
181
- def decorate_source(value)
182
- return ":\"#{value.source}\"" if value.dsym_type?
183
- return "\"#{value.source}\"" if value.dstr_type?
184
- return ":#{value.source}" if value.sym_type?
185
-
186
- "'#{value.source}'"
187
- end
188
-
189
- def except_key(node)
190
- key_argument = node.argument_list.first.source
191
- body = extract_body_if_negated(node.body)
192
- lhs, _method_name, rhs = *body
193
- return if [lhs, rhs].map(&:source).none?(key_argument)
194
-
195
- [lhs, rhs].find { |operand| operand.source != key_argument }
70
+ def semantically_subset_method?(node)
71
+ semantically_except_method?(node)
196
72
  end
197
73
 
198
- def offense_range(node)
199
- range_between(node.loc.selector.begin_pos, node.parent.loc.end.end_pos)
74
+ def preferred_method_name
75
+ 'except'
200
76
  end
201
77
  end
202
78
  end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for usages of `Hash#reject`, `Hash#select`, and `Hash#filter` methods
7
+ # that can be replaced with `Hash#slice` method.
8
+ #
9
+ # This cop should only be enabled on Ruby version 2.5 or higher.
10
+ # (`Hash#slice` was added in Ruby 2.5.)
11
+ #
12
+ # For safe detection, it is limited to commonly used string and symbol comparisons
13
+ # when using `==` or `!=`.
14
+ #
15
+ # This cop doesn't check for `Hash#delete_if` and `Hash#keep_if` because they
16
+ # modify the receiver.
17
+ #
18
+ # @safety
19
+ # This cop is unsafe because it cannot be guaranteed that the receiver
20
+ # is a `Hash` or responds to the replacement method.
21
+ #
22
+ # @example
23
+ #
24
+ # # bad
25
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k == :bar }
26
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| k != :bar }
27
+ # {foo: 1, bar: 2, baz: 3}.filter {|k, v| k == :bar }
28
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k.eql?(:bar) }
29
+ #
30
+ # # bad
31
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].include?(k) }
32
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].include?(k) }
33
+ # {foo: 1, bar: 2, baz: 3}.filter {|k, v| %i[bar].include?(k) }
34
+ #
35
+ # # good
36
+ # {foo: 1, bar: 2, baz: 3}.slice(:bar)
37
+ #
38
+ # @example AllCops:ActiveSupportExtensionsEnabled: false (default)
39
+ #
40
+ # # good
41
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].exclude?(k) }
42
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].exclude?(k) }
43
+ #
44
+ # # good
45
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k.in?(%i[bar]) }
46
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !k.in?(%i[bar]) }
47
+ #
48
+ # @example AllCops:ActiveSupportExtensionsEnabled: true
49
+ #
50
+ # # bad
51
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].exclude?(k) }
52
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].exclude?(k) }
53
+ #
54
+ # # bad
55
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k.in?(%i[bar]) }
56
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !k.in?(%i[bar]) }
57
+ #
58
+ # # good
59
+ # {foo: 1, bar: 2, baz: 3}.slice(:bar)
60
+ #
61
+ class HashSlice < Base
62
+ include HashSubset
63
+ extend TargetRubyVersion
64
+ extend AutoCorrector
65
+
66
+ minimum_target_ruby_version 2.5
67
+
68
+ private
69
+
70
+ def semantically_subset_method?(node)
71
+ semantically_slice_method?(node)
72
+ end
73
+
74
+ def preferred_method_name
75
+ 'slice'
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end