[8.4] Add support for property hooks

Add hooks subnode to Stmt\Property and Param, which contains an
array of PropertyHook.

The property hook support is considered experimental and subject
to change.

RFC: https://wiki.php.net/rfc/property-hooks
This commit is contained in:
Nikita Popov 2024-07-14 21:29:58 +02:00
parent b11fc12cce
commit 03caf4cc99
43 changed files with 3011 additions and 1584 deletions

View File

@ -677,12 +677,12 @@ property_modifier:
parameter:
optional_attributes optional_property_modifiers optional_type_without_static
optional_arg_ref optional_ellipsis plain_variable
{ $$ = new Node\Param($6, null, $3, $4, $5, attributes(), $2, $1);
optional_arg_ref optional_ellipsis plain_variable optional_property_hook_list
{ $$ = new Node\Param($6, null, $3, $4, $5, attributes(), $2, $1, $7);
$this->checkParam($$); }
| optional_attributes optional_property_modifiers optional_type_without_static
optional_arg_ref optional_ellipsis plain_variable '=' expr
{ $$ = new Node\Param($6, $8, $3, $4, $5, attributes(), $2, $1);
optional_arg_ref optional_ellipsis plain_variable '=' expr optional_property_hook_list
{ $$ = new Node\Param($6, $8, $3, $4, $5, attributes(), $2, $1, $9);
$this->checkParam($$); }
| optional_attributes optional_property_modifiers optional_type_without_static
optional_arg_ref optional_ellipsis error
@ -830,6 +830,11 @@ class_statement_list:
class_statement:
optional_attributes variable_modifiers optional_type_without_static property_declaration_list semi
{ $$ = new Stmt\Property($2, $4, attributes(), $3, $1); }
#if PHP8
| optional_attributes variable_modifiers optional_type_without_static property_declaration_list '{' property_hook_list '}'
{ $$ = new Stmt\Property($2, $4, attributes(), $3, $1, $6);
$this->checkPropertyHookList($6, #5); }
#endif
| optional_attributes method_modifiers T_CONST class_const_list semi
{ $$ = new Stmt\ClassConst($4, $2, attributes(), $1);
$this->checkClassConst($$, #2); }
@ -926,6 +931,39 @@ property_declaration:
| property_decl_name '=' expr { $$ = Node\PropertyItem[$1, $3]; }
;
property_hook_list:
/* empty */ { $$ = []; }
| property_hook_list property_hook { push($1, $2); }
;
optional_property_hook_list:
/* empty */ { $$ = []; }
#if PHP8
| '{' property_hook_list '}' { $$ = $2; $this->checkPropertyHookList($2, #1); }
#endif
;
property_hook:
optional_attributes property_hook_modifiers optional_ref identifier_not_reserved property_hook_body
{ $$ = Node\PropertyHook[$4, $5, ['flags' => $2, 'byRef' => $3, 'params' => [], 'attrGroups' => $1]];
$this->checkPropertyHook($$, null); }
| optional_attributes property_hook_modifiers optional_ref identifier_not_reserved '(' parameter_list ')' property_hook_body
{ $$ = Node\PropertyHook[$4, $8, ['flags' => $2, 'byRef' => $3, 'params' => $6, 'attrGroups' => $1]];
$this->checkPropertyHook($$, #5); }
;
property_hook_body:
';' { $$ = null; }
| '{' inner_statement_list '}' { $$ = $2; }
| T_DOUBLE_ARROW expr ';' { $$ = $2; }
;
property_hook_modifiers:
/* empty */ { $$ = 0; }
| property_hook_modifiers member_modifier
{ $this->checkPropertyHookModifiers($1, $2, #2); $$ = $1 | $2; }
;
expr_list_forbid_comma:
non_empty_expr_list no_comma
;

View File

@ -23,6 +23,8 @@ class Property implements PhpParser\Builder {
protected ?Node $type = null;
/** @var list<Node\AttributeGroup> */
protected array $attributeGroups = [];
/** @var list<Node\PropertyHook> */
protected array $hooks = [];
/**
* Creates a property builder.
@ -88,6 +90,28 @@ class Property implements PhpParser\Builder {
return $this;
}
/**
* Makes the property abstract. Requires at least one property hook to be specified as well.
*
* @return $this The builder instance (for fluid interface)
*/
public function makeAbstract() {
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::ABSTRACT);
return $this;
}
/**
* Makes the property final.
*
* @return $this The builder instance (for fluid interface)
*/
public function makeFinal() {
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::FINAL);
return $this;
}
/**
* Sets default value for the property.
*
@ -142,12 +166,27 @@ class Property implements PhpParser\Builder {
return $this;
}
/**
* Adds a property hook.
*
* @return $this The builder instance (for fluid interface)
*/
public function addHook(Node\PropertyHook $hook) {
$this->hooks[] = $hook;
return $this;
}
/**
* Returns the built class node.
*
* @return Stmt\Property The built property node
*/
public function getNode(): PhpParser\Node {
if ($this->flags & Modifiers::ABSTRACT && !$this->hooks) {
throw new PhpParser\Error('Only hooked properties may be declared abstract');
}
return new Stmt\Property(
$this->flags !== 0 ? $this->flags : Modifiers::PUBLIC,
[
@ -155,7 +194,8 @@ class Property implements PhpParser\Builder {
],
$this->attributes,
$this->type,
$this->attributeGroups
$this->attributeGroups,
$this->hooks
);
}
}

View File

@ -21,6 +21,8 @@ class Param extends NodeAbstract {
public int $flags;
/** @var AttributeGroup[] PHP attribute groups */
public array $attrGroups;
/** @var PropertyHook[] Property hooks for promoted properties */
public array $hooks;
/**
* Constructs a parameter node.
@ -33,13 +35,15 @@ class Param extends NodeAbstract {
* @param array<string, mixed> $attributes Additional attributes
* @param int $flags Optional visibility flags
* @param list<AttributeGroup> $attrGroups PHP attribute groups
* @param PropertyHook[] $hooks Property hooks for promoted properties
*/
public function __construct(
Expr $var, ?Expr $default = null, ?Node $type = null,
bool $byRef = false, bool $variadic = false,
array $attributes = [],
int $flags = 0,
array $attrGroups = []
array $attrGroups = [],
array $hooks = []
) {
$this->attributes = $attributes;
$this->type = $type;
@ -49,10 +53,11 @@ class Param extends NodeAbstract {
$this->default = $default;
$this->flags = $flags;
$this->attrGroups = $attrGroups;
$this->hooks = $hooks;
}
public function getSubNodeNames(): array {
return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default'];
return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default', 'hooks'];
}
public function getType(): string {

View File

@ -0,0 +1,78 @@
<?php declare(strict_types=1);
namespace PhpParser\Node;
use PhpParser\Node\Stmt\Return_;
use PhpParser\NodeAbstract;
class PropertyHook extends NodeAbstract implements FunctionLike {
/** @var AttributeGroup[] PHP attribute groups */
public array $attrGroups;
/** @var int Modifiers */
public int $flags;
/** @var bool Whether hook returns by reference */
public bool $byRef;
/** @var Identifier Hook name */
public Identifier $name;
/** @var Param[] Parameters */
public array $params;
/** @var null|Expr|Stmt[] Hook body */
public $body;
/**
* Constructs a property hook node.
*
* @param string|Identifier $name Hook name
* @param null|Expr|Stmt[] $body Hook body
* @param array{
* flags?: int,
* byRef?: bool,
* params?: Param[],
* attrGroups?: AttributeGroup[],
* } $subNodes Array of the following optional subnodes:
* 'byRef' => false : Whether hook returns by reference
* 'params' => array(): Parameters
* 'attrGroups' => array(): PHP attribute groups
* @param array<string, mixed> $attributes Additional attributes
*/
public function __construct($name, $body, array $subNodes = [], array $attributes = []) {
$this->attributes = $attributes;
$this->name = \is_string($name) ? new Identifier($name) : $name;
$this->body = $body;
$this->flags = $subNodes['flags'] ?? 0;
$this->byRef = $subNodes['byRef'] ?? false;
$this->params = $subNodes['params'] ?? [];
$this->attrGroups = $subNodes['attrGroups'] ?? [];
}
public function returnsByRef(): bool {
return $this->byRef;
}
public function getParams(): array {
return $this->params;
}
public function getReturnType() {
return null;
}
public function getStmts(): ?array {
if ($this->body instanceof Expr) {
return [new Return_($this->body)];
}
return $this->body;
}
public function getAttrGroups(): array {
return $this->attrGroups;
}
public function getType(): string {
return 'PropertyHook';
}
public function getSubNodeNames(): array {
return ['attrGroups', 'flags', 'byRef', 'name', 'params', 'body'];
}
}

View File

@ -18,6 +18,8 @@ class Property extends Node\Stmt {
public ?Node $type;
/** @var Node\AttributeGroup[] PHP attribute groups */
public array $attrGroups;
/** @var Node\PropertyHook[] Property hooks */
public array $hooks;
/**
* Constructs a class property list node.
@ -27,17 +29,19 @@ class Property extends Node\Stmt {
* @param array<string, mixed> $attributes Additional attributes
* @param null|Identifier|Name|ComplexType $type Type declaration
* @param Node\AttributeGroup[] $attrGroups PHP attribute groups
* @param Node\PropertyHook[] $hooks Property hooks
*/
public function __construct(int $flags, array $props, array $attributes = [], ?Node $type = null, array $attrGroups = []) {
public function __construct(int $flags, array $props, array $attributes = [], ?Node $type = null, array $attrGroups = [], array $hooks = []) {
$this->attributes = $attributes;
$this->flags = $flags;
$this->props = $props;
$this->type = $type;
$this->attrGroups = $attrGroups;
$this->hooks = $hooks;
}
public function getSubNodeNames(): array {
return ['attrGroups', 'flags', 'type', 'props'];
return ['attrGroups', 'flags', 'type', 'props', 'hooks'];
}
/**

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,7 @@ use PhpParser\Node\Identifier;
use PhpParser\Node\InterpolatedStringPart;
use PhpParser\Node\Name;
use PhpParser\Node\Param;
use PhpParser\Node\PropertyHook;
use PhpParser\Node\Scalar\InterpolatedString;
use PhpParser\Node\Scalar\Int_;
use PhpParser\Node\Scalar\String_;
@ -1158,6 +1159,42 @@ abstract class ParserAbstract implements Parser {
}
}
/** @param PropertyHook[] $hooks */
protected function checkPropertyHookList(array $hooks, int $hookPos): void {
if (empty($hooks)) {
$this->emitError(new Error(
'Property hook list cannot be empty', $this->getAttributesAt($hookPos)));
}
}
protected function checkPropertyHook(PropertyHook $hook, ?int $paramListPos): void {
$name = $hook->name->toLowerString();
if ($name !== 'get' && $name !== 'set') {
$this->emitError(new Error(
'Unknown hook "' . $hook->name . '", expected "get" or "set"',
$hook->name->getAttributes()));
}
if ($name === 'get' && $paramListPos !== null) {
$this->emitError(new Error(
'get hook must not have a parameter list', $this->getAttributesAt($paramListPos)));
}
}
protected function checkPropertyHookModifiers(int $a, int $b, int $modifierPos): void {
try {
Modifiers::verifyModifier($a, $b);
} catch (Error $error) {
$error->setAttributes($this->getAttributesAt($modifierPos));
$this->emitError($error);
}
if ($b != Modifiers::FINAL) {
$this->emitError(new Error(
'Cannot use the ' . Modifiers::toString($b) . ' modifier on a property hook',
$this->getAttributesAt($modifierPos)));
}
}
/**
* Creates the token map.
*

View File

@ -23,7 +23,8 @@ class Standard extends PrettyPrinterAbstract {
. ($node->byRef ? '&' : '')
. ($node->variadic ? '...' : '')
. $this->p($node->var)
. ($node->default ? ' = ' . $this->p($node->default) : '');
. ($node->default ? ' = ' . $this->p($node->default) : '')
. ($node->hooks ? ' {' . $this->pStmts($node->hooks) . $this->nl . '}' : '');
}
protected function pArg(Node\Arg $node): string {
@ -831,7 +832,8 @@ class Standard extends PrettyPrinterAbstract {
return $this->pAttrGroups($node->attrGroups)
. (0 === $node->flags ? 'var ' : $this->pModifiers($node->flags))
. ($node->type ? $this->p($node->type) . ' ' : '')
. $this->pCommaSeparated($node->props) . ';';
. $this->pCommaSeparated($node->props)
. ($node->hooks ? ' {' . $this->pStmts($node->hooks) . $this->nl . '}' : ';');
}
protected function pPropertyItem(Node\PropertyItem $node): string {
@ -839,6 +841,15 @@ class Standard extends PrettyPrinterAbstract {
. (null !== $node->default ? ' = ' . $this->p($node->default) : '');
}
protected function pPropertyHook(Node\PropertyHook $node): string {
return $this->pAttrGroups($node->attrGroups)
. $this->pModifiers($node->flags)
. ($node->byRef ? '&' : '') . $node->name
. ($node->params ? '(' . $this->pMaybeMultiline($node->params, $this->phpVersion->supportsTrailingCommaInParamList()) . ')' : '')
. (\is_array($node->body) ? ' {' . $this->pStmts($node->body) . $this->nl . '}'
: ($node->body !== null ? ' => ' . $this->p($node->body) : '') . ';');
}
protected function pStmt_ClassMethod(Stmt\ClassMethod $node): string {
return $this->pAttrGroups($node->attrGroups)
. $this->pModifiers($node->flags)

View File

@ -14,6 +14,7 @@ use PhpParser\Node\Expr\Cast;
use PhpParser\Node\IntersectionType;
use PhpParser\Node\MatchArm;
use PhpParser\Node\Param;
use PhpParser\Node\PropertyHook;
use PhpParser\Node\Scalar;
use PhpParser\Node\Stmt;
use PhpParser\Node\UnionType;
@ -1517,6 +1518,7 @@ abstract class PrettyPrinterAbstract implements PrettyPrinter {
Stmt\UseUse::class . '->uses' => ', ',
MatchArm::class . '->conds' => ', ',
AttributeGroup::class . '->attrs' => ', ',
PropertyHook::class . '->params' => ', ',
// statement lists
Expr\Closure::class . '->stmts' => "\n",
@ -1554,10 +1556,15 @@ abstract class PrettyPrinterAbstract implements PrettyPrinter {
Expr\Closure::class . '->attrGroups' => ' ',
Expr\ArrowFunction::class . '->attrGroups' => ' ',
Param::class . '->attrGroups' => ' ',
PropertyHook::class . '->attrGroups' => ' ',
Stmt\Switch_::class . '->cases' => "\n",
Stmt\TraitUse::class . '->adaptations' => "\n",
Stmt\TryCatch::class . '->stmts' => "\n",
Stmt\While_::class . '->stmts' => "\n",
PropertyHook::class . '->body' => "\n",
Stmt\Property::class . '->hooks' => "\n",
Param::class . '->hooks' => "\n",
// dummy for top-level context
'File->stmts' => "\n",
@ -1641,6 +1648,7 @@ abstract class PrettyPrinterAbstract implements PrettyPrinter {
Stmt\Property::class . '->flags' => ['pModifiers', \T_VARIABLE],
PrintableNewAnonClassNode::class . '->flags' => ['pModifiers', \T_CLASS],
Param::class . '->flags' => ['pModifiers', \T_VARIABLE],
PropertyHook::class . '->flags' => ['pModifiers', \T_STRING],
Expr\Closure::class . '->static' => ['pStatic', \T_FUNCTION],
Expr\ArrowFunction::class . '->static' => ['pStatic', \T_FN],
//Stmt\TraitUseAdaptation\Alias::class . '->newModifier' => 0, // TODO

View File

@ -3,6 +3,7 @@
namespace PhpParser\Builder;
use PhpParser\Comment;
use PhpParser\Error;
use PhpParser\Modifiers;
use PhpParser\Node\Arg;
use PhpParser\Node\Attribute;
@ -10,6 +11,8 @@ use PhpParser\Node\AttributeGroup;
use PhpParser\Node\Expr;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\PropertyHook;
use PhpParser\Node\PropertyItem;
use PhpParser\Node\Scalar;
use PhpParser\Node\Scalar\Int_;
use PhpParser\Node\Stmt;
@ -29,9 +32,7 @@ class PropertyTest extends \PHPUnit\Framework\TestCase {
$this->assertEquals(
new Stmt\Property(
Modifiers::PRIVATE | Modifiers::STATIC,
[
new \PhpParser\Node\PropertyItem('test')
]
[new PropertyItem('test')]
),
$node
);
@ -44,9 +45,7 @@ class PropertyTest extends \PHPUnit\Framework\TestCase {
$this->assertEquals(
new Stmt\Property(
Modifiers::PROTECTED,
[
new \PhpParser\Node\PropertyItem('test')
]
[new PropertyItem('test')]
),
$node
);
@ -59,9 +58,7 @@ class PropertyTest extends \PHPUnit\Framework\TestCase {
$this->assertEquals(
new Stmt\Property(
Modifiers::PUBLIC,
[
new \PhpParser\Node\PropertyItem('test')
]
[new PropertyItem('test')]
),
$node
);
@ -74,12 +71,23 @@ class PropertyTest extends \PHPUnit\Framework\TestCase {
$this->assertEquals(
new Stmt\Property(
Modifiers::READONLY,
[
new \PhpParser\Node\PropertyItem('test')
]
[new PropertyItem('test')]
),
$node
);
$node = $this->createPropertyBuilder('test')
->makeFinal()
->getNode();
$this->assertEquals(
new Stmt\Property(Modifiers::FINAL, [new PropertyItem('test')]),
$node);
}
public function testAbstractWithoutHook() {
$this->expectException(Error::class);
$this->expectExceptionMessage('Only hooked properties may be declared abstract');
$this->createPropertyBuilder('test')->makeAbstract()->getNode();
}
public function testDocComment(): void {
@ -136,6 +144,23 @@ class PropertyTest extends \PHPUnit\Framework\TestCase {
);
}
public function testAddHook(): void {
$get = new PropertyHook('get', null);
$set = new PropertyHook('set', null);
$node = $this->createPropertyBuilder('test')
->addHook($get)
->addHook($set)
->makeAbstract()
->getNode();
$this->assertEquals(
new Stmt\Property(
Modifiers::ABSTRACT,
[new PropertyItem('test')],
[], null, [],
[$get, $set]),
$node);
}
public static function provideTestDefaultValues() {
return [
[

View File

@ -260,7 +260,8 @@ PHP;
}
},
"flags": 0,
"attrGroups": [],
"attrGroups": [],,
"hooks": []
"attributes": {
"startLine": 4,
"startTokenPos": 9,
@ -301,7 +302,8 @@ PHP;
}
},
"flags": 0,
"attrGroups": [],
"attrGroups": [],,
"hooks": []
"attributes": {
"startLine": 4,
"startTokenPos": 17,
@ -464,7 +466,8 @@ JSON;
"value": 0
},
"flags": 0,
"attrGroups": []
"attrGroups": [],
"hooks": []
},
{
"nodeType": "Param",
@ -505,7 +508,8 @@ JSON;
"value": 1
},
"flags": 0,
"attrGroups": []
"attrGroups": [],
"hooks": []
}
],
"returnType": null,

View File

@ -0,0 +1,128 @@
Property hooks
-----
<?php
class Test {
public $prop
{
get => 42;
}
}
-----
$stmts[0]->stmts[0]->hooks[] = new Node\PropertyHook('set', new Scalar\Int_(123));
-----
<?php
class Test {
public $prop
{
get => 42;
set => 123;
}
}
-----
<?php
class Test {
public function __construct(
public $prop
{ get => 42; }
) {}
}
-----
$stmts[0]->stmts[0]->params[0]->hooks[] = new Node\PropertyHook('set', new Scalar\Int_(123));
-----
<?php
class Test {
public function __construct(
public $prop
{ get => 42;
set => 123; }
) {}
}
-----
<?php
class Test {
public $prop {
set
{
$a;
}
}
}
-----
$stmts[0]->stmts[0]->hooks[0]->body[] = new Stmt\Expression(new Expr\Variable('b'));
-----
<?php
class Test {
public $prop {
set
{
$a;
$b;
}
}
}
-----
<?php
class Test {
public $prop {
get
=> 42;
}
}
-----
$stmts[0]->stmts[0]->hooks[0]->flags = Modifiers::FINAL;
-----
<?php
class Test {
public $prop {
final get
=> 42;
}
}
-----
<?php
// For now, just make sure this works.
class Test {
public $prop {
get
=> 42;
}
}
-----
$stmts[0]->stmts[0]->hooks[0]->body = [new Stmt\Return_(new Scalar\Int_(24))];
-----
<?php
// For now, just make sure this works.
class Test {
public $prop {
get {
return 24;
}
}
}
-----
<?php
// For now, just make sure this works.
class Test {
public $prop1 {
& get;
}
public $prop2 {
& get;
}
}
-----
$stmts[0]->stmts[0]->hooks[0]->body = new Scalar\Int_(24);
$stmts[0]->stmts[1]->hooks[0]->body = [new Stmt\Return_(new Scalar\Int_(24))];
-----
<?php
// For now, just make sure this works.
class Test {
public $prop1 {
&get => 24;
}
public $prop2 {
&get {
return 24;
}
}
}

View File

@ -31,6 +31,8 @@ array(
default: null
)
)
hooks: array(
)
)
1: Stmt_Nop(
comments: array(

View File

@ -714,6 +714,8 @@ array(
default: null
)
)
hooks: array(
)
)
)
)
@ -869,6 +871,8 @@ array(
default: null
)
)
hooks: array(
)
)
1: Stmt_Property(
attrGroups: array(
@ -883,6 +887,8 @@ array(
default: null
)
)
hooks: array(
)
)
)
)
@ -984,6 +990,8 @@ array(
var: Expr_Error(
)
default: null
hooks: array(
)
)
)
returnType: null
@ -1016,6 +1024,8 @@ array(
name: foo
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -1029,6 +1039,8 @@ array(
var: Expr_Error(
)
default: null
hooks: array(
)
)
)
returnType: null
@ -1058,6 +1070,8 @@ array(
var: Expr_Error(
)
default: null
hooks: array(
)
)
)
returnType: null
@ -1087,6 +1101,8 @@ array(
var: Expr_Error(
)
default: null
hooks: array(
)
)
)
returnType: null
@ -1118,6 +1134,8 @@ array(
var: Expr_Error(
)
default: null
hooks: array(
)
)
)
returnType: null
@ -1156,6 +1174,8 @@ array(
var: Expr_Error(
)
default: null
hooks: array(
)
)
)
returnType: null
@ -1183,6 +1203,8 @@ array(
var: Expr_Error(
)
default: null
hooks: array(
)
)
)
uses: array(
@ -1352,7 +1374,7 @@ class B {
const X = 1
}
-----
Syntax error, unexpected T_PUBLIC, expecting ';' from 6:5 to 6:10
Syntax error, unexpected T_PUBLIC, expecting ';' or '{' from 6:5 to 6:10
Syntax error, unexpected '}', expecting ';' from 12:1 to 12:1
array(
0: Stmt_Class(
@ -1379,6 +1401,8 @@ array(
default: null
)
)
hooks: array(
)
comments: array(
0: /** @var ?string */
)
@ -1405,6 +1429,8 @@ array(
name: s
)
default: null
hooks: array(
)
)
)
returnType: null

View File

@ -32,6 +32,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
)
returnType: null
@ -60,6 +62,8 @@ array(
default: Scalar_Int(
value: 42
)
hooks: array(
)
)
)
returnType: null
@ -86,6 +90,8 @@ array(
name: x
)
default: null
hooks: array(
)
)
)
returnType: null
@ -112,6 +118,8 @@ array(
name: x
)
default: null
hooks: array(
)
)
)
returnType: null
@ -138,6 +146,8 @@ array(
name: x
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -150,6 +160,8 @@ array(
name: rest
)
default: null
hooks: array(
)
)
)
returnType: null
@ -192,6 +204,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -204,6 +218,8 @@ array(
name: b
)
default: null
hooks: array(
)
)
)
returnType: null
@ -235,6 +251,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -247,6 +265,8 @@ array(
name: b
)
default: null
hooks: array(
)
)
)
returnType: null

View File

@ -28,6 +28,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
)
uses: array(
@ -60,6 +62,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
)
uses: array(
@ -120,6 +124,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
)
uses: array(
@ -162,6 +168,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
)
uses: array(

View File

@ -211,6 +211,8 @@ array(
name: x
)
default: null
hooks: array(
)
)
)
uses: array(
@ -289,6 +291,8 @@ array(
name: null
)
)
hooks: array(
)
)
)
uses: array(

View File

@ -133,6 +133,8 @@ array(
default: null
)
)
hooks: array(
)
)
5: Stmt_Property(
attrGroups: array(
@ -147,6 +149,8 @@ array(
default: null
)
)
hooks: array(
)
)
6: Stmt_ClassConst(
attrGroups: array(

View File

@ -159,6 +159,8 @@ array(
name: param
)
default: null
hooks: array(
)
)
)
returnType: null
@ -189,6 +191,8 @@ array(
default: null
)
)
hooks: array(
)
)
)
)

