sorbet-runtime 0.5.5316 → 0.5.5325

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 96ac3f40e289c8880e546f48cc793e4e12461e713ac5a6d5daf9777d91af2774
4
- data.tar.gz: 425ccca3f410868f357385eba3bbf0e8cc9cdd4b2cdc252137b0da96b36d5002
3
+ metadata.gz: 4e0334f17e13c054564e58b5baae0c6d7af794f0f9bb2a6c009b8c66a3ca6c2c
4
+ data.tar.gz: 3dfd7376f2c8259102b83724f2536a9094724a8d3ec15f89e86c24dcd56655f8
5
5
  SHA512:
6
- metadata.gz: 28df096a88491a837b89157f6b3fb2a779d0e61729e0c9363740a9fa8ddef7d23156f0c910fcc0b9569daba0826dfef9e22441bb82718872923a444c09b9536c
7
- data.tar.gz: cae44a94689f106188a491200eccf8b0da90e61ce2b089f79dbf8bcbb0ac4c486c9a10934f3647762aa3c179df677bfeee571665e1154b5929ebb8275ed3d7cf
6
+ metadata.gz: 91ccdef7e77ca422b938d018b7c06f5f6d67da79589a1c06e5bfb87c65cd94f198512ad537e086b7810b4be3b51b0d264d236afc07d14034dd800dccf754f508
7
+ data.tar.gz: 14e060cef09fd1b3c2937b879e31a27755182e40d65803aa8a2d98db51ac73617d08ca92f1f4fd321a2d7fbf988b515414b8967ca805d9be09f8d98f33c870d5
@@ -92,8 +92,10 @@ require_relative 'types/props/decorator'
92
92
  require_relative 'types/props/errors'
93
93
  require_relative 'types/props/plugin'
94
94
  require_relative 'types/props/utils'
95
+ require_relative 'types/enum'
95
96
  # Props that run sigs statically so have to be after all the others :(
96
97
  require_relative 'types/props/private/setter_factory'
98
+ require_relative 'types/props/private/apply_default'
97
99
  require_relative 'types/props/optional'
98
100
  require_relative 'types/props/weak_constructor'
99
101
  require_relative 'types/props/constructor'
@@ -102,6 +104,5 @@ require_relative 'types/props/serializable'
102
104
  require_relative 'types/props/type_validation'
103
105
 
104
106
  require_relative 'types/struct'
105
- require_relative 'types/enum'
106
107
 
107
108
  require_relative 'types/compatibility_patches'
@@ -8,13 +8,14 @@ class T::Private::Types::Void < T::Types::Base
8
8
 
9
9
  # The actual return value of `.void` methods.
10
10
  #
11
- # Uses `Module.new` because in Ruby an anonymous module will inherit the name
12
- # of the constant it's assigned to. This gives it a readable name someone
11
+ # Uses `module VOID` because this gives it a readable name when someone
13
12
  # examines it in Pry or with `#inspect` like:
14
13
  #
15
14
  # T::Private::Types::Void::VOID
16
15
  #
17
- VOID = Module.new.freeze
16
+ module VOID
17
+ freeze
18
+ end
18
19
 
19
20
  # @override Base
20
21
  def name
@@ -3,18 +3,32 @@
3
3
 
4
4
  module T::Props::Constructor
5
5
  include T::Props::WeakConstructor
6
+ end
6
7
 
7
- def initialize(hash={})
8
- decorator = self.class.decorator
8
+ module T::Props::Constructor::DecoratorMethods
9
+ extend T::Sig
9
10
 
