Skip to content

Commit fe6a29e

Browse files
fix: correctly instantiate sorbet type aliases for enums and unions
1 parent b4afd0a commit fe6a29e

File tree

64 files changed

+251
-850
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+251
-850
lines changed

lib/orb/internal/type/array_of.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module Type
1212
# Array of items of a given type.
1313
class ArrayOf
1414
include Orb::Internal::Type::Converter
15+
include Orb::Internal::Util::SorbetRuntimeSupport
1516

1617
private_class_method :new
1718

@@ -110,6 +111,13 @@ def dump(value, state:)
110111
end
111112
end
112113

114+
# @api private
115+
#
116+
# @return [Object]
117+
def to_sorbet_type
118+
T::Array[Orb::Internal::Util::SorbetRuntimeSupport.to_sorbet_type(item_type)]
119+
end
120+
113121
# @api private
114122
#
115123
# @return [generic<Elem>]

lib/orb/internal/type/base_model.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,13 @@ def dump(value, state:)
304304

305305
acc
306306
end
307+
308+
# @api private
309+
#
310+
# @return [Object]
311+
def to_sorbet_type
312+
self
313+
end
307314
end
308315

309316
class << self

lib/orb/internal/type/boolean.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module Type
1010
# Ruby has no Boolean class; this is something for models to refer to.
1111
class Boolean
1212
extend Orb::Internal::Type::Converter
13+
extend Orb::Internal::Util::SorbetRuntimeSupport
1314

1415
private_class_method :new
1516

@@ -56,6 +57,13 @@ def coerce(value, state:)
5657
# @option state [Boolean] :can_retry
5758
#
5859
# @return [Boolean, Object]
60+
61+
# @api private
62+
#
63+
# @return [Object]
64+
def to_sorbet_type
65+
T::Boolean
66+
end
5967
end
6068
end
6169
end

lib/orb/internal/type/enum.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,18 @@ def coerce(value, state:)
108108
#
109109
# @return [Symbol, Object]
110110

111+
# @api private
112+
#
113+
# @return [Object]
114+
def to_sorbet_type
115+
case values
116+
in []
117+
T.noreturn
118+
in [value, *_]
119+
T.all(Orb::Internal::Util::SorbetRuntimeSupport.to_sorbet_type(value), self)
120+
end
121+
end
122+
111123
# @api private
112124
#
113125
# @param depth [Integer]

lib/orb/internal/type/file_input.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ def dump(value, state:)
8888

8989
value
9090
end
91+
92+
# @api private
93+
#
94+
# @return [Object]
95+
def to_sorbet_type
96+
T.any(Pathname, StringIO, IO, String, Orb::FilePart)
97+
end
9198
end
9299
end
93100
end

lib/orb/internal/type/hash_of.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module Type
1212
# Hash of items of a given type.
1313
class HashOf
1414
include Orb::Internal::Type::Converter
15+
include Orb::Internal::Util::SorbetRuntimeSupport
1516

1617
private_class_method :new
1718

@@ -130,6 +131,13 @@ def dump(value, state:)
130131
end
131132
end
132133

134+
# @api private
135+
#
136+
# @return [Object]
137+
def to_sorbet_type
138+
T::Hash[Orb::Internal::Util::SorbetRuntimeSupport.to_sorbet_type(item_type)]
139+
end
140+
133141
# @api private
134142
#
135143
# @return [generic<Elem>]

lib/orb/internal/type/union.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,18 @@ def dump(value, state:)
231231
super
232232
end
233233

234+
# @api private
235+
#
236+
# @return [Object]
237+
def to_sorbet_type
238+
case (v = variants)
239+
in []
240+
T.noreturn
241+
else
242+
T.any(*v.map { Orb::Internal::Util::SorbetRuntimeSupport.to_sorbet_type(_1) })
243+
end
244+
end
245+
234246
# rubocop:enable Style/CaseEquality
235247
# rubocop:enable Style/HashEachMethods
236248

lib/orb/internal/type/unknown.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module Type
1010
# When we don't know what to expect for the value.
1111
class Unknown
1212
extend Orb::Internal::Type::Converter
13+
extend Orb::Internal::Util::SorbetRuntimeSupport
1314

1415
# rubocop:disable Lint/UnusedMethodArgument
1516

@@ -58,6 +59,13 @@ def coerce(value, state:)
5859
# @option state [Boolean] :can_retry
5960
#
6061
# @return [Object]
62+
63+
# @api private
64+
#
65+
# @return [Object]
66+
def to_sorbet_type
67+
T.anything
68+
end
6169
end
6270

6371
# rubocop:enable Lint/UnusedMethodArgument

lib/orb/internal/util.rb

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,23 @@ module Util
99
# @return [Float]
1010
def self.monotonic_secs = Process.clock_gettime(Process::CLOCK_MONOTONIC)
1111

