1313
1414use Twig \Environment ;
1515use Twig \Node \AutoEscapeNode ;
16+ use Twig \Node \BodyNode ;
1617use Twig \Node \Expression \ArrayExpression ;
1718use Twig \Node \Expression \AssignNameExpression ;
1819use Twig \Node \Expression \Binary \AddBinary ;
5556use Twig \Node \MacroNode ;
5657use Twig \Node \Node ;
5758use Twig \Node \SetNode ;
59+ use Twig \Node \TypeHintNode ;
5860use Twig \Node \WithNode ;
5961use Twig \TypeHint \ArrayType ;
6062use Twig \TypeHint \TypeFactory ;
@@ -81,6 +83,14 @@ public function enterNode(Node $node, Environment $env): Node
8183 }
8284 }
8385
86+ if ($ node instanceof TypeHintNode) {
87+ $ env ->getTypeHintStack ()->addVariableType ($ node ->getAttribute ('name ' ), TypeFactory::createTypeFromText ($ node ->getAttribute ('type ' )));
88+ }
89+
90+ if ($ node instanceof BodyNode) {
91+ $ env ->getTypeHintStack ()->pushMinorStack ();
92+ }
93+
8494 return $ node ;
8595 }
8696
@@ -89,17 +99,19 @@ public function leaveNode(Node $node, Environment $env): ?Node
8999 $ possibleTypes = [];
90100
91101 foreach ($ this ->getPossibleTypes ($ node , $ env ) as $ possibleType ) {
92- if (!$ possibleType instanceof TypeInterface) {
102+ if (!$ possibleType instanceof TypeInterface && $ possibleType !== null ) {
93103 $ possibleType = TypeFactory::createTypeFromText ((string ) $ possibleType );
94104 }
95105
96106 $ possibleTypes [] = $ possibleType ;
97107 }
98108
99- if (\count ($ possibleTypes ) !== 1 ) {
100- $ node ->setAttribute ('typeHint ' , new UnionType ($ possibleTypes ));
101- } elseif ($ possibleTypes !== []) {
102- $ node ->setAttribute ('typeHint ' , $ possibleTypes [0 ]);
109+ if ($ possibleTypes !== []) {
110+ if (\count ($ possibleTypes ) === 1 ) {
111+ $ node ->setAttribute ('typeHint ' , $ possibleTypes [0 ]);
112+ } else {
113+ $ node ->setAttribute ('typeHint ' , new UnionType ($ possibleTypes ));
114+ }
103115 }
104116
105117 if ($ node instanceof SetNode) {
@@ -178,6 +190,10 @@ public function leaveNode(Node $node, Environment $env): ?Node
178190 }
179191 }
180192
193+ if ($ node instanceof BodyNode) {
194+ $ env ->getTypeHintStack ()->popMinorStack ();
195+ }
196+
181197 return $ node ;
182198 }
183199
@@ -236,7 +252,11 @@ private function getPossibleTypes(Node $node, Environment $env): iterable
236252 }
237253
238254 if ($ node instanceof NameExpression && !$ node instanceof AssignNameExpression) {
239- yield $ env ->getTypeHintStack ()->getVariableType ($ node ->getAttribute ('name ' ));
255+ $ result = $ env ->getTypeHintStack ()->getVariableType ($ node ->getAttribute ('name ' ));
256+
257+ if ($ result !== null ) {
258+ yield $ result ;
259+ }
240260 }
241261
242262 if ($ node instanceof TestExpression) {
@@ -266,7 +286,11 @@ private function getPossibleTypes(Node $node, Environment $env): iterable
266286 continue ;
267287 }
268288
269- yield $ innerNode ->getAttribute ('typeHint ' );
289+ $ typeHint = $ innerNode ->getAttribute ('typeHint ' );
290+
291+ if ($ typeHint !== null ) {
292+ yield $ typeHint ;
293+ }
270294 }
271295 }
272296 }
0 commit comments