From 64ea7276bcd9cf8e503b719aafbec4d802c9eacc Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 27 Jun 2026 15:34:01 -0400 Subject: [PATCH] Support PHP 8.6 (#259) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Support PHP 8.6 Add compatibility shims in php_ast.h for the internal Zend API changes in PHP 8.6: - `ZEND_AST_METHOD_REFERENCE` was renamed to `ZEND_AST_TRAIT_METHOD_REFERENCE` - The `_throw()` ZPP variants were removed; plain ZPP now always throws, so `zend_parse_parameters_throw` maps to `zend_parse_parameters` and the removed `ZEND_PARSE_PARAMS_THROW` flag is defined to `0` (the throwing default). All guarded on `PHP_VERSION_ID >= 80600`, so older versions are unaffected and the userland `ast\AST_METHOD_REFERENCE` constant is unchanged. ## New 8.6 feature: doc comments on parameters Of the implemented PHP 8.6 RFCs, only [Add DocComments for function parameters](https://wiki.php.net/rfc/parameter-doccomments) is a parser change that affects the AST; the rest are library functions, new built-in enums, and reflection/runtime/ini/stream changes that don't touch the parse tree. `AST_PARAM` already has a `docComment` child (index 4), which was always `null` before 8.6. It is now populated by the parser for parameters carrying a doc comment, with no extension changes required. The output matches the engine's own `ReflectionParameter::getDocComment()` (including the before-vs-after-parameter comment behavior), and older AST versions are unaffected. `tests/php86_param_doc_comments.phpt` is added as a version-gated regression test (skips on PHP < 8.6), covering doc comments on both function parameters and property-hook parameters. ## CI There is no published `php:8.6` docker image yet, so 8.6 could not be added to the previous docker-based test matrix. CI now uses `shivammathur/setup-php` for all PHP versions (7.2–8.6) in a single matrix, replacing the docker-based setup. 8.6 is built from php-src master and marked `continue-on-error` since it is still in development and is a moving target. The `package.xml` validation previously run in `ci/test_inner.sh` is preserved as a `pecl package` step, and the now-unused `ci/` docker scripts are removed. --------- Co-authored-by: Claude Opus 4.8 --- .github/workflows/main.yml | 36 ++++++---- ci/Dockerfile | 13 ---- ci/test_dockerized.sh | 16 ----- ci/test_inner.sh | 9 --- php_ast.h | 9 +++ tests/php86_param_doc_comments.phpt | 105 ++++++++++++++++++++++++++++ 6 files changed, 135 insertions(+), 53 deletions(-) delete mode 100644 ci/Dockerfile delete mode 100755 ci/test_dockerized.sh delete mode 100755 ci/test_inner.sh create mode 100644 tests/php86_param_doc_comments.phpt diff --git a/php_ast.h b/php_ast.h index efecc21..06756ed 100644 --- a/php_ast.h +++ b/php_ast.h @@ -99,6 +99,15 @@ extern ast_str_globals str_globals; # define ZEND_AST_CLONE 0x1fc #endif +#if PHP_VERSION_ID >= 80600 +/* ZEND_AST_METHOD_REFERENCE was renamed to ZEND_AST_TRAIT_METHOD_REFERENCE. */ +# define ZEND_AST_METHOD_REFERENCE ZEND_AST_TRAIT_METHOD_REFERENCE +/* The _throw() ZPP variants were removed; plain ZPP now always throws. + * ZEND_PARSE_PARAMS_THROW is gone, so a flag of 0 yields the throwing default. */ +# define ZEND_PARSE_PARAMS_THROW 0 +# define zend_parse_parameters_throw zend_parse_parameters +#endif + /* Pretend it still exists */ # define ZEND_AST_LIST ((1 << (ZEND_AST_IS_LIST_SHIFT + 1)) - 1) diff --git a/tests/php86_param_doc_comments.phpt b/tests/php86_param_doc_comments.phpt new file mode 100644 index 0000000..ae11fd1 --- /dev/null +++ b/tests/php86_param_doc_comments.phpt @@ -0,0 +1,105 @@ +--TEST-- +Doc comments on function/method parameters (PHP 8.6+) +--SKIPIF-- +=8.6 only'); ?> +--FILE-- +p = $value; } + } +} +PHP; + +echo ast_dump(ast\parse_code($code, $version=120)), "\n"; +--EXPECT-- +AST_STMT_LIST + 0: AST_FUNC_DECL + name: "f" + docComment: null + params: AST_PARAM_LIST + 0: AST_PARAM + type: AST_TYPE + flags: TYPE_LONG (4) + name: "a" + default: null + attributes: null + docComment: "/** doc for $a */" + hooks: null + 1: AST_PARAM + type: null + name: "b" + default: null + attributes: null + docComment: null + hooks: null + 2: AST_PARAM + type: AST_TYPE + flags: TYPE_STRING (6) + name: "c" + default: "x" + attributes: null + docComment: "/** doc for $c */" + hooks: null + stmts: AST_STMT_LIST + returnType: null + attributes: null + __declId: 0 + 1: AST_CLASS + name: "C" + 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: "p" + 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: "value" + default: null + attributes: null + docComment: "/** doc for $value */" + hooks: null + stmts: AST_STMT_LIST + 0: AST_ASSIGN + var: AST_PROP + expr: AST_VAR + name: "this" + prop: "p" + expr: AST_VAR + name: "value" + attributes: null + __declId: 1 + attributes: null + attributes: null + type: null + __declId: 2