rubocop 1.76.2 → 1.77.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +19 -0
  4. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +5 -2
  5. data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
  6. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +0 -22
  7. data/lib/rubocop/cop/gemspec/require_mfa.rb +15 -1
  8. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +4 -4
  9. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -1
  10. data/lib/rubocop/cop/layout/line_length.rb +26 -5
  11. data/lib/rubocop/cop/layout/space_before_brackets.rb +2 -9
  12. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +7 -2
  13. data/lib/rubocop/cop/lint/float_comparison.rb +4 -4
  14. data/lib/rubocop/cop/lint/literal_as_condition.rb +2 -2
  15. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  16. data/lib/rubocop/cop/lint/self_assignment.rb +25 -0
  17. data/lib/rubocop/cop/lint/useless_access_modifier.rb +8 -0
  18. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +3 -3
  19. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  20. data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
  21. data/lib/rubocop/cop/mixin/line_length_help.rb +24 -8
  22. data/lib/rubocop/cop/naming/file_name.rb +2 -2
  23. data/lib/rubocop/cop/naming/predicate_method.rb +42 -6
  24. data/lib/rubocop/cop/naming/predicate_prefix.rb +2 -2
  25. data/lib/rubocop/cop/style/case_like_if.rb +1 -1
  26. data/lib/rubocop/cop/style/collection_querying.rb +167 -0
  27. data/lib/rubocop/cop/style/exponential_notation.rb +2 -2
  28. data/lib/rubocop/cop/style/fetch_env_var.rb +32 -6
  29. data/lib/rubocop/cop/style/hash_conversion.rb +12 -3
  30. data/lib/rubocop/cop/style/if_unless_modifier.rb +11 -2
  31. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
  32. data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
  33. data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -1
  34. data/lib/rubocop/cop/style/redundant_self.rb +3 -0
  35. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -1
  36. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  37. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  38. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  39. data/lib/rubocop/lsp/diagnostic.rb +4 -4
  40. data/lib/rubocop/version.rb +1 -1
  41. data/lib/rubocop.rb +2 -0
  42. data/lib/ruby_lsp/rubocop/addon.rb +2 -2
  43. metadata +6 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c98c6b67493a9eeb135c1e86846e068746676cd7caba305df7343f6da5a9307
4
- data.tar.gz: a5e75c620016505e918bc98e273a729f14388b6c3cf95358c4975d785ca7fa57
3
+ metadata.gz: 871a632c96e6a5c92e57b651037eaf7efd7412e64ac77440d5275027ef791d4e
4
+ data.tar.gz: f375ec6479b1f90193cd39e863411707d60cd071e170888005339d89a19ea65b
5
5
  SHA512:
6
- metadata.gz: '08701aa9d2fa3f7a1cf2b950b8bdf8640c47965345c3572645dd04f73507142ebf08aa16d5e7ab829a9e74330d45b4280ef700a7974eb02d7cf29e5890f67bb8'
7
- data.tar.gz: 8d0f787edacfee68d6e6bc13db5c9f2247f137c3074fec0af47dae1b6b0b51403e9d071d1a40a81529271d35d1954a5848e16c489ebb175c9b2a24a4c1192a48
6
+ metadata.gz: f8dac3eb5cb12741c110c8726ec64595cefb89700527144cc590d7febb676164e3902dff171594278f7895d1c3df336dea3e14f869d285a0c7080b1467bd6362
7
+ data.tar.gz: 4aadc7a712774810e1815f4f31bea43fc6d9e121a547621f57894c7df848a6459dfc962af0fb725f4fef6e2017b6a499c203cc05a4d2879d0e50aceaee156b95
data/README.md CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
53
53
  in your `Gemfile`:
54
54
 
55
55
  ```rb
56
- gem 'rubocop', '~> 1.76', require: false
56
+ gem 'rubocop', '~> 1.77', require: false
57
57
  ```
58
58
 
59
59
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -281,6 +281,13 @@ Gemspec/AddRuntimeDependency:
281
281
  Include:
