Conversation
php-parser 3.7 parses property hooks into `property.hooks` (kind
`propertyhook`), but the printer never printed them, so formatting a
hooked property silently dropped the hooks and left a plain property
behind (exit code 0). A comment inside a hook made it fail with
"Comment was not printed" instead.
Print hooks following PER-CS 4.9:
- the opening brace stays on the property line, one hook per line,
a single blank line between hooks is preserved;
- `get => expr;` breaks like an assignment, `get { ... }` keeps the
brace on the hook line, `get;` / `set;` declarations (interfaces,
abstract classes) stay on one line: `public string $x { get; set; }`;
- `final`, `&get`, `set(Type $value)` and attributes on hooks;
- hooks on promoted constructor parameters.
A hooked property statement ends with its closing brace, so it no
longer gets a trailing semicolon.
Property statements also lost `abstract`, `final` and the asymmetric
set visibility (`public private(set)`), which the parser exposes as
`isAbstract`, `isFinal` and `visibilitySet`; print those too.
Guard `handleFunctionParameter` against a missing preceding node,
which a comment right after `set(` reaches.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Thanks for this, @mreiden! I tested this branch on top of
One case still loses code: asymmetric visibility on a promoted constructor parameter. becomes php-parser 3.7.0 has the set visibility in |
`public private(set) int $x` as a promoted constructor parameter lost its `private(set)`: the parser exposes the set visibility as `parameter.flagsSet` (same 1/2/4 mapping as `flags`), but the printer only looked at `flags`. `private(set) int $x` on its own (no explicit get visibility) is printed as written. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Thanks for testing it so thoroughly, @elnebuloso — good catch. Fixed in 313e41e: the |


Problem
php-parser 3.7 (glayzzle/php-parser#1142) parses PHP 8.4 property hooks into
property.hooks, butprinter.mjsnever prints them. Formattingexits 0 and writes back
public ?int $agencyId;— the hooks are silently deleted. A comment anywhere inside the hooks turns that intoError: Comment "..." was not printedinstead, which is the only thing that stopped us from losing code.The same class of bug affects property modifiers the parser already exposes on
propertystatement:abstract,finaland the asymmetric set visibility (public private(set) static string $webUrl;) were all dropped on format.Fix
printPropertyHooks()used bypropertyand byparameter(hooks on promoted constructor properties), and apropertyhookcase printing[#[attr] ][final ][&]get|set[(param)]followed by;,=> expr;(viaprintAssignmentRight, so long expressions break like assignments) or{ ... }.public string $name { get; set; }.lineShouldEndWithSemicolon(): a hooked property statement ends with}, not};(a parse error inside a class body).propertystatementprintsabstract,finalandvisibilitySet(public private(set)).handleFunctionParameter()guards against a missing preceding node, reachable with a comment right afterset(.No parser change is needed:
php-parser@^3.7.0is already the dependency. Supersedes #2458, which needed a fork of the parser at the time; this builds on the same idea and additionally covers hook attributes, promoted-parameter hooks, the one-line form and the property modifiers.Tests
tests/property-hooks/covers interface and abstract declarations,=>and block bodies,final,&get,set(Type $v), attributes on hooks, comments between/after hooks, empty bodies, promoted constructor parameters, long expressions, and the property modifiers. Verified withAST_COMPARE=1; output re-formats idempotently and passesphp -l.🤖 Generated with Claude Code