sorbet-runtime 0.4.4331 → 0.4.4398
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/lib/types/_types.rb +6 -12
- data/lib/types/configuration.rb +14 -8
- data/lib/types/private/methods/_methods.rb +3 -3
- data/lib/types/private/methods/call_validation.rb +6 -0
- data/lib/types/private/methods/decl_builder.rb +21 -32
- data/lib/types/private/methods/signature.rb +4 -4
- data/lib/types/private/runtime_levels.rb +15 -0
- data/lib/types/props/decorator.rb +13 -9
- data/lib/types/props/pretty_printable.rb +1 -0
- data/lib/types/runtime_profiled.rb +11 -23
- data/lib/types/utils.rb +0 -20
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: af4d1867e5caafedef289561e2ad9413bffa3fad
|
|
4
|
+
data.tar.gz: 5652f7e1c9d2d54b253fcc6d2e5e5330c9c34691
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 430f858624d11168a7a5a7109115fc02d26bb919e4d14aa1bb94018abf88276d143a7550e23f320ce135be24d283dc70198d250a568339da9cb2a02ad94dfbbb
|
|
7
|
+
data.tar.gz: 1f1e4cdaba1209536d9cc5da0ef766f841c80a50963146f11dcda2374beaa62835dd79ce5d8c2d6093f354d176bbac42f34d03067b9adf23d391f50e553e329e
|
data/lib/types/_types.rb
CHANGED
|
@@ -176,21 +176,15 @@ module T
|
|
|
176
176
|
# Intended to be used to promise sorbet that a given nilable value happens
|
|
177
177
|
# to contain a non-nil value at this point.
|
|
178
178
|
#
|
|
179
|
-
# sig {params(arg: T.nilable(A)
|
|
180
|
-
def self.must(arg
|
|
179
|
+
# sig {params(arg: T.nilable(A)).returns(A)}
|
|
180
|
+
def self.must(arg)
|
|
181
|
+
return arg if arg
|
|
182
|
+
return arg if arg == false
|
|
183
|
+
|
|
181
184
|
begin
|
|
182
|
-
|
|
183
|
-
if !T.unsafe(msg).is_a?(String)
|
|
184
|
-
raise TypeError.new("T.must expects a string as second argument")
|
|
185
|
-
end
|
|
186
|
-
else
|
|
187
|
-
msg = "Passed `nil` into T.must"
|
|
188
|
-
end
|
|
189
|
-
raise TypeError.new(msg) if arg.nil?
|
|
190
|
-
arg
|
|
185
|
+
raise TypeError.new("Passed `nil` into T.must")
|
|
191
186
|
rescue TypeError => e # raise into rescue to ensure e.backtrace is populated
|
|
192
187
|
T::Private::ErrorHandler.handle_inline_type_error(e)
|
|
193
|
-
arg
|
|
194
188
|
end
|
|
195
189
|
end
|
|
196
190
|
|
data/lib/types/configuration.rb
CHANGED
|
@@ -17,6 +17,19 @@ module T::Configuration
|
|
|
17
17
|
T::Private::RuntimeLevels.enable_checking_in_tests
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
# Configure the default checked level for a sig with no explicit `.checked`
|
|
21
|
+
# builder. When unset, the default checked level is `:always`.
|
|
22
|
+
#
|
|
23
|
+
# Note: setting this option is potentially dangerous! Sorbet can't check all
|
|
24
|
+
# code statically. The runtime checks complement the checks that Sorbet does
|
|
25
|
+
# statically, so that methods don't have to guard themselves from being
|
|
26
|
+
# called incorrectly by untyped code.
|
|
27
|
+
#
|
|
28
|
+
# @param [:never, :tests, :always] default_checked_level
|
|
29
|
+
def self.default_checked_level=(default_checked_level)
|
|
30
|
+
T::Private::RuntimeLevels.default_checked_level = default_checked_level
|
|
31
|
+
end
|
|
32
|
+
|
|
20
33
|
# Set a handler to handle `TypeError`s raised by any in-line type assertions,
|
|
21
34
|
# including `T.must`, `T.let`, `T.cast`, and `T.assert_type!`.
|
|
22
35
|
#
|
|
@@ -175,14 +188,7 @@ module T::Configuration
|
|
|
175
188
|
end
|
|
176
189
|
|
|
177
190
|
private_class_method def self.call_validation_error_handler_default(signature, opts)
|
|
178
|
-
|
|
179
|
-
location = opts[:location]
|
|
180
|
-
|
|
181
|
-
error_message = "#{opts[:kind]}#{opts[:name] ? " '#{opts[:name]}'" : ''}: #{opts[:message]}\n" \
|
|
182
|
-
"Caller: #{location.path}:#{location.lineno}\n" \
|
|
183
|
-
"Definition: #{method_file}:#{method_line}"
|
|
184
|
-
|
|
185
|
-
raise TypeError.new(error_message)
|
|
191
|
+
raise TypeError.new(opts[:pretty_message])
|
|
186
192
|
end
|
|
187
193
|
|
|
188
194
|
def self.call_validation_error_handler(signature, opts)
|
|
@@ -43,8 +43,8 @@ module T::Private::Methods
|
|
|
43
43
|
if decl.returns == ARG_NOT_PROVIDED
|
|
44
44
|
raise "Procs must specify a return type"
|
|
45
45
|
end
|
|
46
|
-
if decl.
|
|
47
|
-
raise "Procs cannot use .
|
|
46
|
+
if decl.on_failure != ARG_NOT_PROVIDED
|
|
47
|
+
raise "Procs cannot use .on_failure"
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
if decl.params == ARG_NOT_PROVIDED
|
|
@@ -224,7 +224,7 @@ module T::Private::Methods
|
|
|
224
224
|
bind: current_declaration.bind,
|
|
225
225
|
mode: current_declaration.mode,
|
|
226
226
|
check_level: current_declaration.checked,
|
|
227
|
-
|
|
227
|
+
on_failure: current_declaration.on_failure,
|
|
228
228
|
override_allow_incompatible: current_declaration.override_allow_incompatible,
|
|
229
229
|
generated: current_declaration.generated,
|
|
230
230
|
)
|
|
@@ -1150,10 +1150,16 @@ module T::Private::Methods::CallValidation
|
|
|
1150
1150
|
def self.report_error(method_sig, error_message, kind, name, type, value, caller_offset: 0)
|
|
1151
1151
|
method_sig.mark_failed
|
|
1152
1152
|
caller_loc = T.must(caller_locations(3 + caller_offset, 1))[0]
|
|
1153
|
+
definition_file, definition_line = method_sig.method.source_location
|
|
1154
|
+
|
|
1155
|
+
pretty_message = "#{kind}#{name ? " '#{name}'" : ''}: #{error_message}\n" \
|
|
1156
|
+
"Caller: #{caller_loc.path}:#{caller_loc.lineno}\n" \
|
|
1157
|
+
"Definition: #{definition_file}:#{definition_line}"
|
|
1153
1158
|
|
|
1154
1159
|
T::Private::ErrorHandler.handle_call_validation_error(
|
|
1155
1160
|
method_sig,
|
|
1156
1161
|
message: error_message,
|
|
1162
|
+
pretty_message: pretty_message,
|
|
1157
1163
|
kind: kind,
|
|
1158
1164
|
name: name,
|
|
1159
1165
|
type: type,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# typed: true
|
|
3
3
|
|
|
4
4
|
module T::Private::Methods
|
|
5
|
-
Declaration = Struct.new(:mod, :params, :returns, :bind, :mode, :checked, :finalized, :
|
|
5
|
+
Declaration = Struct.new(:mod, :params, :returns, :bind, :mode, :checked, :finalized, :on_failure, :override_allow_incompatible, :type_parameters, :generated)
|
|
6
6
|
|
|
7
7
|
class DeclBuilder
|
|
8
8
|
attr_reader :decl
|
|
@@ -25,7 +25,7 @@ module T::Private::Methods
|
|
|
25
25
|
Modes.standard, # mode
|
|
26
26
|
ARG_NOT_PROVIDED, # checked
|
|
27
27
|
false, # finalized
|
|
28
|
-
ARG_NOT_PROVIDED, #
|
|
28
|
+
ARG_NOT_PROVIDED, # on_failure
|
|
29
29
|
nil, # override_allow_incompatible
|
|
30
30
|
ARG_NOT_PROVIDED, # type_parameters
|
|
31
31
|
ARG_NOT_PROVIDED, # generated
|
|
@@ -80,16 +80,13 @@ module T::Private::Methods
|
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
def checked(level)
|
|
83
|
-
if T.unsafe(true)
|
|
84
|
-
raise "The .checked API is unstable, so we don't want it used until we redesign it. To change Sorbet's runtime behavior, see https://sorbet.org/docs/tconfiguration"
|
|
85
|
-
end
|
|
86
83
|
check_live!
|
|
87
84
|
|
|
88
85
|
if !decl.checked.equal?(ARG_NOT_PROVIDED)
|
|
89
86
|
raise BuilderError.new("You can't call .checked multiple times in a signature.")
|
|
90
87
|
end
|
|
91
|
-
if !decl.
|
|
92
|
-
raise BuilderError.new("You can't use .checked with .
|
|
88
|
+
if level == :never && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
89
|
+
raise BuilderError.new("You can't use .checked(:never) with .on_failure because .on_failure will have no effect.")
|
|
93
90
|
end
|
|
94
91
|
if !decl.generated.equal?(ARG_NOT_PROVIDED)
|
|
95
92
|
raise BuilderError.new("You can't use .checked with .generated.")
|
|
@@ -103,37 +100,25 @@ module T::Private::Methods
|
|
|
103
100
|
self
|
|
104
101
|
end
|
|
105
102
|
|
|
106
|
-
def
|
|
107
|
-
if T.unsafe(true)
|
|
108
|
-
raise "The .soft API is unstable, so we don't want it used until we redesign it. To change Sorbet's runtime behavior, see https://sorbet.org/docs/tconfiguration"
|
|
109
|
-
end
|
|
103
|
+
def on_failure(*args)
|
|
110
104
|
check_live!
|
|
111
105
|
|
|
112
|
-
if !decl.
|
|
113
|
-
raise BuilderError.new("You can't call .
|
|
106
|
+
if !decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
107
|
+
raise BuilderError.new("You can't call .on_failure multiple times in a signature.")
|
|
114
108
|
end
|
|
115
|
-
if
|
|
116
|
-
raise BuilderError.new("You can't use .
|
|
109
|
+
if decl.checked == :never
|
|
110
|
+
raise BuilderError.new("You can't use .on_failure with .checked(:never) because .on_failure will have no effect.")
|
|
117
111
|
end
|
|
118
112
|
if !decl.generated.equal?(ARG_NOT_PROVIDED)
|
|
119
|
-
raise BuilderError.new("You can't use .
|
|
113
|
+
raise BuilderError.new("You can't use .on_failure with .generated.")
|
|
120
114
|
end
|
|
121
115
|
|
|
122
|
-
|
|
123
|
-
# as per https://git.corp.stripe.com/stripe-internal/pay-server/blob/master/lib/event/job/sentry_job.rb#L125
|
|
124
|
-
if !notify || notify == ''
|
|
125
|
-
raise BuilderError.new("You can't provide an empty notify to .soft().")
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
decl.soft_notify = notify
|
|
116
|
+
decl.on_failure = args
|
|
129
117
|
|
|
130
118
|
self
|
|
131
119
|
end
|
|
132
120
|
|
|
133
121
|
def generated
|
|
134
|
-
if T.unsafe(true)
|
|
135
|
-
raise "The .generated API is unstable, so we don't want it used until we redesign it. To change Sorbet's runtime behavior, see https://sorbet.org/docs/tconfiguration"
|
|
136
|
-
end
|
|
137
122
|
check_live!
|
|
138
123
|
|
|
139
124
|
if !decl.generated.equal?(ARG_NOT_PROVIDED)
|
|
@@ -142,8 +127,8 @@ module T::Private::Methods
|
|
|
142
127
|
if !decl.checked.equal?(ARG_NOT_PROVIDED)
|
|
143
128
|
raise BuilderError.new("You can't use .generated with .checked.")
|
|
144
129
|
end
|
|
145
|
-
if !decl.
|
|
146
|
-
raise BuilderError.new("You can't use .generated with .
|
|
130
|
+
if !decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
131
|
+
raise BuilderError.new("You can't use .generated with .on_failure.")
|
|
147
132
|
end
|
|
148
133
|
|
|
149
134
|
decl.generated = true
|
|
@@ -252,10 +237,14 @@ module T::Private::Methods
|
|
|
252
237
|
decl.bind = nil
|
|
253
238
|
end
|
|
254
239
|
if decl.checked.equal?(ARG_NOT_PROVIDED)
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
240
|
+
default_checked_level = T::Private::RuntimeLevels.default_checked_level
|
|
241
|
+
if default_checked_level == :never && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
242
|
+
raise BuilderError.new("To use .on_failure you must additionally call .checked(:tests) or .checked(:always), otherwise, the .on_failure has no effect.")
|
|
243
|
+
end
|
|
244
|
+
decl.checked = default_checked_level
|
|
245
|
+
end
|
|
246
|
+
if decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
247
|
+
decl.on_failure = nil
|
|
259
248
|
end
|
|
260
249
|
if decl.generated.equal?(ARG_NOT_PROVIDED)
|
|
261
250
|
decl.generated = false
|
|
@@ -5,7 +5,7 @@ class T::Private::Methods::Signature
|
|
|
5
5
|
attr_reader :method, :method_name, :arg_types, :kwarg_types, :block_type, :block_name,
|
|
6
6
|
:rest_type, :rest_name, :keyrest_type, :keyrest_name, :bind,
|
|
7
7
|
:return_type, :mode, :req_arg_count, :req_kwarg_names, :has_rest, :has_keyrest,
|
|
8
|
-
:check_level, :generated, :parameters, :
|
|
8
|
+
:check_level, :generated, :parameters, :on_failure, :override_allow_incompatible, :ever_failed
|
|
9
9
|
|
|
10
10
|
def self.new_untyped(method:, mode: T::Private::Methods::Modes.untyped, parameters: method.parameters)
|
|
11
11
|
# Using `Untyped` ensures we'll get an error if we ever try validation on these.
|
|
@@ -24,7 +24,7 @@ class T::Private::Methods::Signature
|
|
|
24
24
|
mode: mode,
|
|
25
25
|
check_level: :never,
|
|
26
26
|
parameters: parameters,
|
|
27
|
-
|
|
27
|
+
on_failure: nil,
|
|
28
28
|
)
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -32,7 +32,7 @@ class T::Private::Methods::Signature
|
|
|
32
32
|
@ever_failed = true
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
def initialize(method:, method_name:, raw_arg_types:, raw_return_type:, bind:, mode:, check_level:, parameters: method.parameters,
|
|
35
|
+
def initialize(method:, method_name:, raw_arg_types:, raw_return_type:, bind:, mode:, check_level:, parameters: method.parameters, on_failure:, generated: false, override_allow_incompatible: false)
|
|
36
36
|
@method = method
|
|
37
37
|
@method_name = method_name
|
|
38
38
|
@arg_types = []
|
|
@@ -52,7 +52,7 @@ class T::Private::Methods::Signature
|
|
|
52
52
|
@has_rest = false
|
|
53
53
|
@has_keyrest = false
|
|
54
54
|
@parameters = parameters
|
|
55
|
-
@
|
|
55
|
+
@on_failure = on_failure
|
|
56
56
|
@override_allow_incompatible = override_allow_incompatible
|
|
57
57
|
@generated = generated
|
|
58
58
|
@ever_failed = false
|
|
@@ -17,6 +17,9 @@ module T::Private::RuntimeLevels
|
|
|
17
17
|
@check_tests = false
|
|
18
18
|
@wrapped_tests_with_validation = false
|
|
19
19
|
|
|
20
|
+
@has_read_default_checked_level = false
|
|
21
|
+
@default_checked_level = :always
|
|
22
|
+
|
|
20
23
|
def self.check_tests?
|
|
21
24
|
# Assume that this code path means that some `sig.checked(:tests)`
|
|
22
25
|
# has been wrapped (or not wrapped) already, which is a trapdoor
|
|
@@ -35,6 +38,18 @@ module T::Private::RuntimeLevels
|
|
|
35
38
|
_toggle_checking_tests(true)
|
|
36
39
|
end
|
|
37
40
|
|
|
41
|
+
def self.default_checked_level
|
|
42
|
+
@has_read_default_checked_level = true
|
|
43
|
+
@default_checked_level
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.default_checked_level=(default_checked_level)
|
|
47
|
+
if @has_read_default_checked_level
|
|
48
|
+
raise "Set the default checked level earlier. There are already some methods whose sig blocks have evaluated which would not be affected by the new default."
|
|
49
|
+
end
|
|
50
|
+
@default_checked_level = default_checked_level
|
|
51
|
+
end
|
|
52
|
+
|
|
38
53
|
def self._toggle_checking_tests(checked)
|
|
39
54
|
@check_tests = checked
|
|
40
55
|
end
|
|
@@ -18,7 +18,7 @@ class T::Props::Decorator
|
|
|
18
18
|
|
|
19
19
|
class NoRulesError < StandardError; end
|
|
20
20
|
|
|
21
|
-
sig {params(klass: DecoratedClass).void}
|
|
21
|
+
T::Sig::WithoutRuntime.sig {params(klass: DecoratedClass).void}
|
|
22
22
|
def initialize(klass)
|
|
23
23
|
@class = klass
|
|
24
24
|
klass.plugins.each do |mod|
|
|
@@ -27,7 +27,7 @@ class T::Props::Decorator
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
# prop stuff
|
|
30
|
-
sig {returns(T::Hash[Symbol, Rules])}
|
|
30
|
+
sig {returns(T::Hash[Symbol, Rules]).checked(:never)}
|
|
31
31
|
def props
|
|
32
32
|
@props ||= {}.freeze
|
|
33
33
|
end
|
|
@@ -44,7 +44,7 @@ class T::Props::Decorator
|
|
|
44
44
|
sig {returns(T::Array[Symbol])}
|
|
45
45
|
def all_props; props.keys; end
|
|
46
46
|
|
|
47
|
-
sig {params(prop: T.any(Symbol, String)).returns(Rules)}
|
|
47
|
+
sig {params(prop: T.any(Symbol, String)).returns(Rules).checked(:never)}
|
|
48
48
|
def prop_rules(prop); props[prop.to_sym] || raise("No such prop: #{prop.inspect}"); end
|
|
49
49
|
|
|
50
50
|
sig {params(prop: Symbol, rules: Rules).void}
|
|
@@ -80,7 +80,7 @@ class T::Props::Decorator
|
|
|
80
80
|
}
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
sig {returns(DecoratedClass)}
|
|
83
|
+
sig {returns(DecoratedClass).checked(:never)}
|
|
84
84
|
def decorated_class; @class; end
|
|
85
85
|
|
|
86
86
|
# Accessors
|
|
@@ -94,6 +94,7 @@ class T::Props::Decorator
|
|
|
94
94
|
rules: T.nilable(Rules)
|
|
95
95
|
)
|
|
96
96
|
.returns(T.untyped)
|
|
97
|
+
.checked(:never)
|
|
97
98
|
end
|
|
98
99
|
def get(instance, prop, rules=props[prop.to_sym])
|
|
99
100
|
# For backwards compatibility, fall back to reconstructing the accessor key
|
|
@@ -111,6 +112,7 @@ class T::Props::Decorator
|
|
|
111
112
|
rules: T.nilable(Rules)
|
|
112
113
|
)
|
|
113
114
|
.void
|
|
115
|
+
.checked(:never)
|
|
114
116
|
end
|
|
115
117
|
def set(instance, prop, value, rules=props[prop.to_sym])
|
|
116
118
|
# For backwards compatibility, fall back to reconstructing the accessor key
|
|
@@ -119,7 +121,7 @@ class T::Props::Decorator
|
|
|
119
121
|
end
|
|
120
122
|
|
|
121
123
|
# Use this to validate that a value will validate for a given prop. Useful for knowing whether a value can be set on a model without setting it.
|
|
122
|
-
sig {params(prop: Symbol, val: T.untyped).void}
|
|
124
|
+
sig {params(prop: Symbol, val: T.untyped).void.checked(:never)}
|
|
123
125
|
def validate_prop_value(prop, val)
|
|
124
126
|
# This implements a 'public api' on document so that we don't allow callers to pass in rules
|
|
125
127
|
# Rules seem like an implementation detail so it seems good to now allow people to specify them manually.
|
|
@@ -127,7 +129,7 @@ class T::Props::Decorator
|
|
|
127
129
|
end
|
|
128
130
|
|
|
129
131
|
# Passing in rules here is purely a performance optimization.
|
|
130
|
-
sig {params(prop: Symbol, val: T.untyped, rules: Rules).void}
|
|
132
|
+
sig {params(prop: Symbol, val: T.untyped, rules: Rules).void.checked(:never)}
|
|
131
133
|
private def check_prop_type(prop, val, rules=prop_rules(prop))
|
|
132
134
|
type_object = rules.fetch(:type_object)
|
|
133
135
|
type = rules.fetch(:type)
|
|
@@ -173,6 +175,7 @@ class T::Props::Decorator
|
|
|
173
175
|
rules: T.nilable(Rules)
|
|
174
176
|
)
|
|
175
177
|
.void
|
|
178
|
+
.checked(:never)
|
|
176
179
|
end
|
|
177
180
|
def prop_set(instance, prop, val, rules=prop_rules(prop))
|
|
178
181
|
check_prop_type(prop, val, T.must(rules))
|
|
@@ -188,6 +191,7 @@ class T::Props::Decorator
|
|
|
188
191
|
rules: T.nilable(Rules)
|
|
189
192
|
)
|
|
190
193
|
.returns(T.untyped)
|
|
194
|
+
.checked(:never)
|
|
191
195
|
end
|
|
192
196
|
def prop_get(instance, prop, rules=props[prop.to_sym])
|
|
193
197
|
val = get(instance, prop, rules)
|
|
@@ -222,6 +226,7 @@ class T::Props::Decorator
|
|
|
222
226
|
opts: Hash
|
|
223
227
|
)
|
|
224
228
|
.returns(T.untyped)
|
|
229
|
+
.checked(:never)
|
|
225
230
|
end
|
|
226
231
|
def foreign_prop_get(instance, prop, foreign_class, rules=props[prop.to_sym], opts={})
|
|
227
232
|
return if !(value = prop_get(instance, prop, rules))
|
|
@@ -325,7 +330,6 @@ class T::Props::Decorator
|
|
|
325
330
|
.void
|
|
326
331
|
end
|
|
327
332
|
def prop_defined(name, cls, rules={})
|
|
328
|
-
# TODO(jerry): Create similar soft assertions against false
|
|
329
333
|
if rules[:optional] == true
|
|
330
334
|
T::Configuration.hard_assert_handler(
|
|
331
335
|
'Use of `optional: true` is deprecated, please use `T.nilable(...)` instead.',
|
|
@@ -776,7 +780,7 @@ class T::Props::Decorator
|
|
|
776
780
|
#
|
|
777
781
|
# This gets called when a module or class that extends T::Props gets included, extended,
|
|
778
782
|
# prepended, or inherited.
|
|
779
|
-
sig {params(child: DecoratedClass).void}
|
|
783
|
+
T::Sig::WithoutRuntime.sig {params(child: DecoratedClass).void}
|
|
780
784
|
def model_inherited(child)
|
|
781
785
|
child.extend(T::Props::ClassMethods)
|
|
782
786
|
child.plugins.concat(decorated_class.plugins)
|
|
@@ -797,7 +801,7 @@ class T::Props::Decorator
|
|
|
797
801
|
end
|
|
798
802
|
end
|
|
799
803
|
|
|
800
|
-
sig {params(mod: Module).void}
|
|
804
|
+
T::Sig::WithoutRuntime.sig {params(mod: Module).void}
|
|
801
805
|
def plugin(mod)
|
|
802
806
|
decorated_class.plugins << mod
|
|
803
807
|
Private.apply_class_methods(mod, decorated_class)
|
|
@@ -70,6 +70,7 @@ module T::Props::PrettyPrintable
|
|
|
70
70
|
sig do
|
|
71
71
|
params(instance: T::Props::PrettyPrintable, prop: Symbol, multiline: T::Boolean, indent: String)
|
|
72
72
|
.returns(String)
|
|
73
|
+
.checked(:never)
|
|
73
74
|
end
|
|
74
75
|
private def inspect_prop_value(instance, prop, multiline:, indent:)
|
|
75
76
|
val = T.unsafe(self).get(instance, prop)
|
|
@@ -2,35 +2,23 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
#
|
|
5
|
-
#
|
|
5
|
+
# From the static system, T::Utils::RuntimeProfiled is T.untyped.
|
|
6
6
|
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# signature will always create a type error.
|
|
7
|
+
# But from the runtime system, it's a random class (specifically, a class that
|
|
8
|
+
# normal programs currently don't have any instances of).
|
|
10
9
|
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
10
|
+
# Thus, T::Utils::RuntimeProfiled can be used to introduce runtime-only type
|
|
11
|
+
# errors. This seems like a bad idea, but it's not. It can be used to gather
|
|
12
|
+
# runtime type information from running code via a custom T::Configuration
|
|
13
|
+
# handler.
|
|
14
14
|
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
15
|
+
# This process has only ever been used at Stripe, and is likely to have rough
|
|
16
|
+
# edges. If you've managed to find your way here and you're curious to try it,
|
|
17
|
+
# please chat with us on Slack. There are no docs.
|
|
18
18
|
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
# - If you were just curious, that's it! Leave the sig as is, and carry on.
|
|
22
|
-
# - If you wanted to replace this sig with a better, hand-authored one:
|
|
23
|
-
#
|
|
24
|
-
# 1. Remove 'generated' from the sig.
|
|
25
|
-
# 2. Update the sig to your liking
|
|
26
|
-
#
|
|
27
|
-
# Questions? :portal-to: => #ruby-types
|
|
28
|
-
#
|
|
29
|
-
# [^1]: Unless you happen to be calling T::Utils::RuntimeProfiled.new directly...
|
|
19
|
+
# See also: the --suggest-runtime-profiled flag to sorbet.
|
|
30
20
|
#
|
|
31
21
|
|
|
32
22
|
module T; end
|
|
33
23
|
module T::Utils; end
|
|
34
|
-
# Sorbet guesses this type instead of T.untyped when passed --suggest-runtime-profiled
|
|
35
|
-
|
|
36
24
|
class T::Utils::RuntimeProfiled; end
|
data/lib/types/utils.rb
CHANGED
|
@@ -74,26 +74,6 @@ module T::Utils
|
|
|
74
74
|
T::Private::Methods.run_all_sig_blocks
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
# This can be called in a wholesome test to make sure all the `sig`s are well
|
|
78
|
-
# formed.
|
|
79
|
-
def self.validate_sigs
|
|
80
|
-
exceptions = []
|
|
81
|
-
run_all_sig_blocks
|
|
82
|
-
ObjectSpace.each_object(Module) do |mod| # rubocop:disable PrisonGuard/NoDynamicConstAccess
|
|
83
|
-
begin
|
|
84
|
-
T::Private::Abstract::Validate.validate_subclass(mod)
|
|
85
|
-
if T::AbstractUtils.abstract_module?(mod)
|
|
86
|
-
T::Private::Abstract::Validate.validate_abstract_module(mod)
|
|
87
|
-
end
|
|
88
|
-
rescue => e
|
|
89
|
-
exceptions << e
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
if !exceptions.empty?
|
|
93
|
-
raise "#{exceptions.count} exception thrown during validation:\n\n#{exceptions.map(&:message).sort.join("\n\n")}"
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
77
|
# Give a type which is a subclass of T::Types::Base, determines if the type is a simple nilable type (union of NilClass and something else).
|
|
98
78
|
# If so, returns the T::Types::Base of the something else. Otherwise, returns nil.
|
|
99
79
|
def self.unwrap_nilable(type)
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sorbet-runtime
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.4398
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stripe
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2019-
|
|
11
|
+
date: 2019-07-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: minitest
|