Skip to content

Commit 80e5784

Browse files
Reflection: show the type of object constants used as default properties
When a property default is based on a global constant, show the type of the default. Previously, `format_default_value()` assumed that non-scalar and non-array defaults were always going to be `IS_CONSTANT_AST` pointers, and when the AST expression had been evaluated and produced an object, depending on when the `ReflectionClass` or `ReflectionProperty` instance had been created, the default was shown as one of `callable`, `__CLASS__`, or `...`. Instead, if the default value is an object (`IS_OBJECT`), show the type of that object. Add test cases for each of the `callable`, `__CLASS__`, and `...` cases to confirm that they all now properly show the type of the constant. Closes gh-15902
1 parent dd0ced3 commit 80e5784

7 files changed

+177
-0
lines changed

ext/reflection/php_reflection.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,11 @@ static int format_default_value(smart_str *str, zval *value) {
682682
format_default_value(str, zv);
683683
} ZEND_HASH_FOREACH_END();
684684
smart_str_appendc(str, ']');
685+
} else if (Z_TYPE_P(value) == IS_OBJECT) {
686+
// Show a consistent output with the type of the object, GH-15902
687+
smart_str_appends(str, "object(");
688+
smart_str_append(str, Z_OBJCE_P(value)->name);
689+
smart_str_appends(str, ")");
685690
} else {
686691
ZEND_ASSERT(Z_TYPE_P(value) == IS_CONSTANT_AST);
687692
zend_string *ast_str = zend_ast_export("", Z_ASTVAL_P(value), "");
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
ReflectionClass object default property - used to say "callable"
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public stdClass $a = FOO;
8+
}
9+
define('FOO', new stdClass);
10+
11+
new C;
12+
13+
$reflector = new ReflectionClass(C::class);
14+
var_dump( (string)$reflector );
15+
?>
16+
--EXPECTF--
17+
string(%d) "Class [ <user> class C ] {
18+
@@ %sReflectionClass-callable.php %d-%d
19+
20+
- Constants [0] {
21+
}
22+
23+
- Static properties [0] {
24+
}
25+
26+
- Static methods [0] {
27+
}
28+
29+
- Properties [1] {
30+
Property [ public stdClass $a = object(stdClass) ]
31+
}
32+
33+
- Methods [0] {
34+
}
35+
}
36+
"
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
ReflectionClass object default property - used to say "__CLASS__"
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public stdClass $a = FOO;
8+
}
9+
$reflector = new ReflectionClass(C::class);
10+
11+
define('FOO', new stdClass);
12+
new C;
13+
14+
var_dump( (string)$reflector );
15+
16+
?>
17+
--EXPECTF--
18+
string(%d) "Class [ <user> class C ] {
19+
@@ %sReflectionClass-class.php %d-%d
20+
21+
- Constants [0] {
22+
}
23+
24+
- Static properties [0] {
25+
}
26+
27+
- Static methods [0] {
28+
}
29+
30+
- Properties [1] {
31+
Property [ public stdClass $a = object(stdClass) ]
32+
}
33+
34+
- Methods [0] {
35+
}
36+
}
37+
"
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--TEST--
2+
ReflectionClass object default property - used to say "..."
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public stdClass $a = FOO;
8+
}
9+
$reflector = new ReflectionClass(C::class);
10+
$c = $reflector->newLazyGhost(function () {});
11+
12+
define('FOO', new stdClass);
13+
14+
$c->a;
15+
16+
var_dump( (string)$reflector );
17+
18+
?>
19+
--EXPECTF--
20+
string(%d) "Class [ <user> class C ] {
21+
@@ %sReflectionClass-dots.php %d-%d
22+
23+
- Constants [0] {
24+
}
25+
26+
- Static properties [0] {
27+
}
28+
29+
- Static methods [0] {
30+
}
31+
32+
- Properties [1] {
33+
Property [ public stdClass $a = object(stdClass) ]
34+
}
35+
36+
- Methods [0] {
37+
}
38+
}
39+
"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
ReflectionProperty object default - used to say "callable"
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public stdClass $a = FOO;
8+
}
9+
define('FOO', new stdClass);
10+
11+
new C;
12+
13+
$reflector = new ReflectionProperty(C::class, 'a');
14+
var_dump( (string)$reflector );
15+
16+
?>
17+
--EXPECTF--
18+
string(%d) "Property [ public stdClass $a = object(stdClass) ]
19+
"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
ReflectionProperty object default - used to say "__CLASS__"
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public stdClass $a = FOO;
8+
}
9+
$reflector = new ReflectionProperty(C::class, 'a');
10+
11+
define('FOO', new stdClass);
12+
new C;
13+
14+
var_dump( (string)$reflector );
15+
16+
?>
17+
--EXPECTF--
18+
string(%d) "Property [ public stdClass $a = object(stdClass) ]
19+
"
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
ReflectionProperty object default - used to say "..."
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public stdClass $a = FOO;
8+
}
9+
$reflector = new ReflectionProperty(C::class, 'a');
10+
$lazyFactory = new ReflectionClass(C::class);
11+
$c = $lazyFactory->newLazyGhost(function () {});
12+
13+
define('FOO', new stdClass);
14+
15+
$c->a;
16+
17+
var_dump( (string)$reflector );
18+
19+
?>
20+
--EXPECTF--
21+
string(%d) "Property [ public stdClass $a = object(stdClass) ]
22+
"

0 commit comments

Comments
 (0)