Skip to content

Commit

Permalink
added support for attributes on:
Browse files Browse the repository at this point in the history
- anonymous classes
- class constants
  • Loading branch information
cseufert committed Jun 15, 2021
1 parent c190d18 commit 257595c
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 22 deletions.
3 changes: 3 additions & 0 deletions src/ast/classconstant.js
Expand Up @@ -18,16 +18,19 @@ const IS_PRIVATE = "private";
* @constructor ClassConstant
* @extends {ConstantStatement}
* @property {string} visibility
* @property {AttrGroup[]} attrGroups
*/
const ClassConstant = ConstantStatement.extends(KIND, function ClassConstant(
kind,
constants,
flags,
attrGroups,
docs,
location
) {
ConstantStatement.apply(this, [kind || KIND, constants, docs, location]);
this.parseFlags(flags);
this.attrGroups = attrGroups;
});

/**
Expand Down
13 changes: 7 additions & 6 deletions src/parser/class.js
Expand Up @@ -87,7 +87,7 @@ module.exports = {

// check constant
if (this.token === this.tok.T_CONST) {
const constants = this.read_constant_list(flags);
const constants = this.read_constant_list(flags, attrs);
if (this.expect(";")) {
this.next();
}
Expand Down Expand Up @@ -189,7 +189,7 @@ module.exports = {
* constant_list ::= T_CONST (constant_declaration ',')* constant_declaration
* ```
*/
read_constant_list: function (flags) {
read_constant_list: function (flags, attrs) {
if (this.expect(this.tok.T_CONST)) {
this.next();
}
Expand Down Expand Up @@ -226,7 +226,7 @@ module.exports = {
","
);

return result(null, items, flags);
return result(null, items, flags, attrs || []);
},
/**
* Read member flags
Expand Down Expand Up @@ -375,7 +375,8 @@ module.exports = {
* ```
*/
read_interface_body: function () {
let result = [];
let result = [],
attrs = [];

while (this.token !== this.EOF && this.token !== "}") {
if (this.token === this.tok.T_COMMENT) {
Expand All @@ -387,13 +388,13 @@ module.exports = {
result.push(this.read_doc_comment());
continue;
}

attrs = this.read_attr_list();
// read member flags
const flags = this.read_member_flags(true);

// check constant
if (this.token == this.tok.T_CONST) {
const constants = this.read_constant_list(flags);
const constants = this.read_constant_list(flags, attrs);
if (this.expect(";")) {
this.next();
}
Expand Down
32 changes: 16 additions & 16 deletions src/parser/expr.js
Expand Up @@ -684,19 +684,19 @@ module.exports = {
},
read_attr_list() {
const list = [];
do {
this.expect(this.tok.T_ATTRIBUTE);
const attrGr = this.node("attrgroup")([]);
this.next();
attrGr.attrs.push(this.read_attribute());
while (this.token === ",") {
if (this.token === this.tok.T_ATTRIBUTE)
do {
const attrGr = this.node("attrgroup")([]);
this.next();
if (this.token !== "]") attrGr.attrs.push(this.read_attribute());
}
list.push(attrGr);
this.expect("]");
this.next();
} while (this.token === this.tok.T_ATTRIBUTE);
attrGr.attrs.push(this.read_attribute());
while (this.token === ",") {
this.next();
if (this.token !== "]") attrGr.attrs.push(this.read_attribute());
}
list.push(attrGr);
this.expect("]");
this.next();
} while (this.token === this.tok.T_ATTRIBUTE);
return list;
},

Expand All @@ -710,6 +710,7 @@ module.exports = {
const result = this.node("new");
this.expect(this.tok.T_NEW) && this.next();
let args = [];
const attrs = this.read_attr_list();
if (this.token === this.tok.T_CLASS) {
const what = this.node("class");
// Annonymous class declaration
Expand All @@ -722,10 +723,9 @@ module.exports = {
if (this.expect("{")) {
body = this.next().read_class_body();
}
return result(
what(null, propExtends, propImplements, body, [0, 0, 0]),
args
);
const whatNode = what(null, propExtends, propImplements, body, [0, 0, 0]);
whatNode.attrGroups = attrs;
return result(whatNode, args);
}
// Already existing class
const name = this.read_new_class_name();
Expand Down
1 change: 1 addition & 0 deletions test/snapshot/__snapshots__/acid.test.js.snap
Expand Up @@ -755,6 +755,7 @@ Program {
],
},
ClassConstant {
"attrGroups": Array [],
"constants": Array [
Constant {
"kind": "constant",
Expand Down
100 changes: 100 additions & 0 deletions test/snapshot/__snapshots__/attributes.test.js.snap
@@ -1,5 +1,52 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Parse Attributes can parse anon-class attributes 1`] = `
Program {
"children": Array [
ExpressionStatement {
"expression": Assign {
"kind": "assign",
"left": Variable {
"curly": false,
"kind": "variable",
"name": "a",
},
"operator": "=",
"right": New {
"arguments": Array [],
"kind": "new",
"what": Class {
"attrGroups": Array [
AttrGroup {
"attrs": Array [
Attribute {
"args": Array [],
"kind": "attribute",
"name": "T",
},
],
"kind": "attrgroup",
},
],
"body": Array [],
"extends": null,
"implements": null,
"isAbstract": false,
"isAnonymous": true,
"isFinal": false,
"kind": "class",
"name": null,
},
},
},
"kind": "expressionstatement",
},
],
"errors": Array [],
"kind": "program",
}
`;

exports[`Parse Attributes can parse anonymous function attributes 1`] = `
Program {
"children": Array [
Expand Down Expand Up @@ -135,6 +182,59 @@ Program {
}
`;

exports[`Parse Attributes can parse class const attributes 1`] = `
Program {
"children": Array [
Class {
"attrGroups": Array [],
"body": Array [
ClassConstant {
"attrGroups": Array [
AttrGroup {
"attrs": Array [
Attribute {
"args": Array [],
"kind": "attribute",
"name": "B",
},
],
"kind": "attrgroup",
},
],
"constants": Array [
Constant {
"kind": "constant",
"name": Identifier {
"kind": "identifier",
"name": "B",
},
"value": Number {
"kind": "number",
"value": "1",
},
},
],
"kind": "classconstant",
"visibility": "",
},
],
"extends": null,
"implements": null,
"isAbstract": false,
"isAnonymous": false,
"isFinal": false,
"kind": "class",
"name": Identifier {
"kind": "identifier",
"name": "A",
},
},
],
"errors": Array [],
"kind": "program",
}
`;

exports[`Parse Attributes can parse class property attributes 1`] = `
Program {
"children": Array [
Expand Down
4 changes: 4 additions & 0 deletions test/snapshot/__snapshots__/class.test.js.snap
Expand Up @@ -143,6 +143,7 @@ Program {
Interface {
"body": Array [
ClassConstant {
"attrGroups": Array [],
"constants": Array [
Constant {
"kind": "constant",
Expand Down Expand Up @@ -208,6 +209,7 @@ Program {
Trait {
"body": Array [
ClassConstant {
"attrGroups": Array [],
"constants": Array [
Constant {
"kind": "constant",
Expand Down Expand Up @@ -878,6 +880,7 @@ Program {
"attrGroups": Array [],
"body": Array [
ClassConstant {
"attrGroups": Array [],
"constants": Array [
Constant {
"kind": "constant",
Expand Down Expand Up @@ -983,6 +986,7 @@ Program {
"visibility": "public",
},
ClassConstant {
"attrGroups": Array [],
"constants": Array [
Constant {
"kind": "constant",
Expand Down
5 changes: 5 additions & 0 deletions test/snapshot/__snapshots__/classconstant.test.js.snap
Expand Up @@ -7,6 +7,7 @@ Program {
"attrGroups": Array [],
"body": Array [
ClassConstant {
"attrGroups": Array [],
"constants": Array [
Constant {
"kind": "constant",
Expand Down Expand Up @@ -65,6 +66,7 @@ Program {
"attrGroups": Array [],
"body": Array [
ClassConstant {
"attrGroups": Array [],
"constants": Array [
Constant {
"kind": "constant",
Expand Down Expand Up @@ -109,6 +111,7 @@ Program {
"attrGroups": Array [],
"body": Array [
ClassConstant {
"attrGroups": Array [],
"constants": Array [
Constant {
"kind": "constant",
Expand Down Expand Up @@ -153,6 +156,7 @@ Program {
"attrGroups": Array [],
"body": Array [
ClassConstant {
"attrGroups": Array [],
"constants": Array [
Constant {
"kind": "constant",
Expand Down Expand Up @@ -197,6 +201,7 @@ Program {
"attrGroups": Array [],
"body": Array [
ClassConstant {
"attrGroups": Array [],
"constants": Array [
Constant {
"kind": "constant",
Expand Down
1 change: 1 addition & 0 deletions test/snapshot/__snapshots__/heredoc.test.js.snap
Expand Up @@ -1676,6 +1676,7 @@ Program {
"attrGroups": Array [],
"body": Array [
ClassConstant {
"attrGroups": Array [],
"constants": Array [
Constant {
"kind": "constant",
Expand Down
1 change: 1 addition & 0 deletions test/snapshot/__snapshots__/nowdoc.test.js.snap
Expand Up @@ -128,6 +128,7 @@ Program {
"attrGroups": Array [],
"body": Array [
ClassConstant {
"attrGroups": Array [],
"constants": Array [
Constant {
"kind": "constant",
Expand Down
13 changes: 13 additions & 0 deletions test/snapshot/attributes.test.js
Expand Up @@ -100,4 +100,17 @@ describe("Parse Attributes", () => {
`)
).toMatchSnapshot();
});
it("can parse class const attributes", () => {
expect(
parser.parseEval(`
class A {
#[B]
const B = 1;
}
`)
).toMatchSnapshot();
});
it("can parse anon-class attributes", () => {
expect(parser.parseEval(`$a = new #[T] class {};`)).toMatchSnapshot();
});
});

0 comments on commit 257595c

Please sign in to comment.