comparison vendor/nikic/php-parser/test/PhpParser/NodeVisitor/NameResolverTest.php @ 13:5fb285c0d0e3

Update Drupal core to 8.4.7 via Composer. Security update; I *think* we've been lucky to get away with this so far, as we don't support self-registration which seems to be used by the so-called "drupalgeddon 2" attack that 8.4.5 was vulnerable to.
author Chris Cannam
date Mon, 23 Apr 2018 09:33:26 +0100
parents 4c8ae668cc8c
children 129ea1e6d783
comparison
equal deleted inserted replaced
12:7a779792577d 13:5fb285c0d0e3
1 <?php 1 <?php declare(strict_types=1);
2 2
3 namespace PhpParser\NodeVisitor; 3 namespace PhpParser\NodeVisitor;
4 4
5 use PhpParser; 5 use PhpParser;
6 use PhpParser\Node; 6 use PhpParser\Node;
7 use PhpParser\Node\Expr; 7 use PhpParser\Node\Expr;
8 use PhpParser\Node\Name; 8 use PhpParser\Node\Name;
9 use PhpParser\Node\Stmt; 9 use PhpParser\Node\Stmt;
10 10 use PHPUnit\Framework\TestCase;
11 class NameResolverTest extends \PHPUnit_Framework_TestCase 11
12 class NameResolverTest extends TestCase
12 { 13 {
13 private function canonicalize($string) { 14 private function canonicalize($string) {
14 return str_replace("\r\n", "\n", $string); 15 return str_replace("\r\n", "\n", $string);
15 } 16 }
16 17
277 $prettyPrinter->prettyPrint($stmts) 278 $prettyPrinter->prettyPrint($stmts)
278 ); 279 );
279 } 280 }
280 281
281 public function testNoResolveSpecialName() { 282 public function testNoResolveSpecialName() {
282 $stmts = array(new Node\Expr\New_(new Name('self'))); 283 $stmts = [new Node\Expr\New_(new Name('self'))];
283 284
284 $traverser = new PhpParser\NodeTraverser; 285 $traverser = new PhpParser\NodeTraverser;
285 $traverser->addVisitor(new NameResolver); 286 $traverser->addVisitor(new NameResolver);
286 287
287 $this->assertEquals($stmts, $traverser->traverse($stmts)); 288 $this->assertEquals($stmts, $traverser->traverse($stmts));
288 } 289 }
289 290
290 public function testAddDeclarationNamespacedName() { 291 public function testAddDeclarationNamespacedName() {
291 $nsStmts = array( 292 $nsStmts = [
292 new Stmt\Class_('A'), 293 new Stmt\Class_('A'),
293 new Stmt\Interface_('B'), 294 new Stmt\Interface_('B'),
294 new Stmt\Function_('C'), 295 new Stmt\Function_('C'),
295 new Stmt\Const_(array( 296 new Stmt\Const_([
296 new Node\Const_('D', new Node\Scalar\LNumber(42)) 297 new Node\Const_('D', new Node\Scalar\LNumber(42))
297 )), 298 ]),
298 new Stmt\Trait_('E'), 299 new Stmt\Trait_('E'),
299 new Expr\New_(new Stmt\Class_(null)), 300 new Expr\New_(new Stmt\Class_(null)),
300 ); 301 ];
301 302
302 $traverser = new PhpParser\NodeTraverser; 303 $traverser = new PhpParser\NodeTraverser;
303 $traverser->addVisitor(new NameResolver); 304 $traverser->addVisitor(new NameResolver);
304 305
305 $stmts = $traverser->traverse([new Stmt\Namespace_(new Name('NS'), $nsStmts)]); 306 $stmts = $traverser->traverse([new Stmt\Namespace_(new Name('NS'), $nsStmts)]);
318 $this->assertSame('E', (string) $stmts[0]->stmts[4]->namespacedName); 319 $this->assertSame('E', (string) $stmts[0]->stmts[4]->namespacedName);
319 $this->assertObjectNotHasAttribute('namespacedName', $stmts[0]->stmts[5]->class); 320 $this->assertObjectNotHasAttribute('namespacedName', $stmts[0]->stmts[5]->class);
320 } 321 }
321 322
322 public function testAddRuntimeResolvedNamespacedName() { 323 public function testAddRuntimeResolvedNamespacedName() {
323 $stmts = array( 324 $stmts = [
324 new Stmt\Namespace_(new Name('NS'), array( 325 new Stmt\Namespace_(new Name('NS'), [
325 new Expr\FuncCall(new Name('foo')), 326 new Expr\FuncCall(new Name('foo')),
326 new Expr\ConstFetch(new Name('FOO')), 327 new Expr\ConstFetch(new Name('FOO')),
327 )), 328 ]),
328 new Stmt\Namespace_(null, array( 329 new Stmt\Namespace_(null, [
329 new Expr\FuncCall(new Name('foo')), 330 new Expr\FuncCall(new Name('foo')),
330 new Expr\ConstFetch(new Name('FOO')), 331 new Expr\ConstFetch(new Name('FOO')),
331 )), 332 ]),
332 ); 333 ];
333 334
334 $traverser = new PhpParser\NodeTraverser; 335 $traverser = new PhpParser\NodeTraverser;
335 $traverser->addVisitor(new NameResolver); 336 $traverser->addVisitor(new NameResolver);
336 $stmts = $traverser->traverse($stmts); 337 $stmts = $traverser->traverse($stmts);
337 338
338 $this->assertSame('NS\\foo', (string) $stmts[0]->stmts[0]->name->getAttribute('namespacedName')); 339 $this->assertSame('NS\\foo', (string) $stmts[0]->stmts[0]->name->getAttribute('namespacedName'));
339 $this->assertSame('NS\\FOO', (string) $stmts[0]->stmts[1]->name->getAttribute('namespacedName')); 340 $this->assertSame('NS\\FOO', (string) $stmts[0]->stmts[1]->name->getAttribute('namespacedName'));
340 341
341 $this->assertFalse($stmts[1]->stmts[0]->name->hasAttribute('namespacedName')); 342 $this->assertFalse($stmts[1]->stmts[0]->name->hasAttribute('namespacedName'));
342 $this->assertFalse($stmts[1]->stmts[1]->name->hasAttribute('namespacedName')); 343 $this->assertFalse($stmts[1]->stmts[1]->name->hasAttribute('namespacedName'));
344 345
345 /** 346 /**
346 * @dataProvider provideTestError 347 * @dataProvider provideTestError
347 */ 348 */
348 public function testError(Node $stmt, $errorMsg) { 349 public function testError(Node $stmt, $errorMsg) {
349 $this->setExpectedException('PhpParser\Error', $errorMsg); 350 $this->expectException(\PhpParser\Error::class);
350 351 $this->expectExceptionMessage($errorMsg);
351 $traverser = new PhpParser\NodeTraverser; 352
352 $traverser->addVisitor(new NameResolver); 353 $traverser = new PhpParser\NodeTraverser;
353 $traverser->traverse(array($stmt)); 354 $traverser->addVisitor(new NameResolver);
355 $traverser->traverse([$stmt]);
354 } 356 }
355 357
356 public function provideTestError() { 358 public function provideTestError() {
357 return array( 359 return [
358 array( 360 [
359 new Stmt\Use_(array( 361 new Stmt\Use_([
360 new Stmt\UseUse(new Name('A\B'), 'B', 0, array('startLine' => 1)), 362 new Stmt\UseUse(new Name('A\B'), 'B', 0, ['startLine' => 1]),
361 new Stmt\UseUse(new Name('C\D'), 'B', 0, array('startLine' => 2)), 363 new Stmt\UseUse(new Name('C\D'), 'B', 0, ['startLine' => 2]),
362 ), Stmt\Use_::TYPE_NORMAL), 364 ], Stmt\Use_::TYPE_NORMAL),
363 'Cannot use C\D as B because the name is already in use on line 2' 365 'Cannot use C\D as B because the name is already in use on line 2'
364 ), 366 ],
365 array( 367 [
366 new Stmt\Use_(array( 368 new Stmt\Use_([
367 new Stmt\UseUse(new Name('a\b'), 'b', 0, array('startLine' => 1)), 369 new Stmt\UseUse(new Name('a\b'), 'b', 0, ['startLine' => 1]),
368 new Stmt\UseUse(new Name('c\d'), 'B', 0, array('startLine' => 2)), 370 new Stmt\UseUse(new Name('c\d'), 'B', 0, ['startLine' => 2]),
369 ), Stmt\Use_::TYPE_FUNCTION), 371 ], Stmt\Use_::TYPE_FUNCTION),
370 'Cannot use function c\d as B because the name is already in use on line 2' 372 'Cannot use function c\d as B because the name is already in use on line 2'
371 ), 373 ],
372 array( 374 [
373 new Stmt\Use_(array( 375 new Stmt\Use_([
374 new Stmt\UseUse(new Name('A\B'), 'B', 0, array('startLine' => 1)), 376 new Stmt\UseUse(new Name('A\B'), 'B', 0, ['startLine' => 1]),
375 new Stmt\UseUse(new Name('C\D'), 'B', 0, array('startLine' => 2)), 377 new Stmt\UseUse(new Name('C\D'), 'B', 0, ['startLine' => 2]),
376 ), Stmt\Use_::TYPE_CONSTANT), 378 ], Stmt\Use_::TYPE_CONSTANT),
377 'Cannot use const C\D as B because the name is already in use on line 2' 379 'Cannot use const C\D as B because the name is already in use on line 2'
378 ), 380 ],
379 array( 381 [
380 new Expr\New_(new Name\FullyQualified('self', array('startLine' => 3))), 382 new Expr\New_(new Name\FullyQualified('self', ['startLine' => 3])),
381 "'\\self' is an invalid class name on line 3" 383 "'\\self' is an invalid class name on line 3"
382 ), 384 ],
383 array( 385 [
384 new Expr\New_(new Name\Relative('self', array('startLine' => 3))), 386 new Expr\New_(new Name\Relative('self', ['startLine' => 3])),
385 "'\\self' is an invalid class name on line 3" 387 "'\\self' is an invalid class name on line 3"
386 ), 388 ],
387 array( 389 [
388 new Expr\New_(new Name\FullyQualified('PARENT', array('startLine' => 3))), 390 new Expr\New_(new Name\FullyQualified('PARENT', ['startLine' => 3])),
389 "'\\PARENT' is an invalid class name on line 3" 391 "'\\PARENT' is an invalid class name on line 3"
390 ), 392 ],
391 array( 393 [
392 new Expr\New_(new Name\Relative('STATIC', array('startLine' => 3))), 394 new Expr\New_(new Name\Relative('STATIC', ['startLine' => 3])),
393 "'\\STATIC' is an invalid class name on line 3" 395 "'\\STATIC' is an invalid class name on line 3"
394 ), 396 ],
395 ); 397 ];
396 } 398 }
397 399
398 public function testClassNameIsCaseInsensitive() 400 public function testClassNameIsCaseInsensitive()
399 { 401 {
400 $source = <<<'EOC' 402 $source = <<<'EOC'
411 $traverser->addVisitor(new NameResolver); 413 $traverser->addVisitor(new NameResolver);
412 414
413 $stmts = $traverser->traverse($stmts); 415 $stmts = $traverser->traverse($stmts);
414 $stmt = $stmts[0]; 416 $stmt = $stmts[0];
415 417
416 $this->assertSame(array('Bar', 'Baz'), $stmt->stmts[1]->expr->class->parts); 418 $assign = $stmt->stmts[1]->expr;
419 $this->assertSame(['Bar', 'Baz'], $assign->expr->class->parts);
417 } 420 }
418 421
419 public function testSpecialClassNamesAreCaseInsensitive() { 422 public function testSpecialClassNamesAreCaseInsensitive() {
420 $source = <<<'EOC' 423 $source = <<<'EOC'
421 <?php 424 <?php
440 443
441 $stmts = $traverser->traverse($stmts); 444 $stmts = $traverser->traverse($stmts);
442 $classStmt = $stmts[0]; 445 $classStmt = $stmts[0];
443 $methodStmt = $classStmt->stmts[0]->stmts[0]; 446 $methodStmt = $classStmt->stmts[0]->stmts[0];
444 447
445 $this->assertSame('SELF', (string)$methodStmt->stmts[0]->class); 448 $this->assertSame('SELF', (string) $methodStmt->stmts[0]->expr->class);
446 $this->assertSame('PARENT', (string)$methodStmt->stmts[1]->class); 449 $this->assertSame('PARENT', (string) $methodStmt->stmts[1]->expr->class);
447 $this->assertSame('STATIC', (string)$methodStmt->stmts[2]->class); 450 $this->assertSame('STATIC', (string) $methodStmt->stmts[2]->expr->class);
448 } 451 }
449 452
450 public function testAddOriginalNames() { 453 public function testAddOriginalNames() {
451 $traverser = new PhpParser\NodeTraverser; 454 $traverser = new PhpParser\NodeTraverser;
452 $traverser->addVisitor(new NameResolver(null, ['preserveOriginalNames' => true])); 455 $traverser->addVisitor(new NameResolver(null, ['preserveOriginalNames' => true]));
463 $stmts = $traverser->traverse($origStmts); 466 $stmts = $traverser->traverse($origStmts);
464 467
465 $this->assertSame($n1, $stmts[0]->stmts[0]->class->getAttribute('originalName')); 468 $this->assertSame($n1, $stmts[0]->stmts[0]->class->getAttribute('originalName'));
466 $this->assertSame($n2, $stmts[0]->stmts[1]->name->getAttribute('originalName')); 469 $this->assertSame($n2, $stmts[0]->stmts[1]->name->getAttribute('originalName'));
467 } 470 }
468 } 471
472 public function testAttributeOnlyMode() {
473 $traverser = new PhpParser\NodeTraverser;
474 $traverser->addVisitor(new NameResolver(null, ['replaceNodes' => false]));
475
476 $n1 = new Name('Bar');
477 $n2 = new Name('bar');
478 $origStmts = [
479 new Stmt\Namespace_(new Name('Foo'), [
480 new Expr\ClassConstFetch($n1, 'FOO'),
481 new Expr\FuncCall($n2),
482 ])
483 ];
484
485 $traverser->traverse($origStmts);
486
487 $this->assertEquals(
488 new Name\FullyQualified('Foo\Bar'), $n1->getAttribute('resolvedName'));
489 $this->assertFalse($n2->hasAttribute('resolvedName'));
490 $this->assertEquals(
491 new Name\FullyQualified('Foo\bar'), $n2->getAttribute('namespacedName'));
492 }
493 }