Skip to content

Commit d33a581

Browse files
authored
Fix trait detection recursion for anonymous classes
1 parent 430620c commit d33a581

File tree

4 files changed

+44
-5
lines changed

4 files changed

+44
-5
lines changed

src/Type/FileTypeMapper.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PHPStan\BetterReflection\Util\GetLastDocComment;
1010
use PHPStan\Broker\AnonymousClassNameHelper;
1111
use PHPStan\Cache\Cache;
12+
use PHPStan\File\FileHelper;
1213
use PHPStan\Parser\Parser;
1314
use PHPStan\Php\PhpVersion;
1415
use PHPStan\PhpDoc\PhpDocNodeResolver;
@@ -74,6 +75,7 @@ public function __construct(
7475
private Cache $cache,
7576
private AnonymousClassNameHelper $anonymousClassNameHelper,
7677
private PhpVersion $phpVersion,
78+
private FileHelper $fileHelper,
7779
)
7880
{
7981
}
@@ -87,6 +89,8 @@ public function getResolvedPhpDoc(
8789
string $docComment,
8890
): ResolvedPhpDocBlock
8991
{
92+
$fileName = $this->fileHelper->normalizePath($fileName);
93+
9094
if ($className === null && $traitName !== null) {
9195
throw new ShouldNotHappenException();
9296
}
@@ -189,7 +193,7 @@ private function resolvePhpDocStringToDocNode(string $phpDocString): PhpDocNode
189193
private function getNameScopeMap(string $fileName): array
190194
{
191195
if (!isset($this->memoryCache[$fileName])) {
192-
$cacheKey = sprintf('%s-phpdocstring-v18-filter-ast', $fileName);
196+
$cacheKey = sprintf('%s-phpdocstring-v19-trait-detection-recursion', $fileName);
193197
$variableCacheKey = sprintf('%s-%s', implode(',', array_map(static fn (array $file): string => sprintf('%s-%d', $file['filename'], $file['modifiedTime']), $this->getCachedDependentFilesWithTimestamps($fileName))), $this->phpVersion->getVersionString());
194198
$map = $this->cache->load($cacheKey, $variableCacheKey);
195199

@@ -277,6 +281,10 @@ private function createNameScopeMap(
277281
$this->phpParser->parseFile($fileName),
278282
function (Node $node) use ($fileName, $lookForTrait, &$traitFound, $traitMethodAliases, $originalClassFileName, &$nameScopeMap, &$classStack, &$typeAliasStack, &$namespace, &$functionStack, &$uses, &$typeMapStack): ?int {
279283
if ($node instanceof Node\Stmt\ClassLike) {
284+
if ($traitFound && $fileName === $originalClassFileName) {
285+
return self::SKIP_NODE;
286+
}
287+
280288
if ($lookForTrait !== null && !$traitFound) {
281289
if (!$node instanceof Node\Stmt\Trait_) {
282290
return self::SKIP_NODE;
@@ -296,9 +304,6 @@ function (Node $node) use ($fileName, $lookForTrait, &$traitFound, $traitMethodA
296304
} elseif ((bool) $node->getAttribute('anonymousClass', false)) {
297305
$className = $node->name->name;
298306
} else {
299-
if ($traitFound) {
300-
return self::SKIP_NODE;
301-
}
302307
$className = ltrim(sprintf('%s\\%s', $namespace, $node->name->name), '\\');
303308
}
304309
$classStack[] = $className;

tests/PHPStan/Analyser/AnalyserIntegrationTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,16 @@ public function testBug6253(): void
513513
$this->assertNoErrors($errors);
514514
}
515515

516+
public function testBug6442(): void
517+
{
518+
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6442.php');
519+
$this->assertCount(2, $errors);
520+
$this->assertSame('Dumped type: \'Bug6442\\\A\'', $errors[0]->getMessage());
521+
$this->assertSame(9, $errors[0]->getLine());
522+
$this->assertSame('Dumped type: \'Bug6442\\\B\'', $errors[1]->getMessage());
523+
$this->assertSame(9, $errors[1]->getLine());
524+
}
525+
516526
/**
517527
* @param string[]|null $allAnalysedFiles
518528
* @return Error[]
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Bug6442;
4+
5+
trait T
6+
{
7+
public function x(): void
8+
{
9+
\PHPStan\dumpType(parent::class);
10+
}
11+
}
12+
13+
class A {}
14+
15+
class B extends A
16+
{
17+
use T;
18+
}
19+
20+
new class() extends B
21+
{
22+
use T;
23+
};
24+

tests/PHPStan/Broker/BrokerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ protected function setUp(): void
4444
$setterReflectionProviderProvider,
4545
$classReflectionExtensionRegistryProvider,
4646
$this->createMock(FunctionReflectionFactory::class),
47-
new FileTypeMapper($setterReflectionProviderProvider, $this->getParser(), $phpDocStringResolver, $phpDocNodeResolver, $this->createMock(Cache::class), $anonymousClassNameHelper, self::getContainer()->getByType(PhpVersion::class)),
47+
new FileTypeMapper($setterReflectionProviderProvider, $this->getParser(), $phpDocStringResolver, $phpDocNodeResolver, $this->createMock(Cache::class), $anonymousClassNameHelper, self::getContainer()->getByType(PhpVersion::class), self::getContainer()->getByType(FileHelper::class)),
4848
self::getContainer()->getByType(PhpDocInheritanceResolver::class),
4949
self::getContainer()->getByType(PhpVersion::class),
5050
self::getContainer()->getByType(NativeFunctionReflectionProvider::class),

0 commit comments

Comments
 (0)