rubocop 1.70.0 → 1.71.2

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 (195) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +17 -0
  4. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  5. data/lib/rubocop/comment_config.rb +1 -1
  6. data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
  7. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  8. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  9. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  10. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  11. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  12. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  13. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +229 -0
  14. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  15. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  16. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  17. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  18. data/lib/rubocop/cop/internal_affairs.rb +3 -0
  19. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  20. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  21. data/lib/rubocop/cop/layout/block_alignment.rb +1 -1
  22. data/lib/rubocop/cop/layout/class_structure.rb +9 -9
  23. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  24. data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
  25. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  26. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
  27. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  28. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
  29. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
  30. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  31. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  32. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +1 -1
  33. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  34. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +1 -0
  35. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
  36. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
  37. data/lib/rubocop/cop/layout/redundant_line_break.rb +6 -5
  38. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
  39. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  40. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  41. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  42. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  43. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -0
  44. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  45. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  46. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  47. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
  48. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  49. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +1 -1
  50. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  51. data/lib/rubocop/cop/lint/constant_reassignment.rb +2 -6
  52. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  53. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  54. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  55. data/lib/rubocop/cop/lint/duplicate_set_element.rb +1 -1
  56. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  57. data/lib/rubocop/cop/lint/float_comparison.rb +5 -2
  58. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  59. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  60. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  61. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +13 -3
  62. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  63. data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
  64. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  65. data/lib/rubocop/cop/lint/nested_method_definition.rb +3 -3
  66. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  67. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  68. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +13 -18
  69. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
  70. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  71. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  72. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  73. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  74. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -1
  75. data/lib/rubocop/cop/lint/shared_mutable_default.rb +3 -3
  76. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  77. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  78. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +1 -1
  79. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  80. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
  81. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
  82. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -4
  83. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  84. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  85. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  86. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  87. data/lib/rubocop/cop/lint/void.rb +2 -7
  88. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  89. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  90. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  91. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  92. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  93. data/lib/rubocop/cop/mixin/check_line_breakable.rb +5 -5
  94. data/lib/rubocop/cop/mixin/comments_help.rb +1 -1
  95. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  96. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +4 -4
  97. data/lib/rubocop/cop/mixin/hash_subset.rb +188 -0
  98. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  99. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +22 -8
  100. data/lib/rubocop/cop/mixin/statement_modifier.rb +7 -2
  101. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  102. data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
  103. data/lib/rubocop/cop/naming/block_forwarding.rb +18 -14
  104. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -3
  105. data/lib/rubocop/cop/security/compound_hash.rb +1 -0
  106. data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -4
  107. data/lib/rubocop/cop/style/arguments_forwarding.rb +38 -19
  108. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  109. data/lib/rubocop/cop/style/block_delimiters.rb +7 -20
  110. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  111. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  112. data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
  113. data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
  114. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  115. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
  116. data/lib/rubocop/cop/style/documentation.rb +1 -1
  117. data/lib/rubocop/cop/style/double_negation.rb +3 -3
  118. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  119. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  120. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  121. data/lib/rubocop/cop/style/exact_regexp_match.rb +1 -1
  122. data/lib/rubocop/cop/style/explicit_block_argument.rb +15 -2
  123. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  124. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  125. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -6
  126. data/lib/rubocop/cop/style/hash_except.rb +20 -131
  127. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  128. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  129. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  130. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  131. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
  132. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  133. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  134. data/lib/rubocop/cop/style/inverse_methods.rb +6 -6
  135. data/lib/rubocop/cop/style/it_assignment.rb +1 -1
  136. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  137. data/lib/rubocop/cop/style/map_into_array.rb +1 -1
  138. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  139. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  140. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +10 -13
  141. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
  142. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -4
  143. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  144. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  145. data/lib/rubocop/cop/style/mutable_constant.rb +2 -2
  146. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
  147. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  148. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  149. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -5
  150. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  151. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  152. data/lib/rubocop/cop/style/proc.rb +1 -2
  153. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  154. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  155. data/lib/rubocop/cop/style/redundant_condition.rb +2 -2
  156. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  157. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  158. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  159. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
  160. data/lib/rubocop/cop/style/redundant_line_continuation.rb +27 -10
  161. data/lib/rubocop/cop/style/redundant_parentheses.rb +9 -6
  162. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  163. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  164. data/lib/rubocop/cop/style/redundant_self_assignment.rb +12 -27
  165. data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
  166. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  167. data/lib/rubocop/cop/style/return_nil.rb +1 -1
  168. data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
  169. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  170. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  171. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  172. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
  173. data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
  174. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  175. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  176. data/lib/rubocop/cop/style/super_arguments.rb +4 -4
  177. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  178. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  179. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
  180. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  181. data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
  182. data/lib/rubocop/cop/util.rb +2 -2
  183. data/lib/rubocop/cop/variable_force/variable.rb +14 -2
  184. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  185. data/lib/rubocop/cops_documentation_generator.rb +13 -13
  186. data/lib/rubocop/directive_comment.rb +9 -8
  187. data/lib/rubocop/options.rb +2 -1
  188. data/lib/rubocop/result_cache.rb +13 -13
  189. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  190. data/lib/rubocop/rspec/support.rb +1 -2
  191. data/lib/rubocop/target_finder.rb +1 -0
  192. data/lib/rubocop/version.rb +1 -1
  193. data/lib/rubocop.rb +3 -0
  194. metadata +15 -11
  195. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -32,6 +32,21 @@ module RuboCop
