rubocop-sorbet 0.6.11 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +3 -1
- data/.github/workflows/cla.yml +22 -0
- data/.github/workflows/stale.yml +24 -0
- data/.rubocop.yml +12 -1
- data/.yardopts +1 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +23 -17
- data/README.md +1 -1
- data/Rakefile +6 -6
- data/bin/rspec +4 -2
- data/bin/rubocop +4 -2
- data/config/default.yml +40 -3
- data/dev.yml +1 -1
- data/lib/rubocop/cop/sorbet/binding_constant_without_type_alias.rb +105 -0
- data/lib/rubocop/cop/sorbet/callback_conditionals_binding.rb +39 -11
- data/lib/rubocop/cop/sorbet/constants_from_strings.rb +5 -3
- data/lib/rubocop/cop/sorbet/forbid_include_const_literal.rb +27 -23
- data/lib/rubocop/cop/sorbet/forbid_superclass_const_literal.rb +26 -27
- data/lib/rubocop/cop/sorbet/forbid_t_unsafe.rb +7 -3
- data/lib/rubocop/cop/sorbet/forbid_t_untyped.rb +7 -3
- data/lib/rubocop/cop/sorbet/forbid_untyped_struct_props.rb +15 -9
- data/lib/rubocop/cop/sorbet/implicit_conversion_method.rb +56 -0
- data/lib/rubocop/cop/sorbet/mixin/target_sorbet_version.rb +49 -0
- data/lib/rubocop/cop/sorbet/mutable_constant_sorbet_aware_behaviour.rb +8 -5
- data/lib/rubocop/cop/sorbet/obsolete_strict_memoization.rb +92 -0
- data/lib/rubocop/cop/sorbet/one_ancestor_per_line.rb +8 -3
- data/lib/rubocop/cop/sorbet/rbi/forbid_extend_t_sig_helpers_in_shims.rb +12 -18
- data/lib/rubocop/cop/sorbet/rbi/forbid_rbi_outside_of_allowed_paths.rb +10 -8
- data/lib/rubocop/cop/sorbet/rbi/single_line_rbi_class_module_definitions.rb +12 -18
- data/lib/rubocop/cop/sorbet/redundant_extend_t_sig.rb +49 -0
- data/lib/rubocop/cop/sorbet/sigils/enforce_sigil_order.rb +5 -4
- data/lib/rubocop/cop/sorbet/sigils/enforce_single_sigil.rb +6 -5
- data/lib/rubocop/cop/sorbet/sigils/false_sigil.rb +1 -1
- data/lib/rubocop/cop/sorbet/sigils/has_sigil.rb +1 -1
- data/lib/rubocop/cop/sorbet/sigils/ignore_sigil.rb +1 -1
- data/lib/rubocop/cop/sorbet/sigils/strict_sigil.rb +1 -1
- data/lib/rubocop/cop/sorbet/sigils/strong_sigil.rb +1 -1
- data/lib/rubocop/cop/sorbet/sigils/true_sigil.rb +1 -1
- data/lib/rubocop/cop/sorbet/sigils/valid_sigil.rb +50 -25
- data/lib/rubocop/cop/sorbet/signatures/allow_incompatible_override.rb +19 -30
- data/lib/rubocop/cop/sorbet/signatures/checked_true_in_signature.rb +3 -2
- data/lib/rubocop/cop/sorbet/signatures/empty_line_after_sig.rb +57 -0
- data/lib/rubocop/cop/sorbet/signatures/enforce_signatures.rb +8 -4
- data/lib/rubocop/cop/sorbet/signatures/keyword_argument_ordering.rb +5 -4
- data/lib/rubocop/cop/sorbet/signatures/signature_build_order.rb +10 -3
- data/lib/rubocop/cop/sorbet/signatures/signature_cop.rb +11 -9
- data/lib/rubocop/cop/sorbet/type_alias_name.rb +10 -17
- data/lib/rubocop/cop/sorbet_cops.rb +8 -1
- data/lib/rubocop/sorbet/inject.rb +9 -7
- data/lib/rubocop/sorbet/version.rb +2 -1
- data/lib/rubocop/sorbet.rb +1 -0
- data/manual/cops.md +4 -0
- data/manual/cops_sorbet.md +195 -38
- data/rubocop-sorbet.gemspec +1 -0
- data/service.yml +0 -1
- data/tasks/cops_documentation.rake +16 -5
- metadata +12 -6
- data/.github/probots.yml +0 -3
- data/.github/stale.yml +0 -20
- data/lib/rubocop/cop/sorbet/binding_constants_without_type_alias.rb +0 -127
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0d4456bcb92b2f40f1208842fce6a102f6ce2ba88ff491840d77a3001784677
|
4
|
+
data.tar.gz: 5e389a2c6c772f68aaf95555da670732ac70a9c5262be18c0418e0d787feb5de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c2cb4129f91d6c52aa3affe2728a9c049635ce9ccefdcaa86520bbf0a1d25b7160a3d253597329008661f4207bf953ec36058c3908874b6f9077da0742a9f15f
|
7
|
+
data.tar.gz: c4736a927b8f377f81bf7982e9a6d6fa4669b6ebc7dea5c60bba7a8e54adc843f096c8bfe6a0eea7fc47e34cc4374c4675495936d5c9b1289a17b2d226c44375
|
data/.github/workflows/ci.yml
CHANGED
@@ -11,7 +11,7 @@ jobs:
|
|
11
11
|
strategy:
|
12
12
|
fail-fast: false
|
13
13
|
matrix:
|
14
|
-
ruby: [ '2.
|
14
|
+
ruby: [ '2.7', '3.0', '3.1', '3.2' ]
|
15
15
|
name: Test Ruby ${{ matrix.ruby }}
|
16
16
|
steps:
|
17
17
|
- uses: actions/checkout@v2
|
@@ -22,5 +22,7 @@ jobs:
|
|
22
22
|
bundler-cache: true
|
23
23
|
- name: Lint Ruby files
|
24
24
|
run: bin/rubocop
|
25
|
+
- name: Verify documentation is up to date
|
26
|
+
run: bundle exec rake generate_cops_documentation
|
25
27
|
- name: Run tests
|
26
28
|
run: bin/rspec
|
@@ -0,0 +1,22 @@
|
|
1
|
+
name: Contributor License Agreement (CLA)
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request_target:
|
5
|
+
types: [opened, synchronize, reopened]
|
6
|
+
issue_comment:
|
7
|
+
types: [created]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
cla:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
if: |
|
13
|
+
(github.event.issue.pull_request
|
14
|
+
&& !github.event.issue.pull_request.merged_at
|
15
|
+
&& contains(github.event.comment.body, 'signed')
|
16
|
+
)
|
17
|
+
|| (github.event.pull_request && !github.event.pull_request.merged)
|
18
|
+
steps:
|
19
|
+
- uses: Shopify/shopify-cla-action@v1
|
20
|
+
with:
|
21
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
22
|
+
cla-token: ${{ secrets.CLA_TOKEN }}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
name: "Close stale PRs"
|
2
|
+
|
3
|
+
permissions:
|
4
|
+
pull-requests: write
|
5
|
+
issues: write
|
6
|
+
|
7
|
+
on:
|
8
|
+
schedule:
|
9
|
+
- cron: "55 1 * * *"
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
stale:
|
13
|
+
runs-on: ubuntu-latest
|
14
|
+
steps:
|
15
|
+
- uses: actions/stale@v5
|
16
|
+
with:
|
17
|
+
stale-pr-message: >
|
18
|
+
This PR has been automatically marked as stale because it has not had
|
19
|
+
recent activity. It will be closed if no further activity occurs. Thank you
|
20
|
+
for your contributions.
|
21
|
+
days-before-stale: 30
|
22
|
+
days-before-issue-stale: -1
|
23
|
+
days-before-close: 7
|
24
|
+
exempt-pr-labels: pinned,security
|
data/.rubocop.yml
CHANGED
@@ -3,11 +3,22 @@
|
|
3
3
|
inherit_gem:
|
4
4
|
rubocop-shopify: rubocop.yml
|
5
5
|
|
6
|
+
require:
|
7
|
+
- rubocop/cop/internal_affairs
|
8
|
+
|
6
9
|
AllCops:
|
7
|
-
TargetRubyVersion: 2.
|
10
|
+
TargetRubyVersion: 2.7
|
8
11
|
Exclude:
|
9
12
|
- vendor/**/*
|
13
|
+
NewCops: disable
|
14
|
+
SuggestExtensions: false
|
15
|
+
|
16
|
+
InternalAffairs:
|
17
|
+
Enabled: true
|
10
18
|
|
11
19
|
Naming/FileName:
|
12
20
|
Exclude:
|
13
21
|
- lib/rubocop-sorbet.rb
|
22
|
+
|
23
|
+
Layout/LineLength:
|
24
|
+
IgnoreCopDirectives: true
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--tag safety:"Cop Safety Information"
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rubocop-sorbet (0.
|
4
|
+
rubocop-sorbet (0.7.1)
|
5
5
|
rubocop (>= 0.90.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -10,13 +10,17 @@ GEM
|
|
10
10
|
ast (2.4.2)
|
11
11
|
byebug (11.1.3)
|
12
12
|
diff-lcs (1.3)
|
13
|
-
|
14
|
-
|
13
|
+
json (2.6.3)
|
14
|
+
language_server-protocol (3.17.0.3)
|
15
|
+
parallel (1.23.0)
|
16
|
+
parser (3.2.2.3)
|
15
17
|
ast (~> 2.4.1)
|
18
|
+
racc
|
19
|
+
racc (1.7.1)
|
16
20
|
rainbow (3.1.1)
|
17
21
|
rake (13.0.1)
|
18
|
-
regexp_parser (2.
|
19
|
-
rexml (3.2.
|
22
|
+
regexp_parser (2.8.1)
|
23
|
+
rexml (3.2.6)
|
20
24
|
rspec (3.8.0)
|
21
25
|
rspec-core (~> 3.8.0)
|
22
26
|
rspec-expectations (~> 3.8.0)
|
@@ -30,21 +34,23 @@ GEM
|
|
30
34
|
diff-lcs (>= 1.2.0, < 2.0)
|
31
35
|
rspec-support (~> 3.8.0)
|
32
36
|
rspec-support (3.8.2)
|
33
|
-
rubocop (1.
|
37
|
+
rubocop (1.55.1)
|
38
|
+
json (~> 2.3)
|
39
|
+
language_server-protocol (>= 3.17.0)
|
34
40
|
parallel (~> 1.10)
|
35
|
-
parser (>= 3.
|
41
|
+
parser (>= 3.2.2.3)
|
36
42
|
rainbow (>= 2.2.2, < 4.0)
|
37
43
|
regexp_parser (>= 1.8, < 3.0)
|
38
|
-
rexml
|
39
|
-
rubocop-ast (>= 1.
|
44
|
+
rexml (>= 3.2.5, < 4.0)
|
45
|
+
rubocop-ast (>= 1.28.1, < 2.0)
|
40
46
|
ruby-progressbar (~> 1.7)
|
41
|
-
unicode-display_width (>=
|
42
|
-
rubocop-ast (1.
|
43
|
-
parser (>= 3.
|
44
|
-
rubocop-shopify (2.
|
45
|
-
rubocop (~> 1.
|
46
|
-
ruby-progressbar (1.
|
47
|
-
unicode-display_width (2.
|
47
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
48
|
+
rubocop-ast (1.29.0)
|
49
|
+
parser (>= 3.2.1.0)
|
50
|
+
rubocop-shopify (2.14.0)
|
51
|
+
rubocop (~> 1.51)
|
52
|
+
ruby-progressbar (1.13.0)
|
53
|
+
unicode-display_width (2.4.2)
|
48
54
|
unparser (0.6.0)
|
49
55
|
diff-lcs (~> 1.3)
|
50
56
|
parser (>= 3.0.0)
|
@@ -63,4 +69,4 @@ DEPENDENCIES
|
|
63
69
|
yard (~> 0.9)
|
64
70
|
|
65
71
|
BUNDLED WITH
|
66
|
-
2.
|
72
|
+
2.4.18
|
data/README.md
CHANGED
@@ -98,7 +98,7 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/Shopif
|
|
98
98
|
To contribute a new cop, please use the supplied generator like this:
|
99
99
|
|
100
100
|
```sh
|
101
|
-
bundle exec rake new_cop[Sorbet/NewCopName]
|
101
|
+
bundle exec rake "new_cop[Sorbet/NewCopName]"
|
102
102
|
```
|
103
103
|
|
104
104
|
which will create a skeleton cop, a skeleton spec, an entry in the default config file and will require the new cop so that it is properly exported from the gem.
|
data/Rakefile
CHANGED
@@ -18,19 +18,19 @@ task :new_cop, [:cop] do |_task, args|
|
|
18
18
|
require "rubocop"
|
19
19
|
|
20
20
|
cop_name = args.fetch(:cop) do
|
21
|
-
warn(
|
21
|
+
warn('usage: bundle exec rake "new_cop[Department/Name]"')
|
22
22
|
exit!
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
github_user = "Shopify" if github_user.empty?
|
27
|
-
|
28
|
-
generator = RuboCop::Cop::Generator.new(cop_name, github_user)
|
25
|
+
generator = RuboCop::Cop::Generator.new(cop_name)
|
29
26
|
|
30
27
|
generator.write_source
|
31
28
|
generator.write_spec
|
32
29
|
generator.inject_require(root_file_path: "lib/rubocop/cop/sorbet_cops.rb")
|
33
30
|
generator.inject_config(config_file_path: "config/default.yml")
|
34
31
|
|
35
|
-
|
32
|
+
# We don't use Rubocop's changelog automation workflow
|
33
|
+
todo_without_changelog_instruction = generator.todo
|
34
|
+
.sub(/$\s+4\. Run.*changelog.*for your new cop\.$/m, "")
|
35
|
+
puts todo_without_changelog_instruction
|
36
36
|
end
|
data/bin/rspec
CHANGED
@@ -9,8 +9,10 @@
|
|
9
9
|
#
|
10
10
|
|
11
11
|
require "pathname"
|
12
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
|
13
|
-
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
|
13
|
+
"../../Gemfile",
|
14
|
+
Pathname.new(__FILE__).realpath,
|
15
|
+
)
|
14
16
|
|
15
17
|
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
18
|
|
data/bin/rubocop
CHANGED
@@ -9,8 +9,10 @@
|
|
9
9
|
#
|
10
10
|
|
11
11
|
require "pathname"
|
12
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
|
13
|
-
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
|
13
|
+
"../../Gemfile",
|
14
|
+
Pathname.new(__FILE__).realpath,
|
15
|
+
)
|
14
16
|
|
15
17
|
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
18
|
|
data/config/default.yml
CHANGED
@@ -25,6 +25,11 @@ Sorbet/CheckedTrueInSignature:
|
|
25
25
|
Enabled: true
|
26
26
|
VersionAdded: 0.2.0
|
27
27
|
|
28
|
+
Sorbet/EmptyLineAfterSig:
|
29
|
+
Description: 'Ensures that there are no blank lines after signatures'
|
30
|
+
Enabled: true
|
31
|
+
VersionAdded: 0.7.0
|
32
|
+
|
28
33
|
Sorbet/ConstantsFromStrings:
|
29
34
|
Description: >-
|
30
35
|
Forbids constant access through meta-programming.
|
@@ -42,7 +47,7 @@ Sorbet/EnforceSigilOrder:
|
|
42
47
|
Sorbet/EnforceSingleSigil:
|
43
48
|
Description: 'Ensures that there is only one Sorbet sigil in a file.'
|
44
49
|
Enabled: true
|
45
|
-
VersionAdded:
|
50
|
+
VersionAdded: 0.7.0
|
46
51
|
|
47
52
|
Sorbet/EnforceSignatures:
|
48
53
|
Description: 'Ensures all methods have a valid signature.'
|
@@ -73,6 +78,7 @@ Sorbet/ForbidRBIOutsideOfAllowedPaths:
|
|
73
78
|
Enabled: true
|
74
79
|
VersionAdded: 0.6.1
|
75
80
|
AllowedPaths:
|
81
|
+
- "rbi/**"
|
76
82
|
- "sorbet/rbi/**"
|
77
83
|
Include:
|
78
84
|
- "**/*.rbi"
|
@@ -114,7 +120,8 @@ Sorbet/HasSigil:
|
|
114
120
|
Description: 'Makes the Sorbet typed sigil mandatory in all files.'
|
115
121
|
Enabled: false
|
116
122
|
SuggestedStrictness: "false"
|
117
|
-
MinimumStrictness:
|
123
|
+
MinimumStrictness: nil
|
124
|
+
ExactStrictness: nil
|
118
125
|
VersionAdded: 0.3.3
|
119
126
|
Include:
|
120
127
|
- "**/*.{rb,rbi,rake,ru}"
|
@@ -135,6 +142,13 @@ Sorbet/IgnoreSigil:
|
|
135
142
|
- db/**/*.rb
|
136
143
|
- script/**/*
|
137
144
|
|
145
|
+
Sorbet/ImplicitConversionMethod:
|
146
|
+
Description: >-
|
147
|
+
This cop disallows declaring implicit conversion methods, as sorbet does
|
148
|
+
not support implicit conversion.
|
149
|
+
Enabled: false
|
150
|
+
VersionAdded: '<<next>>'
|
151
|
+
|
138
152
|
Sorbet/KeywordArgumentOrdering:
|
139
153
|
Description: >-
|
140
154
|
Enforces a compatible keyword arguments with Sorbet.
|
@@ -145,11 +159,33 @@ Sorbet/KeywordArgumentOrdering:
|
|
145
159
|
Enabled: true
|
146
160
|
VersionAdded: 0.2.0
|
147
161
|
|
162
|
+
Sorbet/ObsoleteStrictMemoization:
|
163
|
+
Description: >-
|
164
|
+
This cop checks for the obsolete pattern for initializing instance variables that was required for older Sorbet
|
165
|
+
versions in `#typed: strict` files.
|
166
|
+
|
167
|
+
It's no longer required, as of Sorbet 0.5.10210
|
168
|
+
See https://sorbet.org/docs/type-assertions#put-type-assertions-behind-memoization
|
169
|
+
Enabled: true
|
170
|
+
VersionAdded: '0.7.1'
|
171
|
+
Safe: true
|
172
|
+
SafeAutoCorrect: true
|
173
|
+
|
148
174
|
Sorbet/OneAncestorPerLine:
|
149
175
|
Description: 'Enforces one ancestor per call to requires_ancestor'
|
150
176
|
Enabled: false
|
151
177
|
VersionAdded: '0.6.0'
|
152
178
|
|
179
|
+
Sorbet/RedundantExtendTSig:
|
180
|
+
Description: >-
|
181
|
+
Forbid the usage of redundant `extend T::Sig`.
|
182
|
+
|
183
|
+
Only for use in applications that monkey patch `Module.include(T::Sig)` directly,
|
184
|
+
where it is useful to reduce noise.
|
185
|
+
Enabled: false
|
186
|
+
Safe: false
|
187
|
+
VersionAdded: 0.7.0
|
188
|
+
|
153
189
|
Sorbet/SignatureBuildOrder:
|
154
190
|
Description: >-
|
155
191
|
Enforces the order of parts in a signature.
|
@@ -219,7 +255,8 @@ Sorbet/ValidSigil:
|
|
219
255
|
Enabled: true
|
220
256
|
RequireSigilOnAllFiles: false
|
221
257
|
SuggestedStrictness: "false"
|
222
|
-
MinimumStrictness:
|
258
|
+
MinimumStrictness: nil
|
259
|
+
ExactStrictness: nil
|
223
260
|
VersionAdded: 0.3.3
|
224
261
|
Include:
|
225
262
|
- "**/*.{rb,rbi,rake,ru}"
|
data/dev.yml
CHANGED
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubocop"
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
module Cop
|
7
|
+
module Sorbet
|
8
|
+
# Disallows binding the return value of `T.any`, `T.all`, `T.enum`
|
9
|
+
# to a constant directly. To bind the value, one must use `T.type_alias`.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
#
|
13
|
+
# # bad
|
14
|
+
# FooOrBar = T.any(Foo, Bar)
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# FooOrBar = T.type_alias { T.any(Foo, Bar) }
|
18
|
+
class BindingConstantWithoutTypeAlias < RuboCop::Cop::Base
|
19
|
+
extend AutoCorrector
|
20
|
+
|
21
|
+
MSG = "It looks like you're trying to bind a type to a constant. " \
|
22
|
+
"To do this, you must alias the type using `T.type_alias`."
|
23
|
+
WITHOUT_BLOCK_MSG = "It looks like you're using the old `T.type_alias` syntax. " \
|
24
|
+
"`T.type_alias` now expects a block." \
|
25
|
+
'Run Sorbet with the options "--autocorrect --error-white-list=5043" ' \
|
26
|
+
"to automatically upgrade to the new syntax."
|
27
|
+
|
28
|
+
# @!method type_alias_without_block(node)
|
29
|
+
def_node_matcher :type_alias_without_block, <<~PATTERN
|
30
|
+
(send
|
31
|
+
(const {nil? cbase} :T)
|
32
|
+
:type_alias
|
33
|
+
$_
|
34
|
+
)
|
35
|
+
PATTERN
|
36
|
+
|
37
|
+
# @!method type_alias_with_block?(node)
|
38
|
+
def_node_matcher :type_alias_with_block?, <<~PATTERN
|
39
|
+
(block
|
40
|
+
(send
|
41
|
+
(const {nil? cbase} :T)
|
42
|
+
:type_alias)
|
43
|
+
...
|
44
|
+
)
|
45
|
+
PATTERN
|
46
|
+
|
47
|
+
# @!method requires_type_alias?(node)
|
48
|
+
def_node_matcher :requires_type_alias?, <<~PATTERN
|
49
|
+
(send
|
50
|
+
(const {nil? cbase} :T)
|
51
|
+
{
|
52
|
+
:all
|
53
|
+
:any
|
54
|
+
:class_of
|
55
|
+
:nilable
|
56
|
+
:noreturn
|
57
|
+
:proc
|
58
|
+
:self_type
|
59
|
+
:untyped
|
60
|
+
}
|
61
|
+
...
|
62
|
+
)
|
63
|
+
PATTERN
|
64
|
+
|
65
|
+
def on_casgn(node)
|
66
|
+
expression = node.expression
|
67
|
+
return if expression.nil? # multiple assignment
|
68
|
+
|
69
|
+
type_alias_without_block(expression) do |type|
|
70
|
+
return add_offense(expression, message: WITHOUT_BLOCK_MSG) do |corrector|
|
71
|
+
corrector.replace(expression, "T.type_alias { #{type.source} }")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
return if type_alias_with_block?(expression)
|
76
|
+
|
77
|
+
requires_type_alias?(send_leaf(expression)) do
|
78
|
+
return add_offense(expression) do |corrector|
|
79
|
+
corrector.replace(expression, "T.type_alias { #{expression.source} }")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
# Given nested send nodes, returns the leaf with explicit receiver.
|
87
|
+
#
|
88
|
+
# i.e. in Ruby
|
89
|
+
#
|
90
|
+
# a.b.c.d.e.f
|
91
|
+
# ^^^
|
92
|
+
#
|
93
|
+
# i.e. in AST
|
94
|
+
#
|
95
|
+
# (send (send (send (send (send (send nil :a) :b) :c) :d) :e) :f)
|
96
|
+
# ^^^^^^^^^^^^^^^^^^^^^^^
|
97
|
+
#
|
98
|
+
def send_leaf(node)
|
99
|
+
node = node.receiver while node&.receiver&.send_type?
|
100
|
+
node
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Sorbet
|
6
|
-
#
|
6
|
+
# Ensures that callback conditionals are bound to the right type
|
7
7
|
# so that they are type checked properly.
|
8
8
|
#
|
9
9
|
# Auto-correction is unsafe because other libraries define similar style callbacks as Rails, but don't always need
|
@@ -32,16 +32,44 @@ module RuboCop
|
|
32
32
|
# true
|
33
33
|
# end
|
34
34
|
# end
|
35
|
-
class CallbackConditionalsBinding < RuboCop::Cop::Cop
|
35
|
+
class CallbackConditionalsBinding < RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
|
36
36
|
CALLBACKS = [
|
37
|
-
:validate,
|
38
|
-
:
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
42
|
-
:
|
43
|
-
:
|
44
|
-
:
|
37
|
+
:validate,
|
38
|
+
:validates,
|
39
|
+
:validates_with,
|
40
|
+
:before_validation,
|
41
|
+
:around_validation,
|
42
|
+
:before_create,
|
43
|
+
:before_save,
|
44
|
+
:before_destroy,
|
45
|
+
:before_update,
|
46
|
+
:after_create,
|
47
|
+
:after_save,
|
48
|
+
:after_destroy,
|
49
|
+
:after_update,
|
50
|
+
:after_touch,
|
51
|
+
:after_initialize,
|
52
|
+
:after_find,
|
53
|
+
:around_create,
|
54
|
+
:around_save,
|
55
|
+
:around_destroy,
|
56
|
+
:around_update,
|
57
|
+
:before_commit,
|
58
|
+
:after_commit,
|
59
|
+
:after_create_commit,
|
60
|
+
:after_destroy_commit,
|
61
|
+
:after_rollback,
|
62
|
+
:after_save_commit,
|
63
|
+
:after_update_commit,
|
64
|
+
:before_action,
|
65
|
+
:prepend_before_action,
|
66
|
+
:append_before_action,
|
67
|
+
:around_action,
|
68
|
+
:prepend_around_action,
|
69
|
+
:append_around_action,
|
70
|
+
:after_action,
|
71
|
+
:prepend_after_action,
|
72
|
+
:append_after_action,
|
45
73
|
].freeze
|
46
74
|
|
47
75
|
def autocorrect(node)
|
@@ -132,7 +160,7 @@ module RuboCop
|
|
132
160
|
unless block.source.include?("T.bind(self")
|
133
161
|
add_offense(
|
134
162
|
node,
|
135
|
-
message: "Callback conditionals should be bound to the right type. Use T.bind(self, #{expected_class})"
|
163
|
+
message: "Callback conditionals should be bound to the right type. Use T.bind(self, #{expected_class})",
|
136
164
|
)
|
137
165
|
end
|
138
166
|
end
|
@@ -5,7 +5,7 @@ require "rubocop"
|
|
5
5
|
module RuboCop
|
6
6
|
module Cop
|
7
7
|
module Sorbet
|
8
|
-
#
|
8
|
+
# Disallows the calls that are used to get constants fom Strings
|
9
9
|
# such as +constantize+, +const_get+, and +constants+.
|
10
10
|
#
|
11
11
|
# The goal of this cop is to make the code easier to statically analyze,
|
@@ -33,18 +33,20 @@ module RuboCop
|
|
33
33
|
#
|
34
34
|
# # good
|
35
35
|
# { "User" => User }.fetch(class_name)
|
36
|
-
class ConstantsFromStrings < ::RuboCop::Cop::Cop
|
36
|
+
class ConstantsFromStrings < ::RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
|
37
|
+
# @!method constant_from_string?(node)
|
37
38
|
def_node_matcher(:constant_from_string?, <<-PATTERN)
|
38
39
|
(send _ {:constantize :constants :const_get} ...)
|
39
40
|
PATTERN
|
40
41
|
|
41
42
|
def on_send(node)
|
42
43
|
return unless constant_from_string?(node)
|
44
|
+
|
43
45
|
add_offense(
|
44
46
|
node,
|
45
47
|
location: :selector,
|
46
48
|
message: "Don't use `#{node.method_name}`, it makes the code harder to understand, less editor-friendly, " \
|
47
|
-
"and impossible to analyze. Replace `#{node.method_name}` with a case/when or a hash."
|
49
|
+
"and impossible to analyze. Replace `#{node.method_name}` with a case/when or a hash.",
|
48
50
|
)
|
49
51
|
end
|
50
52
|
end
|
@@ -3,34 +3,35 @@
|
|
3
3
|
|
4
4
|
require "rubocop"
|
5
5
|
|
6
|
-
# Correct `send` expressions in include statements by constant literals.
|
7
|
-
#
|
8
|
-
# Sorbet, the static checker, is not (yet) able to support constructs on the
|
9
|
-
# following form:
|
10
|
-
#
|
11
|
-
# ```ruby
|
12
|
-
# class MyClass
|
13
|
-
# include send_expr
|
14
|
-
# end
|
15
|
-
# ```
|
16
|
-
#
|
17
|
-
# Multiple occurences of this can be found in Shopify's code base like:
|
18
|
-
#
|
19
|
-
# ```ruby
|
20
|
-
# include Rails.application.routes.url_helpers
|
21
|
-
# ```
|
22
|
-
# or
|
23
|
-
# ```ruby
|
24
|
-
# include Polaris::Engine.helpers
|
25
|
-
# ```
|
26
6
|
module RuboCop
|
27
7
|
module Cop
|
28
8
|
module Sorbet
|
29
|
-
|
9
|
+
# Correct `send` expressions in include statements by constant literals.
|
10
|
+
#
|
11
|
+
# Sorbet, the static checker, is not (yet) able to support constructs on the
|
12
|
+
# following form:
|
13
|
+
#
|
14
|
+
# ```ruby
|
15
|
+
# class MyClass
|
16
|
+
# include send_expr
|
17
|
+
# end
|
18
|
+
# ```
|
19
|
+
#
|
20
|
+
# Multiple occurences of this can be found in Shopify's code base like:
|
21
|
+
#
|
22
|
+
# ```ruby
|
23
|
+
# include Rails.application.routes.url_helpers
|
24
|
+
# ```
|
25
|
+
# or
|
26
|
+
# ```ruby
|
27
|
+
# include Polaris::Engine.helpers
|
28
|
+
# ```
|
29
|
+
class ForbidIncludeConstLiteral < RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
|
30
30
|
MSG = "Includes must only contain constant literals"
|
31
31
|
|
32
32
|
attr_accessor :used_names
|
33
33
|
|
34
|
+
# @!method not_lit_const_include?(node)
|
34
35
|
def_node_matcher :not_lit_const_include?, <<-PATTERN
|
35
36
|
(send nil? {:include :extend :prepend}
|
36
37
|
$_
|
@@ -46,18 +47,21 @@ module RuboCop
|
|
46
47
|
return unless not_lit_const_include?(node) do |send_argument|
|
47
48
|
![:const, :self].include?(send_argument.type)
|
48
49
|
end
|
50
|
+
|
49
51
|
parent = node.parent
|
50
52
|
return unless parent
|
53
|
+
|
51
54
|
parent = parent.parent if [:begin, :block].include?(parent.type)
|
52
55
|
return unless [:module, :class, :sclass].include?(parent.type)
|
56
|
+
|
53
57
|
add_offense(node)
|
54
58
|
end
|
55
59
|
|
56
60
|
def autocorrect(node)
|
57
61
|
lambda do |corrector|
|
58
62
|
corrector.replace(
|
59
|
-
node
|
60
|
-
"T.unsafe(self).#{node.source}"
|
63
|
+
node,
|
64
|
+
"T.unsafe(self).#{node.source}",
|
61
65
|
)
|
62
66
|
end
|
63
67
|
end
|