From 605b86c2595f36ac3b82f9168c6e8c3859dfbf17 Mon Sep 17 00:00:00 2001 From: Caleb White Date: Fri, 23 Jan 2026 11:57:06 -0600 Subject: [PATCH 1/3] tests: create failing e2e test for nested traits with use --- .github/workflows/e2e-tests.yml | 4 ++++ e2e/nested-trait-use/framework/Builder.php | 5 +++++ e2e/nested-trait-use/framework/HasBuilder.php | 13 +++++++++++++ e2e/nested-trait-use/framework/Model.php | 14 ++++++++++++++ e2e/nested-trait-use/main.php | 10 ++++++++++ e2e/nested-trait-use/phpstan.neon | 8 ++++++++ e2e/nested-trait-use/src/ChildModel.php | 12 ++++++++++++ e2e/nested-trait-use/src/CustomBuilder.php | 7 +++++++ e2e/nested-trait-use/src/HasBuilder.php | 13 +++++++++++++ e2e/nested-trait-use/tmp/.gitignore | 2 ++ 10 files changed, 88 insertions(+) create mode 100644 e2e/nested-trait-use/framework/Builder.php create mode 100644 e2e/nested-trait-use/framework/HasBuilder.php create mode 100644 e2e/nested-trait-use/framework/Model.php create mode 100644 e2e/nested-trait-use/main.php create mode 100644 e2e/nested-trait-use/phpstan.neon create mode 100644 e2e/nested-trait-use/src/ChildModel.php create mode 100644 e2e/nested-trait-use/src/CustomBuilder.php create mode 100644 e2e/nested-trait-use/src/HasBuilder.php create mode 100644 e2e/nested-trait-use/tmp/.gitignore diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 46500b7d12..d3880d3a26 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -293,6 +293,10 @@ jobs: OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan") echo "$OUTPUT" ../bashunit -a contains 'Method StubFiles\Foo::doFoo() has no return type specified.' "$OUTPUT" + - script: | + cd e2e/nested-trait-use + rm -rf ./tmp/cache + ../../bin/phpstan analyze steps: - name: "Checkout" diff --git a/e2e/nested-trait-use/framework/Builder.php b/e2e/nested-trait-use/framework/Builder.php new file mode 100644 index 0000000000..b8d4025be5 --- /dev/null +++ b/e2e/nested-trait-use/framework/Builder.php @@ -0,0 +1,5 @@ + */ + protected static string $builder = Builder::class; + + public function newBuilder(): Builder + { + return new static::$builder(); + } +} diff --git a/e2e/nested-trait-use/main.php b/e2e/nested-trait-use/main.php new file mode 100644 index 0000000000..08cdc532a4 --- /dev/null +++ b/e2e/nested-trait-use/main.php @@ -0,0 +1,10 @@ +newBuilder()); +} diff --git a/e2e/nested-trait-use/phpstan.neon b/e2e/nested-trait-use/phpstan.neon new file mode 100644 index 0000000000..a4b094892f --- /dev/null +++ b/e2e/nested-trait-use/phpstan.neon @@ -0,0 +1,8 @@ +parameters: + level: 9 + tmpDir: tmp + paths: + - main.php + scanDirectories: + - src + - framework diff --git a/e2e/nested-trait-use/src/ChildModel.php b/e2e/nested-trait-use/src/ChildModel.php new file mode 100644 index 0000000000..9310f7939e --- /dev/null +++ b/e2e/nested-trait-use/src/ChildModel.php @@ -0,0 +1,12 @@ + */ + use HasBuilder; + protected static string $builder = CustomBuilder::class; +} diff --git a/e2e/nested-trait-use/src/CustomBuilder.php b/e2e/nested-trait-use/src/CustomBuilder.php new file mode 100644 index 0000000000..a2a93aecd9 --- /dev/null +++ b/e2e/nested-trait-use/src/CustomBuilder.php @@ -0,0 +1,7 @@ + */ + use BaseHasBuilder; +} diff --git a/e2e/nested-trait-use/tmp/.gitignore b/e2e/nested-trait-use/tmp/.gitignore new file mode 100644 index 0000000000..d6b7ef32c8 --- /dev/null +++ b/e2e/nested-trait-use/tmp/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore From 93ea1f2ea3a591749c8eb06cf819cd6d690af6ba Mon Sep 17 00:00:00 2001 From: Caleb White Date: Fri, 23 Jan 2026 11:57:06 -0600 Subject: [PATCH 2/3] fix: use original class file name to get trait data --- src/Type/FileTypeMapper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Type/FileTypeMapper.php b/src/Type/FileTypeMapper.php index f867d9cc15..2c281f58ca 100644 --- a/src/Type/FileTypeMapper.php +++ b/src/Type/FileTypeMapper.php @@ -329,7 +329,7 @@ private function getNameScopeMap(string $fileName): array { if (!isset($this->memoryCache[$fileName])) { $cacheKey = sprintf('ftm-%s', $fileName); - $variableCacheKey = sprintf('v3-%s', ComposerHelper::getPhpDocParserVersion()); + $variableCacheKey = sprintf('v4-%s', ComposerHelper::getPhpDocParserVersion()); $cached = $this->loadCachedPhpDocNodeMap($cacheKey, $variableCacheKey); if ($cached === null) { [$nameScopeMap, $files] = $this->createPhpDocNodeMap($fileName, null, null, [], $fileName); @@ -642,7 +642,7 @@ function (Node $node) use ($fileName, $lookForTrait, &$traitFound, $traitMethodA $traitMethodAliases[$traitName] ?? [], $originalClassFileName, ); - $nameScopeMap = array_merge($nameScopeMap, array_map(static fn ($originalNameScope) => $originalNameScope->getTraitData() === null ? $originalNameScope->withTraitData($fileName, $className, $traitName, $lookForTrait, $docComment) : $originalNameScope, $traitNameScopeMap)); + $nameScopeMap = array_merge($nameScopeMap, array_map(static fn ($originalNameScope) => $originalNameScope->getTraitData() === null ? $originalNameScope->withTraitData($originalClassFileName, $className, $traitName, $lookForTrait, $docComment) : $originalNameScope, $traitNameScopeMap)); $files = array_merge($files, $traitFiles); } } From c25717c80a7c05acf02e1c72fd94b43216bc7543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Mirtes?= Date: Fri, 23 Jan 2026 23:09:52 +0100 Subject: [PATCH 3/3] Update e2e-tests.yml --- .github/workflows/e2e-tests.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index d3880d3a26..80abad6e94 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -295,7 +295,6 @@ jobs: ../bashunit -a contains 'Method StubFiles\Foo::doFoo() has no return type specified.' "$OUTPUT" - script: | cd e2e/nested-trait-use - rm -rf ./tmp/cache ../../bin/phpstan analyze steps: