1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

ReflectionType improvements

Added ReflectionNamedType and updated ReflectionType::__toString()
This commit is contained in:
Aaron Piotrowski
2016-08-09 13:54:06 -05:00
committed by Nikita Popov
parent 283b0cc8a5
commit 622d2f41d1
7 changed files with 121 additions and 28 deletions

4
NEWS
View File

@@ -28,7 +28,9 @@ PHP NEWS
- Reflection:
. Implemented request #38992 (invoke() and invokeArgs() static method calls
should match). (cmb)
should match). (cmb).
. Add ReflectionNamedType::getName() and return leading "?" for nullable types
from ReflectionType::__toString(). (Trowski)
- SQLite3:
. Updated to SQLite3 3.14.0. (cmb)

View File

@@ -93,6 +93,9 @@ PHP 7.1 UPGRADE NOTES
. The behavior of ReflectionMethod::invoke() and ::invokeArgs() has been
aligned, what causes slightly different behavior than before for some
pathological cases.
. ReflectionType::__toString() will now return the type name with a leading
"?" if it is nullable. To retrieve the type name without leading "?" the new
ReflectionNamedType::getName() method can be used.
========================================
2. New Features

View File

@@ -60,6 +60,7 @@ PHPAPI zend_class_entry *reflection_function_ptr;
PHPAPI zend_class_entry *reflection_generator_ptr;
PHPAPI zend_class_entry *reflection_parameter_ptr;
PHPAPI zend_class_entry *reflection_type_ptr;
PHPAPI zend_class_entry *reflection_named_type_ptr;
PHPAPI zend_class_entry *reflection_class_ptr;
PHPAPI zend_class_entry *reflection_object_ptr;
PHPAPI zend_class_entry *reflection_method_ptr;
@@ -1276,7 +1277,7 @@ static void reflection_type_factory(zend_function *fptr, zval *closure_object, s
reflection_object *intern;
type_reference *reference;
reflection_instantiate(reflection_type_ptr, object);
reflection_instantiate(reflection_named_type_ptr, object);
intern = Z_REFLECTION_P(object);
reference = (type_reference*) emalloc(sizeof(type_reference));
reference->arg_info = arg_info;
@@ -2999,35 +3000,66 @@ ZEND_METHOD(reflection_type, isBuiltin)
}
/* }}} */
/* {{{ reflection_type_name */
static zend_string *reflection_type_name(type_reference *param) {
switch (param->arg_info->type_hint) {
case IS_ARRAY: return zend_string_init("array", sizeof("array") - 1, 0);
case IS_CALLABLE: return zend_string_init("callable", sizeof("callable") - 1, 0);
case IS_OBJECT:
if (param->fptr->type == ZEND_INTERNAL_FUNCTION &&
!(param->fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
return zend_string_init(((zend_internal_arg_info*)param->arg_info)->class_name, strlen(((zend_internal_arg_info*)param->arg_info)->class_name), 0);
}
return zend_string_copy(param->arg_info->class_name);
case IS_STRING: return zend_string_init("string", sizeof("string") - 1, 0);
case _IS_BOOL: return zend_string_init("bool", sizeof("bool") - 1, 0);
case IS_LONG: return zend_string_init("int", sizeof("int") - 1, 0);
case IS_DOUBLE: return zend_string_init("float", sizeof("float") - 1, 0);
case IS_VOID: return zend_string_init("void", sizeof("void") - 1, 0);
case IS_ITERABLE: return zend_string_init("iterable", sizeof("iterable") - 1, 0);
EMPTY_SWITCH_DEFAULT_CASE()
}
}
/* }}} */
/* {{{ proto public string ReflectionType::__toString()
Return the text of the type hint */
ZEND_METHOD(reflection_type, __toString)
{
reflection_object *intern;
type_reference *param;
zend_string *str;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
GET_REFLECTION_OBJECT_PTR(param);
switch (param->arg_info->type_hint) {
case IS_ARRAY: RETURN_STRINGL("array", sizeof("array") - 1);
case IS_CALLABLE: RETURN_STRINGL("callable", sizeof("callable") - 1);
case IS_OBJECT:
if (param->fptr->type == ZEND_INTERNAL_FUNCTION &&
!(param->fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
RETURN_STRING(((zend_internal_arg_info*)param->arg_info)->class_name);
}
RETURN_STR_COPY(param->arg_info->class_name);
case IS_STRING: RETURN_STRINGL("string", sizeof("string") - 1);
case _IS_BOOL: RETURN_STRINGL("bool", sizeof("bool") - 1);
case IS_LONG: RETURN_STRINGL("int", sizeof("int") - 1);
case IS_DOUBLE: RETURN_STRINGL("float", sizeof("float") - 1);
case IS_VOID: RETURN_STRINGL("void", sizeof("void") - 1);
case IS_ITERABLE: RETURN_STRINGL("iterable", sizeof("iterable") - 1);
EMPTY_SWITCH_DEFAULT_CASE()
str = reflection_type_name(param);
if (param->arg_info->allow_null) {
str = zend_string_extend(str, ZSTR_LEN(str) + 1, 0);
memmove(ZSTR_VAL(str) + 1, ZSTR_VAL(str), ZSTR_LEN(str) + 1);
ZSTR_VAL(str)[0] = '?';
}
RETURN_STR(str);
}
/* }}} */
/* {{{ proto public string ReflectionNamedType::getName()
Return the text of the type hint */
ZEND_METHOD(reflection_named_type, getName)
{
reflection_object *intern;
type_reference *param;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
GET_REFLECTION_OBJECT_PTR(param);
RETURN_STR(reflection_type_name(param));
}
/* }}} */
@@ -6688,6 +6720,11 @@ static const zend_function_entry reflection_type_functions[] = {
PHP_FE_END
};
static const zend_function_entry reflection_named_type_functions[] = {
ZEND_ME(reflection_named_type, getName, arginfo_reflection__void, 0)
PHP_FE_END
};
ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_extension_export, 0, 0, 1)
ZEND_ARG_INFO(0, name)
ZEND_ARG_INFO(0, return)
@@ -6804,6 +6841,10 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionType", reflection_type_functions);
_reflection_entry.create_object = reflection_objects_new;
reflection_type_ptr = zend_register_internal_class(&_reflection_entry);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionNamedType", reflection_named_type_functions);
_reflection_entry.create_object = reflection_objects_new;
reflection_named_type_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_type_ptr);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionMethod", reflection_method_functions);
_reflection_entry.create_object = reflection_objects_new;

View File

@@ -38,6 +38,7 @@ extern PHPAPI zend_class_entry *reflection_function_abstract_ptr;
extern PHPAPI zend_class_entry *reflection_function_ptr;
extern PHPAPI zend_class_entry *reflection_parameter_ptr;
extern PHPAPI zend_class_entry *reflection_type_ptr;
extern PHPAPI zend_class_entry *reflection_named_type_ptr;
extern PHPAPI zend_class_entry *reflection_class_ptr;
extern PHPAPI zend_class_entry *reflection_object_ptr;
extern PHPAPI zend_class_entry *reflection_method_ptr;

View File

@@ -9,7 +9,7 @@ var_dump($ext->getClasses());
?>
==DONE==
--EXPECT--
array(15) {
array(16) {
["ReflectionException"]=>
object(ReflectionClass)#2 (1) {
["name"]=>
@@ -50,38 +50,43 @@ array(15) {
["name"]=>
string(14) "ReflectionType"
}
["ReflectionMethod"]=>
["ReflectionNamedType"]=>
object(ReflectionClass)#10 (1) {
["name"]=>
string(19) "ReflectionNamedType"
}
["ReflectionMethod"]=>
object(ReflectionClass)#11 (1) {
["name"]=>
string(16) "ReflectionMethod"
}
["ReflectionClass"]=>
object(ReflectionClass)#11 (1) {
object(ReflectionClass)#12 (1) {
["name"]=>
string(15) "ReflectionClass"
}
["ReflectionObject"]=>
object(ReflectionClass)#12 (1) {
object(ReflectionClass)#13 (1) {
["name"]=>
string(16) "ReflectionObject"
}
["ReflectionProperty"]=>
object(ReflectionClass)#13 (1) {
object(ReflectionClass)#14 (1) {
["name"]=>
string(18) "ReflectionProperty"
}
["ReflectionClassConstant"]=>
object(ReflectionClass)#14 (1) {
object(ReflectionClass)#15 (1) {
["name"]=>
string(23) "ReflectionClassConstant"
}
["ReflectionExtension"]=>
object(ReflectionClass)#15 (1) {
object(ReflectionClass)#16 (1) {
["name"]=>
string(19) "ReflectionExtension"
}
["ReflectionZendExtension"]=>
object(ReflectionClass)#16 (1) {
object(ReflectionClass)#17 (1) {
["name"]=>
string(23) "ReflectionZendExtension"
}

