annotate vendor/nikic/php-parser/doc/component/Name_resolution.markdown @ 19:fa3358dc1485 tip

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