2727use PackageFactory \ComponentEngine \TypeSystem \Type \BooleanType \BooleanType ;
2828use PackageFactory \ComponentEngine \TypeSystem \Type \ComponentType \ComponentType ;
2929use PackageFactory \ComponentEngine \TypeSystem \Type \EnumType \EnumType ;
30+ use PackageFactory \ComponentEngine \TypeSystem \Type \NullType \NullType ;
3031use PackageFactory \ComponentEngine \TypeSystem \Type \NumberType \NumberType ;
3132use PackageFactory \ComponentEngine \TypeSystem \Type \SlotType \SlotType ;
3233use PackageFactory \ComponentEngine \TypeSystem \Type \StringType \StringType ;
3334use PackageFactory \ComponentEngine \TypeSystem \Type \StructType \StructType ;
35+ use PackageFactory \ComponentEngine \TypeSystem \Type \UnionType \UnionType ;
36+ use PackageFactory \ComponentEngine \TypeSystem \TypeInterface ;
3437
3538final class TypeReferenceTranspiler
3639{
@@ -43,22 +46,51 @@ public function __construct(
4346 public function transpile (TypeReferenceNode $ typeReferenceNode ): string
4447 {
4548 $ type = $ this ->scope ->resolveTypeReference ($ typeReferenceNode );
46- $ phpTypeReference = match ($ type ::class) {
49+
50+ return match ($ type ::class) {
51+ UnionType::class => $ this ->transpileUnionType ($ type , $ typeReferenceNode ),
52+ default => $ this ->transpileNonUnionType ($ type , $ typeReferenceNode )
53+ };
54+ }
55+
56+ private function transpileUnionType (UnionType $ unionType , TypeReferenceNode $ typeReferenceNode ): string
57+ {
58+ if (count ($ unionType ->members ) === 2 ) {
59+ $ otherTypeIfTypeIsNullable = match (true ) {
60+ $ unionType ->members [0 ]->is (NullType::get ()) => $ unionType ->members [1 ],
61+ $ unionType ->members [1 ]->is (NullType::get ()) => $ unionType ->members [0 ],
62+ default => null
63+ };
64+
65+ if ($ otherTypeIfTypeIsNullable ) {
66+ return $ this ->transpileNullableType ($ otherTypeIfTypeIsNullable , $ typeReferenceNode );
67+ }
68+ }
69+
70+ throw new \Exception ('@TODO Transpilation of complex union types is not implemented ' );
71+
72+ }
73+
74+ private function transpileNonUnionType (TypeInterface $ type , TypeReferenceNode $ typeReferenceNode ): string
75+ {
76+ return match ($ type ::class) {
4777 NumberType::class => 'int|float ' ,
4878 StringType::class => 'string ' ,
4979 BooleanType::class => 'bool ' ,
5080 SlotType::class => $ this ->strategy ->getPhpTypeReferenceForSlotType ($ type , $ typeReferenceNode ),
5181 ComponentType::class => $ this ->strategy ->getPhpTypeReferenceForComponentType ($ type , $ typeReferenceNode ),
5282 EnumType::class => $ this ->strategy ->getPhpTypeReferenceForEnumType ($ type , $ typeReferenceNode ),
5383 StructType::class => $ this ->strategy ->getPhpTypeReferenceForStructType ($ type , $ typeReferenceNode ),
84+ UnionType::class => throw new \Exception ("@TODO: Cannot transpile nested union " ),
5485 default => $ this ->strategy ->getPhpTypeReferenceForCustomType ($ type , $ typeReferenceNode )
5586 };
87+ }
5688
57- return $ typeReferenceNode-> isOptional
58- ? match ( $ phpTypeReference ) {
59- ' int|float ' => ' null|int|float ' ,
60- default => ' ? ' . $ phpTypeReference
61- }
62- : $ phpTypeReference ;
89+ private function transpileNullableType ( TypeInterface $ type , TypeReferenceNode $ typeReferenceNode): string
90+ {
91+ if ( $ type -> is (NumberType:: get ())) {
92+ return ' null|int|float ' ;
93+ }
94+ return ' ? ' . $ this -> transpileNonUnionType ( $ type , $ typeReferenceNode ) ;
6395 }
6496}
0 commit comments