View File

@@ -0,0 +1,41 @@
--TEST--
ReflectionNamedType::getName() and ReflectionNamedType::__toString()
--FILE--
<?php
function testInternalTypes(?Traversable $traversable): ?string {
return 'test';
}
function testUserDefinedTypes(?Test $traversable): ?Test {
return new Test;
}
$function = new ReflectionFunction('testInternalTypes');
$type = $function->getParameters()[0]->getType();
$return = $function->getReturnType();
var_dump($type->getName());
var_dump((string) $type);
var_dump($return->getName());
var_dump((string) $return);
$function = new ReflectionFunction('testUserDefinedTypes');
$type = $function->getParameters()[0]->getType();
$return = $function->getReturnType();
var_dump($type->getName());
var_dump((string) $type);
var_dump($return->getName());
var_dump((string) $return);
?>
--EXPECTF--
string(11) "Traversable"
string(12) "?Traversable"
string(6) "string"
string(7) "?string"
string(4) "Test"
string(5) "?Test"
string(4) "Test"
string(5) "?Test"

View File

@@ -94,7 +94,7 @@ string(8) "callable"
bool(true)
bool(true)
bool(false)
string(8) "stdClass"
string(9) "?stdClass"
** Function 0 - Parameter 4
bool(false)
** Function 0 - Parameter 5