Skip to content

Commit 9960c90

Browse files
committed
Handle first class callables in GNSR
1 parent 018e5dd commit 9960c90

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

src/Analyser/Generator/GeneratorNodeScopeResolver.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,24 @@
66
use Generator;
77
use PhpParser\Node;
88
use PhpParser\Node\Expr;
9+
use PhpParser\Node\Expr\FuncCall;
10+
use PhpParser\Node\Expr\MethodCall;
11+
use PhpParser\Node\Expr\New_;
12+
use PhpParser\Node\Expr\StaticCall;
913
use PhpParser\Node\Stmt;
14+
use PhpParser\Node\Stmt\Class_;
1015
use PHPStan\Analyser\ExpressionContext;
1116
use PHPStan\Analyser\Generator\NodeHandler\AttrGroupsHandler;
1217
use PHPStan\Analyser\Generator\NodeHandler\StmtsHandler;
1318
use PHPStan\Analyser\Scope;
1419
use PHPStan\Analyser\StatementContext;
1520
use PHPStan\DependencyInjection\Container;
1621
use PHPStan\NeverException;
22+
use PHPStan\Node\FunctionCallableNode;
23+
use PHPStan\Node\InstantiationCallableNode;
24+
use PHPStan\Node\MethodCallableNode;
1725
use PHPStan\Node\Printer\ExprPrinter;
26+
use PHPStan\Node\StaticMethodCallableNode;
1827
use PHPStan\ShouldNotHappenException;
1928
use Throwable;
2029
use function array_merge;
@@ -422,6 +431,25 @@ private function analyseExpr(ExprAnalysisResultStorage $storage, Stmt $stmt, Exp
422431
throw new ShouldNotHappenException(sprintf('Expr %s on line %d has already been analysed', $this->exprPrinter->printExpr($expr), $expr->getStartLine()));
423432
}
424433

434+
if ($expr instanceof Expr\CallLike && $expr->isFirstClassCallable()) {
435+
if ($expr instanceof FuncCall) {
436+
$newExpr = new FunctionCallableNode($expr->name, $expr);
437+
} elseif ($expr instanceof MethodCall) {
438+
$newExpr = new MethodCallableNode($expr->var, $expr->name, $expr);
439+
} elseif ($expr instanceof StaticCall) {
440+
$newExpr = new StaticMethodCallableNode($expr->class, $expr->name, $expr);
441+
} elseif ($expr instanceof New_ && !$expr->class instanceof Class_) {
442+
$newExpr = new InstantiationCallableNode($expr->class, $expr);
443+
} else {
444+
throw new ShouldNotHappenException();
445+
}
446+
447+
$exprGen = $this->analyseExpr($storage, $stmt, $newExpr, $scope, $context, $alternativeNodeCallback);
448+
yield from $exprGen;
449+
450+
return $exprGen->getReturn();
451+
}
452+
425453
yield new NodeCallbackRequest($expr, $context->isDeep() ? $scope->exitFirstLevelStatements() : $scope, $alternativeNodeCallback);
426454

427455
/**

0 commit comments

Comments
 (0)