Skip to content

Commit 13db356

Browse files
committed
Implemented access to multi & param attributes.
1 parent e367e00 commit 13db356

File tree

6 files changed

+135
-66
lines changed

6 files changed

+135
-66
lines changed

Zend/zend_ast.c

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,49 +2147,3 @@ zend_ast * ZEND_FASTCALL zend_ast_with_attributes(zend_ast *ast, zend_ast *attr)
21472147

21482148
return ast;
21492149
}
2150-
2151-
static int zend_ast_convert_to_object(zval *ret, zend_ast *ast, zend_class_entry *ce)
2152-
{
2153-
if (ast->kind == ZEND_AST_CONSTANT) {
2154-
zend_string *name = zend_ast_get_constant_name(ast);
2155-
zval *zv = zend_get_constant_ex(name, ce, ast->attr);
2156-
2157-
if (UNEXPECTED(zv == NULL)) {
2158-
return FAILURE;
2159-
}
2160-
2161-
ZVAL_COPY_OR_DUP(ret, zv);
2162-
} else {
2163-
zval tmp;
2164-
2165-
if (UNEXPECTED(zend_ast_evaluate(&tmp, ast, ce) != SUCCESS)) {
2166-
return FAILURE;
2167-
}
2168-
2169-
ZVAL_COPY_VALUE(ret, &tmp);
2170-
}
2171-
2172-
return SUCCESS;
2173-
}
2174-
2175-
int zend_ast_convert_attributes(zval *ret, HashTable *attributes, zend_class_entry *ce)
2176-
{
2177-
zval *val, tmp;
2178-
2179-
array_init(ret);
2180-
2181-
ZEND_HASH_FOREACH_VAL(attributes, val) {
2182-
if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
2183-
if (FAILURE == zend_ast_convert_to_object(&tmp, Z_ASTVAL_P(val), ce)) {
2184-
return FAILURE;
2185-
}
2186-
2187-
add_next_index_zval(ret, &tmp);
2188-
} else {
2189-
Z_TRY_ADDREF_P(val);
2190-
add_next_index_zval(ret, val);
2191-
}
2192-
} ZEND_HASH_FOREACH_END();
2193-
2194-
return SUCCESS;
2195-
}

Zend/zend_ast.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,5 @@ static zend_always_inline zend_ast *zend_ast_list_rtrim(zend_ast *ast) {
358358
}
359359

360360
zend_ast * ZEND_FASTCALL zend_ast_with_attributes(zend_ast *ast, zend_ast *attr);
361-
int zend_ast_convert_attributes(zval *ret, HashTable *attributes, zend_class_entry *ce);
362361

363362
#endif

