[PHP-CVS] [php-src] master: ext/reflection: add namespace methods to ReflectionAttribute

[email protected] (Gina Peter Banyard) Thu, 30 Jul 2026 20:15:40 +0000
Newsgroups php.cvs
Message-ID <[email protected]>
Author: Gina Peter Banyard (Girgias)
Date: 2026-07-30T21:15:35+01:00

Commit: https://github.com/php/php-src/commit/9e9445f7421c7a55e65305f3887995a54d3da410
Raw diff: https://github.com/php/php-src/commit/9e9445f7421c7a55e65305f3887995a54d3da410.diff

ext/reflection: add namespace methods to ReflectionAttribute

Add the ReflectionAttribute::inNamespace(), ReflectionAttribute::getNamespaceName(), and ReflectionAttribute::getShortName() methods.

Closes GH-19556

Changed paths:
  A  ext/reflection/tests/attributes/ReflectionAttribute_name_namespace_methods.phpt
  M  ext/reflection/php_reflection.c
  M  ext/reflection/php_reflection.stub.php
  M  ext/reflection/php_reflection_arginfo.h
  M  ext/reflection/php_reflection_decl.h


Diff:

diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index ec060cbbf3e9..7fa76c121cac 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -7370,6 +7370,58 @@ ZEND_METHOD(ReflectionAttribute, getName)
 }
 /* }}} */
 
+/* Returns whether this attribute name comes from a namespace */
+ZEND_METHOD(ReflectionAttribute, inNamespace)
+{
+	reflection_object *intern;
+	attribute_reference *attr;
+
+	ZEND_PARSE_PARAMETERS_NONE();
+
+	GET_REFLECTION_OBJECT_PTR(attr);
+
+	const zend_string *name = attr->data->name;
+	const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
+	RETURN_BOOL(backslash);
+}
+/* }}} */
+
+/* Returns the name of namespace where this attribute comes from */
+ZEND_METHOD(ReflectionAttribute, getNamespaceName)
+{
+	reflection_object *intern;
+	attribute_reference *attr;
+
+	ZEND_PARSE_PARAMETERS_NONE();
+
+	GET_REFLECTION_OBJECT_PTR(attr);
+
+	const zend_string *name = attr->data->name;
+	const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
+	if (backslash) {
+		RETURN_STRINGL(ZSTR_VAL(name), backslash - ZSTR_VAL(name));
+	}
+	RETURN_EMPTY_STRING();
+}
+
+/* Returns the short name of the attribute (without namespace part) */
+ZEND_METHOD(ReflectionAttribute, getShortName)
+{
+	reflection_object *intern;
+	attribute_reference *attr;
+
+	ZEND_PARSE_PARAMETERS_NONE();
+
+	GET_REFLECTION_OBJECT_PTR(attr);
+
+	zend_string *name = attr->data->name;
+	const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
+	if (backslash) {
+		RETURN_STRINGL(backslash + 1, ZSTR_LEN(name) - (backslash - ZSTR_VAL(name) + 1));
+	}
+	RETURN_STR_COPY(name);
+}
+
 /* {{{ Returns the target of the attribute */
 ZEND_METHOD(ReflectionAttribute, getTarget)
 {
diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php
index dd605100f8ba..b95f01d2ad28 100644
--- a/ext/reflection/php_reflection.stub.php
+++ b/ext/reflection/php_reflection.stub.php
@@ -849,6 +849,9 @@ class ReflectionAttribute implements Reflector
     public string $name;
 
     public function getName(): string {}
+    public function inNamespace(): bool {}
+    public function getNamespaceName(): string {}
+    public function getShortName(): string {}
     public function getTarget(): int {}
     public function isRepeated(): bool {}
     public function getArguments(): array {}
diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h
index 65571f38d43c..7da379d7b989 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 php_reflection.stub.php instead.
- * Stub hash: c80946cc8c8215bb6527e09bb71b3a97a76a6a98
+ * Stub hash: c4dcc2653f826c2c437065faec4bf77772ef88b1
  * Has decl header: yes */
 
 ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0)
@@ -646,6 +646,12 @@ ZEND_END_ARG_INFO()
 
 #define arginfo_class_ReflectionAttribute_getName arginfo_class_ReflectionFunction___toString
 
+#define arginfo_class_ReflectionAttribute_inNamespace arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
+
+#define arginfo_class_ReflectionAttribute_getNamespaceName arginfo_class_ReflectionFunction___toString
+
+#define arginfo_class_ReflectionAttribute_getShortName arginfo_class_ReflectionFunction___toString
+
 #define arginfo_class_ReflectionAttribute_getTarget arginfo_class_ReflectionGenerator_getExecutingLine
 
 #define arginfo_class_ReflectionAttribute_isRepeated arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
@@ -974,6 +980,9 @@ ZEND_METHOD(ReflectionReference, fromArrayElement);
 ZEND_METHOD(ReflectionReference, getId);
 ZEND_METHOD(ReflectionReference, __construct);
 ZEND_METHOD(ReflectionAttribute, getName);