View File

@ -102,6 +102,8 @@ array(
default: null
)
)
hooks: array(
)
)
)
)

View File

@ -37,6 +37,8 @@ array(
default: null
)
)
hooks: array(
)
)
1: Stmt_Property(
attrGroups: array(
@ -51,6 +53,8 @@ array(
default: null
)
)
hooks: array(
)
)
2: Stmt_ClassMethod(
attrGroups: array(

View File

@ -28,6 +28,8 @@ array(
default: null
)
)
hooks: array(
)
)
)
)
@ -61,6 +63,8 @@ array(
default: null
)
)
hooks: array(
)
)
)
)
@ -94,6 +98,8 @@ array(
default: null
)
)
hooks: array(
)
)
)
)
@ -159,6 +165,8 @@ array(
default: null
)
)
hooks: array(
)
)
)
)

View File

@ -33,6 +33,8 @@ array(
default: null
)
)
hooks: array(
)
)
1: Stmt_ClassMethod(
attrGroups: array(

View File

@ -36,6 +36,8 @@ array(
default: null
)
)
hooks: array(
)
)
1: Stmt_Property(
attrGroups: array(
@ -52,6 +54,8 @@ array(
default: null
)
)
hooks: array(
)
)
2: Stmt_Property(
attrGroups: array(
@ -70,6 +74,8 @@ array(
default: null
)
)
hooks: array(
)
)
3: Stmt_Property(
attrGroups: array(
@ -88,6 +94,8 @@ array(
default: null
)
)
hooks: array(
)
)
)
)

