Skip to content

Commit 3fdca6b

Browse files
authored
Merge pull request microsoft#335 from TysonAndre/named-arguments-
Support parsing php 8.0 named arguments
2 parents be9cfce + 869dc7f commit 3fdca6b

34 files changed

+671
-4
lines changed

src/Node/Expression/ArgumentExpression.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010
use Microsoft\PhpParser\Token;
1111

1212
class ArgumentExpression extends Expression {
13+
/** @var Token|null for php named arguments. If this is set, byRefToken and dotDotDotToken will not be set. */
14+
public $name;
15+
16+
/** @var Token|null */
17+
public $colonToken;
18+
1319
/** @var Token|null */
1420
public $byRefToken; // TODO removed in newer versions of PHP. Also only accept variable, not expression if byRef
1521

@@ -20,6 +26,8 @@ class ArgumentExpression extends Expression {
2026
public $expression;
2127

2228
const CHILD_NAMES = [
29+
'name',
30+
'colonToken',
2331
'byRefToken',
2432
'dotDotDotToken',
2533
'expression'

src/Parser.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,17 @@ class Parser {
121121
private $nameOrStaticOrReservedWordTokens;
122122
private $reservedWordTokens;
123123
private $keywordTokens;
124+
private $argumentStartTokensSet;
124125
// TODO consider validating parameter and return types on post-parse instead so we can be more permissive
125126
private $parameterTypeDeclarationTokens;
126127
private $returnTypeDeclarationTokens;
127128

128129
public function __construct() {
129130
$this->reservedWordTokens = \array_values(TokenStringMaps::RESERVED_WORDS);
130131
$this->keywordTokens = \array_values(TokenStringMaps::KEYWORDS);
132+
$this->argumentStartTokensSet = \array_flip(TokenStringMaps::KEYWORDS);
133+
unset($this->argumentStartTokensSet[TokenKind::YieldFromKeyword]);
134+
$this->argumentStartTokensSet[TokenKind::DotDotDotToken] = '...';
131135
$this->nameOrKeywordOrReservedWordTokens = \array_merge([TokenKind::Name], $this->keywordTokens, $this->reservedWordTokens);
132136
$this->nameOrReservedWordTokens = \array_merge([TokenKind::Name], $this->reservedWordTokens);
133137
$this->nameOrStaticOrReservedWordTokens = \array_merge([TokenKind::Name, TokenKind::StaticKeyword], $this->reservedWordTokens);
@@ -2762,16 +2766,30 @@ private function parseMemberName($parentNode) {
27622766
private function isArgumentExpressionStartFn() {
27632767
return function ($token) {
27642768
return
2765-
$token->kind === TokenKind::DotDotDotToken ? true : $this->isExpressionStart($token);
2769+
isset($this->argumentStartTokensSet[$token->kind]) || $this->isExpressionStart($token);
27662770
};
27672771
}
27682772

27692773
private function parseArgumentExpressionFn() {
27702774
return function ($parentNode) {
27712775
$argumentExpression = new ArgumentExpression();
27722776
$argumentExpression->parent = $parentNode;
2773-
$argumentExpression->byRefToken = $this->eatOptional1(TokenKind::AmpersandToken);
2774-
$argumentExpression->dotDotDotToken = $this->eatOptional1(TokenKind::DotDotDotToken);
2777+
2778+
$nextToken = $this->lexer->getTokensArray()[$this->lexer->getCurrentPosition()] ?? null;
2779+
if ($nextToken && $nextToken->kind === TokenKind::ColonToken) {
2780+
$name = $this->token;
2781+
$this->advanceToken();
2782+
if ($name->kind === TokenKind::YieldFromKeyword || !\in_array($name->kind, $this->nameOrKeywordOrReservedWordTokens)) {
2783+
$name = new SkippedToken($name);
2784+
} else {
2785+
$name->kind = TokenKind::Name;
2786+
}
2787+
$argumentExpression->name = $name;
2788+
$argumentExpression->colonToken = $this->eat1(TokenKind::ColonToken);
2789+
} else {
2790+
$argumentExpression->byRefToken = $this->eatOptional1(TokenKind::AmpersandToken);
2791+
$argumentExpression->dotDotDotToken = $this->eatOptional1(TokenKind::DotDotDotToken);
2792+
}
27752793
$argumentExpression->expression = $this->parseExpression($argumentExpression);
27762794
return $argumentExpression;
27772795
};

tests/cases/parser/binaryAssignmentExpressions6.php.tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
"children": [
3737
{
3838
"ArgumentExpression": {
39+
"name": null,
40+
"colonToken": null,
3941
"byRefToken": null,
4042
"dotDotDotToken": null,
4143
"expression": {

tests/cases/parser/callExpression10.php.tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
"children": [
3737
{
3838
"ArgumentExpression": {
39+
"name": null,
40+
"colonToken": null,
3941
"byRefToken": null,
4042
"dotDotDotToken": null,
4143
"expression": {
@@ -54,6 +56,8 @@
5456
},
5557
{
5658
"ArgumentExpression": {
59+
"name": null,
60+
"colonToken": null,
5761
"byRefToken": null,
5862
"dotDotDotToken": null,
5963
"expression": {
@@ -72,6 +76,8 @@
7276
},
7377
{
7478
"ArgumentExpression": {
79+
"name": null,
80+
"colonToken": null,
7581
"byRefToken": null,
7682
"dotDotDotToken": null,
7783
"expression": {

tests/cases/parser/callExpression12.php.tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
"children": [
3737
{
3838
"ArgumentExpression": {
39+
"name": null,
40+
"colonToken": null,
3941
"byRefToken": null,
4042
"dotDotDotToken": null,
4143
"expression": {

tests/cases/parser/callExpression15.php.tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
"children": [
7272
{
7373
"ArgumentExpression": {
74+
"name": null,
75+
"colonToken": null,
7476
"byRefToken": null,
7577
"dotDotDotToken": null,
7678
"expression": {

tests/cases/parser/callExpression2.php.tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
"children": [
3434
{
3535
"ArgumentExpression": {
36+
"name": null,
37+
"colonToken": null,
3638
"byRefToken": null,
3739
"dotDotDotToken": null,
3840
"expression": {

tests/cases/parser/callExpression3.php.tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
"children": [
3434
{
3535
"ArgumentExpression": {
36+
"name": null,
37+
"colonToken": null,
3638
"byRefToken": null,
3739
"dotDotDotToken": null,
3840
"expression": {

tests/cases/parser/callExpression4.php.tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
"children": [
3434
{
3535
"ArgumentExpression": {
36+
"name": null,
37+
"colonToken": null,
3638
"byRefToken": null,
3739
"dotDotDotToken": null,
3840
"expression": {
@@ -69,6 +71,8 @@
6971
},
7072
{
7173
"ArgumentExpression": {
74+
"name": null,
75+
"colonToken": null,
7276
"byRefToken": null,
7377
"dotDotDotToken": null,
7478
"expression": {

tests/cases/parser/callExpression5.php.tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
"children": [
3434
{
3535
"ArgumentExpression": {
36+
"name": null,
37+
"colonToken": null,
3638
"byRefToken": null,
3739
"dotDotDotToken": null,
3840
"expression": {
@@ -69,6 +71,8 @@
6971
},
7072
{
7173
"ArgumentExpression": {
74+
"name": null,
75+
"colonToken": null,
7276
"byRefToken": null,
7377
"dotDotDotToken": null,
7478
"expression": {

0 commit comments

Comments
 (0)