Merge pull request #260 from TysonAndre/fix-trait-use-notice
Fix a PHP notice generating a scoped property access expression
This commit is contained in:
Коммит
54a84f1250
|
@ -1237,7 +1237,7 @@ class Parser {
|
||||||
$node->addElement($delimeterToken);
|
$node->addElement($delimeterToken);
|
||||||
}
|
}
|
||||||
$token = $this->getCurrentToken();
|
$token = $this->getCurrentToken();
|
||||||
// TODO ERROR CASE - no delimeter, but a param follows
|
// TODO ERROR CASE - no delimiter, but a param follows
|
||||||
} while ($delimeterToken !== null);
|
} while ($delimeterToken !== null);
|
||||||
|
|
||||||
|
|
||||||
|
@ -2460,7 +2460,7 @@ class Parser {
|
||||||
return $expression;
|
return $expression;
|
||||||
}
|
}
|
||||||
if ($tokenKind === TokenKind::ColonColonToken) {
|
if ($tokenKind === TokenKind::ColonColonToken) {
|
||||||
$expression = $this->parseScopedPropertyAccessExpression($expression);
|
$expression = $this->parseScopedPropertyAccessExpression($expression, null);
|
||||||
return $this->parsePostfixExpressionRest($expression);
|
return $this->parsePostfixExpressionRest($expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2608,12 +2608,18 @@ class Parser {
|
||||||
return $memberAccessExpression;
|
return $memberAccessExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function parseScopedPropertyAccessExpression($expression):ScopedPropertyAccessExpression {
|
/**
|
||||||
|
* @param Node|null $expression
|
||||||
|
* @param Node|null $fallbackParentNode (Workaround for the invalid AST `use TraitName::foo as ::x`)
|
||||||
|
*/
|
||||||
|
private function parseScopedPropertyAccessExpression($expression, $fallbackParentNode): ScopedPropertyAccessExpression {
|
||||||
$scopedPropertyAccessExpression = new ScopedPropertyAccessExpression();
|
$scopedPropertyAccessExpression = new ScopedPropertyAccessExpression();
|
||||||
$scopedPropertyAccessExpression->parent = $expression->parent;
|
$scopedPropertyAccessExpression->parent = $expression->parent ?? $fallbackParentNode;
|
||||||
$expression->parent = $scopedPropertyAccessExpression;
|
if ($expression instanceof Node) {
|
||||||
|
$expression->parent = $scopedPropertyAccessExpression;
|
||||||
|
$scopedPropertyAccessExpression->scopeResolutionQualifier = $expression; // TODO ensure always a Node
|
||||||
|
}
|
||||||
|
|
||||||
$scopedPropertyAccessExpression->scopeResolutionQualifier = $expression; // TODO ensure always a Node
|
|
||||||
$scopedPropertyAccessExpression->doubleColon = $this->eat1(TokenKind::ColonColonToken);
|
$scopedPropertyAccessExpression->doubleColon = $this->eat1(TokenKind::ColonColonToken);
|
||||||
$scopedPropertyAccessExpression->memberName = $this->parseMemberName($scopedPropertyAccessExpression);
|
$scopedPropertyAccessExpression->memberName = $this->parseMemberName($scopedPropertyAccessExpression);
|
||||||
|
|
||||||
|
@ -3050,7 +3056,7 @@ class Parser {
|
||||||
private function parseQualifiedNameOrScopedPropertyAccessExpression($parentNode) {
|
private function parseQualifiedNameOrScopedPropertyAccessExpression($parentNode) {
|
||||||
$qualifiedNameOrScopedProperty = $this->parseQualifiedName($parentNode);
|
$qualifiedNameOrScopedProperty = $this->parseQualifiedName($parentNode);
|
||||||
if ($this->getCurrentToken()->kind === TokenKind::ColonColonToken) {
|
if ($this->getCurrentToken()->kind === TokenKind::ColonColonToken) {
|
||||||
$qualifiedNameOrScopedProperty = $this->parseScopedPropertyAccessExpression($qualifiedNameOrScopedProperty);
|
$qualifiedNameOrScopedProperty = $this->parseScopedPropertyAccessExpression($qualifiedNameOrScopedProperty, $parentNode);
|
||||||
}
|
}
|
||||||
return $qualifiedNameOrScopedProperty;
|
return $qualifiedNameOrScopedProperty;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A295 {
|
||||||
|
use T1, T2 {
|
||||||
|
T1::foo as ::xyz insteadof T2; // This is invalid, but parser invariants should hold
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"kind": 0,
|
||||||
|
"message": "'}' expected.",
|
||||||
|
"start": 61,
|
||||||
|
"length": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 0,
|
||||||
|
"message": "Unexpected 'insteadof'",
|
||||||
|
"start": 62,
|
||||||
|
"length": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 0,
|
||||||
|
"message": "'}' expected.",
|
||||||
|
"start": 71,
|
||||||
|
"length": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 0,
|
||||||
|
"message": "Unexpected '}'",
|
||||||
|
"start": 135,
|
||||||
|
"length": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 0,
|
||||||
|
"message": "Unexpected '}'",
|
||||||
|
"start": 137,
|
||||||
|
"length": 1
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,189 @@
|
||||||
|
{
|
||||||
|
"SourceFileNode": {
|
||||||
|
"statementList": [
|
||||||
|
{
|
||||||
|
"InlineHtml": {
|
||||||
|
"scriptSectionEndTag": null,
|
||||||
|
"text": null,
|
||||||
|
"scriptSectionStartTag": {
|
||||||
|
"kind": "ScriptSectionStartTag",
|
||||||
|
"textLength": 6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ClassDeclaration": {
|
||||||
|
"abstractOrFinalModifier": null,
|
||||||
|
"classKeyword": {
|
||||||
|
"kind": "ClassKeyword",
|
||||||
|
"textLength": 5
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"kind": "Name",
|
||||||
|
"textLength": 4
|
||||||
|
},
|
||||||
|
"classBaseClause": null,
|
||||||
|
"classInterfaceClause": null,
|
||||||
|
"classMembers": {
|
||||||
|
"ClassMembersNode": {
|
||||||
|
"openBrace": {
|
||||||
|
"kind": "OpenBraceToken",
|
||||||
|
"textLength": 1
|
||||||
|
},
|
||||||
|
"classMemberDeclarations": [
|
||||||
|
{
|
||||||
|
"TraitUseClause": {
|
||||||
|
"useKeyword": {
|
||||||
|
"kind": "UseKeyword",
|
||||||
|
"textLength": 3
|
||||||
|
},
|
||||||
|
"traitNameList": {
|
||||||
|
"QualifiedNameList": {
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"QualifiedName": {
|
||||||
|
"globalSpecifier": null,
|
||||||
|
"relativeSpecifier": null,
|
||||||
|
"nameParts": [
|
||||||
|
{
|
||||||
|
"kind": "Name",
|
||||||
|
"textLength": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "CommaToken",
|
||||||
|
"textLength": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"QualifiedName": {
|
||||||
|
"globalSpecifier": null,
|
||||||
|
"relativeSpecifier": null,
|
||||||
|
"nameParts": [
|
||||||
|
{
|
||||||
|
"kind": "Name",
|
||||||
|
"textLength": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semicolonOrOpenBrace": {
|
||||||
|
"kind": "OpenBraceToken",
|
||||||
|
"textLength": 1
|
||||||
|
},
|
||||||
|
"traitSelectAndAliasClauses": {
|
||||||
|
"TraitSelectOrAliasClauseList": {
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"TraitSelectOrAliasClause": {
|
||||||
|
"name": {
|
||||||
|
"ScopedPropertyAccessExpression": {
|
||||||
|
"scopeResolutionQualifier": {
|
||||||
|
"QualifiedName": {
|
||||||
|
"globalSpecifier": null,
|
||||||
|
"relativeSpecifier": null,
|
||||||
|
"nameParts": [
|
||||||
|
{
|
||||||
|
"kind": "Name",
|
||||||
|
"textLength": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"doubleColon": {
|
||||||
|
"kind": "ColonColonToken",
|
||||||
|
"textLength": 2
|
||||||
|
},
|
||||||
|
"memberName": {
|
||||||
|
"kind": "Name",
|
||||||
|
"textLength": 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"asOrInsteadOfKeyword": {
|
||||||
|
"kind": "AsKeyword",
|
||||||
|
"textLength": 2
|
||||||
|
},
|
||||||
|
"modifiers": [],
|
||||||
|
"targetName": {
|
||||||
|
"ScopedPropertyAccessExpression": {
|
||||||
|
"scopeResolutionQualifier": null,
|
||||||
|
"doubleColon": {
|
||||||
|
"kind": "ColonColonToken",
|
||||||
|
"textLength": 2
|
||||||
|
},
|
||||||
|
"memberName": {
|
||||||
|
"kind": "Name",
|
||||||
|
"textLength": 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"remainingTargetNames": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"closeBrace": {
|
||||||
|
"error": "MissingToken",
|
||||||
|
"kind": "CloseBraceToken",
|
||||||
|
"textLength": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"error": "SkippedToken",
|
||||||
|
"kind": "InsteadOfKeyword",
|
||||||
|
"textLength": 9
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"closeBrace": {
|
||||||
|
"error": "MissingToken",
|
||||||
|
"kind": "CloseBraceToken",
|
||||||
|
"textLength": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ExpressionStatement": {
|
||||||
|
"expression": {
|
||||||
|
"QualifiedName": {
|
||||||
|
"globalSpecifier": null,
|
||||||
|
"relativeSpecifier": null,
|
||||||
|
"nameParts": [
|
||||||
|
{
|
||||||
|
"kind": "Name",
|
||||||
|
"textLength": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semicolon": {
|
||||||
|
"kind": "SemicolonToken",
|
||||||
|
"textLength": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"error": "SkippedToken",
|
||||||
|
"kind": "CloseBraceToken",
|
||||||
|
"textLength": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"error": "SkippedToken",
|
||||||
|
"kind": "CloseBraceToken",
|
||||||
|
"textLength": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"endOfFileToken": {
|
||||||
|
"kind": "EndOfFileToken",
|
||||||
|
"textLength": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче