@@ -261,6 +261,7 @@ public function __construct(
261
261
private readonly bool $ treatPhpDocTypesAsCertain ,
262
262
private readonly bool $ detectDeadTypeInMultiCatch ,
263
263
private readonly bool $ paramOutType ,
264
+ private readonly bool $ preciseMissingReturn ,
264
265
)
265
266
{
266
267
$ earlyTerminatingMethodNames = [];
@@ -360,18 +361,38 @@ public function processStmtNodes(
360
361
if ($ shouldCheckLastStatement && $ isLast ) {
361
362
/** @var Node\Stmt\Function_|Node\Stmt\ClassMethod|Expr\Closure $parentNode */
362
363
$ parentNode = $ parentNode ;
363
- $ nodeCallback (new ExecutionEndNode (
364
- $ stmt ,
365
- new StatementResult (
366
- $ scope ,
367
- $ hasYield ,
368
- $ statementResult ->isAlwaysTerminating (),
369
- $ statementResult ->getExitPoints (),
370
- $ statementResult ->getThrowPoints (),
371
- $ statementResult ->getImpurePoints (),
372
- ),
373
- $ parentNode ->returnType !== null ,
374
- ), $ scope );
364
+
365
+ $ endStatements = $ statementResult ->getEndStatements ();
366
+ if ($ this ->preciseMissingReturn && count ($ endStatements ) > 0 ) {
367
+ foreach ($ endStatements as $ endStatement ) {
368
+ $ endStatementResult = $ endStatement ->getResult ();
369
+ $ nodeCallback (new ExecutionEndNode (
370
+ $ endStatement ->getStatement (),
371
+ new StatementResult (
372
+ $ endStatementResult ->getScope (),
373
+ $ hasYield ,
374
+ $ endStatementResult ->isAlwaysTerminating (),
375
+ $ endStatementResult ->getExitPoints (),
376
+ $ endStatementResult ->getThrowPoints (),
377
+ $ endStatementResult ->getImpurePoints (),
378
+ ),
379
+ $ parentNode ->returnType !== null ,
380
+ ), $ endStatementResult ->getScope ());
381
+ }
382
+ } else {
383
+ $ nodeCallback (new ExecutionEndNode (
384
+ $ stmt ,
385
+ new StatementResult (
386
+ $ scope ,
387
+ $ hasYield ,
388
+ $ statementResult ->isAlwaysTerminating (),
389
+ $ statementResult ->getExitPoints (),
390
+ $ statementResult ->getThrowPoints (),
391
+ $ statementResult ->getImpurePoints (),
392
+ ),
393
+ $ parentNode ->returnType !== null ,
394
+ ), $ scope );
395
+ }
375
396
}
376
397
377
398
$ exitPoints = array_merge ($ exitPoints , $ statementResult ->getExitPoints ());
@@ -915,6 +936,7 @@ private function processStmtNode(
915
936
$ exitPoints = [];
916
937
$ throwPoints = $ overridingThrowPoints ?? $ condResult ->getThrowPoints ();
917
938
$ impurePoints = $ condResult ->getImpurePoints ();
939
+ $ endStatements = [];
918
940
$ finalScope = null ;
919
941
$ alwaysTerminating = true ;
920
942
$ hasYield = $ condResult ->hasYield ();
@@ -928,6 +950,13 @@ private function processStmtNode(
928
950
$ branchScope = $ branchScopeStatementResult ->getScope ();
929
951
$ finalScope = $ branchScopeStatementResult ->isAlwaysTerminating () ? null : $ branchScope ;
930
952
$ alwaysTerminating = $ branchScopeStatementResult ->isAlwaysTerminating ();
953
+ if (count ($ branchScopeStatementResult ->getEndStatements ()) > 0 ) {
954
+ $ endStatements = array_merge ($ endStatements , $ branchScopeStatementResult ->getEndStatements ());
955
+ } elseif (count ($ stmt ->stmts ) > 0 ) {
956
+ $ endStatements [] = new EndStatementResult ($ stmt ->stmts [count ($ stmt ->stmts ) - 1 ], $ branchScopeStatementResult );
957
+ } else {
958
+ $ endStatements [] = new EndStatementResult ($ stmt , $ branchScopeStatementResult );
959
+ }
931
960
$ hasYield = $ branchScopeStatementResult ->hasYield () || $ hasYield ;
932
961
}
933
962
@@ -960,6 +989,13 @@ private function processStmtNode(
960
989
$ branchScope = $ branchScopeStatementResult ->getScope ();
961
990
$ finalScope = $ branchScopeStatementResult ->isAlwaysTerminating () ? $ finalScope : $ branchScope ->mergeWith ($ finalScope );
962
991
$ alwaysTerminating = $ alwaysTerminating && $ branchScopeStatementResult ->isAlwaysTerminating ();
992
+ if (count ($ branchScopeStatementResult ->getEndStatements ()) > 0 ) {
993
+ $ endStatements = array_merge ($ endStatements , $ branchScopeStatementResult ->getEndStatements ());
994
+ } elseif (count ($ elseif ->stmts ) > 0 ) {
995
+ $ endStatements [] = new EndStatementResult ($ elseif ->stmts [count ($ elseif ->stmts ) - 1 ], $ branchScopeStatementResult );
996
+ } else {
997
+ $ endStatements [] = new EndStatementResult ($ elseif , $ branchScopeStatementResult );
998
+ }
963
999
$ hasYield = $ hasYield || $ branchScopeStatementResult ->hasYield ();
964
1000
}
965
1001
@@ -989,6 +1025,13 @@ private function processStmtNode(
989
1025
$ branchScope = $ branchScopeStatementResult ->getScope ();
990
1026
$ finalScope = $ branchScopeStatementResult ->isAlwaysTerminating () ? $ finalScope : $ branchScope ->mergeWith ($ finalScope );
991
1027
$ alwaysTerminating = $ alwaysTerminating && $ branchScopeStatementResult ->isAlwaysTerminating ();
1028
+ if (count ($ branchScopeStatementResult ->getEndStatements ()) > 0 ) {
1029
+ $ endStatements = array_merge ($ endStatements , $ branchScopeStatementResult ->getEndStatements ());
1030
+ } elseif (count ($ stmt ->else ->stmts ) > 0 ) {
1031
+ $ endStatements [] = new EndStatementResult ($ stmt ->else ->stmts [count ($ stmt ->else ->stmts ) - 1 ], $ branchScopeStatementResult );
1032
+ } else {
1033
+ $ endStatements [] = new EndStatementResult ($ stmt ->else , $ branchScopeStatementResult );
1034
+ }
992
1035
$ hasYield = $ hasYield || $ branchScopeStatementResult ->hasYield ();
993
1036
}
994
1037
}
@@ -997,7 +1040,11 @@ private function processStmtNode(
997
1040
$ finalScope = $ scope ;
998
1041
}
999
1042
1000
- return new StatementResult ($ finalScope , $ hasYield , $ alwaysTerminating , $ exitPoints , $ throwPoints , $ impurePoints );
1043
+ if ($ stmt ->else === null && !$ ifAlwaysTrue && !$ lastElseIfConditionIsTrue ) {
1044
+ $ endStatements [] = new EndStatementResult ($ stmt , new StatementResult ($ finalScope , $ hasYield , $ alwaysTerminating , $ exitPoints , $ throwPoints , $ impurePoints ));
1045
+ }
1046
+
1047
+ return new StatementResult ($ finalScope , $ hasYield , $ alwaysTerminating , $ exitPoints , $ throwPoints , $ impurePoints , $ endStatements );
1001
1048
} elseif ($ stmt instanceof Node \Stmt \TraitUse) {
1002
1049
$ hasYield = false ;
1003
1050
$ throwPoints = [];
0 commit comments