View File

@ -0,0 +1,525 @@
Property hooks
-----
<?php
class Test {
public $prop {
get { return 42; }
set { echo $value; }
}
private $prop2 {
get => 42;
set => $value;
}
abstract $prop3 {
&get;
set;
}
public $prop4 {
final get { return 42; }
set(string $value) { }
}
}
-----
array(
0: Stmt_Class(
attrGroups: array(
)
flags: 0
name: Identifier(
name: Test
)
extends: null
implements: array(
)
stmts: array(
0: Stmt_Property(
attrGroups: array(
)
flags: PUBLIC (1)
type: null
props: array(
0: PropertyItem(
name: VarLikeIdentifier(
name: prop
)
default: null
)
)
hooks: array(
0: PropertyHook(
attrGroups: array(
)
flags: 0
byRef: false
name: Identifier(
name: get
)
params: array(
)
body: array(
0: Stmt_Return(
expr: Scalar_Int(
value: 42
)
)
)
)
1: PropertyHook(
attrGroups: array(
)
flags: 0
byRef: false
name: Identifier(
name: set
)
params: array(
)
body: array(
0: Stmt_Echo(
exprs: array(
0: Expr_Variable(
name: value
)
)
)
)
)
)
)
1: Stmt_Property(
attrGroups: array(
)
flags: PRIVATE (4)
type: null
props: array(
0: PropertyItem(
name: VarLikeIdentifier(
name: prop2
)
default: null
)
)
hooks: array(
0: PropertyHook(
attrGroups: array(
)
flags: 0
byRef: false
name: Identifier(
name: get
)
params: array(
)
body: Scalar_Int(
value: 42
)
)
1: PropertyHook(
attrGroups: array(
)
flags: 0
byRef: false
name: Identifier(
name: set
)
params: array(
)
body: Expr_Variable(
name: value
)
)
)
)
2: Stmt_Property(
attrGroups: array(
)
flags: ABSTRACT (16)
type: null
props: array(
0: PropertyItem(
name: VarLikeIdentifier(
name: prop3
)
default: null
)
)
hooks: array(
0: PropertyHook(
attrGroups: array(
)
flags: 0
byRef: true
name: Identifier(
name: get
)
params: array(
)
body: null
)
1: PropertyHook(
attrGroups: array(
)
flags: 0
byRef: false
name: Identifier(
name: set
)
params: array(
)
body: null
)
)
)
3: Stmt_Property(
attrGroups: array(
)
flags: PUBLIC (1)
type: null
props: array(
0: PropertyItem(
name: VarLikeIdentifier(
name: prop4
)
default: null
)
)
hooks: array(
0: PropertyHook(
attrGroups: array(
)
flags: FINAL (32)
byRef: false
name: Identifier(
name: get
)
params: array(
)
body: array(
0: Stmt_Return(
expr: Scalar_Int(
value: 42
)
)
)
)
1: PropertyHook(
attrGroups: array(
)
flags: 0
byRef: false
name: Identifier(
name: set
)
params: array(
0: Param(
attrGroups: array(
)
flags: 0
type: Identifier(
name: string
)
byRef: false
variadic: false
var: Expr_Variable(
name: value
)
default: null
hooks: array(
)
)
)
body: array(
)
)
)
)
)
)
)
-----
<?php
class Test {
public $prop {}
public function __construct(public $prop2 {}) {}
}
-----
Property hook list cannot be empty from 3:18 to 3:18
Property hook list cannot be empty from 4:47 to 4:47
array(
0: Stmt_Class(
attrGroups: array(
)
flags: 0
name: Identifier(
name: Test
)
extends: null
implements: array(
)
stmts: array(
0: Stmt_Property(
attrGroups: array(
)
flags: PUBLIC (1)
type: null
props: array(
0: PropertyItem(
name: VarLikeIdentifier(
name: prop
)
default: null
)
)
hooks: array(
)
)
1: Stmt_ClassMethod(
attrGroups: array(
)
flags: PUBLIC (1)
byRef: false
name: Identifier(
name: __construct
)
params: array(
0: Param(
attrGroups: array(
)
flags: PUBLIC (1)
type: null
byRef: false
variadic: false
var: Expr_Variable(
name: prop2
)
default: null
hooks: array(
)
)
)
returnType: null
stmts: array(
)
)
)
)
)
-----
<?php
class Test {
public $prop {
get() => 42;
}
}
-----
get hook must not have a parameter list from 4:12 to 4:12
array(
0: Stmt_Class(
attrGroups: array(
)
flags: 0
name: Identifier(
name: Test
)
extends: null
implements: array(
)
stmts: array(
0: Stmt_Property(
attrGroups: array(
)
flags: PUBLIC (1)
type: null
props: array(
0: PropertyItem(
name: VarLikeIdentifier(
name: prop
)
default: null
)
)
hooks: array(
0: PropertyHook(
attrGroups: array(
)
flags: 0
byRef: false
name: Identifier(
name: get
)
params: array(
)
body: Scalar_Int(
value: 42
)
)
)
)
)
)
)
-----
<?php
class Test {
public $prop { FOO => bar; }
}
-----
Unknown hook "FOO", expected "get" or "set" from 3:20 to 3:22
array(
0: Stmt_Class(
attrGroups: array(
)
flags: 0
name: Identifier(
name: Test
)
extends: null
implements: array(
)
stmts: array(
0: Stmt_Property(
attrGroups: array(
)
flags: PUBLIC (1)
type: null
props: array(
0: PropertyItem(
name: VarLikeIdentifier(
name: prop
)
default: null
)
)
hooks: array(
0: PropertyHook(
attrGroups: array(
)
flags: 0
byRef: false
name: Identifier(
name: FOO
)
params: array(
)
body: Expr_ConstFetch(
name: Name(
name: bar
)
)
)
)
)
)
)
)
-----
<?php
class Test {
public $prop {
public public get;
protected get;
private get;
abstract static get;
readonly get;
}
}
-----
Cannot use the public modifier on a property hook from 4:9 to 4:14
Multiple access type modifiers are not allowed from 4:16 to 4:21
Cannot use the public modifier on a property hook from 4:16 to 4:21
Cannot use the protected modifier on a property hook from 5:9 to 5:17
Cannot use the private modifier on a property hook from 6:9 to 6:15
Cannot use the abstract modifier on a property hook from 7:9 to 7:16
Cannot use the static modifier on a property hook from 7:18 to 7:23
Cannot use the readonly modifier on a property hook from 8:9 to 8:16
array(
0: Stmt_Class(
attrGroups: array(
)
flags: 0
name: Identifier(
name: Test
)
extends: null
implements: array(
)
stmts: array(
0: Stmt_Property(
attrGroups: array(
)
flags: PUBLIC (1)
type: null
props: array(
0: PropertyItem(
name: VarLikeIdentifier(
name: prop
)
default: null
)
)
hooks: array(
0: PropertyHook(
attrGroups: array(
)
flags: PUBLIC (1)
byRef: false
name: Identifier(
name: get
)
params: array(
)
body: null
)
1: PropertyHook(
attrGroups: array(
)
flags: PROTECTED (2)
byRef: false
name: Identifier(
name: get
)
params: array(
)
body: null
)
2: PropertyHook(
attrGroups: array(
)
flags: PRIVATE (4)
byRef: false
name: Identifier(
name: get
)
params: array(
)
body: null
)
3: PropertyHook(
attrGroups: array(
)
flags: ABSTRACT | STATIC (24)
byRef: false
name: Identifier(
name: get
)
params: array(
)
body: null
)
4: PropertyHook(
attrGroups: array(
)
flags: READONLY (64)
byRef: false
name: Identifier(
name: get
)
params: array(
)
body: null
)
)
)
)
)
)

