aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt20
-rw-r--r--abstractmetabuilder.cpp139
-rw-r--r--abstractmetabuilder.h17
-rw-r--r--abstractmetalang.cpp1
-rw-r--r--abstractmetalang.h26
-rw-r--r--apiextractor.cpp2
-rw-r--r--doc/typesystem_specifying_types.rst19
-rw-r--r--graph.cpp2
-rw-r--r--include.cpp49
-rw-r--r--include.h83
-rw-r--r--parser/codemodel.cpp6
-rw-r--r--reporthandler.cpp1
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/testabstractmetatype.cpp3
-rw-r--r--tests/testenum.cpp7
-rw-r--r--tests/testfunctiontag.cpp64
-rw-r--r--tests/testfunctiontag.h36
-rw-r--r--tests/testutil.h1
-rw-r--r--typedatabase.cpp386
-rw-r--r--typedatabase.h190
-rw-r--r--typesystem.cpp475
-rw-r--r--typesystem.h327
-rw-r--r--typesystem_p.h159
23 files changed, 1226 insertions, 788 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c2cdbd611..e6d3034d2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,16 +7,20 @@ find_package(Qt4 4.5.0 REQUIRED)
find_package(LibXml2 2.6.32 REQUIRED)
find_package(LibXslt 1.1.19 REQUIRED)
+option(BUILD_TESTS "Build tests." TRUE)
+
if (MSVC)
set(CMAKE_CXX_FLAGS "/DWIN32 /D_WINDOWS /w /EHsc- /GS- /GR- /DAPIEXTRACTOR_ENABLE_DUPLICATE_ENUM_VALUES /DAPIEXTRACTOR_BUILD -D_SCL_SECURE_NO_WARNINGS")
else (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -DAPIEXTRACTOR_ENABLE_DUPLICATE_ENUM_VALUES -fvisibility=hidden")
endif(MSVC)
-set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests)
+if (BUILD_TESTS)
+ set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests)
+endif()
set(apiextractor_MAJOR_VERSION 0)
-set(apiextractor_MINOR_VERSION 4)
-set(apiextractor_MICRO_VERSION 1)
+set(apiextractor_MINOR_VERSION 5)
+set(apiextractor_MICRO_VERSION 0)
set(apiextractor_VERSION "${apiextractor_MAJOR_VERSION}.${apiextractor_MINOR_VERSION}.${apiextractor_MICRO_VERSION}")
configure_file(apiextractorversion.h.in ${CMAKE_CURRENT_BINARY_DIR}/apiextractorversion.h @ONLY)
set(QT_USE_QTCORE 1)
@@ -40,6 +44,8 @@ graph.cpp
reporthandler.cpp
typeparser.cpp
typesystem.cpp
+include.cpp
+typedatabase.cpp
parser/ast.cpp
parser/binder.cpp
parser/class_compiler.cpp
@@ -110,10 +116,14 @@ typesystem.h
fileout.h
docparser.h
qtdocparser.h
+include.h
+typedatabase.h
)
-enable_testing()
-add_subdirectory(tests)
+if (BUILD_TESTS)
+ enable_testing()
+ add_subdirectory(tests)
+endif()
install(FILES ${root_HEADERS} DESTINATION include/apiextractor)
install(TARGETS apiextractor EXPORT apiextractor
diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp
index ac1dcd029..facb15ca5 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"
@@ -44,6 +45,7 @@
#include <QDir>
#include <cstdio>
+#include <algorithm>
#include "graph.h"
static QString stripTemplateArgs(const QString &name)
@@ -333,7 +335,10 @@ bool AbstractMetaBuilder::build(QIODevice* input)
fixQObjectForScope(types, model_dynamic_cast<NamespaceModelItem>(m_dom));
// Start the generation...
- QList<ClassModelItem > typeValues = typeMap.values();
+ ClassList typeValues = typeMap.values();
+ ClassList::iterator it = std::unique(typeValues.begin(), typeValues.end());
+ typeValues.erase(it, typeValues.end());
+
ReportHandler::setProgressReference(typeValues);
foreach (ClassModelItem item, typeValues) {
ReportHandler::progress("Generating class model for %s", qPrintable(item->name()));
@@ -375,6 +380,28 @@ bool AbstractMetaBuilder::build(QIODevice* input)
addAbstractMetaClass(cls);
}
+ // Global functions
+ foreach (FunctionModelItem func, m_dom->functions()) {
+ if (func->accessPolicy() != CodeModel::Public || func->name().startsWith("operator"))
+ continue;
+ FunctionTypeEntry* funcEntry = types->findFunctionType(func->name());
+ if (!funcEntry)
+ continue;
+
+ AbstractMetaFunction* metaFunc = traverseFunction(func);
+ if (!metaFunc)
+ continue;
+
+ if (!funcEntry->hasSignature(metaFunc->minimalSignature())) {
+ delete metaFunc;
+ continue;
+ }
+
+ setInclude(funcEntry, func->fileName());
+ metaFunc->setTypeEntry(funcEntry);
+ m_globalFunctions << metaFunc;
+ }
+
ReportHandler::setProgressReference(m_metaClasses);
foreach (AbstractMetaClass *cls, m_metaClasses) {
ReportHandler::progress("Fixing class inheritance...");
@@ -421,9 +448,22 @@ bool AbstractMetaBuilder::build(QIODevice* input)
&& !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()));
- }
-
- if (entry->isEnum()) {
+ } else if (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));
+ }
+ }
+ } else if (entry->isEnum()) {
QString pkg = entry->targetLangPackage();
QString name = (pkg.isEmpty() ? QString() : pkg + ".")
+ ((EnumTypeEntry *) entry)->targetLangQualifier();
@@ -503,17 +543,6 @@ bool AbstractMetaBuilder::build(QIODevice* input)
m_currentClass = 0;
- foreach (FunctionModelItem func, m_dom->functions()) {
- if (func->accessPolicy() != CodeModel::Public || func->name().startsWith("operator"))
- continue;
-
- AbstractMetaFunction* metaFunc = traverseFunction(func);
- if (metaFunc) {
- metaFunc->setIncludeFile(func->fileName());
- m_globalFunctions << metaFunc;
- }
- }
-
// Functions added to the module on the type system.
foreach (AddedFunction addedFunc, types->globalUserFunctions()) {
AbstractMetaFunction* metaFunc = traverseFunction(addedFunc);
@@ -621,10 +650,8 @@ AbstractMetaClass *AbstractMetaBuilder::traverseNamespace(NamespaceModelItem nam
popScope();
m_namespacePrefix = currentScope()->qualifiedName().join("::");
- if (!type->include().isValid()) {
- QFileInfo info(namespaceItem->fileName());
- type->setInclude(Include(Include::IncludePath, info.fileName()));
- }
+ if (!type->include().isValid())
+ setInclude(type, namespaceItem->fileName());
return metaClass;
}
@@ -903,8 +930,6 @@ AbstractMetaEnum *AbstractMetaBuilder::traverseEnum(EnumModelItem enumItem, Abst
default: break;
}
- metaEnum->setIncludeFile(enumItem->fileName());
-
ReportHandler::debugMedium(QString(" - traversing enum %1").arg(metaEnum->fullName()));
foreach (EnumeratorModelItem value, enumItem->enumerators()) {
@@ -928,6 +953,11 @@ AbstractMetaEnum *AbstractMetaBuilder::traverseEnum(EnumModelItem enumItem, Abst
m_enums << metaEnum;
+ if (!metaEnum->typeEntry()->include().isValid())
+ setInclude(metaEnum->typeEntry(), enumItem->fileName());
+
+ metaEnum->setOriginalAttributes(metaEnum->attributes());
+
return metaEnum;
}
@@ -968,10 +998,8 @@ AbstractMetaClass* AbstractMetaBuilder::traverseTypeAlias(TypeAliasModelItem typ
*metaClass += AbstractMetaAttributes::Public;
// Set the default include file name
- if (!type->include().isValid()) {
- QFileInfo info(typeAlias->fileName());
- type->setInclude(Include(Include::IncludePath, info.fileName()));
- }
+ if (!type->include().isValid())
+ setInclude(type, typeAlias->fileName());
return metaClass;
}
@@ -1081,10 +1109,8 @@ AbstractMetaClass *AbstractMetaBuilder::traverseClass(ClassModelItem classItem)
m_currentClass = oldCurrentClass;
// Set the default include file name
- if (!type->include().isValid()) {
- QFileInfo info(classItem->fileName());
- type->setInclude(Include(Include::IncludePath, info.fileName()));
- }
+ if (!type->include().isValid())
+ setInclude(type, classItem->fileName());
return metaClass;
}
@@ -1433,12 +1459,11 @@ bool AbstractMetaBuilder::setupInheritance(AbstractMetaClass *metaClass)
void AbstractMetaBuilder::traverseEnums(ScopeModelItem scopeItem, AbstractMetaClass *metaClass, const QStringList &enumsDeclarations)
{
EnumList enums = scopeItem->enums();
- foreach (EnumModelItem enum_item, enums) {
- AbstractMetaEnum *meta_enum = traverseEnum(enum_item, metaClass, QSet<QString>::fromList(enumsDeclarations));
- if (meta_enum) {
- meta_enum->setOriginalAttributes(meta_enum->attributes());
- metaClass->addEnum(meta_enum);
- meta_enum->setEnclosingClass(metaClass);
+ foreach (EnumModelItem enumItem, enums) {
+ AbstractMetaEnum *metaEnum = traverseEnum(enumItem, metaClass, QSet<QString>::fromList(enumsDeclarations));
+ if (metaEnum) {
+ metaClass->addEnum(metaEnum);
+ metaEnum->setEnclosingClass(metaClass);
}
}
}
@@ -2660,34 +2685,11 @@ AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted(const Abstra
if (clazz->isInterface() || !clazz->typeEntry()->generateCode())
continue;
- // check base class dep.
- QString baseClassName(clazz->baseClassName());
- if (!baseClassName.isNull() && baseClassName != clazz->name() && map.contains(baseClassName)) {
- if (clazz->baseClass()->enclosingClass() &&
- clazz->baseClass()->enclosingClass() != clazz->enclosingClass()) {
- baseClassName = clazz->baseClass()->enclosingClass()->name();
- }
- graph.addEdge(map[baseClassName], map[clazz->name()]);
- }
-
- // interfaces...
- foreach (AbstractMetaClass* interface, clazz->interfaces()) {
- if (!interface->typeEntry()->generateCode())
- continue;
-
- if (interface->isInterface())
- interface = interface->primaryInterfaceImplementor();
+ if (clazz->enclosingClass())
+ graph.addEdge(map[clazz->enclosingClass()->name()], map[clazz->name()]);
- if (interface->enclosingClass() &&
- interface->enclosingClass() != clazz->enclosingClass()) {
- baseClassName = interface->enclosingClass()->name();
- } else {
- baseClassName = interface->name();
- }
-
- if (!baseClassName.isNull() && baseClassName != clazz->name() && map.contains(baseClassName))
- graph.addEdge(map[baseClassName], map[clazz->name()]);
- }
+ foreach(AbstractMetaClass* baseClass, getBaseClasses(clazz))
+ graph.addEdge(map[baseClass->name()], map[clazz->name()]);
foreach (AbstractMetaFunction* func, clazz->functions()) {
foreach (AbstractMetaArgument* arg, func->arguments()) {
@@ -2733,3 +2735,16 @@ AbstractMetaArgumentList AbstractMetaBuilder::reverseList(const AbstractMetaArgu
return ret;
}
+
+void AbstractMetaBuilder::setGlobalHeader(const QString& globalHeader)
+{
+ m_globalHeader = QFileInfo(globalHeader);
+}
+
+void AbstractMetaBuilder::setInclude(TypeEntry* te, const QString& fileName) const
+{
+
+ QFileInfo info(fileName);
+ if (info.exists() && m_globalHeader != info)
+ te->setInclude(Include(Include::IncludePath, info.fileName()));
+}
diff --git a/abstractmetabuilder.h b/abstractmetabuilder.h
index 525d4d3b1..e676f1217 100644
--- a/abstractmetabuilder.h
+++ b/abstractmetabuilder.h
@@ -29,7 +29,10 @@
#include "typesystem.h"
#include "typeparser.h"
-#include <QtCore/QSet>
+#include <QSet>
+#include <QFileInfo>
+
+class TypeDatabase;
class APIEXTRACTOR_API AbstractMetaBuilder
{
@@ -160,8 +163,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<QString> qtMetaTypeDeclaredTypeNames() const
@@ -169,6 +171,13 @@ public:
return m_qmetatypeDeclaredTypenames;
}
+ /**
+ * AbstractMetaBuilder should know what's the global header being used,
+ * so any class declared under this header wont have the include file
+ * filled.
+ */
+ void setGlobalHeader(const QString& globalHeader);
+
protected:
AbstractMetaClass *argumentToClass(ArgumentModelItem);
@@ -212,6 +221,7 @@ protected:
private:
void sortLists();
AbstractMetaArgumentList reverseList(const AbstractMetaArgumentList& list);
+ void setInclude(TypeEntry* te, const QString& fileName) const;
AbstractMetaClassList m_metaClasses;
AbstractMetaClassList m_templates;
@@ -241,6 +251,7 @@ private:
QSet<QString> m_qmetatypeDeclaredTypenames;
QString m_logDirectory;
+ QFileInfo m_globalHeader;
};
#endif // ABSTRACTMETBUILDER_H
diff --git a/abstractmetalang.cpp b/abstractmetalang.cpp
index b800696ca..cc9d7715a 100644
--- a/abstractmetalang.cpp
+++ b/abstractmetalang.cpp
@@ -23,6 +23,7 @@
#include "abstractmetalang.h"
#include "reporthandler.h"
+#include "typedatabase.h"
/*******************************************************************************
* AbstractMetaType
diff --git a/abstractmetalang.h b/abstractmetalang.h
index 512553d04..e4a81e810 100644
--- a/abstractmetalang.h
+++ b/abstractmetalang.h
@@ -274,18 +274,6 @@ public:
return m_originalAttributes & Friendly;
}
- // valid only for global components
- // (e.g.: functions, enums, flags)
- QString includeFile() const
- {
- return m_includeFile;
- }
-
- void setIncludeFile(const QString& file)
- {
- m_includeFile = file;
- }
-
void setDocumentation(const Documentation& doc)
{
m_doc = doc;
@@ -299,7 +287,6 @@ public:
private:
uint m_attributes;
uint m_originalAttributes;
- QString m_includeFile;
Documentation m_doc;
};
@@ -771,7 +758,8 @@ public:
};
AbstractMetaFunction()
- : m_functionType(NormalFunction),
+ : m_typeEntry(0),
+ m_functionType(NormalFunction),
m_type(0),
m_class(0),
m_implementingClass(0),
@@ -1102,12 +1090,22 @@ public:
return m_propertySpec;
}
+ FunctionTypeEntry* typeEntry() const
+ {
+ return m_typeEntry;
+ }
+
+ void setTypeEntry(FunctionTypeEntry* typeEntry)
+ {
+ m_typeEntry = typeEntry;
+ }
private:
QString m_name;
QString m_originalName;
mutable QString m_cachedMinimalSignature;
mutable QString m_cachedModifiedName;
+ FunctionTypeEntry* m_typeEntry;
FunctionType m_functionType;
AbstractMetaType *m_type;
const AbstractMetaClass *m_class;
diff --git a/apiextractor.cpp b/apiextractor.cpp
index 38acf46e8..00734de8d 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,
@@ -165,6 +166,7 @@ bool ApiExtractor::run()
ppFile.seek(0);
m_builder = new AbstractMetaBuilder;
m_builder->setLogDirectory(m_logDirectory);
+ m_builder->setGlobalHeader(m_cppFileName);
m_builder->build(&ppFile);
return true;
diff --git a/doc/typesystem_specifying_types.rst b/doc/typesystem_specifying_types.rst
index 21392c68a..cd65c4b5b 100644
--- a/doc/typesystem_specifying_types.rst
+++ b/doc/typesystem_specifying_types.rst
@@ -60,8 +60,7 @@ rejection
*optional* **function-name** or **field-name** attributes to reject a particular
function or field. Note that the **field-name** and **function-name** cannot
be specified at the same time. To remove all occurrences of a given field or
- function, set the class attribute to \*. You can use an empty class field
- to denote a global function.
+ function, set the class attribute to \*.
.. _primitive-type:
@@ -254,4 +253,20 @@ container-type
container. It can be: *list*, *string-list*, *linked-list*, *vector*, *stack*,
*queue*, *set*, *map*, *multi-map*, *hash*, *multi-hash* or *pair*.
+.. _function:
+function
+^^^^^^^^
+
+ The function node indicates that the given C++ global function is mapped onto
+ the target language.
+
+ .. code-block:: xml
+
+ <typesystem>
+ <function signature="..." />
+ </typesystem>
+
+ This tag has some limitations, it doesn't support function modifications, besides you
+ can't add a function overload using :ref:`add-function` tag to an existent function.
+ These limitation will be addressed in future versions of ApiExtractor.
diff --git a/graph.cpp b/graph.cpp
index a77f658e6..c985449c1 100644
--- a/graph.cpp
+++ b/graph.cpp
@@ -124,7 +124,7 @@ void Graph::dumpDot(const QHash< int, QString >& nodeNames, const QString& fileN
for (int i = 0; i < m_d->edges.size(); ++i) {
GraphPrivate::EdgeIterator it = m_d->edges[i].begin();
for (;it != m_d->edges[i].end(); ++it)
- s << nodeNames[i] << " -> " << nodeNames[*it] << '\n';
+ s << '"' << nodeNames[i] << "\" -> \"" << nodeNames[*it] << "\"\n";
}
s << "}\n";
}
diff --git a/include.cpp b/include.cpp
new file mode 100644
index 000000000..4d4787d03
--- /dev/null
+++ b/include.cpp
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * 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 "include.h"
+#include <QTextStream>
+#include <QHash>
+
+QString Include::toString() const
+{
+ if (m_type == IncludePath)
+ return "#include <" + m_name + '>';
+ else if (m_type == LocalPath)
+ return "#include \"" + m_name + "\"";
+ else
+ return "import " + m_name + ";";
+}
+
+uint qHash(const Include& inc)
+{
+ return qHash(inc.m_name);
+}
+
+QTextStream& operator<<(QTextStream& out, const Include& include)
+{
+ if (include.isValid())
+ out << include.toString() << endl;
+ return out;
+}
+
diff --git a/include.h b/include.h
new file mode 100644
index 000000000..94e6ced88
--- /dev/null
+++ b/include.h
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * 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 INCLUDE_H
+#define INCLUDE_H
+
+#include "apiextractormacros.h"
+#include <QString>
+#include <QList>
+
+class QTextStream;
+
+class APIEXTRACTOR_API Include
+{
+public:
+ enum IncludeType {
+ IncludePath,
+ LocalPath,
+ TargetLangImport
+ };
+
+ Include() : m_type(IncludePath) {}
+ Include(IncludeType t, const QString &nam) : m_type(t), m_name(nam) {};
+
+ bool isValid() const
+ {
+ return !m_name.isEmpty();
+ }
+
+ IncludeType type() const
+ {
+ return m_type;
+ }
+
+ QString name() const
+ {
+ return m_name;
+ }
+
+ QString toString() const;
+
+ bool operator<(const Include& other) const
+ {
+ return m_name < other.m_name;
+ }
+
+ bool operator==(const Include& other) const
+ {
+ return m_type == other.m_type && m_name == other.m_name;
+ }
+
+ friend uint qHash(const Include&);
+ private:
+ IncludeType m_type;
+ QString m_name;
+};
+
+APIEXTRACTOR_API uint qHash(const Include& inc);
+APIEXTRACTOR_API QTextStream& operator<<(QTextStream& out, const Include& include);
+
+typedef QList<Include> IncludeList;
+
+#endif
diff --git a/parser/codemodel.cpp b/parser/codemodel.cpp
index ecc8e3036..861a6708c 100644
--- a/parser/codemodel.cpp
+++ b/parser/codemodel.cpp
@@ -24,6 +24,7 @@
#include "codemodel.h"
+#include <algorithm>
// ---------------------------------------------------------------------------
CodeModel::CodeModel()
@@ -371,7 +372,10 @@ FunctionModelItem _ScopeModelItem::declaredFunction(FunctionModelItem item)
ClassList _ScopeModelItem::classes() const
{
- return _M_classes.values();
+ ClassList result = _M_classes.values();
+ ClassList::iterator it = std::unique(result.begin(), result.end());
+ result.erase(it, result.end());
+ return result;
}
TypeAliasList _ScopeModelItem::typeAliases() const
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 <QtCore/QSet>
#include <cstring>
#include <cstdarg>
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index b4e1fcaec..eaaaf482f 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -25,3 +25,4 @@ declare_test(testreferencetopointer)
declare_test(testremoveimplconv)
declare_test(testreverseoperators)
declare_test(testtoposort)
+declare_test(testfunctiontag)
diff --git a/tests/testabstractmetatype.cpp b/tests/testabstractmetatype.cpp
index 3e75539fb..81e194fd3 100644
--- a/tests/testabstractmetatype.cpp
+++ b/tests/testabstractmetatype.cpp
@@ -30,6 +30,7 @@ void TestAbstractMetaType::testConstCharPtrType()
const char* cppCode ="const char* justAtest();";
const char* xmlCode = "<typesystem package=\"Foo\">\
<primitive-type name='char'/>\
+ <function signature='justAtest()' />\
</typesystem>";
TestUtil t(cppCode, xmlCode);
QCOMPARE(t.builder()->globalFunctions().size(), 1);
@@ -57,6 +58,7 @@ void TestAbstractMetaType::testCharType()
const char* xmlCode = "<typesystem package=\"Foo\">\
<primitive-type name='char'/>\
<value-type name='A' />\
+ <function signature='justAtest()' />\
</typesystem>";
TestUtil t(cppCode, xmlCode);
@@ -118,6 +120,7 @@ void TestAbstractMetaType::testTypedefWithTemplates()
const char* xmlCode = "<typesystem package=\"Foo\">\
<container-type name='A' type='list'/>\
<value-type name='B' />\
+ <function signature='func(A&lt;B&gt;)' />\
</typesystem>";
TestUtil t(cppCode, xmlCode);
diff --git a/tests/testenum.cpp b/tests/testenum.cpp
index 93a678e73..24cb4d963 100644
--- a/tests/testenum.cpp
+++ b/tests/testenum.cpp
@@ -41,12 +41,13 @@ void TestEnum::testEnumCppSignature()
<value-type name='A'/> \
<enum-type name='GlobalEnum' />\
<enum-type name='A::ClassEnum' />\
+ <function signature='func(A::ClassEnum)' />\
</typesystem>";
TestUtil t(cppCode, xmlCode);
AbstractMetaClassList classes = t.builder()->classes();
QCOMPARE(classes.count(), 1);
-
+
AbstractMetaEnumList globalEnums = t.builder()->globalEnums();
QCOMPARE(globalEnums.count(), 1);
QCOMPARE(globalEnums.first()->name(), QString("GlobalEnum"));
@@ -56,7 +57,7 @@ void TestEnum::testEnumCppSignature()
QCOMPARE(functions.count(), 1);
QCOMPARE(functions.first()->arguments().count(), 1);
QCOMPARE(functions.first()->arguments().first()->type()->cppSignature(), QString("A::ClassEnum"));
-
+
// enum as parameter of a method
AbstractMetaClass* classA = classes.findClass("A");
QCOMPARE(classA->enums().count(), 1);
@@ -72,8 +73,6 @@ void TestEnum::testEnumCppSignature()
AbstractMetaEnumList classEnums = classA->enums();
QCOMPARE(classEnums.first()->name(), QString("ClassEnum"));
-
-
}
QTEST_APPLESS_MAIN(TestEnum)
diff --git a/tests/testfunctiontag.cpp b/tests/testfunctiontag.cpp
new file mode 100644
index 000000000..79e3142a5
--- /dev/null
+++ b/tests/testfunctiontag.cpp
@@ -0,0 +1,64 @@
+/*
+* This file is part of the API Extractor project.
+*
+* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* 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 "testfunctiontag.h"
+#include <QtTest/QTest>
+#include "testutil.h"
+
+void TestFunctionTag::testFunctionTagForSpecificSignature()
+{
+ const char cppCode[] = "void globalFunction(int); void globalFunction(float); void dummy()";
+ const char xmlCode[] = "\
+ <typesystem package=\"Foo\">\
+ <primitive-type name='int'/> \
+ <primitive-type name='float'/> \
+ <function signature='globalFunction(int)'/>\
+ </typesystem>";
+ TestUtil t(cppCode, xmlCode, false);
+
+ FunctionTypeEntry* func = (FunctionTypeEntry*) TypeDatabase::instance()->findType("globalFunction");
+ QVERIFY(func);
+ QCOMPARE(t.builder()->globalFunctions().size(), 1);
+}
+
+void TestFunctionTag::testFunctionTagForAllSignatures()
+{
+ const char cppCode[] = "void globalFunction(int); void globalFunction(float); void dummy();";
+ const char xmlCode[] = "\
+ <typesystem package=\"Foo\">\
+ <primitive-type name='int'/> \
+ <primitive-type name='float'/> \
+ <function signature='globalFunction(int)'/>\
+ <function signature='globalFunction(float)'/>\
+ </typesystem>";
+ TestUtil t(cppCode, xmlCode, false);
+
+ FunctionTypeEntry* func = (FunctionTypeEntry*) TypeDatabase::instance()->findType("globalFunction");
+ QVERIFY(func);
+ QCOMPARE(t.builder()->globalFunctions().size(), 2);
+}
+
+QTEST_APPLESS_MAIN(TestFunctionTag)
+
+#include "testfunctiontag.moc"
+
diff --git a/tests/testfunctiontag.h b/tests/testfunctiontag.h
new file mode 100644
index 000000000..8f42774c6
--- /dev/null
+++ b/tests/testfunctiontag.h
@@ -0,0 +1,36 @@
+/*
+* This file is part of the API Extractor project.
+*
+* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* 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 TESTFUNCTIONTAG_H
+#define TESTFUNCTIONTAG_H
+#include <QObject>
+
+class TestFunctionTag : public QObject
+{
+ Q_OBJECT
+private slots:
+ void testFunctionTagForSpecificSignature();
+ void testFunctionTagForAllSignatures();
+};
+
+#endif
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 <QtCore/QBuffer>
#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..ea009eb32
--- /dev/null
+++ b/typedatabase.cpp
@@ -0,0 +1,386 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * 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 <QFile>
+#include <QXmlInputSource>
+#include "reporthandler.h"
+
+TypeDatabase::TypeDatabase() : m_suppressWarnings(true)
+{
+ 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() const
+{
+ 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<char*>(";");
+ #else
+ char* path_splitter = const_cast<char*>(":");
+ #endif
+ m_typesystemPaths += typesystem_paths.split(path_splitter);
+}
+
+IncludeList TypeDatabase::extraIncludes(const QString& className) const
+{
+ ComplexTypeEntry* typeEntry = findComplexType(className);
+ if (typeEntry)
+ return typeEntry->extraIncludes();
+ else
+ return IncludeList();
+}
+
+ContainerTypeEntry* TypeDatabase::findContainerType(const QString &name) const
+{
+ 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<ContainerTypeEntry*>(type_entry);
+ return 0;
+}
+
+FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const
+{
+ TypeEntry* entry = findType(name);
+ if (entry && entry->type() == TypeEntry::FunctionType)
+ return static_cast<FunctionTypeEntry*>(entry);
+ return 0;
+}
+
+
+PrimitiveTypeEntry* TypeDatabase::findTargetLangPrimitiveType(const QString& targetLangName) const
+{
+ foreach (QList<TypeEntry*> entries, m_entries.values()) {
+ foreach (TypeEntry* e, entries) {
+ if (e && e->isPrimitive()) {
+ PrimitiveTypeEntry *pe = static_cast<PrimitiveTypeEntry*>(e);
+ if (pe->targetLangName() == targetLangName && pe->preferredConversion())
+ return pe;
+ }
+ }
+ }
+
+ return 0;
+}
+
+TypeEntry* TypeDatabase::findType(const QString& name) const
+{
+ QList<TypeEntry *> entries = findTypes(name);
+ foreach (TypeEntry *entry, entries) {
+ if (entry &&
+ (!entry->isPrimitive() || static_cast<PrimitiveTypeEntry *>(entry)->preferredTargetLangType())) {
+ return entry;
+ }
+ }
+ return 0;
+}
+
+SingleTypeEntryHash TypeDatabase::entries() const
+{
+ TypeEntryHash entries = allEntries();
+
+ SingleTypeEntryHash returned;
+ QList<QString> keys = entries.keys();
+
+ foreach (QString key, keys)
+ returned[key] = findType(key);
+
+ return returned;
+}
+
+QList<const PrimitiveTypeEntry*> TypeDatabase::primitiveTypes() const
+{
+ TypeEntryHash entries = allEntries();
+ QList<const PrimitiveTypeEntry*> returned;
+ foreach(QString key, entries.keys()) {
+ foreach(const TypeEntry* typeEntry, entries[key]) {
+ if (typeEntry->isPrimitive())
+ returned.append((PrimitiveTypeEntry*) typeEntry);
+ }
+ }
+ return returned;
+}
+
+QList<const ContainerTypeEntry*> TypeDatabase::containerTypes() const
+{
+ TypeEntryHash entries = allEntries();
+ QList<const ContainerTypeEntry*> 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) const
+{
+ 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) const
+{
+ 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) const
+{
+ 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) const
+{
+ 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) const
+{
+ 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) const
+{
+ 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) const
+{
+ QList<TypeEntry*> entries = findTypes(name);
+
+ foreach (TypeEntry* entry, entries) {
+ if (entry && entry->isPrimitive() && static_cast<PrimitiveTypeEntry*>(entry)->preferredTargetLangType())
+ return static_cast<PrimitiveTypeEntry*>(entry);
+ }
+
+ return 0;
+}
+
+ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const
+{
+ TypeEntry* entry = findType(name);
+ if (entry && entry->isComplex())
+ return static_cast<ComplexTypeEntry*>(entry);
+ else
+ return 0;
+}
+
+ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const
+{
+ TypeEntry* entry = findType(name);
+ if (entry && entry->isObject())
+ return static_cast<ObjectTypeEntry*>(entry);
+ else
+ return 0;
+}
+
+NamespaceTypeEntry* TypeDatabase::findNamespaceType(const QString& name) const
+{
+ TypeEntry* entry = findType(name);
+ if (entry && entry->isNamespace())
+ return static_cast<NamespaceTypeEntry*>(entry);
+ else
+ return 0;
+}
+
diff --git a/typedatabase.h b/typedatabase.h
new file mode 100644
index 000000000..10be28d15
--- /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 <contact@pyside.org>
+ *
+ * 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 <QStringList>
+#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() const;
+
+ void addRequiredTargetImport(const QString& moduleName);
+
+ QStringList typesystemPaths() const
+ {
+ return m_typesystemPaths;
+ }
+
+ void addTypesystemPath(const QString& typesystem_paths);
+
+ IncludeList extraIncludes(const QString& className) const;
+
+ PrimitiveTypeEntry* findPrimitiveType(const QString& name) const;
+ ComplexTypeEntry* findComplexType(const QString& name) const;
+ ObjectTypeEntry* findObjectType(const QString& name) const;
+ NamespaceTypeEntry* findNamespaceType(const QString& name) const;
+ ContainerTypeEntry* findContainerType(const QString& name) const;
+ FunctionTypeEntry* findFunctionType(const QString& name) const;
+
+ TypeEntry* findType(const QString& name) const;
+
+ QList<TypeEntry *> findTypes(const QString &name) const
+ {
+ return m_entries.value(name);
+ }
+
+ TypeEntryHash allEntries() const
+ {
+ return m_entries;
+ }
+
+ SingleTypeEntryHash entries() const;
+
+ PrimitiveTypeEntry* findTargetLangPrimitiveType(const QString& targetLangName) const;
+
+ QList<const PrimitiveTypeEntry*> primitiveTypes() const;
+
+ QList<const ContainerTypeEntry*> containerTypes() const;
+
+ void addRejection(const QString& className, const QString& functionName,
+ const QString& fieldName, const QString& enumName);
+ bool isClassRejected(const QString& className) const;
+ bool isFunctionRejected(const QString& className, const QString& functionName) const;
+ bool isFieldRejected(const QString& className, const QString& fieldName) const;
+ bool isEnumRejected(const QString& className, const QString& enumName) const;
+
+ 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) const
+ {
+ 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) const;
+
+ 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) const;
+ 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<QString, bool> m_parsedTypesystemFiles;
+
+ QList<TypeRejection> m_rejections;
+ QStringList m_rebuildClasses;
+};
+
+#endif
diff --git a/typesystem.cpp b/typesystem.cpp
index 837a0e0d0..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 <QtXml>
@@ -31,177 +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,
- 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["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<QString, QString> *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<QString, StackElement::ElementType> 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)
{
@@ -519,6 +397,9 @@ bool Handler::startElement(const QString &, const QString &n,
attributes["target-type"] = QString();
attributes["generic-class"] = QString("no");
break;
+ case StackElement::FunctionTypeEntry:
+ attributes["signature"] = QString();
+ break;
default:
{ } // nada
};
@@ -526,11 +407,18 @@ bool Handler::startElement(const QString &, const QString &n,
fetchAttributeValues(tagName, atts, &attributes);
QString name = attributes["name"];
+ // The top level tag 'function' has only the 'signature' tag
+ // and we should extract the 'name' value from it.
+ if (element->type == StackElement::FunctionTypeEntry) {
+ QString signature = attributes["signature"];
+ name = signature.left(signature.indexOf('(')).trimmed();
+ }
// We need to be able to have duplicate primitive type entries,
// or it's not possible to cover all primitive target language
// types (which we need to do in order to support fake meta objects)
- if (element->type != StackElement::PrimitiveTypeEntry) {
+ if (element->type != StackElement::PrimitiveTypeEntry
+ && element->type != StackElement::FunctionTypeEntry) {
TypeEntry *tmp = m_database->findType(name);
if (tmp)
ReportHandler::warning(QString("Duplicate type entry: '%1'").arg(name));
@@ -728,6 +616,22 @@ bool Handler::startElement(const QString &, const QString &n,
}
break;
+ case StackElement::FunctionTypeEntry: {
+ QString signature = attributes["signature"];
+ signature = TypeDatabase::normalizedSignature(signature.toLatin1().constData());
+ element->entry = m_database->findType(name);
+ if (element->entry) {
+ if (element->entry->type() == TypeEntry::FunctionType) {
+ reinterpret_cast<FunctionTypeEntry*>(element->entry)->addSignature(signature);
+ } else {
+ m_error = QString("%1 expected to be a function, but isn't! Maybe it was already declared as a class or something else.").arg(name);
+ return false;
+ }
+ } else {
+ element->entry = new FunctionTypeEntry(name, signature);
+ }
+ }
+ break;
default:
Q_ASSERT(false);
};
@@ -1654,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)
@@ -1754,56 +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<ContainerTypeEntry *>(type_entry);
- return 0;
-}
-
-PrimitiveTypeEntry *TypeDatabase::findTargetLangPrimitiveType(const QString &targetLangName)
-{
- foreach (QList<TypeEntry *> entries, m_entries.values()) {
- foreach (TypeEntry *e, entries) {
- if (e && e->isPrimitive()) {
- PrimitiveTypeEntry *pe = static_cast<PrimitiveTypeEntry *>(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 Include::toString() const
-{
- if (type == IncludePath)
- return "#include <" + name + '>';
- else if (type == LocalPath)
- return "#include \"" + name + "\"";
- else
- return "import " + name + ";";
-}
-
QString Modification::accessModifierString() const
{
if (isPrivate()) return "private";
@@ -1908,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 be2852bd9..dc7ebc0a7 100644
--- a/typesystem.h
+++ b/typesystem.h
@@ -30,6 +30,7 @@
#include <QtCore/QMap>
#include <QtCore/QDebug>
#include "apiextractormacros.h"
+#include "include.h"
class Indentor;
@@ -39,34 +40,6 @@ class QTextStream;
class EnumTypeEntry;
class FlagsTypeEntry;
-struct APIEXTRACTOR_API Include
-{
- enum IncludeType {
- IncludePath,
- LocalPath,
- TargetLangImport
- };
-
- Include() : type(IncludePath) {}
- Include(IncludeType t, const QString &nam) : type(t), name(nam) {};
-
- bool isValid()
- {
- return !name.isEmpty();
- }
-
- IncludeType type;
- QString name;
-
- QString toString() const;
-
- bool operator<(const Include &other) const
- {
- return name < other.name;
- }
-};
-typedef QList<Include> IncludeList;
-
typedef QMap<int, QString> ArgumentMap;
class TemplateInstance;
@@ -610,7 +583,8 @@ public:
ArrayType,
TypeSystemType,
CustomType,
- TargetLangType
+ TargetLangType,
+ FunctionType
};
enum CodeGeneration {
@@ -874,9 +848,9 @@ public:
}
void addExtraInclude(const Include &include)
{
- if (!m_includesUsed.value(include.name, false)) {
+ if (!m_includesUsed.value(include.name(), false)) {
m_extraIncludes << include;
- m_includesUsed[include.name] = true;
+ m_includesUsed[include.name()] = true;
}
}
@@ -1726,6 +1700,32 @@ private:
};
+class APIEXTRACTOR_API FunctionTypeEntry : public TypeEntry
+{
+public:
+ FunctionTypeEntry(const QString& name, const QString& signature)
+ : TypeEntry(name, FunctionType)
+ {
+ addSignature(signature);
+ }
+ void addSignature(const QString& signature)
+ {
+ m_signatures << signature;
+ }
+
+ QStringList signatures() const
+ {
+ return m_signatures;
+ }
+
+ bool hasSignature(const QString& signature) const
+ {
+ return m_signatures.contains(signature);
+ }
+private:
+ QStringList m_signatures;
+};
+
class APIEXTRACTOR_API ObjectTypeEntry : public ComplexTypeEntry
{
public:
@@ -1758,271 +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<char *>(";");
-#else
- char *path_splitter = const_cast<char *>(":");
-#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);
-
- TypeEntry *findType(const QString &name) const
- {
- QList<TypeEntry *> entries = findTypes(name);
- foreach (TypeEntry *entry, entries) {
- if (entry &&
- (!entry->isPrimitive() || static_cast<PrimitiveTypeEntry *>(entry)->preferredTargetLangType())) {
- return entry;
- }
- }
- return 0;
- }
- QList<TypeEntry *> findTypes(const QString &name) const
- {
- return m_entries.value(name);
- }
- TypeEntryHash allEntries()
- {
- return m_entries;
- }
-
- SingleTypeEntryHash entries()
- {
- TypeEntryHash entries = allEntries();
-
- SingleTypeEntryHash returned;
- QList<QString> keys = entries.keys();
-
- foreach (QString key, keys)
- returned[key] = findType(key);
-
- return returned;
- }
-
- PrimitiveTypeEntry *findTargetLangPrimitiveType(const QString &targetLangName);
-
- QList<const PrimitiveTypeEntry*> primitiveTypes() {
- TypeEntryHash entries = allEntries();
- QList<const PrimitiveTypeEntry*> returned;
- foreach(QString key, entries.keys()) {
- foreach(const TypeEntry* typeEntry, entries[key]) {
- if (typeEntry->isPrimitive())
- returned.append((PrimitiveTypeEntry*) typeEntry);
- }
- }
- return returned;
- }
- QList<const ContainerTypeEntry*> containerTypes() {
- TypeEntryHash entries = allEntries();
- QList<const ContainerTypeEntry*> 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<QString, bool> m_parsedTypesystemFiles;
-
- QList<TypeRejection> m_rejections;
- QStringList m_rebuildClasses;
-};
-
-inline PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString &name)
-{
- QList<TypeEntry *> entries = findTypes(name);
-
- foreach (TypeEntry *entry, entries) {
- if (entry && entry->isPrimitive() && static_cast<PrimitiveTypeEntry *>(entry)->preferredTargetLangType())
- return static_cast<PrimitiveTypeEntry *>(entry);
- }
-
- return 0;
-}
-
-inline ComplexTypeEntry *TypeDatabase::findComplexType(const QString &name)
-{
- TypeEntry *entry = findType(name);
- if (entry && entry->isComplex())
- return static_cast<ComplexTypeEntry *>(entry);
- else
- return 0;
-}
-
-inline ObjectTypeEntry *TypeDatabase::findObjectType(const QString &name)
-{
- TypeEntry *entry = findType(name);
- if (entry && entry->isObject())
- return static_cast<ObjectTypeEntry *>(entry);
- else
- return 0;
-}
-
-inline NamespaceTypeEntry *TypeDatabase::findNamespaceType(const QString &name)
-{
- TypeEntry *entry = findType(name);
- if (entry && entry->isNamespace())
- return static_cast<NamespaceTypeEntry *>(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 <contact@pyside.org>
+ *
+ * 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 <QXmlDefaultHandler>
+#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<QString, QString> *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<QString, StackElement::ElementType> tagNames;
+ QString m_currentSignature;
+};
+
+#endif