From 11176c76aac5b7e15cc16d32e88ecc31cf6de64b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 6 Jan 2022 10:54:54 +0100 Subject: [PATCH] Fix looking for PHPDocs in trait in anonymous class in trait --- src/Type/FileTypeMapper.php | 13 ++++++++--- .../Analyser/AnalyserIntegrationTest.php | 17 ++++++++++++-- .../data/bug-6253-app-scope-trait.php | 22 +++++++++++++++++++ .../data/bug-6253-collection-trait.php | 13 +++++++++++ tests/PHPStan/Analyser/data/bug-6253.php | 8 +++++++ 5 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 tests/PHPStan/Analyser/data/bug-6253-app-scope-trait.php create mode 100644 tests/PHPStan/Analyser/data/bug-6253-collection-trait.php create mode 100644 tests/PHPStan/Analyser/data/bug-6253.php diff --git a/src/Type/FileTypeMapper.php b/src/Type/FileTypeMapper.php index e46d8ce163..8001b04757 100644 --- a/src/Type/FileTypeMapper.php +++ b/src/Type/FileTypeMapper.php @@ -205,7 +205,7 @@ private function resolvePhpDocStringToDocNode(string $phpDocString): PhpDocNode private function getNameScopeMap(string $fileName): array { if (!isset($this->memoryCache[$fileName])) { - $cacheKey = sprintf('%s-phpdocstring-v15-shebang', $fileName); + $cacheKey = sprintf('%s-phpdocstring-v16-look-for-trait', $fileName); $variableCacheKey = implode(',', array_map(static fn (array $file): string => sprintf('%s-%d', $file['filename'], $file['modifiedTime']), $this->getCachedDependentFilesWithTimestamps($fileName))); $map = $this->cache->load($cacheKey, $variableCacheKey); @@ -284,20 +284,24 @@ private function createNameScopeMap( } $namespace = null; + $traitFound = false; + /** @var array $functionStack */ $functionStack = []; $uses = []; $this->processNodes( $this->phpParser->parseFile($fileName), - function (Node $node) use ($fileName, $lookForTrait, $traitMethodAliases, $originalClassFileName, &$nameScopeMap, &$classStack, &$typeAliasStack, &$namespace, &$functionStack, &$uses, &$typeMapStack): ?int { + function (Node $node) use ($fileName, $lookForTrait, &$traitFound, $traitMethodAliases, $originalClassFileName, &$nameScopeMap, &$classStack, &$typeAliasStack, &$namespace, &$functionStack, &$uses, &$typeMapStack): ?int { if ($node instanceof Node\Stmt\ClassLike) { - if ($lookForTrait !== null) { + if ($lookForTrait !== null && !$traitFound) { if (!$node instanceof Node\Stmt\Trait_) { return self::SKIP_NODE; } if ((string) $node->namespacedName !== $lookForTrait) { return self::SKIP_NODE; } + + $traitFound = true; } else { if ($node->name === null) { if (!$node instanceof Node\Stmt\Class_) { @@ -308,6 +312,9 @@ function (Node $node) use ($fileName, $lookForTrait, $traitMethodAliases, $origi } elseif ((bool) $node->getAttribute('anonymousClass', false)) { $className = $node->name->name; } else { + if ($traitFound) { + return self::SKIP_NODE; + } $className = ltrim(sprintf('%s\\%s', $namespace, $node->name->name), '\\'); } $classStack[] = $className; diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index 9d11389b7e..6521824c22 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -500,10 +500,23 @@ public function testBug6300(): void $this->assertSame(24, $errors[1]->getLine()); } + public function testBug6253(): void + { + $errors = $this->runAnalyse( + __DIR__ . '/data/bug-6253.php', + [ + __DIR__ . '/data/bug-6253.php', + __DIR__ . '/data/bug-6253-app-scope-trait.php', + __DIR__ . '/data/bug-6253-collection-trait.php', + ], + ); + $this->assertNoErrors($errors); + } + /** * @return Error[] */ - private function runAnalyse(string $file): array + private function runAnalyse(string $file, ?array $allAnalysedFiles = null): array { $file = $this->getFileHelper()->normalizePath($file); /** @var Analyser $analyser */ @@ -511,7 +524,7 @@ private function runAnalyse(string $file): array /** @var FileHelper $fileHelper */ $fileHelper = self::getContainer()->getByType(FileHelper::class); /** @var Error[] $errors */ - $errors = $analyser->analyse([$file])->getErrors(); + $errors = $analyser->analyse([$file], null, null, true, $allAnalysedFiles)->getErrors(); foreach ($errors as $error) { $this->assertSame($fileHelper->normalizePath($file), $error->getFilePath()); } diff --git a/tests/PHPStan/Analyser/data/bug-6253-app-scope-trait.php b/tests/PHPStan/Analyser/data/bug-6253-app-scope-trait.php new file mode 100644 index 0000000000..d1231361e3 --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-6253-app-scope-trait.php @@ -0,0 +1,22 @@ +