12+
# @api private
13+
#
14+
# @param ns [Module, Class]
15+
#
16+
# @return [Enumerable<Module, Class>]
17+
def self.walk_namespaces(ns)
18+
ns.constants(false).lazy.flat_map do
19+
case (c = ns.const_get(_1, false))
20+
in Module | Class
21+
walk_namespaces(c)
22+
else
23+
[]
24+
end
25+
end
26+
.chain([ns])
27+
end
28+
1229
class << self
1330
# @api private
1431
#
@@ -826,11 +843,39 @@ def const_missing(name)
826843
sorbet_runtime_constants.fetch(name).call
827844
end
828845

846+
# @api private
847+
#
848+
# @param name [Symbol]
849+
#
850+
# @return [Boolean]
851+
def sorbet_constant_defined?(name) = sorbet_runtime_constants.key?(name)
852+
829853
# @api private
830854
#
831855
# @param name [Symbol]
832856
# @param blk [Proc]
833857
def define_sorbet_constant!(name, &blk) = sorbet_runtime_constants.store(name, blk)
858+
859+
# @api private
860+
#
861+
# @return [Object]
862+
def to_sorbet_type = raise NotImplementedError
863+
864+
class << self
865+
# @api private
866+
#
867+
# @param type [Orb::Internal::Util::SorbetRuntimeSupport, Object]
868+
#
869+
# @return [Object]
870+
def to_sorbet_type(type)
871+
case type
872+
in Orb::Internal::Util::SorbetRuntimeSupport
873+
type.to_sorbet_type
874+
else
875+
type
876+
end
877+
end
878+
end
834879
end
835880

836881
extend Orb::Internal::Util::SorbetRuntimeSupport

lib/orb/models.rb

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,40 @@ module Orb
55
cls.define_sorbet_constant!(:OrHash) { T.type_alias { T.any(cls, Orb::Internal::AnyHash) } }
66
end
77

8-
[*Orb::Internal::Type::Enum.included_modules, *Orb::Internal::Type::Union.included_modules].each do |cls|
9-
cls.constants.each do |name|
10-
case cls.const_get(name)
11-
in true | false
12-
cls.define_sorbet_constant!(:TaggedBoolean) { T.type_alias { T.all(T::Boolean, cls) } }
13-
cls.define_sorbet_constant!(:OrBoolean) { T.type_alias { T::Boolean } }
14-
in Integer
15-
cls.define_sorbet_constant!(:TaggedInteger) { T.type_alias { T.all(Integer, cls) } }
16-
cls.define_sorbet_constant!(:OrInteger) { T.type_alias { Integer } }
17-
in Float
18-
cls.define_sorbet_constant!(:TaggedFloat) { T.type_alias { T.all(Float, cls) } }
19-
cls.define_sorbet_constant!(:OrFloat) { T.type_alias { Float } }
20-
in Symbol
21-
cls.define_sorbet_constant!(:TaggedSymbol) { T.type_alias { T.all(Symbol, cls) } }
22-
cls.define_sorbet_constant!(:OrSymbol) { T.type_alias { T.any(Symbol, String) } }
23-
else
8+
Orb::Internal::Util.walk_namespaces(Orb::Models).each do |mod|
9+
case mod
10+
in Orb::Internal::Type::Enum | Orb::Internal::Type::Union
11+
mod.constants.each do |name|
12+
case mod.const_get(name)
13+
in true | false
14+
mod.define_sorbet_constant!(:TaggedBoolean) { T.type_alias { T.all(T::Boolean, mod) } }
15+
mod.define_sorbet_constant!(:OrBoolean) { T.type_alias { T::Boolean } }
16+
in Integer
17+
mod.define_sorbet_constant!(:TaggedInteger) { T.type_alias { T.all(Integer, mod) } }
18+
mod.define_sorbet_constant!(:OrInteger) { T.type_alias { Integer } }
19+
in Float
20+
mod.define_sorbet_constant!(:TaggedFloat) { T.type_alias { T.all(Float, mod) } }
21+
mod.define_sorbet_constant!(:OrFloat) { T.type_alias { Float } }
22+
in Symbol
23+
mod.define_sorbet_constant!(:TaggedSymbol) { T.type_alias { T.all(Symbol, mod) } }
24+
mod.define_sorbet_constant!(:OrSymbol) { T.type_alias { T.any(Symbol, String) } }
25+
else
26+
end
2427
end
28+
else
2529
end
2630
end
2731

32+
Orb::Internal::Util.walk_namespaces(Orb::Models)
33+
.lazy
34+
.grep(Orb::Internal::Type::Union)
35+
.each do |mod|
36+
const = :Variants
37+
next if mod.sorbet_constant_defined?(const)
38+
39+
mod.define_sorbet_constant!(const) { T.type_alias { mod.to_sorbet_type } }
40+
end
41+
2842
Alert = Orb::Models::Alert
2943

3044
AlertCreateForCustomerParams = Orb::Models::AlertCreateForCustomerParams

0 commit comments

Comments
 (0)