View File

@ -33,6 +33,8 @@ array(
default: null
)
)
hooks: array(
)
)
1: Stmt_Property(
attrGroups: array(
@ -47,6 +49,8 @@ array(
default: null
)
)
hooks: array(
)
)
2: Stmt_Property(
attrGroups: array(
@ -61,6 +65,8 @@ array(
default: null
)
)
hooks: array(
)
)
3: Stmt_Property(
attrGroups: array(
@ -75,6 +81,8 @@ array(
default: null
)
)
hooks: array(
)
)
)
)

View File

@ -8,6 +8,8 @@ class Point {
protected array $y = [],
private string $z = 'hello',
public readonly int $a = 0,
public $h { set => $value; },
public $g = 1 { get => 2; },
) {}
}
-----
@ -47,6 +49,8 @@ array(
default: Scalar_Float(
value: 0
)
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -64,6 +68,8 @@ array(
items: array(
)
)
hooks: array(
)
)
2: Param(
attrGroups: array(
@ -80,6 +86,8 @@ array(
default: Scalar_String(
value: hello
)
hooks: array(
)
)
3: Param(
attrGroups: array(
@ -96,6 +104,66 @@ array(
default: Scalar_Int(
value: 0
)
hooks: array(
)
)
4: Param(
attrGroups: array(
)
flags: PUBLIC (1)
type: null
byRef: false
variadic: false
var: Expr_Variable(
name: h
)
default: null
hooks: array(
0: PropertyHook(
attrGroups: array(
)
flags: 0
byRef: false
name: Identifier(
name: set
)
params: array(
)
body: Expr_Variable(
name: value
)
)
)
)
5: Param(
attrGroups: array(
)
flags: PUBLIC (1)
type: null
byRef: false
variadic: false
var: Expr_Variable(
name: g
)
default: Scalar_Int(
value: 1
)
hooks: array(
0: PropertyHook(
attrGroups: array(
)
flags: 0
byRef: false
name: Identifier(
name: get
)
params: array(
)
body: Scalar_Int(
value: 2
)
)
)
)
)
returnType: null

View File

@ -83,6 +83,8 @@ array(
)
)
)
hooks: array(
)
)
2: Stmt_Property(
attrGroups: array(
@ -97,6 +99,8 @@ array(
default: null
)
)
hooks: array(
)
)
3: Stmt_Property(
attrGroups: array(
@ -111,6 +115,8 @@ array(
default: null
)
)
hooks: array(
)
)
4: Stmt_ClassMethod(
attrGroups: array(
@ -146,6 +152,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
)
returnType: null

View File

@ -25,6 +25,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -39,6 +41,8 @@ array(
name: b
)
default: null
hooks: array(
)
)
2: Param(
attrGroups: array(
@ -53,6 +57,8 @@ array(
name: c
)
default: null
hooks: array(
)
)
3: Param(
attrGroups: array(
@ -67,6 +73,8 @@ array(
name: d
)
default: null
hooks: array(
)
)
4: Param(
attrGroups: array(
@ -81,6 +89,8 @@ array(
name: e
)
default: null
hooks: array(
)
)
5: Param(
attrGroups: array(
@ -95,6 +105,8 @@ array(
name: f
)
default: null
hooks: array(
)
)
6: Param(
attrGroups: array(
@ -109,6 +121,8 @@ array(
name: g
)
default: null
hooks: array(
)
)
)
returnType: Identifier(

View File

@ -25,6 +25,8 @@ array(
name: b
)
default: null
hooks: array(
)
)
)
returnType: null
@ -50,6 +52,8 @@ array(
name: b
)
default: null
hooks: array(
)
)
)
returnType: null

View File

@ -38,6 +38,8 @@ array(
name: null
)
)
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -52,6 +54,8 @@ array(
default: Scalar_String(
value: foo
)
hooks: array(
)
)
2: Param(
attrGroups: array(
@ -71,6 +75,8 @@ array(
name: B
)
)
hooks: array(
)
)
3: Param(
attrGroups: array(
@ -87,6 +93,8 @@ array(
value: 1
)
)
hooks: array(
)
)
4: Param(
attrGroups: array(
@ -103,6 +111,8 @@ array(
value: 1
)
)
hooks: array(
)
)
5: Param(
attrGroups: array(
@ -118,6 +128,8 @@ array(
items: array(
)
)
hooks: array(
)
)
6: Param(
attrGroups: array(
@ -133,6 +145,8 @@ array(
items: array(
)
)
hooks: array(
)
)
7: Param(
attrGroups: array(
@ -156,6 +170,8 @@ array(
)
)
)
hooks: array(
)
)
8: Param(
attrGroups: array(
@ -189,6 +205,8 @@ array(
)
)
)
hooks: array(
)
)
)
returnType: null

