Skip to content

Commit b14a035

Browse files
committed
outputs attrs in AST of classes, methods & method params.
1 parent b36164a commit b14a035

File tree

5 files changed

+53
-8
lines changed

5 files changed

+53
-8
lines changed

src/parser/class.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module.exports = {
1212
* class ::= class_scope? T_CLASS T_STRING (T_EXTENDS NAMESPACE_NAME)? (T_IMPLEMENTS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' CLASS_BODY '}'
1313
* ```
1414
*/
15-
read_class_declaration_statement: function () {
15+
read_class_declaration_statement: function (attrs) {
1616
const result = this.node("class");
1717
const flag = this.read_class_modifiers();
1818
// graceful mode : ignore token & go next
@@ -30,7 +30,9 @@ module.exports = {
3030
const propImplements = this.read_implements_list();
3131
this.expect("{");
3232
const body = this.next().read_class_body();
33-
return result(propName, propExtends, propImplements, body, flag);
33+
const node = result(propName, propExtends, propImplements, body, flag);
34+
if (attrs) node.attrs = attrs;
35+
return node;
3436
},
3537

3638
read_class_modifiers: function () {
@@ -59,7 +61,7 @@ module.exports = {
5961
*/
6062
read_class_body: function () {
6163
let result = [];
62-
64+
let attrs = [];
6365
while (this.token !== this.EOF && this.token !== "}") {
6466
if (this.token === this.tok.T_COMMENT) {
6567
result.push(this.read_comment());
@@ -77,6 +79,9 @@ module.exports = {
7779
continue;
7880
}
7981

82+
if (this.token === this.tok.T_ATTRIBUTE) {
83+
attrs = this.read_attr_list();
84+
}
8085
// read member flags
8186
const flags = this.read_member_flags(false);
8287

@@ -99,7 +104,7 @@ module.exports = {
99104

100105
if (this.token === this.tok.T_FUNCTION) {
101106
// reads a function
102-
result.push(this.read_function(false, flags));
107+
result.push(this.read_function(false, flags, attrs));
103108
} else if (
104109
this.token === this.tok.T_VARIABLE ||
105110
// support https://wiki.php.net/rfc/typed_properties_v2

src/parser/expr.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,37 @@ module.exports = {
663663
return conds;
664664
},
665665

666+
read_attribute() {
667+
if (this.expect(this.tok.T_ATTRIBUTE)) {
668+
this.next();
669+
}
670+
const name = this.text();
671+
let args = [];
672+
this.next();
673+
if (this.token === "(") {
674+
args = this.read_argument_list();
675+
}
676+
return this.node("attribute")(name, args);
677+
},
678+
read_attr_list() {
679+
const list = [];
680+
let more = true;
681+
while (more) {
682+
list.push(this.read_attribute());
683+
if (this.token === ",") this.next();
684+
if (this.token === "]") {
685+
this.next();
686+
}
687+
if (this.token === this.tok.T_ATTRIBUTE) {
688+
// this.next();
689+
more = true;
690+
} else {
691+
more = false;
692+
}
693+
}
694+
return list;
695+
},
696+
666697
/**
667698
* ```ebnf
668699
* new_expr ::= T_NEW (namespace_name function_argument_list) | (T_CLASS ... class declaration)

src/parser/function.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ module.exports = {
3232
* function ::= function_declaration code_block
3333
* ```
3434
*/
35-
read_function: function (closure, flag) {
35+
read_function: function (closure, flag, attrs) {
3636
const result = this.read_function_declaration(
3737
closure ? 1 : flag ? 2 : 0,
3838
flag && flag[1] === 1
@@ -54,6 +54,7 @@ module.exports = {
5454
result.parseFlags(flag);
5555
}
5656
}
57+
if (attrs) result.attrs = attrs;
5758
return result;
5859
},
5960
/**
@@ -204,6 +205,8 @@ module.exports = {
204205
let value = null;
205206
let types = null;
206207
let nullable = false;
208+
let attrs = [];
209+
if (this.token === this.tok.T_ATTRIBUTE) attrs = this.read_attr_list();
207210
if (this.token === "?") {
208211
this.next();
209212
nullable = true;
@@ -226,7 +229,7 @@ module.exports = {
226229
if (this.token == "=") {
227230
value = this.next().read_expr();
228231
}
229-
return node(
232+
const result = node(
230233
parameterName,
231234
types,
232235
value,
@@ -235,6 +238,8 @@ module.exports = {
235238
nullable,
236239
flags
237240
);
241+
if (attrs) result.attrs = attrs;
242+
return result;
238243
},
239244
read_types() {
240245
const types = [];

src/parser/statement.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,18 @@ module.exports = {
3737
* ```
3838
*/
3939
read_top_statement: function () {
40+
let attrs = [];
41+
if (this.token === this.tok.T_ATTRIBUTE) {
42+
attrs = this.read_attr_list();
43+
}
4044
switch (this.token) {
4145
case this.tok.T_FUNCTION:
4246
return this.read_function(false, false);
4347
// optional flags
4448
case this.tok.T_ABSTRACT:
4549
case this.tok.T_FINAL:
4650
case this.tok.T_CLASS:
47-
return this.read_class_declaration_statement();
51+
return this.read_class_declaration_statement(attrs);
4852
case this.tok.T_INTERFACE:
4953
return this.read_interface_declaration_statement();
5054
case this.tok.T_TRAIT:

test/snapshot/attributes.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ describe("Parse Attributes", () => {
55
expect(
66
parser.parseEval(`
77
#[Deprecated]
8+
#[replace("use NewClass")]
89
class DepClass {}
910
`)
1011
).toMatchSnapshot();
1112
});
1213
it("can parse method attributes", () => {
1314
expect(
1415
parser.parseEval(`
15-
1616
class Test {
1717
#[Pure]
1818
function m() {}

0 commit comments

Comments
 (0)