Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export AST for default value strings in reflection #7540

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion Zend/zend_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -1947,7 +1947,20 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
zend_ast_export_name(str, ast->child[1], 0, indent);
break;
case ZEND_AST_CLASS_NAME:
zend_ast_export_ns_name(str, ast->child[0], 0, indent);
if (ast->child[0] == NULL) {
/* The const expr representation stores the fetch type instead. */
switch (ast->attr) {
case ZEND_FETCH_CLASS_SELF:
smart_str_appends(str, "self");
break;
case ZEND_FETCH_CLASS_PARENT:
smart_str_appends(str, "parent");
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
} else {
zend_ast_export_ns_name(str, ast->child[0], 0, indent);
}
smart_str_appends(str, "::class");
break;
case ZEND_AST_ASSIGN: BINARY_OP(" = ", 90, 91, 90);
Expand Down
32 changes: 8 additions & 24 deletions ext/reflection/php_reflection.c
Original file line number Diff line number Diff line change
Expand Up @@ -610,24 +610,16 @@ static zval *get_default_from_recv(zend_op_array *op_array, uint32_t offset) {
}

static int format_default_value(smart_str *str, zval *value, zend_class_entry *scope) {
zval zv;
ZVAL_COPY(&zv, value);
if (UNEXPECTED(zval_update_constant_ex(&zv, scope) == FAILURE)) {
zval_ptr_dtor(&zv);
return FAILURE;
}

if (Z_TYPE(zv) <= IS_STRING) {
smart_str_append_scalar(str, &zv, 15);
} else if (Z_TYPE(zv) == IS_ARRAY) {
if (Z_TYPE_P(value) <= IS_STRING) {
smart_str_append_scalar(str, value, 15);
} else if (Z_TYPE_P(value) == IS_ARRAY) {
smart_str_appends(str, "Array");
} else {
zend_string *tmp_zv_str;
zend_string *zv_str = zval_get_tmp_string(&zv, &tmp_zv_str);
smart_str_append(str, zv_str);
zend_tmp_string_release(tmp_zv_str);
ZEND_ASSERT(Z_TYPE_P(value) == IS_CONSTANT_AST);
zend_string *ast_str = zend_ast_export("", Z_ASTVAL_P(value), "");
smart_str_append(str, ast_str);
zend_string_release(ast_str);
}
zval_ptr_dtor(&zv);
return SUCCESS;
}

Expand Down Expand Up @@ -6404,26 +6396,18 @@ ZEND_METHOD(ReflectionAttribute, __toString)
smart_str_append_printf(&str, " - Arguments [%d] {\n", attr->data->argc);

for (uint32_t i = 0; i < attr->data->argc; i++) {
zval tmp;
if (FAILURE == zend_get_attribute_value(&tmp, attr->data, i, attr->scope)) {
smart_str_free(&str);
RETURN_THROWS();
}

smart_str_append_printf(&str, " Argument #%d [ ", i);
if (attr->data->args[i].name != NULL) {
smart_str_append(&str, attr->data->args[i].name);
smart_str_appends(&str, " = ");
}

if (format_default_value(&str, &tmp, NULL) == FAILURE) {
zval_ptr_dtor(&tmp);
if (format_default_value(&str, &attr->data->args[i].value, NULL) == FAILURE) {
smart_str_free(&str);
RETURN_THROWS();
}

smart_str_appends(&str, " ]\n");
zval_ptr_dtor(&tmp);
}
smart_str_appends(&str, " }\n");

Expand Down
20 changes: 13 additions & 7 deletions ext/reflection/tests/ReflectionAttribute_toString.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,15 @@ ReflectionAttribute::__toString
--FILE--
<?php

#[Foo, Bar(a: "foo", b: 1234), Baz("foo", 1234), XXX(ERROR)]
#[Foo, Bar(a: "foo", b: 1234), Baz("foo", 1234), X(NO_ERROR), Y(new stdClass)]
function foo() {}

$refl = new ReflectionFunction('foo');
echo $refl->getAttributes()[0];
echo $refl->getAttributes()[1];
echo $refl->getAttributes()[2];
try {
echo $refl->getAttributes()[3];
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
echo $refl->getAttributes()[3];
echo $refl->getAttributes()[4];

?>
--EXPECT--
Expand All @@ -31,4 +28,13 @@ Attribute [ Baz ] {
Argument #1 [ 1234 ]
}
}
Undefined constant "ERROR"
Attribute [ X ] {
- Arguments [1] {
Argument #0 [ NO_ERROR ]
}
}
Attribute [ Y ] {
- Arguments [1] {
Argument #0 [ new \stdClass() ]
}
}
2 changes: 1 addition & 1 deletion ext/reflection/tests/ReflectionClass_export_basic1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Class [ <user> class C extends A ] {
Parameter #0 [ <required> A $a ]
Parameter #1 [ <required> $b ]
Parameter #2 [ <optional> ?C $c = NULL ]
Parameter #3 [ <optional> $d = '16 chars long -...' ]
Parameter #3 [ <optional> $d = K ]
Parameter #4 [ <optional> $e = '15 chars long -' ]
Parameter #5 [ <optional> $f = NULL ]
Parameter #6 [ <optional> $g = false ]
Expand Down
4 changes: 2 additions & 2 deletions ext/reflection/tests/ReflectionMethod_defaultArg.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ Method [ <user> private method bar ] {
@@ %s

- Parameters [1] {
Parameter #0 [ <optional> $a = 'T' ]
Parameter #0 [ <optional> $a = self::class ]
}
}
Method [ <user> private method bar ] {
@@ %s

- Parameters [1] {
Parameter #0 [ <optional> $a = 'B' ]
Parameter #0 [ <optional> $a = self::class ]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ string(%d) "Method [ <user, overwrites DateTimeZone, prototype DateTimeZone> sta
@@ %s

- Parameters [2] {
Parameter #0 [ <optional> int $timezoneGroup = %d ]
Parameter #0 [ <optional> int $timezoneGroup = DateTimeZone::ALL ]
Parameter #1 [ <optional> ?string $countryCode = NULL ]
}
- Return [ string ]
Expand Down
17 changes: 17 additions & 0 deletions ext/reflection/tests/ReflectionParameter_new_initializer.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
ReflectionParameter::__toString() with new initializer
--FILE--
<?php

function test(
$p1 = new stdClass,
$p2 = new SomeClass(new With, some: new Parameters)
) {}

echo new ReflectionParameter('test', 'p1'), "\n";
echo new ReflectionParameter('test', 'p2'), "\n";

?>
--EXPECT--
Parameter #0 [ <optional> $p1 = new \stdClass() ]
Parameter #1 [ <optional> $p2 = new \SomeClass(new \With(), some: new \Parameters()) ]
2 changes: 1 addition & 1 deletion ext/reflection/tests/bug33389.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Class [ <user> class Test ] {
@@ %sbug33389.php 4 - 5

- Parameters [1] {
Parameter #0 [ <optional> $arg = 1 ]
Parameter #0 [ <optional> $arg = foobar ]
}
}

Expand Down
8 changes: 4 additions & 4 deletions ext/reflection/tests/bug45765.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -51,31 +51,31 @@ Object of class [ <user> class foo extends foo2 ] {
@@ %s 10 - 11

- Parameters [1] {
Parameter #0 [ <optional> $a = 'foo's bar' ]
Parameter #0 [ <optional> $a = self::BAR ]
}
}

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

- Parameters [1] {
Parameter #0 [ <optional> $a = 'foobar' ]
Parameter #0 [ <optional> $a = parent::BAR ]
}
}

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

- Parameters [1] {
Parameter #0 [ <optional> $a = 'foo's bar' ]
Parameter #0 [ <optional> $a = foo::BAR ]
}
}

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

- Parameters [1] {
Parameter #0 [ <optional> $a = 'foobar' ]
Parameter #0 [ <optional> $a = foo2::BAR ]
}
}
}
Expand Down
30 changes: 25 additions & 5 deletions ext/reflection/tests/bug74673.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,28 @@ $class = new ReflectionClass('A');
echo $class;
?>
--EXPECTF--
Fatal error: Uncaught Error: Undefined constant "PHP_SELF" in %s:%d
Stack trace:
#0 %s(%d): ReflectionClass->__toString()
#1 {main}
thrown in %s on line %d
Class [ <user> class A ] {
@@ %s

- Constants [0] {
}

- Static properties [0] {
}

- Static methods [0] {
}

- Properties [0] {
}

- Methods [1] {
Method [ <user> public method method ] {
@@ %s

- Parameters [1] {
Parameter #0 [ <optional> $test = PHP_SELF + 1 ]
}
}
}
}