32
32
  # {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].include?(k) }
33
33
  # {foo: 1, bar: 2, baz: 3}.filter {|k, v| !%i[bar].include?(k) }
34
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
+ #
35
50
  # # bad
36
51
  # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].exclude?(k) }
37
52
  # {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].exclude?(k) }
@@ -44,146 +59,20 @@ module RuboCop
44
59
  # {foo: 1, bar: 2, baz: 3}.except(:bar)
45
60
  #
46
61
  class HashExcept < Base
47
- include RangeHelp
62
+ include HashSubset
48
63
  extend TargetRubyVersion
49
64
  extend AutoCorrector
50
65
 
51
66
  minimum_target_ruby_version 3.0
52
67
 
53
- MSG = 'Use `%<prefer>s` instead.'
54
- RESTRICT_ON_SEND = %i[reject select filter].freeze
55
-
56
- SUBSET_METHODS = %i[== != eql? include?].freeze
57
- ACTIVE_SUPPORT_SUBSET_METHODS = (SUBSET_METHODS + %i[in? exclude?]).freeze
58
-
59
- # @!method block_with_first_arg_check?(node)
60
- def_node_matcher :block_with_first_arg_check?, <<~PATTERN
61
- (block
62
- (call _ _)
63
- (args
64
- $(arg _key)
65
- (arg _))
66
- {
67
- $(send
68
- {(lvar _key) $_ _ | _ $_ (lvar _key)})
69
- (send
70
- $(send
71
- {(lvar _key) $_ _ | _ $_ (lvar _key)}) :!)
72
- })
73
- PATTERN
74
-
75
- def on_send(node)
76
- block = node.parent
77
- return unless extracts_hash_subset?(block) && semantically_except_method?(node, block)
78
-
79
- except_key = except_key(block)
80
- return unless safe_to_register_offense?(block, except_key)
81
-
82
- range = offense_range(node)
83
- preferred_method = "except(#{except_key_source(except_key)})"
84
-
85
- add_offense(range, message: format(MSG, prefer: preferred_method)) do |corrector|
86
- corrector.replace(range, preferred_method)
87
- end
88
- end
89
- alias on_csend on_send
90
-
91
68
  private
92
69
 
