Chris@0: addVisitor(new NameResolver); Chris@0: Chris@0: $stmts = $parser->parse($code); Chris@0: $stmts = $traverser->traverse($stmts); Chris@0: Chris@0: $this->assertSame( Chris@0: $this->canonicalize($expectedCode), Chris@0: $prettyPrinter->prettyPrint($stmts) Chris@0: ); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @covers PhpParser\NodeVisitor\NameResolver Chris@0: */ Chris@0: public function testResolveLocations() { Chris@0: $code = <<<'EOC' Chris@0: addVisitor(new NameResolver); Chris@0: Chris@0: $stmts = $parser->parse($code); Chris@0: $stmts = $traverser->traverse($stmts); Chris@0: Chris@0: $this->assertSame( Chris@0: $this->canonicalize($expectedCode), Chris@0: $prettyPrinter->prettyPrint($stmts) Chris@0: ); Chris@0: } Chris@0: Chris@0: public function testNoResolveSpecialName() { Chris@0: $stmts = array(new Node\Expr\New_(new Name('self'))); Chris@0: Chris@0: $traverser = new PhpParser\NodeTraverser; Chris@0: $traverser->addVisitor(new NameResolver); Chris@0: Chris@0: $this->assertEquals($stmts, $traverser->traverse($stmts)); Chris@0: } Chris@0: Chris@0: public function testAddDeclarationNamespacedName() { Chris@0: $nsStmts = array( Chris@0: new Stmt\Class_('A'), Chris@0: new Stmt\Interface_('B'), Chris@0: new Stmt\Function_('C'), Chris@0: new Stmt\Const_(array( Chris@0: new Node\Const_('D', new Node\Scalar\LNumber(42)) Chris@0: )), Chris@0: new Stmt\Trait_('E'), Chris@0: new Expr\New_(new Stmt\Class_(null)), Chris@0: ); Chris@0: Chris@0: $traverser = new PhpParser\NodeTraverser; Chris@0: $traverser->addVisitor(new NameResolver); Chris@0: Chris@0: $stmts = $traverser->traverse([new Stmt\Namespace_(new Name('NS'), $nsStmts)]); Chris@0: $this->assertSame('NS\\A', (string) $stmts[0]->stmts[0]->namespacedName); Chris@0: $this->assertSame('NS\\B', (string) $stmts[0]->stmts[1]->namespacedName); Chris@0: $this->assertSame('NS\\C', (string) $stmts[0]->stmts[2]->namespacedName); Chris@0: $this->assertSame('NS\\D', (string) $stmts[0]->stmts[3]->consts[0]->namespacedName); Chris@0: $this->assertSame('NS\\E', (string) $stmts[0]->stmts[4]->namespacedName); Chris@0: $this->assertObjectNotHasAttribute('namespacedName', $stmts[0]->stmts[5]->class); Chris@0: Chris@0: $stmts = $traverser->traverse([new Stmt\Namespace_(null, $nsStmts)]); Chris@0: $this->assertSame('A', (string) $stmts[0]->stmts[0]->namespacedName); Chris@0: $this->assertSame('B', (string) $stmts[0]->stmts[1]->namespacedName); Chris@0: $this->assertSame('C', (string) $stmts[0]->stmts[2]->namespacedName); Chris@0: $this->assertSame('D', (string) $stmts[0]->stmts[3]->consts[0]->namespacedName); Chris@0: $this->assertSame('E', (string) $stmts[0]->stmts[4]->namespacedName); Chris@0: $this->assertObjectNotHasAttribute('namespacedName', $stmts[0]->stmts[5]->class); Chris@0: } Chris@0: Chris@0: public function testAddRuntimeResolvedNamespacedName() { Chris@0: $stmts = array( Chris@0: new Stmt\Namespace_(new Name('NS'), array( Chris@0: new Expr\FuncCall(new Name('foo')), Chris@0: new Expr\ConstFetch(new Name('FOO')), Chris@0: )), Chris@0: new Stmt\Namespace_(null, array( Chris@0: new Expr\FuncCall(new Name('foo')), Chris@0: new Expr\ConstFetch(new Name('FOO')), Chris@0: )), Chris@0: ); Chris@0: Chris@0: $traverser = new PhpParser\NodeTraverser; Chris@0: $traverser->addVisitor(new NameResolver); Chris@0: $stmts = $traverser->traverse($stmts); Chris@0: Chris@0: $this->assertSame('NS\\foo', (string) $stmts[0]->stmts[0]->name->getAttribute('namespacedName')); Chris@0: $this->assertSame('NS\\FOO', (string) $stmts[0]->stmts[1]->name->getAttribute('namespacedName')); Chris@0: Chris@0: $this->assertFalse($stmts[1]->stmts[0]->name->hasAttribute('namespacedName')); Chris@0: $this->assertFalse($stmts[1]->stmts[1]->name->hasAttribute('namespacedName')); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @dataProvider provideTestError Chris@0: */ Chris@0: public function testError(Node $stmt, $errorMsg) { Chris@0: $this->setExpectedException('PhpParser\Error', $errorMsg); Chris@0: Chris@0: $traverser = new PhpParser\NodeTraverser; Chris@0: $traverser->addVisitor(new NameResolver); Chris@0: $traverser->traverse(array($stmt)); Chris@0: } Chris@0: Chris@0: public function provideTestError() { Chris@0: return array( Chris@0: array( Chris@0: new Stmt\Use_(array( Chris@0: new Stmt\UseUse(new Name('A\B'), 'B', 0, array('startLine' => 1)), Chris@0: new Stmt\UseUse(new Name('C\D'), 'B', 0, array('startLine' => 2)), Chris@0: ), Stmt\Use_::TYPE_NORMAL), Chris@0: 'Cannot use C\D as B because the name is already in use on line 2' Chris@0: ), Chris@0: array( Chris@0: new Stmt\Use_(array( Chris@0: new Stmt\UseUse(new Name('a\b'), 'b', 0, array('startLine' => 1)), Chris@0: new Stmt\UseUse(new Name('c\d'), 'B', 0, array('startLine' => 2)), Chris@0: ), Stmt\Use_::TYPE_FUNCTION), Chris@0: 'Cannot use function c\d as B because the name is already in use on line 2' Chris@0: ), Chris@0: array( Chris@0: new Stmt\Use_(array( Chris@0: new Stmt\UseUse(new Name('A\B'), 'B', 0, array('startLine' => 1)), Chris@0: new Stmt\UseUse(new Name('C\D'), 'B', 0, array('startLine' => 2)), Chris@0: ), Stmt\Use_::TYPE_CONSTANT), Chris@0: 'Cannot use const C\D as B because the name is already in use on line 2' Chris@0: ), Chris@0: array( Chris@0: new Expr\New_(new Name\FullyQualified('self', array('startLine' => 3))), Chris@0: "'\\self' is an invalid class name on line 3" Chris@0: ), Chris@0: array( Chris@0: new Expr\New_(new Name\Relative('self', array('startLine' => 3))), Chris@0: "'\\self' is an invalid class name on line 3" Chris@0: ), Chris@0: array( Chris@0: new Expr\New_(new Name\FullyQualified('PARENT', array('startLine' => 3))), Chris@0: "'\\PARENT' is an invalid class name on line 3" Chris@0: ), Chris@0: array( Chris@0: new Expr\New_(new Name\Relative('STATIC', array('startLine' => 3))), Chris@0: "'\\STATIC' is an invalid class name on line 3" Chris@0: ), Chris@0: ); Chris@0: } Chris@0: Chris@0: public function testClassNameIsCaseInsensitive() Chris@0: { Chris@0: $source = <<<'EOC' Chris@0: parse($source); Chris@0: Chris@0: $traverser = new PhpParser\NodeTraverser; Chris@0: $traverser->addVisitor(new NameResolver); Chris@0: Chris@0: $stmts = $traverser->traverse($stmts); Chris@0: $stmt = $stmts[0]; Chris@0: Chris@0: $this->assertSame(array('Bar', 'Baz'), $stmt->stmts[1]->expr->class->parts); Chris@0: } Chris@0: Chris@0: public function testSpecialClassNamesAreCaseInsensitive() { Chris@0: $source = <<<'EOC' Chris@0: parse($source); Chris@0: Chris@0: $traverser = new PhpParser\NodeTraverser; Chris@0: $traverser->addVisitor(new NameResolver); Chris@0: Chris@0: $stmts = $traverser->traverse($stmts); Chris@0: $classStmt = $stmts[0]; Chris@0: $methodStmt = $classStmt->stmts[0]->stmts[0]; Chris@0: Chris@0: $this->assertSame('SELF', (string)$methodStmt->stmts[0]->class); Chris@0: $this->assertSame('PARENT', (string)$methodStmt->stmts[1]->class); Chris@0: $this->assertSame('STATIC', (string)$methodStmt->stmts[2]->class); Chris@0: } Chris@0: Chris@0: public function testAddOriginalNames() { Chris@0: $traverser = new PhpParser\NodeTraverser; Chris@0: $traverser->addVisitor(new NameResolver(null, ['preserveOriginalNames' => true])); Chris@0: Chris@0: $n1 = new Name('Bar'); Chris@0: $n2 = new Name('bar'); Chris@0: $origStmts = [ Chris@0: new Stmt\Namespace_(new Name('Foo'), [ Chris@0: new Expr\ClassConstFetch($n1, 'FOO'), Chris@0: new Expr\FuncCall($n2), Chris@0: ]) Chris@0: ]; Chris@0: Chris@0: $stmts = $traverser->traverse($origStmts); Chris@0: Chris@0: $this->assertSame($n1, $stmts[0]->stmts[0]->class->getAttribute('originalName')); Chris@0: $this->assertSame($n2, $stmts[0]->stmts[1]->name->getAttribute('originalName')); Chris@0: } Chris@0: }