44
55namespace TypeLang \Printer ;
66
7+ use TypeLang \Parser \Node \Literal \BoolLiteralNode ;
78use TypeLang \Parser \Node \Literal \LiteralNode ;
89use TypeLang \Parser \Node \Literal \VariableLiteralNode ;
10+ use TypeLang \Parser \Node \Statement ;
911use TypeLang \Parser \Node \Stmt \CallableTypeNode ;
1012use TypeLang \Parser \Node \Stmt \ClassConstMaskNode ;
1113use TypeLang \Parser \Node \Stmt \ClassConstNode ;
1719use TypeLang \Parser \Node \Stmt \NamedTypeNode ;
1820use TypeLang \Parser \Node \Stmt \TernaryConditionNode ;
1921use TypeLang \Parser \Node \Stmt \TypesListNode ;
22+ use TypeLang \Parser \Node \Stmt \TypeStatement ;
2023use TypeLang \Parser \Node \Stmt \UnionTypeNode ;
2124use TypeLang \Printer \Exception \NonPrintableNodeException ;
2225
@@ -112,6 +115,7 @@ public function __construct(
112115 }
113116
114117 /**
118+ * @api
115119 * @param non-empty-string $alias
116120 * @param non-empty-string $type
117121 */
@@ -121,6 +125,7 @@ public function addTypeAlias(string $alias, string $type): void
121125 }
122126
123127 /**
128+ * @api
124129 * @param non-empty-string $alias
125130 * @param non-empty-list<non-empty-string> $types
126131 */
@@ -132,6 +137,7 @@ public function addUnionTypeAlias(string $alias, array $types): void
132137 }
133138
134139 /**
140+ * @api
135141 * @param non-empty-string $alias
136142 * @param non-empty-list<non-empty-string> $types
137143 */
@@ -154,10 +160,7 @@ protected function printTypeListNode(TypesListNode $node): string
154160 #[\Override]
155161 protected function printTernaryType (TernaryConditionNode $ node ): string
156162 {
157- return $ this ->make (new UnionTypeNode (
158- $ node ->then ,
159- $ node ->else ,
160- ));
163+ return $ this ->make (new UnionTypeNode ($ node ->then , $ node ->else ));
161164 }
162165
163166 #[\Override]
@@ -191,35 +194,63 @@ protected function printClassConstNode(ClassConstNode $node): string
191194 #[\Override]
192195 protected function printUnionTypeNode (UnionTypeNode $ node ): string
193196 {
194- try {
195- return \vsprintf ($ this ->nesting > 0 ? '(%s) ' : '%s ' , [
196- \implode ('| ' , [...$ this ->unwrapAndPrint ($ node )]),
197- ]);
198- } finally {
199- ++$ this ->nesting ;
200- }
197+ $ shouldWrap = $ this ->nesting ++ > 0 ;
198+
199+ $ result = $ this ->unwrapAndPrint ($ node );
200+
201+ $ result = $ this ->formatUnionWithMixed ($ result );
202+ $ result = $ this ->formatBoolWithTrueAndFalse ($ result );
203+
204+ return \vsprintf ($ shouldWrap ? '(%s) ' : '%s ' , [
205+ \implode ('| ' , [...\array_unique ($ result )]),
206+ ]);
201207 }
202208
203- #[\Override]
204- protected function printIntersectionTypeNode (IntersectionTypeNode $ node ): string
209+ /**
210+ * Replace "true" + "false" pair into "bool"
211+ *
212+ * @param list<non-empty-string> $result
213+ * @return list<non-empty-string>
214+ */
215+ private function formatBoolWithTrueAndFalse (array $ result ): array
205216 {
206- try {
207- return \vsprintf ($ this ->nesting > 0 ? '(%s) ' : '%s ' , [
208- \implode ('& ' , [...$ this ->unwrapAndPrint ($ node )]),
209- ]);
210- } finally {
211- ++$ this ->nesting ;
217+ $ containsBool = (\in_array ('true ' , $ result , true ) || \in_array ('\true ' , $ result , true ))
218+ && (\in_array ('false ' , $ result , true ) || \in_array ('\false ' , $ result , true ));
219+
220+ if (!$ containsBool ) {
221+ return $ result ;
212222 }
223+
224+ $ filtered = \array_filter ($ result , static fn (string $ type ): bool
225+ => !\in_array ($ type , ['true ' , 'false ' , '\true ' , '\false ' ], true ));
226+ $ filtered [] = 'bool ' ;
227+
228+ /** @var list<non-empty-string> */
229+ return $ filtered ;
213230 }
214231
215232 /**
216- * @param non-empty-string $name
233+ * Replace everything that contain "mixed" type
234+ * if one of the types is "mixed".
217235 *
218- * @return non-empty-string
236+ * @param list<non-empty-string> $result
237+ * @return list<non-empty-string>
219238 */
220- protected function getTypeName ( string $ name ): string
239+ private function formatUnionWithMixed ( array $ result ): array
221240 {
222- return $ this ->aliases [\strtolower ($ name )] ?? $ name ;
241+ if (\in_array ('mixed ' , $ result , true )) {
242+ return ['mixed ' ];
243+ }
244+
245+ return $ result ;
246+ }
247+
248+ #[\Override]
249+ protected function printIntersectionTypeNode (IntersectionTypeNode $ node ): string
250+ {
251+ return \vsprintf ($ this ->nesting ++ > 0 ? '(%s) ' : '%s ' , [
252+ \implode ('& ' , [...$ this ->unwrapAndPrint ($ node )]),
253+ ]);
223254 }
224255
225256 #[\Override]
@@ -228,6 +259,16 @@ protected function printCallableTypeNode(CallableTypeNode $node): string
228259 return $ this ->getTypeName ($ node ->name ->toString ());
229260 }
230261
262+ /**
263+ * @param non-empty-string $name
264+ *
265+ * @return non-empty-string
266+ */
267+ protected function getTypeName (string $ name ): string
268+ {
269+ return $ this ->aliases [\strtolower ($ name )] ?? $ name ;
270+ }
271+
231272 #[\Override]
232273 protected function printNamedTypeNode (NamedTypeNode $ node ): string
233274 {
0 commit comments