Skip to content

Commit f529eee

Browse files
committed
fix with detect nested trait
1 parent 85fa3e9 commit f529eee

4 files changed

Lines changed: 25 additions & 9 deletions

File tree

src/Type/FileTypeMapper.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,9 +394,10 @@ private function loadCachedPhpDocNodeMap(string $cacheKey, string $variableCache
394394

395395
/**
396396
* @param array<string, string> $traitMethodAliases
397+
* @param array<string, true> $activeTraitResolutions
397398
* @return array{array<string, IntermediaryNameScope>, list<string>}
398399
*/
399-
private function createPhpDocNodeMap(string $fileName, ?string $lookForTrait, ?string $traitUseClass, array $traitMethodAliases, string $originalClassFileName): array
400+
private function createPhpDocNodeMap(string $fileName, ?string $lookForTrait, ?string $traitUseClass, array $traitMethodAliases, string $originalClassFileName, array $activeTraitResolutions = []): array
400401
{
401402
/** @var array<string, IntermediaryNameScope> $nameScopeMap */
402403
$nameScopeMap = [];
@@ -425,7 +426,7 @@ private function createPhpDocNodeMap(string $fileName, ?string $lookForTrait, ?s
425426
$constUses = [];
426427
$this->processNodes(
427428
$this->phpParser->parseFile($fileName),
428-
function (Node $node) use ($fileName, $lookForTrait, &$traitFound, $traitMethodAliases, $originalClassFileName, &$nameScopeMap, &$typeMapStack, &$typeAliasStack, &$classStack, &$namespace, &$functionStack, &$uses, &$constUses, &$files): ?int {
429+
function (Node $node) use ($fileName, $lookForTrait, &$traitFound, $traitMethodAliases, $originalClassFileName, $activeTraitResolutions, &$nameScopeMap, &$typeMapStack, &$typeAliasStack, &$classStack, &$namespace, &$functionStack, &$uses, &$constUses, &$files): ?int {
429430
if ($node instanceof Node\Stmt\ClassLike) {
430431
if ($traitFound && $fileName === $originalClassFileName) {
431432
return self::SKIP_NODE;
@@ -635,12 +636,21 @@ function (Node $node) use ($fileName, $lookForTrait, &$traitFound, $traitMethodA
635636
throw new ShouldNotHappenException();
636637
}
637638

639+
$traitResolutionKey = $this->getTraitResolutionKey($traitReflection->getFileName(), $traitName, $className, $originalClassFileName);
640+
if (isset($activeTraitResolutions[$traitResolutionKey])) {
641+
continue;
642+
}
643+
644+
$nestedActiveTraitResolutions = $activeTraitResolutions;
645+
$nestedActiveTraitResolutions[$traitResolutionKey] = true;
646+
638647
[$traitNameScopeMap, $traitFiles] = $this->createPhpDocNodeMap(
639648
$traitReflection->getFileName(),
640649
$traitName,
641650
$className,
642651
$traitMethodAliases[$traitName] ?? [],
643652
$originalClassFileName,
653+
$nestedActiveTraitResolutions,
644654
);
645655
$nameScopeMap = array_merge($nameScopeMap, array_map(static fn ($originalNameScope) => $originalNameScope->getTraitData() === null ? $originalNameScope->withTraitData($originalClassFileName, $className, $traitName, $lookForTrait, $docComment) : $originalNameScope, $traitNameScopeMap));
646656
$files = array_merge($files, $traitFiles);
@@ -818,4 +828,9 @@ private function getPhpDocKey(string $nameScopeKey, string $docComment): string
818828
return md5(sprintf('%s-%s', $nameScopeKey, $doc->getReformattedText()));
819829
}
820830

831+
private function getTraitResolutionKey(string $fileName, string $traitName, string $className, string $originalClassFileName): string
832+
{
833+
return md5(sprintf('%s-%s-%s-%s', $fileName, $traitName, $className, $originalClassFileName));
834+
}
835+
821836
}

tests/PHPStan/Type/FileTypeMapperTest.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Type;
44

5+
use BugSelfReferencedTrait\BaseModel;
56
use DependentPhpDocs\Foo;
67
use PHPStan\PhpDoc\Tag\ReturnTag;
78
use PHPStan\ShouldNotHappenException;
@@ -217,23 +218,23 @@ public function testRecursiveTraitUsedInAnonymousClassDoesNotLoopIndefinitely():
217218
/** @var FileTypeMapper $fileTypeMapper */
218219
$fileTypeMapper = self::getContainer()->getByType(FileTypeMapper::class);
219220

220-
$realpath = realpath(__DIR__ . '/data/bug-9684/BaseModel.php');
221+
$realpath = realpath(__DIR__ . '/data/bug-self-referenced-trait/BaseModel.php');
221222
if ($realpath === false) {
222223
throw new ShouldNotHappenException();
223224
}
224225

225226
$resolved = $fileTypeMapper->getResolvedPhpDoc(
226227
$realpath,
227-
\Bug9684\BaseModel::class,
228+
BaseModel::class,
228229
null,
229230
null,
230231
'/** @method static Builder<static>|BaseModel query() */',
231232
);
232233

233234
$this->assertArrayHasKey('query', $resolved->getMethodTags());
234235
$returnTypeDescription = $resolved->getMethodTags()['query']->getReturnType()->describe(VerbosityLevel::precise());
235-
$this->assertStringContainsString('Bug9684\BaseModel', $returnTypeDescription);
236-
$this->assertStringContainsString('Bug9684\Builder<static(Bug9684\BaseModel)>', $returnTypeDescription);
236+
$this->assertStringContainsString('BugSelfReferencedTrait\BaseModel', $returnTypeDescription);
237+
$this->assertStringContainsString('BugSelfReferencedTrait\Builder<static(BugSelfReferencedTrait\BaseModel)>', $returnTypeDescription);
237238
}
238239

239240
}

tests/PHPStan/Type/data/bug-9684/BaseModel.php renamed to tests/PHPStan/Type/data/bug-self-referenced-trait/BaseModel.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?php declare(strict_types = 1);
22

3-
namespace Bug9684;
3+
namespace BugSelfReferencedTrait;
44

5-
use Bug9684\RecursiveTrait;
5+
use BugSelfReferencedTrait\RecursiveTrait;
66

77
class Model
88
{

tests/PHPStan/Type/data/bug-9684/RecursiveTrait.php renamed to tests/PHPStan/Type/data/bug-self-referenced-trait/RecursiveTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php declare(strict_types = 1);
22

3-
namespace Bug9684;
3+
namespace BugSelfReferencedTrait;
44

55
trait RecursiveTrait
66
{

0 commit comments

Comments
 (0)