rubocop 1.76.0 → 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 +2 -2
- data/config/default.yml +24 -2
- 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/empty_lines_around_access_modifier.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/empty_interpolation.rb +1 -1
- 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/safe_navigation_chain.rb +4 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +25 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +29 -4
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +4 -1
- 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/naming/file_name.rb +2 -2
- data/lib/rubocop/cop/naming/predicate_method.rb +74 -9
- 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/conditional_assignment.rb +3 -1
- 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/it_block_parameter.rb +2 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/min_max_comparison.rb +13 -5
- data/lib/rubocop/cop/style/redundant_array_flatten.rb +3 -1
- data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +12 -2
- data/lib/rubocop/cop/style/redundant_self.rb +8 -5
- data/lib/rubocop/cop/style/safe_navigation.rb +14 -4
- 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/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 +2 -0
- data/lib/ruby_lsp/rubocop/addon.rb +2 -2
- metadata +8 -6
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.
|
@@ -112,7 +112,7 @@ Here's a list of RuboCop's core developers:
|
|
112
112
|
* [Yuji Nakayama](https://github.com/yujinakayama) (retired)
|
113
113
|
* [Evgeni Dzhelyov](https://github.com/edzhelyov) (retired)
|
114
114
|
* [Ted Johansson](https://github.com/drenmi)
|
115
|
-
* [Masataka Kuwabara](https://github.com/pocke)
|
115
|
+
* [Masataka Kuwabara](https://github.com/pocke) (retired)
|
116
116
|
* [Koichi Ito](https://github.com/koic)
|
117
117
|
* [Maxim Krizhanovski](https://github.com/darhazer)
|
118
118
|
* [Benjamin Quorning](https://github.com/bquorning)
|
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.'
|
@@ -2689,7 +2698,7 @@ Metrics/AbcSize:
|
|
2689
2698
|
A calculated magnitude based on number of assignments,
|
2690
2699
|
branches, and conditions.
|
2691
2700
|
References:
|
2692
|
-
-
|
2701
|
+
- https://wiki.c2.com/?AbcMetric
|
2693
2702
|
- https://en.wikipedia.org/wiki/ABC_Software_Metric
|
2694
2703
|
Enabled: true
|
2695
2704
|
VersionAdded: '0.27'
|
@@ -3063,6 +3072,7 @@ Naming/PredicateMethod:
|
|
3063
3072
|
Description: 'Checks that predicate methods end with `?` and non-predicate methods do not.'
|
3064
3073
|
Enabled: pending
|
3065
3074
|
VersionAdded: '1.76'
|
3075
|
+
VersionChanged: '1.76'
|
3066
3076
|
# In `aggressive` mode, the cop will register an offense for predicate methods that
|
3067
3077
|
# may return a non-boolean value.
|
3068
3078
|
# In `conservative` mode, the cop will *not* register an offense for predicate methods
|
@@ -3070,6 +3080,8 @@ Naming/PredicateMethod:
|
|
3070
3080
|
Mode: conservative
|
3071
3081
|
AllowedMethods:
|
3072
3082
|
- call
|
3083
|
+
AllowedPatterns: []
|
3084
|
+
AllowBangMethods: false
|
3073
3085
|
|
3074
3086
|
Naming/PredicatePrefix:
|
3075
3087
|
Description: 'Predicate method names should not be prefixed and end with a `?`.'
|
@@ -3657,6 +3669,13 @@ Style/CollectionMethods:
|
|
3657
3669
|
- inject
|
3658
3670
|
- reduce
|
3659
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
|
+
|
3660
3679
|
Style/ColonMethodCall:
|
3661
3680
|
Description: 'Do not use :: for method call.'
|
3662
3681
|
StyleGuide: '#double-colons'
|
@@ -4058,6 +4077,9 @@ Style/FetchEnvVar:
|
|
4058
4077
|
VersionAdded: '1.28'
|
4059
4078
|
# Environment variables to be excluded from the inspection.
|
4060
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
|
4061
4083
|
|
4062
4084
|
Style/FileEmpty:
|
4063
4085
|
Description: >-
|
@@ -5006,7 +5028,7 @@ Style/OpenStructUse:
|
|
5006
5028
|
Avoid using OpenStruct. As of Ruby 3.0, use is officially discouraged due to performance,
|
5007
5029
|
version compatibility, and potential security issues.
|
5008
5030
|
References:
|
5009
|
-
- https://docs.ruby-lang.org/en/3.0
|
5031
|
+
- https://docs.ruby-lang.org/en/3.0/OpenStruct.html#class-OpenStruct-label-Caveats
|
5010
5032
|
|
5011
5033
|
Enabled: pending
|
5012
5034
|
Safe: false
|
@@ -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
|
|
@@ -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)
|
@@ -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
|
|
@@ -20,7 +20,7 @@ module RuboCop
|
|
20
20
|
|
21
21
|
def on_interpolation(begin_node)
|
22
22
|
node_children = begin_node.children.dup
|
23
|
-
node_children.delete_if { |e| e
|
23
|
+
node_children.delete_if { |e| e.nil_type? || (e.basic_literal? && e.str_content&.empty?) }
|
24
24
|
return unless node_children.empty?
|
25
25
|
|
26
26
|
add_offense(begin_node) { |corrector| corrector.remove(begin_node) }
|
@@ -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)
|
@@ -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
|