10
- decorator.props.each do |prop, rules|
11
- # It's important to explicitly compare against `true` here; the value can also be :existing or
12
- # :on_load (which are truthy) but we don't want to treat those as optional in this context.
13
- if T::Props::Utils.required_prop?(rules) && !decorator.has_default?(rules) && !hash.key?(prop)
14
- raise ArgumentError.new("Missing required prop `#{prop}` for class `#{self.class}`")
11
+ # Set values for all props that have no defaults. Override what `WeakConstructor`
12
+ # does in order to raise errors on nils instead of ignoring them.
13
+ #
14
+ # @return [Integer] A count of props that we successfully initialized (which
15
+ # we'll use to check for any unrecognized input.)
16
+ #
17
+ # checked(:never) - O(runtime object construction)
18
+ sig {params(instance: T::Props::Constructor, hash: T::Hash[Symbol, T.untyped]).returns(Integer).checked(:never)}
19
+ def construct_props_without_defaults(instance, hash)
20
+ @props_without_defaults&.count do |p, setter_proc|
21
+ begin
22
+ val = hash[p]
23
+ instance.instance_exec(val, &setter_proc)
24
+ val || hash.key?(p)
25
+ rescue TypeError, T::Props::InvalidValueError
26
+ if !hash.key?(p)
27
+ raise ArgumentError.new("Missing required prop `#{p}` for class `#{instance.class.name}`")
28
+ else
29
+ raise
30
+ end
15
31
  end
16
- end
17
-
18
- super
32
+ end || 0
19
33
  end
20
34
  end
@@ -12,6 +12,8 @@ end
12
12
  # NB: This must stay in the same file where T::Props::Optional is defined due to
13
13
  # T::Props::Decorator#apply_plugin; see https://git.corp.stripe.com/stripe-internal/pay-server/blob/fc7f15593b49875f2d0499ffecfd19798bac05b3/chalk/odm/lib/chalk-odm/document_decorator.rb#L716-L717
14
14
  module T::Props::Optional::DecoratorMethods
15
+ extend T::Sig
16
+
15
17
  # TODO: clean this up. This set of options is confusing, and some of them are not universally
16
18
  # applicable (e.g., :on_load only applies when using T::Serializable).
17
19
  VALID_OPTIONAL_RULES = Set[
@@ -28,6 +30,9 @@ module T::Props::Optional::DecoratorMethods
28
30
  }.freeze
29
31
  private_constant :VALID_RULE_KEYS
30
32
 
33
+ DEFAULT_SETTER_RULE_KEY = :_t_props_private_apply_default
34
+ private_constant :DEFAULT_SETTER_RULE_KEY
35
+
31
36
  def valid_rule_key?(key)
32
37
  super || VALID_RULE_KEYS[key]
33
38
  end
@@ -39,8 +44,30 @@ module T::Props::Optional::DecoratorMethods
39
44
  rules[:need_nil_read_check] = T::Props::Utils.need_nil_read_check?(rules)
40
45
  end
41
46
 
47
+ # checked(:never) - O(runtime object construction)
48
+ sig {returns(T::Hash[Symbol, T::Props::Private::ApplyDefault]).checked(:never)}
49
+ attr_reader :props_with_defaults
50
+
51
+ # checked(:never) - O(runtime object construction)
52
+ sig {returns(T::Hash[Symbol, T::Props::Private::SetterFactory::SetterProc]).checked(:never)}
53
+ attr_reader :props_without_defaults
54
+
42
55
  def add_prop_definition(prop, rules)
43
56
  compute_derived_rules(rules)
57
+
58
+ default_setter = T::Props::Private::ApplyDefault.for(decorated_class, rules)
59
+ if default_setter
60
+ @props_with_defaults ||= {}
61
+ @props_with_defaults[prop] = default_setter
62
+ @props_without_defaults&.delete(prop) # Handle potential override
63
+
64
+ rules[DEFAULT_SETTER_RULE_KEY] = default_setter
65
+ else
66
+ @props_without_defaults ||= {}
67
+ @props_without_defaults[prop] = rules.fetch(:setter_proc)
68
+ @props_with_defaults&.delete(prop) # Handle potential override
69
+ end
70
+
44
71
  super
45
72
  end
46
73
 
@@ -61,21 +88,10 @@ module T::Props::Optional::DecoratorMethods
61
88
  end
62
89
 
63
90
  def has_default?(rules)
64
- rules.include?(:default) || rules.include?(:factory)
91
+ rules.include?(DEFAULT_SETTER_RULE_KEY)
65
92
  end
66
93
 
67
94
  def get_default(rules, instance_class)
68
- if rules.include?(:default)
69
- default = rules[:default]
70
- T::Props::Utils.deep_clone_object(default)
71
- elsif rules.include?(:factory)
72
- # Factory should never be nil if the key is specified, but
73
- # we do this rather than 'elsif rules[:factory]' for
74
- # consistency with :default.
75
- factory = rules[:factory]
76
- instance_class.class_exec(&factory)
77
- else
78
- nil
79
- end
95
+ rules[DEFAULT_SETTER_RULE_KEY]&.default
80
96
  end
81
97
  end
@@ -0,0 +1,170 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module T::Props
5
+ module Private
6
+ class ApplyDefault
7
+ extend T::Sig
8
+ extend T::Helpers
9
+ abstract!
10
+
11
+ # checked(:never) - O(object construction x prop count)
12
+ sig {returns(SetterFactory::SetterProc).checked(:never)}
13
+ attr_reader :setter_proc
14
+
15
+ # checked(:never) - We do this with `T.let` instead
16
+ sig {params(accessor_key: Symbol, setter_proc: SetterFactory::SetterProc).void.checked(:never)}
17
+ def initialize(accessor_key, setter_proc)
18
+ @accessor_key = T.let(accessor_key, Symbol)
19
+ @setter_proc = T.let(setter_proc, SetterFactory::SetterProc)
20
+ end
21
+
22
+ # checked(:never) - O(object construction x prop count)
23
+ sig {abstract.returns(T.untyped).checked(:never)}
24
+ def default; end
25
+
26
+ # checked(:never) - O(object construction x prop count)
27
+ sig {abstract.params(instance: T.all(T::Props::Optional, Object)).void.checked(:never)}
28
+ def set_default(instance); end
29
+
30
+ NO_CLONE_TYPES = T.let([TrueClass, FalseClass, NilClass, Symbol, Numeric, T::Enum].freeze, T::Array[Module])
31
+
32
+ # checked(:never) - Rules hash is expensive to check
33
+ sig {params(cls: Module, rules: T::Hash[Symbol, T.untyped]).returns(T.nilable(ApplyDefault)).checked(:never)}
34
+ def self.for(cls, rules)
35
+ accessor_key = rules.fetch(:accessor_key)
36
+ setter = rules.fetch(:setter_proc)
37
+
38
+ if rules.key?(:factory)
39
+ ApplyDefaultFactory.new(cls, rules.fetch(:factory), accessor_key, setter)
40
+ elsif rules.key?(:default)
41
+ default = rules.fetch(:default)
42
+ case default
43
+ when *NO_CLONE_TYPES
44
+ return ApplyPrimitiveDefault.new(default, accessor_key, setter)
45
+ when String
46
+ if default.frozen?
47
+ return ApplyPrimitiveDefault.new(default, accessor_key, setter)
48
+ end
49
+ when Array
50
+ if default.empty? && default.class == Array
51
+ return ApplyEmptyArrayDefault.new(accessor_key, setter)
52
+ end
53
+ when Hash
54
+ if default.empty? && default.default.nil? && T.unsafe(default).default_proc.nil? && default.class == Hash
55
+ return ApplyEmptyHashDefault.new(accessor_key, setter)
56
+ end
57
+ end
58
+
59
+ ApplyComplexDefault.new(default, accessor_key, setter)
60
+ else
61
+ nil
62
+ end
63
+ end
64
+ end
65
+
66
+ class ApplyFixedDefault < ApplyDefault
67
+ abstract!
68
+
69
+ # checked(:never) - We do this with `T.let` instead
70
+ sig {params(default: BasicObject, accessor_key: Symbol, setter_proc: SetterFactory::SetterProc).void.checked(:never)}
71
+ def initialize(default, accessor_key, setter_proc)
72
+ # FIXME: Ideally we'd check here that the default is actually a valid
73
+ # value for this field, but existing code relies on the fact that we don't.
74
+ #
75
+ # :(
76
+ #
77
+ # setter_proc.call(default)
78
+ @default = T.let(default, BasicObject)
79
+ super(accessor_key, setter_proc)
80
+ end
81
+
82
+ # checked(:never) - O(object construction x prop count)
83
+ sig {override.params(instance: T.all(T::Props::Optional, Object)).void.checked(:never)}
84
+ def set_default(instance)
85
+ instance.instance_variable_set(@accessor_key, default)
86
+ end
87
+ end
88
+
89
+ class ApplyPrimitiveDefault < ApplyFixedDefault
90
+ # checked(:never) - O(object construction x prop count)
91
+ sig {override.returns(T.untyped).checked(:never)}
92
+ attr_reader :default
93
+ end
94
+
95
+ class ApplyComplexDefault < ApplyFixedDefault
96
+ # checked(:never) - O(object construction x prop count)
97
+ sig {override.returns(T.untyped).checked(:never)}
98
+ def default
99
+ T::Props::Utils.deep_clone_object(@default)
100
+ end
101
+ end
102
+
103
+ # Special case since it's so common, and a literal `[]` is meaningfully
104
+ # faster than falling back to ApplyComplexDefault or even calling
105
+ # `some_empty_array.dup`
106
+ class ApplyEmptyArrayDefault < ApplyDefault
107
+ # checked(:never) - O(object construction x prop count)
108
+ sig {override.params(instance: T.all(T::Props::Optional, Object)).void.checked(:never)}
109
+ def set_default(instance)
110
+ instance.instance_variable_set(@accessor_key, [])
111
+ end
112
+
113
+ # checked(:never) - O(object construction x prop count)
114
+ sig {override.returns(T::Array[T.untyped]).checked(:never)}
115
+ def default
116
+ []
117
+ end
118
+ end
119
+
120
+ # Special case since it's so common, and a literal `{}` is meaningfully
121
+ # faster than falling back to ApplyComplexDefault or even calling
122
+ # `some_empty_hash.dup`
123
+ class ApplyEmptyHashDefault < ApplyDefault
124
+ # checked(:never) - O(object construction x prop count)
125
+ sig {override.params(instance: T.all(T::Props::Optional, Object)).void.checked(:never)}
126
+ def set_default(instance)
127
+ instance.instance_variable_set(@accessor_key, {})
128
+ end
129
+
130
+ # checked(:never) - O(object construction x prop count)
131
+ sig {override.returns(T::Hash[T.untyped, T.untyped]).checked(:never)}
132
+ def default
133
+ {}
134
+ end
135
+ end
136
+
137
+ class ApplyDefaultFactory < ApplyDefault
138
+ # checked(:never) - We do this with `T.let` instead
139
+ sig do
140
+ params(
141
+ cls: Module,
142
+ factory: T.any(Proc, Method),
143
+ accessor_key: Symbol,
144
+ setter_proc: SetterFactory::SetterProc,
145
+ )
146
+ .void
147
+ .checked(:never)
148
+ end
149
+ def initialize(cls, factory, accessor_key, setter_proc)
150
+ @class = T.let(cls, Module)
151
+ @factory = T.let(factory, T.any(Proc, Method))
152
+ super(accessor_key, setter_proc)
153
+ end
154
+
155
+ # checked(:never) - O(object construction x prop count)
156
+ sig {override.params(instance: T.all(T::Props::Optional, Object)).void.checked(:never)}
157
+ def set_default(instance)
158
+ # Use the actual setter to validate the factory returns a legitimate
159
+ # value every time
160
+ instance.instance_exec(default, &@setter_proc)
161
+ end
162
+
163
+ # checked(:never) - O(object construction x prop count)
164
+ sig {override.returns(T.untyped).checked(:never)}
165
+ def default
166
+ @class.class_exec(&@factory)
167
+ end
168
+ end
169
+ end
170
+ end
@@ -3,28 +3,60 @@
3
3
 
