@@ -337,6 +337,22 @@ public function processNodes(
337337 $ nextStmts = $ this ->getNextUnreachableStatements (array_slice ($ nodes , $ i + 1 ), true );
338338 $ this ->processUnreachableStatement ($ nextStmts , $ scope , $ nodeCallback );
339339 }
340+
341+ $ this ->processPendingFibers ($ expressionResultStorage , $ nodeCallback );
342+ }
343+
344+ private function storeResult (ExpressionResultStorage $ storage , Expr $ expr , ExpressionResult $ result ): void
345+ {
346+ $ storage ->storeResult ($ expr , $ result );
347+ $ this ->processPendingFibersForRequestedExpr ($ storage , $ expr , $ result );
348+ }
349+
350+ protected function processPendingFibers (ExpressionResultStorage $ storage , callable $ nodeCallback ): void
351+ {
352+ }
353+
354+ protected function processPendingFibersForRequestedExpr (ExpressionResultStorage $ storage , Expr $ expr , ExpressionResult $ result ): void
355+ {
340356 }
341357
342358 /**
@@ -381,14 +397,18 @@ public function processStmtNodes(
381397 StatementContext $ context ,
382398 ): StatementResult
383399 {
384- return $ this ->processStmtNodesInternal (
400+ $ storage = new ExpressionResultStorage ();
401+ $ result = $ this ->processStmtNodesInternal (
385402 $ parentNode ,
386403 $ stmts ,
387404 $ scope ,
388- new ExpressionResultStorage () ,
405+ $ storage ,
389406 $ nodeCallback ,
390407 $ context ,
391408 )->toPublic ();
409+ $ this ->processPendingFibers ($ storage , $ nodeCallback );
410+
411+ return $ result ;
392412 }
393413
394414 /**
@@ -544,7 +564,7 @@ private function processStmtNode(
544564 $ stmtScope = $ this ->processStmtVarAnnotation ($ scope , $ stmt , $ stmt ->expr , $ nodeCallback );
545565 }
546566
547- $ nodeCallback ( $ stmt , $ stmtScope );
567+ $ this -> callNodeCallback ( $ nodeCallback , $ stmt , $ stmt , $ stmtScope, $ storage , ExpressionContext:: createTopLevel () );
548568
549569 $ overridingThrowPoints = $ this ->getOverridingThrowPoints ($ stmt , $ scope );
550570
@@ -555,8 +575,8 @@ private function processStmtNode(
555575 $ alwaysTerminating = false ;
556576 $ exitPoints = [];
557577 foreach ($ stmt ->declares as $ declare ) {
558- $ nodeCallback ( $ declare , $ scope );
559- $ nodeCallback ( $ declare ->value , $ scope );
578+ $ this -> callNodeCallback ( $ nodeCallback , $ stmt , $ declare , $ scope, $ storage , ExpressionContext:: createTopLevel () );
579+ $ this -> callNodeCallback ( $ nodeCallback , $ stmt , $ declare ->value , $ scope, $ storage , ExpressionContext:: createTopLevel () );
560580 if (
561581 $ declare ->key ->name !== 'strict_types '
562582 || !($ declare ->value instanceof Node \Scalar \Int_)
@@ -2559,7 +2579,7 @@ public function processExprNode(
25592579 throw new ShouldNotHappenException (sprintf ('Expr %s on line %d has already been analysed ' , get_class ($ expr ), $ expr ->getStartLine ()));
25602580 }
25612581
2562- $ this ->callNodeCallbackWithExpression ($ nodeCallback , $ expr , $ scope , $ context );
2582+ $ this ->callNodeCallbackWithExpression ($ nodeCallback , $ stmt , $ expr , $ scope, $ storage , $ context );
25632583
25642584 if ($ expr instanceof Variable) {
25652585 $ hasYield = false ;
@@ -2620,14 +2640,14 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
26202640 }
26212641
26222642 $ result = new ExpressionResult ($ scope , $ hasYield , $ isAlwaysTerminating , $ throwPoints , $ impurePoints );
2623- $ storage ->storeResult ($ expr , $ result );
2643+ $ this ->storeResult ($ storage , $ expr , $ result );
26242644
26252645 return $ result ;
26262646 },
26272647 true ,
26282648 );
26292649 $ scope = $ result ->getScope ();
2630- $ storage ->storeResult ($ expr , $ result );
2650+ $ this ->storeResult ($ storage , $ expr , $ result );
26312651 $ hasYield = $ result ->hasYield ();
26322652 $ throwPoints = $ result ->getThrowPoints ();
26332653 $ impurePoints = $ result ->getImpurePoints ();
@@ -2666,7 +2686,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
26662686 $ result ->getThrowPoints (),
26672687 $ result ->getImpurePoints (),
26682688 );
2669- $ storage ->storeResult ($ expr , $ result );
2689+ $ this ->storeResult ($ storage , $ expr , $ result );
26702690
26712691 return $ result ;
26722692 }
@@ -2676,7 +2696,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
26762696 $ expr instanceof Expr \AssignOp \Coalesce,
26772697 );
26782698 $ scope = $ result ->getScope ();
2679- $ storage ->storeResult ($ expr , $ result );
2699+ $ this ->storeResult ($ storage , $ expr , $ result );
26802700 $ hasYield = $ result ->hasYield ();
26812701 $ throwPoints = $ result ->getThrowPoints ();
26822702 $ impurePoints = $ result ->getImpurePoints ();
@@ -3177,7 +3197,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
31773197 static fn (): MutatingScope => $ scope ->filterByTruthyValue ($ expr ),
31783198 static fn (): MutatingScope => $ scope ->filterByFalseyValue ($ expr ),
31793199 );
3180- $ storage ->storeResult ($ expr , $ result );
3200+ $ this ->storeResult ($ storage , $ expr , $ result );
31813201
31823202 return $ result ;
31833203 } elseif ($ expr instanceof StaticCall) {
@@ -3390,7 +3410,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
33903410 static fn (): MutatingScope => $ scope ->filterByTruthyValue ($ expr ),
33913411 static fn (): MutatingScope => $ scope ->filterByFalseyValue ($ expr ),
33923412 );
3393- $ storage ->storeResult ($ expr , $ result );
3413+ $ this ->storeResult ($ storage , $ expr , $ result );
33943414
33953415 return $ result ;
33963416 } elseif ($ expr instanceof StaticPropertyFetch) {
@@ -3433,7 +3453,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
34333453 [],
34343454 [],
34353455 );
3436- $ storage ->storeResult ($ expr , $ result );
3456+ $ this ->storeResult ($ storage , $ expr , $ result );
34373457
34383458 return $ result ;
34393459 } elseif ($ expr instanceof Expr \ArrowFunction) {
@@ -3445,7 +3465,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
34453465 [],
34463466 [],
34473467 );
3448- $ storage ->storeResult ($ expr , $ exprResult );
3468+ $ this ->storeResult ($ storage , $ expr , $ exprResult );
34493469 return $ exprResult ;
34503470 } elseif ($ expr instanceof ErrorSuppress) {
34513471 $ result = $ this ->processExprNode ($ stmt , $ expr ->expr , $ scope , $ storage , $ nodeCallback , $ context );
@@ -3542,7 +3562,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
35423562 $ leftMergedWithRightScope = $ leftResult ->getScope ()->mergeWith ($ rightResult ->getScope ());
35433563 }
35443564
3545- $ this ->callNodeCallbackWithExpression ($ nodeCallback , new BooleanAndNode ($ expr , $ leftResult ->getTruthyScope ()), $ scope , $ context );
3565+ $ this ->callNodeCallbackWithExpression ($ nodeCallback , $ stmt , new BooleanAndNode ($ expr , $ leftResult ->getTruthyScope ()), $ scope, $ storage , $ context );
35463566
35473567 $ result = new ExpressionResult (
35483568 $ leftMergedWithRightScope ,
@@ -3553,7 +3573,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
35533573 static fn (): MutatingScope => $ rightResult ->getScope ()->filterByTruthyValue ($ expr ),
35543574 static fn (): MutatingScope => $ leftMergedWithRightScope ->filterByFalseyValue ($ expr ),
35553575 );
3556- $ storage ->storeResult ($ expr , $ result );
3576+ $ this ->storeResult ($ storage , $ expr , $ result );
35573577 return $ result ;
35583578 } elseif ($ expr instanceof BooleanOr || $ expr instanceof BinaryOp \LogicalOr) {
35593579 $ leftResult = $ this ->processExprNode ($ stmt , $ expr ->left , $ scope , $ storage , $ nodeCallback , $ context ->enterDeep ());
@@ -3565,7 +3585,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
35653585 $ leftMergedWithRightScope = $ leftResult ->getScope ()->mergeWith ($ rightResult ->getScope ());
35663586 }
35673587
3568- $ this ->callNodeCallbackWithExpression ($ nodeCallback , new BooleanOrNode ($ expr , $ leftResult ->getFalseyScope ()), $ scope , $ context );
3588+ $ this ->callNodeCallbackWithExpression ($ nodeCallback , $ stmt , new BooleanOrNode ($ expr , $ leftResult ->getFalseyScope ()), $ scope, $ storage , $ context );
35693589
35703590 $ result = new ExpressionResult (
35713591 $ leftMergedWithRightScope ,
@@ -3576,7 +3596,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
35763596 static fn (): MutatingScope => $ leftMergedWithRightScope ->filterByTruthyValue ($ expr ),
35773597 static fn (): MutatingScope => $ rightResult ->getScope ()->filterByFalseyValue ($ expr ),
35783598 );
3579- $ storage ->storeResult ($ expr , $ result );
3599+ $ this ->storeResult ($ storage , $ expr , $ result );
35803600 return $ result ;
35813601 } elseif ($ expr instanceof Coalesce) {
35823602 $ nonNullabilityResult = $ this ->ensureNonNullability ($ scope , $ expr ->left );
@@ -4048,7 +4068,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
40484068 static fn (): MutatingScope => $ finalScope ->filterByTruthyValue ($ expr ),
40494069 static fn (): MutatingScope => $ finalScope ->filterByFalseyValue ($ expr ),
40504070 );
4051- $ storage ->storeResult ($ expr , $ result );
4071+ $ this ->storeResult ($ storage , $ expr , $ result );
40524072 return $ result ;
40534073
40544074 } elseif ($ expr instanceof Expr \Yield_) {
@@ -4403,7 +4423,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
44034423 static fn (): MutatingScope => $ scope ->filterByTruthyValue ($ expr ),
44044424 static fn (): MutatingScope => $ scope ->filterByFalseyValue ($ expr ),
44054425 );
4406- $ storage ->storeResult ($ expr , $ result );
4426+ $ this ->storeResult ($ storage , $ expr , $ result );
44074427 return $ result ;
44084428 }
44094429
@@ -4862,15 +4882,29 @@ private function getAssignedVariables(Expr $expr): array
48624882 */
48634883 private function callNodeCallbackWithExpression (
48644884 callable $ nodeCallback ,
4885+ Node \Stmt $ stmt ,
48654886 Expr $ expr ,
48664887 MutatingScope $ scope ,
4888+ ExpressionResultStorage $ storage ,
48674889 ExpressionContext $ context ,
48684890 ): void
48694891 {
48704892 if ($ context ->isDeep ()) {
48714893 $ scope = $ scope ->exitFirstLevelStatements ();
48724894 }
4873- $ nodeCallback ($ expr , $ scope );
4895+ $ this ->callNodeCallback ($ nodeCallback , $ stmt , $ expr , $ scope , $ storage , $ context );
4896+ }
4897+
4898+ protected function callNodeCallback (
4899+ callable $ nodeCallback ,
4900+ Node \Stmt $ stmt ,
4901+ Node $ node ,
4902+ MutatingScope $ scope ,
4903+ ExpressionResultStorage $ storage ,
4904+ ExpressionContext $ context ,
4905+ ): void
4906+ {
4907+ $ nodeCallback ($ node , $ scope );
48744908 }
48754909
48764910 /**
@@ -5131,7 +5165,7 @@ private function processArrowFunctionNode(
51315165 $ exprResult = $ this ->processExprNode ($ stmt , $ expr ->expr , $ arrowFunctionScope , $ storage , $ nodeCallback , ExpressionContext::createTopLevel ());
51325166
51335167 $ result = new ExpressionResult ($ scope , false , $ exprResult ->isAlwaysTerminating (), $ exprResult ->getThrowPoints (), $ exprResult ->getImpurePoints ());
5134- $ storage ->storeResult ($ expr , $ result );
5168+ $ this ->storeResult ($ storage , $ expr , $ result );
51355169
51365170 return $ result ;
51375171 }
@@ -5575,7 +5609,7 @@ private function processArgs(
55755609 }
55765610 }
55775611
5578- $ this ->callNodeCallbackWithExpression ($ nodeCallback , $ arg ->value , $ scopeToPass , $ context );
5612+ $ this ->callNodeCallbackWithExpression ($ nodeCallback , $ stmt , $ arg ->value , $ scopeToPass, $ storage , $ context );
55795613 $ closureResult = $ this ->processClosureNode ($ stmt , $ arg ->value , $ scopeToPass , $ storage , $ nodeCallback , $ context , $ parameterType ?? null );
55805614 if ($ callCallbackImmediately ) {
55815615 $ throwPoints = array_merge ($ throwPoints , array_map (static fn (InternalThrowPoint $ throwPoint ) => $ throwPoint ->isExplicit () ? InternalThrowPoint::createExplicit ($ scope , $ throwPoint ->getType (), $ arg ->value , $ throwPoint ->canContainAnyThrowable ()) : InternalThrowPoint::createImplicit ($ scope , $ arg ->value ), $ closureResult ->getThrowPoints ()));
@@ -5630,7 +5664,7 @@ private function processArgs(
56305664 }
56315665 }
56325666
5633- $ this ->callNodeCallbackWithExpression ($ nodeCallback , $ arg ->value , $ scopeToPass , $ context );
5667+ $ this ->callNodeCallbackWithExpression ($ nodeCallback , $ stmt , $ arg ->value , $ scopeToPass, $ storage , $ context );
56345668 $ arrowFunctionResult = $ this ->processArrowFunctionNode ($ stmt , $ arg ->value , $ scopeToPass , $ storage , $ nodeCallback , $ parameterType ?? null );
56355669 if ($ callCallbackImmediately ) {
56365670 $ throwPoints = array_merge ($ throwPoints , array_map (static fn (InternalThrowPoint $ throwPoint ) => $ throwPoint ->isExplicit () ? InternalThrowPoint::createExplicit ($ scope , $ throwPoint ->getType (), $ arg ->value , $ throwPoint ->canContainAnyThrowable ()) : InternalThrowPoint::createImplicit ($ scope , $ arg ->value ), $ arrowFunctionResult ->getThrowPoints ()));
0 commit comments