From a335d9391501b3f93488e0103a0b3fa771cc5151 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 16 Sep 2024 14:50:47 +0200 Subject: [PATCH] Implement ReflectionProperty::isFinal() --- ext/reflection/php_reflection.c | 7 +++- ext/reflection/php_reflection.stub.php | 4 +++ ext/reflection/php_reflection_arginfo.h | 12 ++++++- ...ReflectionProperty_getModifiers_basic.phpt | 8 ++++- .../tests/ReflectionProperty_isFinal.phpt | 32 +++++++++++++++++++ 5 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 ext/reflection/tests/ReflectionProperty_isFinal.phpt diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 14cde89f21cac..cd1cc9ee96f96 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -5960,7 +5960,7 @@ ZEND_METHOD(ReflectionProperty, getModifiers) { reflection_object *intern; property_reference *ref; - uint32_t keep_flags = ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_STATIC | ZEND_ACC_READONLY | ZEND_ACC_ABSTRACT | ZEND_ACC_VIRTUAL; + uint32_t keep_flags = ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_STATIC | ZEND_ACC_READONLY | ZEND_ACC_ABSTRACT | ZEND_ACC_VIRTUAL | ZEND_ACC_FINAL; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -6604,6 +6604,11 @@ ZEND_METHOD(ReflectionProperty, getHook) reflection_method_factory(hook->common.scope, hook, NULL, return_value); } +ZEND_METHOD(ReflectionProperty, isFinal) +{ + _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL); +} + /* {{{ Constructor. Throws an Exception in case the given extension does not exist */ ZEND_METHOD(ReflectionExtension, __construct) { diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index eb5ae7169119d..28a79feee7542 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -470,6 +470,8 @@ class ReflectionProperty implements Reflector public const int IS_PROTECTED_SET = UNKNOWN; /** @cvalue ZEND_ACC_PRIVATE_SET */ public const int IS_PRIVATE_SET = UNKNOWN; + /** @cvalue ZEND_ACC_FINAL */ + public const int IS_FINAL = UNKNOWN; public string $name; public string $class; @@ -565,6 +567,8 @@ public function getHooks(): array {} public function hasHook(PropertyHookType $type): bool {} public function getHook(PropertyHookType $type): ?ReflectionMethod {} + + public function isFinal(): bool {} } /** @not-serializable */ diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index e96a5442c4e7c..1807416a0c85c 100644 --- a/ext/reflection/php_reflection_arginfo.h +++ b/ext/reflection/php_reflection_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 83e9d4a4b2f49739af3e7faa3037df13e779bb8b */ + * Stub hash: 261798b92d4eac170538185ced1068bc72705385 */ 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) @@ -460,6 +460,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionProperty_getHook, ZEND_ARG_OBJ_INFO(0, type, PropertyHookType, 0) ZEND_END_ARG_INFO() +#define arginfo_class_ReflectionProperty_isFinal arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType + #define arginfo_class_ReflectionClassConstant___clone arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionClassConstant___construct, 0, 0, 2) @@ -868,6 +870,7 @@ ZEND_METHOD(ReflectionProperty, hasHooks); ZEND_METHOD(ReflectionProperty, getHooks); ZEND_METHOD(ReflectionProperty, hasHook); ZEND_METHOD(ReflectionProperty, getHook); +ZEND_METHOD(ReflectionProperty, isFinal); ZEND_METHOD(ReflectionClassConstant, __construct); ZEND_METHOD(ReflectionClassConstant, __toString); ZEND_METHOD(ReflectionClassConstant, getName); @@ -1164,6 +1167,7 @@ static const zend_function_entry class_ReflectionProperty_methods[] = { ZEND_ME(ReflectionProperty, getHooks, arginfo_class_ReflectionProperty_getHooks, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, hasHook, arginfo_class_ReflectionProperty_hasHook, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, getHook, arginfo_class_ReflectionProperty_getHook, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionProperty, isFinal, arginfo_class_ReflectionProperty_isFinal, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -1607,6 +1611,12 @@ static zend_class_entry *register_class_ReflectionProperty(zend_class_entry *cla zend_declare_typed_class_constant(class_entry, const_IS_PRIVATE_SET_name, &const_IS_PRIVATE_SET_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(const_IS_PRIVATE_SET_name); + zval const_IS_FINAL_value; + ZVAL_LONG(&const_IS_FINAL_value, ZEND_ACC_FINAL); + zend_string *const_IS_FINAL_name = zend_string_init_interned("IS_FINAL", sizeof("IS_FINAL") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_IS_FINAL_name, &const_IS_FINAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_IS_FINAL_name); + zval property_name_default_value; ZVAL_UNDEF(&property_name_default_value); zend_string *property_name_name = zend_string_init("name", sizeof("name") - 1, 1); diff --git a/ext/reflection/tests/ReflectionProperty_getModifiers_basic.phpt b/ext/reflection/tests/ReflectionProperty_getModifiers_basic.phpt index 6856569d3eadc..c59c3fc75f272 100644 --- a/ext/reflection/tests/ReflectionProperty_getModifiers_basic.phpt +++ b/ext/reflection/tests/ReflectionProperty_getModifiers_basic.phpt @@ -10,6 +10,8 @@ class C { static public $a4; static protected $a5; static private $a6; + public final $a7; + public static final $a8; } class D extends C { @@ -21,7 +23,7 @@ class D extends C { static private $a6; } -for ($i = 1;$i <= 6;$i++) { +for ($i = 1;$i <= 8;$i++) { $rp = new ReflectionProperty("C", "a$i"); echo "C::a$i: "; var_dump($rp->getModifiers()); @@ -44,3 +46,7 @@ C::a5: int(18) D::a5: int(18) C::a6: int(20) D::a6: int(20) +C::a7: int(33) +D::a7: int(33) +C::a8: int(49) +D::a8: int(49) diff --git a/ext/reflection/tests/ReflectionProperty_isFinal.phpt b/ext/reflection/tests/ReflectionProperty_isFinal.phpt new file mode 100644 index 0000000000000..62b792fd7253f --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_isFinal.phpt @@ -0,0 +1,32 @@ +--TEST-- +ReflectionProperty::isFinal() +--FILE-- + 42; } + public final $p4 { get => 42; } + public protected(set) mixed $p5; + public protected(set) final mixed $p6; + public private(set) mixed $p7; + public private(set) final mixed $p8; +} + +$rc = new ReflectionClass(C::class); +foreach ($rc->getProperties() as $rp) { + echo $rp->getName(), ": "; + var_dump($rp->isFinal()); +} + +?> +--EXPECT-- +p1: bool(false) +p2: bool(true) +p3: bool(false) +p4: bool(true) +p5: bool(false) +p6: bool(true) +p7: bool(true) +p8: bool(true)