diff generator/abstractmetabuilder.cpp @ 1:e78566595089

initial import
author mandel
date Mon, 11 May 2009 16:01:50 +0000
parents
children ae34188ddd84
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/generator/abstractmetabuilder.cpp	Mon May 11 16:01:50 2009 +0000
@@ -0,0 +1,2601 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Nokia. All rights reserved.
+**
+** This file is part of Qt Jambi.
+**
+** * Commercial Usage
+* Licensees holding valid Qt Commercial licenses may use this file in
+* accordance with the Qt Commercial License Agreement provided with the
+* Software or, alternatively, in accordance with the terms contained in
+* a written agreement between you and Nokia.
+*
+*
+* GNU General Public License Usage
+* Alternatively, this file may be used under the terms of the GNU
+* General Public License versions 2.0 or 3.0 as published by the Free
+* Software Foundation and appearing in the file LICENSE.GPL included in
+* the packaging of this file.  Please review the following information
+* to ensure GNU General Public Licensing requirements will be met:
+* http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+* http://www.gnu.org/copyleft/gpl.html.  In addition, as a special
+* exception, Nokia gives you certain additional rights. These rights
+* are described in the Nokia Qt GPL Exception version 1.2, included in
+* the file GPL_EXCEPTION.txt in this package.
+* 
+* Qt for Windows(R) Licensees
+* As a special exception, Nokia, as the sole copyright holder for Qt
+* Designer, grants users of the Qt/Eclipse Integration plug-in the
+* right for the Qt/Eclipse Integration to link to functionality
+* provided by Qt Designer and its related libraries.
+*
+*
+* If you are unsure which license is appropriate for your use, please
+* contact the sales department at qt-sales@nokia.com.
+
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "abstractmetabuilder.h"
+#include "reporthandler.h"
+
+#include "ast.h"
+#include "binder.h"
+#include "control.h"
+#include "default_visitor.h"
+#include "dumptree.h"
+#include "lexer.h"
+#include "parser.h"
+#include "tokens.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTextStream>
+#include <QtCore/QVariant>
+
+static QString strip_template_args(const QString &name)
+{
+    int pos = name.indexOf('<');
+    return pos < 0 ? name : name.left(pos);
+}
+
+static QHash<QString, QString> *operator_names;
+QString rename_operator(const QString &oper)
+{
+    QString op = oper.trimmed();
+    if (!operator_names) {
+        operator_names = new QHash<QString, QString>;
+
+        operator_names->insert("+", "add");
+        operator_names->insert("-", "subtract");
+        operator_names->insert("*", "multiply");
+        operator_names->insert("/", "divide");
+        operator_names->insert("%", "modulo");
+        operator_names->insert("&", "and");
+        operator_names->insert("|", "or");
+        operator_names->insert("^", "xor");
+        operator_names->insert("~", "negate");
+        operator_names->insert("<<", "shift_left");
+        operator_names->insert(">>", "shift_right");
+
+        // assigments
+        operator_names->insert("=", "assign");
+        operator_names->insert("+=", "add_assign");
+        operator_names->insert("-=", "subtract_assign");
+        operator_names->insert("*=", "multiply_assign");
+        operator_names->insert("/=", "divide_assign");
+        operator_names->insert("%=", "modulo_assign");
+        operator_names->insert("&=", "and_assign");
+        operator_names->insert("|=", "or_assign");
+        operator_names->insert("^=", "xor_assign");
+        operator_names->insert("<<=", "shift_left_assign");
+        operator_names->insert(">>=", "shift_right_assign");
+
+        // Logical
+        operator_names->insert("&&", "logical_and");
+        operator_names->insert("||", "logical_or");
+        operator_names->insert("!", "not");
+
+        // incr/decr
+        operator_names->insert("++", "increment");
+        operator_names->insert("--", "decrement");
+
+        // compare
+        operator_names->insert("<", "less");
+        operator_names->insert(">", "greater");
+        operator_names->insert("<=", "less_or_equal");
+        operator_names->insert(">=", "greater_or_equal");
+        operator_names->insert("!=", "not_equal");
+        operator_names->insert("==", "equal");
+
+        // other
+        operator_names->insert("[]", "subscript");
+        operator_names->insert("->", "pointer");
+    }
+
+    if (!operator_names->contains(op)) {
+        TypeDatabase *tb = TypeDatabase::instance();
+
+        TypeParser::Info typeInfo = TypeParser::parse(op);
+        QString cast_to_name = typeInfo.qualified_name.join("::");
+        TypeEntry *te = tb->findType(cast_to_name);
+        if ((te && te->codeGeneration() == TypeEntry::GenerateNothing)
+            || tb->isClassRejected(cast_to_name)) {
+            return QString();
+        } else if (te) {
+            return "operator_cast_" + typeInfo.qualified_name.join("_");
+        } else {
+            ReportHandler::warning(QString("unknown operator '%1'").arg(op));
+            return "operator " + op;
+        }
+    }
+
+    return "operator_" + operator_names->value(op);
+}
+
+AbstractMetaBuilder::AbstractMetaBuilder()
+    : m_current_class(0)
+{
+}
+
+void AbstractMetaBuilder::checkFunctionModifications()
+{
+    TypeDatabase *types = TypeDatabase::instance();
+    SingleTypeEntryHash entryHash = types->entries();
+    QList<TypeEntry *> entries = entryHash.values();
+    foreach (TypeEntry *entry, entries) {
+        if (entry == 0)
+            continue;
+        if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing)
+            continue;
+
+        ComplexTypeEntry *centry = static_cast<ComplexTypeEntry *>(entry);
+        FunctionModificationList modifications = centry->functionModifications();
+
+        foreach (FunctionModification modification, modifications) {
+            QString signature = modification.signature;
+
+            QString name = signature.trimmed();
+            name = name.mid(0, signature.indexOf("("));
+
+            AbstractMetaClass *clazz = m_meta_classes.findClass(centry->qualifiedCppName());
+            if (clazz == 0)
+                continue;
+
+            AbstractMetaFunctionList functions = clazz->functions();
+            bool found = false;
+            QStringList possibleSignatures;
+            foreach (AbstractMetaFunction *function, functions) {
+                if (function->minimalSignature() == signature && function->implementingClass() == clazz) {
+                    found = true;
+                    break;
+                }
+
+                if (function->originalName() == name)
+                    possibleSignatures.append(function->minimalSignature() + " in " + function->implementingClass()->name());
+            }
+
+            if (!found) {
+                QString warning
+                    = QString("signature '%1' for function modification in '%2' not found. Possible candidates: %3")
+                        .arg(signature)
+                        .arg(clazz->qualifiedCppName())
+                        .arg(possibleSignatures.join(", "));
+
+                ReportHandler::warning(warning);
+            }
+        }
+    }
+}
+
+AbstractMetaClass *AbstractMetaBuilder::argumentToClass(ArgumentModelItem argument)
+{
+    AbstractMetaClass *returned = 0;
+    bool ok = false;
+    AbstractMetaType *type = translateType(argument->type(), &ok);
+    if (ok && type != 0 && type->typeEntry() != 0 && type->typeEntry()->isComplex()) {
+        const TypeEntry *entry = type->typeEntry();
+        returned = m_meta_classes.findClass(entry->name());
+    }
+    delete type;
+    return returned;
+}
+
+/**
+ * Checks the argument of a hash function and flags the type if it is a complex type
+ */
+void AbstractMetaBuilder::registerHashFunction(FunctionModelItem function_item)
+{
+    ArgumentList arguments = function_item->arguments();
+    if (arguments.size() == 1) {
+        if (AbstractMetaClass *cls = argumentToClass(arguments.at(0)))
+            cls->setHasHashFunction(true);
+    }
+}
+
+/**
+ * Check if a class has a debug stream operator that can be used as toString
+ */
+
+void AbstractMetaBuilder::registerToStringCapability(FunctionModelItem function_item)
+{
+    ArgumentList arguments = function_item->arguments();
+    if (arguments.size() == 2) {
+        if (arguments.at(0)->type().toString() == "QDebug"){
+            ArgumentModelItem arg = arguments.at(1);
+            if (AbstractMetaClass *cls = argumentToClass(arg)) {
+                if (arg->type().indirections() < 2) {
+                    cls->setToStringCapability(function_item);
+                }
+            }
+        }
+    }
+}
+
+void AbstractMetaBuilder::traverseCompareOperator(FunctionModelItem item) {
+    ArgumentList arguments = item->arguments();
+    if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
+        AbstractMetaClass *comparer_class = argumentToClass(arguments.at(0));
+        AbstractMetaClass *compared_class = argumentToClass(arguments.at(1));
+        if (comparer_class != 0 && compared_class != 0) {
+            AbstractMetaClass *old_current_class = m_current_class;
+            m_current_class = comparer_class;
+
+            AbstractMetaFunction *meta_function = traverseFunction(item);
+            if (meta_function != 0 && !meta_function->isInvalid()) {
+                // Strip away first argument, since that is the containing object
+                AbstractMetaArgumentList arguments = meta_function->arguments();
+                arguments.pop_front();
+                meta_function->setArguments(arguments);
+
+                meta_function->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
+
+                meta_function->setOriginalAttributes(meta_function->attributes());
+                setupFunctionDefaults(meta_function, comparer_class);
+
+                comparer_class->addFunction(meta_function);
+            } else if (meta_function != 0) {
+                delete meta_function;
+            }
+
+            m_current_class = old_current_class;
+        }
+    }
+}
+
+void AbstractMetaBuilder::traverseStreamOperator(FunctionModelItem item)
+{
+    ArgumentList arguments = item->arguments();
+    if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
+        AbstractMetaClass *streamClass = argumentToClass(arguments.at(0));
+        AbstractMetaClass *streamedClass = argumentToClass(arguments.at(1));
+
+        if (streamClass != 0 && streamedClass != 0
+            && (streamClass->name() == "QDataStream" || streamClass->name() == "QTextStream")) {
+            AbstractMetaClass *old_current_class = m_current_class;
+            m_current_class = streamedClass;
+            AbstractMetaFunction *streamFunction = traverseFunction(item);
+
+            if (streamFunction != 0 && !streamFunction->isInvalid()) {
+                QString name = item->name();
+                streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
+
+                if (name.endsWith("<<"))
+                    streamFunction->setName("writeTo");
+                else
+                    streamFunction->setName("readFrom");
+
+                // Strip away last argument, since that is the containing object
+                AbstractMetaArgumentList arguments = streamFunction->arguments();
+                arguments.pop_back();
+                streamFunction->setArguments(arguments);
+
+                *streamFunction += AbstractMetaAttributes::Final;
+                *streamFunction += AbstractMetaAttributes::Public;
+                streamFunction->setOriginalAttributes(streamFunction->attributes());
+
+                streamFunction->setType(0);
+
+                setupFunctionDefaults(streamFunction, streamedClass);
+
+                streamedClass->addFunction(streamFunction);
+                streamedClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include());
+
+                m_current_class = old_current_class;
+            }
+        }
+    }
+}
+
+void AbstractMetaBuilder::fixQObjectForScope(TypeDatabase *types,
+                     NamespaceModelItem scope)
+{
+    foreach (ClassModelItem item, scope->classes()) {
+        QString qualified_name = item->qualifiedName().join("::");
+        TypeEntry *entry = types->findType(qualified_name);
+        if (entry) {
+        if (isQObject(qualified_name) && entry->isComplex()) {
+                ((ComplexTypeEntry *) entry)->setQObject(true);
+        }
+    }
+    }
+
+    foreach (NamespaceModelItem item, scope->namespaceMap().values()) {
+        if (scope != item)
+      fixQObjectForScope(types, item);
+    }
+}
+
+static bool class_less_than(AbstractMetaClass *a, AbstractMetaClass *b)
+{
+    return a->name() < b->name();
+}
+
+
+void AbstractMetaBuilder::sortLists()
+{
+   qSort(m_meta_classes.begin(), m_meta_classes.end(), class_less_than);
+   foreach (AbstractMetaClass *cls, m_meta_classes) {
+        cls->sortFunctions();
+   }
+}
+
+bool AbstractMetaBuilder::build()
+{
+    Q_ASSERT(!m_file_name.isEmpty());
+    ReportHandler::setContext("Parser");
+
+    QFile file(m_file_name);
+
+    if (!file.open(QFile::ReadOnly))
+        return false;
+
+    QTextStream stream(&file);
+    stream.setCodec(QTextCodec::codecForName("UTF-8"));
+    QByteArray contents = stream.readAll().toUtf8();
+    file.close();
+
+    Control control;
+    Parser p(&control);
+    pool __pool;
+
+    TranslationUnitAST *ast = p.parse(contents, contents.size(), &__pool);
+
+    CodeModel model;
+    Binder binder(&model, p.location());
+    m_dom = binder.run(ast);
+
+
+    ReportHandler::setContext("MetaJavaBuilder");
+
+
+    pushScope(model_dynamic_cast<ScopeModelItem>(m_dom));
+
+    QHash<QString, ClassModelItem> typeMap = m_dom->classMap();
+
+
+    // fix up QObject's in the type system..
+    TypeDatabase *types = TypeDatabase::instance();
+    fixQObjectForScope(types, model_dynamic_cast<NamespaceModelItem>(m_dom));
+
+
+    // Start the generation...
+    foreach (ClassModelItem item, typeMap.values()) {
+        AbstractMetaClass *cls = traverseClass(item);
+        addAbstractMetaClass(cls);
+    }
+
+
+    QHash<QString, NamespaceModelItem> namespaceMap = m_dom->namespaceMap();
+    foreach (NamespaceModelItem item, namespaceMap.values()) {
+        AbstractMetaClass *meta_class = traverseNamespace(item);
+        if (meta_class)
+            m_meta_classes << meta_class;
+    }
+
+
+    // Some trickery to support global-namespace enums...
+    QHash<QString, EnumModelItem> enumMap = m_dom->enumMap();
+    m_current_class = 0;
+    foreach (EnumModelItem item, enumMap) {
+        AbstractMetaEnum *meta_enum = traverseEnum(item, 0, QSet<QString>());
+
+        if (meta_enum) {
+            QString package = meta_enum->typeEntry()->javaPackage();
+            QString globalName = TypeDatabase::globalNamespaceClassName(meta_enum->typeEntry());
+
+            AbstractMetaClass *global = m_meta_classes.findClass(package + "." + globalName);
+            if (!global) {
+                ComplexTypeEntry *gte = new ObjectTypeEntry(globalName);
+                gte->setTargetLangPackage(meta_enum->typeEntry()->javaPackage());
+                gte->setCodeGeneration(meta_enum->typeEntry()->codeGeneration());
+                global = createMetaClass();
+                global->setTypeEntry(gte);
+                *global += AbstractMetaAttributes::Final;
+                *global += AbstractMetaAttributes::Public;
+                *global += AbstractMetaAttributes::Fake;
+
+                m_meta_classes << global;
+            }
+
+            global->addEnum(meta_enum);
+            meta_enum->setEnclosingClass(global);
+            meta_enum->typeEntry()->setQualifier(globalName);
+        }
+
+
+    }
+
+
+    // Go through all typedefs to see if we have defined any
+    // specific typedefs to be used as classes.
+    TypeAliasList typeAliases = m_dom->typeAliases();
+    foreach (TypeAliasModelItem typeAlias, typeAliases) {
+        AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
+        addAbstractMetaClass(cls);
+    }
+
+
+
+
+    foreach (AbstractMetaClass *cls, m_meta_classes) {
+        if (!cls->isInterface() && !cls->isNamespace()) {
+            setupInheritance(cls);
+        }
+    }
+
+
+    foreach (AbstractMetaClass *cls, m_meta_classes) {
+        cls->fixFunctions();
+
+        if (cls->typeEntry() == 0) {
+            ReportHandler::warning(QString("class '%1' does not have an entry in the type system")
+                                   .arg(cls->name()));
+        } else {
+            if (!cls->hasConstructors() && !cls->isFinalInCpp() && !cls->isInterface() && !cls->isNamespace())
+                cls->addDefaultConstructor();
+        }
+
+        if (cls->isAbstract() && !cls->isInterface()) {
+            cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + "_ConcreteWrapper");
+        }
+    }
+
+    QList<TypeEntry *> entries = TypeDatabase::instance()->entries().values();
+    foreach (const TypeEntry *entry, entries) {
+        if (entry->isPrimitive())
+            continue;
+
+        if ((entry->isValue() || entry->isObject())
+            && !entry->isString()
+            && !entry->isChar()
+            && !entry->isContainer()
+            && !entry->isCustom()
+            && !entry->isVariant()
+            && !m_meta_classes.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()) {
+            QString pkg = entry->javaPackage();
+            QString name = (pkg.isEmpty() ? QString() : pkg + ".")
+                           + ((EnumTypeEntry *) entry)->javaQualifier();
+            AbstractMetaClass *cls = m_meta_classes.findClass(name);
+
+            if (!cls) {
+                ReportHandler::warning(QString("namespace '%1' for enum '%2' is not declared")
+                                       .arg(name).arg(entry->targetLangName()));
+            } else {
+                AbstractMetaEnum *e = cls->findEnum(entry->targetLangName());
+                if (!e)
+                    ReportHandler::warning(QString("enum '%1' is specified in typesystem, "
+                                                   "but not declared")
+                                           .arg(entry->qualifiedCppName()));
+            }
+        }
+    }
+
+    {
+        FunctionList hash_functions = m_dom->findFunctions("qHash");
+        foreach (FunctionModelItem item, hash_functions) {
+            registerHashFunction(item);
+        }
+    }
+
+    {
+        FunctionList hash_functions = m_dom->findFunctions("operator<<");
+        foreach (FunctionModelItem item, hash_functions) {
+            registerToStringCapability(item);
+        }
+    }
+
+    {
+        FunctionList compare_operators = m_dom->findFunctions("operator==")
+                                         + m_dom->findFunctions("operator<=")
+                                         + m_dom->findFunctions("operator>=")
+                                         + m_dom->findFunctions("operator<")
+                                         + m_dom->findFunctions("operator>");
+        foreach (FunctionModelItem item, compare_operators) {
+            traverseCompareOperator(item);
+        }
+    }
+
+    {
+        FunctionList stream_operators = m_dom->findFunctions("operator<<") + m_dom->findFunctions("operator>>");
+        foreach (FunctionModelItem item, stream_operators) {
+            traverseStreamOperator(item);
+        }
+    }
+
+    figureOutEnumValues();
+    figureOutDefaultEnumArguments();
+    checkFunctionModifications();
+
+    foreach (AbstractMetaClass *cls, m_meta_classes) {
+        setupEquals(cls);
+        setupComparable(cls);
+        setupClonable(cls);
+    }
+
+    dumpLog();
+
+    sortLists();
+
+    return true;
+}
+
+
+void AbstractMetaBuilder::addAbstractMetaClass(AbstractMetaClass *cls)
+{
+    if (!cls)
+        return;
+
+    cls->setOriginalAttributes(cls->attributes());
+    if (cls->typeEntry()->isContainer()) {
+        m_templates << cls;
+    } else {
+        m_meta_classes << cls;
+        if (cls->typeEntry()->designatedInterface()) {
+            AbstractMetaClass *interface = cls->extractInterface();
+            m_meta_classes << interface;
+            ReportHandler::debugSparse(QString(" -> interface '%1'").arg(interface->name()));
+        }
+    }
+}
+
+
+AbstractMetaClass *AbstractMetaBuilder::traverseNamespace(NamespaceModelItem namespace_item)
+{
+    QString namespace_name = (!m_namespace_prefix.isEmpty() ? m_namespace_prefix + "::" : QString()) + namespace_item->name();
+    NamespaceTypeEntry *type = TypeDatabase::instance()->findNamespaceType(namespace_name);
+
+    if (TypeDatabase::instance()->isClassRejected(namespace_name)) {
+        m_rejected_classes.insert(namespace_name, GenerationDisabled);
+        return 0;
+    }
+
+    if (!type) {
+        ReportHandler::warning(QString("namespace '%1' does not have a type entry")
+                               .arg(namespace_name));
+        return 0;
+    }
+
+    AbstractMetaClass *meta_class = createMetaClass();
+    meta_class->setTypeEntry(type);
+
+    *meta_class += AbstractMetaAttributes::Public;
+
+    m_current_class = meta_class;
+
+    ReportHandler::debugSparse(QString("namespace '%1.%2'")
+                               .arg(meta_class->package())
+                               .arg(namespace_item->name()));
+
+    traverseEnums(model_dynamic_cast<ScopeModelItem>(namespace_item), meta_class, namespace_item->enumsDeclarations());
+    traverseFunctions(model_dynamic_cast<ScopeModelItem>(namespace_item), meta_class);
+//     traverseClasses(model_dynamic_cast<ScopeModelItem>(namespace_item));
+
+    pushScope(model_dynamic_cast<ScopeModelItem>(namespace_item));
+    m_namespace_prefix = currentScope()->qualifiedName().join("::");
+
+
+    ClassList classes = namespace_item->classes();
+    foreach (ClassModelItem cls, classes) {
+        AbstractMetaClass *mjc = traverseClass(cls);
+        addAbstractMetaClass(mjc);
+    }
+
+    // Go through all typedefs to see if we have defined any
+    // specific typedefs to be used as classes.
+    TypeAliasList typeAliases = namespace_item->typeAliases();
+    foreach (TypeAliasModelItem typeAlias, typeAliases) {
+        AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
+        addAbstractMetaClass(cls);
+    }
+
+
+
+    // Traverse namespaces recursively
+    QList<NamespaceModelItem> inner_namespaces = namespace_item->namespaceMap().values();
+    foreach (const NamespaceModelItem &ni, inner_namespaces) {
+        AbstractMetaClass *mjc = traverseNamespace(ni);
+        addAbstractMetaClass(mjc);
+    }
+
+    m_current_class = 0;
+
+
+    popScope();
+    m_namespace_prefix = currentScope()->qualifiedName().join("::");
+
+    if (!type->include().isValid()) {
+        QFileInfo info(namespace_item->fileName());
+        type->setInclude(Include(Include::IncludePath, info.fileName()));
+    }
+
+    return meta_class;
+}
+
+struct Operator
+{
+    enum Type { Plus, ShiftLeft, None };
+
+    Operator() : type(None) { }
+
+    int calculate(int x) {
+        switch (type) {
+        case Plus: return x + value;
+        case ShiftLeft: return x << value;
+        case None: return x;
+        }
+        return x;
+    }
+
+    Type type;
+    int value;
+};
+
+
+
+Operator findOperator(QString *s) {
+    const char *names[] = {
+        "+",
+        "<<"
+    };
+
+    for (int i=0; i<Operator::None; ++i) {
+        QString name = QLatin1String(names[i]);
+        QString str = *s;
+        int splitPoint = str.indexOf(name);
+        if (splitPoint > 0) {
+            bool ok;
+            QString right = str.mid(splitPoint + name.length());
+            Operator op;
+            op.value = right.toInt(&ok);
+            if (ok) {
+                op.type = Operator::Type(i);
+                *s = str.left(splitPoint).trimmed();
+                return op;
+            }
+        }
+    }
+    return Operator();
+}
+
+int AbstractMetaBuilder::figureOutEnumValue(const QString &stringValue,
+                                        int oldValuevalue,
+                                        AbstractMetaEnum *meta_enum,
+                                        AbstractMetaFunction *meta_function)
+{
+    if (stringValue.isEmpty())
+        return oldValuevalue;
+
+    QStringList stringValues = stringValue.split("|");
+
+    int returnValue = 0;
+
+    bool matched = false;
+
+    for (int i=0; i<stringValues.size(); ++i) {
+        QString s = stringValues.at(i).trimmed();
+
+        bool ok;
+        int v;
+
+        Operator op = findOperator(&s);
+
+        if (s.length() > 0 && s.at(0) == QLatin1Char('0'))
+            v = s.toUInt(&ok, 0);
+        else
+            v = s.toInt(&ok);
+
+        if (ok) {
+            matched = true;
+
+        } else if (m_enum_values.contains(s)) {
+            v = m_enum_values[s]->value();
+            matched = true;
+
+        } else {
+            AbstractMetaEnumValue *ev = 0;
+
+            if (meta_enum && (ev = meta_enum->values().find(s))) {
+                v = ev->value();
+                matched = true;
+
+            } else if (meta_enum && (ev = meta_enum->enclosingClass()->findEnumValue(s, meta_enum))) {
+                v = ev->value();
+                matched = true;
+
+            } else {
+                if (meta_enum)
+                    ReportHandler::warning("unhandled enum value: " + s + " in "
+                                           + meta_enum->enclosingClass()->name() + "::"
+                                           + meta_enum->name());
+                else
+                    ReportHandler::warning("unhandled enum value: Unknown enum");
+            }
+        }
+
+        if (matched)
+            returnValue |= op.calculate(v);
+    }
+
+    if (!matched) {
+        QString warn = QString("unmatched enum %1").arg(stringValue);
+
+        if (meta_function != 0) {
+            warn += QString(" when parsing default value of '%1' in class '%2'")
+                .arg(meta_function->name())
+                .arg(meta_function->implementingClass()->name());
+        }
+
+        ReportHandler::warning(warn);
+        returnValue = oldValuevalue;
+    }
+
+    return returnValue;
+}
+
+void AbstractMetaBuilder::figureOutEnumValuesForClass(AbstractMetaClass *meta_class,
+                                                  QSet<AbstractMetaClass *> *classes)
+{
+    AbstractMetaClass *base = meta_class->baseClass();
+
+    if (base != 0 && !classes->contains(base))
+        figureOutEnumValuesForClass(base, classes);
+
+    if (classes->contains(meta_class))
+        return;
+
+    AbstractMetaEnumList enums = meta_class->enums();
+    foreach (AbstractMetaEnum *e, enums) {
+        if (!e)
+            ReportHandler::warning("bad enum in class " + meta_class->name());
+        AbstractMetaEnumValueList lst = e->values();
+        int value = 0;
+        for (int i=0; i<lst.size(); ++i) {
+            value = figureOutEnumValue(lst.at(i)->stringValue(), value, e);
+            lst.at(i)->setValue(value);
+            value++;
+        }
+
+        // Check for duplicate values...
+        EnumTypeEntry *ete = e->typeEntry();
+        if (!ete->forceInteger()) {
+            QHash<int, AbstractMetaEnumValue *> entries;
+            foreach (AbstractMetaEnumValue *v, lst) {
+
+                bool vRejected = ete->isEnumValueRejected(v->name());
+
+                AbstractMetaEnumValue *current = entries.value(v->value());
+                if (current) {
+                    bool currentRejected = ete->isEnumValueRejected(current->name());
+                    if (!currentRejected && !vRejected) {
+                        ReportHandler::warning(
+                            QString("duplicate enum values: %1::%2, %3 and %4 are %5, already rejected: (%6)")
+                            .arg(meta_class->name())
+                            .arg(e->name())
+                            .arg(v->name())
+                            .arg(entries[v->value()]->name())
+                            .arg(v->value())
+                            .arg(ete->enumValueRejections().join(", ")));
+                        continue;
+                    }
+                }
+
+                if (!vRejected)
+                    entries[v->value()] = v;
+            }
+
+            // Entries now contain all the original entries, no
+            // rejected ones... Use this to generate the enumValueRedirection table.
+            foreach (AbstractMetaEnumValue *reject, lst) {
+                if (!ete->isEnumValueRejected(reject->name()))
+                    continue;
+
+                AbstractMetaEnumValue *used = entries.value(reject->value());
+                if (!used) {
+                    ReportHandler::warning(
+                        QString::fromLatin1("Rejected enum has no alternative...: %1::%2\n")
+                        .arg(meta_class->name())
+                        .arg(reject->name()));
+                    continue;
+                }
+                ete->addEnumValueRedirection(reject->name(), used->name());
+            }
+
+        }
+    }
+
+
+
+    *classes += meta_class;
+}
+
+
+void AbstractMetaBuilder::figureOutEnumValues()
+{
+    // Keep a set of classes that we already traversed. We use this to
+    // enforce that we traverse base classes prior to subclasses.
+    QSet<AbstractMetaClass *> classes;
+    foreach (AbstractMetaClass *c, m_meta_classes) {
+        figureOutEnumValuesForClass(c, &classes);
+    }
+}
+
+void AbstractMetaBuilder::figureOutDefaultEnumArguments()
+{
+    foreach (AbstractMetaClass *meta_class, m_meta_classes) {
+        foreach (AbstractMetaFunction *meta_function, meta_class->functions()) {
+            foreach (AbstractMetaArgument *arg, meta_function->arguments()) {
+
+                QString expr = arg->defaultValueExpression();
+                if (expr.isEmpty())
+                    continue;
+
+                if (!meta_function->replacedDefaultExpression(meta_function->implementingClass(),
+                    arg->argumentIndex()+1).isEmpty()) {
+                    continue;
+                }
+
+                QString new_expr = expr;
+                if (arg->type()->isEnum()) {
+                    QStringList lst = expr.split(QLatin1String("::"));
+                    if (lst.size() == 1) {
+                        QVector<AbstractMetaClass *> classes(1, meta_class);
+                        AbstractMetaEnum *e = 0;
+                        while (!classes.isEmpty() && e == 0) {
+                            if (classes.front() != 0) {
+                                classes << classes.front()->baseClass();
+
+                                AbstractMetaClassList interfaces = classes.front()->interfaces();
+                                foreach (AbstractMetaClass *interface, interfaces)
+                                    classes << interface->primaryInterfaceImplementor();
+
+                                e = classes.front()->findEnumForValue(expr);
+                            }
+
+                            classes.pop_front();
+                        }
+
+                        if (e != 0) {
+/* qtd                           new_expr = QString("%1.%2")
+                                    .arg(e->typeEntry()->qualifiedTargetLangName())
+                                    .arg(expr);
+                                    */
+//                            new_expr = arg->type()->typeEntry()->targetLangName() + "." + expr;
+                            new_expr = arg->type()->typeEntry()->qualifiedTargetLangName() + "." + expr;
+                        } else {
+                            ReportHandler::warning("Cannot find enum constant for value '" + expr + "' in '" + meta_class->name() + "' or any of its super classes");
+                        }
+                    } else if (lst.size() == 2) {
+                        AbstractMetaClass *cl = m_meta_classes.findClass(lst.at(0));
+                        if (!cl) {
+                            ReportHandler::warning("missing required class for enums: " + lst.at(0));
+                            continue;
+                        }
+/* qtd                        new_expr = QString("%1.%2.%3")
+                                   .arg(cl->typeEntry()->qualifiedTargetLangName())
+                                   .arg(arg->type()->name())
+                                   .arg(lst.at(1));
+                                   */
+//                        new_expr = arg->type()->typeEntry()->targetLangName() + "." + lst.at(1);
+                        new_expr = arg->type()->typeEntry()->qualifiedTargetLangName() + "." + lst.at(1);
+                    } else {
+                        ReportHandler::warning("bad default value passed to enum " + expr);
+                    }
+
+                } else if(arg->type()->isFlags()) {
+                    const FlagsTypeEntry *flagsEntry =
+                        static_cast<const FlagsTypeEntry *>(arg->type()->typeEntry());
+                    EnumTypeEntry *enumEntry = flagsEntry->originator();
+                    AbstractMetaEnum *meta_enum = m_meta_classes.findEnum(enumEntry);
+                    if (!meta_enum) {
+                        ReportHandler::warning("unknown required enum " + enumEntry->qualifiedCppName());
+                        continue;
+                    }
+
+                    int value = figureOutEnumValue(expr, 0, meta_enum, meta_function);
+                    new_expr = QString::number(value);
+
+                } else if (arg->type()->isPrimitive()) {
+                    AbstractMetaEnumValue *value = 0;
+                    if (expr.contains("::"))
+                        value = m_meta_classes.findEnumValue(expr);
+                    if (!value)
+                        value = meta_class->findEnumValue(expr, 0);
+
+                    if (value) {
+                        new_expr = QString::number(value->value());
+                    } else if (expr.contains(QLatin1Char('+'))) {
+                        new_expr = QString::number(figureOutEnumValue(expr, 0, 0));
+
+                    }
+
+
+
+                }
+
+                arg->setDefaultValueExpression(new_expr);
+            }
+        }
+    }
+}
+
+
+AbstractMetaEnum *AbstractMetaBuilder::traverseEnum(EnumModelItem enum_item, AbstractMetaClass *enclosing, const QSet<QString> &enumsDeclarations)
+{
+    // Skipping private enums.
+    if (enum_item->accessPolicy() == CodeModel::Private) {
+        return 0;
+    }
+
+    QString qualified_name = enum_item->qualifiedName().join("::");
+
+    TypeEntry *type_entry = TypeDatabase::instance()->findType(qualified_name);
+    QString enum_name = enum_item->name();
+
+    QString class_name;
+    if (m_current_class)
+        class_name = m_current_class->typeEntry()->qualifiedCppName();
+
+    if (TypeDatabase::instance()->isEnumRejected(class_name, enum_name)) {
+        m_rejected_enums.insert(qualified_name, GenerationDisabled);
+        return 0;
+    }
+
+    if (!type_entry || !type_entry->isEnum()) {
+        QString context = m_current_class ? m_current_class->name() : QLatin1String("");
+        ReportHandler::warning(QString("enum '%1' does not have a type entry or is not an enum")
+                               .arg(qualified_name));
+        m_rejected_enums.insert(qualified_name, NotInTypeSystem);
+       return 0;
+    }
+
+    AbstractMetaEnum *meta_enum = createMetaEnum();
+    if (   enumsDeclarations.contains(qualified_name)
+        || enumsDeclarations.contains(enum_name)) {
+        meta_enum->setHasQEnumsDeclaration(true);
+    }
+
+    meta_enum->setTypeEntry((EnumTypeEntry *) type_entry);
+    switch (enum_item->accessPolicy()) {
+    case CodeModel::Public: *meta_enum += AbstractMetaAttributes::Public; break;
+    case CodeModel::Protected: *meta_enum += AbstractMetaAttributes::Protected; break;
+//     case CodeModel::Private: *meta_enum += AbstractMetaAttributes::Private; break;
+    default: break;
+    }
+
+    ReportHandler::debugMedium(QString(" - traversing enum %1").arg(meta_enum->fullName()));
+
+    foreach (EnumeratorModelItem value, enum_item->enumerators()) {
+
+        AbstractMetaEnumValue *meta_enum_value = createMetaEnumValue();
+        meta_enum_value->setName(value->name());
+        // Deciding the enum value...
+
+        meta_enum_value->setStringValue(value->value());
+        meta_enum->addEnumValue(meta_enum_value);
+
+        ReportHandler::debugFull("   - " + meta_enum_value->name() + " = "
+                                 + meta_enum_value->value());
+
+        // Add into global register...
+        if (enclosing)
+            m_enum_values[enclosing->name() + "::" + meta_enum_value->name()] = meta_enum_value;
+        else
+            m_enum_values[meta_enum_value->name()] = meta_enum_value;
+    }
+
+    m_enums << meta_enum;
+
+    return meta_enum;
+}
+
+AbstractMetaClass *AbstractMetaBuilder::traverseTypeAlias(TypeAliasModelItem typeAlias)
+{
+    QString class_name = strip_template_args(typeAlias->name());
+
+    QString full_class_name = class_name;
+    // we have an inner class
+    if (m_current_class) {
+        full_class_name = strip_template_args(m_current_class->typeEntry()->qualifiedCppName())
+                          + "::" + full_class_name;
+    }
+
+    // If we haven't specified anything for the typedef, then we don't care
+    ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(full_class_name);
+    if (type == 0)
+        return 0;
+
+    if (type->isObject())
+        static_cast<ObjectTypeEntry *>(type)->setQObject(isQObject(strip_template_args(typeAlias->type().qualifiedName().join("::"))));
+
+    AbstractMetaClass *meta_class = createMetaClass();
+    meta_class->setTypeAlias(true);
+    meta_class->setTypeEntry(type);
+    meta_class->setBaseClassNames(QStringList() << typeAlias->type().qualifiedName().join("::"));
+    *meta_class += AbstractMetaAttributes::Public;
+
+    // Set the default include file name
+    if (!type->include().isValid()) {
+        QFileInfo info(typeAlias->fileName());
+        type->setInclude(Include(Include::IncludePath, info.fileName()));
+    }
+
+    return meta_class;
+}
+
+AbstractMetaClass *AbstractMetaBuilder::traverseClass(ClassModelItem class_item)
+{
+    QString class_name = strip_template_args(class_item->name());
+    QString full_class_name = class_name;
+
+    // we have inner an class
+    if (m_current_class) {
+        full_class_name = strip_template_args(m_current_class->typeEntry()->qualifiedCppName())
+                          + "::" + full_class_name;
+    }
+
+    ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(full_class_name);
+    RejectReason reason = NoReason;
+
+
+    if (TypeDatabase::instance()->isClassRejected(full_class_name)) {
+        reason = GenerationDisabled;
+    } else if (!type) {
+        TypeEntry *te = TypeDatabase::instance()->findType(full_class_name);
+        if (te && !te->isComplex())
+            reason = RedefinedToNotClass;
+        else
+            reason = NotInTypeSystem;
+    } else if (type->codeGeneration() == TypeEntry::GenerateNothing) {
+        reason = GenerationDisabled;
+    }
+
+    if (reason != NoReason) {
+        m_rejected_classes.insert(full_class_name, reason);
+        return 0;
+    }
+
+    if (type->isObject()) {
+        ((ObjectTypeEntry *)type)->setQObject(isQObject(full_class_name));
+    }
+
+    AbstractMetaClass *meta_class = createMetaClass();
+    meta_class->setTypeEntry(type);
+    meta_class->setBaseClassNames(class_item->baseClasses());
+    *meta_class += AbstractMetaAttributes::Public;
+
+    AbstractMetaClass *old_current_class = m_current_class;
+    m_current_class = meta_class;
+
+    if (type->isContainer()) {
+        ReportHandler::debugSparse(QString("container: '%1'").arg(full_class_name));
+    } else {
+        ReportHandler::debugSparse(QString("class: '%1'").arg(meta_class->fullName()));
+    }
+
+    TemplateParameterList template_parameters = class_item->templateParameters();
+    QList<TypeEntry *> template_args;
+    template_args.clear();
+    for (int i=0; i<template_parameters.size(); ++i) {
+        const TemplateParameterModelItem &param = template_parameters.at(i);
+        TemplateArgumentEntry *param_type = new TemplateArgumentEntry(param->name());
+        param_type->setOrdinal(i);
+        template_args.append(param_type);
+    }
+    meta_class->setTemplateArguments(template_args);
+
+    parseQ_Property(meta_class, class_item->propertyDeclarations());
+
+    traverseFunctions(model_dynamic_cast<ScopeModelItem>(class_item), meta_class);
+    traverseEnums(model_dynamic_cast<ScopeModelItem>(class_item), meta_class, class_item->enumsDeclarations());
+    traverseFields(model_dynamic_cast<ScopeModelItem>(class_item), meta_class);
+
+    // Inner classes
+    {
+        QList<ClassModelItem> inner_classes = class_item->classMap().values();
+        foreach (const ClassModelItem &ci, inner_classes) {
+            AbstractMetaClass *cl = traverseClass(ci);
+            if (cl) {
+                cl->setEnclosingClass(meta_class);
+                m_meta_classes << cl;
+            }
+        }
+
+    }
+
+    // Go through all typedefs to see if we have defined any
+    // specific typedefs to be used as classes.
+    TypeAliasList typeAliases = class_item->typeAliases();
+    foreach (TypeAliasModelItem typeAlias, typeAliases) {
+        AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
+        if (cls != 0) {
+            cls->setEnclosingClass(meta_class);
+            addAbstractMetaClass(cls);
+        }
+    }
+
+
+    m_current_class = old_current_class;
+
+    // Set the default include file name
+    if (!type->include().isValid()) {
+        QFileInfo info(class_item->fileName());
+        type->setInclude(Include(Include::IncludePath, info.fileName()));
+    }
+
+    return meta_class;
+}
+
+AbstractMetaField *AbstractMetaBuilder::traverseField(VariableModelItem field, const AbstractMetaClass *cls)
+{
+    QString field_name = field->name();
+    QString class_name = m_current_class->typeEntry()->qualifiedCppName();
+
+    // Ignore friend decl.
+    if (field->isFriend())
+        return 0;
+
+    if (field->accessPolicy() == CodeModel::Private)
+        return 0;
+
+    if (TypeDatabase::instance()->isFieldRejected(class_name, field_name)) {
+        m_rejected_fields.insert(class_name + "::" + field_name, GenerationDisabled);
+        return 0;
+    }
+
+
+    AbstractMetaField *meta_field = createMetaField();
+    meta_field->setName(field_name);
+    meta_field->setEnclosingClass(cls);
+
+    bool ok;
+    TypeInfo field_type = field->type();
+    AbstractMetaType *meta_type = translateType(field_type, &ok);
+
+    if (!meta_type || !ok) {
+        ReportHandler::warning(QString("skipping field '%1::%2' with unmatched type '%3'")
+                               .arg(m_current_class->name())
+                               .arg(field_name)
+                               .arg(TypeInfo::resolveType(field_type, currentScope()->toItem()).qualifiedName().join("::")));
+        delete meta_field;
+        return 0;
+    }
+
+    meta_field->setType(meta_type);
+
+    uint attr = 0;
+    if (field->isStatic())
+        attr |= AbstractMetaAttributes::Static;
+
+    CodeModel::AccessPolicy policy = field->accessPolicy();
+    if (policy == CodeModel::Public)
+        attr |= AbstractMetaAttributes::Public;
+    else if (policy == CodeModel::Protected)
+        attr |= AbstractMetaAttributes::Protected;
+    else
+        attr |= AbstractMetaAttributes::Private;
+    meta_field->setAttributes(attr);
+
+    return meta_field;
+}
+
+void AbstractMetaBuilder::traverseFields(ScopeModelItem scope_item, AbstractMetaClass *meta_class)
+{
+    foreach (VariableModelItem field, scope_item->variables()) {
+        AbstractMetaField *meta_field = traverseField(field, meta_class);
+
+        if (meta_field) {
+            meta_field->setOriginalAttributes(meta_field->attributes());
+            meta_class->addField(meta_field);
+        }
+    }
+}
+
+void AbstractMetaBuilder::setupFunctionDefaults(AbstractMetaFunction *meta_function, AbstractMetaClass *meta_class)
+{
+    // Set the default value of the declaring class. This may be changed
+    // in fixFunctions later on
+    meta_function->setDeclaringClass(meta_class);
+
+    // Some of the queries below depend on the implementing class being set
+    // to function properly. Such as function modifications
+    meta_function->setImplementingClass(meta_class);
+
+    if (meta_function->name() == "operator_equal")
+        meta_class->setHasEqualsOperator(true);
+
+    if (!meta_function->isFinalInTargetLang()
+        && meta_function->isRemovedFrom(meta_class, TypeSystem::TargetLangCode)) {
+        *meta_function += AbstractMetaAttributes::FinalInCpp;
+    }
+}
+
+void AbstractMetaBuilder::traverseFunctions(ScopeModelItem scope_item, AbstractMetaClass *meta_class)
+{
+    foreach (FunctionModelItem function, scope_item->functions()) {
+        AbstractMetaFunction *meta_function = traverseFunction(function);
+
+        if (meta_function) {
+            meta_function->setOriginalAttributes(meta_function->attributes());
+            if (meta_class->isNamespace())
+                *meta_function += AbstractMetaAttributes::Static;
+
+            if (!meta_function->isInvalid()) {
+                if (QPropertySpec *read = meta_class->propertySpecForRead(meta_function->name())) {
+                    if (read->type() == meta_function->type()->typeEntry()) {
+                        *meta_function += AbstractMetaAttributes::PropertyReader;
+                        meta_function->setPropertySpec(read);
+//                     printf("%s is reader for %s\n",
+//                            qPrintable(meta_function->name()),
+//                            qPrintable(read->name()));
+                    }
+                } else if (QPropertySpec *write =
+                           meta_class->propertySpecForWrite(meta_function->name())) {
+                    if (write->type() == meta_function->arguments().at(0)->type()->typeEntry()) {
+                    *meta_function += AbstractMetaAttributes::PropertyWriter;
+                    meta_function->setPropertySpec(write);
+/*
+                    // qtd D properties syntax, rename setter from setPropertyName to just propertyName
+                    AbstractMetaFunction *f_copy = new AbstractMetaFunction();
+                    *f_copy = *meta_function;
+
+                    QString f_name = meta_function->name();
+                    QString new_name = f_name.midRef(3, 1).toString().toLower() + f_name.right(f_name.length() - 4);
+                    meta_function->setName(new_name);
+                    // f_copy->setOwnerClass(meta_function->ownerClass());
+                    ((AbstractMetaClass*)(meta_function->ownerClass()))->addFunction(f_copy); // hack qtd2
+                    //
+*/
+//                     printf("%s is writer for %s\n",
+//                            qPrintable(meta_function->name()),
+//                            qPrintable(write->name()));
+                    }
+                } else if (QPropertySpec *reset =
+                           meta_class->propertySpecForReset(meta_function->name())) {
+                    *meta_function += AbstractMetaAttributes::PropertyResetter;
+                    meta_function->setPropertySpec(reset);
+//                     printf("%s is resetter for %s\n",
+//                            qPrintable(meta_function->name()),
+//                            qPrintable(reset->name()));
+                }
+            }
+
+
+            bool isInvalidDestructor = meta_function->isDestructor() && meta_function->isPrivate();
+            bool isInvalidConstructor = meta_function->isConstructor()
+                && (meta_function->isPrivate() || meta_function->isInvalid());
+            if ((isInvalidDestructor || isInvalidConstructor)
+                && !meta_class->hasNonPrivateConstructor()) {
+                *meta_class += AbstractMetaAttributes::Final;
+            } else if (meta_function->isConstructor() && !meta_function->isPrivate()) {
+                *meta_class -= AbstractMetaAttributes::Final;
+                meta_class->setHasNonPrivateConstructor(true);
+            }
+
+            // Classes with virtual destructors should always have a shell class
+            // (since we aren't registering the destructors, we need this extra check)
+            if (meta_function->isDestructor() && !meta_function->isFinal())
+                meta_class->setForceShellClass(true);
+
+            if (!meta_function->isDestructor()
+                && !meta_function->isInvalid()
+                && (!meta_function->isConstructor() || !meta_function->isPrivate())) {
+
+                if (meta_class->typeEntry()->designatedInterface() && !meta_function->isPublic()
+                    && !meta_function->isPrivate()) {
+                    QString warn = QString("non-public function '%1' in interface '%2'")
+                        .arg(meta_function->name()).arg(meta_class->name());
+                    ReportHandler::warning(warn);
+
+                    meta_function->setVisibility(AbstractMetaClass::Public);
+                }
+
+                setupFunctionDefaults(meta_function, meta_class);
+
+                if (meta_function->isSignal() && meta_class->hasSignal(meta_function)) {
+                    QString warn = QString("signal '%1' in class '%2' is overloaded.")
+                        .arg(meta_function->name()).arg(meta_class->name());
+                    ReportHandler::warning(warn);
+                }
+
+                if (meta_function->isSignal() && !meta_class->isQObject()) {
+                    QString warn = QString("signal '%1' in non-QObject class '%2'")
+                        .arg(meta_function->name()).arg(meta_class->name());
+                    ReportHandler::warning(warn);
+                }
+
+                meta_class->addFunction(meta_function);
+            } else if (meta_function->isDestructor() && !meta_function->isPublic()) {
+                meta_class->setHasPublicDestructor(false);
+            }
+        }
+    }
+}
+
+bool AbstractMetaBuilder::setupInheritance(AbstractMetaClass *meta_class)
+{
+    Q_ASSERT(!meta_class->isInterface());
+
+    if (m_setup_inheritance_done.contains(meta_class))
+        return true;
+    m_setup_inheritance_done.insert(meta_class);
+
+    QStringList base_classes = meta_class->baseClassNames();
+
+    TypeDatabase *types = TypeDatabase::instance();
+
+    // we only support our own containers and ONLY if there is only one baseclass
+    if (base_classes.size() == 1 && base_classes.first().count('<') == 1) {
+        QStringList scope = meta_class->typeEntry()->qualifiedCppName().split("::");
+        scope.removeLast();
+        for (int i=scope.size(); i>=0; --i) {
+            QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join("::") + "::" : QString();
+            QString complete_name = prefix + base_classes.first();
+            TypeParser::Info info = TypeParser::parse(complete_name);
+            QString base_name = info.qualified_name.join("::");
+
+            AbstractMetaClass *templ = 0;
+            foreach (AbstractMetaClass *c, m_templates) {
+                if (c->typeEntry()->name() == base_name) {
+                    templ = c;
+                    break;
+                }
+            }
+
+            if (templ == 0)
+                templ = m_meta_classes.findClass(base_name);
+
+            if (templ) {
+                setupInheritance(templ);
+                inheritTemplate(meta_class, templ, info);
+                return true;
+            }
+        }
+
+        ReportHandler::warning(QString("template baseclass '%1' of '%2' is not known")
+                                .arg(base_classes.first())
+                                .arg(meta_class->name()));
+        return false;
+    }
+
+    int primary = -1;
+    int primaries = 0;
+    for (int i=0; i<base_classes.size(); ++i) {
+
+        if (types->isClassRejected(base_classes.at(i)))
+            continue;
+
+        TypeEntry *base_class_entry = types->findType(base_classes.at(i));
+        if (!base_class_entry) {
+            ReportHandler::warning(QString("class '%1' inherits from unknown base class '%2'")
+                                   .arg(meta_class->name()).arg(base_classes.at(i)));
+        }
+
+        // true for primary base class
+        else if (!base_class_entry->designatedInterface()) {
+            if (primaries > 0) {
+                ReportHandler::warning(QString("class '%1' has multiple primary base classes"
+                                               " '%2' and '%3'")
+                                       .arg(meta_class->name())
+                                       .arg(base_classes.at(primary))
+                                       .arg(base_class_entry->name()));
+                return false;
+            }
+            primaries++;
+            primary = i;
+        }
+    }
+
+    if (primary >= 0) {
+        AbstractMetaClass *base_class = m_meta_classes.findClass(base_classes.at(primary));
+        if (!base_class) {
+            ReportHandler::warning(QString("unknown baseclass for '%1': '%2'")
+                                   .arg(meta_class->name())
+                                   .arg(base_classes.at(primary)));
+            return false;
+        }
+        meta_class->setBaseClass(base_class);
+
+        if (meta_class->typeEntry()->designatedInterface() != 0 && meta_class->isQObject()) {
+            ReportHandler::warning(QString("QObject extended by interface type '%1'. This is not supported and the generated Java code will not compile.")
+                                   .arg(meta_class->name()));
+        } else if (meta_class->typeEntry()->designatedInterface() != 0 && base_class != 0 && !base_class->isInterface()) {
+            ReportHandler::warning(QString("object type '%1' extended by interface type '%2'. The resulting API will be less expressive than the original.")
+                                   .arg(base_class->name())
+                                   .arg(meta_class->name()));
+        }
+
+    }
+
+    for (int i=0; i<base_classes.size(); ++i) {
+        if (types->isClassRejected(base_classes.at(i)))
+            continue;
+
+        if (i != primary) {
+            AbstractMetaClass *base_class = m_meta_classes.findClass(base_classes.at(i));
+            if (base_class == 0) {
+                ReportHandler::warning(QString("class not found for setup inheritance '%1'").arg(base_classes.at(i)));
+                return false;
+            }
+
+            setupInheritance(base_class);
+
+            QString interface_name = InterfaceTypeEntry::interfaceName(base_class->name());
+            AbstractMetaClass *iface = m_meta_classes.findClass(interface_name);
+            if (!iface) {
+                ReportHandler::warning(QString("unknown interface for '%1': '%2'")
+                                       .arg(meta_class->name())
+                                       .arg(interface_name));
+                return false;
+            }
+            meta_class->addInterface(iface);
+
+            AbstractMetaClassList interfaces = iface->interfaces();
+            foreach (AbstractMetaClass *iface, interfaces)
+                meta_class->addInterface(iface);
+        }
+    }
+
+    return true;
+}
+
+void AbstractMetaBuilder::traverseEnums(ScopeModelItem scope_item, AbstractMetaClass *meta_class, const QStringList &enumsDeclarations)
+{
+    EnumList enums = scope_item->enums();
+    foreach (EnumModelItem enum_item, enums) {
+        AbstractMetaEnum *meta_enum = traverseEnum(enum_item, meta_class, QSet<QString>::fromList(enumsDeclarations));
+        if (meta_enum) {
+            meta_enum->setOriginalAttributes(meta_enum->attributes());
+            meta_class->addEnum(meta_enum);
+            meta_enum->setEnclosingClass(meta_class);
+        }
+    }
+}
+
+AbstractMetaFunction *AbstractMetaBuilder::traverseFunction(FunctionModelItem function_item)
+{
+    QString function_name = function_item->name();
+    QString class_name = m_current_class->typeEntry()->qualifiedCppName();
+
+    if (TypeDatabase::instance()->isFunctionRejected(class_name, function_name)) {
+        m_rejected_functions.insert(class_name + "::" + function_name, GenerationDisabled);
+        return 0;
+    }
+
+
+    Q_ASSERT(function_item->functionType() == CodeModel::Normal
+             || function_item->functionType() == CodeModel::Signal
+             || function_item->functionType() == CodeModel::Slot);
+
+    if (function_item->isFriend())
+        return 0;
+
+
+    QString cast_type;
+
+    if (function_name.startsWith("operator")) {
+        function_name = rename_operator(function_name.mid(8));
+        if (function_name.isEmpty()) {
+            m_rejected_functions.insert(class_name + "::" + function_name,
+                                        GenerationDisabled);
+            return 0;
+        }
+        if (function_name.contains("_cast_"))
+            cast_type = function_name.mid(14).trimmed();
+    }
+
+    AbstractMetaFunction *meta_function = createMetaFunction();
+    meta_function->setConstant(function_item->isConstant());
+
+    ReportHandler::debugMedium(QString(" - %2()").arg(function_name));
+
+    meta_function->setName(function_name);
+    meta_function->setOriginalName(function_item->name());
+
+    if (function_item->isAbstract())
+        *meta_function += AbstractMetaAttributes::Abstract;
+
+    if (!meta_function->isAbstract())
+        *meta_function += AbstractMetaAttributes::Native;
+
+    if (!function_item->isVirtual())
+        *meta_function += AbstractMetaAttributes::Final;
+
+    if (function_item->isInvokable())
+        *meta_function += AbstractMetaAttributes::Invokable;
+
+    if (function_item->isStatic()) {
+        *meta_function += AbstractMetaAttributes::Static;
+        *meta_function += AbstractMetaAttributes::Final;
+    }
+
+    // Access rights
+    if (function_item->accessPolicy() == CodeModel::Public)
+        *meta_function += AbstractMetaAttributes::Public;
+    else if (function_item->accessPolicy() == CodeModel::Private)
+        *meta_function += AbstractMetaAttributes::Private;
+    else
+        *meta_function += AbstractMetaAttributes::Protected;
+
+
+    QString stripped_class_name = class_name;
+    int cc_pos = stripped_class_name.lastIndexOf("::");
+    if (cc_pos > 0)
+        stripped_class_name = stripped_class_name.mid(cc_pos + 2);
+
+    TypeInfo function_type = function_item->type();
+    if (function_name.startsWith('~')) {
+        meta_function->setFunctionType(AbstractMetaFunction::DestructorFunction);
+        meta_function->setInvalid(true);
+    } else if (strip_template_args(function_name) == stripped_class_name) {
+        meta_function->setFunctionType(AbstractMetaFunction::ConstructorFunction);
+        meta_function->setName(m_current_class->name());
+    } else {
+        bool ok;
+        AbstractMetaType *type = 0;
+
+        if (!cast_type.isEmpty()) {
+            TypeInfo info;
+            info.setQualifiedName(QStringList(cast_type));
+            type = translateType(info, &ok);
+        } else {
+            type = translateType(function_type, &ok);
+        }
+
+        if (!ok) {
+            ReportHandler::warning(QString("skipping function '%1::%2', unmatched return type '%3'")
+                                   .arg(class_name)
+                                   .arg(function_item->name())
+                                   .arg(function_item->type().toString()));
+            m_rejected_functions[class_name + "::" + function_name] =
+                UnmatchedReturnType;
+            meta_function->setInvalid(true);
+            return meta_function;
+        }
+        meta_function->setType(type);
+
+        if (function_item->functionType() == CodeModel::Signal)
+            meta_function->setFunctionType(AbstractMetaFunction::SignalFunction);
+        else if (function_item->functionType() == CodeModel::Slot)
+            meta_function->setFunctionType(AbstractMetaFunction::SlotFunction);
+    }
+
+    ArgumentList arguments = function_item->arguments();
+    AbstractMetaArgumentList meta_arguments;
+
+    int first_default_argument = 0;
+    for (int i=0; i<arguments.size(); ++i) {
+        ArgumentModelItem arg = arguments.at(i);
+
+        bool ok;
+        AbstractMetaType *meta_type = translateType(arg->type(), &ok);
+        if (!meta_type || !ok) {
+            ReportHandler::warning(QString("skipping function '%1::%2', "
+                                           "unmatched parameter type '%3'")
+                                   .arg(class_name)
+                                   .arg(function_item->name())
+                                   .arg(arg->type().toString()));
+            m_rejected_functions[class_name + "::" + function_name] =
+                UnmatchedArgumentType;
+            meta_function->setInvalid(true);
+            return meta_function;
+        }
+        AbstractMetaArgument *meta_argument = createMetaArgument();
+        meta_argument->setType(meta_type);
+        meta_argument->setName(arg->name());
+        meta_argument->setArgumentIndex(i);
+        meta_arguments << meta_argument;
+    }
+
+    meta_function->setArguments(meta_arguments);
+
+    // Find the correct default values
+    for (int i=0; i<arguments.size(); ++i) {
+        ArgumentModelItem arg = arguments.at(i);
+        AbstractMetaArgument *meta_arg = meta_arguments.at(i);
+        if (arg->defaultValue()) {
+            QString expr = arg->defaultValueExpression();
+            if (!expr.isEmpty())
+                meta_arg->setOriginalDefaultValueExpression(expr);
+
+            expr = translateDefaultValue(arg, meta_arg->type(), meta_function, m_current_class, i);
+            if (expr.isEmpty()) {
+                first_default_argument = i;
+            } else {
+                meta_arg->setDefaultValueExpression(expr);
+            }
+
+            if (meta_arg->type()->isEnum() || meta_arg->type()->isFlags()) {
+                m_enum_default_arguments
+                    << QPair<AbstractMetaArgument *, AbstractMetaFunction *>(meta_arg, meta_function);
+            }
+
+        }
+    }
+
+    // If we where not able to translate the default argument make it
+    // reset all default arguments before this one too.
+    for (int i=0; i<first_default_argument; ++i)
+        meta_arguments[i]->setDefaultValueExpression(QString());
+
+    if (ReportHandler::debugLevel() == ReportHandler::FullDebug)
+        foreach(AbstractMetaArgument *arg, meta_arguments)
+            ReportHandler::debugFull("   - " + arg->toString());
+
+    return meta_function;
+}
+
+
+AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei, bool *ok, bool resolveType, bool resolveScope)
+{
+    Q_ASSERT(ok);
+    *ok = true;
+
+    // 1. Test the type info without resolving typedefs in case this is present in the
+    //    type system
+    TypeInfo typei;
+    if (resolveType) {
+        bool ok;
+        AbstractMetaType *t = translateType(_typei, &ok, false, resolveScope);
+        if (t != 0 && ok)
+            return t;
+    }
+
+    if (!resolveType)
+        typei = _typei;
+    else {
+        // Go through all parts of the current scope (including global namespace)
+        // to resolve typedefs. The parser does not properly resolve typedefs in
+        // the global scope when they are referenced from inside a namespace.
+        // This is a work around to fix this bug since fixing it in resolveType
+        // seemed non-trivial
+        int i = m_scopes.size() - 1;
+        while (i >= 0) {
+            typei = TypeInfo::resolveType(_typei, m_scopes.at(i--)->toItem());
+            if (typei.qualifiedName().join("::") != _typei.qualifiedName().join("::"))
+                break;
+        }
+
+    }
+
+    if (typei.isFunctionPointer()) {
+        *ok = false;
+        return 0;
+    }
+
+    TypeParser::Info typeInfo = TypeParser::parse(typei.toString());
+    if (typeInfo.is_busted) {
+        *ok = false;
+        return 0;
+    }
+
+    // 2. Handle pointers specified as arrays with unspecified size
+    bool array_of_unspecified_size = false;
+    if (typeInfo.arrays.size() > 0) {
+        array_of_unspecified_size = true;
+        for (int i=0; i<typeInfo.arrays.size(); ++i)
+            array_of_unspecified_size = array_of_unspecified_size && typeInfo.arrays.at(i).isEmpty();
+
+        if (!array_of_unspecified_size) {
+            TypeInfo newInfo;
+            //newInfo.setArguments(typei.arguments());
+            newInfo.setIndirections(typei.indirections());
+            newInfo.setConstant(typei.isConstant());
+            newInfo.setFunctionPointer(typei.isFunctionPointer());
+            newInfo.setQualifiedName(typei.qualifiedName());
+            newInfo.setReference(typei.isReference());
+            newInfo.setVolatile(typei.isVolatile());
+
+            AbstractMetaType *elementType = translateType(newInfo, ok);
+            if (!ok)
+                return 0;
+
+            for (int i=typeInfo.arrays.size()-1; i>=0; --i) {
+                QString s = typeInfo.arrays.at(i);
+                bool ok;
+
+                int elems = s.toInt(&ok);
+                if (!ok)
+                    return 0;
+
+                AbstractMetaType *arrayType = createMetaType();
+                arrayType->setArrayElementCount(elems);
+                arrayType->setArrayElementType(elementType);
+                arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry()));
+                decideUsagePattern(arrayType);
+
+                elementType = arrayType;
+            }
+
+            return elementType;
+        }  else {
+            typeInfo.indirections += typeInfo.arrays.size();
+        }
+    }
+
+    QStringList qualifier_list = typeInfo.qualified_name;
+    if (qualifier_list.isEmpty()) {
+        ReportHandler::warning(QString("horribly broken type '%1'").arg(_typei.toString()));
+        *ok = false;
+        return 0;
+    }
+
+    QString qualified_name = qualifier_list.join("::");
+    QString name = qualifier_list.takeLast();
+
+    // 3. Special case 'void' type
+    if (name == "void" && typeInfo.indirections == 0) {
+        return 0;
+    }
+
+    // 4. Special case QFlags (include instantiation in name)
+    if (qualified_name == "QFlags")
+        qualified_name = typeInfo.toString();
+
+    // 5. Try to find the type
+    const TypeEntry *type = TypeDatabase::instance()->findType(qualified_name);
+
+    // 6. No? Try looking it up as a flags type
+    if (!type)
+        type = TypeDatabase::instance()->findFlagsType(qualified_name);
+
+    // 7. No? Try looking it up as a container type
+    if (!type)
+        type = TypeDatabase::instance()->findContainerType(name);
+
+    // 8. No? Check if the current class is a template and this type is one
+    //    of the parameters.
+    if (type == 0 && m_current_class != 0) {
+        QList<TypeEntry *> template_args = m_current_class->templateArguments();
+        foreach (TypeEntry *te, template_args) {
+            if (te->name() == qualified_name)
+                type = te;
+        }
+    }
+
+    // 9. Try finding the type by prefixing it with the current
+    //    context and all baseclasses of the current context
+    if (!type && !TypeDatabase::instance()->isClassRejected(qualified_name) && m_current_class != 0 && resolveScope) {
+        QStringList contexts;
+        contexts.append(m_current_class->qualifiedCppName());
+        contexts.append(currentScope()->qualifiedName().join("::"));
+
+
+        TypeInfo info = typei;
+        bool subclasses_done = false;
+        while (!contexts.isEmpty() && type == 0) {
+            //type = TypeDatabase::instance()->findType(contexts.at(0) + "::" + qualified_name);
+
+            bool ok;
+            info.setQualifiedName(QStringList() << contexts.at(0) << qualified_name);
+            AbstractMetaType *t = translateType(info, &ok, true, false);
+            if (t != 0 && ok)
+                return t;
+
+            ClassModelItem item = m_dom->findClass(contexts.at(0));
+            if (item != 0)
+                contexts += item->baseClasses();
+            contexts.pop_front();
+
+            // 10. Last resort: Special cased prefix of Qt namespace since the meta object implicitly inherits this, so
+            //     enum types from there may be addressed without any scope resolution in properties.
+            if (contexts.size() == 0 && !subclasses_done) {
+                contexts << "Qt";
+                subclasses_done = true;
+            }
+        }
+
+    }
+
+    if (!type) {
+        *ok = false;
+        return 0;
+    }
+
+    // Used to for diagnostics later...
+    m_used_types << type;
+
+    // These are only implicit and should not appear in code...
+    Q_ASSERT(!type->isInterface());
+
+    AbstractMetaType *meta_type = createMetaType();
+    meta_type->setTypeEntry(type);
+    meta_type->setIndirections(typeInfo.indirections);
+    meta_type->setReference(typeInfo.is_reference);
+    meta_type->setConstant(typeInfo.is_constant);
+    meta_type->setOriginalTypeDescription(_typei.toString());
+    decideUsagePattern(meta_type);
+
+    if (meta_type->typeEntry()->isContainer()) {
+        ContainerTypeEntry::Type container_type = static_cast<const ContainerTypeEntry *>(type)->type();
+
+        if (container_type == ContainerTypeEntry::StringListContainer) {
+            TypeInfo info;
+            info.setQualifiedName(QStringList() << "QString");
+            AbstractMetaType *targ_type = translateType(info, ok);
+
+            Q_ASSERT(*ok);
+            Q_ASSERT(targ_type);
+
+            meta_type->addInstantiation(targ_type);
+            meta_type->setInstantiationInCpp(false);
+
+        } else {
+            foreach (const TypeParser::Info &ta, typeInfo.template_instantiations) {
+                TypeInfo info;
+                info.setConstant(ta.is_constant);
+                info.setReference(ta.is_reference);
+                info.setIndirections(ta.indirections);
+
+                info.setFunctionPointer(false);
+                info.setQualifiedName(ta.instantiationName().split("::"));
+
+                AbstractMetaType *targ_type = translateType(info, ok);
+                if (!(*ok)) {
+                    delete meta_type;
+                    return 0;
+                }
+
+                meta_type->addInstantiation(targ_type);
+            }
+        }
+
+        if (container_type == ContainerTypeEntry::ListContainer
+            || container_type == ContainerTypeEntry::VectorContainer
+            || container_type == ContainerTypeEntry::StringListContainer) {
+            Q_ASSERT(meta_type->instantiations().size() == 1);
+        }
+    }
+
+    return meta_type;
+}
+
+void AbstractMetaBuilder::decideUsagePattern(AbstractMetaType *meta_type)
+{
+    const TypeEntry *type = meta_type->typeEntry();
+
+    if (type->isPrimitive() && (meta_type->actualIndirections() == 0
+                                || (meta_type->isConstant() && meta_type->isReference() && meta_type->indirections() == 0))) {
+        meta_type->setTypeUsagePattern(AbstractMetaType::PrimitivePattern);
+
+    } else if (type->isVoid()) {
+        meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
+
+    } else if (type->isString()
+               && meta_type->indirections() == 0
+               && (meta_type->isConstant() == meta_type->isReference()
+                   || meta_type->isConstant())) {
+        meta_type->setTypeUsagePattern(AbstractMetaType::StringPattern);
+
+    } else if (type->isChar()
+        && meta_type->indirections() == 0
+        && meta_type->isConstant() == meta_type->isReference()) {
+        meta_type->setTypeUsagePattern(AbstractMetaType::CharPattern);
+
+    } else if (type->isJObjectWrapper()
+        && meta_type->indirections() == 0
+        && meta_type->isConstant() == meta_type->isReference()) {
+        meta_type->setTypeUsagePattern(AbstractMetaType::JObjectWrapperPattern);
+
+    } else if (type->isVariant()
+        && meta_type->indirections() == 0
+        && meta_type->isConstant() == meta_type->isReference()) {
+        meta_type->setTypeUsagePattern(AbstractMetaType::VariantPattern);
+
+    } else if (type->isEnum() && meta_type->actualIndirections() == 0) {
+        meta_type->setTypeUsagePattern(AbstractMetaType::EnumPattern);
+
+    } else if (type->isObject()
+                && meta_type->indirections() == 0
+                && meta_type->isReference()) {
+        if (((ComplexTypeEntry *) type)->isQObject())
+            meta_type->setTypeUsagePattern(AbstractMetaType::QObjectPattern);
+        else
+            meta_type->setTypeUsagePattern(AbstractMetaType::ObjectPattern);
+
+    } else if (type->isObject()
+               && meta_type->indirections() == 1) {
+        if (((ComplexTypeEntry *) type)->isQObject())
+            meta_type->setTypeUsagePattern(AbstractMetaType::QObjectPattern);
+        else
+            meta_type->setTypeUsagePattern(AbstractMetaType::ObjectPattern);
+
+        // const-references to pointers can be passed as pointers
+        if (meta_type->isReference() && meta_type->isConstant()) {
+            meta_type->setReference(false);
+            meta_type->setConstant(false);
+        }
+
+    } else if (type->isContainer() && meta_type->indirections() == 0) {
+        meta_type->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
+
+    } else if (type->isTemplateArgument()) {
+
+    } else if (type->isFlags()
+               && meta_type->indirections() == 0
+               && (meta_type->isConstant() == meta_type->isReference())) {
+        meta_type->setTypeUsagePattern(AbstractMetaType::FlagsPattern);
+
+    } else if (type->isArray()) {
+        meta_type->setTypeUsagePattern(AbstractMetaType::ArrayPattern);
+
+    } else if (type->isThread()) {
+        Q_ASSERT(meta_type->indirections() == 1);
+        meta_type->setTypeUsagePattern(AbstractMetaType::ThreadPattern);
+
+    } else if (type->isValue()
+               && meta_type->indirections() == 0
+               && (meta_type->isConstant() == meta_type->isReference()
+                   || !meta_type->isReference())) {
+        meta_type->setTypeUsagePattern(AbstractMetaType::ValuePattern);
+
+    } else if (type->isObject() && meta_type->actualIndirections() == 0) {
+
+        ReportHandler::warning(QString("Object type '%1' passed as value. Resulting code will not compile.")
+                               .arg(meta_type->cppSignature()));
+        meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
+
+    } else {
+        meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
+        ReportHandler::debugFull(QString("native pointer pattern for '%1'")
+                                 .arg(meta_type->cppSignature()));
+    }
+}
+
+QString AbstractMetaBuilder::translateDefaultValue(ArgumentModelItem item, AbstractMetaType *type,
+                                               AbstractMetaFunction *fnc, AbstractMetaClass *implementing_class,
+                                               int argument_index)
+{
+    QString function_name = fnc->name();
+    QString class_name = implementing_class->name();
+
+    QString replaced_expression = fnc->replacedDefaultExpression(implementing_class, argument_index + 1);
+    if (fnc->removedDefaultExpression(implementing_class, argument_index +1))
+        return "";
+    if (!replaced_expression.isEmpty())
+        return replaced_expression;
+
+    QString expr = item->defaultValueExpression();
+    if (type->isPrimitive()) {
+        if (type->name() == "boolean") {
+            if (expr == "false" || expr=="true") {
+                return expr;
+            } else {
+                bool ok = false;
+                int number = expr.toInt(&ok);
+                if (ok && number)
+                    return "true";
+                else
+                    return "false";
+            }
+        } else if (expr == "ULONG_MAX") {
+            return "Long.MAX_VALUE";
+        } else if (expr == "QVariant::Invalid") {
+            return QString::number(QVariant::Invalid);
+        } else {
+            // This can be an enum or flag so I need to delay the
+            // translation untill all namespaces are completly
+            // processed. This is done in figureOutEnumValues()
+            return expr;
+        }
+    } else if (type != 0 && (type->isFlags() || type->isEnum())) {
+        // Same as with enum explanation above...
+        return expr;
+
+    } else {
+
+        // constructor or functioncall can be a bit tricky...
+        if (expr == "QVariant()" /* qtd || expr == "QModelIndex()"*/) {
+            return "null";
+        } else if (expr == "QString()") {
+            return "null";
+        } else if (expr.endsWith(")") && expr.contains("::")) {
+            TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(expr.indexOf("::")));
+            if (typeEntry)
+                return typeEntry->qualifiedTargetLangName() + "." + expr.right(expr.length() - expr.indexOf("::") - 2);
+        } else if (expr.endsWith(")") && type->isValue()) {
+            int pos = expr.indexOf("(");
+
+            TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(pos));
+            if (typeEntry) { // qtd
+                if(typeEntry->isStructInD())
+                    return typeEntry->qualifiedCppName() + expr.right(expr.length() - pos);
+                else
+                    return "new " + typeEntry->qualifiedCppName() + expr.right(expr.length() - pos);
+            } else
+                return expr;
+        } else if (expr == "0") {
+            return "null";
+        } else if (type->isObject() || type->isValue() || expr.contains("::")) { // like Qt::black passed to a QColor
+            TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(expr.indexOf("::")));
+
+            expr = expr.right(expr.length() - expr.indexOf("::") - 2);
+            if (typeEntry) {
+                return "new " + type->typeEntry()->qualifiedCppName() +
+                       "(" + typeEntry->qualifiedCppName() + "." + expr + ")";
+            }
+        }
+    }
+
+    QString warn = QString("unsupported default value '%3' of argument in function '%1', class '%2'")
+        .arg(function_name).arg(class_name).arg(item->defaultValueExpression());
+    ReportHandler::warning(warn);
+
+    return QString();
+}
+
+
+bool AbstractMetaBuilder::isQObject(const QString &qualified_name)
+{
+    if (qualified_name == "QObject")
+        return true;
+
+    ClassModelItem class_item = m_dom->findClass(qualified_name);
+
+    if (!class_item) {
+      QStringList names = qualified_name.split(QLatin1String("::"));
+      NamespaceModelItem ns = model_dynamic_cast<NamespaceModelItem>(m_dom);
+      for (int i=0; i<names.size() - 1 && ns; ++i)
+          ns = ns->namespaceMap().value(names.at(i));
+      if (ns && names.size() >= 2)
+          class_item = ns->findClass(names.at(names.size() - 1));
+    }
+
+    bool isqobject = class_item && class_item->extendsClass("QObject");
+
+    if (class_item && !isqobject) {
+        QStringList baseClasses = class_item->baseClasses();
+        for (int i=0; i<baseClasses.count(); ++i) {
+
+            isqobject = isQObject(baseClasses.at(i));
+            if (isqobject)
+                break;
+        }
+    }
+
+    return isqobject;
+}
+
+
+bool AbstractMetaBuilder::isEnum(const QStringList &qualified_name)
+{
+    CodeModelItem item = m_dom->model()->findItem(qualified_name, m_dom->toItem());
+    return item && item->kind() == _EnumModelItem::__node_kind;
+}
+
+AbstractMetaType *AbstractMetaBuilder::inheritTemplateType(const QList<AbstractMetaType *> &template_types,
+                                                   AbstractMetaType *meta_type, bool *ok)
+{
+    if (ok != 0)
+        *ok = true;
+    if (!meta_type || (!meta_type->typeEntry()->isTemplateArgument() && !meta_type->hasInstantiations()))
+        return meta_type ? meta_type->copy() : 0;
+
+    AbstractMetaType *returned = meta_type->copy();
+    returned->setOriginalTemplateType(meta_type->copy());
+
+    if (returned->typeEntry()->isTemplateArgument()) {
+        const TemplateArgumentEntry *tae = static_cast<const TemplateArgumentEntry *>(returned->typeEntry());
+
+        // If the template is intantiated with void we special case this as rejecting the functions that use this
+        // parameter from the instantiation.
+        if (template_types.size() <= tae->ordinal() || template_types.at(tae->ordinal())->typeEntry()->name() == "void") {
+            if (ok != 0)
+                *ok = false;
+            return 0;
+        }
+
+        AbstractMetaType *t = returned->copy();
+        t->setTypeEntry(template_types.at(tae->ordinal())->typeEntry());
+        t->setIndirections(template_types.at(tae->ordinal())->indirections() + t->indirections()
+                           ? 1
+                           : 0);
+        decideUsagePattern(t);
+
+        delete returned;
+        returned = inheritTemplateType(template_types, t, ok);
+        if (ok != 0 && !(*ok))
+            return 0;
+    }
+
+    if (returned->hasInstantiations()) {
+        QList<AbstractMetaType *> instantiations = returned->instantiations();
+        for (int i=0; i<instantiations.count(); ++i) {
+            instantiations[i] = inheritTemplateType(template_types, instantiations.at(i), ok);
+            if (ok != 0 && !(*ok))
+                return 0;
+        }
+        returned->setInstantiations(instantiations);
+    }
+
+    return returned;
+}
+
+bool AbstractMetaBuilder::inheritTemplate(AbstractMetaClass *subclass,
+                                      const AbstractMetaClass *template_class,
+                                      const TypeParser::Info &info)
+{
+    QList<TypeParser::Info> targs = info.template_instantiations;
+
+    QList<AbstractMetaType *> template_types;
+    foreach (const TypeParser::Info &i, targs) {
+        TypeEntry *t = TypeDatabase::instance()->findType(i.qualified_name.join("::"));
+
+        if (t != 0) {
+            AbstractMetaType *temporary_type = createMetaType();
+            temporary_type->setTypeEntry(t);
+            temporary_type->setConstant(i.is_constant);
+            temporary_type->setReference(i.is_reference);
+            temporary_type->setIndirections(i.indirections);
+            template_types << temporary_type;
+        }
+    }
+
+    AbstractMetaFunctionList funcs = subclass->functions();
+    foreach (const AbstractMetaFunction *function, template_class->functions()) {
+
+        if (function->isModifiedRemoved(TypeSystem::All))
+            continue;
+
+        AbstractMetaFunction *f = function->copy();
+        f->setArguments(AbstractMetaArgumentList());
+
+        bool ok = true;
+        AbstractMetaType *ftype = function->type();
+        f->setType(inheritTemplateType(template_types, ftype, &ok));
+        if (!ok) {
+            delete f;
+            continue;
+        }
+
+        foreach (AbstractMetaArgument *argument, function->arguments()) {
+            AbstractMetaType *atype = argument->type();
+
+            AbstractMetaArgument *arg = argument->copy();
+            arg->setType(inheritTemplateType(template_types, atype, &ok));
+            if (!ok)
+                break;
+            f->addArgument(arg);
+        }
+
+        if (!ok) {
+            delete f;
+            continue ;
+        }
+
+        // There is no base class in java to inherit from here, so the
+        // template instantiation is the class that implements the function..
+        f->setImplementingClass(subclass);
+
+        // We also set it as the declaring class, since the superclass is
+        // supposed to disappear. This allows us to make certain function modifications
+        // on the inherited functions.
+        f->setDeclaringClass(subclass);
+
+
+        if (f->isConstructor() && subclass->isTypeAlias()) {
+            f->setName(subclass->name());
+        } else if (f->isConstructor()) {
+            delete f;
+            continue;
+        }
+
+        // if the instantiation has a function named the same as an existing
+        // function we have shadowing so we need to skip it.
+        bool found = false;
+        for (int i=0; i<funcs.size(); ++i) {
+            if (funcs.at(i)->name() == f->name()) {
+                found = true;
+                continue;
+            }
+        }
+        if (found) {
+            delete f;
+            continue;
+        }
+
+        ComplexTypeEntry *te = subclass->typeEntry();
+        FunctionModificationList mods = function->modifications(template_class);
+        for (int i=0; i<mods.size(); ++i) {
+            FunctionModification mod = mods.at(i);
+            mod.signature = f->minimalSignature();
+
+            // If we ever need it... Below is the code to do
+            // substitution of the template instantation type inside
+            // injected code..
+#if 0
+            if (mod.modifiers & Modification::CodeInjection) {
+                for (int j=0; j<template_types.size(); ++j) {
+                    CodeSnip &snip = mod.snips.last();
+                    QString code = snip.code();
+                    code.replace(QString::fromLatin1("$$QT_TEMPLATE_%1$$").arg(j),
+                                 template_types.at(j)->typeEntry()->qualifiedCppName());
+                    snip.codeList.clear();
+                    snip.addCode(code);
+                }
+            }
+#endif
+            te->addFunctionModification(mod);
+        }
+
+        subclass->addFunction(f);
+    }
+
+    // Clean up
+    foreach (AbstractMetaType *type, template_types) {
+        delete type;
+    }
+
+
+    {
+        subclass->setTemplateBaseClass(template_class);
+
+        subclass->setInterfaces(template_class->interfaces());
+        subclass->setBaseClass(template_class->baseClass());
+    }
+
+    return true;
+}
+
+void AbstractMetaBuilder::parseQ_Property(AbstractMetaClass *meta_class, const QStringList &declarations)
+{
+    for (int i=0; i<declarations.size(); ++i) {
+        QString p = declarations.at(i);
+
+        QStringList l = p.split(QLatin1String(" "));
+
+
+        QStringList qualifiedScopeName = currentScope()->qualifiedName();
+        bool ok = false;
+        AbstractMetaType *type = 0;
+        QString scope;
+        for (int j=qualifiedScopeName.size(); j>=0; --j) {
+            scope = j > 0 ? QStringList(qualifiedScopeName.mid(0, j)).join("::") + "::" : QString();
+            TypeInfo info;
+            info.setQualifiedName((scope + l.at(0)).split("::"));
+
+            type = translateType(info, &ok);
+            if (type != 0 && ok) {
+                break;
+            }
+        }
+
+        if (type == 0 || !ok) {
+            ReportHandler::warning(QString("Unable to decide type of property: '%1' in class '%2'")
+                                   .arg(l.at(0)).arg(meta_class->name()));
+            continue;
+        }
+
+        QString typeName = scope + l.at(0);
+
+        QPropertySpec *spec = new QPropertySpec(type->typeEntry());
+        spec->setName(l.at(1));
+        spec->setIndex(i);
+
+        for (int pos=2; pos+1<l.size(); pos+=2) {
+            if (l.at(pos) == QLatin1String("READ"))
+                spec->setRead(l.at(pos+1));
+            else if (l.at(pos) == QLatin1String("WRITE"))
+                spec->setWrite(l.at(pos+1));
+            else if (l.at(pos) == QLatin1String("DESIGNABLE"))
+                spec->setDesignable(l.at(pos+1));
+            else if (l.at(pos) == QLatin1String("RESET"))
+                spec->setReset(l.at(pos+1));
+        }
+
+        meta_class->addPropertySpec(spec);
+        delete type;
+    }
+}
+
+static void hide_functions(const AbstractMetaFunctionList &l) {
+    foreach (AbstractMetaFunction *f, l) {
+        FunctionModification mod;
+        mod.signature = f->minimalSignature();
+        mod.modifiers = FunctionModification::Private;
+        ((ComplexTypeEntry *) f->implementingClass()->typeEntry())->addFunctionModification(mod);
+    }
+}
+
+static void remove_function(AbstractMetaFunction *f) {
+    FunctionModification mod;
+    mod.removal = TypeSystem::All;
+    mod.signature = f->minimalSignature();
+    ((ComplexTypeEntry *) f->implementingClass()->typeEntry())->addFunctionModification(mod);
+}
+
+static AbstractMetaFunctionList filter_functions(const AbstractMetaFunctionList &lst, QSet<QString> *signatures)
+{
+    AbstractMetaFunctionList functions;
+    foreach (AbstractMetaFunction *f, lst) {
+        QString signature = f->minimalSignature();
+        int start = signature.indexOf(QLatin1Char('(')) + 1;
+        int end = signature.lastIndexOf(QLatin1Char(')'));
+        signature = signature.mid(start, end - start);
+        if (signatures->contains(signature)) {
+            remove_function(f);
+            continue;
+        }
+        (*signatures) << signature;
+        functions << f;
+    }
+    return functions;
+}
+
+void AbstractMetaBuilder::setupEquals(AbstractMetaClass *cls)
+{
+    AbstractMetaFunctionList equals;
+    AbstractMetaFunctionList nequals;
+
+    QString op_equals = QLatin1String("operator_equal");
+    QString op_nequals = QLatin1String("operator_not_equal");
+
+    AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements
+                                                         | AbstractMetaClass::NotRemovedFromTargetLang);
+    foreach (AbstractMetaFunction *f, functions) {
+        if (f->name() == op_equals)
+            equals << f;
+        else if (f->name() == op_nequals)
+            nequals << f;
+    }
+
+    if (equals.size() || nequals.size()) {
+        if (!cls->hasHashFunction()) {
+            ReportHandler::warning(QString::fromLatin1("Class '%1' has equals operators but no qHash() function")
+                                   .arg(cls->name()));
+        }
+
+        hide_functions(equals);
+        hide_functions(nequals);
+
+        // We only need == if we have both == and !=, and one == for
+        // each signature type, like QDateTime::==(QDate) and (QTime)
+        // if such a thing exists...
+        QSet<QString> func_signatures;
+        cls->setEqualsFunctions(filter_functions(equals, &func_signatures));
+        cls->setNotEqualsFunctions(filter_functions(nequals, &func_signatures));
+    }
+}
+
+void AbstractMetaBuilder::setupComparable(AbstractMetaClass *cls)
+{
+    AbstractMetaFunctionList greater;
+    AbstractMetaFunctionList greaterEquals;
+    AbstractMetaFunctionList less;
+    AbstractMetaFunctionList lessEquals;
+
+    QString op_greater = QLatin1String("operator_greater");
+    QString op_greater_eq = QLatin1String("operator_greater_or_equal");
+    QString op_less = QLatin1String("operator_less");
+    QString op_less_eq = QLatin1String("operator_less_or_equal");
+
+    AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements
+                                                         | AbstractMetaClass::NotRemovedFromTargetLang);
+    foreach (AbstractMetaFunction *f, functions) {
+        if (f->name() == op_greater)
+            greater << f;
+        else if (f->name() == op_greater_eq)
+            greaterEquals << f;
+        else if (f->name() == op_less)
+            less << f;
+        else if (f->name() == op_less_eq)
+            lessEquals << f;
+    }
+
+    bool hasEquals = cls->equalsFunctions().size() || cls->notEqualsFunctions().size();
+
+    // Conditions for comparable is:
+    //     >, ==, <             - The basic case
+    //     >, ==                - Less than becomes else case
+    //     <, ==                - Greater than becomes else case
+    //     >=, <=               - if (<= && >=) -> equal
+    bool mightBeComparable = greater.size() || greaterEquals.size() || less.size() || lessEquals.size()
+                        || greaterEquals.size() == 1 || lessEquals.size() == 1;
+
+    if (mightBeComparable) {
+        QSet<QString> signatures;
+
+        // We only hide the original functions if we are able to make a compareTo() method
+        bool wasComparable = false;
+
+        // The three upper cases, prefer the <, == approach
+        if (hasEquals && (greater.size() || less.size())) {
+            cls->setLessThanFunctions(filter_functions(less, &signatures));
+            cls->setGreaterThanFunctions(filter_functions(greater, &signatures));
+            filter_functions(greaterEquals, &signatures);
+            filter_functions(lessEquals, &signatures);
+            wasComparable = true;
+        } else if (hasEquals && (greaterEquals.size() || lessEquals.size())) {
+            cls->setLessThanEqFunctions(filter_functions(lessEquals, &signatures));
+            cls->setGreaterThanEqFunctions(filter_functions(greaterEquals, &signatures));
+            wasComparable = true;
+        } else if (greaterEquals.size() == 1 || lessEquals.size() == 1) {
+            cls->setGreaterThanEqFunctions(greaterEquals);
+            cls->setLessThanEqFunctions(lessEquals);
+            filter_functions(less, &signatures);
+            filter_functions(greater, &signatures);
+            wasComparable = true;
+        }
+
+        if (wasComparable) {
+            hide_functions(greater);
+            hide_functions(greaterEquals);
+            hide_functions(less);
+            hide_functions(lessEquals);
+        }
+    }
+
+}
+
+void AbstractMetaBuilder::setupClonable(AbstractMetaClass *cls)
+{
+    // All value types are required to have a copy constructor,
+    // or they will not work as value types (it won't even compile,
+    // because of calls to qRegisterMetaType(). Thus all value types
+    // should be cloneable.
+    if (cls->typeEntry()->isValue()) {
+        cls->setHasCloneOperator(true);
+        return;
+    } else {
+        QString op_assign = QLatin1String("operator_assign");
+
+        AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements);
+        foreach (AbstractMetaFunction *f, functions) {
+            if ((f->name() == op_assign || f->isConstructor()) && f->isPublic()) {
+                AbstractMetaArgumentList arguments = f->arguments();
+                if (f->actualMinimumArgumentCount() == 1) {
+                    if (cls->typeEntry()->qualifiedCppName() == arguments.at(0)->type()->typeEntry()->qualifiedCppName()) {
+                        if (cls->typeEntry()->isValue()) {
+                            cls->setHasCloneOperator(true);
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+static void write_reject_log_file(const QString &name,
+                                  const QMap<QString, AbstractMetaBuilder::RejectReason> &rejects)
+{
+    QFile f(name);
+    if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
+        ReportHandler::warning(QString("failed to write log file: '%1'")
+                               .arg(f.fileName()));
+        return;
+    }
+
+    QTextStream s(&f);
+
+
+    for (int reason=0; reason<AbstractMetaBuilder::NoReason; ++reason) {
+        s << QString(72, '*') << endl;
+        switch (reason) {
+        case AbstractMetaBuilder::NotInTypeSystem:
+            s << "Not in type system";
+            break;
+        case AbstractMetaBuilder::GenerationDisabled:
+            s << "Generation disabled by type system";
+            break;
+        case AbstractMetaBuilder::RedefinedToNotClass:
+            s << "Type redefined to not be a class";
+            break;
+
+        case AbstractMetaBuilder::UnmatchedReturnType:
+            s << "Unmatched return type";
+            break;
+
+        case AbstractMetaBuilder::UnmatchedArgumentType:
+            s << "Unmatched argument type";
+            break;
+
+        default:
+            s << "unknown reason";
+            break;
+        }
+
+        s << endl;
+
+        for (QMap<QString, AbstractMetaBuilder::RejectReason>::const_iterator it = rejects.constBegin();
+             it != rejects.constEnd(); ++it) {
+            if (it.value() != reason)
+                continue;
+            s << " - " << it.key() << endl;
+        }
+
+        s << QString(72, '*') << endl << endl;
+    }
+
+}
+
+
+void AbstractMetaBuilder::dumpLog()
+{
+    write_reject_log_file("mjb_rejected_classes.log", m_rejected_classes);
+    write_reject_log_file("mjb_rejected_enums.log", m_rejected_enums);
+    write_reject_log_file("mjb_rejected_functions.log", m_rejected_functions);
+    write_reject_log_file("mjb_rejected_fields.log", m_rejected_fields);
+}
+
+AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted() const
+{
+    AbstractMetaClassList res;
+
+    AbstractMetaClassList classes = m_meta_classes;
+    qSort(classes);
+
+    QSet<AbstractMetaClass*> noDependency;
+    QHash<AbstractMetaClass*, QSet<AbstractMetaClass* >* > hash;
+    foreach (AbstractMetaClass *cls, classes) {
+        QSet<AbstractMetaClass* > *depends = new QSet<AbstractMetaClass* >();
+
+        if (cls->baseClass())
+            depends->insert(cls->baseClass());
+
+        foreach (AbstractMetaClass *interface, cls->interfaces()) {
+            depends->insert(interface);
+        }
+
+        if (depends->empty()) {
+            noDependency.insert(cls);
+        } else {
+            hash.insert(cls, depends);
+        }
+    }
+
+    while (!noDependency.empty()) {
+        foreach (AbstractMetaClass *cls, noDependency.values()) {
+            if(!cls->isInterface())
+                res.append(cls);
+            noDependency.remove(cls);
+            QHashIterator<AbstractMetaClass*, QSet<AbstractMetaClass* >* > i(hash);
+            while (i.hasNext()) {
+                i.next();
+                i.value()->remove(cls);
+                if (i.value()->empty()) {
+                    AbstractMetaClass *key = i.key();
+                    noDependency.insert(key);
+                    hash.remove(key);
+                    delete(i.value());
+                }
+            }
+        }
+    }
+
+    if (!noDependency.empty() || !hash.empty()) {
+        qWarning("dependency graph was cyclic.");
+    }
+
+    return res;
+}