PluginProbe
WPIDE – File Manager & Code Editor / 3.5.9
WPIDE – File Manager & Code Editor v3.5.9
3.5.9 3.5.8 3.5.7 2.0.14 2.0.15 2.0.16 2.0.2 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1 2.2 2.3 2.3.1 2.3.2 2.4.0 2.5 2.6 3.0 3.1 3.2 3.3 All 55 releases
wpide / vendor / nikic / php-parser / lib / PhpParser / NodeVisitor / NameResolver.php

NameResolver.php in WPIDE – File Manager & Code Editor 3.5.9, at vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php

261 lines 9.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php declare(strict_types=1);
2
3 namespace PhpParser\NodeVisitor;
4
5 use PhpParser\ErrorHandler;
6 use PhpParser\NameContext;
7 use PhpParser\Node;
8 use PhpParser\Node\Expr;
9 use PhpParser\Node\Name;
10 use PhpParser\Node\Name\FullyQualified;
11 use PhpParser\Node\Stmt;
12 use PhpParser\NodeVisitorAbstract;
13
14 class NameResolver extends NodeVisitorAbstract
15 {
16 /** @var NameContext Naming context */
17 protected $nameContext;
18
19 /** @var bool Whether to preserve original names */
20 protected $preserveOriginalNames;
21
22 /** @var bool Whether to replace resolved nodes in place, or to add resolvedNode attributes */
23 protected $replaceNodes;
24
25 /**
26 * Constructs a name resolution visitor.
27 *
28 * Options:
29 * * preserveOriginalNames (default false): An "originalName" attribute will be added to
30 * all name nodes that underwent resolution.
31 * * replaceNodes (default true): Resolved names are replaced in-place. Otherwise, a
32 * resolvedName attribute is added. (Names that cannot be statically resolved receive a
33 * namespacedName attribute, as usual.)
34 *
35 * @param ErrorHandler|null $errorHandler Error handler
36 * @param array $options Options
37 */
38 public function __construct(?ErrorHandler $errorHandler = null, array $options = []) {
39 $this->nameContext = new NameContext($errorHandler ?? new ErrorHandler\Throwing);
40 $this->preserveOriginalNames = $options['preserveOriginalNames'] ?? false;
41 $this->replaceNodes = $options['replaceNodes'] ?? true;
42 }
43
44 /**
45 * Get name resolution context.
46 *
47 * @return NameContext
48 */
49 public function getNameContext() : NameContext {
50 return $this->nameContext;
51 }
52
53 public function beforeTraverse(array $nodes) {
54 $this->nameContext->startNamespace();
55 return null;
56 }
57
58 public function enterNode(Node $node) {
59 if ($node instanceof Stmt\Namespace_) {
60 $this->nameContext->startNamespace($node->name);
61 } elseif ($node instanceof Stmt\Use_) {
62 foreach ($node->uses as $use) {
63 $this->addAlias($use, $node->type, null);
64 }
65 } elseif ($node instanceof Stmt\GroupUse) {
66 foreach ($node->uses as $use) {
67 $this->addAlias($use, $node->type, $node->prefix);
68 }
69 } elseif ($node instanceof Stmt\Class_) {
70 if (null !== $node->extends) {
71 $node->extends = $this->resolveClassName($node->extends);
72 }
73
74 foreach ($node->implements as &$interface) {
75 $interface = $this->resolveClassName($interface);
76 }
77
78 $this->resolveAttrGroups($node);
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->resolveAttrGroups($node);
88 $this->addNamespacedName($node);
89 } elseif ($node instanceof Stmt\Enum_) {
90 foreach ($node->implements as &$interface) {
91 $interface = $this->resolveClassName($interface);
92 }
93
94 $this->resolveAttrGroups($node);
95 if (null !== $node->name) {
96 $this->addNamespacedName($node);
97 }
98 } elseif ($node instanceof Stmt\Trait_) {
99 $this->resolveAttrGroups($node);
100 $this->addNamespacedName($node);
101 } elseif ($node instanceof Stmt\Function_) {
102 $this->resolveSignature($node);
103 $this->resolveAttrGroups($node);
104 $this->addNamespacedName($node);
105 } elseif ($node instanceof Stmt\ClassMethod
106 || $node instanceof Expr\Closure
107 || $node instanceof Expr\ArrowFunction
108 ) {
109 $this->resolveSignature($node);
110 $this->resolveAttrGroups($node);
111 } elseif ($node instanceof Stmt\Property) {
112 if (null !== $node->type) {
113 $node->type = $this->resolveType($node->type);
114 }
115 $this->resolveAttrGroups($node);
116 } elseif ($node instanceof Stmt\Const_) {
117 foreach ($node->consts as $const) {
118 $this->addNamespacedName($const);
119 }
120 } else if ($node instanceof Stmt\ClassConst) {
121 if (null !== $node->type) {
122 $node->type = $this->resolveType($node->type);
123 }
124 $this->resolveAttrGroups($node);
125 } else if ($node instanceof Stmt\EnumCase) {
126 $this->resolveAttrGroups($node);
127 } elseif ($node instanceof Expr\StaticCall
128 || $node instanceof Expr\StaticPropertyFetch
129 || $node instanceof Expr\ClassConstFetch
130 || $node instanceof Expr\New_
131 || $node instanceof Expr\Instanceof_
132 ) {
133 if ($node->class instanceof Name) {
134 $node->class = $this->resolveClassName($node->class);
135 }
136 } elseif ($node instanceof Stmt\Catch_) {
137 foreach ($node->types as &$type) {
138 $type = $this->resolveClassName($type);
139 }
140 } elseif ($node instanceof Expr\FuncCall) {
141 if ($node->name instanceof Name) {
142 $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_FUNCTION);
143 }
144 } elseif ($node instanceof Expr\ConstFetch) {
145 $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_CONSTANT);
146 } elseif ($node instanceof Stmt\TraitUse) {
147 foreach ($node->traits as &$trait) {
148 $trait = $this->resolveClassName($trait);
149 }
150
151 foreach ($node->adaptations as $adaptation) {
152 if (null !== $adaptation->trait) {
153 $adaptation->trait = $this->resolveClassName($adaptation->trait);
154 }
155
156 if ($adaptation instanceof Stmt\TraitUseAdaptation\Precedence) {
157 foreach ($adaptation->insteadof as &$insteadof) {
158 $insteadof = $this->resolveClassName($insteadof);
159 }
160 }
161 }
162 }
163
164 return null;
165 }
166
167 private function addAlias(Stmt\UseUse $use, int $type, ?Name $prefix = null) {
168 // Add prefix for group uses
169 $name = $prefix ? Name::concat($prefix, $use->name) : $use->name;
170 // Type is determined either by individual element or whole use declaration
171 $type |= $use->type;
172
173 $this->nameContext->addAlias(
174 $name, (string) $use->getAlias(), $type, $use->getAttributes()
175 );
176 }
177
178 /** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */
179 private function resolveSignature($node) {
180 foreach ($node->params as $param) {
181 $param->type = $this->resolveType($param->type);
182 $this->resolveAttrGroups($param);
183 }
184 $node->returnType = $this->resolveType($node->returnType);
185 }
186
187 private function resolveType($node) {
188 if ($node instanceof Name) {
189 return $this->resolveClassName($node);
190 }
191 if ($node instanceof Node\NullableType) {
192 $node->type = $this->resolveType($node->type);
193 return $node;
194 }
195 if ($node instanceof Node\UnionType || $node instanceof Node\IntersectionType) {
196 foreach ($node->types as &$type) {
197 $type = $this->resolveType($type);
198 }
199 return $node;
200 }
201 return $node;
202 }
203
204 /**
205 * Resolve name, according to name resolver options.
206 *
207 * @param Name $name Function or constant name to resolve
208 * @param int $type One of Stmt\Use_::TYPE_*
209 *
210 * @return Name Resolved name, or original name with attribute
211 */
212 protected function resolveName(Name $name, int $type) : Name {
213 if (!$this->replaceNodes) {
214 $resolvedName = $this->nameContext->getResolvedName($name, $type);
215 if (null !== $resolvedName) {
216 $name->setAttribute('resolvedName', $resolvedName);
217 } else {
218 $name->setAttribute('namespacedName', FullyQualified::concat(
219 $this->nameContext->getNamespace(), $name, $name->getAttributes()));
220 }
221 return $name;
222 }
223
224 if ($this->preserveOriginalNames) {
225 // Save the original name
226 $originalName = $name;
227 $name = clone $originalName;
228 $name->setAttribute('originalName', $originalName);
229 }
230
231 $resolvedName = $this->nameContext->getResolvedName($name, $type);
232 if (null !== $resolvedName) {
233 return $resolvedName;
234 }
235
236 // unqualified names inside a namespace cannot be resolved at compile-time
237 // add the namespaced version of the name as an attribute
238 $name->setAttribute('namespacedName', FullyQualified::concat(
239 $this->nameContext->getNamespace(), $name, $name->getAttributes()));
240 return $name;
241 }
242
243 protected function resolveClassName(Name $name) {
244 return $this->resolveName($name, Stmt\Use_::TYPE_NORMAL);
245 }
246
247 protected function addNamespacedName(Node $node) {
248 $node->namespacedName = Name::concat(
249 $this->nameContext->getNamespace(), (string) $node->name);
250 }
251
252 protected function resolveAttrGroups(Node $node)
253 {
254 foreach ($node->attrGroups as $attrGroup) {
255 foreach ($attrGroup->attrs as $attr) {
256 $attr->name = $this->resolveClassName($attr->name);
257 }
258 }
259 }
260 }
261