Файл: gapps/vendor/nikic/php-parser/test/PhpParser/NodeVisitor/NameResolverTest.php
Строк: 308
<?php
namespace PhpParserNodeVisitor;
use PhpParser;
use PhpParserNode;
use PhpParserNodeName;
use PhpParserNodeStmt;
use PhpParserNodeExpr;
class NameResolverTest extends PHPUnit_Framework_TestCase
{
private function canonicalize($string) {
return str_replace("rn", "n", $string);
}
/**
* @covers PhpParserNodeVisitorNameResolver
*/
public function testResolveNames() {
$code = <<<'EOC'
<?php
namespace Foo {
use Hallo as Hi;
new Bar();
new Hi();
new HiBar();
new Bar();
new namespaceBar();
bar();
hi();
Hibar();
foobar();
bar();
namespacebar();
}
namespace {
use Hallo as Hi;
new Bar();
new Hi();
new HiBar();
new Bar();
new namespaceBar();
bar();
hi();
Hibar();
foobar();
bar();
namespacebar();
}
namespace Bar {
use function foobar as baz;
use const fooBAR as BAZ;
use foo as bar;
bar();
baz();
barfoo();
bazfoo();
BAR();
BAZ();
BARFOO();
BAZFOO();
bar;
baz;
barfoo;
bazfoo;
BAR;
BAZ;
BARFOO;
BAZFOO;
}
namespace Baz {
use AT{BC, DE};
use function XT{bc, de};
use const YT{BC, DE};
use ZT{G, function f, const K};
new C;
new E;
new CD;
new EF;
new G;
c();
e();
f();
C;
E;
K;
}
EOC;
$expectedCode = <<<'EOC'
namespace Foo {
use Hallo as Hi;
new FooBar();
new Hallo();
new HalloBar();
new Bar();
new FooBar();
bar();
hi();
Hallobar();
Foofoobar();
bar();
Foobar();
}
namespace {
use Hallo as Hi;
new Bar();
new Hallo();
new HalloBar();
new Bar();
new Bar();
bar();
hi();
Hallobar();
foobar();
bar();
bar();
}
namespace Bar {
use function foobar as baz;
use const fooBAR as BAZ;
use foo as bar;
bar();
foobar();
foofoo();
Barbazfoo();
BAR();
foobar();
fooFOO();
BarBAZFOO();
bar;
baz;
foofoo;
Barbazfoo;
BAR;
fooBAR;
fooFOO;
BarBAZFOO;
}
namespace Baz {
use AT{BC, DE};
use function XT{bc, de};
use const YT{BC, DE};
use ZT{G, function f, const K};
new ATBC();
new ATDE();
new ATBCD();
new ATDEF();
new ZTG();
XTbc();
XTde();
ZTf();
YTBC;
YTDE;
ZTK;
}
EOC;
$parser = new PhpParserParserPhp7(new PhpParserLexerEmulative);
$prettyPrinter = new PhpParserPrettyPrinterStandard;
$traverser = new PhpParserNodeTraverser;
$traverser->addVisitor(new NameResolver);
$stmts = $parser->parse($code);
$stmts = $traverser->traverse($stmts);
$this->assertSame(
$this->canonicalize($expectedCode),
$prettyPrinter->prettyPrint($stmts)
);
}
/**
* @covers PhpParserNodeVisitorNameResolver
*/
public function testResolveLocations() {
$code = <<<'EOC'
<?php
namespace NS;
class A extends B implements C, D {
use E, F, G {
f as private g;
E::h as i;
E::j insteadof F, G;
}
}
interface A extends C, D {
public function a(A $a) : A;
}
function fn() : A {}
function fn2() : array {}
function() : A {};
A::b();
A::$b;
A::B;
new A;
$a instanceof A;
namespacea();
namespaceA;
try {
$someThing;
} catch (A $a) {
$someThingElse;
}
EOC;
$expectedCode = <<<'EOC'
namespace NS;
class A extends NSB implements NSC, NSD
{
use NSE, NSF, NSG {
f as private g;
NSE::h as i;
NSE::j insteadof NSF, NSG;
}
}
interface A extends NSC, NSD
{
public function a(NSA $a) : NSA;
}
function fn() : NSA
{
}
function fn2() : array
{
}
function () : NSA {
};
NSA::b();
NSA::$b;
NSA::B;
new NSA();
$a instanceof NSA;
NSa();
NSA;
try {
$someThing;
} catch (NSA $a) {
$someThingElse;
}
EOC;
$parser = new PhpParserParserPhp7(new PhpParserLexerEmulative);
$prettyPrinter = new PhpParserPrettyPrinterStandard;
$traverser = new PhpParserNodeTraverser;
$traverser->addVisitor(new NameResolver);
$stmts = $parser->parse($code);
$stmts = $traverser->traverse($stmts);
$this->assertSame(
$this->canonicalize($expectedCode),
$prettyPrinter->prettyPrint($stmts)
);
}
public function testNoResolveSpecialName() {
$stmts = array(new NodeExprNew_(new Name('self')));
$traverser = new PhpParserNodeTraverser;
$traverser->addVisitor(new NameResolver);
$this->assertEquals($stmts, $traverser->traverse($stmts));
}
public function testAddNamespacedName() {
$nsStmts = array(
new StmtClass_('A'),
new StmtInterface_('B'),
new StmtFunction_('C'),
new StmtConst_(array(
new NodeConst_('D', new NodeScalarLNumber(42))
)),
new StmtTrait_('E'),
new ExprNew_(new StmtClass_(null)),
);
$traverser = new PhpParserNodeTraverser;
$traverser->addVisitor(new NameResolver);
$stmts = $traverser->traverse([new StmtNamespace_(new Name('NS'), $nsStmts)]);
$this->assertSame('NS\A', (string) $stmts[0]->stmts[0]->namespacedName);
$this->assertSame('NS\B', (string) $stmts[0]->stmts[1]->namespacedName);
$this->assertSame('NS\C', (string) $stmts[0]->stmts[2]->namespacedName);
$this->assertSame('NS\D', (string) $stmts[0]->stmts[3]->consts[0]->namespacedName);
$this->assertSame('NS\E', (string) $stmts[0]->stmts[4]->namespacedName);
$this->assertObjectNotHasAttribute('namespacedName', $stmts[0]->stmts[5]->class);
$stmts = $traverser->traverse([new StmtNamespace_(null, $nsStmts)]);
$this->assertSame('A', (string) $stmts[0]->stmts[0]->namespacedName);
$this->assertSame('B', (string) $stmts[0]->stmts[1]->namespacedName);
$this->assertSame('C', (string) $stmts[0]->stmts[2]->namespacedName);
$this->assertSame('D', (string) $stmts[0]->stmts[3]->consts[0]->namespacedName);
$this->assertSame('E', (string) $stmts[0]->stmts[4]->namespacedName);
$this->assertObjectNotHasAttribute('namespacedName', $stmts[0]->stmts[5]->class);
}
/**
* @dataProvider provideTestError
*/
public function testError(Node $stmt, $errorMsg) {
$this->setExpectedException('PhpParserError', $errorMsg);
$traverser = new PhpParserNodeTraverser;
$traverser->addVisitor(new NameResolver);
$traverser->traverse(array($stmt));
}
public function provideTestError() {
return array(
array(
new StmtUse_(array(
new StmtUseUse(new Name('AB'), 'B', 0, array('startLine' => 1)),
new StmtUseUse(new Name('CD'), 'B', 0, array('startLine' => 2)),
), StmtUse_::TYPE_NORMAL),
'Cannot use CD as B because the name is already in use on line 2'
),
array(
new StmtUse_(array(
new StmtUseUse(new Name('ab'), 'b', 0, array('startLine' => 1)),
new StmtUseUse(new Name('cd'), 'B', 0, array('startLine' => 2)),
), StmtUse_::TYPE_FUNCTION),
'Cannot use function cd as B because the name is already in use on line 2'
),
array(
new StmtUse_(array(
new StmtUseUse(new Name('AB'), 'B', 0, array('startLine' => 1)),
new StmtUseUse(new Name('CD'), 'B', 0, array('startLine' => 2)),
), StmtUse_::TYPE_CONSTANT),
'Cannot use const CD as B because the name is already in use on line 2'
),
array(
new ExprNew_(new NameFullyQualified('self', array('startLine' => 3))),
"'\self' is an invalid class name on line 3"
),
array(
new ExprNew_(new NameRelative('self', array('startLine' => 3))),
"'\self' is an invalid class name on line 3"
),
array(
new ExprNew_(new NameFullyQualified('PARENT', array('startLine' => 3))),
"'\PARENT' is an invalid class name on line 3"
),
array(
new ExprNew_(new NameRelative('STATIC', array('startLine' => 3))),
"'\STATIC' is an invalid class name on line 3"
),
);
}
public function testClassNameIsCaseInsensitive()
{
$source = <<<'EOC'
<?php
namespace Foo;
use BarBaz;
$test = new baz();
EOC;
$parser = new PhpParserParserPhp7(new PhpParserLexerEmulative);
$stmts = $parser->parse($source);
$traverser = new PhpParserNodeTraverser;
$traverser->addVisitor(new NameResolver);
$stmts = $traverser->traverse($stmts);
$stmt = $stmts[0];
$this->assertSame(array('Bar', 'Baz'), $stmt->stmts[1]->expr->class->parts);
}
public function testSpecialClassNamesAreCaseInsensitive() {
$source = <<<'EOC'
<?php
namespace Foo;
class Bar
{
public static function method()
{
SELF::method();
PARENT::method();
STATIC::method();
}
}
EOC;
$parser = new PhpParserParserPhp7(new PhpParserLexerEmulative);
$stmts = $parser->parse($source);
$traverser = new PhpParserNodeTraverser;
$traverser->addVisitor(new NameResolver);
$stmts = $traverser->traverse($stmts);
$classStmt = $stmts[0];
$methodStmt = $classStmt->stmts[0]->stmts[0];
$this->assertSame('SELF', (string)$methodStmt->stmts[0]->class);
$this->assertSame('PARENT', (string)$methodStmt->stmts[1]->class);
$this->assertSame('STATIC', (string)$methodStmt->stmts[2]->class);
}
}