vendor/symfony/property-info/Util/PhpDocTypeHelper.php line 108
<?php/** This file is part of the Symfony package.** (c) Fabien Potencier <fabien@symfony.com>** For the full copyright and license information, please view the LICENSE* file that was distributed with this source code.*/namespace Symfony\Component\PropertyInfo\Util;use phpDocumentor\Reflection\PseudoType;use phpDocumentor\Reflection\PseudoTypes\ConstExpression;use phpDocumentor\Reflection\PseudoTypes\List_;use phpDocumentor\Reflection\Type as DocType;use phpDocumentor\Reflection\Types\Array_;use phpDocumentor\Reflection\Types\Collection;use phpDocumentor\Reflection\Types\Compound;use phpDocumentor\Reflection\Types\Integer;use phpDocumentor\Reflection\Types\Null_;use phpDocumentor\Reflection\Types\Nullable;use phpDocumentor\Reflection\Types\String_;use Symfony\Component\PropertyInfo\Type;// Workaround for phpdocumentor/type-resolver < 1.6// We trigger the autoloader here, so we don't need to trigger it inside the loop later.class_exists(List_::class);/*** Transforms a php doc type to a {@link Type} instance.** @author Kévin Dunglas <dunglas@gmail.com>* @author Guilhem N. <egetick@gmail.com>*/final class PhpDocTypeHelper{/*** Creates a {@see Type} from a PHPDoc type.** @return Type[]*/public function getTypes(DocType $varType): array{if ($varType instanceof ConstExpression) {// It's safer to fall back to other extractors here, as resolving const types correctly is not easy at the momentreturn [];}$types = [];$nullable = false;if ($varType instanceof Nullable) {$nullable = true;$varType = $varType->getActualType();}if (!$varType instanceof Compound) {if ($varType instanceof Null_) {$nullable = true;}$type = $this->createType($varType, $nullable);if (null !== $type) {$types[] = $type;}return $types;}$varTypes = [];for ($typeIndex = 0; $varType->has($typeIndex); ++$typeIndex) {$type = $varType->get($typeIndex);if ($type instanceof ConstExpression) {// It's safer to fall back to other extractors here, as resolving const types correctly is not easy at the momentreturn [];}// If null is present, all types are nullableif ($type instanceof Null_) {$nullable = true;continue;}if ($type instanceof Nullable) {$nullable = true;$type = $type->getActualType();}$varTypes[] = $type;}foreach ($varTypes as $varType) {$type = $this->createType($varType, $nullable);if (null !== $type) {$types[] = $type;}}return $types;}/*** Creates a {@see Type} from a PHPDoc type.*/private function createType(DocType $type, bool $nullable, string $docType = null): ?Type{$docType ??= (string) $type;if ($type instanceof Collection) {$fqsen = $type->getFqsen();if ($fqsen && 'list' === $fqsen->getName() && !class_exists(List_::class, false) && !class_exists((string) $fqsen)) {// Workaround for phpdocumentor/type-resolver < 1.6return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, new Type(Type::BUILTIN_TYPE_INT), $this->getTypes($type->getValueType()));}[$phpType, $class] = $this->getPhpTypeAndClass((string) $fqsen);$key = $this->getTypes($type->getKeyType());$value = $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);}// Cannot guessif (!$docType || 'mixed' === $docType) {return null;}if (str_ends_with($docType, '[]')) {$collectionKeyType = new Type(Type::BUILTIN_TYPE_INT);$collectionValueType = $this->createType($type, false, substr($docType, 0, -2));return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, $collectionKeyType, $collectionValueType);}if ((str_starts_with($docType, 'list<') || str_starts_with($docType, 'array<')) && $type instanceof Array_) {// array<value> is converted to x[] which is handled above// so it's only necessary to handle array<key, value> here$collectionKeyType = $this->getTypes($type->getKeyType())[0];$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);}if ($type instanceof PseudoType) {if ($type->underlyingType() instanceof Integer) {return new Type(Type::BUILTIN_TYPE_INT, $nullable, null);} elseif ($type->underlyingType() instanceof String_) {return new Type(Type::BUILTIN_TYPE_STRING, $nullable, null);}}$docType = $this->normalizeType($docType);[$phpType, $class] = $this->getPhpTypeAndClass($docType);if ('array' === $docType) {return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, null, null);}return new Type($phpType, $nullable, $class);}private function normalizeType(string $docType): string{return match ($docType) {'integer' => 'int','boolean' => 'bool',// real is not part of the PHPDoc standard, so we ignore it'double' => 'float','callback' => 'callable','void' => 'null',default => $docType,};}private function getPhpTypeAndClass(string $docType): array{if (\in_array($docType, Type::$builtinTypes)) {return [$docType, null];}if (\in_array($docType, ['parent', 'self', 'static'], true)) {return ['object', $docType];}return ['object', ltrim($docType, '\\')];}}