fix(preprocessor): enforce property-hook placement rules for class properties - #63
Conversation
matyhtf
left a comment
There was a problem hiding this comment.
The abstract-property branch is missing two Zend modifier conflicts; both currently dry-compile:
abstract class A {
abstract private int $x { get; }
}Zend: Property hook cannot be both abstract and private. Unlike abstract private trait methods, an abstract private property hook is also forbidden inside a trait. Protected abstract hooks remain legal.
abstract class A {
abstract public int $x { final get; }
}Zend: Property hook cannot be both abstract and final. A bodiless hook must not carry final.
Please add these checks with the same Zend precedence and negative tests for both. The existing focused tests pass (8/8), but do not cover abstract/private or abstract/final combinations.
277fde3 to
70985b6
Compare
|
Added, with the precedence pinned by probes first: static → readonly → per-hook final+private ("Property hook cannot be both final and private" — it wins your combined One probe finding worth noting: a Five new fixtures (abstract-private in class and trait, abstract-final, the final-private precedence case, and the protected-abstract positive), all Zend-validated; 27/27 across the hook suites. |
…operties
The interface path already validated hook placement; class and trait
properties accepted every combination. parseClassPropertyDef now
mirrors Zend's compile-time rules (probed on 8.4.13, including the
precedence order static -> readonly -> abstract rules):
- hooks on a static property ("Cannot declare hooks for static
property")
- hooks on a readonly property, including properties made readonly by
a `readonly class` ("Hooked properties cannot be readonly")
- `abstract` on a hook-less property ("Only hooked properties may be
declared abstract")
- abstract hooked property with a default value ("Cannot specify
default value for virtual hooked property A::$x")
- abstract hooked property whose hooks all have bodies ("Abstract
property A::$x must specify at least one abstract hook")
- abstract hooked property in a non-abstract class; traits stay exempt
(the consuming class satisfies the hook) and enums are already
rejected by the property ban
- bodiless hook on a non-abstract property, in classes and traits
("Non-abstract property hook must have a body"); previously the
lowering fabricated a concrete backing-store accessor for it
…private hooks
Three hook-level modifier conflicts Zend rejects at compile time were
still accepted by the class/trait property path (all probed on 8.4.13):
- `abstract private int $x { get; }` — an abstract (bodiless) hook must
be implemented by a subclass, which private visibility forbids
("Property hook cannot be both abstract and private"). Unlike abstract
private trait methods, Zend does NOT exempt traits from this rule.
- `abstract public int $x { final get; }` — a bodiless hook must stay
overridable to ever gain a body ("Property hook cannot be both
abstract and final").
- `private int $x { final get => 1; }` — a final hook on a private
property is meaningless because private members cannot be overridden
("Property hook cannot be both final and private").
Diagnostic precedence follows Zend: static, then readonly, then the
per-hook final+private conflict (which wins over both abstract
conflicts: `abstract private int $x { final get; }` reports
final+private), then per bodiless hook abstract+private before
abstract+final, all ahead of the default-value and
at-least-one-abstract-hook rules. Protected abstract hooks remain
legal in classes and traits.
70985b6 to
2a166f7
Compare
Property-hook placement rules were unenforced on the class path (the interface path already had them): hooks on static properties ("Cannot declare hooks for static property"), hooks on readonly properties incl. readonly classes ("Hooked properties cannot be readonly"), abstract hooked properties in non-abstract classes, abstract properties without hooks, abstract hooked properties with a default or with all hooks bodied, and bodiless hooks on non-abstract properties (previously the lowering silently fabricated a concrete accessor).
Each rule and its precedence (static → readonly → abstract) probed against Zend 8.4.13; traits keep abstract hooked properties.
Part of the split of #39.