Skip to content

Commit e36cc7d

Browse files
authored
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
1 parent a5b2f60 commit e36cc7d

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

ast.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
#include "zend_language_parser.h"
1414
#include "zend_exceptions.h"
1515
#include "zend_smart_str.h"
16+
#if PHP_VERSION_ID >= 80200
17+
/* Used for AllowDynamicProperties */
18+
#include "zend_attributes.h"
19+
#endif
1620

1721
#ifndef ZEND_ARG_INFO_WITH_DEFAULT_VALUE
1822
#define ZEND_ARG_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, default_value) \
@@ -1518,6 +1522,10 @@ PHP_MINIT_FUNCTION(ast) {
15181522
ast_declare_property(ast_node_ce, AST_STR(str_flags), &zv_null);
15191523
ast_declare_property(ast_node_ce, AST_STR(str_lineno), &zv_null);
15201524
ast_declare_property(ast_node_ce, AST_STR(str_children), &zv_null);
1525+
#ifdef ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES
1526+
zend_add_class_attribute(ast_node_ce, zend_ce_allow_dynamic_properties->name, 0);
1527+
ast_node_ce->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES;
1528+
#endif
15211529

15221530
INIT_CLASS_ENTRY(tmp_ce, "ast\\Metadata", NULL);
15231531
ast_metadata_ce = zend_register_internal_class(&tmp_ce);

package.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
</stability>
3030
<license uri="https://github.com/nikic/php-ast/blob/master/LICENSE">BSD-3-Clause</license>
3131
<notes>
32-
- TBD
32+
- Allow ast\Node to have dynamic properties without emitting a notice in PHP 8.2.
3333
</notes>
3434
<contents>
3535
<dir name="/">
@@ -115,6 +115,7 @@
115115
<file name="php81_final_class_const.phpt" role="test" />
116116
<file name="php81_intersection_types.phpt" role="test" />
117117
<file name="php81_readonly.phpt" role="test" />
118+
<file name="php82_metadata.phpt" role="test" />
118119
<file name="prop_doc_comments.phpt" role="test" />
119120
<file name="short_arrow_function.phpt" role="test" />
120121
<file name="short_arrow_function_return.phpt" role="test" />

tests/php82_metadata.phpt

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
--TEST--
2+
Dynamic property support in php 8.2+
3+
--SKIPIF--
4+
<?php if (!class_exists('AllowDynamicProperties')) die('skip PHP >=8.2 only'); ?>
5+
--FILE--
6+
<?php
7+
error_reporting(E_ALL);
8+
ini_set('display_errors', 'stderr');
9+
10+
function dump($x) {
11+
var_export($x);
12+
echo "\n";
13+
}
14+
15+
function dump_attributes(string $class) {
16+
echo "Attributes of $class:\n";
17+
foreach ((new ReflectionClass($class))->getAttributes() as $attribute) {
18+
echo "- " . $attribute->getName() . "\n";
19+
}
20+
}
21+
22+
$node = new ast\Node();
23+
$node->undeclaredDynamic = 123;
24+
dump($node);
25+
$metadata = new ast\Metadata();
26+
$metadata->undeclaredDynamic = 123;
27+
dump($metadata);
28+
dump_attributes(ast\Node::class);
29+
dump_attributes(ast\Metadata::class);
30+
--EXPECTF--
31+
ast\Node::__set_state(array(
32+
'kind' => NULL,
33+
'flags' => NULL,
34+
'lineno' => NULL,
35+
'children' => NULL,
36+
'undeclaredDynamic' => 123,
37+
))
38+
Deprecated: Creation of dynamic property ast\Metadata::$undeclaredDynamic is deprecated in %sphp82_metadata.php on line 21
39+
ast\Metadata::__set_state(array(
40+
'kind' => NULL,
41+
'name' => NULL,
42+
'flags' => NULL,
43+
'flagsCombinable' => NULL,
44+
'undeclaredDynamic' => 123,
45+
))
46+
Attributes of ast\Node:
47+
- AllowDynamicProperties
48+
Attributes of ast\Metadata:

0 commit comments

Comments
 (0)