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