93
- def extracts_hash_subset?(block)
94
- block_with_first_arg_check?(block) do |key_arg, send_node, method|
95
- return false unless supported_subset_method?(method)
96
-
97
- case method
98
- when :include?, :exclude?
99
- send_node.first_argument.source == key_arg.source
100
- when :in?
101
- send_node.receiver.source == key_arg.source
102
- else
103
- true
104
- end
105
- end
106
- end
107
-
108
- def supported_subset_method?(method)
109
- if active_support_extensions_enabled?
110
- ACTIVE_SUPPORT_SUBSET_METHODS.include?(method)
111
- else
112
- SUBSET_METHODS.include?(method)
113
- end
114
- end
115
-
116
- def semantically_except_method?(node, block)
117
- body, negated = extract_body_if_negated(block.body)
118
-
119
- if node.method?('reject')
120
- body.method?('==') || body.method?('eql?') || included?(body, negated)
121
- else
122
- body.method?('!=') || not_included?(body, negated)
123
- end
124
- end
125
-
126
- def included?(body, negated)
127
- if negated
128
- body.method?('exclude?')
129
- else
130
- body.method?('include?') || body.method?('in?')
131
- end
132
- end
133
-
134
- def not_included?(body, negated)
135
- included?(body, !negated)
136
- end
137
-
138
- def safe_to_register_offense?(block, except_key)
139
- body = block.body
140
-
141
- if body.method?('==') || body.method?('!=')
142
- except_key.sym_type? || except_key.str_type?
143
- else
144
- true
145
- end
146
- end
147
-
148
- def extract_body_if_negated(body)
149
- if body.method?('!')
150
- [body.receiver, true]
151
- else
152
- [body, false]
153
- end
154
- end
155
-
156
- def except_key_source(key)
157
- if key.array_type?
158
- key = if key.percent_literal?
159
- key.each_value.map { |v| decorate_source(v) }
160
- else
161
- key.each_value.map(&:source)
162
- end
163
- return key.join(', ')
164
- end
165
-
166
- key.literal? ? key.source : "*#{key.source}"
167
- end
168
-
169
- def decorate_source(value)
170
- return ":\"#{value.source}\"" if value.dsym_type?
171
- return "\"#{value.source}\"" if value.dstr_type?
172
- return ":#{value.source}" if value.sym_type?
173
-
174
- "'#{value.source}'"
175
- end
176
-
177
- def except_key(node)
178
- key_arg = node.argument_list.first.source
179
- body, = extract_body_if_negated(node.body)
180
- lhs, _method_name, rhs = *body
181
-
182
- lhs.source == key_arg ? rhs : lhs
70
+ def semantically_subset_method?(node)
71
+ semantically_except_method?(node)
183
72
  end
184
73
 
185
- def offense_range(node)
186
- range_between(node.loc.selector.begin_pos, node.parent.loc.end.end_pos)
74
+ def preferred_method_name
75
+ 'except'
187
76
  end
188
77
  end
189
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
@@ -209,7 +209,7 @@ module RuboCop
209
209
  end
210
210
 
211
211
  def word_symbol_pair?(pair)
212
- return false unless pair.key.sym_type? || pair.key.dsym_type?
212
+ return false unless pair.key.type?(:sym, :dsym)
213
213
 
214
214
  acceptable_19_syntax_symbol?(pair.key.source)
215
215
  end
@@ -203,17 +203,36 @@ module RuboCop
203
203
  corrector.remove(range)
204
204
  next if inserted_expression
205
205
 
206
- if insert_position == :after_condition
207
- corrector.insert_after(node, "\n#{expression.source}")
206
+ if node.parent&.assignment?
207
+ correct_assignment(corrector, node, expression, insert_position)
208
208
  else
209
- corrector.insert_before(node, "#{expression.source}\n")
209
+ correct_no_assignment(corrector, node, expression, insert_position)
210
210
  end
211
+
211
212
  inserted_expression = true
212
213
  end
213
214
  end
214
215
  end
215
216
  # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
216
217
 
