diff options
-rw-r--r-- | abstractmetabuilder.cpp | 21 | ||||
-rw-r--r-- | doc/typesystem_specifying_types.rst | 20 | ||||
-rw-r--r-- | tests/testaddfunction.cpp | 24 | ||||
-rw-r--r-- | tests/testimplicitconversions.cpp | 42 | ||||
-rw-r--r-- | tests/testnestedtypes.cpp | 4 | ||||
-rw-r--r-- | typedatabase.cpp | 23 | ||||
-rw-r--r-- | typesystem.cpp | 4 | ||||
-rw-r--r-- | typesystem_p.h | 1 |
8 files changed, 82 insertions, 57 deletions
diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp index abdf5c70a..1d01e9ce2 100644 --- a/abstractmetabuilder.cpp +++ b/abstractmetabuilder.cpp @@ -2018,8 +2018,25 @@ AbstractMetaType* AbstractMetaBuilder::translateType(double vr, const AddedFunct } if (!type) { - type = new TypeEntry(typeInfo.name, TypeEntry::CustomType, vr); - typeDb->addType(type); + QStringList candidates; + SingleTypeEntryHash entries = typeDb->entries(); + foreach (QString candidate, entries.keys()) { + // Let's try to find the type in different scopes. + if (candidate.endsWith("::"+typeName)) + candidates << candidate; + } + + QString msg = QString("Type '%1' wasn't found in the type database.\n").arg(typeName); + + if (candidates.isEmpty()) + qFatal(qPrintable(QString(msg + "Declare it in the type system using the proper <*-type> tag.")), NULL); + + msg += "Remember to inform the full qualified name for the type you want to use.\nCandidates are:\n"; + candidates.sort(); + foreach (const QString& candidate, candidates) { + msg += " " + candidate + "\n"; + } + qFatal(qPrintable(msg), NULL); } AbstractMetaType* metaType = createMetaType(); diff --git a/doc/typesystem_specifying_types.rst b/doc/typesystem_specifying_types.rst index d5a4ef2d9..0d24a6d52 100644 --- a/doc/typesystem_specifying_types.rst +++ b/doc/typesystem_specifying_types.rst @@ -328,6 +328,26 @@ container-type The *optional* **since** value is used to specify the API version of this container. + +.. _custom-type: + +custom-type +^^^^^^^^^^^ + + The custom-type node simply makes the parser aware of the existence of a target + language type, thus avoiding errors when trying to find a type used in function + signatures and other places. The proper handling of the custom type is meant to + be done by a generator using the APIExractor. + + .. code-block:: xml + + <typesystem> + <custom-type name="..." /> + </typesystem> + + The **name** attribute is the name of the custom type, e.g., "PyObject". + + .. _function: function diff --git a/tests/testaddfunction.cpp b/tests/testaddfunction.cpp index beb49fa18..c1189c346 100644 --- a/tests/testaddfunction.cpp +++ b/tests/testaddfunction.cpp @@ -67,7 +67,7 @@ void TestAddFunction::testAddFunction() { const char cppCode[] = "struct B {}; struct A { void a(int); };"; const char xmlCode[] = "\ - <typesystem package=\"Foo\">\ + <typesystem package='Foo'>\ <primitive-type name='int' />\ <primitive-type name='float' />\ <value-type name='B' />\ @@ -108,7 +108,8 @@ void TestAddFunction::testAddFunctionConstructor() { const char cppCode[] = "struct A { A() {} };"; const char xmlCode[] = "\ - <typesystem package=\"Foo\">\ + <typesystem package='Foo'>\ + <primitive-type name='int' />\ <value-type name='A'>\ <add-function signature='A(int)' />\ </value-type>\ @@ -130,7 +131,7 @@ void TestAddFunction::testAddFunctionTagDefaultValues() { const char cppCode[] = "struct A {};"; const char xmlCode[] = "\ - <typesystem package=\"Foo\">\ + <typesystem package='Foo'>\ <value-type name='A'>\ <add-function signature='func()' />\ </value-type>\ @@ -151,7 +152,7 @@ void TestAddFunction::testAddFunctionCodeSnippets() { const char cppCode[] = "struct A {};"; const char xmlCode[] = "\ - <typesystem package=\"Foo\">\ + <typesystem package='Foo'>\ <value-type name='A'>\ <add-function signature='func()'>\ <inject-code class='target' position='end'>Hi!, I am the code.</inject-code>\ @@ -178,7 +179,7 @@ void TestAddFunction::testAddFunctionWithoutParenteses() const char cppCode[] = "struct A {};"; const char xmlCode[] = "\ - <typesystem package=\"Foo\">\ + <typesystem package='Foo'>\ <value-type name='A'>\ <add-function signature='func'>\ <inject-code class='target' position='end'>Hi!, I am the code.</inject-code>\ @@ -207,7 +208,7 @@ void TestAddFunction::testAddFunctionWithDefaultArgs() const char cppCode[] = "struct A { };"; const char xmlCode[] = "\ - <typesystem package=\"Foo\">\ + <typesystem package='Foo'>\ <primitive-type name='int'/> \ <value-type name='A'>\ <add-function signature='func(int, int)'>\ @@ -232,7 +233,7 @@ void TestAddFunction::testAddFunctionAtModuleLevel() { const char cppCode[] = "struct A { };"; const char xmlCode[] = "\ - <typesystem package=\"Foo\">\ + <typesystem package='Foo'>\ <primitive-type name='int'/> \ <value-type name='A'/>\ <add-function signature='func(int, int)'>\ @@ -270,7 +271,7 @@ void TestAddFunction::testAddFunctionWithVarargs() const char cppCode[] = "struct A {};"; const char xmlCode[] = "\ - <typesystem package=\"Foo\">\ + <typesystem package='Foo'>\ <primitive-type name='int'/> \ <primitive-type name='char'/> \ <value-type name='A'>\ @@ -293,7 +294,7 @@ void TestAddFunction::testAddStaticFunction() { const char cppCode[] = "struct A { };"; const char xmlCode[] = "\ - <typesystem package=\"Foo\">\ + <typesystem package='Foo'>\ <primitive-type name='int'/> \ <value-type name='A'>\ <add-function signature='func(int, int)' static='yes'>\ @@ -314,7 +315,7 @@ void TestAddFunction::testAddGlobalFunction() { const char cppCode[] = "struct A { };struct B {};"; const char xmlCode[] = "\ - <typesystem package=\"Foo\">\ + <typesystem package='Foo'>\ <primitive-type name='int'/> \ <value-type name='A' />\ <add-function signature='globalFunc(int, int)' static='yes'>\ @@ -385,9 +386,10 @@ void TestAddFunction::testAddFunctionOnTypedef() const char cppCode[] = "template<class T> class Foo { }; typedef Foo<int> FooInt;"; const char xmlCode[] = "\ <typesystem package='Package'>\ + <custom-type name='PySequence'/>\ <primitive-type name='int'/>\ <value-type name='FooInt'>\ - <add-function signature='FooInt(PySequence*)'>\ + <add-function signature='FooInt(PySequence)'>\ <inject-code class='target' position='beginning'>custom_code();</inject-code>\ </add-function>\ <add-function signature='method()'>\ diff --git a/tests/testimplicitconversions.cpp b/tests/testimplicitconversions.cpp index 86032acaf..4bc4d73fc 100644 --- a/tests/testimplicitconversions.cpp +++ b/tests/testimplicitconversions.cpp @@ -30,22 +30,20 @@ void TestImplicitConversions::testWithPrivateCtors() const char* cppCode ="\ class B;\ class C;\ - \ class A {\ A(const B&);\ public:\ A(const C&);\ };\ - \ class B {};\ class C {};\ "; const char* xmlCode = "\ - <typesystem package=\"Foo\"> \ - <value-type name=\"A\"/> \ - <value-type name=\"B\"/> \ - <value-type name=\"C\"/> \ - </typesystem>"; + <typesystem package='Foo'> \ + <value-type name='A'/> \ + <value-type name='B'/> \ + <value-type name='C'/> \ + </typesystem>"; TestUtil t(cppCode, xmlCode); AbstractMetaClassList classes = t.builder()->classes(); QCOMPARE(classes.count(), 3); @@ -65,18 +63,17 @@ void TestImplicitConversions::testWithModifiedVisibility() public:\ A(const B&);\ };\ - \ class B {};\ "; const char* xmlCode = "\ - <typesystem package=\"Foo\">\ - <value-type name=\"A\">\ + <typesystem package='Foo'>\ + <value-type name='A'>\ <modify-function signature='A(const B&)'>\ <access modifier='private' />\ </modify-function>\ </value-type>\ - <value-type name=\"B\"/>\ - </typesystem>"; + <value-type name='B'/>\ + </typesystem>"; TestUtil t(cppCode, xmlCode); AbstractMetaClassList classes = t.builder()->classes(); QCOMPARE(classes.count(), 2); @@ -96,20 +93,20 @@ void TestImplicitConversions::testWithAddedCtor() public:\ A(const B&);\ };\ - \ class B {};\ class C {};\ "; const char* xmlCode = "\ - <typesystem package=\"Foo\">\ - <value-type name=\"A\">\ + <typesystem package='Foo'>\ + <custom-type name='TARGETLANGTYPE' />\ + <value-type name='A'>\ <add-function signature='A(const C&)' />\ </value-type>\ - <value-type name=\"B\">\ + <value-type name='B'>\ <add-function signature='B(TARGETLANGTYPE*)' />\ </value-type>\ - <value-type name=\"C\"/>\ - </typesystem>"; + <value-type name='C'/>\ + </typesystem>"; TestUtil t(cppCode, xmlCode); AbstractMetaClassList classes = t.builder()->classes(); QCOMPARE(classes.count(), 3); @@ -133,10 +130,10 @@ void TestImplicitConversions::testWithExternalConversionOperator() };\ "; const char* xmlCode = "\ - <typesystem package=\"Foo\">\ - <value-type name=\"A\"/>\ - <value-type name=\"B\"/>\ - </typesystem>"; + <typesystem package='Foo'>\ + <value-type name='A'/>\ + <value-type name='B'/>\ + </typesystem>"; TestUtil t(cppCode, xmlCode); AbstractMetaClassList classes = t.builder()->classes(); QCOMPARE(classes.count(), 2); @@ -159,4 +156,3 @@ void TestImplicitConversions::testWithExternalConversionOperator() QTEST_APPLESS_MAIN(TestImplicitConversions) #include "testimplicitconversions.moc" - diff --git a/tests/testnestedtypes.cpp b/tests/testnestedtypes.cpp index 4e000cb08..83512f7db 100644 --- a/tests/testnestedtypes.cpp +++ b/tests/testnestedtypes.cpp @@ -93,7 +93,7 @@ void TestNestedTypes::testDuplicationOfNestedTypes() <typesystem package='Foo'> \ <namespace-type name='Namespace'>\ <value-type name='SomeClass'>\ - <add-function signature='createSomeClass(SomeClass)'/>\ + <add-function signature='createSomeClass(Namespace::SomeClass)'/>\ </value-type>\ </namespace-type>\ </typesystem>"; @@ -114,7 +114,7 @@ void TestNestedTypes::testDuplicationOfNestedTypes() TypeEntry* t1 = TypeDatabase::instance()->findType("Namespace::SomeClass"); QVERIFY(t1); TypeEntry* t2 = TypeDatabase::instance()->findType("SomeClass"); - QCOMPARE(t1, t2); + QVERIFY(!t2); } QTEST_APPLESS_MAIN(TestNestedTypes) diff --git a/typedatabase.cpp b/typedatabase.cpp index 1247bf7f3..d5c1eb6ce 100644 --- a/typedatabase.cpp +++ b/typedatabase.cpp @@ -141,29 +141,14 @@ PrimitiveTypeEntry* TypeDatabase::findTargetLangPrimitiveType(const QString& tar TypeEntry* TypeDatabase::findType(const QString& name) const { - TypeEntry* typeEntry = 0; - QList<TypeEntry *> typeEntries = findTypes(name); - - if (typeEntries.isEmpty()) { - SingleTypeEntryHash entriesHash = entries(); - foreach (QString typeName, entriesHash.keys()) { - // Let's try to find the type in different scopes. - // We will prefer the ones with the least depth. - if (typeName.endsWith("::"+name) - && (!typeEntry || typeEntry->qualifiedCppName().count("::") < typeName.count("::"))) { - typeEntry = entriesHash[typeName]; - } - } - } - - foreach (TypeEntry* entry, typeEntries) { + QList<TypeEntry *> entries = findTypes(name); + foreach (TypeEntry *entry, entries) { if (entry && (!entry->isPrimitive() || static_cast<PrimitiveTypeEntry *>(entry)->preferredTargetLangType())) { - typeEntry = entry; - break; + return entry; } } - return typeEntry; + return 0; } SingleTypeEntryHash TypeDatabase::entries() const diff --git a/typesystem.cpp b/typesystem.cpp index 8808e5314..a08c2df2e 100644 --- a/typesystem.cpp +++ b/typesystem.cpp @@ -45,6 +45,7 @@ Handler::Handler(TypeDatabase* database, bool generate) m_ignoreDepth = 0; tagNames["rejection"] = StackElement::Rejection; + tagNames["custom-type"] = StackElement::CustomTypeEntry; tagNames["primitive-type"] = StackElement::PrimitiveTypeEntry; tagNames["container-type"] = StackElement::ContainerTypeEntry; tagNames["object-type"] = StackElement::ObjectTypeEntry; @@ -629,6 +630,9 @@ bool Handler::startElement(const QString &, const QString &n, } switch (element->type) { + case StackElement::CustomTypeEntry: + element->entry = new TypeEntry(name, TypeEntry::CustomType, since); + break; case StackElement::PrimitiveTypeEntry: { QString targetLangName = attributes["target-lang-name"]; QString targetLangApiName = attributes["target-lang-api-name"]; diff --git a/typesystem_p.h b/typesystem_p.h index 371321bc2..e8f5f2406 100644 --- a/typesystem_p.h +++ b/typesystem_p.h @@ -46,6 +46,7 @@ class StackElement EnumTypeEntry = 0x9, ContainerTypeEntry = 0xa, FunctionTypeEntry = 0xb, + CustomTypeEntry = 0xc, TypeEntryMask = 0xf, // Documentation tags |