Skip to content

Commit d18dbc2

Browse files
committed
Revert "Even further optimize FileTypeMapper - everything is a callback at first"
This reverts commit fe36e29.
1 parent 4f884c9 commit d18dbc2

2 files changed

Lines changed: 57 additions & 32 deletions

File tree

src/Type/FileTypeMapper.php

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class FileTypeMapper
4343
private const SKIP_NODE = 1;
4444
private const POP_TYPE_MAP_STACK = 2;
4545

46-
/** @var array<string, array<string, callable(): NameScope>> */
46+
/** @var NameScope[][] */
4747
private array $memoryCache = [];
4848

4949
private int $memoryCacheCount = 0;
@@ -98,18 +98,24 @@ public function getResolvedPhpDoc(
9898
return $this->createResolvedPhpDocBlock($phpDocKey, new NameScope(null, []), $docComment, null);
9999
}
100100

101-
if (!isset($this->inProcess[$fileName][$nameScopeKey])) {
101+
$nameScopeMap = [];
102+
103+
if (!isset($this->inProcess[$fileName])) {
102104
$nameScopeMap = $this->getNameScopeMap($fileName);
103-
if (!array_key_exists($nameScopeKey, $nameScopeMap)) {
104-
return ResolvedPhpDocBlock::createEmpty();
105-
}
105+
}
106+
107+
if (isset($nameScopeMap[$nameScopeKey])) {
108+
return $this->createResolvedPhpDocBlock($phpDocKey, $nameScopeMap[$nameScopeKey], $docComment, $fileName);
109+
}
106110

107-
$this->inProcess[$fileName][$nameScopeKey] = $nameScopeMap[$nameScopeKey];
111+
if (!isset($this->inProcess[$fileName][$nameScopeKey])) { // wrong $fileName due to traits
112+
return ResolvedPhpDocBlock::createEmpty();
108113
}
109114

110115
if ($this->inProcess[$fileName][$nameScopeKey] === true) { // PHPDoc has cyclic dependency
111116
return ResolvedPhpDocBlock::createEmpty();
112117
}
118+
113119
if (is_callable($this->inProcess[$fileName][$nameScopeKey])) {
114120
$resolveCallback = $this->inProcess[$fileName][$nameScopeKey];
115121
$this->inProcess[$fileName][$nameScopeKey] = true;
@@ -159,13 +165,12 @@ private function createResolvedPhpDocBlock(string $phpDocKey, NameScope $nameSco
159165
}
160166

161167
/**
162-
* @return array<string, callable(): NameScope>
168+
* @return NameScope[]
163169
*/
164170
private function getNameScopeMap(string $fileName): array
165171
{
166172
if (!isset($this->memoryCache[$fileName])) {
167-
$phpDocNodeMap = $this->createPhpDocNodeMap($fileName, null, $fileName, [], $fileName);
168-
$map = $this->createNameScopeMap($fileName, null, null, [], $fileName, $phpDocNodeMap);
173+
$map = $this->createResolvedPhpDocMap($fileName);
169174
if ($this->memoryCacheCount >= 2048) {
170175
$this->memoryCache = array_slice(
171176
$this->memoryCache,
@@ -183,6 +188,31 @@ private function getNameScopeMap(string $fileName): array
183188
return $this->memoryCache[$fileName];
184189
}
185190

191+
/**
192+
* @return NameScope[]
193+
*/
194+
private function createResolvedPhpDocMap(string $fileName): array
195+
{
196+
$phpDocNodeMap = $this->createPhpDocNodeMap($fileName, null, $fileName, [], $fileName);
197+
$nameScopeMap = $this->createNameScopeMap($fileName, null, null, [], $fileName, $phpDocNodeMap);
198+
$resolvedNameScopeMap = [];
199+
200+
try {
201+
$this->inProcess[$fileName] = $nameScopeMap;
202+
203+
foreach ($nameScopeMap as $nameScopeKey => $resolveCallback) {
204+
$this->inProcess[$fileName][$nameScopeKey] = true;
205+
$this->inProcess[$fileName][$nameScopeKey] = $data = $resolveCallback();
206+
$resolvedNameScopeMap[$nameScopeKey] = $data;
207+
}
208+
209+
} finally {
210+
unset($this->inProcess[$fileName]);
211+
}
212+
213+
return $resolvedNameScopeMap;
214+
}
215+
186216
/**
187217
* @param array<string, string> $traitMethodAliases
188218
*/
@@ -352,7 +382,7 @@ static function (Node $node) use (&$namespace, &$functionStack, &$classStack): v
352382

353383
/**
354384
* @param array<string, string> $traitMethodAliases
355-
* @return array<string, callable(): NameScope>
385+
* @return (callable(): NameScope)[]
356386
*/
357387
private function createNameScopeMap(
358388
string $fileName,
@@ -369,14 +399,14 @@ private function createNameScopeMap(
369399
/** @var (callable(): TemplateTypeMap)[] $typeMapStack */
370400
$typeMapStack = [];
371401

372-
/** @var array<int, callable(): array<string, true>> $typeAliasStack */
402+
/** @var array<int, array<string, true>> $typeAliasStack */
373403
$typeAliasStack = [];
374404

375405
/** @var string[] $classStack */
376406
$classStack = [];
377407
if ($lookForTrait !== null && $traitUseClass !== null) {
378408
$classStack[] = $traitUseClass;
379-
$typeAliasStack[] = static fn () => [];
409+
$typeAliasStack[] = [];
380410
}
381411
$namespace = null;
382412

@@ -405,9 +435,9 @@ function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFoun
405435
$traitFound = true;
406436
$traitNameScopeKey = $this->getNameScopeKey($originalClassFileName, $classStack[count($classStack) - 1] ?? null, $lookForTrait, null);
407437
if ($phpDocNodeMap->has($traitNameScopeKey)) {
408-
$typeAliasStack[] = fn () => $this->getTypeAliasesMap($phpDocNodeMap->get($traitNameScopeKey));
438+
$typeAliasStack[] = $this->getTypeAliasesMap($phpDocNodeMap->get($traitNameScopeKey));
409439
} else {
410-
$typeAliasStack[] = static fn () => [];
440+
$typeAliasStack[] = [];
411441
}
412442
$functionStack[] = null;
413443
} else {
@@ -428,9 +458,9 @@ function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFoun
428458
$classStack[] = $className;
429459
$classNameScopeKey = $this->getNameScopeKey($originalClassFileName, $className, $lookForTrait, null);
430460
if ($phpDocNodeMap->has($classNameScopeKey)) {
431-
$typeAliasStack[] = fn () => $this->getTypeAliasesMap($phpDocNodeMap->get($classNameScopeKey));
461+
$typeAliasStack[] = $this->getTypeAliasesMap($phpDocNodeMap->get($classNameScopeKey));
432462
} else {
433-
$typeAliasStack[] = static fn () => [];
463+
$typeAliasStack[] = [];
434464
}
435465
$functionStack[] = null;
436466
}
@@ -450,13 +480,12 @@ function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFoun
450480

451481
if ($node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_) {
452482
if ($phpDocNodeMap->has($nameScopeKey)) {
453-
$typeMapStack[] = function () use ($namespace, $uses, $className, $lookForTrait, $functionName, $phpDocNodeMap, $nameScopeKey, $typeMapStack, $typeAliasStack, $constUses): TemplateTypeMap {
483+
$phpDocNode = $phpDocNodeMap->get($nameScopeKey);
484+
$typeMapStack[] = function () use ($namespace, $uses, $className, $lookForTrait, $functionName, $phpDocNode, $typeMapStack, $typeAliasStack, $constUses): TemplateTypeMap {
454485
$typeMapCb = $typeMapStack[count($typeMapStack) - 1] ?? null;
455486
$currentTypeMap = $typeMapCb !== null ? $typeMapCb() : null;
456-
$typeAliasesMapCb = $typeAliasStack[count($typeAliasStack) - 1] ?? null;
457-
$typeAliasesMap = $typeAliasesMapCb !== null ? $typeAliasesMapCb() : [];
487+
$typeAliasesMap = $typeAliasStack[count($typeAliasStack) - 1] ?? [];
458488
$nameScope = new NameScope($namespace, $uses, $className, $functionName, $currentTypeMap, $typeAliasesMap, false, $constUses, $lookForTrait);
459-
$phpDocNode = $phpDocNodeMap->get($nameScopeKey);
460489
$templateTags = $this->phpDocNodeResolver->resolveTemplateTags($phpDocNode, $nameScope);
461490
$templateTypeScope = $nameScope->getTemplateTypeScope();
462491
if ($templateTypeScope === null) {
@@ -476,7 +505,7 @@ function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFoun
476505
}
477506

478507
$typeMapCb = $typeMapStack[count($typeMapStack) - 1] ?? null;
479-
$typeAliasesMapCb = $typeAliasStack[count($typeAliasStack) - 1] ?? null;
508+
$typeAliasesMap = $typeAliasStack[count($typeAliasStack) - 1] ?? [];
480509

481510
if (
482511
$node instanceof Node\Stmt
@@ -498,7 +527,7 @@ function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFoun
498527
$className,
499528
$functionName,
500529
($typeMapCb !== null ? $typeMapCb() : TemplateTypeMap::createEmpty()),
501-
($typeAliasesMapCb !== null ? $typeAliasesMapCb() : []),
530+
$typeAliasesMap,
502531
false,
503532
$constUses,
504533
$lookForTrait,

tests/PHPStan/Analyser/AnalyserIntegrationTest.php

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,17 +1025,13 @@ public function testBug3865(): void
10251025
public function testBug5312(): void
10261026
{
10271027
$errors = $this->runAnalyse(__DIR__ . '/data/bug-5312.php');
1028-
$this->assertCount(5, $errors);
1029-
$this->assertSame('PHPDoc tag @template T for interface Bug5312\Updatable has invalid bound type Bug5312\T.', $errors[0]->getMessage());
1030-
$this->assertSame(8, $errors[0]->getLine());
1031-
$this->assertSame('Type Bug5312\T in generic type Bug5312\Updatable<Bug5312\T> in PHPDoc tag @template T is not subtype of template type T of Bug5312\Updatable<Bug5312\T> of interface Bug5312\Updatable.', $errors[1]->getMessage());
1032-
$this->assertSame(8, $errors[1]->getLine());
1033-
$this->assertSame('Parameter $object of method Bug5312\Updatable::update() has invalid type Bug5312\T.', $errors[2]->getMessage());
1028+
$this->assertCount(3, $errors);
1029+
$this->assertSame('Parameter $object of method Bug5312\Updatable::update() has invalid type Bug5312\T.', $errors[0]->getMessage());
1030+
$this->assertSame(13, $errors[0]->getLine());
1031+
$this->assertSame('Type Bug5312\T in generic type Bug5312\Updatable<Bug5312\T> in PHPDoc tag @param for parameter $object is not subtype of template type T of Bug5312\Updatable<Bug5312\T> of interface Bug5312\Updatable.', $errors[1]->getMessage());
1032+
$this->assertSame(13, $errors[1]->getLine());
1033+
$this->assertSame('Type Bug5312\T in generic type Bug5312\Updatable<Bug5312\T> in PHPDoc tag @param for parameter $object is not subtype of template type T of Bug5312\Updatable<Bug5312\T> of interface Bug5312\Updatable.', $errors[2]->getMessage());
10341034
$this->assertSame(13, $errors[2]->getLine());
1035-
$this->assertSame('Type Bug5312\T in generic type Bug5312\Updatable<Bug5312\T> in PHPDoc tag @param for parameter $object is not subtype of template type T of Bug5312\Updatable<Bug5312\T> of interface Bug5312\Updatable.', $errors[3]->getMessage());
1036-
$this->assertSame(13, $errors[3]->getLine());
1037-
$this->assertSame('Type Bug5312\T in generic type Bug5312\Updatable<Bug5312\T> in PHPDoc tag @param for parameter $object is not subtype of template type T of Bug5312\Updatable<Bug5312\T> of interface Bug5312\Updatable.', $errors[4]->getMessage());
1038-
$this->assertSame(13, $errors[4]->getLine());
10391035
}
10401036

10411037
public function testBug5390(): void

0 commit comments

Comments
 (0)