sorbet-runtime 0.5.11176 → 0.5.11212

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,6 +7,7 @@ module T::Props
7
7
  extend T::Sig
8
8
 
9
9
  SetterProc = T.type_alias {T.proc.params(val: T.untyped).void}
10
+ ValueValidationProc = T.type_alias {T.proc.params(val: T.untyped).void}
10
11
  ValidateProc = T.type_alias {T.proc.params(prop: Symbol, value: T.untyped).void}
11
12
 
12
13
  sig do
@@ -15,7 +16,7 @@ module T::Props
15
16
  prop: Symbol,
16
17
  rules: T::Hash[Symbol, T.untyped]
17
18
  )
18
- .returns(SetterProc)
19
+ .returns([SetterProc, ValueValidationProc])
19
20
  .checked(:never)
20
21
  end
21
22
  def self.build_setter_proc(klass, prop, rules)
@@ -55,20 +56,32 @@ module T::Props
55
56
  non_nil_type: Module,
56
57
  klass: T.all(Module, T::Props::ClassMethods),
57
58
  )
58
- .returns(SetterProc)
59
+ .returns([SetterProc, ValueValidationProc])
59
60
  end
60
61
  private_class_method def self.simple_non_nil_proc(prop, accessor_key, non_nil_type, klass)
61
- proc do |val|
62
- unless val.is_a?(non_nil_type)
63
- T::Props::Private::SetterFactory.raise_pretty_error(
64
- klass,
65
- prop,
66
- T::Utils.coerce(non_nil_type),
67
- val,
68
- )
69
- end
70
- instance_variable_set(accessor_key, val)
71
- end
62
+ [
63
+ proc do |val|
64
+ unless val.is_a?(non_nil_type)
65
+ T::Props::Private::SetterFactory.raise_pretty_error(
66
+ klass,
67
+ prop,
68
+ T::Utils.coerce(non_nil_type),
69
+ val,
70
+ )
71
+ end
72
+ instance_variable_set(accessor_key, val)
73
+ end,
74
+ proc do |val|
75
+ unless val.is_a?(non_nil_type)
76
+ T::Props::Private::SetterFactory.raise_pretty_error(
77
+ klass,
78
+ prop,
79
+ T::Utils.coerce(non_nil_type),
80
+ val,
81
+ )
82
+ end
83
+ end,
84
+ ]
72
85
  end
73
86
 
74
87
  sig do
@@ -79,27 +92,46 @@ module T::Props
79
92
  klass: T.all(Module, T::Props::ClassMethods),
80
93
  validate: T.nilable(ValidateProc)
81
94
  )
82
- .returns(SetterProc)
95
+ .returns([SetterProc, ValueValidationProc])
83
96
  end
84
97
  private_class_method def self.non_nil_proc(prop, accessor_key, non_nil_type, klass, validate)
85
- proc do |val|
86
- # this use of recursively_valid? is intentional: unlike for
87
- # methods, we want to make sure data at the 'edge'
88
- # (e.g. models that go into databases or structs serialized
89
- # from disk) are correct, so we use more thorough runtime
90
- # checks there
91
- if non_nil_type.recursively_valid?(val)
92
- validate&.call(prop, val)
93
- else
94
- T::Props::Private::SetterFactory.raise_pretty_error(
95
- klass,
96
- prop,
97
- non_nil_type,
98
- val,
99
- )
100
- end
101
- instance_variable_set(accessor_key, val)
102
- end
98
+ [
99
+ proc do |val|
100
+ # this use of recursively_valid? is intentional: unlike for
101
+ # methods, we want to make sure data at the 'edge'
102
+ # (e.g. models that go into databases or structs serialized
103
+ # from disk) are correct, so we use more thorough runtime
104
+ # checks there
105
+ if non_nil_type.recursively_valid?(val)
106
+ validate&.call(prop, val)
107
+ else
108
+ T::Props::Private::SetterFactory.raise_pretty_error(
109
+ klass,
110
+ prop,
111
+ non_nil_type,
112
+ val,
113
+ )
114
+ end
115
+ instance_variable_set(accessor_key, val)
116
+ end,
117
+ proc do |val|
118
+ # this use of recursively_valid? is intentional: unlike for
119
+ # methods, we want to make sure data at the 'edge'
120
+ # (e.g. models that go into databases or structs serialized
121
+ # from disk) are correct, so we use more thorough runtime
122
+ # checks there
123
+ if non_nil_type.recursively_valid?(val)
124
+ validate&.call(prop, val)
125
+ else
126
+ T::Props::Private::SetterFactory.raise_pretty_error(
127
+ klass,
128
+ prop,
129
+ non_nil_type,
130
+ val,
131
+ )
132
+ end
133
+ end,
134
+ ]
103
135
  end
