Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace PhpParser\NodeVisitor;
|
Chris@0
|
4
|
Chris@0
|
5 use PhpParser;
|
Chris@0
|
6 use PhpParser\Node;
|
Chris@0
|
7 use PhpParser\Node\Expr;
|
Chris@0
|
8 use PhpParser\Node\Name;
|
Chris@0
|
9 use PhpParser\Node\Stmt;
|
Chris@0
|
10
|
Chris@0
|
11 class NameResolverTest extends \PHPUnit_Framework_TestCase
|
Chris@0
|
12 {
|
Chris@0
|
13 private function canonicalize($string) {
|
Chris@0
|
14 return str_replace("\r\n", "\n", $string);
|
Chris@0
|
15 }
|
Chris@0
|
16
|
Chris@0
|
17 /**
|
Chris@0
|
18 * @covers PhpParser\NodeVisitor\NameResolver
|
Chris@0
|
19 */
|
Chris@0
|
20 public function testResolveNames() {
|
Chris@0
|
21 $code = <<<'EOC'
|
Chris@0
|
22 <?php
|
Chris@0
|
23
|
Chris@0
|
24 namespace Foo {
|
Chris@0
|
25 use Hallo as Hi;
|
Chris@0
|
26
|
Chris@0
|
27 new Bar();
|
Chris@0
|
28 new Hi();
|
Chris@0
|
29 new Hi\Bar();
|
Chris@0
|
30 new \Bar();
|
Chris@0
|
31 new namespace\Bar();
|
Chris@0
|
32
|
Chris@0
|
33 bar();
|
Chris@0
|
34 hi();
|
Chris@0
|
35 Hi\bar();
|
Chris@0
|
36 foo\bar();
|
Chris@0
|
37 \bar();
|
Chris@0
|
38 namespace\bar();
|
Chris@0
|
39 }
|
Chris@0
|
40 namespace {
|
Chris@0
|
41 use Hallo as Hi;
|
Chris@0
|
42
|
Chris@0
|
43 new Bar();
|
Chris@0
|
44 new Hi();
|
Chris@0
|
45 new Hi\Bar();
|
Chris@0
|
46 new \Bar();
|
Chris@0
|
47 new namespace\Bar();
|
Chris@0
|
48
|
Chris@0
|
49 bar();
|
Chris@0
|
50 hi();
|
Chris@0
|
51 Hi\bar();
|
Chris@0
|
52 foo\bar();
|
Chris@0
|
53 \bar();
|
Chris@0
|
54 namespace\bar();
|
Chris@0
|
55 }
|
Chris@0
|
56 namespace Bar {
|
Chris@0
|
57 use function foo\bar as baz;
|
Chris@0
|
58 use const foo\BAR as BAZ;
|
Chris@0
|
59 use foo as bar;
|
Chris@0
|
60
|
Chris@0
|
61 bar();
|
Chris@0
|
62 baz();
|
Chris@0
|
63 bar\foo();
|
Chris@0
|
64 baz\foo();
|
Chris@0
|
65 BAR();
|
Chris@0
|
66 BAZ();
|
Chris@0
|
67 BAR\FOO();
|
Chris@0
|
68 BAZ\FOO();
|
Chris@0
|
69
|
Chris@0
|
70 bar;
|
Chris@0
|
71 baz;
|
Chris@0
|
72 bar\foo;
|
Chris@0
|
73 baz\foo;
|
Chris@0
|
74 BAR;
|
Chris@0
|
75 BAZ;
|
Chris@0
|
76 BAR\FOO;
|
Chris@0
|
77 BAZ\FOO;
|
Chris@0
|
78 }
|
Chris@0
|
79 namespace Baz {
|
Chris@0
|
80 use A\T\{B\C, D\E};
|
Chris@0
|
81 use function X\T\{b\c, d\e};
|
Chris@0
|
82 use const Y\T\{B\C, D\E};
|
Chris@0
|
83 use Z\T\{G, function f, const K};
|
Chris@0
|
84
|
Chris@0
|
85 new C;
|
Chris@0
|
86 new E;
|
Chris@0
|
87 new C\D;
|
Chris@0
|
88 new E\F;
|
Chris@0
|
89 new G;
|
Chris@0
|
90
|
Chris@0
|
91 c();
|
Chris@0
|
92 e();
|
Chris@0
|
93 f();
|
Chris@0
|
94 C;
|
Chris@0
|
95 E;
|
Chris@0
|
96 K;
|
Chris@0
|
97 }
|
Chris@0
|
98 EOC;
|
Chris@0
|
99 $expectedCode = <<<'EOC'
|
Chris@0
|
100 namespace Foo {
|
Chris@0
|
101 use Hallo as Hi;
|
Chris@0
|
102 new \Foo\Bar();
|
Chris@0
|
103 new \Hallo();
|
Chris@0
|
104 new \Hallo\Bar();
|
Chris@0
|
105 new \Bar();
|
Chris@0
|
106 new \Foo\Bar();
|
Chris@0
|
107 bar();
|
Chris@0
|
108 hi();
|
Chris@0
|
109 \Hallo\bar();
|
Chris@0
|
110 \Foo\foo\bar();
|
Chris@0
|
111 \bar();
|
Chris@0
|
112 \Foo\bar();
|
Chris@0
|
113 }
|
Chris@0
|
114 namespace {
|
Chris@0
|
115 use Hallo as Hi;
|
Chris@0
|
116 new \Bar();
|
Chris@0
|
117 new \Hallo();
|
Chris@0
|
118 new \Hallo\Bar();
|
Chris@0
|
119 new \Bar();
|
Chris@0
|
120 new \Bar();
|
Chris@0
|
121 \bar();
|
Chris@0
|
122 \hi();
|
Chris@0
|
123 \Hallo\bar();
|
Chris@0
|
124 \foo\bar();
|
Chris@0
|
125 \bar();
|
Chris@0
|
126 \bar();
|
Chris@0
|
127 }
|
Chris@0
|
128 namespace Bar {
|
Chris@0
|
129 use function foo\bar as baz;
|
Chris@0
|
130 use const foo\BAR as BAZ;
|
Chris@0
|
131 use foo as bar;
|
Chris@0
|
132 bar();
|
Chris@0
|
133 \foo\bar();
|
Chris@0
|
134 \foo\foo();
|
Chris@0
|
135 \Bar\baz\foo();
|
Chris@0
|
136 BAR();
|
Chris@0
|
137 \foo\bar();
|
Chris@0
|
138 \foo\FOO();
|
Chris@0
|
139 \Bar\BAZ\FOO();
|
Chris@0
|
140 bar;
|
Chris@0
|
141 baz;
|
Chris@0
|
142 \foo\foo;
|
Chris@0
|
143 \Bar\baz\foo;
|
Chris@0
|
144 BAR;
|
Chris@0
|
145 \foo\BAR;
|
Chris@0
|
146 \foo\FOO;
|
Chris@0
|
147 \Bar\BAZ\FOO;
|
Chris@0
|
148 }
|
Chris@0
|
149 namespace Baz {
|
Chris@0
|
150 use A\T\{B\C, D\E};
|
Chris@0
|
151 use function X\T\{b\c, d\e};
|
Chris@0
|
152 use const Y\T\{B\C, D\E};
|
Chris@0
|
153 use Z\T\{G, function f, const K};
|
Chris@0
|
154 new \A\T\B\C();
|
Chris@0
|
155 new \A\T\D\E();
|
Chris@0
|
156 new \A\T\B\C\D();
|
Chris@0
|
157 new \A\T\D\E\F();
|
Chris@0
|
158 new \Z\T\G();
|
Chris@0
|
159 \X\T\b\c();
|
Chris@0
|
160 \X\T\d\e();
|
Chris@0
|
161 \Z\T\f();
|
Chris@0
|
162 \Y\T\B\C;
|
Chris@0
|
163 \Y\T\D\E;
|
Chris@0
|
164 \Z\T\K;
|
Chris@0
|
165 }
|
Chris@0
|
166 EOC;
|
Chris@0
|
167
|
Chris@0
|
168 $parser = new PhpParser\Parser\Php7(new PhpParser\Lexer\Emulative);
|
Chris@0
|
169 $prettyPrinter = new PhpParser\PrettyPrinter\Standard;
|
Chris@0
|
170 $traverser = new PhpParser\NodeTraverser;
|
Chris@0
|
171 $traverser->addVisitor(new NameResolver);
|
Chris@0
|
172
|
Chris@0
|
173 $stmts = $parser->parse($code);
|
Chris@0
|
174 $stmts = $traverser->traverse($stmts);
|
Chris@0
|
175
|
Chris@0
|
176 $this->assertSame(
|
Chris@0
|
177 $this->canonicalize($expectedCode),
|
Chris@0
|
178 $prettyPrinter->prettyPrint($stmts)
|
Chris@0
|
179 );
|
Chris@0
|
180 }
|
Chris@0
|
181
|
Chris@0
|
182 /**
|
Chris@0
|
183 * @covers PhpParser\NodeVisitor\NameResolver
|
Chris@0
|
184 */
|
Chris@0
|
185 public function testResolveLocations() {
|
Chris@0
|
186 $code = <<<'EOC'
|
Chris@0
|
187 <?php
|
Chris@0
|
188 namespace NS;
|
Chris@0
|
189
|
Chris@0
|
190 class A extends B implements C, D {
|
Chris@0
|
191 use E, F, G {
|
Chris@0
|
192 f as private g;
|
Chris@0
|
193 E::h as i;
|
Chris@0
|
194 E::j insteadof F, G;
|
Chris@0
|
195 }
|
Chris@0
|
196 }
|
Chris@0
|
197
|
Chris@0
|
198 interface A extends C, D {
|
Chris@0
|
199 public function a(A $a) : A;
|
Chris@0
|
200 }
|
Chris@0
|
201
|
Chris@0
|
202 function fn(A $a) : A {}
|
Chris@0
|
203 function fn2(array $a) : array {}
|
Chris@0
|
204 function(A $a) : A {};
|
Chris@0
|
205
|
Chris@0
|
206 function fn3(?A $a) : ?A {}
|
Chris@0
|
207 function fn4(?array $a) : ?array {}
|
Chris@0
|
208
|
Chris@0
|
209 A::b();
|
Chris@0
|
210 A::$b;
|
Chris@0
|
211 A::B;
|
Chris@0
|
212 new A;
|
Chris@0
|
213 $a instanceof A;
|
Chris@0
|
214
|
Chris@0
|
215 namespace\a();
|
Chris@0
|
216 namespace\A;
|
Chris@0
|
217
|
Chris@0
|
218 try {
|
Chris@0
|
219 $someThing;
|
Chris@0
|
220 } catch (A $a) {
|
Chris@0
|
221 $someThingElse;
|
Chris@0
|
222 }
|
Chris@0
|
223 EOC;
|
Chris@0
|
224 $expectedCode = <<<'EOC'
|
Chris@0
|
225 namespace NS;
|
Chris@0
|
226
|
Chris@0
|
227 class A extends \NS\B implements \NS\C, \NS\D
|
Chris@0
|
228 {
|
Chris@0
|
229 use \NS\E, \NS\F, \NS\G {
|
Chris@0
|
230 f as private g;
|
Chris@0
|
231 \NS\E::h as i;
|
Chris@0
|
232 \NS\E::j insteadof \NS\F, \NS\G;
|
Chris@0
|
233 }
|
Chris@0
|
234 }
|
Chris@0
|
235 interface A extends \NS\C, \NS\D
|
Chris@0
|
236 {
|
Chris@0
|
237 public function a(\NS\A $a) : \NS\A;
|
Chris@0
|
238 }
|
Chris@0
|
239 function fn(\NS\A $a) : \NS\A
|
Chris@0
|
240 {
|
Chris@0
|
241 }
|
Chris@0
|
242 function fn2(array $a) : array
|
Chris@0
|
243 {
|
Chris@0
|
244 }
|
Chris@0
|
245 function (\NS\A $a) : \NS\A {
|
Chris@0
|
246 };
|
Chris@0
|
247 function fn3(?\NS\A $a) : ?\NS\A
|
Chris@0
|
248 {
|
Chris@0
|
249 }
|
Chris@0
|
250 function fn4(?array $a) : ?array
|
Chris@0
|
251 {
|
Chris@0
|
252 }
|
Chris@0
|
253 \NS\A::b();
|
Chris@0
|
254 \NS\A::$b;
|
Chris@0
|
255 \NS\A::B;
|
Chris@0
|
256 new \NS\A();
|
Chris@0
|
257 $a instanceof \NS\A;
|
Chris@0
|
258 \NS\a();
|
Chris@0
|
259 \NS\A;
|
Chris@0
|
260 try {
|
Chris@0
|
261 $someThing;
|
Chris@0
|
262 } catch (\NS\A $a) {
|
Chris@0
|
263 $someThingElse;
|
Chris@0
|
264 }
|
Chris@0
|
265 EOC;
|
Chris@0
|
266
|
Chris@0
|
267 $parser = new PhpParser\Parser\Php7(new PhpParser\Lexer\Emulative);
|
Chris@0
|
268 $prettyPrinter = new PhpParser\PrettyPrinter\Standard;
|
Chris@0
|
269 $traverser = new PhpParser\NodeTraverser;
|
Chris@0
|
270 $traverser->addVisitor(new NameResolver);
|
Chris@0
|
271
|
Chris@0
|
272 $stmts = $parser->parse($code);
|
Chris@0
|
273 $stmts = $traverser->traverse($stmts);
|
Chris@0
|
274
|
Chris@0
|
275 $this->assertSame(
|
Chris@0
|
276 $this->canonicalize($expectedCode),
|
Chris@0
|
277 $prettyPrinter->prettyPrint($stmts)
|
Chris@0
|
278 );
|
Chris@0
|
279 }
|
Chris@0
|
280
|
Chris@0
|
281 public function testNoResolveSpecialName() {
|
Chris@0
|
282 $stmts = array(new Node\Expr\New_(new Name('self')));
|
Chris@0
|
283
|
Chris@0
|
284 $traverser = new PhpParser\NodeTraverser;
|
Chris@0
|
285 $traverser->addVisitor(new NameResolver);
|
Chris@0
|
286
|
Chris@0
|
287 $this->assertEquals($stmts, $traverser->traverse($stmts));
|
Chris@0
|
288 }
|
Chris@0
|
289
|
Chris@0
|
290 public function testAddDeclarationNamespacedName() {
|
Chris@0
|
291 $nsStmts = array(
|
Chris@0
|
292 new Stmt\Class_('A'),
|
Chris@0
|
293 new Stmt\Interface_('B'),
|
Chris@0
|
294 new Stmt\Function_('C'),
|
Chris@0
|
295 new Stmt\Const_(array(
|
Chris@0
|
296 new Node\Const_('D', new Node\Scalar\LNumber(42))
|
Chris@0
|
297 )),
|
Chris@0
|
298 new Stmt\Trait_('E'),
|
Chris@0
|
299 new Expr\New_(new Stmt\Class_(null)),
|
Chris@0
|
300 );
|
Chris@0
|
301
|
Chris@0
|
302 $traverser = new PhpParser\NodeTraverser;
|
Chris@0
|
303 $traverser->addVisitor(new NameResolver);
|
Chris@0
|
304
|
Chris@0
|
305 $stmts = $traverser->traverse([new Stmt\Namespace_(new Name('NS'), $nsStmts)]);
|
Chris@0
|
306 $this->assertSame('NS\\A', (string) $stmts[0]->stmts[0]->namespacedName);
|
Chris@0
|
307 $this->assertSame('NS\\B', (string) $stmts[0]->stmts[1]->namespacedName);
|
Chris@0
|
308 $this->assertSame('NS\\C', (string) $stmts[0]->stmts[2]->namespacedName);
|
Chris@0
|
309 $this->assertSame('NS\\D', (string) $stmts[0]->stmts[3]->consts[0]->namespacedName);
|
Chris@0
|
310 $this->assertSame('NS\\E', (string) $stmts[0]->stmts[4]->namespacedName);
|
Chris@0
|
311 $this->assertObjectNotHasAttribute('namespacedName', $stmts[0]->stmts[5]->class);
|
Chris@0
|
312
|
Chris@0
|
313 $stmts = $traverser->traverse([new Stmt\Namespace_(null, $nsStmts)]);
|
Chris@0
|
314 $this->assertSame('A', (string) $stmts[0]->stmts[0]->namespacedName);
|
Chris@0
|
315 $this->assertSame('B', (string) $stmts[0]->stmts[1]->namespacedName);
|
Chris@0
|
316 $this->assertSame('C', (string) $stmts[0]->stmts[2]->namespacedName);
|
Chris@0
|
317 $this->assertSame('D', (string) $stmts[0]->stmts[3]->consts[0]->namespacedName);
|
Chris@0
|
318 $this->assertSame('E', (string) $stmts[0]->stmts[4]->namespacedName);
|
Chris@0
|
319 $this->assertObjectNotHasAttribute('namespacedName', $stmts[0]->stmts[5]->class);
|
Chris@0
|
320 }
|
Chris@0
|
321
|
Chris@0
|
322 public function testAddRuntimeResolvedNamespacedName() {
|
Chris@0
|
323 $stmts = array(
|
Chris@0
|
324 new Stmt\Namespace_(new Name('NS'), array(
|
Chris@0
|
325 new Expr\FuncCall(new Name('foo')),
|
Chris@0
|
326 new Expr\ConstFetch(new Name('FOO')),
|
Chris@0
|
327 )),
|
Chris@0
|
328 new Stmt\Namespace_(null, array(
|
Chris@0
|
329 new Expr\FuncCall(new Name('foo')),
|
Chris@0
|
330 new Expr\ConstFetch(new Name('FOO')),
|
Chris@0
|
331 )),
|
Chris@0
|
332 );
|
Chris@0
|
333
|
Chris@0
|
334 $traverser = new PhpParser\NodeTraverser;
|
Chris@0
|
335 $traverser->addVisitor(new NameResolver);
|
Chris@0
|
336 $stmts = $traverser->traverse($stmts);
|
Chris@0
|
337
|
Chris@0
|
338 $this->assertSame('NS\\foo', (string) $stmts[0]->stmts[0]->name->getAttribute('namespacedName'));
|
Chris@0
|
339 $this->assertSame('NS\\FOO', (string) $stmts[0]->stmts[1]->name->getAttribute('namespacedName'));
|
Chris@0
|
340
|
Chris@0
|
341 $this->assertFalse($stmts[1]->stmts[0]->name->hasAttribute('namespacedName'));
|
Chris@0
|
342 $this->assertFalse($stmts[1]->stmts[1]->name->hasAttribute('namespacedName'));
|
Chris@0
|
343 }
|
Chris@0
|
344
|
Chris@0
|
345 /**
|
Chris@0
|
346 * @dataProvider provideTestError
|
Chris@0
|
347 */
|
Chris@0
|
348 public function testError(Node $stmt, $errorMsg) {
|
Chris@0
|
349 $this->setExpectedException('PhpParser\Error', $errorMsg);
|
Chris@0
|
350
|
Chris@0
|
351 $traverser = new PhpParser\NodeTraverser;
|
Chris@0
|
352 $traverser->addVisitor(new NameResolver);
|
Chris@0
|
353 $traverser->traverse(array($stmt));
|
Chris@0
|
354 }
|
Chris@0
|
355
|
Chris@0
|
356 public function provideTestError() {
|
Chris@0
|
357 return array(
|
Chris@0
|
358 array(
|
Chris@0
|
359 new Stmt\Use_(array(
|
Chris@0
|
360 new Stmt\UseUse(new Name('A\B'), 'B', 0, array('startLine' => 1)),
|
Chris@0
|
361 new Stmt\UseUse(new Name('C\D'), 'B', 0, array('startLine' => 2)),
|
Chris@0
|
362 ), Stmt\Use_::TYPE_NORMAL),
|
Chris@0
|
363 'Cannot use C\D as B because the name is already in use on line 2'
|
Chris@0
|
364 ),
|
Chris@0
|
365 array(
|
Chris@0
|
366 new Stmt\Use_(array(
|
Chris@0
|
367 new Stmt\UseUse(new Name('a\b'), 'b', 0, array('startLine' => 1)),
|
Chris@0
|
368 new Stmt\UseUse(new Name('c\d'), 'B', 0, array('startLine' => 2)),
|
Chris@0
|
369 ), Stmt\Use_::TYPE_FUNCTION),
|
Chris@0
|
370 'Cannot use function c\d as B because the name is already in use on line 2'
|
Chris@0
|
371 ),
|
Chris@0
|
372 array(
|
Chris@0
|
373 new Stmt\Use_(array(
|
Chris@0
|
374 new Stmt\UseUse(new Name('A\B'), 'B', 0, array('startLine' => 1)),
|
Chris@0
|
375 new Stmt\UseUse(new Name('C\D'), 'B', 0, array('startLine' => 2)),
|
Chris@0
|
376 ), Stmt\Use_::TYPE_CONSTANT),
|
Chris@0
|
377 'Cannot use const C\D as B because the name is already in use on line 2'
|
Chris@0
|
378 ),
|
Chris@0
|
379 array(
|
Chris@0
|
380 new Expr\New_(new Name\FullyQualified('self', array('startLine' => 3))),
|
Chris@0
|
381 "'\\self' is an invalid class name on line 3"
|
Chris@0
|
382 ),
|
Chris@0
|
383 array(
|
Chris@0
|
384 new Expr\New_(new Name\Relative('self', array('startLine' => 3))),
|
Chris@0
|
385 "'\\self' is an invalid class name on line 3"
|
Chris@0
|
386 ),
|
Chris@0
|
387 array(
|
Chris@0
|
388 new Expr\New_(new Name\FullyQualified('PARENT', array('startLine' => 3))),
|
Chris@0
|
389 "'\\PARENT' is an invalid class name on line 3"
|
Chris@0
|
390 ),
|
Chris@0
|
391 array(
|
Chris@0
|
392 new Expr\New_(new Name\Relative('STATIC', array('startLine' => 3))),
|
Chris@0
|
393 "'\\STATIC' is an invalid class name on line 3"
|
Chris@0
|
394 ),
|
Chris@0
|
395 );
|
Chris@0
|
396 }
|
Chris@0
|
397
|
Chris@0
|
398 public function testClassNameIsCaseInsensitive()
|
Chris@0
|
399 {
|
Chris@0
|
400 $source = <<<'EOC'
|
Chris@0
|
401 <?php
|
Chris@0
|
402 namespace Foo;
|
Chris@0
|
403 use Bar\Baz;
|
Chris@0
|
404 $test = new baz();
|
Chris@0
|
405 EOC;
|
Chris@0
|
406
|
Chris@0
|
407 $parser = new PhpParser\Parser\Php7(new PhpParser\Lexer\Emulative);
|
Chris@0
|
408 $stmts = $parser->parse($source);
|
Chris@0
|
409
|
Chris@0
|
410 $traverser = new PhpParser\NodeTraverser;
|
Chris@0
|
411 $traverser->addVisitor(new NameResolver);
|
Chris@0
|
412
|
Chris@0
|
413 $stmts = $traverser->traverse($stmts);
|
Chris@0
|
414 $stmt = $stmts[0];
|
Chris@0
|
415
|
Chris@0
|
416 $this->assertSame(array('Bar', 'Baz'), $stmt->stmts[1]->expr->class->parts);
|
Chris@0
|
417 }
|
Chris@0
|
418
|
Chris@0
|
419 public function testSpecialClassNamesAreCaseInsensitive() {
|
Chris@0
|
420 $source = <<<'EOC'
|
Chris@0
|
421 <?php
|
Chris@0
|
422 namespace Foo;
|
Chris@0
|
423
|
Chris@0
|
424 class Bar
|
Chris@0
|
425 {
|
Chris@0
|
426 public static function method()
|
Chris@0
|
427 {
|
Chris@0
|
428 SELF::method();
|
Chris@0
|
429 PARENT::method();
|
Chris@0
|
430 STATIC::method();
|
Chris@0
|
431 }
|
Chris@0
|
432 }
|
Chris@0
|
433 EOC;
|
Chris@0
|
434
|
Chris@0
|
435 $parser = new PhpParser\Parser\Php7(new PhpParser\Lexer\Emulative);
|
Chris@0
|
436 $stmts = $parser->parse($source);
|
Chris@0
|
437
|
Chris@0
|
438 $traverser = new PhpParser\NodeTraverser;
|
Chris@0
|
439 $traverser->addVisitor(new NameResolver);
|
Chris@0
|
440
|
Chris@0
|
441 $stmts = $traverser->traverse($stmts);
|
Chris@0
|
442 $classStmt = $stmts[0];
|
Chris@0
|
443 $methodStmt = $classStmt->stmts[0]->stmts[0];
|
Chris@0
|
444
|
Chris@0
|
445 $this->assertSame('SELF', (string)$methodStmt->stmts[0]->class);
|
Chris@0
|
446 $this->assertSame('PARENT', (string)$methodStmt->stmts[1]->class);
|
Chris@0
|
447 $this->assertSame('STATIC', (string)$methodStmt->stmts[2]->class);
|
Chris@0
|
448 }
|
Chris@0
|
449
|
Chris@0
|
450 public function testAddOriginalNames() {
|
Chris@0
|
451 $traverser = new PhpParser\NodeTraverser;
|
Chris@0
|
452 $traverser->addVisitor(new NameResolver(null, ['preserveOriginalNames' => true]));
|
Chris@0
|
453
|
Chris@0
|
454 $n1 = new Name('Bar');
|
Chris@0
|
455 $n2 = new Name('bar');
|
Chris@0
|
456 $origStmts = [
|
Chris@0
|
457 new Stmt\Namespace_(new Name('Foo'), [
|
Chris@0
|
458 new Expr\ClassConstFetch($n1, 'FOO'),
|
Chris@0
|
459 new Expr\FuncCall($n2),
|
Chris@0
|
460 ])
|
Chris@0
|
461 ];
|
Chris@0
|
462
|
Chris@0
|
463 $stmts = $traverser->traverse($origStmts);
|
Chris@0
|
464
|
Chris@0
|
465 $this->assertSame($n1, $stmts[0]->stmts[0]->class->getAttribute('originalName'));
|
Chris@0
|
466 $this->assertSame($n2, $stmts[0]->stmts[1]->name->getAttribute('originalName'));
|
Chris@0
|
467 }
|
Chris@0
|
468 }
|