Changeset View
Changeset View
Standalone View
Standalone View
duchain/tests/duchain.cpp
Show First 20 Lines • Show All 732 Lines • ▼ Show 20 Line(s) | 728 | { | |||
---|---|---|---|---|---|
733 | TopDUContext* top = parse(method, DumpAll); | 733 | TopDUContext* top = parse(method, DumpAll); | ||
734 | DUChainReleaser releaseTop(top); | 734 | DUChainReleaser releaseTop(top); | ||
735 | 735 | | |||
736 | DUChainWriteLocker lock(DUChain::lock()); | 736 | DUChainWriteLocker lock(DUChain::lock()); | ||
737 | 737 | | |||
738 | FunctionType::Ptr fun = top->localDeclarations().first()->type<FunctionType>(); | 738 | FunctionType::Ptr fun = top->localDeclarations().first()->type<FunctionType>(); | ||
739 | QVERIFY(fun); | 739 | QVERIFY(fun); | ||
740 | QCOMPARE(fun->arguments().count(), 1); | 740 | QCOMPARE(fun->arguments().count(), 1); | ||
741 | QVERIFY(IntegralType::Ptr::dynamicCast(fun->arguments().first())); | 741 | QVERIFY(IntegralTypeExtended::Ptr::dynamicCast(fun->arguments().first())); | ||
742 | QVERIFY(IntegralType::Ptr::dynamicCast(fun->arguments().first())->dataType() == IntegralType::TypeMixed); | 742 | QVERIFY(IntegralTypeExtended::Ptr::dynamicCast(fun->arguments().first())->dataType() == IntegralTypeExtended::TypeCallable); | ||
743 | 743 | | |||
744 | IntegralType::Ptr type = top->childContexts().first()->localDeclarations().first()->type<IntegralType>(); | 744 | IntegralTypeExtended::Ptr type = top->childContexts().first()->localDeclarations().first()->type<IntegralTypeExtended>(); | ||
745 | QVERIFY(type); | 745 | QVERIFY(type); | ||
746 | QVERIFY(type->dataType() == IntegralType::TypeMixed); | 746 | QVERIFY(type->dataType() == IntegralTypeExtended::TypeCallable); | ||
747 | } | ||||
748 | | ||||
749 | void Php::TestDUChain::functionWithCallableAndFunctionReturn() | ||||
750 | { | ||||
751 | QByteArray method("<? function foo(callable $i) { return $i; return function () {}; } "); | ||||
zhigalin: For `return $i();` the return type should be mixed, not callable | |||||
Both return statements return a callable: $i (note: without ()) is a callable, and function () {} is a callable too. So I think this behaviour is correct, but correct me if I'm wrong. mtijink: Both return statements return a callable: `$i` (note: without `()`) is a callable, and… | |||||
The problem arises then you return the result of calling $i() and the parser still think you're returning a callable zhigalin: The problem arises then you return the **result** of calling `$i()` and the parser still think… | |||||
Ah ok, you're correct. But that's not due to a problem in this code, but problems in the ExpressionVisitor: it skips most operators, such that the resulting type is that of the last appearing variable/literal. Thus, it applies the type of $i instead of the result of calling the function. For example, function foo() { $i = function () {}; return $i(); } yields type void () foo (), which also is incorrect. mtijink: Ah ok, you're correct. But that's not due to a problem in this code, but problems in the… | |||||
zhigalin: Okay then, commiting | |||||
752 | | ||||
753 | TopDUContext* top = parse(method, DumpAll); | ||||
754 | DUChainReleaser releaseTop(top); | ||||
755 | | ||||
756 | DUChainWriteLocker lock(DUChain::lock()); | ||||
757 | | ||||
758 | FunctionType::Ptr fun = top->localDeclarations().first()->type<FunctionType>(); | ||||
759 | QVERIFY(fun); | ||||
760 | QCOMPARE(fun->arguments().count(), 1); | ||||
761 | QVERIFY(IntegralTypeExtended::Ptr::dynamicCast(fun->arguments().first())); | ||||
762 | QVERIFY(IntegralTypeExtended::Ptr::dynamicCast(fun->arguments().first())->dataType() == IntegralTypeExtended::TypeCallable); | ||||
763 | | ||||
764 | IntegralTypeExtended::Ptr retType = IntegralTypeExtended::Ptr::dynamicCast(fun->returnType()); | ||||
765 | QVERIFY(retType); | ||||
766 | QVERIFY(retType->dataType() == IntegralTypeExtended::TypeCallable); | ||||
747 | } | 767 | } | ||
748 | 768 | | |||
749 | void TestDUChain::declareTypehintIterableFunction() | 769 | void TestDUChain::declareTypehintIterableFunction() | ||
750 | { | 770 | { | ||
751 | //Note: in practice, Traversable is defined by php, but this interface is not loaded in this test, so define it ourselves | 771 | //Note: in practice, Traversable is defined by php, but this interface is not loaded in this test, so define it ourselves | ||
752 | // 0 1 2 3 | 772 | // 0 1 2 3 | ||
753 | // 0123456789012345678901234567890123 | 773 | // 0123456789012345678901234567890123 | ||
754 | QByteArray method("<? interface Traversable { } function foo(iterable $i) { } "); | 774 | QByteArray method("<? interface Traversable { } function foo(iterable $i) { } "); | ||
▲ Show 20 Lines • Show All 154 Lines • ▼ Show 20 Line(s) | 916 | { | |||
909 | QVERIFY(IntegralType::Ptr::dynamicCast(fun->arguments().first())); | 929 | QVERIFY(IntegralType::Ptr::dynamicCast(fun->arguments().first())); | ||
910 | QVERIFY(IntegralType::Ptr::dynamicCast(fun->arguments().first())->dataType() == IntegralType::TypeInt); | 930 | QVERIFY(IntegralType::Ptr::dynamicCast(fun->arguments().first())->dataType() == IntegralType::TypeInt); | ||
911 | 931 | | |||
912 | IntegralType::Ptr type = top->childContexts().first()->localDeclarations().first()->type<IntegralType>(); | 932 | IntegralType::Ptr type = top->childContexts().first()->localDeclarations().first()->type<IntegralType>(); | ||
913 | QVERIFY(type); | 933 | QVERIFY(type); | ||
914 | QVERIFY(type->dataType() == IntegralType::TypeInt); | 934 | QVERIFY(type->dataType() == IntegralType::TypeInt); | ||
915 | } | 935 | } | ||
916 | 936 | | |||
917 | void TestDUChain::declareNullableTypehintCallableFunction() | 937 | void TestDUChain::declareNullableTypehintMixedFunction() | ||
918 | { | 938 | { | ||
919 | // 0 1 2 3 | 939 | // 0 1 2 3 | ||
920 | // 0123456789012345678901234567890123 | 940 | // 0123456789012345678901234567890123 | ||
921 | QByteArray method("<? function foo(?callable $i) { } "); | 941 | QByteArray method("<? function foo(?UnknownClass $i) { } "); | ||
922 | 942 | | |||
923 | TopDUContext* top = parse(method, DumpAll); | 943 | TopDUContext* top = parse(method, DumpAll); | ||
924 | DUChainReleaser releaseTop(top); | 944 | DUChainReleaser releaseTop(top); | ||
925 | 945 | | |||
926 | DUChainWriteLocker lock(DUChain::lock()); | 946 | DUChainWriteLocker lock(DUChain::lock()); | ||
927 | 947 | | |||
928 | FunctionType::Ptr fun = top->localDeclarations().first()->type<FunctionType>(); | 948 | FunctionType::Ptr fun = top->localDeclarations().first()->type<FunctionType>(); | ||
929 | QVERIFY(fun); | 949 | QVERIFY(fun); | ||
▲ Show 20 Lines • Show All 2471 Lines • Show Last 20 Lines |
For return $i(); the return type should be mixed, not callable