104
136
 
105
137
  sig do
@@ -109,24 +141,32 @@ module T::Props
109
141
  non_nil_type: Module,
110
142
  klass: T.all(Module, T::Props::ClassMethods),
111
143
  )
112
- .returns(SetterProc)
144
+ .returns([SetterProc, ValueValidationProc])
113
145
  end
114
146
  private_class_method def self.simple_nilable_proc(prop, accessor_key, non_nil_type, klass)
115
- proc do |val|
116
- if val.nil?
117
- instance_variable_set(accessor_key, nil)
118
- elsif val.is_a?(non_nil_type)
119
- instance_variable_set(accessor_key, val)
120
- else
121
- T::Props::Private::SetterFactory.raise_pretty_error(
122
- klass,
123
- prop,
124
- T::Utils.coerce(non_nil_type),
125
- val,
126
- )
147
+ [
148
+ proc do |val|
149
+ unless val.nil? || val.is_a?(non_nil_type)
150
+ T::Props::Private::SetterFactory.raise_pretty_error(
151
+ klass,
152
+ prop,
153
+ T::Utils.coerce(non_nil_type),
154
+ val,
155
+ )
156
+ end
127
157
  instance_variable_set(accessor_key, val)
128
- end
129
- end
158
+ end,
159
+ proc do |val|
160
+ unless val.nil? || val.is_a?(non_nil_type)
161
+ T::Props::Private::SetterFactory.raise_pretty_error(
162
+ klass,
163
+ prop,
164
+ T::Utils.coerce(non_nil_type),
165
+ val,
166
+ )
167
+ end
168
+ end,
169
+ ]
130
170
  end
131
171
 
132
172
  sig do
@@ -137,30 +177,50 @@ module T::Props
137
177
  klass: T.all(Module, T::Props::ClassMethods),
138
178
  validate: T.nilable(ValidateProc),
139
179
  )
140
- .returns(SetterProc)
180
+ .returns([SetterProc, ValueValidationProc])
141
181
  end
142
182
  private_class_method def self.nilable_proc(prop, accessor_key, non_nil_type, klass, validate)
143
- proc do |val|
144
- if val.nil?
145
- instance_variable_set(accessor_key, nil)
146
- # this use of recursively_valid? is intentional: unlike for
147
- # methods, we want to make sure data at the 'edge'
148
- # (e.g. models that go into databases or structs serialized
149
- # from disk) are correct, so we use more thorough runtime
150
- # checks there
151
- elsif non_nil_type.recursively_valid?(val)
152
- validate&.call(prop, val)
153
- instance_variable_set(accessor_key, val)
154
- else
155
- T::Props::Private::SetterFactory.raise_pretty_error(
156
- klass,
157
- prop,
158
- non_nil_type,
159
- val,
160
- )
161
- instance_variable_set(accessor_key, val)
162
- end
163
- end
183
+ [
184
+ proc do |val|
185
+ if val.nil?
186
+ instance_variable_set(accessor_key, nil)
187
+ # this use of recursively_valid? is intentional: unlike for
188
+ # methods, we want to make sure data at the 'edge'
189
+ # (e.g. models that go into databases or structs serialized
190
+ # from disk) are correct, so we use more thorough runtime
191
+ # checks there
192
+ elsif non_nil_type.recursively_valid?(val)
193
+ validate&.call(prop, val)
194
+ instance_variable_set(accessor_key, val)
195
+ else
196
+ T::Props::Private::SetterFactory.raise_pretty_error(
197
+ klass,
198
+ prop,
199
+ non_nil_type,
200
+ val,
201
+ )
202
+ instance_variable_set(accessor_key, val)
203
+ end
204
+ end,
205
+ proc do |val|
206
+ if val.nil?
207
+ # this use of recursively_valid? is intentional: unlike for
208
+ # methods, we want to make sure data at the 'edge'
209
+ # (e.g. models that go into databases or structs serialized
210
+ # from disk) are correct, so we use more thorough runtime
211
+ # checks there
212
+ elsif non_nil_type.recursively_valid?(val)
213
+ validate&.call(prop, val)
214
+ else
215
+ T::Props::Private::SetterFactory.raise_pretty_error(
216
+ klass,
217
+ prop,
218
+ non_nil_type,
219
+ val,
220
+ )
221
+ end
222
+ end,
223
+ ]
164
224
  end
