From 4889efc199243af54cf71accffb3f9554cba933d Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Fri, 23 Dec 2011 15:10:17 -0300 Subject: Added the "" tag, and better requirements for function signatures. Trying to find a non-qualified (without scope information) class, found in a function signature or return type, was a bad idea for it makes the parsing awfully slow when dealing with huge libraries. If the user writes a type in short form in a function signature (e.g. "SomeClass", instead of "Namespace::SomeClass"), APIExtractor will exit with a message indicating the error and the possible candidates for the type. The "" tag is for types of the target language ("PyObject" in Python, for instance) and will be handled by the generator. Reviewed by Hugo Parente Reviewed by Paulo Alcantara --- abstractmetabuilder.cpp | 21 +++++++++++++++++-- doc/typesystem_specifying_types.rst | 20 ++++++++++++++++++ tests/testaddfunction.cpp | 24 +++++++++++---------- tests/testimplicitconversions.cpp | 42 +++++++++++++++++-------------------- tests/testnestedtypes.cpp | 4 ++-- typedatabase.cpp | 23 ++++---------------- typesystem.cpp | 4 ++++ 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 + + + + + + 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[] = "\ - \ + \ \ \ \ @@ -108,7 +108,8 @@ void TestAddFunction::testAddFunctionConstructor() { const char cppCode[] = "struct A { A() {} };"; const char xmlCode[] = "\ - \ + \ + \ \ \ \ @@ -130,7 +131,7 @@ void TestAddFunction::testAddFunctionTagDefaultValues() { const char cppCode[] = "struct A {};"; const char xmlCode[] = "\ - \ + \ \ \ \ @@ -151,7 +152,7 @@ void TestAddFunction::testAddFunctionCodeSnippets() { const char cppCode[] = "struct A {};"; const char xmlCode[] = "\ - \ + \ \ \ Hi!, I am the code.\ @@ -178,7 +179,7 @@ void TestAddFunction::testAddFunctionWithoutParenteses() const char cppCode[] = "struct A {};"; const char xmlCode[] = "\ - \ + \ \ \ Hi!, I am the code.\ @@ -207,7 +208,7 @@ void TestAddFunction::testAddFunctionWithDefaultArgs() const char cppCode[] = "struct A { };"; const char xmlCode[] = "\ - \ + \ \ \ \ @@ -232,7 +233,7 @@ void TestAddFunction::testAddFunctionAtModuleLevel() { const char cppCode[] = "struct A { };"; const char xmlCode[] = "\ - \ + \ \ \ \ @@ -270,7 +271,7 @@ void TestAddFunction::testAddFunctionWithVarargs() const char cppCode[] = "struct A {};"; const char xmlCode[] = "\ - \ + \ \ \ \ @@ -293,7 +294,7 @@ void TestAddFunction::testAddStaticFunction() { const char cppCode[] = "struct A { };"; const char xmlCode[] = "\ - \ + \ \ \ \ @@ -314,7 +315,7 @@ void TestAddFunction::testAddGlobalFunction() { const char cppCode[] = "struct A { };struct B {};"; const char xmlCode[] = "\ - \ + \ \ \ \ @@ -385,9 +386,10 @@ void TestAddFunction::testAddFunctionOnTypedef() const char cppCode[] = "template class Foo { }; typedef Foo FooInt;"; const char xmlCode[] = "\ \ + \ \ \ - \ + \ custom_code();\ \ \ 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 = "\ - \ - \ - \ - \ - "; + \ + \ + \ + \ + "; 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 = "\ - \ - \ + \ + \ \ \ \ \ - \ - "; + \ + "; 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 = "\ - \ - \ + \ + \ + \ \ \ - \ + \ \ \ - \ - "; + \ + "; TestUtil t(cppCode, xmlCode); AbstractMetaClassList classes = t.builder()->classes(); QCOMPARE(classes.count(), 3); @@ -133,10 +130,10 @@ void TestImplicitConversions::testWithExternalConversionOperator() };\ "; const char* xmlCode = "\ - \ - \ - \ - "; + \ + \ + \ + "; 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() \ \ \ - \ + \ \ \ "; @@ -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 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 entries = findTypes(name); + foreach (TypeEntry *entry, entries) { if (entry && (!entry->isPrimitive() || static_cast(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 -- cgit v1.2.3