[Draft RFC] Support named extension declarations (Extension Methods RFC, in review)#43
Draft
hollyschilling wants to merge 2 commits into
Draft
[Draft RFC] Support named extension declarations (Extension Methods RFC, in review)#43hollyschilling wants to merge 2 commits into
extension declarations (Extension Methods RFC, in review)#43hollyschilling wants to merge 2 commits into
Conversation
… RFC)
Recognizes the proposed `extension Name on Target $var { ... }` declaration
in the class map, following the approach used for enum support. The full
"Name on Target $var" tail is required, so the anonymous form, the RFC's
"use extension ..." import statement, and existing symbols named
"extension" cannot produce false positives. Parsing is purely text-based
and works on any PHP version.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The target after "on" is now captured as a named group (exttarget), exactly as written in the source — relative names and import aliases stay unresolved. Nothing is emitted yet: the class map output is unchanged. This settles the regex shape for the target-hint optimization described in the RFC's Future Scope. The extension branch of the parser regex is exposed as an @internal constant so tests assert against the exact pattern used in production. Co-Authored-By: Claude Fable 5 <noreply@anthropic.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.
What
Draft support for the named form of
extensiondeclarations from the proposed PHP "Extension Methods" RFC family, which is currently in informal review:The named form declares an autoloadable symbol, namespaced exactly like a
classdeclaration's name:→ class-map entry
Acme\DomKit\DomTraversalmapping to this file. The target afteronand the receiver variable are not part of the name and are not captured.This follows the approach used when
enumsupport was added (composer/composer#9670): parsing is purely text-based (PhpFileCleaner+ regex), so it does not depend ontoken_get_all()or on the running PHP understanding the syntax, and works on every PHP version this package supports.How
PhpFileParser:extensionis added to the early-exit prefilter, and the main regex gets a dedicated branch that requires the fullextension Name on Target $vartail.extensionandonare contextual identifiers in the RFC grammar, so requiring the complete tail (including the mandatory receiver variable) is what makes false positives near-impossible —extensionremains a perfectly valid class/function/method name today. The target may be an identifier, qualified/fully-qualified name, or a built-in type name (string,int,float,bool,array). Keywords match case-insensitively like the existing ones.PhpFileCleaner: the keyword shortlist was keyed by first character, soextensioncollided withenumundere; the config now holds a list per character.extensiongets a tail-aware pattern so the single-match early return keeps everything the parser regex needs to see (a name-only pattern would truncate the declaration after the name and drop the match).extension \DateTimeImmutable $date { ... },extension string $s { ... }) declares no addressable symbol and produces no entry — it can't match because there is noName onsequence.use extension Acme\DomKit\Traversal;import statement declares nothing and produces no entry — it can't match because noon Target $vartail follows.filterByNamespace()is symbol-agnostic, so a named extension declaration matching the file path is accepted as the file's expected symbol (covered by tests). PSR-4 itself needs no amendment either — the spec's "classes, interfaces, traits, and other similar structures" wording covers extension declarations, as it did enums.onas a named group (exttarget), exactly as written in the source — relative names and import aliases stay unresolved (covered by tests, including an aliased-target fixture). Nothing consumes it yet and the class map output is unchanged; this settles the pattern shape for the target-hint optimization described in the RFC's Future Scope (the engine filters autoload candidates by target, with a load-the-rest fallback). The extension branch of the parser regex is exposed as an@internalconstant so the tests assert against the exact pattern used in production.Deliberately not in this PR
No new autoload artifact and no map format change (no
autoload_extensions.php, no target metadata in the emitted map). That half waits until the engine-side hint API is a live proposal — keeping this PR minimal and mergeable on the enum precedent.Tests
New fixtures cover: global + namespaced named forms, fully-qualified/qualified/unqualified/scalar/
arraytargets, a multiline declaration with comments between tokens, non-lowercase keywords, both anonymous forms (no entries), an extension declared alongside a class in one file (both mapped), PSR-4 acceptance + PSR-4 violation for a mis-named extension, duplicate-name ambiguity, and the false-positive zoo:class extension,function extension(),$obj->extension(),new extension(),use extension …;, and a declaration inside a string literal.Fixture files use the proposed syntax and are not valid PHP on any current version; they sit under
tests/Fixtures/, which lint, php-cs-fixer, and PHPStan already exclude (same mechanism as the enum fixtures on PHP < 8.1).Why now / draft status
Map entries for extension names are inert until PHP ships the engine-side autoload trigger (a later phase of the RFC), so landing this early is harmless and unblocks the ecosystem story. The grammar is draft-stable but not final — this PR tracks the RFC and should stay draft until the RFC is accepted.
Disclosure: I am the author of the RFC drafts linked above.
🤖 Generated with Claude Code