165
225
 
166
226
  sig do
@@ -54,7 +54,7 @@ module T::Types
54
54
  value_type = types[1]
55
55
  obj.each_pair do |key, val|
56
56
  # Some objects (I'm looking at you Rack::Utils::HeaderHash) don't
57
- # iterate over a [key, value] array, so we can't juse use the type.recursively_valid?(v)
57
+ # iterate over a [key, value] array, so we can't just use the type.recursively_valid?(v)
58
58
  return false if !key_type.recursively_valid?(key) || !value_type.recursively_valid?(val)
59
59
  end
60
60
  true
@@ -26,12 +26,6 @@ module T::Types
26
26
  @type ||= T::Utils.coerce([keys, values])
27
27
  end
28
28
 
29
- def build_type
30
- keys
31
- values
32
- super
33
- end
34
-
35
29
  # overrides Base
36
30
  def name
37
31
  "T::Hash[#{keys.name}, #{values.name}]"
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.5.11176
4
+ version: 0.5.11212
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-05 00:00:00.000000000 Z
11
+ date: 2024-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -165,7 +165,6 @@ files:
165
165
  - lib/types/enum.rb
166
166
  - lib/types/generic.rb
167
167
  - lib/types/helpers.rb
168
- - lib/types/interface_wrapper.rb
169
168
  - lib/types/non_forcing_constants.rb
170
169
  - lib/types/private/abstract/data.rb
171
170
  - lib/types/private/abstract/declare.rb
