rubocop 1.22.2 → 1.24.1
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 -2
- data/config/default.yml +87 -5
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
- data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
- data/lib/rubocop/cli/command/show_docs_url.rb +48 -0
- data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
- data/lib/rubocop/cli.rb +1 -0
- data/lib/rubocop/config_loader_resolver.rb +1 -1
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/if_then_corrector.rb +55 -0
- data/lib/rubocop/cop/documentation.rb +19 -2
- data/lib/rubocop/cop/gemspec/date_assignment.rb +2 -10
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -10
- data/lib/rubocop/cop/gemspec/require_mfa.rb +144 -0
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -10
- data/lib/rubocop/cop/generator.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +47 -0
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +3 -1
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
- data/lib/rubocop/cop/layout/comment_indentation.rb +31 -2
- data/lib/rubocop/cop/layout/dot_position.rb +9 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +22 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_colon.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_first_arg.rb +4 -0
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +11 -5
- data/lib/rubocop/cop/lint/ambiguous_range.rb +2 -2
- data/lib/rubocop/cop/lint/constant_definition_in_block.rb +1 -1
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +16 -4
- data/lib/rubocop/cop/lint/deprecated_constants.rb +3 -2
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +6 -0
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +4 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +5 -2
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +7 -4
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +117 -0
- data/lib/rubocop/cop/metrics/block_length.rb +1 -0
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -9
- data/lib/rubocop/cop/metrics/method_length.rb +1 -0
- data/lib/rubocop/cop/metrics/module_length.rb +1 -1
- data/lib/rubocop/cop/metrics/parameter_lists.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +1 -1
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +5 -0
- data/lib/rubocop/cop/mixin/gemspec_help.rb +30 -0
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +4 -3
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +56 -0
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -5
- data/lib/rubocop/cop/naming/block_forwarding.rb +107 -0
- data/lib/rubocop/cop/naming/file_name.rb +37 -4
- data/lib/rubocop/cop/security/open.rb +11 -1
- data/lib/rubocop/cop/style/character_literal.rb +8 -1
- data/lib/rubocop/cop/style/collection_compact.rb +31 -13
- data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/empty_case_condition.rb +10 -0
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/file_read.rb +112 -0
- data/lib/rubocop/cop/style/file_write.rb +124 -0
- data/lib/rubocop/cop/style/format_string_token.rb +2 -1
- data/lib/rubocop/cop/style/hash_conversion.rb +2 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +22 -0
- data/lib/rubocop/cop/style/hash_transform_keys.rb +6 -6
- data/lib/rubocop/cop/style/hash_transform_values.rb +6 -6
- data/lib/rubocop/cop/style/if_inside_else.rb +15 -0
- data/lib/rubocop/cop/style/map_to_hash.rb +68 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +13 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +3 -1
- data/lib/rubocop/cop/style/method_def_parentheses.rb +17 -13
- data/lib/rubocop/cop/style/numeric_literals.rb +10 -1
- data/lib/rubocop/cop/style/one_line_conditional.rb +18 -39
- data/lib/rubocop/cop/style/open_struct_use.rb +69 -0
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +12 -2
- data/lib/rubocop/cop/style/quoted_symbols.rb +11 -1
- data/lib/rubocop/cop/style/redundant_interpolation.rb +17 -3
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +5 -1
- data/lib/rubocop/cop/style/redundant_self.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +1 -5
- data/lib/rubocop/cop/style/select_by_regexp.rb +4 -3
- data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/util.rb +9 -1
- data/lib/rubocop/formatter/html_formatter.rb +5 -2
- data/lib/rubocop/formatter/json_formatter.rb +4 -1
- data/lib/rubocop/options.rb +6 -1
- data/lib/rubocop/remote_config.rb +2 -4
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop/yaml_duplication_checker.rb +1 -1
- data/lib/rubocop.rb +11 -0
- metadata +18 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a2e7d2cbe48c6ff81a071b353132db29ed017af57a32bcd142038e2e551f3a5b
|
|
4
|
+
data.tar.gz: 8ae72a3ce8b6ab13b4d451bbdb1dbcdf54f898711a3009dae81450a49fb037e0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d868781732056622d0f5157a50553c0b521f81f2ca14d2ede65b4c7372ef0e3b89be5146db8664fac5b28a39c82be52fc297a43d8280647b1b7426ce9ee87337
|
|
7
|
+
data.tar.gz: e3d8f4dc8ab53859197eb3f05c62290cf72ba11c7e742869d619d6c4564e28f5c0fc70e4e15f90fc4f9bfe2d46cafdeedde8aa16d982adfc7d6eb482f7d20093
|
data/README.md
CHANGED
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
[](https://github.com/rubocop/rubocop/actions?query=workflow%3ACI)
|
|
10
10
|
[](https://codeclimate.com/github/rubocop/rubocop/test_coverage)
|
|
11
11
|
[](https://codeclimate.com/github/rubocop/rubocop/maintainability)
|
|
12
|
-
[](https://dependabot.com/compatibility-score.html?dependency-name=rubocop&package-manager=bundler&version-scheme=semver)
|
|
13
12
|
[](https://discord.gg/wJjWvGRDmm)
|
|
14
13
|
|
|
15
14
|
> Role models are important. <br/>
|
|
@@ -54,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
|
54
53
|
in your `Gemfile`:
|
|
55
54
|
|
|
56
55
|
```rb
|
|
57
|
-
gem 'rubocop', '~> 1.
|
|
56
|
+
gem 'rubocop', '~> 1.24', require: false
|
|
58
57
|
```
|
|
59
58
|
|
|
60
59
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
data/config/default.yml
CHANGED
|
@@ -78,6 +78,8 @@ AllCops:
|
|
|
78
78
|
# When specifying style guide URLs, any paths and/or fragments will be
|
|
79
79
|
# evaluated relative to the base URL.
|
|
80
80
|
StyleGuideBaseURL: https://rubystyle.guide
|
|
81
|
+
# Documentation URLs will be constructed using the base URL.
|
|
82
|
+
DocumentationBaseURL: https://docs.rubocop.org/rubocop
|
|
81
83
|
# Extra details are not displayed in offense messages by default. Change
|
|
82
84
|
# behavior by overriding ExtraDetails, or by giving the
|
|
83
85
|
# `-E/--extra-details` option.
|
|
@@ -150,6 +152,7 @@ AllCops:
|
|
|
150
152
|
rubocop-minitest: [minitest]
|
|
151
153
|
rubocop-sequel: [sequel]
|
|
152
154
|
rubocop-rake: [rake]
|
|
155
|
+
rubocop-graphql: [graphql]
|
|
153
156
|
|
|
154
157
|
#################### Bundler ###############################
|
|
155
158
|
|
|
@@ -258,6 +261,15 @@ Gemspec/OrderedDependencies:
|
|
|
258
261
|
Include:
|
|
259
262
|
- '**/*.gemspec'
|
|
260
263
|
|
|
264
|
+
Gemspec/RequireMFA:
|
|
265
|
+
Description: 'Checks that the gemspec has metadata to require MFA from RubyGems.'
|
|
266
|
+
Enabled: pending
|
|
267
|
+
VersionAdded: '1.23'
|
|
268
|
+
Reference:
|
|
269
|
+
- https://guides.rubygems.org/mfa-requirement-opt-in/
|
|
270
|
+
Include:
|
|
271
|
+
- '**/*.gemspec'
|
|
272
|
+
|
|
261
273
|
Gemspec/RequiredRubyVersion:
|
|
262
274
|
Description: 'Checks that `required_ruby_version` of gemspec is specified and equal to `TargetRubyVersion` of .rubocop.yml.'
|
|
263
275
|
Enabled: true
|
|
@@ -439,7 +451,11 @@ Layout/ClosingParenthesisIndentation:
|
|
|
439
451
|
Layout/CommentIndentation:
|
|
440
452
|
Description: 'Indentation of comments.'
|
|
441
453
|
Enabled: true
|
|
454
|
+
# When true, allows comments to have extra indentation if that aligns them
|
|
455
|
+
# with a comment on the preceding line.
|
|
456
|
+
AllowForAlignment: false
|
|
442
457
|
VersionAdded: '0.49'
|
|
458
|
+
VersionChanged: '1.24'
|
|
443
459
|
|
|
444
460
|
Layout/ConditionPosition:
|
|
445
461
|
Description: >-
|
|
@@ -511,13 +527,13 @@ Layout/EmptyLineBetweenDefs:
|
|
|
511
527
|
StyleGuide: '#empty-lines-between-methods'
|
|
512
528
|
Enabled: true
|
|
513
529
|
VersionAdded: '0.49'
|
|
514
|
-
VersionChanged: '1.
|
|
530
|
+
VersionChanged: '1.23'
|
|
515
531
|
EmptyLineBetweenMethodDefs: true
|
|
516
532
|
EmptyLineBetweenClassDefs: true
|
|
517
533
|
EmptyLineBetweenModuleDefs: true
|
|
518
|
-
#
|
|
519
|
-
# need an empty line between them.
|
|
520
|
-
AllowAdjacentOneLineDefs:
|
|
534
|
+
# `AllowAdjacentOneLineDefs` means that single line method definitions don't
|
|
535
|
+
# need an empty line between them. `true` by default.
|
|
536
|
+
AllowAdjacentOneLineDefs: true
|
|
521
537
|
# Can be array to specify minimum and maximum number of empty lines, e.g. [1, 2]
|
|
522
538
|
NumberOfEmptyLines: 1
|
|
523
539
|
|
|
@@ -1568,6 +1584,7 @@ Lint/DeprecatedConstants:
|
|
|
1568
1584
|
Description: 'Checks for deprecated constants.'
|
|
1569
1585
|
Enabled: pending
|
|
1570
1586
|
VersionAdded: '1.8'
|
|
1587
|
+
VersionChanged: '1.22'
|
|
1571
1588
|
# You can configure deprecated constants.
|
|
1572
1589
|
# If there is an alternative method, you can set alternative value as `Alternative`.
|
|
1573
1590
|
# And you can set the deprecated version as `DeprecatedVersion`.
|
|
@@ -1588,6 +1605,9 @@ Lint/DeprecatedConstants:
|
|
|
1588
1605
|
'FALSE':
|
|
1589
1606
|
Alternative: 'false'
|
|
1590
1607
|
DeprecatedVersion: '2.4'
|
|
1608
|
+
'Net::HTTPServerException':
|
|
1609
|
+
Alternative: 'Net::HTTPClientException'
|
|
1610
|
+
DeprecatedVersion: '2.6'
|
|
1591
1611
|
'Random::DEFAULT':
|
|
1592
1612
|
Alternative: 'Random.new'
|
|
1593
1613
|
DeprecatedVersion: '3.0'
|
|
@@ -1782,7 +1802,9 @@ Lint/ImplicitStringConcatenation:
|
|
|
1782
1802
|
Lint/IncompatibleIoSelectWithFiberScheduler:
|
|
1783
1803
|
Description: 'Checks for `IO.select` that is incompatible with Fiber Scheduler.'
|
|
1784
1804
|
Enabled: pending
|
|
1805
|
+
SafeAutoCorrect: false
|
|
1785
1806
|
VersionAdded: '1.21'
|
|
1807
|
+
VersionChanged: '1.24'
|
|
1786
1808
|
|
|
1787
1809
|
Lint/IneffectiveAccessModifier:
|
|
1788
1810
|
Description: >-
|
|
@@ -2304,6 +2326,11 @@ Lint/UselessMethodDefinition:
|
|
|
2304
2326
|
Safe: false
|
|
2305
2327
|
AllowComments: true
|
|
2306
2328
|
|
|
2329
|
+
Lint/UselessRuby2Keywords:
|
|
2330
|
+
Description: 'Finds unnecessary uses of `ruby2_keywords`.'
|
|
2331
|
+
Enabled: pending
|
|
2332
|
+
VersionAdded: '1.23'
|
|
2333
|
+
|
|
2307
2334
|
Lint/UselessSetterCall:
|
|
2308
2335
|
Description: 'Checks for useless setter call to a local variable.'
|
|
2309
2336
|
Enabled: true
|
|
@@ -2460,6 +2487,16 @@ Naming/BinaryOperatorParameterName:
|
|
|
2460
2487
|
VersionAdded: '0.50'
|
|
2461
2488
|
VersionChanged: '1.2'
|
|
2462
2489
|
|
|
2490
|
+
Naming/BlockForwarding:
|
|
2491
|
+
Description: 'Use anonymous block forwarding.'
|
|
2492
|
+
StyleGuide: '#block-forwarding'
|
|
2493
|
+
Enabled: pending
|
|
2494
|
+
VersionAdded: '1.24'
|
|
2495
|
+
EnforcedStyle: anonymous
|
|
2496
|
+
SupportedStyles:
|
|
2497
|
+
- anonymous
|
|
2498
|
+
- explicit
|
|
2499
|
+
|
|
2463
2500
|
Naming/BlockParameterName:
|
|
2464
2501
|
Description: >-
|
|
2465
2502
|
Checks for block parameter names that contain capital letters,
|
|
@@ -2497,6 +2534,7 @@ Naming/FileName:
|
|
|
2497
2534
|
StyleGuide: '#snake-case-files'
|
|
2498
2535
|
Enabled: true
|
|
2499
2536
|
VersionAdded: '0.50'
|
|
2537
|
+
VersionChanged: '1.23'
|
|
2500
2538
|
# Camel case file names listed in `AllCops:Include` and all file names listed
|
|
2501
2539
|
# in `AllCops:Exclude` are excluded by default. Add extra excludes here.
|
|
2502
2540
|
Exclude: []
|
|
@@ -2509,6 +2547,13 @@ Naming/FileName:
|
|
|
2509
2547
|
# whether each source file's class or module name matches the file name --
|
|
2510
2548
|
# not whether the nested module hierarchy matches the subdirectory path.
|
|
2511
2549
|
CheckDefinitionPathHierarchy: true
|
|
2550
|
+
# paths that are considered root directories, for example "lib" in most ruby projects
|
|
2551
|
+
# or "app/models" in rails projects
|
|
2552
|
+
CheckDefinitionPathHierarchyRoots:
|
|
2553
|
+
- lib
|
|
2554
|
+
- spec
|
|
2555
|
+
- test
|
|
2556
|
+
- src
|
|
2512
2557
|
# If non-`nil`, expect all source file names to match the following regex.
|
|
2513
2558
|
# Only the file name itself is matched, not the entire file path.
|
|
2514
2559
|
# Use anchors as necessary if you want to match the entire name rather than
|
|
@@ -3465,6 +3510,18 @@ Style/ExponentialNotation:
|
|
|
3465
3510
|
- engineering
|
|
3466
3511
|
- integral
|
|
3467
3512
|
|
|
3513
|
+
Style/FileRead:
|
|
3514
|
+
Description: 'Favor `File.(bin)read` convenience methods.'
|
|
3515
|
+
StyleGuide: '#file-read'
|
|
3516
|
+
Enabled: pending
|
|
3517
|
+
VersionAdded: '1.24'
|
|
3518
|
+
|
|
3519
|
+
Style/FileWrite:
|
|
3520
|
+
Description: 'Favor `File.(bin)write` convenience methods.'
|
|
3521
|
+
StyleGuide: '#file-write'
|
|
3522
|
+
Enabled: pending
|
|
3523
|
+
VersionAdded: '1.24'
|
|
3524
|
+
|
|
3468
3525
|
Style/FloatDivision:
|
|
3469
3526
|
Description: 'For performing float division, coerce one side only.'
|
|
3470
3527
|
StyleGuide: '#float-division'
|
|
@@ -3623,7 +3680,7 @@ Style/HashSyntax:
|
|
|
3623
3680
|
StyleGuide: '#hash-literals'
|
|
3624
3681
|
Enabled: true
|
|
3625
3682
|
VersionAdded: '0.9'
|
|
3626
|
-
VersionChanged: '
|
|
3683
|
+
VersionChanged: '1.24'
|
|
3627
3684
|
EnforcedStyle: ruby19
|
|
3628
3685
|
SupportedStyles:
|
|
3629
3686
|
# checks for 1.9 syntax (e.g. {a: 1}) for all symbol keys
|
|
@@ -3634,6 +3691,13 @@ Style/HashSyntax:
|
|
|
3634
3691
|
- no_mixed_keys
|
|
3635
3692
|
# enforces both ruby19 and no_mixed_keys styles
|
|
3636
3693
|
- ruby19_no_mixed_keys
|
|
3694
|
+
# Force hashes that have a hash value omission
|
|
3695
|
+
EnforcedShorthandSyntax: always
|
|
3696
|
+
SupportedShorthandSyntax:
|
|
3697
|
+
# forces use of the 3.1 syntax (e.g. {foo:}) when the hash key and value are the same.
|
|
3698
|
+
- always
|
|
3699
|
+
# forces use of explicit hash literal value.
|
|
3700
|
+
- never
|
|
3637
3701
|
# Force hashes that have a symbol value to use hash rockets
|
|
3638
3702
|
UseHashRocketsWithSymbolValues: false
|
|
3639
3703
|
# Do not suggest { a?: 1 } over { :a? => 1 } in ruby19 style
|
|
@@ -3810,6 +3874,12 @@ Style/LineEndConcatenation:
|
|
|
3810
3874
|
VersionAdded: '0.18'
|
|
3811
3875
|
VersionChanged: '0.64'
|
|
3812
3876
|
|
|
3877
|
+
Style/MapToHash:
|
|
3878
|
+
Description: 'Prefer `to_h` with a block over `map.to_h`.'
|
|
3879
|
+
Enabled: pending
|
|
3880
|
+
VersionAdded: '1.24'
|
|
3881
|
+
Safe: false
|
|
3882
|
+
|
|
3813
3883
|
Style/MethodCallWithArgsParentheses:
|
|
3814
3884
|
Description: 'Use parentheses for method calls with arguments.'
|
|
3815
3885
|
StyleGuide: '#method-invocation-parens'
|
|
@@ -4178,6 +4248,8 @@ Style/NumericLiterals:
|
|
|
4178
4248
|
VersionChanged: '0.48'
|
|
4179
4249
|
MinDigits: 5
|
|
4180
4250
|
Strict: false
|
|
4251
|
+
# You can specify allowed numbers. (e.g. port number 3000, 8080, and etc)
|
|
4252
|
+
AllowedNumbers: []
|
|
4181
4253
|
|
|
4182
4254
|
Style/NumericPredicate:
|
|
4183
4255
|
Description: >-
|
|
@@ -4212,6 +4284,16 @@ Style/OneLineConditional:
|
|
|
4212
4284
|
VersionAdded: '0.9'
|
|
4213
4285
|
VersionChanged: '0.90'
|
|
4214
4286
|
|
|
4287
|
+
Style/OpenStructUse:
|
|
4288
|
+
Description: >-
|
|
4289
|
+
Avoid using OpenStruct. As of Ruby 3.0, use is officially discouraged due to performance,
|
|
4290
|
+
version compatibility, and potential security issues.
|
|
4291
|
+
Reference:
|
|
4292
|
+
- https://docs.ruby-lang.org/en/3.0.0/OpenStruct.html#class-OpenStruct-label-Caveats
|
|
4293
|
+
|
|
4294
|
+
Enabled: pending
|
|
4295
|
+
VersionAdded: '1.23'
|
|
4296
|
+
|
|
4215
4297
|
Style/OptionHash:
|
|
4216
4298
|
Description: "Don't use option hashes when you can use keyword arguments."
|
|
4217
4299
|
Enabled: false
|
|
@@ -124,7 +124,7 @@ module RuboCop
|
|
|
124
124
|
lines = /\S/.match?(rubocop_yml_contents) ? rubocop_yml_contents.split("\n", -1) : []
|
|
125
125
|
doc_start_index = lines.index { |line| YAML_OPTIONAL_DOC_START.match?(line) } || -1
|
|
126
126
|
lines.insert(doc_start_index + 1, "inherit_from:#{file_string}\n")
|
|
127
|
-
File.
|
|
127
|
+
File.write(file_name, lines.join("\n"))
|
|
128
128
|
end
|
|
129
129
|
end
|
|
130
130
|
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
class CLI
|
|
5
|
+
module Command
|
|
6
|
+
# Prints out url to documentation of provided cops
|
|
7
|
+
# or documentation base url by default.
|
|
8
|
+
# @api private
|
|
9
|
+
class ShowDocsUrl < Base
|
|
10
|
+
self.command_name = :show_docs_url
|
|
11
|
+
|
|
12
|
+
def initialize(env)
|
|
13
|
+
super
|
|
14
|
+
|
|
15
|
+
@config = @config_store.for(Dir.pwd)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def run
|
|
19
|
+
print_documentation_url
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def print_documentation_url
|
|
25
|
+
puts Cop::Documentation.default_base_url if cops_array.empty?
|
|
26
|
+
|
|
27
|
+
cops_array.each do |cop_name|
|
|
28
|
+
cop = registry_hash[cop_name]
|
|
29
|
+
|
|
30
|
+
next if cop.empty?
|
|
31
|
+
|
|
32
|
+
puts Cop::Documentation.url_for(cop.first, @config)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
puts
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def cops_array
|
|
39
|
+
@cops_array ||= @options[:show_docs_url]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def registry_hash
|
|
43
|
+
@registry_hash ||= Cop::Registry.global.to_h
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -22,7 +22,7 @@ module RuboCop
|
|
|
22
22
|
'RuboCop extension libraries might be helpful:'
|
|
23
23
|
|
|
24
24
|
extensions.sort.each do |extension|
|
|
25
|
-
puts " * #{extension} (https://
|
|
25
|
+
puts " * #{extension} (https://rubygems.org/gems/#{extension})"
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
puts
|
data/lib/rubocop/cli.rb
CHANGED
|
@@ -74,7 +74,7 @@ module RuboCop
|
|
|
74
74
|
# Merges the given configuration with the default one. If
|
|
75
75
|
# AllCops:DisabledByDefault is true, it changes the Enabled params so that
|
|
76
76
|
# only cops from user configuration are enabled. If
|
|
77
|
-
# AllCops
|
|
77
|
+
# AllCops:EnabledByDefault is true, it changes the Enabled params so that
|
|
78
78
|
# only cops explicitly disabled in user configuration are disabled.
|
|
79
79
|
def merge_with_default(config, config_file, unset_nil:)
|
|
80
80
|
default_configuration = ConfigLoader.default_configuration
|
|
@@ -68,7 +68,7 @@ module RuboCop
|
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
def conditional_declaration?(nodes)
|
|
71
|
-
parent = nodes[0].
|
|
71
|
+
parent = nodes[0].each_ancestor.find { |ancestor| !ancestor.begin_type? }
|
|
72
72
|
return false unless parent&.if_type? || parent&.when_type?
|
|
73
73
|
|
|
74
74
|
root_conditional_node = parent.if_type? ? parent : parent.parent
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
# This class auto-corrects `if...then` structures to a multiline `if` statement
|
|
6
|
+
class IfThenCorrector
|
|
7
|
+
DEFAULT_INDENTATION_WIDTH = 2
|
|
8
|
+
|
|
9
|
+
def initialize(if_node, indentation: nil)
|
|
10
|
+
@if_node = if_node
|
|
11
|
+
@indentation = indentation || DEFAULT_INDENTATION_WIDTH
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call(corrector)
|
|
15
|
+
corrector.replace(if_node, replacement)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
attr_reader :if_node, :indentation
|
|
21
|
+
|
|
22
|
+
def replacement(node = if_node, indentation = nil)
|
|
23
|
+
indentation = ' ' * node.source_range.column if indentation.nil?
|
|
24
|
+
if_branch_source = node.if_branch&.source || 'nil'
|
|
25
|
+
elsif_indentation = indentation if node.respond_to?(:elsif?) && node.elsif?
|
|
26
|
+
|
|
27
|
+
if_branch = <<~RUBY
|
|
28
|
+
#{elsif_indentation}#{node.keyword} #{node.condition.source}
|
|
29
|
+
#{indentation}#{branch_body_indentation}#{if_branch_source}
|
|
30
|
+
RUBY
|
|
31
|
+
|
|
32
|
+
else_branch = rewrite_else_branch(node.else_branch, indentation)
|
|
33
|
+
if_branch + else_branch
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def rewrite_else_branch(else_branch, indentation)
|
|
37
|
+
if else_branch.nil?
|
|
38
|
+
'end'
|
|
39
|
+
elsif else_branch.if_type? && else_branch.elsif?
|
|
40
|
+
replacement(else_branch, indentation)
|
|
41
|
+
else
|
|
42
|
+
<<~RUBY.chomp
|
|
43
|
+
#{indentation}else
|
|
44
|
+
#{indentation}#{branch_body_indentation}#{else_branch.source}
|
|
45
|
+
#{indentation}end
|
|
46
|
+
RUBY
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def branch_body_indentation
|
|
51
|
+
@branch_body_indentation ||= (' ' * indentation).freeze
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -12,10 +12,27 @@ module RuboCop
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
# @api private
|
|
15
|
-
def url_for(cop_class)
|
|
15
|
+
def url_for(cop_class, config = nil)
|
|
16
16
|
base = department_to_basename(cop_class.department)
|
|
17
17
|
fragment = cop_class.cop_name.downcase.gsub(/[^a-z]/, '')
|
|
18
|
-
|
|
18
|
+
base_url = base_url_for(cop_class, config)
|
|
19
|
+
|
|
20
|
+
"#{base_url}/#{base}.html##{fragment}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @api private
|
|
24
|
+
def base_url_for(cop_class, config)
|
|
25
|
+
return default_base_url unless config
|
|
26
|
+
|
|
27
|
+
department_name = cop_class.department.to_s
|
|
28
|
+
|
|
29
|
+
config.for_department(department_name)['DocumentationBaseURL'] ||
|
|
30
|
+
config.for_all_cops['DocumentationBaseURL']
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @api private
|
|
34
|
+
def default_base_url
|
|
35
|
+
'https://docs.rubocop.org/rubocop'
|
|
19
36
|
end
|
|
20
37
|
end
|
|
21
38
|
end
|
|
@@ -21,21 +21,13 @@ module RuboCop
|
|
|
21
21
|
#
|
|
22
22
|
class DateAssignment < Base
|
|
23
23
|
include RangeHelp
|
|
24
|
+
include GemspecHelp
|
|
24
25
|
extend AutoCorrector
|
|
25
26
|
|
|
26
27
|
MSG = 'Do not use `date =` in gemspec, it is set automatically when the gem is packaged.'
|
|
27
28
|
|
|
28
|
-
# @!method gem_specification(node)
|
|
29
|
-
def_node_matcher :gem_specification, <<~PATTERN
|
|
30
|
-
(block
|
|
31
|
-
(send
|
|
32
|
-
(const
|
|
33
|
-
(const {cbase nil?} :Gem) :Specification) :new)
|
|
34
|
-
...)
|
|
35
|
-
PATTERN
|
|
36
|
-
|
|
37
29
|
def on_block(block_node)
|
|
38
|
-
return unless gem_specification(block_node)
|
|
30
|
+
return unless gem_specification?(block_node)
|
|
39
31
|
|
|
40
32
|
block_parameter = block_node.arguments.first.source
|
|
41
33
|
|
|
@@ -36,20 +36,11 @@ module RuboCop
|
|
|
36
36
|
# end
|
|
37
37
|
class DuplicatedAssignment < Base
|
|
38
38
|
include RangeHelp
|
|
39
|
+
include GemspecHelp
|
|
39
40
|
|
|
40
41
|
MSG = '`%<assignment>s` method calls already given on line '\
|
|
41
42
|
'%<line_of_first_occurrence>d of the gemspec.'
|
|
42
43
|
|
|
43
|
-
# @!method gem_specification(node)
|
|
44
|
-
def_node_search :gem_specification, <<~PATTERN
|
|
45
|
-
(block
|
|
46
|
-
(send
|
|
47
|
-
(const
|
|
48
|
-
(const {cbase nil?} :Gem) :Specification) :new)
|
|
49
|
-
(args
|
|
50
|
-
(arg $_)) ...)
|
|
51
|
-
PATTERN
|
|
52
|
-
|
|
53
44
|
# @!method assignment_method_declarations(node)
|
|
54
45
|
def_node_search :assignment_method_declarations, <<~PATTERN
|
|
55
46
|
(send
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Gemspec
|
|
6
|
+
# Requires a gemspec to have `rubygems_mfa_required` metadata set.
|
|
7
|
+
#
|
|
8
|
+
# This setting tells RubyGems that MFA is required for accounts to
|
|
9
|
+
# be able perform privileged operations, such as (see
|
|
10
|
+
# RubyGems' documentation for the full list of privileged operations):
|
|
11
|
+
#
|
|
12
|
+
# * `gem push`
|
|
13
|
+
# * `gem yank`
|
|
14
|
+
# * `gem owner --add/remove`
|
|
15
|
+
# * adding or removing owners using gem ownership page
|
|
16
|
+
#
|
|
17
|
+
# This helps make your gem more secure, as users can be more
|
|
18
|
+
# confident that gem updates were pushed by maintainers.
|
|
19
|
+
#
|
|
20
|
+
# @example
|
|
21
|
+
# # bad
|
|
22
|
+
# Gem::Specification.new do |spec|
|
|
23
|
+
# # no `rubygems_mfa_required` metadata specified
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# # good
|
|
27
|
+
# Gem::Specification.new do |spec|
|
|
28
|
+
# spec.metadata = {
|
|
29
|
+
# 'rubygems_mfa_required' => 'true'
|
|
30
|
+
# }
|
|
31
|
+
# end
|
|
32
|
+
#
|
|
33
|
+
# # good
|
|
34
|
+
# Gem::Specification.new do |spec|
|
|
35
|
+
# spec.metadata['rubygems_mfa_required'] = 'true'
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# # bad
|
|
39
|
+
# Gem::Specification.new do |spec|
|
|
40
|
+
# spec.metadata = {
|
|
41
|
+
# 'rubygems_mfa_required' => 'false'
|
|
42
|
+
# }
|
|
43
|
+
# end
|
|
44
|
+
#
|
|
45
|
+
# # good
|
|
46
|
+
# Gem::Specification.new do |spec|
|
|
47
|
+
# spec.metadata = {
|
|
48
|
+
# 'rubygems_mfa_required' => 'true'
|
|
49
|
+
# }
|
|
50
|
+
# end
|
|
51
|
+
#
|
|
52
|
+
# # bad
|
|
53
|
+
# Gem::Specification.new do |spec|
|
|
54
|
+
# spec.metadata['rubygems_mfa_required'] = 'false'
|
|
55
|
+
# end
|
|
56
|
+
#
|
|
57
|
+
# # good
|
|
58
|
+
# Gem::Specification.new do |spec|
|
|
59
|
+
# spec.metadata['rubygems_mfa_required'] = 'true'
|
|
60
|
+
# end
|
|
61
|
+
#
|
|
62
|
+
class RequireMFA < Base
|
|
63
|
+
include GemspecHelp
|
|
64
|
+
extend AutoCorrector
|
|
65
|
+
|
|
66
|
+
MSG = "`metadata['rubygems_mfa_required']` must be set to `'true'`."
|
|
67
|
+
|
|
68
|
+
# @!method metadata(node)
|
|
69
|
+
def_node_matcher :metadata, <<~PATTERN
|
|
70
|
+
`{
|
|
71
|
+
(send _ :metadata= $_)
|
|
72
|
+
(send (send _ :metadata) :[]= (str "rubygems_mfa_required") $_)
|
|
73
|
+
}
|
|
74
|
+
PATTERN
|
|
75
|
+
|
|
76
|
+
# @!method rubygems_mfa_required(node)
|
|
77
|
+
def_node_search :rubygems_mfa_required, <<~PATTERN
|
|
78
|
+
(pair (str "rubygems_mfa_required") $_)
|
|
79
|
+
PATTERN
|
|
80
|
+
|
|
81
|
+
# @!method true_string?(node)
|
|
82
|
+
def_node_matcher :true_string?, <<~PATTERN
|
|
83
|
+
(str "true")
|
|
84
|
+
PATTERN
|
|
85
|
+
|
|
86
|
+
def on_block(node) # rubocop:disable Metrics/MethodLength
|
|
87
|
+
gem_specification(node) do |block_var|
|
|
88
|
+
metadata_value = metadata(node)
|
|
89
|
+
mfa_value = mfa_value(metadata_value)
|
|
90
|
+
|
|
91
|
+
if mfa_value
|
|
92
|
+
unless true_string?(mfa_value)
|
|
93
|
+
add_offense(mfa_value) do |corrector|
|
|
94
|
+
change_value(corrector, mfa_value)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
else
|
|
98
|
+
add_offense(node) do |corrector|
|
|
99
|
+
autocorrect(corrector, node, block_var, metadata_value)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
private
|
|
106
|
+
|
|
107
|
+
def mfa_value(metadata_value)
|
|
108
|
+
return unless metadata_value
|
|
109
|
+
return metadata_value if metadata_value.str_type?
|
|
110
|
+
|
|
111
|
+
rubygems_mfa_required(metadata_value).first
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def autocorrect(corrector, node, block_var, metadata)
|
|
115
|
+
if metadata
|
|
116
|
+
return unless metadata.hash_type?
|
|
117
|
+
|
|
118
|
+
correct_metadata(corrector, metadata)
|
|
119
|
+
else
|
|
120
|
+
insert_mfa_required(corrector, node, block_var)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def correct_metadata(corrector, metadata)
|
|
125
|
+
if metadata.pairs.any?
|
|
126
|
+
corrector.insert_after(metadata.pairs.last, ",\n'rubygems_mfa_required' => 'true'")
|
|
127
|
+
else
|
|
128
|
+
corrector.insert_before(metadata.loc.end, "'rubygems_mfa_required' => 'true'")
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def insert_mfa_required(corrector, node, block_var)
|
|
133
|
+
corrector.insert_before(node.loc.end, <<~RUBY)
|
|
134
|
+
#{block_var}.metadata['rubygems_mfa_required'] = 'true'
|
|
135
|
+
RUBY
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def change_value(corrector, value)
|
|
139
|
+
corrector.replace(value, "'true'")
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -26,20 +26,13 @@ module RuboCop
|
|
|
26
26
|
# end
|
|
27
27
|
#
|
|
28
28
|
class RubyVersionGlobalsUsage < Base
|
|
29
|
+
include GemspecHelp
|
|
30
|
+
|
|
29
31
|
MSG = 'Do not use `RUBY_VERSION` in gemspec file.'
|
|
30
32
|
|
|
31
33
|
# @!method ruby_version?(node)
|
|
32
34
|
def_node_matcher :ruby_version?, '(const {cbase nil?} :RUBY_VERSION)'
|
|
33
35
|
|
|
34
|
-
# @!method gem_specification?(node)
|
|
35
|
-
def_node_search :gem_specification?, <<~PATTERN
|
|
36
|
-
(block
|
|
37
|
-
(send
|
|
38
|
-
(const
|
|
39
|
-
(const {cbase nil?} :Gem) :Specification) :new)
|
|
40
|
-
...)
|
|
41
|
-
PATTERN
|
|
42
|
-
|
|
43
36
|
def on_const(node)
|
|
44
37
|
return unless gem_spec_with_ruby_version?(node)
|
|
45
38
|
|
|
@@ -49,7 +42,7 @@ module RuboCop
|
|
|
49
42
|
private
|
|
50
43
|
|
|
51
44
|
def gem_spec_with_ruby_version?(node)
|
|
52
|
-
gem_specification
|
|
45
|
+
gem_specification(processed_source.ast) && ruby_version?(node)
|
|
53
46
|
end
|
|
54
47
|
end
|
|
55
48
|
end
|