Skip to content

Check written case of single-part class names imported with use statements - #6271

Merged
ondrejmirtes merged 2 commits into
phpstan:2.2.xfrom
janedbal:class-name-case-with-use-statements
Aug 26, 2026
Merged

Check written case of single-part class names imported with use statements#6271
ondrejmirtes merged 2 commits into
phpstan:2.2.xfrom
janedbal:class-name-case-with-use-statements

Conversation

@janedbal

@janedbal janedbal commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

NameResolver replaces a single-part imported name with the use statement's spelling. The written case survives only in the originalName attribute. ClassCaseSensitivityCheck now reconstructs the written name from that attribute.

Because every affected rule goes through this check, one change fixes the case check for attributes, new, ::class, instanceof, extends, implements, trait use and catch. Multi-part, fully qualified and relative names keep their written case in the resolved name, so the reconstruction applies only to single-part unqualified names. The existing UseAliasVisitor skip keeps explicit use ... as aliases exempt (phpstan/phpstan#14205 stays fixed).

FunctionDefinitionCheck now shares the same reconstruction logic instead of its own copy. This also fixes its old splice logic, which produced non-existent names like App\S\FOO for aliased namespace prefixes and silently skipped the check.

Closes phpstan/phpstan#12827


Integration-test triage: the new nameCase errors in doctrine/dbal, neos/flow, drupal and efabrica/phpstan-latte are true positives (e.g. dbal imports SQLitePlatform and writes extends SqlitePlatform; neos imports MySQLPlatform and writes instanceof MySqlPlatform). The rector, larastan, phpstan-laravel and phpstan-doctrine failures come from unrelated 2.2.x changes (toMutatingScope() deprecation, model property message), and the e2e/bug-11826 job already fails on 2.2.x.

…ments

NameResolver replaces a single-part imported name with the use
statement's spelling. The written case survives only in the
originalName attribute. ClassCaseSensitivityCheck now reconstructs
the written name from that attribute. This makes the check work for
attributes, instantiation, class constants, instanceof, extends,
implements and catch. FunctionDefinitionCheck now shares the same
reconstruction logic.
@janedbal
janedbal marked this pull request as ready for review August 26, 2026 08:47
@phpstan-bot

Copy link
Copy Markdown
Collaborator

This pull request has been marked as ready for review.

@ondrejmirtes
ondrejmirtes merged commit 61f10fd into phpstan:2.2.x Aug 26, 2026
746 of 764 checks passed
@ondrejmirtes

Copy link
Copy Markdown
Member

Thank you!

@ondrejmirtes

Copy link
Copy Markdown
Member

FYI decided this causes too many errors in existing projects and it will be a bleeding edge feature: #6285 (enabled for everyone in PHPStan 3.0).

ondrejmirtes added a commit that referenced this pull request Aug 27, 2026
The written-case reconstruction from PR #6271 is now gated behind the new
checkImportedClassNameCase feature toggle, enabled in bleedingEdge.neon.
With the toggle off, ClassCaseSensitivityCheck and FunctionDefinitionCheck
behave exactly as before that PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016MGaekUJQDX9kJR9PdJtQu
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Attribute name case sensitivity not checked when present in use statement

3 participants