Merge pull request #243 from TysonAndre/fix-trait-list

Fixes #190: `insteadof` should be able to accept a name list
This commit is contained in:
Rob Lourens 2018-05-12 12:12:14 -07:00 коммит произвёл GitHub
Родитель 31cffdb9ab 797f79578d
Коммит 7647b60b13
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
21 изменённых файлов: 524 добавлений и 45 удалений

Просмотреть файл

@ -22,10 +22,26 @@ class TraitSelectOrAliasClause extends Node {
/** @var QualifiedName|Node\Expression\ScopedPropertyAccessExpression */
public $targetName;
/**
* @var Token[]|QualifiedName[]|null
*
* This is set if $asOrInsteadOfKeyword is an insteadof keyword.
* (E.g. for parsing `use T1, T2, T3{T1::foo insteadof T2, T3}`
*
* NOTE: This was added as a separate property to minimize
* backwards compatibility breaks in applications using this file.
*
* TODO: Use a more consistent design such as either of the following:
* 1. Combine targetName and remainingTargetNames into a DelimitedList
* 2. Use two distinct properties for the targets of `as` and `insteadof`
*/
public $remainingTargetNames;
const CHILD_NAMES = [
'name',
'asOrInsteadOfKeyword',
'modifiers',
'targetName'
'targetName',
'remainingTargetNames',
];
}

Просмотреть файл

@ -2665,6 +2665,10 @@ class Parser {
return $propertyDeclaration;
}
/**
* @param Node $parentNode
* @return DelimitedList\QualifiedNameList
*/
private function parseQualifiedNameList($parentNode) {
return $this->parseDelimitedList(
DelimitedList\QualifiedNameList::class,
@ -2943,8 +2947,17 @@ class Parser {
$traitSelectAndAliasClause->asOrInsteadOfKeyword = $this->eat(TokenKind::AsKeyword, TokenKind::InsteadOfKeyword);
$traitSelectAndAliasClause->modifiers = $this->parseModifiers(); // TODO accept all modifiers, verify later
$traitSelectAndAliasClause->targetName =
$this->parseQualifiedNameOrScopedPropertyAccessExpression($traitSelectAndAliasClause);
if ($traitSelectAndAliasClause->asOrInsteadOfKeyword->kind === TokenKind::InsteadOfKeyword) {
// https://github.com/Microsoft/tolerant-php-parser/issues/190
// TODO: In the next backwards incompatible release, convert targetName to a list?
$interfaceNameList = $this->parseQualifiedNameList($traitSelectAndAliasClause)->children ?? [];
$traitSelectAndAliasClause->targetName = $interfaceNameList[0] ?? new MissingToken(TokenKind::BarToken, $this->token->fullStart);
$traitSelectAndAliasClause->remainingTargetNames = array_slice($interfaceNameList, 1);
} else {
$traitSelectAndAliasClause->targetName =
$this->parseQualifiedNameOrScopedPropertyAccessExpression($traitSelectAndAliasClause);
$traitSelectAndAliasClause->remainingTargetNames = [];
}
// TODO errors for insteadof/as
return $traitSelectAndAliasClause;

Просмотреть файл

@ -89,7 +89,8 @@
}
]
}
}
},
"remainingTargetNames": []
}
}
]

Просмотреть файл