218
+ def correct_assignment(corrector, node, expression, insert_position)
219
+ if insert_position == :after_condition
220
+ assignment = node.parent.source_range.with(end_pos: node.source_range.begin_pos)
221
+ corrector.remove(assignment)
222
+ corrector.insert_after(node, "\n#{assignment.source}#{expression.source}")
223
+ else
224
+ corrector.insert_before(node.parent, "#{expression.source}\n")
225
+ end
226
+ end
227
+
228
+ def correct_no_assignment(corrector, node, expression, insert_position)
229
+ if insert_position == :after_condition
230
+ corrector.insert_after(node, "\n#{expression.source}")
231
+ else
232
+ corrector.insert_before(node, "#{expression.source}\n")
233
+ end
234
+ end
235
+
217
236
  def last_child_of_parent?(node)
218
237
  return true unless (parent = node.parent)
219
238
 
@@ -103,7 +103,7 @@ module RuboCop
103
103
 
104
104
  def defined_argument_is_undefined?(if_node, defined_node)
105
105
  defined_argument = defined_node.first_argument
106
- return false unless defined_argument.lvar_type? || defined_argument.send_type?
106
+ return false unless defined_argument.type?(:lvar, :send)
107
107
 
108
108
  if_node.left_siblings.none? do |sibling|
109
109
  sibling.respond_to?(:lvasgn_type?) && sibling.lvasgn_type? &&
@@ -112,11 +112,11 @@ module RuboCop
112
112
  end
113
113
 
114
114
  def pattern_matching_nodes(condition)
115
- if condition.match_pattern_type? || condition.match_pattern_p_type?
115
+ if condition.type?(:match_pattern, :match_pattern_p)
116
116
  [condition]
117
117
  else
118
118
  condition.each_descendant.select do |node|
119
- node.match_pattern_type? || node.match_pattern_p_type?
119
+ node.type?(:match_pattern, :match_pattern_p)
120
120
  end
121
121
  end
122
122
  end
@@ -67,7 +67,7 @@ module RuboCop
67
67
 
68
68
  # @!method if_with_boolean_literal_branches?(node)
69
69
  def_node_matcher :if_with_boolean_literal_branches?, <<~PATTERN