@@ -1,162 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: false
3
-
4
- # Wraps an object, exposing only the methods defined on a given class/module. The idea is that, in
5
- # the absence of a static type checker that would prevent you from calling non-Bar methods on a
6
- # variable of type Bar, we can use these wrappers as a way of enforcing it at runtime.
7
- #
8
- # Once we ship static type checking, we should get rid of this entirely.
9
- class T::InterfaceWrapper
10
- extend T::Sig
11
-
12
- module Helpers
13
- def wrap_instance(obj)
14
- T::InterfaceWrapper.wrap_instance(obj, self)
15
- end
16
-
17
- def wrap_instances(arr)
18
- T::InterfaceWrapper.wrap_instances(arr, self)
19
- end
20
- end
21
-
22
- private_class_method :new # use `wrap_instance`
23
-
24
- def self.wrap_instance(obj, interface_mod)
25
- wrapper = wrapped_dynamic_cast(obj, interface_mod)
26
- if wrapper.nil?
27
- raise "#{obj.class} cannot be cast to #{interface_mod}"
28
- end
29
- wrapper
30
- end
31
-
32
- sig do
33
- params(
34
- arr: Array,
35
- interface_mod: T.untyped
36
- )
37
- .returns(Array)
38
- end
39
- def self.wrap_instances(arr, interface_mod)
40
- arr.map {|instance| self.wrap_instance(instance, interface_mod)}
41
- end
42
-
43
- def initialize(target_obj, interface_mod)
44
- if target_obj.is_a?(T::InterfaceWrapper)
45
- # wrapped_dynamic_cast should guarantee this never happens.
46
- raise "Unexpected: wrapping a wrapper. Please report this bug at https://github.com/sorbet/sorbet/issues"
47
- end
48
-
49
- if !target_obj.is_a?(interface_mod)
50
- # wrapped_dynamic_cast should guarantee this never happens.
51
- raise "Unexpected: `is_a?` failed. Please report this bug at https://github.com/sorbet/sorbet/issues"
52
- end
53
-
54
- if target_obj.class == interface_mod
55
- # wrapped_dynamic_cast should guarantee this never happens.
56
- raise "Unexpected: exact class match. Please report this bug at https://github.com/sorbet/sorbet/issues"
57
- end
58
-
59
- @target_obj = target_obj
60
- @interface_mod = interface_mod
61
- self_methods = self.class.self_methods
62
-
63
- # If perf becomes an issue, we can define these on an anonymous subclass, and keep a cache
64
- # so we only need to do it once per unique `interface_mod`
65
- T::Utils.methods_excluding_object(interface_mod).each do |method_name|
66
- if self_methods.include?(method_name)
67
- raise "interface_mod has a method that conflicts with #{self.class}: #{method_name}"
68
- end
69
-
70
- define_singleton_method(method_name) do |*args, &blk|
71
- target_obj.send(method_name, *args, &blk)
72
- end
73
-
74
- if singleton_class.respond_to?(:ruby2_keywords, true)
75
- singleton_class.send(:ruby2_keywords, method_name)
76
- end
77
-
78
- if target_obj.singleton_class.public_method_defined?(method_name)
79
- # no-op, it's already public
80
- elsif target_obj.singleton_class.protected_method_defined?(method_name)
81
- singleton_class.send(:protected, method_name)
82
- elsif target_obj.singleton_class.private_method_defined?(method_name)
83
- singleton_class.send(:private, method_name)
84
- else
85
- raise "This should never happen. Report this bug at https://github.com/sorbet/sorbet/issues"
86
- end
87
- end
88
- end
89
-
90
- def kind_of?(other)
91
- is_a?(other)
92
- end
93
-
94
- def is_a?(other)
95
- if !other.is_a?(Module)
96
- raise TypeError.new("class or module required")
97
- end
98
-
99
- # This makes is_a? return true for T::InterfaceWrapper (and its ancestors),
100
- # as well as for @interface_mod and its ancestors.
101
- self.class <= other || @interface_mod <= other
102
- end
103
-
104
- # Prefixed because we're polluting the namespace of the interface we're wrapping, and we don't
105
- # want anyone else (besides dynamic_cast) calling it.
106
- def __target_obj_DO_NOT_USE # rubocop:disable Naming/MethodName
107
- @target_obj
108
- end
109
-
110
- # Prefixed because we're polluting the namespace of the interface we're wrapping, and we don't
111
- # want anyone else (besides wrapped_dynamic_cast) calling it.
112
- def __interface_mod_DO_NOT_USE # rubocop:disable Naming/MethodName
113
- @interface_mod
114
- end
115
-
116
- # "Cast" an object to another type. If `obj` is an InterfaceWrapper, returns the the wrapped
117
- # object if that matches `type`. Otherwise, returns `obj` if it matches `type`. Otherwise,
118
- # returns nil.
119
- #
120
- # @param obj [Object] object to cast
121
- # @param mod [Module] type to cast `obj` to
122
- #
123
- # @example
124
- # if (impl = T::InterfaceWrapper.dynamic_cast(iface, MyImplementation))
125
- # impl.do_things
126
- # end
127
- def self.dynamic_cast(obj, mod)
128
- if obj.is_a?(T::InterfaceWrapper)
129
- target_obj = obj.__target_obj_DO_NOT_USE
130
- target_obj.is_a?(mod) ? target_obj : nil
131
- elsif obj.is_a?(mod)
132
- obj
133
- else
134
- nil
135
- end
136
- end
137
-
138
- # Like dynamic_cast, but puts the result in its own wrapper if necessary.
139
- #
140
- # @param obj [Object] object to cast
141
- # @param mod [Module] type to cast `obj` to
142
- def self.wrapped_dynamic_cast(obj, mod)
143
- # Avoid unwrapping and creating an equivalent wrapper.
144
- if obj.is_a?(T::InterfaceWrapper) && obj.__interface_mod_DO_NOT_USE == mod
145
- return obj
146
- end
147
-
148
- cast_obj = dynamic_cast(obj, mod)
149
- if cast_obj.nil?
150
- nil
151
- elsif cast_obj.class == mod
152
- # Nothing to wrap, they want the full class
153
- cast_obj
154
- else
155
- new(cast_obj, mod)
156
- end
157
- end
158
-
159
- def self.self_methods
160
- @self_methods ||= self.instance_methods(false).to_set
161
- end
162
- end