Skip to content

Commit bd4eed0

Browse files
committed
Implemented AST export of attribute nodes.
1 parent 6ce5c27 commit bd4eed0

File tree

2 files changed

+108
-1
lines changed

2 files changed

+108
-1
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
--TEST--
2+
Attributes AST can be exported.
3+
--FILE--
4+
<?php
5+
6+
assert(0 && ($a = <<A1>><<A2>> function ($a, <<A3(1)>> $b) { }));
7+
8+
assert(0 && ($a = <<A1(1, 2, 1 + 2)>> fn () => 1));
9+
10+
assert(0 && ($a = new <<A1>> class() {
11+
<<A1>><<A2>> const FOO = 'foo';
12+
<<A2>> public $x;
13+
<<A3>> function a() { }
14+
}));
15+
16+
assert(0 && ($a = function () {
17+
<<A1>> class Test1 { }
18+
<<A2>> interface Test2 { }
19+
<<A3>> trait Test3 { }
20+
}));
21+
22+
?>
23+
--EXPECTF--
24+
Warning: assert(): assert(0 && ($a = <<A1>> <<A2>> function ($a, <<A3(1)>> $b) {
25+
})) failed in %s on line %d
26+
27+
Warning: assert(): assert(0 && ($a = <<A1(1, 2, 1 + 2)>> fn() => 1)) failed in %s on line %d
28+
29+
Warning: assert(): assert(0 && ($a = new <<A1>> class {
30+
<<A1>>
31+
<<A2>>
32+
const FOO = 'foo';
33+
<<A2>>
34+
public $x;
35+
<<A3>>
36+
public function a() {
37+
}
38+
39+
})) failed in %s on line %d
40+
41+
Warning: assert(): assert(0 && ($a = function () {
42+
<<A1>>
43+
class Test1 {
44+
}
45+
46+
<<A2>>
47+
interface Test2 {
48+
}
49+
50+
<<A3>>
51+
trait Test3 {
52+
}
53+
54+
})) failed in %s on line %d

Zend/zend_ast.c

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1317,6 +1317,41 @@ static ZEND_COLD void zend_ast_export_class_no_header(smart_str *str, zend_ast_d
13171317
smart_str_appends(str, "}");
13181318
}
13191319

1320+
static ZEND_COLD void zend_ast_export_attributes(smart_str *str, zend_ast *ast, int indent, zend_bool newlines) {
1321+
zend_ast_list *list = zend_ast_get_list(ast);
1322+
uint32_t i;
1323+
1324+
for (i = 0; i < list->children; i++) {
1325+
zend_ast *attr = list->child[i];
1326+
1327+
smart_str_appends(str, "<<");
1328+
smart_str_append(str, zend_ast_get_str(attr->child[0]));
1329+
1330+
if (attr->child[1]) {
1331+
zend_ast_list *args = zend_ast_get_list(attr->child[1]);
1332+
uint32_t j;
1333+
1334+
smart_str_appendc(str, '(');
1335+
for (j = 0; j < args->children; j++) {
1336+
if (j) {
1337+
smart_str_appends(str, ", ");
1338+
}
1339+
zend_ast_export_ex(str, args->child[j], 0, indent);
1340+
}
1341+
smart_str_appendc(str, ')');
1342+
}
1343+
1344+
smart_str_appends(str, ">>");
1345+
1346+
if (newlines) {
1347+
smart_str_appendc(str, '\n');
1348+
zend_ast_export_indent(str, indent);
1349+
} else {
1350+
smart_str_appendc(str, ' ');
1351+
}
1352+
}
1353+
}
1354+
13201355
static ZEND_COLD void zend_ast_export_type(smart_str *str, zend_ast *ast, int indent) {
13211356
if (ast->kind == ZEND_AST_TYPE_UNION) {
13221357
zend_ast_list *list = zend_ast_get_list(ast);
@@ -1410,6 +1445,10 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
14101445
case ZEND_AST_ARROW_FUNC:
14111446
case ZEND_AST_METHOD:
14121447
decl = (zend_ast_decl *) ast;
1448+
if (decl->attributes) {
1449+
zend_bool newlines = (ast->kind == ZEND_AST_CLOSURE || ast->kind == ZEND_AST_ARROW_FUNC) ? 0 : 1;
1450+
zend_ast_export_attributes(str, decl->attributes, indent, newlines);
1451+
}
14131452
if (decl->flags & ZEND_ACC_PUBLIC) {
14141453
smart_str_appends(str, "public ");
14151454
} else if (decl->flags & ZEND_ACC_PROTECTED) {
@@ -1466,6 +1505,9 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
14661505
break;
14671506
case ZEND_AST_CLASS:
14681507
decl = (zend_ast_decl *) ast;
1508+
if (decl->attributes) {
1509+
zend_ast_export_attributes(str, decl->attributes, indent, 1);
1510+
}
14691511
if (decl->flags & ZEND_ACC_INTERFACE) {
14701512
smart_str_appends(str, "interface ");
14711513
} else if (decl->flags & ZEND_ACC_TRAIT) {
@@ -1521,6 +1563,9 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
15211563
zend_ast *type_ast = ast->child[0];
15221564
zend_ast *prop_ast = ast->child[1];
15231565

1566+
if (ast->child[2]) {
1567+
zend_ast_export_attributes(str, ast->child[2], indent, 1);
1568+
}
15241569
if (ast->attr & ZEND_ACC_PUBLIC) {
15251570
smart_str_appends(str, "public ");
15261571
} else if (ast->attr & ZEND_ACC_PROTECTED) {
@@ -1546,6 +1591,7 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
15461591
smart_str_appends(str, "const ");
15471592
goto simple_list;
15481593
case ZEND_AST_CLASS_CONST_DECL_ATTRIBUTES:
1594+
zend_ast_export_attributes(str, ast->child[1], indent, 1);
15491595
zend_ast_export_ex(str, ast->child[0], 0, indent);
15501596
break;
15511597
case ZEND_AST_NAME_LIST:
@@ -1789,13 +1835,17 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
17891835
case ZEND_AST_NEW:
17901836
smart_str_appends(str, "new ");
17911837
if (ast->child[0]->kind == ZEND_AST_CLASS) {
1838+
zend_ast_decl *decl = (zend_ast_decl *) ast->child[0];
1839+
if (decl->attributes) {
1840+
zend_ast_export_attributes(str, decl->attributes, indent, 0);
1841+
}
17921842
smart_str_appends(str, "class");
17931843
if (zend_ast_get_list(ast->child[1])->children) {
17941844
smart_str_appendc(str, '(');
17951845
zend_ast_export_ex(str, ast->child[1], 0, indent);
17961846
smart_str_appendc(str, ')');
17971847
}
1798-
zend_ast_export_class_no_header(str, (zend_ast_decl *) ast->child[0], indent);
1848+
zend_ast_export_class_no_header(str, decl, indent);
17991849
} else {
18001850
zend_ast_export_ns_name(str, ast->child[0], 0, indent);
18011851
smart_str_appendc(str, '(');
@@ -2006,6 +2056,9 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
20062056
zend_ast_export_indent(str, indent);
20072057
break;
20082058
case ZEND_AST_PARAM:
2059+
if (ast->child[3]) {
2060+
zend_ast_export_attributes(str, ast->child[3], indent, 0);
2061+
}
20092062
if (ast->child[0]) {
20102063
zend_ast_export_type(str, ast->child[0], indent);
20112064
smart_str_appendc(str, ' ');

0 commit comments

Comments
 (0)