Skip to content

Commit 9c5902b

Browse files
authored
PHP 8.3 parser support untyped Class constant (glayzzle#1147)
1 parent 50d3bfb commit 9c5902b

File tree

3 files changed

+140
-3
lines changed

3 files changed

+140
-3
lines changed

src/parser/class.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ module.exports = {
228228
}
229229

230230
const [nullable, type] =
231-
this.version >= 830 ? this.read_optional_type() : [false, null];
231+
this.version >= 803 ? this.read_optional_type() : [false, null];
232232

233233
const result = this.node("classconstant");
234234
const items = this.read_list(
@@ -357,6 +357,11 @@ module.exports = {
357357
if (nullable) {
358358
this.next();
359359
}
360+
361+
if (this.peek() === "=") {
362+
return [false, null];
363+
}
364+
360365
let type = this.read_types();
361366
if (nullable && !type) {
362367
this.raiseError(

test/snapshot/__snapshots__/classconstant.test.js.snap

+112
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,69 @@ Program {
112112
}
113113
`;
114114

115+
exports[`classconstant multiple 8.3 1`] = `
116+
Program {
117+
"children": [
118+
Class {
119+
"attrGroups": [],
120+
"body": [
121+
ClassConstant {
122+
"attrGroups": [],
123+
"constants": [
124+
Constant {
125+
"kind": "constant",
126+
"name": Identifier {
127+
"kind": "identifier",
128+
"name": "NAME_1",
129+
},
130+
"value": String {
131+
"isDoubleQuote": true,
132+
"kind": "string",
133+
"raw": ""Hello world!"",
134+
"unicode": false,
135+
"value": "Hello world!",
136+
},
137+
},
138+
Constant {
139+
"kind": "constant",
140+
"name": Identifier {
141+
"kind": "identifier",
142+
"name": "NAME_2",
143+
},
144+
"value": String {
145+
"isDoubleQuote": true,
146+
"kind": "string",
147+
"raw": ""Other hello world!"",
148+
"unicode": false,
149+
"value": "Other hello world!",
150+
},
151+
},
152+
],
153+
"final": false,
154+
"kind": "classconstant",
155+
"nullable": false,
156+
"type": null,
157+
"visibility": "",
158+
},
159+
],
160+
"extends": null,
161+
"implements": null,
162+
"isAbstract": false,
163+
"isAnonymous": false,
164+
"isFinal": false,
165+
"isReadonly": false,
166+
"kind": "class",
167+
"name": Identifier {
168+
"kind": "identifier",
169+
"name": "Foo",
170+
},
171+
},
172+
],
173+
"errors": [],
174+
"kind": "program",
175+
}
176+
`;
177+
115178
exports[`classconstant private 1`] = `
116179
Program {
117180
"children": [
@@ -308,6 +371,55 @@ Program {
308371
}
309372
`;
310373

374+
exports[`classconstant simple using 8.3 1`] = `
375+
Program {
376+
"children": [
377+
Class {
378+
"attrGroups": [],
379+
"body": [
380+
ClassConstant {
381+
"attrGroups": [],
382+
"constants": [
383+
Constant {
384+
"kind": "constant",
385+
"name": Identifier {
386+
"kind": "identifier",
387+
"name": "CONSTANT",
388+
},
389+
"value": String {
390+
"isDoubleQuote": true,
391+
"kind": "string",
392+
"raw": ""Hello world!"",
393+
"unicode": false,
394+
"value": "Hello world!",
395+
},
396+
},
397+
],
398+
"final": false,
399+
"kind": "classconstant",
400+
"nullable": false,
401+
"type": null,
402+
"visibility": "",
403+
},
404+
],
405+
"extends": null,
406+
"implements": null,
407+
"isAbstract": false,
408+
"isAnonymous": false,
409+
"isFinal": false,
410+
"isReadonly": false,
411+
"kind": "class",
412+
"name": Identifier {
413+
"kind": "identifier",
414+
"name": "Foo",
415+
},
416+
},
417+
],
418+
"errors": [],
419+
"kind": "program",
420+
}
421+
`;
422+
311423
exports[`classconstant type hinted (supported) 1`] = `
312424
Program {
313425
"children": [

test/snapshot/classconstant.test.js

+22-2
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,33 @@ describe("classconstant", () => {
66
parser.parseEval('class Foo { const CONSTANT = "Hello world!"; }'),
77
).toMatchSnapshot();
88
});
9+
it("simple using 8.3", () => {
10+
expect(
11+
parser.parseEval(`class Foo { const CONSTANT = "Hello world!"; }`, {
12+
parser: { version: 803 },
13+
}),
14+
).toMatchSnapshot();
15+
});
16+
917
it("multiple", () => {
1018
expect(
1119
parser.parseEval(
1220
'class Foo { const CONSTANT = "Hello world!", OTHER_CONSTANT = "Other hello world!"; }',
1321
),
1422
).toMatchSnapshot();
1523
});
24+
25+
it("multiple 8.3", () => {
26+
expect(
27+
parser.parseEval(
28+
'class Foo { const NAME_1 = "Hello world!", NAME_2 = "Other hello world!"; }',
29+
{
30+
parser: { version: 803 },
31+
},
32+
),
33+
).toMatchSnapshot();
34+
});
35+
1636
it("public", () => {
1737
expect(
1838
parser.parseEval('class Foo { public const CONSTANT = "Hello world!"; }'),
@@ -43,15 +63,15 @@ describe("classconstant", () => {
4363
expect(
4464
parser.parseEval(
4565
'class Foo { public const string CONSTANT = "Hello world!"; }',
46-
{ parser: { version: 830 } },
66+
{ parser: { version: 803 } },
4767
),
4868
).toMatchSnapshot();
4969
});
5070
it("type hinted (unsupported)", () => {
5171
expect(() =>
5272
parser.parseEval(
5373
'class Foo { public const string CONSTANT = "Hello world!"; }',
54-
{ parser: { version: 820 } },
74+
{ parser: { version: 802 } },
5575
),
5676
).toThrowErrorMatchingSnapshot();
5777
});

0 commit comments

Comments
 (0)