Skip to content

Commit 9004305

Browse files
committed
Implement reflection API for tentative types
1 parent 04e1738 commit 9004305

File tree

4 files changed

+127
-15
lines changed

4 files changed

+127
-15
lines changed

ext/reflection/php_reflection.c

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,7 @@ static void _function_string(smart_str *str, zend_function *fptr, zend_class_ent
855855
}
856856
_function_parameter_string(str, fptr, ZSTR_VAL(param_indent.s));
857857
smart_str_free(&param_indent);
858-
if (fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
858+
if (fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && !ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1])) {
859859
smart_str_append_printf(str, " %s- Return [ ", indent);
860860
if (ZEND_TYPE_IS_SET(fptr->common.arg_info[-1].type)) {
861861
zend_string *type_str = zend_type_to_string(fptr->common.arg_info[-1].type);
@@ -3454,7 +3454,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, hasReturnType)
34543454

34553455
GET_REFLECTION_OBJECT_PTR(fptr);
34563456

3457-
RETVAL_BOOL(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE);
3457+
RETVAL_BOOL(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && !ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1]));
34583458
}
34593459
/* }}} */
34603460

@@ -3470,7 +3470,43 @@ ZEND_METHOD(ReflectionFunctionAbstract, getReturnType)
34703470

34713471
GET_REFLECTION_OBJECT_PTR(fptr);
34723472

3473-
if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
3473+
if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1])) {
3474+
RETURN_NULL();
3475+
}
3476+
3477+
reflection_type_factory(fptr->common.arg_info[-1].type, return_value, 1);
3478+
}
3479+
/* }}} */
3480+
3481+
/* {{{ Return whether the function has a return type */
3482+
ZEND_METHOD(ReflectionFunctionAbstract, hasTentativeReturnType)
3483+
{
3484+
reflection_object *intern;
3485+
zend_function *fptr;
3486+
3487+
if (zend_parse_parameters_none() == FAILURE) {
3488+
RETURN_THROWS();
3489+
}
3490+
3491+
GET_REFLECTION_OBJECT_PTR(fptr);
3492+
3493+
RETVAL_BOOL(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1]));
3494+
}
3495+
/* }}} */
3496+
3497+
/* {{{ Returns the return type associated with the function */
3498+
ZEND_METHOD(ReflectionFunctionAbstract, getTentativeReturnType)
3499+
{
3500+
reflection_object *intern;
3501+
zend_function *fptr;
3502+
3503+
if (zend_parse_parameters_none() == FAILURE) {
3504+
RETURN_THROWS();
3505+
}
3506+
3507+
GET_REFLECTION_OBJECT_PTR(fptr);
3508+
3509+
if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || !ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1])) {
34743510
RETURN_NULL();
34753511
}
34763512

ext/reflection/php_reflection.stub.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ public function hasReturnType() {}
9898
/** @return ReflectionType|null */
9999
public function getReturnType() {}
100100

101+
public function hasTentativeReturnType(): bool {}
102+
103+
public function getTentativeReturnType(): ?ReflectionType {}
104+
101105
/** @return ReflectionAttribute[] */
102106
public function getAttributes(?string $name = null, int $flags = 0): array {}
103107
}

ext/reflection/php_reflection_arginfo.h

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 3594ec0b0c3ed7266223be9c6b426aac56e3aabe */
2+
* Stub hash: 806f091fa7e5bb0d58cb1f765e0010e81a06bd2a */
33

44
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0)
55
ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0)
@@ -68,6 +68,12 @@ ZEND_END_ARG_INFO()
6868
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionFunctionAbstract_getReturnType, 0, 0, ReflectionType, 1)
6969
ZEND_END_ARG_INFO()
7070

71+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType, 0, 0, _IS_BOOL, 0)
72+
ZEND_END_ARG_INFO()
73+
74+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionFunctionAbstract_getTentativeReturnType, 0, 0, ReflectionType, 1)
75+
ZEND_END_ARG_INFO()
76+
7177
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFunctionAbstract_getAttributes, 0, 0, IS_ARRAY, 0)
7278
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, name, IS_STRING, 1, "null")
7379
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0")
@@ -241,8 +247,7 @@ ZEND_END_ARG_INFO()
241247

