From dd7f06be4d8687cd4ed45a41aac674ec50e645ed Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 15 Apr 2010 11:29:12 -0300 Subject: TypeDatabase class moved to its own header/cpp. --- CMakeLists.txt | 2 + abstractmetabuilder.cpp | 1 + abstractmetabuilder.h | 5 +- abstractmetalang.cpp | 1 + apiextractor.cpp | 1 + reporthandler.cpp | 1 + tests/testutil.h | 1 + typedatabase.cpp | 390 ++++++++++++++++++++++++++++++++++++++++++ typedatabase.h | 190 +++++++++++++++++++++ typesystem.cpp | 446 ++++++------------------------------------------ typesystem.h | 266 ----------------------------- typesystem_p.h | 159 +++++++++++++++++ 12 files changed, 797 insertions(+), 666 deletions(-) create mode 100644 typedatabase.cpp create mode 100644 typedatabase.h create mode 100644 typesystem_p.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 736e4b625..31ff7e4b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ reporthandler.cpp typeparser.cpp typesystem.cpp include.cpp +typedatabase.cpp parser/ast.cpp parser/binder.cpp parser/class_compiler.cpp @@ -116,6 +117,7 @@ fileout.h docparser.h qtdocparser.h include.h +typedatabase.h ) if (BUILD_TESTS) diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp index 4d8a4f1d8..994448b9a 100644 --- a/abstractmetabuilder.cpp +++ b/abstractmetabuilder.cpp @@ -23,6 +23,7 @@ #include "abstractmetabuilder.h" #include "reporthandler.h" +#include "typedatabase.h" #include "parser/ast.h" #include "parser/binder.h" diff --git a/abstractmetabuilder.h b/abstractmetabuilder.h index 525d4d3b1..9aef28a55 100644 --- a/abstractmetabuilder.h +++ b/abstractmetabuilder.h @@ -31,6 +31,8 @@ #include +class TypeDatabase; + class APIEXTRACTOR_API AbstractMetaBuilder { public: @@ -160,8 +162,7 @@ public: bool isQObject(const QString &qualifiedName); bool isEnum(const QStringList &qualifiedName); - void fixQObjectForScope(TypeDatabase *types, - NamespaceModelItem item); + void fixQObjectForScope(TypeDatabase* types, NamespaceModelItem item); // QtScript QSet qtMetaTypeDeclaredTypeNames() const diff --git a/abstractmetalang.cpp b/abstractmetalang.cpp index c7d0adf44..3ae80e0e5 100644 --- a/abstractmetalang.cpp +++ b/abstractmetalang.cpp @@ -23,6 +23,7 @@ #include "abstractmetalang.h" #include "reporthandler.h" +#include "typedatabase.h" /******************************************************************************* * AbstractMetaType diff --git a/apiextractor.cpp b/apiextractor.cpp index 38acf46e8..2e16b8ec5 100644 --- a/apiextractor.cpp +++ b/apiextractor.cpp @@ -33,6 +33,7 @@ #include "parser/rpp/pp.h" #include "abstractmetabuilder.h" #include "apiextractorversion.h" +#include "typedatabase.h" static bool preprocess(const QString& sourceFile, QFile& targetFile, diff --git a/reporthandler.cpp b/reporthandler.cpp index fd41983c5..4b0128930 100644 --- a/reporthandler.cpp +++ b/reporthandler.cpp @@ -23,6 +23,7 @@ #include "reporthandler.h" #include "typesystem.h" +#include "typedatabase.h" #include #include #include diff --git a/tests/testutil.h b/tests/testutil.h index b4124e4c3..1aed98349 100644 --- a/tests/testutil.h +++ b/tests/testutil.h @@ -26,6 +26,7 @@ #include #include "abstractmetabuilder.h" #include "reporthandler.h" +#include "typedatabase.h" class TestUtil { diff --git a/typedatabase.cpp b/typedatabase.cpp new file mode 100644 index 000000000..57bf24149 --- /dev/null +++ b/typedatabase.cpp @@ -0,0 +1,390 @@ +/* + * This file is part of the API Extractor project. + * + * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include "typedatabase.h" +#include "typesystem.h" +#include "typesystem_p.h" + +#include +#include +#include "reporthandler.h" + +TypeDatabase::TypeDatabase() : m_suppressWarnings(true) +{ + StringTypeEntry* e = new StringTypeEntry("QXmlStreamStringRef"); + e->setPreferredConversion(false); + addType(e); + + addType(new VoidTypeEntry()); + addType(new VarargsTypeEntry()); +} + +TypeDatabase* TypeDatabase::instance(bool newInstance) +{ + static TypeDatabase* db = 0; + if (!db || newInstance) { + if (db) + delete db; + db = new TypeDatabase; + } + return db; +} + +QString TypeDatabase::normalizedSignature(const char* signature) +{ + QString normalized = QMetaObject::normalizedSignature(signature); + + if (!instance() || !QString(signature).contains("unsigned")) + return normalized; + + QStringList types; + types << "char" << "short" << "int" << "long"; + foreach (const QString& type, types) { + if (instance()->findType(QString("u%1").arg(type))) + continue; + normalized.replace(QRegExp(QString("\\bu%1\\b").arg(type)), QString("unsigned %1").arg(type)); + } + + return normalized; +} + +QStringList TypeDatabase::requiredTargetImports() +{ + return m_requiredTargetImports; +} + +void TypeDatabase::addRequiredTargetImport(const QString& moduleName) +{ + if (!m_requiredTargetImports.contains(moduleName)) + m_requiredTargetImports << moduleName; +} + +void TypeDatabase::addTypesystemPath(const QString& typesystem_paths) +{ + #if defined(Q_OS_WIN32) + char* path_splitter = const_cast(";"); + #else + char* path_splitter = const_cast(":"); + #endif + m_typesystemPaths += typesystem_paths.split(path_splitter); +} + +IncludeList TypeDatabase::extraIncludes(const QString& className) +{ + ComplexTypeEntry* typeEntry = findComplexType(className); + if (typeEntry) + return typeEntry->extraIncludes(); + else + return IncludeList(); +} + +ContainerTypeEntry* TypeDatabase::findContainerType(const QString &name) +{ + QString template_name = name; + + int pos = name.indexOf('<'); + if (pos > 0) + template_name = name.left(pos); + + TypeEntry* type_entry = findType(template_name); + if (type_entry && type_entry->isContainer()) + return static_cast(type_entry); + return 0; +} + +FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) +{ + TypeEntry* entry = findType(name); + if (entry && entry->type() == TypeEntry::FunctionType) + return static_cast(entry); + return 0; +} + + +PrimitiveTypeEntry* TypeDatabase::findTargetLangPrimitiveType(const QString& targetLangName) +{ + foreach (QList entries, m_entries.values()) { + foreach (TypeEntry* e, entries) { + if (e && e->isPrimitive()) { + PrimitiveTypeEntry *pe = static_cast(e); + if (pe->targetLangName() == targetLangName && pe->preferredConversion()) + return pe; + } + } + } + + return 0; +} + +TypeEntry* TypeDatabase::findType(const QString& name) const +{ + QList entries = findTypes(name); + foreach (TypeEntry *entry, entries) { + if (entry && + (!entry->isPrimitive() || static_cast(entry)->preferredTargetLangType())) { + return entry; + } + } + return 0; +} + +SingleTypeEntryHash TypeDatabase::entries() +{ + TypeEntryHash entries = allEntries(); + + SingleTypeEntryHash returned; + QList keys = entries.keys(); + + foreach (QString key, keys) + returned[key] = findType(key); + + return returned; +} + +QList TypeDatabase::primitiveTypes() +{ + TypeEntryHash entries = allEntries(); + QList returned; + foreach(QString key, entries.keys()) { + foreach(const TypeEntry* typeEntry, entries[key]) { + if (typeEntry->isPrimitive()) + returned.append((PrimitiveTypeEntry*) typeEntry); + } + } + return returned; +} + +QList TypeDatabase::containerTypes() +{ + TypeEntryHash entries = allEntries(); + QList returned; + foreach(QString key, entries.keys()) { + foreach(const TypeEntry* typeEntry, entries[key]) { + if (typeEntry->isContainer()) + returned.append((ContainerTypeEntry*) typeEntry); + } + } + return returned; +} +void TypeDatabase::addRejection(const QString& className, const QString& functionName, + const QString& fieldName, const QString& enumName) +{ + TypeRejection r; + r.class_name = className; + r.function_name = functionName; + r.field_name = fieldName; + r.enum_name = enumName; + + m_rejections << r; +} + +bool TypeDatabase::isClassRejected(const QString& className) +{ + if (!m_rebuildClasses.isEmpty()) + return !m_rebuildClasses.contains(className); + + foreach (const TypeRejection& r, m_rejections) + if (r.class_name == className && r.function_name == "*" && r.field_name == "*" && r.enum_name == "*") + return true; + + return false; +} + +bool TypeDatabase::isEnumRejected(const QString& className, const QString& enumName) +{ + foreach (const TypeRejection& r, m_rejections) { + if (r.enum_name == enumName + && (r.class_name == className || r.class_name == "*")) { + return true; + } + } + + return false; +} + +bool TypeDatabase::isFunctionRejected(const QString& className, const QString& functionName) +{ + foreach (const TypeRejection& r, m_rejections) + if (r.function_name == functionName && + (r.class_name == className || r.class_name == "*")) + return true; + return false; +} + + +bool TypeDatabase::isFieldRejected(const QString& className, const QString& fieldName) +{ + foreach (const TypeRejection& r, m_rejections) + if (r.field_name == fieldName && + (r.class_name == className || r.class_name == "*")) + return true; + return false; +} + +FlagsTypeEntry* TypeDatabase::findFlagsType(const QString &name) const +{ + FlagsTypeEntry* fte = (FlagsTypeEntry*) findType(name); + return fte ? fte : (FlagsTypeEntry*) m_flagsEntries.value(name); +} + +AddedFunctionList TypeDatabase::findGlobalUserFunctions(const QString& name) const +{ + AddedFunctionList addedFunctions; + foreach (AddedFunction func, m_globalUserFunctions) { + if (func.name() == name) + addedFunctions.append(func); + } + return addedFunctions; +} + + +QString TypeDatabase::globalNamespaceClassName(const TypeEntry * /*entry*/) +{ + return QLatin1String("Global"); +} + +FunctionModificationList TypeDatabase::functionModifications(const QString& signature) const +{ + FunctionModificationList lst; + for (int i = 0; i < m_functionMods.count(); ++i) { + const FunctionModification& mod = m_functionMods.at(i); + if (mod.signature == signature) + lst << mod; + } + + return lst; +} + +bool TypeDatabase::isSuppressedWarning(const QString& s) +{ + if (!m_suppressWarnings) + return false; + + foreach (const QString &_warning, m_suppressedWarnings) { + QString warning(QString(_warning).replace("\\*", "&place_holder_for_asterisk;")); + + QStringList segs = warning.split("*", QString::SkipEmptyParts); + if (!segs.size()) + continue; + + int i = 0; + int pos = s.indexOf(QString(segs.at(i++)).replace("&place_holder_for_asterisk;", "*")); + //qDebug() << "s == " << s << ", warning == " << segs; + while (pos != -1) { + if (i == segs.size()) + return true; + pos = s.indexOf(QString(segs.at(i++)).replace("&place_holder_for_asterisk;", "*"), pos); + } + } + + return false; +} + +QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile) +{ + if (!QFile::exists(tsFile)) { + int idx = tsFile.lastIndexOf('/'); + QString fileName = idx >= 0 ? tsFile.right(tsFile.length() - idx - 1) : tsFile; + foreach (const QString &path, m_typesystemPaths) { + QString filepath(path + '/' + fileName); + if (QFile::exists(filepath)) + return filepath; + } + } + return tsFile; +} + +bool TypeDatabase::parseFile(const QString &filename, bool generate) +{ + QString filepath = modifiedTypesystemFilepath(filename); + if (m_parsedTypesystemFiles.contains(filepath)) + return m_parsedTypesystemFiles[filepath]; + + QFile file(filepath); + if (!file.exists()) { + ReportHandler::warning("Can't find " + filename+", typesystem paths: "+m_typesystemPaths.join(", ")); + return false; + } + + int count = m_entries.size(); + bool ok = parseFile(&file, generate); + m_parsedTypesystemFiles[filepath] = ok; + int newCount = m_entries.size(); + + ReportHandler::debugSparse(QString::fromLatin1("Parsed: '%1', %2 new entries") + .arg(filename) + .arg(newCount - count)); + return ok; +} + +bool TypeDatabase::parseFile(QIODevice* device, bool generate) +{ + QXmlInputSource source(device); + QXmlSimpleReader reader; + Handler handler(this, generate); + + reader.setContentHandler(&handler); + reader.setErrorHandler(&handler); + + return reader.parse(&source, false); +} + +PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) +{ + QList entries = findTypes(name); + + foreach (TypeEntry* entry, entries) { + if (entry && entry->isPrimitive() && static_cast(entry)->preferredTargetLangType()) + return static_cast(entry); + } + + return 0; +} + +ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) +{ + TypeEntry* entry = findType(name); + if (entry && entry->isComplex()) + return static_cast(entry); + else + return 0; +} + +ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) +{ + TypeEntry* entry = findType(name); + if (entry && entry->isObject()) + return static_cast(entry); + else + return 0; +} + +NamespaceTypeEntry* TypeDatabase::findNamespaceType(const QString& name) +{ + TypeEntry* entry = findType(name); + if (entry && entry->isNamespace()) + return static_cast(entry); + else + return 0; +} + diff --git a/typedatabase.h b/typedatabase.h new file mode 100644 index 000000000..3e361e736 --- /dev/null +++ b/typedatabase.h @@ -0,0 +1,190 @@ +/* + * This file is part of the API Extractor project. + * + * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef TYPEDATABASE_H +#define TYPEDATABASE_H + +#include +#include "typesystem.h" + +class ContainerTypeEntry; +class PrimitiveTypeEntry; +class APIEXTRACTOR_API TypeDatabase +{ + TypeDatabase(); + TypeDatabase(const TypeDatabase&); + TypeDatabase& operator=(const TypeDatabase&); +public: + + /** + * Return the type system instance. + * \param newInstance This parameter is usefull just for unit testing, because singletons causes + * too many side effects on unit testing. + */ + static TypeDatabase* instance(bool newInstance = false); + + static QString normalizedSignature(const char* signature); + + QStringList requiredTargetImports(); + + void addRequiredTargetImport(const QString& moduleName); + + QStringList typesystemPaths() + { + return m_typesystemPaths; + } + + void addTypesystemPath(const QString& typesystem_paths); + + IncludeList extraIncludes(const QString& className); + + PrimitiveTypeEntry* findPrimitiveType(const QString& name); + ComplexTypeEntry* findComplexType(const QString& name); + ObjectTypeEntry* findObjectType(const QString& name); + NamespaceTypeEntry* findNamespaceType(const QString& name); + ContainerTypeEntry* findContainerType(const QString& name); + FunctionTypeEntry* findFunctionType(const QString& name); + + TypeEntry* findType(const QString& name) const; + + QList findTypes(const QString &name) const + { + return m_entries.value(name); + } + + TypeEntryHash allEntries() + { + return m_entries; + } + + SingleTypeEntryHash entries(); + + PrimitiveTypeEntry *findTargetLangPrimitiveType(const QString &targetLangName); + + QList primitiveTypes(); + + QList containerTypes(); + + void addRejection(const QString& className, const QString& functionName, + const QString& fieldName, const QString& enumName); + bool isClassRejected(const QString& className); + bool isFunctionRejected(const QString& className, const QString& functionName); + bool isFieldRejected(const QString& className, const QString& fieldName); + bool isEnumRejected(const QString& className, const QString& enumName); + + void addType(TypeEntry* e) + { + m_entries[e->qualifiedCppName()].append(e); + } + + SingleTypeEntryHash flagsEntries() const + { + return m_flagsEntries; + } + FlagsTypeEntry* findFlagsType(const QString& name) const; + void addFlagsType(FlagsTypeEntry* fte) + { + m_flagsEntries[fte->originalName()] = fte; + } + + TemplateEntry* findTemplate(const QString& name) + { + return m_templates[name]; + } + + void addTemplate(TemplateEntry* t) + { + m_templates[t->name()] = t; + } + + AddedFunctionList globalUserFunctions() const + { + return m_globalUserFunctions; + } + + void addGlobalUserFunctions(const AddedFunctionList& functions) + { + m_globalUserFunctions << functions; + } + + AddedFunctionList findGlobalUserFunctions(const QString& name) const; + + void addGlobalUserFunctionModifications(const FunctionModificationList& functionModifications) + { + m_functionMods << functionModifications; + } + + void addGlobalUserFunctionModification(const FunctionModification& functionModification) + { + m_functionMods << functionModification; + } + + FunctionModificationList functionModifications(const QString& signature) const; + + void setSuppressWarnings(bool on) + { + m_suppressWarnings = on; + } + + void addSuppressedWarning(const QString& s) + { + m_suppressedWarnings.append(s); + } + + bool isSuppressedWarning(const QString& s); + + void setRebuildClasses(const QStringList &cls) + { + m_rebuildClasses = cls; + } + + static QString globalNamespaceClassName(const TypeEntry *te); + QString filename() const + { + return "typesystem.txt"; + } + + QString modifiedTypesystemFilepath(const QString& tsFile); + bool parseFile(const QString &filename, bool generate = true); + bool parseFile(QIODevice* device, bool generate = true); + +private: + bool m_suppressWarnings; + TypeEntryHash m_entries; + SingleTypeEntryHash m_flagsEntries; + TemplateEntryHash m_templates; + QStringList m_suppressedWarnings; + + AddedFunctionList m_globalUserFunctions; + FunctionModificationList m_functionMods; + + QStringList m_requiredTargetImports; + + QStringList m_typesystemPaths; + QHash m_parsedTypesystemFiles; + + QList m_rejections; + QStringList m_rebuildClasses; +}; + +#endif diff --git a/typesystem.cpp b/typesystem.cpp index 32da2ca8d..267777564 100644 --- a/typesystem.cpp +++ b/typesystem.cpp @@ -22,6 +22,8 @@ */ #include "typesystem.h" +#include "typesystem_p.h" +#include "typedatabase.h" #include "reporthandler.h" #include @@ -31,179 +33,53 @@ static QString strings_char = QLatin1String("char"); static QString strings_jchar = QLatin1String("jchar"); static QString strings_jobject = QLatin1String("jobject"); -class StackElement -{ -public: - enum ElementType { - None = 0x0, - - // Type tags (0x1, ... , 0xff) - ObjectTypeEntry = 0x1, - ValueTypeEntry = 0x2, - InterfaceTypeEntry = 0x3, - NamespaceTypeEntry = 0x4, - ComplexTypeEntryMask = 0x7, - - // Non-complex type tags (0x8, 0x9, ... , 0xf) - PrimitiveTypeEntry = 0x8, - EnumTypeEntry = 0x9, - ContainerTypeEntry = 0xa, - FunctionTypeEntry = 0xb, - TypeEntryMask = 0xf, - - // Documentation tags - InjectDocumentation = 0x10, - ModifyDocumentation = 0x20, - DocumentationMask = 0xf0, - - // Simple tags (0x100, 0x200, ... , 0xf00) - ExtraIncludes = 0x0100, - Include = 0x0200, - ModifyFunction = 0x0300, - ModifyField = 0x0400, - Root = 0x0500, - CustomMetaConstructor = 0x0600, - CustomMetaDestructor = 0x0700, - ArgumentMap = 0x0800, - SuppressedWarning = 0x0900, - Rejection = 0x0a00, - LoadTypesystem = 0x0b00, - RejectEnumValue = 0x0c00, - Template = 0x0d00, - TemplateInstanceEnum = 0x0e00, - Replace = 0x0f00, - AddFunction = 0x1000, - SimpleMask = 0x3f00, - - // Code snip tags (0x1000, 0x2000, ... , 0xf000) - InjectCode = 0x4000, - InjectCodeInFunction = 0x8000, - CodeSnipMask = 0xc000, - - // Function modifier tags (0x010000, 0x020000, ... , 0xf00000) - Access = 0x010000, - Removal = 0x020000, - Rename = 0x040000, - ModifyArgument = 0x080000, - Thread = 0x100000, - FunctionModifiers = 0xff0000, - - // Argument modifier tags (0x01000000 ... 0xf0000000) - ConversionRule = 0x01000000, - ReplaceType = 0x02000000, - ReplaceDefaultExpression = 0x04000000, - RemoveArgument = 0x08000000, - DefineOwnership = 0x10000000, - RemoveDefaultExpression = 0x20000000, - NoNullPointers = 0x40000000, - ReferenceCount = 0x80000000, - ParentOwner = 0x90000000, - ArgumentModifiers = 0xff000000 - }; - - StackElement(StackElement *p) : entry(0), type(None), parent(p) { } - - TypeEntry *entry; - ElementType type; - StackElement *parent; - - union { - TemplateInstance *templateInstance; - TemplateEntry *templateEntry; - CustomFunction *customFunction; - } value; -}; - -class Handler : public QXmlDefaultHandler -{ -public: - Handler(TypeDatabase *database, bool generate) +Handler::Handler(TypeDatabase* database, bool generate) : m_database(database), m_generate(generate ? TypeEntry::GenerateAll : TypeEntry::GenerateForSubclass) - { - m_currentEnum = 0; - m_current = 0; - - tagNames["rejection"] = StackElement::Rejection; - tagNames["primitive-type"] = StackElement::PrimitiveTypeEntry; - tagNames["container-type"] = StackElement::ContainerTypeEntry; - tagNames["object-type"] = StackElement::ObjectTypeEntry; - tagNames["value-type"] = StackElement::ValueTypeEntry; - tagNames["interface-type"] = StackElement::InterfaceTypeEntry; - tagNames["namespace-type"] = StackElement::NamespaceTypeEntry; - tagNames["enum-type"] = StackElement::EnumTypeEntry; - tagNames["function"] = StackElement::FunctionTypeEntry; - tagNames["extra-includes"] = StackElement::ExtraIncludes; - tagNames["include"] = StackElement::Include; - tagNames["inject-code"] = StackElement::InjectCode; - tagNames["modify-function"] = StackElement::ModifyFunction; - tagNames["modify-field"] = StackElement::ModifyField; - tagNames["access"] = StackElement::Access; - tagNames["remove"] = StackElement::Removal; - tagNames["rename"] = StackElement::Rename; - tagNames["typesystem"] = StackElement::Root; - tagNames["custom-constructor"] = StackElement::CustomMetaConstructor; - tagNames["custom-destructor"] = StackElement::CustomMetaDestructor; - tagNames["argument-map"] = StackElement::ArgumentMap; - tagNames["suppress-warning"] = StackElement::SuppressedWarning; - tagNames["load-typesystem"] = StackElement::LoadTypesystem; - tagNames["define-ownership"] = StackElement::DefineOwnership; - tagNames["replace-default-expression"] = StackElement::ReplaceDefaultExpression; - tagNames["reject-enum-value"] = StackElement::RejectEnumValue; - tagNames["replace-type"] = StackElement::ReplaceType; - tagNames["conversion-rule"] = StackElement::ConversionRule; - tagNames["modify-argument"] = StackElement::ModifyArgument; - tagNames["remove-argument"] = StackElement::RemoveArgument; - tagNames["remove-default-expression"] = StackElement::RemoveDefaultExpression; - tagNames["template"] = StackElement::Template; - tagNames["insert-template"] = StackElement::TemplateInstanceEnum; - tagNames["replace"] = StackElement::Replace; - tagNames["no-null-pointer"] = StackElement::NoNullPointers; - tagNames["reference-count"] = StackElement::ReferenceCount; - tagNames["parent"] = StackElement::ParentOwner; - tagNames["inject-documentation"] = StackElement::InjectDocumentation; - tagNames["modify-documentation"] = StackElement::ModifyDocumentation; - tagNames["add-function"] = StackElement::AddFunction; - } - - bool startElement(const QString &namespaceURI, const QString &localName, - const QString &qName, const QXmlAttributes &atts); - bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName); - - QString errorString() const - { - return m_error; - } - bool error(const QXmlParseException &exception); - bool fatalError(const QXmlParseException &exception); - bool warning(const QXmlParseException &exception); - - bool characters(const QString &ch); - -private: - void fetchAttributeValues(const QString &name, const QXmlAttributes &atts, - QHash *acceptedAttributes); - - bool importFileElement(const QXmlAttributes &atts); - bool convertBoolean(const QString &, const QString &, bool); - - TypeDatabase *m_database; - StackElement* m_current; - QString m_defaultPackage; - QString m_defaultSuperclass; - QString m_error; - TypeEntry::CodeGeneration m_generate; - - EnumTypeEntry *m_currentEnum; - - CodeSnipList m_codeSnips; - AddedFunctionList m_addedFunctions; - FunctionModificationList m_functionMods; - FieldModificationList m_fieldMods; - DocModificationList m_docModifications; - - QHash tagNames; - QString m_currentSignature; -}; +{ + m_currentEnum = 0; + m_current = 0; + + tagNames["rejection"] = StackElement::Rejection; + tagNames["primitive-type"] = StackElement::PrimitiveTypeEntry; + tagNames["container-type"] = StackElement::ContainerTypeEntry; + tagNames["object-type"] = StackElement::ObjectTypeEntry; + tagNames["value-type"] = StackElement::ValueTypeEntry; + tagNames["interface-type"] = StackElement::InterfaceTypeEntry; + tagNames["namespace-type"] = StackElement::NamespaceTypeEntry; + tagNames["enum-type"] = StackElement::EnumTypeEntry; + tagNames["function"] = StackElement::FunctionTypeEntry; + tagNames["extra-includes"] = StackElement::ExtraIncludes; + tagNames["include"] = StackElement::Include; + tagNames["inject-code"] = StackElement::InjectCode; + tagNames["modify-function"] = StackElement::ModifyFunction; + tagNames["modify-field"] = StackElement::ModifyField; + tagNames["access"] = StackElement::Access; + tagNames["remove"] = StackElement::Removal; + tagNames["rename"] = StackElement::Rename; + tagNames["typesystem"] = StackElement::Root; + tagNames["custom-constructor"] = StackElement::CustomMetaConstructor; + tagNames["custom-destructor"] = StackElement::CustomMetaDestructor; + tagNames["argument-map"] = StackElement::ArgumentMap; + tagNames["suppress-warning"] = StackElement::SuppressedWarning; + tagNames["load-typesystem"] = StackElement::LoadTypesystem; + tagNames["define-ownership"] = StackElement::DefineOwnership; + tagNames["replace-default-expression"] = StackElement::ReplaceDefaultExpression; + tagNames["reject-enum-value"] = StackElement::RejectEnumValue; + tagNames["replace-type"] = StackElement::ReplaceType; + tagNames["conversion-rule"] = StackElement::ConversionRule; + tagNames["modify-argument"] = StackElement::ModifyArgument; + tagNames["remove-argument"] = StackElement::RemoveArgument; + tagNames["remove-default-expression"] = StackElement::RemoveDefaultExpression; + tagNames["template"] = StackElement::Template; + tagNames["insert-template"] = StackElement::TemplateInstanceEnum; + tagNames["replace"] = StackElement::Replace; + tagNames["no-null-pointer"] = StackElement::NoNullPointers; + tagNames["reference-count"] = StackElement::ReferenceCount; + tagNames["parent"] = StackElement::ParentOwner; + tagNames["inject-documentation"] = StackElement::InjectDocumentation; + tagNames["modify-documentation"] = StackElement::ModifyDocumentation; + tagNames["add-function"] = StackElement::AddFunction; +} bool Handler::error(const QXmlParseException &e) { @@ -1682,94 +1558,6 @@ bool Handler::startElement(const QString &, const QString &n, return true; } -TypeDatabase *TypeDatabase::instance(bool newInstance) -{ - static TypeDatabase *db = 0; - if (!db || newInstance) { - if (db) - delete db; - db = new TypeDatabase; - } - return db; -} - -QString TypeDatabase::normalizedSignature(const char* signature) -{ - QString normalized = QMetaObject::normalizedSignature(signature); - - if (!instance() || !QString(signature).contains("unsigned")) - return normalized; - - QStringList types; - types << "char" << "short" << "int" << "long"; - foreach (const QString& type, types) { - if (instance()->findType(QString("u%1").arg(type))) - continue; - normalized.replace(QRegExp(QString("\\bu%1\\b").arg(type)), QString("unsigned %1").arg(type)); - } - - return normalized; -} - -TypeDatabase::TypeDatabase() : m_suppressWarnings(true) -{ - StringTypeEntry* e = new StringTypeEntry("QXmlStreamStringRef"); - e->setPreferredConversion(false); - addType(e); - - addType(new VoidTypeEntry()); - addType(new VarargsTypeEntry()); -} - -QString TypeDatabase::modifiedTypesystemFilepath(const QString &ts_file) -{ - if (!QFile::exists(ts_file)) { - int idx = ts_file.lastIndexOf('/'); - QString fileName = idx >= 0 ? ts_file.right(ts_file.length() - idx - 1) : ts_file; - foreach (const QString &path, m_typesystemPaths) { - QString filepath(path + '/' + fileName); - if (QFile::exists(filepath)) - return filepath; - } - } - return ts_file; -} - -bool TypeDatabase::parseFile(const QString &filename, bool generate) -{ - QString filepath = modifiedTypesystemFilepath(filename); - if (m_parsedTypesystemFiles.contains(filepath)) - return m_parsedTypesystemFiles[filepath]; - - QFile file(filepath); - if (!file.exists()) { - ReportHandler::warning("Can't find " + filename+", typesystem paths: "+m_typesystemPaths.join(", ")); - return false; - } - - int count = m_entries.size(); - bool ok = parseFile(&file, generate); - m_parsedTypesystemFiles[filepath] = ok; - int newCount = m_entries.size(); - - ReportHandler::debugSparse(QString::fromLatin1("Parsed: '%1', %2 new entries") - .arg(filename) - .arg(newCount - count)); - return ok; -} - -bool TypeDatabase::parseFile(QIODevice* device, bool generate) -{ - QXmlInputSource source(device); - QXmlSimpleReader reader; - Handler handler(this, generate); - - reader.setContentHandler(&handler); - reader.setErrorHandler(&handler); - - return reader.parse(&source, false); -} - PrimitiveTypeEntry* PrimitiveTypeEntry::basicAliasedTypeEntry() const { if (!m_aliasedTypeEntry) @@ -1782,53 +1570,6 @@ PrimitiveTypeEntry* PrimitiveTypeEntry::basicAliasedTypeEntry() const return m_aliasedTypeEntry; } -ContainerTypeEntry *TypeDatabase::findContainerType(const QString &name) -{ - QString template_name = name; - - int pos = name.indexOf('<'); - if (pos > 0) - template_name = name.left(pos); - - TypeEntry *type_entry = findType(template_name); - if (type_entry && type_entry->isContainer()) - return static_cast(type_entry); - return 0; -} - -FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) -{ - TypeEntry* entry = findType(name); - if (entry && entry->type() == TypeEntry::FunctionType) - return static_cast(entry); - return 0; -} - - -PrimitiveTypeEntry *TypeDatabase::findTargetLangPrimitiveType(const QString &targetLangName) -{ - foreach (QList entries, m_entries.values()) { - foreach (TypeEntry *e, entries) { - if (e && e->isPrimitive()) { - PrimitiveTypeEntry *pe = static_cast(e); - if (pe->targetLangName() == targetLangName && pe->preferredConversion()) - return pe; - } - } - } - - return 0; -} - -IncludeList TypeDatabase::extraIncludes(const QString &className) -{ - ComplexTypeEntry *typeEntry = findComplexType(className); - if (typeEntry) - return typeEntry->extraIncludes(); - else - return IncludeList(); -} - QString Modification::accessModifierString() const { if (isPrivate()) return "private"; @@ -1933,97 +1674,6 @@ QString FlagsTypeEntry::qualifiedTargetLangName() const return targetLangPackage() + "." + m_enum->targetLangQualifier() + "." + targetLangName(); } - -void TypeDatabase::addRejection(const QString &class_name, const QString &function_name, - const QString &field_name, const QString &enum_name) -{ - TypeRejection r; - r.class_name = class_name; - r.function_name = function_name; - r.field_name = field_name; - r.enum_name = enum_name; - - m_rejections << r; -} - -bool TypeDatabase::isClassRejected(const QString &class_name) -{ - if (!m_rebuildClasses.isEmpty()) - return !m_rebuildClasses.contains(class_name); - - foreach (const TypeRejection &r, m_rejections) - if (r.class_name == class_name && r.function_name == "*" && r.field_name == "*" && r.enum_name == "*") - return true; - - return false; -} - -bool TypeDatabase::isEnumRejected(const QString &class_name, const QString &enum_name) -{ - foreach (const TypeRejection &r, m_rejections) { - if (r.enum_name == enum_name - && (r.class_name == class_name || r.class_name == "*")) { - return true; - } - } - - return false; -} - -bool TypeDatabase::isFunctionRejected(const QString &class_name, const QString &function_name) -{ - foreach (const TypeRejection &r, m_rejections) - if (r.function_name == function_name && - (r.class_name == class_name || r.class_name == "*")) - return true; - return false; -} - - -bool TypeDatabase::isFieldRejected(const QString &class_name, const QString &field_name) -{ - foreach (const TypeRejection &r, m_rejections) - if (r.field_name == field_name && - (r.class_name == class_name || r.class_name == "*")) - return true; - return false; -} - -FlagsTypeEntry *TypeDatabase::findFlagsType(const QString &name) const -{ - FlagsTypeEntry *fte = (FlagsTypeEntry *) findType(name); - return fte ? fte : (FlagsTypeEntry *) m_flagsEntries.value(name); -} - -AddedFunctionList TypeDatabase::findGlobalUserFunctions(const QString& name) const -{ - AddedFunctionList addedFunctions; - foreach (AddedFunction func, m_globalUserFunctions) { - if (func.name() == name) - addedFunctions.append(func); - } - return addedFunctions; -} - - -QString TypeDatabase::globalNamespaceClassName(const TypeEntry * /*entry*/) -{ - return QLatin1String("Global"); -} - -FunctionModificationList TypeDatabase::functionModifications(const QString& signature) const -{ - FunctionModificationList lst; - for (int i = 0; i < m_functionMods.count(); ++i) { - const FunctionModification& mod = m_functionMods.at(i); - if (mod.signature == signature) - lst << mod; - } - - return lst; -} - - /*! * The Visual Studio 2002 compiler doesn't support these symbols, * which our typedefs unforntuatly expand to. diff --git a/typesystem.h b/typesystem.h index 662cb53e1..34f60b0d5 100644 --- a/typesystem.h +++ b/typesystem.h @@ -1758,272 +1758,6 @@ struct TypeRejection QString enum_name; }; -class APIEXTRACTOR_API TypeDatabase -{ - TypeDatabase(); - TypeDatabase(const TypeDatabase&); - TypeDatabase& operator=(const TypeDatabase&); -public: - - /** - * Return the type system instance. - * \param newInstance This parameter is usefull just for unit testing, because singletons causes - * too many side effects on unit testing. - */ - static TypeDatabase *instance(bool newInstance = false); - - static QString normalizedSignature(const char* signature); - - QStringList requiredTargetImports() - { - return m_requiredTargetImports; - } - - void addRequiredTargetImport(const QString &moduleName) - { - if (!m_requiredTargetImports.contains(moduleName)) - m_requiredTargetImports << moduleName; - } - - QStringList typesystemPaths() - { - return m_typesystemPaths; - } - void addTypesystemPath(const QString &typesystem_paths) - { -#if defined(Q_OS_WIN32) - char *path_splitter = const_cast(";"); -#else - char *path_splitter = const_cast(":"); -#endif - m_typesystemPaths += typesystem_paths.split(path_splitter); - } - - IncludeList extraIncludes(const QString &className); - - inline PrimitiveTypeEntry *findPrimitiveType(const QString &name); - inline ComplexTypeEntry *findComplexType(const QString &name); - inline ObjectTypeEntry *findObjectType(const QString &name); - inline NamespaceTypeEntry *findNamespaceType(const QString &name); - ContainerTypeEntry *findContainerType(const QString &name); - FunctionTypeEntry* findFunctionType(const QString& name); - - TypeEntry *findType(const QString &name) const - { - QList entries = findTypes(name); - foreach (TypeEntry *entry, entries) { - if (entry && - (!entry->isPrimitive() || static_cast(entry)->preferredTargetLangType())) { - return entry; - } - } - return 0; - } - QList findTypes(const QString &name) const - { - return m_entries.value(name); - } - TypeEntryHash allEntries() - { - return m_entries; - } - - SingleTypeEntryHash entries() - { - TypeEntryHash entries = allEntries(); - - SingleTypeEntryHash returned; - QList keys = entries.keys(); - - foreach (QString key, keys) - returned[key] = findType(key); - - return returned; - } - - PrimitiveTypeEntry *findTargetLangPrimitiveType(const QString &targetLangName); - - QList primitiveTypes() { - TypeEntryHash entries = allEntries(); - QList returned; - foreach(QString key, entries.keys()) { - foreach(const TypeEntry* typeEntry, entries[key]) { - if (typeEntry->isPrimitive()) - returned.append((PrimitiveTypeEntry*) typeEntry); - } - } - return returned; - } - QList containerTypes() { - TypeEntryHash entries = allEntries(); - QList returned; - foreach(QString key, entries.keys()) { - foreach(const TypeEntry* typeEntry, entries[key]) { - if (typeEntry->isContainer()) - returned.append((ContainerTypeEntry*) typeEntry); - } - } - return returned; - } - - void addRejection(const QString &class_name, const QString &function_name, - const QString &field_name, const QString &enum_name); - bool isClassRejected(const QString &class_name); - bool isFunctionRejected(const QString &class_name, const QString &function_name); - bool isFieldRejected(const QString &class_name, const QString &field_name); - bool isEnumRejected(const QString &class_name, const QString &enum_name); - - void addType(TypeEntry *e) - { - m_entries[e->qualifiedCppName()].append(e); - } - - SingleTypeEntryHash flagsEntries() const - { - return m_flagsEntries; - } - FlagsTypeEntry *findFlagsType(const QString &name) const; - void addFlagsType(FlagsTypeEntry *fte) - { - m_flagsEntries[fte->originalName()] = fte; - } - - TemplateEntry *findTemplate(const QString &name) - { - return m_templates[name]; - } - void addTemplate(TemplateEntry *t) - { - m_templates[t->name()] = t; - } - - AddedFunctionList globalUserFunctions() const - { - return m_globalUserFunctions; - } - void addGlobalUserFunctions(const AddedFunctionList& functions) - { - m_globalUserFunctions << functions; - } - AddedFunctionList findGlobalUserFunctions(const QString& name) const; - - void addGlobalUserFunctionModifications(const FunctionModificationList& functionModifications) - { - m_functionMods << functionModifications; - } - void addGlobalUserFunctionModification(const FunctionModification& functionModification) - { - m_functionMods << functionModification; - } - FunctionModificationList functionModifications(const QString& signature) const; - - void setSuppressWarnings(bool on) - { - m_suppressWarnings = on; - } - void addSuppressedWarning(const QString &s) - { - m_suppressedWarnings.append(s); - } - - bool isSuppressedWarning(const QString &s) - { - if (!m_suppressWarnings) - return false; - - foreach (const QString &_warning, m_suppressedWarnings) { - QString warning(QString(_warning).replace("\\*", "&place_holder_for_asterisk;")); - - QStringList segs = warning.split("*", QString::SkipEmptyParts); - if (!segs.size()) - continue; - - int i = 0; - int pos = s.indexOf(QString(segs.at(i++)).replace("&place_holder_for_asterisk;", "*")); - //qDebug() << "s == " << s << ", warning == " << segs; - while (pos != -1) { - if (i == segs.size()) - return true; - pos = s.indexOf(QString(segs.at(i++)).replace("&place_holder_for_asterisk;", "*"), pos); - } - } - - return false; - } - - void setRebuildClasses(const QStringList &cls) - { - m_rebuildClasses = cls; - } - - static QString globalNamespaceClassName(const TypeEntry *te); - QString filename() const - { - return "typesystem.txt"; - } - - QString modifiedTypesystemFilepath(const QString &ts_file); - bool parseFile(const QString &filename, bool generate = true); - bool parseFile(QIODevice* device, bool generate = true); - -private: - bool m_suppressWarnings; - TypeEntryHash m_entries; - SingleTypeEntryHash m_flagsEntries; - TemplateEntryHash m_templates; - QStringList m_suppressedWarnings; - - AddedFunctionList m_globalUserFunctions; - FunctionModificationList m_functionMods; - - QStringList m_requiredTargetImports; - - QStringList m_typesystemPaths; - QHash m_parsedTypesystemFiles; - - QList m_rejections; - QStringList m_rebuildClasses; -}; - -inline PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString &name) -{ - QList entries = findTypes(name); - - foreach (TypeEntry *entry, entries) { - if (entry && entry->isPrimitive() && static_cast(entry)->preferredTargetLangType()) - return static_cast(entry); - } - - return 0; -} - -inline ComplexTypeEntry *TypeDatabase::findComplexType(const QString &name) -{ - TypeEntry *entry = findType(name); - if (entry && entry->isComplex()) - return static_cast(entry); - else - return 0; -} - -inline ObjectTypeEntry *TypeDatabase::findObjectType(const QString &name) -{ - TypeEntry *entry = findType(name); - if (entry && entry->isObject()) - return static_cast(entry); - else - return 0; -} - -inline NamespaceTypeEntry *TypeDatabase::findNamespaceType(const QString &name) -{ - TypeEntry *entry = findType(name); - if (entry && entry->isNamespace()) - return static_cast(entry); - else - return 0; -} - QString fixCppTypeName(const QString &name); #endif // TYPESYSTEM_H diff --git a/typesystem_p.h b/typesystem_p.h new file mode 100644 index 000000000..a62056db9 --- /dev/null +++ b/typesystem_p.h @@ -0,0 +1,159 @@ +/* + * This file is part of the API Extractor project. + * + * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ +#ifndef TYPESYSTEM_P_H +#define TYPESYSTEM_P_H + +#include +#include "typesystem.h" + +class TypeDatabase; +class StackElement +{ + public: + enum ElementType { + None = 0x0, + + // Type tags (0x1, ... , 0xff) + ObjectTypeEntry = 0x1, + ValueTypeEntry = 0x2, + InterfaceTypeEntry = 0x3, + NamespaceTypeEntry = 0x4, + ComplexTypeEntryMask = 0x7, + + // Non-complex type tags (0x8, 0x9, ... , 0xf) + PrimitiveTypeEntry = 0x8, + EnumTypeEntry = 0x9, + ContainerTypeEntry = 0xa, + FunctionTypeEntry = 0xb, + TypeEntryMask = 0xf, + + // Documentation tags + InjectDocumentation = 0x10, + ModifyDocumentation = 0x20, + DocumentationMask = 0xf0, + + // Simple tags (0x100, 0x200, ... , 0xf00) + ExtraIncludes = 0x0100, + Include = 0x0200, + ModifyFunction = 0x0300, + ModifyField = 0x0400, + Root = 0x0500, + CustomMetaConstructor = 0x0600, + CustomMetaDestructor = 0x0700, + ArgumentMap = 0x0800, + SuppressedWarning = 0x0900, + Rejection = 0x0a00, + LoadTypesystem = 0x0b00, + RejectEnumValue = 0x0c00, + Template = 0x0d00, + TemplateInstanceEnum = 0x0e00, + Replace = 0x0f00, + AddFunction = 0x1000, + SimpleMask = 0x3f00, + + // Code snip tags (0x1000, 0x2000, ... , 0xf000) + InjectCode = 0x4000, + InjectCodeInFunction = 0x8000, + CodeSnipMask = 0xc000, + + // Function modifier tags (0x010000, 0x020000, ... , 0xf00000) + Access = 0x010000, + Removal = 0x020000, + Rename = 0x040000, + ModifyArgument = 0x080000, + Thread = 0x100000, + FunctionModifiers = 0xff0000, + + // Argument modifier tags (0x01000000 ... 0xf0000000) + ConversionRule = 0x01000000, + ReplaceType = 0x02000000, + ReplaceDefaultExpression = 0x04000000, + RemoveArgument = 0x08000000, + DefineOwnership = 0x10000000, + RemoveDefaultExpression = 0x20000000, + NoNullPointers = 0x40000000, + ReferenceCount = 0x80000000, + ParentOwner = 0x90000000, + ArgumentModifiers = 0xff000000 + }; + + StackElement(StackElement *p) : entry(0), type(None), parent(p) { } + + TypeEntry* entry; + ElementType type; + StackElement *parent; + + union { + TemplateInstance* templateInstance; + TemplateEntry* templateEntry; + CustomFunction* customFunction; + } value; +}; + +class Handler : public QXmlDefaultHandler +{ +public: + Handler(TypeDatabase* database, bool generate); + + bool startElement(const QString& namespaceURI, const QString& localName, + const QString& qName, const QXmlAttributes& atts); + bool endElement(const QString& namespaceURI, const QString& localName, const QString& qName); + + QString errorString() const + { + return m_error; + } + + bool error(const QXmlParseException &exception); + bool fatalError(const QXmlParseException &exception); + bool warning(const QXmlParseException &exception); + + bool characters(const QString &ch); + +private: + void fetchAttributeValues(const QString &name, const QXmlAttributes &atts, + QHash *acceptedAttributes); + + bool importFileElement(const QXmlAttributes &atts); + bool convertBoolean(const QString &, const QString &, bool); + + TypeDatabase *m_database; + StackElement* m_current; + QString m_defaultPackage; + QString m_defaultSuperclass; + QString m_error; + TypeEntry::CodeGeneration m_generate; + + EnumTypeEntry* m_currentEnum; + + CodeSnipList m_codeSnips; + AddedFunctionList m_addedFunctions; + FunctionModificationList m_functionMods; + FieldModificationList m_fieldMods; + DocModificationList m_docModifications; + + QHash tagNames; + QString m_currentSignature; +}; + +#endif -- cgit v1.2.3