+ZEND_METHOD(ReflectionAttribute, inNamespace);
+ZEND_METHOD(ReflectionAttribute, getNamespaceName);
+ZEND_METHOD(ReflectionAttribute, getShortName);
 ZEND_METHOD(ReflectionAttribute, getTarget);
 ZEND_METHOD(ReflectionAttribute, isRepeated);
 ZEND_METHOD(ReflectionAttribute, getArguments);
@@ -1327,6 +1336,9 @@ static const zend_function_entry class_ReflectionReference_methods[] = {
 
 static const zend_function_entry class_ReflectionAttribute_methods[] = {
 	ZEND_ME(ReflectionAttribute, getName, arginfo_class_ReflectionAttribute_getName, ZEND_ACC_PUBLIC)
+	ZEND_ME(ReflectionAttribute, inNamespace, arginfo_class_ReflectionAttribute_inNamespace, ZEND_ACC_PUBLIC)
+	ZEND_ME(ReflectionAttribute, getNamespaceName, arginfo_class_ReflectionAttribute_getNamespaceName, ZEND_ACC_PUBLIC)
+	ZEND_ME(ReflectionAttribute, getShortName, arginfo_class_ReflectionAttribute_getShortName, ZEND_ACC_PUBLIC)
 	ZEND_ME(ReflectionAttribute, getTarget, arginfo_class_ReflectionAttribute_getTarget, ZEND_ACC_PUBLIC)
 	ZEND_ME(ReflectionAttribute, isRepeated, arginfo_class_ReflectionAttribute_isRepeated, ZEND_ACC_PUBLIC)
 	ZEND_ME(ReflectionAttribute, getArguments, arginfo_class_ReflectionAttribute_getArguments, ZEND_ACC_PUBLIC)
diff --git a/ext/reflection/php_reflection_decl.h b/ext/reflection/php_reflection_decl.h
index a87e1635419b..555ed84feebe 100644
--- a/ext/reflection/php_reflection_decl.h
+++ b/ext/reflection/php_reflection_decl.h
@@ -1,12 +1,12 @@
 /* This is a generated file, edit php_reflection.stub.php instead.
- * Stub hash: c80946cc8c8215bb6527e09bb71b3a97a76a6a98 */
+ * Stub hash: c4dcc2653f826c2c437065faec4bf77772ef88b1 */
 
-#ifndef ZEND_PHP_REFLECTION_DECL_c80946cc8c8215bb6527e09bb71b3a97a76a6a98_H
-#define ZEND_PHP_REFLECTION_DECL_c80946cc8c8215bb6527e09bb71b3a97a76a6a98_H
+#ifndef ZEND_PHP_REFLECTION_DECL_c4dcc2653f826c2c437065faec4bf77772ef88b1_H
+#define ZEND_PHP_REFLECTION_DECL_c4dcc2653f826c2c437065faec4bf77772ef88b1_H
 
 typedef enum zend_enum_PropertyHookType {
 	ZEND_ENUM_PropertyHookType_Get = 1,
 	ZEND_ENUM_PropertyHookType_Set = 2,
 } zend_enum_PropertyHookType;
 
-#endif /* ZEND_PHP_REFLECTION_DECL_c80946cc8c8215bb6527e09bb71b3a97a76a6a98_H */
+#endif /* ZEND_PHP_REFLECTION_DECL_c4dcc2653f826c2c437065faec4bf77772ef88b1_H */
diff --git a/ext/reflection/tests/attributes/ReflectionAttribute_name_namespace_methods.phpt b/ext/reflection/tests/attributes/ReflectionAttribute_name_namespace_methods.phpt
new file mode 100644
index 000000000000..9f465e3c05cd
--- /dev/null
+++ b/ext/reflection/tests/attributes/ReflectionAttribute_name_namespace_methods.phpt
@@ -0,0 +1,52 @@
+--TEST--
+ReflectionAttribute name and namespace methods
+--FILE--
+<?php
+
+namespace {
+
+	#[Attribute]
+	class AttrNotNamespace {}
+
+}
+
+namespace A\B {
+
+	#[Attribute]
+	class AttrNamespace {}
+
+	class Foo {
+	    #[\Attr]
+	    public function fn1() {}
+
+	    #[AttrNamespace]
+	    public function fn2() {}
+	}
+
+	$rm = new \ReflectionMethod(Foo::class, "fn1");
+	$attribute = $rm->getAttributes()[0];
+
+	var_dump($attribute->inNamespace());
+	var_dump($attribute->getName());
+	var_dump($attribute->getNamespaceName());
+	var_dump($attribute->getShortName());
+
+	$rm = new \ReflectionMethod(Foo::class, "fn2");
+	$attribute = $rm->getAttributes()[0];
+
+	var_dump($attribute->inNamespace());
+	var_dump($attribute->getName());
+	var_dump($attribute->getNamespaceName());
+	var_dump($attribute->getShortName());
+}
+
+?>
+--EXPECT--
+bool(false)
+string(4) "Attr"
+string(0) ""
+string(4) "Attr"
+bool(true)
+string(17) "A\B\AttrNamespace"
+string(3) "A\B"
+string(13) "AttrNamespace"