sorbet-runtime 0.5.5841
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 +7 -0
- data/lib/sorbet-runtime.rb +116 -0
- data/lib/types/_types.rb +285 -0
- data/lib/types/abstract_utils.rb +50 -0
- data/lib/types/boolean.rb +8 -0
- data/lib/types/compatibility_patches.rb +95 -0
- data/lib/types/configuration.rb +428 -0
- data/lib/types/enum.rb +349 -0
- data/lib/types/generic.rb +23 -0
- data/lib/types/helpers.rb +39 -0
- data/lib/types/interface_wrapper.rb +158 -0
- data/lib/types/non_forcing_constants.rb +51 -0
- data/lib/types/private/abstract/data.rb +36 -0
- data/lib/types/private/abstract/declare.rb +48 -0
- data/lib/types/private/abstract/hooks.rb +43 -0
- data/lib/types/private/abstract/validate.rb +128 -0
- data/lib/types/private/casts.rb +22 -0
- data/lib/types/private/class_utils.rb +111 -0
- data/lib/types/private/decl_state.rb +30 -0
- data/lib/types/private/final.rb +51 -0
- data/lib/types/private/methods/_methods.rb +460 -0
- data/lib/types/private/methods/call_validation.rb +1149 -0
- data/lib/types/private/methods/decl_builder.rb +228 -0
- data/lib/types/private/methods/modes.rb +16 -0
- data/lib/types/private/methods/signature.rb +196 -0
- data/lib/types/private/methods/signature_validation.rb +229 -0
- data/lib/types/private/mixins/mixins.rb +27 -0
- data/lib/types/private/retry.rb +10 -0
- data/lib/types/private/runtime_levels.rb +56 -0
- data/lib/types/private/sealed.rb +65 -0
- data/lib/types/private/types/not_typed.rb +23 -0
- data/lib/types/private/types/string_holder.rb +26 -0
- data/lib/types/private/types/type_alias.rb +26 -0
- data/lib/types/private/types/void.rb +34 -0
- data/lib/types/profile.rb +31 -0
- data/lib/types/props/_props.rb +161 -0
- data/lib/types/props/constructor.rb +40 -0
- data/lib/types/props/custom_type.rb +108 -0
- data/lib/types/props/decorator.rb +672 -0
- data/lib/types/props/errors.rb +8 -0
- data/lib/types/props/generated_code_validation.rb +268 -0
- data/lib/types/props/has_lazily_specialized_methods.rb +92 -0
- data/lib/types/props/optional.rb +81 -0
- data/lib/types/props/plugin.rb +37 -0
- data/lib/types/props/pretty_printable.rb +107 -0
- data/lib/types/props/private/apply_default.rb +170 -0
- data/lib/types/props/private/deserializer_generator.rb +165 -0
- data/lib/types/props/private/parser.rb +32 -0
- data/lib/types/props/private/serde_transform.rb +192 -0
- data/lib/types/props/private/serializer_generator.rb +77 -0
- data/lib/types/props/private/setter_factory.rb +134 -0
- data/lib/types/props/serializable.rb +330 -0
- data/lib/types/props/type_validation.rb +111 -0
- data/lib/types/props/utils.rb +59 -0
- data/lib/types/props/weak_constructor.rb +67 -0
- data/lib/types/runtime_profiled.rb +24 -0
- data/lib/types/sig.rb +30 -0
- data/lib/types/struct.rb +18 -0
- data/lib/types/types/attached_class.rb +37 -0
- data/lib/types/types/base.rb +151 -0
- data/lib/types/types/class_of.rb +38 -0
- data/lib/types/types/enum.rb +42 -0
- data/lib/types/types/fixed_array.rb +60 -0
- data/lib/types/types/fixed_hash.rb +59 -0
- data/lib/types/types/intersection.rb +37 -0
- data/lib/types/types/noreturn.rb +29 -0
- data/lib/types/types/proc.rb +51 -0
- data/lib/types/types/self_type.rb +35 -0
- data/lib/types/types/simple.rb +33 -0
- data/lib/types/types/t_enum.rb +38 -0
- data/lib/types/types/type_member.rb +7 -0
- data/lib/types/types/type_parameter.rb +23 -0
- data/lib/types/types/type_template.rb +7 -0
- data/lib/types/types/type_variable.rb +31 -0
- data/lib/types/types/typed_array.rb +34 -0
- data/lib/types/types/typed_enumerable.rb +161 -0
- data/lib/types/types/typed_enumerator.rb +36 -0
- data/lib/types/types/typed_hash.rb +43 -0
- data/lib/types/types/typed_range.rb +26 -0
- data/lib/types/types/typed_set.rb +36 -0
- data/lib/types/types/union.rb +56 -0
- data/lib/types/types/untyped.rb +29 -0
- data/lib/types/utils.rb +217 -0
- metadata +223 -0
@@ -0,0 +1,8 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module T
|
5
|
+
# T::Boolean is a type alias helper for the common `T.any(TrueClass, FalseClass)`.
|
6
|
+
# Defined separately from _types.rb because it has a dependency on T::Types::Union.
|
7
|
+
Boolean = T.type_alias {T.any(TrueClass, FalseClass)}
|
8
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: ignore
|
3
|
+
|
4
|
+
require_relative 'private/methods/_methods'
|
5
|
+
|
6
|
+
# Work around an interaction bug with sorbet-runtime and rspec-mocks,
|
7
|
+
# which occurs when using message expectations (*_any_instance_of,
|
8
|
+
# expect, allow) and and_call_original.
|
9
|
+
#
|
10
|
+
# When a sig is defined, sorbet-runtime will replace the sigged method
|
11
|
+
# with a wrapper that, upon first invocation, re-wraps the method with a faster
|
12
|
+
# implementation.
|
13
|
+
#
|
14
|
+
# When expect_any_instance_of is used, rspec stores a reference to the first wrapper,
|
15
|
+
# to be restored later.
|
16
|
+
#
|
17
|
+
# The first wrapper is invoked as part of the test and sorbet-runtime replaces
|
18
|
+
# the method definition with the second wrapper.
|
19
|
+
#
|
20
|
+
# But when mocks are cleaned up, rspec restores back to the first wrapper.
|
21
|
+
# Upon subsequent invocations, the first wrapper is called, and sorbet-runtime
|
22
|
+
# throws a runtime error, since this is an unexpected state.
|
23
|
+
#
|
24
|
+
# We work around this by forcing re-wrapping before rspec stores a reference
|
25
|
+
# to the method.
|
26
|
+
if defined? ::RSpec::Mocks
|
27
|
+
module T
|
28
|
+
module CompatibilityPatches
|
29
|
+
module RSpecCompatibility
|
30
|
+
module RecorderExtensions
|
31
|
+
def observe!(method_name)
|
32
|
+
method = @klass.instance_method(method_name.to_sym)
|
33
|
+
T::Private::Methods.maybe_run_sig_block_for_method(method)
|
34
|
+
super(method_name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
::RSpec::Mocks::AnyInstance::Recorder.prepend(RecorderExtensions) if defined?(::RSpec::Mocks::AnyInstance::Recorder)
|
38
|
+
|
39
|
+
module MethodDoubleExtensions
|
40
|
+
def initialize(object, method_name, proxy)
|
41
|
+
if ::Kernel.instance_method(:respond_to?).bind(object).call(method_name, true)
|
42
|
+
method = ::RSpec::Support.method_handle_for(object, method_name)
|
43
|
+
T::Private::Methods.maybe_run_sig_block_for_method(method)
|
44
|
+
end
|
45
|
+
super(object, method_name, proxy)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
::RSpec::Mocks::MethodDouble.prepend(MethodDoubleExtensions) if defined?(::RSpec::Mocks::MethodDouble)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Work around for sorbet-runtime wrapped methods.
|
55
|
+
#
|
56
|
+
# When a sig is defined, sorbet-runtime will replace the sigged method
|
57
|
+
# with a wrapper. Those wrapper methods look like `foo(*args, &blk)`
|
58
|
+
# so that wrappers can handle and pass on all the arguments supplied.
|
59
|
+
#
|
60
|
+
# However, that creates a problem with runtime reflection on the methods,
|
61
|
+
# since when a sigged method is introspected, it will always return its
|
62
|
+
# `arity` as `-1`, its `parameters` as `[[:rest, :args], [:block, :blk]]`,
|
63
|
+
# and its `source_location` as `[<some_file_in_sorbet>, <some_line_number>]`.
|
64
|
+
#
|
65
|
+
# This might be a problem for some applications that rely on getting the
|
66
|
+
# correct information from these methods.
|
67
|
+
#
|
68
|
+
# This compatibility module, when prepended to the `Method` class, would fix
|
69
|
+
# the return values of `arity`, `parameters` and `source_location`.
|
70
|
+
#
|
71
|
+
# @example
|
72
|
+
# require 'sorbet-runtime'
|
73
|
+
# ::Method.prepend(T::CompatibilityPatches::MethodExtensions)
|
74
|
+
module T
|
75
|
+
module CompatibilityPatches
|
76
|
+
module MethodExtensions
|
77
|
+
def arity
|
78
|
+
arity = super
|
79
|
+
return arity if arity != -1 || self.is_a?(Proc)
|
80
|
+
sig = T::Private::Methods.signature_for_method(self)
|
81
|
+
sig ? sig.method.arity : arity
|
82
|
+
end
|
83
|
+
|
84
|
+
def source_location
|
85
|
+
sig = T::Private::Methods.signature_for_method(self)
|
86
|
+
sig ? sig.method.source_location : super
|
87
|
+
end
|
88
|
+
|
89
|
+
def parameters
|
90
|
+
sig = T::Private::Methods.signature_for_method(self)
|
91
|
+
sig ? sig.method.parameters : super
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,428 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module T::Configuration
|
5
|
+
# Announces to Sorbet that we are currently in a test environment, so it
|
6
|
+
# should treat any sigs which are marked `.checked(:tests)` as if they were
|
7
|
+
# just a normal sig.
|
8
|
+
#
|
9
|
+
# If this method is not called, sigs marked `.checked(:tests)` will not be
|
10
|
+
# checked. In fact, such methods won't even be wrapped--the runtime will put
|
11
|
+
# back the original method.
|
12
|
+
#
|
13
|
+
# Note: Due to the way sigs are evaluated and methods are wrapped, this
|
14
|
+
# method MUST be called before any code calls `sig`. This method raises if
|
15
|
+
# it has been called too late.
|
16
|
+
def self.enable_checking_for_sigs_marked_checked_tests
|
17
|
+
T::Private::RuntimeLevels.enable_checking_in_tests
|
18
|
+
end
|
19
|
+
|
20
|
+
# Announce to Sorbet that we would like the final checks to be enabled when
|
21
|
+
# including and extending modules. Iff this is not called, then the following
|
22
|
+
# example will not raise an error.
|
23
|
+
#
|
24
|
+
# ```ruby
|
25
|
+
# module M
|
26
|
+
# extend T::Sig
|
27
|
+
# sig(:final) {void}
|
28
|
+
# def foo; end
|
29
|
+
# end
|
30
|
+
# class C
|
31
|
+
# include M
|
32
|
+
# def foo; end
|
33
|
+
# end
|
34
|
+
# ```
|
35
|
+
def self.enable_final_checks_on_hooks
|
36
|
+
T::Private::Methods.set_final_checks_on_hooks(true)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Undo the effects of a previous call to
|
40
|
+
# `enable_final_checks_on_hooks`.
|
41
|
+
def self.reset_final_checks_on_hooks
|
42
|
+
T::Private::Methods.set_final_checks_on_hooks(false)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Configure the default checked level for a sig with no explicit `.checked`
|
46
|
+
# builder. When unset, the default checked level is `:always`.
|
47
|
+
#
|
48
|
+
# Note: setting this option is potentially dangerous! Sorbet can't check all
|
49
|
+
# code statically. The runtime checks complement the checks that Sorbet does
|
50
|
+
# statically, so that methods don't have to guard themselves from being
|
51
|
+
# called incorrectly by untyped code.
|
52
|
+
#
|
53
|
+
# @param [:never, :tests, :always] default_checked_level
|
54
|
+
def self.default_checked_level=(default_checked_level)
|
55
|
+
T::Private::RuntimeLevels.default_checked_level = default_checked_level
|
56
|
+
end
|
57
|
+
|
58
|
+
# Set a handler to handle `TypeError`s raised by any in-line type assertions,
|
59
|
+
# including `T.must`, `T.let`, `T.cast`, and `T.assert_type!`.
|
60
|
+
#
|
61
|
+
# By default, any `TypeError`s detected by this gem will be raised. Setting
|
62
|
+
# inline_type_error_handler to an object that implements :call (e.g. proc or
|
63
|
+
# lambda) allows users to customize the behavior when a `TypeError` is
|
64
|
+
# raised on any inline type assertion.
|
65
|
+
#
|
66
|
+
# @param [Lambda, Proc, Object, nil] value Proc that handles the error (pass
|
67
|
+
# nil to reset to default behavior)
|
68
|
+
#
|
69
|
+
# Parameters passed to value.call:
|
70
|
+
#
|
71
|
+
# @param [TypeError] error TypeError that was raised
|
72
|
+
#
|
73
|
+
# @example
|
74
|
+
# T::Configuration.inline_type_error_handler = lambda do |error|
|
75
|
+
# puts error.message
|
76
|
+
# end
|
77
|
+
def self.inline_type_error_handler=(value)
|
78
|
+
validate_lambda_given!(value)
|
79
|
+
@inline_type_error_handler = value
|
80
|
+
end
|
81
|
+
|
82
|
+
private_class_method def self.inline_type_error_handler_default(error)
|
83
|
+
raise error
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.inline_type_error_handler(error)
|
87
|
+
if @inline_type_error_handler
|
88
|
+
@inline_type_error_handler.call(error)
|
89
|
+
else
|
90
|
+
inline_type_error_handler_default(error)
|
91
|
+
end
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
95
|
+
# Set a handler to handle errors that occur when the builder methods in the
|
96
|
+
# body of a sig are executed. The sig builder methods are inside a proc so
|
97
|
+
# that they can be lazily evaluated the first time the method being sig'd is
|
98
|
+
# called.
|
99
|
+
#
|
100
|
+
# By default, improper use of the builder methods within the body of a sig
|
101
|
+
# cause an ArgumentError to be raised. Setting sig_builder_error_handler to an
|
102
|
+
# object that implements :call (e.g. proc or lambda) allows users to
|
103
|
+
# customize the behavior when a sig can't be built for some reason.
|
104
|
+
#
|
105
|
+
# @param [Lambda, Proc, Object, nil] value Proc that handles the error (pass
|
106
|
+
# nil to reset to default behavior)
|
107
|
+
#
|
108
|
+
# Parameters passed to value.call:
|
109
|
+
#
|
110
|
+
# @param [StandardError] error The error that was raised
|
111
|
+
# @param [Thread::Backtrace::Location] location Location of the error
|
112
|
+
#
|
113
|
+
# @example
|
114
|
+
# T::Configuration.sig_builder_error_handler = lambda do |error, location|
|
115
|
+
# puts error.message
|
116
|
+
# end
|
117
|
+
def self.sig_builder_error_handler=(value)
|
118
|
+
validate_lambda_given!(value)
|
119
|
+
@sig_builder_error_handler = value
|
120
|
+
end
|
121
|
+
|
122
|
+
private_class_method def self.sig_builder_error_handler_default(error, location)
|
123
|
+
raise ArgumentError.new("#{location.path}:#{location.lineno}: Error interpreting `sig`:\n #{error.message}\n\n")
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.sig_builder_error_handler(error, location)
|
127
|
+
if @sig_builder_error_handler
|
128
|
+
@sig_builder_error_handler.call(error, location)
|
129
|
+
else
|
130
|
+
sig_builder_error_handler_default(error, location)
|
131
|
+
end
|
132
|
+
nil
|
133
|
+
end
|
134
|
+
|
135
|
+
# Set a handler to handle sig validation errors.
|
136
|
+
#
|
137
|
+
# Sig validation errors include things like abstract checks, override checks,
|
138
|
+
# and type compatibility of arguments. They happen after a sig has been
|
139
|
+
# successfully built, but the built sig is incompatible with other sigs in
|
140
|
+
# some way.
|
141
|
+
#
|
142
|
+
# By default, sig validation errors cause an exception to be raised.
|
143
|
+
# Setting sig_validation_error_handler to an object that implements :call
|
144
|
+
# (e.g. proc or lambda) allows users to customize the behavior when a method
|
145
|
+
# signature's build fails.
|
146
|
+
#
|
147
|
+
# @param [Lambda, Proc, Object, nil] value Proc that handles the error (pass
|
148
|
+
# nil to reset to default behavior)
|
149
|
+
#
|
150
|
+
# Parameters passed to value.call:
|
151
|
+
#
|
152
|
+
# @param [StandardError] error The error that was raised
|
153
|
+
# @param [Hash] opts A hash containing contextual information on the error:
|
154
|
+
# @option opts [Method, UnboundMethod] :method Method on which the signature build failed
|
155
|
+
# @option opts [T::Private::Methods::Declaration] :declaration Method
|
156
|
+
# signature declaration struct
|
157
|
+
# @option opts [T::Private::Methods::Signature, nil] :signature Signature
|
158
|
+
# that failed (nil if sig build failed before Signature initialization)
|
159
|
+
# @option opts [T::Private::Methods::Signature, nil] :super_signature Super
|
160
|
+
# method's signature (nil if method is not an override or super method
|
161
|
+
# does not have a method signature)
|
162
|
+
#
|
163
|
+
# @example
|
164
|
+
# T::Configuration.sig_validation_error_handler = lambda do |error, opts|
|
165
|
+
# puts error.message
|
166
|
+
# end
|
167
|
+
def self.sig_validation_error_handler=(value)
|
168
|
+
validate_lambda_given!(value)
|
169
|
+
@sig_validation_error_handler = value
|
170
|
+
end
|
171
|
+
|
172
|
+
private_class_method def self.sig_validation_error_handler_default(error, opts)
|
173
|
+
raise error
|
174
|
+
end
|
175
|
+
|
176
|
+
def self.sig_validation_error_handler(error, opts={})
|
177
|
+
if @sig_validation_error_handler
|
178
|
+
@sig_validation_error_handler.call(error, opts)
|
179
|
+
else
|
180
|
+
sig_validation_error_handler_default(error, opts)
|
181
|
+
end
|
182
|
+
nil
|
183
|
+
end
|
184
|
+
|
185
|
+
# Set a handler for type errors that result from calling a method.
|
186
|
+
#
|
187
|
+
# By default, errors from calling a method cause an exception to be raised.
|
188
|
+
# Setting call_validation_error_handler to an object that implements :call
|
189
|
+
# (e.g. proc or lambda) allows users to customize the behavior when a method
|
190
|
+
# is called with invalid parameters, or returns an invalid value.
|
191
|
+
#
|
192
|
+
# @param [Lambda, Proc, Object, nil] value Proc that handles the error
|
193
|
+
# report (pass nil to reset to default behavior)
|
194
|
+
#
|
195
|
+
# Parameters passed to value.call:
|
196
|
+
#
|
197
|
+
# @param [T::Private::Methods::Signature] signature Signature that failed
|
198
|
+
# @param [Hash] opts A hash containing contextual information on the error:
|
199
|
+
# @option opts [String] :message Error message
|
200
|
+
# @option opts [String] :kind One of:
|
201
|
+
# ['Parameter', 'Block parameter', 'Return value']
|
202
|
+
# @option opts [Symbol] :name Param or block param name (nil for return
|
203
|
+
# value)
|
204
|
+
# @option opts [Object] :type Expected param/return value type
|
205
|
+
# @option opts [Object] :value Actual param/return value
|
206
|
+
# @option opts [Thread::Backtrace::Location] :location Location of the
|
207
|
+
# caller
|
208
|
+
#
|
209
|
+
# @example
|
210
|
+
# T::Configuration.call_validation_error_handler = lambda do |signature, opts|
|
211
|
+
# puts opts[:message]
|
212
|
+
# end
|
213
|
+
def self.call_validation_error_handler=(value)
|
214
|
+
validate_lambda_given!(value)
|
215
|
+
@call_validation_error_handler = value
|
216
|
+
end
|
217
|
+
|
218
|
+
private_class_method def self.call_validation_error_handler_default(signature, opts)
|
219
|
+
raise TypeError.new(opts[:pretty_message])
|
220
|
+
end
|
221
|
+
|
222
|
+
def self.call_validation_error_handler(signature, opts={})
|
223
|
+
if @call_validation_error_handler
|
224
|
+
@call_validation_error_handler.call(signature, opts)
|
225
|
+
else
|
226
|
+
call_validation_error_handler_default(signature, opts)
|
227
|
+
end
|
228
|
+
nil
|
229
|
+
end
|
230
|
+
|
231
|
+
# Set a handler for logging
|
232
|
+
#
|
233
|
+
# @param [Lambda, Proc, Object, nil] value Proc that handles the error
|
234
|
+
# report (pass nil to reset to default behavior)
|
235
|
+
#
|
236
|
+
# Parameters passed to value.call:
|
237
|
+
#
|
238
|
+
# @param [String] str Message to be logged
|
239
|
+
# @param [Hash] extra A hash containing additional parameters to be passed along to the logger.
|
240
|
+
#
|
241
|
+
# @example
|
242
|
+
# T::Configuration.log_info_handler = lambda do |str, extra|
|
243
|
+
# puts "#{str}, context: #{extra}"
|
244
|
+
# end
|
245
|
+
def self.log_info_handler=(value)
|
246
|
+
validate_lambda_given!(value)
|
247
|
+
@log_info_handler = value
|
248
|
+
end
|
249
|
+
|
250
|
+
private_class_method def self.log_info_handler_default(str, extra)
|
251
|
+
puts "#{str}, extra: #{extra}" # rubocop:disable PrisonGuard/NoBarePuts
|
252
|
+
end
|
253
|
+
|
254
|
+
def self.log_info_handler(str, extra)
|
255
|
+
if @log_info_handler
|
256
|
+
@log_info_handler.call(str, extra)
|
257
|
+
else
|
258
|
+
log_info_handler_default(str, extra)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# Set a handler for soft assertions
|
263
|
+
#
|
264
|
+
# These generally shouldn't stop execution of the program, but rather inform
|
265
|
+
# some party of the assertion to action on later.
|
266
|
+
#
|
267
|
+
# @param [Lambda, Proc, Object, nil] value Proc that handles the error
|
268
|
+
# report (pass nil to reset to default behavior)
|
269
|
+
#
|
270
|
+
# Parameters passed to value.call:
|
271
|
+
#
|
272
|
+
# @param [String] str Assertion message
|
273
|
+
# @param [Hash] extra A hash containing additional parameters to be passed along to the handler.
|
274
|
+
#
|
275
|
+
# @example
|
276
|
+
# T::Configuration.soft_assert_handler = lambda do |str, extra|
|
277
|
+
# puts "#{str}, context: #{extra}"
|
278
|
+
# end
|
279
|
+
def self.soft_assert_handler=(value)
|
280
|
+
validate_lambda_given!(value)
|
281
|
+
@soft_assert_handler = value
|
282
|
+
end
|
283
|
+
|
284
|
+
private_class_method def self.soft_assert_handler_default(str, extra)
|
285
|
+
puts "#{str}, extra: #{extra}" # rubocop:disable PrisonGuard/NoBarePuts
|
286
|
+
end
|
287
|
+
|
288
|
+
def self.soft_assert_handler(str, extra)
|
289
|
+
if @soft_assert_handler
|
290
|
+
@soft_assert_handler.call(str, extra)
|
291
|
+
else
|
292
|
+
soft_assert_handler_default(str, extra)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
# Set a handler for hard assertions
|
297
|
+
#
|
298
|
+
# These generally should stop execution of the program, and optionally inform
|
299
|
+
# some party of the assertion.
|
300
|
+
#
|
301
|
+
# @param [Lambda, Proc, Object, nil] value Proc that handles the error
|
302
|
+
# report (pass nil to reset to default behavior)
|
303
|
+
#
|
304
|
+
# Parameters passed to value.call:
|
305
|
+
#
|
306
|
+
# @param [String] str Assertion message
|
307
|
+
# @param [Hash] extra A hash containing additional parameters to be passed along to the handler.
|
308
|
+
#
|
309
|
+
# @example
|
310
|
+
# T::Configuration.hard_assert_handler = lambda do |str, extra|
|
311
|
+
# raise "#{str}, context: #{extra}"
|
312
|
+
# end
|
313
|
+
def self.hard_assert_handler=(value)
|
314
|
+
validate_lambda_given!(value)
|
315
|
+
@hard_assert_handler = value
|
316
|
+
end
|
317
|
+
|
318
|
+
private_class_method def self.hard_assert_handler_default(str, _)
|
319
|
+
raise str
|
320
|
+
end
|
321
|
+
|
322
|
+
def self.hard_assert_handler(str, extra={})
|
323
|
+
if @hard_assert_handler
|
324
|
+
@hard_assert_handler.call(str, extra)
|
325
|
+
else
|
326
|
+
hard_assert_handler_default(str, extra)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
# Set a list of class strings that are to be considered scalar.
|
331
|
+
# (pass nil to reset to default behavior)
|
332
|
+
#
|
333
|
+
# @param [String] value Class name.
|
334
|
+
#
|
335
|
+
# @example
|
336
|
+
# T::Configuration.scalar_types = ["NilClass", "TrueClass", "FalseClass", ...]
|
337
|
+
def self.scalar_types=(values)
|
338
|
+
if values.nil?
|
339
|
+
@scalar_types = values
|
340
|
+
else
|
341
|
+
bad_values = values.select {|v| v.class != String}
|
342
|
+
unless bad_values.empty?
|
343
|
+
raise ArgumentError.new("Provided values must all be class name strings.")
|
344
|
+
end
|
345
|
+
|
346
|
+
@scalar_types = Set.new(values).freeze
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
@default_scalar_types = Set.new(%w{
|
351
|
+
NilClass
|
352
|
+
TrueClass
|
353
|
+
FalseClass
|
354
|
+
Integer
|
355
|
+
Float
|
356
|
+
String
|
357
|
+
Symbol
|
358
|
+
Time
|
359
|
+
T::Enum
|
360
|
+
}).freeze
|
361
|
+
|
362
|
+
def self.scalar_types
|
363
|
+
@scalar_types || @default_scalar_types
|
364
|
+
end
|
365
|
+
|
366
|
+
# Temporarily disable ruby warnings while executing the given block. This is
|
367
|
+
# useful when doing something that would normally cause a warning to be
|
368
|
+
# emitted in Ruby verbose mode ($VERBOSE = true).
|
369
|
+
#
|
370
|
+
# @yield
|
371
|
+
#
|
372
|
+
def self.without_ruby_warnings
|
373
|
+
if $VERBOSE
|
374
|
+
begin
|
375
|
+
original_verbose = $VERBOSE
|
376
|
+
$VERBOSE = false
|
377
|
+
yield
|
378
|
+
ensure
|
379
|
+
$VERBOSE = original_verbose
|
380
|
+
end
|
381
|
+
else
|
382
|
+
yield
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
def self.enable_legacy_t_enum_migration_mode
|
387
|
+
@legacy_t_enum_migration_mode = true
|
388
|
+
end
|
389
|
+
def self.disable_legacy_t_enum_migration_mode
|
390
|
+
@legacy_t_enum_migration_mode = false
|
391
|
+
end
|
392
|
+
def self.legacy_t_enum_migration_mode?
|
393
|
+
@legacy_t_enum_migration_mode || false
|
394
|
+
end
|
395
|
+
|
396
|
+
# @param [Array] sealed_violation_whitelist An array of Regexp to validate
|
397
|
+
# whether inheriting /including a sealed module outside the defining module
|
398
|
+
# should be allowed. Useful to whitelist benign violations, like shim files
|
399
|
+
# generated for an autoloader.
|
400
|
+
def self.sealed_violation_whitelist=(sealed_violation_whitelist)
|
401
|
+
if @sealed_violation_whitelist != nil
|
402
|
+
raise ArgumentError.new("Cannot overwrite sealed_violation_whitelist after setting it")
|
403
|
+
end
|
404
|
+
|
405
|
+
case sealed_violation_whitelist
|
406
|
+
when Array
|
407
|
+
sealed_violation_whitelist.each do |x|
|
408
|
+
case x
|
409
|
+
when Regexp then nil
|
410
|
+
else raise TypeError.new("sealed_violation_whitelist accepts an Array of Regexp")
|
411
|
+
end
|
412
|
+
end
|
413
|
+
else
|
414
|
+
raise TypeError.new("sealed_violation_whitelist= accepts an Array of Regexp")
|
415
|
+
end
|
416
|
+
|
417
|
+
@sealed_violation_whitelist = sealed_violation_whitelist
|
418
|
+
end
|
419
|
+
def self.sealed_violation_whitelist
|
420
|
+
@sealed_violation_whitelist
|
421
|
+
end
|
422
|
+
|
423
|
+
private_class_method def self.validate_lambda_given!(value)
|
424
|
+
if !value.nil? && !value.respond_to?(:call)
|
425
|
+
raise ArgumentError.new("Provided value must respond to :call")
|
426
|
+
end
|
427
|
+
end
|
428
|
+
end
|