Zend/zend_compile.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,10 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
10631063
ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void*)));
10641064
ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
10651065
}
1066+
1067+
if (op_array->attributes) {
1068+
GC_ADDREF(op_array->attributes);
1069+
}
10661070
} else if (function->type == ZEND_INTERNAL_FUNCTION) {
10671071
if (function->common.function_name) {
10681072
zend_string_addref(function->common.function_name);

ext/reflection/php_reflection.c

Lines changed: 121 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ static void reflection_free_objects_storage(zend_object *object) /* {{{ */
257257
break;
258258
case REF_TYPE_ATTRIBUTE:
259259
attr_reference = (attribute_reference*)intern->ptr;
260+
zend_string_release(attr_reference->name);
260261
zval_ptr_dtor(&attr_reference->arguments);
261262
efree(attr_reference);
262263
break;
@@ -1047,38 +1048,112 @@ static void reflection_attribute_factory(zval *object, zend_string *name, zval *
10471048
reflection_instantiate(reflection_attribute_ptr, object);
10481049
intern = Z_REFLECTION_P(object);
10491050
reference = (attribute_reference*) emalloc(sizeof(attribute_reference));
1050-
reference->name = name;
1051+
reference->name = zend_string_copy(name);
10511052
ZVAL_COPY(&reference->arguments, arguments);
10521053
intern->ptr = reference;
10531054
intern->ref_type = REF_TYPE_ATTRIBUTE;
10541055
}
10551056
/* }}} */
10561057

1058+
static int convert_ast_to_zval(zval *ret, zend_ast *ast, zend_class_entry *ce)
1059+
{
1060+
if (ast->kind == ZEND_AST_CONSTANT) {
1061+
zend_string *name = zend_ast_get_constant_name(ast);
1062+
zval *zv = zend_get_constant_ex(name, ce, ast->attr);
1063+
1064+
if (UNEXPECTED(zv == NULL)) {
1065+
return FAILURE;
1066+
}
1067+
1068+
ZVAL_COPY_OR_DUP(ret, zv);
1069+
} else {
1070+
zval tmp;
1071+
1072+
if (UNEXPECTED(zend_ast_evaluate(&tmp, ast, ce) != SUCCESS)) {
1073+
return FAILURE;
1074+
}
1075+
1076+
ZVAL_COPY_OR_DUP(ret, &tmp);
1077+
zval_ptr_dtor(&tmp);
1078+
}
1079+
1080+
return SUCCESS;
1081+
}
1082+
1083+
static int convert_ast_attributes(zval *ret, HashTable *attributes, zend_class_entry *ce)
1084+
{
1085+
Bucket *p;
1086+
zval tmp;
1087+
1088+
array_init(ret);
1089+
1090+
ZEND_HASH_FOREACH_BUCKET(attributes, p) {
1091+
if (!p->key && p->h == 0) {
1092+
continue;
1093+
}
1094+
1095+
if (Z_TYPE(p->val) == IS_CONSTANT_AST) {
1096+
if (FAILURE == convert_ast_to_zval(&tmp, Z_ASTVAL(p->val), ce)) {
1097+
return FAILURE;
1098+
}
1099+
1100+
add_next_index_zval(ret, &tmp);
1101+
} else {
1102+
Z_TRY_ADDREF(p->val);
1103+
add_next_index_zval(ret, &p->val);
1104+
}
1105+
} ZEND_HASH_FOREACH_END();
1106+
1107+
return SUCCESS;
1108+
}
10571109

10581110
static int convert_attributes(zval *ret, HashTable *attributes, zend_class_entry *ce)
10591111
{
1060-
zend_string *attribute_name;
1061-
zval *attr;
1112+
Bucket *p;
1113+
zval *v;
10621114

1063-
zval converted_attributes;
1115+
zval result;
10641116
zval obj;
10651117

10661118
array_init(ret);
10671119

1068-
ZEND_HASH_FOREACH_STR_KEY_VAL(attributes, attribute_name, attr) {
1069-
if (!attribute_name) {
1120+
ZEND_HASH_FOREACH_BUCKET(attributes, p) {
1121+
if (!p->key) {
1122+
// Skip inlined parameter annotations.
10701123
continue;
10711124
}
10721125

1073-
if (FAILURE == zend_ast_convert_attributes(&converted_attributes, Z_ARRVAL_P(attr), ce)) {
1074-
zval_ptr_dtor(ret);
1075-
return FAILURE;
1076-
}
1126+
ZEND_ASSERT(Z_TYPE(p->val) == IS_ARRAY);
10771127

1078-
reflection_attribute_factory(&obj, attribute_name, &converted_attributes);
1079-
zval_ptr_dtor(&converted_attributes);
1128+
v = zend_hash_index_find(Z_ARRVAL(p->val), 0);
10801129

1081-
add_next_index_zval(ret, &obj);
1130+
if (Z_TYPE_P(v) == IS_STRING) {
1131+
if (FAILURE == convert_ast_attributes(&result, Z_ARRVAL(p->val), ce)) {
1132+
zval_ptr_dtor(ret);
1133+
return FAILURE;
1134+
}
1135+
1136+
reflection_attribute_factory(&obj, Z_STR_P(v), &result);
1137+
add_next_index_zval(ret, &obj);
1138+
zval_ptr_dtor(&result);
1139+
} else {
1140+
zval *zv;
1141+
1142+
ZEND_ASSERT(Z_TYPE_P(v) == IS_ARRAY);
1143+
1144+
ZEND_HASH_FOREACH_VAL(Z_ARRVAL(p->val), zv) {
1145+
ZEND_ASSERT(Z_TYPE_P(zv) == IS_ARRAY);
1146+
1147+
if (FAILURE == convert_ast_attributes(&result, Z_ARRVAL_P(zv), ce)) {
1148+
zval_ptr_dtor(ret);
1149+
return FAILURE;
1150+
}
1151+
1152+
reflection_attribute_factory(&obj, Z_STR_P(zend_hash_index_find(Z_ARRVAL_P(zv), 0)), &result);
1153+
add_next_index_zval(ret, &obj);
1154+
zval_ptr_dtor(&result);
1155+
} ZEND_HASH_FOREACH_END();
1156+
}
10821157
} ZEND_HASH_FOREACH_END();
10831158

10841159
return SUCCESS;
@@ -1701,7 +1776,6 @@ ZEND_METHOD(reflection_function, getAttributes)
17011776
if (zend_parse_parameters_none() == FAILURE) {
17021777
return;
17031778
}
1704-
17051779
GET_REFLECTION_OBJECT_PTR(fptr);
17061780

17071781
if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.attributes) {
@@ -2640,6 +2714,37 @@ ZEND_METHOD(reflection_parameter, canBePassedByValue)
26402714
}
26412715
/* }}} */
26422716

2717+
/* {{{ proto public bool ReflectionParameter::getAttributes(?string $name = null)
2718+
Get parameter attributes. */
2719+
ZEND_METHOD(reflection_parameter, getAttributes)
2720+
{
2721+
reflection_object *intern;
2722+
parameter_reference *param;
2723+
2724+
if (zend_parse_parameters_none() == FAILURE) {
2725+
RETURN_THROWS();
2726+
}
2727+
GET_REFLECTION_OBJECT_PTR(param);
2728+
2729+
if (param->fptr->type == ZEND_USER_FUNCTION && param->fptr->op_array.attributes) {
2730+
zval *attr;
2731+
2732+
if (NULL != (attr = zend_hash_index_find(param->fptr->op_array.attributes, param->offset))) {
2733+
zval ret;
2734+
2735+
ZEND_ASSERT(Z_TYPE_P(attr) == IS_ARRAY);
2736+
2737+
if (FAILURE == convert_attributes(&ret, Z_ARRVAL_P(attr), param->fptr->common.scope)) {
2738+
RETURN_THROWS();
2739+
}
2740+
2741+
RETURN_ZVAL(&ret, 1, 1);
2742+
}
2743+
}
2744+
2745+
RETURN_EMPTY_ARRAY();
2746+
}
2747+
26432748
/* {{{ proto public bool ReflectionParameter::getPosition()
26442749
Returns whether this parameter is an optional parameter */
26452750
ZEND_METHOD(reflection_parameter, getPosition)
@@ -5626,6 +5731,7 @@ ZEND_METHOD(reflection_property, getAttributes)
56265731
return;
56275732
}
56285733
GET_REFLECTION_OBJECT_PTR(ref);
5734+
56295735
if (ref->prop->attributes) {
56305736
zval ret;
56315737

@@ -6614,6 +6720,7 @@ static const zend_function_entry reflection_parameter_functions[] = {
66146720
ZEND_ME(reflection_parameter, isArray, arginfo_class_ReflectionParameter_isArray, 0)
66156721
ZEND_ME(reflection_parameter, isCallable, arginfo_class_ReflectionParameter_isCallable, 0)
66166722
ZEND_ME(reflection_parameter, allowsNull, arginfo_class_ReflectionParameter_allowsNull, 0)
6723+
ZEND_ME(reflection_parameter, getAttributes, arginfo_class_ReflectionParameter_getAttributes, 0)
66176724
ZEND_ME(reflection_parameter, getPosition, arginfo_class_ReflectionParameter_getPosition, 0)
66186725
ZEND_ME(reflection_parameter, isOptional, arginfo_class_ReflectionParameter_isOptional, 0)
66196726
ZEND_ME(reflection_parameter, isDefaultValueAvailable, arginfo_class_ReflectionParameter_isDefaultValueAvailable, 0)

ext/reflection/php_reflection.stub.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ public function hasReturnType() {}
9696
public function getReturnType() {}
9797

9898
/** @return ReflectionAttribute[] */
99-
public function getAttributes($name = null) {}
99+
public function getAttributes(?string $name = null) {}
100100
}
101101

102102
class ReflectionFunction extends ReflectionFunctionAbstract
@@ -358,7 +358,7 @@ public function getNamespaceName() {}
358358
public function getShortName() {}
359359

360360
/** @return ReflectionAttribute[] */
361-
public function getAttributes($name = null) {}
361+
public function getAttributes(?string $name = null) {}
362362
}
363363

364364
class ReflectionObject extends ReflectionClass
@@ -426,7 +426,7 @@ public function hasDefaultValue(): bool {}
426426
public function getDefaultValue() {}
427427

428428
/** @return ReflectionAttribute[] */
429-
public function getAttributes($name = null) {}
429+
public function getAttributes(?string $name = null) {}
430430
}
431431

432432
class ReflectionClassConstant implements Reflector
@@ -463,7 +463,7 @@ public function getDeclaringClass() {}
463463
public function getDocComment() {}
464464

465465
/** @return ReflectionAttribute[] */
466-
public function getAttributes($name = null) {}
466+
public function getAttributes(?string $name = null) {}
467467
}
468468

469469
class ReflectionParameter implements Reflector
@@ -531,6 +531,9 @@ public function getDefaultValueConstantName() {}
531531

532532
/** @return bool */
533533
public function isVariadic() {}
534+
535+
/** @return ReflectionAttribute[] */
536+
public function getAttributes(?string $name = null) {}
534537
}
535538

536539
abstract class ReflectionType

ext/reflection/php_reflection_arginfo.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ ZEND_END_ARG_INFO()
6060
#define arginfo_class_ReflectionFunctionAbstract_getReturnType arginfo_class_Reflector___toString
6161

6262
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionFunctionAbstract_getAttributes, 0, 0, 0)
63-
ZEND_ARG_INFO(0, name)
63+
ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 1)
6464
ZEND_END_ARG_INFO()
6565

6666
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionFunction___construct, 0, 0, 1)
@@ -398,6 +398,8 @@ ZEND_END_ARG_INFO()
398398

399399
#define arginfo_class_ReflectionParameter_isVariadic arginfo_class_Reflector___toString
400400

401+
#define arginfo_class_ReflectionParameter_getAttributes arginfo_class_ReflectionFunctionAbstract_getAttributes
402+
401403
#define arginfo_class_ReflectionType___clone arginfo_class_Reflector___toString
402404

403405
#define arginfo_class_ReflectionType_allowsNull arginfo_class_Reflector___toString

0 commit comments

Comments
 (0)