rubocop 1.75.7 → 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 +20 -14
- data/config/default.yml +72 -7
- data/config/obsoletion.yml +6 -3
- data/lib/rubocop/cop/autocorrect_logic.rb +18 -10
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
- 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/ordered_dependencies.rb +1 -1
- 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/internal_affairs/node_pattern_groups.rb +1 -0
- data/lib/rubocop/cop/layout/class_structure.rb +35 -0
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +7 -3
- data/lib/rubocop/cop/layout/first_argument_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/ambiguous_range.rb +5 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
- data/lib/rubocop/cop/lint/empty_interpolation.rb +3 -1
- data/lib/rubocop/cop/lint/float_comparison.rb +31 -4
- data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
- data/lib/rubocop/cop/lint/literal_as_condition.rb +19 -27
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +4 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +25 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +5 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +29 -4
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +90 -0
- data/lib/rubocop/cop/lint/useless_or.rb +98 -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/frozen_string_literal.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/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/naming/file_name.rb +2 -2
- data/lib/rubocop/cop/naming/predicate_method.rb +281 -0
- data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +4 -4
- 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/conditional_assignment.rb +3 -1
- data/lib/rubocop/cop/style/def_with_parentheses.rb +18 -5
- data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +100 -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 +13 -6
- data/lib/rubocop/cop/style/it_block_parameter.rb +33 -14
- data/lib/rubocop/cop/style/map_to_hash.rb +11 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/min_max_comparison.rb +13 -5
- data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
- data/lib/rubocop/cop/style/redundant_format.rb +6 -1
- data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +26 -5
- data/lib/rubocop/cop/style/redundant_self.rb +8 -5
- data/lib/rubocop/cop/style/safe_navigation.rb +24 -11
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/team.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/rspec/expect_offense.rb +9 -3
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +8 -1
- data/lib/ruby_lsp/rubocop/addon.rb +2 -2
- metadata +14 -7
@@ -116,7 +116,7 @@ module RuboCop
|
|
116
116
|
def allowed_only_before_style?(node)
|
117
117
|
if node.special_modifier?
|
118
118
|
return true if processed_source[node.last_line] == 'end'
|
119
|
-
return false if
|
119
|
+
return false if next_line_empty_and_exists?(node.last_line)
|
120
120
|
end
|
121
121
|
|
122
122
|
previous_line_empty?(node.first_line)
|
@@ -129,7 +129,7 @@ module RuboCop
|
|
129
129
|
when :around
|
130
130
|
corrector.insert_after(line, "\n") unless next_line_empty?(node.last_line)
|
131
131
|
when :only_before
|
132
|
-
if
|
132
|
+
if next_line_empty_and_exists?(node.last_line)
|
133
133
|
range = next_empty_line_range(node)
|
134
134
|
|
135
135
|
corrector.remove(range)
|
@@ -138,7 +138,7 @@ module RuboCop
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def previous_line_ignoring_comments(processed_source, send_line)
|
141
|
-
processed_source[0..send_line - 2].reverse.find { |line| !comment_line?(line) }
|
141
|
+
processed_source[0..(send_line - 2)].reverse.find { |line| !comment_line?(line) }
|
142
142
|
end
|
143
143
|
|
144
144
|
def previous_line_empty?(send_line)
|
@@ -154,6 +154,10 @@ module RuboCop
|
|
154
154
|
body_end?(last_send_line) || next_line.blank?
|
155
155
|
end
|
156
156
|
|
157
|
+
def next_line_empty_and_exists?(last_send_line)
|
158
|
+
next_line_empty?(last_send_line) && last_send_line.next != processed_source.lines.size
|
159
|
+
end
|
160
|
+
|
157
161
|
def empty_lines_around?(node)
|
158
162
|
previous_line_empty?(node.first_line) && next_line_empty?(node.last_line)
|
159
163
|
end
|
@@ -155,7 +155,7 @@ module RuboCop
|
|
155
155
|
def on_send(node)
|
156
156
|
return unless should_check?(node)
|
157
157
|
return if same_line?(node, node.first_argument)
|
158
|
-
return if
|
158
|
+
return if enforce_first_argument_with_fixed_indentation? &&
|
159
159
|
!enable_layout_first_method_argument_line_break?
|
160
160
|
|
161
161
|
indent = base_indentation(node) + configured_indentation_width
|
@@ -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
|
|
@@ -27,7 +27,9 @@ module RuboCop
|
|
27
27
|
# @example
|
28
28
|
# # bad
|
29
29
|
# x || 1..2
|
30
|
+
# x - 1..2
|
30
31
|
# (x || 1..2)
|
32
|
+
# x || 1..y || 2
|
31
33
|
# 1..2.to_a
|
32
34
|
#
|
33
35
|
# # good, unambiguous
|
@@ -41,6 +43,7 @@ module RuboCop
|
|
41
43
|
#
|
42
44
|
# # good, ambiguity removed
|
43
45
|
# x || (1..2)
|
46
|
+
# (x - 1)..2
|
44
47
|
# (x || 1)..2
|
45
48
|
# (x || 1)..(y || 2)
|
46
49
|
# (1..2).to_a
|
@@ -96,6 +99,8 @@ module RuboCop
|
|
96
99
|
# to avoid the ambiguity of `1..2.to_a`.
|
97
100
|
return false if node.receiver&.basic_literal?
|
98
101
|
|
102
|
+
return false if node.operator_method? && !node.method?(:[])
|
103
|
+
|
99
104
|
require_parentheses_for_method_chain? || node.receiver.nil?
|
100
105
|
end
|
101
106
|
|
@@ -19,7 +19,9 @@ module RuboCop
|
|
19
19
|
MSG = 'Empty interpolation detected.'
|
20
20
|
|
21
21
|
def on_interpolation(begin_node)
|
22
|
-
|
22
|
+
node_children = begin_node.children.dup
|
23
|
+
node_children.delete_if { |e| e.nil_type? || (e.basic_literal? && e.str_content&.empty?) }
|
24
|
+
return unless node_children.empty?
|
23
25
|
|
24
26
|
add_offense(begin_node) { |corrector| corrector.remove(begin_node) }
|
25
27
|
end
|
@@ -15,6 +15,14 @@ module RuboCop
|
|
15
15
|
# x == 0.1
|
16
16
|
# x != 0.1
|
17
17
|
#
|
18
|
+
# # bad
|
19
|
+
# case value
|
20
|
+
# when 1.0
|
21
|
+
# foo
|
22
|
+
# when 2.0
|
23
|
+
# bar
|
24
|
+
# end
|
25
|
+
#
|
18
26
|
# # good - using BigDecimal
|
19
27
|
# x.to_d == 0.1.to_d
|
20
28
|
#
|
@@ -32,12 +40,21 @@ module RuboCop
|
|
32
40
|
# # good - comparing against nil
|
33
41
|
# Float(x, exception: false) == nil
|
34
42
|
#
|
43
|
+
# # good - using epsilon comparison in case expression
|
44
|
+
# case
|
45
|
+
# when (value - 1.0).abs < Float::EPSILON
|
46
|
+
# foo
|
47
|
+
# when (value - 2.0).abs < Float::EPSILON
|
48
|
+
# bar
|
49
|
+
# end
|
50
|
+
#
|
35
51
|
# # Or some other epsilon based type of comparison:
|
36
52
|
# # https://www.embeddeduse.com/2019/08/26/qt-compare-two-floats/
|
37
53
|
#
|
38
54
|
class FloatComparison < Base
|
39
55
|
MSG_EQUALITY = 'Avoid equality comparisons of floats as they are unreliable.'
|
40
56
|
MSG_INEQUALITY = 'Avoid inequality comparisons of floats as they are unreliable.'
|
57
|
+
MSG_CASE = 'Avoid float literal comparisons in case statements as they are unreliable.'
|
41
58
|
|
42
59
|
EQUALITY_METHODS = %i[== != eql? equal?].freeze
|
43
60
|
FLOAT_RETURNING_METHODS = %i[to_f Float fdiv].freeze
|
@@ -58,6 +75,16 @@ module RuboCop
|
|
58
75
|
end
|
59
76
|
alias on_csend on_send
|
60
77
|
|
78
|
+
def on_case(node)
|
79
|
+
node.when_branches.each do |when_branch|
|
80
|
+
when_branch.each_condition do |condition|
|
81
|
+
next if !float?(condition) || literal_safe?(condition)
|
82
|
+
|
83
|
+
add_offense(condition, message: MSG_CASE)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
61
88
|
private
|
62
89
|
|
63
90
|
def float?(node)
|
@@ -67,7 +94,7 @@ module RuboCop
|
|
67
94
|
when :float
|
68
95
|
true
|
69
96
|
when :send
|
70
|
-
|
97
|
+
float_send?(node)
|
71
98
|
when :begin
|
72
99
|
float?(node.children.first)
|
73
100
|
else
|
@@ -81,18 +108,18 @@ module RuboCop
|
|
81
108
|
(node.numeric_type? && node.value.zero?) || node.nil_type?
|
82
109
|
end
|
83
110
|
|
84
|
-
def
|
111
|
+
def float_send?(node)
|
85
112
|
if node.arithmetic_operation?
|
86
113
|
float?(node.receiver) || float?(node.first_argument)
|
87
114
|
elsif FLOAT_RETURNING_METHODS.include?(node.method_name)
|
88
115
|
true
|
89
116
|
elsif node.receiver&.float_type?
|
90
117
|
FLOAT_INSTANCE_METHODS.include?(node.method_name) ||
|
91
|
-
|
118
|
+
numeric_returning_method?(node)
|
92
119
|
end
|
93
120
|
end
|
94
121
|
|
95
|
-
def
|
122
|
+
def numeric_returning_method?(node)
|
96
123
|
return false unless node.receiver
|
97
124
|
|
98
125
|
case node.method_name
|
@@ -11,39 +11,43 @@ module RuboCop
|
|
11
11
|
# @example
|
12
12
|
# # bad
|
13
13
|
# foo.object_id == bar.object_id
|
14
|
+
# foo.object_id != baz.object_id
|
14
15
|
#
|
15
16
|
# # good
|
16
17
|
# foo.equal?(bar)
|
18
|
+
# !foo.equal?(baz)
|
17
19
|
#
|
18
20
|
class IdentityComparison < Base
|
19
21
|
extend AutoCorrector
|
20
22
|
|
21
|
-
MSG = 'Use
|
22
|
-
RESTRICT_ON_SEND = %i[==].freeze
|
23
|
+
MSG = 'Use `%<bang>sequal?` instead of `%<comparison_method>s` when comparing `object_id`.'
|
24
|
+
RESTRICT_ON_SEND = %i[== !=].freeze
|
25
|
+
|
26
|
+
# @!method object_id_comparison(node)
|
27
|
+
def_node_matcher :object_id_comparison, <<~PATTERN
|
28
|
+
(send
|
29
|
+
(send
|
30
|
+
_lhs_receiver :object_id) ${:== :!=}
|
31
|
+
(send
|
32
|
+
_rhs_receiver :object_id))
|
33
|
+
PATTERN
|
23
34
|
|
24
35
|
def on_send(node)
|
25
|
-
return unless
|
36
|
+
return unless (comparison_method = object_id_comparison(node))
|
26
37
|
|
27
|
-
|
38
|
+
bang = comparison_method == :== ? '' : '!'
|
39
|
+
add_offense(node,
|
40
|
+
message: format(MSG, comparison_method: comparison_method,
|
41
|
+
bang: bang)) do |corrector|
|
28
42
|
receiver = node.receiver.receiver
|
29
43
|
argument = node.first_argument.receiver
|
30
44
|
return unless receiver && argument
|
31
45
|
|
32
|
-
replacement = "#{receiver.source}.equal?(#{argument.source})"
|
46
|
+
replacement = "#{bang}#{receiver.source}.equal?(#{argument.source})"
|
33
47
|
|
34
48
|
corrector.replace(node, replacement)
|
35
49
|
end
|
36
50
|
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def compare_between_object_id_by_double_equal?(node)
|
41
|
-
object_id_method?(node.receiver) && object_id_method?(node.first_argument)
|
42
|
-
end
|
43
|
-
|
44
|
-
def object_id_method?(node)
|
45
|
-
node.send_type? && node.method?(:object_id)
|
46
|
-
end
|
47
51
|
end
|
48
52
|
end
|
49
53
|
end
|
@@ -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,32 +238,24 @@ 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)
|
242
|
-
|
243
|
-
if node.elsif? && result
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
elsif node.else? || node.ternary?
|
260
|
-
add_offense(cond) do |corrector|
|
261
|
-
corrector.replace(node, node.else_branch.source)
|
262
|
-
end
|
263
|
-
else
|
264
|
-
add_offense(cond) do |corrector|
|
265
|
-
corrector.remove(node)
|
266
|
-
end
|
241
|
+
result = condition_evaluation?(node, cond)
|
242
|
+
|
243
|
+
new_node = if node.elsif? && result
|
244
|
+
"else\n #{range_with_comments(node.if_branch).source}"
|
245
|
+
elsif node.elsif? && !result
|
246
|
+
"else\n #{node.else_branch.source}"
|
247
|
+
elsif node.if_branch && result
|
248
|
+
node.if_branch.source
|
249
|
+
elsif node.elsif_conditional?
|
250
|
+
"#{node.else_branch.source.sub('elsif', 'if')}\nend"
|
251
|
+
elsif node.else? || node.ternary?
|
252
|
+
node.else_branch.source
|
253
|
+
else
|
254
|
+
'' # Equivalent to removing the node
|
255
|
+
end
|
256
|
+
|
257
|
+
add_offense(cond) do |corrector|
|
258
|
+
corrector.replace(node, new_node)
|
267
259
|
end
|
268
260
|
end
|
269
261
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
@@ -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)
|
@@ -97,7 +97,7 @@ module RuboCop
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def require_parentheses?(send_node)
|
100
|
-
return true if
|
100
|
+
return true if operator_inside_collection_literal?(send_node)
|
101
101
|
return false unless send_node.comparison_method?
|
102
102
|
return false unless (node = send_node.parent)
|
103
103
|
|
@@ -105,10 +105,10 @@ module RuboCop
|
|
105
105
|
(node.respond_to?(:comparison_method?) && node.comparison_method?)
|
106
106
|
end
|
107
107
|
|
108
|
-
def
|
109
|
-
# If an operator call (without a dot) is inside a hash, it needs
|
108
|
+
def operator_inside_collection_literal?(send_node)
|
109
|
+
# If an operator call (without a dot) is inside an array or a hash, it needs
|
110
110
|
# to be parenthesized when converted to safe navigation.
|
111
|
-
send_node.parent&.
|
111
|
+
send_node.parent&.type?(:array, :pair) && !send_node.loc.dot
|
112
112
|
end
|
113
113
|
end
|
114
114
|
end
|
@@ -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
|
@@ -8,6 +8,11 @@ module RuboCop
|
|
8
8
|
# given by `ruby -cw` prior to Ruby 2.6:
|
9
9
|
# "shadowing outer local variable - foo".
|
10
10
|
#
|
11
|
+
# The cop is now disabled by default to match the upstream Ruby behavior.
|
12
|
+
# It's useful, however, if you'd like to avoid shadowing variables from outer
|
13
|
+
# scopes, which some people consider an anti-pattern that makes it harder
|
14
|
+
# to keep track of what's going on in a program.
|
15
|
+
#
|
11
16
|
# NOTE: Shadowing of variables in block passed to `Ractor.new` is allowed
|
12
17
|
# because `Ractor` should not access outer variables.
|
13
18
|
# eg. following style is encouraged:
|
@@ -4,10 +4,10 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Lint
|
6
6
|
# Checks for redundant access modifiers, including those with no
|
7
|
-
# code, those which are repeated,
|
8
|
-
# class or module body.
|
9
|
-
#
|
10
|
-
# are not redundant.
|
7
|
+
# code, those which are repeated, those which are on top-level, and
|
8
|
+
# leading `public` modifiers in a class or module body.
|
9
|
+
# Conditionally-defined methods are considered as always being defined,
|
10
|
+
# and thus access modifiers guarding such methods are not redundant.
|
11
11
|
#
|
12
12
|
# This cop has `ContextCreatingMethods` option. The default setting value
|
13
13
|
# is an empty array that means no method is specified.
|
@@ -58,6 +58,12 @@ module RuboCop
|
|
58
58
|
# private # this is redundant (no following methods are defined)
|
59
59
|
# end
|
60
60
|
#
|
61
|
+
# # bad
|
62
|
+
# private # this is useless (access modifiers have no effect on top-level)
|
63
|
+
#
|
64
|
+
# def method
|
65
|
+
# end
|
66
|
+
#
|
61
67
|
# # good
|
62
68
|
# class Foo
|
63
69
|
# private # this is not redundant (a method is defined)
|
@@ -145,6 +151,17 @@ module RuboCop
|
|
145
151
|
alias on_numblock on_block
|
146
152
|
alias on_itblock on_block
|
147
153
|
|
154
|
+
def on_begin(node)
|
155
|
+
return if node.parent
|
156
|
+
|
157
|
+
node.child_nodes.each do |child|
|
158
|
+
next unless child.send_type? && access_modifier?(child)
|
159
|
+
|
160
|
+
# This call always registers an offense for access modifier `child.method_name`
|
161
|
+
check_send_node(child, child.method_name, true)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
148
165
|
private
|
149
166
|
|
150
167
|
def autocorrect(corrector, node)
|
@@ -257,6 +274,10 @@ module RuboCop
|
|
257
274
|
|
258
275
|
def any_method_definition?(child)
|
259
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
|
+
|
260
281
|
matcher_name = :"#{m}_method?"
|
261
282
|
unless respond_to?(matcher_name)
|
262
283
|
self.class.def_node_matcher matcher_name, <<~PATTERN
|
@@ -279,7 +300,11 @@ module RuboCop
|
|
279
300
|
end
|
280
301
|
|
281
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.
|
282
305
|
cop_config.fetch('ContextCreatingMethods', []).any? do |m|
|
306
|
+
next if m == 'included'
|
307
|
+
|
283
308
|
matcher_name = :"#{m}_block?"
|
284
309
|
unless respond_to?(matcher_name)
|
285
310
|
self.class.def_node_matcher matcher_name, <<~PATTERN
|