Fix nested namespaced typed property in gen_stub.php (#7418)

Property escape namespaced class name in property types.
This commit is contained in:
Go Kudo 2021-08-31 18:56:39 +09:00 committed by GitHub
parent 52d3af1790
commit eaac77f4e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 5 deletions

View file

@ -395,6 +395,11 @@ class SimpleType {
return str_replace('\\', '\\\\', $this->name); return str_replace('\\', '\\\\', $this->name);
} }
public function toCVarEscapedName(): string {
$name = str_replace('_', '__', $this->name);
return str_replace('\\', '_', $this->name);
}
public function equals(SimpleType $other): bool { public function equals(SimpleType $other): bool {
return $this->name === $other->name && $this->isBuiltin === $other->isBuiltin; return $this->name === $other->name && $this->isBuiltin === $other->isBuiltin;
} }
@ -1374,7 +1379,9 @@ class PropertyInfo
if (count($arginfoType->classTypes) >= 2) { if (count($arginfoType->classTypes) >= 2) {
foreach ($arginfoType->classTypes as $classType) { foreach ($arginfoType->classTypes as $classType) {
$className = $classType->name; $className = $classType->name;
$code .= "\tzend_string *property_{$propertyName}_class_{$className} = zend_string_init(\"$className\", sizeof(\"$className\") - 1, 1);\n"; $escapedClassName = $classType->toEscapedName();
$varEscapedClassName = $classType->toCVarEscapedName();
$code .= "\tzend_string *property_{$propertyName}_class_{$varEscapedClassName} = zend_string_init(\"{$escapedClassName}\", sizeof(\"{$escapedClassName}\") - 1, 1);\n";
} }
$classTypeCount = count($arginfoType->classTypes); $classTypeCount = count($arginfoType->classTypes);
@ -1383,7 +1390,8 @@ class PropertyInfo
foreach ($arginfoType->classTypes as $k => $classType) { foreach ($arginfoType->classTypes as $k => $classType) {
$className = $classType->name; $className = $classType->name;
$code .= "\tproperty_{$propertyName}_type_list->types[$k] = (zend_type) ZEND_TYPE_INIT_CLASS(property_{$propertyName}_class_{$className}, 0, 0);\n"; $escapedClassName = $classType->toEscapedName();
$code .= "\tproperty_{$propertyName}_type_list->types[$k] = (zend_type) ZEND_TYPE_INIT_CLASS(property_{$propertyName}_class_{$escapedClassName}, 0, 0);\n";
} }
$typeMaskCode = $this->type->toArginfoType()->toTypeMask(); $typeMaskCode = $this->type->toArginfoType()->toTypeMask();
@ -1392,9 +1400,11 @@ class PropertyInfo
$typeCode = "property_{$propertyName}_type"; $typeCode = "property_{$propertyName}_type";
} else { } else {
$className = $arginfoType->classTypes[0]->name; $className = $arginfoType->classTypes[0]->name;
$code .= "\tzend_string *property_{$propertyName}_class_{$className} = zend_string_init(\"$className\", sizeof(\"$className\")-1, 1);\n"; $escapedClassName = $arginfoType->classTypes[0]->toEscapedName();
$varEscapedClassName = $arginfoType->classTypes[0]->toCVarEscapedName();
$code .= "\tzend_string *property_{$propertyName}_class_{$varEscapedClassName} = zend_string_init(\"{$escapedClassName}\", sizeof(\"${escapedClassName}\")-1, 1);\n";
$typeCode = "(zend_type) ZEND_TYPE_INIT_CLASS(property_{$propertyName}_class_{$className}, 0, " . $arginfoType->toTypeMask() . ")"; $typeCode = "(zend_type) ZEND_TYPE_INIT_CLASS(property_{$propertyName}_class_{$varEscapedClassName}, 0, " . $arginfoType->toTypeMask() . ")";
} }
} else { } else {
$typeCode = "(zend_type) ZEND_TYPE_INIT_MASK(" . $arginfoType->toTypeMask() . ")"; $typeCode = "(zend_type) ZEND_TYPE_INIT_MASK(" . $arginfoType->toTypeMask() . ")";

View file

@ -88,6 +88,8 @@ namespace ZendTestNS {
namespace ZendTestNS2 { namespace ZendTestNS2 {
class Foo { class Foo {
public ZendSubNS\Foo $foo;
public function method(): void {} public function method(): void {}
} }

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead. /* This is a generated file, edit the .stub.php file instead.
* Stub hash: 93bb8b9120e510e8c3afc29dc0a5d47cb6b5f10e */ * Stub hash: 04d48fa64594bacba57210dcb94381f83951116c */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
ZEND_END_ARG_INFO() ZEND_END_ARG_INFO()
@ -296,6 +296,13 @@ static zend_class_entry *register_class_ZendTestNS2_Foo(void)
INIT_NS_CLASS_ENTRY(ce, "ZendTestNS2", "Foo", class_ZendTestNS2_Foo_methods); INIT_NS_CLASS_ENTRY(ce, "ZendTestNS2", "Foo", class_ZendTestNS2_Foo_methods);
class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry = zend_register_internal_class_ex(&ce, NULL);
zend_string *property_foo_class_ZendTestNS2_ZendSubNS_Foo = zend_string_init("ZendTestNS2\\ZendSubNS\\Foo", sizeof("ZendTestNS2\\ZendSubNS\\Foo")-1, 1);
zval property_foo_default_value;
ZVAL_UNDEF(&property_foo_default_value);
zend_string *property_foo_name = zend_string_init("foo", sizeof("foo") - 1, 1);
zend_declare_typed_property(class_entry, property_foo_name, &property_foo_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_foo_class_ZendTestNS2_ZendSubNS_Foo, 0, 0));
zend_string_release(property_foo_name);
return class_entry; return class_entry;
} }

View file

@ -0,0 +1,22 @@
--TEST--
gen_stub.php: nested namespaced typed properties test.
--EXTENSIONS--
zend_test
--FILE--
<?php
$foo = new \ZendTestNS2\Foo();
var_dump($foo);
$foo->foo = new \ZendTestNS2\ZendSubNS\Foo();
var_dump($foo);
?>
--EXPECTF--
object(ZendTestNS2\Foo)#%d (%d) {
["foo"]=>
uninitialized(ZendTestNS2\ZendSubNS\Foo)
}
object(ZendTestNS2\Foo)#%d (%d) {
["foo"]=>
object(ZendTestNS2\ZendSubNS\Foo)#%d (%d) {
}
}