242248
#define arginfo_class_ReflectionClass_isTrait arginfo_class_ReflectionFunctionAbstract_inNamespace
243249

244-
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionClass_isEnum, 0, 0, _IS_BOOL, 0)
245-
ZEND_END_ARG_INFO()
250+
#define arginfo_class_ReflectionClass_isEnum arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
246251

247252
#define arginfo_class_ReflectionClass_isAbstract arginfo_class_ReflectionFunctionAbstract_inNamespace
248253

@@ -345,7 +350,7 @@ ZEND_END_ARG_INFO()
345350

346351
#define arginfo_class_ReflectionProperty_isDefault arginfo_class_ReflectionFunctionAbstract_inNamespace
347352

348-
#define arginfo_class_ReflectionProperty_isPromoted arginfo_class_ReflectionClass_isEnum
353+
#define arginfo_class_ReflectionProperty_isPromoted arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
349354

350355
#define arginfo_class_ReflectionProperty_getModifiers arginfo_class_ReflectionFunctionAbstract_getNumberOfParameters
351356

@@ -359,7 +364,7 @@ ZEND_END_ARG_INFO()
359364

360365
#define arginfo_class_ReflectionProperty_hasType arginfo_class_ReflectionFunctionAbstract_inNamespace
361366

362-
#define arginfo_class_ReflectionProperty_hasDefaultValue arginfo_class_ReflectionClass_isEnum
367+
#define arginfo_class_ReflectionProperty_hasDefaultValue arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
363368

364369
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionProperty_getDefaultValue, 0, 0, IS_MIXED, 0)
365370
ZEND_END_ARG_INFO()
@@ -393,7 +398,7 @@ ZEND_END_ARG_INFO()
393398

394399
#define arginfo_class_ReflectionClassConstant_getAttributes arginfo_class_ReflectionFunctionAbstract_getAttributes
395400

396-
#define arginfo_class_ReflectionClassConstant_isEnumCase arginfo_class_ReflectionClass_isEnum
401+
#define arginfo_class_ReflectionClassConstant_isEnumCase arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
397402

398403
#define arginfo_class_ReflectionParameter___clone arginfo_class_ReflectionFunctionAbstract___clone
399404

@@ -441,7 +446,7 @@ ZEND_END_ARG_INFO()
441446

442447
#define arginfo_class_ReflectionParameter_isVariadic arginfo_class_ReflectionFunctionAbstract_inNamespace
443448

444-
#define arginfo_class_ReflectionParameter_isPromoted arginfo_class_ReflectionClass_isEnum
449+
#define arginfo_class_ReflectionParameter_isPromoted arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
445450

446451
#define arginfo_class_ReflectionParameter_getAttributes arginfo_class_ReflectionFunctionAbstract_getAttributes
447452

@@ -522,7 +527,7 @@ ZEND_END_ARG_INFO()
522527
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionAttribute_getTarget, 0, 0, IS_LONG, 0)
523528
ZEND_END_ARG_INFO()
524529

525-
#define arginfo_class_ReflectionAttribute_isRepeated arginfo_class_ReflectionClass_isEnum
530+
#define arginfo_class_ReflectionAttribute_isRepeated arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
526531

527532
#define arginfo_class_ReflectionAttribute_getArguments arginfo_class_ReflectionUnionType_getTypes
528533

@@ -543,12 +548,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionEnum_getCase, 0,
543548
ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0)
544549
ZEND_END_ARG_INFO()
545550

546-
#define arginfo_class_ReflectionEnum_getCases arginfo_class_ReflectionUnionType_getTypes
551+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionEnum_getCases, 0, 0, IS_ARRAY, 0)
552+
ZEND_END_ARG_INFO()
547553

548-
#define arginfo_class_ReflectionEnum_isBacked arginfo_class_ReflectionClass_isEnum
554+
#define arginfo_class_ReflectionEnum_isBacked arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
549555

550-
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionEnum_getBackingType, 0, 0, ReflectionType, 1)
551-
ZEND_END_ARG_INFO()
556+
#define arginfo_class_ReflectionEnum_getBackingType arginfo_class_ReflectionFunctionAbstract_getTentativeReturnType
552557