@ -89,7 +89,8 @@
}
]
}
}
},
"remainingTargetNames": []
}
},
{
@ -126,7 +127,8 @@
}
]
}
}
},
"remainingTargetNames": []
}
},
{

Просмотреть файл

@ -97,7 +97,8 @@
}
]
}
}
},
"remainingTargetNames": []
}
},
{

Просмотреть файл

@ -97,7 +97,8 @@
}
]
}
}
},
"remainingTargetNames": []
}
},
{

Просмотреть файл

@ -101,7 +101,8 @@
}
]
}
}
},
"remainingTargetNames": []
}
},
{

Просмотреть файл

@ -1 +1,32 @@
[]
[
{
"kind": 0,
"message": "'}' expected.",
"start": 41,
"length": 0
},
{
"kind": 0,
"message": "Unexpected '::'",
"start": 41,
"length": 2
},
{
"kind": 0,
"message": "'}' expected.",
"start": 43,
"length": 0
},
{
"kind": 0,
"message": "Unexpected '}'",
"start": 46,
"length": 1
},
{
"kind": 0,
"message": "Unexpected '}'",
"start": 48,
"length": 1
}
]

Просмотреть файл

@ -79,52 +79,74 @@
},
"modifiers": [],
"targetName": {
"ScopedPropertyAccessExpression": {
"scopeResolutionQualifier": {
"QualifiedName": {
"globalSpecifier": null,
"relativeSpecifier": null,
"nameParts": [
{
"kind": "Name",
"textLength": 1
}
]
"QualifiedName": {
"globalSpecifier": null,
"relativeSpecifier": null,
"nameParts": [
{
"kind": "Name",
"textLength": 1
}
},
"doubleColon": {
"kind": "ColonColonToken",
"textLength": 2
},
"memberName": {
"kind": "Name",
"textLength": 1
}
]
}
}
},
"remainingTargetNames": []
}
},
{
"kind": "SemicolonToken",
"textLength": 1
}
]
}
},
"closeBrace": {
"error": "MissingToken",
"kind": "CloseBraceToken",
"textLength": 1
"textLength": 0
}
}
},
{
"error": "SkippedToken",
"kind": "ColonColonToken",
"textLength": 2
}
],
"closeBrace": {
"error": "MissingToken",
"kind": "CloseBraceToken",
"textLength": 1
"textLength": 0
}
}
}
}
},
{
"ExpressionStatement": {
"expression": {
"QualifiedName": {
"globalSpecifier": null,
"relativeSpecifier": null,
"nameParts": [
{
"kind": "Name",
"textLength": 1
}
]
}
},
"semicolon": {
"kind": "SemicolonToken",
"textLength": 1
}
}
},
{
"error": "SkippedToken",
"kind": "CloseBraceToken",
"textLength": 1
},
{
"error": "SkippedToken",
"kind": "CloseBraceToken",
"textLength": 1
}
],
"endOfFileToken": {

Просмотреть файл

@ -109,7 +109,8 @@
}
]
}
}
},
"remainingTargetNames": []
}
},
{

Просмотреть файл

@ -94,7 +94,8 @@
}
]
}
}
},
"remainingTargetNames": []
}
},
{

Просмотреть файл

@ -98,7 +98,8 @@
}
]
}
}
},
"remainingTargetNames": []
}
},
{

Просмотреть файл

@ -95,7 +95,8 @@
}
]
}
}
},
"remainingTargetNames": []
}
},
{
@ -155,7 +156,8 @@
}
]
}
}
},
"remainingTargetNames": []
}
},
{

Просмотреть файл

@ -110,7 +110,8 @@
}
]
}
}
},
"remainingTargetNames": []
}
},
{
@ -147,7 +148,8 @@
}
]
}
}
},
"remainingTargetNames": []
}
},
{

Просмотреть файл

@ -0,0 +1,8 @@
<?php
// https://github.com/Microsoft/tolerant-php-parser/issues/98
class A {
use X, Y, Z {
\X::b insteadof Y, Z;
}
}

Просмотреть файл

@ -0,0 +1 @@
[]

Просмотреть файл

@ -0,0 +1,191 @@
{
"SourceFileNode": {
"statementList": [
{
"InlineHtml": {
"scriptSectionEndTag": null,
"text": null,
"scriptSectionStartTag": {
"kind": "ScriptSectionStartTag",
"textLength": 6
}
}
},
{
"ClassDeclaration": {
"abstractOrFinalModifier": null,
"classKeyword": {
"kind": "ClassKeyword",
"textLength": 5
},
"name": {
"kind": "Name",
"textLength": 1
},
"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": 1
}
]
}
},
{
"kind": "CommaToken",
"textLength": 1
},
{
"QualifiedName": {
"globalSpecifier": null,
"relativeSpecifier": null,
"nameParts": [
{
"kind": "Name",
"textLength": 1
}
]
}
},
{
"kind": "CommaToken",
"textLength": 1
},
{
"QualifiedName": {
"globalSpecifier": null,
"relativeSpecifier": null,
"nameParts": [
{
"kind": "Name",
"textLength": 1
}
]
}
}
]
}
},
"semicolonOrOpenBrace": {
"kind": "OpenBraceToken",
"textLength": 1
},
"traitSelectAndAliasClauses": {
"TraitSelectOrAliasClauseList": {
"children": [
{
"TraitSelectOrAliasClause": {
"name": {
"ScopedPropertyAccessExpression": {
"scopeResolutionQualifier": {
"QualifiedName": {
"globalSpecifier": {
"kind": "BackslashToken",
"textLength": 1
},
"relativeSpecifier": null,
"nameParts": [
{
"kind": "Name",
"textLength": 1
}
]
}
},
"doubleColon": {
"kind": "ColonColonToken",
"textLength": 2
},
"memberName": {
"kind": "Name",
"textLength": 1
}
}
},
"asOrInsteadOfKeyword": {
"kind": "InsteadOfKeyword",
"textLength": 9
},
"modifiers": [],
"targetName": {
"QualifiedName": {
"globalSpecifier": null,
"relativeSpecifier": null,
"nameParts": [
{
"kind": "Name",
"textLength": 1
}
]
}
},
"remainingTargetNames": [
{
"kind": "CommaToken",
"textLength": 1
},
{
"QualifiedName": {
"globalSpecifier": null,
"relativeSpecifier": null,
"nameParts": [
{
"kind": "Name",
"textLength": 1
}
]
}
}
]
}
},
{
"kind": "SemicolonToken",
"textLength": 1
}
]
}
},
"closeBrace": {
"kind": "CloseBraceToken",
"textLength": 1
}
}
}
],
"closeBrace": {
"kind": "CloseBraceToken",
"textLength": 1
}
}
}
}
}
],
"endOfFileToken": {
"kind": "EndOfFileToken",
"textLength": 0
}
}
}

