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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +19 -0
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +5 -2
- data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +0 -22
- data/lib/rubocop/cop/gemspec/require_mfa.rb +15 -1
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +4 -4
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +26 -5
- data/lib/rubocop/cop/layout/space_before_brackets.rb +2 -9
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +7 -2
- data/lib/rubocop/cop/lint/float_comparison.rb +4 -4
- data/lib/rubocop/cop/lint/literal_as_condition.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
- data/lib/rubocop/cop/lint/self_assignment.rb +25 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +8 -0
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +3 -3
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
- data/lib/rubocop/cop/mixin/line_length_help.rb +24 -8
- data/lib/rubocop/cop/naming/file_name.rb +2 -2
- data/lib/rubocop/cop/naming/predicate_method.rb +42 -6
- data/lib/rubocop/cop/naming/predicate_prefix.rb +2 -2
- data/lib/rubocop/cop/style/case_like_if.rb +1 -1
- data/lib/rubocop/cop/style/collection_querying.rb +167 -0
- data/lib/rubocop/cop/style/exponential_notation.rb +2 -2
- data/lib/rubocop/cop/style/fetch_env_var.rb +32 -6
- data/lib/rubocop/cop/style/hash_conversion.rb +12 -3
- data/lib/rubocop/cop/style/if_unless_modifier.rb +11 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -1
- data/lib/rubocop/cop/style/redundant_self.rb +3 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
- data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/lsp/diagnostic.rb +4 -4
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +2 -0
- data/lib/ruby_lsp/rubocop/addon.rb +2 -2
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 871a632c96e6a5c92e57b651037eaf7efd7412e64ac77440d5275027ef791d4e
|
4
|
+
data.tar.gz: f375ec6479b1f90193cd39e863411707d60cd071e170888005339d89a19ea65b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
-
|
14
|
-
corrector.remove(node.loc.
|
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
|
-
|
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
|
|
@@ -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
|
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
|
362
|
-
uri_range
|
363
|
-
|
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
|
-
|
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(&:
|
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].
|
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
|
-
|
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
|
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
|
-
|
118
|
+
numeric_returning_method?(node)
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
-
def
|
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.
|
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
|