553558
#define arginfo_class_ReflectionEnumUnitCase___construct arginfo_class_ReflectionClassConstant___construct
554559

@@ -591,6 +596,8 @@ ZEND_METHOD(ReflectionFunctionAbstract, getStaticVariables);
591596
ZEND_METHOD(ReflectionFunctionAbstract, returnsReference);
592597
ZEND_METHOD(ReflectionFunctionAbstract, hasReturnType);
593598
ZEND_METHOD(ReflectionFunctionAbstract, getReturnType);
599+
ZEND_METHOD(ReflectionFunctionAbstract, hasTentativeReturnType);
600+
ZEND_METHOD(ReflectionFunctionAbstract, getTentativeReturnType);
594601
ZEND_METHOD(ReflectionFunctionAbstract, getAttributes);
595602
ZEND_METHOD(ReflectionFunction, __construct);
596603
ZEND_METHOD(ReflectionFunction, __toString);
@@ -821,6 +828,8 @@ static const zend_function_entry class_ReflectionFunctionAbstract_methods[] = {
821828
ZEND_ME(ReflectionFunctionAbstract, returnsReference, arginfo_class_ReflectionFunctionAbstract_returnsReference, ZEND_ACC_PUBLIC)
822829
ZEND_ME(ReflectionFunctionAbstract, hasReturnType, arginfo_class_ReflectionFunctionAbstract_hasReturnType, ZEND_ACC_PUBLIC)
823830
ZEND_ME(ReflectionFunctionAbstract, getReturnType, arginfo_class_ReflectionFunctionAbstract_getReturnType, ZEND_ACC_PUBLIC)
831+
ZEND_ME(ReflectionFunctionAbstract, hasTentativeReturnType, arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType, ZEND_ACC_PUBLIC)
832+
ZEND_ME(ReflectionFunctionAbstract, getTentativeReturnType, arginfo_class_ReflectionFunctionAbstract_getTentativeReturnType, ZEND_ACC_PUBLIC)
824833
ZEND_ME(ReflectionFunctionAbstract, getAttributes, arginfo_class_ReflectionFunctionAbstract_getAttributes, ZEND_ACC_PUBLIC)
825834
ZEND_FE_END
826835
};
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
--TEST--
2+
ReflectionMethod returns tentative return type information correctly
3+
--FILE--
4+
<?php
5+
6+
class MyDateTimeZone extends DateTimeZone
7+
{
8+
#[SuppressTentativeReturnTypeNotice]
9+
public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): string
10+
{
11+
return "";
12+
}
13+
}
14+
15+
class Foo
16+
{
17+
#[TentativeReturnType]
18+
public static function bar(): string
19+
{
20+
return "";
21+
}
22+
}
23+
24+
$methodInfo = new ReflectionMethod(DateTimeZone::class, 'listIdentifiers');
25+
26+
var_dump($methodInfo->hasReturnType());
27+
var_dump($methodInfo->hasTentativeReturnType());
28+
var_dump($methodInfo->getReturnType());
29+
var_dump((string) $methodInfo->getTentativeReturnType());
30+
echo "\n";
31+
32+
$methodInfo = new ReflectionMethod(MyDateTimeZone::class, 'listIdentifiers');
33+
34+
var_dump($methodInfo->hasReturnType());
35+
var_dump($methodInfo->hasTentativeReturnType());
36+
var_dump((string) $methodInfo->getReturnType());
37+
var_dump($methodInfo->getTentativeReturnType());
38+
echo "\n";
39+
40+
$methodInfo = new ReflectionMethod(Foo::class, 'bar');
41+
42+
var_dump($methodInfo->hasReturnType());
43+
var_dump($methodInfo->hasTentativeReturnType());
44+
var_dump((string) $methodInfo->getReturnType());
45+
var_dump($methodInfo->getTentativeReturnType());
46+
47+
?>
48+
--EXPECTF--
49+
bool(false)
50+
bool(true)
51+
NULL
52+
string(5) "array"
53+
54+
bool(true)
55+
bool(false)
56+
string(6) "string"
57+
NULL
58+
59+
bool(false)
60+
bool(true)
61+
string(0) ""
62+
object(ReflectionNamedType)#2 (0) {
63+
}

0 commit comments

Comments
 (0)