Changeset View
Changeset View
Standalone View
Standalone View
duchain/tests/duchain.cpp
Show First 20 Lines • Show All 441 Lines • ▼ Show 20 Line(s) | 419 | { | |||
---|---|---|---|---|---|
442 | 442 | | |||
443 | //$foo | 443 | //$foo | ||
444 | ClassMemberDeclaration* var = dynamic_cast<ClassMemberDeclaration*>(contextClassA->localDeclarations().first()); | 444 | ClassMemberDeclaration* var = dynamic_cast<ClassMemberDeclaration*>(contextClassA->localDeclarations().first()); | ||
445 | QVERIFY(var); | 445 | QVERIFY(var); | ||
446 | QCOMPARE(var->identifier(), Identifier("foo")); | 446 | QCOMPARE(var->identifier(), Identifier("foo")); | ||
447 | QCOMPARE(var->accessPolicy(), Declaration::Public); | 447 | QCOMPARE(var->accessPolicy(), Declaration::Public); | ||
448 | QCOMPARE(var->isStatic(), false); | 448 | QCOMPARE(var->isStatic(), false); | ||
449 | QVERIFY(var->type<IntegralType>()); | 449 | QVERIFY(var->type<IntegralType>()); | ||
450 | QVERIFY(var->type<IntegralType>()->dataType() == IntegralType::TypeMixed); | 450 | QVERIFY(var->type<IntegralType>()->dataType() == IntegralType::TypeNull); | ||
451 | 451 | | |||
452 | //$bar | 452 | //$bar | ||
453 | var = dynamic_cast<ClassMemberDeclaration*>(contextClassA->localDeclarations().at(1)); | 453 | var = dynamic_cast<ClassMemberDeclaration*>(contextClassA->localDeclarations().at(1)); | ||
454 | QVERIFY(var); | 454 | QVERIFY(var); | ||
455 | QCOMPARE(var->identifier(), Identifier("bar")); | 455 | QCOMPARE(var->identifier(), Identifier("bar")); | ||
456 | QCOMPARE(var->accessPolicy(), Declaration::Protected); | 456 | QCOMPARE(var->accessPolicy(), Declaration::Protected); | ||
457 | QCOMPARE(var->isStatic(), false); | 457 | QCOMPARE(var->isStatic(), false); | ||
458 | StructureType::Ptr type = var->type<StructureType>(); | 458 | StructureType::Ptr type = var->type<StructureType>(); | ||
Show All 14 Lines | |||||
473 | QVERIFY(var); | 473 | QVERIFY(var); | ||
474 | QCOMPARE(var->identifier(), Identifier("boo")); | 474 | QCOMPARE(var->identifier(), Identifier("boo")); | ||
475 | QCOMPARE(var->accessPolicy(), Declaration::Public); | 475 | QCOMPARE(var->accessPolicy(), Declaration::Public); | ||
476 | QCOMPARE(var->isStatic(), false); | 476 | QCOMPARE(var->isStatic(), false); | ||
477 | QVERIFY(var->type<IntegralType>()); | 477 | QVERIFY(var->type<IntegralType>()); | ||
478 | QVERIFY(var->type<IntegralType>()->dataType() == IntegralType::TypeInt); | 478 | QVERIFY(var->type<IntegralType>()->dataType() == IntegralType::TypeInt); | ||
479 | } | 479 | } | ||
480 | 480 | | |||
481 | void TestDUChain::classMemberVarAfterUse() | ||||
482 | { | ||||
483 | // 0 1 2 3 4 5 6 7 | ||||
484 | // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 | ||||
485 | QByteArray method("<?php class B { function x() { $this->a = 1; } public $a = 1; }"); | ||||
486 | | ||||
487 | TopDUContext* top = parse(method, DumpNone); | ||||
488 | DUChainReleaser releaseTop(top); | ||||
489 | DUChainWriteLocker lock(DUChain::lock()); | ||||
490 | | ||||
491 | QVERIFY(!top->parentContext()); | ||||
492 | QCOMPARE(top->childContexts().count(), 1); | ||||
493 | QVERIFY(top->problems().isEmpty()); | ||||
494 | | ||||
495 | DUContext* contextClassB = top->childContexts().first(); | ||||
496 | | ||||
497 | QCOMPARE(top->localDeclarations().count(), 1); | ||||
498 | Declaration* dec = top->localDeclarations().first(); | ||||
499 | QCOMPARE(dec->qualifiedIdentifier(), QualifiedIdentifier("b")); | ||||
500 | QCOMPARE(dec->isDefinition(), true); | ||||
501 | QCOMPARE(dec->logicalInternalContext(top), contextClassB); | ||||
502 | | ||||
503 | QCOMPARE(contextClassB->localScopeIdentifier(), QualifiedIdentifier("b")); | ||||
504 | QCOMPARE(contextClassB->childContexts().count(), 2); | ||||
505 | QCOMPARE(contextClassB->localDeclarations().count(), 2); | ||||
506 | | ||||
507 | //$foo | ||||
508 | ClassMemberDeclaration* var = dynamic_cast<ClassMemberDeclaration*>(contextClassB->localDeclarations().at(1)); | ||||
509 | QVERIFY(var); | ||||
510 | QCOMPARE(var->identifier(), Identifier("a")); | ||||
511 | QCOMPARE(var->accessPolicy(), Declaration::Public); | ||||
512 | QCOMPARE(var->isStatic(), false); | ||||
513 | QVERIFY(var->type<IntegralType>()); | ||||
514 | QVERIFY(var->type<IntegralType>()->dataType() == IntegralType::TypeInt); | ||||
515 | QVERIFY(var->range() == RangeInRevision(0, 54, 0, 56)); | ||||
516 | } | ||||
517 | | ||||
518 | void TestDUChain::classMemberVarDocBlockType() | ||||
519 | { | ||||
520 | // 0 1 2 3 4 5 6 7 | ||||
521 | // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 | ||||
522 | QByteArray method("<? namespace Test { class A {} }\n" | ||||
523 | "namespace Test2 { class B { /** @var \\Test\\A **/ public $foo; } }\n" | ||||
524 | ); | ||||
525 | | ||||
526 | TopDUContext* top = parse(method, DumpNone); | ||||
527 | DUChainReleaser releaseTop(top); | ||||
528 | DUChainWriteLocker lock(DUChain::lock()); | ||||
529 | | ||||
530 | QVERIFY(!top->parentContext()); | ||||
531 | QCOMPARE(top->childContexts().count(), 2); | ||||
532 | | ||||
533 | DUContext* contextClassA = top->childContexts().at(0)->childContexts().first(); | ||||
534 | DUContext* contextClassB = top->childContexts().at(1)->childContexts().first(); | ||||
535 | | ||||
536 | QCOMPARE(top->localDeclarations().count(), 2); | ||||
537 | Declaration* dec = top->childContexts().first()->localDeclarations().first(); | ||||
538 | QCOMPARE(dec->qualifiedIdentifier(), QualifiedIdentifier("test::a")); | ||||
539 | QCOMPARE(dec->isDefinition(), true); | ||||
540 | | ||||
541 | QCOMPARE(contextClassA->localScopeIdentifier(), QualifiedIdentifier("a")); | ||||
542 | QCOMPARE(contextClassA->childContexts().count(), 0); | ||||
543 | QCOMPARE(contextClassA->localDeclarations().count(), 0); | ||||
544 | | ||||
545 | QCOMPARE(contextClassB->localScopeIdentifier(), QualifiedIdentifier("b")); | ||||
546 | QCOMPARE(contextClassB->childContexts().count(), 0); | ||||
547 | QCOMPARE(contextClassB->localDeclarations().count(), 1); | ||||
548 | | ||||
549 | //$foo | ||||
550 | ClassMemberDeclaration* var = dynamic_cast<ClassMemberDeclaration*>(contextClassB->localDeclarations().first()); | ||||
551 | QVERIFY(var); | ||||
552 | QCOMPARE(var->identifier(), Identifier("foo")); | ||||
553 | QCOMPARE(var->accessPolicy(), Declaration::Public); | ||||
554 | QCOMPARE(var->isStatic(), false); | ||||
555 | StructureType::Ptr type = var->type<StructureType>(); | ||||
556 | QVERIFY(type); | ||||
557 | QCOMPARE(type->qualifiedIdentifier(), QualifiedIdentifier("test::a")); | ||||
558 | } | ||||
559 | | ||||
481 | void TestDUChain::returnTypeGenerator_data() | 560 | void TestDUChain::returnTypeGenerator_data() | ||
482 | { | 561 | { | ||
483 | QTest::addColumn<QString>("code"); | 562 | QTest::addColumn<QString>("code"); | ||
484 | 563 | | |||
485 | //Note: in practice, Generator is defined by php, but this class is not loaded in this test, so define it ourselves | 564 | //Note: in practice, Generator is defined by php, but this class is not loaded in this test, so define it ourselves | ||
486 | QTest::newRow("simple yield expression") << QStringLiteral("<? class Generator {} function foo() { yield 1; }\n"); | 565 | QTest::newRow("simple yield expression") << QStringLiteral("<? class Generator {} function foo() { yield 1; }\n"); | ||
487 | QTest::newRow("yield assignment expression") << QStringLiteral("<? class Generator {} function foo() { yield $a = 1; }\n"); | 566 | QTest::newRow("yield assignment expression") << QStringLiteral("<? class Generator {} function foo() { yield $a = 1; }\n"); | ||
488 | QTest::newRow("yield null-coalesce expression") << QStringLiteral("<? class Generator {} function foo() { yield ?? 1; }\n"); | 567 | QTest::newRow("yield null-coalesce expression") << QStringLiteral("<? class Generator {} function foo() { yield ?? 1; }\n"); | ||
▲ Show 20 Lines • Show All 1933 Lines • ▼ Show 20 Line(s) | 2477 | { | |||
2422 | // public $bar | 2501 | // public $bar | ||
2423 | { | 2502 | { | ||
2424 | ClassMemberDeclaration* var = dynamic_cast<ClassMemberDeclaration*>(contextClassA->localDeclarations().at(1)); | 2503 | ClassMemberDeclaration* var = dynamic_cast<ClassMemberDeclaration*>(contextClassA->localDeclarations().at(1)); | ||
2425 | QVERIFY(var); | 2504 | QVERIFY(var); | ||
2426 | QCOMPARE(var->identifier(), Identifier("bar")); | 2505 | QCOMPARE(var->identifier(), Identifier("bar")); | ||
2427 | QCOMPARE(var->accessPolicy(), Declaration::Public); | 2506 | QCOMPARE(var->accessPolicy(), Declaration::Public); | ||
2428 | QCOMPARE(var->isStatic(), false); | 2507 | QCOMPARE(var->isStatic(), false); | ||
2429 | QVERIFY(var->type<IntegralType>()); | 2508 | QVERIFY(var->type<IntegralType>()); | ||
2430 | QVERIFY(var->type<IntegralType>()->dataType() == IntegralType::TypeMixed); | 2509 | QVERIFY(var->type<IntegralType>()->dataType() == IntegralType::TypeNull); | ||
2431 | } | 2510 | } | ||
2432 | } | 2511 | } | ||
2433 | 2512 | | |||
2434 | 2513 | | |||
2435 | void TestDUChain::catchDeclaration() | 2514 | void TestDUChain::catchDeclaration() | ||
2436 | { | 2515 | { | ||
2437 | // 0 1 2 3 4 5 6 7 | 2516 | // 0 1 2 3 4 5 6 7 | ||
2438 | // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 | 2517 | // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 | ||
▲ Show 20 Lines • Show All 357 Lines • ▼ Show 20 Line(s) | 2874 | { | |||
2796 | Declaration *dec = decs.last(); | 2875 | Declaration *dec = decs.last(); | ||
2797 | QVERIFY(dynamic_cast<ClassDeclaration*>(dec)); | 2876 | QVERIFY(dynamic_cast<ClassDeclaration*>(dec)); | ||
2798 | QVERIFY(dec->type<StructureType>()); | 2877 | QVERIFY(dec->type<StructureType>()); | ||
2799 | QVERIFY(dec->type<StructureType>()->declaration(top)->identifier().nameEquals(Identifier("a"))); | 2878 | QVERIFY(dec->type<StructureType>()->declaration(top)->identifier().nameEquals(Identifier("a"))); | ||
2800 | } | 2879 | } | ||
2801 | 2880 | | |||
2802 | { // check if x got declared | 2881 | { // check if x got declared | ||
2803 | QList<Declaration*> decs = top->childContexts().first()->findDeclarations(Identifier(QStringLiteral("x"))); | 2882 | QList<Declaration*> decs = top->childContexts().first()->findDeclarations(Identifier(QStringLiteral("x"))); | ||
2804 | // the type of both assignments to $bar->asdf are the same, hence it should only be declared once | 2883 | // the type of both assignments to $a->x are the same, hence it should only be declared once | ||
2805 | QCOMPARE(decs.size(), 1); | 2884 | QCOMPARE(decs.size(), 1); | ||
2806 | ClassMemberDeclaration* cmdec = dynamic_cast<ClassMemberDeclaration*>(decs.first()); | 2885 | ClassMemberDeclaration* cmdec = dynamic_cast<ClassMemberDeclaration*>(decs.first()); | ||
2807 | QVERIFY(cmdec); | 2886 | QVERIFY(cmdec); | ||
2808 | QVERIFY(cmdec->accessPolicy() == Declaration::Public); | 2887 | QVERIFY(cmdec->accessPolicy() == Declaration::Public); | ||
2809 | QVERIFY(!cmdec->isStatic()); | 2888 | QVERIFY(!cmdec->isStatic()); | ||
2810 | QVERIFY(cmdec->type<IntegralType>()); | 2889 | QVERIFY(cmdec->type<IntegralType>()); | ||
2811 | QCOMPARE(cmdec->type<IntegralType>()->dataType(), (uint) IntegralType::TypeInt); | 2890 | QCOMPARE(cmdec->type<IntegralType>()->dataType(), (uint) IntegralType::TypeInt); | ||
2812 | } | 2891 | } | ||
2813 | } | 2892 | } | ||
2814 | 2893 | | |||
2815 | void TestDUChain::declareMemberInClassMethod() | 2894 | void TestDUChain::declareMemberInClassMethod() | ||
2816 | { | 2895 | { | ||
2817 | QByteArray code("<? class foo { private $priv = 0; protected $prot = 0; } class bar extends foo {\n" | 2896 | QByteArray code("<? class foo { private $priv = 0; protected $prot = 0; } class bar extends foo {\n" | ||
2818 | // should declare member variable asdf (once!) as public | 2897 | // should declare member variable asdf (once!) as public | ||
2819 | " function test() { $this->asdf = true; $this->asdf = false; }\n" | 2898 | " function test() { $this->asdf = true; $this->asdf = false; }\n" | ||
2820 | // should only declare bar once as private | 2899 | // should only declare bar once as private | ||
2821 | " private $xyz = 0; function test2() { $this->xyz = 42; }\n" | 2900 | " private $xyz = 0; function test2() { $this->xyz = 42; }\n" | ||
2822 | // should not create any local declarations, and issue an error for trying to | 2901 | // should create a local declaration for the private attribute | ||
2823 | // assign something to a private member variable of a parent class | | |||
2824 | " function test3() { $this->prot = 42;\n$this->priv = 42; }\n" | 2902 | " function test3() { $this->prot = 42;\n$this->priv = 42; }\n" | ||
2825 | " }"); | 2903 | " }"); | ||
2826 | TopDUContext* top = parse(code, DumpAST); | 2904 | TopDUContext* top = parse(code, DumpAST); | ||
2827 | DUChainReleaser releaseTop(top); | 2905 | DUChainReleaser releaseTop(top); | ||
2828 | DUChainWriteLocker lock(DUChain::lock()); | 2906 | DUChainWriteLocker lock(DUChain::lock()); | ||
2829 | 2907 | | |||
2830 | { // asdf | 2908 | { // asdf | ||
2831 | QList<Declaration*> decs = top->childContexts().last()->findLocalDeclarations(Identifier(QStringLiteral("asdf"))); | 2909 | QList<Declaration*> decs = top->childContexts().last()->findLocalDeclarations(Identifier(QStringLiteral("asdf"))); | ||
Show All 12 Lines | 2919 | { // xyz | |||
2844 | ClassMemberDeclaration *dec = dynamic_cast<ClassMemberDeclaration*>(decs.first()); | 2922 | ClassMemberDeclaration *dec = dynamic_cast<ClassMemberDeclaration*>(decs.first()); | ||
2845 | QVERIFY(dec); | 2923 | QVERIFY(dec); | ||
2846 | QVERIFY(dec->accessPolicy() == Declaration::Private); | 2924 | QVERIFY(dec->accessPolicy() == Declaration::Private); | ||
2847 | QVERIFY(!dec->isStatic()); | 2925 | QVERIFY(!dec->isStatic()); | ||
2848 | QVERIFY(dec->type<IntegralType>()); | 2926 | QVERIFY(dec->type<IntegralType>()); | ||
2849 | QVERIFY(dec->type<IntegralType>()->dataType() == IntegralType::TypeInt); | 2927 | QVERIFY(dec->type<IntegralType>()->dataType() == IntegralType::TypeInt); | ||
2850 | } | 2928 | } | ||
2851 | 2929 | | |||
2852 | { // prot and priv | 2930 | { // priv | ||
2931 | QList<Declaration*> decs = top->childContexts().last()->findLocalDeclarations(Identifier(QStringLiteral("priv"))); | ||||
2932 | QCOMPARE(decs.size(), 1); | ||||
2933 | ClassMemberDeclaration *dec = dynamic_cast<ClassMemberDeclaration*>(decs.first()); | ||||
2934 | QVERIFY(dec); | ||||
2935 | QVERIFY(dec->accessPolicy() == Declaration::Public); | ||||
2936 | QVERIFY(!dec->isStatic()); | ||||
2937 | QVERIFY(dec->type<IntegralType>()); | ||||
2938 | QVERIFY(dec->type<IntegralType>()->dataType() == IntegralType::TypeInt); | ||||
2939 | } | ||||
2940 | | ||||
2941 | { // prot | ||||
2853 | QVERIFY(top->childContexts().last()->findLocalDeclarations(Identifier("prot")).isEmpty()); | 2942 | QVERIFY(top->childContexts().last()->findLocalDeclarations(Identifier("prot")).isEmpty()); | ||
2854 | QVERIFY(top->childContexts().last()->findLocalDeclarations(Identifier("priv")).isEmpty()); | | |||
2855 | } | 2943 | } | ||
2856 | 2944 | | |||
2857 | // only one problem: error trying to assign to a private member of a parent class | 2945 | QCOMPARE(top->problems().count(), 0); | ||
2858 | QCOMPARE(top->problems().count(), 1); | | |||
2859 | QCOMPARE(top->problems().first()->finalLocation().start().line(), 4); | | |||
2860 | } | 2946 | } | ||
2861 | 2947 | | |||
2862 | void TestDUChain::thisRedeclaration() | 2948 | void TestDUChain::thisRedeclaration() | ||
2863 | { | 2949 | { | ||
2864 | // 0 1 2 3 4 5 6 7 | 2950 | // 0 1 2 3 4 5 6 7 | ||
2865 | // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 | 2951 | // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 | ||
2866 | QByteArray code("<? class foo{ function foo(){ $this->test = true; $this = false;} }"); | 2952 | QByteArray code("<? class foo{ function foo(){ $this->test = true; $this = false;} }"); | ||
2867 | TopDUContext* top = parse(code, DumpAST); | 2953 | TopDUContext* top = parse(code, DumpAST); | ||
▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Line(s) | 3032 | { | |||
2975 | // a is already declared | 3061 | // a is already declared | ||
2976 | QList<Declaration*> decs = top->childContexts().last()->findDeclarations(Identifier(QStringLiteral("a"))); | 3062 | QList<Declaration*> decs = top->childContexts().last()->findDeclarations(Identifier(QStringLiteral("a"))); | ||
2977 | QCOMPARE(decs.size(), 1); | 3063 | QCOMPARE(decs.size(), 1); | ||
2978 | ClassMemberDeclaration* cmdec = dynamic_cast<ClassMemberDeclaration*>(decs.first()); | 3064 | ClassMemberDeclaration* cmdec = dynamic_cast<ClassMemberDeclaration*>(decs.first()); | ||
2979 | QVERIFY(cmdec); | 3065 | QVERIFY(cmdec); | ||
2980 | QVERIFY(cmdec->type<IntegralType>()); | 3066 | QVERIFY(cmdec->type<IntegralType>()); | ||
2981 | 3067 | | |||
2982 | qDebug() << cmdec->type<IntegralType>()->dataType() << cmdec->toString(); | 3068 | qDebug() << cmdec->type<IntegralType>()->dataType() << cmdec->toString(); | ||
2983 | QVERIFY(cmdec->type<IntegralType>()->dataType() == IntegralType::TypeMixed); | 3069 | QVERIFY(cmdec->type<IntegralType>()->dataType() == IntegralType::TypeNull); | ||
2984 | } | 3070 | } | ||
2985 | } | 3071 | } | ||
2986 | 3072 | | |||
2987 | void TestDUChain::classContextRange() | 3073 | void TestDUChain::classContextRange() | ||
2988 | { | 3074 | { | ||
2989 | // 0 1 2 3 4 5 6 7 | 3075 | // 0 1 2 3 4 5 6 7 | ||
2990 | // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 | 3076 | // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 | ||
2991 | QByteArray code("<?php class A { } $a = new A; ?> <?php $b = 1; $a->foobar = 1; $a->barFoo= 0;"); | 3077 | QByteArray code("<?php class A { } $a = new A; ?> <?php $b = 1; $a->foobar = 1; $a->barFoo= 0;"); | ||
▲ Show 20 Lines • Show All 993 Lines • Show Last 20 Lines |