Skip to content

Commit 15976ca

Browse files
authored
fix ClassEntry typehints (#206)
1 parent d161e96 commit 15976ca

File tree

3 files changed

+43
-14
lines changed

3 files changed

+43
-14
lines changed

phper-sys/php_wrapper.c

+27-5
Original file line numberDiff line numberDiff line change
@@ -516,12 +516,24 @@ phper_zend_begin_arg_with_return_obj_info_ex(bool return_reference,
516516
#define static
517517
#define const
518518
#if PHP_VERSION_ID >= 80000
519-
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(info, return_reference, required_num_args, class_name, allow_null)
519+
zend_string *zstr = zend_string_init(class_name, strlen(class_name), /*persistent*/ 1);
520+
//this macro uses class_name as a literal, so we overwrite it immediately
521+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(infos, return_reference, required_num_args, class_name, allow_null)
522+
ZEND_END_ARG_INFO()
523+
zend_internal_arg_info info = infos[0];
524+
#if PHP_VERSION_ID >= 80300
525+
info.type.ptr = zstr;
526+
#else
527+
info.type.ptr = ZSTR_VAL(zstr);
528+
#endif
529+
info.type.type_mask = _ZEND_TYPE_NAME_BIT | (allow_null ? MAY_BE_NULL : 0);
530+
return info;
520531
#else
521532
ZEND_BEGIN_ARG_INFO_EX(info, 0, return_reference, required_num_args)
522-
#endif
523533
ZEND_END_ARG_INFO()
524534
return info[0];
535+
#endif
536+
525537
#undef static
526538
#undef const
527539
}
@@ -560,10 +572,20 @@ zend_internal_arg_info phper_zend_arg_obj_info(bool pass_by_ref,
560572
(void)class_name;
561573
(void)allow_null;
562574
#if PHP_VERSION_ID >= 80000
563-
zend_internal_arg_info info[] = {
564-
ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, class_name, allow_null, NULL)
575+
zend_string *zstr = zend_string_init(class_name, strlen(class_name), /*persistent*/ 1);
576+
//this macro uses name and class_name as literals, so we overwrite them immediately
577+
zend_internal_arg_info infos[] = {
578+
ZEND_ARG_OBJ_INFO(pass_by_ref, name, class_name, allow_null)
565579
};
566-
return info[0];
580+
zend_internal_arg_info info = infos[0];
581+
info.name = name;
582+
#if PHP_VERSION_ID >= 80300
583+
info.type.ptr = zstr;
584+
#else
585+
info.type.ptr = ZSTR_VAL(zstr);
586+
#endif
587+
info.type.type_mask = _ZEND_TYPE_NAME_BIT | (allow_null ? MAY_BE_NULL : 0);
588+
return info;
567589
#elif PHP_VERSION_ID >= 70200
568590
zend_internal_arg_info info = {
569591
.name = name,

tests/integration/src/typehints.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ pub fn integrate(module: &mut Module) {
5858
.with_type_hint(ArgumentTypeHint::Mixed)
5959
.with_default_value("1.23"),
6060
)
61+
.argument(
62+
Argument::new("ce")
63+
.with_type_hint(ArgumentTypeHint::ClassEntry(String::from("Stringable"))),
64+
)
6165
.return_type(ReturnType::new(ReturnTypeHint::Void));
6266
}
6367

@@ -417,7 +421,7 @@ fn make_arg_typehint_class() -> ClassEntity<()> {
417421
phper::ok(())
418422
})
419423
.argument(
420-
Argument::new("classentry")
424+
Argument::new("some_class_entry")
421425
.with_type_hint(ArgumentTypeHint::ClassEntry(String::from(I_FOO))),
422426
);
423427

@@ -426,7 +430,7 @@ fn make_arg_typehint_class() -> ClassEntity<()> {
426430
phper::ok(())
427431
})
428432
.argument(
429-
Argument::new("classentry")
433+
Argument::new("some_class_entry")
430434
.with_type_hint(ArgumentTypeHint::ClassEntry(String::from(I_FOO)))
431435
.allow_null(),
432436
);

tests/integration/tests/php/typehints.php

+10-7
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@
5858

5959
['testNull', 'null', true, true, '8.2'],
6060

61-
['testClassEntry', 'class_name', false, true, '8.0'],
62-
['testClassEntryOptional', 'class_name', false, false, '8.0'],
63-
['testClassEntryNullable', 'class_name', true, true, '8.0'],
61+
['testClassEntry', 'IntegrationTest\\TypeHints\\IFoo', false, true, '8.0'],
62+
['testClassEntryOptional', 'IntegrationTest\\TypeHints\\IFoo', false, false, '8.0'],
63+
['testClassEntryNullable', 'IntegrationTest\\TypeHints\\IFoo', true, true, '8.0'],
6464
];
6565

6666
// typehints
@@ -113,8 +113,8 @@
113113
['returnMixed', 'mixed', true, '8.0'],
114114
['returnNever', 'never', false, '8.1'],
115115
['returnVoid', 'void', false],
116-
['returnClassEntry', 'class_name', false, '8.0'],
117-
['returnClassEntryNullable', 'class_name', true, '8.0'],
116+
['returnClassEntry', 'IntegrationTest\\TypeHints\\IFoo', false, '8.0'],
117+
['returnClassEntryNullable', 'IntegrationTest\\TypeHints\\IFoo', true, '8.0'],
118118
];
119119
echo PHP_EOL . 'Testing return typehints' . PHP_EOL;
120120
$cls = new \IntegrationTest\TypeHints\ReturnTypeHintTest();
@@ -186,13 +186,14 @@ public function setValue($value): void {
186186
}
187187

188188
$expectedArgs = [
189+
// <arg name>, <type>, <default value>
189190
['s', 'string', 'foobarbaz'],
190191
['i', 'int', 42],
191192
['f', 'float', 7.89],
192193
['b', 'bool', true],
193194
['a', 'array', ['a'=>'b']],
194195
['m', 'mixed', 1.23],
195-
196+
['ce', 'Stringable'], //default value not supported for ClassEntry
196197
];
197198
if (PHP_VERSION_ID >= 80000) {
198199
echo PHP_EOL . 'Testing function typehints' . PHP_EOL;
@@ -202,7 +203,9 @@ public function setValue($value): void {
202203
echo(sprintf("argument %d..", $i));
203204
assert_eq($input[0], $params[$i]->getName(), sprintf('argument %d has correct name', $i));
204205
assert_eq($input[1], $params[$i]->getType()->getName(), sprintf('argument %d has correct type', $i));
205-
assert_eq($input[2], $params[$i]->getDefaultValue(), sprintf('argument %d has correct default value', $i));
206+
if (array_key_exists(2, $input)) {
207+
assert_eq($input[2], $params[$i]->getDefaultValue(), sprintf('argument %d has correct default value', $i));
208+
}
206209
echo "PASS" . PHP_EOL;
207210
}
208211
assert_eq('void', $reflection->getReturnType()->getName(), 'integration_function_typehints return type is void');

0 commit comments

Comments
 (0)