282
282
  - '**/*.gemspec'
283
283
 
284
+ Gemspec/AttributeAssignment:
285
+ Description: 'Use consistent style for Gemspec attributes assignment.'
286
+ Enabled: pending
287
+ VersionAdded: '1.77'
288
+ Include:
289
+ - '**/*.gemspec'
290
+
284
291
  Gemspec/DependencyVersion:
285
292
  Description: 'Requires or forbids specifying gem dependency versions.'
286
293
  Enabled: false
@@ -1095,6 +1102,7 @@ Layout/LineLength:
1095
1102
  # To make it possible to copy or click on URIs in the code, we allow lines
1096
1103
  # containing a URI to be longer than Max.
1097
1104
  AllowURI: true
1105
+ AllowQualifiedName: true
1098
1106
  URISchemes:
1099
1107
  - http
1100
1108
  - https
@@ -2400,6 +2408,7 @@ Lint/SelfAssignment:
2400
2408
  Description: 'Checks for self-assignments.'
2401
2409
  Enabled: true
2402
2410
  VersionAdded: '0.89'
2411
+ AllowRBSInlineAnnotation: false
2403
2412
 
2404
2413
  Lint/SendWithMixinArgument:
2405
2414
  Description: 'Checks for `send` method when using mixin.'
@@ -3660,6 +3669,13 @@ Style/CollectionMethods:
3660
3669
  - inject
3661
3670
  - reduce
3662
3671
 
3672
+ Style/CollectionQuerying:
3673
+ Description: 'Prefer `Enumerable` predicate methods over expressions with `count`.'
3674
+ StyleGuide: '#collection-querying'
3675
+ Enabled: pending
3676
+ VersionAdded: '1.77'
3677
+ Safe: false
3678
+
3663
3679
  Style/ColonMethodCall:
3664
3680
  Description: 'Do not use :: for method call.'
3665
3681
  StyleGuide: '#double-colons'
@@ -4061,6 +4077,9 @@ Style/FetchEnvVar:
4061
4077
  VersionAdded: '1.28'
4062
4078
  # Environment variables to be excluded from the inspection.
4063
4079
  AllowedVars: []
4080
+ # When `true`, autocorrects `ENV["key"]` to `ENV.fetch("key", nil)`.
4081
+ # When `false`, autocorrects `ENV["key"]` to `ENV.fetch("key")`.
4082
+ DefaultToNil: true
4064
4083
 
4065
4084
  Style/FileEmpty:
4066
4085
  Description: >-
@@ -10,8 +10,11 @@ module RuboCop
10
10
  COMMA_REGEXP = /(?<=\))\s*,/.freeze
11
11
 
12
12
  def correct(corrector, node)
13
- corrector.remove(node.loc.begin)
14
- corrector.remove(node.loc.end)
13
+ buffer = node.source_range.source_buffer
14
+ corrector.remove(range_with_surrounding_space(range: node.loc.begin, buffer: buffer,
15
+ side: :right, whitespace: true))
16
+ corrector.remove(range_with_surrounding_space(range: node.loc.end, buffer: buffer,
17
+ side: :left))
15
18
  handle_orphaned_comma(corrector, node)
16
19
 
