Fix #12639: phpstan ignoring use paths in trait context#4966
Open
phpstan-bot wants to merge 1 commit into2.1.xfrom
Open
Fix #12639: phpstan ignoring use paths in trait context#4966phpstan-bot wants to merge 1 commit into2.1.xfrom
phpstan-bot wants to merge 1 commit into2.1.xfrom
Conversation
…eclarations - When a trait file had a statement (e.g. `if/die`) before `use` declarations, FileTypeMapper::createPhpDocNodeMap() would create a premature name scope entry with empty `$uses` for non-trait statements during recursive trait processing, preventing the correct entry from being created later - Added condition to skip name scope map entries for statements before the trait is found during recursive trait file processing ($lookForTrait) - New regression tests in FileTypeMapperTest and NSRT for bug #12639 Closes phpstan/phpstan#12639
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a trait file contained a statement (e.g.
if (...) die(...)) beforeuseimport declarations, PHPStan would ignore thoseuseimports when resolving PHPDoc types on trait properties. This caused generic types likeObjectRefT<Account>to resolveAccountagainst the consuming class's namespace instead of the trait's namespace, producing incorrect types.Changes
&& ($lookForTrait === null || $traitFound)toFileTypeMapper::createPhpDocNodeMap()to skip creating name scope map entries for statements that appear before the target trait during recursive trait file processing (src/Type/FileTypeMapper.php)testBug12639TraitPropertyPhpDocResolutionintests/PHPStan/Type/FileTypeMapperTest.phptests/PHPStan/Type/data/bug-12639-trait.phpandtests/PHPStan/Type/data/bug-12639-class.php(separate-file trait with a statement beforeusedeclarations)tests/PHPStan/Analyser/nsrt/bug-12639.phpfor cross-namespace trait PHPDoc type resolutionRoot cause
In
FileTypeMapper::createPhpDocNodeMap(), when recursively processing a trait file ($lookForTrait !== null), the method traverses the entire AST. Any non-use/non-namespace statement (likeif/die) encountered before theusedeclarations triggers creation of a$nameScopeMapentry with an empty$usesarray. Because of the!array_key_exists($nameScopeKey, $nameScopeMap)guard, this premature entry prevents the correct entry (with populated$usesfrom the actual import declarations) from being created when the trait's properties are later processed.The fix adds a check so that when processing a trait file recursively, name scope map entries are only created after the target trait has been found (
$traitFound), skipping statements that precede it.Test
The regression test in
FileTypeMapperTestcreates a trait file (bug-12639-trait.php) that has anif (true) {}statement beforeusedeclarations, and a class file (bug-12639-class.php) in a different namespace that uses the trait. The test callsFileTypeMapper::getResolvedPhpDoc()the same wayPhpClassReflectionExtensiondoes for trait properties, and verifies thatObjectRefT<Account>resolves toBug12639Separate\Types\ObjectRefT<Bug12639Separate\Accounts\Account>(from the trait'suseimports) rather than falling back to the consuming class's namespace.An additional NSRT test verifies trait PHPDoc type resolution across namespaces in a single-file scenario.
Fixes phpstan/phpstan#12639