4
4
  module T::Props::WeakConstructor
5
5
  include T::Props::Optional
6
+ extend T::Sig
6
7
 
8
+ # checked(:never) - O(runtime object construction)
9
+ sig {params(hash: T::Hash[Symbol, T.untyped]).void.checked(:never)}
7
10
  def initialize(hash={})
8
- expected_keys = {}
9
- hash.each_key {|key| expected_keys[key] = true}
10
-
11
11
  decorator = self.class.decorator
12
12
 
13
- decorator.props.each do |p, rules|
13
+ hash_keys_matching_props = decorator.construct_props_with_defaults(self, hash) +
14
+ decorator.construct_props_without_defaults(self, hash)
15
+
16
+ if hash_keys_matching_props < hash.size
17
+ raise ArgumentError.new("#{self.class}: Unrecognized properties: #{(hash.keys - decorator.props.keys).join(', ')}")
18
+ end
19
+ end
20
+ end
21
+
22
+ module T::Props::WeakConstructor::DecoratorMethods
23
+ extend T::Sig
24
+
25
+ # Set values for all props that have no defaults. Ignore any not present.
26
+ #
27
+ # @return [Integer] A count of props that we successfully initialized (which
28
+ # we'll use to check for any unrecognized input.)
29
+ #
30
+ # checked(:never) - O(runtime object construction)
31
+ sig {params(instance: T::Props::WeakConstructor, hash: T::Hash[Symbol, T.untyped]).returns(Integer).checked(:never)}
32
+ def construct_props_without_defaults(instance, hash)
33
+ @props_without_defaults&.count do |p, setter_proc|
14
34
  if hash.key?(p)
