Fix #80097: Have ReflectionAttribute implement Reflector and __toString

Implement printing for ReflectionAttribute. Attributes aren't
printed as part of reflection output for other structures (classes
etc) yet.

Closes GH-6117.
This commit is contained in:
Benjamin Eberlei 2021-06-19 21:28:18 +02:00 committed by Nikita Popov
parent ce3846cd87
commit bc39abe8c3
5 changed files with 90 additions and 5 deletions

3
NEWS
View file

@ -2,7 +2,8 @@ PHP NEWS
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.1.0beta1 ?? ??? ????, PHP 8.1.0beta1
- Reflection:
. Fixed bug #80097 (ReflectionAttribute is not a Reflector). (beberlei)
08 Jul 2021, PHP 8.1.0alpha3 08 Jul 2021, PHP 8.1.0alpha3

View file

@ -6452,6 +6452,57 @@ ZEND_METHOD(ReflectionAttribute, __clone)
_DO_THROW("Cannot clone object using __clone()"); _DO_THROW("Cannot clone object using __clone()");
} }
/* {{{ Returns a string representation */
ZEND_METHOD(ReflectionAttribute, __toString)
{
reflection_object *intern;
attribute_reference *attr;
if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
}
GET_REFLECTION_OBJECT_PTR(attr);
smart_str str = {0};
smart_str_appends(&str, "Attribute [ ");
smart_str_append(&str, attr->data->name);
smart_str_appends(&str, " ]");
if (attr->data->argc > 0) {
smart_str_appends(&str, " {\n");
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)) {
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) {
return;
}
smart_str_appends(&str, " ]\n");
zval_ptr_dtor(&tmp);
}
smart_str_appends(&str, " }\n");
smart_str_appends(&str, "}\n");
} else {
smart_str_appendc(&str, '\n');
}
RETURN_STR(smart_str_extract(&str));
}
/* }}} */
/* {{{ * Returns the name of the attribute */ /* {{{ * Returns the name of the attribute */
ZEND_METHOD(ReflectionAttribute, getName) ZEND_METHOD(ReflectionAttribute, getName)
{ {
@ -7121,7 +7172,7 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
reflection_reference_ptr = register_class_ReflectionReference(); reflection_reference_ptr = register_class_ReflectionReference();
reflection_init_class_handlers(reflection_reference_ptr); reflection_init_class_handlers(reflection_reference_ptr);
reflection_attribute_ptr = register_class_ReflectionAttribute(); reflection_attribute_ptr = register_class_ReflectionAttribute(reflector_ptr);
reflection_init_class_handlers(reflection_attribute_ptr); reflection_init_class_handlers(reflection_attribute_ptr);
reflection_enum_ptr = register_class_ReflectionEnum(reflection_class_ptr); reflection_enum_ptr = register_class_ReflectionEnum(reflection_class_ptr);

View file

@ -687,7 +687,7 @@ final class ReflectionReference
private function __construct() {} private function __construct() {}
} }
final class ReflectionAttribute final class ReflectionAttribute implements Reflector
{ {
public function getName(): string {} public function getName(): string {}
public function getTarget(): int {} public function getTarget(): int {}
@ -695,6 +695,8 @@ final class ReflectionAttribute
public function getArguments(): array {} public function getArguments(): array {}
public function newInstance(): object {} public function newInstance(): object {}
public function __toString(): string {}
private function __clone(): void {} private function __clone(): void {}
private function __construct() {} private function __construct() {}

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead. /* This is a generated file, edit the .stub.php file instead.
* Stub hash: 2564122a201ca462ee35ead1562c94da3ea3c8a3 */ * Stub hash: b70561858fb66134ce9596921215881fd9b946c0 */
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0) ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0)
ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0)
@ -543,6 +543,8 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionAttribute_newInstance, 0, 0, IS_OBJECT, 0) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionAttribute_newInstance, 0, 0, IS_OBJECT, 0)
ZEND_END_ARG_INFO() ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionAttribute___toString arginfo_class_ReflectionFunction___toString
#define arginfo_class_ReflectionAttribute___clone arginfo_class_ReflectionFunctionAbstract___clone #define arginfo_class_ReflectionAttribute___clone arginfo_class_ReflectionFunctionAbstract___clone
#define arginfo_class_ReflectionAttribute___construct arginfo_class_ReflectionReference___construct #define arginfo_class_ReflectionAttribute___construct arginfo_class_ReflectionReference___construct
@ -800,6 +802,7 @@ ZEND_METHOD(ReflectionAttribute, getTarget);
ZEND_METHOD(ReflectionAttribute, isRepeated); ZEND_METHOD(ReflectionAttribute, isRepeated);
ZEND_METHOD(ReflectionAttribute, getArguments); ZEND_METHOD(ReflectionAttribute, getArguments);
ZEND_METHOD(ReflectionAttribute, newInstance); ZEND_METHOD(ReflectionAttribute, newInstance);
ZEND_METHOD(ReflectionAttribute, __toString);
ZEND_METHOD(ReflectionAttribute, __clone); ZEND_METHOD(ReflectionAttribute, __clone);
ZEND_METHOD(ReflectionAttribute, __construct); ZEND_METHOD(ReflectionAttribute, __construct);
ZEND_METHOD(ReflectionEnum, __construct); ZEND_METHOD(ReflectionEnum, __construct);
@ -1130,6 +1133,7 @@ static const zend_function_entry class_ReflectionAttribute_methods[] = {
ZEND_ME(ReflectionAttribute, isRepeated, arginfo_class_ReflectionAttribute_isRepeated, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionAttribute, isRepeated, arginfo_class_ReflectionAttribute_isRepeated, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionAttribute, getArguments, arginfo_class_ReflectionAttribute_getArguments, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionAttribute, getArguments, arginfo_class_ReflectionAttribute_getArguments, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionAttribute, newInstance, arginfo_class_ReflectionAttribute_newInstance, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionAttribute, newInstance, arginfo_class_ReflectionAttribute_newInstance, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionAttribute, __toString, arginfo_class_ReflectionAttribute___toString, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionAttribute, __clone, arginfo_class_ReflectionAttribute___clone, ZEND_ACC_PRIVATE) ZEND_ME(ReflectionAttribute, __clone, arginfo_class_ReflectionAttribute___clone, ZEND_ACC_PRIVATE)
ZEND_ME(ReflectionAttribute, __construct, arginfo_class_ReflectionAttribute___construct, ZEND_ACC_PRIVATE) ZEND_ME(ReflectionAttribute, __construct, arginfo_class_ReflectionAttribute___construct, ZEND_ACC_PRIVATE)
ZEND_FE_END ZEND_FE_END
@ -1435,13 +1439,14 @@ static zend_class_entry *register_class_ReflectionReference(void)
return class_entry; return class_entry;
} }
static zend_class_entry *register_class_ReflectionAttribute(void) static zend_class_entry *register_class_ReflectionAttribute(zend_class_entry *class_entry_Reflector)
{ {
zend_class_entry ce, *class_entry; zend_class_entry ce, *class_entry;
INIT_CLASS_ENTRY(ce, "ReflectionAttribute", class_ReflectionAttribute_methods); INIT_CLASS_ENTRY(ce, "ReflectionAttribute", class_ReflectionAttribute_methods);
class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry = zend_register_internal_class_ex(&ce, NULL);
class_entry->ce_flags |= ZEND_ACC_FINAL; class_entry->ce_flags |= ZEND_ACC_FINAL;
zend_class_implements(class_entry, 1, class_entry_Reflector);
return class_entry; return class_entry;
} }

View file

@ -0,0 +1,26 @@
--TEST--
ReflectionAttribute::__toString
--FILE--
<?php
#[Foo, Bar(a: "foo", b: 1234), Baz("foo", 1234)]
function foo() {}
$refl = new ReflectionFunction('foo');
echo $refl->getAttributes()[0];
echo $refl->getAttributes()[1];
echo $refl->getAttributes()[2];
--EXPECTF--
Attribute [ Foo ]
Attribute [ Bar ] {
- Arguments [2] {
Argument #0 [ a = 'foo' ]
Argument #1 [ b = 1234 ]
}
}
Attribute [ Baz ] {
- Arguments [2] {
Argument #0 [ 'foo' ]
Argument #1 [ 1234 ]
}
}