Skip to content

Commit c45eb54

Browse files
committed
Implement reflection API for tentative types
1 parent eb92b52 commit c45eb54

File tree

4 files changed

+121
-9
lines changed

4 files changed

+121
-9
lines changed

ext/reflection/php_reflection.c

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,7 @@ static void _function_string(smart_str *str, zend_function *fptr, zend_class_ent
848848
}
849849
_function_parameter_string(str, fptr, ZSTR_VAL(param_indent.s));
850850
smart_str_free(&param_indent);
851-
if (fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
851+
if (fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && !ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1])) {
852852
smart_str_append_printf(str, " %s- Return [ ", indent);
853853
if (ZEND_TYPE_IS_SET(fptr->common.arg_info[-1].type)) {
854854
zend_string *type_str = zend_type_to_string(fptr->common.arg_info[-1].type);
@@ -3407,7 +3407,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, hasReturnType)
34073407

34083408
GET_REFLECTION_OBJECT_PTR(fptr);
34093409

3410-
RETVAL_BOOL(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE);
3410+
RETVAL_BOOL(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && !ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1]));
34113411
}
34123412
/* }}} */
34133413

@@ -3423,7 +3423,43 @@ ZEND_METHOD(ReflectionFunctionAbstract, getReturnType)
34233423

34243424
GET_REFLECTION_OBJECT_PTR(fptr);
34253425

3426-
if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
3426+
if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1])) {
3427+
RETURN_NULL();
3428+
}
3429+
3430+
reflection_type_factory(fptr->common.arg_info[-1].type, return_value, 1);
3431+
}
3432+
/* }}} */
3433+
3434+
/* {{{ Return whether the function has a return type */
3435+
ZEND_METHOD(ReflectionFunctionAbstract, hasTentativeReturnType)
3436+
{
3437+
reflection_object *intern;
3438+
zend_function *fptr;
3439+
3440+
if (zend_parse_parameters_none() == FAILURE) {
3441+
RETURN_THROWS();
3442+
}
3443+
3444+
GET_REFLECTION_OBJECT_PTR(fptr);
3445+
3446+
RETVAL_BOOL(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1]));
3447+
}
3448+
/* }}} */
3449+
3450+
/* {{{ Returns the return type associated with the function */
3451+
ZEND_METHOD(ReflectionFunctionAbstract, getTentativeReturnType)
3452+
{
3453+
reflection_object *intern;
3454+
zend_function *fptr;
3455+
3456+
if (zend_parse_parameters_none() == FAILURE) {
3457+
RETURN_THROWS();
3458+
}
3459+
3460+
GET_REFLECTION_OBJECT_PTR(fptr);
3461+
3462+
if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || !ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1])) {
34273463
RETURN_NULL();
34283464
}
34293465

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: 15 additions & 6 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: fb4e29d088862cc76d22c9902c79c86dbfa7ac95 */
2+
* Stub hash: 547f75b2dd3aecd163d0b03225a451a360ebf2ff */
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")
@@ -342,8 +348,7 @@ ZEND_END_ARG_INFO()
342348

343349
#define arginfo_class_ReflectionProperty_isDefault arginfo_class_ReflectionFunctionAbstract_inNamespace
344350

345-
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionProperty_isPromoted, 0, 0, _IS_BOOL, 0)
346-
ZEND_END_ARG_INFO()
351+
#define arginfo_class_ReflectionProperty_isPromoted arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
347352

348353
#define arginfo_class_ReflectionProperty_getModifiers arginfo_class_ReflectionFunctionAbstract_getNumberOfParameters
349354

@@ -357,7 +362,7 @@ ZEND_END_ARG_INFO()
357362

358363
#define arginfo_class_ReflectionProperty_hasType arginfo_class_ReflectionFunctionAbstract_inNamespace
359364

360-
#define arginfo_class_ReflectionProperty_hasDefaultValue arginfo_class_ReflectionProperty_isPromoted
365+
#define arginfo_class_ReflectionProperty_hasDefaultValue arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
361366

362367
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionProperty_getDefaultValue, 0, 0, IS_MIXED, 0)
363368
ZEND_END_ARG_INFO()
@@ -437,7 +442,7 @@ ZEND_END_ARG_INFO()
437442

438443
#define arginfo_class_ReflectionParameter_isVariadic arginfo_class_ReflectionFunctionAbstract_inNamespace
439444

440-
#define arginfo_class_ReflectionParameter_isPromoted arginfo_class_ReflectionProperty_isPromoted
445+
#define arginfo_class_ReflectionParameter_isPromoted arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
441446

442447
#define arginfo_class_ReflectionParameter_getAttributes arginfo_class_ReflectionFunctionAbstract_getAttributes
443448

@@ -518,7 +523,7 @@ ZEND_END_ARG_INFO()
518523
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionAttribute_getTarget, 0, 0, IS_LONG, 0)
519524
ZEND_END_ARG_INFO()
520525

521-
#define arginfo_class_ReflectionAttribute_isRepeated arginfo_class_ReflectionProperty_isPromoted
526+
#define arginfo_class_ReflectionAttribute_isRepeated arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
522527

523528
#define arginfo_class_ReflectionAttribute_getArguments arginfo_class_ReflectionUnionType_getTypes
524529

@@ -557,6 +562,8 @@ ZEND_METHOD(ReflectionFunctionAbstract, getStaticVariables);
557562
ZEND_METHOD(ReflectionFunctionAbstract, returnsReference);
558563
ZEND_METHOD(ReflectionFunctionAbstract, hasReturnType);
559564
ZEND_METHOD(ReflectionFunctionAbstract, getReturnType);
565+
ZEND_METHOD(ReflectionFunctionAbstract, hasTentativeReturnType);
566+
ZEND_METHOD(ReflectionFunctionAbstract, getTentativeReturnType);
560567
ZEND_METHOD(ReflectionFunctionAbstract, getAttributes);
561568
ZEND_METHOD(ReflectionFunction, __construct);
562569
ZEND_METHOD(ReflectionFunction, __toString);
@@ -775,6 +782,8 @@ static const zend_function_entry class_ReflectionFunctionAbstract_methods[] = {
775782
ZEND_ME(ReflectionFunctionAbstract, returnsReference, arginfo_class_ReflectionFunctionAbstract_returnsReference, ZEND_ACC_PUBLIC)
776783
ZEND_ME(ReflectionFunctionAbstract, hasReturnType, arginfo_class_ReflectionFunctionAbstract_hasReturnType, ZEND_ACC_PUBLIC)
777784
ZEND_ME(ReflectionFunctionAbstract, getReturnType, arginfo_class_ReflectionFunctionAbstract_getReturnType, ZEND_ACC_PUBLIC)
785+
ZEND_ME(ReflectionFunctionAbstract, hasTentativeReturnType, arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType, ZEND_ACC_PUBLIC)
786+
ZEND_ME(ReflectionFunctionAbstract, getTentativeReturnType, arginfo_class_ReflectionFunctionAbstract_getTentativeReturnType, ZEND_ACC_PUBLIC)
778787
ZEND_ME(ReflectionFunctionAbstract, getAttributes, arginfo_class_ReflectionFunctionAbstract_getAttributes, ZEND_ACC_PUBLIC)
779788
ZEND_FE_END
780789
};
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)