[3.0] Checks that class names are written as ::class resolvers - #9666
Open
albertlast wants to merge 1 commit into
Open
[3.0] Checks that class names are written as ::class resolvers#9666albertlast wants to merge 1 commit into
albertlast wants to merge 1 commit into
Conversation
A class name in a string is not a name PHP ever checks, and nothing in CI looks inside a string, so the next one written that way would sit there until somebody read the error log of a forum they do not own. This walks the tree and fails on any string that spells out a class name. Four names have to stay strings: a namespace prefix, the alias class_alias() is about to create, and two Unicode helper functions. Each is listed with its reason, and a second test fails if an entry names something no longer there. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
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.
Description
#9665 rewrote every class name SMF wrote down as a string into a
::classresolver. This isthe test that keeps it that way.
Nothing else can.
phplintsees a valid string,php-cs-fixerdoes not read inside strings,and PHP itself never resolves the name until the moment it is used — which for a background
task is a cron run on somebody else's forum, where
TaskRunner::execute()logs the class itcould not find, drops the row from the queue and carries on. So the next one to be written
would sit there exactly as
'SMF\Tasks\FetchSMfiles'did, until somebody read the error logof a forum they do not own.
The test walks
Sources/,Themes/and the five entry points, tokenises everything thatmentions
SMF\in a string at all, and fails on any string that spells out a class name:with a message saying to write it as a resolver or to add it to the list of exceptions with
a reason.
The exceptions
Four names have to stay in a string, and the list says why for each:
ActionRouterasks whether its own class sits under'SMF\Actions', which is a namespaceand never a class.
Sources/Actions/Admin/PackageManager.phpnames the aliasclass_alias()is about tocreate. Writing the name being created as a resolver would claim the alias already exists.
Punycodeprobes for two Unicode helper functions, which only some data files define.Functions have no resolver.
The list is keyed by file and by the name itself rather than by line, so moving code around
a file does not invalidate it, and a second test fails if an entry names something that is
no longer there. An allowlist that outlives its reason is how a test like this stops meaning
anything, and I would rather it said so out loud than quietly wave through the next one.
The docblock on the list also heads off the entry somebody will reach for first: "the class
does not exist yet" is not a reason.
::classresolves at compile time and never asks theautoloader, so it is perfectly happy to name a class that has not been loaded, or one that
is never loaded at all.
What it cannot see
A name assembled at run time. The menus build theirs as
__NAMESPACE__ . '\\Home::call', and the class half of that is not written down foranything to check either — not by this test, and not by the compiler. Worth knowing before
reading a pass here as "every class name in SMF is checked".
Proving it fails
Both assertions were watched failing before being trusted: a throwaway
Sources/TempProbe.phpholding
'SMF\Tasks\CreatePost_Notify'produced the failure above, and a bogus entry in theexception list produced
Cost and its relationship to #9661
13.3s in the Docker environment. That is the bind-mounted filesystem rather than the work:
#9661's
ClassReferenceTest, which walks the same tree, measures 12.1s in the same containeragainst the 0.151s quoted on that PR.
The two overlap, and reviewers may want only one. They answer different questions — #9661
asks whether a name written as a string is real, which still matters for the four above and
for anything a future change adds; this one asks whether SMF writes them as strings at all,
which after #9665 is the stronger statement. If both land they could share a single walk of
the tree. Happy to fold them together either way round.
Issues References (Fixes|Related|Closes)
🤖 Generated with Claude Code