From fbabe7a32b49d214ee5653cf6f0ced2f936c81ab Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 11 Aug 2011 16:54:44 -0300 Subject: Fix bug 731 - "Can't specify more than a single 'since' argument" --- abstractmetabuilder.cpp | 24 -------------------- abstractmetalang.cpp | 2 +- apiextractor.cpp | 7 +++++- apiextractor.h | 3 ++- apiextractormacros.h | 15 ++++++++----- tests/testabstractmetatype.cpp | 4 ++-- tests/testaddfunction.cpp | 2 +- tests/testcodeinjection.cpp | 4 ++-- tests/testenum.cpp | 2 +- tests/testmodifyfunction.cpp | 4 ++-- tests/testrefcounttag.cpp | 2 +- tests/testutil.h | 5 +++-- typedatabase.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++ typedatabase.h | 8 ++++--- typesystem.cpp | 36 ++++++++++++++++++----------- typesystem_p.h | 1 + 16 files changed, 110 insertions(+), 60 deletions(-) diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp index 29a21a051..f310aad4c 100644 --- a/abstractmetabuilder.cpp +++ b/abstractmetabuilder.cpp @@ -72,7 +72,6 @@ void AbstractMetaBuilder::checkFunctionModifications() TypeDatabase *types = TypeDatabase::instance(); SingleTypeEntryHash entryHash = types->entries(); QList entries = entryHash.values(); - double apiVersion = TypeDatabase::instance()->apiVersion(); foreach (TypeEntry* entry, entries) { if (!entry) @@ -84,8 +83,6 @@ void AbstractMetaBuilder::checkFunctionModifications() FunctionModificationList modifications = centry->functionModifications(); foreach (FunctionModification modification, modifications) { - if (modification.version() > apiVersion) - continue; QString signature = modification.signature; QString name = signature.trimmed(); @@ -423,11 +420,6 @@ bool AbstractMetaBuilder::build(QIODevice* input) if (!funcEntry || !funcEntry->generateCode()) continue; - if (!types->supportedApiVersion(funcEntry->version())) { - m_rejectedFunctions.insert(func->name(), ApiIncompatible); - continue; - } - AbstractMetaFunction* metaFunc = traverseFunction(func); if (!metaFunc) continue; @@ -486,11 +478,6 @@ bool AbstractMetaBuilder::build(QIODevice* input) if (entry->isPrimitive()) continue; - if (!types->supportedApiVersion(entry->version())) { - m_rejectedClasses.insert(entry->name(), ApiIncompatible); - continue; - } - if ((entry->isValue() || entry->isObject()) && !entry->isString() && !entry->isChar() @@ -606,10 +593,6 @@ bool AbstractMetaBuilder::build(QIODevice* input) // Functions added to the module on the type system. foreach (AddedFunction addedFunc, types->globalUserFunctions()) { - if (!types->supportedApiVersion(addedFunc.version())) { - m_rejectedFunctions.insert(addedFunc.name(), ApiIncompatible); - continue; - } AbstractMetaFunction* metaFunc = traverseFunction(addedFunc); metaFunc->setFunctionType(AbstractMetaFunction::NormalFunction); m_globalFunctions << metaFunc; @@ -967,13 +950,6 @@ AbstractMetaEnum* AbstractMetaBuilder::traverseEnum(EnumModelItem enumItem, Abst return 0; } - // Skipping api incompatible - if (!TypeDatabase::instance()->supportedApiVersion(typeEntry->version())) { - typeEntry->setCodeGeneration(TypeEntry::GenerateNothing); - m_rejectedEnums.insert(qualifiedName, ApiIncompatible); - return 0; - } - AbstractMetaEnum* metaEnum = createMetaEnum(); if (enumsDeclarations.contains(qualifiedName) || enumsDeclarations.contains(enumName)) { diff --git a/abstractmetalang.cpp b/abstractmetalang.cpp index 5c1641c42..04fec2d8c 100644 --- a/abstractmetalang.cpp +++ b/abstractmetalang.cpp @@ -814,7 +814,7 @@ CodeSnipList AbstractMetaFunction::injectedCodeSnips(CodeSnip::Position position { CodeSnipList result; foreach (const FunctionModification mod, modifications(ownerClass())) { - if (mod.isCodeInjection() && TypeDatabase::instance()->supportedApiVersion(mod.version())) { + if (mod.isCodeInjection()) { QList::const_iterator it = mod.snips.constBegin(); for (;it != mod.snips.constEnd(); ++it) { if ((it->language & language) && (it->position == position || position == CodeSnip::Any)) diff --git a/apiextractor.cpp b/apiextractor.cpp index 6443c0735..c26e6f690 100644 --- a/apiextractor.cpp +++ b/apiextractor.cpp @@ -106,7 +106,12 @@ void ApiExtractor::setSilent ( bool value ) void ApiExtractor::setApiVersion(double version) { - TypeDatabase::instance()->setApiVersion(version); + TypeDatabase::instance()->setApiVersion("*", QByteArray::number(version)); +} + +void ApiExtractor::setApiVersion(const QString& package, const QByteArray& version) +{ + TypeDatabase::instance()->setApiVersion(package, version); } void ApiExtractor::setDropTypeEntries(QString dropEntries) diff --git a/apiextractor.h b/apiextractor.h index 9874d1275..0a71f1a22 100644 --- a/apiextractor.h +++ b/apiextractor.h @@ -48,7 +48,8 @@ public: void addIncludePath(const QString& path); void addIncludePath(const QStringList& paths); void setLogDirectory(const QString& logDir); - void setApiVersion(double version); + APIEXTRACTOR_DEPRECATED(void setApiVersion(double version)); + void setApiVersion(const QString& package, const QByteArray& version); void setDropTypeEntries(QString dropEntries); AbstractMetaEnumList globalEnums() const; diff --git a/apiextractormacros.h b/apiextractormacros.h index 27a8778e2..1c493c23f 100644 --- a/apiextractormacros.h +++ b/apiextractormacros.h @@ -9,12 +9,15 @@ #else #define APIEXTRACTOR_API #endif -#else - #if __GNUC__ >= 4 - #define APIEXTRACTOR_API __attribute__ ((visibility("default"))) - #else - #define APIEXTRACTOR_API - #endif + #define APIEXTRACTOR_DEPRECATED(func) __declspec(deprecated) func +#elif __GNUC__ >= 4 + #define APIEXTRACTOR_API __attribute__ ((visibility("default"))) + #define APIEXTRACTOR_DEPRECATED(func) func __attribute__ ((deprecated)) +#endif + +#ifndef APIEXTRACTOR_API + #define APIEXTRACTOR_API + #define APIEXTRACTOR_API(func) func #endif #endif diff --git a/tests/testabstractmetatype.cpp b/tests/testabstractmetatype.cpp index 207ec88f0..17e5278a9 100644 --- a/tests/testabstractmetatype.cpp +++ b/tests/testabstractmetatype.cpp @@ -64,7 +64,7 @@ void TestAbstractMetaType::testApiVersionSupported() \ \ "; - TestUtil t(cppCode, xmlCode, false, 1.0); + TestUtil t(cppCode, xmlCode, false, "1.0"); AbstractMetaClassList classes = t.builder()->classes(); QCOMPARE(classes.size(), 2); @@ -81,7 +81,7 @@ void TestAbstractMetaType::testApiVersionNotSupported() const char* xmlCode = "\ \ "; - TestUtil t(cppCode, xmlCode, true, 0.1); + TestUtil t(cppCode, xmlCode, true, "0.1"); AbstractMetaClassList classes = t.builder()->classes(); QCOMPARE(classes.size(), 1); diff --git a/tests/testaddfunction.cpp b/tests/testaddfunction.cpp index 2d4ee91fd..beb49fa18 100644 --- a/tests/testaddfunction.cpp +++ b/tests/testaddfunction.cpp @@ -347,7 +347,7 @@ void TestAddFunction::testAddFunctionWithApiVersion() custom_code();\ \ "; - TestUtil t(cppCode, xmlCode, true, 0.1); + TestUtil t(cppCode, xmlCode, true, "0.1"); AbstractMetaFunctionList globalFuncs = t.builder()->globalFunctions(); QCOMPARE(globalFuncs.count(), 1); } diff --git a/tests/testcodeinjection.cpp b/tests/testcodeinjection.cpp index ab1aa8033..ed2c379c2 100644 --- a/tests/testcodeinjection.cpp +++ b/tests/testcodeinjection.cpp @@ -65,7 +65,7 @@ void TestCodeInjections::testInjectWithValidApiVersion() \ "; - TestUtil t(cppCode, xmlCode, true, 1.0); + TestUtil t(cppCode, xmlCode, true, "1.0"); AbstractMetaClassList classes = t.builder()->classes(); AbstractMetaClass* classA = classes.findClass("A"); @@ -84,7 +84,7 @@ void TestCodeInjections::testInjectWithInvalidApiVersion() \ "; - TestUtil t(cppCode, xmlCode, true, 0.1); + TestUtil t(cppCode, xmlCode, true, "0.1"); AbstractMetaClassList classes = t.builder()->classes(); AbstractMetaClass* classA = classes.findClass("A"); diff --git a/tests/testenum.cpp b/tests/testenum.cpp index 62c43c6c8..07aa0e8cb 100644 --- a/tests/testenum.cpp +++ b/tests/testenum.cpp @@ -92,7 +92,7 @@ void TestEnum::testEnumWithApiVersion() \ "; - TestUtil t(cppCode, xmlCode, true, 0.1); + TestUtil t(cppCode, xmlCode, true, "0.1"); AbstractMetaClassList classes = t.builder()->classes(); QCOMPARE(classes.count(), 1); QCOMPARE(classes[0]->enums().count(), 1); diff --git a/tests/testmodifyfunction.cpp b/tests/testmodifyfunction.cpp index 3f92e3e13..245a3e169 100644 --- a/tests/testmodifyfunction.cpp +++ b/tests/testmodifyfunction.cpp @@ -118,7 +118,7 @@ void TestModifyFunction::invalidateAfterUse() \ \ "; - TestUtil t(cppCode, xmlCode, false, 0.1); + TestUtil t(cppCode, xmlCode, false, "0.1"); AbstractMetaClassList classes = t.builder()->classes(); AbstractMetaClass* classB = classes.findClass("B"); const AbstractMetaFunction* func = classB->findFunction("call"); @@ -190,7 +190,7 @@ void TestModifyFunction::testWithApiVersion() \ \ "; - TestUtil t(cppCode, xmlCode, false, 0.1); + TestUtil t(cppCode, xmlCode, false, "0.1"); AbstractMetaClassList classes = t.builder()->classes(); AbstractMetaClass* classB = classes.findClass("B"); const AbstractMetaFunction* func = classB->findFunction("method"); diff --git a/tests/testrefcounttag.cpp b/tests/testrefcounttag.cpp index 6f6f87367..424055f2c 100644 --- a/tests/testrefcounttag.cpp +++ b/tests/testrefcounttag.cpp @@ -76,7 +76,7 @@ void TestRefCountTag::testWithApiVersion() \ "; - TestUtil t(cppCode, xmlCode, false, 0.1); + TestUtil t(cppCode, xmlCode, false, "0.1"); AbstractMetaClassList classes = t.builder()->classes(); AbstractMetaClass* classB = classes.findClass("B"); const AbstractMetaFunction* func = classB->findFunction("keepObject"); diff --git a/tests/testutil.h b/tests/testutil.h index 775f3a1c9..9519fb8b2 100644 --- a/tests/testutil.h +++ b/tests/testutil.h @@ -32,14 +32,15 @@ class TestUtil { public: TestUtil(const char* cppCode, const char* xmlCode, - bool silent = true, double apiVersion = 0, + bool silent = true, const char* apiVersion = 0, QStringList dropTypeEntries = QStringList()) : m_builder(0) { ReportHandler::setSilent(silent); m_builder = new AbstractMetaBuilder; TypeDatabase* td = TypeDatabase::instance(true); - td->setApiVersion(apiVersion); + if (apiVersion) + td->setApiVersion("*", apiVersion); td->setDropTypeEntries(dropTypeEntries); QBuffer buffer; // parse typesystem diff --git a/typedatabase.cpp b/typedatabase.cpp index 4ff2128ed..d5c1eb6ce 100644 --- a/typedatabase.cpp +++ b/typedatabase.cpp @@ -31,6 +31,11 @@ // #include #include +// package -> api-version +typedef QMap ApiVersionMap; + +Q_GLOBAL_STATIC(ApiVersionMap, apiVersions) + TypeDatabase::TypeDatabase() : m_suppressWarnings(true), m_apiVersion(0) { addType(new VoidTypeEntry()); @@ -349,6 +354,9 @@ bool TypeDatabase::parseFile(const QString &filename, bool generate) bool TypeDatabase::parseFile(QIODevice* device, bool generate) { + if (m_apiVersion) // backwards compatibility with deprecated API + setApiVersion("*", QByteArray::number(m_apiVersion)); + QXmlInputSource source(device); QXmlSimpleReader reader; Handler handler(this, generate); @@ -495,3 +503,46 @@ int getMaxTypeIndex() return maxTypeIndex; } +void TypeDatabase::setApiVersion(const QString& package, const QByteArray& version) +{ + (*apiVersions())[package.trimmed()] = version.trimmed(); +} + +/** + * Returns -1, 0 or 1 if v1 is less, equal or greater than v2 + */ +static int versionCheck(const QByteArray& v1, const QByteArray& v2) +{ + if (v1.isEmpty() || v2.isEmpty()) + return 0; + + QList v1Components = v1.split('.'); + QList v2Components = v2.split('.'); + int numComponents = qMax(v1Components.count(), v2Components.count()); + while (v1Components.count() < numComponents) + v1Components.append("0"); + while (v2Components.count() < numComponents) + v2Components.append("0"); + + for (int i = 0, max = v1Components.count(); i < max; ++i) { + int v1Comp = v1Components[i].toInt(); + int v2Comp = v2Components[i].toInt(); + if (v1Comp > v2Comp) + return 1; + else if (v1Comp < v2Comp) + return -1; + } + return 0; +} + +bool TypeDatabase::checkApiVersion(const QString& package, const QByteArray& version) const +{ + ApiVersionMap* vMap = apiVersions(); + ApiVersionMap::const_iterator it = vMap->begin(); + for (; it != vMap->end(); ++it) { + QRegExp regex(it.key(), Qt::CaseSensitive, QRegExp::Wildcard); + if (regex.exactMatch(package)) + return versionCheck(it.value(), version) >= 0; + } + return false; +} diff --git a/typedatabase.h b/typedatabase.h index ef454ff0e..8c735c1c1 100644 --- a/typedatabase.h +++ b/typedatabase.h @@ -173,17 +173,19 @@ public: bool parseFile(const QString &filename, bool generate = true); bool parseFile(QIODevice* device, bool generate = true); - double apiVersion() const + APIEXTRACTOR_DEPRECATED(double apiVersion() const) { return m_apiVersion; } - void setApiVersion(double version) + APIEXTRACTOR_DEPRECATED(void setApiVersion(double version)) { m_apiVersion = version; } + void setApiVersion(const QString& package, const QByteArray& version); - bool supportedApiVersion(double version) const; + APIEXTRACTOR_DEPRECATED(bool supportedApiVersion(double version) const); + bool checkApiVersion(const QString& package, const QByteArray& version) const; const QStringList& dropTypeEntries() const { diff --git a/typesystem.cpp b/typesystem.cpp index d062655da..0c1eae7c3 100644 --- a/typesystem.cpp +++ b/typesystem.cpp @@ -40,6 +40,7 @@ Handler::Handler(TypeDatabase* database, bool generate) m_current = 0; m_currentDroppedEntry = 0; m_currentDroppedEntryDepth = 0; + m_ignoreDepth = 0; tagNames["rejection"] = StackElement::Rejection; tagNames["primitive-type"] = StackElement::PrimitiveTypeEntry; @@ -125,6 +126,11 @@ void Handler::fetchAttributeValues(const QString &name, const QXmlAttributes &at bool Handler::endElement(const QString &, const QString &localName, const QString &) { + if (m_ignoreDepth) { + --m_ignoreDepth; + return true; + } + if (m_currentDroppedEntry) { if (m_currentDroppedEntryDepth == 1) { m_current = m_currentDroppedEntry->parent; @@ -222,7 +228,7 @@ bool Handler::endElement(const QString &, const QString &localName, const QStrin bool Handler::characters(const QString &ch) { - if (m_currentDroppedEntry) + if (m_currentDroppedEntry || m_ignoreDepth) return true; if (m_current->type == StackElement::Template) { @@ -380,6 +386,20 @@ static QString getNamePrefix(StackElement* element) bool Handler::startElement(const QString &, const QString &n, const QString &, const QXmlAttributes &atts) { + if (m_ignoreDepth) { + ++m_ignoreDepth; + return true; + } + + if (!m_defaultPackage.isEmpty() && atts.index("since") != -1) { + TypeDatabase* td = TypeDatabase::instance(); + if (!td->checkApiVersion(m_defaultPackage, atts.value("since").toAscii())) { + ++m_ignoreDepth; + return true; + } + } + + QString tagName = n.toLower(); if (tagName == "import-file") return importFileElement(atts); @@ -1016,10 +1036,6 @@ bool Handler::startElement(const QString &, const QString &n, return false; } QString name = attributes["name"]; - - if (!name.isEmpty() && m_database->supportedApiVersion(since)) - m_currentEnum->addEnumValueRejection(name); - } break; case StackElement::ReplaceType: { if (topElement.type != StackElement::ModifyArgument) { @@ -1711,13 +1727,7 @@ PrimitiveTypeEntry* PrimitiveTypeEntry::basicAliasedTypeEntry() const CodeSnipList TypeEntry::codeSnips() const { - CodeSnipList lst; - TypeDatabase *td = TypeDatabase::instance(); - foreach(CodeSnip cs, m_codeSnips) { - if (td->supportedApiVersion(cs.version)) - lst.append(cs); - } - return lst; + return m_codeSnips; } QString Modification::accessModifierString() const @@ -1735,7 +1745,7 @@ FunctionModificationList ComplexTypeEntry::functionModifications(const QString & TypeDatabase *td = TypeDatabase::instance(); for (int i = 0; i < m_functionMods.count(); ++i) { const FunctionModification &mod = m_functionMods.at(i); - if ((mod.signature == signature) && (td->supportedApiVersion(mod.version()))) + if (mod.signature == signature) lst << mod; } diff --git a/typesystem_p.h b/typesystem_p.h index d69de3fcb..0cf575509 100644 --- a/typesystem_p.h +++ b/typesystem_p.h @@ -151,6 +151,7 @@ private: StackElement* m_current; StackElement* m_currentDroppedEntry; int m_currentDroppedEntryDepth; + int m_ignoreDepth; QString m_defaultPackage; QString m_defaultSuperclass; QString m_error; -- cgit v1.2.3