Changeset View
Changeset View
Standalone View
Standalone View
duchain/tests/duchain.cpp
Show First 20 Lines • Show All 472 Lines • ▼ Show 20 Line(s) | 419 | { | |||
---|---|---|---|---|---|
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::returnTypeGenerator_data() | ||||
482 | { | ||||
483 | QTest::addColumn<QString>("code"); | ||||
484 | | ||||
485 | //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"); | ||||
487 | 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"); | ||||
489 | QTest::newRow("yield boolean expression") << QStringLiteral("<? class Generator {} function foo() { yield || 1; }\n"); | ||||
490 | QTest::newRow("yield additive expression") << QStringLiteral("<? class Generator {} function foo() { yield + 1; }\n"); | ||||
491 | QTest::newRow("yield multiplicative expression") << QStringLiteral("<? class Generator {} function foo() { yield * 2; }\n"); | ||||
492 | QTest::newRow("yield relational expression") << QStringLiteral("<? class Generator {} function foo() { yield > 1; }\n"); | ||||
493 | QTest::newRow("yield equality expression") << QStringLiteral("<? class Generator {} function foo() { yield == 1; }\n"); | ||||
494 | QTest::newRow("yield shift expression") << QStringLiteral("<? class Generator {} function foo() { yield >> 1; }\n"); | ||||
495 | QTest::newRow("yield bit expression") << QStringLiteral("<? class Generator {} function foo() { yield | 1; }\n"); | ||||
496 | QTest::newRow("multiple yield expression") << QStringLiteral("<? class Generator {} function foo() { yield 1 || yield; }\n"); | ||||
497 | QTest::newRow("yield key/value expression") << QStringLiteral("<? class Generator {} function foo() { yield 'key' => 'value'; }\n"); | ||||
498 | } | ||||
499 | | ||||
500 | void TestDUChain::returnTypeGenerator() | ||||
501 | { | ||||
502 | QFETCH(QString, code); | ||||
503 | | ||||
504 | TopDUContext* top = parse(code.toUtf8(), DumpNone); | ||||
505 | DUChainReleaser releaseTop(top); | ||||
506 | DUChainWriteLocker lock(DUChain::lock()); | ||||
507 | | ||||
508 | QVERIFY(!top->parentContext()); | ||||
509 | QCOMPARE(top->childContexts().count(), 3); | ||||
510 | QCOMPARE(top->localDeclarations().count(), 2); | ||||
511 | | ||||
512 | Declaration* dec = top->localDeclarations().at(1); | ||||
513 | QCOMPARE(dec->qualifiedIdentifier(), QualifiedIdentifier("foo")); | ||||
514 | FunctionType::Ptr functionType = dec->type<FunctionType>(); | ||||
515 | QVERIFY(functionType); | ||||
516 | StructureType::Ptr retType = StructureType::Ptr::dynamicCast(functionType->returnType()); | ||||
517 | QVERIFY(retType); | ||||
518 | QCOMPARE(retType->qualifiedIdentifier(), QualifiedIdentifier("generator")); | ||||
519 | } | ||||
520 | | ||||
521 | void TestDUChain::returnTypeGeneratorDelegation() | ||||
522 | { | ||||
523 | //Note: in practice, Generator is defined by php, but this class is not loaded in this test, so define it ourselves | ||||
524 | // 0 1 2 3 4 5 6 7 | ||||
525 | // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 | ||||
526 | QByteArray method("<? class Generator {} function foo() { yield 1; } function bar() { yield from foo(); }\n"); | ||||
527 | | ||||
528 | TopDUContext* top = parse(method, DumpNone); | ||||
529 | DUChainReleaser releaseTop(top); | ||||
530 | DUChainWriteLocker lock(DUChain::lock()); | ||||
531 | | ||||
532 | QVERIFY(!top->parentContext()); | ||||
533 | QCOMPARE(top->childContexts().count(), 5); | ||||
534 | QCOMPARE(top->localDeclarations().count(), 3); | ||||
535 | | ||||
536 | Declaration* dec = top->localDeclarations().at(1); | ||||
537 | QCOMPARE(dec->qualifiedIdentifier(), QualifiedIdentifier("foo")); | ||||
538 | FunctionType::Ptr functionType = dec->type<FunctionType>(); | ||||
539 | QVERIFY(functionType); | ||||
540 | StructureType::Ptr retType = StructureType::Ptr::dynamicCast(functionType->returnType()); | ||||
541 | QVERIFY(retType); | ||||
542 | QCOMPARE(retType->qualifiedIdentifier(), QualifiedIdentifier("generator")); | ||||
543 | | ||||
544 | dec = top->localDeclarations().at(2); | ||||
545 | QCOMPARE(dec->qualifiedIdentifier(), QualifiedIdentifier("bar")); | ||||
546 | functionType = dec->type<FunctionType>(); | ||||
547 | QVERIFY(functionType); | ||||
548 | retType = StructureType::Ptr::dynamicCast(functionType->returnType()); | ||||
549 | QVERIFY(retType); | ||||
550 | QCOMPARE(retType->qualifiedIdentifier(), QualifiedIdentifier("generator")); | ||||
551 | } | ||||
552 | | ||||
481 | void TestDUChain::returnTypeClass() | 553 | void TestDUChain::returnTypeClass() | ||
482 | { | 554 | { | ||
483 | // 0 1 2 3 4 5 6 7 | 555 | // 0 1 2 3 4 5 6 7 | ||
484 | // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 | 556 | // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 | ||
485 | QByteArray method("<? class A {} function foo() { return new A(); } function bar() { $i = new A(); return $i; }"); | 557 | QByteArray method("<? class A {} function foo() { return new A(); } function bar() { $i = new A(); return $i; }"); | ||
486 | 558 | | |||
487 | TopDUContext* top = parse(method, DumpNone); | 559 | TopDUContext* top = parse(method, DumpNone); | ||
488 | DUChainReleaser releaseTop(top); | 560 | DUChainReleaser releaseTop(top); | ||
▲ Show 20 Lines • Show All 3333 Lines • ▼ Show 20 Line(s) | 3892 | { | |||
3822 | 3894 | | |||
3823 | TopDUContext* top = parse(code.toUtf8(), DumpNone); | 3895 | TopDUContext* top = parse(code.toUtf8(), DumpNone); | ||
3824 | QVERIFY(top); | 3896 | QVERIFY(top); | ||
3825 | DUChainReleaser releaseTop(top); | 3897 | DUChainReleaser releaseTop(top); | ||
3826 | DUChainWriteLocker lock(DUChain::lock()); | 3898 | DUChainWriteLocker lock(DUChain::lock()); | ||
3827 | 3899 | | |||
3828 | QVERIFY(top->problems().isEmpty()); | 3900 | QVERIFY(top->problems().isEmpty()); | ||
3829 | } | 3901 | } | ||
3902 | | ||||
3903 | void TestDUChain::generatorAssignment() | ||||
3904 | { | ||||
3905 | //Note: in practice, Generator is defined by php, but this class is not loaded in this test, so define it ourselves | ||||
3906 | // 0 1 2 3 4 5 6 7 | ||||
3907 | // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 | ||||
3908 | QByteArray method("<? class Generator {} function foo() { $a = yield 1; }\n"); | ||||
3909 | | ||||
3910 | TopDUContext* top = parse(method, DumpNone); | ||||
3911 | QVERIFY(top); | ||||
3912 | DUChainReleaser releaseTop(top); | ||||
3913 | DUChainWriteLocker lock(DUChain::lock()); | ||||
3914 | | ||||
3915 | QVERIFY(!top->parentContext()); | ||||
3916 | QCOMPARE(top->childContexts().count(), 3); | ||||
3917 | QCOMPARE(top->localDeclarations().count(), 2); | ||||
3918 | | ||||
3919 | Declaration* dec = top->localDeclarations().at(1); | ||||
3920 | QCOMPARE(dec->qualifiedIdentifier(), QualifiedIdentifier("foo")); | ||||
3921 | FunctionType::Ptr functionType = dec->type<FunctionType>(); | ||||
3922 | QVERIFY(functionType); | ||||
3923 | StructureType::Ptr retType = StructureType::Ptr::dynamicCast(functionType->returnType()); | ||||
3924 | QVERIFY(retType); | ||||
3925 | QCOMPARE(retType->qualifiedIdentifier(), QualifiedIdentifier("generator")); | ||||
3926 | | ||||
3927 | dec = top->childContexts().at(2)->localDeclarations().at(0); | ||||
3928 | QCOMPARE(dec->identifier(), Identifier("a")); | ||||
3929 | IntegralType::Ptr type = dec->type<IntegralType>(); | ||||
3930 | QVERIFY(type); | ||||
3931 | QVERIFY(type->dataType() == IntegralType::TypeMixed); | ||||
3932 | } | ||||
3933 | | ||||
3934 | void TestDUChain::generatorClosure() | ||||
3935 | { | ||||
3936 | //Note: in practice, Generator is defined by php, but this class is not loaded in this test, so define it ourselves | ||||
3937 | // 0 1 2 3 4 5 6 7 | ||||
3938 | // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 | ||||
3939 | QByteArray method("<? class Generator {} function foo() { $a = function() { $b = function() { yield 1; }; }; }\n"); | ||||
3940 | | ||||
3941 | TopDUContext* top = parse(method, DumpNone); | ||||
3942 | QVERIFY(top); | ||||
3943 | DUChainReleaser releaseTop(top); | ||||
3944 | DUChainWriteLocker lock(DUChain::lock()); | ||||
3945 | | ||||
3946 | QVERIFY(!top->parentContext()); | ||||
3947 | QCOMPARE(top->childContexts().count(), 3); | ||||
3948 | QCOMPARE(top->localDeclarations().count(), 2); | ||||
3949 | | ||||
3950 | Declaration* dec = top->localDeclarations().at(1); | ||||
3951 | QCOMPARE(dec->qualifiedIdentifier(), QualifiedIdentifier("foo")); | ||||
3952 | FunctionType::Ptr functionType = dec->type<FunctionType>(); | ||||
3953 | QVERIFY(functionType); | ||||
3954 | IntegralType::Ptr retType = IntegralType::Ptr::dynamicCast(functionType->returnType()); | ||||
3955 | QVERIFY(retType); | ||||
3956 | QVERIFY(retType->dataType() == IntegralType::TypeVoid); | ||||
3957 | | ||||
3958 | dec = top->childContexts().at(2)->localDeclarations().at(0); | ||||
3959 | QCOMPARE(dec->identifier(), Identifier("a")); | ||||
3960 | | ||||
3961 | Declaration* closure = top->childContexts().at(2)->localDeclarations().at(1); | ||||
3962 | QVERIFY(closure->identifier().isEmpty()); | ||||
3963 | | ||||
3964 | FunctionType::Ptr funcType = closure->type<FunctionType>(); | ||||
3965 | QVERIFY(funcType); | ||||
3966 | QVERIFY(funcType->returnType().cast<IntegralType>()); | ||||
3967 | QCOMPARE(funcType->returnType().cast<IntegralType>()->dataType(), static_cast<uint>(IntegralType::TypeVoid)); | ||||
3968 | | ||||
3969 | QVERIFY(dec->abstractType()->equals(closure->abstractType().constData())); | ||||
3970 | | ||||
3971 | dec = top->childContexts().at(2)->childContexts().at(1)->localDeclarations().at(0); | ||||
3972 | QCOMPARE(dec->identifier(), Identifier("b")); | ||||
3973 | | ||||
3974 | closure = top->childContexts().at(2)->childContexts().at(1)->localDeclarations().at(1); | ||||
3975 | QVERIFY(closure->identifier().isEmpty()); | ||||
3976 | | ||||
3977 | funcType = closure->type<FunctionType>(); | ||||
3978 | QVERIFY(funcType); | ||||
3979 | StructureType::Ptr generatorType = StructureType::Ptr::dynamicCast(funcType->returnType()); | ||||
3980 | QVERIFY(generatorType); | ||||
3981 | QCOMPARE(generatorType->qualifiedIdentifier(), QualifiedIdentifier("generator")); | ||||
3982 | | ||||
3983 | QVERIFY(dec->abstractType()->equals(closure->abstractType().constData())); | ||||
3984 | } |