rubocop 1.75.3 → 1.76.2
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 +55 -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/gemspec/duplicated_assignment.rb +50 -6
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
- 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/empty_lines_around_access_modifier.rb +7 -3
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/leading_comment_space.rb +13 -1
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +10 -0
- data/lib/rubocop/cop/layout/space_before_brackets.rb +6 -32
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +5 -1
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
- data/lib/rubocop/cop/lint/ambiguous_range.rb +5 -0
- data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
- data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -5
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +84 -2
- data/lib/rubocop/cop/lint/empty_interpolation.rb +3 -1
- data/lib/rubocop/cop/lint/float_comparison.rb +27 -0
- data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
- data/lib/rubocop/cop/lint/literal_as_condition.rb +31 -25
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +4 -4
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +5 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +21 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +2 -0
- 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/void.rb +2 -2
- data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +6 -2
- data/lib/rubocop/cop/naming/predicate_method.rb +245 -0
- data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +2 -2
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +32 -10
- data/lib/rubocop/cop/style/arguments_forwarding.rb +4 -1
- data/lib/rubocop/cop/style/class_and_module_children.rb +12 -2
- data/lib/rubocop/cop/style/command_literal.rb +1 -1
- data/lib/rubocop/cop/style/comparable_between.rb +5 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +3 -1
- data/lib/rubocop/cop/style/data_inheritance.rb +7 -0
- 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/identical_conditional_branches.rb +3 -3
- data/lib/rubocop/cop/style/if_unless_modifier.rb +22 -4
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -7
- 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 +4 -1
- data/lib/rubocop/cop/style/min_max_comparison.rb +13 -5
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
- data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
- 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_parentheses.rb +31 -5
- data/lib/rubocop/cop/style/redundant_self.rb +5 -5
- data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +25 -12
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -2
- data/lib/rubocop/cop/style/string_concatenation.rb +1 -2
- data/lib/rubocop/cop/style/struct_inheritance.rb +8 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +7 -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/cop/variable_force/assignment.rb +7 -3
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -0
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/rspec/cop_helper.rb +2 -2
- data/lib/rubocop/rspec/expect_offense.rb +9 -3
- data/lib/rubocop/rspec/shared_contexts.rb +1 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +6 -1
- metadata +12 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c98c6b67493a9eeb135c1e86846e068746676cd7caba305df7343f6da5a9307
|
4
|
+
data.tar.gz: a5e75c620016505e918bc98e273a729f14388b6c3cf95358c4975d785ca7fa57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '08701aa9d2fa3f7a1cf2b950b8bdf8640c47965345c3572645dd04f73507142ebf08aa16d5e7ab829a9e74330d45b4280ef700a7974eb02d7cf29e5890f67bb8'
|
7
|
+
data.tar.gz: 8d0f787edacfee68d6e6bc13db5c9f2247f137c3074fec0af47dae1b6b0b51403e9d071d1a40a81529271d35d1954a5848e16c489ebb175c9b2a24a4c1192a48
|
data/README.md
CHANGED
@@ -36,10 +36,11 @@ Working on RuboCop is often fun, but it also requires a great deal of time and e
|
|
36
36
|
**RuboCop**'s installation is pretty standard:
|
37
37
|
|
38
38
|
```sh
|
39
|
-
|
39
|
+
gem install rubocop
|
40
40
|
```
|
41
41
|
|
42
|
-
If you'd rather install RuboCop using `bundler`, add a line for it in your
|
42
|
+
If you'd rather install RuboCop using `bundler`, add a line for it in your
|
43
|
+
`Gemfile` (but set the `require` option to `false`, as it is a standalone tool):
|
43
44
|
|
44
45
|
```rb
|
45
46
|
gem 'rubocop', require: false
|
@@ -52,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
52
53
|
in your `Gemfile`:
|
53
54
|
|
54
55
|
```rb
|
55
|
-
gem 'rubocop', '~> 1.
|
56
|
+
gem 'rubocop', '~> 1.76', require: false
|
56
57
|
```
|
57
58
|
|
58
59
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
@@ -61,12 +62,15 @@ See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) fo
|
|
61
62
|
|
62
63
|
Just type `rubocop` in a Ruby project's folder and watch the magic happen.
|
63
64
|
|
64
|
-
```
|
65
|
-
|
66
|
-
|
65
|
+
```sh
|
66
|
+
cd my/cool/ruby/project
|
67
|
+
rubocop
|
67
68
|
```
|
68
69
|
|
69
|
-
|
70
|
+
> [!TIP]
|
71
|
+
>
|
72
|
+
> You can also use this magic in your favorite editor with RuboCop's
|
73
|
+
> [built-in LSP server](https://docs.rubocop.org/rubocop/usage/lsp.html).
|
70
74
|
|
71
75
|
## Documentation
|
72
76
|
|
@@ -79,7 +83,7 @@ RuboCop officially supports the following runtime Ruby implementations:
|
|
79
83
|
* MRI 2.7+
|
80
84
|
* JRuby 9.4+
|
81
85
|
|
82
|
-
|
86
|
+
It targets Ruby 2.0+ for code analysis.
|
83
87
|
|
84
88
|
See the [compatibility documentation](https://docs.rubocop.org/rubocop/compatibility.html) for further details.
|
85
89
|
|
@@ -91,7 +95,6 @@ If you use RuboCop in your project, you can include one of these badges in your
|
|
91
95
|
|
92
96
|
[](https://rubystyle.guide)
|
93
97
|
|
94
|
-
|
95
98
|
Here are the Markdown snippets for the two badges:
|
96
99
|
|
97
100
|
``` markdown
|
@@ -109,7 +112,7 @@ Here's a list of RuboCop's core developers:
|
|
109
112
|
* [Yuji Nakayama](https://github.com/yujinakayama) (retired)
|
110
113
|
* [Evgeni Dzhelyov](https://github.com/edzhelyov) (retired)
|
111
114
|
* [Ted Johansson](https://github.com/drenmi)
|
112
|
-
* [Masataka Kuwabara](https://github.com/pocke)
|
115
|
+
* [Masataka Kuwabara](https://github.com/pocke) (retired)
|
113
116
|
* [Koichi Ito](https://github.com/koic)
|
114
117
|
* [Maxim Krizhanovski](https://github.com/darhazer)
|
115
118
|
* [Benjamin Quorning](https://github.com/bquorning)
|
@@ -157,8 +160,8 @@ wide array of funding channels to account for your preferences
|
|
157
160
|
currently [Open Collective](https://opencollective.com/rubocop) is our
|
158
161
|
preferred funding platform).
|
159
162
|
|
160
|
-
**If you're working in a company that's making significant use of RuboCop we'd
|
161
|
-
to become a RuboCop sponsor.**
|
163
|
+
**If you're working in a company that's making significant use of RuboCop we'd
|
164
|
+
appreciate it if you suggest to your company to become a RuboCop sponsor.**
|
162
165
|
|
163
166
|
You can support the development of RuboCop via
|
164
167
|
[GitHub Sponsors](https://github.com/sponsors/bbatsov),
|
@@ -168,8 +171,11 @@ You can support the development of RuboCop via
|
|
168
171
|
and [Tidelift](https://tidelift.com/subscription/pkg/rubygems-rubocop?utm_source=rubygems-rubocop&utm_medium=referral&utm_campaign=readme)
|
169
172
|
.
|
170
173
|
|
171
|
-
|
172
|
-
|
174
|
+
> [!NOTE]
|
175
|
+
>
|
176
|
+
> If doing a sponsorship in the form of donation is problematic for your company
|
177
|
+
> from an accounting standpoint, we'd recommend the use of Tidelift, where you
|
178
|
+
> can get a support-like subscription instead.
|
173
179
|
|
174
180
|
### Open Collective for Individuals
|
175
181
|
|
data/config/default.yml
CHANGED
@@ -1923,7 +1923,7 @@ Lint/EmptyInterpolation:
|
|
1923
1923
|
Enabled: true
|
1924
1924
|
AutoCorrect: contextual
|
1925
1925
|
VersionAdded: '0.20'
|
1926
|
-
VersionChanged: '1.
|
1926
|
+
VersionChanged: '1.76'
|
1927
1927
|
|
1928
1928
|
Lint/EmptyWhen:
|
1929
1929
|
Description: 'Checks for `when` branches with empty bodies.'
|
@@ -2423,8 +2423,9 @@ Lint/ShadowingOuterLocalVariable:
|
|
2423
2423
|
Description: >-
|
2424
2424
|
Do not use the same name as outer local variable
|
2425
2425
|
for block arguments or block local variables.
|
2426
|
-
Enabled:
|
2426
|
+
Enabled: false
|
2427
2427
|
VersionAdded: '0.9'
|
2428
|
+
VersionChanged: '1.76'
|
2428
2429
|
|
2429
2430
|
Lint/SharedMutableDefault:
|
2430
2431
|
Description: 'Checks for mutable literals used as default arguments during Hash initialization.'
|
@@ -2612,6 +2613,13 @@ Lint/UselessConstantScoping:
|
|
2612
2613
|
Enabled: pending
|
2613
2614
|
VersionAdded: '1.72'
|
2614
2615
|
|
2616
|
+
Lint/UselessDefaultValueArgument:
|
2617
|
+
Description: 'Checks for usage of `fetch` or `Array.new` with default value argument and block.'
|
2618
|
+
Enabled: pending
|
2619
|
+
VersionAdded: '1.76'
|
2620
|
+
Safe: false
|
2621
|
+
AllowedReceivers: []
|
2622
|
+
|
2615
2623
|
Lint/UselessDefined:
|
2616
2624
|
Description: 'Checks for calls to `defined?` with strings and symbols. The result of such a call will always be truthy.'
|
2617
2625
|
Enabled: pending
|
@@ -2636,6 +2644,11 @@ Lint/UselessNumericOperation:
|
|
2636
2644
|
Enabled: pending
|
2637
2645
|
VersionAdded: '1.66'
|
2638
2646
|
|
2647
|
+
Lint/UselessOr:
|
2648
|
+
Description: 'Checks for useless OR expressions.'
|
2649
|
+
Enabled: pending
|
2650
|
+
VersionAdded: '1.76'
|
2651
|
+
|
2639
2652
|
Lint/UselessRescue:
|
2640
2653
|
Description: 'Checks for useless `rescue`s.'
|
2641
2654
|
Enabled: pending
|
@@ -2676,7 +2689,7 @@ Metrics/AbcSize:
|
|
2676
2689
|
A calculated magnitude based on number of assignments,
|
2677
2690
|
branches, and conditions.
|
2678
2691
|
References:
|
2679
|
-
-
|
2692
|
+
- https://wiki.c2.com/?AbcMetric
|
2680
2693
|
- https://en.wikipedia.org/wiki/ABC_Software_Metric
|
2681
2694
|
Enabled: true
|
2682
2695
|
VersionAdded: '0.27'
|
@@ -3046,8 +3059,23 @@ Naming/MethodParameterName:
|
|
3046
3059
|
# Forbidden names that will register an offense
|
3047
3060
|
ForbiddenNames: []
|
3048
3061
|
|
3049
|
-
Naming/
|
3050
|
-
Description: '
|
3062
|
+
Naming/PredicateMethod:
|
3063
|
+
Description: 'Checks that predicate methods end with `?` and non-predicate methods do not.'
|
3064
|
+
Enabled: pending
|
3065
|
+
VersionAdded: '1.76'
|
3066
|
+
VersionChanged: '1.76'
|
3067
|
+
# In `aggressive` mode, the cop will register an offense for predicate methods that
|
3068
|
+
# may return a non-boolean value.
|
3069
|
+
# In `conservative` mode, the cop will *not* register an offense for predicate methods
|
3070
|
+
# that may return a non-boolean value.
|
3071
|
+
Mode: conservative
|
3072
|
+
AllowedMethods:
|
3073
|
+
- call
|
3074
|
+
AllowedPatterns: []
|
3075
|
+
AllowBangMethods: false
|
3076
|
+
|
3077
|
+
Naming/PredicatePrefix:
|
3078
|
+
Description: 'Predicate method names should not be prefixed and end with a `?`.'
|
3051
3079
|
StyleGuide: '#bool-methods-qmark'
|
3052
3080
|
Enabled: true
|
3053
3081
|
VersionAdded: '0.50'
|
@@ -3702,7 +3730,9 @@ Style/CommentedKeyword:
|
|
3702
3730
|
Style/ComparableBetween:
|
3703
3731
|
Description: 'Enforces the use of `Comparable#between?` instead of logical comparison.'
|
3704
3732
|
Enabled: pending
|
3733
|
+
Safe: false
|
3705
3734
|
VersionAdded: '1.74'
|
3735
|
+
VersionChanged: '1.75'
|
3706
3736
|
StyleGuide: '#ranges-or-between'
|
3707
3737
|
|
3708
3738
|
Style/ComparableClamp:
|
@@ -3937,6 +3967,16 @@ Style/EmptyMethod:
|
|
3937
3967
|
- compact
|
3938
3968
|
- expanded
|
3939
3969
|
|
3970
|
+
Style/EmptyStringInsideInterpolation:
|
3971
|
+
Description: 'Checks for empty strings being assigned inside string interpolation.'
|
3972
|
+
StyleGuide: '#empty-strings-in-interpolation'
|
3973
|
+
Enabled: pending
|
3974
|
+
EnforcedStyle: trailing_conditional
|
3975
|
+
SupportedStyles:
|
3976
|
+
- trailing_conditional
|
3977
|
+
- ternary
|
3978
|
+
VersionAdded: '1.76'
|
3979
|
+
|
3940
3980
|
Style/Encoding:
|
3941
3981
|
Description: 'Use UTF-8 as the source file encoding.'
|
3942
3982
|
StyleGuide: '#utf-8'
|
@@ -4431,12 +4471,14 @@ Style/ItAssignment:
|
|
4431
4471
|
Style/ItBlockParameter:
|
4432
4472
|
Description: 'Checks for blocks with one argument where `it` block parameter can be used.'
|
4433
4473
|
Enabled: pending
|
4434
|
-
EnforcedStyle:
|
4474
|
+
EnforcedStyle: allow_single_line
|
4435
4475
|
SupportedStyles:
|
4476
|
+
- allow_single_line
|
4436
4477
|
- only_numbered_parameters
|
4437
4478
|
- always
|
4438
4479
|
- disallow
|
4439
4480
|
VersionAdded: '1.75'
|
4481
|
+
VersionChanged: '1.76'
|
4440
4482
|
|
4441
4483
|
Style/KeywordArgumentsMerging:
|
4442
4484
|
Description: >-
|
@@ -4967,7 +5009,7 @@ Style/OpenStructUse:
|
|
4967
5009
|
Avoid using OpenStruct. As of Ruby 3.0, use is officially discouraged due to performance,
|
4968
5010
|
version compatibility, and potential security issues.
|
4969
5011
|
References:
|
4970
|
-
- https://docs.ruby-lang.org/en/3.0
|
5012
|
+
- https://docs.ruby-lang.org/en/3.0/OpenStruct.html#class-OpenStruct-label-Caveats
|
4971
5013
|
|
4972
5014
|
Enabled: pending
|
4973
5015
|
Safe: false
|
@@ -5149,6 +5191,12 @@ Style/RedundantArrayConstructor:
|
|
5149
5191
|
Enabled: pending
|
5150
5192
|
VersionAdded: '1.52'
|
5151
5193
|
|
5194
|
+
Style/RedundantArrayFlatten:
|
5195
|
+
Description: 'Checks for redundant calls of `Array#flatten`.'
|
5196
|
+
Enabled: pending
|
5197
|
+
Safe: false
|
5198
|
+
VersionAdded: '1.76'
|
5199
|
+
|
5152
5200
|
Style/RedundantAssignment:
|
5153
5201
|
Description: 'Checks for redundant assignment before returning.'
|
5154
5202
|
Enabled: true
|
data/config/obsoletion.yml
CHANGED
@@ -31,6 +31,9 @@ renamed:
|
|
31
31
|
Lint/UnneededRequireStatement: Lint/RedundantRequireStatement
|
32
32
|
Lint/UnneededSplatExpansion: Lint/RedundantSplatExpansion
|
33
33
|
Metrics/LineLength: Layout/LineLength
|
34
|
+
Naming/PredicateName:
|
35
|
+
new_name: Naming/PredicatePrefix
|
36
|
+
severity: warning
|
34
37
|
Naming/UncommunicativeBlockParamName: Naming/BlockParameterName
|
35
38
|
Naming/UncommunicativeMethodParamName: Naming/MethodParameterName
|
36
39
|
Style/AccessorMethodName: Naming/AccessorMethodName
|
@@ -44,7 +47,7 @@ renamed:
|
|
44
47
|
Style/MethodName: Naming/MethodName
|
45
48
|
Style/OpMethod: Naming/BinaryOperatorParameterName
|
46
49
|
Style/PredicateName:
|
47
|
-
new_name: Naming/
|
50
|
+
new_name: Naming/PredicatePrefix
|
48
51
|
severity: warning
|
49
52
|
Style/SingleSpaceBeforeFirstArg: Layout/SpaceBeforeFirstArg
|
50
53
|
Style/UnneededCapitalW: Style/RedundantCapitalW
|
@@ -179,10 +182,10 @@ changed_parameters:
|
|
179
182
|
- cops: Naming/HeredocDelimiterNaming
|
180
183
|
parameters: Blacklist
|
181
184
|
alternative: ForbiddenDelimiters
|
182
|
-
- cops: Naming/
|
185
|
+
- cops: Naming/PredicatePrefix
|
183
186
|
parameters: NamePrefixBlacklist
|
184
187
|
alternative: ForbiddenPrefixes
|
185
|
-
- cops: Naming/
|
188
|
+
- cops: Naming/PredicatePrefix
|
186
189
|
parameters: NameWhitelist
|
187
190
|
alternative: AllowedMethods
|
188
191
|
- cops:
|
@@ -50,7 +50,7 @@ module RuboCop
|
|
50
50
|
|
51
51
|
def disable_offense(offense_range)
|
52
52
|
unbreakable_range = multiline_ranges(offense_range)&.find do |range|
|
53
|
-
|
53
|
+
eol_comment_would_be_inside_literal?(offense_range, range)
|
54
54
|
end
|
55
55
|
|
56
56
|
if unbreakable_range
|
@@ -75,18 +75,22 @@ module RuboCop
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def disable_offense_with_eol_or_surround_comment(range)
|
78
|
-
|
79
|
-
needed_line_length = (range.source_line + eol_comment).length
|
80
|
-
|
81
|
-
if needed_line_length <= max_line_length
|
82
|
-
disable_offense_at_end_of_line(range_of_first_line(range), eol_comment)
|
83
|
-
else
|
78
|
+
if line_with_eol_comment_too_long?(range)
|
84
79
|
disable_offense_before_and_after(range_by_lines(range))
|
80
|
+
else
|
81
|
+
disable_offense_at_end_of_line(range_of_first_line(range))
|
85
82
|
end
|
86
83
|
end
|
87
84
|
|
88
|
-
def
|
89
|
-
|
85
|
+
def eol_comment_would_be_inside_literal?(offense_range, literal_range)
|
86
|
+
return true if line_with_eol_comment_too_long?(offense_range)
|
87
|
+
|
88
|
+
offense_line = offense_range.line
|
89
|
+
offense_line >= literal_range.first_line && offense_line < literal_range.last_line
|
90
|
+
end
|
91
|
+
|
92
|
+
def line_with_eol_comment_too_long?(range)
|
93
|
+
(range.source_line + eol_comment).length > max_line_length
|
90
94
|
end
|
91
95
|
|
92
96
|
def surrounding_heredoc?(node)
|
@@ -132,10 +136,14 @@ module RuboCop
|
|
132
136
|
config.for_cop('Layout/LineLength')['Max'] || 120
|
133
137
|
end
|
134
138
|
|
135
|
-
def disable_offense_at_end_of_line(range
|
139
|
+
def disable_offense_at_end_of_line(range)
|
136
140
|
Corrector.new(range).insert_after(range, eol_comment)
|
137
141
|
end
|
138
142
|
|
143
|
+
def eol_comment
|
144
|
+
" # rubocop:todo #{cop_name}"
|
145
|
+
end
|
146
|
+
|
139
147
|
def disable_offense_before_and_after(range_by_lines)
|
140
148
|
range_with_newline = range_by_lines.resize(range_by_lines.size + 1)
|
141
149
|
leading_whitespace = range_by_lines.source_line[/^\s*/]
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
45
45
|
|
46
46
|
gem_declarations(processed_source.ast)
|
47
47
|
.each_cons(2) do |previous, current|
|
48
|
-
next unless consecutive_lines(previous, current)
|
48
|
+
next unless consecutive_lines?(previous, current)
|
49
49
|
next unless case_insensitive_out_of_order?(gem_name(current), gem_name(previous))
|
50
50
|
|
51
51
|
register_offense(previous, current)
|
@@ -6,10 +6,11 @@ module RuboCop
|
|
6
6
|
# An attribute assignment method calls should be listed only once
|
7
7
|
# in a gemspec.
|
8
8
|
#
|
9
|
-
# Assigning to an attribute with the same name using `spec.foo =`
|
10
|
-
# an unintended usage. On the other hand,
|
11
|
-
# as `spec.requirements`,
|
12
|
-
# permitted because it is
|
9
|
+
# Assigning to an attribute with the same name using `spec.foo =` or
|
10
|
+
# `spec.attribute#[]=` will be an unintended usage. On the other hand,
|
11
|
+
# duplication of methods such # as `spec.requirements`,
|
12
|
+
# `spec.add_runtime_dependency`, and others are permitted because it is
|
13
|
+
# the intended use of appending values.
|
13
14
|
#
|
14
15
|
# @example
|
15
16
|
# # bad
|
@@ -34,6 +35,18 @@ module RuboCop
|
|
34
35
|
# spec.add_dependency('parallel', '~> 1.10')
|
35
36
|
# spec.add_dependency('parser', '>= 2.3.3.1', '< 3.0')
|
36
37
|
# end
|
38
|
+
#
|
39
|
+
# # bad
|
40
|
+
# Gem::Specification.new do |spec|
|
41
|
+
# spec.metadata["key"] = "value"
|
42
|
+
# spec.metadata["key"] = "value"
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# # good
|
46
|
+
# Gem::Specification.new do |spec|
|
47
|
+
# spec.metadata["key"] = "value"
|
48
|
+
# end
|
49
|
+
#
|
37
50
|
class DuplicatedAssignment < Base
|
38
51
|
include RangeHelp
|
39
52
|
include GemspecHelp
|
@@ -44,12 +57,29 @@ module RuboCop
|
|
44
57
|
# @!method assignment_method_declarations(node)
|
45
58
|
def_node_search :assignment_method_declarations, <<~PATTERN
|
46
59
|
(send
|
47
|
-
(lvar #match_block_variable_name?) _ ...)
|
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
|
+
)
|
48
71
|
PATTERN
|
49
72
|
|
50
73
|
def on_new_investigation
|
51
74
|
return if processed_source.blank?
|
52
75
|
|
76
|
+
process_assignment_method_nodes
|
77
|
+
process_indexed_assignment_method_nodes
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def process_assignment_method_nodes
|
53
83
|
duplicated_assignment_method_nodes.each do |nodes|
|
54
84
|
nodes[1..].each do |node|
|
55
85
|
register_offense(node, node.method_name, nodes.first.first_line)
|
@@ -57,7 +87,14 @@ module RuboCop
|
|
57
87
|
end
|
58
88
|
end
|
59
89
|
|
60
|
-
|
90
|
+
def process_indexed_assignment_method_nodes
|
91
|
+
duplicated_indexed_assignment_method_nodes.each do |nodes|
|
92
|
+
nodes[1..].each do |node|
|
93
|
+
assignment = "#{node.children.first.method_name}[#{node.first_argument.source}]="
|
94
|
+
register_offense(node, assignment, nodes.first.first_line)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
61
98
|
|
62
99
|
def match_block_variable_name?(receiver_name)
|
63
100
|
gem_specification(processed_source.ast) do |block_variable_name|
|
@@ -73,6 +110,13 @@ module RuboCop
|
|
73
110
|
.select { |nodes| nodes.size > 1 }
|
74
111
|
end
|
75
112
|
|
113
|
+
def duplicated_indexed_assignment_method_nodes
|
114
|
+
indexed_assignment_method_declarations(processed_source.ast)
|
115
|
+
.group_by { |node| [node.children.first.method_name, node.first_argument] }
|
116
|
+
.values
|
117
|
+
.select { |nodes| nodes.size > 1 }
|
118
|
+
end
|
119
|
+
|
76
120
|
def register_offense(node, assignment, line_of_first_occurrence)
|
77
121
|
line_range = node.loc.column...node.loc.last_column
|
78
122
|
offense_location = source_range(processed_source.buffer, node.first_line, line_range)
|
@@ -71,7 +71,7 @@ module RuboCop
|
|
71
71
|
|
72
72
|
dependency_declarations(processed_source.ast)
|
73
73
|
.each_cons(2) do |previous, current|
|
74
|
-
next unless consecutive_lines(previous, current)
|
74
|
+
next unless consecutive_lines?(previous, current)
|
75
75
|
next unless case_insensitive_out_of_order?(gem_name(current), gem_name(previous))
|
76
76
|
next unless get_dependency_name(previous) == get_dependency_name(current)
|
77
77
|
|
@@ -29,6 +29,7 @@ module RuboCop
|
|
29
29
|
NODE_GROUPS = {
|
30
30
|
any_block: %i[block numblock itblock],
|
31
31
|
any_def: %i[def defs],
|
32
|
+
any_match_pattern: %i[match_pattern match_pattern_p],
|
32
33
|
argument: %i[arg optarg restarg kwarg kwoptarg kwrestarg blockarg forward_arg shadowarg],
|
33
34
|
boolean: %i[true false],
|
34
35
|
call: %i[send csend],
|
@@ -22,6 +22,11 @@ module RuboCop
|
|
22
22
|
# * Private attribute macros (`attr_accessor`, `attr_writer`, `attr_reader`)
|
23
23
|
# * Private instance methods
|
24
24
|
#
|
25
|
+
# NOTE: Simply enabling the cop with `Enabled: true` will not use
|
26
|
+
# the example order shown below.
|
27
|
+
# To enforce the order of macros like `attr_reader`,
|
28
|
+
# you must define both `ExpectedOrder` *and* `Categories`.
|
29
|
+
#
|
25
30
|
# You can configure the following order:
|
26
31
|
#
|
27
32
|
# [source,yaml]
|
@@ -68,6 +73,36 @@ module RuboCop
|
|
68
73
|
# - extend
|
69
74
|
# ----
|
70
75
|
#
|
76
|
+
# If you only set `ExpectedOrder`
|
77
|
+
# without defining `Categories`,
|
78
|
+
# macros such as `attr_reader` or `has_many`
|
79
|
+
# will not be recognized as part of a category, and their order will not be validated.
|
80
|
+
# For example, the following will NOT raise any offenses, even if the order is incorrect:
|
81
|
+
#
|
82
|
+
# [source,yaml]
|
83
|
+
# ----
|
84
|
+
# Layout/ClassStructure:
|
85
|
+
# Enabled: true
|
86
|
+
# ExpectedOrder:
|
87
|
+
# - public_attribute_macros
|
88
|
+
# - initializer
|
89
|
+
# ----
|
90
|
+
#
|
91
|
+
# To make it work as expected, you must also specify `Categories` like this:
|
92
|
+
#
|
93
|
+
# [source,yaml]
|
94
|
+
# ----
|
95
|
+
# Layout/ClassStructure:
|
96
|
+
# ExpectedOrder:
|
97
|
+
# - public_attribute_macros
|
98
|
+
# - initializer
|
99
|
+
# Categories:
|
100
|
+
# attribute_macros:
|
101
|
+
# - attr_reader
|
102
|
+
# - attr_writer
|
103
|
+
# - attr_accessor
|
104
|
+
# ----
|
105
|
+
#
|
71
106
|
# @safety
|
72
107
|
# Autocorrection is unsafe because class methods and module inclusion
|
73
108
|
# can behave differently, based on which methods or constants have
|
@@ -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
|
@@ -250,7 +250,7 @@ module RuboCop
|
|
250
250
|
reset!
|
251
251
|
|
252
252
|
alignment_for(first_pair).each do |alignment|
|
253
|
-
delta = alignment.deltas_for_first_pair(first_pair
|
253
|
+
delta = alignment.deltas_for_first_pair(first_pair)
|
254
254
|
check_delta delta, node: first_pair, alignment: alignment
|
255
255
|
end
|
256
256
|
|
@@ -58,6 +58,12 @@ module RuboCop
|
|
58
58
|
# attr_reader :name #: String
|
59
59
|
# attr_reader :age #: Integer?
|
60
60
|
#
|
61
|
+
# #: (
|
62
|
+
# #| Integer,
|
63
|
+
# #| String
|
64
|
+
# #| ) -> void
|
65
|
+
# def foo; end
|
66
|
+
#
|
61
67
|
# @example AllowRBSInlineAnnotation: true
|
62
68
|
#
|
63
69
|
# # good
|
@@ -67,6 +73,12 @@ module RuboCop
|
|
67
73
|
# attr_reader :name #: String
|
68
74
|
# attr_reader :age #: Integer?
|
69
75
|
#
|
76
|
+
# #: (
|
77
|
+
# #| Integer,
|
78
|
+
# #| String
|
79
|
+
# #| ) -> void
|
80
|
+
# def foo; end
|
81
|
+
#
|
70
82
|
# @example AllowSteepAnnotation: false (default)
|
71
83
|
#
|
72
84
|
# # bad
|
@@ -175,7 +187,7 @@ module RuboCop
|
|
175
187
|
end
|
176
188
|
|
177
189
|
def rbs_inline_annotation?(comment)
|
178
|
-
allow_rbs_inline_annotation? && comment.text.start_with?(/#:|#\[.+\]
|
190
|
+
allow_rbs_inline_annotation? && comment.text.start_with?(/#:|#\[.+\]|#\|/)
|
179
191
|
end
|
180
192
|
|
181
193
|
def allow_steep_annotation?
|
@@ -23,6 +23,16 @@ module RuboCop
|
|
23
23
|
def kind(token)
|
24
24
|
'semicolon' if token.semicolon?
|
25
25
|
end
|
26
|
+
|
27
|
+
def space_missing?(token1, token2)
|
28
|
+
super && !semicolon_sequence?(token1, token2)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def semicolon_sequence?(token, next_token)
|
34
|
+
token.semicolon? && next_token.semicolon?
|
35
|
+
end
|
26
36
|
end
|
27
37
|
end
|
28
38
|
end
|
@@ -22,51 +22,25 @@ module RuboCop
|
|
22
22
|
RESTRICT_ON_SEND = %i[[] []=].freeze
|
23
23
|
|
24
24
|
def on_send(node)
|
25
|
-
return unless (first_argument = node.first_argument)
|
26
|
-
|
27
|
-
begin_pos = first_argument.source_range.begin_pos
|
28
|
-
return unless (range = offense_range(node, begin_pos))
|
29
|
-
|
30
|
-
register_offense(range)
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def offense_range(node, begin_pos)
|
36
25
|
receiver_end_pos = node.receiver.source_range.end_pos
|
37
26
|
selector_begin_pos = node.loc.selector.begin_pos
|
38
27
|
return if receiver_end_pos >= selector_begin_pos
|
39
28
|
return if dot_before_brackets?(node, receiver_end_pos, selector_begin_pos)
|
40
29
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
30
|
+
range = range_between(receiver_end_pos, selector_begin_pos)
|
31
|
+
|
32
|
+
add_offense(range) do |corrector|
|
33
|
+
corrector.remove(range)
|
45
34
|
end
|
46
35
|
end
|
47
36
|
|
37
|
+
private
|
38
|
+
|
48
39
|
def dot_before_brackets?(node, receiver_end_pos, selector_begin_pos)
|
49
40
|
return false unless node.loc.respond_to?(:dot) && (dot = node.loc.dot)
|
50
41
|
|
51
42
|
dot.begin_pos == receiver_end_pos && dot.end_pos == selector_begin_pos
|
52
43
|
end
|
53
|
-
|
54
|
-
def offense_range_for_assignment(node, begin_pos)
|
55
|
-
end_pos = node.receiver.source_range.end_pos
|
56
|
-
|
57
|
-
return if begin_pos - end_pos == 1 ||
|
58
|
-
(range = range_between(end_pos, begin_pos - 1)).source.start_with?('[')
|
59
|
-
|
60
|
-
range
|
61
|
-
end
|
62
|
-
|
63
|
-
def register_offense(range)
|
64
|
-
add_offense(range) { |corrector| corrector.remove(range) }
|
65
|
-
end
|
66
|
-
|
67
|
-
def reference_variable_with_brackets?(node)
|
68
|
-
node.receiver&.variable? && node.method?(:[]) && node.arguments.size == 1
|
69
|
-
end
|
70
44
|
end
|
71
45
|
end
|
72
46
|
end
|