Skip class name case check for type hints using explicit use ... as aliases#5671
Open
phpstan-bot wants to merge 2 commits into
Open
Skip class name case check for type hints using explicit use ... as aliases#5671phpstan-bot wants to merge 2 commits into
use ... as aliases#5671phpstan-bot wants to merge 2 commits into
Conversation
… aliases - Add `UseAliasVisitor` parser visitor that tracks explicit `use ... as` aliases and sets an `isExplicitUseAlias` attribute on resolved Name nodes whose original name matches an explicit alias exactly (case-sensitively) - In `FunctionDefinitionCheck::getOriginalClassNamePairsFromTypeNode()`, skip the case sensitivity check when the Name node is marked as an explicit alias - The false positive occurred because the method reconstructed the original-case class name by combining the resolved namespace prefix with the original alias name, producing e.g. `Foo\myclass` when the alias was `myclass` for `Foo\MyClass`, which was then incorrectly flagged as a case mismatch - Verified that analogous contexts (new, instanceof, catch, extends, implements, trait use, static access, PHPDoc types) are not affected because they pass the fully-resolved class name directly to `ClassCaseSensitivityCheck`
Contributor
VincentLanglet
left a comment
There was a problem hiding this comment.
The condition
if (strtolower($originalCaseClassName) !== strtolower($resolvedName)) {
// use alias, not just a case difference
return [];
}
should not be needed anymore
The UseAliasVisitor now explicitly tracks `use ... as` aliases, making the old heuristic that compared lowercase class names unnecessary. The old check was a broad approximation; the new attribute-based approach is precise. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Collaborator
Author
|
Done. Removed the redundant |
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 class is imported with an explicit alias via
use Foo\MyClass as myclass, PHPStan incorrectly reported "Class Foo\MyClass referenced with incorrect case: Foo\myclass" on type hints using the alias. The alias name is intentionally chosen by the user and should not trigger a case sensitivity error.Changes
src/Parser/UseAliasVisitor.php— a new parser visitor that:use ... asaliases (both regular and group use statements)isExplicitUseAliasattribute when the original name matches an explicit alias case-sensitivelysrc/Rules/FunctionDefinitionCheck.phpto check theisExplicitUseAliasattribute ingetOriginalClassNamePairsFromTypeNode()and skip the case sensitivity check for explicit aliasesRoot cause
FunctionDefinitionCheck::getOriginalClassNamePairsFromTypeNode()reconstructs the "original case" class name by combining the namespace prefix from the resolved name with the original name parts. Foruse Foo\MyClass as myclass, the original namemyclasswas combined with prefixFooto produceFoo\myclass. Sincestrtolower('Foo\myclass') === strtolower('Foo\MyClass'), the existing alias detection (which only catches aliases with entirely different names) did not fire, and the name was incorrectly flagged as a case mismatch.The fix distinguishes explicit
use ... asaliases from wrong-case references by tracking which aliases were explicitly defined via theaskeyword inusestatements.Analogous cases probed
The following contexts were tested and confirmed to NOT be affected (they pass the fully-resolved class name to
ClassCaseSensitivityCheck, bypassing the problematic reconstruction logic):newexpressions (InstantiationRule)instanceofexpressions (ExistingClassInInstanceOfRule)catchclauses (CaughtExceptionExistenceRule)ClassConstantRule)AccessStaticPropertiesCheck)StaticMethodCallCheck)ExistingClassesInPropertiesRule)@param,@return)Test
Added
tests/PHPStan/Rules/Methods/data/bug-14617.phpwith a regression test covering:newexpression with explicit alias (viaInstantiationRule, verified no error)Fixes phpstan/phpstan#14617