17
20
  return unless ternary_condition?(node) && next_char_is_question_mark?(node)
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Gemspec
6
+ # Use consistent style for Gemspec attributes assignment.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # # This example uses two styles for assignment of metadata attribute.
12
+ # Gem::Specification.new do |spec|
13
+ # spec.metadata = { 'key' => 'value' }
14
+ # spec.metadata['another-key'] = 'another-value'
15
+ # end
16
+ #
17
+ # # good
18
+ # Gem::Specification.new do |spec|
19
+ # spec.metadata['key'] = 'value'
20
+ # spec.metadata['another-key'] = 'another-value'
21
+ # end
22
+ #
23
+ # # good
24
+ # Gem::Specification.new do |spec|
25
+ # spec.metadata = { 'key' => 'value', 'another-key' => 'another-value' }
26
+ # end
27
+ #
28
+ # # bad
29
+ # # This example uses two styles for assignment of authors attribute.
30
+ # Gem::Specification.new do |spec|
31
+ # spec.authors = %w[author-0 author-1]
32
+ # spec.authors[2] = 'author-2'
33
+ # end
34
+ #
35
+ # # good
36
+ # Gem::Specification.new do |spec|
37
+ # spec.authors = %w[author-0 author-1 author-2]
38
+ # end
39
+ #
40
+ # # good
41
+ # Gem::Specification.new do |spec|
42
+ # spec.authors[0] = 'author-0'
43
+ # spec.authors[1] = 'author-1'
44
+ # spec.authors[2] = 'author-2'
45
+ # end
46
+ #
47
+ # # good
48
+ # # This example uses consistent assignment per attribute,
49
+ # # even though two different styles are used overall.
50
+ # Gem::Specification.new do |spec|
51
+ # spec.metadata = { 'key' => 'value' }
52
+ # spec.authors[0] = 'author-0'
53
+ # spec.authors[1] = 'author-1'
54
+ # spec.authors[2] = 'author-2'
55
+ # end
56
+ #
57
+ class AttributeAssignment < Base
58
+ include GemspecHelp
59
+
60
+ MSG = 'Use consistent style for Gemspec attributes assignment.'
61
+
62
+ def on_new_investigation
63
+ return if processed_source.blank?
64
+
65
+ assignments = source_assignments(processed_source.ast)
66
+ indexed_assignments = source_indexed_assignments(processed_source.ast)
67
+
68
+ assignments.keys.intersection(indexed_assignments.keys).each do |attribute|
69
+ indexed_assignments[attribute].each do |node|
70
+ add_offense(node)
71
+ end
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def source_assignments(ast)
78
+ assignment_method_declarations(ast)
79
+ .select(&:assignment_method?)
80
+ .group_by(&:method_name)
81
+ .transform_keys { |method_name| method_name.to_s.delete_suffix('=').to_sym }
82
+ end
83
+
84
+ def source_indexed_assignments(ast)
85
+ indexed_assignment_method_declarations(ast)
86
+ .group_by { |node| node.children.first.method_name }
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -54,22 +54,6 @@ module RuboCop
54
54
  MSG = '`%<assignment>s` method calls already given on line ' \
55
55
  '%<line_of_first_occurrence>d of the gemspec.'
56
56
 
