aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Parente Lima <hugo.pl@gmail.com>2011-07-07 14:09:04 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-09 19:10:17 -0300
commit28510ddcf9d856c9ae351a30abb7593d418b7dd6 (patch)
treec193f938c1311371e5c257f3f4c1ee00fe1b694c
parent9aabb6c3a5505da1e44be2dbec366f51fb2249ba (diff)
Check inconsistencies for enums and disable generation of private entities.
Reviewer: Marcelo Lira <marcelo.lira@openbossa.org> Renato Filho <renato.filho@openbossa.org>
-rw-r--r--abstractmetabuilder.cpp111
-rw-r--r--typedatabase.cpp70
-rw-r--r--typedatabase.h4
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;