├── src ├── PseudoTypes │ ├── ObjectShapeItem.php │ ├── ListShapeItem.php │ ├── ListShape.php │ ├── ArrayShapeItem.php │ ├── PublicPropertiesOf.php │ ├── PrivatePropertiesOf.php │ ├── ProtectedPropertiesOf.php │ ├── NoReturn.php │ ├── NeverReturn.php │ ├── False_.php │ ├── NeverReturns.php │ ├── True_.php │ ├── TruthyString.php │ ├── NonFalsyString.php │ ├── OpenResource.php │ ├── ClosedResource.php │ ├── NonPositiveInteger.php │ ├── ObjectShape.php │ ├── LiteralString.php │ ├── NegativeInteger.php │ ├── NonZeroInteger.php │ ├── NumericString.php │ ├── PositiveInteger.php │ ├── CallableString.php │ ├── LowercaseString.php │ ├── NonEmptyString.php │ ├── NonNegativeInteger.php │ ├── HtmlEscapedString.php │ ├── NonEmptyLowercaseString.php │ ├── FloatValue.php │ ├── IntegerValue.php │ ├── KeyOf.php │ ├── StringValue.php │ ├── CallableArray.php │ ├── ValueOf.php │ ├── IntMaskOf.php │ ├── ArrayKey.php │ ├── Scalar.php │ ├── IntMask.php │ ├── List_.php │ ├── NonEmptyArray.php │ ├── Generic.php │ ├── NonEmptyList.php │ ├── PropertiesOf.php │ ├── ArrayShape.php │ ├── ShapeItem.php │ ├── ConstExpression.php │ ├── Numeric_.php │ ├── EnumString.php │ ├── ClassString.php │ ├── TraitString.php │ ├── InterfaceString.php │ ├── IntegerRange.php │ ├── OffsetAccess.php │ ├── Conditional.php │ └── ConditionalForParameter.php ├── PseudoType.php ├── Type.php ├── Types │ ├── Float_.php │ ├── Integer.php │ ├── Boolean.php │ ├── Null_.php │ ├── String_.php │ ├── Mixed_.php │ ├── Resource_.php │ ├── Array_.php │ ├── Parent_.php │ ├── Never_.php │ ├── Void_.php │ ├── Iterable_.php │ ├── This.php │ ├── Compound.php │ ├── Intersection.php │ ├── Expression.php │ ├── Nullable.php │ ├── Self_.php │ ├── Static_.php │ ├── Object_.php │ ├── Callable_.php │ ├── CallableParameter.php │ ├── AbstractList.php │ ├── Context.php │ ├── AggregatedType.php │ └── ContextFactory.php ├── FqsenResolver.php └── TypeResolver.php ├── .phpdoc └── template │ └── base.html.twig ├── docs ├── index.rst ├── generics.rst ├── getting-started.rst └── upgrade-v1-to-v2.rst ├── LICENSE ├── composer.json ├── phpdoc.dist.xml └── README.md /src/PseudoTypes/ObjectShapeItem.php: -------------------------------------------------------------------------------- 1 | getItems()) . '}'; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/PseudoTypes/ArrayShapeItem.php: -------------------------------------------------------------------------------- 1 | type . '>'; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/PseudoTypes/PrivatePropertiesOf.php: -------------------------------------------------------------------------------- 1 | type . '>'; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/PseudoTypes/ProtectedPropertiesOf.php: -------------------------------------------------------------------------------- 1 | type . '>'; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Types/Float_.php: -------------------------------------------------------------------------------- 1 | valueType === null) { 29 | return 'iterable'; 30 | } 31 | 32 | if ($this->keyType) { 33 | return 'iterable<' . $this->keyType . ', ' . $this->valueType . '>'; 34 | } 35 | 36 | return 'iterable<' . $this->valueType . '>'; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Types/This.php: -------------------------------------------------------------------------------- 1 | items = $items; 22 | } 23 | 24 | /** 25 | * @return ObjectShapeItem[] 26 | */ 27 | public function getItems(): array 28 | { 29 | return $this->items; 30 | } 31 | 32 | public function underlyingType(): Type 33 | { 34 | return new Object_(); 35 | } 36 | 37 | public function __toString(): string 38 | { 39 | return 'object{' . implode(', ', $this->items) . '}'; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /docs/generics.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | Generics 3 | ======== 4 | 5 | This project is capable of parsing generics notation as used by PHPStan. But it has some limitations, in regards to 6 | PHPStan. The main difference is that PHPStan does scan your whole codebase to find out what types are used in generics, 7 | while this library only parses the types as they are given to it. 8 | 9 | This means that if you use a generic type like. 10 | 11 | .. code:: php 12 | 13 | namespace MyApp; 14 | 15 | /** 16 | * @template T of Item 17 | */ 18 | class Collection { 19 | 20 | /** 21 | * @return T[] 22 | */ 23 | public function getItems() : array { 24 | // ... 25 | } 26 | } 27 | 28 | The type resolver will not be able to determine what ``T`` is. In fact there is no difference between ``T`` and any other relative 29 | used classname like ``Item``. The resolver will handle ``T`` as a normal class name. In this example it will resolve ``T`` to ``\MyApp\T``. 30 | -------------------------------------------------------------------------------- /src/PseudoTypes/LiteralString.php: -------------------------------------------------------------------------------- 1 | value = $value; 29 | } 30 | 31 | public function getValue(): float 32 | { 33 | return $this->value; 34 | } 35 | 36 | public function underlyingType(): Type 37 | { 38 | return new Float_(); 39 | } 40 | 41 | public function __toString(): string 42 | { 43 | return (string) $this->value; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/PseudoTypes/IntegerValue.php: -------------------------------------------------------------------------------- 1 | value = $value; 29 | } 30 | 31 | public function getValue(): int 32 | { 33 | return $this->value; 34 | } 35 | 36 | public function underlyingType(): Type 37 | { 38 | return new Integer(); 39 | } 40 | 41 | public function __toString(): string 42 | { 43 | return (string) $this->value; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/PseudoTypes/KeyOf.php: -------------------------------------------------------------------------------- 1 | type = $type; 32 | } 33 | 34 | public function getType(): Type 35 | { 36 | return $this->type; 37 | } 38 | 39 | public function underlyingType(): Type 40 | { 41 | return new ArrayKey(); 42 | } 43 | 44 | public function __toString(): string 45 | { 46 | return 'key-of<' . $this->type . '>'; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2010 Mike van Riel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/PseudoTypes/StringValue.php: -------------------------------------------------------------------------------- 1 | value = $value; 31 | } 32 | 33 | public function getValue(): string 34 | { 35 | return $this->value; 36 | } 37 | 38 | public function underlyingType(): Type 39 | { 40 | return new String_(); 41 | } 42 | 43 | public function __toString(): string 44 | { 45 | return sprintf('"%s"', $this->value); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/PseudoTypes/CallableArray.php: -------------------------------------------------------------------------------- 1 | type = $type; 33 | } 34 | 35 | public function getType(): Type 36 | { 37 | return $this->type; 38 | } 39 | 40 | public function underlyingType(): Type 41 | { 42 | return new Mixed_(); 43 | } 44 | 45 | public function __toString(): string 46 | { 47 | return 'value-of<' . $this->type . '>'; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Types/Compound.php: -------------------------------------------------------------------------------- 1 | $types 33 | */ 34 | public function __construct(array $types) 35 | { 36 | parent::__construct($types, '|'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/PseudoTypes/IntMaskOf.php: -------------------------------------------------------------------------------- 1 | type = $type; 33 | } 34 | 35 | public function getType(): Type 36 | { 37 | return $this->type; 38 | } 39 | 40 | public function underlyingType(): Type 41 | { 42 | return new Integer(); 43 | } 44 | 45 | public function __toString(): string 46 | { 47 | return 'int-mask-of<' . $this->type . '>'; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Types/Intersection.php: -------------------------------------------------------------------------------- 1 | $types 32 | */ 33 | public function __construct(array $types) 34 | { 35 | parent::__construct($types, '&'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/PseudoTypes/ArrayKey.php: -------------------------------------------------------------------------------- 1 | types = $types; 35 | } 36 | 37 | /** 38 | * @return Type[] 39 | */ 40 | public function getTypes(): array 41 | { 42 | return $this->types; 43 | } 44 | 45 | public function underlyingType(): Type 46 | { 47 | return new Integer(); 48 | } 49 | 50 | public function __toString(): string 51 | { 52 | return 'int-mask<' . implode(', ', $this->types) . '>'; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Types/Expression.php: -------------------------------------------------------------------------------- 1 | valueType = $valueType; 34 | } 35 | 36 | /** 37 | * Returns the value for the keys of this array. 38 | */ 39 | public function getValueType(): Type 40 | { 41 | return $this->valueType; 42 | } 43 | 44 | /** 45 | * Returns a rendered output of the Type as it would be used in a DocBlock. 46 | */ 47 | public function __toString(): string 48 | { 49 | return '(' . $this->valueType . ')'; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/PseudoTypes/List_.php: -------------------------------------------------------------------------------- 1 | valueType === null) { 44 | return 'list'; 45 | } 46 | 47 | return 'list<' . $this->valueType . '>'; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Types/Nullable.php: -------------------------------------------------------------------------------- 1 | realType = $realType; 34 | } 35 | 36 | /** 37 | * Provide access to the actual type directly, if needed. 38 | */ 39 | public function getActualType(): Type 40 | { 41 | return $this->realType; 42 | } 43 | 44 | /** 45 | * Returns a rendered output of the Type as it would be used in a DocBlock. 46 | */ 47 | public function __toString(): string 48 | { 49 | return '?' . $this->realType->__toString(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/PseudoTypes/NonEmptyArray.php: -------------------------------------------------------------------------------- 1 | valueType, $this->keyType); 30 | } 31 | 32 | /** 33 | * Returns a rendered output of the Type as it would be used in a DocBlock. 34 | */ 35 | public function __toString(): string 36 | { 37 | if ($this->valueType === null) { 38 | return 'non-empty-array'; 39 | } 40 | 41 | if ($this->keyType) { 42 | return 'non-empty-array<' . $this->keyType . ', ' . $this->valueType . '>'; 43 | } 44 | 45 | return 'non-empty-array<' . $this->valueType . '>'; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/PseudoTypes/Generic.php: -------------------------------------------------------------------------------- 1 | types = $types; 40 | } 41 | 42 | /** 43 | * @return Type[] 44 | */ 45 | public function getTypes(): array 46 | { 47 | return $this->types; 48 | } 49 | 50 | public function __toString(): string 51 | { 52 | $objectType = (string) ($this->fqsen ?? 'object'); 53 | 54 | return $objectType . '<' . implode(', ', $this->types) . '>'; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /docs/getting-started.rst: -------------------------------------------------------------------------------- 1 | =============== 2 | Getting started 3 | =============== 4 | 5 | On this page you will find a brief introduction on how to use the TypeResolver in your project. 6 | 7 | Installation 8 | ============ 9 | 10 | The TypeResolver is available on Packagist and can be installed using Composer: 11 | 12 | .. code:: bash 13 | composer require phpdocumentor/type-resolver 14 | 15 | 16 | General usage 17 | =========== 18 | 19 | After you installed the TypeResolver you can use it in your project. This can be done by creating a new instance 20 | of the :php:class:`\phpDocumentor\Reflection\TypeResolver` class and calling 21 | :php:method:`\phpDocumentor\Reflection\TypeResolver::resolve()` with the type you want to resolve. 22 | 23 | .. code:: php 24 | $typeResolver = new \phpDocumentor\Reflection\TypeResolver(); 25 | $type = $typeResolver->resolve('string'); 26 | echo get_class($type); // phpDocumentor\Reflection\Types\String_ 27 | 28 | The real power of this resolver is in its capability to expand partial class names into fully qualified class names; 29 | but in order to do that we need an additional :php:class:`\phpDocumentor\Reflection\Types\Context` class that 30 | will inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply. 31 | 32 | Read more about the Context class in the next section. 33 | -------------------------------------------------------------------------------- /src/PseudoTypes/NonEmptyList.php: -------------------------------------------------------------------------------- 1 | valueType, $this->keyType); 31 | } 32 | 33 | public function __construct(?Type $valueType = null) 34 | { 35 | parent::__construct($valueType, new Integer()); 36 | } 37 | 38 | /** 39 | * Returns a rendered output of the Type as it would be used in a DocBlock. 40 | */ 41 | public function __toString(): string 42 | { 43 | if ($this->valueType === null) { 44 | return 'non-empty-list'; 45 | } 46 | 47 | return 'non-empty-list<' . $this->valueType . '>'; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/PseudoTypes/PropertiesOf.php: -------------------------------------------------------------------------------- 1 | type = $type; 37 | } 38 | 39 | public function getType(): Type 40 | { 41 | return $this->type; 42 | } 43 | 44 | public function underlyingType(): Type 45 | { 46 | return new Array_(new Mixed_(), new String_()); 47 | } 48 | 49 | public function __toString(): string 50 | { 51 | return 'properties-of<' . $this->type . '>'; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/PseudoTypes/ArrayShape.php: -------------------------------------------------------------------------------- 1 | items = $items; 34 | } 35 | 36 | /** 37 | * @return ArrayShapeItem[] 38 | */ 39 | public function getItems(): array 40 | { 41 | return $this->items; 42 | } 43 | 44 | public function underlyingType(): Type 45 | { 46 | return new Array_(new Mixed_(), new ArrayKey()); 47 | } 48 | 49 | public function __toString(): string 50 | { 51 | return 'array{' . implode(', ', $this->items) . '}'; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/PseudoTypes/ShapeItem.php: -------------------------------------------------------------------------------- 1 | key = $key; 24 | $this->value = $value ?? new Mixed_(); 25 | $this->optional = $optional; 26 | } 27 | 28 | public function getKey(): ?string 29 | { 30 | return $this->key; 31 | } 32 | 33 | public function getValue(): Type 34 | { 35 | return $this->value; 36 | } 37 | 38 | public function isOptional(): bool 39 | { 40 | return $this->optional; 41 | } 42 | 43 | public function __toString(): string 44 | { 45 | if ($this->key !== null && $this->key !== '') { 46 | return sprintf( 47 | '%s%s: %s', 48 | $this->key, 49 | $this->optional ? '?' : '', 50 | (string) $this->value 51 | ); 52 | } 53 | 54 | return (string) $this->value; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Types/Self_.php: -------------------------------------------------------------------------------- 1 | genericTypes = $genericTypes; 35 | } 36 | 37 | /** 38 | * @return Type[] 39 | */ 40 | public function getGenericTypes(): array 41 | { 42 | return $this->genericTypes; 43 | } 44 | 45 | /** 46 | * Returns a rendered output of the Type as it would be used in a DocBlock. 47 | */ 48 | public function __toString(): string 49 | { 50 | if ($this->genericTypes) { 51 | return 'self<' . implode(', ', $this->genericTypes) . '>'; 52 | } 53 | 54 | return 'self'; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/PseudoTypes/ConstExpression.php: -------------------------------------------------------------------------------- 1 | owner = $owner; 33 | $this->expression = $expression; 34 | } 35 | 36 | public function getOwner(): Type 37 | { 38 | return $this->owner; 39 | } 40 | 41 | public function getExpression(): string 42 | { 43 | return $this->expression; 44 | } 45 | 46 | public function underlyingType(): Type 47 | { 48 | return new Mixed_(); 49 | } 50 | 51 | public function __toString(): string 52 | { 53 | return sprintf('%s::%s', (string) $this->owner, $this->expression); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/PseudoTypes/Numeric_.php: -------------------------------------------------------------------------------- 1 | genericType = $genericType; 33 | } 34 | 35 | public function underlyingType(): Type 36 | { 37 | return new String_(); 38 | } 39 | 40 | public function getGenericType(): ?Type 41 | { 42 | return $this->genericType; 43 | } 44 | 45 | /** 46 | * Returns a rendered output of the Type as it would be used in a DocBlock. 47 | */ 48 | public function __toString(): string 49 | { 50 | if ($this->genericType === null) { 51 | return 'enum-string'; 52 | } 53 | 54 | return 'enum-string<' . (string) $this->genericType . '>'; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/PseudoTypes/ClassString.php: -------------------------------------------------------------------------------- 1 | genericType = $genericType; 33 | } 34 | 35 | public function underlyingType(): Type 36 | { 37 | return new String_(); 38 | } 39 | 40 | public function getGenericType(): ?Type 41 | { 42 | return $this->genericType; 43 | } 44 | 45 | /** 46 | * Returns a rendered output of the Type as it would be used in a DocBlock. 47 | */ 48 | public function __toString(): string 49 | { 50 | if ($this->genericType === null) { 51 | return 'class-string'; 52 | } 53 | 54 | return 'class-string<' . (string) $this->genericType . '>'; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/PseudoTypes/TraitString.php: -------------------------------------------------------------------------------- 1 | genericType = $genericType; 33 | } 34 | 35 | public function underlyingType(): Type 36 | { 37 | return new String_(); 38 | } 39 | 40 | public function getGenericType(): ?Type 41 | { 42 | return $this->genericType; 43 | } 44 | 45 | /** 46 | * Returns a rendered output of the Type as it would be used in a DocBlock. 47 | */ 48 | public function __toString(): string 49 | { 50 | if ($this->genericType === null) { 51 | return 'trait-string'; 52 | } 53 | 54 | return 'trait-string<' . (string) $this->genericType . '>'; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/PseudoTypes/InterfaceString.php: -------------------------------------------------------------------------------- 1 | genericType = $genericType; 33 | } 34 | 35 | public function underlyingType(): Type 36 | { 37 | return new String_(); 38 | } 39 | 40 | public function getGenericType(): ?Type 41 | { 42 | return $this->genericType; 43 | } 44 | 45 | /** 46 | * Returns a rendered output of the Type as it would be used in a DocBlock. 47 | */ 48 | public function __toString(): string 49 | { 50 | if ($this->genericType === null) { 51 | return 'interface-string'; 52 | } 53 | 54 | return 'interface-string<' . (string) $this->genericType . '>'; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phpdocumentor/type-resolver", 3 | "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", 4 | "type": "library", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Mike van Riel", 9 | "email": "me@mikevanriel.com" 10 | } 11 | ], 12 | "require": { 13 | "php": "^7.4 || ^8.0", 14 | "phpdocumentor/reflection-common": "^2.0", 15 | "phpstan/phpdoc-parser": "^2.0", 16 | "doctrine/deprecations": "^1.0" 17 | }, 18 | "require-dev": { 19 | "ext-tokenizer": "*", 20 | "phpunit/phpunit": "^9.5", 21 | "phpstan/phpstan": "^2.1", 22 | "phpstan/phpstan-phpunit": "^2.0", 23 | "phpstan/extension-installer": "^1.4", 24 | "phpbench/phpbench": "^1.2", 25 | "psalm/phar": "^4" 26 | }, 27 | "autoload": { 28 | "psr-4": { 29 | "phpDocumentor\\Reflection\\": "src" 30 | } 31 | }, 32 | "autoload-dev": { 33 | "psr-4": { 34 | "phpDocumentor\\Reflection\\": ["tests/unit", "tests/benchmark"] 35 | } 36 | }, 37 | "extra": { 38 | "branch-alias": { 39 | "dev-1.x": "1.x-dev", 40 | "dev-2.x": "2.x-dev" 41 | } 42 | }, 43 | "config": { 44 | "platform": { 45 | "php": "7.4.0" 46 | }, 47 | "allow-plugins": { 48 | "phpstan/extension-installer": true 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/PseudoTypes/IntegerRange.php: -------------------------------------------------------------------------------- 1 | minValue = $minValue; 36 | $this->maxValue = $maxValue; 37 | } 38 | 39 | public function underlyingType(): Type 40 | { 41 | return new Integer(); 42 | } 43 | 44 | public function getMinValue(): string 45 | { 46 | return $this->minValue; 47 | } 48 | 49 | public function getMaxValue(): string 50 | { 51 | return $this->maxValue; 52 | } 53 | 54 | /** 55 | * Returns a rendered output of the Type as it would be used in a DocBlock. 56 | */ 57 | public function __toString(): string 58 | { 59 | return 'int<' . $this->minValue . ', ' . $this->maxValue . '>'; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /phpdoc.dist.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | Type Resolver 9 | 10 | build/docs 11 | 12 | 13 | latest 14 | 15 | 16 | src/ 17 | 18 | api 19 | 25 | 26 | php 27 | 28 | 29 | template 30 | template-extends 31 | template-implements 32 | extends 33 | implements 34 | 35 | phpDocumentor 36 | 37 | 38 | 39 | docs 40 | 41 | guides 42 | 43 | 44 | 45 |