11
11
HackBuilderKeys ,
12
12
HackBuilderValues ,
13
13
};
14
+ use type Slack\Hack\JsonSchema\Sentinel ;
14
15
15
16
type TUntypedSchema = shape(
16
17
?' anyOf' => vec <TSchema >,
@@ -141,24 +142,35 @@ private function generateNotChecks(vec<TSchema> $schemas, HackBuilder $hb): void
141
142
142
143
}
143
144
144
- // TODO: Determine Lowest Upper Bound for oneOf constraint.
145
145
private function generateOneOfChecks (vec <TSchema > $schemas , HackBuilder $hb ): void {
146
146
$constraints = vec [];
147
+ $types = vec [];
147
148
foreach ($schemas as $index => $schema ) {
148
149
$schema_builder =
149
150
new SchemaBuilder ($this -> ctx , $this -> generateClassName($this -> suffix , ' oneOf' , (string )$index ), $schema );
150
151
$schema_builder -> build();
151
152
$constraints [] = " {$schema_builder->getClassName()} ::check<>" ;
153
+ $types [] = $schema_builder -> getTypeInfo();
152
154
}
153
155
156
+ $type_info = Typing \TypeSystem :: union($types );
157
+ // For now, keep upcasting nonnull to mixed.
158
+ // This is a temporary cludge to reduce the amount of code changed by generating unions.
159
+ // TODO: Stop doing the above.
160
+ if ($type_info is Typing \ConcreteType && $type_info -> getConcreteTypeName() === Typing \ConcreteTypeName :: NONNULL ) {
161
+ $type_info = Typing \TypeSystem :: mixed();
162
+ }
163
+ $this -> type_info = $type_info ;
164
+
154
165
$hb
155
166
-> addAssignment(' $constraints' , $constraints , HackBuilderValues :: vec(HackBuilderValues :: literal()))
156
167
-> ensureEmptyLine();
157
168
158
169
$hb
159
170
-> addAssignment(' $passed_any' , false , HackBuilderValues :: export())
160
171
-> addAssignment(' $passed_multi' , false , HackBuilderValues :: export())
161
- -> addAssignment(' $output' , null , HackBuilderValues :: export())
172
+ // Use `Sentinel` rather than `null` so that it's obvious when we failed to match any constraint.
173
+ -> addAssignment(' $output' , Str \format (' \%s::get()' , Sentinel :: class ), HackBuilderValues :: literal())
162
174
-> startForeachLoop(' $constraints' , null , ' $constraint' )
163
175
-> startTryBlock()
164
176
-> addMultilineCall(' $output = $constraint' , vec [' $input' , ' $pointer' ])
@@ -181,7 +193,7 @@ private function generateOneOfChecks(vec<TSchema> $schemas, HackBuilder $hb): vo
181
193
);
182
194
183
195
$hb
184
- -> startIfBlock (' $passed_multi || !$passed_any' )
196
+ -> startIfBlockf (' $passed_multi || !$passed_any || $output is \%s ' , Sentinel :: class )
185
197
-> addAssignment(
186
198
' $error' ,
187
199
$error ,
@@ -452,7 +464,7 @@ private function getOptimizedAnyOfTypes(vec<SchemaBuilder> $schema_builders): ?T
452
464
453
465
if ($property_type === TSchemaType :: STRING_T && C \contains ($required , $property_name )) {
454
466
$typed_property_schema =
455
- type_assert_shape ($property_schema , ' Slack\Hack\JsonSchema\Codegen\TStringSchema' );
467
+ type_assert_type ($property_schema , \ Slack \Hack \JsonSchema \Codegen \TStringSchema :: class );
456
468
457
469
$enum = $typed_property_schema [' enum' ] ?? null ;
458
470
if ($enum is nonnull && C \count ($enum ) === 1 ) {
0 commit comments