Skip to content

Commit

Permalink
feat: add support for PHP 8.3 typed class constants (#1136)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kenneth-Sills authored Nov 6, 2024
1 parent 80eb946 commit 7a82704
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 4 deletions.
17 changes: 15 additions & 2 deletions src/ast/classconstant.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,27 @@ const IS_PRIVATE = "private";
* @memberOf module:php-parser
* @extends {ConstantStatement}
* @property {string} visibility
* @property {bool} final
* @property {boolean} final
* @property {boolean} nullable
* @property {TypeReference|IntersectionType|UnionType|null} type
* @property {AttrGroup[]} attrGroups
*/
const ClassConstant = ConstantStatement.extends(
KIND,
function ClassConstant(kind, constants, flags, attrGroups, docs, location) {
function ClassConstant(
kind,
constants,
flags,
nullable,
type,
attrGroups,
docs,
location
) {
ConstantStatement.apply(this, [kind || KIND, constants, docs, location]);
this.parseFlags(flags);
this.nullable = nullable;
this.type = type;
this.attrGroups = attrGroups;
}
);
Expand Down
8 changes: 6 additions & 2 deletions src/parser/class.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,17 @@ module.exports = {
/*
* Reads constant list
* ```ebnf
* constant_list ::= T_CONST (constant_declaration ',')* constant_declaration
* constant_list ::= T_CONST [type] (constant_declaration ',')* constant_declaration
* ```
*/
read_constant_list: function (flags, attrs) {
if (this.expect(this.tok.T_CONST)) {
this.next();
}

const [nullable, type] =
this.version >= 830 ? this.read_optional_type() : [false, null];

const result = this.node("classconstant");
const items = this.read_list(
/*
Expand Down Expand Up @@ -266,7 +270,7 @@ module.exports = {
","
);

return result(null, items, flags, attrs || []);
return result(null, items, flags, nullable, type, attrs || []);
},
/*
* Read member flags
Expand Down
2 changes: 2 additions & 0 deletions test/snapshot/__snapshots__/acid.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,8 @@ Program {
"offset": 544,
},
},
"nullable": false,
"type": null,
"visibility": "",
},
PropertyStatement {
Expand Down
4 changes: 4 additions & 0 deletions test/snapshot/__snapshots__/attributes.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@ Program {
],
"final": false,
"kind": "classconstant",
"nullable": false,
"type": null,
"visibility": "",
},
],
Expand Down Expand Up @@ -524,6 +526,8 @@ Program {
],
"final": false,
"kind": "classconstant",
"nullable": false,
"type": null,
"visibility": "",
},
Method {
Expand Down
8 changes: 8 additions & 0 deletions test/snapshot/__snapshots__/class.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ Program {
",
},
],
"nullable": false,
"type": null,
"visibility": "",
},
Method {
Expand Down Expand Up @@ -240,6 +242,8 @@ Program {
",
},
],
"nullable": false,
"type": null,
"visibility": "",
},
Method {
Expand Down Expand Up @@ -1338,6 +1342,8 @@ Program {
],
"final": false,
"kind": "classconstant",
"nullable": false,
"type": null,
"visibility": "",
},
PropertyStatement {
Expand Down Expand Up @@ -1448,6 +1454,8 @@ Program {
],
"final": false,
"kind": "classconstant",
"nullable": false,
"type": null,
"visibility": "",
},
Method {
Expand Down
67 changes: 67 additions & 0 deletions test/snapshot/__snapshots__/classconstant.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ Program {
],
"final": true,
"kind": "classconstant",
"nullable": false,
"type": null,
"visibility": "public",
},
],
Expand Down Expand Up @@ -87,6 +89,8 @@ Program {
],
"final": false,
"kind": "classconstant",
"nullable": false,
"type": null,
"visibility": "",
},
],
Expand Down Expand Up @@ -134,6 +138,8 @@ Program {
],
"final": false,
"kind": "classconstant",
"nullable": false,
"type": null,
"visibility": "private",
},
],
Expand Down Expand Up @@ -181,6 +187,8 @@ Program {
],
"final": false,
"kind": "classconstant",
"nullable": false,
"type": null,
"visibility": "protected",
},
],
Expand Down Expand Up @@ -228,6 +236,8 @@ Program {
],
"final": false,
"kind": "classconstant",
"nullable": false,
"type": null,
"visibility": "public",
},
],
Expand Down Expand Up @@ -275,6 +285,8 @@ Program {
],
"final": false,
"kind": "classconstant",
"nullable": false,
"type": null,
"visibility": "",
},
],
Expand All @@ -295,3 +307,58 @@ Program {
"kind": "program",
}
`;

exports[`classconstant type hinted (supported) 1`] = `
Program {
"children": [
Class {
"attrGroups": [],
"body": [
ClassConstant {
"attrGroups": [],
"constants": [
Constant {
"kind": "constant",
"name": Identifier {
"kind": "identifier",
"name": "CONSTANT",
},
"value": String {
"isDoubleQuote": true,
"kind": "string",
"raw": ""Hello world!"",
"unicode": false,
"value": "Hello world!",
},
},
],
"final": false,
"kind": "classconstant",
"nullable": false,
"type": TypeReference {
"kind": "typereference",
"name": "string",
"raw": "string",
},
"visibility": "public",
},
],
"extends": null,
"implements": null,
"isAbstract": false,
"isAnonymous": false,
"isFinal": false,
"isReadonly": false,
"kind": "class",
"name": Identifier {
"kind": "identifier",
"name": "Foo",
},
},
],
"errors": [],
"kind": "program",
}
`;

exports[`classconstant type hinted (unsupported) 1`] = `"Parse Error : syntax error, unexpected 'CONSTANT' (T_STRING), expecting '=' on line 1"`;
2 changes: 2 additions & 0 deletions test/snapshot/__snapshots__/enum.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ Program {
],
"final": false,
"kind": "classconstant",
"nullable": false,
"type": null,
"visibility": "public",
},
],
Expand Down
2 changes: 2 additions & 0 deletions test/snapshot/__snapshots__/heredoc.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1711,6 +1711,8 @@ FOOBAR",
],
"final": false,
"kind": "classconstant",
"nullable": false,
"type": null,
"visibility": "",
},
PropertyStatement {
Expand Down
2 changes: 2 additions & 0 deletions test/snapshot/__snapshots__/interface.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ Program {
],
"final": false,
"kind": "classconstant",
"nullable": false,
"type": null,
"visibility": "",
},
],
Expand Down
2 changes: 2 additions & 0 deletions test/snapshot/__snapshots__/nowdoc.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ FOOBAR",
],
"final": false,
"kind": "classconstant",
"nullable": false,
"type": null,
"visibility": "",
},
PropertyStatement {
Expand Down
16 changes: 16 additions & 0 deletions test/snapshot/classconstant.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,20 @@ describe("classconstant", () => {
)
).toMatchSnapshot();
});
it("type hinted (supported)", () => {
expect(
parser.parseEval(
'class Foo { public const string CONSTANT = "Hello world!"; }',
{ parser: { version: 830 } }
)
).toMatchSnapshot();
});
it("type hinted (unsupported)", () => {
expect(() =>
parser.parseEval(
'class Foo { public const string CONSTANT = "Hello world!"; }',
{ parser: { version: 820 } }
)
).toThrowErrorMatchingSnapshot();
});
});

0 comments on commit 7a82704

Please sign in to comment.