From 1e4a27ae24399f5ed0edaea7c84a31db5dac5df8 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 11 Aug 2024 11:20:00 -0400 Subject: [PATCH] Support parsing of PHP 8.4 property hooks As part of this, stricten the parsing of property names and use a narrower syntax but reuse AssignmentExpression for backwards compatibility of applications that originally used tolerant-php-parser's result of parseExpression. References: https://wiki.php.net/rfc/property-hooks and the linked php-src PR's zend_language_parser.y https://wiki.php.net/rfc/property-hooks#abbreviated_syntax https://wiki.php.net/rfc/property-hooks#interaction_with_constructor_property_promotion --- src/Node/Parameter.php | 5 +- src/Node/PropertyDeclaration.php | 5 + src/Node/PropertyHook.php | 44 ++ src/Node/PropertyHooks.php | 28 + src/Parser.php | 117 +++- tests/cases/parser/classMethods3.php.tree | 6 +- tests/cases/parser/classMethods4.php.tree | 6 +- .../cases/parser/dnfTypesParameter1.php.tree | 3 +- .../cases/parser/dnfTypesParameter2.php.tree | 3 +- .../cases/parser/dnfTypesParameter3.php.tree | 3 +- .../cases/parser/dnfTypesParameter4.php.tree | 3 +- .../cases/parser/dnfTypesParameter5.php.tree | 3 +- tests/cases/parser/dnfTypesProperty1.php.tree | 1 + tests/cases/parser/functions10.php.tree | 6 +- tests/cases/parser/functions11.php.tree | 6 +- tests/cases/parser/functions12.php.tree | 6 +- tests/cases/parser/functions13.php.tree | 6 +- tests/cases/parser/functions14.php.tree | 9 +- tests/cases/parser/functions15.php.tree | 9 +- tests/cases/parser/functions16.php.tree | 3 +- tests/cases/parser/functions17.php.tree | 6 +- tests/cases/parser/functions18.php.tree | 6 +- tests/cases/parser/functions3.php.tree | 6 +- tests/cases/parser/functions6.php.tree | 6 +- tests/cases/parser/functions7.php.tree | 6 +- tests/cases/parser/functions8.php.tree | 6 +- tests/cases/parser/functions9.php.tree | 6 +- .../parser/interfaceDeclaration10.php.tree | 6 +- .../parser/interfaceDeclaration8.php.tree | 6 +- .../parser/interfaceDeclaration9.php.tree | 6 +- .../intersectionTypeParameter1.php.tree | 3 +- .../intersectionTypeParameter2.php.tree | 3 +- tests/cases/parser/paramHook1.php | 8 + tests/cases/parser/paramHook1.php.diag | 1 + tests/cases/parser/paramHook1.php.tree | 211 +++++++ .../cases/parser/parameterPromotion1.php.tree | 9 +- .../cases/parser/parameterPromotion2.php.tree | 3 +- tests/cases/parser/parameterTypes1.php.tree | 6 +- .../parser/propertyDeclaration1.php.tree | 1 + tests/cases/parser/propertyDeclaration10.php | 4 + .../parser/propertyDeclaration10.php.diag | 1 + .../parser/propertyDeclaration10.php.tree | 105 ++++ tests/cases/parser/propertyDeclaration11.php | 4 + .../parser/propertyDeclaration11.php.diag | 20 + .../parser/propertyDeclaration11.php.tree | 126 ++++ tests/cases/parser/propertyDeclaration12.php | 4 + .../parser/propertyDeclaration12.php.diag | 14 + .../parser/propertyDeclaration12.php.tree | 127 ++++ .../parser/propertyDeclaration2.php.tree | 1 + .../parser/propertyDeclaration3.php.tree | 1 + .../parser/propertyDeclaration4.php.tree | 1 + .../parser/propertyDeclaration5.php.tree | 1 + tests/cases/parser/propertyDeclaration8.php | 4 + .../parser/propertyDeclaration8.php.diag | 26 + .../parser/propertyDeclaration8.php.tree | 112 ++++ tests/cases/parser/propertyDeclaration9.php | 4 + .../parser/propertyDeclaration9.php.diag | 8 + .../parser/propertyDeclaration9.php.tree | 114 ++++ tests/cases/parser/propertyHook1.php | 4 + tests/cases/parser/propertyHook1.php.diag | 1 + tests/cases/parser/propertyHook1.php.tree | 93 +++ tests/cases/parser/propertyHook2.php | 12 + tests/cases/parser/propertyHook2.php.diag | 1 + tests/cases/parser/propertyHook2.php.tree | 303 ++++++++++ tests/cases/parser/propertyHook3.php | 15 + tests/cases/parser/propertyHook3.php.diag | 1 + tests/cases/parser/propertyHook3.php.tree | 569 ++++++++++++++++++ tests/cases/parser/true.php.tree | 3 +- tests/cases/parser/typedProperties.php.tree | 4 + .../parser/typedPropertiesNoType.php.tree | 1 + .../parser/typedPropertiesSimple.php.tree | 1 + .../cases/parser/unionTypeParameter1.php.tree | 3 +- .../cases/parser/unionTypeParameter2.php.tree | 3 +- tests/cases/parser/unionTypeProperty.php.tree | 2 + .../cases/parser/unionTypeProperty2.php.tree | 1 + tests/cases/parser/yieldExpression18.php.tree | 3 +- tests/cases/parser/yieldExpression19.php.tree | 3 +- tests/cases/parser74/arrowFunction.php.tree | 18 +- .../parser74/arrowFunctionFallback.php.tree | 15 +- .../parser74/arrowFunctionTypes.php.tree | 15 +- .../parser74/arrowFunctionUnionTypes.php.tree | 12 +- tests/cases/parser80/attributes18.php.tree | 3 +- tests/cases/parser80/attributes20.php | 7 + tests/cases/parser80/attributes20.php.diag | 1 + tests/cases/parser80/attributes20.php.tree | 172 ++++++ tests/cases/parser80/attributes4.php.tree | 1 + tests/cases/parser80/attributes5.php.tree | 3 +- tests/cases/parser80/mixedType1.php.tree | 3 +- .../cases/parser81/intersection_type.php.tree | 7 +- .../cases/parser81/readonly_property.php.tree | 2 + 90 files changed, 2449 insertions(+), 87 deletions(-) create mode 100644 src/Node/PropertyHook.php create mode 100644 src/Node/PropertyHooks.php create mode 100644 tests/cases/parser/paramHook1.php create mode 100644 tests/cases/parser/paramHook1.php.diag create mode 100644 tests/cases/parser/paramHook1.php.tree create mode 100644 tests/cases/parser/propertyDeclaration10.php create mode 100644 tests/cases/parser/propertyDeclaration10.php.diag create mode 100644 tests/cases/parser/propertyDeclaration10.php.tree create mode 100644 tests/cases/parser/propertyDeclaration11.php create mode 100644 tests/cases/parser/propertyDeclaration11.php.diag create mode 100644 tests/cases/parser/propertyDeclaration11.php.tree create mode 100644 tests/cases/parser/propertyDeclaration12.php create mode 100644 tests/cases/parser/propertyDeclaration12.php.diag create mode 100644 tests/cases/parser/propertyDeclaration12.php.tree create mode 100644 tests/cases/parser/propertyDeclaration8.php create mode 100644 tests/cases/parser/propertyDeclaration8.php.diag create mode 100644 tests/cases/parser/propertyDeclaration8.php.tree create mode 100644 tests/cases/parser/propertyDeclaration9.php create mode 100644 tests/cases/parser/propertyDeclaration9.php.diag create mode 100644 tests/cases/parser/propertyDeclaration9.php.tree create mode 100644 tests/cases/parser/propertyHook1.php create mode 100644 tests/cases/parser/propertyHook1.php.diag create mode 100644 tests/cases/parser/propertyHook1.php.tree create mode 100644 tests/cases/parser/propertyHook2.php create mode 100644 tests/cases/parser/propertyHook2.php.diag create mode 100644 tests/cases/parser/propertyHook2.php.tree create mode 100644 tests/cases/parser/propertyHook3.php create mode 100644 tests/cases/parser/propertyHook3.php.diag create mode 100644 tests/cases/parser/propertyHook3.php.tree create mode 100644 tests/cases/parser80/attributes20.php create mode 100644 tests/cases/parser80/attributes20.php.diag create mode 100644 tests/cases/parser80/attributes20.php.tree diff --git a/src/Node/Parameter.php b/src/Node/Parameter.php index d3fde6f5..61f940b0 100644 --- a/src/Node/Parameter.php +++ b/src/Node/Parameter.php @@ -31,6 +31,8 @@ class Parameter extends Node { public $equalsToken; /** @var null|Expression */ public $default; + /** @var PropertyHooks|null */ + public $propertyHooks; const CHILD_NAMES = [ 'attributes', @@ -42,7 +44,8 @@ class Parameter extends Node { 'dotDotDotToken', 'variableName', 'equalsToken', - 'default' + 'default', + 'propertyHooks', ]; public function isVariadic() { diff --git a/src/Node/PropertyDeclaration.php b/src/Node/PropertyDeclaration.php index 1995aed5..a30cefae 100644 --- a/src/Node/PropertyDeclaration.php +++ b/src/Node/PropertyDeclaration.php @@ -10,6 +10,7 @@ use Microsoft\PhpParser\ModifiedTypeInterface; use Microsoft\PhpParser\ModifiedTypeTrait; use Microsoft\PhpParser\Node; +use Microsoft\PhpParser\Node\PropertyHooks; use Microsoft\PhpParser\Node\DelimitedList\QualifiedNameList; use Microsoft\PhpParser\Token; @@ -28,6 +29,9 @@ class PropertyDeclaration extends Node implements ModifiedTypeInterface { /** @var DelimitedList\ExpressionList */ public $propertyElements; + /** @var PropertyHooks|null */ + public $propertyHooks; + /** @var Token */ public $semicolon; @@ -37,6 +41,7 @@ class PropertyDeclaration extends Node implements ModifiedTypeInterface { 'questionToken', 'typeDeclarationList', 'propertyElements', + 'propertyHooks', 'semicolon' ]; } diff --git a/src/Node/PropertyHook.php b/src/Node/PropertyHook.php new file mode 100644 index 00000000..9d2cadf0 --- /dev/null +++ b/src/Node/PropertyHook.php @@ -0,0 +1,44 @@ +lexer = $this->makeLexer($fileContents); $this->reset(); @@ -877,6 +879,10 @@ private function parseParameterFn() { // TODO add post-parse rule that checks for invalid assignments $parameter->default = $this->parseExpression($parameter); } + + if ($this->token->kind === TokenKind::OpenBraceToken) { + $parameter->propertyHooks = $this->parsePropertyHooks($parameter); + } return $parameter; }; } @@ -1417,7 +1423,7 @@ private function parseStringLiteralExpression2($parentNode): StringLiteral { case TokenKind::DollarOpenBraceToken: case TokenKind::OpenBraceDollarToken: $expression->children[] = $this->eat(TokenKind::DollarOpenBraceToken, TokenKind::OpenBraceDollarToken); - /** + /** * @phpstan-ignore-next-line "Strict comparison using * === between 403|404 and 408 will always evaluate to * false" is wrong because those tokens were eaten above @@ -3423,12 +3429,115 @@ private function parsePropertyDeclaration($parentNode, $modifiers, $questionToke } elseif ($questionToken) { $propertyDeclaration->typeDeclarationList = new MissingToken(TokenKind::PropertyType, $this->token->fullStart); } - $propertyDeclaration->propertyElements = $this->parseExpressionList($propertyDeclaration); - $propertyDeclaration->semicolon = $this->eat1(TokenKind::SemicolonToken); + $propertyDeclaration->propertyElements = $this->parsePropertyNameList($propertyDeclaration); + if ($this->token->kind === TokenKind::OpenBraceToken) { + $propertyDeclaration->propertyHooks = $this->parsePropertyHooks($propertyDeclaration); + } else { + $propertyDeclaration->semicolon = $this->eat1(TokenKind::SemicolonToken); + } return $propertyDeclaration; } + /** + * @param PropertyDeclaration $parentNode + * @return DelimitedList\VariableNameList + */ + private function parsePropertyNameList($parentNode) { + // XXX this used to be implemented with parseExpressionList so keep the same classes. + return $this->parseDelimitedList( + DelimitedList\ExpressionList::class, + TokenKind::CommaToken, + function ($token) { + return $token->kind === TokenKind::VariableName; + }, + $this->parsePropertyVariableNameAndDefault(), + $parentNode + ); + } + + private function parsePropertyVariableNameAndDefault() { + return function ($parentNode) { + // Imitate the format that parseExpression would have returned from when + // parseExpression was originally used. + // This is more precise and rules out parse errors such as `public $propName + 2;` + // This approach also avoids conflict with the deprecated $x{expr} array access syntax. + $variable = new Variable(); + $variable->name = $this->eat1(TokenKind::VariableName); + $equalsToken = $this->eatOptional1(TokenKind::EqualsToken); + if ($equalsToken === null) { + $variable->parent = $parentNode; + return $variable; + } + + $byRefToken = $this->eatOptional1(TokenKind::AmpersandToken); // byRef default is nonsense, but this is a compile-time error instead of a parse error. + $rightOperand = $this->parseExpression($parentNode); // gets overridden in makeBinaryExpression + return $this->makeBinaryExpression($variable, $equalsToken, $byRefToken, $rightOperand, $parentNode); + }; + } + + /** + * @param PropertyDeclaration|Parameter $parent + * @return PropertyHooks + */ + private function parsePropertyHooks(Node $parent) { + $propertyHooks = new PropertyHooks(); + $propertyHooks->parent = $parent; + $propertyHooks->openBrace = $this->eat1(TokenKind::OpenBraceToken); + $hooks = []; + while (in_array($this->getCurrentToken()->kind, self::PROPERTY_HOOK_START_TOKENS, true)) { + $hooks[] = $this->parsePropertyHook($propertyHooks); + } + $propertyHooks->hookDeclarations = $hooks; + $propertyHooks->closeBrace = $this->eat1(TokenKind::CloseBraceToken); + return $propertyHooks; + } + + const PROPERTY_HOOK_START_TOKENS = [ + TokenKind::Name, + TokenKind::AmpersandToken, // by reference + TokenKind::AttributeToken, + ]; + + private function isPropertyHookStart() { + return function ($token) { + return \in_array($token->kind, self::PROPERTY_HOOK_START_TOKENS, true); + }; + } + + /** + * @param PropertyHooks $parentNode + * @return PropertyHook + */ + private function parsePropertyHook($parentNode) { + $node = new PropertyHook(); + $node->parent = $parentNode; + if ($this->getCurrentToken()->kind === TokenKind::AttributeToken) { + $node->attributes = $this->parseAttributeGroups($node); + } + $node->byRefToken = $this->eatOptional1(TokenKind::AmpersandToken); + $node->name = $this->eat1(TokenKind::Name); // "get" or "set" - other values are compile errors, not parse errors. + $node->openParen = $this->eatOptional1(TokenKind::OpenParenToken); + if ($node->openParen) { + $node->parameters = $this->parseDelimitedList( + DelimitedList\ParameterDeclarationList::class, + TokenKind::CommaToken, + $this->isParameterStartFn(), + $this->parseParameterFn(), + $node); + $node->closeParen = $this->eat1(TokenKind::CloseParenToken); + } + // e.g. `get => expr;` or `get { return $expr; }` + $node->arrowToken = $this->eatOptional1(TokenKind::DoubleArrowToken); + if ($node->arrowToken) { + $node->body = $this->parseExpression($node); + $node->semicolon = $this->eat1(TokenKind::SemicolonToken); + } else { + $node->body = $this->parseCompoundStatement($node); + } + return $node; + } + /** * Parse a comma separated qualified name list (e.g. interfaces implemented by a class) * diff --git a/tests/cases/parser/classMethods3.php.tree b/tests/cases/parser/classMethods3.php.tree index ff156ef9..96e3d20a 100644 --- a/tests/cases/parser/classMethods3.php.tree +++ b/tests/cases/parser/classMethods3.php.tree @@ -72,7 +72,8 @@ "textLength": 8 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -93,7 +94,8 @@ "textLength": 6 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/classMethods4.php.tree b/tests/cases/parser/classMethods4.php.tree index eb3536dd..3e147ad6 100644 --- a/tests/cases/parser/classMethods4.php.tree +++ b/tests/cases/parser/classMethods4.php.tree @@ -72,7 +72,8 @@ "textLength": 8 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -93,7 +94,8 @@ "textLength": 6 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/dnfTypesParameter1.php.tree b/tests/cases/parser/dnfTypesParameter1.php.tree index 6da52940..a9ad6e37 100644 --- a/tests/cases/parser/dnfTypesParameter1.php.tree +++ b/tests/cases/parser/dnfTypesParameter1.php.tree @@ -111,7 +111,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/dnfTypesParameter2.php.tree b/tests/cases/parser/dnfTypesParameter2.php.tree index 22b9aedd..218278a0 100644 --- a/tests/cases/parser/dnfTypesParameter2.php.tree +++ b/tests/cases/parser/dnfTypesParameter2.php.tree @@ -100,7 +100,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/dnfTypesParameter3.php.tree b/tests/cases/parser/dnfTypesParameter3.php.tree index 9cdf7078..00311b61 100644 --- a/tests/cases/parser/dnfTypesParameter3.php.tree +++ b/tests/cases/parser/dnfTypesParameter3.php.tree @@ -71,7 +71,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/dnfTypesParameter4.php.tree b/tests/cases/parser/dnfTypesParameter4.php.tree index 91a5fd2a..7054ba96 100644 --- a/tests/cases/parser/dnfTypesParameter4.php.tree +++ b/tests/cases/parser/dnfTypesParameter4.php.tree @@ -73,7 +73,8 @@ "textLength": 0 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/dnfTypesParameter5.php.tree b/tests/cases/parser/dnfTypesParameter5.php.tree index 719e80f9..ff37d00e 100644 --- a/tests/cases/parser/dnfTypesParameter5.php.tree +++ b/tests/cases/parser/dnfTypesParameter5.php.tree @@ -104,7 +104,8 @@ "textLength": 0 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/dnfTypesProperty1.php.tree b/tests/cases/parser/dnfTypesProperty1.php.tree index 8356cefc..82aaca40 100644 --- a/tests/cases/parser/dnfTypesProperty1.php.tree +++ b/tests/cases/parser/dnfTypesProperty1.php.tree @@ -135,6 +135,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/functions10.php.tree b/tests/cases/parser/functions10.php.tree index 4d0b84a1..e66f895a 100644 --- a/tests/cases/parser/functions10.php.tree +++ b/tests/cases/parser/functions10.php.tree @@ -44,7 +44,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -71,7 +72,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/functions11.php.tree b/tests/cases/parser/functions11.php.tree index d05667b1..8fb4a4d9 100644 --- a/tests/cases/parser/functions11.php.tree +++ b/tests/cases/parser/functions11.php.tree @@ -44,7 +44,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -88,7 +89,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/functions12.php.tree b/tests/cases/parser/functions12.php.tree index be4536e8..8f5617f7 100644 --- a/tests/cases/parser/functions12.php.tree +++ b/tests/cases/parser/functions12.php.tree @@ -44,7 +44,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -85,7 +86,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/functions13.php.tree b/tests/cases/parser/functions13.php.tree index f034806c..103c01fe 100644 --- a/tests/cases/parser/functions13.php.tree +++ b/tests/cases/parser/functions13.php.tree @@ -44,7 +44,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -85,7 +86,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { diff --git a/tests/cases/parser/functions14.php.tree b/tests/cases/parser/functions14.php.tree index 4f274fdc..3b337ebc 100644 --- a/tests/cases/parser/functions14.php.tree +++ b/tests/cases/parser/functions14.php.tree @@ -44,7 +44,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -85,7 +86,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -106,7 +108,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/functions15.php.tree b/tests/cases/parser/functions15.php.tree index 13421349..0186b9af 100644 --- a/tests/cases/parser/functions15.php.tree +++ b/tests/cases/parser/functions15.php.tree @@ -44,7 +44,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -85,7 +86,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -109,7 +111,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/functions16.php.tree b/tests/cases/parser/functions16.php.tree index 15d6d764..62944fe6 100644 --- a/tests/cases/parser/functions16.php.tree +++ b/tests/cases/parser/functions16.php.tree @@ -44,7 +44,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/functions17.php.tree b/tests/cases/parser/functions17.php.tree index 2d8cd231..a7d61fcb 100644 --- a/tests/cases/parser/functions17.php.tree +++ b/tests/cases/parser/functions17.php.tree @@ -64,7 +64,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -97,7 +98,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/functions18.php.tree b/tests/cases/parser/functions18.php.tree index 56fc06f5..5b3a6b91 100644 --- a/tests/cases/parser/functions18.php.tree +++ b/tests/cases/parser/functions18.php.tree @@ -61,7 +61,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -91,7 +92,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/functions3.php.tree b/tests/cases/parser/functions3.php.tree index 4b2182ed..f1c6a9b0 100644 --- a/tests/cases/parser/functions3.php.tree +++ b/tests/cases/parser/functions3.php.tree @@ -61,7 +61,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -91,7 +92,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/functions6.php.tree b/tests/cases/parser/functions6.php.tree index 9e09f45c..6f80a8b1 100644 --- a/tests/cases/parser/functions6.php.tree +++ b/tests/cases/parser/functions6.php.tree @@ -55,7 +55,8 @@ "textLength": 2 } } - } + }, + "propertyHooks": null } }, { @@ -76,7 +77,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/functions7.php.tree b/tests/cases/parser/functions7.php.tree index bb10e305..555f7f1c 100644 --- a/tests/cases/parser/functions7.php.tree +++ b/tests/cases/parser/functions7.php.tree @@ -51,7 +51,8 @@ "error": "MissingToken", "kind": "Expression", "textLength": 0 - } + }, + "propertyHooks": null } }, { @@ -72,7 +73,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/functions8.php.tree b/tests/cases/parser/functions8.php.tree index f3c4953f..07dcd1ba 100644 --- a/tests/cases/parser/functions8.php.tree +++ b/tests/cases/parser/functions8.php.tree @@ -44,7 +44,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -65,7 +66,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/functions9.php.tree b/tests/cases/parser/functions9.php.tree index cf02019b..ae02a5f3 100644 --- a/tests/cases/parser/functions9.php.tree +++ b/tests/cases/parser/functions9.php.tree @@ -44,7 +44,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -68,7 +69,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/interfaceDeclaration10.php.tree b/tests/cases/parser/interfaceDeclaration10.php.tree index a96d2a5e..7f20c230 100644 --- a/tests/cases/parser/interfaceDeclaration10.php.tree +++ b/tests/cases/parser/interfaceDeclaration10.php.tree @@ -69,7 +69,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -100,7 +101,8 @@ "textLength": 1 } } - } + }, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/interfaceDeclaration8.php.tree b/tests/cases/parser/interfaceDeclaration8.php.tree index ad10fd8b..c9afe318 100644 --- a/tests/cases/parser/interfaceDeclaration8.php.tree +++ b/tests/cases/parser/interfaceDeclaration8.php.tree @@ -69,7 +69,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -90,7 +91,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/interfaceDeclaration9.php.tree b/tests/cases/parser/interfaceDeclaration9.php.tree index bbcf73df..760dac7e 100644 --- a/tests/cases/parser/interfaceDeclaration9.php.tree +++ b/tests/cases/parser/interfaceDeclaration9.php.tree @@ -69,7 +69,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -100,7 +101,8 @@ "textLength": 1 } } - } + }, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/intersectionTypeParameter1.php.tree b/tests/cases/parser/intersectionTypeParameter1.php.tree index 6104ca92..103b148f 100644 --- a/tests/cases/parser/intersectionTypeParameter1.php.tree +++ b/tests/cases/parser/intersectionTypeParameter1.php.tree @@ -78,7 +78,8 @@ "textLength": 0 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/intersectionTypeParameter2.php.tree b/tests/cases/parser/intersectionTypeParameter2.php.tree index 44cf3b08..11ffc9bb 100644 --- a/tests/cases/parser/intersectionTypeParameter2.php.tree +++ b/tests/cases/parser/intersectionTypeParameter2.php.tree @@ -97,7 +97,8 @@ "textLength": 0 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/paramHook1.php b/tests/cases/parser/paramHook1.php new file mode 100644 index 00000000..db250448 --- /dev/null +++ b/tests/cases/parser/paramHook1.php @@ -0,0 +1,8 @@ + strtolower($value); } + ) {} +} diff --git a/tests/cases/parser/paramHook1.php.diag b/tests/cases/parser/paramHook1.php.diag new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/tests/cases/parser/paramHook1.php.diag @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/tests/cases/parser/paramHook1.php.tree b/tests/cases/parser/paramHook1.php.tree new file mode 100644 index 00000000..d4f60b53 --- /dev/null +++ b/tests/cases/parser/paramHook1.php.tree @@ -0,0 +1,211 @@ +{ + "SourceFileNode": { + "statementList": [ + { + "InlineHtml": { + "scriptSectionEndTag": null, + "text": null, + "scriptSectionStartTag": { + "kind": "ScriptSectionStartTag", + "textLength": 6 + } + } + }, + { + "ClassDeclaration": { + "attributes": null, + "abstractOrFinalModifier": null, + "modifiers": [], + "classKeyword": { + "kind": "ClassKeyword", + "textLength": 5 + }, + "name": { + "kind": "Name", + "textLength": 4 + }, + "classBaseClause": null, + "classInterfaceClause": null, + "classMembers": { + "ClassMembersNode": { + "openBrace": { + "kind": "OpenBraceToken", + "textLength": 1 + }, + "classMemberDeclarations": [ + { + "MethodDeclaration": { + "attributes": null, + "modifiers": [ + { + "kind": "PublicKeyword", + "textLength": 6 + } + ], + "functionKeyword": { + "kind": "FunctionKeyword", + "textLength": 8 + }, + "byRefToken": null, + "name": { + "kind": "Name", + "textLength": 11 + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "parameters": { + "ParameterDeclarationList": { + "children": [ + { + "Parameter": { + "attributes": null, + "visibilityToken": { + "kind": "PublicKeyword", + "textLength": 6 + }, + "modifiers": null, + "questionToken": null, + "typeDeclarationList": { + "QualifiedNameList": { + "children": [ + { + "kind": "StringReservedWord", + "textLength": 6 + } + ] + } + }, + "byRefToken": null, + "dotDotDotToken": null, + "variableName": { + "kind": "VariableName", + "textLength": 9 + }, + "equalsToken": null, + "default": null, + "propertyHooks": { + "PropertyHooks": { + "openBrace": { + "kind": "OpenBraceToken", + "textLength": 1 + }, + "hookDeclarations": [ + { + "PropertyHook": { + "attributes": null, + "byRefToken": null, + "name": { + "kind": "Name", + "textLength": 3 + }, + "openParen": null, + "parameters": null, + "closeParen": null, + "arrowToken": { + "kind": "DoubleArrowToken", + "textLength": 2 + }, + "body": { + "CallExpression": { + "callableExpression": { + "QualifiedName": { + "globalSpecifier": null, + "relativeSpecifier": null, + "nameParts": [ + { + "kind": "Name", + "textLength": 10 + } + ] + } + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "argumentExpressionList": { + "ArgumentExpressionList": { + "children": [ + { + "ArgumentExpression": { + "name": null, + "colonToken": null, + "dotDotDotToken": null, + "expression": { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 6 + } + } + } + } + } + ] + } + }, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 + } + } + }, + "semicolon": { + "kind": "SemicolonToken", + "textLength": 1 + } + } + } + ], + "closeBrace": { + "kind": "CloseBraceToken", + "textLength": 1 + } + } + } + } + } + ] + } + }, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 + }, + "colonToken": null, + "questionToken": null, + "returnTypeList": null, + "compoundStatementOrSemicolon": { + "CompoundStatementNode": { + "openBrace": { + "kind": "OpenBraceToken", + "textLength": 1 + }, + "statements": [], + "closeBrace": { + "kind": "CloseBraceToken", + "textLength": 1 + } + } + } + } + } + ], + "closeBrace": { + "kind": "CloseBraceToken", + "textLength": 1 + } + } + } + } + } + ], + "endOfFileToken": { + "kind": "EndOfFileToken", + "textLength": 0 + } + } +} \ No newline at end of file diff --git a/tests/cases/parser/parameterPromotion1.php.tree b/tests/cases/parser/parameterPromotion1.php.tree index 44e83ae6..a3388b17 100644 --- a/tests/cases/parser/parameterPromotion1.php.tree +++ b/tests/cases/parser/parameterPromotion1.php.tree @@ -75,7 +75,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -108,7 +109,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -132,7 +134,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/parameterPromotion2.php.tree b/tests/cases/parser/parameterPromotion2.php.tree index 62983624..e30ce698 100644 --- a/tests/cases/parser/parameterPromotion2.php.tree +++ b/tests/cases/parser/parameterPromotion2.php.tree @@ -80,7 +80,8 @@ "textLength": 4 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/parameterTypes1.php.tree b/tests/cases/parser/parameterTypes1.php.tree index 55f2f7c9..c97f5d07 100644 --- a/tests/cases/parser/parameterTypes1.php.tree +++ b/tests/cases/parser/parameterTypes1.php.tree @@ -53,7 +53,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -83,7 +84,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/propertyDeclaration1.php.tree b/tests/cases/parser/propertyDeclaration1.php.tree index 9a97493e..4b624572 100644 --- a/tests/cases/parser/propertyDeclaration1.php.tree +++ b/tests/cases/parser/propertyDeclaration1.php.tree @@ -59,6 +59,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/propertyDeclaration10.php b/tests/cases/parser/propertyDeclaration10.php new file mode 100644 index 00000000..5d74ab3a --- /dev/null +++ b/tests/cases/parser/propertyDeclaration10.php @@ -0,0 +1,4 @@ + $this->_baz; + set { + $this->_baz = strtoupper($value); + } + } +} diff --git a/tests/cases/parser/propertyHook2.php.diag b/tests/cases/parser/propertyHook2.php.diag new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/tests/cases/parser/propertyHook2.php.diag @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/tests/cases/parser/propertyHook2.php.tree b/tests/cases/parser/propertyHook2.php.tree new file mode 100644 index 00000000..d857fe2f --- /dev/null +++ b/tests/cases/parser/propertyHook2.php.tree @@ -0,0 +1,303 @@ +{ + "SourceFileNode": { + "statementList": [ + { + "InlineHtml": { + "scriptSectionEndTag": null, + "text": null, + "scriptSectionStartTag": { + "kind": "ScriptSectionStartTag", + "textLength": 6 + } + } + }, + { + "ClassDeclaration": { + "attributes": null, + "abstractOrFinalModifier": null, + "modifiers": [], + "classKeyword": { + "kind": "ClassKeyword", + "textLength": 5 + }, + "name": { + "kind": "Name", + "textLength": 3 + }, + "classBaseClause": null, + "classInterfaceClause": null, + "classMembers": { + "ClassMembersNode": { + "openBrace": { + "kind": "OpenBraceToken", + "textLength": 1 + }, + "classMemberDeclarations": [ + { + "PropertyDeclaration": { + "attributes": null, + "modifiers": [ + { + "kind": "PrivateKeyword", + "textLength": 7 + } + ], + "questionToken": null, + "typeDeclarationList": { + "QualifiedNameList": { + "children": [ + { + "kind": "StringReservedWord", + "textLength": 6 + } + ] + } + }, + "propertyElements": { + "ExpressionList": { + "children": [ + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 5 + } + } + } + ] + } + }, + "propertyHooks": null, + "semicolon": { + "kind": "SemicolonToken", + "textLength": 1 + } + } + }, + { + "PropertyDeclaration": { + "attributes": null, + "modifiers": [ + { + "kind": "PublicKeyword", + "textLength": 6 + } + ], + "questionToken": null, + "typeDeclarationList": { + "QualifiedNameList": { + "children": [ + { + "kind": "StringReservedWord", + "textLength": 6 + } + ] + } + }, + "propertyElements": { + "ExpressionList": { + "children": [ + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 4 + } + } + } + ] + } + }, + "propertyHooks": { + "PropertyHooks": { + "openBrace": { + "kind": "OpenBraceToken", + "textLength": 1 + }, + "hookDeclarations": [ + { + "PropertyHook": { + "attributes": null, + "byRefToken": { + "kind": "AmpersandToken", + "textLength": 1 + }, + "name": { + "kind": "Name", + "textLength": 3 + }, + "openParen": null, + "parameters": null, + "closeParen": null, + "arrowToken": { + "kind": "DoubleArrowToken", + "textLength": 2 + }, + "body": { + "MemberAccessExpression": { + "dereferencableExpression": { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 5 + } + } + }, + "arrowToken": { + "kind": "ArrowToken", + "textLength": 2 + }, + "memberName": { + "kind": "Name", + "textLength": 4 + } + } + }, + "semicolon": { + "kind": "SemicolonToken", + "textLength": 1 + } + } + }, + { + "PropertyHook": { + "attributes": null, + "byRefToken": null, + "name": { + "kind": "Name", + "textLength": 3 + }, + "openParen": null, + "parameters": null, + "closeParen": null, + "arrowToken": null, + "body": { + "CompoundStatementNode": { + "openBrace": { + "kind": "OpenBraceToken", + "textLength": 1 + }, + "statements": [ + { + "ExpressionStatement": { + "expression": { + "AssignmentExpression": { + "leftOperand": { + "MemberAccessExpression": { + "dereferencableExpression": { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 5 + } + } + }, + "arrowToken": { + "kind": "ArrowToken", + "textLength": 2 + }, + "memberName": { + "kind": "Name", + "textLength": 4 + } + } + }, + "operator": { + "kind": "EqualsToken", + "textLength": 1 + }, + "byRef": null, + "rightOperand": { + "CallExpression": { + "callableExpression": { + "QualifiedName": { + "globalSpecifier": null, + "relativeSpecifier": null, + "nameParts": [ + { + "kind": "Name", + "textLength": 10 + } + ] + } + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "argumentExpressionList": { + "ArgumentExpressionList": { + "children": [ + { + "ArgumentExpression": { + "name": null, + "colonToken": null, + "dotDotDotToken": null, + "expression": { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 6 + } + } + } + } + } + ] + } + }, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 + } + } + } + } + }, + "semicolon": { + "kind": "SemicolonToken", + "textLength": 1 + } + } + } + ], + "closeBrace": { + "kind": "CloseBraceToken", + "textLength": 1 + } + } + }, + "semicolon": null + } + } + ], + "closeBrace": { + "kind": "CloseBraceToken", + "textLength": 1 + } + } + }, + "semicolon": null + } + } + ], + "closeBrace": { + "kind": "CloseBraceToken", + "textLength": 1 + } + } + } + } + } + ], + "endOfFileToken": { + "kind": "EndOfFileToken", + "textLength": 0 + } + } +} \ No newline at end of file diff --git a/tests/cases/parser/propertyHook3.php b/tests/cases/parser/propertyHook3.php new file mode 100644 index 00000000..d06352ec --- /dev/null +++ b/tests/cases/parser/propertyHook3.php @@ -0,0 +1,15 @@ +first $this->last"; + } + set(string $value) { + [$this->first, $this->last] = explode(' ', $value, 2); + } + } +} diff --git a/tests/cases/parser/propertyHook3.php.diag b/tests/cases/parser/propertyHook3.php.diag new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/tests/cases/parser/propertyHook3.php.diag @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/tests/cases/parser/propertyHook3.php.tree b/tests/cases/parser/propertyHook3.php.tree new file mode 100644 index 00000000..5436f03b --- /dev/null +++ b/tests/cases/parser/propertyHook3.php.tree @@ -0,0 +1,569 @@ +{ + "SourceFileNode": { + "statementList": [ + { + "InlineHtml": { + "scriptSectionEndTag": null, + "text": null, + "scriptSectionStartTag": { + "kind": "ScriptSectionStartTag", + "textLength": 6 + } + } + }, + { + "ClassDeclaration": { + "attributes": null, + "abstractOrFinalModifier": null, + "modifiers": [], + "classKeyword": { + "kind": "ClassKeyword", + "textLength": 5 + }, + "name": { + "kind": "Name", + "textLength": 4 + }, + "classBaseClause": null, + "classInterfaceClause": null, + "classMembers": { + "ClassMembersNode": { + "openBrace": { + "kind": "OpenBraceToken", + "textLength": 1 + }, + "classMemberDeclarations": [ + { + "MethodDeclaration": { + "attributes": null, + "modifiers": [ + { + "kind": "PublicKeyword", + "textLength": 6 + } + ], + "functionKeyword": { + "kind": "FunctionKeyword", + "textLength": 8 + }, + "byRefToken": null, + "name": { + "kind": "Name", + "textLength": 11 + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "parameters": { + "ParameterDeclarationList": { + "children": [ + { + "Parameter": { + "attributes": null, + "visibilityToken": { + "kind": "PublicKeyword", + "textLength": 6 + }, + "modifiers": null, + "questionToken": null, + "typeDeclarationList": { + "QualifiedNameList": { + "children": [ + { + "kind": "StringReservedWord", + "textLength": 6 + } + ] + } + }, + "byRefToken": null, + "dotDotDotToken": null, + "variableName": { + "kind": "VariableName", + "textLength": 6 + }, + "equalsToken": null, + "default": null, + "propertyHooks": null + } + }, + { + "kind": "CommaToken", + "textLength": 1 + }, + { + "Parameter": { + "attributes": null, + "visibilityToken": { + "kind": "PublicKeyword", + "textLength": 6 + }, + "modifiers": null, + "questionToken": null, + "typeDeclarationList": { + "QualifiedNameList": { + "children": [ + { + "kind": "StringReservedWord", + "textLength": 6 + } + ] + } + }, + "byRefToken": null, + "dotDotDotToken": null, + "variableName": { + "kind": "VariableName", + "textLength": 5 + }, + "equalsToken": null, + "default": null, + "propertyHooks": null + } + } + ] + } + }, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 + }, + "colonToken": null, + "questionToken": null, + "returnTypeList": null, + "compoundStatementOrSemicolon": { + "CompoundStatementNode": { + "openBrace": { + "kind": "OpenBraceToken", + "textLength": 1 + }, + "statements": [], + "closeBrace": { + "kind": "CloseBraceToken", + "textLength": 1 + } + } + } + } + }, + { + "PropertyDeclaration": { + "attributes": null, + "modifiers": [ + { + "kind": "PublicKeyword", + "textLength": 6 + } + ], + "questionToken": null, + "typeDeclarationList": { + "QualifiedNameList": { + "children": [ + { + "kind": "StringReservedWord", + "textLength": 6 + } + ] + } + }, + "propertyElements": { + "ExpressionList": { + "children": [ + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 9 + } + } + } + ] + } + }, + "propertyHooks": { + "PropertyHooks": { + "openBrace": { + "kind": "OpenBraceToken", + "textLength": 1 + }, + "hookDeclarations": [ + { + "PropertyHook": { + "attributes": null, + "byRefToken": null, + "name": { + "kind": "Name", + "textLength": 3 + }, + "openParen": null, + "parameters": null, + "closeParen": null, + "arrowToken": null, + "body": { + "CompoundStatementNode": { + "openBrace": { + "kind": "OpenBraceToken", + "textLength": 1 + }, + "statements": [ + { + "ReturnStatement": { + "returnKeyword": { + "kind": "ReturnKeyword", + "textLength": 6 + }, + "expression": { + "StringLiteral": { + "startQuote": { + "kind": "DoubleQuoteToken", + "textLength": 1 + }, + "children": [ + { + "MemberAccessExpression": { + "dereferencableExpression": { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 5 + } + } + }, + "arrowToken": { + "kind": "ArrowToken", + "textLength": 2 + }, + "memberName": { + "kind": "Name", + "textLength": 5 + } + } + }, + { + "kind": "EncapsedAndWhitespace", + "textLength": 1 + }, + { + "MemberAccessExpression": { + "dereferencableExpression": { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 5 + } + } + }, + "arrowToken": { + "kind": "ArrowToken", + "textLength": 2 + }, + "memberName": { + "kind": "Name", + "textLength": 4 + } + } + } + ], + "endQuote": { + "kind": "DoubleQuoteToken", + "textLength": 1 + } + } + }, + "semicolon": { + "kind": "SemicolonToken", + "textLength": 1 + } + } + } + ], + "closeBrace": { + "kind": "CloseBraceToken", + "textLength": 1 + } + } + }, + "semicolon": null + } + }, + { + "PropertyHook": { + "attributes": null, + "byRefToken": null, + "name": { + "kind": "Name", + "textLength": 3 + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "parameters": { + "ParameterDeclarationList": { + "children": [ + { + "Parameter": { + "attributes": null, + "visibilityToken": null, + "modifiers": null, + "questionToken": null, + "typeDeclarationList": { + "QualifiedNameList": { + "children": [ + { + "kind": "StringReservedWord", + "textLength": 6 + } + ] + } + }, + "byRefToken": null, + "dotDotDotToken": null, + "variableName": { + "kind": "VariableName", + "textLength": 6 + }, + "equalsToken": null, + "default": null, + "propertyHooks": null + } + } + ] + } + }, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 + }, + "arrowToken": null, + "body": { + "CompoundStatementNode": { + "openBrace": { + "kind": "OpenBraceToken", + "textLength": 1 + }, + "statements": [ + { + "ExpressionStatement": { + "expression": { + "AssignmentExpression": { + "leftOperand": { + "ArrayCreationExpression": { + "arrayKeyword": null, + "openParenOrBracket": { + "kind": "OpenBracketToken", + "textLength": 1 + }, + "arrayElements": { + "ArrayElementList": { + "children": [ + { + "ArrayElement": { + "elementKey": null, + "arrowToken": null, + "byRef": null, + "dotDotDot": null, + "elementValue": { + "MemberAccessExpression": { + "dereferencableExpression": { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 5 + } + } + }, + "arrowToken": { + "kind": "ArrowToken", + "textLength": 2 + }, + "memberName": { + "kind": "Name", + "textLength": 5 + } + } + } + } + }, + { + "kind": "CommaToken", + "textLength": 1 + }, + { + "ArrayElement": { + "elementKey": null, + "arrowToken": null, + "byRef": null, + "dotDotDot": null, + "elementValue": { + "MemberAccessExpression": { + "dereferencableExpression": { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 5 + } + } + }, + "arrowToken": { + "kind": "ArrowToken", + "textLength": 2 + }, + "memberName": { + "kind": "Name", + "textLength": 4 + } + } + } + } + } + ] + } + }, + "closeParenOrBracket": { + "kind": "CloseBracketToken", + "textLength": 1 + } + } + }, + "operator": { + "kind": "EqualsToken", + "textLength": 1 + }, + "byRef": null, + "rightOperand": { + "CallExpression": { + "callableExpression": { + "QualifiedName": { + "globalSpecifier": null, + "relativeSpecifier": null, + "nameParts": [ + { + "kind": "Name", + "textLength": 7 + } + ] + } + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "argumentExpressionList": { + "ArgumentExpressionList": { + "children": [ + { + "ArgumentExpression": { + "name": null, + "colonToken": null, + "dotDotDotToken": null, + "expression": { + "StringLiteral": { + "startQuote": null, + "children": { + "kind": "StringLiteralToken", + "textLength": 3 + }, + "endQuote": null + } + } + } + }, + { + "kind": "CommaToken", + "textLength": 1 + }, + { + "ArgumentExpression": { + "name": null, + "colonToken": null, + "dotDotDotToken": null, + "expression": { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 6 + } + } + } + } + }, + { + "kind": "CommaToken", + "textLength": 1 + }, + { + "ArgumentExpression": { + "name": null, + "colonToken": null, + "dotDotDotToken": null, + "expression": { + "NumericLiteral": { + "children": { + "kind": "IntegerLiteralToken", + "textLength": 1 + } + } + } + } + } + ] + } + }, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 + } + } + } + } + }, + "semicolon": { + "kind": "SemicolonToken", + "textLength": 1 + } + } + } + ], + "closeBrace": { + "kind": "CloseBraceToken", + "textLength": 1 + } + } + }, + "semicolon": null + } + } + ], + "closeBrace": { + "kind": "CloseBraceToken", + "textLength": 1 + } + } + }, + "semicolon": null + } + } + ], + "closeBrace": { + "kind": "CloseBraceToken", + "textLength": 1 + } + } + } + } + } + ], + "endOfFileToken": { + "kind": "EndOfFileToken", + "textLength": 0 + } + } +} \ No newline at end of file diff --git a/tests/cases/parser/true.php.tree b/tests/cases/parser/true.php.tree index 4e4cfe2c..24669863 100644 --- a/tests/cases/parser/true.php.tree +++ b/tests/cases/parser/true.php.tree @@ -53,7 +53,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/typedProperties.php.tree b/tests/cases/parser/typedProperties.php.tree index 00286e48..3aa68e99 100644 --- a/tests/cases/parser/typedProperties.php.tree +++ b/tests/cases/parser/typedProperties.php.tree @@ -92,6 +92,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1 @@ -141,6 +142,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1 @@ -205,6 +207,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1 @@ -265,6 +268,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/typedPropertiesNoType.php.tree b/tests/cases/parser/typedPropertiesNoType.php.tree index b794cc28..a3dfbdc5 100644 --- a/tests/cases/parser/typedPropertiesNoType.php.tree +++ b/tests/cases/parser/typedPropertiesNoType.php.tree @@ -83,6 +83,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/typedPropertiesSimple.php.tree b/tests/cases/parser/typedPropertiesSimple.php.tree index da0973a5..19961159 100644 --- a/tests/cases/parser/typedPropertiesSimple.php.tree +++ b/tests/cases/parser/typedPropertiesSimple.php.tree @@ -85,6 +85,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/unionTypeParameter1.php.tree b/tests/cases/parser/unionTypeParameter1.php.tree index b1ed34cf..aeec322c 100644 --- a/tests/cases/parser/unionTypeParameter1.php.tree +++ b/tests/cases/parser/unionTypeParameter1.php.tree @@ -61,7 +61,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/unionTypeParameter2.php.tree b/tests/cases/parser/unionTypeParameter2.php.tree index 11a5b87e..aee37913 100644 --- a/tests/cases/parser/unionTypeParameter2.php.tree +++ b/tests/cases/parser/unionTypeParameter2.php.tree @@ -107,7 +107,8 @@ "textLength": 4 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/unionTypeProperty.php.tree b/tests/cases/parser/unionTypeProperty.php.tree index e55f841b..7abaee00 100644 --- a/tests/cases/parser/unionTypeProperty.php.tree +++ b/tests/cases/parser/unionTypeProperty.php.tree @@ -84,6 +84,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1 @@ -183,6 +184,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/unionTypeProperty2.php.tree b/tests/cases/parser/unionTypeProperty2.php.tree index 2ecf8975..3c6ab566 100644 --- a/tests/cases/parser/unionTypeProperty2.php.tree +++ b/tests/cases/parser/unionTypeProperty2.php.tree @@ -174,6 +174,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/yieldExpression18.php.tree b/tests/cases/parser/yieldExpression18.php.tree index f0cd6119..fef7a725 100644 --- a/tests/cases/parser/yieldExpression18.php.tree +++ b/tests/cases/parser/yieldExpression18.php.tree @@ -44,7 +44,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser/yieldExpression19.php.tree b/tests/cases/parser/yieldExpression19.php.tree index 1c02f0c1..ca76eb78 100644 --- a/tests/cases/parser/yieldExpression19.php.tree +++ b/tests/cases/parser/yieldExpression19.php.tree @@ -44,7 +44,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser74/arrowFunction.php.tree b/tests/cases/parser74/arrowFunction.php.tree index 0d202395..4ec8281b 100644 --- a/tests/cases/parser74/arrowFunction.php.tree +++ b/tests/cases/parser74/arrowFunction.php.tree @@ -69,7 +69,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] @@ -205,7 +206,8 @@ "textLength": 2 } } - } + }, + "propertyHooks": null } } ] @@ -291,7 +293,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] @@ -361,7 +364,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] @@ -428,7 +432,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -452,7 +457,8 @@ "textLength": 5 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser74/arrowFunctionFallback.php.tree b/tests/cases/parser74/arrowFunctionFallback.php.tree index 3d236338..9e0b731a 100644 --- a/tests/cases/parser74/arrowFunctionFallback.php.tree +++ b/tests/cases/parser74/arrowFunctionFallback.php.tree @@ -80,7 +80,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] @@ -267,7 +268,8 @@ "textLength": 2 } } - } + }, + "propertyHooks": null } } ] @@ -372,7 +374,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] @@ -486,7 +489,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] @@ -603,7 +607,8 @@ "textLength": 4 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser74/arrowFunctionTypes.php.tree b/tests/cases/parser74/arrowFunctionTypes.php.tree index 045202fe..f5f74f49 100644 --- a/tests/cases/parser74/arrowFunctionTypes.php.tree +++ b/tests/cases/parser74/arrowFunctionTypes.php.tree @@ -80,7 +80,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] @@ -282,7 +283,8 @@ "textLength": 2 } } - } + }, + "propertyHooks": null } } ] @@ -386,7 +388,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] @@ -499,7 +502,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] @@ -612,7 +616,8 @@ "textLength": 4 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser74/arrowFunctionUnionTypes.php.tree b/tests/cases/parser74/arrowFunctionUnionTypes.php.tree index 901721b0..ab6a4306 100644 --- a/tests/cases/parser74/arrowFunctionUnionTypes.php.tree +++ b/tests/cases/parser74/arrowFunctionUnionTypes.php.tree @@ -64,7 +64,8 @@ "textLength": 7 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] @@ -169,7 +170,8 @@ "textLength": 2 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] @@ -281,7 +283,8 @@ "textLength": 6 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] @@ -443,7 +446,8 @@ "textLength": 0 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser80/attributes18.php.tree b/tests/cases/parser80/attributes18.php.tree index 16abce90..ee93aaa9 100644 --- a/tests/cases/parser80/attributes18.php.tree +++ b/tests/cases/parser80/attributes18.php.tree @@ -65,7 +65,8 @@ "textLength": 0 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser80/attributes20.php b/tests/cases/parser80/attributes20.php new file mode 100644 index 00000000..8711b4b5 --- /dev/null +++ b/tests/cases/parser80/attributes20.php @@ -0,0 +1,7 @@ + 'default'; + } +} diff --git a/tests/cases/parser80/attributes20.php.diag b/tests/cases/parser80/attributes20.php.diag new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/tests/cases/parser80/attributes20.php.diag @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/tests/cases/parser80/attributes20.php.tree b/tests/cases/parser80/attributes20.php.tree new file mode 100644 index 00000000..07243c97 --- /dev/null +++ b/tests/cases/parser80/attributes20.php.tree @@ -0,0 +1,172 @@ +{ + "SourceFileNode": { + "statementList": [ + { + "InlineHtml": { + "scriptSectionEndTag": null, + "text": null, + "scriptSectionStartTag": { + "kind": "ScriptSectionStartTag", + "textLength": 6 + } + } + }, + { + "ClassDeclaration": { + "attributes": null, + "abstractOrFinalModifier": null, + "modifiers": [], + "classKeyword": { + "kind": "ClassKeyword", + "textLength": 5 + }, + "name": { + "kind": "Name", + "textLength": 1 + }, + "classBaseClause": null, + "classInterfaceClause": null, + "classMembers": { + "ClassMembersNode": { + "openBrace": { + "kind": "OpenBraceToken", + "textLength": 1 + }, + "classMemberDeclarations": [ + { + "PropertyDeclaration": { + "attributes": null, + "modifiers": [ + { + "kind": "PublicKeyword", + "textLength": 6 + } + ], + "questionToken": null, + "typeDeclarationList": { + "QualifiedNameList": { + "children": [ + { + "kind": "StringReservedWord", + "textLength": 6 + } + ] + } + }, + "propertyElements": { + "ExpressionList": { + "children": [ + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 5 + } + } + } + ] + } + }, + "propertyHooks": { + "PropertyHooks": { + "openBrace": { + "kind": "OpenBraceToken", + "textLength": 1 + }, + "hookDeclarations": [ + { + "PropertyHook": { + "attributes": [ + { + "AttributeGroup": { + "startToken": { + "kind": "AttributeToken", + "textLength": 2 + }, + "attributes": { + "AttributeElementList": { + "children": [ + { + "Attribute": { + "name": { + "QualifiedName": { + "globalSpecifier": null, + "relativeSpecifier": null, + "nameParts": [ + { + "kind": "Name", + "textLength": 13 + } + ] + } + }, + "openParen": null, + "argumentExpressionList": null, + "closeParen": null + } + } + ] + } + }, + "endToken": { + "kind": "CloseBracketToken", + "textLength": 1 + } + } + } + ], + "byRefToken": null, + "name": { + "kind": "Name", + "textLength": 3 + }, + "openParen": null, + "parameters": null, + "closeParen": null, + "arrowToken": { + "kind": "DoubleArrowToken", + "textLength": 2 + }, + "body": { + "StringLiteral": { + "startQuote": null, + "children": { + "kind": "StringLiteralToken", + "textLength": 9 + }, + "endQuote": null + } + }, + "semicolon": { + "kind": "SemicolonToken", + "textLength": 1 + } + } + } + ], + "closeBrace": { + "kind": "CloseBraceToken", + "textLength": 1 + } + } + }, + "semicolon": null + } + } + ], + "closeBrace": { + "kind": "CloseBraceToken", + "textLength": 1 + } + } + } + } + } + ], + "endOfFileToken": { + "kind": "EndOfFileToken", + "textLength": 0 + } + } +} \ No newline at end of file diff --git a/tests/cases/parser80/attributes4.php.tree b/tests/cases/parser80/attributes4.php.tree index 6fae34ba..d2387ebd 100644 --- a/tests/cases/parser80/attributes4.php.tree +++ b/tests/cases/parser80/attributes4.php.tree @@ -108,6 +108,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser80/attributes5.php.tree b/tests/cases/parser80/attributes5.php.tree index 4c5f1c18..92102aba 100644 --- a/tests/cases/parser80/attributes5.php.tree +++ b/tests/cases/parser80/attributes5.php.tree @@ -82,7 +82,8 @@ "textLength": 6 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { diff --git a/tests/cases/parser80/mixedType1.php.tree b/tests/cases/parser80/mixedType1.php.tree index ce93968b..858b5e74 100644 --- a/tests/cases/parser80/mixedType1.php.tree +++ b/tests/cases/parser80/mixedType1.php.tree @@ -53,7 +53,8 @@ "textLength": 4 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] diff --git a/tests/cases/parser81/intersection_type.php.tree b/tests/cases/parser81/intersection_type.php.tree index 2be7447a..5ef247ad 100644 --- a/tests/cases/parser81/intersection_type.php.tree +++ b/tests/cases/parser81/intersection_type.php.tree @@ -93,7 +93,8 @@ "textLength": 6 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } }, { @@ -150,7 +151,8 @@ "textLength": 7 }, "equalsToken": null, - "default": null + "default": null, + "propertyHooks": null } } ] @@ -295,6 +297,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser81/readonly_property.php.tree b/tests/cases/parser81/readonly_property.php.tree index c6991256..5426d070 100644 --- a/tests/cases/parser81/readonly_property.php.tree +++ b/tests/cases/parser81/readonly_property.php.tree @@ -72,6 +72,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1 @@ -166,6 +167,7 @@ ] } }, + "propertyHooks": null, "semicolon": { "kind": "SemicolonToken", "textLength": 1