Skip to content

Commit ba3805b

Browse files
committed
Fix infinite loop parsing trait #[
Fixes microsoft#343
1 parent 6d546ce commit ba3805b

File tree

10 files changed

+368
-0
lines changed

10 files changed

+368
-0
lines changed

src/Parser.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,12 @@ private function parseAttributeStatement($parentNode) {
711711
if ($parentNode instanceof ClassMembersNode) {
712712
// Create a class element or a MissingMemberDeclaration
713713
$statement = $this->parseClassElementFn()($parentNode);
714+
} elseif ($parentNode instanceof TraitMembers) {
715+
// Create a trait element or a MissingMemberDeclaration
716+
$statement = $this->parseTraitElementFn()($parentNode);
717+
} elseif ($parentNode instanceof InterfaceMembers) {
718+
// Create an interface element or a MissingMemberDeclaration
719+
$statement = $this->parseInterfaceElementFn()($parentNode);
714720
} else {
715721
// Classlikes, anonymous functions, global functions, and arrow functions can have attributes. Global constants cannot.
716722
if (in_array($this->token->kind, [TokenKind::ClassKeyword, TokenKind::TraitKeyword, TokenKind::InterfaceKeyword, TokenKind::AbstractKeyword, TokenKind::FinalKeyword, TokenKind::FunctionKeyword, TokenKind::FnKeyword], true) ||
@@ -3319,6 +3325,9 @@ private function parseInterfaceElementFn() {
33193325
case TokenKind::FunctionKeyword:
33203326
return $this->parseMethodDeclaration($parentNode, $modifiers);
33213327

3328+
case TokenKind::AttributeToken:
3329+
return $this->parseAttributeStatement($parentNode);
3330+
33223331
default:
33233332
$missingInterfaceMemberDeclaration = new MissingMemberDeclaration();
33243333
$missingInterfaceMemberDeclaration->parent = $parentNode;
@@ -3499,6 +3508,9 @@ private function parseTraitElementFn() {
34993508
case TokenKind::UseKeyword:
35003509
return $this->parseTraitUseClause($parentNode);
35013510

3511+
case TokenKind::AttributeToken:
3512+
return $this->parseAttributeStatement($parentNode);
3513+
35023514
default:
35033515
return $this->parseRemainingPropertyDeclarationOrMissingMemberDeclaration($parentNode, $modifiers);
35043516
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
3+
trait #[
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[
2+
{
3+
"kind": 0,
4+
"message": "'Name' expected.",
5+
"start": 12,
6+
"length": 0
7+
},
8+
{
9+
"kind": 0,
10+
"message": "'{' expected.",
11+
"start": 12,
12+
"length": 0
13+
},
14+
{
15+
"kind": 0,
16+
"message": "']' expected.",
17+
"start": 15,
18+
"length": 0
19+
},
20+
{
21+
"kind": 0,
22+
"message": "'}' expected.",
23+
"start": 15,
24+
"length": 0
25+
}
26+
]
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
{
2+
"SourceFileNode": {
3+
"statementList": [
4+
{
5+
"InlineHtml": {
6+
"scriptSectionEndTag": null,
7+
"text": null,
8+
"scriptSectionStartTag": {
9+
"kind": "ScriptSectionStartTag",
10+
"textLength": 6
11+
}
12+
}
13+
},
14+
{
15+
"TraitDeclaration": {
16+
"attributes": null,
17+
"traitKeyword": {
18+
"kind": "TraitKeyword",
19+
"textLength": 5
20+
},
21+
"name": {
22+
"error": "MissingToken",
23+
"kind": "Name",
24+
"textLength": 0
25+
},
26+
"traitMembers": {
27+
"TraitMembers": {
28+
"openBrace": {
29+
"error": "MissingToken",
30+
"kind": "OpenBraceToken",
31+
"textLength": 0
32+
},
33+
"traitMemberDeclarations": [
34+
{
35+
"MissingMemberDeclaration": {
36+
"attributes": [
37+
{
38+
"AttributeGroup": {
39+
"startToken": {
40+
"kind": "AttributeToken",
41+
"textLength": 2
42+
},
43+
"attributes": null,
44+
"endToken": {
45+
"error": "MissingToken",
46+
"kind": "CloseBracketToken",
47+
"textLength": 0
48+
}
49+
}
50+
}
51+
],
52+
"modifiers": [],
53+
"questionToken": null,
54+
"typeDeclaration": null,
55+
"otherTypeDeclarations": null
56+
}
57+
}
58+
],
59+
"closeBrace": {
60+
"error": "MissingToken",
61+
"kind": "CloseBraceToken",
62+
"textLength": 0
63+
}
64+
}
65+
}
66+
}
67+
}
68+
],
69+
"endOfFileToken": {
70+
"kind": "EndOfFileToken",
71+
"textLength": 0
72+
}
73+
}
74+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?php
2+
interface #[
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[
2+
{
3+
"kind": 0,
4+
"message": "'Name' expected.",
5+
"start": 15,
6+
"length": 0
7+
},
8+
{
9+
"kind": 0,
10+
"message": "'{' expected.",
11+
"start": 15,
12+
"length": 0
13+
},
14+
{
15+
"kind": 0,
16+
"message": "']' expected.",
17+
"start": 18,
18+
"length": 0
19+
},
20+
{
21+
"kind": 0,
22+
"message": "'}' expected.",
23+
"start": 18,
24+
"length": 0
25+
}
26+
]
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
{
2+
"SourceFileNode": {
3+
"statementList": [
4+
{
5+
"InlineHtml": {
6+
"scriptSectionEndTag": null,
7+
"text": null,
8+
"scriptSectionStartTag": {
9+
"kind": "ScriptSectionStartTag",
10+
"textLength": 6
11+
}
12+
}
13+
},
14+
{
15+
"InterfaceDeclaration": {
16+
"attributes": null,
17+
"interfaceKeyword": {
18+
"kind": "InterfaceKeyword",
19+
"textLength": 9
20+
},
21+
"name": {
22+
"error": "MissingToken",
23+
"kind": "Name",
24+
"textLength": 0
25+
},
26+
"interfaceBaseClause": null,
27+
"interfaceMembers": {
28+
"InterfaceMembers": {
29+
"openBrace": {
30+
"error": "MissingToken",
31+
"kind": "OpenBraceToken",
32+
"textLength": 0
33+
},
34+
"interfaceMemberDeclarations": [
35+
{
36+
"MissingMemberDeclaration": {
37+
"attributes": [
38+
{
39+
"AttributeGroup": {
40+
"startToken": {
41+
"kind": "AttributeToken",
42+
"textLength": 2
43+
},
44+
"attributes": null,
45+
"endToken": {
46+
"error": "MissingToken",
47+
"kind": "CloseBracketToken",
48+
"textLength": 0
49+
}
50+
}
51+
}
52+
],
53+
"modifiers": [],
54+
"questionToken": null,
55+
"typeDeclaration": null,
56+
"otherTypeDeclarations": null
57+
}
58+
}
59+
],
60+
"closeBrace": {
61+
"error": "MissingToken",
62+
"kind": "CloseBraceToken",
63+
"textLength": 0
64+
}
65+
}
66+
}
67+
}
68+
}
69+
],
70+
"endOfFileToken": {
71+
"kind": "EndOfFileToken",
72+
"textLength": 0
73+
}
74+
}
75+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?php
2+
fn #[
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
[
2+
{
3+
"kind": 0,
4+
"message": "'(' expected.",
5+
"start": 8,
6+
"length": 0
7+
},
8+
{
9+
"kind": 0,
10+
"message": "']' expected.",
11+
"start": 11,
12+
"length": 0
13+
},
14+
{
15+
"kind": 0,
16+
"message": "'VariableName' expected.",
17+
"start": 11,
18+
"length": 0
19+
},
20+
{
21+
"kind": 0,
22+
"message": "')' expected.",
23+
"start": 11,
24+
"length": 0
25+
},
26+
{
27+
"kind": 0,
28+
"message": "'=>' expected.",
29+
"start": 11,
30+
"length": 0
31+
},
32+
{
33+
"kind": 0,
34+
"message": "'Expression' expected.",
35+
"start": 11,
36+
"length": 0
37+
},
38+
{
39+
"kind": 0,
40+
"message": "';' expected.",
41+
"start": 11,
42+
"length": 0
43+
}
44+
]

0 commit comments

Comments
 (0)