57
- # @!method assignment_method_declarations(node)
58
- def_node_search :assignment_method_declarations, <<~PATTERN
59
- (send
60
- (lvar {#match_block_variable_name? :_1 :it}) _ ...)
61
- PATTERN
62
-
63
- # @!method indexed_assignment_method_declarations(node)
64
- def_node_search :indexed_assignment_method_declarations, <<~PATTERN
65
- (send
66
- (send (lvar {#match_block_variable_name? :_1 :it}) _)
67
- :[]=
68
- literal?
69
- _
70
- )
71
- PATTERN
72
-
73
57
  def on_new_investigation
74
58
  return if processed_source.blank?
75
59
 
@@ -96,12 +80,6 @@ module RuboCop
96
80
  end
97
81
  end
98
82
 
99
- def match_block_variable_name?(receiver_name)
100
- gem_specification(processed_source.ast) do |block_variable_name|
101
- return block_variable_name == receiver_name
102
- end
103
- end
104
-
105
83
  def duplicated_assignment_method_nodes
106
84
  assignment_method_declarations(processed_source.ast)
107
85
  .select(&:assignment_method?)
@@ -74,6 +74,14 @@ module RuboCop
74
74
  }
75
75
  PATTERN
76
76
 
77
+ # @!method metadata_assignment(node)
78
+ def_node_search :metadata_assignment, <<~PATTERN
79
+ `{
80
+ (send _ :metadata= _)
81
+ (send (send _ :metadata) :[]= (str _) _)
82
+ }
83
+ PATTERN
84
+
77
85
  # @!method rubygems_mfa_required(node)
78
86
  def_node_search :rubygems_mfa_required, <<~PATTERN
79
87
  (pair (str "rubygems_mfa_required") $_)
@@ -131,9 +139,15 @@ module RuboCop
131
139
  end
132
140
 
133
141
  def insert_mfa_required(corrector, node, block_var)
134
- corrector.insert_before(node.loc.end, <<~RUBY)
142
+ require_mfa_directive = <<~RUBY.strip
135
143
  #{block_var}.metadata['rubygems_mfa_required'] = 'true'
136
144
  RUBY
145
+
146
+ if (last_assignment = metadata_assignment(processed_source.ast).to_a.last)
147
+ corrector.insert_after(last_assignment, "\n#{require_mfa_directive}")
148
+ else
149
+ corrector.insert_before(node.loc.end, "#{require_mfa_directive}\n")
150
+ end
137
151
  end
138
152
 
139
153
  def change_value(corrector, value)
@@ -110,8 +110,8 @@ module RuboCop
110
110
  def directive_offense_type(directive, actual_name)
111
111
  return :missing_directive unless directive
112
112
 
113
- return :wrong_scope if wrong_scope(directive, actual_name)
114
- return :no_scope if no_scope(directive, actual_name)
113
+ return :wrong_scope if wrong_scope?(directive, actual_name)
114
+ return :no_scope if no_scope?(directive, actual_name)
115
115
 
116
116
  # The method directive being prefixed by 'self.' is always an offense.
117
117
  # The matched method_name does not contain the receiver but the
@@ -121,11 +121,11 @@ module RuboCop
121
121
  end
122
122
  end
123
123
 
124
- def wrong_scope(directive, actual_name)
124
+ def wrong_scope?(directive, actual_name)
125
125
  !actual_name.start_with?('self.') && directive[:has_scope_directive]
126
126
  end
127
127
 
128
- def no_scope(directive, actual_name)
128
+ def no_scope?(directive, actual_name)
129
129
  actual_name.start_with?('self.') && !directive[:has_scope_directive]
130
130
  end
131
131
 
@@ -161,7 +161,7 @@ module RuboCop
161
161
  elements.flat_map do |e|
162
162
  e.loc.column
163
163
  end
164
- end.uniq.count == 1
164
+ end.uniq.one?
165
165
  end
166
166
 
167
167
  def first_argument_line(elements)
@@ -258,7 +258,7 @@ module RuboCop
258
258
  if ignore_cop_directives? && directive_on_source_line?(line_index)
259
259
  return check_directive_line(line, line_index)
260
260
  end
261
- return check_uri_line(line, line_index) if allow_uri?
261
+ return check_line_for_exemptions(line, line_index) if allow_uri? || allow_qualified_name?
262
262
 
263
263
  register_offense(excess_range(nil, line, line_index), line, line_index)
264
264
  end
@@ -358,11 +358,32 @@ module RuboCop
358
358
  )
359
359
  end
360
360
 
361
- def check_uri_line(line, line_index)
362
- uri_range = find_excessive_uri_range(line)
363
- return if uri_range && allowed_uri_position?(line, uri_range)
361
+ def check_line_for_exemptions(line, line_index)
362
+ uri_range = range_if_applicable(line, :uri)
363
+ qualified_name_range = range_if_applicable(line, :qualified_name)
364
364
 
365
- register_offense(excess_range(uri_range, line, line_index), line, line_index)
365
+ return if allowed_combination?(line, uri_range, qualified_name_range)
366
+
367
+ range = uri_range || qualified_name_range
368
+ register_offense(excess_range(range, line, line_index), line, line_index)
369
+ end
370
+
371
+ def range_if_applicable(line, type)
372
+ return unless type == :uri ? allow_uri? : allow_qualified_name?
373
+
374
+ find_excessive_range(line, type)
375
+ end
376
+
377
+ def allowed_combination?(line, uri_range, qualified_name_range)
378
+ if uri_range && qualified_name_range
379
+ allowed_position?(line, uri_range) && allowed_position?(line, qualified_name_range)
380
+ elsif uri_range
381
+ allowed_position?(line, uri_range)
382
+ elsif qualified_name_range
383
+ allowed_position?(line, qualified_name_range)
384
+ else
385
+ false
386
+ end
366
387
  end
367
388
 
368
389
  def breakable_dstr?(node)
@@ -22,10 +22,11 @@ module RuboCop
22
22
  RESTRICT_ON_SEND = %i[[] []=].freeze
23
23
 
24
24
  def on_send(node)
25
+ return if node.loc.dot
26
+
25
27
  receiver_end_pos = node.receiver.source_range.end_pos
26
28
  selector_begin_pos = node.loc.selector.begin_pos
27
29
  return if receiver_end_pos >= selector_begin_pos
28
- return if dot_before_brackets?(node, receiver_end_pos, selector_begin_pos)
29
30
 
30
31
  range = range_between(receiver_end_pos, selector_begin_pos)
31
32
 
@@ -33,14 +34,6 @@ module RuboCop
33
34
  corrector.remove(range)
34
35
  end
35
36
  end
36
-
37
- private
38
-
39
- def dot_before_brackets?(node, receiver_end_pos, selector_begin_pos)
40
- return false unless node.loc.respond_to?(:dot) && (dot = node.loc.dot)
41
-
42
- dot.begin_pos == receiver_end_pos && dot.end_pos == selector_begin_pos
43
- end
44
37
  end
45
38
  end
46
39
  end
@@ -86,6 +86,7 @@ module RuboCop
86
86
  def on_array(node)
87
87
  return if node.array_type? && !node.square_brackets?
88
88
 
89
+ node = find_node_with_brackets(node)
89
90
  tokens, left, right = array_brackets(node)
90
91
  return unless left && right
91
92
 
@@ -102,6 +103,10 @@ module RuboCop
102
103
 
103
104
  private
104
105
 
106
+ def find_node_with_brackets(node)
107
+ node.ancestors.find(&:const_pattern_type?) || node
108
+ end
109
+
105
110
  def autocorrect(corrector, node)
106
111
  tokens, left, right = array_brackets(node)
107
112
 
@@ -119,7 +124,7 @@ module RuboCop
119
124
  def array_brackets(node)
120
125
  tokens = processed_source.tokens_within(node)
121
126
 
122
- left = tokens.find(&:left_array_bracket?)
127
+ left = tokens.find(&:left_bracket?)
123
128
  right = tokens.reverse_each.find(&:right_bracket?)
124
129
 
125
130
  [tokens, left, right]
@@ -192,7 +197,7 @@ module RuboCop
192
197
  if side == :right
193
198
  processed_source.tokens_within(node)[i].right_bracket?
194
199
  else
195
- processed_source.tokens_within(node)[i].left_array_bracket?
200
+ processed_source.tokens_within(node)[i].left_bracket?
196
201
  end
197
202
  end
198
203
 
@@ -94,7 +94,7 @@ module RuboCop
94
94
  when :float
95
95
  true
96
96
  when :send
97
- check_send(node)
97
+ float_send?(node)
98
98
  when :begin
99
99
  float?(node.children.first)
100
100
  else
@@ -108,18 +108,18 @@ module RuboCop
108
108
  (node.numeric_type? && node.value.zero?) || node.nil_type?
109
109
  end
110
110
 
111
- def check_send(node)
111
+ def float_send?(node)
112
112
  if node.arithmetic_operation?
113
113
  float?(node.receiver) || float?(node.first_argument)
114
114
  elsif FLOAT_RETURNING_METHODS.include?(node.method_name)
115
115
  true
116
116
  elsif node.receiver&.float_type?
117
117
  FLOAT_INSTANCE_METHODS.include?(node.method_name) ||
118
- check_numeric_returning_method(node)
118
+ numeric_returning_method?(node)
119
119
  end
120
120
  end
121
121
 
122
- def check_numeric_returning_method(node)
122
+ def numeric_returning_method?(node)
123
123
  return false unless node.receiver
124
124
 
125
125
  case node.method_name
@@ -228,7 +228,7 @@ module RuboCop
228
228
  )
229
229
  end
230
230
 
231
- def condition_evaluation(node, cond)
231
+ def condition_evaluation?(node, cond)
232
232
  if node.unless?
233
233
  cond.falsey_literal?
234
234
  else
@@ -238,7 +238,7 @@ module RuboCop
238
238
 
239
239
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
240
240
  def correct_if_node(node, cond)
241
- result = condition_evaluation(node, cond)
241
+ result = condition_evaluation?(node, cond)
242
242
 
243
243
  new_node = if node.elsif? && result
244
244
  "else\n #{range_with_comments(node.if_branch).source}"
@@ -73,7 +73,7 @@ module RuboCop
73
73
  end
74
74
 
75
75
  def redundant_group?(expr)
76
- expr.is?(:passive, :group) && expr.count { |child| child.type != :free_space } == 1
76
+ expr.is?(:passive, :group) && expr.one? { |child| child.type != :free_space }
77
77
  end
78
78
 
79
79
  def redundantly_quantifiable?(node)
@@ -23,6 +23,14 @@ module RuboCop
23
23
  # # good (method calls possibly can return different results)
24
24
  # hash[foo] = hash[foo]
25
25
  #
26
+ # @example AllowRBSInlineAnnotation:true
27
+ # # good
28
+ # foo = foo #: Integer
29
+ # foo, bar = foo, bar #: Integer
30
+ # Foo = Foo #: Integer
31
+ # hash['foo'] = hash['foo'] #: Integer
32
+ # obj.attr = obj.attr #: Integer
33
+ #
26
34
  class SelfAssignment < Base
27
35
  MSG = 'Self-assignment detected.'
28
36
 
@@ -34,6 +42,8 @@ module RuboCop
34
42
  }.freeze
35
43
 
36
44
  def on_send(node)
45
+ return if allow_rbs_inline_annotation? && rbs_inline_annotation?(node.receiver)
46
+
37
47
  if node.method?(:[]=)
38
48
  handle_key_assignment(node) if node.arguments.size == 2
39
49
  elsif node.assignment_method?
@@ -44,6 +54,7 @@ module RuboCop
44
54
 
45
55
  def on_lvasgn(node)
46
56
  return unless node.rhs
57
+ return if allow_rbs_inline_annotation? && rbs_inline_annotation?(node.rhs)
47
58
 
48
59
  rhs_type = ASSIGNMENT_TYPE_TO_RHS_TYPE[node.type]
49
60
 
@@ -55,16 +66,22 @@ module RuboCop
55
66
 
56
67
  def on_casgn(node)
57
68
  return unless node.rhs&.const_type?
69
+ return if allow_rbs_inline_annotation? && rbs_inline_annotation?(node.rhs)
58
70
 
59
71
  add_offense(node) if node.namespace == node.rhs.namespace &&
60
72
  node.short_name == node.rhs.short_name
61
73
  end
62
74
 
63
75
  def on_masgn(node)
76
+ first_lhs = node.lhs.assignments.first
77
+ return if allow_rbs_inline_annotation? && rbs_inline_annotation?(first_lhs)
78
+
64
79
  add_offense(node) if multiple_self_assignment?(node)
65
80
  end
66
81
 
67
82
  def on_or_asgn(node)
83
+ return if allow_rbs_inline_annotation? && rbs_inline_annotation?(node.lhs)
84
+
68
85
  add_offense(node) if rhs_matches_lhs?(node.rhs, node.lhs)
69
86
  end
70
87
  alias on_and_asgn on_or_asgn
@@ -108,6 +125,14 @@ module RuboCop
108
125
  add_offense(node)
109
126
  end
110
127
  end
128
+
129
+ def rbs_inline_annotation?(node)
130
+ processed_source.ast_with_comments[node].any? { |comment| comment.text.start_with?('#:') }
131
+ end
132
+
133
+ def allow_rbs_inline_annotation?
134
+ cop_config['AllowRBSInlineAnnotation']
135
+ end
111
136
  end
112
137
  end
113
138
  end
@@ -274,6 +274,10 @@ module RuboCop
274
274
 
275
275
  def any_method_definition?(child)
276
276
  cop_config.fetch('MethodCreatingMethods', []).any? do |m|
277
+ # Some users still have `"included"` in their `MethodCreatingMethods` configurations,
278
+ # so to prevent Ruby method redefinition warnings let's just skip this value.
279
+ next if m == 'included'
280
+
277
281
  matcher_name = :"#{m}_method?"
278
282
  unless respond_to?(matcher_name)
279
283
  self.class.def_node_matcher matcher_name, <<~PATTERN
@@ -296,7 +300,11 @@ module RuboCop
296
300
  end
297
301
 
298
302
  def any_context_creating_methods?(child)
303
+ # Some users still have `"included"` in their `ContextCreatingMethods` configurations,
304
+ # so to prevent Ruby method redefinition warnings let's just skip this value.
299
305
  cop_config.fetch('ContextCreatingMethods', []).any? do |m|
306
+ next if m == 'included'
307
+
300
308
  matcher_name = :"#{m}_block?"
301
309
  unless respond_to?(matcher_name)
302
310
  self.class.def_node_matcher matcher_name, <<~PATTERN
@@ -89,7 +89,7 @@ module RuboCop
89
89
  private
90
90
 
91
91
  def inspect_def(node, def_node)
92
- return if allowed_arguments(def_node.arguments)
92
+ return if allowed_arguments?(def_node.arguments)
93
93
 
94
94
  add_offense(node.loc.selector, message: format(MSG, method_name: def_node.method_name))
95
95
  end
@@ -101,7 +101,7 @@ module RuboCop
101
101
  definition = find_method_definition(node, method_name)
102
102
 
103
103
  return unless definition
104
- return if allowed_arguments(definition.arguments)
104
+ return if allowed_arguments?(definition.arguments)
105
105
 
106
106
  add_offense(node, message: format(MSG, method_name: method_name))
107
107
  end
@@ -115,7 +115,7 @@ module RuboCop
115
115
  end
116
116
 
117
117
  # `ruby2_keywords` is only allowed if there's a `restarg` and no keyword arguments
118
- def allowed_arguments(arguments)
118
+ def allowed_arguments?(arguments)
119
119
  return false if arguments.empty?
120
120
 
121
121
  arguments.each_child_node(:restarg).any? &&
@@ -66,7 +66,7 @@ module RuboCop
66
66
  end
67
67
 
68
68
  # @deprecated Use processed_source.line_with_comment?(line)
69
- def end_of_line_comment(line)
69
+ def end_of_line_comment(line) # rubocop:disable Naming/PredicateMethod
70
70
  warn Rainbow(<<~WARNING).yellow, uplevel: 1
71
71
  `end_of_line_comment` is deprecated. Use `processed_source.line_with_comment?` instead.
72
72
  WARNING
@@ -25,6 +25,28 @@ module RuboCop
25
25
  (args
26
26
  (arg $_)) ...)
27
27
  PATTERN
28
+
29
+ # @!method assignment_method_declarations(node)
30
+ def_node_search :assignment_method_declarations, <<~PATTERN
31
+ (send
32
+ (lvar {#match_block_variable_name? :_1 :it}) _ ...)
33
+ PATTERN
34
+
35
+ # @!method indexed_assignment_method_declarations(node)
36
+ def_node_search :indexed_assignment_method_declarations, <<~PATTERN
37
+ (send
38
+ (send (lvar {#match_block_variable_name? :_1 :it}) _)
39
+ :[]=
40
+ literal?
41
+ _
42
+ )
43
+ PATTERN
44
+
45
+ def match_block_variable_name?(receiver_name)
46
+ gem_specification(processed_source.ast) do |block_variable_name|
47
+ return block_variable_name == receiver_name
48
+ end
49
+ end
28
50
  end
29
51
  end
30
52
  end