diff options
-rw-r--r-- | abstractmetabuilder.cpp | 111 | ||||
-rw-r--r-- | typedatabase.cpp | 70 | ||||
-rw-r--r-- | typedatabase.h | 4 |
3 files changed, 133 insertions, 52 deletions
diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp index 45ceab872..d8e5514c9 100644 --- a/abstractmetabuilder.cpp +++ b/abstractmetabuilder.cpp @@ -478,55 +478,64 @@ bool AbstractMetaBuilder::build(QIODevice* input) } ReportHandler::flush(); - QList<TypeEntry*> entries = types->entries().values(); - ReportHandler::setProgressReference(entries); - foreach (const TypeEntry *entry, entries) { - ReportHandler::progress("Detecting inconsistencies in typesystem..."); + TypeEntryHash allEntries = types->allEntries(); + ReportHandler::progress("Detecting inconsistencies in typesystem..."); + foreach (QList<TypeEntry*> entries, allEntries) { + foreach (TypeEntry* entry, entries) { - if (entry->isPrimitive()) - continue; + if (entry->isPrimitive()) + continue; - if (!types->supportedApiVersion(entry->version())) { - m_rejectedClasses.insert(entry->name(), ApiIncompatible); - continue; - } + if (!types->supportedApiVersion(entry->version())) { + m_rejectedClasses.insert(entry->name(), ApiIncompatible); + continue; + } - if ((entry->isValue() || entry->isObject()) - && !entry->isString() - && !entry->isChar() - && !entry->isContainer() - && !entry->isCustom() - && !entry->isVariant() - && !m_metaClasses.findClass(entry->qualifiedCppName())) { - ReportHandler::warning(QString("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.") - .arg(entry->qualifiedCppName())); - } else if (entry->generateCode() && entry->type() == TypeEntry::FunctionType) { - const FunctionTypeEntry* fte = static_cast<const FunctionTypeEntry*>(entry); - foreach (QString signature, fte->signatures()) { - bool ok = false; - foreach (AbstractMetaFunction* func, m_globalFunctions) { - if (signature == func->minimalSignature()) { - ok = true; - break; + if ((entry->isValue() || entry->isObject()) + && !entry->isString() + && !entry->isChar() + && !entry->isContainer() + && !entry->isCustom() + && !entry->isVariant() + && !m_metaClasses.findClass(entry->qualifiedCppName())) { + ReportHandler::warning(QString("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.") + .arg(entry->qualifiedCppName())); + } else if (entry->generateCode() && entry->type() == TypeEntry::FunctionType) { + const FunctionTypeEntry* fte = static_cast<const FunctionTypeEntry*>(entry); + foreach (QString signature, fte->signatures()) { + bool ok = false; + foreach (AbstractMetaFunction* func, m_globalFunctions) { + if (signature == func->minimalSignature()) { + ok = true; + break; + } + } + if (!ok) { + ReportHandler::warning(QString("Global function '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.") + .arg(signature)); } } - if (!ok) { - ReportHandler::warning(QString("Global function '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.") - .arg(signature)); + } else if (entry->isEnum()) { + const QString name = ((EnumTypeEntry*) entry)->targetLangQualifier(); + AbstractMetaClass* cls = m_metaClasses.findClass(name); + + bool enumFound = false; + if (cls) { + enumFound = cls->findEnum(entry->targetLangName()); + } else { // Global enum + foreach (AbstractMetaEnum* metaEnum, m_enums) { + if (metaEnum->typeEntry() == entry) { + enumFound = true; + break; + } + } } - } - } else if (entry->isEnum()) { - QString pkg = entry->targetLangPackage(); - QString name = (pkg.isEmpty() ? QString() : pkg + ".") - + ((EnumTypeEntry*) entry)->targetLangQualifier(); - AbstractMetaClass* cls = m_metaClasses.findClass(name); - - if (cls) { - AbstractMetaEnum* e = cls->findEnum(entry->targetLangName()); - if (!e) - ReportHandler::warning(QString("enum '%1' is specified in typesystem, " - "but not declared") + if (!enumFound) { + entry->setCodeGeneration(TypeEntry::GenerateNothing); + ReportHandler::warning(QString("enum '%1' is specified in typesystem, but not declared") .arg(entry->qualifiedCppName())); + } + } } } @@ -945,6 +954,7 @@ AbstractMetaEnum* AbstractMetaBuilder::traverseEnum(EnumModelItem enumItem, Abst className = m_currentClass->typeEntry()->qualifiedCppName(); if (TypeDatabase::instance()->isEnumRejected(className, enumName)) { + typeEntry->setCodeGeneration(TypeEntry::GenerateNothing); m_rejectedEnums.insert(qualifiedName, GenerationDisabled); return 0; } @@ -958,6 +968,7 @@ AbstractMetaEnum* AbstractMetaBuilder::traverseEnum(EnumModelItem enumItem, Abst // Skipping api incompatible if (!TypeDatabase::instance()->supportedApiVersion(typeEntry->version())) { + typeEntry->setCodeGeneration(TypeEntry::GenerateNothing); m_rejectedEnums.insert(qualifiedName, ApiIncompatible); return 0; } @@ -970,10 +981,18 @@ AbstractMetaEnum* AbstractMetaBuilder::traverseEnum(EnumModelItem enumItem, Abst metaEnum->setTypeEntry((EnumTypeEntry*) typeEntry); switch (enumItem->accessPolicy()) { - case CodeModel::Public: *metaEnum += AbstractMetaAttributes::Public; break; - case CodeModel::Protected: *metaEnum += AbstractMetaAttributes::Protected; break; - case CodeModel::Private: *metaEnum += AbstractMetaAttributes::Private; break; - default: break; + case CodeModel::Public: + *metaEnum += AbstractMetaAttributes::Public; + break; + case CodeModel::Protected: + *metaEnum += AbstractMetaAttributes::Protected; + break; + case CodeModel::Private: + *metaEnum += AbstractMetaAttributes::Private; + typeEntry->setCodeGeneration(TypeEntry::GenerateNothing); + break; + default: + break; } ReportHandler::debugMedium(QString(" - traversing enum %1").arg(metaEnum->fullName())); diff --git a/typedatabase.cpp b/typedatabase.cpp index 338c40394..98ffc0b82 100644 --- a/typedatabase.cpp +++ b/typedatabase.cpp @@ -28,6 +28,8 @@ #include <QFile> #include <QXmlInputSource> #include "reporthandler.h" +// #include <tr1/tuple> +#include <algorithm> TypeDatabase::TypeDatabase() : m_suppressWarnings(true), m_apiVersion(0) { @@ -415,17 +417,75 @@ void TypeDatabase::setDropTypeEntries(QStringList dropTypeEntries) m_dropTypeEntries.sort(); } -typedef QHash<TypeEntry*, int> TypeRevisionMap; -Q_GLOBAL_STATIC(TypeRevisionMap, typeRevisions); +// Using std::pair to save some memory +// the pair means (revision, typeIndex) +// This global variable exists only because we can't break the ABI +typedef QHash<const TypeEntry*, std::pair<int, int> > TypeRevisionMap; +Q_GLOBAL_STATIC(TypeRevisionMap, typeEntryFields); +static bool computeTypeIndexes = true; +static int maxTypeIndex; -int getTypeRevision(TypeEntry* typeEntry) +int getTypeRevision(const TypeEntry* typeEntry) { - return typeRevisions()->value(typeEntry); + return typeEntryFields()->value(typeEntry).first; } void setTypeRevision(TypeEntry* typeEntry, int revision) { - typeRevisions()->insert(typeEntry, revision); + (*typeEntryFields())[typeEntry].first = revision; + computeTypeIndexes = true; } +static bool compareTypeEntriesByName(const TypeEntry* t1, const TypeEntry* t2) +{ + return t1->qualifiedCppName() < t2->qualifiedCppName(); +} + +int getTypeIndex(const TypeEntry* typeEntry) +{ + if (computeTypeIndexes) { + TypeDatabase* tdb = TypeDatabase::instance(); + typedef QMap<int, QList<TypeEntry*> > GroupedTypeEntries; + GroupedTypeEntries groupedEntries; + + // Group type entries by revision numbers + TypeEntryHash allEntries = tdb->allEntries(); + foreach (QList<TypeEntry*> entryList, allEntries) { + foreach (TypeEntry* entry, entryList) { + if (entry->isPrimitive() + || entry->isContainer() + || entry->isFunction() + || !entry->generateCode() + || entry->isEnumValue() + || entry->isVarargs() + || entry->isTypeSystem() + || entry->isVoid() + || entry->isCustom()) + continue; + groupedEntries[getTypeRevision(entry)] << entry; + } + } + + maxTypeIndex = 0; + GroupedTypeEntries::iterator it = groupedEntries.begin(); + for (; it != groupedEntries.end(); ++it) { + // Remove duplicates + QList<TypeEntry*>::iterator newEnd = std::unique(it.value().begin(), it.value().end()); + it.value().erase(newEnd, it.value().end()); + // Sort the type entries by name + qSort(it.value().begin(), newEnd, compareTypeEntriesByName); + + foreach (TypeEntry* entry, it.value()) { + (*typeEntryFields())[entry].second = maxTypeIndex++; + } + } + } + + return typeEntryFields()->value(typeEntry).second; +} + +int getMaxTypeIndex() +{ + return maxTypeIndex; +} diff --git a/typedatabase.h b/typedatabase.h index d6ceeecc7..ef454ff0e 100644 --- a/typedatabase.h +++ b/typedatabase.h @@ -28,7 +28,9 @@ #include "typesystem.h" APIEXTRACTOR_API void setTypeRevision(TypeEntry* typeEntry, int revision); -APIEXTRACTOR_API int getTypeRevision(TypeEntry* typeEntry); +APIEXTRACTOR_API int getTypeRevision(const TypeEntry* typeEntry); +APIEXTRACTOR_API int getTypeIndex(const TypeEntry* typeEntry); +APIEXTRACTOR_API int getMaxTypeIndex(); class ContainerTypeEntry; class PrimitiveTypeEntry; |