From 28f5201f3526b5dbe6dc5b0f66733aef6b067e4d Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Mon, 5 Apr 2021 13:12:53 -0400 Subject: [PATCH 01/53] Support php 8.1 enums (#197) * Support php 8.1 enums * Test with travis and php 8.0, again * AST_ENUM_CASE can have attributes * Set `type` property of `AST_CLASS` iff ast version 85+ (iff === if and only if) * Add AST_CLASS's type in version 85+ prior to php 8.1 * [skip ci] Document support for php 8.1 enums --- .appveyor.yml | 22 ++-- .travis.yml | 3 +- README.md | 6 +- ast.c | 45 +++++++- ast_data.c | 11 ++ ast_stub.php | 18 +-- package.xml | 1 + php_ast.h | 6 + scripts/generate_ast_data.php | 3 +- tests/class_type_85.phpt | 40 +++++++ tests/get_supported_versions.phpt | 10 +- tests/metadata.phpt | 3 +- tests/php81_enums.phpt | 180 ++++++++++++++++++++++++++++++ 13 files changed, 314 insertions(+), 34 deletions(-) create mode 100644 tests/class_type_85.phpt create mode 100644 tests/php81_enums.phpt diff --git a/.appveyor.yml b/.appveyor.yml index 2dd3083..35ee899 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -32,22 +32,22 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 ARCH: x86 VC: vs16 - PHP_VER: 8.0.0 + PHP_VER: 8.0.3 TS: 1 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 ARCH: x64 VC: vs16 - PHP_VER: 8.0.0 + PHP_VER: 8.0.3 TS: 1 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 ARCH: x86 VC: vs16 - PHP_VER: 8.0.0 + PHP_VER: 8.0.3 TS: 0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 ARCH: x64 VC: vs16 - PHP_VER: 8.0.0 + PHP_VER: 8.0.3 TS: 0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 ARCH: x64 @@ -117,37 +117,37 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x64 VC: vc15 - PHP_VER: 7.3.25 + PHP_VER: 7.3.27 TS: 1 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x86 VC: vc15 - PHP_VER: 7.3.25 + PHP_VER: 7.3.27 TS: 0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x86 VC: vc15 - PHP_VER: 7.3.25 + PHP_VER: 7.3.27 TS: 1 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x64 VC: vc15 - PHP_VER: 7.4.13 + PHP_VER: 7.4.16 TS: 0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x64 VC: vc15 - PHP_VER: 7.4.13 + PHP_VER: 7.4.16 TS: 1 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x86 VC: vc15 - PHP_VER: 7.4.13 + PHP_VER: 7.4.16 TS: 0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x86 VC: vc15 - PHP_VER: 7.4.13 + PHP_VER: 7.4.16 TS: 1 build_script: diff --git a/.travis.yml b/.travis.yml index 78ce0ff..69d60a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,7 @@ php: - 7.2 - 7.3 - 7.4 - # https://travis-ci.community/t/php-8-0-missing/10132 - # - 8.0snapshot + - 8.0 - nightly before_script: diff --git a/README.md b/README.md index 50f6aa8..c1562b1 100644 --- a/README.md +++ b/README.md @@ -246,12 +246,13 @@ ast\flags\FUNC_GENERATOR // used only in PHP >= 7.1 // Used by ast\AST_CLOSURE_VAR ast\flags\CLOSURE_USE_REF -// Used by ast\AST_CLASS (exclusive) +// Used by ast\AST_CLASS (combinable since PHP 8.1 enums) ast\flags\CLASS_ABSTRACT ast\flags\CLASS_FINAL ast\flags\CLASS_TRAIT ast\flags\CLASS_INTERFACE ast\flags\CLASS_ANONYMOUS +ast\flags\CLASS_ENUM // Used by ast\AST_PARAM (combinable) ast\flags\PARAM_REF @@ -374,7 +375,7 @@ AST_BREAK: depth AST_CALL: expr, args AST_CAST: expr AST_CATCH: class, var, stmts -AST_CLASS: name, docComment, extends, implements, stmts +AST_CLASS: name, docComment, extends, implements, stmts, (for enums) type AST_CLASS_CONST: class, const AST_CLASS_CONST_GROUP class, attributes // version 80+ AST_CLASS_NAME: class // version 70+ @@ -390,6 +391,7 @@ AST_DIM: expr, dim AST_DO_WHILE: stmts, cond AST_ECHO: expr AST_EMPTY: expr +AST_ENUM_CASE: name, expr, attributes // php 8.1+ enums AST_EXIT: expr AST_FOR: init, cond, loop, stmts AST_FOREACH: expr, value, key, stmts diff --git a/ast.c b/ast.c index 692ec4e..0d00314 100644 --- a/ast.c +++ b/ast.c @@ -132,6 +132,7 @@ static const char *class_flags[] = { AST_FLAG(CLASS_TRAIT), AST_FLAG(CLASS_INTERFACE), AST_FLAG(CLASS_ANONYMOUS), + AST_FLAG(CLASS_ENUM), NULL }; @@ -294,7 +295,7 @@ static const char *conditional_flags[] = { static const ast_flag_info flag_info[] = { { AST_NAME, 0, name_flags }, - { ZEND_AST_CLASS, 0, class_flags }, + { ZEND_AST_CLASS, 1, class_flags }, { ZEND_AST_PARAM, 1, param_flags }, { ZEND_AST_TYPE, 0, type_flags }, { ZEND_AST_CAST, 0, type_flags }, @@ -448,6 +449,12 @@ static inline zend_bool ast_is_name(zend_ast *ast, zend_ast *parent, uint32_t i) || parent->kind == ZEND_AST_METHOD; } +#if PHP_VERSION_ID >= 80100 + if (i == 4) { + return parent->kind == ZEND_AST_CLASS; + } +#endif + return 0; } @@ -472,6 +479,11 @@ static inline zend_bool ast_is_type(zend_ast *ast, zend_ast *parent, uint32_t i) #endif || parent->kind == ZEND_AST_METHOD; } +#if PHP_VERSION_ID >= 80100 + if (i == 4) { + return parent->kind == ZEND_AST_CLASS; + } +#endif return 0; } @@ -557,10 +569,12 @@ static inline zend_ast_attr ast_assign_op_to_binary_op(zend_ast_attr attr) { } #endif -static inline zend_ast **ast_get_children(zend_ast *ast, uint32_t *count) { +static inline zend_ast **ast_get_children(zend_ast *ast, ast_state_info_t *state, uint32_t *count) { if (ast_kind_is_decl(ast->kind)) { zend_ast_decl *decl = (zend_ast_decl *) ast; -#if PHP_VERSION_ID >= 80000 +#if PHP_VERSION_ID >= 80100 + *count = decl->kind == ZEND_AST_CLASS ? (state->version >= 85 ? 5 : 4) : 5; +#elif PHP_VERSION_ID >= 80000 *count = decl->kind == ZEND_AST_CLASS ? 4 : 5; #else *count = decl->kind == ZEND_AST_CLASS ? 3 : 4; @@ -662,7 +676,7 @@ static inline void ast_name_to_zval(zend_ast *child, zend_ast *ast, zval *child_ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t *state) { uint32_t i, count; zend_bool is_list = zend_ast_is_list(ast); - zend_ast **children = ast_get_children(ast, &count); + zend_ast **children = ast_get_children(ast, state, &count); const zend_ast_kind ast_kind = ast->kind; for (i = 0; i < count; ++i) { zend_ast *child = children[i]; @@ -697,7 +711,7 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t } break; case ZEND_AST_CLASS: - if (i == 3) { + if (i >= 3) { continue; } break; @@ -708,6 +722,13 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t break; } } +#if PHP_VERSION_ID >= 80100 + if (ast_kind == ZEND_AST_CLASS && i == 4) { + if (state->version < 85) { + continue; + } + } +#endif #endif /* This AST_CATCH check should occur before ast_is_name() */ #if PHP_VERSION_ID < 70100 @@ -809,6 +830,17 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t zend_hash_add_new(ht, AST_STR(str_attributes), &tmp); } #endif + +#if PHP_VERSION_ID < 80100 + if (ast_kind == ZEND_AST_CLASS) { + if (state->version >= 85) { + zval tmp; + ZVAL_NULL(&tmp); + zend_hash_add_new(ht, AST_STR(str_type), &tmp); + } + } +#endif + ZVAL_LONG(&id_zval, state->declIdCounter); state->declIdCounter++; zend_hash_add_new(ht, AST_STR(str___declId), &id_zval); @@ -1027,7 +1059,7 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { #endif } -static const zend_long versions[] = {50, 60, 70, 80}; +static const zend_long versions[] = {50, 60, 70, 80, 85}; static const size_t versions_count = sizeof(versions)/sizeof(versions[0]); static inline zend_bool ast_version_deprecated(zend_long version) { @@ -1377,6 +1409,7 @@ PHP_MINIT_FUNCTION(ast) { ast_register_flag_constant("CLASS_TRAIT", ZEND_ACC_TRAIT); ast_register_flag_constant("CLASS_INTERFACE", ZEND_ACC_INTERFACE); ast_register_flag_constant("CLASS_ANONYMOUS", ZEND_ACC_ANON_CLASS); + ast_register_flag_constant("CLASS_ENUM", ZEND_ACC_ENUM); ast_register_flag_constant("PARAM_REF", ZEND_PARAM_REF); ast_register_flag_constant("PARAM_VARIADIC", ZEND_PARAM_VARIADIC); diff --git a/ast_data.c b/ast_data.c index a6ec290..abbd1ab 100644 --- a/ast_data.c +++ b/ast_data.c @@ -97,6 +97,7 @@ 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, @@ -208,6 +209,7 @@ 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"; @@ -281,6 +283,7 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { case 1: return AST_STR(str_implements); case 2: return AST_STR(str_stmts); case 3: return AST_STR(str_attributes); + case 4: return AST_STR(str_type); } return NULL; case ZEND_AST_MAGIC_CONST: @@ -651,6 +654,13 @@ 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); @@ -820,6 +830,7 @@ 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); diff --git a/ast_stub.php b/ast_stub.php index 0f34b31..3a06dbb 100644 --- a/ast_stub.php +++ b/ast_stub.php @@ -103,6 +103,7 @@ 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; @@ -138,6 +139,7 @@ const CLASS_TRAIT = 2; const CLASS_INTERFACE = 1; const CLASS_ANONYMOUS = 4; +const CLASS_ENUM = 268435456; const PARAM_REF = 8; const PARAM_VARIADIC = 16; const TYPE_NULL = 1; @@ -191,14 +193,14 @@ const USE_NORMAL = 1; const USE_FUNCTION = 2; const USE_CONST = 4; -const MAGIC_LINE = 375; -const MAGIC_FILE = 376; -const MAGIC_DIR = 377; -const MAGIC_NAMESPACE = 382; -const MAGIC_FUNCTION = 381; -const MAGIC_METHOD = 380; -const MAGIC_CLASS = 378; -const MAGIC_TRAIT = 379; +const MAGIC_LINE = 376; +const MAGIC_FILE = 377; +const MAGIC_DIR = 378; +const MAGIC_NAMESPACE = 383; +const MAGIC_FUNCTION = 382; +const MAGIC_METHOD = 381; +const MAGIC_CLASS = 379; +const MAGIC_TRAIT = 380; const ARRAY_SYNTAX_LIST = 1; const ARRAY_SYNTAX_LONG = 2; const ARRAY_SYNTAX_SHORT = 3; diff --git a/package.xml b/package.xml index 53de8d0..29c1f3e 100644 --- a/package.xml +++ b/package.xml @@ -29,6 +29,7 @@ BSD-3-Clause +- Support php 8.1 enums, add 'type' (for enum type) to AST_CLASS nodes in AST version 85+. diff --git a/php_ast.h b/php_ast.h index 129ec3d..6d3b78a 100644 --- a/php_ast.h +++ b/php_ast.h @@ -75,6 +75,12 @@ extern ast_str_globals str_globals; // NOTE: The first hex digit is the number of child nodes a given kind has #endif +#if PHP_VERSION_ID < 80100 +# define ZEND_ACC_ENUM (1 << 22) +/* 3 child nodes - name, expr, attributes */ +# define ZEND_AST_ENUM_CASE 0x3fe +#endif + /* Pretend it still exists */ #if PHP_VERSION_ID >= 70100 # define ZEND_AST_LIST ((1 << (ZEND_AST_IS_LIST_SHIFT + 1)) - 1) diff --git a/scripts/generate_ast_data.php b/scripts/generate_ast_data.php index 1547f33..588f0be 100644 --- a/scripts/generate_ast_data.php +++ b/scripts/generate_ast_data.php @@ -58,7 +58,7 @@ 'ZEND_AST_CLOSURE' => $funcNames, 'ZEND_AST_METHOD' => $funcNames, 'ZEND_AST_ARROW_FUNC' => $funcNames, - 'ZEND_AST_CLASS' => ['extends', 'implements', 'stmts', 'attributes'], + 'ZEND_AST_CLASS' => ['extends', 'implements', 'stmts', 'attributes', 'type'], /* 0 child nodes */ 'ZEND_AST_MAGIC_CONST' => [], @@ -134,6 +134,7 @@ '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'], diff --git a/tests/class_type_85.phpt b/tests/class_type_85.phpt new file mode 100644 index 0000000..f599e30 --- /dev/null +++ b/tests/class_type_85.phpt @@ -0,0 +1,40 @@ +--TEST-- +Class types only used for enums in AST version 85 +--FILE-- + --EXPECT-- -array(4) { +array(5) { [0]=> int(50) [1]=> @@ -17,8 +17,10 @@ array(4) { int(70) [3]=> int(80) + [4]=> + int(85) } -array(4) { +array(5) { [0]=> int(50) [1]=> @@ -27,4 +29,6 @@ array(4) { int(70) [3]=> int(80) -} + [4]=> + int(85) +} \ No newline at end of file diff --git a/tests/metadata.phpt b/tests/metadata.phpt index bfd73bd..37e75a5 100644 --- a/tests/metadata.phpt +++ b/tests/metadata.phpt @@ -54,7 +54,7 @@ AST_FUNC_DECL: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVA AST_CLOSURE: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, FUNC_RETURNS_REF, FUNC_GENERATOR] AST_METHOD: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, FUNC_RETURNS_REF, FUNC_GENERATOR] AST_ARROW_FUNC: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, FUNC_RETURNS_REF, FUNC_GENERATOR] -AST_CLASS: [CLASS_ABSTRACT, CLASS_FINAL, CLASS_TRAIT, CLASS_INTERFACE, CLASS_ANONYMOUS] +AST_CLASS: (combinable) [CLASS_ABSTRACT, CLASS_FINAL, CLASS_TRAIT, CLASS_INTERFACE, CLASS_ANONYMOUS, CLASS_ENUM] AST_MAGIC_CONST: [MAGIC_LINE, MAGIC_FILE, MAGIC_DIR, MAGIC_NAMESPACE, MAGIC_FUNCTION, MAGIC_METHOD, MAGIC_CLASS, MAGIC_TRAIT] AST_TYPE: [TYPE_NULL, TYPE_FALSE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED] AST_VAR: [] @@ -122,6 +122,7 @@ AST_ATTRIBUTE: [] AST_MATCH: [] AST_MATCH_ARM: [] AST_NAMED_ARG: [] +AST_ENUM_CASE: [] AST_METHOD_CALL: [] AST_NULLSAFE_METHOD_CALL: [] AST_STATIC_CALL: [] diff --git a/tests/php81_enums.phpt b/tests/php81_enums.phpt new file mode 100644 index 0000000..ee23cd9 --- /dev/null +++ b/tests/php81_enums.phpt @@ -0,0 +1,180 @@ +--TEST-- +Enums in php 8.1 +--SKIPIF-- += 8.1 only'); ?> +--FILE-- + Date: Sat, 17 Apr 2021 11:02:19 -0400 Subject: [PATCH 02/53] Support php 8.1 never RFC (#199) https://wiki.php.net/rfc/noreturn_type --- README.md | 1 + ast.c | 7 +++++++ ast_stub.php | 3 ++- package.xml | 1 + tests/metadata.phpt | 4 ++-- tests/never_return_type.phpt | 27 +++++++++++++++++++++++++++ 6 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 tests/never_return_type.phpt diff --git a/README.md b/README.md index c1562b1..40424ac 100644 --- a/README.md +++ b/README.md @@ -275,6 +275,7 @@ ast\flags\TYPE_NULL // php 8.0 union types ast\flags\TYPE_FALSE // php 8.0 union types ast\flags\TYPE_STATIC // php 8.0 static return type ast\flags\TYPE_MIXED // php 8.0 mixed type +ast\flags\TYPE_NEVER // php 8.1 never type // Used by ast\AST_CAST (exclusive) ast\flags\TYPE_NULL diff --git a/ast.c b/ast.c index 0d00314..66dcfeb 100644 --- a/ast.c +++ b/ast.c @@ -98,6 +98,10 @@ # define PARAM_MODIFIER_PRIVATE ZEND_ACC_PRIVATE #endif +#if PHP_VERSION_ID < 80100 +# define IS_NEVER 22 +#endif + /* This contains state of the ast Node creator. */ typedef struct ast_state_info { zend_long version; @@ -159,6 +163,7 @@ static const char *type_flags[] = { AST_FLAG(TYPE_ITERABLE), AST_FLAG(TYPE_STATIC), AST_FLAG(TYPE_MIXED), + AST_FLAG(TYPE_NEVER), NULL }; @@ -535,6 +540,7 @@ static const builtin_type_info builtin_types[] = { {ZEND_STRL("false"), IS_FALSE}, // {ZEND_STRL("static"), IS_STATIC}, /* Impossible to be parsed before php 8 */ {ZEND_STRL("mixed"), IS_MIXED}, + {ZEND_STRL("never"), IS_NEVER}, {NULL, 0, IS_UNDEF} }; static inline zend_uchar lookup_builtin_type(const zend_string *name) { @@ -1427,6 +1433,7 @@ PHP_MINIT_FUNCTION(ast) { ast_register_flag_constant("TYPE_ITERABLE", IS_ITERABLE); ast_register_flag_constant("TYPE_STATIC", IS_STATIC); ast_register_flag_constant("TYPE_MIXED", IS_MIXED); + ast_register_flag_constant("TYPE_NEVER", IS_NEVER); ast_register_flag_constant("UNARY_BOOL_NOT", ZEND_BOOL_NOT); ast_register_flag_constant("UNARY_BITWISE_NOT", ZEND_BW_NOT); diff --git a/ast_stub.php b/ast_stub.php index 3a06dbb..e30df73 100644 --- a/ast_stub.php +++ b/ast_stub.php @@ -144,7 +144,7 @@ const PARAM_VARIADIC = 16; const TYPE_NULL = 1; const TYPE_FALSE = 2; -const TYPE_BOOL = 17; +const TYPE_BOOL = 18; const TYPE_LONG = 4; const TYPE_DOUBLE = 5; const TYPE_STRING = 6; @@ -155,6 +155,7 @@ const TYPE_ITERABLE = 13; const TYPE_STATIC = 15; const TYPE_MIXED = 16; +const TYPE_NEVER = 17; const UNARY_BOOL_NOT = 14; const UNARY_BITWISE_NOT = 13; const UNARY_SILENCE = 260; diff --git a/package.xml b/package.xml index 29c1f3e..10ebcbd 100644 --- a/package.xml +++ b/package.xml @@ -30,6 +30,7 @@ BSD-3-Clause - 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. diff --git a/tests/metadata.phpt b/tests/metadata.phpt index 37e75a5..67f3264 100644 --- a/tests/metadata.phpt +++ b/tests/metadata.phpt @@ -56,11 +56,11 @@ AST_METHOD: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, AST_ARROW_FUNC: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, FUNC_RETURNS_REF, FUNC_GENERATOR] AST_CLASS: (combinable) [CLASS_ABSTRACT, CLASS_FINAL, CLASS_TRAIT, CLASS_INTERFACE, CLASS_ANONYMOUS, CLASS_ENUM] AST_MAGIC_CONST: [MAGIC_LINE, MAGIC_FILE, MAGIC_DIR, MAGIC_NAMESPACE, MAGIC_FUNCTION, MAGIC_METHOD, MAGIC_CLASS, MAGIC_TRAIT] -AST_TYPE: [TYPE_NULL, TYPE_FALSE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED] +AST_TYPE: [TYPE_NULL, TYPE_FALSE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED, TYPE_NEVER] AST_VAR: [] AST_CONST: [] AST_UNPACK: [] -AST_CAST: [TYPE_NULL, TYPE_FALSE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED] +AST_CAST: [TYPE_NULL, TYPE_FALSE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED, TYPE_NEVER] AST_EMPTY: [] AST_ISSET: [] AST_SHELL_EXEC: [] diff --git a/tests/never_return_type.phpt b/tests/never_return_type.phpt new file mode 100644 index 0000000..4d208d0 --- /dev/null +++ b/tests/never_return_type.phpt @@ -0,0 +1,27 @@ +--TEST-- +'never' return type parsing +--FILE-- + Date: Sat, 17 Apr 2021 12:09:54 -0400 Subject: [PATCH 03/53] Start testing with github actions (#202) The script `ci/test_dockerized.sh 8.0` can be used to run the exact same tests locally. Closes #198 Change the comment text to avoid -Wimplicit-fallthrough to avoid noise https://developers.redhat.com/blog/2017/03/10/wimplicit-fallthrough-in-gcc-7/ --- .dockerignore | 40 +++++++++++++++++++++++++++++++++++ .github/workflows/main.yml | 43 ++++++++++++++++++++++++++++++++++++++ ast.c | 8 +++---- ci/Dockerfile | 13 ++++++++++++ ci/test_dockerized.sh | 15 +++++++++++++ ci/test_inner.sh | 9 ++++++++ package.xml | 6 +++++- 7 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 .dockerignore create mode 100644 .github/workflows/main.yml create mode 100644 ci/Dockerfile create mode 100755 ci/test_dockerized.sh create mode 100755 ci/test_inner.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2640be1 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,40 @@ +*.dll +*.tgz +.deps +*.o +*.lo +*.la +*.swp +.github +.libs +acinclude.m4 +aclocal.m4 +autom4te.cache +build +config.guess +config.h +config.h.in +config.log +config.nice +config.status +config.sub +configure +configure.in +include +install-sh +libtool +ltmain.sh +Makefile +Makefile.fragments +Makefile.global +Makefile.objects +missing +mkinstalldirs +modules +run-tests.php +tests/*.diff +tests/*.out +# tests/*.php php files are used as helpers +tests/*.exp +tests/*.log +tests/*.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..33cfef2 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,43 @@ +# Runs php-ast's tests and verifies that the package can be built. + +name: CI + +# Controls when the action will run. +on: + # Triggers the workflow on push or pull request events but only for the master branch + push: + branches: [ master ] + pull_request: + branches: [ master ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#using-environment-variables-in-a-matrix + strategy: + matrix: + include: + # NOTE: If this is not quoted, the yaml parser will convert 7.0 to the number 7, + # and the docker image `php:7` is the latest minor version of php 7.x (7.4). + - PHP_VERSION: '7.0' + - PHP_VERSION: '7.1' + - PHP_VERSION: '7.2' + - PHP_VERSION: '7.3' + - PHP_VERSION: '7.4' + - PHP_VERSION: '8.0' + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + + # Runs a single command using the runners shell + - name: Build and test in docker + run: bash ci/test_dockerized.sh ${{ matrix.PHP_VERSION }} diff --git a/ast.c b/ast.c index 66dcfeb..d7dd586 100644 --- a/ast.c +++ b/ast.c @@ -1331,22 +1331,22 @@ PHP_METHOD(ast_Node, __construct) { if (!linenoNull) { ast_update_property_long(zv, AST_STR(str_lineno), lineno, AST_CACHE_SLOT_LINENO); } - /* break missing intentionally */ + /* Falls through - break missing intentionally */ case 3: if (children != NULL) { ast_update_property(zv, AST_STR(str_children), children, AST_CACHE_SLOT_CHILDREN); } - /* break missing intentionally */ + /* Falls through - break missing intentionally */ case 2: if (!flagsNull) { ast_update_property_long(zv, AST_STR(str_flags), flags, AST_CACHE_SLOT_FLAGS); } - /* break missing intentionally */ + /* Falls through - break missing intentionally */ case 1: if (!kindNull) { ast_update_property_long(zv, AST_STR(str_kind), kind, AST_CACHE_SLOT_KIND); } - /* break missing intentionally */ + /* Falls through - break missing intentionally */ case 0: break; } diff --git a/ci/Dockerfile b/ci/Dockerfile new file mode 100644 index 0000000..1a6343b --- /dev/null +++ b/ci/Dockerfile @@ -0,0 +1,13 @@ +ARG PHP_VERSION +FROM php:$PHP_VERSION +WORKDIR /php-ast +ADD *.c *.h *.php config.m4 config.w32 package.xml LICENSE README.md ./ + +# Assume compilation will be the time consuming step. +# Add tests after compiling so that it's faster to update tests and re-run them locally. +# +# Use the same CFLAGS used to build the docker image but also check for warnings (this will emit warnings but not fail the build) +RUN phpize && EXTRA_CFLAGS='-Wall -Wextra -Wno-unused-parameter' ./configure && make -j2 && make install +RUN docker-php-ext-enable ast +ADD tests ./tests +ADD ci ./ci diff --git a/ci/test_dockerized.sh b/ci/test_dockerized.sh new file mode 100755 index 0000000..f263e72 --- /dev/null +++ b/ci/test_dockerized.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +if [ $# != 1 ]; then + echo "Usage: $0 PHP_VERSION" 1>&2 + echo "e.g. $0 8.0 or $0 8.0-alpine" 1>&2 + echo "The PHP_VERSION is the version of the php docker image to use" 1>&2 + exit 1 +fi +# -x Exit immediately if any command fails +# -e Echo all commands being executed. +# -u fail for undefined variables +set -xeu +PHP_VERSION=$1 +DOCKER_IMAGE=php-ast-$PHP_VERSION-test-runner +docker build --build-arg="PHP_VERSION=$PHP_VERSION" --tag="$DOCKER_IMAGE" -f ci/Dockerfile . +docker run --rm $DOCKER_IMAGE ci/test_inner.sh diff --git a/ci/test_inner.sh b/ci/test_inner.sh new file mode 100755 index 0000000..47be172 --- /dev/null +++ b/ci/test_inner.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# -x Exit immediately if any command fails +# -e Echo all commands being executed. +# -u fail for undefined variables +set -xeu +echo "Run tests in docker" +REPORT_EXIT_STATUS=1 php ./run-tests.php -P -q --show-diff +echo "Test that package.xml is valid" +pecl package diff --git a/package.xml b/package.xml index 10ebcbd..6f2c09f 100644 --- a/package.xml +++ b/package.xml @@ -51,6 +51,7 @@ + @@ -62,6 +63,7 @@ + @@ -86,6 +88,7 @@ + @@ -105,9 +108,10 @@ - + + From b8fa288b4922fe923236a198e0fb17e3441a888b Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Tue, 20 Apr 2021 10:05:28 -0400 Subject: [PATCH 04/53] Release ast version 1.0.11 (#203) --- README.md | 4 ++++ package.xml | 7 ++++--- php_ast.h | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 40424ac..b6754eb 100644 --- a/README.md +++ b/README.md @@ -494,6 +494,10 @@ function accepts a boolean argument that determines whether deprecated versions In the following the changes in the respective AST versions, as well as their current support state, are listed. +### 85 (experimental) + +* Add a `type` child node (for enum type) for all AST_CLASS nodes. + ### 80 (current) Supported since 1.0.10 (2020-09-12). diff --git a/package.xml b/package.xml index 6f2c09f..ed43328 100644 --- a/package.xml +++ b/package.xml @@ -18,10 +18,10 @@ tandre@php.net yes - 2020-09-12 + 2021-04-20 - 1.0.11dev - 1.0.11dev + 1.0.11 + 1.0.11 stable @@ -29,6 +29,7 @@ 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. diff --git a/php_ast.h b/php_ast.h index 6d3b78a..bec98cf 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.11dev" +#define PHP_AST_VERSION "1.0.11" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) From f8248ff890f1e4a9360a5beb62c7a1c162ca6661 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Fri, 14 May 2021 15:30:04 -0400 Subject: [PATCH 05/53] Support doc comments for php 8.1 code, combine equivalent switch cases (#204) * 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) * Combine equivalent case statements in generated code --- ast_data.c | 221 ++++------------------------------ ast_stub.php | 2 +- package.xml | 29 +++-- php_ast.h | 2 +- scripts/generate_ast_data.php | 19 ++- tests/metadata.phpt | 2 +- tests/php81_enums.phpt | 7 ++ 7 files changed, 72 insertions(+), 210 deletions(-) diff --git a/ast_data.c b/ast_data.c index abbd1ab..264d44e 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"; } @@ -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); @@ -654,20 +488,7 @@ 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); - 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); @@ -719,6 +540,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 +659,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 +667,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..006da9c 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'], @@ -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); 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 dafc341c2b76f8cd9082fda081d4167c16eecb0c Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 16 May 2021 10:59:10 -0400 Subject: [PATCH 06/53] Release php-ast 1.0.12 (#205) --- package.xml | 8 ++++---- php_ast.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.xml b/package.xml index 27c5e40..e3d9b61 100644 --- a/package.xml +++ b/package.xml @@ -18,13 +18,13 @@ tandre@php.net yes - 2021-05-14 + 2021-05-16 - 1.0.12dev - 1.0.12dev + 1.0.12 + 1.0.12 - alpha + stable stable BSD-3-Clause diff --git a/php_ast.h b/php_ast.h index d9a2edc..7438bdf 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.12dev" +#define PHP_AST_VERSION "1.0.12" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) From 83c769f58974feaa49bcfe1a697d0532e4732f21 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Wed, 7 Jul 2021 09:06:06 -0400 Subject: [PATCH 07/53] Support php 8.1 intersection types (#208) * Add tests of final class constant modifier, update metadata (https://wiki.php.net/rfc/final_class_const for php 8.1) * Support proposed php 8.1 intersection types (https://wiki.php.net/rfc/pure-intersection-types) * Allow using any modifier on any class element in metadata --- README.md | 5 +- ast.c | 14 +++- ast_data.c | 3 + ast_stub.php | 23 ++++--- package.xml | 30 +++++++-- php_ast.h | 3 +- scripts/generate_ast_data.php | 1 + tests/metadata.phpt | 9 +-- tests/php81_final_class_const.phpt | 56 ++++++++++++++++ tests/php81_intersection_types.phpt | 100 ++++++++++++++++++++++++++++ 10 files changed, 219 insertions(+), 25 deletions(-) create mode 100644 tests/php81_final_class_const.phpt create mode 100644 tests/php81_intersection_types.phpt diff --git a/README.md b/README.md index b6754eb..ae647d8 100644 --- a/README.md +++ b/README.md @@ -227,8 +227,8 @@ ast\flags\NAME_FQ (= 0) // example: \Foo\Bar ast\flags\NAME_NOT_FQ // example: Foo\Bar ast\flags\NAME_RELATIVE // example: namespace\Foo\Bar -// Used by ast\AST_METHOD, ast\AST_PROP_DECL, ast\AST_CLASS_CONST_DECL, -// ast\AST_PROP_GROUP and ast\AST_TRAIT_ALIAS (combinable) +// Used by ast\AST_METHOD, ast\AST_PROP_DECL, ast\AST_PROP_GROUP, +// ast\AST_CLASS_CONST_DECL, ast\AST_CLASS_CONST_GROUP, and ast\AST_TRAIT_ALIAS (combinable) ast\flags\MODIFIER_PUBLIC ast\flags\MODIFIER_PROTECTED ast\flags\MODIFIER_PRIVATE @@ -475,6 +475,7 @@ AST_SWITCH_LIST AST_TRAIT_ADAPTATIONS AST_USE AST_TYPE_UNION // php 8.0+ union types +AST_TYPE_INTERSECTION // php 8.1+ intersection types ``` AST Versioning diff --git a/ast.c b/ast.c index d7dd586..11399b3 100644 --- a/ast.c +++ b/ast.c @@ -321,8 +321,8 @@ static const ast_flag_info flag_info[] = { { ZEND_AST_ARROW_FUNC, 1, func_flags }, { ZEND_AST_PROP_DECL, 1, modifier_flags }, { ZEND_AST_PROP_GROUP, 1, modifier_flags }, - { ZEND_AST_CLASS_CONST_DECL, 1, visibility_flags }, - { ZEND_AST_CLASS_CONST_GROUP, 1, visibility_flags }, + { ZEND_AST_CLASS_CONST_DECL, 1, modifier_flags }, + { ZEND_AST_CLASS_CONST_GROUP, 1, modifier_flags }, { ZEND_AST_TRAIT_ALIAS, 1, modifier_flags }, { ZEND_AST_DIM, 1, dim_flags }, { ZEND_AST_CONDITIONAL, 1, conditional_flags }, @@ -423,6 +423,11 @@ static inline zend_bool ast_is_name(zend_ast *ast, zend_ast *parent, uint32_t i) if (parent->kind == ZEND_AST_NAME_LIST) { return 1; } +#if PHP_VERSION_ID >= 80100 + if (parent->kind == ZEND_AST_TYPE_INTERSECTION) { + return 1; + } +#endif #if PHP_VERSION_ID >= 80000 if (parent->kind == ZEND_AST_TYPE_UNION) { return 1; @@ -465,6 +470,11 @@ static inline zend_bool ast_is_name(zend_ast *ast, zend_ast *parent, uint32_t i) /* Assumes that ast_is_name is already true */ static inline zend_bool ast_is_type(zend_ast *ast, zend_ast *parent, uint32_t i) { +#if PHP_VERSION_ID >= 80100 + if (parent->kind == ZEND_AST_TYPE_INTERSECTION) { + return 1; + } +#endif #if PHP_VERSION_ID >= 80000 if (parent->kind == ZEND_AST_TYPE_UNION) { return 1; diff --git a/ast_data.c b/ast_data.c index 264d44e..f429cc8 100644 --- a/ast_data.c +++ b/ast_data.c @@ -19,6 +19,7 @@ const zend_ast_kind ast_kinds[] = { ZEND_AST_TRAIT_ADAPTATIONS, ZEND_AST_USE, ZEND_AST_TYPE_UNION, + ZEND_AST_TYPE_INTERSECTION, ZEND_AST_ATTRIBUTE_LIST, ZEND_AST_ATTRIBUTE_GROUP, ZEND_AST_MATCH_ARM_LIST, @@ -131,6 +132,7 @@ const char *ast_kind_to_name(zend_ast_kind kind) { case ZEND_AST_TRAIT_ADAPTATIONS: return "AST_TRAIT_ADAPTATIONS"; case ZEND_AST_USE: return "AST_USE"; case ZEND_AST_TYPE_UNION: return "AST_TYPE_UNION"; + case ZEND_AST_TYPE_INTERSECTION: return "AST_TYPE_INTERSECTION"; case ZEND_AST_ATTRIBUTE_LIST: return "AST_ATTRIBUTE_LIST"; case ZEND_AST_ATTRIBUTE_GROUP: return "AST_ATTRIBUTE_GROUP"; case ZEND_AST_MATCH_ARM_LIST: return "AST_MATCH_ARM_LIST"; @@ -581,6 +583,7 @@ void ast_register_kind_constants(INIT_FUNC_ARGS) { REGISTER_NS_LONG_CONSTANT("ast", "AST_TRAIT_ADAPTATIONS", ZEND_AST_TRAIT_ADAPTATIONS, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_USE", ZEND_AST_USE, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_TYPE_UNION", ZEND_AST_TYPE_UNION, CONST_CS | CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("ast", "AST_TYPE_INTERSECTION", ZEND_AST_TYPE_INTERSECTION, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_ATTRIBUTE_LIST", ZEND_AST_ATTRIBUTE_LIST, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_ATTRIBUTE_GROUP", ZEND_AST_ATTRIBUTE_GROUP, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_MATCH_ARM_LIST", ZEND_AST_MATCH_ARM_LIST, CONST_CS | CONST_PERSISTENT); diff --git a/ast_stub.php b/ast_stub.php index 014858c..849c887 100644 --- a/ast_stub.php +++ b/ast_stub.php @@ -25,9 +25,10 @@ const AST_TRAIT_ADAPTATIONS = 142; const AST_USE = 143; const AST_TYPE_UNION = 144; -const AST_ATTRIBUTE_LIST = 145; -const AST_ATTRIBUTE_GROUP = 146; -const AST_MATCH_ARM_LIST = 147; +const AST_TYPE_INTERSECTION = 145; +const AST_ATTRIBUTE_LIST = 146; +const AST_ATTRIBUTE_GROUP = 147; +const AST_MATCH_ARM_LIST = 148; const AST_NAME = 2048; const AST_CLOSURE_VAR = 2049; const AST_NULLABLE_TYPE = 2050; @@ -194,14 +195,14 @@ const USE_NORMAL = 1; const USE_FUNCTION = 2; const USE_CONST = 4; -const MAGIC_LINE = 376; -const MAGIC_FILE = 377; -const MAGIC_DIR = 378; -const MAGIC_NAMESPACE = 383; -const MAGIC_FUNCTION = 382; -const MAGIC_METHOD = 381; -const MAGIC_CLASS = 379; -const MAGIC_TRAIT = 380; +const MAGIC_LINE = 379; +const MAGIC_FILE = 380; +const MAGIC_DIR = 381; +const MAGIC_NAMESPACE = 386; +const MAGIC_FUNCTION = 385; +const MAGIC_METHOD = 384; +const MAGIC_CLASS = 382; +const MAGIC_TRAIT = 383; const ARRAY_SYNTAX_LIST = 1; const ARRAY_SYNTAX_LONG = 2; const ARRAY_SYNTAX_SHORT = 3; diff --git a/package.xml b/package.xml index e3d9b61..5cc2cd6 100644 --- a/package.xml +++ b/package.xml @@ -20,16 +20,18 @@ 2021-05-16 - 1.0.12 - 1.0.12 + 1.0.13dev + 1.0.13dev - stable - stable + alpha + alpha BSD-3-Clause -- Support parsing 'docComment' on php 8.1 enums +- Indicate in metadata that 'AST_CLASS_CONST_GROUP' and 'AST_CLASS_CONST_DECL' can have MODIFIER_FINAL + (and any modifier a class element can have, to reflect what the parser can actually parse) +- Support php 8.1 intersection types, add node kind 'AST_TYPE_INTERSECTION' @@ -111,6 +113,8 @@ + + @@ -138,6 +142,22 @@ ast + + 2021-05-16 + + 1.0.12 + 1.0.12 + + + stable + stable + + BSD-3-Clause + +- Support parsing 'docComment' on php 8.1 enums +- Indicate in metadata that 'AST_CLASS_CONST_GROUP' and 'AST_CLASS_CONST_DECL' can have MODIFIER_FINAL + + 2021-04-20 diff --git a/php_ast.h b/php_ast.h index 7438bdf..d06861f 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.12" +#define PHP_AST_VERSION "1.0.13dev" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) @@ -79,6 +79,7 @@ extern ast_str_globals str_globals; # define ZEND_ACC_ENUM (1 << 22) /* 3 child nodes - name, expr, attributes */ # define ZEND_AST_ENUM_CASE 0x3fe +# define ZEND_AST_TYPE_INTERSECTION ((1 << (ZEND_AST_IS_LIST_SHIFT + 1)) - 6) #endif /* Pretend it still exists */ diff --git a/scripts/generate_ast_data.php b/scripts/generate_ast_data.php index 006da9c..c098d1f 100644 --- a/scripts/generate_ast_data.php +++ b/scripts/generate_ast_data.php @@ -172,6 +172,7 @@ 'ZEND_AST_TRAIT_ADAPTATIONS', 'ZEND_AST_USE', 'ZEND_AST_TYPE_UNION', + 'ZEND_AST_TYPE_INTERSECTION', 'ZEND_AST_ATTRIBUTE_LIST', 'ZEND_AST_ATTRIBUTE_GROUP', 'ZEND_AST_MATCH_ARM_LIST', diff --git a/tests/metadata.phpt b/tests/metadata.phpt index fccc05e..f2eafe0 100644 --- a/tests/metadata.phpt +++ b/tests/metadata.phpt @@ -25,7 +25,7 @@ foreach ($metadata as $data) { // NOTE: AST_PARAM has overlapping flag values for MODIFIER_PUBLIC and PARAM_REF in php 7.4. // To work around this, MODIFIER_* were omitted from get_metadata in 7.4 and older. ?> ---EXPECTF-- +--EXPECT-- AST_ARG_LIST: [] AST_LIST: [] AST_ARRAY: [ARRAY_SYNTAX_LIST, ARRAY_SYNTAX_LONG, ARRAY_SYNTAX_SHORT] @@ -39,11 +39,12 @@ AST_PARAM_LIST: [] AST_CLOSURE_USES: [] AST_PROP_DECL: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL] AST_CONST_DECL: [] -AST_CLASS_CONST_DECL: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE] +AST_CLASS_CONST_DECL: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL] AST_NAME_LIST: [] AST_TRAIT_ADAPTATIONS: [] AST_USE: [USE_NORMAL, USE_FUNCTION, USE_CONST] AST_TYPE_UNION: [] +AST_TYPE_INTERSECTION: [] AST_ATTRIBUTE_LIST: [] AST_ATTRIBUTE_GROUP: [] AST_MATCH_ARM_LIST: [] @@ -86,7 +87,7 @@ AST_GOTO: [] AST_BREAK: [] AST_CONTINUE: [] AST_CLASS_NAME: [] -AST_CLASS_CONST_GROUP: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE] +AST_CLASS_CONST_GROUP: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL] AST_DIM: (combinable) [DIM_ALTERNATIVE_SYNTAX] AST_PROP: [] AST_NULLSAFE_PROP: [] @@ -131,4 +132,4 @@ 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] +AST_PARAM: (combinable) [PARAM_REF, PARAM_VARIADIC, PARAM_MODIFIER_PUBLIC, PARAM_MODIFIER_PROTECTED, PARAM_MODIFIER_PRIVATE] \ No newline at end of file diff --git a/tests/php81_final_class_const.phpt b/tests/php81_final_class_const.phpt new file mode 100644 index 0000000..4612388 --- /dev/null +++ b/tests/php81_final_class_const.phpt @@ -0,0 +1,56 @@ +--TEST-- +Final class constants in php 8.1 +--SKIPIF-- + +--FILE-- += 8.1 only'); ?> +--FILE-- + Date: Wed, 7 Jul 2021 09:08:03 -0400 Subject: [PATCH 08/53] Document AST_ENUM_CASE docComment in README.md (#206) Followup to f8248ff890f1e4a9360a5beb62c7a1c162ca6661 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ae647d8..77a8b99 100644 --- a/README.md +++ b/README.md @@ -392,7 +392,7 @@ AST_DIM: expr, dim AST_DO_WHILE: stmts, cond AST_ECHO: expr AST_EMPTY: expr -AST_ENUM_CASE: name, expr, attributes // php 8.1+ enums +AST_ENUM_CASE: name, expr, docComment, attributes // php 8.1+ enums AST_EXIT: expr AST_FOR: init, cond, loop, stmts AST_FOREACH: expr, value, key, stmts From 900e41ac1a516913e046143933cb4b0f319ca448 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Thu, 8 Jul 2021 09:42:54 -0400 Subject: [PATCH 09/53] Release php-ast 1.0.13 (#210) --- package.xml | 10 +++++----- php_ast.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.xml b/package.xml index 5cc2cd6..7c2ce74 100644 --- a/package.xml +++ b/package.xml @@ -18,14 +18,14 @@ tandre@php.net yes - 2021-05-16 + 2021-07-08 - 1.0.13dev - 1.0.13dev + 1.0.13 + 1.0.13 - alpha - alpha + stable + stable BSD-3-Clause diff --git a/php_ast.h b/php_ast.h index d06861f..9faea7b 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.13dev" +#define PHP_AST_VERSION "1.0.13" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) From c533904c019e0ddabd113f3228cf0f7695f0baf0 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sat, 24 Jul 2021 10:50:35 -0400 Subject: [PATCH 10/53] Support php 8.1 read-only properties, first-class callable syntax (#209) Add php 8.1 readonly property support, first-class callables And run all tests even after the first case fails Mark ast version 90 as current and 85 as no longer experimental. Add date to changelog, bump version in php_ast.h --- .github/workflows/main.yml | 1 + README.md | 16 ++++- ast.c | 8 ++- ast_data.c | 4 ++ ast_stub.php | 2 + package.xml | 33 ++++++++--- php_ast.h | 6 +- scripts/generate_ast_data.php | 1 + tests/get_supported_versions.phpt | 8 ++- tests/metadata.phpt | 19 +++--- tests/php81_first_class_callable_support.phpt | 46 +++++++++++++++ tests/php81_readonly.phpt | 58 +++++++++++++++++++ 12 files changed, 177 insertions(+), 25 deletions(-) create mode 100644 tests/php81_first_class_callable_support.phpt create mode 100644 tests/php81_readonly.phpt diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 33cfef2..c9875b3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,6 +22,7 @@ jobs: # See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#using-environment-variables-in-a-matrix strategy: + fail-fast: false matrix: include: # NOTE: If this is not quoted, the yaml parser will convert 7.0 to the number 7, diff --git a/README.md b/README.md index 77a8b99..92c3e05 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ Basic usage Code can be parsed using either `ast\parse_code()`, which accepts a code string, or `ast\parse_file()`, which accepts a file path. Additionally, both functions require a `$version` -argument to ensure forward-compatibility. The current version is 70. +argument to ensure forward-compatibility. The current version is 90. ```php $ast = ast\parse_code('tandre@php.net yes - 2021-07-08 + 2021-07-24 - 1.0.13 - 1.0.13 + 1.0.14 + 1.0.14 stable @@ -29,9 +29,9 @@ BSD-3-Clause -- Indicate in metadata that 'AST_CLASS_CONST_GROUP' and 'AST_CLASS_CONST_DECL' can have MODIFIER_FINAL - (and any modifier a class element can have, to reflect what the parser can actually parse) -- Support php 8.1 intersection types, add node kind 'AST_TYPE_INTERSECTION' +- Support php 8.1 readonly properties with the flag 'MODIFIER_READONLY' +- Support php 8.1 first-class callable syntax, add the node kind 'AST_CALLABLE_CONVERT' +- Change the current AST version from 80 to the new version 90. AST version 85 is no longer experimental. @@ -113,8 +113,10 @@ + + @@ -142,6 +144,23 @@ ast + + 2021-07-08 + + 1.0.13 + 1.0.13 + + + stable + stable + + BSD-3-Clause + + - Indicate in metadata that 'AST_CLASS_CONST_GROUP' and 'AST_CLASS_CONST_DECL' can have 'MODIFIER_FINAL' + (and any modifier a class element can have, to reflect what the parser can actually parse) + - Support php 8.1 intersection types, add the node kind 'AST_TYPE_INTERSECTION' + + 2021-05-16 @@ -154,7 +173,7 @@ BSD-3-Clause -- Support parsing 'docComment' on php 8.1 enums +- Support parsing 'docComment' on php 8.1 enum cases - Indicate in metadata that 'AST_CLASS_CONST_GROUP' and 'AST_CLASS_CONST_DECL' can have MODIFIER_FINAL diff --git a/php_ast.h b/php_ast.h index 9faea7b..e4e3a46 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.13" +#define PHP_AST_VERSION "1.0.14" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) @@ -77,6 +77,10 @@ extern ast_str_globals str_globals; #if PHP_VERSION_ID < 80100 # define ZEND_ACC_ENUM (1 << 22) +# define ZEND_ACC_READONLY (1 << 7) + +/* 0 child nodes */ +# define ZEND_AST_CALLABLE_CONVERT 3 /* 3 child nodes - name, expr, attributes */ # define ZEND_AST_ENUM_CASE 0x3fe # define ZEND_AST_TYPE_INTERSECTION ((1 << (ZEND_AST_IS_LIST_SHIFT + 1)) - 6) diff --git a/scripts/generate_ast_data.php b/scripts/generate_ast_data.php index c098d1f..02cc93a 100644 --- a/scripts/generate_ast_data.php +++ b/scripts/generate_ast_data.php @@ -63,6 +63,7 @@ /* 0 child nodes */ 'ZEND_AST_MAGIC_CONST' => [], 'ZEND_AST_TYPE' => [], + 'ZEND_AST_CALLABLE_CONVERT' => [], /* 1 child node */ 'ZEND_AST_VAR' => ['name'], diff --git a/tests/get_supported_versions.phpt b/tests/get_supported_versions.phpt index e786555..bb664bb 100644 --- a/tests/get_supported_versions.phpt +++ b/tests/get_supported_versions.phpt @@ -8,7 +8,7 @@ var_dump(ast\get_supported_versions(true)); ?> --EXPECT-- -array(5) { +array(6) { [0]=> int(50) [1]=> @@ -19,8 +19,10 @@ array(5) { int(80) [4]=> int(85) + [5]=> + int(90) } -array(5) { +array(6) { [0]=> int(50) [1]=> @@ -31,4 +33,6 @@ array(5) { int(80) [4]=> int(85) + [5]=> + int(90) } \ No newline at end of file diff --git a/tests/metadata.phpt b/tests/metadata.phpt index f2eafe0..92eb2f3 100644 --- a/tests/metadata.phpt +++ b/tests/metadata.phpt @@ -37,9 +37,9 @@ AST_SWITCH_LIST: [] AST_CATCH_LIST: [] AST_PARAM_LIST: [] AST_CLOSURE_USES: [] -AST_PROP_DECL: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL] +AST_PROP_DECL: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY] AST_CONST_DECL: [] -AST_CLASS_CONST_DECL: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL] +AST_CLASS_CONST_DECL: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY] AST_NAME_LIST: [] AST_TRAIT_ADAPTATIONS: [] AST_USE: [USE_NORMAL, USE_FUNCTION, USE_CONST] @@ -51,13 +51,14 @@ AST_MATCH_ARM_LIST: [] AST_NAME: [NAME_FQ, NAME_NOT_FQ, NAME_RELATIVE] AST_CLOSURE_VAR: [CLOSURE_USE_REF] AST_NULLABLE_TYPE: [] -AST_FUNC_DECL: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, FUNC_RETURNS_REF, FUNC_GENERATOR] -AST_CLOSURE: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, FUNC_RETURNS_REF, FUNC_GENERATOR] -AST_METHOD: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, FUNC_RETURNS_REF, FUNC_GENERATOR] -AST_ARROW_FUNC: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, FUNC_RETURNS_REF, FUNC_GENERATOR] +AST_FUNC_DECL: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY, FUNC_RETURNS_REF, FUNC_GENERATOR] +AST_CLOSURE: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY, FUNC_RETURNS_REF, FUNC_GENERATOR] +AST_METHOD: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY, FUNC_RETURNS_REF, FUNC_GENERATOR] +AST_ARROW_FUNC: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY, FUNC_RETURNS_REF, FUNC_GENERATOR] AST_CLASS: (combinable) [CLASS_ABSTRACT, CLASS_FINAL, CLASS_TRAIT, CLASS_INTERFACE, CLASS_ANONYMOUS, CLASS_ENUM] AST_MAGIC_CONST: [MAGIC_LINE, MAGIC_FILE, MAGIC_DIR, MAGIC_NAMESPACE, MAGIC_FUNCTION, MAGIC_METHOD, MAGIC_CLASS, MAGIC_TRAIT] AST_TYPE: [TYPE_NULL, TYPE_FALSE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED, TYPE_NEVER] +AST_CALLABLE_CONVERT: [] AST_VAR: [] AST_CONST: [] AST_UNPACK: [] @@ -87,7 +88,7 @@ AST_GOTO: [] AST_BREAK: [] AST_CONTINUE: [] AST_CLASS_NAME: [] -AST_CLASS_CONST_GROUP: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL] +AST_CLASS_CONST_GROUP: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY] AST_DIM: (combinable) [DIM_ALTERNATIVE_SYNTAX] AST_PROP: [] AST_NULLSAFE_PROP: [] @@ -110,14 +111,14 @@ AST_SWITCH: [] AST_SWITCH_CASE: [] AST_DECLARE: [] AST_PROP_ELEM: [] -AST_PROP_GROUP: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL] +AST_PROP_GROUP: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY] AST_CONST_ELEM: [] AST_USE_TRAIT: [] AST_TRAIT_PRECEDENCE: [] AST_METHOD_REFERENCE: [] AST_NAMESPACE: [] AST_USE_ELEM: [USE_NORMAL, USE_FUNCTION, USE_CONST] -AST_TRAIT_ALIAS: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL] +AST_TRAIT_ALIAS: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY] AST_GROUP_USE: [USE_NORMAL, USE_FUNCTION, USE_CONST] AST_ATTRIBUTE: [] AST_MATCH: [] diff --git a/tests/php81_first_class_callable_support.phpt b/tests/php81_first_class_callable_support.phpt new file mode 100644 index 0000000..5231e47 --- /dev/null +++ b/tests/php81_first_class_callable_support.phpt @@ -0,0 +1,46 @@ +--TEST-- +First-class callables in php 8.1 +--SKIPIF-- += 8.1 only'); ?> +--FILE-- +foo(...); +PHP; + +$node = ast\parse_code($code, $version=80); +echo ast_dump($node), "\n"; +?> +--EXPECTF-- +AST_STMT_LIST + 0: AST_ASSIGN + var: AST_VAR + name: "c1" + expr: AST_CALL + expr: AST_NAME + flags: NAME_NOT_FQ (1) + name: "foo" + args: AST_CALLABLE_CONVERT + 1: AST_ASSIGN + var: AST_VAR + name: "c2" + expr: AST_STATIC_CALL + class: AST_NAME + flags: NAME_NOT_FQ (1) + name: "C" + method: "foo" + args: AST_CALLABLE_CONVERT + 2: AST_ASSIGN + var: AST_VAR + name: "c2" + expr: AST_METHOD_CALL + expr: AST_VAR + name: "x" + method: "foo" + args: AST_CALLABLE_CONVERT \ No newline at end of file diff --git a/tests/php81_readonly.phpt b/tests/php81_readonly.phpt new file mode 100644 index 0000000..d23f102 --- /dev/null +++ b/tests/php81_readonly.phpt @@ -0,0 +1,58 @@ +--TEST-- +Readonly properties in php 8.1 +--SKIPIF-- += 8.1 only'); ?> +--FILE-- + Date: Sat, 24 Jul 2021 11:30:53 -0400 Subject: [PATCH 11/53] Bump current version to 1.0.15-dev (#211) --- package.xml | 33 ++++++++++++++++++++++++--------- php_ast.h | 2 +- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/package.xml b/package.xml index 5cd3436..a7d4d0f 100644 --- a/package.xml +++ b/package.xml @@ -20,18 +20,16 @@ 2021-07-24 - 1.0.14 - 1.0.14 + 1.0.15dev + 1.0.15dev - stable + devel stable BSD-3-Clause -- Support php 8.1 readonly properties with the flag 'MODIFIER_READONLY' -- Support php 8.1 first-class callable syntax, add the node kind 'AST_CALLABLE_CONVERT' -- Change the current AST version from 80 to the new version 90. AST version 85 is no longer experimental. +- TBD @@ -144,6 +142,23 @@ ast + + 2021-07-24 + + 1.0.14 + 1.0.14 + + + stable + stable + + BSD-3-Clause + +- Support php 8.1 readonly properties with the flag 'MODIFIER_READONLY' +- Support php 8.1 first-class callable syntax, add the node kind 'AST_CALLABLE_CONVERT' +- Change the current AST version from 80 to the new version 90. AST version 85 is no longer experimental. + + 2021-07-08 @@ -156,9 +171,9 @@ BSD-3-Clause - - Indicate in metadata that 'AST_CLASS_CONST_GROUP' and 'AST_CLASS_CONST_DECL' can have 'MODIFIER_FINAL' - (and any modifier a class element can have, to reflect what the parser can actually parse) - - Support php 8.1 intersection types, add the node kind 'AST_TYPE_INTERSECTION' +- Indicate in metadata that 'AST_CLASS_CONST_GROUP' and 'AST_CLASS_CONST_DECL' can have 'MODIFIER_FINAL' + (and any modifier a class element can have, to reflect what the parser can actually parse) +- Support php 8.1 intersection types, add the node kind 'AST_TYPE_INTERSECTION' diff --git a/php_ast.h b/php_ast.h index e4e3a46..17cfadd 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.14" +#define PHP_AST_VERSION "1.0.15-dev" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) From 89980f4683fbb6d82a009767f85aea6833586d20 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sat, 24 Jul 2021 11:40:18 -0400 Subject: [PATCH 12/53] Run GitHub Actions test in php 8.1.0beta1 as well (#212) --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c9875b3..ce649c0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -33,6 +33,7 @@ jobs: - PHP_VERSION: '7.3' - PHP_VERSION: '7.4' - PHP_VERSION: '8.0' + - PHP_VERSION: '8.1.0beta1' # Steps represent a sequence of tasks that will be executed as part of the job steps: From a5b2f60240363c0a9c30aff6287db14c5609352b Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sat, 27 Nov 2021 08:49:47 -0500 Subject: [PATCH 13/53] Use array_init_size as size hint for created arrays (#216) --- ast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ast.c b/ast.c index 90b91b3..cd4d54d 100644 --- a/ast.c +++ b/ast.c @@ -624,7 +624,7 @@ static void ast_create_virtual_node_ex( ast_update_property_long(zv, AST_STR(str_lineno), lineno, AST_CACHE_SLOT_LINENO); - array_init(&tmp_zv); + array_init_size(&tmp_zv, num_children); Z_DELREF(tmp_zv); ast_update_property(zv, AST_STR(str_children), &tmp_zv, AST_CACHE_SLOT_CHILDREN); From e36cc7def412834b67774289cfb6307a54c1e5c6 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sat, 27 Nov 2021 10:22:40 -0500 Subject: [PATCH 14/53] Allow dynamic properties (e.g. endLineno) without deprecation notice in ast\Node (#217) (But use the default deprecation behavior for ast\Metadata) 1. php-ast itself sets the dynamic property on endLineno right now, causing deprecation notices in PHP 8.2. Because all declaration types are associative arrays(not lists), a future AST version number may add this as a property of $node->children instead to avoid this notice. 2. WeakMap is only available in PHP 8.0+ (and WeakReference 7.4), but https://github.com/phan/phan targets PHP 7.2+. 3. Because some nodes make `$node->children` a list, applications such as Phan using php-ast can't associate string keys with that. (e.g. to mark nodes that were already processed in a certain step) https://github.com/nikic/php-parser solves that by adding `attributes`, `setAttribute`, `getAttribute`, etc. separately from children, but php-ast currently doesn't have an attributes node. That may be worth it in a future release. 4. When processing a large number of ast nodes in a large number of files, the deprecation notices have a noticeable performance impact, even when suppressed. Related to #214 --- ast.c | 8 +++++++ package.xml | 3 ++- tests/php82_metadata.phpt | 48 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 tests/php82_metadata.phpt diff --git a/ast.c b/ast.c index cd4d54d..6c2a653 100644 --- a/ast.c +++ b/ast.c @@ -13,6 +13,10 @@ #include "zend_language_parser.h" #include "zend_exceptions.h" #include "zend_smart_str.h" +#if PHP_VERSION_ID >= 80200 +/* Used for AllowDynamicProperties */ +#include "zend_attributes.h" +#endif #ifndef ZEND_ARG_INFO_WITH_DEFAULT_VALUE #define ZEND_ARG_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, default_value) \ @@ -1518,6 +1522,10 @@ PHP_MINIT_FUNCTION(ast) { ast_declare_property(ast_node_ce, AST_STR(str_flags), &zv_null); ast_declare_property(ast_node_ce, AST_STR(str_lineno), &zv_null); ast_declare_property(ast_node_ce, AST_STR(str_children), &zv_null); +#ifdef ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES + zend_add_class_attribute(ast_node_ce, zend_ce_allow_dynamic_properties->name, 0); + ast_node_ce->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES; +#endif INIT_CLASS_ENTRY(tmp_ce, "ast\\Metadata", NULL); ast_metadata_ce = zend_register_internal_class(&tmp_ce); diff --git a/package.xml b/package.xml index a7d4d0f..9193e1f 100644 --- a/package.xml +++ b/package.xml @@ -29,7 +29,7 @@ BSD-3-Clause -- TBD +- Allow ast\Node to have dynamic properties without emitting a notice in PHP 8.2. @@ -115,6 +115,7 @@ + diff --git a/tests/php82_metadata.phpt b/tests/php82_metadata.phpt new file mode 100644 index 0000000..bd643e2 --- /dev/null +++ b/tests/php82_metadata.phpt @@ -0,0 +1,48 @@ +--TEST-- +Dynamic property support in php 8.2+ +--SKIPIF-- +=8.2 only'); ?> +--FILE-- +getAttributes() as $attribute) { + echo "- " . $attribute->getName() . "\n"; + } +} + +$node = new ast\Node(); +$node->undeclaredDynamic = 123; +dump($node); +$metadata = new ast\Metadata(); +$metadata->undeclaredDynamic = 123; +dump($metadata); +dump_attributes(ast\Node::class); +dump_attributes(ast\Metadata::class); +--EXPECTF-- +ast\Node::__set_state(array( + 'kind' => NULL, + 'flags' => NULL, + 'lineno' => NULL, + 'children' => NULL, + 'undeclaredDynamic' => 123, +)) +Deprecated: Creation of dynamic property ast\Metadata::$undeclaredDynamic is deprecated in %sphp82_metadata.php on line 21 +ast\Metadata::__set_state(array( + 'kind' => NULL, + 'name' => NULL, + 'flags' => NULL, + 'flagsCombinable' => NULL, + 'undeclaredDynamic' => 123, +)) +Attributes of ast\Node: +- AllowDynamicProperties +Attributes of ast\Metadata: From 6b05823ebc5157396d03667e1aa09fd83458f52f Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sat, 27 Nov 2021 12:02:04 -0500 Subject: [PATCH 15/53] Update php versions tested in CI, prepare the 1.0.15 release (#218) * Update php versions tested in CI PHP '8.1' isn't published yet on docker hub. Start testing with php 8.1 in appveyor * Prepare for a 1.0.15 release Make it possible to test with php 8.2 without deprecation notes for endLineno, etc. See #217 Also, document how to properly update cache slot numbers if new properties are added to ast\Node in the future. --- .appveyor.yml | 44 +++++++++++++++++++++++++++----------- .github/workflows/main.yml | 2 +- ast.c | 1 + ci/test_dockerized.sh | 3 ++- package.xml | 6 +++--- php_ast.h | 3 ++- 6 files changed, 41 insertions(+), 18 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 35ee899..4e56831 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -32,22 +32,42 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 ARCH: x86 VC: vs16 - PHP_VER: 8.0.3 + PHP_VER: 8.1.0 TS: 1 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 ARCH: x64 VC: vs16 - PHP_VER: 8.0.3 + PHP_VER: 8.1.0 TS: 1 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 ARCH: x86 VC: vs16 - PHP_VER: 8.0.3 + PHP_VER: 8.1.0 TS: 0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 ARCH: x64 VC: vs16 - PHP_VER: 8.0.3 + PHP_VER: 8.1.0 + TS: 0 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + ARCH: x86 + VC: vs16 + PHP_VER: 8.0.13 + TS: 1 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + ARCH: x64 + VC: vs16 + PHP_VER: 8.0.13 + TS: 1 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + ARCH: x86 + VC: vs16 + PHP_VER: 8.0.13 + TS: 0 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + ARCH: x64 + VC: vs16 + PHP_VER: 8.0.13 TS: 0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 ARCH: x64 @@ -112,42 +132,42 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x64 VC: vc15 - PHP_VER: 7.3.25 + PHP_VER: 7.3.33 TS: 0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x64 VC: vc15 - PHP_VER: 7.3.27 + PHP_VER: 7.3.33 TS: 1 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x86 VC: vc15 - PHP_VER: 7.3.27 + PHP_VER: 7.3.33 TS: 0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x86 VC: vc15 - PHP_VER: 7.3.27 + PHP_VER: 7.3.33 TS: 1 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x64 VC: vc15 - PHP_VER: 7.4.16 + PHP_VER: 7.4.26 TS: 0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x64 VC: vc15 - PHP_VER: 7.4.16 + PHP_VER: 7.4.26 TS: 1 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x86 VC: vc15 - PHP_VER: 7.4.16 + PHP_VER: 7.4.26 TS: 0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x86 VC: vc15 - PHP_VER: 7.4.16 + PHP_VER: 7.4.26 TS: 1 build_script: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ce649c0..e279f45 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -33,7 +33,7 @@ jobs: - PHP_VERSION: '7.3' - PHP_VERSION: '7.4' - PHP_VERSION: '8.0' - - PHP_VERSION: '8.1.0beta1' + - PHP_VERSION: '8.1.0RC6' # Steps represent a sequence of tasks that will be executed as part of the job steps: diff --git a/ast.c b/ast.c index 6c2a653..bb20d8e 100644 --- a/ast.c +++ b/ast.c @@ -50,6 +50,7 @@ #define ast_register_flag_constant(name, value) \ REGISTER_NS_LONG_CONSTANT("ast\\flags", name, value, CONST_CS | CONST_PERSISTENT) +// The number of cache slots there are must be the same as AST_NUM_CACHE_SLOTS in php_ast.h #define AST_CACHE_SLOT_KIND &AST_G(cache_slots)[3 * 0] #define AST_CACHE_SLOT_FLAGS &AST_G(cache_slots)[3 * 1] #define AST_CACHE_SLOT_LINENO &AST_G(cache_slots)[3 * 2] diff --git a/ci/test_dockerized.sh b/ci/test_dockerized.sh index f263e72..e9ce09b 100755 --- a/ci/test_dockerized.sh +++ b/ci/test_dockerized.sh @@ -10,6 +10,7 @@ fi # -u fail for undefined variables set -xeu PHP_VERSION=$1 -DOCKER_IMAGE=php-ast-$PHP_VERSION-test-runner +# uppercase is not allowed in image names, only in tags +DOCKER_IMAGE=php-ast-test-runner:$PHP_VERSION docker build --build-arg="PHP_VERSION=$PHP_VERSION" --tag="$DOCKER_IMAGE" -f ci/Dockerfile . docker run --rm $DOCKER_IMAGE ci/test_inner.sh diff --git a/package.xml b/package.xml index 9193e1f..cbd9d23 100644 --- a/package.xml +++ b/package.xml @@ -18,10 +18,10 @@ tandre@php.net yes - 2021-07-24 + 2021-11-27 - 1.0.15dev - 1.0.15dev + 1.0.15 + 1.0.15 devel diff --git a/php_ast.h b/php_ast.h index 17cfadd..8fbaee0 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.15-dev" +#define PHP_AST_VERSION "1.0.15" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) @@ -23,6 +23,7 @@ extern zend_module_entry ast_module_entry; // PHP 7.4 added a 3rd cache slot for property_info // and expects cache_slot[2] to be null. +// There are 4 entries in ast.c in `AST_CACHE_SLOT_*` #define AST_NUM_CACHE_SLOTS (3 * 4) ZEND_BEGIN_MODULE_GLOBALS(ast) From 8f1e75f66e4d1746c11cf4d96a68181a6e8ff693 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sat, 27 Nov 2021 15:10:12 -0500 Subject: [PATCH 16/53] Release 1.0.16: Optimize ast\Node property setting. Document `#[AllowsDynamicProperties]` in stubs (#219) Add `#[AllowsDynamicProperties]` to AST stubs Use OBJ_PROP_NUM for ast\Node and ast\Metadata building (Do it even for Metadata. The resulting assembly code should be smaller and it's an example of how to write other classes efficiently in the future) Mark 1.0.15 and 1.0.16 as stable --- ast.c | 120 +++++++++++++++++++++++++++----------------------- ast.stub.php | 48 ++++---------------- ast_arginfo.h | 2 +- ast_stub.php | 2 + package.xml | 24 ++++++++-- php_ast.h | 8 +--- 6 files changed, 98 insertions(+), 106 deletions(-) diff --git a/ast.c b/ast.c index bb20d8e..ebbc515 100644 --- a/ast.c +++ b/ast.c @@ -12,12 +12,17 @@ #include "zend_language_scanner_defs.h" #include "zend_language_parser.h" #include "zend_exceptions.h" +#include "zend_hash.h" #include "zend_smart_str.h" #if PHP_VERSION_ID >= 80200 /* Used for AllowDynamicProperties */ #include "zend_attributes.h" #endif +#ifndef ZEND_THIS +#define ZEND_THIS getThis() +#endif + #ifndef ZEND_ARG_INFO_WITH_DEFAULT_VALUE #define ZEND_ARG_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, default_value) \ ZEND_ARG_INFO(pass_by_ref, name) @@ -50,11 +55,23 @@ #define ast_register_flag_constant(name, value) \ REGISTER_NS_LONG_CONSTANT("ast\\flags", name, value, CONST_CS | CONST_PERSISTENT) -// The number of cache slots there are must be the same as AST_NUM_CACHE_SLOTS in php_ast.h -#define AST_CACHE_SLOT_KIND &AST_G(cache_slots)[3 * 0] -#define AST_CACHE_SLOT_FLAGS &AST_G(cache_slots)[3 * 1] -#define AST_CACHE_SLOT_LINENO &AST_G(cache_slots)[3 * 2] -#define AST_CACHE_SLOT_CHILDREN &AST_G(cache_slots)[3 * 3] +// These are in the order the properties were declared with ast_declare_property. +#define AST_NODE_PROP_KIND(object) OBJ_PROP_NUM((object), 0) +#define AST_NODE_PROP_FLAGS(object) OBJ_PROP_NUM((object), 1) +#define AST_NODE_PROP_LINENO(object) OBJ_PROP_NUM((object), 2) +#define AST_NODE_PROP_CHILDREN(object) OBJ_PROP_NUM((object), 3) + +#define AST_NODE_SET_PROP_KIND(object, num) ZVAL_LONG(AST_NODE_PROP_KIND((object)), (num)) +#define AST_NODE_SET_PROP_FLAGS(object, num) ZVAL_LONG(AST_NODE_PROP_FLAGS((object)), (num)) +#define AST_NODE_SET_PROP_LINENO(object, num) ZVAL_LONG(AST_NODE_PROP_LINENO((object)), (num)) +// Set the ast\Node->children array to the given reference-counted array without incrementing the reference count of the array. +// Do not use this macro with immutable arrays. +#define AST_NODE_SET_PROP_CHILDREN_ARRAY(object, array) ZVAL_ARR(AST_NODE_PROP_CHILDREN((object)), (array)) + +#define AST_METADATA_PROP_KIND(object) OBJ_PROP_NUM((object), 0) +#define AST_METADATA_PROP_NAME(object) OBJ_PROP_NUM((object), 1) +#define AST_METADATA_PROP_FLAGS(object) OBJ_PROP_NUM((object), 2) +#define AST_METADATA_PROP_FLAGS_COMBINABLE(object) OBJ_PROP_NUM((object), 3) #define AST_CURRENT_VERSION 90 @@ -334,22 +351,20 @@ static const ast_flag_info flag_info[] = { { ZEND_AST_CONDITIONAL, 1, conditional_flags }, }; -// NOTE(tandre) in php 8, to get a writeable pointer to a property, OBJ_PROP_NUM(AST_CACHE_SLOT_PROPNAME) can be used. - -static inline void ast_update_property(zval *object, zend_string *name, zval *value, void **cache_slot) { +static inline void ast_update_property(zval *object, zend_string *name, zval *value) { #if PHP_VERSION_ID < 80000 zval name_zv; ZVAL_STR(&name_zv, name); - Z_OBJ_HT_P(object)->write_property(object, &name_zv, value, cache_slot); + Z_OBJ_HT_P(object)->write_property(object, &name_zv, value, NULL); #else - Z_OBJ_HT_P(object)->write_property(Z_OBJ_P(object), name, value, cache_slot); + Z_OBJ_HT_P(object)->write_property(Z_OBJ_P(object), name, value, NULL); #endif } -static inline void ast_update_property_long(zval *object, zend_string *name, zend_long value_raw, void **cache_slot) { +static inline void ast_update_property_long(zval *object, zend_string *name, zend_long value_raw) { zval value_zv; ZVAL_LONG(&value_zv, value_raw); - ast_update_property(object, name, &value_zv, cache_slot); + ast_update_property(object, name, &value_zv); } static zend_ast *get_ast(zend_string *code, zend_arena **ast_arena, zend_string *filename) { @@ -617,30 +632,28 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state); static void ast_create_virtual_node_ex( zval *zv, zend_ast_kind kind, zend_ast_attr attr, uint32_t lineno, ast_state_info_t *state, uint32_t num_children, ...) { - zval tmp_zv; va_list va; uint32_t i; object_init_ex(zv, ast_node_ce); - ast_update_property_long(zv, AST_STR(str_kind), kind, AST_CACHE_SLOT_KIND); - - ast_update_property_long(zv, AST_STR(str_flags), attr, AST_CACHE_SLOT_FLAGS); + zend_object *obj = Z_OBJ_P(zv); - ast_update_property_long(zv, AST_STR(str_lineno), lineno, AST_CACHE_SLOT_LINENO); + AST_NODE_SET_PROP_KIND(obj, kind); + AST_NODE_SET_PROP_FLAGS(obj, attr); + AST_NODE_SET_PROP_LINENO(obj, lineno); - array_init_size(&tmp_zv, num_children); - Z_DELREF(tmp_zv); - ast_update_property(zv, AST_STR(str_children), &tmp_zv, AST_CACHE_SLOT_CHILDREN); + array_init_size(AST_NODE_PROP_CHILDREN(obj), num_children); + HashTable *children = Z_ARRVAL_P(AST_NODE_PROP_CHILDREN(obj)); va_start(va, num_children); for (i = 0; i < num_children; i++) { zval *child_zv = va_arg(va, zval *); zend_string *child_name = ast_kind_child_name(kind, i); if (child_name) { - zend_hash_add_new(Z_ARRVAL(tmp_zv), child_name, child_zv); + zend_hash_add_new(children, child_name, child_zv); } else { - zend_hash_next_index_insert(Z_ARRVAL(tmp_zv), child_zv); + zend_hash_next_index_insert(children, child_zv); } } va_end(va); @@ -870,7 +883,7 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t } static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { - zval tmp_zv, children_zv; + zval tmp_zv; if (ast == NULL) { ZVAL_NULL(zv); @@ -939,7 +952,7 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { ast_to_zval(zv, ast->child[1], state); // The property visibility is on the AST_PROP_GROUP node. // Add it to the AST_PROP_DECL node for old - ast_update_property_long(zv, AST_STR(str_flags), ast->attr, AST_CACHE_SLOT_FLAGS); + AST_NODE_SET_PROP_FLAGS(Z_OBJ_P(zv), ast->attr); return; } break; @@ -1007,48 +1020,50 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { object_init_ex(zv, ast_node_ce); - ast_update_property_long(zv, AST_STR(str_kind), ast->kind, AST_CACHE_SLOT_KIND); + zend_object *obj = Z_OBJ_P(zv); + + AST_NODE_SET_PROP_KIND(obj, ast->kind); - ast_update_property_long(zv, AST_STR(str_lineno), zend_ast_get_lineno(ast), AST_CACHE_SLOT_LINENO); + AST_NODE_SET_PROP_LINENO(obj, zend_ast_get_lineno(ast)); - array_init(&children_zv); - Z_DELREF(children_zv); - ast_update_property(zv, AST_STR(str_children), &children_zv, AST_CACHE_SLOT_CHILDREN); + array_init(AST_NODE_PROP_CHILDREN(obj)); + HashTable *children = Z_ARRVAL_P(AST_NODE_PROP_CHILDREN(obj)); if (ast_kind_is_decl(ast->kind)) { zend_ast_decl *decl = (zend_ast_decl *) ast; - ast_update_property_long(zv, AST_STR(str_flags), decl->flags, AST_CACHE_SLOT_FLAGS); + AST_NODE_SET_PROP_FLAGS(obj, decl->flags); - ast_update_property_long(zv, AST_STR(str_endLineno), decl->end_lineno, NULL); + // This is an undeclared dynamic property and has no cache slot. + ast_update_property_long(zv, AST_STR(str_endLineno), decl->end_lineno); if (decl->name) { ZVAL_STR(&tmp_zv, decl->name); + Z_TRY_ADDREF(tmp_zv); } else { ZVAL_NULL(&tmp_zv); } - Z_TRY_ADDREF(tmp_zv); - zend_hash_add_new(Z_ARRVAL(children_zv), AST_STR(str_name), &tmp_zv); + zend_hash_add_new(children, AST_STR(str_name), &tmp_zv); if (decl->doc_comment) { ZVAL_STR(&tmp_zv, decl->doc_comment); + Z_TRY_ADDREF(tmp_zv); } else { ZVAL_NULL(&tmp_zv); } - Z_TRY_ADDREF(tmp_zv); - zend_hash_add_new(Z_ARRVAL(children_zv), AST_STR(str_docComment), &tmp_zv); + zend_hash_add_new(children, AST_STR(str_docComment), &tmp_zv); } else { #if PHP_VERSION_ID < 70100 if (ast->kind == ZEND_AST_CLASS_CONST_DECL) { ast->attr = ZEND_ACC_PUBLIC; } #endif - ast_update_property_long(zv, AST_STR(str_flags), ast->attr, AST_CACHE_SLOT_FLAGS); + AST_NODE_SET_PROP_FLAGS(obj, ast->attr); } - ast_fill_children_ht(Z_ARRVAL(children_zv), ast, state); + ast_fill_children_ht(children, ast, state); #if PHP_VERSION_ID < 70400 if (ast->kind == ZEND_AST_PROP_DECL && state->version >= 70) { zval type_zval; @@ -1064,7 +1079,7 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { ast_create_virtual_node_ex( zv, ZEND_AST_PROP_GROUP, ast->attr, zend_ast_get_lineno(ast), state, 2, &type_zval, &prop_group_zval); } - ast_update_property_long(&prop_group_zval, AST_STR(str_flags), 0, AST_CACHE_SLOT_FLAGS); + AST_NODE_SET_PROP_FLAGS(obj, 0); } #endif #if PHP_VERSION_ID < 80000 @@ -1073,7 +1088,7 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { zval attributes_zval; ZVAL_COPY_VALUE(&const_decl_zval, zv); ZVAL_NULL(&attributes_zval); - ast_update_property_long(zv, AST_STR(str_flags), 0, AST_CACHE_SLOT_FLAGS); + AST_NODE_SET_PROP_FLAGS(obj, 0); // For version 80, create an AST_CLASS_CONST_GROUP wrapping the created AST_CLASS_CONST_DECL ast_create_virtual_node_ex( zv, ZEND_AST_CLASS_CONST_GROUP, ast->attr, zend_ast_get_lineno(ast), state, 2, &const_decl_zval, &attributes_zval); @@ -1255,21 +1270,21 @@ static inline const ast_flag_info *ast_get_flag_info(uint16_t ast_kind) { static void ast_build_metadata(zval *result) { size_t i; - array_init(result); + array_init_size(result, ast_kinds_count); for (i = 0; i < ast_kinds_count; i++) { zend_ast_kind kind = ast_kinds[i]; const ast_flag_info *flag_info = ast_get_flag_info(kind); zval info_zv, tmp_zv; + zend_object *obj; object_init_ex(&info_zv, ast_metadata_ce); + obj = Z_OBJ(info_zv); /* kind */ - ast_update_property_long(&info_zv, AST_STR(str_kind), kind, NULL); + ZVAL_LONG(AST_METADATA_PROP_KIND(obj), kind); /* name */ - ZVAL_STRING(&tmp_zv, ast_kind_to_name(kind)); - Z_TRY_DELREF(tmp_zv); - ast_update_property(&info_zv, AST_STR(str_name), &tmp_zv, NULL); + ZVAL_STRING(AST_METADATA_PROP_NAME(obj), ast_kind_to_name(kind)); /* flags */ array_init(&tmp_zv); @@ -1279,12 +1294,10 @@ static void ast_build_metadata(zval *result) { add_next_index_string(&tmp_zv, *flag); } } - Z_TRY_DELREF(tmp_zv); - ast_update_property(&info_zv, AST_STR(str_flags), &tmp_zv, NULL); + ZVAL_ARR(AST_METADATA_PROP_FLAGS(obj), Z_ARRVAL(tmp_zv)); /* flagsCombinable */ - ZVAL_BOOL(&tmp_zv, flag_info && flag_info->combinable); - ast_update_property(&info_zv, AST_STR(str_flagsCombinable), &tmp_zv, NULL); + ZVAL_BOOL(AST_METADATA_PROP_FLAGS_COMBINABLE(obj), flag_info && flag_info->combinable); add_index_zval(result, kind, &info_zv); } @@ -1340,27 +1353,27 @@ PHP_METHOD(ast_Node, __construct) { Z_PARAM_LONG_EX(lineno, linenoNull, 1, 0) ZEND_PARSE_PARAMETERS_END(); - zval *zv = getThis(); + zend_object *obj = Z_OBJ_P(ZEND_THIS); switch (num_args) { case 4: if (!linenoNull) { - ast_update_property_long(zv, AST_STR(str_lineno), lineno, AST_CACHE_SLOT_LINENO); + AST_NODE_SET_PROP_LINENO(obj, lineno); } /* Falls through - break missing intentionally */ case 3: if (children != NULL) { - ast_update_property(zv, AST_STR(str_children), children, AST_CACHE_SLOT_CHILDREN); + ZVAL_COPY(AST_NODE_PROP_CHILDREN(obj), children); } /* Falls through - break missing intentionally */ case 2: if (!flagsNull) { - ast_update_property_long(zv, AST_STR(str_flags), flags, AST_CACHE_SLOT_FLAGS); + AST_NODE_SET_PROP_FLAGS(obj, flags); } /* Falls through - break missing intentionally */ case 1: if (!kindNull) { - ast_update_property_long(zv, AST_STR(str_kind), kind, AST_CACHE_SLOT_KIND); + AST_NODE_SET_PROP_KIND(obj, kind); } /* Falls through - break missing intentionally */ case 0: @@ -1381,7 +1394,6 @@ PHP_MINFO_FUNCTION(ast) { } PHP_RINIT_FUNCTION(ast) { - memset(AST_G(cache_slots), 0, sizeof(void *) * AST_NUM_CACHE_SLOTS); ZVAL_UNDEF(&AST_G(metadata)); return SUCCESS; } diff --git a/ast.stub.php b/ast.stub.php index a849a47..daf9e18 100644 --- a/ast.stub.php +++ b/ast.stub.php @@ -3,7 +3,9 @@ /** @generate-function-entries */ /** - * USE ast_stub.php INSTEAD IF YOU ARE LOOKING FOR DOCUMENTATION OR STUBS FOR YOUR IDE. + * ======================================================================================== + * | USE ast_stub.php INSTEAD IF YOU ARE LOOKING FOR DOCUMENTATION OR STUBS FOR YOUR IDE. | + * ======================================================================================== * * This is a stub file meant only for use with https://github.com/php/php-src/blob/master/build/gen_stub.php * to generate Reflection information (ReflectionParameter, ReflectionFunction, ReflectionMethod, etc.) @@ -11,62 +13,28 @@ namespace ast; -/** - * Parses code file and returns AST root node. - * - * @param string $filename Code file to parse - * @param int $version AST version - * @return Node Root node of AST - * - * @see https://github.com/nikic/php-ast for version information - */ +// XXX: @param in doc comments will cause build/gen_stub.php to emit an error if there is already a real type in the latest php versions. +// Use ast_stub.php instead for documentation. + function parse_code(string $code, int $version, string $filename = 'string code'): \ast\Node {} function parse_file(string $filename, int $version): \ast\Node {} -/** - * @param int $kind AST_* constant value defining the kind of an AST node - * @return string String representation of AST kind value - */ function get_kind_name(int $kind): string {} -/** - * @param int $kind AST_* constant value defining the kind of an AST node - * @return bool Returns true if AST kind uses flags - */ function kind_uses_flags(int $kind): bool {} -/** - * Provides metadata for the AST kinds. - * - * The returned array is a map from AST kind to a Metadata object. - * - * @return Metadata[] Metadata about AST kinds - */ function get_metadata(): array {} -/** - * Returns currently supported AST versions. - * - * @param bool $exclude_deprecated Whether to exclude deprecated versions - * @return int[] Array of supported AST versions - */ function get_supported_versions(bool $exclude_deprecated = false): array {} +// In php 8.2+, ast\Node implements the attribute AllowDynamicProperties /** * This class describes a single node in a PHP AST. */ +#[AllowDynamicProperties] class Node { - /** - * A constructor which accepts any types for the properties. - * For backwards compatibility reasons, all values are optional and can be any type, and properties default to null - * - * @param int|null $kind - * @param int|null $flags - * @param array|null $children - * @param int|null $lineno - */ public function __construct(?int $kind = null, ?int $flags = null, ?array $children = null, ?int $lineno = null) { } } diff --git a/ast_arginfo.h b/ast_arginfo.h index 36107d8..b27bebb 100644 --- a/ast_arginfo.h +++ b/ast_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 41024915fb5255fdbd22c2864f1d3793de262593 */ + * Stub hash: d7ef66b95afbb59ff4fba8ab475785c699c07173 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_ast_parse_code, 0, 2, ast\\Node, 0) ZEND_ARG_TYPE_INFO(0, code, IS_STRING, 0) diff --git a/ast_stub.php b/ast_stub.php index 10292d3..8e699bf 100644 --- a/ast_stub.php +++ b/ast_stub.php @@ -278,9 +278,11 @@ function get_supported_versions($exclude_deprecated = false): array { } +// In php 8.2+, this class has the attribute AllowDynamicProperties /** * This class describes a single node in a PHP AST. */ +#[AllowDynamicProperties] class Node { /** @var int AST Node Kind. Values are one of ast\AST_* constants. */ diff --git a/package.xml b/package.xml index cbd9d23..d8d218c 100644 --- a/package.xml +++ b/package.xml @@ -20,16 +20,17 @@ 2021-11-27 - 1.0.15 - 1.0.15 + 1.0.16 + 1.0.16 - devel + stable stable BSD-3-Clause -- Allow ast\Node to have dynamic properties without emitting a notice in PHP 8.2. +- Optimize instantiating properties of ast\Node and ast\Metadata. +- Document that ast\Node implements `#[AllowDynamicProperties]` in php 8.2 @@ -143,6 +144,21 @@ ast + + 2021-11-27 + + 1.0.15 + 1.0.15 + + + stable + stable + + BSD-3-Clause + +- Allow ast\Node to have dynamic properties without emitting a notice in PHP 8.2. + + 2021-07-24 diff --git a/php_ast.h b/php_ast.h index 8fbaee0..60a81b6 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.15" +#define PHP_AST_VERSION "1.0.16" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) @@ -21,13 +21,7 @@ extern zend_module_entry ast_module_entry; #include "TSRM.h" #endif -// PHP 7.4 added a 3rd cache slot for property_info -// and expects cache_slot[2] to be null. -// There are 4 entries in ast.c in `AST_CACHE_SLOT_*` -#define AST_NUM_CACHE_SLOTS (3 * 4) - ZEND_BEGIN_MODULE_GLOBALS(ast) - void *cache_slots[AST_NUM_CACHE_SLOTS]; zval metadata; ZEND_END_MODULE_GLOBALS(ast) From fec004c257166a386c91e8049e6d688ac87038ed Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sat, 12 Feb 2022 12:54:04 -0500 Subject: [PATCH 17/53] Properly namespace `#[\AllowDynamicProperties]` in documentation (#220) This was previously resolved relative to the `ast\` namespace in type checkers or if gen_stubs supported attributes in the future. --- ast.stub.php | 2 +- ast_arginfo.h | 2 +- package.xml | 25 ++++++++++++++++++++----- php_ast.h | 2 +- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/ast.stub.php b/ast.stub.php index daf9e18..1e270e9 100644 --- a/ast.stub.php +++ b/ast.stub.php @@ -32,7 +32,7 @@ function get_supported_versions(bool $exclude_deprecated = false): array {} /** * This class describes a single node in a PHP AST. */ -#[AllowDynamicProperties] +#[\AllowDynamicProperties] class Node { public function __construct(?int $kind = null, ?int $flags = null, ?array $children = null, ?int $lineno = null) { diff --git a/ast_arginfo.h b/ast_arginfo.h index b27bebb..ce61f55 100644 --- a/ast_arginfo.h +++ b/ast_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: d7ef66b95afbb59ff4fba8ab475785c699c07173 */ + * Stub hash: bd6cdcf553c8e2d0fa06a42f9ff86e716544f817 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_ast_parse_code, 0, 2, ast\\Node, 0) ZEND_ARG_TYPE_INFO(0, code, IS_STRING, 0) diff --git a/package.xml b/package.xml index d8d218c..3e538e6 100644 --- a/package.xml +++ b/package.xml @@ -18,10 +18,10 @@ tandre@php.net yes - 2021-11-27 + 2022-02-12 - 1.0.16 - 1.0.16 + 1.0.17dev + 1.0.17dev stable @@ -29,8 +29,7 @@ BSD-3-Clause -- Optimize instantiating properties of ast\Node and ast\Metadata. -- Document that ast\Node implements `#[AllowDynamicProperties]` in php 8.2 +- Change documentation files to properly namespace attributes as `#[\AllowDynamicProperties]`. The reflection attributes are already correct. @@ -144,6 +143,22 @@ ast + + 2021-11-27 + + 1.0.16 + 1.0.16 + + + stable + stable + + BSD-3-Clause + +- Optimize instantiating properties of ast\Node and ast\Metadata. +- Document that ast\Node implements `#[AllowDynamicProperties]` in php 8.2 + + 2021-11-27 diff --git a/php_ast.h b/php_ast.h index 60a81b6..54d8944 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.16" +#define PHP_AST_VERSION "1.0.17dev" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) From f2f7cadc6f98be4819875de6cfd0f7de6d77bcaf Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 7 Aug 2022 08:33:54 -0400 Subject: [PATCH 18/53] Fix test failures seen in php 8.2 (#226) Fix bug where ZEND_AST_ARROW_FUNC output for 'stmts' in php 8.2 did not match earlier php versions, which would affect tools using php-ast. Handle var_export's output changing to always be fully qualified in php 8.2 test output (`\ast\Node::__set_state(array(` starting with backslash) And start running tests in php 8.2. --- .github/workflows/main.yml | 3 ++- ast.c | 12 +++++++++++- tests/php82_metadata.phpt | 4 ++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e279f45..335dc51 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -33,7 +33,8 @@ jobs: - PHP_VERSION: '7.3' - PHP_VERSION: '7.4' - PHP_VERSION: '8.0' - - PHP_VERSION: '8.1.0RC6' + - PHP_VERSION: '8.1' + - PHP_VERSION: '8.2.0beta2' # Steps represent a sequence of tasks that will be executed as part of the job steps: diff --git a/ast.c b/ast.c index ebbc515..8d6a068 100644 --- a/ast.c +++ b/ast.c @@ -821,8 +821,18 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t } else { ast_to_zval(&child_zv, child, state); } - if (child_name) { +#if PHP_VERSION_ID >= 80200 + if (ast_kind == ZEND_AST_ARROW_FUNC && i == 2) { + /* Imitate the native arrow function ast structure used in php 7.4-8.1 for stmts */ + /* (This is still different from regular functions, which have AST_STMT_LIST) */ + /* TODO: In a new node type, remove the ZEND_AST_RETURN node instead. */ + zval tmp; + ast_to_zval(&tmp, child, state); + ast_create_virtual_node_ex( + &child_zv, ZEND_AST_RETURN, 0, zend_ast_get_lineno(child), state, 1, &tmp); + } +#endif zend_hash_add_new(ht, child_name, &child_zv); } else { zend_hash_next_index_insert(ht, &child_zv); diff --git a/tests/php82_metadata.phpt b/tests/php82_metadata.phpt index bd643e2..0c150ae 100644 --- a/tests/php82_metadata.phpt +++ b/tests/php82_metadata.phpt @@ -28,7 +28,7 @@ dump($metadata); dump_attributes(ast\Node::class); dump_attributes(ast\Metadata::class); --EXPECTF-- -ast\Node::__set_state(array( +%Sast\Node::__set_state(array( 'kind' => NULL, 'flags' => NULL, 'lineno' => NULL, @@ -36,7 +36,7 @@ ast\Node::__set_state(array( 'undeclaredDynamic' => 123, )) Deprecated: Creation of dynamic property ast\Metadata::$undeclaredDynamic is deprecated in %sphp82_metadata.php on line 21 -ast\Metadata::__set_state(array( +%Sast\Metadata::__set_state(array( 'kind' => NULL, 'name' => NULL, 'flags' => NULL, From 91f59467f9dce2e5718bd052277926a3039c9f6e Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 7 Aug 2022 12:20:06 -0400 Subject: [PATCH 19/53] php-ast 1.1.0dev: Deprecate AST versions 50 and 60, drop support for php < 7.2 (#185) * Deprecate AST versions 50 and 60 AST version 70 has been supported since php-ast 1.0.1 (2019-02-11). Related to #114 * Drop support for php <= 7.1 Update documentation to mention this. * Update test expectation for AST version 60 deprecation --- .appveyor.yml | 40 ------------- .github/workflows/main.yml | 6 +- README.md | 18 +++--- ast.c | 73 ++--------------------- package.xml | 9 ++- php_ast.h | 4 +- tests/001.phpt | 3 +- tests/array_destructuring.phpt | 4 +- tests/array_destructuring_old.phpt | 2 +- tests/assign_ops.phpt | 2 +- tests/ast_dump_with_linenos.phpt | 5 +- tests/binary_ops.phpt | 2 +- tests/by_ref_destructuring.phpt | 2 +- tests/class.phpt | 71 ++++++++++++++++++++-- tests/class_consts.phpt | 4 +- tests/class_consts_80.phpt | 2 - tests/class_name_version_50.phpt | 1 + tests/class_types.phpt | 2 +- tests/closure_use_vars.phpt | 2 +- tests/coalesce.phpt | 2 +- tests/decl_ids.phpt | 13 ++-- tests/decl_normalization.phpt | 69 +++++++++++++++++++--- tests/empty_file_parse.phpt | 4 +- tests/eval_include.phpt | 2 +- tests/functions_dont_use.phpt | 6 +- tests/generator_flag.phpt | 9 +-- tests/get_supported_versions.phpt | 12 ++-- tests/magic_constants.phpt | 2 +- tests/multi_catch.phpt | 4 +- tests/multiple_final_modifiers.phpt | 2 +- tests/name_node.phpt | 2 +- tests/named_children.phpt | 2 +- tests/nested_stmt_lists.phpt | 2 +- tests/nop_statements.phpt | 2 +- tests/nullable_types.phpt | 7 +-- tests/object_type.phpt | 8 +-- tests/params.phpt | 82 ++++++++++++++++++++++++-- tests/parse_code_parse_error.phpt | 4 +- tests/parse_file.phpt | 2 +- tests/parse_file_not_existing.phpt | 2 +- tests/parse_file_parse_error.phpt | 2 +- tests/php74_type_hints.phpt | 1 + tests/php80_union_types_nullable.phpt | 63 ++++++++++++++++++-- tests/php81_final_class_const.phpt | 4 +- tests/php81_readonly.phpt | 1 + tests/prop_doc_comments.phpt | 36 +++++++++++ tests/short_arrow_function.phpt | 2 + tests/short_arrow_function_return.phpt | 2 + tests/stmt_list.phpt | 2 +- tests/try_catch_finally.phpt | 2 +- tests/type_hints.phpt | 3 +- tests/unary_ops.phpt | 2 +- tests/use_declarations.phpt | 2 +- 53 files changed, 385 insertions(+), 227 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 4e56831..5243ddb 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -69,46 +69,6 @@ environment: VC: vs16 PHP_VER: 8.0.13 TS: 0 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - ARCH: x64 - VC: vc14 - PHP_VER: 7.0.33 - TS: 0 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - ARCH: x64 - VC: vc14 - PHP_VER: 7.0.33 - TS: 1 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - ARCH: x86 - VC: vc14 - PHP_VER: 7.0.33 - TS: 0 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - ARCH: x86 - VC: vc14 - PHP_VER: 7.0.33 - TS: 1 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - ARCH: x64 - VC: vc14 - PHP_VER: 7.1.33 - TS: 0 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - ARCH: x64 - VC: vc14 - PHP_VER: 7.1.33 - TS: 1 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - ARCH: x86 - VC: vc14 - PHP_VER: 7.1.33 - TS: 0 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - ARCH: x86 - VC: vc14 - PHP_VER: 7.1.33 - TS: 1 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ARCH: x64 VC: vc15 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 335dc51..226abac 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,10 +25,8 @@ jobs: fail-fast: false matrix: include: - # NOTE: If this is not quoted, the yaml parser will convert 7.0 to the number 7, - # and the docker image `php:7` is the latest minor version of php 7.x (7.4). - - PHP_VERSION: '7.0' - - PHP_VERSION: '7.1' + # NOTE: If this is not quoted, the yaml parser will convert 8.0 to the number 8, + # and the docker image `php:8` is the latest minor version of php 8.x (8.1). - PHP_VERSION: '7.2' - PHP_VERSION: '7.3' - PHP_VERSION: '7.4' diff --git a/README.md b/README.md index 92c3e05..09f1179 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ php-ast ======= -This extension exposes the abstract syntax tree generated by PHP 7. +This extension exposes the abstract syntax tree generated by PHP 7 and 8. -**This is the documentation for version 1.0.x. See also [documentation for version 0.1.x][v0_1_x].** +**This is the documentation for version 1.x.y. See also [documentation for version 0.1.x][v0_1_x].** Table of Contents ----------------- @@ -529,18 +529,20 @@ Supported since 1.0.1 (2019-02-11). Note that property group type information is only available with AST versions 70+. * `AST_CLASS_NAME` is created instead of `AST_CLASS_CONST` for `SomeClass::class`. -### 60 (stable) +### 60 (deprecated) Supported since 0.1.7 (2018-10-06). +Deprecated in php-ast 1.1.0. * `AST_FUNC_DECL` and `AST_METHOD` no longer generate a `uses` child. Previously this child was always `null`. * `AST_CONST_ELEM` now always has a `docComment` child. Previously it was absent on PHP 7.0. On PHP 7.0 the value is always `null`. -### 50 (stable) +### 50 (deprecated) Supported since 0.1.5 (2017-07-19). +Deprecated in php-ast 1.1.0. This is the oldest AST version available in 1.0.0. See the [0.1.x AST version changelog][v0_1_x_versions] for information on changes prior to this version. @@ -553,7 +555,7 @@ this extension. This section summarizes the main differences between php-ast and may decide which is preferable for your use-case. The primary difference is that php-ast is a PHP extension (written in C) which exports the AST -internally used by PHP 7. PHP-Parser on the other hand is library written in PHP. This has a number +internally used by PHP 7 and 8. PHP-Parser on the other hand is library written in PHP. This has a number of consequences: * php-ast is significantly faster than PHP-Parser, because the AST construction is implemented in @@ -561,11 +563,11 @@ of consequences: * php-ast needs to be installed as an extension, on Linux either by compiling it manually or retrieving it from a package manager, on Windows by loading a DLL. PHP-Parser is installed as a Composer dependency. - * php-ast only runs on PHP >= 7.0, as prior versions did not use an internal AST. PHP-Parser + * php-ast only runs on PHP >= 7.0 (php-ast 1.0.16 was the last version supporting php <= 7.1), as prior versions did not use an internal AST. PHP-Parser supports PHP >= 5.5. * php-ast may only parse code that is syntactically valid on the version of PHP it runs on. This - means that it's not possible to parse code using features of newer versions (e.g. PHP 7.1 code - while running on PHP 7.0). Similarly, it is not possible to parse code that is no longer + means that it's not possible to parse code using features of newer versions (e.g. PHP 7.4 code + while running on PHP 7.2). Similarly, it is not possible to parse code that is no longer syntactically valid on the used version (e.g. some PHP 5 code may no longer be parsed -- however most code will work). PHP-Parser supports parsing both newer and older (up to PHP 5.2) versions. * php-ast can only parse code which is syntactically valid, while PHP-Parser can provide a partial diff --git a/ast.c b/ast.c index 8d6a068..6c69f70 100644 --- a/ast.c +++ b/ast.c @@ -19,6 +19,10 @@ #include "zend_attributes.h" #endif +#if PHP_VERSION_ID < 70200 +#error "The php-ast 1.1 release dropped support for php 7.0-7.1. Use php-ast 1.0.16 instead." +#endif + #ifndef ZEND_THIS #define ZEND_THIS getThis() #endif @@ -27,12 +31,6 @@ #define ZEND_ARG_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, default_value) \ ZEND_ARG_INFO(pass_by_ref, name) #endif -#if PHP_VERSION_ID < 70200 -#undef ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX -#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \ - static const zend_internal_arg_info name[] = { \ - { (const char*)(zend_uintptr_t)(required_num_args), ( #class_name ), 0, return_reference, allow_null, 0 }, -#endif #ifndef ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX #define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \ @@ -87,16 +85,6 @@ #define AST_PLUS 261 #define AST_MINUS 262 -/* Define some compatibility constants */ -#if PHP_VERSION_ID < 70100 -# define IS_VOID 18 -# define IS_ITERABLE 19 -# define ZEND_TYPE_NULLABLE (1<<8) -# define ZEND_ARRAY_SYNTAX_LIST 1 -# define ZEND_ARRAY_SYNTAX_LONG 2 -# define ZEND_ARRAY_SYNTAX_SHORT 3 -#endif - #if PHP_VERSION_ID < 70300 # define ZEND_BIND_REF 1 #endif @@ -764,16 +752,6 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t } } #endif -#endif - /* This AST_CATCH check should occur before ast_is_name() */ -#if PHP_VERSION_ID < 70100 - if (ast_kind == ZEND_AST_CATCH && i == 0) { - /* Emulate PHP 7.1 format (name list) */ - zval tmp; - ast_create_virtual_node(&tmp, AST_NAME, child->attr, child, state); - ast_create_virtual_node_ex( - &child_zv, ZEND_AST_NAME_LIST, 0, zend_ast_get_lineno(child), state, 1, &tmp); - } else #endif if (ast_is_name(child, ast, i)) { ast_name_to_zval(child, ast, &child_zv, i, state); @@ -803,21 +781,9 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t /* Skip "uses" child since it is always empty */ continue; #endif -#if PHP_VERSION_ID >= 70100 } else if (ast_kind == ZEND_AST_LIST && child != NULL) { /* Emulate simple variable list */ ast_to_zval(&child_zv, child->child[0], state); -#else - } else if (ast_kind == ZEND_AST_ARRAY - && ast->attr == ZEND_ARRAY_SYNTAX_LIST && child != NULL) { - /* Emulate ARRAY_ELEM list */ - zval ch0, ch1; - ast_to_zval(&ch0, child, state); - ZVAL_NULL(&ch1); - ast_create_virtual_node_ex( - &child_zv, ZEND_AST_ARRAY_ELEM, 0, zend_ast_get_lineno(child), state, - 2, &ch0, &ch1); -#endif } else { ast_to_zval(&child_zv, child, state); } @@ -840,15 +806,6 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t } -#if PHP_VERSION_ID < 70100 - /* Emulate docComment on constants, which is not available in PHP 7.0 */ - if (state->version >= 60 && ast_kind == ZEND_AST_CONST_ELEM) { - zval tmp; - ZVAL_NULL(&tmp); - zend_hash_add_new(ht, AST_STR(str_docComment), &tmp); - return; - } -#endif #if PHP_VERSION_ID < 80000 if (state->version >= 80) { if (ast_kind == ZEND_AST_PARAM) { @@ -1020,14 +977,6 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { #endif } -#if PHP_VERSION_ID < 70100 - /* Normalize to PHP 7.1 format */ - if (ast->kind == ZEND_AST_LIST) { - ast->kind = ZEND_AST_ARRAY; - ast->attr = ZEND_ARRAY_SYNTAX_LIST; - } -#endif - object_init_ex(zv, ast_node_ce); zend_object *obj = Z_OBJ_P(zv); @@ -1065,11 +1014,6 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { zend_hash_add_new(children, AST_STR(str_docComment), &tmp_zv); } else { -#if PHP_VERSION_ID < 70100 - if (ast->kind == ZEND_AST_CLASS_CONST_DECL) { - ast->attr = ZEND_ACC_PUBLIC; - } -#endif AST_NODE_SET_PROP_FLAGS(obj, ast->attr); } @@ -1110,8 +1054,7 @@ static const zend_long versions[] = {50, 60, 70, 80, 85, 90}; static const size_t versions_count = sizeof(versions)/sizeof(versions[0]); static inline zend_bool ast_version_deprecated(zend_long version) { - /* Currently no deprecated versions */ - return 0; + return version < 70; } static zend_string *ast_version_info() { @@ -1512,15 +1455,9 @@ PHP_MINIT_FUNCTION(ast) { ast_register_flag_constant("EXEC_REQUIRE", ZEND_REQUIRE); ast_register_flag_constant("EXEC_REQUIRE_ONCE", ZEND_REQUIRE_ONCE); -#if PHP_VERSION_ID >= 70200 ast_register_flag_constant("USE_NORMAL", ZEND_SYMBOL_CLASS); ast_register_flag_constant("USE_FUNCTION", ZEND_SYMBOL_FUNCTION); ast_register_flag_constant("USE_CONST", ZEND_SYMBOL_CONST); -#else - ast_register_flag_constant("USE_NORMAL", T_CLASS); - ast_register_flag_constant("USE_FUNCTION", T_FUNCTION); - ast_register_flag_constant("USE_CONST", T_CONST); -#endif ast_register_flag_constant("MAGIC_LINE", T_LINE); ast_register_flag_constant("MAGIC_FILE", T_FILE); diff --git a/package.xml b/package.xml index 3e538e6..05bc3e2 100644 --- a/package.xml +++ b/package.xml @@ -20,8 +20,8 @@ 2022-02-12 - 1.0.17dev - 1.0.17dev + 1.1.0dev + 1.1.0dev stable @@ -30,6 +30,8 @@ BSD-3-Clause - Change documentation files to properly namespace attributes as `#[\AllowDynamicProperties]`. The reflection attributes are already correct. +- Deprecated AST versions 50 and 60. +- Drop support for php <= 7.1 @@ -133,7 +135,7 @@ - 7.0.0 + 7.2.0 1.10.0 @@ -157,6 +159,7 @@ - Optimize instantiating properties of ast\Node and ast\Metadata. - Document that ast\Node implements `#[AllowDynamicProperties]` in php 8.2 +- Allow ast\Node to have dynamic properties without emitting a notice in PHP 8.2. diff --git a/php_ast.h b/php_ast.h index 54d8944..2c522b2 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.17dev" +#define PHP_AST_VERSION "1.1.0dev" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) @@ -82,9 +82,7 @@ extern ast_str_globals str_globals; #endif /* Pretend it still exists */ -#if PHP_VERSION_ID >= 70100 # define ZEND_AST_LIST ((1 << (ZEND_AST_IS_LIST_SHIFT + 1)) - 1) -#endif extern const size_t ast_kinds_count; extern const zend_ast_kind ast_kinds[]; diff --git a/tests/001.phpt b/tests/001.phpt index d2914c1..aaf7e25 100644 --- a/tests/001.phpt +++ b/tests/001.phpt @@ -20,7 +20,7 @@ function test(Type $arg = XYZ) : Ret { } PHP; -echo ast_dump(ast\parse_code($code, $version=50)); +echo ast_dump(ast\parse_code($code, $version=70)); --EXPECT-- AST_STMT_LIST 0: AST_FUNC_DECL @@ -38,7 +38,6 @@ AST_STMT_LIST name: AST_NAME flags: NAME_NOT_FQ (1) name: "XYZ" - uses: null stmts: AST_STMT_LIST 0: AST_IF 0: AST_IF_ELEM diff --git a/tests/array_destructuring.phpt b/tests/array_destructuring.phpt index be73b6a..b64c4c7 100644 --- a/tests/array_destructuring.phpt +++ b/tests/array_destructuring.phpt @@ -1,7 +1,5 @@ --TEST-- Array destructuring ---SKIPIF-- -= 7.1 only'); ?> --FILE-- $a, 'bar' => $b) = $x; [, [$a]] = $x; PHP; -echo ast_dump(ast\parse_code($code, $version=50)); +echo ast_dump(ast\parse_code($code, $version=70)); ?> --EXPECT-- diff --git a/tests/array_destructuring_old.phpt b/tests/array_destructuring_old.phpt index e1f25cb..c0e55a0 100644 --- a/tests/array_destructuring_old.phpt +++ b/tests/array_destructuring_old.phpt @@ -11,7 +11,7 @@ list($a, $b) = $x; list(, $b) = $x; PHP; -echo ast_dump(ast\parse_code($code, $version=50)); +echo ast_dump(ast\parse_code($code, $version=70)); ?> --EXPECTF-- diff --git a/tests/assign_ops.phpt b/tests/assign_ops.phpt index 0c53290..956538f 100644 --- a/tests/assign_ops.phpt +++ b/tests/assign_ops.phpt @@ -21,7 +21,7 @@ $a <<= $b; $a >>= $b; PHP; -echo ast_dump(ast\parse_code($code, $version=50)), "\n"; +echo ast_dump(ast\parse_code($code, $version=70)), "\n"; ?> --EXPECTF-- diff --git a/tests/ast_dump_with_linenos.phpt b/tests/ast_dump_with_linenos.phpt index 29f6210..d67ccb7 100644 --- a/tests/ast_dump_with_linenos.phpt +++ b/tests/ast_dump_with_linenos.phpt @@ -3,8 +3,6 @@ ast_dump() with AST_DUMP_LINENOS --SKIPIF-- = 70000 && PHP_VERSION_ID < 70018) print "skip buggy PHP version"; -if (PHP_VERSION_ID >= 70100 && PHP_VERSION_ID < 70104) print "skip buggy PHP version"; ?> --FILE-- @@ -34,7 +32,6 @@ AST_STMT_LIST @ 1 name: "test" docComment: null params: AST_PARAM_LIST @ 4 - uses: null stmts: AST_STMT_LIST @ 5 0: AST_CALL @ 6 expr: AST_NAME @ 6 diff --git a/tests/binary_ops.phpt b/tests/binary_ops.phpt index ab916d0..f94d510 100644 --- a/tests/binary_ops.phpt +++ b/tests/binary_ops.phpt @@ -13,7 +13,7 @@ $a and $b; $a or $b; PHP; -echo ast_dump(ast\parse_code($code, $version=50)), "\n"; +echo ast_dump(ast\parse_code($code, $version=70)), "\n"; ?> --EXPECT-- diff --git a/tests/by_ref_destructuring.phpt b/tests/by_ref_destructuring.phpt index 1937339..c6bed76 100644 --- a/tests/by_ref_destructuring.phpt +++ b/tests/by_ref_destructuring.phpt @@ -13,7 +13,7 @@ list($a, &$b) = $c; [$a, &$b] = $c; $c = [$a, &$b]; PHP; -echo ast_dump(ast\parse_code($code, $version=50)), "\n"; +echo ast_dump(ast\parse_code($code, $version=70)), "\n"; ?> --EXPECT-- diff --git a/tests/class.phpt b/tests/class.phpt index cba75fe..4ac74ce 100644 --- a/tests/class.phpt +++ b/tests/class.phpt @@ -15,33 +15,35 @@ class A extends B implements D, E { } PHP; -echo ast_dump(ast\parse_code($code, $version=60)); +echo ast_dump(ast\parse_code($code, $version=60)), "\n"; +echo ast_dump(ast\parse_code($code, $version=70)), "\n"; ?> --EXPECTF-- +Deprecated: ast\parse_code(): Version 60 is deprecated in %sclass.php on line 15 AST_STMT_LIST 0: AST_CLASS flags: 0 name: "A" docComment: null extends: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "B" implements: AST_NAME_LIST 0: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "D" 1: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "E" stmts: AST_STMT_LIST 0: AST_USE_TRAIT traits: AST_NAME_LIST 0: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "T" 1: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "S" adaptations: null 1: AST_CLASS_CONST_DECL @@ -73,3 +75,60 @@ AST_STMT_LIST returnType: null __declId: 0 __declId: 1 +AST_STMT_LIST + 0: AST_CLASS + flags: 0 + name: "A" + docComment: null + extends: AST_NAME + flags: NAME_NOT_FQ (%d) + name: "B" + implements: AST_NAME_LIST + 0: AST_NAME + flags: NAME_NOT_FQ (%d) + name: "D" + 1: AST_NAME + flags: NAME_NOT_FQ (%d) + name: "E" + stmts: AST_STMT_LIST + 0: AST_USE_TRAIT + traits: AST_NAME_LIST + 0: AST_NAME + flags: NAME_NOT_FQ (%d) + name: "T" + 1: AST_NAME + flags: NAME_NOT_FQ (%d) + name: "S" + adaptations: null + 1: AST_CLASS_CONST_DECL + flags: MODIFIER_PUBLIC (%d) + 0: AST_CONST_ELEM + name: "X" + value: "Y" + docComment: null + 1: AST_CONST_ELEM + name: "Y" + value: "X" + docComment: null + 2: AST_PROP_GROUP + flags: MODIFIER_PUBLIC (%d) + type: null + props: AST_PROP_DECL + flags: 0 + 0: AST_PROP_ELEM + name: "foo" + default: null + docComment: null + 1: AST_PROP_ELEM + name: "bar" + default: null + docComment: null + 3: AST_METHOD + flags: MODIFIER_PUBLIC | MODIFIER_ABSTRACT (%d) + name: "test" + docComment: null + params: AST_PARAM_LIST + stmts: null + returnType: null + __declId: 0 + __declId: 1 \ No newline at end of file diff --git a/tests/class_consts.phpt b/tests/class_consts.phpt index a23f8a7..c097b73 100644 --- a/tests/class_consts.phpt +++ b/tests/class_consts.phpt @@ -1,7 +1,5 @@ --TEST-- Class constants ---SKIPIF-- -= 7.1 only'); ?> --FILE-- --EXPECTF-- diff --git a/tests/class_consts_80.phpt b/tests/class_consts_80.phpt index d64bc64..59b7786 100644 --- a/tests/class_consts_80.phpt +++ b/tests/class_consts_80.phpt @@ -1,7 +1,5 @@ --TEST-- Class constants in AST version 80 ---SKIPIF-- -= 7.1 only'); ?> --FILE-- --EXPECTF-- +Deprecated: ast\parse_code(): Version 50 is deprecated in %s.php on line 13 AST_STMT_LIST 0: AST_NAMESPACE name: "Foo" diff --git a/tests/class_types.phpt b/tests/class_types.phpt index 34b8963..5f91c96 100644 --- a/tests/class_types.phpt +++ b/tests/class_types.phpt @@ -15,7 +15,7 @@ interface E {} new class {}; PHP; -echo ast_dump(ast\parse_code($code, $version=50)); +echo ast_dump(ast\parse_code($code, $version=70)); ?> --EXPECTF-- diff --git a/tests/closure_use_vars.phpt b/tests/closure_use_vars.phpt index 5777e80..63bd194 100644 --- a/tests/closure_use_vars.phpt +++ b/tests/closure_use_vars.phpt @@ -10,7 +10,7 @@ $code = <<<'PHP' $fn = static function &($a, &$b) use ($c, &$d) { }; PHP; -echo ast_dump(ast\parse_code($code, $version=50)); +echo ast_dump(ast\parse_code($code, $version=70)); ?> --EXPECTF-- diff --git a/tests/coalesce.phpt b/tests/coalesce.phpt index 376f126..fef5bbe 100644 --- a/tests/coalesce.phpt +++ b/tests/coalesce.phpt @@ -10,7 +10,7 @@ $code = <<<'PHP' $a ?? $b; PHP; -echo ast_dump(ast\parse_code($code, $version=50)), "\n"; +echo ast_dump(ast\parse_code($code, $version=70)), "\n"; ?> --EXPECT-- diff --git a/tests/decl_ids.phpt b/tests/decl_ids.phpt index d9a7c19..c82d626 100644 --- a/tests/decl_ids.phpt +++ b/tests/decl_ids.phpt @@ -12,10 +12,11 @@ function test() {} function test() {} class Test {} class Test{} PHP; echo ast_dump(ast\parse_code($code, $version=50)) . "\n"; -echo ast_dump(ast\parse_code($code, $version=50)) . "\n"; +echo ast_dump(ast\parse_code($code, $version=80)) . "\n"; ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ast\parse_code(): Version 50 is deprecated in %s.php on line 11 AST_STMT_LIST 0: AST_CLOSURE flags: 0 @@ -78,6 +79,7 @@ AST_STMT_LIST uses: null stmts: AST_STMT_LIST returnType: null + attributes: null __declId: 0 1: AST_CLOSURE flags: 0 @@ -87,24 +89,25 @@ AST_STMT_LIST uses: null stmts: AST_STMT_LIST returnType: null + attributes: null __declId: 1 2: AST_FUNC_DECL flags: 0 name: "test" docComment: null params: AST_PARAM_LIST - uses: null stmts: AST_STMT_LIST returnType: null + attributes: null __declId: 2 3: AST_FUNC_DECL flags: 0 name: "test" docComment: null params: AST_PARAM_LIST - uses: null stmts: AST_STMT_LIST returnType: null + attributes: null __declId: 3 4: AST_CLASS flags: 0 @@ -113,6 +116,7 @@ AST_STMT_LIST extends: null implements: null stmts: AST_STMT_LIST + attributes: null __declId: 4 5: AST_CLASS flags: 0 @@ -121,4 +125,5 @@ AST_STMT_LIST extends: null implements: null stmts: AST_STMT_LIST + attributes: null __declId: 5 diff --git a/tests/decl_normalization.phpt b/tests/decl_normalization.phpt index 32c3b48..bc6a4fc 100644 --- a/tests/decl_normalization.phpt +++ b/tests/decl_normalization.phpt @@ -1,10 +1,5 @@ --TEST-- -As of version 50 Decl is no more ---SKIPIF-- - +The class ast\Node\Decl no longer exists --FILE-- children)); echo ast_dump($ast) . "\n"; +$ast = ast\parse_code($code, $version=50); +echo ast_dump($ast) . "\n"; ?> --EXPECTF-- @@ -47,6 +44,62 @@ array(4) { [3]=> string(8) "ast\Node" } +AST_STMT_LIST + 0: AST_CLASS + flags: 0 + name: "A" + docComment: "/** A */" + extends: null + implements: null + stmts: AST_STMT_LIST + 0: AST_CLASS_CONST_DECL + flags: MODIFIER_PUBLIC (%d) + 0: AST_CONST_ELEM + name: "B" + value: 0 + docComment: "/** B */" + 1: AST_PROP_GROUP + flags: MODIFIER_PUBLIC (%d) + type: null + props: AST_PROP_DECL + flags: 0 + 0: AST_PROP_ELEM + name: "c" + default: null + docComment: "/** c */" + 2: AST_METHOD + flags: MODIFIER_PUBLIC (%d) + name: "d" + docComment: "/** d */" + params: AST_PARAM_LIST + stmts: AST_STMT_LIST + returnType: null + __declId: 0 + __declId: 1 + 1: AST_CONST_DECL + 0: AST_CONST_ELEM + name: "E" + value: 0 + docComment: "/** E */" + 2: AST_FUNC_DECL + flags: 0 + name: "f" + docComment: "/** f */" + params: AST_PARAM_LIST + stmts: AST_STMT_LIST + returnType: null + __declId: 2 + 3: AST_CLOSURE + flags: 0 + name: "{closure}" + docComment: "/** g */" + params: AST_PARAM_LIST + uses: null + stmts: AST_STMT_LIST + returnType: null + __declId: 3 + +Deprecated: ast\parse_code(): Version 50 is deprecated in %sdecl_normalization.php on line 29 AST_STMT_LIST 0: AST_CLASS flags: 0 @@ -99,4 +152,4 @@ AST_STMT_LIST uses: null stmts: AST_STMT_LIST returnType: null - __declId: 3 + __declId: 3 \ No newline at end of file diff --git a/tests/empty_file_parse.phpt b/tests/empty_file_parse.phpt index be85216..ca5f0ce 100644 --- a/tests/empty_file_parse.phpt +++ b/tests/empty_file_parse.phpt @@ -4,10 +4,10 @@ ast\parse_file() with empty file diff --git a/tests/eval_include.phpt b/tests/eval_include.phpt index 5f450b7..4b80a72 100644 --- a/tests/eval_include.phpt +++ b/tests/eval_include.phpt @@ -14,7 +14,7 @@ require 'foo.php'; require_once 'foo.php'; PHP; -echo ast_dump(ast\parse_code($code, $version=50)); +echo ast_dump(ast\parse_code($code, $version=70)); ?> --EXPECT-- diff --git a/tests/functions_dont_use.phpt b/tests/functions_dont_use.phpt index df883c6..c1aa273 100644 --- a/tests/functions_dont_use.phpt +++ b/tests/functions_dont_use.phpt @@ -15,7 +15,9 @@ echo ast_dump(ast\parse_code($code, $version=50)), "\n"; echo ast_dump(ast\parse_code($code, $version=60)), "\n"; ?> ---EXPECT-- +--EXPECTF-- + +Deprecated: ast\parse_code(): Version 50 is deprecated in %s.php on line 11 AST_STMT_LIST 0: AST_CLOSURE flags: 0 @@ -35,6 +37,8 @@ AST_STMT_LIST stmts: AST_STMT_LIST returnType: null __declId: 1 + +Deprecated: ast\parse_code(): Version 60 is deprecated in %s.php on line 12 AST_STMT_LIST 0: AST_CLOSURE flags: 0 diff --git a/tests/generator_flag.phpt b/tests/generator_flag.phpt index 13e529f..230f44e 100644 --- a/tests/generator_flag.phpt +++ b/tests/generator_flag.phpt @@ -1,9 +1,5 @@ --TEST-- -Flag on generator functions in PHP 7.1 ---SKIPIF-- - +Flag on generator functions --FILE-- --EXPECTF-- @@ -26,7 +22,6 @@ AST_STMT_LIST name: "gen" docComment: null params: AST_PARAM_LIST - uses: null stmts: AST_STMT_LIST 0: AST_YIELD value: null diff --git a/tests/get_supported_versions.phpt b/tests/get_supported_versions.phpt index bb664bb..2384f37 100644 --- a/tests/get_supported_versions.phpt +++ b/tests/get_supported_versions.phpt @@ -22,17 +22,13 @@ array(6) { [5]=> int(90) } -array(6) { +array(4) { [0]=> - int(50) - [1]=> - int(60) - [2]=> int(70) - [3]=> + [1]=> int(80) - [4]=> + [2]=> int(85) - [5]=> + [3]=> int(90) } \ No newline at end of file diff --git a/tests/magic_constants.phpt b/tests/magic_constants.phpt index 175d772..039d22f 100644 --- a/tests/magic_constants.phpt +++ b/tests/magic_constants.phpt @@ -17,7 +17,7 @@ __CLASS__; __TRAIT__; PHP; -echo ast_dump(ast\parse_code($code, $version=50)); +echo ast_dump(ast\parse_code($code, $version=70)); ?> --EXPECTF-- diff --git a/tests/multi_catch.phpt b/tests/multi_catch.phpt index 13edb45..724e7e7 100644 --- a/tests/multi_catch.phpt +++ b/tests/multi_catch.phpt @@ -1,7 +1,5 @@ --TEST-- Multi catch ---SKIPIF-- -= 7.1 only'); ?> --FILE-- --EXPECT-- diff --git a/tests/multiple_final_modifiers.phpt b/tests/multiple_final_modifiers.phpt index e85e3b6..29d94e5 100644 --- a/tests/multiple_final_modifiers.phpt +++ b/tests/multiple_final_modifiers.phpt @@ -12,7 +12,7 @@ $code = <<<'PHP' PHP; try { - ast\parse_code($code, $version=50); + ast\parse_code($code, $version=70); } catch (CompileError $e) { echo $e->getMessage(), "\n"; } diff --git a/tests/name_node.phpt b/tests/name_node.phpt index 6b45ab9..2bcfae8 100644 --- a/tests/name_node.phpt +++ b/tests/name_node.phpt @@ -13,7 +13,7 @@ foo(); ('\foo')(); PHP; -echo ast_dump(ast\parse_code($code, $version=50)), "\n"; +echo ast_dump(ast\parse_code($code, $version=70)), "\n"; ?> --EXPECT-- diff --git a/tests/named_children.phpt b/tests/named_children.phpt index 7fc9ee2..ca1c7e2 100644 --- a/tests/named_children.phpt +++ b/tests/named_children.phpt @@ -13,7 +13,7 @@ $fn = function() use(&$var) { }; PHP; -echo ast_dump(ast\parse_code($code, $version=50)); +echo ast_dump(ast\parse_code($code, $version=70)); ?> --EXPECT-- diff --git a/tests/nested_stmt_lists.phpt b/tests/nested_stmt_lists.phpt index 2ad95d1..8e0332c 100644 --- a/tests/nested_stmt_lists.phpt +++ b/tests/nested_stmt_lists.phpt @@ -22,7 +22,7 @@ $a; $g; PHP; -echo ast_dump(ast\parse_code($code, $version=50)), "\n"; +echo ast_dump(ast\parse_code($code, $version=70)), "\n"; ?> --EXPECT-- diff --git a/tests/nop_statements.phpt b/tests/nop_statements.phpt index 84c27e9..65321f9 100644 --- a/tests/nop_statements.phpt +++ b/tests/nop_statements.phpt @@ -12,7 +12,7 @@ $a; $b; PHP; -echo ast_dump(ast\parse_code($code, $version=50)), "\n"; +echo ast_dump(ast\parse_code($code, $version=70)), "\n"; ?> --EXPECT-- diff --git a/tests/nullable_types.phpt b/tests/nullable_types.phpt index 945f3b5..691364d 100644 --- a/tests/nullable_types.phpt +++ b/tests/nullable_types.phpt @@ -1,7 +1,5 @@ --TEST-- Nullable types ---SKIPIF-- -= 7.1 only'); ?> --FILE-- --EXPECT-- @@ -35,7 +33,6 @@ AST_STMT_LIST name: "Foo" name: "foo" default: null - uses: null stmts: AST_STMT_LIST returnType: AST_NULLABLE_TYPE type: AST_NAME @@ -54,7 +51,6 @@ AST_STMT_LIST flags: TYPE_LONG (4) name: "foo" default: null - uses: null stmts: AST_STMT_LIST returnType: AST_NULLABLE_TYPE type: AST_TYPE @@ -72,7 +68,6 @@ AST_STMT_LIST flags: TYPE_ARRAY (7) name: "foo" default: null - uses: null stmts: AST_STMT_LIST returnType: AST_NULLABLE_TYPE type: AST_TYPE diff --git a/tests/object_type.phpt b/tests/object_type.phpt index 858c289..28f3243 100644 --- a/tests/object_type.phpt +++ b/tests/object_type.phpt @@ -10,10 +10,10 @@ $code = <<<'PHP' function test(object $obj) : object {} PHP; -echo ast_dump(ast\parse_code($code, $version=60)); +echo ast_dump(ast\parse_code($code, $version=70)); ?> ---EXPECT-- +--EXPECTF-- AST_STMT_LIST 0: AST_FUNC_DECL flags: 0 @@ -23,10 +23,10 @@ AST_STMT_LIST 0: AST_PARAM flags: 0 type: AST_TYPE - flags: TYPE_OBJECT (8) + flags: TYPE_OBJECT (%d) name: "obj" default: null stmts: AST_STMT_LIST returnType: AST_TYPE - flags: TYPE_OBJECT (8) + flags: TYPE_OBJECT (%d) __declId: 0 diff --git a/tests/params.phpt b/tests/params.phpt index b9cb5a6..30f3f7a 100644 --- a/tests/params.phpt +++ b/tests/params.phpt @@ -12,7 +12,8 @@ function test2(&$a, &...$b) {} function test3(array &$a, array &...$b) {} PHP; -echo ast_dump(ast\parse_code($code, $version=50)), "\n"; +echo ast_dump(ast\parse_code($code, $version=70)), "\n"; +echo ast_dump(ast\parse_code($code, $version=80)), "\n"; ?> --EXPECTF-- @@ -32,7 +33,6 @@ AST_STMT_LIST type: null name: "b" default: null - uses: null stmts: AST_STMT_LIST returnType: null __declId: 0 @@ -51,7 +51,6 @@ AST_STMT_LIST type: null name: "b" default: null - uses: null stmts: AST_STMT_LIST returnType: null __declId: 1 @@ -63,16 +62,87 @@ AST_STMT_LIST 0: AST_PARAM flags: PARAM_REF (%d) type: AST_TYPE - flags: TYPE_ARRAY (7) + flags: TYPE_ARRAY (%d) name: "a" default: null 1: AST_PARAM flags: PARAM_REF | PARAM_VARIADIC (%d) type: AST_TYPE - flags: TYPE_ARRAY (7) + flags: TYPE_ARRAY (%d) name: "b" default: null - uses: null stmts: AST_STMT_LIST returnType: null __declId: 2 +AST_STMT_LIST + 0: AST_FUNC_DECL + flags: 0 + name: "test" + docComment: null + params: AST_PARAM_LIST + 0: AST_PARAM + flags: 0 + type: null + name: "a" + default: null + attributes: null + docComment: null + 1: AST_PARAM + flags: PARAM_VARIADIC (%d) + type: null + name: "b" + default: null + attributes: null + docComment: null + stmts: AST_STMT_LIST + returnType: null + attributes: null + __declId: 0 + 1: AST_FUNC_DECL + flags: 0 + name: "test2" + docComment: null + params: AST_PARAM_LIST + 0: AST_PARAM + flags: PARAM_REF (%d) + type: null + name: "a" + default: null + attributes: null + docComment: null + 1: AST_PARAM + flags: PARAM_REF | PARAM_VARIADIC (%d) + type: null + name: "b" + default: null + attributes: null + docComment: null + stmts: AST_STMT_LIST + returnType: null + attributes: null + __declId: 1 + 2: AST_FUNC_DECL + flags: 0 + name: "test3" + docComment: null + params: AST_PARAM_LIST + 0: AST_PARAM + flags: PARAM_REF (%d) + type: AST_TYPE + flags: TYPE_ARRAY (%d) + name: "a" + default: null + attributes: null + docComment: null + 1: AST_PARAM + flags: PARAM_REF | PARAM_VARIADIC (%d) + type: AST_TYPE + flags: TYPE_ARRAY (%d) + name: "b" + default: null + attributes: null + docComment: null + stmts: AST_STMT_LIST + returnType: null + attributes: null + __declId: 2 \ No newline at end of file diff --git a/tests/parse_code_parse_error.phpt b/tests/parse_code_parse_error.phpt index d82c043..711da99 100644 --- a/tests/parse_code_parse_error.phpt +++ b/tests/parse_code_parse_error.phpt @@ -6,12 +6,12 @@ ast\parse_code() throwing a ParseError $code = ' diff --git a/tests/parse_file_not_existing.phpt b/tests/parse_file_not_existing.phpt index ae89f25..38f9ed1 100644 --- a/tests/parse_file_not_existing.phpt +++ b/tests/parse_file_not_existing.phpt @@ -4,7 +4,7 @@ ast\parse_file() on file that does not exist --EXPECTF-- +Deprecated: ast\parse_code(): Version 60 is deprecated in %s.php on line 18 The type property should not be set in version 60 AST_STMT_LIST 0: AST_NAMESPACE diff --git a/tests/php80_union_types_nullable.phpt b/tests/php80_union_types_nullable.phpt index d8b3134..ce22607 100644 --- a/tests/php80_union_types_nullable.phpt +++ b/tests/php80_union_types_nullable.phpt @@ -19,9 +19,12 @@ class X { } PHP; +$node = ast\parse_code($code, $version=50); +echo ast_dump($node), "\n"; $node = ast\parse_code($code, $version=70); echo ast_dump($node), "\n"; --EXPECTF-- +Deprecated: ast\parse_code(): Version 50 is deprecated in %s.php on line 17 AST_STMT_LIST 0: AST_FUNC_DECL flags: 0 @@ -32,14 +35,66 @@ AST_STMT_LIST flags: 0 type: AST_NULLABLE_TYPE type: AST_TYPE - flags: TYPE_ARRAY (%d) + flags: TYPE_ARRAY (7) name: "a" default: null 1: AST_PARAM flags: 0 type: AST_NULLABLE_TYPE type: AST_TYPE - flags: TYPE_OBJECT (%d) + flags: TYPE_OBJECT (8) + name: "o" + default: null + uses: null + stmts: AST_STMT_LIST + 0: AST_RETURN + expr: AST_CONST + name: AST_NAME + flags: NAME_NOT_FQ (1) + name: "null" + returnType: AST_NULLABLE_TYPE + type: AST_NAME + flags: NAME_FQ (0) + name: "stdClass" + __declId: 0 + 1: AST_CLASS + flags: 0 + name: "X" + docComment: null + extends: null + implements: null + stmts: AST_STMT_LIST + 0: AST_PROP_DECL + flags: MODIFIER_PUBLIC (1) + 0: AST_PROP_ELEM + name: "arr" + default: null + docComment: null + 1: AST_PROP_DECL + flags: MODIFIER_PUBLIC (1) + 0: AST_PROP_ELEM + name: "obj" + default: null + docComment: null + __declId: 1 +AST_STMT_LIST + 0: AST_FUNC_DECL + flags: 0 + name: "test" + docComment: null + params: AST_PARAM_LIST + 0: AST_PARAM + flags: 0 + type: AST_NULLABLE_TYPE + type: AST_TYPE + flags: TYPE_ARRAY (7) + name: "a" + default: null + 1: AST_PARAM + flags: 0 + type: AST_NULLABLE_TYPE + type: AST_TYPE + flags: TYPE_OBJECT (8) name: "o" default: null stmts: AST_STMT_LIST @@ -64,7 +119,7 @@ AST_STMT_LIST flags: MODIFIER_PUBLIC (1) type: AST_NULLABLE_TYPE type: AST_TYPE - flags: TYPE_ARRAY (%d) + flags: TYPE_ARRAY (7) props: AST_PROP_DECL flags: 0 0: AST_PROP_ELEM @@ -83,4 +138,4 @@ AST_STMT_LIST name: "obj" default: null docComment: null - __declId: 1 + __declId: 1 \ No newline at end of file diff --git a/tests/php81_final_class_const.phpt b/tests/php81_final_class_const.phpt index 4612388..f1dbf71 100644 --- a/tests/php81_final_class_const.phpt +++ b/tests/php81_final_class_const.phpt @@ -1,7 +1,5 @@ --TEST-- -Final class constants in php 8.1 ---SKIPIF-- - +Final class constants --FILE-- --EXPECTF-- +Deprecated: ast\parse_code(): Version 50 is deprecated in %s.php on line 20 AST_STMT_LIST 0: AST_CLASS flags: 0 @@ -49,3 +51,37 @@ AST_STMT_LIST default: null docComment: "/** docComment $c */" __declId: 0 +AST_STMT_LIST + 0: AST_CLASS + flags: 0 + name: "A" + docComment: null + extends: null + implements: null + stmts: AST_STMT_LIST + 0: AST_PROP_GROUP + flags: MODIFIER_PUBLIC (%d) + type: null + props: AST_PROP_DECL + flags: 0 + 0: AST_PROP_ELEM + name: "a" + default: null + docComment: "/** docComment $a */" + attributes: null + 1: AST_PROP_GROUP + flags: MODIFIER_PUBLIC (%d) + type: null + props: AST_PROP_DECL + flags: 0 + 0: AST_PROP_ELEM + name: "b" + default: null + docComment: "/** docComment $b */" + 1: AST_PROP_ELEM + name: "c" + default: null + docComment: "/** docComment $c */" + attributes: null + attributes: null + __declId: 0 \ No newline at end of file diff --git a/tests/short_arrow_function.phpt b/tests/short_arrow_function.phpt index 02c50ab..57d322e 100644 --- a/tests/short_arrow_function.phpt +++ b/tests/short_arrow_function.phpt @@ -100,4 +100,6 @@ AST_STMT_LIST key: null returnType: null __declId: 3 + +Deprecated: ast\parse_code(): Version 50 is deprecated in %s.php on line 17 Same representation in version 50/70: true \ No newline at end of file diff --git a/tests/short_arrow_function_return.phpt b/tests/short_arrow_function_return.phpt index 4bf45fc..357689f 100644 --- a/tests/short_arrow_function_return.phpt +++ b/tests/short_arrow_function_return.phpt @@ -96,4 +96,6 @@ AST_STMT_LIST flags: NAME_NOT_FQ (1) name: "stdClass" __declId: 3 + +Deprecated: ast\parse_code(): Version 50 is deprecated in %s.php on line 16 Same representation in version 50/70: true \ No newline at end of file diff --git a/tests/stmt_list.phpt b/tests/stmt_list.phpt index 2bd943d..cb44a2f 100644 --- a/tests/stmt_list.phpt +++ b/tests/stmt_list.phpt @@ -15,7 +15,7 @@ declare(ticks=1); declare(ticks=1) {} PHP; -echo ast_dump(ast\parse_code($code, $version=60)), "\n"; +echo ast_dump(ast\parse_code($code, $version=70)), "\n"; ?> --EXPECT-- diff --git a/tests/try_catch_finally.phpt b/tests/try_catch_finally.phpt index 1288428..b89c335 100644 --- a/tests/try_catch_finally.phpt +++ b/tests/try_catch_finally.phpt @@ -18,7 +18,7 @@ try { } PHP; -echo ast_dump(ast\parse_code($code, $version=50)), "\n"; +echo ast_dump(ast\parse_code($code, $version=70)), "\n"; ?> --EXPECT-- diff --git a/tests/type_hints.phpt b/tests/type_hints.phpt index f234985..09fb038 100644 --- a/tests/type_hints.phpt +++ b/tests/type_hints.phpt @@ -13,7 +13,7 @@ function test( } PHP; -echo ast_dump(ast\parse_code($code, $version=50)), "\n"; +echo ast_dump(ast\parse_code($code, $version=70)), "\n"; ?> --EXPECTF-- @@ -72,7 +72,6 @@ AST_STMT_LIST flags: TYPE_ITERABLE (%d) name: "h" default: null - uses: null stmts: AST_STMT_LIST returnType: AST_TYPE flags: TYPE_VOID (%d) diff --git a/tests/unary_ops.phpt b/tests/unary_ops.phpt index 7eabdfb..f62d832 100644 --- a/tests/unary_ops.phpt +++ b/tests/unary_ops.phpt @@ -12,7 +12,7 @@ $code = <<<'PHP' -1; PHP; -echo ast_dump(ast\parse_code($code, $version=50)), "\n"; +echo ast_dump(ast\parse_code($code, $version=70)), "\n"; ?> --EXPECT-- diff --git a/tests/use_declarations.phpt b/tests/use_declarations.phpt index cf0c44f..36d5cf1 100644 --- a/tests/use_declarations.phpt +++ b/tests/use_declarations.phpt @@ -13,7 +13,7 @@ use Foo\{Bar, function bar}; use function foo\{bar, baz}; PHP; -echo ast_dump(ast\parse_code($code, $version=50)); +echo ast_dump(ast\parse_code($code, $version=70)); ?> --EXPECTF-- From e460595bb69f5283be054c56fb99b4cc85bfc2df Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 7 Aug 2022 15:56:04 -0400 Subject: [PATCH 20/53] Add tests, flag constants for php 8.2 readonly classes (#228) * Add tests, flag constants for php 8.2 readonly classes * Address review comments --- README.md | 3 ++- ast.c | 11 +++++++++-- ast_stub.php | 1 + package.xml | 1 + php_ast.h | 4 ++++ tests/metadata.phpt | 2 +- tests/php82_metadata.phpt | 2 +- tests/php82_readonly_class.phpt | 27 +++++++++++++++++++++++++++ 8 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 tests/php82_readonly_class.phpt diff --git a/README.md b/README.md index 09f1179..4037426 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,8 @@ ast\flags\CLASS_FINAL ast\flags\CLASS_TRAIT ast\flags\CLASS_INTERFACE ast\flags\CLASS_ANONYMOUS -ast\flags\CLASS_ENUM +ast\flags\CLASS_ENUM // php 8.1 enums +ast\flags\CLASS_READONLY // php 8.2 readonly classes // Used by ast\AST_PARAM (combinable) ast\flags\PARAM_REF diff --git a/ast.c b/ast.c index 6c69f70..11ac865 100644 --- a/ast.c +++ b/ast.c @@ -147,6 +147,7 @@ static const char *class_flags[] = { AST_FLAG(CLASS_INTERFACE), AST_FLAG(CLASS_ANONYMOUS), AST_FLAG(CLASS_ENUM), + AST_FLAG(CLASS_READONLY), NULL }; @@ -842,7 +843,6 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t } } #endif - ZVAL_LONG(&id_zval, state->declIdCounter); state->declIdCounter++; zend_hash_add_new(ht, AST_STR(str___declId), &id_zval); @@ -990,8 +990,14 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { if (ast_kind_is_decl(ast->kind)) { zend_ast_decl *decl = (zend_ast_decl *) ast; + uint32_t flags = decl->flags; +#if PHP_VERSION_ID >= 80200 + if (ast->kind == ZEND_AST_CLASS) { + flags &= ~ZEND_ACC_NO_DYNAMIC_PROPERTIES; + } +#endif - AST_NODE_SET_PROP_FLAGS(obj, decl->flags); + AST_NODE_SET_PROP_FLAGS(obj, flags); // This is an undeclared dynamic property and has no cache slot. ast_update_property_long(zv, AST_STR(str_endLineno), decl->end_lineno); @@ -1398,6 +1404,7 @@ PHP_MINIT_FUNCTION(ast) { ast_register_flag_constant("CLASS_INTERFACE", ZEND_ACC_INTERFACE); ast_register_flag_constant("CLASS_ANONYMOUS", ZEND_ACC_ANON_CLASS); ast_register_flag_constant("CLASS_ENUM", ZEND_ACC_ENUM); + ast_register_flag_constant("CLASS_READONLY", ZEND_ACC_READONLY_CLASS); ast_register_flag_constant("PARAM_REF", ZEND_PARAM_REF); ast_register_flag_constant("PARAM_VARIADIC", ZEND_PARAM_VARIADIC); diff --git a/ast_stub.php b/ast_stub.php index 8e699bf..b83150b 100644 --- a/ast_stub.php +++ b/ast_stub.php @@ -143,6 +143,7 @@ const CLASS_INTERFACE = 1; const CLASS_ANONYMOUS = 4; const CLASS_ENUM = 268435456; +const CLASS_READONLY = 65536; const PARAM_REF = 8; const PARAM_VARIADIC = 16; const TYPE_NULL = 1; diff --git a/package.xml b/package.xml index 05bc3e2..6b31617 100644 --- a/package.xml +++ b/package.xml @@ -32,6 +32,7 @@ - Change documentation files to properly namespace attributes as `#[\AllowDynamicProperties]`. The reflection attributes are already correct. - Deprecated AST versions 50 and 60. - Drop support for php <= 7.1 +- Add support for php 8.2 readonly classes. Add `ast\flags\CLASS_READONLY` constant. diff --git a/php_ast.h b/php_ast.h index 2c522b2..14f23a7 100644 --- a/php_ast.h +++ b/php_ast.h @@ -81,6 +81,10 @@ extern ast_str_globals str_globals; # define ZEND_AST_TYPE_INTERSECTION ((1 << (ZEND_AST_IS_LIST_SHIFT + 1)) - 6) #endif +#if PHP_VERSION_ID < 80200 +# define ZEND_ACC_READONLY_CLASS (1 << 23) +#endif + /* Pretend it still exists */ # define ZEND_AST_LIST ((1 << (ZEND_AST_IS_LIST_SHIFT + 1)) - 1) diff --git a/tests/metadata.phpt b/tests/metadata.phpt index 92eb2f3..0dad26f 100644 --- a/tests/metadata.phpt +++ b/tests/metadata.phpt @@ -55,7 +55,7 @@ AST_FUNC_DECL: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVA AST_CLOSURE: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY, FUNC_RETURNS_REF, FUNC_GENERATOR] AST_METHOD: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY, FUNC_RETURNS_REF, FUNC_GENERATOR] AST_ARROW_FUNC: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY, FUNC_RETURNS_REF, FUNC_GENERATOR] -AST_CLASS: (combinable) [CLASS_ABSTRACT, CLASS_FINAL, CLASS_TRAIT, CLASS_INTERFACE, CLASS_ANONYMOUS, CLASS_ENUM] +AST_CLASS: (combinable) [CLASS_ABSTRACT, CLASS_FINAL, CLASS_TRAIT, CLASS_INTERFACE, CLASS_ANONYMOUS, CLASS_ENUM, CLASS_READONLY] AST_MAGIC_CONST: [MAGIC_LINE, MAGIC_FILE, MAGIC_DIR, MAGIC_NAMESPACE, MAGIC_FUNCTION, MAGIC_METHOD, MAGIC_CLASS, MAGIC_TRAIT] AST_TYPE: [TYPE_NULL, TYPE_FALSE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED, TYPE_NEVER] AST_CALLABLE_CONVERT: [] diff --git a/tests/php82_metadata.phpt b/tests/php82_metadata.phpt index 0c150ae..046a6df 100644 --- a/tests/php82_metadata.phpt +++ b/tests/php82_metadata.phpt @@ -1,7 +1,7 @@ --TEST-- Dynamic property support in php 8.2+ --SKIPIF-- -=8.2 only'); ?> +=8.2 only'); ?> --FILE-- =8.2 only'); ?> +--FILE-- + Date: Mon, 8 Aug 2022 06:57:45 -0400 Subject: [PATCH 21/53] Fix redundant call to ast_to_zval (#230) I noticed in 1.1.0dev that the __declId did not match a polyfill when short arrow functions were nested. ast_to_zval was already being called on the above lines in ast.c, calling it again would create `ast\Node` instances again. --- ast.c | 2 +- package.xml | 1 + tests/short_arrow_function_decl_id.phpt | 42 +++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 tests/short_arrow_function_decl_id.phpt diff --git a/ast.c b/ast.c index 11ac865..a02e5fb 100644 --- a/ast.c +++ b/ast.c @@ -795,7 +795,7 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t /* (This is still different from regular functions, which have AST_STMT_LIST) */ /* TODO: In a new node type, remove the ZEND_AST_RETURN node instead. */ zval tmp; - ast_to_zval(&tmp, child, state); + ZVAL_COPY_VALUE(&tmp, &child_zv); ast_create_virtual_node_ex( &child_zv, ZEND_AST_RETURN, 0, zend_ast_get_lineno(child), state, 1, &tmp); } diff --git a/package.xml b/package.xml index 6b31617..4105fe7 100644 --- a/package.xml +++ b/package.xml @@ -122,6 +122,7 @@ + diff --git a/tests/short_arrow_function_decl_id.phpt b/tests/short_arrow_function_decl_id.phpt new file mode 100644 index 0000000..3a8d430 --- /dev/null +++ b/tests/short_arrow_function_decl_id.phpt @@ -0,0 +1,42 @@ +--TEST-- +Nested arrow functions in PHP 7.4 +--SKIPIF-- += 7.4 only'); ?> +--FILE-- + fn() => $undef; +PHP; + +$node = ast\parse_code($code, $version=85); +echo ast_dump($node) . "\n"; +?> +--EXPECT-- +AST_STMT_LIST + 0: AST_ASSIGN + var: AST_VAR + name: "cb" + expr: AST_ARROW_FUNC + flags: 0 + name: "{closure}" + docComment: null + params: AST_PARAM_LIST + stmts: AST_RETURN + expr: AST_ARROW_FUNC + flags: 0 + name: "{closure}" + docComment: null + params: AST_PARAM_LIST + stmts: AST_RETURN + expr: AST_VAR + name: "undef" + returnType: null + attributes: null + __declId: 0 + returnType: null + attributes: null + __declId: 1 From e7dceba794ee44b9d3560ccaac1f702a84caa994 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Mon, 8 Aug 2022 07:47:45 -0400 Subject: [PATCH 22/53] Add support for TYPE_TRUE for php 8.2 (#229) * Add support for TYPE_TRUE for php 8.2 https://wiki.php.net/rfc/true-type * Fix test name --- README.md | 1 + ast.c | 3 +++ ast_stub.php | 1 + package.xml | 2 ++ tests/metadata.phpt | 4 ++-- tests/true_type.phpt | 39 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 tests/true_type.phpt diff --git a/README.md b/README.md index 4037426..5df3bd6 100644 --- a/README.md +++ b/README.md @@ -275,6 +275,7 @@ ast\flags\TYPE_ITERABLE ast\flags\TYPE_OBJECT ast\flags\TYPE_NULL // php 8.0 union types ast\flags\TYPE_FALSE // php 8.0 union types +ast\flags\TYPE_TRUE // php 8.2 true type ast\flags\TYPE_STATIC // php 8.0 static return type ast\flags\TYPE_MIXED // php 8.0 mixed type ast\flags\TYPE_NEVER // php 8.1 never type diff --git a/ast.c b/ast.c index a02e5fb..0c2b8c9 100644 --- a/ast.c +++ b/ast.c @@ -163,6 +163,7 @@ static const char *param_flags[] = { static const char *type_flags[] = { AST_FLAG(TYPE_NULL), AST_FLAG(TYPE_FALSE), + AST_FLAG(TYPE_TRUE), AST_FLAG(TYPE_BOOL), AST_FLAG(TYPE_LONG), AST_FLAG(TYPE_DOUBLE), @@ -561,6 +562,7 @@ static const builtin_type_info builtin_types[] = { // {ZEND_STRL("static"), IS_STATIC}, /* Impossible to be parsed before php 8 */ {ZEND_STRL("mixed"), IS_MIXED}, {ZEND_STRL("never"), IS_NEVER}, + {ZEND_STRL("true"), IS_TRUE}, /* PHP 8.2 added the true type */ {NULL, 0, IS_UNDEF} }; static inline zend_uchar lookup_builtin_type(const zend_string *name) { @@ -1411,6 +1413,7 @@ PHP_MINIT_FUNCTION(ast) { ast_register_flag_constant("TYPE_NULL", IS_NULL); ast_register_flag_constant("TYPE_FALSE", IS_FALSE); + ast_register_flag_constant("TYPE_TRUE", IS_TRUE); ast_register_flag_constant("TYPE_BOOL", _IS_BOOL); ast_register_flag_constant("TYPE_LONG", IS_LONG); ast_register_flag_constant("TYPE_DOUBLE", IS_DOUBLE); diff --git a/ast_stub.php b/ast_stub.php index b83150b..04cf9eb 100644 --- a/ast_stub.php +++ b/ast_stub.php @@ -148,6 +148,7 @@ const PARAM_VARIADIC = 16; const TYPE_NULL = 1; const TYPE_FALSE = 2; +const TYPE_TRUE = 3; const TYPE_BOOL = 18; const TYPE_LONG = 4; const TYPE_DOUBLE = 5; diff --git a/package.xml b/package.xml index 4105fe7..e55c1f9 100644 --- a/package.xml +++ b/package.xml @@ -33,6 +33,7 @@ - Deprecated AST versions 50 and 60. - Drop support for php <= 7.1 - Add support for php 8.2 readonly classes. Add `ast\flags\CLASS_READONLY` constant. +- Add support for php 8.2 `true` type. Add `ast\flags\TYPE_TRUE` constant. @@ -124,6 +125,7 @@ + diff --git a/tests/metadata.phpt b/tests/metadata.phpt index 0dad26f..35b5862 100644 --- a/tests/metadata.phpt +++ b/tests/metadata.phpt @@ -57,12 +57,12 @@ AST_METHOD: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, AST_ARROW_FUNC: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY, FUNC_RETURNS_REF, FUNC_GENERATOR] AST_CLASS: (combinable) [CLASS_ABSTRACT, CLASS_FINAL, CLASS_TRAIT, CLASS_INTERFACE, CLASS_ANONYMOUS, CLASS_ENUM, CLASS_READONLY] AST_MAGIC_CONST: [MAGIC_LINE, MAGIC_FILE, MAGIC_DIR, MAGIC_NAMESPACE, MAGIC_FUNCTION, MAGIC_METHOD, MAGIC_CLASS, MAGIC_TRAIT] -AST_TYPE: [TYPE_NULL, TYPE_FALSE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED, TYPE_NEVER] +AST_TYPE: [TYPE_NULL, TYPE_FALSE, TYPE_TRUE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED, TYPE_NEVER] AST_CALLABLE_CONVERT: [] AST_VAR: [] AST_CONST: [] AST_UNPACK: [] -AST_CAST: [TYPE_NULL, TYPE_FALSE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED, TYPE_NEVER] +AST_CAST: [TYPE_NULL, TYPE_FALSE, TYPE_TRUE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED, TYPE_NEVER] AST_EMPTY: [] AST_ISSET: [] AST_SHELL_EXEC: [] diff --git a/tests/true_type.phpt b/tests/true_type.phpt new file mode 100644 index 0000000..26aad58 --- /dev/null +++ b/tests/true_type.phpt @@ -0,0 +1,39 @@ +--TEST-- +'true' type parsing +--FILE-- + Date: Tue, 9 Aug 2022 17:31:45 -0400 Subject: [PATCH 23/53] Add encaps var flags for AST_DIM/AST_VAR for php 8.2 (#227) For https://wiki.php.net/rfc/deprecate_dollar_brace_string_interpolation Closes #224 In util.php: Don't print a 0 flag value for combinable flags For php-ast self-testing, minimize the number of changes in the future when similar combinable flags get added to existing ast var types. --- README.md | 5 +++ ast.c | 20 ++++++++- ast_stub.php | 2 + package.xml | 6 ++- tests/001.phpt | 4 +- tests/array_destructuring.phpt | 2 +- tests/array_destructuring_old.phpt | 6 +-- tests/assign_ops.phpt | 24 +++++----- tests/ast_dump_with_exclude_doc.phpt | 2 - tests/ast_dump_with_linenos.phpt | 7 ++- tests/attributes_01.phpt | 5 --- tests/attributes_02.phpt | 9 ---- tests/by_ref_destructuring.phpt | 2 +- tests/class.phpt | 3 -- tests/class_consts.phpt | 1 - tests/class_consts_80.phpt | 3 -- tests/class_types.phpt | 1 - tests/closure_use_vars.phpt | 5 +-- tests/coalesce.phpt | 6 +-- tests/decl_ids.phpt | 12 ----- tests/decl_normalization.phpt | 7 --- tests/functions_dont_use.phpt | 4 -- tests/metadata.phpt | 4 +- tests/mixed_type.phpt | 4 -- tests/multi_catch.phpt | 2 +- tests/named_children.phpt | 3 +- tests/nested_stmt_lists.phpt | 2 +- tests/never_return_type.phpt | 1 - tests/nullable_types.phpt | 6 --- tests/object_type.phpt | 2 - tests/params.phpt | 8 ---- tests/php74_ast_assign_coalesce.phpt | 3 +- tests/php74_dim_alternative_syntax.phpt | 6 +-- tests/php74_ordinary_class.phpt | 5 --- tests/php74_parenthesized_conditional.phpt | 5 +-- tests/php74_type_hints.phpt | 8 ---- tests/php80_promotion.phpt | 1 - tests/php80_static_type.phpt | 5 +-- tests/php80_union_types.phpt | 30 +++++-------- tests/php80_union_types_false.phpt | 6 --- tests/php80_union_types_nullable.phpt | 10 ----- tests/php81_enums.phpt | 2 - tests/php81_final_class_const.phpt | 3 -- tests/php81_first_class_callable_support.phpt | 4 +- tests/php81_intersection_types.phpt | 4 -- tests/php81_readonly.phpt | 3 -- ... => php82_dynamic_property_attribute.phpt} | 2 +- tests/php82_encaps_list.phpt | 44 +++++++++++++++++++ tests/prop_doc_comments.phpt | 4 -- tests/short_arrow_function.phpt | 14 +++--- tests/short_arrow_function_decl_id.phpt | 4 +- tests/short_arrow_function_return.phpt | 24 ++++------ tests/stmt_list.phpt | 2 +- tests/true_type.phpt | 2 - tests/try_catch_finally.phpt | 2 +- tests/type_hints.phpt | 9 ---- tests/unary_ops.phpt | 2 +- tests/use_declarations.phpt | 2 +- util.php | 5 ++- 59 files changed, 151 insertions(+), 228 deletions(-) rename tests/{php82_metadata.phpt => php82_dynamic_property_attribute.phpt} (93%) create mode 100644 tests/php82_encaps_list.phpt diff --git a/README.md b/README.md index 5df3bd6..d02f9da 100644 --- a/README.md +++ b/README.md @@ -357,6 +357,11 @@ ast\flags\ARRAY_ELEM_REF // Used by ast\AST_DIM (combinable), since PHP 7.4 ast\flags\DIM_ALTERNATIVE_SYNTAX +ast\flags\ENCAPS_VAR_DOLLAR_CURLY // php 8.2 deprecation, only available in php 8.2+ + +// Used by ast\AST_VAR (combinable), since PHP 8.2 +ast\flags\ENCAPS_VAR_DOLLAR_CURLY +ast\flags\ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR // Used by ast\AST_CONDITIONAL (combinable), since PHP 7.4 ast\flags\PARENTHESIZED_CONDITIONAL diff --git a/ast.c b/ast.c index 0c2b8c9..3c6acfa 100644 --- a/ast.c +++ b/ast.c @@ -112,6 +112,11 @@ # define IS_NEVER 22 #endif +#if PHP_VERSION_ID < 80200 +# define ZEND_ENCAPS_VAR_DOLLAR_CURLY (1<<0) +# define ZEND_ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR (1<<1) +#endif + /* This contains state of the ast Node creator. */ typedef struct ast_state_info { zend_long version; @@ -299,9 +304,9 @@ static const char *func_flags[] = { NULL }; -// Flags of AST_DIM are marked as combinable in case any other flags get added in the future. static const char *dim_flags[] = { AST_FLAG(DIM_ALTERNATIVE_SYNTAX), + AST_FLAG(ENCAPS_VAR_DOLLAR_CURLY), NULL }; @@ -311,6 +316,12 @@ static const char *conditional_flags[] = { NULL }; +static const char *var_flags[] = { + AST_FLAG(ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR), + AST_FLAG(ENCAPS_VAR_DOLLAR_CURLY), + NULL +}; + static const ast_flag_info flag_info[] = { { AST_NAME, 0, name_flags }, { ZEND_AST_CLASS, 1, class_flags }, @@ -339,6 +350,7 @@ static const ast_flag_info flag_info[] = { { ZEND_AST_TRAIT_ALIAS, 1, modifier_flags }, { ZEND_AST_DIM, 1, dim_flags }, { ZEND_AST_CONDITIONAL, 1, conditional_flags }, + { ZEND_AST_VAR, 1, var_flags }, }; static inline void ast_update_property(zval *object, zend_string *name, zval *value) { @@ -414,7 +426,8 @@ static inline zend_bool ast_kind_uses_attr(zend_ast_kind kind) { || kind == ZEND_AST_GROUP_USE || kind == ZEND_AST_USE_ELEM || kind == AST_NAME || kind == AST_CLOSURE_VAR || kind == ZEND_AST_CLASS_CONST_DECL || kind == ZEND_AST_CLASS_CONST_GROUP - || kind == ZEND_AST_ARRAY || kind == ZEND_AST_DIM || kind == ZEND_AST_CONDITIONAL; + || kind == ZEND_AST_ARRAY || kind == ZEND_AST_DIM || kind == ZEND_AST_CONDITIONAL + || kind == ZEND_AST_VAR; } static inline zend_bool ast_kind_is_decl(zend_ast_kind kind) { @@ -1486,6 +1499,9 @@ PHP_MINIT_FUNCTION(ast) { ast_register_flag_constant("PARENTHESIZED_CONDITIONAL", ZEND_PARENTHESIZED_CONDITIONAL); + ast_register_flag_constant("ENCAPS_VAR_DOLLAR_CURLY", ZEND_ENCAPS_VAR_DOLLAR_CURLY); + ast_register_flag_constant("ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR", ZEND_ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR); + INIT_CLASS_ENTRY(tmp_ce, "ast\\Node", class_ast_Node_methods); ast_node_ce = zend_register_internal_class(&tmp_ce); ast_declare_property(ast_node_ce, AST_STR(str_kind), &zv_null); diff --git a/ast_stub.php b/ast_stub.php index 04cf9eb..095705b 100644 --- a/ast_stub.php +++ b/ast_stub.php @@ -212,6 +212,8 @@ const ARRAY_SYNTAX_SHORT = 3; const DIM_ALTERNATIVE_SYNTAX = 2; const PARENTHESIZED_CONDITIONAL = 1; +const ENCAPS_VAR_DOLLAR_CURLY = 1; +const ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR = 2; // END AST FLAG CONSTANTS namespace ast; diff --git a/package.xml b/package.xml index e55c1f9..666e3b5 100644 --- a/package.xml +++ b/package.xml @@ -32,8 +32,10 @@ - Change documentation files to properly namespace attributes as `#[\AllowDynamicProperties]`. The reflection attributes are already correct. - Deprecated AST versions 50 and 60. - Drop support for php <= 7.1 +- Fix test failures seen in php 8.2.0beta2 due to change to var_export's output format. - Add support for php 8.2 readonly classes. Add `ast\flags\CLASS_READONLY` constant. - Add support for php 8.2 `true` type. Add `ast\flags\TYPE_TRUE` constant. +- Fix bug in php 8.2 where ZEND_AST_ARROW_FUNC output did not include the stub `AST_RETURN` node that was included in php 8.1 and below. @@ -119,7 +121,9 @@ - + + + diff --git a/tests/001.phpt b/tests/001.phpt index aaf7e25..963cad5 100644 --- a/tests/001.phpt +++ b/tests/001.phpt @@ -24,12 +24,10 @@ echo ast_dump(ast\parse_code($code, $version=70)); --EXPECT-- AST_STMT_LIST 0: AST_FUNC_DECL - flags: 0 name: "test" docComment: "/** Test function */" params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_NAME flags: NAME_NOT_FQ (1) name: "Type" @@ -69,4 +67,4 @@ AST_STMT_LIST returnType: AST_NAME flags: NAME_NOT_FQ (1) name: "Ret" - __declId: 0 + __declId: 0 \ No newline at end of file diff --git a/tests/array_destructuring.phpt b/tests/array_destructuring.phpt index b64c4c7..451f77d 100644 --- a/tests/array_destructuring.phpt +++ b/tests/array_destructuring.phpt @@ -78,4 +78,4 @@ AST_STMT_LIST key: null key: null expr: AST_VAR - name: "x" + name: "x" \ No newline at end of file diff --git a/tests/array_destructuring_old.phpt b/tests/array_destructuring_old.phpt index c0e55a0..07a24c6 100644 --- a/tests/array_destructuring_old.phpt +++ b/tests/array_destructuring_old.phpt @@ -18,7 +18,7 @@ echo ast_dump(ast\parse_code($code, $version=70)); AST_STMT_LIST 0: AST_ASSIGN var: AST_ARRAY - flags: ARRAY_SYNTAX_LIST (1) + flags: ARRAY_SYNTAX_LIST (%d) 0: AST_ARRAY_ELEM flags: 0 value: AST_VAR @@ -33,7 +33,7 @@ AST_STMT_LIST name: "x" 1: AST_ASSIGN var: AST_ARRAY - flags: ARRAY_SYNTAX_LIST (1) + flags: ARRAY_SYNTAX_LIST (%d) 0: null 1: AST_ARRAY_ELEM flags: 0 @@ -41,4 +41,4 @@ AST_STMT_LIST name: "b" key: null expr: AST_VAR - name: "x" + name: "x" \ No newline at end of file diff --git a/tests/assign_ops.phpt b/tests/assign_ops.phpt index 956538f..6d69798 100644 --- a/tests/assign_ops.phpt +++ b/tests/assign_ops.phpt @@ -27,55 +27,55 @@ echo ast_dump(ast\parse_code($code, $version=70)), "\n"; --EXPECTF-- AST_STMT_LIST 0: AST_ASSIGN_OP - flags: BINARY_BITWISE_OR (9) + flags: BINARY_BITWISE_OR (%d) var: AST_VAR name: "a" expr: AST_VAR name: "b" 1: AST_ASSIGN_OP - flags: BINARY_BITWISE_AND (10) + flags: BINARY_BITWISE_AND (%d) var: AST_VAR name: "a" expr: AST_VAR name: "b" 2: AST_ASSIGN_OP - flags: BINARY_BITWISE_XOR (11) + flags: BINARY_BITWISE_XOR (%d) var: AST_VAR name: "a" expr: AST_VAR name: "b" 3: AST_ASSIGN_OP - flags: BINARY_CONCAT (8) + flags: BINARY_CONCAT (%d) var: AST_VAR name: "a" expr: AST_VAR name: "b" 4: AST_ASSIGN_OP - flags: BINARY_ADD (1) + flags: BINARY_ADD (%d) var: AST_VAR name: "a" expr: AST_VAR name: "b" 5: AST_ASSIGN_OP - flags: BINARY_SUB (2) + flags: BINARY_SUB (%d) var: AST_VAR name: "a" expr: AST_VAR name: "b" 6: AST_ASSIGN_OP - flags: BINARY_MUL (3) + flags: BINARY_MUL (%d) var: AST_VAR name: "a" expr: AST_VAR name: "b" 7: AST_ASSIGN_OP - flags: BINARY_DIV (4) + flags: BINARY_DIV (%d) var: AST_VAR name: "a" expr: AST_VAR name: "b" 8: AST_ASSIGN_OP - flags: BINARY_MOD (5) + flags: BINARY_MOD (%d) var: AST_VAR name: "a" expr: AST_VAR @@ -87,14 +87,14 @@ AST_STMT_LIST expr: AST_VAR name: "b" 10: AST_ASSIGN_OP - flags: BINARY_SHIFT_LEFT (6) + flags: BINARY_SHIFT_LEFT (%d) var: AST_VAR name: "a" expr: AST_VAR name: "b" 11: AST_ASSIGN_OP - flags: BINARY_SHIFT_RIGHT (7) + flags: BINARY_SHIFT_RIGHT (%d) var: AST_VAR name: "a" expr: AST_VAR - name: "b" + name: "b" \ No newline at end of file diff --git a/tests/ast_dump_with_exclude_doc.phpt b/tests/ast_dump_with_exclude_doc.phpt index e3b2585..3ecacc8 100644 --- a/tests/ast_dump_with_exclude_doc.phpt +++ b/tests/ast_dump_with_exclude_doc.phpt @@ -23,11 +23,9 @@ echo ast_dump($ast, AST_DUMP_EXCLUDE_DOC_COMMENT); --EXPECT-- AST_STMT_LIST 0: AST_FUNC_DECL - flags: 0 name: "test" params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: null name: "foo" default: null diff --git a/tests/ast_dump_with_linenos.phpt b/tests/ast_dump_with_linenos.phpt index d67ccb7..62f9626 100644 --- a/tests/ast_dump_with_linenos.phpt +++ b/tests/ast_dump_with_linenos.phpt @@ -25,20 +25,19 @@ $ast = ast\parse_code($code, $version=70); echo ast_dump($ast, AST_DUMP_LINENOS); ?> ---EXPECT-- +--EXPECTF-- AST_STMT_LIST @ 1 0: AST_FUNC_DECL @ 2-9 - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST @ 4 stmts: AST_STMT_LIST @ 5 0: AST_CALL @ 6 expr: AST_NAME @ 6 - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "var_dump" args: AST_ARG_LIST @ 7 0: AST_VAR @ 7 name: "foo" returnType: null - __declId: 0 + __declId: 0 \ No newline at end of file diff --git a/tests/attributes_01.phpt b/tests/attributes_01.phpt index a464848..09a3184 100644 --- a/tests/attributes_01.phpt +++ b/tests/attributes_01.phpt @@ -27,12 +27,10 @@ AST_STMT_LIST name: "NS" stmts: null 1: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_NAME flags: NAME_NOT_FQ (%d) name: "Type" @@ -45,7 +43,6 @@ AST_STMT_LIST var: AST_VAR name: "x" expr: AST_CLOSURE - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST @@ -57,12 +54,10 @@ AST_STMT_LIST var: AST_VAR name: "y" expr: AST_ARROW_FUNC - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: null name: "a" default: null diff --git a/tests/attributes_02.phpt b/tests/attributes_02.phpt index 767f767..699fd82 100644 --- a/tests/attributes_02.phpt +++ b/tests/attributes_02.phpt @@ -41,7 +41,6 @@ AST_STMT_LIST name: "NS" stmts: null 1: AST_CLASS - flags: 0 name: "X" docComment: null extends: null @@ -51,7 +50,6 @@ AST_STMT_LIST flags: MODIFIER_PUBLIC (%d) type: null props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "prop" default: null @@ -68,7 +66,6 @@ AST_STMT_LIST docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: null name: "parameter" default: null @@ -77,7 +74,6 @@ AST_STMT_LIST __declId: 0 __declId: 1 2: AST_FUNC_DECL - flags: 0 name: "myGlobal" docComment: null params: AST_PARAM_LIST @@ -90,7 +86,6 @@ AST_STMT_LIST name: "NS" stmts: null 1: AST_CLASS - flags: 0 name: "X" docComment: null extends: null @@ -100,7 +95,6 @@ AST_STMT_LIST flags: MODIFIER_PUBLIC (%d) type: null props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "prop" default: null @@ -125,7 +119,6 @@ AST_STMT_LIST 1: AST_CLASS_CONST_GROUP flags: MODIFIER_PUBLIC (%d) const: AST_CLASS_CONST_DECL - flags: 0 0: AST_CONST_ELEM name: "CONST_WITH_ATTRIBUTE" value: 123 @@ -143,7 +136,6 @@ AST_STMT_LIST docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: null name: "parameter" default: null @@ -184,7 +176,6 @@ AST_STMT_LIST args: AST_ARG_LIST __declId: 1 2: AST_FUNC_DECL - flags: 0 name: "myGlobal" docComment: null params: AST_PARAM_LIST diff --git a/tests/by_ref_destructuring.phpt b/tests/by_ref_destructuring.phpt index c6bed76..b3cfdf3 100644 --- a/tests/by_ref_destructuring.phpt +++ b/tests/by_ref_destructuring.phpt @@ -62,4 +62,4 @@ AST_STMT_LIST flags: ARRAY_ELEM_REF (1) value: AST_VAR name: "b" - key: null + key: null \ No newline at end of file diff --git a/tests/class.phpt b/tests/class.phpt index 4ac74ce..b51661c 100644 --- a/tests/class.phpt +++ b/tests/class.phpt @@ -23,7 +23,6 @@ echo ast_dump(ast\parse_code($code, $version=70)), "\n"; Deprecated: ast\parse_code(): Version 60 is deprecated in %sclass.php on line 15 AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "A" docComment: null extends: AST_NAME @@ -77,7 +76,6 @@ AST_STMT_LIST __declId: 1 AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "A" docComment: null extends: AST_NAME @@ -114,7 +112,6 @@ AST_STMT_LIST flags: MODIFIER_PUBLIC (%d) type: null props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "foo" default: null diff --git a/tests/class_consts.phpt b/tests/class_consts.phpt index c097b73..22a4dd0 100644 --- a/tests/class_consts.phpt +++ b/tests/class_consts.phpt @@ -27,7 +27,6 @@ echo ast_dump(ast\parse_code($code, $version=70)); --EXPECTF-- AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "Test" docComment: null extends: null diff --git a/tests/class_consts_80.phpt b/tests/class_consts_80.phpt index 59b7786..cf2076f 100644 --- a/tests/class_consts_80.phpt +++ b/tests/class_consts_80.phpt @@ -24,7 +24,6 @@ echo ast_dump(ast\parse_code($code, $version=80)); --EXPECTF-- AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "Test" docComment: null extends: null @@ -33,7 +32,6 @@ AST_STMT_LIST 0: AST_CLASS_CONST_GROUP flags: MODIFIER_PUBLIC (%d) const: AST_CLASS_CONST_DECL - flags: 0 0: AST_CONST_ELEM name: "A" value: 1 @@ -42,7 +40,6 @@ AST_STMT_LIST 1: AST_CLASS_CONST_GROUP flags: MODIFIER_PROTECTED (%d) const: AST_CLASS_CONST_DECL - flags: 0 0: AST_CONST_ELEM name: "E" value: 5 diff --git a/tests/class_types.phpt b/tests/class_types.phpt index 5f91c96..e1307e7 100644 --- a/tests/class_types.phpt +++ b/tests/class_types.phpt @@ -21,7 +21,6 @@ echo ast_dump(ast\parse_code($code, $version=70)); --EXPECTF-- AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "A" docComment: null extends: null diff --git a/tests/closure_use_vars.phpt b/tests/closure_use_vars.phpt index 63bd194..64922d0 100644 --- a/tests/closure_use_vars.phpt +++ b/tests/closure_use_vars.phpt @@ -24,7 +24,6 @@ AST_STMT_LIST docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: null name: "a" default: null @@ -38,8 +37,8 @@ AST_STMT_LIST flags: 0 name: "c" 1: AST_CLOSURE_VAR - flags: CLOSURE_USE_REF (1) + flags: CLOSURE_USE_REF (%d) name: "d" stmts: AST_STMT_LIST returnType: null - __declId: 0 + __declId: 0 \ No newline at end of file diff --git a/tests/coalesce.phpt b/tests/coalesce.phpt index fef5bbe..dce6a5e 100644 --- a/tests/coalesce.phpt +++ b/tests/coalesce.phpt @@ -13,11 +13,11 @@ PHP; echo ast_dump(ast\parse_code($code, $version=70)), "\n"; ?> ---EXPECT-- +--EXPECTF-- AST_STMT_LIST 0: AST_BINARY_OP - flags: BINARY_COALESCE (260) + flags: BINARY_COALESCE (%d) left: AST_VAR name: "a" right: AST_VAR - name: "b" + name: "b" \ No newline at end of file diff --git a/tests/decl_ids.phpt b/tests/decl_ids.phpt index c82d626..6376787 100644 --- a/tests/decl_ids.phpt +++ b/tests/decl_ids.phpt @@ -19,7 +19,6 @@ echo ast_dump(ast\parse_code($code, $version=80)) . "\n"; Deprecated: ast\parse_code(): Version 50 is deprecated in %s.php on line 11 AST_STMT_LIST 0: AST_CLOSURE - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST @@ -28,7 +27,6 @@ AST_STMT_LIST returnType: null __declId: 0 1: AST_CLOSURE - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST @@ -37,7 +35,6 @@ AST_STMT_LIST returnType: null __declId: 1 2: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST @@ -46,7 +43,6 @@ AST_STMT_LIST returnType: null __declId: 2 3: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST @@ -55,7 +51,6 @@ AST_STMT_LIST returnType: null __declId: 3 4: AST_CLASS - flags: 0 name: "Test" docComment: null extends: null @@ -63,7 +58,6 @@ AST_STMT_LIST stmts: AST_STMT_LIST __declId: 4 5: AST_CLASS - flags: 0 name: "Test" docComment: null extends: null @@ -72,7 +66,6 @@ AST_STMT_LIST __declId: 5 AST_STMT_LIST 0: AST_CLOSURE - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST @@ -82,7 +75,6 @@ AST_STMT_LIST attributes: null __declId: 0 1: AST_CLOSURE - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST @@ -92,7 +84,6 @@ AST_STMT_LIST attributes: null __declId: 1 2: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST @@ -101,7 +92,6 @@ AST_STMT_LIST attributes: null __declId: 2 3: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST @@ -110,7 +100,6 @@ AST_STMT_LIST attributes: null __declId: 3 4: AST_CLASS - flags: 0 name: "Test" docComment: null extends: null @@ -119,7 +108,6 @@ AST_STMT_LIST attributes: null __declId: 4 5: AST_CLASS - flags: 0 name: "Test" docComment: null extends: null diff --git a/tests/decl_normalization.phpt b/tests/decl_normalization.phpt index bc6a4fc..f7d2a8f 100644 --- a/tests/decl_normalization.phpt +++ b/tests/decl_normalization.phpt @@ -46,7 +46,6 @@ array(4) { } AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "A" docComment: "/** A */" extends: null @@ -62,7 +61,6 @@ AST_STMT_LIST flags: MODIFIER_PUBLIC (%d) type: null props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "c" default: null @@ -82,7 +80,6 @@ AST_STMT_LIST value: 0 docComment: "/** E */" 2: AST_FUNC_DECL - flags: 0 name: "f" docComment: "/** f */" params: AST_PARAM_LIST @@ -90,7 +87,6 @@ AST_STMT_LIST returnType: null __declId: 2 3: AST_CLOSURE - flags: 0 name: "{closure}" docComment: "/** g */" params: AST_PARAM_LIST @@ -102,7 +98,6 @@ AST_STMT_LIST Deprecated: ast\parse_code(): Version 50 is deprecated in %sdecl_normalization.php on line 29 AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "A" docComment: "/** A */" extends: null @@ -136,7 +131,6 @@ AST_STMT_LIST value: 0 docComment: "/** E */" 2: AST_FUNC_DECL - flags: 0 name: "f" docComment: "/** f */" params: AST_PARAM_LIST @@ -145,7 +139,6 @@ AST_STMT_LIST returnType: null __declId: 2 3: AST_CLOSURE - flags: 0 name: "{closure}" docComment: "/** g */" params: AST_PARAM_LIST diff --git a/tests/functions_dont_use.phpt b/tests/functions_dont_use.phpt index c1aa273..a3c8e24 100644 --- a/tests/functions_dont_use.phpt +++ b/tests/functions_dont_use.phpt @@ -20,7 +20,6 @@ echo ast_dump(ast\parse_code($code, $version=60)), "\n"; Deprecated: ast\parse_code(): Version 50 is deprecated in %s.php on line 11 AST_STMT_LIST 0: AST_CLOSURE - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST @@ -29,7 +28,6 @@ AST_STMT_LIST returnType: null __declId: 0 1: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST @@ -41,7 +39,6 @@ AST_STMT_LIST Deprecated: ast\parse_code(): Version 60 is deprecated in %s.php on line 12 AST_STMT_LIST 0: AST_CLOSURE - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST @@ -50,7 +47,6 @@ AST_STMT_LIST returnType: null __declId: 0 1: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST diff --git a/tests/metadata.phpt b/tests/metadata.phpt index 35b5862..a3363da 100644 --- a/tests/metadata.phpt +++ b/tests/metadata.phpt @@ -59,7 +59,7 @@ AST_CLASS: (combinable) [CLASS_ABSTRACT, CLASS_FINAL, CLASS_TRAIT, CLASS_INTERFA AST_MAGIC_CONST: [MAGIC_LINE, MAGIC_FILE, MAGIC_DIR, MAGIC_NAMESPACE, MAGIC_FUNCTION, MAGIC_METHOD, MAGIC_CLASS, MAGIC_TRAIT] AST_TYPE: [TYPE_NULL, TYPE_FALSE, TYPE_TRUE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED, TYPE_NEVER] AST_CALLABLE_CONVERT: [] -AST_VAR: [] +AST_VAR: (combinable) [ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR, ENCAPS_VAR_DOLLAR_CURLY] AST_CONST: [] AST_UNPACK: [] AST_CAST: [TYPE_NULL, TYPE_FALSE, TYPE_TRUE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED, TYPE_NEVER] @@ -89,7 +89,7 @@ AST_BREAK: [] AST_CONTINUE: [] AST_CLASS_NAME: [] AST_CLASS_CONST_GROUP: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY] -AST_DIM: (combinable) [DIM_ALTERNATIVE_SYNTAX] +AST_DIM: (combinable) [DIM_ALTERNATIVE_SYNTAX, ENCAPS_VAR_DOLLAR_CURLY] AST_PROP: [] AST_NULLSAFE_PROP: [] AST_STATIC_PROP: [] diff --git a/tests/mixed_type.phpt b/tests/mixed_type.phpt index 6d9275c..ec7efa2 100644 --- a/tests/mixed_type.phpt +++ b/tests/mixed_type.phpt @@ -21,7 +21,6 @@ echo ast_dump($node), "\n"; --EXPECTF-- AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "Xyz" docComment: null extends: null @@ -33,7 +32,6 @@ AST_STMT_LIST docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_NAME flags: NAME_NOT_FQ (%d) name: "mixed" @@ -50,7 +48,6 @@ AST_STMT_LIST __declId: 1 AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "Xyz" docComment: null extends: null @@ -62,7 +59,6 @@ AST_STMT_LIST docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_TYPE flags: TYPE_MIXED (%d) name: "x" diff --git a/tests/multi_catch.phpt b/tests/multi_catch.phpt index 724e7e7..79d1933 100644 --- a/tests/multi_catch.phpt +++ b/tests/multi_catch.phpt @@ -31,4 +31,4 @@ AST_STMT_LIST var: AST_VAR name: "b" stmts: AST_STMT_LIST - finally: null + finally: null \ No newline at end of file diff --git a/tests/named_children.phpt b/tests/named_children.phpt index ca1c7e2..afc6bf3 100644 --- a/tests/named_children.phpt +++ b/tests/named_children.phpt @@ -22,7 +22,6 @@ AST_STMT_LIST var: AST_VAR name: "fn" expr: AST_CLOSURE - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST @@ -41,4 +40,4 @@ AST_STMT_LIST name: "func" args: AST_ARG_LIST returnType: null - __declId: 0 + __declId: 0 \ No newline at end of file diff --git a/tests/nested_stmt_lists.phpt b/tests/nested_stmt_lists.phpt index 8e0332c..cf830cc 100644 --- a/tests/nested_stmt_lists.phpt +++ b/tests/nested_stmt_lists.phpt @@ -40,4 +40,4 @@ AST_STMT_LIST 5: AST_VAR name: "f" 6: AST_VAR - name: "g" + name: "g" \ No newline at end of file diff --git a/tests/never_return_type.phpt b/tests/never_return_type.phpt index 4d208d0..16115a9 100644 --- a/tests/never_return_type.phpt +++ b/tests/never_return_type.phpt @@ -16,7 +16,6 @@ echo ast_dump($node), "\n"; --EXPECTF-- AST_STMT_LIST 0: AST_FUNC_DECL - flags: 0 name: "up" docComment: null params: AST_PARAM_LIST diff --git a/tests/nullable_types.phpt b/tests/nullable_types.phpt index 691364d..cd1022c 100644 --- a/tests/nullable_types.phpt +++ b/tests/nullable_types.phpt @@ -21,12 +21,10 @@ echo ast_dump(ast\parse_code($code, $version=70)); --EXPECT-- AST_STMT_LIST 0: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_NULLABLE_TYPE type: AST_NAME flags: NAME_NOT_FQ (1) @@ -40,12 +38,10 @@ AST_STMT_LIST name: "Bar" __declId: 0 1: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_NULLABLE_TYPE type: AST_TYPE flags: TYPE_LONG (4) @@ -57,12 +53,10 @@ AST_STMT_LIST flags: TYPE_LONG (4) __declId: 1 2: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_NULLABLE_TYPE type: AST_TYPE flags: TYPE_ARRAY (7) diff --git a/tests/object_type.phpt b/tests/object_type.phpt index 28f3243..7903ca3 100644 --- a/tests/object_type.phpt +++ b/tests/object_type.phpt @@ -16,12 +16,10 @@ echo ast_dump(ast\parse_code($code, $version=70)); --EXPECTF-- AST_STMT_LIST 0: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_TYPE flags: TYPE_OBJECT (%d) name: "obj" diff --git a/tests/params.phpt b/tests/params.phpt index 30f3f7a..72128f7 100644 --- a/tests/params.phpt +++ b/tests/params.phpt @@ -19,12 +19,10 @@ echo ast_dump(ast\parse_code($code, $version=80)), "\n"; --EXPECTF-- AST_STMT_LIST 0: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: null name: "a" default: null @@ -37,7 +35,6 @@ AST_STMT_LIST returnType: null __declId: 0 1: AST_FUNC_DECL - flags: 0 name: "test2" docComment: null params: AST_PARAM_LIST @@ -55,7 +52,6 @@ AST_STMT_LIST returnType: null __declId: 1 2: AST_FUNC_DECL - flags: 0 name: "test3" docComment: null params: AST_PARAM_LIST @@ -76,12 +72,10 @@ AST_STMT_LIST __declId: 2 AST_STMT_LIST 0: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: null name: "a" default: null @@ -99,7 +93,6 @@ AST_STMT_LIST attributes: null __declId: 0 1: AST_FUNC_DECL - flags: 0 name: "test2" docComment: null params: AST_PARAM_LIST @@ -122,7 +115,6 @@ AST_STMT_LIST attributes: null __declId: 1 2: AST_FUNC_DECL - flags: 0 name: "test3" docComment: null params: AST_PARAM_LIST diff --git a/tests/php74_ast_assign_coalesce.phpt b/tests/php74_ast_assign_coalesce.phpt index 024b77d..84d50f0 100644 --- a/tests/php74_ast_assign_coalesce.phpt +++ b/tests/php74_ast_assign_coalesce.phpt @@ -26,7 +26,6 @@ AST_STMT_LIST 1: AST_ASSIGN_OP flags: BINARY_COALESCE (%d) var: AST_DIM - flags: 0 expr: AST_STATIC_PROP class: AST_NAME flags: NAME_NOT_FQ (%d) @@ -37,4 +36,4 @@ AST_STMT_LIST flags: BINARY_COALESCE (%d) var: AST_VAR name: "other" - expr: "value" + expr: "value" \ No newline at end of file diff --git a/tests/php74_dim_alternative_syntax.phpt b/tests/php74_dim_alternative_syntax.phpt index 2ff5ed9..2d7bc56 100644 --- a/tests/php74_dim_alternative_syntax.phpt +++ b/tests/php74_dim_alternative_syntax.phpt @@ -19,11 +19,11 @@ echo ast_dump($node), "\n"; AST_STMT_LIST 0: AST_CALL expr: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "var_export" args: AST_ARG_LIST 0: AST_DIM - flags: DIM_ALTERNATIVE_SYNTAX (2) + flags: DIM_ALTERNATIVE_SYNTAX (%d) expr: AST_VAR name: "x" - dim: "offset" + dim: "offset" \ No newline at end of file diff --git a/tests/php74_ordinary_class.phpt b/tests/php74_ordinary_class.phpt index b3b9533..5598e95 100644 --- a/tests/php74_ordinary_class.phpt +++ b/tests/php74_ordinary_class.phpt @@ -25,7 +25,6 @@ AST_STMT_LIST name: "Foo" stmts: null 1: AST_CLASS - flags: 0 name: "test" docComment: null extends: null @@ -35,7 +34,6 @@ AST_STMT_LIST flags: MODIFIER_PUBLIC (%d) type: null props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "i" default: 2 @@ -48,7 +46,6 @@ AST_STMT_LIST flags: MODIFIER_PROTECTED (%d) type: null props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "row" default: null @@ -57,7 +54,6 @@ AST_STMT_LIST flags: MODIFIER_PUBLIC (%d) type: null props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "o" default: null @@ -66,7 +62,6 @@ AST_STMT_LIST flags: MODIFIER_PRIVATE | MODIFIER_STATIC (%d) type: null props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "normal" default: AST_CONST diff --git a/tests/php74_parenthesized_conditional.phpt b/tests/php74_parenthesized_conditional.phpt index e76713f..c742377 100644 --- a/tests/php74_parenthesized_conditional.phpt +++ b/tests/php74_parenthesized_conditional.phpt @@ -20,9 +20,7 @@ echo ast_dump($node), "\n"; AST_STMT_LIST 0: AST_RETURN expr: AST_CONDITIONAL - flags: 0 cond: AST_CONDITIONAL - flags: 0 cond: AST_VAR name: "a" true: AST_VAR @@ -35,7 +33,6 @@ AST_STMT_LIST name: "e" 1: AST_RETURN expr: AST_CONDITIONAL - flags: 0 cond: AST_VAR name: "a" true: AST_VAR @@ -47,4 +44,4 @@ AST_STMT_LIST true: AST_VAR name: "d" false: AST_VAR - name: "e" + name: "e" \ No newline at end of file diff --git a/tests/php74_type_hints.phpt b/tests/php74_type_hints.phpt index 9290bd3..eebee5d 100644 --- a/tests/php74_type_hints.phpt +++ b/tests/php74_type_hints.phpt @@ -35,7 +35,6 @@ AST_STMT_LIST name: "Foo" stmts: null 1: AST_CLASS - flags: 0 name: "test" docComment: null extends: null @@ -91,7 +90,6 @@ AST_STMT_LIST name: "Foo" stmts: null 1: AST_CLASS - flags: 0 name: "test" docComment: null extends: null @@ -102,7 +100,6 @@ AST_STMT_LIST type: AST_TYPE flags: TYPE_LONG (4) props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "i" default: 2 @@ -117,7 +114,6 @@ AST_STMT_LIST type: AST_TYPE flags: TYPE_STRING (6) props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "s" default: null @@ -128,7 +124,6 @@ AST_STMT_LIST type: AST_TYPE flags: TYPE_ITERABLE (%d) props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "it" default: null @@ -139,7 +134,6 @@ AST_STMT_LIST flags: NAME_NOT_FQ (1) name: "Row" props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "row" default: null @@ -150,7 +144,6 @@ AST_STMT_LIST flags: NAME_FQ (0) name: "stdClass" props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "o" default: null @@ -159,7 +152,6 @@ AST_STMT_LIST flags: MODIFIER_PRIVATE | MODIFIER_STATIC (%d) type: null props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "normal" default: AST_CONST diff --git a/tests/php80_promotion.phpt b/tests/php80_promotion.phpt index b9a91d6..5e725ac 100644 --- a/tests/php80_promotion.phpt +++ b/tests/php80_promotion.phpt @@ -26,7 +26,6 @@ echo ast_dump($node), "\n"; --EXPECTF-- AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "Promotion" docComment: null extends: null diff --git a/tests/php80_static_type.phpt b/tests/php80_static_type.phpt index dd3c970..705ec31 100644 --- a/tests/php80_static_type.phpt +++ b/tests/php80_static_type.phpt @@ -24,14 +24,13 @@ echo ast_dump($node), "\n"; --EXPECTF-- AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "Xyz" docComment: null extends: null implements: null stmts: AST_STMT_LIST 0: AST_METHOD - flags: MODIFIER_PUBLIC (1) + flags: MODIFIER_PUBLIC (%d) name: "test" docComment: null params: AST_PARAM_LIST @@ -43,7 +42,7 @@ AST_STMT_LIST flags: TYPE_STATIC (%d) __declId: 0 1: AST_METHOD - flags: MODIFIER_PUBLIC (1) + flags: MODIFIER_PUBLIC (%d) name: "test2" docComment: null params: AST_PARAM_LIST diff --git a/tests/php80_union_types.phpt b/tests/php80_union_types.phpt index ed0d3c9..7fd7e76 100644 --- a/tests/php80_union_types.phpt +++ b/tests/php80_union_types.phpt @@ -31,12 +31,10 @@ AST_STMT_LIST name: "NS" stmts: null 1: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_TYPE_UNION 0: AST_TYPE flags: TYPE_OBJECT (%d) @@ -56,7 +54,7 @@ AST_STMT_LIST 0: AST_RETURN expr: AST_CALL expr: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "json_encode" args: AST_ARG_LIST 0: AST_VAR @@ -68,42 +66,38 @@ AST_STMT_LIST flags: TYPE_FALSE (%d) __declId: 0 2: AST_CLASS - flags: 0 name: "Xyz" docComment: null extends: null implements: null stmts: AST_STMT_LIST 0: AST_PROP_GROUP - flags: MODIFIER_PUBLIC (1) + flags: MODIFIER_PUBLIC (%d) type: AST_TYPE_UNION 0: AST_TYPE flags: TYPE_BOOL (%d) 1: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "stdClass" props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "x" default: null docComment: null __declId: 1 3: AST_FUNC_DECL - flags: 0 name: "testClasses" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_TYPE_UNION 0: AST_TYPE flags: TYPE_ITERABLE (%d) 1: AST_NAME - flags: NAME_FQ (0) + flags: NAME_FQ (%d) name: "stdClass" 2: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "Xyz" name: "s" default: null @@ -111,12 +105,12 @@ AST_STMT_LIST 0: AST_RETURN expr: AST_NEW class: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "X" args: AST_ARG_LIST returnType: AST_TYPE_UNION 0: AST_NAME - flags: NAME_RELATIVE (2) + flags: NAME_RELATIVE (%d) name: "Xyz" 1: AST_TYPE flags: TYPE_FALSE (%d) @@ -125,18 +119,18 @@ AST_STMT_LIST __declId: 2 4: AST_CALL expr: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "test" args: AST_ARG_LIST 0: AST_ARRAY - flags: ARRAY_SYNTAX_SHORT (3) + flags: ARRAY_SYNTAX_SHORT (%d) 5: AST_CALL expr: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "testClasses" args: AST_ARG_LIST 0: AST_ARRAY - flags: ARRAY_SYNTAX_SHORT (3) + flags: ARRAY_SYNTAX_SHORT (%d) 0: AST_ARRAY_ELEM flags: 0 value: 2 @@ -144,4 +138,4 @@ AST_STMT_LIST 1: AST_ARRAY_ELEM flags: 0 value: 3 - key: null + key: null \ No newline at end of file diff --git a/tests/php80_union_types_false.phpt b/tests/php80_union_types_false.phpt index e78cfad..ae28049 100644 --- a/tests/php80_union_types_false.phpt +++ b/tests/php80_union_types_false.phpt @@ -22,7 +22,6 @@ echo ast_dump($node), "\n"; --EXPECTF-- AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "Example" docComment: null extends: null @@ -38,7 +37,6 @@ AST_STMT_LIST 2: AST_TYPE flags: TYPE_FALSE (%d) props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "value" default: null @@ -48,12 +46,10 @@ AST_STMT_LIST var: AST_VAR name: "f" expr: AST_ARROW_FUNC - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_TYPE_UNION 0: AST_TYPE flags: TYPE_OBJECT (%d) @@ -71,12 +67,10 @@ AST_STMT_LIST var: AST_VAR name: "g" expr: AST_CLOSURE - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_TYPE flags: TYPE_FALSE (%d) name: "arg" diff --git a/tests/php80_union_types_nullable.phpt b/tests/php80_union_types_nullable.phpt index ce22607..842fa57 100644 --- a/tests/php80_union_types_nullable.phpt +++ b/tests/php80_union_types_nullable.phpt @@ -27,19 +27,16 @@ echo ast_dump($node), "\n"; Deprecated: ast\parse_code(): Version 50 is deprecated in %s.php on line 17 AST_STMT_LIST 0: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_NULLABLE_TYPE type: AST_TYPE flags: TYPE_ARRAY (7) name: "a" default: null 1: AST_PARAM - flags: 0 type: AST_NULLABLE_TYPE type: AST_TYPE flags: TYPE_OBJECT (8) @@ -58,7 +55,6 @@ AST_STMT_LIST name: "stdClass" __declId: 0 1: AST_CLASS - flags: 0 name: "X" docComment: null extends: null @@ -79,19 +75,16 @@ AST_STMT_LIST __declId: 1 AST_STMT_LIST 0: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_NULLABLE_TYPE type: AST_TYPE flags: TYPE_ARRAY (7) name: "a" default: null 1: AST_PARAM - flags: 0 type: AST_NULLABLE_TYPE type: AST_TYPE flags: TYPE_OBJECT (8) @@ -109,7 +102,6 @@ AST_STMT_LIST name: "stdClass" __declId: 0 1: AST_CLASS - flags: 0 name: "X" docComment: null extends: null @@ -121,7 +113,6 @@ AST_STMT_LIST type: AST_TYPE flags: TYPE_ARRAY (7) props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "arr" default: null @@ -133,7 +124,6 @@ AST_STMT_LIST flags: NAME_FQ (0) name: "ArrayObject" props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "obj" default: null diff --git a/tests/php81_enums.phpt b/tests/php81_enums.phpt index 299cdcf..c741fa4 100644 --- a/tests/php81_enums.phpt +++ b/tests/php81_enums.phpt @@ -88,7 +88,6 @@ AST_STMT_LIST 1: AST_CLASS_CONST_GROUP flags: MODIFIER_PUBLIC (%d) const: AST_CLASS_CONST_DECL - flags: 0 0: AST_CONST_ELEM name: "FOO_ALIAS" value: AST_CLASS_CONST @@ -143,7 +142,6 @@ AST_STMT_LIST 1: AST_CLASS_CONST_GROUP flags: MODIFIER_PUBLIC (%d) const: AST_CLASS_CONST_DECL - flags: 0 0: AST_CONST_ELEM name: "FOO_ALIAS" value: AST_CLASS_CONST diff --git a/tests/php81_final_class_const.phpt b/tests/php81_final_class_const.phpt index f1dbf71..6c4db0f 100644 --- a/tests/php81_final_class_const.phpt +++ b/tests/php81_final_class_const.phpt @@ -20,7 +20,6 @@ echo ast_dump($node), "\n"; --EXPECTF-- AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "X" docComment: null extends: null @@ -35,7 +34,6 @@ AST_STMT_LIST __declId: 0 AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "X" docComment: null extends: null @@ -44,7 +42,6 @@ AST_STMT_LIST 0: AST_CLASS_CONST_GROUP flags: MODIFIER_PRIVATE | MODIFIER_FINAL (%d) const: AST_CLASS_CONST_DECL - flags: 0 0: AST_CONST_ELEM name: "Y" value: 1 diff --git a/tests/php81_first_class_callable_support.phpt b/tests/php81_first_class_callable_support.phpt index 5231e47..abb330a 100644 --- a/tests/php81_first_class_callable_support.phpt +++ b/tests/php81_first_class_callable_support.phpt @@ -24,7 +24,7 @@ AST_STMT_LIST name: "c1" expr: AST_CALL expr: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "foo" args: AST_CALLABLE_CONVERT 1: AST_ASSIGN @@ -32,7 +32,7 @@ AST_STMT_LIST name: "c2" expr: AST_STATIC_CALL class: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "C" method: "foo" args: AST_CALLABLE_CONVERT diff --git a/tests/php81_intersection_types.phpt b/tests/php81_intersection_types.phpt index 15623fb..1fa53ff 100644 --- a/tests/php81_intersection_types.phpt +++ b/tests/php81_intersection_types.phpt @@ -26,7 +26,6 @@ echo ast_dump($node), "\n"; --EXPECTF-- AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "X" docComment: null extends: null @@ -45,7 +44,6 @@ AST_STMT_LIST flags: NAME_NOT_FQ (%d) name: "Traversable" props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "arrayLike" default: null @@ -57,7 +55,6 @@ AST_STMT_LIST docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_TYPE_INTERSECTION 0: AST_NAME flags: NAME_NOT_FQ (%d) @@ -85,7 +82,6 @@ AST_STMT_LIST attributes: null __declId: 1 1: AST_FUNC_DECL - flags: 0 name: "this_is_a_compile_error" docComment: null params: AST_PARAM_LIST diff --git a/tests/php81_readonly.phpt b/tests/php81_readonly.phpt index 690d09c..e41a2fe 100644 --- a/tests/php81_readonly.phpt +++ b/tests/php81_readonly.phpt @@ -22,7 +22,6 @@ echo ast_dump($node), "\n"; Deprecated: ast\parse_code(): Version 60 is deprecated in %sphp81_readonly.php on line 12 AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "X" docComment: null extends: null @@ -37,7 +36,6 @@ AST_STMT_LIST __declId: 0 AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "X" docComment: null extends: null @@ -48,7 +46,6 @@ AST_STMT_LIST type: AST_TYPE flags: TYPE_LONG (%d) props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "var" default: null diff --git a/tests/php82_metadata.phpt b/tests/php82_dynamic_property_attribute.phpt similarity index 93% rename from tests/php82_metadata.phpt rename to tests/php82_dynamic_property_attribute.phpt index 046a6df..d6ee836 100644 --- a/tests/php82_metadata.phpt +++ b/tests/php82_dynamic_property_attribute.phpt @@ -35,7 +35,7 @@ dump_attributes(ast\Metadata::class); 'children' => NULL, 'undeclaredDynamic' => 123, )) -Deprecated: Creation of dynamic property ast\Metadata::$undeclaredDynamic is deprecated in %sphp82_metadata.php on line 21 +Deprecated: Creation of dynamic property ast\Metadata::$undeclaredDynamic is deprecated in %sphp82_dynamic_property_attribute.php on line 21 %Sast\Metadata::__set_state(array( 'kind' => NULL, 'name' => NULL, diff --git a/tests/php82_encaps_list.phpt b/tests/php82_encaps_list.phpt new file mode 100644 index 0000000..808cf93 --- /dev/null +++ b/tests/php82_encaps_list.phpt @@ -0,0 +1,44 @@ +--TEST-- +Encapsulated variable flags in PHP 8.2 +--SKIPIF-- += 8.2 only'); ?> +--FILE-- +c}{$d}${$e["f"]}${g[\'h\']}{$i{\'j\'}}";'; +$node = ast\parse_code($code, $version=85); +echo ast_dump($node), "\n"; +--EXPECTF-- +AST_STMT_LIST + 0: AST_ENCAPS_LIST + 0: AST_VAR + flags: ENCAPS_VAR_DOLLAR_CURLY (%d) + name: "a" + 1: AST_VAR + flags: ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR (%d) + name: AST_PROP + expr: AST_CONST + name: AST_NAME + flags: NAME_NOT_FQ (%d) + name: "b" + prop: "c" + 2: AST_VAR + name: "d" + 3: AST_VAR + flags: ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR (%d) + name: AST_DIM + expr: AST_VAR + name: "e" + dim: "f" + 4: AST_DIM + flags: ENCAPS_VAR_DOLLAR_CURLY (%d) + expr: AST_VAR + name: "g" + dim: "h" + 5: AST_DIM + flags: DIM_ALTERNATIVE_SYNTAX (%d) + expr: AST_VAR + name: "i" + dim: "j" diff --git a/tests/prop_doc_comments.phpt b/tests/prop_doc_comments.phpt index 8fd60b5..eff5ed1 100644 --- a/tests/prop_doc_comments.phpt +++ b/tests/prop_doc_comments.phpt @@ -28,7 +28,6 @@ echo ast_dump(ast\parse_code($code, $version=80)), "\n"; Deprecated: ast\parse_code(): Version 50 is deprecated in %s.php on line 20 AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "A" docComment: null extends: null @@ -53,7 +52,6 @@ AST_STMT_LIST __declId: 0 AST_STMT_LIST 0: AST_CLASS - flags: 0 name: "A" docComment: null extends: null @@ -63,7 +61,6 @@ AST_STMT_LIST flags: MODIFIER_PUBLIC (%d) type: null props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "a" default: null @@ -73,7 +70,6 @@ AST_STMT_LIST flags: MODIFIER_PUBLIC (%d) type: null props: AST_PROP_DECL - flags: 0 0: AST_PROP_ELEM name: "b" default: null diff --git a/tests/short_arrow_function.phpt b/tests/short_arrow_function.phpt index 57d322e..9e92a19 100644 --- a/tests/short_arrow_function.phpt +++ b/tests/short_arrow_function.phpt @@ -35,18 +35,16 @@ AST_STMT_LIST var: AST_VAR name: "a" expr: AST_ARROW_FUNC - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: null name: "x" default: null stmts: AST_RETURN expr: AST_BINARY_OP - flags: BINARY_MUL (3) + flags: BINARY_MUL (%d) left: AST_VAR name: "x" right: AST_VAR @@ -57,7 +55,7 @@ AST_STMT_LIST var: AST_VAR name: "b" expr: AST_ARROW_FUNC - flags: MODIFIER_STATIC (16) + flags: MODIFIER_STATIC (%d) name: "{closure}" docComment: null params: AST_PARAM_LIST @@ -69,7 +67,7 @@ AST_STMT_LIST var: AST_VAR name: "c" expr: AST_ARROW_FUNC - flags: MODIFIER_STATIC (16) + flags: MODIFIER_STATIC (%d) name: "{closure}" docComment: "/** doc comment */" params: AST_PARAM_LIST @@ -77,20 +75,20 @@ AST_STMT_LIST flags: PARAM_VARIADIC (%d) type: AST_NULLABLE_TYPE type: AST_TYPE - flags: TYPE_LONG (4) + flags: TYPE_LONG (%d) name: "args" default: null stmts: AST_RETURN expr: AST_VAR name: "args" returnType: AST_TYPE - flags: TYPE_ARRAY (7) + flags: TYPE_ARRAY (%d) __declId: 2 4: AST_ASSIGN var: AST_VAR name: "fn" expr: AST_ARROW_FUNC - flags: FUNC_GENERATOR (16777216) + flags: FUNC_GENERATOR (%d) name: "{closure}" docComment: null params: AST_PARAM_LIST diff --git a/tests/short_arrow_function_decl_id.phpt b/tests/short_arrow_function_decl_id.phpt index 3a8d430..8ff0a80 100644 --- a/tests/short_arrow_function_decl_id.phpt +++ b/tests/short_arrow_function_decl_id.phpt @@ -21,13 +21,11 @@ AST_STMT_LIST var: AST_VAR name: "cb" expr: AST_ARROW_FUNC - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST stmts: AST_RETURN expr: AST_ARROW_FUNC - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST @@ -39,4 +37,4 @@ AST_STMT_LIST __declId: 0 returnType: null attributes: null - __declId: 1 + __declId: 1 \ No newline at end of file diff --git a/tests/short_arrow_function_return.phpt b/tests/short_arrow_function_return.phpt index 357689f..658326b 100644 --- a/tests/short_arrow_function_return.phpt +++ b/tests/short_arrow_function_return.phpt @@ -27,46 +27,42 @@ echo "\n"; --EXPECTF-- AST_STMT_LIST 0: AST_ARROW_FUNC - flags: MODIFIER_STATIC (16) + flags: MODIFIER_STATIC (%d) name: "{closure}" docComment: null params: AST_PARAM_LIST stmts: AST_RETURN expr: 1 returnType: AST_TYPE - flags: TYPE_LONG (4) + flags: TYPE_LONG (%d) __declId: 0 1: AST_ARROW_FUNC - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_TYPE flags: TYPE_ITERABLE (%d) name: "i" default: null stmts: AST_RETURN expr: AST_ARRAY - flags: ARRAY_SYNTAX_SHORT (3) + flags: ARRAY_SYNTAX_SHORT (%d) 0: AST_ARRAY_ELEM flags: 0 value: AST_VAR name: "i" key: null returnType: AST_TYPE - flags: TYPE_ARRAY (7) + flags: TYPE_ARRAY (%d) __declId: 1 2: AST_ARROW_FUNC - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "stdClass" name: "param" default: null @@ -74,18 +70,16 @@ AST_STMT_LIST expr: AST_VAR name: "param" returnType: AST_NAME - flags: NAME_FQ (0) + flags: NAME_FQ (%d) name: "stdClass" __declId: 2 3: AST_ARROW_FUNC - flags: 0 name: "{closure}" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_NAME - flags: NAME_FQ (0) + flags: NAME_FQ (%d) name: "stdClass" name: "param" default: null @@ -93,9 +87,9 @@ AST_STMT_LIST expr: AST_VAR name: "param" returnType: AST_NAME - flags: NAME_NOT_FQ (1) + flags: NAME_NOT_FQ (%d) name: "stdClass" __declId: 3 -Deprecated: ast\parse_code(): Version 50 is deprecated in %s.php on line 16 +Deprecated: ast\parse_code(): Version 50 is deprecated in %sshort_arrow_function_return.php on line 16 Same representation in version 50/70: true \ No newline at end of file diff --git a/tests/stmt_list.phpt b/tests/stmt_list.phpt index cb44a2f..0e35f3f 100644 --- a/tests/stmt_list.phpt +++ b/tests/stmt_list.phpt @@ -49,4 +49,4 @@ AST_STMT_LIST name: "ticks" value: 1 docComment: null - stmts: AST_STMT_LIST + stmts: AST_STMT_LIST \ No newline at end of file diff --git a/tests/true_type.phpt b/tests/true_type.phpt index 26aad58..3f1b324 100644 --- a/tests/true_type.phpt +++ b/tests/true_type.phpt @@ -17,12 +17,10 @@ echo ast_dump($node), "\n"; --EXPECTF-- AST_STMT_LIST 0: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_TYPE flags: TYPE_TRUE (%d) name: "x" diff --git a/tests/try_catch_finally.phpt b/tests/try_catch_finally.phpt index b89c335..711eb0c 100644 --- a/tests/try_catch_finally.phpt +++ b/tests/try_catch_finally.phpt @@ -50,4 +50,4 @@ AST_STMT_LIST expr: "catch 2" finally: AST_STMT_LIST 0: AST_ECHO - expr: "finally" + expr: "finally" \ No newline at end of file diff --git a/tests/type_hints.phpt b/tests/type_hints.phpt index 09fb038..c91cd76 100644 --- a/tests/type_hints.phpt +++ b/tests/type_hints.phpt @@ -19,55 +19,46 @@ echo ast_dump(ast\parse_code($code, $version=70)), "\n"; --EXPECTF-- AST_STMT_LIST 0: AST_FUNC_DECL - flags: 0 name: "test" docComment: null params: AST_PARAM_LIST 0: AST_PARAM - flags: 0 type: AST_NAME flags: NAME_NOT_FQ (1) name: "A" name: "a" default: null 1: AST_PARAM - flags: 0 type: AST_TYPE flags: TYPE_ARRAY (7) name: "b" default: null 2: AST_PARAM - flags: 0 type: AST_TYPE flags: TYPE_CALLABLE (%d) name: "c" default: null 3: AST_PARAM - flags: 0 type: AST_TYPE flags: TYPE_LONG (4) name: "d" default: null 4: AST_PARAM - flags: 0 type: AST_TYPE flags: TYPE_DOUBLE (5) name: "e" default: null 5: AST_PARAM - flags: 0 type: AST_TYPE flags: TYPE_STRING (6) name: "f" default: null 6: AST_PARAM - flags: 0 type: AST_TYPE flags: TYPE_BOOL (%d) name: "g" default: null 7: AST_PARAM - flags: 0 type: AST_TYPE flags: TYPE_ITERABLE (%d) name: "h" diff --git a/tests/unary_ops.phpt b/tests/unary_ops.phpt index f62d832..1fcdb5c 100644 --- a/tests/unary_ops.phpt +++ b/tests/unary_ops.phpt @@ -26,4 +26,4 @@ AST_STMT_LIST expr: 1 2: AST_UNARY_OP flags: UNARY_MINUS (262) - expr: 1 + expr: 1 \ No newline at end of file diff --git a/tests/use_declarations.phpt b/tests/use_declarations.phpt index 36d5cf1..11b6307 100644 --- a/tests/use_declarations.phpt +++ b/tests/use_declarations.phpt @@ -55,4 +55,4 @@ AST_STMT_LIST 1: AST_USE_ELEM flags: 0 name: "baz" - alias: null + alias: null \ No newline at end of file diff --git a/util.php b/util.php index dbe17bb..96c5199 100644 --- a/util.php +++ b/util.php @@ -27,6 +27,9 @@ function get_flag_info() : array { return $info; } +function is_combinable_flag(int $kind) : bool { + return isset(get_flag_info()[1][$kind]); +} function format_flags(int $kind, int $flags) : string { list($exclusive, $combinable) = get_flag_info(); @@ -62,7 +65,7 @@ function ast_dump($ast, int $options = 0) : string { } } - if (ast\kind_uses_flags($ast->kind) || $ast->flags != 0) { + if ((ast\kind_uses_flags($ast->kind) && !is_combinable_flag($ast->kind)) || $ast->flags != 0) { $result .= "\n flags: " . format_flags($ast->kind, $ast->flags); } foreach ($ast->children as $i => $child) { From 26880c1ec604b6bdf4e06563305d3bbc224a2756 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Tue, 9 Aug 2022 17:39:51 -0400 Subject: [PATCH 24/53] Release php-ast 1.1.0 (#231) --- package.xml | 6 +++--- php_ast.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.xml b/package.xml index 666e3b5..6c58676 100644 --- a/package.xml +++ b/package.xml @@ -18,10 +18,10 @@ tandre@php.net yes - 2022-02-12 + 2022-08-09 - 1.1.0dev - 1.1.0dev + 1.1.0 + 1.1.0 stable diff --git a/php_ast.h b/php_ast.h index 14f23a7..2dd62ba 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.1.0dev" +#define PHP_AST_VERSION "1.1.0" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) From d7950c2d7be2dd4a419f63388cf551a017027465 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Tue, 9 Aug 2022 17:42:22 -0400 Subject: [PATCH 25/53] Switch from 1.1.0 to 1.1.1dev --- package.xml | 33 ++++++++++++++++++++++++--------- php_ast.h | 2 +- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/package.xml b/package.xml index 6c58676..86385fb 100644 --- a/package.xml +++ b/package.xml @@ -20,8 +20,8 @@ 2022-08-09 - 1.1.0 - 1.1.0 + 1.1.1dev + 1.1.1dev stable @@ -29,13 +29,7 @@ BSD-3-Clause -- Change documentation files to properly namespace attributes as `#[\AllowDynamicProperties]`. The reflection attributes are already correct. -- Deprecated AST versions 50 and 60. -- Drop support for php <= 7.1 -- Fix test failures seen in php 8.2.0beta2 due to change to var_export's output format. -- Add support for php 8.2 readonly classes. Add `ast\flags\CLASS_READONLY` constant. -- Add support for php 8.2 `true` type. Add `ast\flags\TYPE_TRUE` constant. -- Fix bug in php 8.2 where ZEND_AST_ARROW_FUNC output did not include the stub `AST_RETURN` node that was included in php 8.1 and below. +- TBD @@ -153,6 +147,27 @@ ast + + 2022-08-09 + + 1.1.0 + 1.1.0 + + + stable + stable + + BSD-3-Clause + +- Change documentation files to properly namespace attributes as `#[\AllowDynamicProperties]`. The reflection attributes are already correct. +- Deprecated AST versions 50 and 60. +- Drop support for php <= 7.1 +- Fix test failures seen in php 8.2.0beta2 due to change to var_export's output format. +- Add support for php 8.2 readonly classes. Add `ast\flags\CLASS_READONLY` constant. +- Add support for php 8.2 `true` type. Add `ast\flags\TYPE_TRUE` constant. +- Fix bug in php 8.2 where ZEND_AST_ARROW_FUNC output did not include the stub `AST_RETURN` node that was included in php 8.1 and below. + + 2021-11-27 diff --git a/php_ast.h b/php_ast.h index 2dd62ba..88d91cc 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.1.0" +#define PHP_AST_VERSION "1.1.1-dev" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) From dfca9531020f8b67f7e3d27eed5eae0d362763a8 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 11 Nov 2023 23:29:09 +0100 Subject: [PATCH 26/53] Fix strict-prototypes error --- ast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ast.c b/ast.c index 3c6acfa..62b8f8d 100644 --- a/ast.c +++ b/ast.c @@ -1078,7 +1078,7 @@ static inline zend_bool ast_version_deprecated(zend_long version) { return version < 70; } -static zend_string *ast_version_info() { +static zend_string *ast_version_info(void) { smart_str str = {0}; size_t i; From c132c5d5a4d1d3f2c0ff3deeda5dd915655741ca Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 11 Nov 2023 23:30:05 +0100 Subject: [PATCH 27/53] Remove unused array --- ast.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/ast.c b/ast.c index 62b8f8d..6916adf 100644 --- a/ast.c +++ b/ast.c @@ -275,23 +275,16 @@ static const char *closure_use_flags[] = { NULL }; -#define AST_VISIBILITY_FLAGS \ - AST_FLAG(MODIFIER_PUBLIC), \ - AST_FLAG(MODIFIER_PROTECTED), \ - AST_FLAG(MODIFIER_PRIVATE) #define AST_MODIFIER_FLAGS \ - AST_VISIBILITY_FLAGS, \ + AST_FLAG(MODIFIER_PUBLIC), \ + AST_FLAG(MODIFIER_PROTECTED), \ + AST_FLAG(MODIFIER_PRIVATE) \ AST_FLAG(MODIFIER_STATIC), \ AST_FLAG(MODIFIER_ABSTRACT), \ AST_FLAG(MODIFIER_FINAL), \ AST_FLAG(MODIFIER_READONLY) -static const char *visibility_flags[] = { - AST_VISIBILITY_FLAGS, - NULL -}; - static const char *modifier_flags[] = { AST_MODIFIER_FLAGS, NULL From 741eda1c7262bfb5c5d35b93232f54a7bc0d7e79 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 11 Nov 2023 23:33:02 +0100 Subject: [PATCH 28/53] Add missing comma Ooops. --- ast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ast.c b/ast.c index 6916adf..e98b54f 100644 --- a/ast.c +++ b/ast.c @@ -279,7 +279,7 @@ static const char *closure_use_flags[] = { #define AST_MODIFIER_FLAGS \ AST_FLAG(MODIFIER_PUBLIC), \ AST_FLAG(MODIFIER_PROTECTED), \ - AST_FLAG(MODIFIER_PRIVATE) \ + AST_FLAG(MODIFIER_PRIVATE), \ AST_FLAG(MODIFIER_STATIC), \ AST_FLAG(MODIFIER_ABSTRACT), \ AST_FLAG(MODIFIER_FINAL), \ From 71f6a54d057927d42e920e8385c503292623288a Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 11 Nov 2023 23:55:27 +0100 Subject: [PATCH 29/53] Add support for typed class constants --- README.md | 12 +++- ast.c | 29 +++++++++- ast_data.c | 1 + scripts/generate_ast_data.php | 2 +- tests/class_const_types.phpt | 95 +++++++++++++++++++++++++++++++ tests/get_supported_versions.phpt | 10 +++- tests/version_errors.phpt | 4 +- 7 files changed, 143 insertions(+), 10 deletions(-) create mode 100644 tests/class_const_types.phpt diff --git a/README.md b/README.md index d02f9da..3f4db06 100644 --- a/README.md +++ b/README.md @@ -387,8 +387,8 @@ AST_CAST: expr AST_CATCH: class, var, stmts AST_CLASS: name, docComment, extends, implements, stmts, (for enums) type AST_CLASS_CONST: class, const -AST_CLASS_CONST_GROUP class, attributes // version 80+ -AST_CLASS_NAME: class // version 70+ +AST_CLASS_CONST_GROUP class, attributes, type // version 80+ +AST_CLASS_NAME: class // version 70+ AST_CLONE: expr AST_CLOSURE: name, docComment, params, uses, stmts, returnType, attributes AST_CLOSURE_VAR: name @@ -504,7 +504,13 @@ function accepts a boolean argument that determines whether deprecated versions In the following the changes in the respective AST versions, as well as their current support state, are listed. -### 90 (current) +### 100 (development) + +Supported since 1.1.1 (TBD). + +* Add a `type` child node for all AST_CLASS_CONST_GROUP nodes. + +### 90 (stable) Supported since 1.0.14 (2021-07-24) diff --git a/ast.c b/ast.c index e98b54f..9a89f0b 100644 --- a/ast.c +++ b/ast.c @@ -464,6 +464,12 @@ static inline zend_bool ast_is_name(zend_ast *ast, zend_ast *parent, uint32_t i) ; } +#if PHP_VERSION_ID >= 80300 + if (i == 2) { + return parent->kind == ZEND_AST_CLASS_CONST_GROUP; + } +#endif + if (i == 1) { return parent->kind == ZEND_AST_INSTANCEOF; } @@ -504,6 +510,11 @@ static inline zend_bool ast_is_type(zend_ast *ast, zend_ast *parent, uint32_t i) #endif ; } +#if PHP_VERSION_ID >= 80300 + if (i == 2) { + return parent->kind == ZEND_AST_CLASS_CONST_GROUP; + } +#endif if (i == 3) { return parent->kind == ZEND_AST_CLOSURE || parent->kind == ZEND_AST_FUNC_DECL #if PHP_VERSION_ID >= 70400 @@ -761,6 +772,13 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t } } #endif +#if PHP_VERSION_ID >= 80300 + if (ast_kind == ZEND_AST_CLASS_CONST_GROUP && i == 2) { + if (state->version < 100) { + continue; + } + } +#endif #endif if (ast_is_name(child, ast, i)) { ast_name_to_zval(child, ast, &child_zv, i, state); @@ -850,6 +868,15 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t zend_hash_add_new(ht, AST_STR(str_type), &tmp); } } +#endif +#if PHP_VERSION_ID < 80300 + if (ast_kind == ZEND_AST_CLASS_CONST_GROUP) { + if (state->version >= 100) { + zval tmp; + ZVAL_NULL(&tmp); + zend_hash_add_new(ht, AST_STR(str_type), &tmp); + } + } #endif ZVAL_LONG(&id_zval, state->declIdCounter); state->declIdCounter++; @@ -1064,7 +1091,7 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { #endif } -static const zend_long versions[] = {50, 60, 70, 80, 85, 90}; +static const zend_long versions[] = {50, 60, 70, 80, 85, 90, 100}; static const size_t versions_count = sizeof(versions)/sizeof(versions[0]); static inline zend_bool ast_version_deprecated(zend_long version) { diff --git a/ast_data.c b/ast_data.c index 26cc92d..f2b7fa8 100644 --- a/ast_data.c +++ b/ast_data.c @@ -323,6 +323,7 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { switch (child) { case 0: return AST_STR(str_const); case 1: return AST_STR(str_attributes); + case 2: return AST_STR(str_type); } return NULL; case ZEND_AST_DIM: diff --git a/scripts/generate_ast_data.php b/scripts/generate_ast_data.php index 02cc93a..1629b3a 100644 --- a/scripts/generate_ast_data.php +++ b/scripts/generate_ast_data.php @@ -98,7 +98,7 @@ 'ZEND_AST_CLASS_NAME' => ['class'], /* 2 child nodes */ - 'ZEND_AST_CLASS_CONST_GROUP' => ['const', 'attributes'], + 'ZEND_AST_CLASS_CONST_GROUP' => ['const', 'attributes', 'type'], 'ZEND_AST_DIM' => ['expr', 'dim'], 'ZEND_AST_PROP' => ['expr', 'prop'], 'ZEND_AST_NULLSAFE_PROP' => ['expr', 'prop'], diff --git a/tests/class_const_types.phpt b/tests/class_const_types.phpt new file mode 100644 index 0000000..b3c4e39 --- /dev/null +++ b/tests/class_const_types.phpt @@ -0,0 +1,95 @@ +--TEST-- +PHP 8.3 class constant types +--SKIPIF-- += 8.3 only'); ?> +--FILE-- + --EXPECT-- -array(6) { +array(7) { [0]=> int(50) [1]=> @@ -21,8 +21,10 @@ array(6) { int(85) [5]=> int(90) + [6]=> + int(100) } -array(4) { +array(5) { [0]=> int(70) [1]=> @@ -31,4 +33,6 @@ array(4) { int(85) [3]=> int(90) -} \ No newline at end of file + [4]=> + int(100) +} diff --git a/tests/version_errors.phpt b/tests/version_errors.phpt index 6186821..6759b13 100644 --- a/tests/version_errors.phpt +++ b/tests/version_errors.phpt @@ -10,7 +10,7 @@ try { } try { - ast\parse_code('getMessage(), "\n"; } @@ -18,4 +18,4 @@ try { ?> --EXPECTF-- No version specified. Current version is %d. All versions (including experimental): {%d, %s} -Unknown version 100. Current version is %d. All versions (including experimental): {%d, %s} +Unknown version 10000. Current version is %d. All versions (including experimental): {%d, %s} From 52ac25d7e4f194e309bbb175f9cbd3ce0e0e43ad Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 12 Nov 2023 00:00:40 +0100 Subject: [PATCH 30/53] Test PHP 8.3 in CI --- .github/workflows/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 226abac..bfc4cd0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,7 +32,8 @@ jobs: - PHP_VERSION: '7.4' - PHP_VERSION: '8.0' - PHP_VERSION: '8.1' - - PHP_VERSION: '8.2.0beta2' + - PHP_VERSION: '8.2' + - PHP_VERSION: '8.3.0RC5' # Steps represent a sequence of tasks that will be executed as part of the job steps: From a64955106f155788e1c2ac3cbbf1d9c71281dd9c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 12 Nov 2023 12:23:57 +0100 Subject: [PATCH 31/53] Release 1.1.1 --- README.md | 4 ++-- package.xml | 10 ++++++---- php_ast.h | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3f4db06..9addbce 100644 --- a/README.md +++ b/README.md @@ -504,9 +504,9 @@ function accepts a boolean argument that determines whether deprecated versions In the following the changes in the respective AST versions, as well as their current support state, are listed. -### 100 (development) +### 100 (current) -Supported since 1.1.1 (TBD). +Supported since 1.1.1 (2023-11-12). * Add a `type` child node for all AST_CLASS_CONST_GROUP nodes. diff --git a/package.xml b/package.xml index 86385fb..6142712 100644 --- a/package.xml +++ b/package.xml @@ -18,10 +18,10 @@ tandre@php.net yes - 2022-08-09 + 2023-11-12 - 1.1.1dev - 1.1.1dev + 1.1.1 + 1.1.1 stable @@ -29,7 +29,8 @@ BSD-3-Clause -- TBD +- Added support for PHP 8.3 +- In version 100, `AST_CLASS_CONST_GROUP` nodes have a `type` child node to represent typed class constants. @@ -58,6 +59,7 @@ + diff --git a/php_ast.h b/php_ast.h index 88d91cc..6a03961 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.1.1-dev" +#define PHP_AST_VERSION "1.1.1" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) From 5b3b99079a96a11a3dd0d1e51a0d193b6e1ac7c3 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 12 Nov 2023 12:30:34 +0100 Subject: [PATCH 32/53] Back to dev --- package.xml | 22 ++++++++++++++++++---- php_ast.h | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/package.xml b/package.xml index 6142712..58cd8c1 100644 --- a/package.xml +++ b/package.xml @@ -20,8 +20,8 @@ 2023-11-12 - 1.1.1 - 1.1.1 + 1.1.2dev + 1.1.2dev stable @@ -29,8 +29,7 @@ BSD-3-Clause -- Added support for PHP 8.3 -- In version 100, `AST_CLASS_CONST_GROUP` nodes have a `type` child node to represent typed class constants. +- TBD @@ -149,6 +148,21 @@ ast + + + 1.1.1 + 1.1.1 + + + stable + stable + + BSD-3-Clause + +- Added support for PHP 8.3 +- In version 100, `AST_CLASS_CONST_GROUP` nodes have a `type` child node to represent typed class constants. + + 2022-08-09 diff --git a/php_ast.h b/php_ast.h index 6a03961..d326e1b 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.1.1" +#define PHP_AST_VERSION "1.1.2dev" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) From 4c5efd5dbf139b9ac80b1df151b89112bb5bd779 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 12 Nov 2023 12:31:44 +0100 Subject: [PATCH 33/53] Update current version number --- README.md | 6 +++--- RELEASE_CHECKLIST | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9addbce..06d6233 100644 --- a/README.md +++ b/README.md @@ -59,12 +59,12 @@ Basic usage Code can be parsed using either `ast\parse_code()`, which accepts a code string, or `ast\parse_file()`, which accepts a file path. Additionally, both functions require a `$version` -argument to ensure forward-compatibility. The current version is 90. +argument to ensure forward-compatibility. The current version is 100. ```php -$ast = ast\parse_code(' Date: Sat, 10 Aug 2024 11:19:58 -0400 Subject: [PATCH 34/53] Support PHP 8.4 property hooks in AST version 110 (#241) Add 'hooks' child of type `AST_PROPERTY_HOOK` to `AST_PROP_ELEM` and `AST_PARAM` (constructor property promotion) in AST version 110. In version 110, change `AST_CLOSURE` and `AST_ARROW_FUNC` nodes to have no `name`. Fixes #240 --- .dockerignore | 4 + .github/workflows/main.yml | 3 +- .gitignore | 4 + README.md | 17 +++- ast.c | 69 ++++++++++++--- ast_data.c | 10 +++ ast_str_defs.h | 98 ++++++++++----------- ast_stub.php | 10 +-- package.xml | 20 +++-- php_ast.h | 12 ++- scripts/generate_ast_data.php | 11 ++- tests/get_supported_versions.phpt | 8 +- tests/metadata.phpt | 4 +- tests/php74_dim_alternative_syntax.phpt | 4 +- tests/php82_encaps_list.phpt | 4 +- tests/php82_encaps_list2.phpt | 43 +++++++++ tests/php84_dim_alternative_syntax.phpt | 23 +++++ tests/php84_property_hook.phpt | 54 ++++++++++++ tests/php84_property_hook2.phpt | 110 ++++++++++++++++++++++++ tests/php84_property_hook3.phpt | 60 +++++++++++++ tests/php84_property_hook4.phpt | 61 +++++++++++++ tests/prop_doc_comments.phpt | 38 +++++++- 22 files changed, 577 insertions(+), 90 deletions(-) create mode 100644 tests/php82_encaps_list2.phpt create mode 100644 tests/php84_dim_alternative_syntax.phpt create mode 100644 tests/php84_property_hook.phpt create mode 100644 tests/php84_property_hook2.phpt create mode 100644 tests/php84_property_hook3.phpt create mode 100644 tests/php84_property_hook4.phpt diff --git a/.dockerignore b/.dockerignore index 2640be1..cb9f075 100644 --- a/.dockerignore +++ b/.dockerignore @@ -38,3 +38,7 @@ tests/*.out tests/*.exp tests/*.log tests/*.sh +*.dep +*~ +tags +configure.ac diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bfc4cd0..6b5371e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -33,7 +33,8 @@ jobs: - PHP_VERSION: '8.0' - PHP_VERSION: '8.1' - PHP_VERSION: '8.2' - - PHP_VERSION: '8.3.0RC5' + - PHP_VERSION: '8.3' + - PHP_VERSION: '8.4.0alpha4' # Steps represent a sequence of tasks that will be executed as part of the job steps: diff --git a/.gitignore b/.gitignore index f1f7125..9aea666 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,7 @@ tests/*.php tests/*.exp tests/*.log tests/*.sh +*.dep +*~ +tags +configure.ac diff --git a/README.md b/README.md index 06d6233..7ecc17a 100644 --- a/README.md +++ b/README.md @@ -374,7 +374,7 @@ This section lists the AST node kinds that are supported and the names of their ``` AST_ARRAY_ELEM: value, key -AST_ARROW_FUNC: name, docComment, params, stmts, returnType, attributes +AST_ARROW_FUNC: name, docComment, params, stmts, returnType, attributes // name removed in version 110 AST_ASSIGN: var, expr AST_ASSIGN_OP: var, expr AST_ASSIGN_REF: var, expr @@ -390,7 +390,7 @@ AST_CLASS_CONST: class, const AST_CLASS_CONST_GROUP class, attributes, type // version 80+ AST_CLASS_NAME: class // version 70+ AST_CLONE: expr -AST_CLOSURE: name, docComment, params, uses, stmts, returnType, attributes +AST_CLOSURE: name, docComment, params, uses, stmts, returnType, attributes // name removed in version 110 AST_CLOSURE_VAR: name AST_CONDITIONAL: cond, true, false AST_CONST: name @@ -430,15 +430,17 @@ AST_NEW: class, args AST_NULLABLE_TYPE: type // Used only since PHP 7.1 AST_NULLSAFE_METHOD_CALL: expr, method, args // php 8.0 null safe operator AST_NULLSAFE_PROP: expr, prop // php 8.0 null safe operator -AST_PARAM: type, name, default, attributes, docComment +AST_PARAM: type, name, default, attributes, docComment, hooks // 'hooks' field added in version 110 AST_POST_DEC: var AST_POST_INC: var AST_PRE_DEC: var AST_PRE_INC: var AST_PRINT: expr AST_PROP: expr, prop -AST_PROP_ELEM: name, default, docComment +AST_PROP_ELEM: name, default, docComment, hooks // 'hooks' field added in version 110 AST_PROP_GROUP: type, props, attributes // version 70+ +AST_PROPERTY_HOOK: name, docComment, params, stmts, attributes // version 110+ +AST_PROPERTY_HOOK_SHORT_BODY: expr AST_REF: var // only used in foreach ($a as &$v) AST_RETURN: expr AST_SHELL_EXEC: expr @@ -504,6 +506,13 @@ function accepts a boolean argument that determines whether deprecated versions In the following the changes in the respective AST versions, as well as their current support state, are listed. +### 110 (current) + +Supported since 1.1.2 (2024-08-08). + +* Add a `hooks` child node for `AST_PROP_ELEM` (PHP 8.4 property hooks) and `AST_PARAM` (constructor property promotion can have property hooks) (AST version 110+) +* Add new node kinds `AST_PROPERTY_HOOK` and `AST_PROPERTY_HOOK_SHORT_BODY`. + ### 100 (current) Supported since 1.1.1 (2023-11-12). diff --git a/ast.c b/ast.c index 9a89f0b..e372d75 100644 --- a/ast.c +++ b/ast.c @@ -71,7 +71,7 @@ #define AST_METADATA_PROP_FLAGS(object) OBJ_PROP_NUM((object), 2) #define AST_METADATA_PROP_FLAGS_COMBINABLE(object) OBJ_PROP_NUM((object), 3) -#define AST_CURRENT_VERSION 90 +#define AST_CURRENT_VERSION 110 /* Additional flags for BINARY_OP */ #define AST_BINARY_IS_GREATER 256 @@ -117,6 +117,10 @@ # define ZEND_ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR (1<<1) #endif +#if PHP_VERSION_ID >= 80400 +# define ZEND_DIM_ALTERNATIVE_SYNTAX (1<<1) +#endif + /* This contains state of the ast Node creator. */ typedef struct ast_state_info { zend_long version; @@ -336,6 +340,7 @@ static const ast_flag_info flag_info[] = { { ZEND_AST_FUNC_DECL, 1, func_flags }, { ZEND_AST_CLOSURE, 1, func_flags }, { ZEND_AST_ARROW_FUNC, 1, func_flags }, + { ZEND_AST_PROPERTY_HOOK, 1, func_flags }, { ZEND_AST_PROP_DECL, 1, modifier_flags }, { ZEND_AST_PROP_GROUP, 1, modifier_flags }, { ZEND_AST_CLASS_CONST_DECL, 1, modifier_flags }, @@ -423,9 +428,11 @@ static inline zend_bool ast_kind_uses_attr(zend_ast_kind kind) { || kind == ZEND_AST_VAR; } +/* Returns true if nodes of this kind are represented with the C struct zend_ast_decl. */ static inline zend_bool ast_kind_is_decl(zend_ast_kind kind) { return kind == ZEND_AST_FUNC_DECL || kind == ZEND_AST_CLOSURE || kind == ZEND_AST_ARROW_FUNC + || kind == ZEND_AST_PROPERTY_HOOK || kind == ZEND_AST_METHOD || kind == ZEND_AST_CLASS; } @@ -741,7 +748,7 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t switch (ast_kind) { case ZEND_AST_PARAM: if (i >= 3) { - /* Skip attributes and doc comment */ + /* Skip attributes and doc comment and hooks. */ continue; } break; @@ -779,6 +786,24 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t } } #endif +#if PHP_VERSION_ID >= 80400 + if (ast_kind == ZEND_AST_PROP_ELEM && i == 3) { + if (state->version < 110) { + continue; + } + } + if (ast_kind == ZEND_AST_PROPERTY_HOOK && (i == 1 || i == 3)) { + /* Property hooks don't have uses/returnType but they do have params/stmts/attributes. */ + continue; + } + /* Constructor property promotion shorthand can have property hooks. */ + if (ast_kind == ZEND_AST_PARAM && i == 5) { + if (state->version < 110) { + continue; + } + } +#endif + #endif if (ast_is_name(child, ast, i)) { ast_name_to_zval(child, ast, &child_zv, i, state); @@ -850,6 +875,17 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t } #endif +#if PHP_VERSION_ID < 80400 + if (state->version >= 110) { + if (ast_kind == ZEND_AST_PARAM || ast_kind == ZEND_AST_PROP_ELEM) { + zval tmp; + ZVAL_NULL(&tmp); + zend_hash_add_new(ht, AST_STR(str_hooks), &tmp); + return; + } + } +#endif + if (ast_kind_is_decl(ast_kind)) { zval id_zval; #if PHP_VERSION_ID < 80000 @@ -1016,18 +1052,19 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { zend_object *obj = Z_OBJ_P(zv); - AST_NODE_SET_PROP_KIND(obj, ast->kind); + zend_ast_kind kind = ast->kind; + AST_NODE_SET_PROP_KIND(obj, kind); AST_NODE_SET_PROP_LINENO(obj, zend_ast_get_lineno(ast)); array_init(AST_NODE_PROP_CHILDREN(obj)); HashTable *children = Z_ARRVAL_P(AST_NODE_PROP_CHILDREN(obj)); - if (ast_kind_is_decl(ast->kind)) { + if (ast_kind_is_decl(kind)) { zend_ast_decl *decl = (zend_ast_decl *) ast; uint32_t flags = decl->flags; #if PHP_VERSION_ID >= 80200 - if (ast->kind == ZEND_AST_CLASS) { + if (kind == ZEND_AST_CLASS) { flags &= ~ZEND_ACC_NO_DYNAMIC_PROPERTIES; } #endif @@ -1037,14 +1074,22 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { // This is an undeclared dynamic property and has no cache slot. ast_update_property_long(zv, AST_STR(str_endLineno), decl->end_lineno); - if (decl->name) { + if (kind == ZEND_AST_CLOSURE || kind == ZEND_AST_ARROW_FUNC) { + if (state->version < 110) { + ZVAL_STR(&tmp_zv, AST_STR(str_bracketed_closure)); + } else { + /* These never have names. */ + ZVAL_UNDEF(&tmp_zv); + } + } else if (decl->name) { ZVAL_STR(&tmp_zv, decl->name); Z_TRY_ADDREF(tmp_zv); } else { ZVAL_NULL(&tmp_zv); } - - zend_hash_add_new(children, AST_STR(str_name), &tmp_zv); + if (!Z_ISUNDEF(tmp_zv)) { + zend_hash_add_new(children, AST_STR(str_name), &tmp_zv); + } if (decl->doc_comment) { ZVAL_STR(&tmp_zv, decl->doc_comment); @@ -1091,7 +1136,7 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { #endif } -static const zend_long versions[] = {50, 60, 70, 80, 85, 90, 100}; +static const zend_long versions[] = {50, 60, 70, 80, 85, 90, 100, 110}; static const size_t versions_count = sizeof(versions)/sizeof(versions[0]); static inline zend_bool ast_version_deprecated(zend_long version) { @@ -1402,9 +1447,9 @@ PHP_MINIT_FUNCTION(ast) { zval zv_null; ZVAL_NULL(&zv_null); -#define X(str) \ +#define X(str, value) \ AST_STR(str_ ## str) = zend_new_interned_string( \ - zend_string_init(#str, sizeof(#str) - 1, 1)); + zend_string_init(value, sizeof(value) - 1, 1)); AST_STR_DEFS #undef X @@ -1544,7 +1589,7 @@ PHP_MINIT_FUNCTION(ast) { } PHP_MSHUTDOWN_FUNCTION(ast) { -#define X(str) zend_string_release(AST_STR(str_ ## str)); +#define X(str, value) zend_string_release(AST_STR(str_ ## str)); AST_STR_DEFS #undef X diff --git a/ast_data.c b/ast_data.c index f2b7fa8..3d19b2f 100644 --- a/ast_data.c +++ b/ast_data.c @@ -31,6 +31,7 @@ const zend_ast_kind ast_kinds[] = { ZEND_AST_METHOD, ZEND_AST_ARROW_FUNC, ZEND_AST_CLASS, + ZEND_AST_PROPERTY_HOOK, ZEND_AST_MAGIC_CONST, ZEND_AST_TYPE, ZEND_AST_CALLABLE_CONVERT, @@ -63,6 +64,7 @@ const zend_ast_kind ast_kinds[] = { ZEND_AST_BREAK, ZEND_AST_CONTINUE, ZEND_AST_CLASS_NAME, + ZEND_AST_PROPERTY_HOOK_SHORT_BODY, ZEND_AST_CLASS_CONST_GROUP, ZEND_AST_DIM, ZEND_AST_PROP, @@ -145,6 +147,7 @@ const char *ast_kind_to_name(zend_ast_kind kind) { case ZEND_AST_METHOD: return "AST_METHOD"; case ZEND_AST_ARROW_FUNC: return "AST_ARROW_FUNC"; case ZEND_AST_CLASS: return "AST_CLASS"; + case ZEND_AST_PROPERTY_HOOK: return "AST_PROPERTY_HOOK"; case ZEND_AST_MAGIC_CONST: return "AST_MAGIC_CONST"; case ZEND_AST_TYPE: return "AST_TYPE"; case ZEND_AST_CALLABLE_CONVERT: return "AST_CALLABLE_CONVERT"; @@ -177,6 +180,7 @@ const char *ast_kind_to_name(zend_ast_kind kind) { case ZEND_AST_BREAK: return "AST_BREAK"; case ZEND_AST_CONTINUE: return "AST_CONTINUE"; case ZEND_AST_CLASS_NAME: return "AST_CLASS_NAME"; + case ZEND_AST_PROPERTY_HOOK_SHORT_BODY: return "AST_PROPERTY_HOOK_SHORT_BODY"; case ZEND_AST_CLASS_CONST_GROUP: return "AST_CLASS_CONST_GROUP"; case ZEND_AST_DIM: return "AST_DIM"; case ZEND_AST_PROP: return "AST_PROP"; @@ -248,6 +252,7 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { case ZEND_AST_CLOSURE: case ZEND_AST_METHOD: case ZEND_AST_ARROW_FUNC: + case ZEND_AST_PROPERTY_HOOK: switch (child) { case 0: return AST_STR(str_params); case 1: return AST_STR(str_uses); @@ -282,6 +287,7 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { case ZEND_AST_RETURN: case ZEND_AST_ECHO: case ZEND_AST_THROW: + case ZEND_AST_PROPERTY_HOOK_SHORT_BODY: switch (child) { case 0: return AST_STR(str_expr); } @@ -424,6 +430,7 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { case 0: return AST_STR(str_name); case 1: return AST_STR(str_default); case 2: return AST_STR(str_docComment); + case 3: return AST_STR(str_hooks); } return NULL; case ZEND_AST_PROP_GROUP: @@ -561,6 +568,7 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) { case 2: return AST_STR(str_default); case 3: return AST_STR(str_attributes); case 4: return AST_STR(str_docComment); + case 5: return AST_STR(str_hooks); } return NULL; } @@ -599,6 +607,7 @@ void ast_register_kind_constants(INIT_FUNC_ARGS) { REGISTER_NS_LONG_CONSTANT("ast", "AST_METHOD", ZEND_AST_METHOD, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_ARROW_FUNC", ZEND_AST_ARROW_FUNC, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_CLASS", ZEND_AST_CLASS, CONST_CS | CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("ast", "AST_PROPERTY_HOOK", ZEND_AST_PROPERTY_HOOK, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_MAGIC_CONST", ZEND_AST_MAGIC_CONST, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_TYPE", ZEND_AST_TYPE, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_CALLABLE_CONVERT", ZEND_AST_CALLABLE_CONVERT, CONST_CS | CONST_PERSISTENT); @@ -631,6 +640,7 @@ void ast_register_kind_constants(INIT_FUNC_ARGS) { REGISTER_NS_LONG_CONSTANT("ast", "AST_BREAK", ZEND_AST_BREAK, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_CONTINUE", ZEND_AST_CONTINUE, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_CLASS_NAME", ZEND_AST_CLASS_NAME, CONST_CS | CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("ast", "AST_PROPERTY_HOOK_SHORT_BODY", ZEND_AST_PROPERTY_HOOK_SHORT_BODY, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_CLASS_CONST_GROUP", ZEND_AST_CLASS_CONST_GROUP, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_DIM", ZEND_AST_DIM, CONST_CS | CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("ast", "AST_PROP", ZEND_AST_PROP, CONST_CS | CONST_PERSISTENT); diff --git a/ast_str_defs.h b/ast_str_defs.h index dac5ff0..559dcb1 100644 --- a/ast_str_defs.h +++ b/ast_str_defs.h @@ -2,53 +2,55 @@ #define AST_STR_DEFS_H #define AST_STR_DEFS \ - X(kind) \ - X(flags) \ - X(lineno) \ - X(children) \ - X(name) \ - X(docComment) \ - X(endLineno) \ - X(__declId) \ - X(flagsCombinable) \ - X(type) \ - X(params) \ - X(uses) \ - X(stmts) \ - X(returnType) \ - X(attributes) \ - X(extends) \ - X(implements) \ - X(expr) \ - X(var) \ - X(offset) \ - X(label) \ - X(depth) \ - X(class) \ - X(const) \ - X(dim) \ - X(prop) \ - X(args) \ - X(left) \ - X(right) \ - X(value) \ - X(key) \ - X(default) \ - X(cond) \ - X(declares) \ - X(props) \ - X(traits) \ - X(adaptations) \ - X(method) \ - X(insteadof) \ - X(alias) \ - X(prefix) \ - X(true) \ - X(false) \ - X(try) \ - X(catches) \ - X(finally) \ - X(init) \ - X(loop) \ + X(kind, "kind") \ + X(flags, "flags") \ + X(lineno, "lineno") \ + X(children, "children") \ + X(name, "name") \ + X(docComment, "docComment") \ + X(endLineno, "endLineno") \ + X(__declId, "__declId") \ + X(flagsCombinable, "flagsCombinable") \ + X(type, "type") \ + X(params, "params") \ + X(uses, "uses") \ + X(stmts, "stmts") \ + X(returnType, "returnType") \ + X(attributes, "attributes") \ + X(extends, "extends") \ + X(implements, "implements") \ + X(expr, "expr") \ + X(var, "var") \ + X(offset, "offset") \ + X(label, "label") \ + X(depth, "depth") \ + X(class, "class") \ + X(const, "const") \ + X(dim, "dim") \ + X(prop, "prop") \ + X(args, "args") \ + X(left, "left") \ + X(right, "right") \ + X(value, "value") \ + X(key, "key") \ + X(default, "default") \ + X(cond, "cond") \ + X(declares, "declares") \ + X(hooks, "hooks") \ + X(props, "props") \ + X(traits, "traits") \ + X(adaptations, "adaptations") \ + X(method, "method") \ + X(insteadof, "insteadof") \ + X(alias, "alias") \ + X(prefix, "prefix") \ + X(true, "true") \ + X(false, "false") \ + X(try, "try") \ + X(catches, "catches") \ + X(finally, "finally") \ + X(init, "init") \ + X(loop, "loop") \ + X(bracketed_closure, "{closure}") \ #endif diff --git a/ast_stub.php b/ast_stub.php index 095705b..3a6cfcd 100644 --- a/ast_stub.php +++ b/ast_stub.php @@ -69,7 +69,7 @@ const AST_BREAK = 286; const AST_CONTINUE = 287; const AST_CLASS_NAME = 276; -const AST_CLASS_CONST_GROUP = 546; +const AST_CLASS_CONST_GROUP = 777; const AST_DIM = 512; const AST_PROP = 513; const AST_NULLSAFE_PROP = 514; @@ -101,10 +101,10 @@ const AST_USE_ELEM = 543; const AST_TRAIT_ALIAS = 544; const AST_GROUP_USE = 545; -const AST_ATTRIBUTE = 547; -const AST_MATCH = 548; -const AST_MATCH_ARM = 549; -const AST_NAMED_ARG = 550; +const AST_ATTRIBUTE = 546; +const AST_MATCH = 547; +const AST_MATCH_ARM = 548; +const AST_NAMED_ARG = 549; const AST_METHOD_CALL = 768; const AST_NULLSAFE_METHOD_CALL = 769; const AST_STATIC_CALL = 770; diff --git a/package.xml b/package.xml index 58cd8c1..537e52a 100644 --- a/package.xml +++ b/package.xml @@ -18,10 +18,10 @@ tandre@php.net yes - 2023-11-12 + 2024-08-10 - 1.1.2dev - 1.1.2dev + 1.1.2 + 1.1.2 stable @@ -29,7 +29,9 @@ BSD-3-Clause -- TBD +- Fix compilation errors in PHP 8.4. +- In version 110, `AST_PARAM` and `AST_PROP_ELEM` nodes have a `hooks` node for property hooks (https://wiki.php.net/rfc/property-hooks) +- In version 110, `AST_CLOSURE` and `AST_ARROW_FUNC` nodes have no `name`. @@ -112,17 +114,23 @@ - + + + + + + + - + diff --git a/php_ast.h b/php_ast.h index d326e1b..30d8af8 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.1.2dev" +#define PHP_AST_VERSION "1.1.2" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) @@ -30,7 +30,7 @@ ZEND_EXTERN_MODULE_GLOBALS(ast) #define AST_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(ast, v) typedef struct _ast_str_globals { -#define X(str) zend_string *str_ ## str; +#define X(str, value) zend_string *str_ ## str; AST_STR_DEFS #undef X } ast_str_globals; @@ -49,6 +49,7 @@ extern ast_str_globals str_globals; // NOTE: The first hex digit is the number of child nodes a given kind has # define ZEND_AST_CLASS_NAME 0x1ff # define ZEND_AST_PROP_GROUP 0x2ff +// ZEND_AST_ARROW_FUNC technically should have been in the ZEND_AST_SPECIAL_SHIFT group, but keeping this value for compatibility with older releases. (e.g. serialized ast Nodes) # define ZEND_AST_ARROW_FUNC 0x5ff #endif @@ -85,6 +86,13 @@ extern ast_str_globals str_globals; # define ZEND_ACC_READONLY_CLASS (1 << 23) #endif +#if PHP_VERSION_ID < 80400 +# define ZEND_AST_PROPERTY_HOOK ((1 << (ZEND_AST_SPECIAL_SHIFT + 1)) - 1) +// NOTE: The first hex digit is the number of child nodes a given kind has +# define ZEND_AST_PROPERTY_HOOK_SHORT_BODY 0x1fe +# define ZEND_AST_PARENT_PROPERTY_HOOK_CALL 0x2f8 +#endif + /* Pretend it still exists */ # define ZEND_AST_LIST ((1 << (ZEND_AST_IS_LIST_SHIFT + 1)) - 1) diff --git a/scripts/generate_ast_data.php b/scripts/generate_ast_data.php index 1629b3a..b68dfa2 100644 --- a/scripts/generate_ast_data.php +++ b/scripts/generate_ast_data.php @@ -59,6 +59,7 @@ 'ZEND_AST_METHOD' => $funcNames, 'ZEND_AST_ARROW_FUNC' => $funcNames, 'ZEND_AST_CLASS' => ['extends', 'implements', 'stmts', 'attributes', 'type'], + 'ZEND_AST_PROPERTY_HOOK' => $funcNames, // only params/stmts are used. /* 0 child nodes */ 'ZEND_AST_MAGIC_CONST' => [], @@ -96,6 +97,7 @@ 'ZEND_AST_BREAK' => ['depth'], 'ZEND_AST_CONTINUE' => ['depth'], 'ZEND_AST_CLASS_NAME' => ['class'], + 'ZEND_AST_PROPERTY_HOOK_SHORT_BODY' => ['expr'], /* 2 child nodes */ 'ZEND_AST_CLASS_CONST_GROUP' => ['const', 'attributes', 'type'], @@ -121,7 +123,7 @@ 'ZEND_AST_SWITCH' => ['cond', 'stmts'], 'ZEND_AST_SWITCH_CASE' => ['cond', 'stmts'], 'ZEND_AST_DECLARE' => ['declares', 'stmts'], - 'ZEND_AST_PROP_ELEM' => ['name', 'default', 'docComment'], + 'ZEND_AST_PROP_ELEM' => ['name', 'default', 'docComment', 'hooks'], 'ZEND_AST_PROP_GROUP' => ['type', 'props', 'attributes'], 'ZEND_AST_CONST_ELEM' => ['name', 'value', 'docComment'], 'ZEND_AST_USE_TRAIT' => ['traits', 'adaptations'], @@ -150,8 +152,8 @@ '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'], + /* 6 child nodes */ + 'ZEND_AST_PARAM' => ['type', 'name', 'default', 'attributes', 'docComment', 'hooks'], ]; $listNodes = [ @@ -265,8 +267,9 @@ $strings = get_possible_strings($names); $strDefs = []; foreach ($strings as $name) { - $strDefs[] .= "\tX($name) \\"; + $strDefs[] = "\tX($name, \"$name\") \\"; } +$strDefs[] = "\tX(bracketed_closure, \"{closure}\") \\"; $strDefsHeader = str_replace('{STR_DEFS}', implode("\n", $strDefs), $strDefsHeader); file_put_contents($strDefsFile, $strDefsHeader); diff --git a/tests/get_supported_versions.phpt b/tests/get_supported_versions.phpt index 57e482a..0f1b787 100644 --- a/tests/get_supported_versions.phpt +++ b/tests/get_supported_versions.phpt @@ -8,7 +8,7 @@ var_dump(ast\get_supported_versions(true)); ?> --EXPECT-- -array(7) { +array(8) { [0]=> int(50) [1]=> @@ -23,8 +23,10 @@ array(7) { int(90) [6]=> int(100) + [7]=> + int(110) } -array(5) { +array(6) { [0]=> int(70) [1]=> @@ -35,4 +37,6 @@ array(5) { int(90) [4]=> int(100) + [5]=> + int(110) } diff --git a/tests/metadata.phpt b/tests/metadata.phpt index a3363da..615e151 100644 --- a/tests/metadata.phpt +++ b/tests/metadata.phpt @@ -56,6 +56,7 @@ AST_CLOSURE: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE AST_METHOD: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY, FUNC_RETURNS_REF, FUNC_GENERATOR] AST_ARROW_FUNC: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY, FUNC_RETURNS_REF, FUNC_GENERATOR] AST_CLASS: (combinable) [CLASS_ABSTRACT, CLASS_FINAL, CLASS_TRAIT, CLASS_INTERFACE, CLASS_ANONYMOUS, CLASS_ENUM, CLASS_READONLY] +AST_PROPERTY_HOOK: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY, FUNC_RETURNS_REF, FUNC_GENERATOR] AST_MAGIC_CONST: [MAGIC_LINE, MAGIC_FILE, MAGIC_DIR, MAGIC_NAMESPACE, MAGIC_FUNCTION, MAGIC_METHOD, MAGIC_CLASS, MAGIC_TRAIT] AST_TYPE: [TYPE_NULL, TYPE_FALSE, TYPE_TRUE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED, TYPE_NEVER] AST_CALLABLE_CONVERT: [] @@ -88,6 +89,7 @@ AST_GOTO: [] AST_BREAK: [] AST_CONTINUE: [] AST_CLASS_NAME: [] +AST_PROPERTY_HOOK_SHORT_BODY: [] AST_CLASS_CONST_GROUP: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, MODIFIER_READONLY] AST_DIM: (combinable) [DIM_ALTERNATIVE_SYNTAX, ENCAPS_VAR_DOLLAR_CURLY] AST_PROP: [] @@ -133,4 +135,4 @@ 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] \ No newline at end of file +AST_PARAM: (combinable) [PARAM_REF, PARAM_VARIADIC, PARAM_MODIFIER_PUBLIC, PARAM_MODIFIER_PROTECTED, PARAM_MODIFIER_PRIVATE] diff --git a/tests/php74_dim_alternative_syntax.phpt b/tests/php74_dim_alternative_syntax.phpt index 2d7bc56..b3c8c77 100644 --- a/tests/php74_dim_alternative_syntax.phpt +++ b/tests/php74_dim_alternative_syntax.phpt @@ -1,7 +1,7 @@ --TEST-- '$x{"offset"}' flag in PHP 7.4 --SKIPIF-- -= 7.4 only'); ?> += 80400) die('skip PHP 7.4-8.3 only'); ?> --FILE-- = 8.2 only'); ?> += 80400) die('skip PHP >= 8.2 < 8.4 only'); ?> --FILE-- = 8.2 only'); ?> +--FILE-- +c}{$d}${$e["f"]}${g[\'h\']}{$i[\'j\']}";'; +$node = ast\parse_code($code, $version=85); +echo ast_dump($node), "\n"; +--EXPECTF-- +AST_STMT_LIST + 0: AST_ENCAPS_LIST + 0: AST_VAR + flags: ENCAPS_VAR_DOLLAR_CURLY (%d) + name: "a" + 1: AST_VAR + flags: ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR (%d) + name: AST_PROP + expr: AST_CONST + name: AST_NAME + flags: NAME_NOT_FQ (%d) + name: "b" + prop: "c" + 2: AST_VAR + name: "d" + 3: AST_VAR + flags: ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR (%d) + name: AST_DIM + expr: AST_VAR + name: "e" + dim: "f" + 4: AST_DIM + flags: ENCAPS_VAR_DOLLAR_CURLY (%d) + expr: AST_VAR + name: "g" + dim: "h" + 5: AST_DIM + expr: AST_VAR + name: "i" + dim: "j" diff --git a/tests/php84_dim_alternative_syntax.phpt b/tests/php84_dim_alternative_syntax.phpt new file mode 100644 index 0000000..6409457 --- /dev/null +++ b/tests/php84_dim_alternative_syntax.phpt @@ -0,0 +1,23 @@ +--TEST-- +'$x{"offset"}' flag in PHP 8.4 is a Parse error +--SKIPIF-- += 8.4 only'); ?> +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECT-- +Caught: syntax error, unexpected token "{", expecting ")" diff --git a/tests/php84_property_hook.phpt b/tests/php84_property_hook.phpt new file mode 100644 index 0000000..cff36d8 --- /dev/null +++ b/tests/php84_property_hook.phpt @@ -0,0 +1,54 @@ +--TEST-- +Property hooks in php 8.4 +--SKIPIF-- +=8.4 only'); ?> +--FILE-- +=8.4 only'); ?> +--FILE-- +name = $newName; + } + } +} +PHP; + +$node = ast\parse_code($code, $version=90); +echo ast_dump($node), "\n"; +$node = ast\parse_code($code, $version=110); +echo ast_dump($node), "\n"; +--EXPECTF-- +AST_STMT_LIST + 0: AST_CLASS + name: "A" + docComment: null + extends: null + implements: null + stmts: AST_STMT_LIST + 0: AST_PROP_GROUP + flags: MODIFIER_PUBLIC (1) + type: AST_TYPE + flags: TYPE_STRING (6) + props: AST_PROP_DECL + 0: AST_PROP_ELEM + name: "normal" + default: null + docComment: null + attributes: null + 1: AST_PROP_GROUP + flags: MODIFIER_PUBLIC (1) + type: AST_TYPE + flags: TYPE_STRING (6) + props: AST_PROP_DECL + 0: AST_PROP_ELEM + name: "name" + default: null + docComment: null + attributes: null + attributes: null + type: null + __declId: 0 +AST_STMT_LIST + 0: AST_CLASS + name: "A" + docComment: null + extends: null + implements: null + stmts: AST_STMT_LIST + 0: AST_PROP_GROUP + flags: MODIFIER_PUBLIC (1) + type: AST_TYPE + flags: TYPE_STRING (6) + props: AST_PROP_DECL + 0: AST_PROP_ELEM + name: "normal" + default: null + docComment: null + hooks: null + attributes: null + 1: AST_PROP_GROUP + flags: MODIFIER_PUBLIC (1) + type: AST_TYPE + flags: TYPE_STRING (6) + props: AST_PROP_DECL + 0: AST_PROP_ELEM + name: "name" + default: null + docComment: null + hooks: AST_STMT_LIST + 0: AST_PROPERTY_HOOK + name: "set" + docComment: null + params: AST_PARAM_LIST + 0: AST_PARAM + type: AST_TYPE + flags: TYPE_STRING (6) + name: "newName" + default: null + attributes: null + docComment: null + hooks: null + stmts: AST_STMT_LIST + 0: AST_ASSIGN + var: AST_PROP + expr: AST_VAR + name: "this" + prop: "name" + expr: AST_VAR + name: "newName" + attributes: null + __declId: 0 + attributes: null + attributes: null + type: null + __declId: 1 diff --git a/tests/php84_property_hook3.phpt b/tests/php84_property_hook3.phpt new file mode 100644 index 0000000..61b442f --- /dev/null +++ b/tests/php84_property_hook3.phpt @@ -0,0 +1,60 @@ +--TEST-- +Property hooks in php 8.4 bodies flags +--SKIPIF-- +=8.4 only'); ?> +--FILE-- +=8.4 only'); ?> +--FILE-- + strtolower($value); } + ) {} +} +PHP; +$node = ast\parse_code($code, $version=110); +echo ast_dump($node), "\n"; +--EXPECTF-- +AST_STMT_LIST + 0: AST_CLASS + name: "User" + docComment: null + extends: null + implements: null + stmts: AST_STMT_LIST + 0: AST_METHOD + flags: MODIFIER_PUBLIC (%d) + name: "__construct" + docComment: null + params: AST_PARAM_LIST + 0: AST_PARAM + flags: PARAM_MODIFIER_PUBLIC (%d) + type: AST_TYPE + flags: TYPE_STRING (%d) + name: "username" + default: null + attributes: null + docComment: null + hooks: AST_STMT_LIST + 0: AST_PROPERTY_HOOK + name: "set" + docComment: null + params: null + stmts: AST_PROPERTY_HOOK_SHORT_BODY + expr: AST_CALL + expr: AST_NAME + flags: NAME_NOT_FQ (%d) + name: "strtolower" + args: AST_ARG_LIST + 0: AST_VAR + name: "value" + attributes: null + __declId: 0 + stmts: AST_STMT_LIST + returnType: null + attributes: null + __declId: 1 + attributes: null + type: null + __declId: 2 diff --git a/tests/prop_doc_comments.phpt b/tests/prop_doc_comments.phpt index eff5ed1..6ec56f1 100644 --- a/tests/prop_doc_comments.phpt +++ b/tests/prop_doc_comments.phpt @@ -22,6 +22,7 @@ PHP; echo ast_dump(ast\parse_code($code, $version=50)), "\n"; echo ast_dump(ast\parse_code($code, $version=80)), "\n"; +echo ast_dump(ast\parse_code($code, $version=110)), "\n"; ?> --EXPECTF-- @@ -80,4 +81,39 @@ AST_STMT_LIST docComment: "/** docComment $c */" attributes: null attributes: null - __declId: 0 \ No newline at end of file + __declId: 0 +AST_STMT_LIST + 0: AST_CLASS + name: "A" + docComment: null + extends: null + implements: null + stmts: AST_STMT_LIST + 0: AST_PROP_GROUP + flags: MODIFIER_PUBLIC (%d) + type: null + props: AST_PROP_DECL + 0: AST_PROP_ELEM + name: "a" + default: null + docComment: "/** docComment $a */" + hooks: null + attributes: null + 1: AST_PROP_GROUP + flags: MODIFIER_PUBLIC (%d) + type: null + props: AST_PROP_DECL + 0: AST_PROP_ELEM + name: "b" + default: null + docComment: "/** docComment $b */" + hooks: null + 1: AST_PROP_ELEM + name: "c" + default: null + docComment: "/** docComment $c */" + hooks: null + attributes: null + attributes: null + type: null + __declId: 0 From 1b2c17eca72844658f0d603aceae0b8c745b9899 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sat, 10 Aug 2024 14:08:52 -0400 Subject: [PATCH 35/53] Update the download link for php-ast (#243) Update the download link for php-ast This changed to https://downloads.php.net/~windows/pecl/releases/ast/ and may change again. https://pecl.php.net/package/ast should have the most up to date links and be easier to read. Related to #236 --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7ecc17a..cb15481 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,10 @@ Table of Contents Installation ------------ -**Windows**: Download a [prebuilt Windows DLL](http://windows.php.net/downloads/pecl/releases/ast/) -and move it into the `ext/` directory of your PHP installation. Furthermore add +**Windows**: Download a [prebuilt Windows DLL](https://downloads.php.net/~windows/pecl/releases/ast/) +and move it into the `ext/` directory of your PHP installation. Furthermore, add `extension=php_ast.dll` to your `php.ini` file. +(The [php-ast PECL page](https://downloads.php.net/~windows/pecl/releases/ast/) also links to the same DLLs for Windows.) **Unix (PECL)**: Run `pecl install ast` and add `extension=ast.so` to your `php.ini`. From 152b420ed6ca9029b47e52362916af0b25b2c7b3 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sat, 10 Aug 2024 14:09:09 -0400 Subject: [PATCH 36/53] Update README.md to indicate that the current version is 110 (#242) --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index cb15481..7a48b45 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Basic usage Code can be parsed using either `ast\parse_code()`, which accepts a code string, or `ast\parse_file()`, which accepts a file path. Additionally, both functions require a `$version` -argument to ensure forward-compatibility. The current version is 100. +argument to ensure forward-compatibility. The current version is 110. ```php $ast = ast\parse_code(' Date: Sat, 10 Aug 2024 14:38:40 -0400 Subject: [PATCH 37/53] Back to 1.1.3dev (#244) --- package.xml | 26 +++++++++++++++++++++----- php_ast.h | 2 +- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/package.xml b/package.xml index 537e52a..b5680ab 100644 --- a/package.xml +++ b/package.xml @@ -20,8 +20,8 @@ 2024-08-10 - 1.1.2 - 1.1.2 + 1.1.3dev + 1.1.3dev stable @@ -29,9 +29,7 @@ BSD-3-Clause -- Fix compilation errors in PHP 8.4. -- In version 110, `AST_PARAM` and `AST_PROP_ELEM` nodes have a `hooks` node for property hooks (https://wiki.php.net/rfc/property-hooks) -- In version 110, `AST_CLOSURE` and `AST_ARROW_FUNC` nodes have no `name`. +- TBD @@ -157,6 +155,24 @@ + 2024-08-10 + + 1.1.2 + 1.1.2 + + + stable + stable + + BSD-3-Clause + +- Fix compilation errors in PHP 8.4. +- In version 110, `AST_PARAM` and `AST_PROP_ELEM` nodes have a `hooks` node for property hooks (https://wiki.php.net/rfc/property-hooks) +- In version 110, `AST_CLOSURE` and `AST_ARROW_FUNC` nodes have no `name`. + + + + 2023-11-12 1.1.1 1.1.1 diff --git a/php_ast.h b/php_ast.h index 30d8af8..29e4450 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.1.2" +#define PHP_AST_VERSION "1.1.3dev" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) From d546378de770fbe5d40a7bf181d2b77ea408f59f Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 1 Jun 2025 17:33:35 +0200 Subject: [PATCH 38/53] Add compatibility define for ZEND_AST_EXIT --- php_ast.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/php_ast.h b/php_ast.h index 29e4450..4ba3bbc 100644 --- a/php_ast.h +++ b/php_ast.h @@ -93,6 +93,11 @@ extern ast_str_globals str_globals; # define ZEND_AST_PARENT_PROPERTY_HOOK_CALL 0x2f8 #endif +/* ZEND_AST_EXIT has been replaced with plain function call. */ +#if PHP_VERSION_ID >= 80500 +# define ZEND_AST_EXIT 0x1fd +#endif + /* Pretend it still exists */ # define ZEND_AST_LIST ((1 << (ZEND_AST_IS_LIST_SHIFT + 1)) - 1) From f81147834876626844d2c0d8eac02909c7b4692c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 1 Jun 2025 18:02:40 +0200 Subject: [PATCH 39/53] Use non-alpha for PHP 8.4 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6b5371e..174897a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -34,7 +34,7 @@ jobs: - PHP_VERSION: '8.1' - PHP_VERSION: '8.2' - PHP_VERSION: '8.3' - - PHP_VERSION: '8.4.0alpha4' + - PHP_VERSION: '8.4' # Steps represent a sequence of tasks that will be executed as part of the job steps: From 7e7c1c48054458dbf72fe8d3aa12cb7426b6c324 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Fri, 13 Jun 2025 20:21:01 +0100 Subject: [PATCH 40/53] Add PIE support (#249) --- composer.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 composer.json diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..35251b0 --- /dev/null +++ b/composer.json @@ -0,0 +1,12 @@ +{ + "name": "nikic/php-ast", + "type": "php-ext", + "license": "BSD-3-Clause", + "description": "Extension exposing PHP 7 abstract syntax tree", + "require": { + "php": ">= 7.2.0" + }, + "php-ext": { + "extension-name": "ast" + } +} From faca6cc1d963fa10670c671415db52457ff2127b Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Sat, 12 Jul 2025 17:42:40 +0200 Subject: [PATCH 41/53] Add compatibility define for ZEND_AST_CLONE (#253) --- php_ast.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/php_ast.h b/php_ast.h index 4ba3bbc..0eeb28c 100644 --- a/php_ast.h +++ b/php_ast.h @@ -93,9 +93,10 @@ extern ast_str_globals str_globals; # define ZEND_AST_PARENT_PROPERTY_HOOK_CALL 0x2f8 #endif -/* ZEND_AST_EXIT has been replaced with plain function call. */ +/* ZEND_AST_EXIT and ZEND_AST_CLONE have been replaced with plain function call. */ #if PHP_VERSION_ID >= 80500 # define ZEND_AST_EXIT 0x1fd +# define ZEND_AST_CLONE 0x1fc #endif /* Pretend it still exists */ From 869ea5ef4f69966c71614964739cb115a84bb7f0 Mon Sep 17 00:00:00 2001 From: Sergii <166042958+SergiiDolgushev@users.noreply.github.com> Date: Sat, 12 Jul 2025 16:47:06 +0100 Subject: [PATCH 42/53] Add Asymmetric Visibility flags (#250) Introduces new asymmetric visibility flags: MODIFIER_PUBLIC_SET, MODIFIER_PROTECTED_SET and MODIFIER_PRIVATE_SET. --- README.md | 3 + ast.c | 28 ++++++- ast_stub.php | 3 + package.xml | 1 + tests/asymmetric_visibility.phpt | 134 +++++++++++++++++++++++++++++++ tests/metadata.phpt | 4 +- 6 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 tests/asymmetric_visibility.phpt diff --git a/README.md b/README.md index 7a48b45..35ef082 100644 --- a/README.md +++ b/README.md @@ -237,6 +237,9 @@ ast\flags\MODIFIER_STATIC ast\flags\MODIFIER_ABSTRACT ast\flags\MODIFIER_FINAL ast\flags\MODIFIER_READONLY +ast\flags\MODIFIER_PUBLIC_SET +ast\flags\MODIFIER_PROTECTED_SET +ast\flags\MODIFIER_PRIVATE_SET // Used by ast\AST_CLOSURE, ast\AST_ARROW_FUNC (combinable) ast\flags\MODIFIER_STATIC diff --git a/ast.c b/ast.c index e372d75..64fd3d3 100644 --- a/ast.c +++ b/ast.c @@ -117,6 +117,16 @@ # define ZEND_ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR (1<<1) #endif +#if PHP_VERSION_ID < 80400 +# define MODIFIER_PUBLIC_SET (1 << 11) +# define MODIFIER_PROTECTED_SET (1 << 12) +# define MODIFIER_PRIVATE_SET (1 << 13) +#else +# define MODIFIER_PUBLIC_SET ZEND_ACC_PUBLIC_SET +# define MODIFIER_PROTECTED_SET ZEND_ACC_PROTECTED_SET +# define MODIFIER_PRIVATE_SET ZEND_ACC_PRIVATE_SET +#endif + #if PHP_VERSION_ID >= 80400 # define ZEND_DIM_ALTERNATIVE_SYNTAX (1<<1) #endif @@ -289,11 +299,22 @@ static const char *closure_use_flags[] = { AST_FLAG(MODIFIER_FINAL), \ AST_FLAG(MODIFIER_READONLY) +#define AST_ASYMMETRIC_VISIBILITY_FLAGS \ + AST_FLAG(MODIFIER_PUBLIC_SET), \ + AST_FLAG(MODIFIER_PROTECTED_SET), \ + AST_FLAG(MODIFIER_PRIVATE_SET) + static const char *modifier_flags[] = { AST_MODIFIER_FLAGS, NULL }; +static const char *property_modifier_flags[] = { + AST_MODIFIER_FLAGS, + AST_ASYMMETRIC_VISIBILITY_FLAGS, + NULL +}; + static const char *func_flags[] = { AST_MODIFIER_FLAGS, AST_FLAG(FUNC_RETURNS_REF), @@ -341,8 +362,8 @@ static const ast_flag_info flag_info[] = { { ZEND_AST_CLOSURE, 1, func_flags }, { ZEND_AST_ARROW_FUNC, 1, func_flags }, { ZEND_AST_PROPERTY_HOOK, 1, func_flags }, - { ZEND_AST_PROP_DECL, 1, modifier_flags }, - { ZEND_AST_PROP_GROUP, 1, modifier_flags }, + { ZEND_AST_PROP_DECL, 1, property_modifier_flags }, + { ZEND_AST_PROP_GROUP, 1, property_modifier_flags }, { ZEND_AST_CLASS_CONST_DECL, 1, modifier_flags }, { ZEND_AST_CLASS_CONST_GROUP, 1, modifier_flags }, { ZEND_AST_TRAIT_ALIAS, 1, modifier_flags }, @@ -1466,6 +1487,9 @@ PHP_MINIT_FUNCTION(ast) { ast_register_flag_constant("MODIFIER_ABSTRACT", ZEND_ACC_ABSTRACT); ast_register_flag_constant("MODIFIER_FINAL", ZEND_ACC_FINAL); ast_register_flag_constant("MODIFIER_READONLY", ZEND_ACC_READONLY); + ast_register_flag_constant("MODIFIER_PUBLIC_SET", MODIFIER_PUBLIC_SET); + ast_register_flag_constant("MODIFIER_PROTECTED_SET", MODIFIER_PROTECTED_SET); + ast_register_flag_constant("MODIFIER_PRIVATE_SET", MODIFIER_PRIVATE_SET); ast_register_flag_constant("PARAM_MODIFIER_PUBLIC", PARAM_MODIFIER_PUBLIC); ast_register_flag_constant("PARAM_MODIFIER_PROTECTED", PARAM_MODIFIER_PROTECTED); diff --git a/ast_stub.php b/ast_stub.php index 3a6cfcd..e5e5c2a 100644 --- a/ast_stub.php +++ b/ast_stub.php @@ -129,6 +129,9 @@ const MODIFIER_ABSTRACT = 64; const MODIFIER_FINAL = 32; const MODIFIER_READONLY = 128; +const MODIFIER_PUBLIC_SET = 1024; +const MODIFIER_PROTECTED_SET = 2048; +const MODIFIER_PRIVATE_SET = 4096; const PARAM_MODIFIER_PUBLIC = 1; const PARAM_MODIFIER_PROTECTED = 2; const PARAM_MODIFIER_PRIVATE = 4; diff --git a/package.xml b/package.xml index b5680ab..ad0363b 100644 --- a/package.xml +++ b/package.xml @@ -52,6 +52,7 @@ + diff --git a/tests/asymmetric_visibility.phpt b/tests/asymmetric_visibility.phpt new file mode 100644 index 0000000..78562ae --- /dev/null +++ b/tests/asymmetric_visibility.phpt @@ -0,0 +1,134 @@ +--TEST-- +Asymmetric Visibility in php 8.4 +--SKIPIF-- +=8.4 only'); ?> +--FILE-- + Date: Sun, 10 Aug 2025 16:39:06 +0200 Subject: [PATCH 43/53] Add support for pipe operator --- README.md | 1 + ast.c | 9 +++++++++ ast_stub.php | 21 ++++++++++----------- tests/metadata.phpt | 2 +- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 35ef082..de1524c 100644 --- a/README.md +++ b/README.md @@ -314,6 +314,7 @@ ast\flags\BINARY_POW ast\flags\BINARY_SHIFT_LEFT ast\flags\BINARY_SHIFT_RIGHT ast\flags\BINARY_COALESCE +ast\flags\BINARY_PIPE // Used by ast\AST_BINARY_OP (exclusive) ast\flags\BINARY_BOOL_AND diff --git a/ast.c b/ast.c index 64fd3d3..de0f511 100644 --- a/ast.c +++ b/ast.c @@ -79,6 +79,7 @@ #define AST_BINARY_BOOL_OR 258 #define AST_BINARY_BOOL_AND 259 #define AST_BINARY_COALESCE 260 +#define AST_BINARY_PIPE 261 /* Flags for UNARY_OP to use instead of AST_SILENCE, AST_UNARY_PLUS, AST_UNARY_MINUS */ #define AST_SILENCE 260 @@ -236,6 +237,7 @@ static const char *binary_op_flags[] = { AST_FLAG(BINARY_IS_GREATER), AST_FLAG(BINARY_IS_GREATER_OR_EQUAL), AST_FLAG(BINARY_SPACESHIP), + AST_FLAG(BINARY_PIPE), NULL }; @@ -980,6 +982,12 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { ast->kind = ZEND_AST_BINARY_OP; ast->attr = AST_BINARY_COALESCE; break; +#if PHP_VERSION_ID >= 80500 + case ZEND_AST_PIPE: + ast->kind = ZEND_AST_BINARY_OP; + ast->attr = AST_BINARY_PIPE; + break; +#endif case ZEND_AST_SILENCE: ast->kind = ZEND_AST_UNARY_OP; ast->attr = AST_SILENCE; @@ -1560,6 +1568,7 @@ PHP_MINIT_FUNCTION(ast) { ast_register_flag_constant("BINARY_IS_GREATER_OR_EQUAL", AST_BINARY_IS_GREATER_OR_EQUAL); ast_register_flag_constant("BINARY_SPACESHIP", ZEND_SPACESHIP); ast_register_flag_constant("BINARY_COALESCE", AST_BINARY_COALESCE); + ast_register_flag_constant("BINARY_PIPE", AST_BINARY_PIPE); ast_register_flag_constant("EXEC_EVAL", ZEND_EVAL); ast_register_flag_constant("EXEC_INCLUDE", ZEND_INCLUDE); diff --git a/ast_stub.php b/ast_stub.php index e5e5c2a..723e2fc 100644 --- a/ast_stub.php +++ b/ast_stub.php @@ -37,6 +37,7 @@ const AST_METHOD = 69; const AST_ARROW_FUNC = 71; const AST_CLASS = 70; +const AST_PROPERTY_HOOK = 127; const AST_MAGIC_CONST = 0; const AST_TYPE = 1; const AST_CALLABLE_CONVERT = 3; @@ -69,6 +70,7 @@ const AST_BREAK = 286; const AST_CONTINUE = 287; const AST_CLASS_NAME = 276; +const AST_PROPERTY_HOOK_SHORT_BODY = 510; const AST_CLASS_CONST_GROUP = 777; const AST_DIM = 512; const AST_PROP = 513; @@ -129,9 +131,6 @@ const MODIFIER_ABSTRACT = 64; const MODIFIER_FINAL = 32; const MODIFIER_READONLY = 128; -const MODIFIER_PUBLIC_SET = 1024; -const MODIFIER_PROTECTED_SET = 2048; -const MODIFIER_PRIVATE_SET = 4096; const PARAM_MODIFIER_PUBLIC = 1; const PARAM_MODIFIER_PROTECTED = 2; const PARAM_MODIFIER_PRIVATE = 4; @@ -202,14 +201,14 @@ const USE_NORMAL = 1; const USE_FUNCTION = 2; const USE_CONST = 4; -const MAGIC_LINE = 379; -const MAGIC_FILE = 380; -const MAGIC_DIR = 381; -const MAGIC_NAMESPACE = 386; -const MAGIC_FUNCTION = 385; -const MAGIC_METHOD = 384; -const MAGIC_CLASS = 382; -const MAGIC_TRAIT = 383; +const MAGIC_LINE = 343; +const MAGIC_FILE = 344; +const MAGIC_DIR = 345; +const MAGIC_NAMESPACE = 350; +const MAGIC_FUNCTION = 349; +const MAGIC_METHOD = 348; +const MAGIC_CLASS = 346; +const MAGIC_TRAIT = 347; const ARRAY_SYNTAX_LIST = 1; const ARRAY_SYNTAX_LONG = 2; const ARRAY_SYNTAX_SHORT = 3; diff --git a/tests/metadata.phpt b/tests/metadata.phpt index a8165b2..afe6ce8 100644 --- a/tests/metadata.phpt +++ b/tests/metadata.phpt @@ -100,7 +100,7 @@ AST_CLASS_CONST: [] AST_ASSIGN: [] AST_ASSIGN_REF: [] AST_ASSIGN_OP: [BINARY_BITWISE_OR, BINARY_BITWISE_AND, BINARY_BITWISE_XOR, BINARY_CONCAT, BINARY_ADD, BINARY_SUB, BINARY_MUL, BINARY_DIV, BINARY_MOD, BINARY_POW, BINARY_SHIFT_LEFT, BINARY_SHIFT_RIGHT, BINARY_COALESCE] -AST_BINARY_OP: [BINARY_BITWISE_OR, BINARY_BITWISE_AND, BINARY_BITWISE_XOR, BINARY_CONCAT, BINARY_ADD, BINARY_SUB, BINARY_MUL, BINARY_DIV, BINARY_MOD, BINARY_POW, BINARY_SHIFT_LEFT, BINARY_SHIFT_RIGHT, BINARY_COALESCE, BINARY_BOOL_AND, BINARY_BOOL_OR, BINARY_BOOL_XOR, BINARY_IS_IDENTICAL, BINARY_IS_NOT_IDENTICAL, BINARY_IS_EQUAL, BINARY_IS_NOT_EQUAL, BINARY_IS_SMALLER, BINARY_IS_SMALLER_OR_EQUAL, BINARY_IS_GREATER, BINARY_IS_GREATER_OR_EQUAL, BINARY_SPACESHIP] +AST_BINARY_OP: [BINARY_BITWISE_OR, BINARY_BITWISE_AND, BINARY_BITWISE_XOR, BINARY_CONCAT, BINARY_ADD, BINARY_SUB, BINARY_MUL, BINARY_DIV, BINARY_MOD, BINARY_POW, BINARY_SHIFT_LEFT, BINARY_SHIFT_RIGHT, BINARY_COALESCE, BINARY_BOOL_AND, BINARY_BOOL_OR, BINARY_BOOL_XOR, BINARY_IS_IDENTICAL, BINARY_IS_NOT_IDENTICAL, BINARY_IS_EQUAL, BINARY_IS_NOT_EQUAL, BINARY_IS_SMALLER, BINARY_IS_SMALLER_OR_EQUAL, BINARY_IS_GREATER, BINARY_IS_GREATER_OR_EQUAL, BINARY_SPACESHIP, BINARY_PIPE] AST_ARRAY_ELEM: [ARRAY_ELEM_REF] AST_NEW: [] AST_INSTANCEOF: [] From 61c886650e7f27a8c2f7832f74dd2bb91913dda0 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 10 Aug 2025 16:45:33 +0200 Subject: [PATCH 44/53] Add PHP 8.5 to CI --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 174897a..ea8e48f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,6 +35,7 @@ jobs: - PHP_VERSION: '8.2' - PHP_VERSION: '8.3' - PHP_VERSION: '8.4' + - PHP_VERSION: '8.5.0alpha4' # Steps represent a sequence of tasks that will be executed as part of the job steps: From 1d59f6e8617e6e4adec407e97868b8c2bcf40c3e Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 10 Aug 2025 16:52:29 +0200 Subject: [PATCH 45/53] Add support for void cast --- ast.c | 6 ++++++ tests/php85_pipe_operator.phpt | 24 ++++++++++++++++++++++++ tests/php85_void_cast.phpt | 25 +++++++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 tests/php85_pipe_operator.phpt create mode 100644 tests/php85_void_cast.phpt diff --git a/ast.c b/ast.c index de0f511..af92327 100644 --- a/ast.c +++ b/ast.c @@ -1074,6 +1074,12 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { } } break; +#endif +#if PHP_VERSION_ID >= 80500 + case ZEND_AST_CAST_VOID: + ast->kind = ZEND_AST_CAST; + ast->attr = IS_VOID; + break; #endif } diff --git a/tests/php85_pipe_operator.phpt b/tests/php85_pipe_operator.phpt new file mode 100644 index 0000000..d715ec8 --- /dev/null +++ b/tests/php85_pipe_operator.phpt @@ -0,0 +1,24 @@ +--TEST-- +Pipe operator +--SKIPIF-- +=8.5 only'); ?> +--FILE-- + $b; +PHP; + +$node = ast\parse_code($code, $version=110); +echo ast_dump($node), "\n"; +--EXPECTF-- +AST_STMT_LIST + 0: AST_BINARY_OP + flags: BINARY_PIPE (%d) + left: AST_VAR + name: "a" + right: AST_VAR + name: "b" diff --git a/tests/php85_void_cast.phpt b/tests/php85_void_cast.phpt new file mode 100644 index 0000000..6ca5ebc --- /dev/null +++ b/tests/php85_void_cast.phpt @@ -0,0 +1,25 @@ +--TEST-- +Void cast +--SKIPIF-- +=8.5 only'); ?> +--FILE-- + Date: Sun, 10 Aug 2025 17:18:10 +0200 Subject: [PATCH 46/53] Convert between AST_CLONE and AST_CALL --- README.md | 8 ++- ast.c | 45 +++++++++++++++- ast_str_defs.h | 1 + scripts/generate_ast_data.php | 2 +- tests/clone.phpt | 29 +++++++++++ tests/get_supported_versions.phpt | 8 ++- tests/php85_clone.phpt | 86 +++++++++++++++++++++++++++++++ 7 files changed, 174 insertions(+), 5 deletions(-) create mode 100644 tests/clone.phpt create mode 100644 tests/php85_clone.phpt diff --git a/README.md b/README.md index de1524c..c0f2091 100644 --- a/README.md +++ b/README.md @@ -394,7 +394,7 @@ AST_CLASS: name, docComment, extends, implements, stmts, (for enu AST_CLASS_CONST: class, const AST_CLASS_CONST_GROUP class, attributes, type // version 80+ AST_CLASS_NAME: class // version 70+ -AST_CLONE: expr +AST_CLONE: expr // version <120 AST_CLOSURE: name, docComment, params, uses, stmts, returnType, attributes // name removed in version 110 AST_CLOSURE_VAR: name AST_CONDITIONAL: cond, true, false @@ -511,6 +511,12 @@ function accepts a boolean argument that determines whether deprecated versions In the following the changes in the respective AST versions, as well as their current support state, are listed. +### 120 (experimental) + +Supported since 1.1.3 (TBD). + +* `clone $expr` is now represented like a `clone($expr)` function call (using `AST_CALL`). + ### 110 (current) Supported since 1.1.2 (2024-08-10). diff --git a/ast.c b/ast.c index af92327..74464e1 100644 --- a/ast.c +++ b/ast.c @@ -1081,6 +1081,49 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { ast->attr = IS_VOID; break; #endif + case ZEND_AST_CALL: + if (state->version < 120) { + // Convert clone($expr) call to ZEND_AST_CLONE node. + zend_ast *name_ast = ast->child[0]; + if (name_ast->kind != ZEND_AST_ZVAL || name_ast->attr != ZEND_NAME_FQ || + Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING || + ast->child[1]->kind != ZEND_AST_ARG_LIST) { + break; + } + + zend_ast_list *args = zend_ast_get_list(ast->child[1]); + if (args->children != 1) { + break; + } + + zend_ast *arg = args->child[0]; + if (arg->kind == ZEND_AST_NAMED_ARG || arg->kind == ZEND_AST_UNPACK) { + break; + } + + zend_string *name = zend_ast_get_str(name_ast); + if (zend_string_equals_literal_ci(name, "clone")) { + ast_create_virtual_node(zv, ZEND_AST_CLONE, 0, arg, state); + return; + } + } + break; + case ZEND_AST_CLONE: + if (state->version >= 120) { + // Convert to call node. + uint32_t lineno = zend_ast_get_lineno(ast); + zval name_str_zv, name_node_zv, args_zv, arg_zv; + ZVAL_STR(&name_str_zv, AST_STR(str_clone)); + ast_to_zval(&arg_zv, ast->child[0], state); + ast_create_virtual_node_ex( + &name_node_zv, AST_NAME, ZEND_NAME_FQ, lineno, state, 1, &name_str_zv); + ast_create_virtual_node_ex( + &args_zv, ZEND_AST_ARG_LIST, 0, lineno, state, 1, &arg_zv); + ast_create_virtual_node_ex( + zv, ZEND_AST_CALL, 0, lineno, state, 2, &name_node_zv, &args_zv); + return; + } + break; } object_init_ex(zv, ast_node_ce); @@ -1171,7 +1214,7 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { #endif } -static const zend_long versions[] = {50, 60, 70, 80, 85, 90, 100, 110}; +static const zend_long versions[] = {50, 60, 70, 80, 85, 90, 100, 110, 120}; static const size_t versions_count = sizeof(versions)/sizeof(versions[0]); static inline zend_bool ast_version_deprecated(zend_long version) { diff --git a/ast_str_defs.h b/ast_str_defs.h index 559dcb1..ba1d192 100644 --- a/ast_str_defs.h +++ b/ast_str_defs.h @@ -11,6 +11,7 @@ X(endLineno, "endLineno") \ X(__declId, "__declId") \ X(flagsCombinable, "flagsCombinable") \ + X(clone, "clone") \ X(type, "type") \ X(params, "params") \ X(uses, "uses") \ diff --git a/scripts/generate_ast_data.php b/scripts/generate_ast_data.php index b68dfa2..8942cfb 100644 --- a/scripts/generate_ast_data.php +++ b/scripts/generate_ast_data.php @@ -278,7 +278,7 @@ function get_possible_strings(array $spec) { $strings = array_fill_keys([ 'kind', 'flags', 'lineno', 'children', 'name', 'docComment', 'endLineno', '__declId', - 'flagsCombinable', + 'flagsCombinable', 'clone', ], true); foreach ($spec as $kind => $children) { diff --git a/tests/clone.phpt b/tests/clone.phpt new file mode 100644 index 0000000..e364122 --- /dev/null +++ b/tests/clone.phpt @@ -0,0 +1,29 @@ +--TEST-- +Simple clone +--FILE-- + --EXPECT-- -array(8) { +array(9) { [0]=> int(50) [1]=> @@ -25,8 +25,10 @@ array(8) { int(100) [7]=> int(110) + [8]=> + int(120) } -array(6) { +array(7) { [0]=> int(70) [1]=> @@ -39,4 +41,6 @@ array(6) { int(100) [5]=> int(110) + [6]=> + int(120) } diff --git a/tests/php85_clone.phpt b/tests/php85_clone.phpt new file mode 100644 index 0000000..98e3b65 --- /dev/null +++ b/tests/php85_clone.phpt @@ -0,0 +1,86 @@ +--TEST-- +Complex clone +--SKIPIF-- += 8.5 only'); ?> +--FILE-- + Date: Sun, 10 Aug 2025 17:50:21 +0200 Subject: [PATCH 47/53] Convert between AST_EXIT and AST_CALL --- README.md | 7 +-- ast.c | 11 ++++- ast_str_defs.h | 1 + scripts/generate_ast_data.php | 2 +- tests/exit.phpt | 29 ++++++++++++ tests/php84_exit.phpt | 86 +++++++++++++++++++++++++++++++++++ 6 files changed, 131 insertions(+), 5 deletions(-) create mode 100644 tests/exit.phpt create mode 100644 tests/php84_exit.phpt diff --git a/README.md b/README.md index c0f2091..9ddc4e2 100644 --- a/README.md +++ b/README.md @@ -394,7 +394,7 @@ AST_CLASS: name, docComment, extends, implements, stmts, (for enu AST_CLASS_CONST: class, const AST_CLASS_CONST_GROUP class, attributes, type // version 80+ AST_CLASS_NAME: class // version 70+ -AST_CLONE: expr // version <120 +AST_CLONE: expr // prior to version 120 AST_CLOSURE: name, docComment, params, uses, stmts, returnType, attributes // name removed in version 110 AST_CLOSURE_VAR: name AST_CONDITIONAL: cond, true, false @@ -407,7 +407,7 @@ AST_DO_WHILE: stmts, cond AST_ECHO: expr AST_EMPTY: expr AST_ENUM_CASE: name, expr, docComment, attributes // php 8.1+ enums -AST_EXIT: expr +AST_EXIT: expr // prior to version 120 AST_FOR: init, cond, loop, stmts AST_FOREACH: expr, value, key, stmts AST_FUNC_DECL: name, docComment, params, stmts, returnType, attributes @@ -515,7 +515,8 @@ are listed. Supported since 1.1.3 (TBD). -* `clone $expr` is now represented like a `clone($expr)` function call (using `AST_CALL`). +* `clone $expr` is now represented like a function call (using `AST_CALL` instead of `AST_CLONE`). +* `exit($expr)` is now represented like a function call (using `AST_CALL` instead of `AST_EXIT`). ### 110 (current) diff --git a/ast.c b/ast.c index 74464e1..1d339eb 100644 --- a/ast.c +++ b/ast.c @@ -1106,14 +1106,23 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) { ast_create_virtual_node(zv, ZEND_AST_CLONE, 0, arg, state); return; } + if (zend_string_equals_literal_ci(name, "exit")) { + ast_create_virtual_node(zv, ZEND_AST_EXIT, 0, arg, state); + return; + } } break; case ZEND_AST_CLONE: + case ZEND_AST_EXIT: if (state->version >= 120) { // Convert to call node. uint32_t lineno = zend_ast_get_lineno(ast); zval name_str_zv, name_node_zv, args_zv, arg_zv; - ZVAL_STR(&name_str_zv, AST_STR(str_clone)); + if (ast->kind == ZEND_AST_CLONE) { + ZVAL_STR(&name_str_zv, AST_STR(str_clone)); + } else { + ZVAL_STR(&name_str_zv, AST_STR(str_exit)); + } ast_to_zval(&arg_zv, ast->child[0], state); ast_create_virtual_node_ex( &name_node_zv, AST_NAME, ZEND_NAME_FQ, lineno, state, 1, &name_str_zv); diff --git a/ast_str_defs.h b/ast_str_defs.h index ba1d192..aaa7245 100644 --- a/ast_str_defs.h +++ b/ast_str_defs.h @@ -12,6 +12,7 @@ X(__declId, "__declId") \ X(flagsCombinable, "flagsCombinable") \ X(clone, "clone") \ + X(exit, "exit") \ X(type, "type") \ X(params, "params") \ X(uses, "uses") \ diff --git a/scripts/generate_ast_data.php b/scripts/generate_ast_data.php index 8942cfb..2fe8214 100644 --- a/scripts/generate_ast_data.php +++ b/scripts/generate_ast_data.php @@ -278,7 +278,7 @@ function get_possible_strings(array $spec) { $strings = array_fill_keys([ 'kind', 'flags', 'lineno', 'children', 'name', 'docComment', 'endLineno', '__declId', - 'flagsCombinable', 'clone', + 'flagsCombinable', 'clone', 'exit', ], true); foreach ($spec as $kind => $children) { diff --git a/tests/exit.phpt b/tests/exit.phpt new file mode 100644 index 0000000..2b17dd7 --- /dev/null +++ b/tests/exit.phpt @@ -0,0 +1,29 @@ +--TEST-- +Simple exit +--FILE-- += 8.5 only'); ?> +--FILE-- + Date: Sun, 10 Aug 2025 17:52:48 +0200 Subject: [PATCH 48/53] Mark version 120 as current --- README.md | 10 +++++----- ast.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9ddc4e2..ac6ff92 100644 --- a/README.md +++ b/README.md @@ -60,12 +60,12 @@ Basic usage Code can be parsed using either `ast\parse_code()`, which accepts a code string, or `ast\parse_file()`, which accepts a file path. Additionally, both functions require a `$version` -argument to ensure forward-compatibility. The current version is 110. +argument to ensure forward-compatibility. The current version is 120. ```php -$ast = ast\parse_code(' Date: Sun, 10 Aug 2025 17:57:40 +0200 Subject: [PATCH 49/53] Update package.xml --- package.xml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/package.xml b/package.xml index ad0363b..b771e01 100644 --- a/package.xml +++ b/package.xml @@ -29,7 +29,11 @@ BSD-3-Clause -- TBD +- Fix build against PHP 8.5. +- In version 120, `exit` and `clone` are represented as `AST_CALL` instead of `AST_EXIT` and `AST_CLONE`. +- Added `MODIFIER_PUBLIC_SET`, `MODIFIER_PROTECTED_SET` and `MODIFIER_PRIVATE_SET` asymmetric visibility flags. +- Added `BINARY_PIPE` flag for `AST_BINARY_OP` for `|>` pipe operator. +- Support `(void)` cast via `TYPE_VOID` flag on `AST_CAST`. @@ -66,6 +70,7 @@ + @@ -75,6 +80,7 @@ + @@ -122,10 +128,14 @@ + + + + From c2faa5d071454ba3c2d0170611e92846ca606bba Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 10 Aug 2025 17:58:50 +0200 Subject: [PATCH 50/53] Release version 1.1.3 --- package.xml | 6 +++--- php_ast.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.xml b/package.xml index b771e01..6a607c9 100644 --- a/package.xml +++ b/package.xml @@ -18,10 +18,10 @@ tandre@php.net yes - 2024-08-10 + 2025-08-10 - 1.1.3dev - 1.1.3dev + 1.1.3 + 1.1.3 stable diff --git a/php_ast.h b/php_ast.h index 0eeb28c..13f7a19 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.1.3dev" +#define PHP_AST_VERSION "1.1.3" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) From 426bf89811f545081a1b650473c6bc6b6762e969 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 10 Aug 2025 18:15:46 +0200 Subject: [PATCH 51/53] Back to dev --- package.xml | 26 +++++++++++++++++++------- php_ast.h | 2 +- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/package.xml b/package.xml index 6a607c9..72663bc 100644 --- a/package.xml +++ b/package.xml @@ -20,8 +20,8 @@ 2025-08-10 - 1.1.3 - 1.1.3 + 1.1.4dev + 1.1.4dev stable @@ -29,11 +29,6 @@ BSD-3-Clause -- Fix build against PHP 8.5. -- In version 120, `exit` and `clone` are represented as `AST_CALL` instead of `AST_EXIT` and `AST_CLONE`. -- Added `MODIFIER_PUBLIC_SET`, `MODIFIER_PROTECTED_SET` and `MODIFIER_PRIVATE_SET` asymmetric visibility flags. -- Added `BINARY_PIPE` flag for `AST_BINARY_OP` for `|>` pipe operator. -- Support `(void)` cast via `TYPE_VOID` flag on `AST_CAST`. @@ -165,6 +160,23 @@ ast + 2025-08-10 + + 1.1.3 + 1.1.3 + + + stable + stable + + BSD-3-Clause + +- Fix build against PHP 8.5. +- In version 120, `exit` and `clone` are represented as `AST_CALL` instead of `AST_EXIT` and `AST_CLONE`. +- Added `MODIFIER_PUBLIC_SET`, `MODIFIER_PROTECTED_SET` and `MODIFIER_PRIVATE_SET` asymmetric visibility flags. +- Added `BINARY_PIPE` flag for `AST_BINARY_OP` for `|>` pipe operator. +- Support `(void)` cast via `TYPE_VOID` flag on `AST_CAST`. + 2024-08-10 diff --git a/php_ast.h b/php_ast.h index 13f7a19..efecc21 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.1.3" +#define PHP_AST_VERSION "1.1.4dev" #ifdef PHP_WIN32 # define PHP_AST_API __declspec(dllexport) From 217ec5717c8fc7a5a83afaeffe80ee832cccafce Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 10 Aug 2025 18:17:13 +0200 Subject: [PATCH 52/53] Make package.xml notes non-empty --- package.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/package.xml b/package.xml index 72663bc..08c503c 100644 --- a/package.xml +++ b/package.xml @@ -29,6 +29,7 @@ BSD-3-Clause +- From 4adc6ad0de2a9502bcff00112c6c82cef515222c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 11 Aug 2025 20:29:34 +0200 Subject: [PATCH 53/53] Regenerate stubs --- ast_stub.php | 92 +++++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/ast_stub.php b/ast_stub.php index 723e2fc..a3530f0 100644 --- a/ast_stub.php +++ b/ast_stub.php @@ -32,12 +32,12 @@ const AST_NAME = 2048; const AST_CLOSURE_VAR = 2049; const AST_NULLABLE_TYPE = 2050; -const AST_FUNC_DECL = 67; -const AST_CLOSURE = 68; -const AST_METHOD = 69; -const AST_ARROW_FUNC = 71; -const AST_CLASS = 70; -const AST_PROPERTY_HOOK = 127; +const AST_FUNC_DECL = 68; +const AST_CLOSURE = 69; +const AST_METHOD = 70; +const AST_ARROW_FUNC = 72; +const AST_CLASS = 71; +const AST_PROPERTY_HOOK = 73; const AST_MAGIC_CONST = 0; const AST_TYPE = 1; const AST_CALLABLE_CONVERT = 3; @@ -45,33 +45,33 @@ const AST_CONST = 257; const AST_UNPACK = 258; const AST_CAST = 261; -const AST_EMPTY = 262; -const AST_ISSET = 263; -const AST_SHELL_EXEC = 265; -const AST_CLONE = 266; -const AST_EXIT = 267; -const AST_PRINT = 268; -const AST_INCLUDE_OR_EVAL = 269; -const AST_UNARY_OP = 270; -const AST_PRE_INC = 271; -const AST_PRE_DEC = 272; -const AST_POST_INC = 273; -const AST_POST_DEC = 274; -const AST_YIELD_FROM = 275; -const AST_GLOBAL = 277; -const AST_UNSET = 278; -const AST_RETURN = 279; -const AST_LABEL = 280; -const AST_REF = 281; -const AST_HALT_COMPILER = 282; -const AST_ECHO = 283; -const AST_THROW = 284; -const AST_GOTO = 285; -const AST_BREAK = 286; -const AST_CONTINUE = 287; -const AST_CLASS_NAME = 276; -const AST_PROPERTY_HOOK_SHORT_BODY = 510; -const AST_CLASS_CONST_GROUP = 777; +const AST_EMPTY = 263; +const AST_ISSET = 264; +const AST_SHELL_EXEC = 266; +const AST_CLONE = 508; +const AST_EXIT = 509; +const AST_PRINT = 267; +const AST_INCLUDE_OR_EVAL = 268; +const AST_UNARY_OP = 269; +const AST_PRE_INC = 270; +const AST_PRE_DEC = 271; +const AST_POST_INC = 272; +const AST_POST_DEC = 273; +const AST_YIELD_FROM = 274; +const AST_GLOBAL = 276; +const AST_UNSET = 277; +const AST_RETURN = 278; +const AST_LABEL = 279; +const AST_REF = 280; +const AST_HALT_COMPILER = 281; +const AST_ECHO = 282; +const AST_THROW = 283; +const AST_GOTO = 284; +const AST_BREAK = 285; +const AST_CONTINUE = 286; +const AST_CLASS_NAME = 275; +const AST_PROPERTY_HOOK_SHORT_BODY = 287; +const AST_CLASS_CONST_GROUP = 776; const AST_DIM = 512; const AST_PROP = 513; const AST_NULLSAFE_PROP = 514; @@ -93,9 +93,9 @@ const AST_SWITCH = 536; const AST_SWITCH_CASE = 537; const AST_DECLARE = 538; -const AST_PROP_ELEM = 775; +const AST_PROP_ELEM = 1027; const AST_PROP_GROUP = 774; -const AST_CONST_ELEM = 776; +const AST_CONST_ELEM = 775; const AST_USE_TRAIT = 539; const AST_TRAIT_PRECEDENCE = 540; const AST_METHOD_REFERENCE = 541; @@ -116,7 +116,7 @@ const AST_FOR = 1024; const AST_FOREACH = 1025; const AST_ENUM_CASE = 1026; -const AST_PARAM = 1280; +const AST_PARAM = 1536; // END AST KIND CONSTANTS // AST FLAG CONSTANTS @@ -131,6 +131,9 @@ const MODIFIER_ABSTRACT = 64; const MODIFIER_FINAL = 32; const MODIFIER_READONLY = 128; +const MODIFIER_PUBLIC_SET = 1024; +const MODIFIER_PROTECTED_SET = 2048; +const MODIFIER_PRIVATE_SET = 4096; const PARAM_MODIFIER_PUBLIC = 1; const PARAM_MODIFIER_PROTECTED = 2; const PARAM_MODIFIER_PRIVATE = 4; @@ -193,6 +196,7 @@ const BINARY_IS_GREATER_OR_EQUAL = 257; const BINARY_SPACESHIP = 170; const BINARY_COALESCE = 260; +const BINARY_PIPE = 261; const EXEC_EVAL = 1; const EXEC_INCLUDE = 2; const EXEC_INCLUDE_ONCE = 4; @@ -201,14 +205,14 @@ const USE_NORMAL = 1; const USE_FUNCTION = 2; const USE_CONST = 4; -const MAGIC_LINE = 343; -const MAGIC_FILE = 344; -const MAGIC_DIR = 345; -const MAGIC_NAMESPACE = 350; -const MAGIC_FUNCTION = 349; -const MAGIC_METHOD = 348; -const MAGIC_CLASS = 346; -const MAGIC_TRAIT = 347; +const MAGIC_LINE = 346; +const MAGIC_FILE = 347; +const MAGIC_DIR = 348; +const MAGIC_NAMESPACE = 354; +const MAGIC_FUNCTION = 352; +const MAGIC_METHOD = 351; +const MAGIC_CLASS = 349; +const MAGIC_TRAIT = 350; const ARRAY_SYNTAX_LIST = 1; const ARRAY_SYNTAX_LONG = 2; const ARRAY_SYNTAX_SHORT = 3;