1TypeResolver and FqsenResolver 2============================== 3 4The specification on types in DocBlocks (PSR-5) describes various keywords and special constructs 5but also how to statically resolve the partial name of a Class into a Fully Qualified Class Name (FQCN). 6 7PSR-5 also introduces an additional way to describe deeper elements than Classes, Interfaces and Traits 8called the Fully Qualified Structural Element Name (FQSEN). Using this it is possible to refer to methods, 9properties and class constants but also functions and global constants. 10 11This package provides two Resolvers that are capable of 12 131. Returning a series of Value Object for given expression while resolving any partial class names, and 142. Returning an FQSEN object after resolving any partial Structural Element Names into Fully Qualified Structural 15 Element names. 16 17## Installing 18 19The easiest way to install this library is with [Composer](https://getcomposer.org) using the following command: 20 21 $ composer require phpdocumentor/type-resolver 22 23## Examples 24 25Ready to dive in and don't want to read through all that text below? Just consult the [examples](examples) folder and 26check which type of action that your want to accomplish. 27 28## On Types and Element Names 29 30This component can be used in one of two ways 31 321. To resolve a Type or 332. To resolve a Fully Qualified Structural Element Name 34 35The big difference between these two is in the number of things it can resolve. 36 37The TypeResolver can resolve: 38 39- a php primitive or pseudo-primitive such as a string or void (`@var string` or `@return void`). 40- a composite such as an array of string (`@var string[]`). 41- a compound such as a string or integer (`@var string|integer`). 42- an object or interface such as the TypeResolver class (`@var TypeResolver` 43 or `@var \phpDocumentor\Reflection\TypeResolver`) 44 45 > please note that if you want to pass partial class names that additional steps are necessary, see the 46 > chapter `Resolving partial classes and FQSENs` for more information. 47 48Where the FqsenResolver can resolve: 49 50- Constant expressions (i.e. `@see \MyNamespace\MY_CONSTANT`) 51- Function expressions (i.e. `@see \MyNamespace\myFunction()`) 52- Class expressions (i.e. `@see \MyNamespace\MyClass`) 53- Interface expressions (i.e. `@see \MyNamespace\MyInterface`) 54- Trait expressions (i.e. `@see \MyNamespace\MyTrait`) 55- Class constant expressions (i.e. `@see \MyNamespace\MyClass::MY_CONSTANT`) 56- Property expressions (i.e. `@see \MyNamespace\MyClass::$myProperty`) 57- Method expressions (i.e. `@see \MyNamespace\MyClass::myMethod()`) 58 59## Resolving a type 60 61In order to resolve a type you will have to instantiate the class `\phpDocumentor\Reflection\TypeResolver` 62and call its `resolve` method like this: 63 64```php 65$typeResolver = new \phpDocumentor\Reflection\TypeResolver(); 66$type = $typeResolver->resolve('string|integer'); 67``` 68 69In this example you will receive a Value Object of class `\phpDocumentor\Reflection\Types\Compound` that has two 70elements, one of type `\phpDocumentor\Reflection\Types\String_` and one of type 71`\phpDocumentor\Reflection\Types\Integer`. 72 73The real power of this resolver is in its capability to expand partial class names into fully qualified class names; but 74in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will inform the resolver 75in which namespace the given expression occurs and which namespace aliases (or imports) apply. 76 77## Resolving an FQSEN 78 79A Fully Qualified Structural Element Name is a reference to another element in your code bases and can be resolved using 80the `\phpDocumentor\Reflection\FqsenResolver` class' `resolve` method, like this: 81 82```php 83$fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver(); 84$fqsen = $fqsenResolver->resolve('\phpDocumentor\Reflection\FqsenResolver::resolve()'); 85``` 86 87In this example we resolve a Fully Qualified Structural Element Name (meaning that it includes the full namespace, class 88name and element name) and receive a Value Object of type `\phpDocumentor\Reflection\Fqsen`. 89 90The real power of this resolver is in its capability to expand partial element names into Fully Qualified Structural 91Element Names; but in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will 92inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply. 93 94## Resolving partial Classes and Structural Element Names 95 96Perhaps the best feature of this library is that it knows how to resolve partial class names into fully qualified class 97names. 98 99For example, you have this file: 100 101```php 102namespace My\Example; 103 104use phpDocumentor\Reflection\Types; 105 106class Classy 107{ 108 /** 109 * @var Types\Context 110 * @see Classy::otherFunction() 111 */ 112 public function __construct($context) {} 113 114 public function otherFunction(){} 115} 116``` 117 118Suppose that you would want to resolve (and expand) the type in the `@var` tag and the element name in the `@see` tag. 119For the resolvers to know how to expand partial names you have to provide a bit of _Context_ for them by instantiating 120a new class named `\phpDocumentor\Reflection\Types\Context` with the name of the namespace and the aliases that are in 121play. 122 123### Creating a Context 124 125You can do this by manually creating a Context like this: 126 127```php 128$context = new \phpDocumentor\Reflection\Types\Context( 129 '\My\Example', 130 [ 'Types' => '\phpDocumentor\Reflection\Types'] 131); 132``` 133 134Or by using the `\phpDocumentor\Reflection\Types\ContextFactory` to instantiate a new context based on a Reflector 135object or by providing the namespace that you'd like to extract and the source code of the file in which the given 136type expression occurs. 137 138```php 139$contextFactory = new \phpDocumentor\Reflection\Types\ContextFactory(); 140$context = $contextFactory->createFromReflector(new ReflectionMethod('\My\Example\Classy', '__construct')); 141``` 142 143or 144 145```php 146$contextFactory = new \phpDocumentor\Reflection\Types\ContextFactory(); 147$context = $contextFactory->createForNamespace('\My\Example', file_get_contents('My/Example/Classy.php')); 148``` 149 150### Using the Context 151 152After you have obtained a Context it is just a matter of passing it along with the `resolve` method of either Resolver 153class as second argument and the Resolvers will take this into account when resolving partial names. 154 155To obtain the resolved class name for the `@var` tag in the example above you can do: 156 157```php 158$typeResolver = new \phpDocumentor\Reflection\TypeResolver(); 159$type = $typeResolver->resolve('Types\Context', $context); 160``` 161 162When you do this you will receive an object of class `\phpDocumentor\Reflection\Types\Object_` for which you can call 163the `getFqsen` method to receive a Value Object that represents the complete FQSEN. So that would be 164`phpDocumentor\Reflection\Types\Context`. 165 166> Why is the FQSEN wrapped in another object `Object_`? 167> 168> The resolve method of the TypeResolver only returns object with the interface `Type` and the FQSEN is a common 169> type that does not represent a Type. Also: in some cases a type can represent an "Untyped Object", meaning that it 170> is an object (signified by the `object` keyword) but does not refer to a specific element using an FQSEN. 171 172Another example is on how to resolve the FQSEN of a method as can be seen with the `@see` tag in the example above. To 173resolve that you can do the following: 174 175```php 176$fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver(); 177$type = $fqsenResolver->resolve('Classy::otherFunction()', $context); 178``` 179 180Because Classy is a Class in the current namespace its FQSEN will have the `My\Example` namespace and by calling the 181`resolve` method of the FQSEN Resolver you will receive an `Fqsen` object that refers to 182`\My\Example\Classy::otherFunction()`. 183