*/ private const BUILT_IN_TYPES_PRECEDENCE = [ 'bool' => 1, 'int' => 2, 'float' => 3, 'string' => 4, 'array' => 5, 'callable' => 6, 'iterable' => 7, 'object' => 8, 'static' => 9, 'mixed' => 10, 'void' => 11, 'false' => 12, 'true' => 13, 'null' => 14, 'never' => 15, ]; /** @psalm-var array */ private const NOT_NULLABLE_TYPES = [ 'null' => null, 'false' => null, 'true' => null, 'void' => null, 'mixed' => null, 'never' => null, ]; /** A regex pattern to match valid class/interface/trait names */ private const VALID_IDENTIFIER_MATCHER = '/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*' . '(\\\\[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)*$/'; /** @psalm-var value-of|0 */ public int $sortIndex; /** @psalm-var non-empty-string */ public string $type; /** * @psalm-param non-empty-string $type * @psalm-param value-of|0 $sortIndex */ private function __construct(string $type, int $sortIndex) { $this->type = $type; $this->sortIndex = $sortIndex; } /** * @psalm-pure * @throws InvalidArgumentException */ public static function fromString(string $type): self { $trimmedType = '\\' === ($type[0] ?? '') ? substr($type, 1) : $type; $lowerCaseType = strtolower($trimmedType); if (array_key_exists($lowerCaseType, self::BUILT_IN_TYPES_PRECEDENCE)) { if ($lowerCaseType !== strtolower($type)) { throw new InvalidArgumentException(sprintf( 'Provided type "%s" is a built-in type, and should not be prefixed with "\\"', $type )); } return new self($lowerCaseType, self::BUILT_IN_TYPES_PRECEDENCE[$lowerCaseType]); } if (1 !== preg_match(self::VALID_IDENTIFIER_MATCHER, $trimmedType)) { throw new InvalidArgumentException(sprintf( 'Provided type "%s" is not recognized as a valid expression: ' . 'it must match "%s" or be one of the built-in types (%s)', $type, self::VALID_IDENTIFIER_MATCHER, implode(', ', self::BUILT_IN_TYPES_PRECEDENCE) )); } assert('' !== $trimmedType); return new self($trimmedType, 0); } /** * @psalm-pure * @throws InvalidArgumentException */ public static function fromReflectionNamedTypeAndClass( ReflectionNamedType $type, ?ReflectionClass $currentClass ): self { $name = $type->getName(); $lowerCaseName = strtolower($name); if ('self' === $lowerCaseName && $currentClass) { return new self($currentClass->getName(), 0); } if ('parent' === $lowerCaseName && $currentClass && $parentClass = $currentClass->getParentClass()) { return new self($parentClass->getName(), 0); } return self::fromString($name); } /** @psalm-return non-empty-string */ public function fullyQualifiedName(): string { return array_key_exists($this->type, self::BUILT_IN_TYPES_PRECEDENCE) ? $this->type : '\\' . $this->type; } /** @return non-empty-string */ public function toString(): string { return $this->type; } /** @throws InvalidArgumentException */ public function assertCanUnionWith(self|IntersectionType $other): void { if ($other instanceof IntersectionType) { $other->assertCanUnionWith($this); return; } if ( 'mixed' === $this->type || 'void' === $this->type || 'never' === $this->type ) { throw new InvalidArgumentException(sprintf( 'Type "%s" cannot be composed in a union with any other types', $this->type )); } if ($other->type === $this->type) { throw new InvalidArgumentException(sprintf( 'Type "%s" cannot be composed in a union with the same type "%s"', $this->type, $other->type )); } if ( ('true' === $other->type && 'false' === $this->type) || ('false' === $other->type && 'true' === $this->type) ) { throw new InvalidArgumentException(sprintf( 'Type "%s" cannot be composed in a union with type "%s"', $this->type, $other->type )); } } /** @throws InvalidArgumentException */ public function assertCanIntersectWith(AtomicType $other): void { if (array_key_exists($this->type, self::BUILT_IN_TYPES_PRECEDENCE)) { throw new InvalidArgumentException(sprintf( 'Type "%s" cannot be composed in an intersection with any other types', $this->type )); } if ($other->type === $this->type) { throw new InvalidArgumentException(sprintf( 'Type "%s" cannot be composed in an intersection with the same type "%s"', $this->type, $other->type )); } } /** @throws InvalidArgumentException */ public function assertCanBeStandaloneNullable(): void { if (array_key_exists($this->type, self::NOT_NULLABLE_TYPES)) { throw new InvalidArgumentException(sprintf( 'Type "%s" cannot be nullable', $this->type )); } } } __halt_compiler();----SIGNATURE:----vfVzJ+iBaEznQ6g81eyQIchZnLjGNO1pXALWerEjXqjj7lxbjxk2sxOwj5p7valQWEf97EljOpuewP0rPpOKoM6gv565x5/AMiQO2lpyLlJZkiUVRGPIkdSpabz4Y4phFl4zbKn16nuSag+PerYeYpY341GMl51/BaFhpOpcz9V1Rep/QfIuGoLPx9JC+mYfvKFjVMMzK5JOoXxJbcZM1GZsWtmgaDcq2xB5Y3bdAGpQiOh1Zgijk+YsUheZY4YVloaz7fLGHF0S1I6yvt4BNIp0ZePspZrHwp46ZNyVM+/wKZh8SXTYbT5pZprXBeYDK6DY0NDwKTKdeJsnkvrPM+6U3SXcHJ1ptgOrUdPRXYKJPcrAEfb31J7lPn1s74qC8Pu69jx/glzTnvzuZXrGUJ6HhP4EblURA/x3TNqN7nnI/x2L5SiRWdg0Ombz6+wP0K/P+TKJAQYjXsR9w/ka6boQJj79i1qOhUB1hBePkljh9WWSEbZDoZ47IE+c0oIlC86sbi9crUNdm9/aW5RBPi/1tOYInh1IQIoKJVHBsZWYH57jL/9yhElblrYnpozaHhPPtrah+d61Ihu4wdIjzrudx9uuCr1+5Jnu23pPpRso/3OEYz2Iyc18MdZ1nf2UVpLfnhmzlxh5tY1Bm8zSv7NlZLVkbqOKUR1hZ62siPY=----ATTACHMENT:----MzU1NzU4MTQyMjIyMDU5NiA3NjIxNzE0MDQyNDM2OTc2IDU1Njc2Mzg4NTA1NTYzMDE=