From e446f0f64635adab3cb7f87a50f602c41263a963 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Fri, 14 May 2021 14:04:37 -0400 Subject: [PATCH 1/2] Support parsing php 8.1 enum doc comments Requires https://github.com/php/php-src/pull/6984 (php 8.1 has no public alphas yet) --- ast_data.c | 21 +++++++++++---------- ast_stub.php | 2 +- package.xml | 29 ++++++++++++++++++++++------- php_ast.h | 2 +- scripts/generate_ast_data.php | 2 +- tests/metadata.phpt | 2 +- tests/php81_enums.phpt | 7 +++++++ 7 files changed, 44 insertions(+), 21 deletions(-) diff --git a/ast_data.c b/ast_data.c index abbd1ab..f576c97 100644 --- a/ast_data.c +++ b/ast_data.c @@ -97,7 +97,6 @@ const zend_ast_kind ast_kinds[] = { ZEND_AST_MATCH, ZEND_AST_MATCH_ARM, ZEND_AST_NAMED_ARG, - ZEND_AST_ENUM_CASE, ZEND_AST_METHOD_CALL, ZEND_AST_NULLSAFE_METHOD_CALL, ZEND_AST_STATIC_CALL, @@ -106,6 +105,7 @@ const zend_ast_kind ast_kinds[] = { ZEND_AST_CATCH, ZEND_AST_FOR, ZEND_AST_FOREACH, + ZEND_AST_ENUM_CASE, ZEND_AST_PARAM, }; @@ -209,7 +209,6 @@ const char *ast_kind_to_name(zend_ast_kind kind) { case ZEND_AST_MATCH: return "AST_MATCH"; case ZEND_AST_MATCH_ARM: return "AST_MATCH_ARM"; case ZEND_AST_NAMED_ARG: return "AST_NAMED_ARG"; - case ZEND_AST_ENUM_CASE: return "AST_ENUM_CASE"; case ZEND_AST_METHOD_CALL: return "AST_METHOD_CALL"; case ZEND_AST_NULLSAFE_METHOD_CALL: return "AST_NULLSAFE_METHOD_CALL"; case ZEND_AST_STATIC_CALL: return "AST_STATIC_CALL"; @@ -218,6 +217,7 @@ const char *ast_kind_to_name(zend_ast_kind kind) { case ZEND_AST_CATCH: return "AST_CATCH"; case ZEND_AST_FOR: return "AST_FOR"; case ZEND_AST_FOREACH: return "AST_FOREACH"; + case ZEND_AST_ENUM_CASE: return "AST_ENUM_CASE"; case ZEND_AST_PARAM: return "AST_PARAM"; } @@ -654,13 +654,6 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { case 1: return AST_STR(str_expr); } return NULL; - case ZEND_AST_ENUM_CASE: - switch (child) { - case 0: return AST_STR(str_name); - case 1: return AST_STR(str_expr); - case 2: return AST_STR(str_attributes); - } - return NULL; case ZEND_AST_METHOD_CALL: switch (child) { case 0: return AST_STR(str_expr); @@ -719,6 +712,14 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { case 3: return AST_STR(str_stmts); } return NULL; + case ZEND_AST_ENUM_CASE: + switch (child) { + case 0: return AST_STR(str_name); + case 1: return AST_STR(str_expr); + case 2: return AST_STR(str_docComment); + case 3: return AST_STR(str_attributes); + } + return NULL; case ZEND_AST_PARAM: switch (child) { case 0: return AST_STR(str_type); @@ -830,7 +831,6 @@ void ast_register_kind_constants(INIT_FUNC_ARGS) { REGISTER_NS_LONG_CONSTANT("ast", "AST_MATCH", ZEND_AST_MATCH, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_MATCH_ARM", ZEND_AST_MATCH_ARM, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_NAMED_ARG", ZEND_AST_NAMED_ARG, CONST_CS | CONST_PERSISTENT); - REGISTER_NS_LONG_CONSTANT("ast", "AST_ENUM_CASE", ZEND_AST_ENUM_CASE, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_METHOD_CALL", ZEND_AST_METHOD_CALL, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_NULLSAFE_METHOD_CALL", ZEND_AST_NULLSAFE_METHOD_CALL, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_STATIC_CALL", ZEND_AST_STATIC_CALL, CONST_CS | CONST_PERSISTENT); @@ -839,5 +839,6 @@ void ast_register_kind_constants(INIT_FUNC_ARGS) { REGISTER_NS_LONG_CONSTANT("ast", "AST_CATCH", ZEND_AST_CATCH, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_FOR", ZEND_AST_FOR, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_FOREACH", ZEND_AST_FOREACH, CONST_CS | CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("ast", "AST_ENUM_CASE", ZEND_AST_ENUM_CASE, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_PARAM", ZEND_AST_PARAM, CONST_CS | CONST_PERSISTENT); } diff --git a/ast_stub.php b/ast_stub.php index e30df73..014858c 100644 --- a/ast_stub.php +++ b/ast_stub.php @@ -103,7 +103,6 @@ const AST_MATCH = 548; const AST_MATCH_ARM = 549; const AST_NAMED_ARG = 550; -const AST_ENUM_CASE = 777; const AST_METHOD_CALL = 768; const AST_NULLSAFE_METHOD_CALL = 769; const AST_STATIC_CALL = 770; @@ -112,6 +111,7 @@ const AST_CATCH = 773; const AST_FOR = 1024; const AST_FOREACH = 1025; +const AST_ENUM_CASE = 1026; const AST_PARAM = 1280; // END AST KIND CONSTANTS diff --git a/package.xml b/package.xml index ed43328..27c5e40 100644 --- a/package.xml +++ b/package.xml @@ -18,20 +18,18 @@ tandre@php.net yes - 2021-04-20 + 2021-05-14 - 1.0.11 - 1.0.11 + 1.0.12dev + 1.0.12dev - stable + alpha stable BSD-3-Clause -- Add the experimental AST version 85. -- Support php 8.1 enums, add 'type' (for enum type) to AST_CLASS nodes in AST version 85+. -- Support php 8.1 'never' return type. +- Support parsing 'docComment' on php 8.1 enums @@ -140,6 +138,23 @@ ast + + 2021-04-20 + + 1.0.11 + 1.0.11 + + + stable + stable + + BSD-3-Clause + +- Add the experimental AST version 85. +- Support php 8.1 enums, add 'type' (for enum type) to AST_CLASS nodes in AST version 85+. +- Support php 8.1 'never' return type. + + 2020-09-12 diff --git a/php_ast.h b/php_ast.h index bec98cf..d9a2edc 100644 --- a/php_ast.h +++ b/php_ast.h @@ -7,7 +7,7 @@ extern zend_module_entry ast_module_entry; #define phpext_ast_ptr &ast_module_entry -#define PHP_AST_VERSION "1.0.11" +#define PHP_AST_VERSION "1.0.12dev" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) diff --git a/scripts/generate_ast_data.php b/scripts/generate_ast_data.php index 588f0be..4c24433 100644 --- a/scripts/generate_ast_data.php +++ b/scripts/generate_ast_data.php @@ -134,7 +134,6 @@ 'ZEND_AST_MATCH' => ['cond', 'stmts'], 'ZEND_AST_MATCH_ARM' => ['cond', 'expr'], 'ZEND_AST_NAMED_ARG' => ['name', 'expr'], - 'ZEND_AST_ENUM_CASE' => ['name', 'expr', 'attributes'], /* 3 child nodes */ 'ZEND_AST_METHOD_CALL' => ['expr', 'method', 'args'], @@ -148,6 +147,7 @@ /* 4 child nodes */ 'ZEND_AST_FOR' => ['init', 'cond', 'loop', 'stmts'], 'ZEND_AST_FOREACH' => ['expr', 'value', 'key', 'stmts'], + 'ZEND_AST_ENUM_CASE' => ['name', 'expr', 'docComment', 'attributes'], /* 5 child nodes */ 'ZEND_AST_PARAM' => ['type', 'name', 'default', 'attributes', 'docComment'], diff --git a/tests/metadata.phpt b/tests/metadata.phpt index 67f3264..fccc05e 100644 --- a/tests/metadata.phpt +++ b/tests/metadata.phpt @@ -122,7 +122,6 @@ AST_ATTRIBUTE: [] AST_MATCH: [] AST_MATCH_ARM: [] AST_NAMED_ARG: [] -AST_ENUM_CASE: [] AST_METHOD_CALL: [] AST_NULLSAFE_METHOD_CALL: [] AST_STATIC_CALL: [] @@ -131,4 +130,5 @@ AST_TRY: [] AST_CATCH: [] AST_FOR: [] AST_FOREACH: [] +AST_ENUM_CASE: [] AST_PARAM: (combinable) [PARAM_REF, PARAM_VARIADIC, PARAM_MODIFIER_PUBLIC, PARAM_MODIFIER_PROTECTED, PARAM_MODIFIER_PRIVATE] diff --git a/tests/php81_enums.phpt b/tests/php81_enums.phpt index ee23cd9..299cdcf 100644 --- a/tests/php81_enums.phpt +++ b/tests/php81_enums.phpt @@ -16,6 +16,7 @@ enum HasValue: int { #[MyAttribute(1)] enum NoValue { + /** Case doc comment */ #[OtherAttribute()] case FOO; } @@ -39,6 +40,7 @@ AST_STMT_LIST 0: AST_ENUM_CASE name: "FOO" expr: 42 + docComment: null attributes: null 1: AST_CLASS_CONST_DECL flags: MODIFIER_PUBLIC (%d) @@ -61,6 +63,7 @@ AST_STMT_LIST 0: AST_ENUM_CASE name: "FOO" expr: null + docComment: "/** Case doc comment */" attributes: AST_ATTRIBUTE_LIST 0: AST_ATTRIBUTE_GROUP 0: AST_ATTRIBUTE @@ -80,6 +83,7 @@ AST_STMT_LIST 0: AST_ENUM_CASE name: "FOO" expr: 42 + docComment: null attributes: null 1: AST_CLASS_CONST_GROUP flags: MODIFIER_PUBLIC (%d) @@ -106,6 +110,7 @@ AST_STMT_LIST 0: AST_ENUM_CASE name: "FOO" expr: null + docComment: "/** Case doc comment */" attributes: AST_ATTRIBUTE_LIST 0: AST_ATTRIBUTE_GROUP 0: AST_ATTRIBUTE @@ -133,6 +138,7 @@ AST_STMT_LIST 0: AST_ENUM_CASE name: "FOO" expr: 42 + docComment: null attributes: null 1: AST_CLASS_CONST_GROUP flags: MODIFIER_PUBLIC (%d) @@ -161,6 +167,7 @@ AST_STMT_LIST 0: AST_ENUM_CASE name: "FOO" expr: null + docComment: "/** Case doc comment */" attributes: AST_ATTRIBUTE_LIST 0: AST_ATTRIBUTE_GROUP 0: AST_ATTRIBUTE From f58aecd88b22f716098874319af063a9a5228aa4 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Fri, 14 May 2021 14:17:48 -0400 Subject: [PATCH 2/2] Combine equivalent case statements in generated code --- ast_data.c | 200 +++------------------------------- scripts/generate_ast_data.php | 17 ++- 2 files changed, 28 insertions(+), 189 deletions(-) diff --git a/ast_data.c b/ast_data.c index f576c97..264d44e 100644 --- a/ast_data.c +++ b/ast_data.c @@ -227,11 +227,10 @@ const char *ast_kind_to_name(zend_ast_kind kind) { zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { switch (kind) { case AST_NAME: - switch (child) { - case 0: return AST_STR(str_name); - } - return NULL; case AST_CLOSURE_VAR: + case ZEND_AST_VAR: + case ZEND_AST_CONST: + case ZEND_AST_LABEL: switch (child) { case 0: return AST_STR(str_name); } @@ -242,32 +241,8 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { } return NULL; case ZEND_AST_FUNC_DECL: - switch (child) { - case 0: return AST_STR(str_params); - case 1: return AST_STR(str_uses); - case 2: return AST_STR(str_stmts); - case 3: return AST_STR(str_returnType); - case 4: return AST_STR(str_attributes); - } - return NULL; case ZEND_AST_CLOSURE: - switch (child) { - case 0: return AST_STR(str_params); - case 1: return AST_STR(str_uses); - case 2: return AST_STR(str_stmts); - case 3: return AST_STR(str_returnType); - case 4: return AST_STR(str_attributes); - } - return NULL; case ZEND_AST_METHOD: - switch (child) { - case 0: return AST_STR(str_params); - case 1: return AST_STR(str_uses); - case 2: return AST_STR(str_stmts); - case 3: return AST_STR(str_returnType); - case 4: return AST_STR(str_attributes); - } - return NULL; case ZEND_AST_ARROW_FUNC: switch (child) { case 0: return AST_STR(str_params); @@ -287,114 +262,32 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { } return NULL; case ZEND_AST_MAGIC_CONST: - return NULL; case ZEND_AST_TYPE: return NULL; - case ZEND_AST_VAR: - switch (child) { - case 0: return AST_STR(str_name); - } - return NULL; - case ZEND_AST_CONST: - switch (child) { - case 0: return AST_STR(str_name); - } - return NULL; case ZEND_AST_UNPACK: - switch (child) { - case 0: return AST_STR(str_expr); - } - return NULL; case ZEND_AST_CAST: - switch (child) { - case 0: return AST_STR(str_expr); - } - return NULL; case ZEND_AST_EMPTY: - switch (child) { - case 0: return AST_STR(str_expr); - } - return NULL; - case ZEND_AST_ISSET: - switch (child) { - case 0: return AST_STR(str_var); - } - return NULL; case ZEND_AST_SHELL_EXEC: - switch (child) { - case 0: return AST_STR(str_expr); - } - return NULL; case ZEND_AST_CLONE: - switch (child) { - case 0: return AST_STR(str_expr); - } - return NULL; case ZEND_AST_EXIT: - switch (child) { - case 0: return AST_STR(str_expr); - } - return NULL; case ZEND_AST_PRINT: - switch (child) { - case 0: return AST_STR(str_expr); - } - return NULL; case ZEND_AST_INCLUDE_OR_EVAL: - switch (child) { - case 0: return AST_STR(str_expr); - } - return NULL; case ZEND_AST_UNARY_OP: + case ZEND_AST_YIELD_FROM: + case ZEND_AST_RETURN: + case ZEND_AST_ECHO: + case ZEND_AST_THROW: switch (child) { case 0: return AST_STR(str_expr); } return NULL; + case ZEND_AST_ISSET: case ZEND_AST_PRE_INC: - switch (child) { - case 0: return AST_STR(str_var); - } - return NULL; case ZEND_AST_PRE_DEC: - switch (child) { - case 0: return AST_STR(str_var); - } - return NULL; case ZEND_AST_POST_INC: - switch (child) { - case 0: return AST_STR(str_var); - } - return NULL; case ZEND_AST_POST_DEC: - switch (child) { - case 0: return AST_STR(str_var); - } - return NULL; - case ZEND_AST_YIELD_FROM: - switch (child) { - case 0: return AST_STR(str_expr); - } - return NULL; case ZEND_AST_GLOBAL: - switch (child) { - case 0: return AST_STR(str_var); - } - return NULL; case ZEND_AST_UNSET: - switch (child) { - case 0: return AST_STR(str_var); - } - return NULL; - case ZEND_AST_RETURN: - switch (child) { - case 0: return AST_STR(str_expr); - } - return NULL; - case ZEND_AST_LABEL: - switch (child) { - case 0: return AST_STR(str_name); - } - return NULL; case ZEND_AST_REF: switch (child) { case 0: return AST_STR(str_var); @@ -405,26 +298,12 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { case 0: return AST_STR(str_offset); } return NULL; - case ZEND_AST_ECHO: - switch (child) { - case 0: return AST_STR(str_expr); - } - return NULL; - case ZEND_AST_THROW: - switch (child) { - case 0: return AST_STR(str_expr); - } - return NULL; case ZEND_AST_GOTO: switch (child) { case 0: return AST_STR(str_label); } return NULL; case ZEND_AST_BREAK: - switch (child) { - case 0: return AST_STR(str_depth); - } - return NULL; case ZEND_AST_CONTINUE: switch (child) { case 0: return AST_STR(str_depth); @@ -448,11 +327,6 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { } return NULL; case ZEND_AST_PROP: - switch (child) { - case 0: return AST_STR(str_expr); - case 1: return AST_STR(str_prop); - } - return NULL; case ZEND_AST_NULLSAFE_PROP: switch (child) { case 0: return AST_STR(str_expr); @@ -478,17 +352,7 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { } return NULL; case ZEND_AST_ASSIGN: - switch (child) { - case 0: return AST_STR(str_var); - case 1: return AST_STR(str_expr); - } - return NULL; case ZEND_AST_ASSIGN_REF: - switch (child) { - case 0: return AST_STR(str_var); - case 1: return AST_STR(str_expr); - } - return NULL; case ZEND_AST_ASSIGN_OP: switch (child) { case 0: return AST_STR(str_var); @@ -502,12 +366,14 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { } return NULL; case ZEND_AST_ARRAY_ELEM: + case ZEND_AST_YIELD: switch (child) { case 0: return AST_STR(str_value); case 1: return AST_STR(str_key); } return NULL; case ZEND_AST_NEW: + case ZEND_AST_ATTRIBUTE: switch (child) { case 0: return AST_STR(str_class); case 1: return AST_STR(str_args); @@ -519,12 +385,6 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { case 1: return AST_STR(str_class); } return NULL; - case ZEND_AST_YIELD: - switch (child) { - case 0: return AST_STR(str_value); - case 1: return AST_STR(str_key); - } - return NULL; case ZEND_AST_STATIC: switch (child) { case 0: return AST_STR(str_var); @@ -532,6 +392,10 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { } return NULL; case ZEND_AST_WHILE: + case ZEND_AST_IF_ELEM: + case ZEND_AST_SWITCH: + case ZEND_AST_SWITCH_CASE: + case ZEND_AST_MATCH: switch (child) { case 0: return AST_STR(str_cond); case 1: return AST_STR(str_stmts); @@ -543,24 +407,6 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { case 1: return AST_STR(str_cond); } return NULL; - case ZEND_AST_IF_ELEM: - switch (child) { - case 0: return AST_STR(str_cond); - case 1: return AST_STR(str_stmts); - } - return NULL; - case ZEND_AST_SWITCH: - switch (child) { - case 0: return AST_STR(str_cond); - case 1: return AST_STR(str_stmts); - } - return NULL; - case ZEND_AST_SWITCH_CASE: - switch (child) { - case 0: return AST_STR(str_cond); - case 1: return AST_STR(str_stmts); - } - return NULL; case ZEND_AST_DECLARE: switch (child) { case 0: return AST_STR(str_declares); @@ -630,18 +476,6 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { case 1: return AST_STR(str_uses); } return NULL; - case ZEND_AST_ATTRIBUTE: - switch (child) { - case 0: return AST_STR(str_class); - case 1: return AST_STR(str_args); - } - return NULL; - case ZEND_AST_MATCH: - switch (child) { - case 0: return AST_STR(str_cond); - case 1: return AST_STR(str_stmts); - } - return NULL; case ZEND_AST_MATCH_ARM: switch (child) { case 0: return AST_STR(str_cond); @@ -655,12 +489,6 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { } return NULL; case ZEND_AST_METHOD_CALL: - switch (child) { - case 0: return AST_STR(str_expr); - case 1: return AST_STR(str_method); - case 2: return AST_STR(str_args); - } - return NULL; case ZEND_AST_NULLSAFE_METHOD_CALL: switch (child) { case 0: return AST_STR(str_expr); diff --git a/scripts/generate_ast_data.php b/scripts/generate_ast_data.php index 4c24433..006da9c 100644 --- a/scripts/generate_ast_data.php +++ b/scripts/generate_ast_data.php @@ -231,10 +231,10 @@ $code = str_replace('{STRS}', implode("\n", $strs), $code); $code = str_replace('{CONSTS}', implode("\n", $consts), $code); -$childNames = []; +$implementations = []; foreach ($names as $kind => $children) { if (empty($children)) { - $childNames[] = "\t\tcase $kind:\n\t\t\treturn NULL;"; + $implementations["\t\t\treturn NULL;"][] = $kind; continue; } @@ -242,9 +242,20 @@ foreach ($children as $index => $name) { $kindChildNames[] = "\t\t\t\tcase $index: return AST_STR(str_$name);"; } - $childNames[] = "\t\tcase $kind:\n\t\t\tswitch (child) {\n" + $body = "\t\t\tswitch (child) {\n" . implode("\n", $kindChildNames) . "\n\t\t\t}\n\t\t\treturn NULL;"; + $implementations[$body][] = $kind; } +$childNames = []; +foreach ($implementations as $body => $kindList) { + $codeForGroup = ''; + foreach ($kindList as $kind) { + $codeForGroup .= "\t\tcase $kind:\n"; + } + $codeForGroup .= $body; + $childNames[] = $codeForGroup; +} + $code = str_replace('{CHILD_NAMES}', implode("\n", $childNames), $code); file_put_contents($outCodeFile, $code);