Skip to content

Commit fd31156

Browse files
committed
MutatingScope::resolveType() - cache closure body analysis data
1 parent b41f520 commit fd31156

File tree

1 file changed

+59
-2
lines changed

1 file changed

+59
-2
lines changed

src/Analyser/MutatingScope.php

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@
148148
use function is_numeric;
149149
use function is_string;
150150
use function ltrim;
151+
use function md5;
151152
use function sprintf;
152153
use function str_starts_with;
153154
use function strlen;
@@ -702,6 +703,30 @@ private function getNodeKey(Expr $node): string
702703
return $key;
703704
}
704705

706+
private function getClosureScopeCacheKey(): string
707+
{
708+
$parts = [];
709+
foreach ($this->expressionTypes as $exprString => $expressionTypeHolder) {
710+
$parts[] = sprintf('%s::%s', $exprString, $expressionTypeHolder->getType()->describe(VerbosityLevel::cache()));
711+
}
712+
$parts[] = '---';
713+
foreach ($this->nativeExpressionTypes as $exprString => $expressionTypeHolder) {
714+
$parts[] = sprintf('%s::%s', $exprString, $expressionTypeHolder->getType()->describe(VerbosityLevel::cache()));
715+
}
716+
717+
$parts[] = sprintf(':%d', count($this->inFunctionCallsStack));
718+
foreach ($this->inFunctionCallsStack as [$method, $parameter]) {
719+
if ($parameter === null) {
720+
$parts[] = ',null';
721+
continue;
722+
}
723+
724+
$parts[] = sprintf(',%s', $parameter->getType()->describe(VerbosityLevel::cache()));
725+
}
726+
727+
return md5(implode("\n", $parts));
728+
}
729+
705730
private function resolveType(string $exprString, Expr $node): Type
706731
{
707732
foreach ($this->expressionTypeResolverExtensionRegistry->getExtensions() as $extension) {
@@ -1318,6 +1343,25 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu
13181343
$impurePoints = array_merge($arrowFunctionImpurePoints, $arrowFunctionExprResult->getImpurePoints());
13191344
$usedVariables = [];
13201345
} else {
1346+
$cachedTypes = $node->getAttribute('phpstanCachedTypes', []);
1347+
$cacheKey = $this->getClosureScopeCacheKey();
1348+
if (array_key_exists($cacheKey, $cachedTypes)) {
1349+
$cachedClosureData = $cachedTypes[$cacheKey];
1350+
1351+
return new ClosureType(
1352+
$parameters,
1353+
$cachedClosureData['returnType'],
1354+
$isVariadic,
1355+
TemplateTypeMap::createEmpty(),
1356+
TemplateTypeMap::createEmpty(),
1357+
TemplateTypeVarianceMap::createEmpty(),
1358+
[],
1359+
$cachedClosureData['throwPoints'],
1360+
$cachedClosureData['impurePoints'],
1361+
$cachedClosureData['invalidateExpressions'],
1362+
$cachedClosureData['usedVariables'],
1363+
);
1364+
}
13211365
if (self::$resolveClosureTypeDepth >= 2) {
13221366
return new ClosureType(
13231367
$parameters,
@@ -1483,6 +1527,19 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu
14831527
}
14841528
}
14851529

1530+
$throwPointsForClosureType = array_map(static fn (ThrowPoint $throwPoint) => $throwPoint->isExplicit() ? SimpleThrowPoint::createExplicit($throwPoint->getType(), $throwPoint->canContainAnyThrowable()) : SimpleThrowPoint::createImplicit(), $throwPoints);
1531+
$impurePointsForClosureType = array_map(static fn (ImpurePoint $impurePoint) => new SimpleImpurePoint($impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()), $impurePoints);
1532+
1533+
$cachedTypes = $node->getAttribute('phpstanCachedTypes', []);
1534+
$cachedTypes[$this->getClosureScopeCacheKey()] = [
1535+
'returnType' => $returnType,
1536+
'throwPoints' => $throwPointsForClosureType,
1537+
'impurePoints' => $impurePointsForClosureType,
1538+
'invalidateExpressions' => $invalidateExpressions,
1539+
'usedVariables' => $usedVariables,
1540+
];
1541+
$node->setAttribute('phpstanCachedTypes', $cachedTypes);
1542+
14861543
return new ClosureType(
14871544
$parameters,
14881545
$returnType,
@@ -1491,8 +1548,8 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu
14911548
TemplateTypeMap::createEmpty(),
14921549
TemplateTypeVarianceMap::createEmpty(),
14931550
[],
1494-
array_map(static fn (ThrowPoint $throwPoint) => $throwPoint->isExplicit() ? SimpleThrowPoint::createExplicit($throwPoint->getType(), $throwPoint->canContainAnyThrowable()) : SimpleThrowPoint::createImplicit(), $throwPoints),
1495-
array_map(static fn (ImpurePoint $impurePoint) => new SimpleImpurePoint($impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()), $impurePoints),
1551+
$throwPointsForClosureType,
1552+
$impurePointsForClosureType,
14961553
$invalidateExpressions,
14971554
$usedVariables,
14981555
);

0 commit comments

Comments
 (0)