rubocop 1.68.0 → 1.69.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 (148) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +41 -6
  4. data/lib/rubocop/cop/base.rb +1 -1
  5. data/lib/rubocop/cop/bundler/gem_filename.rb +0 -1
  6. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +0 -1
  7. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +1 -1
  8. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
  9. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
  10. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +2 -4
  11. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
  12. data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +46 -0
  13. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
  14. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  15. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -2
  16. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  17. data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
  18. data/lib/rubocop/cop/layout/block_alignment.rb +1 -2
  19. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  20. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +2 -3
  21. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +3 -4
  22. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +3 -1
  23. data/lib/rubocop/cop/layout/indentation_width.rb +7 -7
  24. data/lib/rubocop/cop/layout/leading_comment_space.rb +15 -0
  25. data/lib/rubocop/cop/layout/line_length.rb +118 -4
  26. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
  27. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
  28. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -3
  29. data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
  30. data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -35
  31. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -2
  32. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  33. data/lib/rubocop/cop/layout/space_around_operators.rb +16 -17
  34. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +6 -0
  35. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +4 -0
  36. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
  37. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +11 -12
  38. data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -0
  39. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  40. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
  41. data/lib/rubocop/cop/lint/empty_file.rb +0 -2
  42. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  43. data/lib/rubocop/cop/lint/float_comparison.rb +14 -6
  44. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -3
  45. data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
  46. data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
  47. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +3 -0
  48. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  49. data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -5
  50. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  51. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
  52. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +1 -1
  53. data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
  54. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
  55. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +106 -0
  56. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -2
  57. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
  58. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  59. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +12 -7
  60. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
  61. data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
  62. data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
  63. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +2 -0
  64. data/lib/rubocop/cop/lint/self_assignment.rb +8 -10
  65. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  66. data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
  67. data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
  68. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
  69. data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
  70. data/lib/rubocop/cop/lint/void.rb +3 -2
  71. data/lib/rubocop/cop/metrics/class_length.rb +7 -7
  72. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  73. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -2
  74. data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
  75. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
  76. data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
  77. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +5 -9
  78. data/lib/rubocop/cop/mixin/range_help.rb +0 -1
  79. data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
  80. data/lib/rubocop/cop/naming/constant_name.rb +6 -7
  81. data/lib/rubocop/cop/naming/file_name.rb +0 -2
  82. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +11 -12
  83. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -11
  84. data/lib/rubocop/cop/naming/variable_name.rb +3 -4
  85. data/lib/rubocop/cop/naming/variable_number.rb +2 -3
  86. data/lib/rubocop/cop/style/access_modifier_declarations.rb +53 -24
  87. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +1 -1
  88. data/lib/rubocop/cop/style/array_intersect.rb +5 -4
  89. data/lib/rubocop/cop/style/bitwise_predicate.rb +1 -1
  90. data/lib/rubocop/cop/style/block_delimiters.rb +1 -1
  91. data/lib/rubocop/cop/style/case_like_if.rb +8 -11
  92. data/lib/rubocop/cop/style/commented_keyword.rb +11 -1
  93. data/lib/rubocop/cop/style/conditional_assignment.rb +19 -21
  94. data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
  95. data/lib/rubocop/cop/style/dig_chain.rb +90 -0
  96. data/lib/rubocop/cop/style/file_null.rb +73 -0
  97. data/lib/rubocop/cop/style/file_touch.rb +75 -0
  98. data/lib/rubocop/cop/style/for.rb +0 -1
  99. data/lib/rubocop/cop/style/global_vars.rb +1 -3
  100. data/lib/rubocop/cop/style/guard_clause.rb +1 -1
  101. data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
  102. data/lib/rubocop/cop/style/if_inside_else.rb +0 -1
  103. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -2
  104. data/lib/rubocop/cop/style/if_with_semicolon.rb +14 -5
  105. data/lib/rubocop/cop/style/inverse_methods.rb +0 -1
  106. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +2 -2
  107. data/lib/rubocop/cop/style/lambda_call.rb +0 -1
  108. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
  109. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +7 -11
  110. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
  111. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  112. data/lib/rubocop/cop/style/mutable_constant.rb +4 -5
  113. data/lib/rubocop/cop/style/negated_if_else_condition.rb +6 -4
  114. data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
  115. data/lib/rubocop/cop/style/not.rb +1 -1
  116. data/lib/rubocop/cop/style/one_line_conditional.rb +25 -4
  117. data/lib/rubocop/cop/style/operator_method_call.rb +5 -6
  118. data/lib/rubocop/cop/style/or_assignment.rb +3 -6
  119. data/lib/rubocop/cop/style/parallel_assignment.rb +8 -13
  120. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  121. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
  122. data/lib/rubocop/cop/style/redundant_condition.rb +36 -21
  123. data/lib/rubocop/cop/style/redundant_line_continuation.rb +7 -6
  124. data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
  125. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +1 -0
  126. data/lib/rubocop/cop/style/redundant_return.rb +2 -2
  127. data/lib/rubocop/cop/style/redundant_self.rb +7 -14
  128. data/lib/rubocop/cop/style/redundant_self_assignment.rb +7 -5
  129. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
  130. data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
  131. data/lib/rubocop/cop/style/rescue_modifier.rb +2 -3
  132. data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
  133. data/lib/rubocop/cop/style/select_by_regexp.rb +1 -1
  134. data/lib/rubocop/cop/style/self_assignment.rb +11 -17
  135. data/lib/rubocop/cop/style/signal_exception.rb +2 -3
  136. data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
  137. data/lib/rubocop/cop/style/single_line_do_end_block.rb +13 -3
  138. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -3
  139. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  140. data/lib/rubocop/cop/style/string_concatenation.rb +0 -1
  141. data/lib/rubocop/cop/style/swap_values.rb +4 -15
  142. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
  143. data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
  144. data/lib/rubocop/cop/variable_force.rb +4 -10
  145. data/lib/rubocop/cops_documentation_generator.rb +9 -1
  146. data/lib/rubocop/version.rb +1 -1
  147. data/lib/rubocop.rb +8 -0
  148. metadata +17 -8
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Checks for code on multiple lines that could be rewritten on a single line
6
+ # without changing semantics or exceeding the `Max` parameter of `Layout/LineLength`.
7
+ module CheckSingleLineSuitability
8
+ def suitable_as_single_line?(node)
9
+ !too_long?(node) &&
10
+ !comment_within?(node) &&
11
+ safe_to_split?(node)
12
+ end
13
+
14
+ private
15
+
16
+ def too_long?(node)
17
+ lines = processed_source.lines[(node.first_line - 1)...node.last_line]
18
+ to_single_line(lines.join("\n")).length > max_line_length
19
+ end
20
+
21
+ def to_single_line(source)
22
+ source
23
+ .gsub(/" *\\\n\s*'/, %q(" + ')) # Double quote, backslash, and then single quote
24
+ .gsub(/' *\\\n\s*"/, %q(' + ")) # Single quote, backslash, and then double quote
25
+ .gsub(/(["']) *\\\n\s*\1/, '') # Double or single quote, backslash, then same quote
26
+ .gsub(/\n\s*(?=(&)?\.\w)/, '') # Extra space within method chaining which includes `&.`
27
+ .gsub(/\s*\\?\n\s*/, ' ') # Any other line break, with or without backslash
28
+ end
29
+
30
+ def max_line_length
31
+ config.for_cop('Layout/LineLength')['Max']
32
+ end
33
+
34
+ def comment_within?(node)
35
+ comment_line_numbers = processed_source.comments.map { |comment| comment.loc.line }
36
+
37
+ comment_line_numbers.any? do |comment_line_number|
38
+ comment_line_number >= node.first_line && comment_line_number <= node.last_line
39
+ end
40
+ end
41
+
42
+ def safe_to_split?(node)
43
+ node.each_descendant(:if, :case, :kwbegin, :def, :defs).none? &&
44
+ node.each_descendant(:dstr, :str).none? { |n| n.heredoc? || n.value.include?("\n") } &&
45
+ node.each_descendant(:begin, :sym).none? { |b| !b.single_line? }
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Help methods for working with `Enumerable#dig` in cops.
6
+ # Used by `Style::DigChain` and `Style::SingleArgumentDig`
7
+ module DigHelp
8
+ extend NodePattern::Macros
9
+
10
+ # @!method dig?(node)
11
+ def_node_matcher :dig?, <<~PATTERN
12
+ (call _ :dig !{hash block_pass}+)
13
+ PATTERN
14
+
15
+ # @!method single_argument_dig?(node)
16
+ def_node_matcher :single_argument_dig?, <<~PATTERN
17
+ (send _ :dig $!splat)
18
+ PATTERN
19
+
20
+ private
21
+
22
+ def dig_chain_enabled?
23
+ @config.for_cop('Style/DigChain')['Enabled']
24
+ end
25
+ end
26
+ end
27
+ end
@@ -121,12 +121,10 @@ module RuboCop
121
121
 
122
122
  def indented_keyword_expression(node)
123
123
  if node.for_type?
124
- expression = node.collection
124
+ node.collection
125
125
  else
126
- expression, = *node
126
+ node.children.first
127
127
  end
128
-
129
- expression
130
128
  end
131
129
 
132
130
  def argument_in_method_call(node, kind) # rubocop:todo Metrics/CyclomaticComplexity
@@ -187,12 +185,10 @@ module RuboCop
187
185
 
188
186
  def assignment_rhs(node)
189
187
  case node.type
190
- when :casgn then _scope, _lhs, rhs = *node
191
- when :op_asgn then _lhs, _op, rhs = *node
192
- when :send, :csend then rhs = node.last_argument
193
- else _lhs, rhs = *node
188
+ when :casgn, :op_asgn then node.rhs
189
+ when :send, :csend then node.last_argument
190
+ else node.children.last
194
191
  end
195
- rhs
196
192
  end
197
193
 
198
194
  def not_for_this_cop?(node)
@@ -56,7 +56,6 @@ module RuboCop
56
56
  range: NOT_GIVEN, side: :both, newlines: true,
57
57
  whitespace: false, continuations: false,
58
58
  buffer: @processed_source.buffer)
59
-
60
59
  range = range_positional unless range_positional == NOT_GIVEN
61
60
 
62
61
  src = buffer.source
@@ -8,12 +8,28 @@ module RuboCop
8
8
  @minimum_target_ruby_version
9
9
  end
10
10
 
11
+ def required_maximum_ruby_version
12
+ @maximum_target_ruby_version
13
+ end
14
+
11
15
  def minimum_target_ruby_version(version)
12
16
  @minimum_target_ruby_version = version
13
17
  end
14
18
 
19
+ def maximum_target_ruby_version(version)
20
+ @maximum_target_ruby_version = version
21
+ end
22
+
15
23
  def support_target_ruby_version?(version)
16
- required_minimum_ruby_version <= version
24
+ # By default, no minimum or maximum versions of ruby are required
25
+ # to run any cop. In order to do a simple numerical comparison of
26
+ # the requested version against any requirements, we use 0 and
27
+ # Infinity as the default values to indicate no minimum (0) and no
28
+ # maximum (Infinity).
29
+ min = required_minimum_ruby_version || 0
30
+ max = required_maximum_ruby_version || Float::INFINITY
31
+
32
+ min <= version && max >= version
17
33
  end
18
34
  end
19
35
  end
@@ -31,12 +31,11 @@ module RuboCop
31
31
  PATTERN
32
32
 
33
33
  def on_casgn(node)
34
- if node.parent&.or_asgn_type?
35
- lhs, value = *node.parent
36
- _scope, const_name = *lhs
37
- else
38
- _scope, const_name, value = *node
39
- end
34
+ value = if node.parent&.or_asgn_type?
35
+ node.parent.expression
36
+ else
37
+ node.expression
38
+ end
40
39
 
41
40
  # We cannot know the result of method calls like
42
41
  # NewClass = something_that_returns_a_class
@@ -46,7 +45,7 @@ module RuboCop
46
45
  # SomeClass = Class.new(...)
47
46
  # SomeClass = Struct.new(...)
48
47
  return if allowed_assignment?(value)
49
- return if SNAKE_CASE.match?(const_name)
48
+ return if SNAKE_CASE.match?(node.name)
50
49
 
51
50
  add_offense(node.loc.name)
52
51
  end
@@ -37,8 +37,6 @@ module RuboCop
37
37
  #
38
38
  # anything/using_snake_case.rake
39
39
  class FileName < Base
40
- include RangeHelp
41
-
42
40
  MSG_SNAKE_CASE = 'The name of this source file (`%<basename>s`) should use snake_case.'
43
41
  MSG_NO_DEFINITION = '`%<basename>s` should define a class or module called `%<namespace>s`.'
44
42
  MSG_REGEX = '`%<basename>s` should match `%<regex>s`.'
@@ -155,6 +155,7 @@ module RuboCop
155
155
  UNDERSCORE_REQUIRED = 'Memoized variable `%<var>s` does not start ' \
156
156
  'with `_`. Use `@%<suggested_var>s` instead.'
157
157
  DYNAMIC_DEFINE_METHODS = %i[define_method define_singleton_method].to_set.freeze
158
+ INITIALIZE_METHODS = %i[initialize initialize_clone initialize_copy initialize_dup].freeze
158
159
 
159
160
  # @!method method_definition?(node)
160
161
  def_node_matcher :method_definition?, <<~PATTERN
@@ -168,7 +169,7 @@ module RuboCop
168
169
  # rubocop:disable Metrics/AbcSize
169
170
  # rubocop:disable Metrics/MethodLength
170
171
  def on_or_asgn(node)
171
- lhs, _value = *node
172
+ lhs = node.lhs
172
173
  return unless lhs.ivasgn_type?
173
174
 
174
175
  method_node, method_name = find_definition(node)
@@ -181,8 +182,8 @@ module RuboCop
181
182
 
182
183
  suggested_var = suggested_var(method_name)
183
184
  msg = format(
184
- message(lhs.children.first.to_s),
185
- var: lhs.children.first.to_s,
185
+ message(lhs.name),
186
+ var: lhs.name,
186
187
  suggested_var: suggested_var,
187
188
  method: method_name
188
189
  )
@@ -209,14 +210,13 @@ module RuboCop
209
210
  method_node, method_name = find_definition(node)
210
211
  return false unless method_node
211
212
 
212
- var_name = arg.children.first
213
- defined_memoized?(method_node.body, var_name) do |defined_ivar, return_ivar, ivar_assign|
213
+ defined_memoized?(method_node.body, arg.name) do |defined_ivar, return_ivar, ivar_assign|
214
214
  return false if matches?(method_name, ivar_assign)
215
215
 
216
216
  suggested_var = suggested_var(method_name)
217
217
  msg = format(
218
- message(var_name.to_s),
219
- var: var_name.to_s,
218
+ message(arg.name),
219
+ var: arg.name,
220
220
  suggested_var: suggested_var,
221
221
  method: method_name
222
222
  )
@@ -251,11 +251,10 @@ module RuboCop
251
251
  end
252
252
 
253
253
  def matches?(method_name, ivar_assign)
254
- return true if ivar_assign.nil? || method_name == :initialize
254
+ return true if ivar_assign.nil? || INITIALIZE_METHODS.include?(method_name)
255
255
 
256
- method_name = method_name.to_s.delete('!?')
257
- variable = ivar_assign.children.first
258
- variable_name = variable.to_s.sub('@', '')
256
+ method_name = method_name.to_s.delete('!?=')
257
+ variable_name = ivar_assign.name.to_s.sub('@', '')
259
258
 
260
259
  variable_name_candidates(method_name).include?(variable_name)
261
260
  end
@@ -269,7 +268,7 @@ module RuboCop
269
268
  end
270
269
 
271
270
  def suggested_var(method_name)
272
- suggestion = method_name.to_s.delete('!?')
271
+ suggestion = method_name.to_s.delete('!?=')
273
272
 
274
273
  style == :required ? "_#{suggestion}" : suggestion
275
274
  end
@@ -109,7 +109,7 @@ module RuboCop
109
109
  variable_name_matches?(lvasgn_node, name)
110
110
  end
111
111
  else
112
- node.children.first == name
112
+ node.name == name
113
113
  end
114
114
  end
115
115
 
@@ -141,12 +141,7 @@ module RuboCop
141
141
  # Further `lvar` nodes will not be corrected though since they now refer to a
142
142
  # different variable.
143
143
  def correct_reassignment(corrector, node, offending_name, preferred_name)
144
- if node.lvasgn_type?
145
- correct_node(corrector, node.child_nodes.first, offending_name, preferred_name)
146
- elsif node.masgn_type?
147
- # With multiple assign, the assignments are in an array as the last child
148
- correct_node(corrector, node.children.last, offending_name, preferred_name)
149
- end
144
+ correct_node(corrector, node.rhs, offending_name, preferred_name)
150
145
  end
151
146
 
152
147
  def preferred_name(variable_name)
@@ -159,10 +154,7 @@ module RuboCop
159
154
  end
160
155
 
161
156
  def variable_name(node)
162
- asgn_node = node.exception_variable
163
- return unless asgn_node
164
-
165
- asgn_node.children.last
157
+ node.exception_variable&.name
166
158
  end
167
159
 
168
160
  def message(node)
@@ -40,11 +40,10 @@ module RuboCop
40
40
  end
41
41
 
42
42
  def on_lvasgn(node)
43
- name, = *node
44
- return unless name
45
- return if allowed_identifier?(name)
43
+ return unless node.name
44
+ return if allowed_identifier?(node.name)
46
45
 
47
- check_name(node, name, node.loc.name)
46
+ check_name(node, node.name, node.loc.name)
48
47
  end
49
48
  alias on_ivasgn on_lvasgn
50
49
  alias on_cvasgn on_lvasgn
@@ -113,10 +113,9 @@ module RuboCop
113
113
 
114
114
  def on_arg(node)
115
115
  @node = node
116
- name, = *node
117
- return if allowed_identifier?(name)
116
+ return if allowed_identifier?(node.name)
118
117
 
119
- check_name(node, name, node.loc.name)
118
+ check_name(node, node.name, node.loc.name)
120
119
  end
121
120
  alias on_lvasgn on_arg
122
121
  alias on_ivasgn on_arg
@@ -70,6 +70,7 @@ module RuboCop
70
70
  # private :bar, :baz
71
71
  # private *%i[qux quux]
72
72
  # private *METHOD_NAMES
73
+ # private *private_methods
73
74
  #
74
75
  # end
75
76
  #
@@ -80,6 +81,7 @@ module RuboCop
80
81
  # private :bar, :baz
81
82
  # private *%i[qux quux]
82
83
  # private *METHOD_NAMES
84
+ # private *private_methods
83
85
  #
84
86
  # end
85
87
  #
@@ -133,21 +135,18 @@ module RuboCop
133
135
  # @!method access_modifier_with_symbol?(node)
134
136
  def_node_matcher :access_modifier_with_symbol?, <<~PATTERN
135
137
  (send nil? {:private :protected :public :module_function}
136
- {(sym _) (splat {#percent_symbol_array? const})}
138
+ {(sym _)+ (splat {#percent_symbol_array? const send})}
137
139
  )
138
140
  PATTERN
139
141
 
140
142
  # @!method access_modifier_with_attr?(node)
141
143
  def_node_matcher :access_modifier_with_attr?, <<~PATTERN
142
144
  (send nil? {:private :protected :public :module_function}
143
- (send nil? {:attr :attr_reader :attr_writer :attr_accessor} _))
145
+ (send nil? {:attr :attr_reader :attr_writer :attr_accessor} _+))
144
146
  PATTERN
145
147
 
146
148
  def on_send(node)
147
- return unless node.access_modifier?
148
- return if ALLOWED_NODE_TYPES.include?(node.parent&.type)
149
- return if allow_modifiers_on_symbols?(node)
150
- return if allow_modifiers_on_attrs?(node)
149
+ return if allowed?(node)
151
150
 
152
151
  if offense?(node)
153
152
  add_offense(node.loc.selector) do |corrector|
@@ -161,15 +160,22 @@ module RuboCop
161
160
 
162
161
  private
163
162
 
163
+ def allowed?(node)
164
+ !node.access_modifier? ||
165
+ ALLOWED_NODE_TYPES.include?(node.parent&.type) ||
166
+ allow_modifiers_on_symbols?(node) ||
167
+ allow_modifiers_on_attrs?(node)
168
+ end
169
+
164
170
  def autocorrect(corrector, node)
165
171
  case style
166
172
  when :group
167
- def_node = find_corresponding_def_node(node)
168
- return unless def_node
173
+ def_nodes = find_corresponding_def_nodes(node)
174
+ return unless def_nodes.any?
169
175
 
170
- replace_def(corrector, node, def_node)
176
+ replace_defs(corrector, node, def_nodes)
171
177
  when :inline
172
- remove_node(corrector, node)
178
+ remove_nodes(corrector, node)
173
179
  select_grouped_def_nodes(node).each do |grouped_def_node|
174
180
  insert_inline_modifier(corrector, grouped_def_node, node.method_name)
175
181
  end
@@ -194,6 +200,13 @@ module RuboCop
194
200
  (inline_style? && access_modifier_is_not_inlined?(node))
195
201
  end
196
202
 
203
+ def correctable_group_offense?(node)
204
+ return false unless group_style?
205
+ return false if allowed?(node)
206
+
207
+ access_modifier_is_inlined?(node) && find_corresponding_def_nodes(node).any?
208
+ end
209
+
197
210
  def group_style?
198
211
  style == :group
199
212
  end
@@ -212,7 +225,11 @@ module RuboCop
212
225
 
213
226
  def right_siblings_same_inline_method?(node)
214
227
  node.right_siblings.any? do |sibling|
215
- sibling.send_type? && sibling.method?(node.method_name) && !sibling.arguments.empty?
228
+ sibling.send_type? &&
229
+ correctable_group_offense?(sibling) &&
230
+ sibling.method?(node.method_name) &&
231
+ !sibling.arguments.empty? &&
232
+ find_corresponding_def_nodes(sibling).any?
216
233
  end
217
234
  end
218
235
 
@@ -226,14 +243,22 @@ module RuboCop
226
243
  end
227
244
  end
228
245
 
229
- def find_corresponding_def_node(node)
246
+ def find_corresponding_def_nodes(node)
230
247
  if access_modifier_with_symbol?(node)
231
- method_name = node.first_argument.respond_to?(:value) && node.first_argument.value
232
- node.parent.each_child_node(:def).find do |child|
233
- child.method?(method_name)
248
+ method_names = node.arguments.filter_map do |argument|
249
+ next unless argument.sym_type?
250
+
251
+ argument.respond_to?(:value) && argument.value
252
+ end
253
+
254
+ def_nodes = node.parent.each_child_node(:def).select do |child|
255
+ method_names.include?(child.method_name)
234
256
  end
257
+
258
+ # If there isn't a `def` node for each symbol, we will skip autocorrection.
259
+ def_nodes.size == method_names.size ? def_nodes : []
235
260
  else
236
- node.first_argument
261
+ [node.first_argument]
237
262
  end
238
263
  end
239
264
 
@@ -251,8 +276,8 @@ module RuboCop
251
276
  end.select(&:def_type?)
252
277
  end
253
278
 
254
- def replace_def(corrector, node, def_node)
255
- source = def_source(node, def_node)
279
+ def replace_defs(corrector, node, def_nodes)
280
+ source = def_source(node, def_nodes)
256
281
  argument_less_modifier_node = find_argument_less_modifier_node(node)
257
282
  if argument_less_modifier_node
258
283
  corrector.insert_after(argument_less_modifier_node, "\n\n#{source}")
@@ -264,20 +289,24 @@ module RuboCop
264
289
  return
265
290
  end
266
291
 
267
- remove_node(corrector, def_node)
268
- remove_node(corrector, node)
292
+ remove_nodes(corrector, *def_nodes, node)
269
293
  end
270
294
 
271
295
  def insert_inline_modifier(corrector, node, modifier_name)
272
296
  corrector.insert_before(node, "#{modifier_name} ")
273
297
  end
274
298
 
275
- def remove_node(corrector, node)
276
- corrector.remove(range_with_comments_and_lines(node))
299
+ def remove_nodes(corrector, *nodes)
300
+ nodes.each do |node|
301
+ corrector.remove(range_with_comments_and_lines(node))
302
+ end
277
303
  end
278
304
 
279
- def def_source(node, def_node)
280
- [*processed_source.ast_with_comments[node].map(&:text), def_node.source].join("\n")
305
+ def def_source(node, def_nodes)
306
+ [
307
+ *processed_source.ast_with_comments[node].map(&:text),
308
+ *def_nodes.map(&:source)
309
+ ].join("\n")
281
310
  end
282
311
  end
283
312
  end
@@ -61,7 +61,7 @@ module RuboCop
61
61
  private
62
62
 
63
63
  def modifier_form?(operation)
64
- return true if operation.and_type? || operation.or_type?
64
+ return true if operation.operator_keyword?
65
65
 
66
66
  operation.modifier_form?
67
67
  end
@@ -28,6 +28,7 @@ module RuboCop
28
28
  # # bad
29
29
  # (array1 & array2).any?
30
30
  # (array1 & array2).empty?
31
+ # (array1 & array2).none?
31
32
  #
32
33
  # # good
33
34
  # array1.intersect?(array2)
@@ -57,7 +58,7 @@ module RuboCop
57
58
  (send
58
59
  (begin
59
60
  (send $(...) :& $(...))
60
- ) ${:any? :empty?}
61
+ ) ${:any? :empty? :none?}
61
62
  )
62
63
  PATTERN
63
64
 
@@ -66,18 +67,18 @@ module RuboCop
66
67
  (send
67
68
  (begin
68
69
  (send $(...) :& $(...))
69
- ) ${:present? :any? :blank? :empty?}
70
+ ) ${:present? :any? :blank? :empty? :none?}
70
71
  )
71
72
  PATTERN
72
73
 
73
74
  MSG = 'Use `%<negated>s%<receiver>s.intersect?(%<argument>s)` ' \
74
75
  'instead of `(%<receiver>s & %<argument>s).%<method_name>s`.'
75
76
  STRAIGHT_METHODS = %i[present? any?].freeze
76
- NEGATED_METHODS = %i[blank? empty?].freeze
77
+ NEGATED_METHODS = %i[blank? empty? none?].freeze
77
78
  RESTRICT_ON_SEND = (STRAIGHT_METHODS + NEGATED_METHODS).freeze
78
79
 
79
80
  def on_send(node)
80
- return if (parent = node.parent) && (parent.block_type? || parent.numblock_type?)
81
+ return if node.block_literal?
81
82
  return unless (receiver, argument, method_name = bad_intersection_check?(node))
82
83
 
83
84
  message = message(receiver.source, argument.source, method_name)
@@ -71,7 +71,7 @@ module RuboCop
71
71
  PATTERN
72
72
 
73
73
  def on_send(node)
74
- return unless node.receiver.begin_type?
74
+ return unless node.receiver&.begin_type?
75
75
  return unless (preferred_method = preferred_method(node))
76
76
 
77
77
  bit_operation = node.receiver.children.first
@@ -481,7 +481,7 @@ module RuboCop
481
481
  end
482
482
 
483
483
  def conditional?(node)
484
- node.if_type? || node.or_type? || node.and_type?
484
+ node.if_type? || node.operator_keyword?
485
485
  end
486
486
 
487
487
  def array_or_range?(node)
@@ -106,7 +106,7 @@ module RuboCop
106
106
  when :or
107
107
  find_target(node.lhs)
108
108
  when :match_with_lvasgn
109
- lhs, rhs = *node
109
+ lhs, rhs = *node # rubocop:disable InternalAffairs/NodeDestructuring
110
110
  if lhs.regexp_type?
111
111
  rhs
112
112
  elsif rhs.regexp_type?
@@ -172,7 +172,7 @@ module RuboCop
172
172
  return collect_conditions(node.lhs, target, conditions) &&
173
173
  collect_conditions(node.rhs, target, conditions)
174
174
  when :match_with_lvasgn
175
- lhs, rhs = *node
175
+ lhs, rhs = *node # rubocop:disable InternalAffairs/NodeDestructuring
176
176
  condition_from_binary_op(lhs, rhs, target)
177
177
  when :send
178
178
  condition_from_send_node(node, target)
@@ -191,8 +191,7 @@ module RuboCop
191
191
  when :=~, :match, :match?
192
192
  condition_from_match_node(node, target)
193
193
  when :===
194
- lhs, _method, rhs = *node
195
- lhs if rhs == target
194
+ node.receiver if node.first_argument == target
196
195
  when :include?, :cover?
197
196
  condition_from_include_or_cover_node(node, target)
198
197
  end
@@ -200,14 +199,12 @@ module RuboCop
200
199
  # rubocop:enable Metrics/CyclomaticComplexity
201
200
 
202
201
  def condition_from_equality_node(node, target)
203
- lhs, _method, rhs = *node
204
- condition = condition_from_binary_op(lhs, rhs, target)
202
+ condition = condition_from_binary_op(node.receiver, node.first_argument, target)
205
203
  condition if condition && !class_reference?(condition)
206
204
  end
207
205
 
208
206
  def condition_from_match_node(node, target)
209
- lhs, _method, rhs = *node
210
- condition_from_binary_op(lhs, rhs, target)
207
+ condition_from_binary_op(node.receiver, node.first_argument, target)
211
208
  end
212
209
 
213
210
  def condition_from_include_or_cover_node(node, target)
@@ -263,11 +260,11 @@ module RuboCop
263
260
  def regexp_with_working_captures?(node)
264
261
  case node.type
265
262
  when :match_with_lvasgn
266
- lhs, _rhs = *node
263
+ lhs, _rhs = *node # rubocop:disable InternalAffairs/NodeDestructuring
267
264
  node.loc.selector.source == '=~' && regexp_with_named_captures?(lhs)
268
265
  when :send
269
- lhs, method, rhs = *node
270
- method == :match && [lhs, rhs].any? { |n| regexp_with_named_captures?(n) }
266
+ node.method?(:match) &&
267
+ [node.receiver, node.first_argument].any? { |n| regexp_with_named_captures?(n) }
271
268
  end
272
269
  end
273
270
 
@@ -57,6 +57,9 @@ module RuboCop
57
57
 
58
58
  REGEXP = /(?<keyword>\S+).*#/.freeze
59
59
 
60
+ SUBCLASS_DEFINITION = /\A\s*class\s+\w+\s*<\s*\w+/.freeze
61
+ METHOD_DEFINITION = /\A\s*def\s/.freeze
62
+
60
63
  def on_new_investigation
61
64
  processed_source.comments.each do |comment|
62
65
  next unless offensive?(comment) && (match = source_line(comment).match(REGEXP))
@@ -93,7 +96,14 @@ module RuboCop
93
96
  end
94
97
 
95
98
  def rbs_inline_annotation?(line, comment)
96
- comment.text.start_with?('#:') && line.start_with?(/\A\s*def\s/)
99
+ case line
100
+ when SUBCLASS_DEFINITION
101
+ comment.text.start_with?(/#\[.+\]/)
102
+ when METHOD_DEFINITION
103
+ comment.text.start_with?('#:')
104
+ else
105
+ false
106
+ end
97
107
  end
98
108
  end
99
109
  end