15
- expected_keys.delete(p)
16
- val = hash[p]
17
- elsif decorator.has_default?(rules)
18
- val = decorator.get_default(rules, self.class)
35
+ instance.instance_exec(hash[p], &setter_proc)
36
+ true
19
37
  else
20
- next
38
+ false
21
39
  end
40
+ end || 0
41
+ end
22
42
 
23
- decorator.prop_set(self, p, val, rules)
24
- end
25
-
26
- unless expected_keys.empty?
27
- raise ArgumentError.new("#{@class}: Unrecognized properties in #with_props: #{expected_keys.keys.join(', ')}")
28
- end
43
+ # Set values for all props that have defaults. Use the default if and only if
44
+ # the prop key isn't in the input.
45
+ #
46
+ # @return [Integer] A count of props that we successfully initialized (which
47
+ # we'll use to check for any unrecognized input.)
48
+ #
49
+ # checked(:never) - O(runtime object construction)
50
+ sig {params(instance: T::Props::WeakConstructor, hash: T::Hash[Symbol, T.untyped]).returns(Integer).checked(:never)}
51
+ def construct_props_with_defaults(instance, hash)
52
+ @props_with_defaults&.count do |p, default_struct|
53
+ if hash.key?(p)
54
+ instance.instance_exec(hash[p], &default_struct.setter_proc)
55
+ true
56
+ else
57
+ default_struct.set_default(instance)
58
+ false
59
+ end
60
+ end || 0
29
61
  end
30
62
  end
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.5316
4
+ version: 0.5.5325
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-31 00:00:00.000000000 Z
11
+ date: 2020-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -112,6 +112,7 @@ files:
112
112
  - lib/types/props/optional.rb
113
113
  - lib/types/props/plugin.rb
114
114
  - lib/types/props/pretty_printable.rb
115
+ - lib/types/props/private/apply_default.rb
115
116
  - lib/types/props/private/setter_factory.rb
116
117
  - lib/types/props/serializable.rb
117
118
  - lib/types/props/type_validation.rb