1Name resolution 2=============== 3 4Since the introduction of namespaces in PHP 5.3, literal names in PHP code are subject to a 5relatively complex name resolution process, which is based on the current namespace, the current 6import table state, as well the type of the referenced symbol. PHP-Parser implements name 7resolution and related functionality, both as reusable logic (NameContext), as well as a node 8visitor (NameResolver) based on it. 9 10The NameResolver visitor 11------------------------ 12 13The `NameResolver` visitor can (and for nearly all uses of the AST, should) be applied to resolve names 14to their fully-qualified form, to the degree that this is possible. 15 16```php 17$nameResolver = new PhpParser\NodeVisitor\NameResolver; 18$nodeTraverser = new PhpParser\NodeTraverser; 19$nodeTraverser->addVisitor($nameResolver); 20 21// Resolve names 22$stmts = $nodeTraverser->traverse($stmts); 23``` 24 25In the default configuration, the name resolver will perform three actions: 26 27 * Declarations of functions, classes, interfaces, traits, enums and global constants will have a 28 `namespacedName` property added, which contains the function/class/etc name including the 29 namespace prefix. For historic reasons this is a **property** rather than an attribute. 30 * Names will be replaced by fully qualified resolved names, which are instances of 31 `Node\Name\FullyQualified`. 32 * Unqualified function and constant names inside a namespace cannot be statically resolved. Inside 33 a namespace `Foo`, a call to `strlen()` may either refer to the namespaced `\Foo\strlen()`, or 34 the global `\strlen()`. Because PHP-Parser does not have the necessary context to decide this, 35 such names are left unresolved. Additionally, a `namespacedName` **attribute** is added to the 36 name node. 37 38The name resolver accepts an option array as the second argument, with the following default values: 39 40```php 41$nameResolver = new PhpParser\NodeVisitor\NameResolver(null, [ 42 'preserveOriginalNames' => false, 43 'replaceNodes' => true, 44]); 45``` 46 47If the `preserveOriginalNames` option is enabled, then the resolved (fully qualified) name will have 48an `originalName` attribute, which contains the unresolved name. 49 50If the `replaceNodes` option is disabled, then names will no longer be resolved in-place. Instead, a 51`resolvedName` attribute will be added to each name, which contains the resolved (fully qualified) 52name. Once again, if an unqualified function or constant name cannot be resolved, then the 53`resolvedName` attribute will not be present, and instead a `namespacedName` attribute is added. 54 55The `replaceNodes` attribute is useful if you wish to perform modifications on the AST, as you 56probably do not wish the resulting code to have fully resolved names as a side-effect. 57 58The NameContext 59--------------- 60 61The actual name resolution logic is implemented in the `NameContext` class, which has the following 62public API: 63 64```php 65class NameContext { 66 public function __construct(ErrorHandler $errorHandler); 67 public function startNamespace(Name $namespace = null); 68 public function addAlias(Name $name, string $aliasName, int $type, array $errorAttrs = []); 69 70 public function getNamespace(); 71 public function getResolvedName(Name $name, int $type); 72 public function getResolvedClassName(Name $name) : Name; 73 public function getPossibleNames(string $name, int $type) : array; 74 public function getShortName(string $name, int $type) : Name; 75} 76``` 77 78The `$type` parameters accept one of the `Stmt\Use_::TYPE_*` constants, which represent the three 79basic symbol types in PHP (functions, constants and everything else). 80 81Next to name resolution, the `NameContext` also supports the reverse operation of finding a short 82representation of a name given the current name resolution environment. 83 84The name context is intended to be used for name resolution operations outside the AST itself, such 85as class names inside doc comments. A visitor running in parallel with the name resolver can access 86the name context using `$nameResolver->getNameContext()`. Alternatively a visitor can use an 87independent context and explicitly feed `Namespace` and `Use` nodes to it. 88