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,47 @@ 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 && $ otherMemberTypeIfOneMemberIsNullType = match (NullType::class) {
59+ $ unionType ->members [0 ]::class => $ unionType ->members [1 ],
60+ $ unionType ->members [1 ]::class => $ unionType ->members [0 ],
61+ default => null
62+ }) {
63+ return $ this ->transpileNullableType ($ otherMemberTypeIfOneMemberIsNullType , $ typeReferenceNode );
64+ }
65+
66+ throw new \Exception ('@TODO Transpilation of complex union types is not implemented ' );
67+
68+ }
69+
70+ private function transpileNonUnionType (TypeInterface $ type , TypeReferenceNode $ typeReferenceNode ): string
71+ {
72+ return match ($ type ::class) {
4773 NumberType::class => 'int|float ' ,
4874 StringType::class => 'string ' ,
4975 BooleanType::class => 'bool ' ,
5076 SlotType::class => $ this ->strategy ->getPhpTypeReferenceForSlotType ($ type , $ typeReferenceNode ),
5177 ComponentType::class => $ this ->strategy ->getPhpTypeReferenceForComponentType ($ type , $ typeReferenceNode ),
5278 EnumType::class => $ this ->strategy ->getPhpTypeReferenceForEnumType ($ type , $ typeReferenceNode ),
5379 StructType::class => $ this ->strategy ->getPhpTypeReferenceForStructType ($ type , $ typeReferenceNode ),
80+ UnionType::class => throw new \Exception ("There is no such thing as nested unions, think again. " ),
5481 default => $ this ->strategy ->getPhpTypeReferenceForCustomType ($ type , $ typeReferenceNode )
5582 };
83+ }
5684
57- return $ typeReferenceNode-> isOptional
58- ? match ( $ phpTypeReference ) {
59- ' int|float ' => ' null|int|float ' ,
60- default => ' ? ' . $ phpTypeReference
61- }
62- : $ phpTypeReference ;
85+ private function transpileNullableType ( TypeInterface $ type , TypeReferenceNode $ typeReferenceNode): string
86+ {
87+ if ( $ type -> is (NumberType:: get ())) {
88+ return ' null|int|float ' ;
89+ }
90+ return ' ? ' . $ this -> transpileNonUnionType ( $ type , $ typeReferenceNode ) ;
6391 }
6492}
0 commit comments