summaryrefslogtreecommitdiff
path: root/ext/reflection
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-03-24 13:18:28 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-06-05 15:15:51 +0200
commit064b4644484d38e9dce40aef7e8e0e8190e9d863 (patch)
treeceb34fd4bc375ea0accdf3f8b1b15c389c7e103a /ext/reflection
parent91f283a0bfc6792d84fb9a6361e21f6f33769c4d (diff)
downloadphp-git-064b4644484d38e9dce40aef7e8e0e8190e9d863.tar.gz
Implement "Constructor Promotion" RFC
RFC: https://wiki.php.net/rfc/constructor_promotion Closes GH-5291.
Diffstat (limited to 'ext/reflection')
-rw-r--r--ext/reflection/php_reflection.c24
-rw-r--r--ext/reflection/php_reflection.stub.php4
-rw-r--r--ext/reflection/php_reflection_arginfo.h12
-rw-r--r--ext/reflection/tests/bug71767.phpt9
-rw-r--r--ext/reflection/tests/constructor_promotion.phpt70
5 files changed, 117 insertions, 2 deletions
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 6d4f257eb4..d986f828f5 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -2870,6 +2870,22 @@ ZEND_METHOD(ReflectionParameter, isVariadic)
}
/* }}} */
+/* {{{ proto public bool ReflectionParameter::isPromoted()
+ Returns this constructor parameter has been promoted to a property */
+ZEND_METHOD(ReflectionParameter, isPromoted)
+{
+ reflection_object *intern;
+ parameter_reference *param;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ RETURN_THROWS();
+ }
+ GET_REFLECTION_OBJECT_PTR(param);
+
+ RETVAL_BOOL(ZEND_ARG_IS_PROMOTED(param->arg_info));
+}
+/* }}} */
+
/* {{{ proto public bool ReflectionType::allowsNull()
Returns whether parameter MAY be null */
ZEND_METHOD(ReflectionType, allowsNull)
@@ -5461,6 +5477,14 @@ ZEND_METHOD(ReflectionProperty, isDefault)
}
/* }}} */
+/* {{{ proto public bool ReflectionProperty::isPromoted()
+ Returns whether this property has been promoted from a constructor */
+ZEND_METHOD(ReflectionProperty, isPromoted)
+{
+ _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROMOTED);
+}
+/* }}} */
+
/* {{{ proto public int ReflectionProperty::getModifiers()
Returns a bitfield of the access modifiers for this property */
ZEND_METHOD(ReflectionProperty, getModifiers)
diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php
index c27f971c07..e3d3fee52c 100644
--- a/ext/reflection/php_reflection.stub.php
+++ b/ext/reflection/php_reflection.stub.php
@@ -413,6 +413,8 @@ class ReflectionProperty implements Reflector
/** @return bool */
public function isDefault() {}
+ public function isPromoted(): bool {}
+
/** @return int */
public function getModifiers() {}
@@ -553,6 +555,8 @@ class ReflectionParameter implements Reflector
/** @return bool */
public function isVariadic() {}
+ public function isPromoted(): bool {}
+
/** @return ReflectionAttribute[] */
public function getAttributes(?string $name = null, int $flags = 0): array {}
}
diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h
index 3dec73ec8b..e5ed4742ff 100644
--- a/ext/reflection/php_reflection_arginfo.h
+++ b/ext/reflection/php_reflection_arginfo.h
@@ -312,6 +312,9 @@ ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionProperty_isDefault arginfo_class_ReflectionFunctionAbstract___clone
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionProperty_isPromoted, 0, 0, _IS_BOOL, 0)
+ZEND_END_ARG_INFO()
+
#define arginfo_class_ReflectionProperty_getModifiers arginfo_class_ReflectionFunctionAbstract___clone
#define arginfo_class_ReflectionProperty_getDeclaringClass arginfo_class_ReflectionFunctionAbstract___clone
@@ -324,8 +327,7 @@ ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionProperty_hasType arginfo_class_ReflectionFunctionAbstract___clone
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionProperty_hasDefaultValue, 0, 0, _IS_BOOL, 0)
-ZEND_END_ARG_INFO()
+#define arginfo_class_ReflectionProperty_hasDefaultValue arginfo_class_ReflectionProperty_isPromoted
#define arginfo_class_ReflectionProperty_getDefaultValue arginfo_class_ReflectionFunctionAbstract___clone
@@ -400,6 +402,8 @@ ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionParameter_isVariadic arginfo_class_ReflectionFunctionAbstract___clone
+#define arginfo_class_ReflectionParameter_isPromoted arginfo_class_ReflectionProperty_isPromoted
+
#define arginfo_class_ReflectionParameter_getAttributes arginfo_class_ReflectionFunctionAbstract_getAttributes
#define arginfo_class_ReflectionType___clone arginfo_class_ReflectionFunctionAbstract___clone
@@ -604,6 +608,7 @@ ZEND_METHOD(ReflectionProperty, isPrivate);
ZEND_METHOD(ReflectionProperty, isProtected);
ZEND_METHOD(ReflectionProperty, isStatic);
ZEND_METHOD(ReflectionProperty, isDefault);
+ZEND_METHOD(ReflectionProperty, isPromoted);
ZEND_METHOD(ReflectionProperty, getModifiers);
ZEND_METHOD(ReflectionProperty, getDeclaringClass);
ZEND_METHOD(ReflectionProperty, getDocComment);
@@ -644,6 +649,7 @@ ZEND_METHOD(ReflectionParameter, getDefaultValue);
ZEND_METHOD(ReflectionParameter, isDefaultValueConstant);
ZEND_METHOD(ReflectionParameter, getDefaultValueConstantName);
ZEND_METHOD(ReflectionParameter, isVariadic);
+ZEND_METHOD(ReflectionParameter, isPromoted);
ZEND_METHOD(ReflectionParameter, getAttributes);
ZEND_METHOD(ReflectionType, allowsNull);
ZEND_METHOD(ReflectionType, __toString);
@@ -851,6 +857,7 @@ static const zend_function_entry class_ReflectionProperty_methods[] = {
ZEND_ME(ReflectionProperty, isProtected, arginfo_class_ReflectionProperty_isProtected, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionProperty, isStatic, arginfo_class_ReflectionProperty_isStatic, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionProperty, isDefault, arginfo_class_ReflectionProperty_isDefault, ZEND_ACC_PUBLIC)
+ ZEND_ME(ReflectionProperty, isPromoted, arginfo_class_ReflectionProperty_isPromoted, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionProperty, getModifiers, arginfo_class_ReflectionProperty_getModifiers, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionProperty, getDeclaringClass, arginfo_class_ReflectionProperty_getDeclaringClass, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionProperty, getDocComment, arginfo_class_ReflectionProperty_getDocComment, ZEND_ACC_PUBLIC)
@@ -903,6 +910,7 @@ static const zend_function_entry class_ReflectionParameter_methods[] = {
ZEND_ME(ReflectionParameter, isDefaultValueConstant, arginfo_class_ReflectionParameter_isDefaultValueConstant, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionParameter, getDefaultValueConstantName, arginfo_class_ReflectionParameter_getDefaultValueConstantName, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionParameter, isVariadic, arginfo_class_ReflectionParameter_isVariadic, ZEND_ACC_PUBLIC)
+ ZEND_ME(ReflectionParameter, isPromoted, arginfo_class_ReflectionParameter_isPromoted, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionParameter, getAttributes, arginfo_class_ReflectionParameter_getAttributes, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
diff --git a/ext/reflection/tests/bug71767.phpt b/ext/reflection/tests/bug71767.phpt
index c20073c67a..95094290bf 100644
--- a/ext/reflection/tests/bug71767.phpt
+++ b/ext/reflection/tests/bug71767.phpt
@@ -27,13 +27,21 @@ $func = function(
) {
};
+/** Correct docblock */
+$func2 = fn(
+ /** wrong docblock */
+ $arg
+) => null;
+
$reflectionFunction = new ReflectionFunction('foo');
$reflectionClass = new ReflectionClass(Foo::class);
$reflectionClosure = new ReflectionFunction($func);
+$reflectionArrowFn = new ReflectionFunction($func2);
echo $reflectionFunction->getDocComment() . PHP_EOL;
echo $reflectionClass->getMethod('bar')->getDocComment() . PHP_EOL;
echo $reflectionClosure->getDocComment() . PHP_EOL;
+echo $reflectionArrowFn->getDocComment() . PHP_EOL;
echo "Done\n";
?>
@@ -41,4 +49,5 @@ echo "Done\n";
/** Correct docblock */
/** Correct docblock */
/** Correct docblock */
+/** Correct docblock */
Done
diff --git a/ext/reflection/tests/constructor_promotion.phpt b/ext/reflection/tests/constructor_promotion.phpt
new file mode 100644
index 0000000000..d0a09aaee0
--- /dev/null
+++ b/ext/reflection/tests/constructor_promotion.phpt
@@ -0,0 +1,70 @@
+--TEST--
+Using Reflection on promoted properties
+--FILE--
+<?php
+
+class Test {
+ public $z;
+ public function __construct(
+ public int $x,
+ /** @SomeAnnotation() */
+ public string $y = "123",
+ string $z = "abc",
+ ) {}
+}
+
+$rc = new ReflectionClass(Test::class);
+echo $rc, "\n";
+
+$y = $rc->getProperty('y');
+var_dump($y->isPromoted());
+var_dump($y->getDocComment());
+$z = $rc->getProperty('z');
+var_dump($z->isPromoted());
+
+echo "\n";
+
+$rp = new ReflectionParameter([Test::class, '__construct'], 'y');
+var_dump($rp->isPromoted());
+$rp = new ReflectionParameter([Test::class, '__construct'], 'z');
+var_dump($rp->isPromoted());
+
+?>
+--EXPECTF--
+Class [ <user> class Test ] {
+ @@ %s 3-11
+
+ - Constants [0] {
+ }
+
+ - Static properties [0] {
+ }
+
+ - Static methods [0] {
+ }
+
+ - Properties [3] {
+ Property [ public $z = NULL ]
+ Property [ public int $x ]
+ Property [ public string $y ]
+ }
+
+ - Methods [1] {
+ Method [ <user, ctor> public method __construct ] {
+ @@ %s 5 - 10
+
+ - Parameters [3] {
+ Parameter #0 [ <required> int $x ]
+ Parameter #1 [ <optional> string $y = '123' ]
+ Parameter #2 [ <optional> string $z = 'abc' ]
+ }
+ }
+ }
+}
+
+bool(true)
+string(24) "/** @SomeAnnotation() */"
+bool(false)
+
+bool(true)
+bool(false)