Skip to content

Commit 979ccb9

Browse files
committed
Export AST for default value strings in reflection
When dumping default values in ReflectionXXX::__toString(), for expression initializers print the AST export instead of trying to evaluate the expression. With the introduction of "new in initializers" the result of the evaluation will commonly not be printable at all, and "__toString" will throw an exception, which is not particularly useful. Using the AST export also provides more information on how the parameter was originally declared, e.g. it preserves the fact that a certain constant was used.
1 parent 6d3ef57 commit 979ccb9

9 files changed

+72
-30
lines changed

Zend/zend_ast.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1947,7 +1947,20 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
19471947
zend_ast_export_name(str, ast->child[1], 0, indent);
19481948
break;
19491949
case ZEND_AST_CLASS_NAME:
1950-
zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1950+
if (ast->child[0] == NULL) {
1951+
/* The const expr representation stores the fetch type instead. */
1952+
switch (ast->attr) {
1953+
case ZEND_FETCH_CLASS_SELF:
1954+
smart_str_appends(str, "self");
1955+
break;
1956+
case ZEND_FETCH_CLASS_PARENT:
1957+
smart_str_appends(str, "parent");
1958+
break;
1959+
EMPTY_SWITCH_DEFAULT_CASE()
1960+
}
1961+
} else {
1962+
zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1963+
}
19511964
smart_str_appends(str, "::class");
19521965
break;
19531966
case ZEND_AST_ASSIGN: BINARY_OP(" = ", 90, 91, 90);

ext/reflection/php_reflection.c

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -610,24 +610,16 @@ static zval *get_default_from_recv(zend_op_array *op_array, uint32_t offset) {
610610
}
611611

