sorbet-runtime 0.5.5316 → 0.5.5325

Sign up to get free protection for your applications and to get access to all the features.
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