diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php index c6a02b5f2f3e..b3489d9fb0c1 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php @@ -169,7 +169,7 @@ public function testExtractCollection($property, array $type = null, $shortDescr public static function provideCollectionTypes() { return [ - ['iteratorCollection', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Iterator', true, null, new Type(Type::BUILTIN_TYPE_STRING))], null, null], + ['iteratorCollection', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Iterator', true, [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)], new Type(Type::BUILTIN_TYPE_STRING))], null, null], ['iteratorCollectionWithKey', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Iterator', true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))], null, null], [ 'nestedIterators', @@ -265,6 +265,8 @@ public static function typesWithCustomPrefixesProvider() ['i', [new Type(Type::BUILTIN_TYPE_STRING, true), new Type(Type::BUILTIN_TYPE_INT, true)], null, null], ['j', [new Type(Type::BUILTIN_TYPE_OBJECT, true, 'DateTime')], null, null], ['nullableCollectionOfNonNullableElements', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT, false))], null, null], + ['nonNullableCollectionOfNullableElements', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT, true))], null, null], + ['nullableCollectionOfMultipleNonNullableElementTypes', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, new Type(Type::BUILTIN_TYPE_INT), [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)])], null, null], ['donotexist', null, null, null], ['staticGetter', null, null, null], ['staticSetter', null, null, null], diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php index b7955584d8c3..5f81dd5a6518 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php @@ -62,6 +62,8 @@ public function testGetProperties() 'i', 'j', 'nullableCollectionOfNonNullableElements', + 'nonNullableCollectionOfNullableElements', + 'nullableCollectionOfMultipleNonNullableElementTypes', 'emptyVar', 'iteratorCollection', 'iteratorCollectionWithKey', @@ -124,6 +126,8 @@ public function testGetPropertiesWithCustomPrefixes() 'i', 'j', 'nullableCollectionOfNonNullableElements', + 'nonNullableCollectionOfNullableElements', + 'nullableCollectionOfMultipleNonNullableElementTypes', 'emptyVar', 'iteratorCollection', 'iteratorCollectionWithKey', @@ -175,6 +179,8 @@ public function testGetPropertiesWithNoPrefixes() 'i', 'j', 'nullableCollectionOfNonNullableElements', + 'nonNullableCollectionOfNullableElements', + 'nullableCollectionOfMultipleNonNullableElementTypes', 'emptyVar', 'iteratorCollection', 'iteratorCollectionWithKey', diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php index 8d956a1103fc..2fb3d2e0f807 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php @@ -98,6 +98,16 @@ class Dummy extends ParentDummy */ public $nullableCollectionOfNonNullableElements; + /** + * @var array + */ + public $nonNullableCollectionOfNullableElements; + + /** + * @var null|array + */ + public $nullableCollectionOfMultipleNonNullableElementTypes; + /** * @var array */ diff --git a/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php b/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php index 2c858c3bf9f8..44a461498556 100644 --- a/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php +++ b/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php @@ -115,15 +115,10 @@ private function createType(DocType $type, bool $nullable, string $docType = nul [$phpType, $class] = $this->getPhpTypeAndClass((string) $fqsen); - $key = $this->getTypes($type->getKeyType()); - $value = $this->getTypes($type->getValueType()); + $keys = $this->getTypes($type->getKeyType()); + $values = $this->getTypes($type->getValueType()); - // More than 1 type returned means it is a Compound type, which is - // not handled by Type, so better use a null value. - $key = 1 === \count($key) ? $key[0] : null; - $value = 1 === \count($value) ? $value[0] : null; - - return new Type($phpType, $nullable, $class, true, $key, $value); + return new Type($phpType, $nullable, $class, true, $keys, $values); } // Cannot guess @@ -131,27 +126,20 @@ private function createType(DocType $type, bool $nullable, string $docType = nul return null; } - if (str_ends_with($docType, '[]')) { - $collectionKeyType = new Type(Type::BUILTIN_TYPE_INT); - $collectionValueType = $this->createType($type, false, substr($docType, 0, -2)); + if (str_ends_with($docType, '[]') && $type instanceof Array_) { + $collectionKeyTypes = new Type(Type::BUILTIN_TYPE_INT); + $collectionValueTypes = $this->getTypes($type->getValueType()); - return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, $collectionKeyType, $collectionValueType); + return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, $collectionKeyTypes, $collectionValueTypes); } if ((str_starts_with($docType, 'list<') || str_starts_with($docType, 'array<')) && $type instanceof Array_) { // array is converted to x[] which is handled above // so it's only necessary to handle array here - $collectionKeyType = $this->getTypes($type->getKeyType())[0]; - + $collectionKeyTypes = $this->getTypes($type->getKeyType()); $collectionValueTypes = $this->getTypes($type->getValueType()); - if (1 != \count($collectionValueTypes)) { - // the Type class does not support union types yet, so assume that no type was defined - $collectionValueType = null; - } else { - $collectionValueType = $collectionValueTypes[0]; - } - return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, $collectionKeyType, $collectionValueType); + return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, $collectionKeyTypes, $collectionValueTypes); } $docType = $this->normalizeType($docType);