612612
static int format_default_value(smart_str *str, zval *value, zend_class_entry *scope) {
613-
zval zv;
614-
ZVAL_COPY(&zv, value);
615-
if (UNEXPECTED(zval_update_constant_ex(&zv, scope) == FAILURE)) {
616-
zval_ptr_dtor(&zv);
617-
return FAILURE;
618-
}
619-
620-
if (Z_TYPE(zv) <= IS_STRING) {
621-
smart_str_append_scalar(str, &zv, 15);
622-
} else if (Z_TYPE(zv) == IS_ARRAY) {
613+
if (Z_TYPE_P(value) <= IS_STRING) {
614+
smart_str_append_scalar(str, value, 15);
615+
} else if (Z_TYPE_P(value) == IS_ARRAY) {
623616
smart_str_appends(str, "Array");
624617
} else {
625-
zend_string *tmp_zv_str;
626-
zend_string *zv_str = zval_get_tmp_string(&zv, &tmp_zv_str);
627-
smart_str_append(str, zv_str);
628-
zend_tmp_string_release(tmp_zv_str);
618+
ZEND_ASSERT(Z_TYPE_P(value) == IS_CONSTANT_AST);
619+
zend_string *ast_str = zend_ast_export("", Z_ASTVAL_P(value), "");
620+
smart_str_append(str, ast_str);
621+
zend_string_release(ast_str);
629622
}
630-
zval_ptr_dtor(&zv);
631623
return SUCCESS;
632624
}
633625

ext/reflection/tests/ReflectionClass_export_basic1.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ Class [ <user> class C extends A ] {
5151
Parameter #0 [ <required> A $a ]
5252
Parameter #1 [ <required> $b ]
5353
Parameter #2 [ <optional> ?C $c = NULL ]
54-
Parameter #3 [ <optional> $d = '16 chars long -...' ]
54+
Parameter #3 [ <optional> $d = K ]
5555
Parameter #4 [ <optional> $e = '15 chars long -' ]
5656
Parameter #5 [ <optional> $f = NULL ]
5757
Parameter #6 [ <optional> $g = false ]

ext/reflection/tests/ReflectionMethod_defaultArg.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ Method [ <user> private method bar ] {
3232
@@ %s
3333

3434
- Parameters [1] {
35-
Parameter #0 [ <optional> $a = 'T' ]
35+
Parameter #0 [ <optional> $a = self::class ]
3636
}
3737
}
3838
Method [ <user> private method bar ] {
3939
@@ %s
4040

4141
- Parameters [1] {
42-
Parameter #0 [ <optional> $a = 'B' ]
42+
Parameter #0 [ <optional> $a = self::class ]
4343
}
4444
}

ext/reflection/tests/ReflectionMethod_tentative_return_type.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ string(%d) "Method [ <user, overwrites DateTimeZone, prototype DateTimeZone> sta
4949
@@ %s
5050

5151
- Parameters [2] {
52-
Parameter #0 [ <optional> int $timezoneGroup = %d ]
52+
Parameter #0 [ <optional> int $timezoneGroup = DateTimeZone::ALL ]
5353
Parameter #1 [ <optional> ?string $countryCode = NULL ]
5454
}
5555
- Return [ string ]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
ReflectionParameter::__toString() with new initializer
3+
--FILE--
4+
<?php
5+
6+
function test(
7+
$p1 = new stdClass,
8+
$p2 = new SomeClass(new With, some: new Parameters)
9+
) {}
10+
11+
echo new ReflectionParameter('test', 'p1'), "\n";
12+
echo new ReflectionParameter('test', 'p2'), "\n";
13+
14+
?>
15+
--EXPECT--
16+
Parameter #0 [ <optional> $p1 = new \stdClass() ]
17+
Parameter #1 [ <optional> $p2 = new \SomeClass(new \With(), some: new \Parameters()) ]

ext/reflection/tests/bug33389.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Class [ <user> class Test ] {
4242
@@ %sbug33389.php 4 - 5
4343

4444
- Parameters [1] {
45-
Parameter #0 [ <optional> $arg = 1 ]
45+
Parameter #0 [ <optional> $arg = foobar ]
4646
}
4747
}
4848

ext/reflection/tests/bug45765.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,31 +51,31 @@ Object of class [ <user> class foo extends foo2 ] {
5151
@@ %s 10 - 11
5252

5353
- Parameters [1] {
54-
Parameter #0 [ <optional> $a = 'foo's bar' ]
54+
Parameter #0 [ <optional> $a = self::BAR ]
5555
}
5656
}
5757

5858
Method [ <user> public method test2 ] {
5959
@@ %s 13 - 14
6060

6161
- Parameters [1] {
62-
Parameter #0 [ <optional> $a = 'foobar' ]
62+
Parameter #0 [ <optional> $a = parent::BAR ]
6363
}
6464
}
6565

6666
Method [ <user> public method test3 ] {
6767
@@ %s 16 - 17
6868

6969
- Parameters [1] {
70-
Parameter #0 [ <optional> $a = 'foo's bar' ]
70+
Parameter #0 [ <optional> $a = foo::BAR ]
7171
}
7272
}
7373

7474
Method [ <user> public method test4 ] {
7575
@@ %s 19 - 20
7676

7777
- Parameters [1] {
78-
Parameter #0 [ <optional> $a = 'foobar' ]
78+
Parameter #0 [ <optional> $a = foo2::BAR ]
7979
}
8080
}
8181
}

ext/reflection/tests/bug74673.phpt

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,28 @@ $class = new ReflectionClass('A');
1515
echo $class;
1616
?>
1717
--EXPECTF--
18-
Fatal error: Uncaught Error: Undefined constant "PHP_SELF" in %s:%d
19-
Stack trace:
20-
#0 %s(%d): ReflectionClass->__toString()
21-
#1 {main}
22-
thrown in %s on line %d
18+
Class [ <user> class A ] {
19+
@@ %s
20+
21+
- Constants [0] {
22+
}
23+
24+
- Static properties [0] {
25+
}
26+
27+
- Static methods [0] {
28+
}
29+
30+
- Properties [0] {
31+
}
32+
33+
- Methods [1] {
34+
Method [ <user> public method method ] {
35+
@@ %s
36+
37+
- Parameters [1] {
38+
Parameter #0 [ <optional> $test = PHP_SELF + 1 ]
39+
}
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)