rubocop-sorbet 0.7.0 → 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 +1 -1
- 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 +1 -1
- data/bin/rspec +4 -2
- data/bin/rubocop +4 -2
- data/config/default.yml +23 -2
- 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 +13 -11
- 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 +8 -7
- 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 +5 -6
- data/lib/rubocop/cop/sorbet/sigils/enforce_sigil_order.rb +3 -2
- 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 +3 -3
- 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 +8 -3
- data/lib/rubocop/cop/sorbet/signatures/signature_cop.rb +6 -1
- data/lib/rubocop/cop/sorbet/type_alias_name.rb +10 -17
- data/lib/rubocop/cop/sorbet_cops.rb +6 -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 +2 -0
- data/manual/cops_sorbet.md +137 -31
- data/rubocop-sorbet.gemspec +1 -0
- data/tasks/cops_documentation.rake +16 -5
- metadata +8 -4
- 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
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.7.
|
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
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
@@ -120,7 +120,8 @@ Sorbet/HasSigil:
|
|
120
120
|
Description: 'Makes the Sorbet typed sigil mandatory in all files.'
|
121
121
|
Enabled: false
|
122
122
|
SuggestedStrictness: "false"
|
123
|
-
MinimumStrictness:
|
123
|
+
MinimumStrictness: nil
|
124
|
+
ExactStrictness: nil
|
124
125
|
VersionAdded: 0.3.3
|
125
126
|
Include:
|
126
127
|
- "**/*.{rb,rbi,rake,ru}"
|
@@ -141,6 +142,13 @@ Sorbet/IgnoreSigil:
|
|
141
142
|
- db/**/*.rb
|
142
143
|
- script/**/*
|
143
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
|
+
|
144
152
|
Sorbet/KeywordArgumentOrdering:
|
145
153
|
Description: >-
|
146
154
|
Enforces a compatible keyword arguments with Sorbet.
|
@@ -151,6 +159,18 @@ Sorbet/KeywordArgumentOrdering:
|
|
151
159
|
Enabled: true
|
152
160
|
VersionAdded: 0.2.0
|
153
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
|
+
|
154
174
|
Sorbet/OneAncestorPerLine:
|
155
175
|
Description: 'Enforces one ancestor per call to requires_ancestor'
|
156
176
|
Enabled: false
|
@@ -235,7 +255,8 @@ Sorbet/ValidSigil:
|
|
235
255
|
Enabled: true
|
236
256
|
RequireSigilOnAllFiles: false
|
237
257
|
SuggestedStrictness: "false"
|
238
|
-
MinimumStrictness:
|
258
|
+
MinimumStrictness: nil
|
259
|
+
ExactStrictness: nil
|
239
260
|
VersionAdded: 0.3.3
|
240
261
|
Include:
|
241
262
|
- "**/*.{rb,rbi,rake,ru}"
|
@@ -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
|
@@ -3,41 +3,40 @@
|
|
3
3
|
|
4
4
|
require "rubocop"
|
5
5
|
|
6
|
-
# Correct superclass `send` expressions 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 Foo < send_expr; end
|
13
|
-
# ```
|
14
|
-
#
|
15
|
-
# Multiple occurences of this can be found in Shopify's code base like:
|
16
|
-
#
|
17
|
-
# ```ruby
|
18
|
-
# class ShopScope < Component::TrustedIdScope[ShopIdentity::ShopId]
|
19
|
-
# ```
|
20
|
-
# or
|
21
|
-
# ```ruby
|
22
|
-
# class ApiClientEligibility < Struct.new(:api_client, :match_results, :shop)
|
23
|
-
# ```
|
24
6
|
module RuboCop
|
25
7
|
module Cop
|
26
8
|
module Sorbet
|
27
|
-
|
9
|
+
# Correct superclass `send` expressions 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 Foo < send_expr; end
|
16
|
+
# ```
|
17
|
+
#
|
18
|
+
# Multiple occurences of this can be found in Shopify's code base like:
|
19
|
+
#
|
20
|
+
# ```ruby
|
21
|
+
# class ShopScope < Component::TrustedIdScope[ShopIdentity::ShopId]
|
22
|
+
# ```
|
23
|
+
# or
|
24
|
+
# ```ruby
|
25
|
+
# class ApiClientEligibility < Struct.new(:api_client, :match_results, :shop)
|
26
|
+
# ```
|
27
|
+
|
28
|
+
class ForbidSuperclassConstLiteral < RuboCop::Cop::Base
|
28
29
|
MSG = "Superclasses must only contain constant literals"
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
(send ...)
|
34
|
-
...
|
35
|
-
)
|
31
|
+
# @!method dynamic_superclass?(node)
|
32
|
+
def_node_matcher :dynamic_superclass?, <<-PATTERN
|
33
|
+
(class (const ...) $(send ...) ...)
|
36
34
|
PATTERN
|
37
35
|
|
38
36
|
def on_class(node)
|
39
|
-
|
40
|
-
|
37
|
+
dynamic_superclass?(node) do |superclass|
|
38
|
+
add_offense(superclass)
|
39
|
+
end
|
41
40
|
end
|
42
41
|
end
|
43
42
|
end
|
@@ -5,7 +5,7 @@ require "rubocop"
|
|
5
5
|
module RuboCop
|
6
6
|
module Cop
|
7
7
|
module Sorbet
|
8
|
-
#
|
8
|
+
# Disallows using `T.unsafe` anywhere.
|
9
9
|
#
|
10
10
|
# @example
|
11
11
|
#
|
@@ -14,11 +14,15 @@ module RuboCop
|
|
14
14
|
#
|
15
15
|
# # good
|
16
16
|
# foo
|
17
|
-
class ForbidTUnsafe < RuboCop::Cop::
|
17
|
+
class ForbidTUnsafe < RuboCop::Cop::Base
|
18
|
+
MSG = "Do not use `T.unsafe`."
|
19
|
+
RESTRICT_ON_SEND = [:unsafe].freeze
|
20
|
+
|
21
|
+
# @!method t_unsafe?(node)
|
18
22
|
def_node_matcher(:t_unsafe?, "(send (const nil? :T) :unsafe _)")
|
19
23
|
|
20
24
|
def on_send(node)
|
21
|
-
add_offense(node
|
25
|
+
add_offense(node) if t_unsafe?(node)
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
@@ -5,7 +5,7 @@ require "rubocop"
|
|
5
5
|
module RuboCop
|
6
6
|
module Cop
|
7
7
|
module Sorbet
|
8
|
-
#
|
8
|
+
# Disallows using `T.untyped` anywhere.
|
9
9
|
#
|
10
10
|
# @example
|
11
11
|
#
|
@@ -17,11 +17,15 @@ module RuboCop
|
|
17
17
|
# sig { params(my_argument: String).void }
|
18
18
|
# def foo(my_argument); end
|
19
19
|
#
|
20
|
-
class ForbidTUntyped < RuboCop::Cop::
|
20
|
+
class ForbidTUntyped < RuboCop::Cop::Base
|
21
|
+
MSG = "Do not use `T.untyped`."
|
22
|
+
RESTRICT_ON_SEND = [:untyped].freeze
|
23
|
+
|
24
|
+
# @!method t_untyped?(node)
|
21
25
|
def_node_matcher(:t_untyped?, "(send (const nil? :T) :untyped)")
|
22
26
|
|
23
27
|
def on_send(node)
|
24
|
-
add_offense(node
|
28
|
+
add_offense(node) if t_untyped?(node)
|
25
29
|
end
|
26
30
|
end
|
27
31
|
end
|