Repository navigation
Lex PHP attributes natively so blink fixers format inside #[...] - #245
Merged
Merged
Conversation
The lexer used to fold a whole #[...] attribute into one opaque Comment
token, so no fixer could see the arrays, named arguments or operators
inside it. That left attribute-internal code diverging from PHP ECS
(e.g. concat spacing in #[WithEnv('X', __DIR__.'/y')]).
Attributes now lex natively: "#[" is an AttributeStart token, the
closing "]" is retagged as AttributeEnd, and the contents lex as
ordinary tokens, mirroring php-cs-fixer's T_ATTRIBUTE / T_ATTRIBUTE_CLOSE.
Both delimiters are distinct kinds, so generic bracket-depth scans never
mistake them for array brackets.
Fixers that reasoned about an attribute as a whole were ported to the
native tokens: a shared helper set (AttributeEnd/AttributeStartOf,
attributeStartsAt/EndsAt, prevMeaningfulSkippingAttributes) plus a text
bridge that re-lexes the existing string reflows (symfony standalone
line, line-length break, arg collapse, anon-class flatten). The old
string hacks on the comment value are gone.
Making #[...] lex as real tokens exposed four fixers that did not account for an attribute in the token stream: - NoUnusedImports: an attribute name (#[AsCommand(...)]) now counts as a class use even with a following (, so its import is not dropped. - BracesPosition: a class header scan no longer reads a leading attribute's ) as a multiline signature, so the class brace moves to its own line. - NoSuperfluousPhpdocTags: parseParams skips a param attribute, so a @PARAM covered by the native type is removed even with #[\SensitiveParameter]. - StatementIndentation: a promoted param with a leading attribute is still a param, not a class property, so following params keep their indent.
rector-src now matches PHP ECS on all 1568 files, so ratchet the locker from 0.25% to 0% - any future divergence fails CI.
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.
Problem
blink's lexer folded a whole
#[...]attribute into one opaqueCommenttoken, so no fixer could see the arrays, named arguments or operators inside it. Attribute-internal code therefore diverged from PHP ECS, e.g. concat spacing in#[WithEnv('X', __DIR__.'/y')]was never applied.Change
Attributes now lex natively:
#[becomes anAttributeStarttoken.]is retagged asAttributeEnd(a post-lex pass).This mirrors php-cs-fixer's
T_ATTRIBUTE/T_ATTRIBUTE_CLOSE. Both delimiters are distinct token kinds, so generic bracket-depth scans never mistake them for array brackets.Fixers that reasoned about an attribute as a whole were ported to the native tokens via a small shared helper set (
AttributeEnd/AttributeStartOf,attributeStartsAt/attributeEndsAt,prevMeaningfulSkippingAttributes) plus a text bridge that re-lexes the existing string reflows (symfony standalone-line, line-length break, arg collapse, anon-class flatten). The old string hacks on the comment value are removed.Result
Formatting inside attributes (concat, arrays, named args,
=>, operator spacing) now matches PHP ECS byte for byte. Verified on the concat case:```php
#[WithEnv('A', DIR.'/x.php')] -> #[WithEnv('A', DIR . '/x.php')]
```
Verification
go test -race ./..., plus a new native-attribute lexer test