Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/php-static-scanner-instrumentalization.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/nikic/php-parser/test/PhpParser/NodeVisitor/NameResolverTest.php')
-rw-r--r--vendor/nikic/php-parser/test/PhpParser/NodeVisitor/NameResolverTest.php449
1 files changed, 449 insertions, 0 deletions
diff --git a/vendor/nikic/php-parser/test/PhpParser/NodeVisitor/NameResolverTest.php b/vendor/nikic/php-parser/test/PhpParser/NodeVisitor/NameResolverTest.php
new file mode 100644
index 0000000..a9c6cb5
--- /dev/null
+++ b/vendor/nikic/php-parser/test/PhpParser/NodeVisitor/NameResolverTest.php
@@ -0,0 +1,449 @@
+<?php
+
+namespace PhpParser\NodeVisitor;
+
+use PhpParser;
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+use PhpParser\Node\Name;
+use PhpParser\Node\Stmt;
+
+class NameResolverTest extends \PHPUnit_Framework_TestCase
+{
+ private function canonicalize($string) {
+ return str_replace("\r\n", "\n", $string);
+ }
+
+ /**
+ * @covers PhpParser\NodeVisitor\NameResolver
+ */
+ public function testResolveNames() {
+ $code = <<<'EOC'
+<?php
+
+namespace Foo {
+ use Hallo as Hi;
+
+ new Bar();
+ new Hi();
+ new Hi\Bar();
+ new \Bar();
+ new namespace\Bar();
+
+ bar();
+ hi();
+ Hi\bar();
+ foo\bar();
+ \bar();
+ namespace\bar();
+}
+namespace {
+ use Hallo as Hi;
+
+ new Bar();
+ new Hi();
+ new Hi\Bar();
+ new \Bar();
+ new namespace\Bar();
+
+ bar();
+ hi();
+ Hi\bar();
+ foo\bar();
+ \bar();
+ namespace\bar();
+}
+namespace Bar {
+ use function foo\bar as baz;
+ use const foo\BAR as BAZ;
+ use foo as bar;
+
+ bar();
+ baz();
+ bar\foo();
+ baz\foo();
+ BAR();
+ BAZ();
+ BAR\FOO();
+ BAZ\FOO();
+
+ bar;
+ baz;
+ bar\foo;
+ baz\foo;
+ BAR;
+ BAZ;
+ BAR\FOO;
+ BAZ\FOO;
+}
+namespace Baz {
+ use A\T\{B\C, D\E};
+ use function X\T\{b\c, d\e};
+ use const Y\T\{B\C, D\E};
+ use Z\T\{G, function f, const K};
+
+ new C;
+ new E;
+ new C\D;
+ new E\F;
+ new G;
+
+ c();
+ e();
+ f();
+ C;
+ E;
+ K;
+}
+EOC;
+ $expectedCode = <<<'EOC'
+namespace Foo {
+ use Hallo as Hi;
+ new \Foo\Bar();
+ new \Hallo();
+ new \Hallo\Bar();
+ new \Bar();
+ new \Foo\Bar();
+ bar();
+ hi();
+ \Hallo\bar();
+ \Foo\foo\bar();
+ \bar();
+ \Foo\bar();
+}
+namespace {
+ use Hallo as Hi;
+ new \Bar();
+ new \Hallo();
+ new \Hallo\Bar();
+ new \Bar();
+ new \Bar();
+ \bar();
+ \hi();
+ \Hallo\bar();
+ \foo\bar();
+ \bar();
+ \bar();
+}
+namespace Bar {
+ use function foo\bar as baz;
+ use const foo\BAR as BAZ;
+ use foo as bar;
+ bar();
+ \foo\bar();
+ \foo\foo();
+ \Bar\baz\foo();
+ BAR();
+ \foo\bar();
+ \foo\FOO();
+ \Bar\BAZ\FOO();
+ bar;
+ baz;
+ \foo\foo;
+ \Bar\baz\foo;
+ BAR;
+ \foo\BAR;
+ \foo\FOO;
+ \Bar\BAZ\FOO;
+}
+namespace Baz {
+ use A\T\{B\C, D\E};
+ use function X\T\{b\c, d\e};
+ use const Y\T\{B\C, D\E};
+ use Z\T\{G, function f, const K};
+ new \A\T\B\C();
+ new \A\T\D\E();
+ new \A\T\B\C\D();
+ new \A\T\D\E\F();
+ new \Z\T\G();
+ \X\T\b\c();
+ \X\T\d\e();
+ \Z\T\f();
+ \Y\T\B\C;
+ \Y\T\D\E;
+ \Z\T\K;
+}
+EOC;
+
+ $parser = new PhpParser\Parser\Php7(new PhpParser\Lexer\Emulative);
+ $prettyPrinter = new PhpParser\PrettyPrinter\Standard;
+ $traverser = new PhpParser\NodeTraverser;
+ $traverser->addVisitor(new NameResolver);
+
+ $stmts = $parser->parse($code);
+ $stmts = $traverser->traverse($stmts);
+
+ $this->assertSame(
+ $this->canonicalize($expectedCode),
+ $prettyPrinter->prettyPrint($stmts)
+ );
+ }
+
+ /**
+ * @covers PhpParser\NodeVisitor\NameResolver
+ */
+ 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 $a) : A {}
+function fn2(array $a) : array {}
+function(A $a) : A {};
+
+function fn3(?A $a) : ?A {}
+function fn4(?array $a) : ?array {}
+
+A::b();
+A::$b;
+A::B;
+new A;
+$a instanceof A;
+
+namespace\a();
+namespace\A;
+
+try {
+ $someThing;
+} catch (A $a) {
+ $someThingElse;
+}
+EOC;
+ $expectedCode = <<<'EOC'
+namespace NS;
+
+class A extends \NS\B implements \NS\C, \NS\D
+{
+ use \NS\E, \NS\F, \NS\G {
+ f as private g;
+ \NS\E::h as i;
+ \NS\E::j insteadof \NS\F, \NS\G;
+ }
+}
+interface A extends \NS\C, \NS\D
+{
+ public function a(\NS\A $a) : \NS\A;
+}
+function fn(\NS\A $a) : \NS\A
+{
+}
+function fn2(array $a) : array
+{
+}
+function (\NS\A $a) : \NS\A {
+};
+function fn3(?\NS\A $a) : ?\NS\A
+{
+}
+function fn4(?array $a) : ?array
+{
+}
+\NS\A::b();
+\NS\A::$b;
+\NS\A::B;
+new \NS\A();
+$a instanceof \NS\A;
+\NS\a();
+\NS\A;
+try {
+ $someThing;
+} catch (\NS\A $a) {
+ $someThingElse;
+}
+EOC;
+
+ $parser = new PhpParser\Parser\Php7(new PhpParser\Lexer\Emulative);
+ $prettyPrinter = new PhpParser\PrettyPrinter\Standard;
+ $traverser = new PhpParser\NodeTraverser;
+ $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 Node\Expr\New_(new Name('self')));
+
+ $traverser = new PhpParser\NodeTraverser;
+ $traverser->addVisitor(new NameResolver);
+
+ $this->assertEquals($stmts, $traverser->traverse($stmts));
+ }
+
+ public function testAddDeclarationNamespacedName() {
+ $nsStmts = array(
+ new Stmt\Class_('A'),
+ new Stmt\Interface_('B'),
+ new Stmt\Function_('C'),
+ new Stmt\Const_(array(
+ new Node\Const_('D', new Node\Scalar\LNumber(42))
+ )),
+ new Stmt\Trait_('E'),
+ new Expr\New_(new Stmt\Class_(null)),
+ );
+
+ $traverser = new PhpParser\NodeTraverser;
+ $traverser->addVisitor(new NameResolver);
+
+ $stmts = $traverser->traverse([new Stmt\Namespace_(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 Stmt\Namespace_(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);
+ }
+
+ public function testAddRuntimeResolvedNamespacedName() {
+ $stmts = array(
+ new Stmt\Namespace_(new Name('NS'), array(
+ new Expr\FuncCall(new Name('foo')),
+ new Expr\ConstFetch(new Name('FOO')),
+ )),
+ new Stmt\Namespace_(null, array(
+ new Expr\FuncCall(new Name('foo')),
+ new Expr\ConstFetch(new Name('FOO')),
+ )),
+ );
+
+ $traverser = new PhpParser\NodeTraverser;
+ $traverser->addVisitor(new NameResolver);
+ $stmts = $traverser->traverse($stmts);
+
+ $this->assertSame('NS\\foo', (string) $stmts[0]->stmts[0]->name->getAttribute('namespacedName'));
+ $this->assertSame('NS\\FOO', (string) $stmts[0]->stmts[1]->name->getAttribute('namespacedName'));
+
+ $this->assertFalse($stmts[1]->stmts[0]->name->hasAttribute('namespacedName'));
+ $this->assertFalse($stmts[1]->stmts[1]->name->hasAttribute('namespacedName'));
+ }
+
+ /**
+ * @dataProvider provideTestError
+ */
+ public function testError(Node $stmt, $errorMsg) {
+ $this->setExpectedException('PhpParser\Error', $errorMsg);
+
+ $traverser = new PhpParser\NodeTraverser;
+ $traverser->addVisitor(new NameResolver);
+ $traverser->traverse(array($stmt));
+ }
+
+ public function provideTestError() {
+ return array(
+ array(
+ new Stmt\Use_(array(
+ new Stmt\UseUse(new Name('A\B'), 'B', 0, array('startLine' => 1)),
+ new Stmt\UseUse(new Name('C\D'), 'B', 0, array('startLine' => 2)),
+ ), Stmt\Use_::TYPE_NORMAL),
+ 'Cannot use C\D as B because the name is already in use on line 2'
+ ),
+ array(
+ new Stmt\Use_(array(
+ new Stmt\UseUse(new Name('a\b'), 'b', 0, array('startLine' => 1)),
+ new Stmt\UseUse(new Name('c\d'), 'B', 0, array('startLine' => 2)),
+ ), Stmt\Use_::TYPE_FUNCTION),
+ 'Cannot use function c\d as B because the name is already in use on line 2'
+ ),
+ array(
+ new Stmt\Use_(array(
+ new Stmt\UseUse(new Name('A\B'), 'B', 0, array('startLine' => 1)),
+ new Stmt\UseUse(new Name('C\D'), 'B', 0, array('startLine' => 2)),
+ ), Stmt\Use_::TYPE_CONSTANT),
+ 'Cannot use const C\D as B because the name is already in use on line 2'
+ ),
+ array(
+ new Expr\New_(new Name\FullyQualified('self', array('startLine' => 3))),
+ "'\\self' is an invalid class name on line 3"
+ ),
+ array(
+ new Expr\New_(new Name\Relative('self', array('startLine' => 3))),
+ "'\\self' is an invalid class name on line 3"
+ ),
+ array(
+ new Expr\New_(new Name\FullyQualified('PARENT', array('startLine' => 3))),
+ "'\\PARENT' is an invalid class name on line 3"
+ ),
+ array(
+ new Expr\New_(new Name\Relative('STATIC', array('startLine' => 3))),
+ "'\\STATIC' is an invalid class name on line 3"
+ ),
+ );
+ }
+
+ public function testClassNameIsCaseInsensitive()
+ {
+ $source = <<<'EOC'
+<?php
+namespace Foo;
+use Bar\Baz;
+$test = new baz();
+EOC;
+
+ $parser = new PhpParser\Parser\Php7(new PhpParser\Lexer\Emulative);
+ $stmts = $parser->parse($source);
+
+ $traverser = new PhpParser\NodeTraverser;
+ $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 PhpParser\Parser\Php7(new PhpParser\Lexer\Emulative);
+ $stmts = $parser->parse($source);
+
+ $traverser = new PhpParser\NodeTraverser;
+ $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);
+ }
+}