70
- (if #return_boolean_value? {(true) (false) | (false) (true)})
70
+ (if #return_boolean_value? <true false>)
71
71
  PATTERN
72
72
  # @!method double_negative?(node)
73
73
  def_node_matcher :double_negative?, '(send (send _ :!) :!)'
@@ -42,7 +42,7 @@ module RuboCop
42
42
  def message(node)
43
43
  template = if require_newline?(node)
44
44
  MSG_NEWLINE
45
- elsif node.else_branch&.if_type? || node.else_branch&.begin_type? ||
45
+ elsif node.else_branch&.type?(:if, :begin) ||
46
46
  use_masgn_or_block_in_branches?(node)
47
47
  MSG_IF_ELSE
48
48
  else
@@ -66,7 +66,7 @@ module RuboCop
66
66
 
67
67
  def use_masgn_or_block_in_branches?(node)
68
68
  node.branches.compact.any? do |branch|
69
- branch.masgn_type? || branch.block_type? || branch.numblock_type?
69
+ branch.type?(:masgn, :any_block)
70
70
  end
71
71
  end
72
72
 
@@ -68,7 +68,7 @@ module RuboCop
68
68
  end
69
69
 
70
70
  def autocorrect(corrector, node)
71
- if node.while_post_type? || node.until_post_type?
71
+ if node.type?(:while_post, :until_post)
72
72
  replace_begin_end_with_modifier(corrector, node)
73
73
  elsif node.modifier_form?
74
74
  replace_source(corrector, node.source_range, modifier_replacement(node))
@@ -60,18 +60,18 @@ module RuboCop
60
60
  def_node_matcher :inverse_candidate?, <<~PATTERN
61
61
  {
62
62
  (send $(call $(...) $_ $...) :!)
63
- (send ({block numblock} $(call $(...) $_) $...) :!)
63
+ (send (any_block $(call $(...) $_) $...) :!)
64
64
  (send (begin $(call $(...) $_ $...)) :!)
65
65
  }
66
66
  PATTERN
67
67
 
68
68
  # @!method inverse_block?(node)
69
69
  def_node_matcher :inverse_block?, <<~PATTERN
70
- ({block numblock} $(call (...) $_) ... { $(call ... :!)
71
- $(send (...) {:!= :!~} ...)
72
- (begin ... $(call ... :!))
73
- (begin ... $(send (...) {:!= :!~} ...))
74
- })
70
+ (any_block $(call (...) $_) ... { $(call ... :!)
71
+ $(send (...) {:!= :!~} ...)
72
+ (begin ... $(call ... :!))
73
+ (begin ... $(send (...) {:!= :!~} ...))
74
+ })
75
75
  PATTERN
76
76
 
77
77
  def on_send(node)
@@ -26,7 +26,7 @@ module RuboCop
26
26
 
27
27
  def on_lvasgn(node)
28
28
  return unless node.name == :it
29
- return unless node.each_ancestor(:block, :numblock).any?
29
+ return unless node.each_ancestor(:any_block).any?
30
30
 
31
31
  add_offense(node.loc.name)
32
32
  end
@@ -57,7 +57,7 @@ module RuboCop
57
57
 
58
58
  def append_newline_to_last_kwoptarg(arguments, corrector)
59
59
  last_argument = arguments.last
60
- return if last_argument.kwrestarg_type? || last_argument.blockarg_type?
60
+ return if last_argument.type?(:kwrestarg, :blockarg)
61
61
 
62
62
  last_kwoptarg = arguments.reverse.find(&:kwoptarg_type?)
63
63
  corrector.insert_after(last_kwoptarg, "\n") unless arguments.parent.block_type?
@@ -72,7 +72,7 @@ module RuboCop
72
72
  def_node_matcher :each_block_with_push?, <<-PATTERN
73
73
  [
74
74
  ^({begin kwbegin block} ...)
75
- ({block numblock} (send !{nil? self} :each) _
75
+ (any_block (send !{nil? self} :each) _
76
76
  (send (lvar _) {:<< :push :append} #suitable_argument_node?))
77
77
  ]
78
78
  PATTERN
@@ -40,7 +40,7 @@ module RuboCop
40
40
  # @!method map_to_h(node)
41
41
  def_node_matcher :map_to_h, <<~PATTERN
42
42
  {
43
- $(call ({block numblock} $(call _ {:map :collect}) ...) :to_h)
43
+ $(call (any_block $(call _ {:map :collect}) ...) :to_h)
44
44
  $(call $(call _ {:map :collect} (block_pass sym)) :to_h)
45
45
  }
46
46
  PATTERN
@@ -33,8 +33,8 @@ module RuboCop
33
33
  # @!method map_to_set?(node)
34
34
  def_node_matcher :map_to_set?, <<~PATTERN
35
35
  {
36
- $(send ({block numblock} $(send _ {:map :collect}) ...) :to_set)
37
- $(send $(send _ {:map :collect} (block_pass sym)) :to_set)
36
+ $(call (any_block $(call _ {:map :collect}) ...) :to_set)
37
+ $(call $(call _ {:map :collect} (block_pass sym)) :to_set)
38
38
  }
39
39
  PATTERN
40
40
 
@@ -49,6 +49,7 @@ module RuboCop
49
49
  autocorrect(corrector, to_set_node, map_node)
50
50
  end
51
51
  end
52
+ alias on_csend on_send
52
53
 
53
54
  private
54
55
 
@@ -111,9 +111,7 @@ module RuboCop
111
111
  parent = node.parent&.block_type? ? node.parent.parent : node.parent
112
112
  return false unless parent
113
113
 
114
- parent.pair_type? ||
115
- parent.array_type? ||
116
- parent.range_type? ||
114
+ parent.type?(:pair, :array, :range) ||
117
115
  splat?(parent) ||
118
116
  ternary_if?(parent)
119
117
  end
@@ -128,14 +126,14 @@ module RuboCop
128
126
  end
129
127
 
130
128
  def call_in_optional_arguments?(node)
131
- node.parent && (node.parent.optarg_type? || node.parent.kwoptarg_type?)
129
+ node.parent&.type?(:optarg, :kwoptarg)
132
130
  end
133
131
 
134
132
  def call_in_single_line_inheritance?(node)
135
133
  node.parent&.class_type? && node.parent.single_line?
136
134
  end
137
135
 
138
- # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
136
+ # rubocop:disable Metrics/PerceivedComplexity
139
137
  def call_with_ambiguous_arguments?(node)
140
138
  call_with_braced_block?(node) ||
141
139
  call_in_argument_with_block?(node) ||
@@ -144,33 +142,32 @@ module RuboCop
144
142
  hash_literal_in_arguments?(node) ||
145
143
  ambiguous_range_argument?(node) ||
146
144
  node.descendants.any? do |n|
147
- n.forwarded_args_type? || n.block_type? || n.numblock_type? ||
145
+ n.type?(:forwarded_args, :any_block) ||
148
146
  ambiguous_literal?(n) || logical_operator?(n)
149
147
  end
150
148
  end
151
- # rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity
149
+ # rubocop:enable Metrics/PerceivedComplexity
152
150
 
153
151
  def call_with_braced_block?(node)
154
- (node.call_type? || node.super_type?) && node.block_node&.braces?
152
+ node.type?(:call, :super) && node.block_node&.braces?
155
153
  end
156
154
 
157
155
  def call_in_argument_with_block?(node)
158
156
  parent = node.parent&.block_type? && node.parent.parent
159
157
  return false unless parent
160
158
 
161
- parent.call_type? || parent.super_type? || parent.yield_type?
159
+ parent.type?(:call, :super, :yield)
162
160
  end
163
161
 
164
162
  def call_as_argument_or_chain?(node)
165
- node.parent &&
166
- (node.parent.call_type? || node.parent.super_type? || node.parent.yield_type?) &&
163
+ node.parent&.type?(:call, :super, :yield) &&
167
164
  !assigned_before?(node.parent, node)
168
165
  end
169
166
 
170
167
  def call_in_match_pattern?(node)
171
168
  return false unless (parent = node.parent)
172
169
 
173
- parent.match_pattern_type? || parent.match_pattern_p_type?
170
+ parent.type?(:match_pattern, :match_pattern_p)
174
171
  end
175
172
 
176
173
  def hash_literal_in_arguments?(node)
@@ -205,7 +202,7 @@ module RuboCop
205
202
  end
206
203
 
207
204
  def splat?(node)
208
- node.splat_type? || node.kwsplat_type? || node.block_pass_type?
205
+ node.type?(:splat, :kwsplat, :block_pass)
209
206
  end
210
207
 
211
208
  def ternary_if?(node)
@@ -45,6 +45,7 @@ module RuboCop
45
45
  register_offense(node)
46
46
  end
47
47
  # rubocop:enable Metrics/CyclomaticComplexity
48
+ alias on_csend on_send
48
49
 
49
50
  private
50
51
 
@@ -100,7 +101,7 @@ module RuboCop
100
101
  # `obj.method ||= value` parses as (or-asgn (send ...) ...)
101
102
  # which IS an `asgn_node`. Similarly, `obj.method += value` parses
102
103
  # as (op-asgn (send ...) ...), which is also an `asgn_node`.
103
- next if asgn_node.shorthand_asgn? && asgn_node.lhs.send_type?
104
+ next if asgn_node.shorthand_asgn? && asgn_node.lhs.call_type?
104
105
 
105
106
  yield asgn_node
106
107
  end
@@ -40,10 +40,8 @@ module RuboCop
40
40
  def on_send(node)
41
41
  return if ignored_node?(node)
42
42
 
43
- receiver = node.receiver
44
-
45
- return unless (receiver&.block_type? || receiver&.numblock_type?) &&
46
- receiver.loc.end.is?('end')
43
+ return unless (receiver = node.receiver)
44
+ return unless receiver.any_block_type? && receiver.loc.end.is?('end')
47
45
 
48
46
  range = range_between(receiver.loc.end.begin_pos, node.source_range.end_pos)
49
47
 
@@ -168,7 +168,7 @@ module RuboCop
168
168
 
169
169
  def anonymous_arguments?(node)
170
170
  return true if node.arguments.any? do |arg|
171
- arg.forward_arg_type? || arg.restarg_type? || arg.kwrestarg_type?
171
+ arg.type?(:forward_arg, :restarg, :kwrestarg)
172
172
  end
173
173
  return false unless (last_argument = node.last_argument)
174
174
 
@@ -31,7 +31,7 @@ module RuboCop
31
31
  node.send_node.each_node(:send, :csend) do |send_node|
32
32
  receiver = send_node.receiver
33
33
 
34
- next unless (receiver&.block_type? || receiver&.numblock_type?) && receiver&.multiline?
34
+ next unless receiver&.any_block_type? && receiver.multiline?
35
35
 
36
36
  range = range_between(receiver.loc.end.begin_pos, node.send_node.source_range.end_pos)
37
37
 
@@ -19,7 +19,7 @@ module RuboCop
19
19
  # acceptable value other than none, it will suppress the offenses
20
20
  # raised by this cop. It enforces frozen state.
21
21
  #
22
- # NOTE: Regexp and Range literals are frozen objects since Ruby 3.0.
22
+ # NOTE: `Regexp` and `Range` literals are frozen objects since Ruby 3.0.
23
23
  #
24
24
  # NOTE: From Ruby 3.0, interpolated strings are not frozen when
25
25
  # `# frozen-string-literal: true` is used, so this cop enforces explicit
@@ -197,7 +197,7 @@ module RuboCop
197
197
  end
198
198
 
199
199
  def frozen_regexp_or_range_literals?(node)
200
- target_ruby_version >= 3.0 && (node.regexp_type? || node.range_type?)
200
+ target_ruby_version >= 3.0 && node.type?(:regexp, :range)
201
201
  end
202
202
 
203
203
  def requires_parentheses?(node)
@@ -74,7 +74,7 @@ module RuboCop
74
74
  end
75
75
 
76
76
  def unwrap_begin_nodes(node)
77
- node = node.children.first while node && (node.begin_type? || node.kwbegin_type?)
77
+ node = node.children.first while node&.type?(:begin, :kwbegin)
78
78
 
79
79
  node
80
80
  end
@@ -35,7 +35,7 @@ module RuboCop
35
35
  def on_send(node)
36
36
  return unless node.parenthesized?
37
37
 
38
- node.each_child_node(:send, :csend) do |nested|
38
+ node.each_child_node(:call) do |nested|
39
39
  next if allowed_omission?(nested)
40
40
 
41
41
  message = format(MSG, source: nested.source)
@@ -3,15 +3,15 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Flags uses of OpenStruct, as it is now officially discouraged
6
+ # Flags uses of `OpenStruct`, as it is now officially discouraged
7
7
  # to be used for performance, version compatibility, and potential security issues.
8
8
  #
9
9
  # @safety
10
- #
11
10
  # Note that this cop may flag false positives; for instance, the following legal
12
11
  # use of a hand-rolled `OpenStruct` type would be considered an offense:
13
12
  #
14
- # ```
13
+ # [source,ruby]
14
+ # -----
15
15
  # module MyNamespace
16
16
  # class OpenStruct # not the OpenStruct we're looking for
17
17
  # end
@@ -20,7 +20,7 @@ module RuboCop
20
20
  # OpenStruct.new # resolves to MyNamespace::OpenStruct
21
21
  # end
22
22
  # end
23
- # ```
23
+ # -----
24
24
  #
25
25
  # @example
26
26
  #
@@ -61,7 +61,7 @@ module RuboCop
61
61
  def custom_class_or_module_definition?(node)
62
62
  parent = node.parent
63
63
 
64
- (parent.class_type? || parent.module_type?) && node.left_siblings.empty?
64
+ parent.type?(:class, :module) && node.left_siblings.empty?
65
65
  end
66
66
  end
67
67
  end