rubocop-gusto 10.8.0 → 10.9.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/CHANGELOG.md +25 -2
- data/README.md +50 -12
- data/config/default.yml +0 -135
- data/config/rails.yml +0 -16
- data/lib/rubocop/cop/gusto/no_rescue_error_message_checking.rb +1 -1
- data/lib/rubocop/cop/gusto/perform_class_method.rb +8 -10
- data/lib/rubocop/cop/gusto/polymorphic_type_validation.rb +1 -1
- data/lib/rubocop/cop/gusto/rails_env.rb +13 -8
- data/lib/rubocop/cop/gusto/rspec_date_time_mock.rb +8 -7
- data/lib/rubocop/cop/gusto/sidekiq_params.rb +6 -7
- data/lib/rubocop/cop/gusto/use_paint_not_colorize.rb +7 -10
- data/lib/rubocop/cop/rspec/scattered_let.rb +75 -0
- data/lib/rubocop/gusto/move_node_patch.rb +62 -0
- data/lib/rubocop/gusto/version.rb +1 -1
- data/lib/rubocop-gusto.rb +1 -0
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bfe32904ee2cd054ac91081d5cab3f9cd4b15deb007e816ca1afefdf00aa41b0
|
|
4
|
+
data.tar.gz: 244866f38efc30bc95881ff3129664f136448284209a5b04f76bbe9241338d89
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ec813a15822dbd2030267110dd697142e51c705bf48c9c2b197d0b6567d4373a2d389e1465a12f67df5edc640d932e2a3587fc4fb2a921577594ff93a78ecc07
|
|
7
|
+
data.tar.gz: abf67fb4291bc44ab9b86c3a0bdf91c9871af49bee41ac8de6f9f986888b6231cecb3cb9d754289b97ae389a1aa56e7727cc5f64097d5140fadf59f286c55fd8
|
data/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,33 @@
|
|
|
1
|
-
## Pending
|
|
2
|
-
|
|
3
1
|
## 10.8.0
|
|
4
2
|
|
|
5
3
|
- Remove redundant `Rails: Enabled: true` from `config/rails.yml` (already set by rubocop-rails' own defaults)
|
|
6
4
|
- Enable `Rails/DefaultScope` cop (disabled by default in rubocop-rails)
|
|
7
5
|
|
|
6
|
+
## [10.9.1](https://github.com/Gusto/rubocop-gusto/compare/v10.9.0...v10.9.1) (2026-05-22)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* remove redundant config entries ([#112](https://github.com/Gusto/rubocop-gusto/issues/112)) ([e3dab8d](https://github.com/Gusto/rubocop-gusto/commit/e3dab8d3f96907a4b4be955fd3407926aa47b5a7))
|
|
12
|
+
|
|
13
|
+
## [10.9.0](https://github.com/Gusto/rubocop-gusto/compare/v10.8.1...v10.9.0) (2026-05-22)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* make rubocop-rspec move/scatter cops Sorbet-sig-aware ([#107](https://github.com/Gusto/rubocop-gusto/issues/107)) ([b3f1449](https://github.com/Gusto/rubocop-gusto/commit/b3f14491b74548adbd05738b90484ba6ccb5ea67))
|
|
19
|
+
|
|
20
|
+
## [10.8.1](https://github.com/Gusto/rubocop-gusto/compare/v10.8.0...v10.8.1) (2026-03-30)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
* Change runner configuration to use custom group ([#95](https://github.com/Gusto/rubocop-gusto/issues/95)) ([87af85d](https://github.com/Gusto/rubocop-gusto/commit/87af85d17c150d689ca73448e0d2b5372968f21b))
|
|
26
|
+
* correct release-please-action pinned SHA ([#89](https://github.com/Gusto/rubocop-gusto/issues/89)) ([87db13a](https://github.com/Gusto/rubocop-gusto/commit/87db13ad17f60d0398a84dc7957515cac623efee))
|
|
27
|
+
* pin GitHub Actions to commit SHAs to prevent supply-chain attacks ([#85](https://github.com/Gusto/rubocop-gusto/issues/85)) ([bc85834](https://github.com/Gusto/rubocop-gusto/commit/bc85834d5fbed70278f9cd67eff6e564fb4e9925))
|
|
28
|
+
* remove extra empty line at block body end in execute_migration_spec ([87af85d](https://github.com/Gusto/rubocop-gusto/commit/87af85d17c150d689ca73448e0d2b5372968f21b))
|
|
29
|
+
* use GitHub App token in release-please to trigger CI on PRs ([#98](https://github.com/Gusto/rubocop-gusto/issues/98)) ([a2d3171](https://github.com/Gusto/rubocop-gusto/commit/a2d3171909ee8fe04be233b13adb8aaac48e0bef))
|
|
30
|
+
|
|
8
31
|
## 10.7.0
|
|
9
32
|
|
|
10
33
|
- Improve `Rack/LowercaseHeaderKeys` for Rack 3 migration
|
data/README.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
#
|
|
1
|
+
# RuboCop::Gusto
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://rubygems.org/gems/rubocop-gusto)
|
|
4
|
+
[](https://github.com/Gusto/rubocop-gusto/actions/workflows/build.yml)
|
|
5
|
+
[](https://github.com/Gusto/rubocop-gusto/releases)
|
|
6
|
+
|
|
7
|
+
Gusto's custom [RuboCop](https://rubocop.org/) cops and shared configuration, distributed as a gem and integrated via the [`lint_roller`](https://github.com/standardrb/lint_roller) plugin interface.
|
|
4
8
|
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
@@ -18,36 +22,70 @@ $ bundle
|
|
|
18
22
|
|
|
19
23
|
## Usage
|
|
20
24
|
|
|
21
|
-
`rubocop-gusto` ships with
|
|
25
|
+
`rubocop-gusto` ships with a CLI that sets up your project's `.rubocop.yml`:
|
|
22
26
|
|
|
23
27
|
```sh
|
|
24
28
|
bundle exec rubocop-gusto init
|
|
25
29
|
```
|
|
26
30
|
|
|
31
|
+
This adds `rubocop-gusto` to your `.rubocop.yml` `plugins:` list and includes any relevant configuration (e.g. Rails-specific rules when Rails is detected).
|
|
32
|
+
|
|
27
33
|
If this is an existing project, it is recommended to run the autocorrector (`bundle exec rubocop -a`) and then to regenerate the `.rubocop_todo.yml` (`bundle exec rubocop --auto-gen-config`), so issues can be dealt with piecemeal.
|
|
28
34
|
|
|
35
|
+
### Available cops
|
|
36
|
+
|
|
37
|
+
Custom cops live under the following namespaces:
|
|
38
|
+
|
|
39
|
+
- `Gusto/` — general Gusto-specific cops (see [`lib/rubocop/cop/gusto/`](lib/rubocop/cop/gusto/))
|
|
40
|
+
- `Rack/` — cops scoped to Rack middleware patterns (see [`lib/rubocop/cop/rack/`](lib/rubocop/cop/rack/))
|
|
41
|
+
|
|
29
42
|
## Publishing New Versions
|
|
30
43
|
|
|
31
|
-
|
|
44
|
+
Releases are fully automated via [release-please](https://github.com/googleapis/release-please).
|
|
45
|
+
|
|
46
|
+
**How it works:**
|
|
47
|
+
|
|
48
|
+
1. Merge PRs to `main` using [Conventional Commits](https://www.conventionalcommits.org/) in the PR title (enforced by CI).
|
|
49
|
+
2. release-please automatically creates and maintains a "Release PR" that bumps the version and updates the changelog.
|
|
50
|
+
3. When you merge the Release PR, a GitHub Release and git tag are created, and the gem is published to RubyGems.
|
|
32
51
|
|
|
33
|
-
|
|
34
|
-
2. Document your changes in the [changelog](CHANGELOG.md).
|
|
35
|
-
3. Open a pull request and follow the typical review/merge process.
|
|
36
|
-
4. TODO: finish release process
|
|
52
|
+
**Conventional commit types and version bumps:**
|
|
37
53
|
|
|
38
|
-
|
|
54
|
+
| PR title prefix | Version bump | Example |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| `feat:` | Minor (10.8.0 -> 10.9.0) | `feat: add Gusto/NewCop cop` |
|
|
57
|
+
| `fix:` | Patch (10.8.0 -> 10.8.1) | `fix: correct false positive in DefaultScope` |
|
|
58
|
+
| `feat!:` or `BREAKING CHANGE` footer | Major (10.8.0 -> 11.0.0) | `feat!: drop Ruby 3.1 support` |
|
|
59
|
+
| `chore:`, `docs:`, `ci:`, etc. | No release | `chore: update dev dependencies` |
|
|
39
60
|
|
|
40
61
|
## Contributing
|
|
41
62
|
|
|
42
63
|
Submit new rules, updated configuration, and other checks to be used organization wide by submitting a Pull Request!
|
|
43
64
|
|
|
65
|
+
PR titles must use [Conventional Commits](https://www.conventionalcommits.org/) format (enforced by CI) — see the version bump table above for which prefixes trigger releases.
|
|
66
|
+
|
|
67
|
+
### Adding a new cop
|
|
68
|
+
|
|
69
|
+
1. Create `lib/rubocop/cop/gusto/<cop_name>.rb`
|
|
70
|
+
2. Add an entry to `config/default.yml`, then sort it:
|
|
71
|
+
```sh
|
|
72
|
+
bundle exec rubocop-gusto sort config/default.yml
|
|
73
|
+
```
|
|
74
|
+
3. Add a spec in `spec/rubocop/cop/gusto/<cop_name>_spec.rb`
|
|
75
|
+
4. Run tests and lint:
|
|
76
|
+
```sh
|
|
77
|
+
bundle exec rspec
|
|
78
|
+
bundle exec rubocop
|
|
79
|
+
```
|
|
80
|
+
|
|
44
81
|
### Versioning policy
|
|
45
82
|
|
|
46
|
-
|
|
83
|
+
rubocop-gusto generally follows semver, with the exception that the only thing that is considered a breaking change is a change in the public API to use rubocop-gusto.
|
|
47
84
|
|
|
48
85
|
Users can generally expect to need to regenerate their rubocop todo when they make a minor version bump to rubocop-gusto.
|
|
49
86
|
|
|
50
|
-
### Git
|
|
51
|
-
|
|
87
|
+
### Git pre-commit hooks
|
|
88
|
+
|
|
89
|
+
```sh
|
|
52
90
|
git config core.hooksPath script/githooks
|
|
53
91
|
```
|
data/config/default.yml
CHANGED
|
@@ -155,37 +155,13 @@ Layout/BlockAlignment:
|
|
|
155
155
|
|
|
156
156
|
Layout/CaseIndentation:
|
|
157
157
|
EnforcedStyle: end
|
|
158
|
-
IndentOneStep: false
|
|
159
|
-
|
|
160
|
-
Layout/DotPosition:
|
|
161
|
-
Enabled: true
|
|
162
|
-
# We use the (default) leading dot position for Sorbet and IDE compatibility.
|
|
163
|
-
EnforcedStyle: leading
|
|
164
|
-
|
|
165
|
-
Layout/EmptyLineAfterGuardClause:
|
|
166
|
-
Enabled: true
|
|
167
|
-
|
|
168
|
-
Layout/EmptyLineAfterMagicComment:
|
|
169
|
-
Enabled: true
|
|
170
|
-
|
|
171
|
-
Layout/EmptyLineBetweenDefs:
|
|
172
|
-
AllowAdjacentOneLineDefs: true
|
|
173
158
|
|
|
174
159
|
Layout/EmptyLinesAroundAttributeAccessor:
|
|
175
160
|
Enabled: false
|
|
176
161
|
|
|
177
|
-
Layout/EmptyLinesAroundClassBody:
|
|
178
|
-
EnforcedStyle: no_empty_lines
|
|
179
|
-
|
|
180
|
-
Layout/EmptyLinesAroundModuleBody:
|
|
181
|
-
EnforcedStyle: no_empty_lines
|
|
182
|
-
|
|
183
162
|
Layout/EndAlignment:
|
|
184
163
|
EnforcedStyleAlignWith: start_of_line
|
|
185
164
|
|
|
186
|
-
Layout/ExtraSpacing:
|
|
187
|
-
AllowForAlignment: true
|
|
188
|
-
|
|
189
165
|
Layout/FirstArgumentIndentation:
|
|
190
166
|
EnforcedStyle: consistent
|
|
191
167
|
|
|
@@ -211,53 +187,22 @@ Layout/LineLength:
|
|
|
211
187
|
# TODO: Pick some maximum like 200 to start with
|
|
212
188
|
Enabled: false
|
|
213
189
|
|
|
214
|
-
Layout/MultilineArrayBraceLayout:
|
|
215
|
-
EnforcedStyle: symmetrical
|
|
216
|
-
|
|
217
|
-
Layout/MultilineAssignmentLayout:
|
|
218
|
-
Enabled: false
|
|
219
|
-
|
|
220
|
-
Layout/MultilineHashBraceLayout:
|
|
221
|
-
EnforcedStyle: symmetrical
|
|
222
|
-
|
|
223
|
-
Layout/MultilineMethodCallBraceLayout:
|
|
224
|
-
EnforcedStyle: symmetrical
|
|
225
|
-
|
|
226
190
|
Layout/MultilineMethodCallIndentation:
|
|
227
191
|
EnforcedStyle: indented
|
|
228
192
|
|
|
229
|
-
Layout/MultilineMethodDefinitionBraceLayout:
|
|
230
|
-
EnforcedStyle: symmetrical
|
|
231
|
-
|
|
232
193
|
Layout/MultilineOperationIndentation:
|
|
233
194
|
EnforcedStyle: indented
|
|
234
195
|
|
|
235
196
|
Layout/ParameterAlignment:
|
|
236
197
|
EnforcedStyle: with_fixed_indentation
|
|
237
198
|
|
|
238
|
-
Layout/SpaceAroundEqualsInParameterDefault:
|
|
239
|
-
Enabled: true
|
|
240
|
-
|
|
241
|
-
Layout/SpaceAroundMethodCallOperator:
|
|
242
|
-
Enabled: true
|
|
243
|
-
|
|
244
199
|
Layout/SpaceInLambdaLiteral:
|
|
245
200
|
EnforcedStyle: require_space
|
|
246
201
|
|
|
247
202
|
Lint/AmbiguousBlockAssociation:
|
|
248
|
-
Enabled: true
|
|
249
203
|
Exclude:
|
|
250
204
|
- '**/spec/**/*'
|
|
251
205
|
|
|
252
|
-
Lint/EmptyFile:
|
|
253
|
-
Enabled: true
|
|
254
|
-
|
|
255
|
-
Lint/EnsureReturn:
|
|
256
|
-
Enabled: true
|
|
257
|
-
|
|
258
|
-
Lint/RaiseException:
|
|
259
|
-
Enabled: true
|
|
260
|
-
|
|
261
206
|
Lint/SelfAssignment:
|
|
262
207
|
Severity: error
|
|
263
208
|
|
|
@@ -287,7 +232,6 @@ Metrics/BlockLength:
|
|
|
287
232
|
Enabled: false
|
|
288
233
|
|
|
289
234
|
Metrics/ClassLength:
|
|
290
|
-
Enabled: true
|
|
291
235
|
Max: 2500
|
|
292
236
|
|
|
293
237
|
Metrics/CyclomaticComplexity:
|
|
@@ -333,16 +277,9 @@ Performance/RedundantBlockCall:
|
|
|
333
277
|
Performance/ZipWithoutBlock:
|
|
334
278
|
Enabled: true
|
|
335
279
|
|
|
336
|
-
RSpec:
|
|
337
|
-
Include:
|
|
338
|
-
- '**/spec/**/*'
|
|
339
|
-
|
|
340
280
|
RSpec/ContainExactly:
|
|
341
281
|
Enabled: false
|
|
342
282
|
|
|
343
|
-
RSpec/ContextWording:
|
|
344
|
-
Enabled: true
|
|
345
|
-
|
|
346
283
|
RSpec/DescribeClass:
|
|
347
284
|
Enabled: false
|
|
348
285
|
|
|
@@ -370,12 +307,6 @@ RSpec/ExpectInHook:
|
|
|
370
307
|
RSpec/IndexedLet:
|
|
371
308
|
Enabled: false
|
|
372
309
|
|
|
373
|
-
RSpec/IteratedExpectation:
|
|
374
|
-
Enabled: true
|
|
375
|
-
|
|
376
|
-
RSpec/LeadingSubject:
|
|
377
|
-
Enabled: true
|
|
378
|
-
|
|
379
310
|
RSpec/LetSetup:
|
|
380
311
|
Enabled: false
|
|
381
312
|
|
|
@@ -417,12 +348,6 @@ RSpec/ReceiveMessages:
|
|
|
417
348
|
RSpec/ScatteredSetup:
|
|
418
349
|
AutoCorrect: false
|
|
419
350
|
|
|
420
|
-
RSpec/SpecFilePathFormat:
|
|
421
|
-
Enabled: true
|
|
422
|
-
|
|
423
|
-
RSpec/SpecFilePathSuffix:
|
|
424
|
-
Enabled: true
|
|
425
|
-
|
|
426
351
|
RSpec/StubbedMock:
|
|
427
352
|
Enabled: false
|
|
428
353
|
|
|
@@ -452,12 +377,6 @@ Rack/LowercaseHeaderKeys:
|
|
|
452
377
|
Rake/ClassDefinitionInTask:
|
|
453
378
|
Enabled: false
|
|
454
379
|
|
|
455
|
-
Rake/Desc:
|
|
456
|
-
Enabled: true
|
|
457
|
-
|
|
458
|
-
Security/YAMLLoad:
|
|
459
|
-
Enabled: true
|
|
460
|
-
|
|
461
380
|
Sorbet:
|
|
462
381
|
# TODO: validate these choices for Harmonization
|
|
463
382
|
# BindingConstantWithoutTypeAlias
|
|
@@ -466,11 +385,6 @@ Sorbet:
|
|
|
466
385
|
# SignatureBuildOrder
|
|
467
386
|
Enabled: true
|
|
468
387
|
|
|
469
|
-
Sorbet/FalseSigil:
|
|
470
|
-
# We want to avoid `typed: ignore` as much as possible, as it breaks LSP tooling.
|
|
471
|
-
Include:
|
|
472
|
-
- "**/*.{rb,rbi,rake,ru}"
|
|
473
|
-
|
|
474
388
|
Sorbet/Refinement:
|
|
475
389
|
# Still marked pending upstream, we contributed this and enable it here.
|
|
476
390
|
Enabled: true
|
|
@@ -479,8 +393,6 @@ Sorbet/StrictSigil:
|
|
|
479
393
|
# Forgot the difference between typed levels? (ignore, false, true, strict, and strong)
|
|
480
394
|
# Check this out: https://sorbet.org/docs/static#file-level-granularity-strictness-levels
|
|
481
395
|
Enabled: true
|
|
482
|
-
Include:
|
|
483
|
-
- "**/*.{rb,rbi,rake,ru}"
|
|
484
396
|
Exclude:
|
|
485
397
|
- bin/**/*
|
|
486
398
|
- db/**/*.rb
|
|
@@ -488,7 +400,6 @@ Sorbet/StrictSigil:
|
|
|
488
400
|
- spec/**/*spec.rb
|
|
489
401
|
|
|
490
402
|
Sorbet/ValidSigil:
|
|
491
|
-
Enabled: true
|
|
492
403
|
RequireSigilOnAllFiles: true
|
|
493
404
|
# We don't want to require any specific typed level at this point – only that there IS a typed sigil.
|
|
494
405
|
MinimumStrictness: ignore
|
|
@@ -503,7 +414,6 @@ Style/AccessorGrouping:
|
|
|
503
414
|
Enabled: false
|
|
504
415
|
|
|
505
416
|
Style/Alias:
|
|
506
|
-
Enabled: true
|
|
507
417
|
EnforcedStyle: prefer_alias_method
|
|
508
418
|
|
|
509
419
|
Style/ArgumentsForwarding:
|
|
@@ -517,7 +427,6 @@ Style/AutoResourceCleanup:
|
|
|
517
427
|
Enabled: true
|
|
518
428
|
|
|
519
429
|
Style/BlockDelimiters:
|
|
520
|
-
EnforcedStyle: line_count_based
|
|
521
430
|
AllowedMethods:
|
|
522
431
|
- it
|
|
523
432
|
- expect
|
|
@@ -529,15 +438,11 @@ Style/ClassAndModuleChildren:
|
|
|
529
438
|
# EnforcedStyle: compact
|
|
530
439
|
Enabled: false
|
|
531
440
|
|
|
532
|
-
Style/CollectionMethods:
|
|
533
|
-
Enabled: false
|
|
534
|
-
|
|
535
441
|
Style/CommandLiteral:
|
|
536
442
|
# This cop Style/CommandLiteral protects us from accidentally using backticks for strings quotes.
|
|
537
443
|
# Forcing the use of %x() should make it more obvious visually where the command literals are.
|
|
538
444
|
# This is easy to miss, but is a bug-without-test-failures at best and an opportunity for an
|
|
539
445
|
# attack vector at worst.
|
|
540
|
-
Enabled: true
|
|
541
446
|
EnforcedStyle: percent_x
|
|
542
447
|
|
|
543
448
|
Style/ConditionalAssignment:
|
|
@@ -560,9 +465,6 @@ Style/ExpandPathArguments:
|
|
|
560
465
|
Exclude:
|
|
561
466
|
- '**/bin/*'
|
|
562
467
|
|
|
563
|
-
Style/ExponentialNotation:
|
|
564
|
-
Enabled: true
|
|
565
|
-
|
|
566
468
|
Style/FormatString:
|
|
567
469
|
Enabled: false
|
|
568
470
|
|
|
@@ -571,15 +473,11 @@ Style/FormatStringToken:
|
|
|
571
473
|
|
|
572
474
|
Style/FrozenStringLiteralComment:
|
|
573
475
|
EnforcedStyle: always_true
|
|
574
|
-
Enabled: true
|
|
575
476
|
|
|
576
477
|
# This can make lines longer and impair readability
|
|
577
478
|
Style/GuardClause:
|
|
578
479
|
Enabled: false
|
|
579
480
|
|
|
580
|
-
Style/HashEachMethods:
|
|
581
|
-
Enabled: true
|
|
582
|
-
|
|
583
481
|
Style/HashSyntax:
|
|
584
482
|
EnforcedStyle: ruby19_no_mixed_keys
|
|
585
483
|
|
|
@@ -595,9 +493,6 @@ Style/IfInsideElse:
|
|
|
595
493
|
Style/IfUnlessModifier:
|
|
596
494
|
Enabled: false
|
|
597
495
|
|
|
598
|
-
Style/ImplicitRuntimeError:
|
|
599
|
-
Enabled: false
|
|
600
|
-
|
|
601
496
|
Style/ItBlockParameter:
|
|
602
497
|
Enabled: true
|
|
603
498
|
EnforcedStyle: only_numbered_parameters
|
|
@@ -609,7 +504,6 @@ Style/LambdaCall:
|
|
|
609
504
|
Enabled: false
|
|
610
505
|
|
|
611
506
|
Style/MethodCallWithArgsParentheses:
|
|
612
|
-
IgnoreMacros: true
|
|
613
507
|
AllowedMethods:
|
|
614
508
|
# Ruby
|
|
615
509
|
- puts
|
|
@@ -698,18 +592,11 @@ Style/MethodCallWithArgsParentheses:
|
|
|
698
592
|
- input
|
|
699
593
|
- action
|
|
700
594
|
|
|
701
|
-
Style/MethodCalledOnDoEndBlock:
|
|
702
|
-
Enabled: false
|
|
703
|
-
|
|
704
|
-
Style/MissingElse:
|
|
705
|
-
Enabled: false
|
|
706
|
-
|
|
707
595
|
Style/ModuleFunction:
|
|
708
596
|
# Sorbet does not enforce the singleton version of module function methods: https://github.com/sorbet/sorbet/issues/8531
|
|
709
597
|
# Even if did, requiring the code to typecheck both paths would be a pain for maintainability.
|
|
710
598
|
# Also, it's better for the code to be explicit about which version of the method is being called,
|
|
711
599
|
# as it is one fewer decision the downstream developer has to make.
|
|
712
|
-
Enabled: true
|
|
713
600
|
EnforcedStyle: forbidden
|
|
714
601
|
|
|
715
602
|
Style/MultilineBlockChain:
|
|
@@ -728,9 +615,6 @@ Style/Next:
|
|
|
728
615
|
Style/NumericPredicate:
|
|
729
616
|
Enabled: false
|
|
730
617
|
|
|
731
|
-
Style/OptionHash:
|
|
732
|
-
Enabled: false
|
|
733
|
-
|
|
734
618
|
Style/OptionalBooleanParameter:
|
|
735
619
|
AllowedMethods:
|
|
736
620
|
- respond_to_missing?
|
|
@@ -745,9 +629,6 @@ Style/PercentLiteralDelimiters:
|
|
|
745
629
|
'%w': ()
|
|
746
630
|
'%W': ()
|
|
747
631
|
|
|
748
|
-
Style/RaiseArgs:
|
|
749
|
-
Enabled: true
|
|
750
|
-
|
|
751
632
|
Style/RedundantSelf:
|
|
752
633
|
Enabled: false
|
|
753
634
|
|
|
@@ -755,22 +636,15 @@ Style/RegexpLiteral:
|
|
|
755
636
|
Enabled: false
|
|
756
637
|
|
|
757
638
|
Style/RescueStandardError:
|
|
758
|
-
Enabled: true
|
|
759
639
|
AutoCorrect: true
|
|
760
640
|
EnforcedStyle: 'implicit'
|
|
761
641
|
|
|
762
642
|
Style/Send:
|
|
763
643
|
Enabled: true
|
|
764
644
|
|
|
765
|
-
Style/SingleLineBlockParams:
|
|
766
|
-
Enabled: false
|
|
767
|
-
|
|
768
645
|
Style/SlicingWithRange:
|
|
769
646
|
Enabled: false
|
|
770
647
|
|
|
771
|
-
Style/SpecialGlobalVars:
|
|
772
|
-
Enabled: true
|
|
773
|
-
|
|
774
648
|
Style/StringLiterals:
|
|
775
649
|
Enabled: false
|
|
776
650
|
|
|
@@ -780,22 +654,13 @@ Style/StringMethods:
|
|
|
780
654
|
Style/SymbolArray:
|
|
781
655
|
Enabled: false
|
|
782
656
|
|
|
783
|
-
Style/SymbolProc:
|
|
784
|
-
Enabled: true
|
|
785
|
-
|
|
786
657
|
Style/TernaryParentheses:
|
|
787
658
|
Enabled: false
|
|
788
659
|
|
|
789
|
-
Style/TrailingCommaInArguments:
|
|
790
|
-
Enabled: true
|
|
791
|
-
EnforcedStyleForMultiline: no_comma # matches Standard https://github.com/standardrb/standard/blob/250b306cd44bea509d20023d9ab63170da67c815/config/base.yml#L1857
|
|
792
|
-
|
|
793
660
|
Style/TrailingCommaInArrayLiteral:
|
|
794
|
-
Enabled: true
|
|
795
661
|
EnforcedStyleForMultiline: consistent_comma
|
|
796
662
|
|
|
797
663
|
Style/TrailingCommaInHashLiteral:
|
|
798
|
-
Enabled: true
|
|
799
664
|
EnforcedStyleForMultiline: consistent_comma
|
|
800
665
|
|
|
801
666
|
Style/TrivialAccessors:
|
data/config/rails.yml
CHANGED
|
@@ -31,9 +31,6 @@ Performance/DoubleStartEndWith:
|
|
|
31
31
|
Rails/ActiveRecordAliases:
|
|
32
32
|
Enabled: false
|
|
33
33
|
|
|
34
|
-
Rails/ActiveRecordOverride:
|
|
35
|
-
Enabled: true
|
|
36
|
-
|
|
37
34
|
Rails/ApplicationRecord:
|
|
38
35
|
AutoCorrect: true
|
|
39
36
|
|
|
@@ -42,7 +39,6 @@ Rails/BulkChangeTable:
|
|
|
42
39
|
|
|
43
40
|
Rails/Date:
|
|
44
41
|
AutoCorrect: false
|
|
45
|
-
Enabled: true
|
|
46
42
|
|
|
47
43
|
Rails/DefaultScope:
|
|
48
44
|
Enabled: true
|
|
@@ -112,18 +108,6 @@ Rails/NotNullColumn:
|
|
|
112
108
|
Rails/ReadWriteAttribute:
|
|
113
109
|
Enabled: false
|
|
114
110
|
|
|
115
|
-
Rails/SaveBang:
|
|
116
|
-
SafeAutoCorrect: false
|
|
117
|
-
|
|
118
|
-
Rails/SkipsModelValidations:
|
|
119
|
-
Enabled: true
|
|
120
|
-
|
|
121
|
-
Rails/TimeZone:
|
|
122
|
-
Enabled: true
|
|
123
|
-
|
|
124
|
-
Rails/UniqueValidationWithoutIndex:
|
|
125
|
-
Enabled: true
|
|
126
|
-
|
|
127
111
|
Rails/UnknownEnv:
|
|
128
112
|
Environments:
|
|
129
113
|
- demo
|
|
@@ -41,7 +41,7 @@ module RuboCop
|
|
|
41
41
|
METHODS_TO_CHECK = %i(match? include? ==).to_set.freeze
|
|
42
42
|
|
|
43
43
|
def on_rescue(node)
|
|
44
|
-
node.resbody_branches.last.each_descendant(:if, :unless)
|
|
44
|
+
node.resbody_branches.last.each_descendant(:if, :unless) do |condition_node|
|
|
45
45
|
add_offense(condition_node) if message_check?(condition_node)
|
|
46
46
|
end
|
|
47
47
|
end
|
|
@@ -30,6 +30,11 @@ module RuboCop
|
|
|
30
30
|
WORKER_FALLBACK = %w(Sidekiq::Worker).freeze
|
|
31
31
|
WORKER_MODULES = "WorkerModules"
|
|
32
32
|
|
|
33
|
+
# @!method worker_module_include?(node)
|
|
34
|
+
def_node_matcher :worker_module_include?, <<~PATTERN
|
|
35
|
+
(send nil? :include (const _ _))
|
|
36
|
+
PATTERN
|
|
37
|
+
|
|
33
38
|
def on_def(node)
|
|
34
39
|
return unless node.method?(:perform)
|
|
35
40
|
return unless (method_type = perform_class_method_type(node))
|
|
@@ -51,19 +56,12 @@ module RuboCop
|
|
|
51
56
|
|
|
52
57
|
def is_sidekiq_worker?(search_node, method_type)
|
|
53
58
|
search_node = search_node.parent if method_type == :sclass
|
|
54
|
-
search_node.parent.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
next unless sibling.first_argument.const_type?
|
|
58
|
-
|
|
59
|
-
worker_modules.include?(sibling.first_argument.const_name)
|
|
59
|
+
search_node.parent.each_child_node.any? do |sibling|
|
|
60
|
+
worker_module_include?(sibling) &&
|
|
61
|
+
worker_modules.include?(sibling.first_argument.const_name)
|
|
60
62
|
end
|
|
61
63
|
end
|
|
62
64
|
|
|
63
|
-
def is_include?(node)
|
|
64
|
-
node.send_type? && node.method?(:include)
|
|
65
|
-
end
|
|
66
|
-
|
|
67
65
|
def worker_modules
|
|
68
66
|
@worker_modules ||= cop_config.fetch(WORKER_MODULES, WORKER_FALLBACK)
|
|
69
67
|
end
|
|
@@ -69,7 +69,7 @@ module RuboCop
|
|
|
69
69
|
if type_validation?(validation_node) && validation_node.first_argument.value == type_field
|
|
70
70
|
has_validation = true
|
|
71
71
|
# Check for allow_blank in the validation options
|
|
72
|
-
validation_node.
|
|
72
|
+
validation_node.last_argument.each_node(:pair) do |pair_node|
|
|
73
73
|
has_allow_blank = true if allow_blank?(pair_node)
|
|
74
74
|
end
|
|
75
75
|
elsif polymorphic_methods_for?(validation_node) && validation_node.first_argument.value == relation_name
|
|
@@ -52,19 +52,24 @@ module RuboCop
|
|
|
52
52
|
)
|
|
53
53
|
).freeze
|
|
54
54
|
MSG = "Use Feature Flags or config instead of `Rails.env`."
|
|
55
|
-
PROHIBITED_CLASS = "Rails"
|
|
56
55
|
RESTRICT_ON_SEND = %i(env).freeze
|
|
57
56
|
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
# @!method prohibited_rails_env?(node)
|
|
58
|
+
def_node_matcher :prohibited_rails_env?, <<~PATTERN
|
|
59
|
+
(send
|
|
60
|
+
(send (const _ :Rails) :env)
|
|
61
|
+
#prohibited_predicate?
|
|
62
|
+
)
|
|
63
|
+
PATTERN
|
|
60
64
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
def on_send(node)
|
|
66
|
+
add_offense(node.parent) if prohibited_rails_env?(node.parent)
|
|
67
|
+
end
|
|
64
68
|
|
|
65
|
-
|
|
69
|
+
private
|
|
66
70
|
|
|
67
|
-
|
|
71
|
+
def prohibited_predicate?(name)
|
|
72
|
+
name.to_s.end_with?("?") && !ALLOWED_LIST.include?(name)
|
|
68
73
|
end
|
|
69
74
|
end
|
|
70
75
|
end
|
|
@@ -33,6 +33,11 @@ module RuboCop
|
|
|
33
33
|
MSG = "Don't mock #{CLASSES.join('/')} directly. Use Rails Testing Time Helpers (eg `freeze_time` and `travel_to`) instead.".freeze
|
|
34
34
|
RESTRICT_ON_SEND = %i(to).freeze
|
|
35
35
|
|
|
36
|
+
# @!method and_call_original?(node)
|
|
37
|
+
def_node_search :and_call_original?, <<~PATTERN
|
|
38
|
+
(send _ :and_call_original)
|
|
39
|
+
PATTERN
|
|
40
|
+
|
|
36
41
|
# Matches allow/expect with a time class (or chain) receiver and a `receive` or `receive_message_chain`
|
|
37
42
|
# Examples matched:
|
|
38
43
|
# allow(Time).to receive(:now)
|
|
@@ -70,9 +75,7 @@ module RuboCop
|
|
|
70
75
|
return false if node.nil?
|
|
71
76
|
|
|
72
77
|
current = node
|
|
73
|
-
|
|
74
|
-
current = current.receiver
|
|
75
|
-
end
|
|
78
|
+
current = current.receiver while current&.send_type?
|
|
76
79
|
|
|
77
80
|
if current.nil?
|
|
78
81
|
return false
|
|
@@ -83,16 +86,14 @@ module RuboCop
|
|
|
83
86
|
# Accept both `Time` and `::Time` as root-level constants
|
|
84
87
|
namespace = current.namespace
|
|
85
88
|
is_root_level = namespace.nil? || namespace.cbase_type?
|
|
86
|
-
is_root_level && CLASSES.include?(current.
|
|
89
|
+
is_root_level && CLASSES.include?(current.short_name)
|
|
87
90
|
end
|
|
88
91
|
|
|
89
92
|
def and_call_original_in_chain?(node)
|
|
90
93
|
return false if node.nil?
|
|
91
94
|
return false unless node.send_type?
|
|
92
95
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
node.each_descendant(:send).any? { |send_node| send_node.method?(:and_call_original) }
|
|
96
|
+
and_call_original?(node)
|
|
96
97
|
end
|
|
97
98
|
end
|
|
98
99
|
end
|
|
@@ -5,15 +5,14 @@ module RuboCop
|
|
|
5
5
|
module Gusto
|
|
6
6
|
class SidekiqParams < Base
|
|
7
7
|
MSG = "Sidekiq perform methods cannot take keyword arguments"
|
|
8
|
-
PROHIBITED_ARG_TYPES = Set.new(%i(kwoptarg kwarg)).freeze
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
# @!method perform_with_kwargs?(node)
|
|
10
|
+
def_node_matcher :perform_with_kwargs?, <<~PATTERN
|
|
11
|
+
(def :perform (args <{kwarg kwoptarg} ...>) ...)
|
|
12
|
+
PATTERN
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
end
|
|
14
|
+
def on_def(node)
|
|
15
|
+
add_offense(node) if perform_with_kwargs?(node)
|
|
17
16
|
end
|
|
18
17
|
end
|
|
19
18
|
end
|
|
@@ -129,7 +129,7 @@ module RuboCop
|
|
|
129
129
|
|
|
130
130
|
def colorized_string?(node)
|
|
131
131
|
node.send_type? &&
|
|
132
|
-
node.receiver
|
|
132
|
+
node.receiver &&
|
|
133
133
|
string_or_colorized_receiver?(node.receiver)
|
|
134
134
|
end
|
|
135
135
|
|
|
@@ -152,19 +152,16 @@ module RuboCop
|
|
|
152
152
|
foreground = ":#{args.first.value}"
|
|
153
153
|
elsif args.length == 1 && args.first.hash_type?
|
|
154
154
|
# Hash argument, like colorize(color: :red, background: :blue)
|
|
155
|
-
args.first.
|
|
156
|
-
break unless
|
|
155
|
+
args.first.each_pair do |key_node, value_node|
|
|
156
|
+
break unless value_node.sym_type? # can't handle non-symbol arguments
|
|
157
157
|
|
|
158
|
-
|
|
159
|
-
value = ":#{pair.value.value}"
|
|
160
|
-
|
|
161
|
-
case key
|
|
158
|
+
case key_node.value
|
|
162
159
|
when :color
|
|
163
|
-
foreground = value
|
|
160
|
+
foreground = ":#{value_node.value}"
|
|
164
161
|
when :background
|
|
165
|
-
background = value
|
|
162
|
+
background = ":#{value_node.value}"
|
|
166
163
|
when :mode
|
|
167
|
-
styles << value
|
|
164
|
+
styles << ":#{value_node.value}"
|
|
168
165
|
else
|
|
169
166
|
break # unknown key, skip the rest of the hash
|
|
170
167
|
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rubocop/cop/rspec/scattered_let"
|
|
4
|
+
|
|
5
|
+
module RuboCop
|
|
6
|
+
module Cop
|
|
7
|
+
module RSpec
|
|
8
|
+
# Patches the upstream `RSpec/ScatteredLet` cop so that Sorbet `sig`
|
|
9
|
+
# declarations attached to `let`/`let!` blocks (Sorbet's RSpec mode)
|
|
10
|
+
# do not interrupt the consecutive-let chain.
|
|
11
|
+
#
|
|
12
|
+
# Without this patch the upstream cop flags valid `sig`+`let`
|
|
13
|
+
# arrangements because the intervening `sig` block breaks the
|
|
14
|
+
# consecutive-sibling check. (The sig-aware `MoveNode` patch in
|
|
15
|
+
# `lib/rubocop/gusto/move_node_patch.rb` handles dragging the `sig`
|
|
16
|
+
# along during autocorrect.)
|
|
17
|
+
#
|
|
18
|
+
# @example
|
|
19
|
+
# # good (no longer flagged)
|
|
20
|
+
# context "..." do
|
|
21
|
+
# sig { returns(Something) }
|
|
22
|
+
# let(:thing) { create(:something) }
|
|
23
|
+
#
|
|
24
|
+
# sig { returns(Other) }
|
|
25
|
+
# let(:other) { create(:other) }
|
|
26
|
+
# end
|
|
27
|
+
class ScatteredLet
|
|
28
|
+
LetUnit = Struct.new(:let, :start_index, :length)
|
|
29
|
+
private_constant :LetUnit
|
|
30
|
+
|
|
31
|
+
# @!method sig_block?(node)
|
|
32
|
+
def_node_matcher :sig_block?, <<~PATTERN
|
|
33
|
+
(block (send nil? :sig) _ _)
|
|
34
|
+
PATTERN
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def check_let_declarations(body)
|
|
39
|
+
children = body.each_child_node.to_a
|
|
40
|
+
units = build_let_units(children)
|
|
41
|
+
return if units.empty?
|
|
42
|
+
|
|
43
|
+
reference_unit = units.first
|
|
44
|
+
expected_start = reference_unit.start_index
|
|
45
|
+
|
|
46
|
+
units.each do |unit|
|
|
47
|
+
if unit.start_index == expected_start
|
|
48
|
+
reference_unit = unit
|
|
49
|
+
else
|
|
50
|
+
add_offense(unit.let) do |corrector|
|
|
51
|
+
::RuboCop::RSpec::Corrector::MoveNode.new(
|
|
52
|
+
unit.let, corrector, processed_source
|
|
53
|
+
).move_after(reference_unit.let)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
expected_start += unit.length
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def build_let_units(children)
|
|
61
|
+
children.each_with_index.with_object([]) do |(node, idx), units|
|
|
62
|
+
next unless let?(node)
|
|
63
|
+
|
|
64
|
+
prev = idx.positive? ? children[idx - 1] : nil
|
|
65
|
+
if prev && sig_block?(prev)
|
|
66
|
+
units << LetUnit.new(node, prev.sibling_index, 2)
|
|
67
|
+
else
|
|
68
|
+
units << LetUnit.new(node, node.sibling_index, 1)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rubocop/rspec/corrector/move_node"
|
|
4
|
+
|
|
5
|
+
module RuboCop
|
|
6
|
+
module RSpec
|
|
7
|
+
module Corrector
|
|
8
|
+
# Patches `MoveNode` to treat Sorbet `sig { ... }` blocks as part of the
|
|
9
|
+
# `let`/`subject`/hook they precede.
|
|
10
|
+
#
|
|
11
|
+
# Sorbet's RSpec mode attaches type signatures to memoized helpers via a
|
|
12
|
+
# `sig` block immediately above the declaration:
|
|
13
|
+
#
|
|
14
|
+
# sig { returns(Something) }
|
|
15
|
+
# let(:thing) { create(:something) }
|
|
16
|
+
#
|
|
17
|
+
# Several rubocop-rspec cops use `MoveNode` to relocate `let`/`subject`/
|
|
18
|
+
# hook nodes (`ScatteredLet`, `LeadingSubject`, `LetBeforeExamples`,
|
|
19
|
+
# `HooksBeforeExamples`). Without this patch, the move strands the `sig`
|
|
20
|
+
# at the original location. This patch:
|
|
21
|
+
#
|
|
22
|
+
# 1. Extends the source range of the moved node to include a preceding
|
|
23
|
+
# `sig` block, so `sig` is carried with the move.
|
|
24
|
+
# 2. In `move_before`, redirects the insertion point above a preceding
|
|
25
|
+
# `sig` on the destination, so the destination's `sig` pairing stays
|
|
26
|
+
# intact.
|
|
27
|
+
module SigAwareMoveNode
|
|
28
|
+
extend ::RuboCop::AST::NodePattern::Macros
|
|
29
|
+
|
|
30
|
+
# @!method sig_block?(node)
|
|
31
|
+
def_node_matcher :sig_block?, <<~PATTERN
|
|
32
|
+
(block (send nil? :sig ...) _ _)
|
|
33
|
+
PATTERN
|
|
34
|
+
|
|
35
|
+
def move_before(other)
|
|
36
|
+
sig = preceding_sig_block(other)
|
|
37
|
+
super(sig || other)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def node_range(node)
|
|
43
|
+
sig = preceding_sig_block(node)
|
|
44
|
+
return super unless sig
|
|
45
|
+
|
|
46
|
+
::Parser::Source::Range.new(
|
|
47
|
+
buffer,
|
|
48
|
+
begin_pos_with_comment(sig).begin_pos,
|
|
49
|
+
end_line_position(node).end_pos
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def preceding_sig_block(node)
|
|
54
|
+
prev = node.left_sibling
|
|
55
|
+
prev if sig_block?(prev)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
MoveNode.prepend(SigAwareMoveNode)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
data/lib/rubocop-gusto.rb
CHANGED
|
@@ -6,6 +6,7 @@ require "rubocop-rspec"
|
|
|
6
6
|
require_relative "rubocop/gusto"
|
|
7
7
|
require_relative "rubocop/gusto/version"
|
|
8
8
|
require_relative "rubocop/gusto/plugin"
|
|
9
|
+
require_relative "rubocop/gusto/move_node_patch"
|
|
9
10
|
|
|
10
11
|
# Require all cops
|
|
11
12
|
Dir.glob(File.join(File.dirname(__FILE__), "rubocop/cop/**/*.rb")).each do |file|
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubocop-gusto
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 10.
|
|
4
|
+
version: 10.9.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gusto Engineering
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: lint_roller
|
|
@@ -148,10 +148,12 @@ files:
|
|
|
148
148
|
- lib/rubocop/cop/internal_affairs/assignment_first.rb
|
|
149
149
|
- lib/rubocop/cop/internal_affairs/require_restrict_on_send.rb
|
|
150
150
|
- lib/rubocop/cop/rack/lowercase_header_keys.rb
|
|
151
|
+
- lib/rubocop/cop/rspec/scattered_let.rb
|
|
151
152
|
- lib/rubocop/gusto.rb
|
|
152
153
|
- lib/rubocop/gusto/cli.rb
|
|
153
154
|
- lib/rubocop/gusto/config_yml.rb
|
|
154
155
|
- lib/rubocop/gusto/init.rb
|
|
156
|
+
- lib/rubocop/gusto/move_node_patch.rb
|
|
155
157
|
- lib/rubocop/gusto/plugin.rb
|
|
156
158
|
- lib/rubocop/gusto/templates/rubocop.yml
|
|
157
159
|
- lib/rubocop/gusto/version.rb
|
|
@@ -174,7 +176,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
174
176
|
- !ruby/object:Gem::Version
|
|
175
177
|
version: '0'
|
|
176
178
|
requirements: []
|
|
177
|
-
rubygems_version:
|
|
179
|
+
rubygems_version: 4.0.10
|
|
178
180
|
specification_version: 4
|
|
179
181
|
summary: A gem for sharing gusto rubocop rules
|
|
180
182
|
test_files: []
|