Mercurial > hg > cmmr2012-drupal-site
comparison vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php @ 0:c75dbcec494b
Initial commit from drush-created site
author | Chris Cannam |
---|---|
date | Thu, 05 Jul 2018 14:24:15 +0000 |
parents | |
children | a9cd425dd02b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c75dbcec494b |
---|---|
1 <?php declare(strict_types=1); | |
2 | |
3 namespace PhpParser\NodeVisitor; | |
4 | |
5 use PhpParser\Error; | |
6 use PhpParser\ErrorHandler; | |
7 use PhpParser\NameContext; | |
8 use PhpParser\Node; | |
9 use PhpParser\Node\Expr; | |
10 use PhpParser\Node\Name; | |
11 use PhpParser\Node\Name\FullyQualified; | |
12 use PhpParser\Node\Stmt; | |
13 use PhpParser\NodeVisitorAbstract; | |
14 | |
15 class NameResolver extends NodeVisitorAbstract | |
16 { | |
17 /** @var NameContext Naming context */ | |
18 protected $nameContext; | |
19 | |
20 /** @var bool Whether to preserve original names */ | |
21 protected $preserveOriginalNames; | |
22 | |
23 /** @var bool Whether to replace resolved nodes in place, or to add resolvedNode attributes */ | |
24 protected $replaceNodes; | |
25 | |
26 /** | |
27 * Constructs a name resolution visitor. | |
28 * | |
29 * Options: | |
30 * * preserveOriginalNames (default false): An "originalName" attribute will be added to | |
31 * all name nodes that underwent resolution. | |
32 * * replaceNodes (default true): Resolved names are replaced in-place. Otherwise, a | |
33 * resolvedName attribute is added. (Names that cannot be statically resolved receive a | |
34 * namespacedName attribute, as usual.) | |
35 * | |
36 * @param ErrorHandler|null $errorHandler Error handler | |
37 * @param array $options Options | |
38 */ | |
39 public function __construct(ErrorHandler $errorHandler = null, array $options = []) { | |
40 $this->nameContext = new NameContext($errorHandler ?? new ErrorHandler\Throwing); | |
41 $this->preserveOriginalNames = $options['preserveOriginalNames'] ?? false; | |
42 $this->replaceNodes = $options['replaceNodes'] ?? true; | |
43 } | |
44 | |
45 /** | |
46 * Get name resolution context. | |
47 * | |
48 * @return NameContext | |
49 */ | |
50 public function getNameContext() : NameContext { | |
51 return $this->nameContext; | |
52 } | |
53 | |
54 public function beforeTraverse(array $nodes) { | |
55 $this->nameContext->startNamespace(); | |
56 return null; | |
57 } | |
58 | |
59 public function enterNode(Node $node) { | |
60 if ($node instanceof Stmt\Namespace_) { | |
61 $this->nameContext->startNamespace($node->name); | |
62 } elseif ($node instanceof Stmt\Use_) { | |
63 foreach ($node->uses as $use) { | |
64 $this->addAlias($use, $node->type, null); | |
65 } | |
66 } elseif ($node instanceof Stmt\GroupUse) { | |
67 foreach ($node->uses as $use) { | |
68 $this->addAlias($use, $node->type, $node->prefix); | |
69 } | |
70 } elseif ($node instanceof Stmt\Class_) { | |
71 if (null !== $node->extends) { | |
72 $node->extends = $this->resolveClassName($node->extends); | |
73 } | |
74 | |
75 foreach ($node->implements as &$interface) { | |
76 $interface = $this->resolveClassName($interface); | |
77 } | |
78 | |
79 if (null !== $node->name) { | |
80 $this->addNamespacedName($node); | |
81 } | |
82 } elseif ($node instanceof Stmt\Interface_) { | |
83 foreach ($node->extends as &$interface) { | |
84 $interface = $this->resolveClassName($interface); | |
85 } | |
86 | |
87 $this->addNamespacedName($node); | |
88 } elseif ($node instanceof Stmt\Trait_) { | |
89 $this->addNamespacedName($node); | |
90 } elseif ($node instanceof Stmt\Function_) { | |
91 $this->addNamespacedName($node); | |
92 $this->resolveSignature($node); | |
93 } elseif ($node instanceof Stmt\ClassMethod | |
94 || $node instanceof Expr\Closure | |
95 ) { | |
96 $this->resolveSignature($node); | |
97 } elseif ($node instanceof Stmt\Const_) { | |
98 foreach ($node->consts as $const) { | |
99 $this->addNamespacedName($const); | |
100 } | |
101 } elseif ($node instanceof Expr\StaticCall | |
102 || $node instanceof Expr\StaticPropertyFetch | |
103 || $node instanceof Expr\ClassConstFetch | |
104 || $node instanceof Expr\New_ | |
105 || $node instanceof Expr\Instanceof_ | |
106 ) { | |
107 if ($node->class instanceof Name) { | |
108 $node->class = $this->resolveClassName($node->class); | |
109 } | |
110 } elseif ($node instanceof Stmt\Catch_) { | |
111 foreach ($node->types as &$type) { | |
112 $type = $this->resolveClassName($type); | |
113 } | |
114 } elseif ($node instanceof Expr\FuncCall) { | |
115 if ($node->name instanceof Name) { | |
116 $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_FUNCTION); | |
117 } | |
118 } elseif ($node instanceof Expr\ConstFetch) { | |
119 $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_CONSTANT); | |
120 } elseif ($node instanceof Stmt\TraitUse) { | |
121 foreach ($node->traits as &$trait) { | |
122 $trait = $this->resolveClassName($trait); | |
123 } | |
124 | |
125 foreach ($node->adaptations as $adaptation) { | |
126 if (null !== $adaptation->trait) { | |
127 $adaptation->trait = $this->resolveClassName($adaptation->trait); | |
128 } | |
129 | |
130 if ($adaptation instanceof Stmt\TraitUseAdaptation\Precedence) { | |
131 foreach ($adaptation->insteadof as &$insteadof) { | |
132 $insteadof = $this->resolveClassName($insteadof); | |
133 } | |
134 } | |
135 } | |
136 } | |
137 | |
138 return null; | |
139 } | |
140 | |
141 private function addAlias(Stmt\UseUse $use, $type, Name $prefix = null) { | |
142 // Add prefix for group uses | |
143 $name = $prefix ? Name::concat($prefix, $use->name) : $use->name; | |
144 // Type is determined either by individual element or whole use declaration | |
145 $type |= $use->type; | |
146 | |
147 $this->nameContext->addAlias( | |
148 $name, (string) $use->getAlias(), $type, $use->getAttributes() | |
149 ); | |
150 } | |
151 | |
152 /** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */ | |
153 private function resolveSignature($node) { | |
154 foreach ($node->params as $param) { | |
155 $param->type = $this->resolveType($param->type); | |
156 } | |
157 $node->returnType = $this->resolveType($node->returnType); | |
158 } | |
159 | |
160 private function resolveType($node) { | |
161 if ($node instanceof Node\NullableType) { | |
162 $node->type = $this->resolveType($node->type); | |
163 return $node; | |
164 } | |
165 if ($node instanceof Name) { | |
166 return $this->resolveClassName($node); | |
167 } | |
168 return $node; | |
169 } | |
170 | |
171 /** | |
172 * Resolve name, according to name resolver options. | |
173 * | |
174 * @param Name $name Function or constant name to resolve | |
175 * @param int $type One of Stmt\Use_::TYPE_* | |
176 * | |
177 * @return Name Resolved name, or original name with attribute | |
178 */ | |
179 protected function resolveName(Name $name, int $type) : Name { | |
180 if (!$this->replaceNodes) { | |
181 $resolvedName = $this->nameContext->getResolvedName($name, $type); | |
182 if (null !== $resolvedName) { | |
183 $name->setAttribute('resolvedName', $resolvedName); | |
184 } else { | |
185 $name->setAttribute('namespacedName', FullyQualified::concat( | |
186 $this->nameContext->getNamespace(), $name, $name->getAttributes())); | |
187 } | |
188 return $name; | |
189 } | |
190 | |
191 if ($this->preserveOriginalNames) { | |
192 // Save the original name | |
193 $originalName = $name; | |
194 $name = clone $originalName; | |
195 $name->setAttribute('originalName', $originalName); | |
196 } | |
197 | |
198 $resolvedName = $this->nameContext->getResolvedName($name, $type); | |
199 if (null !== $resolvedName) { | |
200 return $resolvedName; | |
201 } | |
202 | |
203 // unqualified names inside a namespace cannot be resolved at compile-time | |
204 // add the namespaced version of the name as an attribute | |
205 $name->setAttribute('namespacedName', FullyQualified::concat( | |
206 $this->nameContext->getNamespace(), $name, $name->getAttributes())); | |
207 return $name; | |
208 } | |
209 | |
210 protected function resolveClassName(Name $name) { | |
211 return $this->resolveName($name, Stmt\Use_::TYPE_NORMAL); | |
212 } | |
213 | |
214 protected function addNamespacedName(Node $node) { | |
215 $node->namespacedName = Name::concat( | |
216 $this->nameContext->getNamespace(), (string) $node->name); | |
217 } | |
218 } |