Просмотреть файл

@ -0,0 +1,8 @@
<?php
// https://github.com/Microsoft/tolerant-php-parser/issues/98
class A {
use X, Y, Z {
\X::b insteadof;
}
}

Просмотреть файл

@ -0,0 +1,8 @@
[
{
"kind": 0,
"message": "'|' expected.",
"start": 121,
"length": 0
}
]

Просмотреть файл

@ -0,0 +1,167 @@
{
"SourceFileNode": {
"statementList": [
{
"InlineHtml": {
"scriptSectionEndTag": null,
"text": null,
"scriptSectionStartTag": {
"kind": "ScriptSectionStartTag",
"textLength": 6
}
}
},
{
"ClassDeclaration": {
"abstractOrFinalModifier": null,
"classKeyword": {
"kind": "ClassKeyword",
"textLength": 5
},
"name": {
"kind": "Name",
"textLength": 1
},
"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": 1
}
]
}
},
{
"kind": "CommaToken",
"textLength": 1
},
{
"QualifiedName": {
"globalSpecifier": null,
"relativeSpecifier": null,
"nameParts": [
{
"kind": "Name",
"textLength": 1
}
]
}
},
{
"kind": "CommaToken",
"textLength": 1
},
{
"QualifiedName": {
"globalSpecifier": null,
"relativeSpecifier": null,
"nameParts": [
{
"kind": "Name",
"textLength": 1
}
]
}
}
]
}
},
"semicolonOrOpenBrace": {
"kind": "OpenBraceToken",
"textLength": 1
},
"traitSelectAndAliasClauses": {
"TraitSelectOrAliasClauseList": {
"children": [
{
"TraitSelectOrAliasClause": {
"name": {
"ScopedPropertyAccessExpression": {
"scopeResolutionQualifier": {
"QualifiedName": {
"globalSpecifier": {
"kind": "BackslashToken",
"textLength": 1
},
"relativeSpecifier": null,
"nameParts": [
{
"kind": "Name",
"textLength": 1
}
]
}
},
"doubleColon": {
"kind": "ColonColonToken",
"textLength": 2
},
"memberName": {
"kind": "Name",
"textLength": 1
}
}
},
"asOrInsteadOfKeyword": {
"kind": "InsteadOfKeyword",
"textLength": 9
},
"modifiers": [],
"targetName": {
"error": "MissingToken",
"kind": "BarToken",
"textLength": 0
},
"remainingTargetNames": []
}
},
{
"kind": "SemicolonToken",
"textLength": 1
}
]
}
},
"closeBrace": {
"kind": "CloseBraceToken",
"textLength": 1
}
}
}
],
"closeBrace": {
"kind": "CloseBraceToken",
"textLength": 1
}
}
}
}
}
],
"endOfFileToken": {
"kind": "EndOfFileToken",
"textLength": 0
}
}
}

Просмотреть файл

@ -89,7 +89,8 @@
}
]
}
}
},
"remainingTargetNames": []
}
},
{