View File

@ -57,6 +57,8 @@ array(
default: null
)
)
hooks: array(
)
)
1: Stmt_Property(
attrGroups: array(
@ -87,6 +89,8 @@ array(
default: null
)
)
hooks: array(
)
)
)
)
@ -132,6 +136,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
)
returnType: UnionType(

View File

@ -42,6 +42,8 @@ array(
default: null
)
)
hooks: array(
)
)
)
)
@ -73,6 +75,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
)
returnType: IntersectionType(

View File

@ -29,6 +29,8 @@ array(
name: bar
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -45,6 +47,8 @@ array(
name: foo
)
default: null
hooks: array(
)
)
)
returnType: NullableType(

View File

@ -25,6 +25,8 @@ array(
name: bar
)
default: null
hooks: array(
)
)
)
returnType: null
@ -74,6 +76,8 @@ array(
name: name
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -86,6 +90,8 @@ array(
name: value
)
default: null
hooks: array(
)
)
)
returnType: null
@ -118,6 +124,8 @@ array(
name: foo
)
default: null
hooks: array(
)
)
)
returnType: null

View File

@ -24,6 +24,8 @@ array(
name: b
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -38,6 +40,8 @@ array(
name: c
)
default: null
hooks: array(
)
)
2: Param(
attrGroups: array(
@ -52,6 +56,8 @@ array(
name: d
)
default: null
hooks: array(
)
)
3: Param(
attrGroups: array(
@ -66,6 +72,8 @@ array(
name: f
)
default: null
hooks: array(
)
)
)
returnType: null

View File

@ -34,6 +34,8 @@ array(
name: a1
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -48,6 +50,8 @@ array(
name: a2
)
default: null
hooks: array(
)
)
2: Param(
attrGroups: array(
@ -62,6 +66,8 @@ array(
name: a3
)
default: null
hooks: array(
)
)
3: Param(
attrGroups: array(
@ -76,6 +82,8 @@ array(
name: a4
)
default: null
hooks: array(
)
)
4: Param(
attrGroups: array(
@ -90,6 +98,8 @@ array(
name: a5
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.0
)
@ -107,6 +117,8 @@ array(
name: a6
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.1
)
@ -124,6 +136,8 @@ array(
name: a7
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.2
)
@ -141,6 +155,8 @@ array(
name: a8
)
default: null
hooks: array(
)
comments: array(
0: // PHP 8.0
)
@ -158,6 +174,8 @@ array(
name: a9
)
default: null
hooks: array(
)
comments: array(
0: // PHP 8.0
)
@ -228,6 +246,8 @@ array(
name: a1
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -242,6 +262,8 @@ array(
name: a2
)
default: null
hooks: array(
)
)
2: Param(
attrGroups: array(
@ -256,6 +278,8 @@ array(
name: a3
)
default: null
hooks: array(
)
)
3: Param(
attrGroups: array(
@ -270,6 +294,8 @@ array(
name: a4
)
default: null
hooks: array(
)
)
4: Param(
attrGroups: array(
@ -284,6 +310,8 @@ array(
name: a5
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.0
)
@ -301,6 +329,8 @@ array(
name: a6
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.1
)
@ -318,6 +348,8 @@ array(
name: a7
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.2
)
@ -335,6 +367,8 @@ array(
name: a8
)
default: null
hooks: array(
)
comments: array(
0: // PHP 8.0
)
@ -352,6 +386,8 @@ array(
name: a9
)
default: null
hooks: array(
)
comments: array(
0: // PHP 8.0
)
@ -422,6 +458,8 @@ array(
name: a1
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -436,6 +474,8 @@ array(
name: a2
)
default: null
hooks: array(
)
)
2: Param(
attrGroups: array(
@ -450,6 +490,8 @@ array(
name: a3
)
default: null
hooks: array(
)
)
3: Param(
attrGroups: array(
@ -464,6 +506,8 @@ array(
name: a4
)
default: null
hooks: array(
)
)
4: Param(
attrGroups: array(
@ -478,6 +522,8 @@ array(
name: a5
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.0
)
@ -495,6 +541,8 @@ array(
name: a6
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.1
)
@ -512,6 +560,8 @@ array(
name: a7
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.2
)
@ -529,6 +579,8 @@ array(
name: a8
)
default: null
hooks: array(
)
comments: array(
0: // PHP 8.0
)
@ -546,6 +598,8 @@ array(
name: a9
)
default: null
hooks: array(
)
comments: array(
0: // PHP 8.0
)
@ -616,6 +670,8 @@ array(
name: a1
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -630,6 +686,8 @@ array(
name: a2
)
default: null
hooks: array(
)
)
2: Param(
attrGroups: array(
@ -644,6 +702,8 @@ array(
name: a3
)
default: null
hooks: array(
)
)
3: Param(
attrGroups: array(
@ -658,6 +718,8 @@ array(
name: a4
)
default: null
hooks: array(
)
)
4: Param(
attrGroups: array(
@ -672,6 +734,8 @@ array(
name: a5
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.0
)
@ -689,6 +753,8 @@ array(
name: a6
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.1
)
@ -706,6 +772,8 @@ array(
name: a7
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.2
)
@ -723,6 +791,8 @@ array(
name: a8
)
default: null
hooks: array(
)
comments: array(
0: // PHP 8.0
)
@ -740,6 +810,8 @@ array(
name: a9
)
default: null
hooks: array(
)
comments: array(
0: // PHP 8.0
)
@ -810,6 +882,8 @@ array(
name: a1
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -824,6 +898,8 @@ array(
name: a2
)
default: null
hooks: array(
)
)
2: Param(
attrGroups: array(
@ -838,6 +914,8 @@ array(
name: a3
)
default: null
hooks: array(
)
)
3: Param(
attrGroups: array(
@ -852,6 +930,8 @@ array(
name: a4
)
default: null
hooks: array(
)
)
4: Param(
attrGroups: array(
@ -866,6 +946,8 @@ array(
name: a5
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.0
)
@ -883,6 +965,8 @@ array(
name: a6
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.1
)
@ -900,6 +984,8 @@ array(
name: a7
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.2
)
@ -917,6 +1003,8 @@ array(
name: a8
)
default: null
hooks: array(
)
comments: array(
0: // PHP 8.0
)
@ -934,6 +1022,8 @@ array(
name: a9
)
default: null
hooks: array(
)
comments: array(
0: // PHP 8.0
)
@ -1004,6 +1094,8 @@ array(
name: a1
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -1018,6 +1110,8 @@ array(
name: a2
)
default: null
hooks: array(
)
)
2: Param(
attrGroups: array(
@ -1032,6 +1126,8 @@ array(
name: a3
)
default: null
hooks: array(
)
)
3: Param(
attrGroups: array(
@ -1046,6 +1142,8 @@ array(
name: a4
)
default: null
hooks: array(
)
)
4: Param(
attrGroups: array(
@ -1060,6 +1158,8 @@ array(
name: a5
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.0
)
@ -1077,6 +1177,8 @@ array(
name: a6
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.1
)
@ -1094,6 +1196,8 @@ array(
name: a7
)
default: null
hooks: array(
)
comments: array(
0: // PHP 7.2
)
@ -1111,6 +1215,8 @@ array(
name: a8
)
default: null
hooks: array(
)
comments: array(
0: // PHP 8.0
)
@ -1128,6 +1234,8 @@ array(
name: a9
)
default: null
hooks: array(
)
comments: array(
0: // PHP 8.0
)

View File

@ -45,6 +45,8 @@ array(
default: null
)
)
hooks: array(
)
)
)
)
@ -76,6 +78,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
)
returnType: UnionType(

View File

@ -26,6 +26,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -38,6 +40,8 @@ array(
name: b
)
default: null
hooks: array(
)
)
)
returnType: null
@ -63,6 +67,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -75,6 +81,8 @@ array(
name: b
)
default: null
hooks: array(
)
)
)
returnType: null
@ -100,6 +108,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -114,6 +124,8 @@ array(
name: b
)
default: null
hooks: array(
)
)
)
returnType: null
@ -139,6 +151,8 @@ array(
name: a
)
default: null
hooks: array(
)
)
1: Param(
attrGroups: array(
@ -153,6 +167,8 @@ array(
name: b
)
default: null
hooks: array(
)
)
)
returnType: null

View File

@ -27,6 +27,8 @@ array(
items: array(
)
)
hooks: array(
)
)
)
returnType: null

View File

@ -56,6 +56,8 @@ array(
args: array(
)
)
hooks: array(
)
)
)
returnType: null
@ -151,6 +153,8 @@ array(
)
)
)
hooks: array(
)
)
)
)

View File

@ -0,0 +1,59 @@
Property hooks
-----
<?php
class Test {
public int $prop {
get {
return $this->prop + 1;
}
set {
$this->prop = $value - 1;
}
}
public $prop = 1 {
#[Attr]
&get => $this->prop;
final set($value) => $value - 1;
}
abstract public $prop {
get;
set;
}
// TODO: Force multiline for hooks?
public function __construct(
public $foo {
get => 42;
set => 123;
},
public $bar
) {}
}
-----
class Test
{
public int $prop {
get {
return $this->prop + 1;
}
set {
$this->prop = $value - 1;
}
}
public $prop = 1 {
#[Attr]
&get => $this->prop;
final set($value) => $value - 1;
}
abstract public $prop {
get;
set;
}
// TODO: Force multiline for hooks?
public function __construct(public $foo {
get => 42;
set => 123;
}, public $bar)
{
}
}