Mercurial > projects > qtd
diff generator/abstractmetalang.cpp @ 1:e78566595089
initial import
author | mandel |
---|---|
date | Mon, 11 May 2009 16:01:50 +0000 |
parents | |
children | a5cba313c924 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/generator/abstractmetalang.cpp Mon May 11 16:01:50 2009 +0000 @@ -0,0 +1,2035 @@ +/**************************************************************************** +** +** 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 "abstractmetalang.h" +#include "reporthandler.h" +#include "jumptable.h" + +/******************************************************************************* + * AbstractMetaType + */ +AbstractMetaType *AbstractMetaType::copy() const +{ + AbstractMetaType *cpy = new AbstractMetaType; + + cpy->setTypeUsagePattern(typeUsagePattern()); + cpy->setConstant(isConstant()); + cpy->setReference(isReference()); + cpy->setIndirections(indirections()); + cpy->setInstantiations(instantiations()); + cpy->setArrayElementCount(arrayElementCount()); + cpy->setOriginalTypeDescription(originalTypeDescription()); + cpy->setOriginalTemplateType(originalTemplateType() ? originalTemplateType()->copy() : 0); + + cpy->setArrayElementType(arrayElementType() ? arrayElementType()->copy() : 0); + + cpy->setTypeEntry(typeEntry()); + + return cpy; +} + +QString AbstractMetaType::cppSignature() const +{ + QString s; + + if (isConstant()) + s += "const "; + + s += typeEntry()->qualifiedCppName(); + + if (hasInstantiationInCpp()) { + QList<AbstractMetaType *> types = instantiations(); + s += "<"; + for (int i=0; i<types.count(); ++i) { + if (i > 0) + s += ", "; + s += types.at(i)->cppSignature(); + } + s += " >"; + } + + if (actualIndirections()) { + s += ' '; + if (indirections()) + s += QString(indirections(), '*'); + if (isReference()) + s += '&'; + } + return s; +} + +/******************************************************************************* + * AbstractMetaArgument + */ +AbstractMetaArgument *AbstractMetaArgument::copy() const +{ + AbstractMetaArgument *cpy = new AbstractMetaArgument; + cpy->setName(AbstractMetaVariable::name()); + cpy->setDefaultValueExpression(defaultValueExpression()); + cpy->setType(type()->copy()); + cpy->setArgumentIndex(argumentIndex()); + + return cpy; +} + + +QString AbstractMetaArgument::argumentName() const +{ + QString n = AbstractMetaVariable::name(); + // replace for arguments which are D keywords such as "version" + n = ArgumentReplace::translate(n); + + if (n.isEmpty()) { + return QString("arg__%2").arg(m_argument_index + 1); + } + return n; +} + + +QString AbstractMetaArgument::indexedName() const +{ + QString n = AbstractMetaVariable::name(); + if (n.isEmpty()) + return argumentName(); + return QString("%1%2").arg(n).arg(m_argument_index); +} + +QString AbstractMetaArgument::name() const +{ + Q_ASSERT_X(0, "AbstractMetaArgument::name()", "use argumentName() or indexedName() instead"); + return QString(); +} + + +/******************************************************************************* + * AbstractMetaFunction + */ +AbstractMetaFunction::~AbstractMetaFunction() +{ + qDeleteAll(m_arguments); + delete m_type; +} + +/******************************************************************************* + * Indicates that this function has a modification that removes it + */ +bool AbstractMetaFunction::isModifiedRemoved(int types) const +{ + FunctionModificationList mods = modifications(implementingClass()); + foreach (FunctionModification mod, mods) { + if (!mod.isRemoveModifier()) + continue; + + if ((mod.removal & types) == types) + return true; + } + + return false; +} + +bool AbstractMetaFunction::needsCallThrough() const +{ + if (ownerClass()->isInterface()) + return false; + if (referenceCounts(implementingClass()).size() > 0) + return true; + if (argumentsHaveNativeId() || !isStatic()) + return true; + if (JumpTableGenerator::isJumpTableActive()) + return true; + + foreach (const AbstractMetaArgument *arg, arguments()) { + if (arg->type()->isArray() || arg->type()->isTargetLangEnum() || arg->type()->isTargetLangFlags()) + return true; + } + + if (type() && (type()->isArray() || type()->isTargetLangEnum() || type()->isTargetLangFlags())) + return true; + + for (int i=-1; i<=arguments().size(); ++i) { + TypeSystem::Ownership owner = this->ownership(implementingClass(), TypeSystem::TargetLangCode, i); + if (owner != TypeSystem::InvalidOwnership) + return true; + } + + return false; +} + +bool AbstractMetaFunction::needsSuppressUncheckedWarning() const +{ + for (int i=-1; i<=arguments().size(); ++i) { + QList<ReferenceCount> referenceCounts = this->referenceCounts(implementingClass(), i); + foreach (ReferenceCount referenceCount, referenceCounts) { + if (referenceCount.action != ReferenceCount::Set) + return true; + } + } + return false; +} + +QString AbstractMetaFunction::marshalledName(bool classIsOwner) const +{ + QString returned = "qtd_"; + if(classIsOwner) + returned += ownerClass()->name(); + else + returned += declaringClass()->name(); + + returned += "_" + name(); + AbstractMetaArgumentList arguments = this->arguments(); + foreach (const AbstractMetaArgument *arg, arguments) { + returned += "_"; + if (arg->type()->isNativePointer()) { + returned += "nativepointer" + arg->type()->name().replace("[]", "_3").replace(".", "_"); + } else if (arg->type()->isIntegerEnum() || arg->type()->isIntegerFlags()) { + returned += "int"; + } else { + returned += arg->type()->name().replace("[]", "_3").replace(".", "_"); + } + } + return returned; +} + +bool AbstractMetaFunction::operator<(const AbstractMetaFunction &other) const +{ + uint result = compareTo(&other); + return result & NameLessThan; +} + + +/*! + Returns a mask of CompareResult describing how this function is + compares to another function +*/ +uint AbstractMetaFunction::compareTo(const AbstractMetaFunction *other) const +{ + uint result = 0; + + // Enclosing class... + if (ownerClass() == other->ownerClass()) { + result |= EqualImplementor; + } + + // Attributes + if (attributes() == other->attributes()) { + result |= EqualAttributes; + } + + // Compare types + AbstractMetaType *t = type(); + AbstractMetaType *ot = other->type(); + if ((!t && !ot) || ((t && ot && t->name() == ot->name()))) { + result |= EqualReturnType; + } + + // Compare names + int cmp = originalName().compare(other->originalName()); + + if (cmp < 0) { + result |= NameLessThan; + } else if (cmp == 0) { + result |= EqualName; + } + + // compare name after modification... + cmp = modifiedName().compare(other->modifiedName()); + if (cmp == 0) + result |= EqualModifiedName; + + // Compare arguments... + AbstractMetaArgumentList min_arguments; + AbstractMetaArgumentList max_arguments; + if (arguments().size() < other->arguments().size()) { + min_arguments = arguments(); + max_arguments = other->arguments(); + } else { + min_arguments = other->arguments(); + max_arguments = arguments(); + } + + int min_count = min_arguments.size(); + int max_count = max_arguments.size(); + bool same = true; + for (int i=0; i<max_count; ++i) { + if (i < min_count) { + const AbstractMetaArgument *min_arg = min_arguments.at(i); + const AbstractMetaArgument *max_arg = max_arguments.at(i); + if (min_arg->type()->name() != max_arg->type()->name() + && (min_arg->defaultValueExpression().isEmpty() || max_arg->defaultValueExpression().isEmpty())) { + same = false; + break; + } + } else { + if (max_arguments.at(i)->defaultValueExpression().isEmpty()) { + same = false; + break; + } + } + } + + if (same) + result |= min_count == max_count ? EqualArguments : EqualDefaultValueOverload; + + return result; +} + +AbstractMetaFunction *AbstractMetaFunction::copy() const +{ + AbstractMetaFunction *cpy = new AbstractMetaFunction; + cpy->setName(name()); + cpy->setOriginalName(originalName()); + cpy->setOwnerClass(ownerClass()); + cpy->setImplementingClass(implementingClass()); + cpy->setInterfaceClass(interfaceClass()); + cpy->setFunctionType(functionType()); + cpy->setAttributes(attributes()); + cpy->setDeclaringClass(declaringClass()); + if (type()) + cpy->setType(type()->copy()); + cpy->setConstant(isConstant()); + cpy->setOriginalAttributes(originalAttributes()); + + foreach (AbstractMetaArgument *arg, arguments()) + cpy->addArgument(arg->copy()); + + Q_ASSERT((!type() && !cpy->type()) + || (type()->instantiations() == cpy->type()->instantiations())); + + return cpy; +} + +QStringList AbstractMetaFunction::introspectionCompatibleSignatures(const QStringList &resolvedArguments) const +{ + AbstractMetaArgumentList arguments = this->arguments(); + if (arguments.size() == resolvedArguments.size()) { + return (QStringList() << QMetaObject::normalizedSignature((name() + "(" + resolvedArguments.join(",") + ")").toUtf8().constData())); + } else { + QStringList returned; + + AbstractMetaArgument *argument = arguments.at(resolvedArguments.size()); + QStringList minimalTypeSignature = argument->type()->minimalSignature().split("::"); + for (int i=0; i<minimalTypeSignature.size(); ++i) { + returned += introspectionCompatibleSignatures(QStringList(resolvedArguments) + << QStringList(minimalTypeSignature.mid(minimalTypeSignature.size() - i - 1)).join("::")); + } + + return returned; + } +} + +QString AbstractMetaFunction::signature() const +{ + QString s(m_original_name); + + s += "("; + + for (int i=0; i<m_arguments.count(); ++i) { + if (i > 0) + s += ", "; + AbstractMetaArgument *a = m_arguments.at(i); + s += a->type()->cppSignature(); + + // We need to have the argument names in the qdoc files + s += " "; + s += a->argumentName(); + } + s += ")"; + + if (isConstant()) + s += " const"; + + return s; +} + +int AbstractMetaFunction::actualMinimumArgumentCount() const +{ + AbstractMetaArgumentList arguments = this->arguments(); + + int count = 0; + for (int i=0; i<arguments.size(); ++i && ++count) { + if (argumentRemoved(i + 1)) --count; + else if (!arguments.at(i)->defaultValueExpression().isEmpty()) break; + } + + return count; +} + +// Returns reference counts for argument at idx, or all arguments if idx == -2 +QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const +{ + QList<ReferenceCount> returned; + + FunctionModificationList mods = this->modifications(cls); + foreach (FunctionModification mod, mods) { + QList<ArgumentModification> argument_mods = mod.argument_mods; + foreach (ArgumentModification argument_mod, argument_mods) { + if (argument_mod.index != idx && idx != -2) + continue; + returned += argument_mod.referenceCounts; + } + } + + return returned; +} + +QString AbstractMetaFunction::replacedDefaultExpression(const AbstractMetaClass *cls, int key) const +{ + FunctionModificationList modifications = this->modifications(cls); + foreach (FunctionModification modification, modifications) { + QList<ArgumentModification> argument_modifications = modification.argument_mods; + foreach (ArgumentModification argument_modification, argument_modifications) { + if (argument_modification.index == key + && !argument_modification.replaced_default_expression.isEmpty()) { + return argument_modification.replaced_default_expression; + } + } + } + + return QString(); +} + +bool AbstractMetaFunction::removedDefaultExpression(const AbstractMetaClass *cls, int key) const +{ + FunctionModificationList modifications = this->modifications(cls); + foreach (FunctionModification modification, modifications) { + QList<ArgumentModification> argument_modifications = modification.argument_mods; + foreach (ArgumentModification argument_modification, argument_modifications) { + if (argument_modification.index == key + && argument_modification.removed_default_expression) { + return true; + } + } + } + + return false; +} + +bool AbstractMetaFunction::resetObjectAfterUse(int argument_idx) const +{ + const AbstractMetaClass *cls = declaringClass(); + FunctionModificationList modifications = this->modifications(cls); + foreach (FunctionModification modification, modifications) { + QList<ArgumentModification> argumentModifications = modification.argument_mods; + foreach (ArgumentModification argumentModification, argumentModifications) { + if (argumentModification.index == argument_idx && argumentModification.reset_after_use) + return true; + } + } + + return false; +} + +QString AbstractMetaFunction::nullPointerDefaultValue(const AbstractMetaClass *mainClass, int argument_idx) const +{ + Q_ASSERT(nullPointersDisabled(mainClass, argument_idx)); + + const AbstractMetaClass *cls = mainClass; + if (cls == 0) + cls = implementingClass(); + + do { + FunctionModificationList modifications = this->modifications(cls); + foreach (FunctionModification modification, modifications) { + QList<ArgumentModification> argument_modifications = modification.argument_mods; + foreach (ArgumentModification argument_modification, argument_modifications) { + if (argument_modification.index == argument_idx + && argument_modification.no_null_pointers) { + return argument_modification.null_pointer_default_value; + } + } + } + + cls = cls->baseClass(); + } while (cls != 0 && mainClass == 0); // Once when mainClass != 0, or once for all base classes of implementing class + + return QString(); + +} + +bool AbstractMetaFunction::nullPointersDisabled(const AbstractMetaClass *mainClass, int argument_idx) const +{ + const AbstractMetaClass *cls = mainClass; + if (cls == 0) + cls = implementingClass(); + + do { + FunctionModificationList modifications = this->modifications(cls); + foreach (FunctionModification modification, modifications) { + QList<ArgumentModification> argument_modifications = modification.argument_mods; + foreach (ArgumentModification argument_modification, argument_modifications) { + if (argument_modification.index == argument_idx + && argument_modification.no_null_pointers) { + return true; + } + } + } + + cls = cls->baseClass(); + } while (cls != 0 && mainClass == 0); // Once when mainClass != 0, or once for all base classes of implementing class + + return false; +} + +QString AbstractMetaFunction::conversionRule(TypeSystem::Language language, int key) const +{ + FunctionModificationList modifications = this->modifications(declaringClass()); + foreach (FunctionModification modification, modifications) { + QList<ArgumentModification> argument_modifications = modification.argument_mods; + foreach (ArgumentModification argument_modification, argument_modifications) { + if (argument_modification.index != key) + continue; + + foreach (CodeSnip snip, argument_modification.conversion_rules) { + if (snip.language == language && !snip.code().isEmpty()) + return snip.code(); + } + } + } + + return QString(); +} + +QString AbstractMetaFunction::argumentReplaced(int key) const +{ + FunctionModificationList modifications = this->modifications(declaringClass()); + foreach (FunctionModification modification, modifications) { + QList<ArgumentModification> argument_modifications = modification.argument_mods; + foreach (ArgumentModification argument_modification, argument_modifications) { + if (argument_modification.index == key && !argument_modification.replace_value.isEmpty()) { + return argument_modification.replace_value; + } + } + } + + return ""; +} + +bool AbstractMetaFunction::argumentRemoved(int key) const +{ + FunctionModificationList modifications = this->modifications(declaringClass()); + foreach (FunctionModification modification, modifications) { + QList<ArgumentModification> argument_modifications = modification.argument_mods; + foreach (ArgumentModification argument_modification, argument_modifications) { + if (argument_modification.index == key) { + if (argument_modification.removed) { + return true; + } + } + } + } + + return false; +} + +bool AbstractMetaFunction::storeResult() const +{ + if (m_store_result == 2) + return true; + else + return false; +} + +void AbstractMetaFunction::checkStoreResult() +{ + FunctionModificationList modifications = this->modifications(declaringClass()); + foreach (FunctionModification modification, modifications) { + if (modification.store_result) { + m_store_result = 2; + return; + } + } + + m_store_result = 1; +} + +bool AbstractMetaFunction::isVirtualSlot() const +{ + FunctionModificationList modifications = this->modifications(declaringClass()); + foreach (FunctionModification modification, modifications) { + if (modification.isVirtualSlot()) + return true; + } + + return false; +} + +bool AbstractMetaFunction::disabledGarbageCollection(const AbstractMetaClass *cls, int key) const +{ + FunctionModificationList modifications = this->modifications(cls); + foreach (FunctionModification modification, modifications) { + QList<ArgumentModification> argument_modifications = modification.argument_mods; + foreach (ArgumentModification argument_modification, argument_modifications) { + if (argument_modification.index != key) + continue; + + foreach (TypeSystem::Ownership ownership, argument_modification.ownerships.values()) { + if (ownership == TypeSystem::CppOwnership) + return true; + } + + } + } + + return false; +} + +bool AbstractMetaFunction::isDeprecated() const +{ + FunctionModificationList modifications = this->modifications(declaringClass()); + foreach (FunctionModification modification, modifications) { + if (modification.isDeprecated()) + return true; + } + return false; +} + +TypeSystem::Ownership AbstractMetaFunction::ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int key) const +{ + FunctionModificationList modifications = this->modifications(cls); + foreach (FunctionModification modification, modifications) { + QList<ArgumentModification> argument_modifications = modification.argument_mods; + foreach (ArgumentModification argument_modification, argument_modifications) { + if (argument_modification.index == key) + return argument_modification.ownerships.value(language, TypeSystem::InvalidOwnership); + } + } + + return TypeSystem::InvalidOwnership; +} + +bool AbstractMetaFunction::isRemovedFromAllLanguages(const AbstractMetaClass *cls) const +{ + return isRemovedFrom(cls, TypeSystem::All); +} + +bool AbstractMetaFunction::isRemovedFrom(const AbstractMetaClass *cls, TypeSystem::Language language) const +{ + FunctionModificationList modifications = this->modifications(cls); + foreach (FunctionModification modification, modifications) { + if ((modification.removal & language) == language) + return true; + } + + return false; + +} + +QString AbstractMetaFunction::typeReplaced(int key) const +{ + FunctionModificationList modifications = this->modifications(declaringClass()); + foreach (FunctionModification modification, modifications) { + QList<ArgumentModification> argument_modifications = modification.argument_mods; + foreach (ArgumentModification argument_modification, argument_modifications) { + if (argument_modification.index == key + && !argument_modification.modified_type.isEmpty()) { + return argument_modification.modified_type; + } + } + } + + return QString(); +} + +QString AbstractMetaFunction::minimalSignature() const +{ + if (!m_cached_minimal_signature.isEmpty()) + return m_cached_minimal_signature; + + QString minimalSignature = originalName() + "("; + AbstractMetaArgumentList arguments = this->arguments(); + + for (int i=0; i<arguments.count(); ++i) { + AbstractMetaType *t = arguments.at(i)->type(); + + if (i > 0) + minimalSignature += ","; + + minimalSignature += t->minimalSignature(); + } + minimalSignature += ")"; + if (isConstant()) + minimalSignature += "const"; + + minimalSignature = QMetaObject::normalizedSignature(minimalSignature.toLocal8Bit().constData()); + m_cached_minimal_signature = minimalSignature; + + return minimalSignature; +} + +FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaClass *implementor) const +{ + Q_ASSERT(implementor); + return implementor->typeEntry()->functionModifications(minimalSignature()); +} + +bool AbstractMetaFunction::hasModifications(const AbstractMetaClass *implementor) const +{ + FunctionModificationList mods = modifications(implementor); + return mods.count() > 0; +} + +QString AbstractMetaFunction::modifiedName() const +{ + if (m_cached_modified_name.isEmpty()) { + FunctionModificationList mods = modifications(implementingClass()); + foreach (FunctionModification mod, mods) { + if (mod.isRenameModifier()) { + m_cached_modified_name = mod.renamedToName; + break; + } + } + if (m_cached_modified_name.isEmpty()) + m_cached_modified_name = name(); + } + return m_cached_modified_name; +} + +QString AbstractMetaFunction::targetLangSignature(bool minimal) const +{ + QString s; + + // Attributes... + if (!minimal) { + if (isPublic()) s += "public "; + else if (isProtected()) s += "protected "; + else if (isPrivate()) s += "private "; + +// if (isNative()) s += "native "; +// else + if (isFinalInTargetLang()) s += "final "; + else if (isAbstract()) s += "abstract "; + + if (isStatic()) s += "static "; + + // Return type + if (type()) + s += type()->fullName() + " "; + else + s += "void "; + } + + s += name(); + s += "("; + + for (int i=0; i<m_arguments.size(); ++i) { + if (i != 0) { + s += ","; + if (!minimal) + s += QLatin1Char(' '); + } + s += m_arguments.at(i)->type()->fullName(); + + if (!minimal) { + s += " "; + s += m_arguments.at(i)->argumentName(); + } + } + + s += ")"; + + return s; +} + + +bool function_sorter(AbstractMetaFunction *a, AbstractMetaFunction *b) +{ + return a->signature() < b->signature(); +} + +/******************************************************************************* + * AbstractMetaClass + */ +AbstractMetaClass::~AbstractMetaClass() +{ + qDeleteAll(m_functions); + qDeleteAll(m_fields); +} + +/*AbstractMetaClass *AbstractMetaClass::copy() const +{ + AbstractMetaClass *cls = new AbstractMetaClass; + cls->setAttributes(attributes()); + cls->setBaseClass(baseClass()); + cls->setTypeEntry(typeEntry()); + foreach (AbstractMetaFunction *function, functions()) { + AbstractMetaFunction *copy = function->copy(); + function->setImplementingClass(cls); + cls->addFunction(copy); + } + cls->setEnums(enums()); + foreach (const AbstractMetaField *field, fields()) { + AbstractMetaField *copy = field->copy(); + copy->setEnclosingClass(cls); + cls->addField(copy); + } + cls->setInterfaces(interfaces()); + + return cls; +}*/ + +/******************************************************************************* + * Returns true if this class is a subclass of the given class + */ +bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const +{ + Q_ASSERT(cls != 0); + + const AbstractMetaClass *clazz = this; + while (clazz != 0) { + if (clazz == cls) + return true; + + clazz = clazz->baseClass(); + } + + return false; +} + +/******************************************************************************* + * Constructs an interface based on the functions and enums in this + * class and returns it... + */ +AbstractMetaClass *AbstractMetaClass::extractInterface() +{ + Q_ASSERT(typeEntry()->designatedInterface()); + + if (m_extracted_interface == 0) { + AbstractMetaClass *iface = new AbstractMetaClass; + iface->setAttributes(attributes()); + iface->setBaseClass(0); + iface->setPrimaryInterfaceImplementor(this); + + iface->setTypeEntry(typeEntry()->designatedInterface()); + + foreach (AbstractMetaFunction *function, functions()) { + if (!function->isConstructor()) + iface->addFunction(function->copy()); + } + +// iface->setEnums(enums()); +// setEnums(AbstractMetaEnumList()); + + foreach (const AbstractMetaField *field, fields()) { + if (field->isPublic()) { + AbstractMetaField *new_field = field->copy(); + new_field->setEnclosingClass(iface); + iface->addField(new_field); + } + } + + m_extracted_interface = iface; + addInterface(iface); + } + + return m_extracted_interface; +} + +/******************************************************************************* + * Returns a list of all the functions with a given name + */ +AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString &name) const +{ + AbstractMetaFunctionList returned; + AbstractMetaFunctionList functions = this->functions(); + foreach (AbstractMetaFunction *function, functions) { + if (function->name() == name) + returned.append(function); + } + + return returned; +} + +/******************************************************************************* + * Returns all reference count modifications for any function in the class + */ +QList<ReferenceCount> AbstractMetaClass::referenceCounts() const +{ + QList<ReferenceCount> returned; + + AbstractMetaFunctionList functions = this->functions(); + foreach (AbstractMetaFunction *function, functions) { + returned += function->referenceCounts(this); + } + + return returned; +} + +/******************************************************************************* + * Returns a list of all the functions retrieved during parsing which should + * be added to the Java API. + */ +AbstractMetaFunctionList AbstractMetaClass::functionsInTargetLang() const +{ + int default_flags = NormalFunctions | Visible | NotRemovedFromTargetLang; + + // Interfaces don't implement functions + default_flags |= isInterface() ? 0 : ClassImplements; + + // Only public functions in final classes + // default_flags |= isFinal() ? WasPublic : 0; + int public_flags = isFinal() ? WasPublic : 0; + + // Constructors + AbstractMetaFunctionList returned = queryFunctions(Constructors | default_flags | public_flags); + + // Final functions + returned += queryFunctions(FinalInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags); + + // Virtual functions + returned += queryFunctions(VirtualInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags); + + // Static functions + returned += queryFunctions(StaticFunctions | default_flags | public_flags); + + // Empty, private functions, since they aren't caught by the other ones + returned += queryFunctions(Empty | Invisible); + + return returned; +} + +AbstractMetaFunctionList AbstractMetaClass::virtualFunctions() const +{ + AbstractMetaFunctionList list = functionsInShellClass(); + + AbstractMetaFunctionList returned; + foreach (AbstractMetaFunction *f, list) { + if (!f->isFinalInCpp() || f->isVirtualSlot()) + returned += f; + } + + return returned; +} + +AbstractMetaFunctionList AbstractMetaClass::nonVirtualShellFunctions() const +{ + AbstractMetaFunctionList list = functionsInShellClass(); + AbstractMetaFunctionList returned; + foreach (AbstractMetaFunction *f, list) { + if (f->isFinalInCpp() && !f->isVirtualSlot()) + returned += f; + } + + return returned; +} + +/******************************************************************************* + * Returns a list of all functions that should be declared and implemented in + * the shell class which is generated as a wrapper on top of the actual C++ class + */ +AbstractMetaFunctionList AbstractMetaClass::functionsInShellClass() const +{ + // Only functions and only protected and public functions + int default_flags = NormalFunctions | Visible | WasVisible | NotRemovedFromShell; + + // All virtual functions + AbstractMetaFunctionList returned = queryFunctions(VirtualFunctions | default_flags); + + // All functions explicitly set to be implemented by the shell class + // (mainly superclass functions that are hidden by other declarations) + returned += queryFunctions(ForcedShellFunctions | default_flags); + + // All functions explicitly set to be virtual slots + returned += queryFunctions(VirtualSlots | default_flags); + + return returned; +} + +/******************************************************************************* + * Returns a list of all functions that require a public override function to + * be generated in the shell class. This includes all functions that were originally + * protected in the superclass. + */ +AbstractMetaFunctionList AbstractMetaClass::publicOverrideFunctions() const +{ + return queryFunctions(NormalFunctions | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang) + + queryFunctions(Signals | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang); +} + +AbstractMetaFunctionList AbstractMetaClass::virtualOverrideFunctions() const +{ + return queryFunctions(NormalFunctions | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell) + + queryFunctions(Signals | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell); +} + +void AbstractMetaClass::sortFunctions() +{ + qSort(m_functions.begin(), m_functions.end(), function_sorter); +} + +void AbstractMetaClass::setFunctions(const AbstractMetaFunctionList &functions) +{ + m_functions = functions; + + // Functions must be sorted by name before next loop + sortFunctions(); + + QString currentName; + bool hasVirtuals = false; + AbstractMetaFunctionList final_functions; + foreach (AbstractMetaFunction *f, m_functions) { + f->setOwnerClass(this); + + m_has_virtual_slots |= f->isVirtualSlot(); + m_has_virtuals |= !f->isFinal() || f->isVirtualSlot(); + m_has_nonpublic |= !f->isPublic(); + + // If we have non-virtual overloads of a virtual function, we have to implement + // all the overloads in the shell class to override the hiding rule + if (currentName == f->name()) { + hasVirtuals = hasVirtuals || !f->isFinal(); + if (f->isFinal()) + final_functions += f; + } else { + if (hasVirtuals && final_functions.size() > 0) { + foreach (AbstractMetaFunction *final_function, final_functions) { + *final_function += AbstractMetaAttributes::ForceShellImplementation; + + QString warn = QString("hiding of function '%1' in class '%2'") + .arg(final_function->name()).arg(name()); + ReportHandler::warning(warn); + } + } + + hasVirtuals = !f->isFinal(); + final_functions.clear(); + if (f->isFinal()) + final_functions += f; + currentName = f->name(); + } + } + +#ifndef QT_NO_DEBUG + bool duplicate_function = false; + for (int j=0; j<m_functions.size(); ++j) { + FunctionModificationList mods = m_functions.at(j)->modifications(m_functions.at(j)->implementingClass()); + + bool removed = false; + foreach (const FunctionModification &mod, mods) { + if (mod.isRemoveModifier()) { + removed = true; + break ; + } + } + if (removed) + continue ; + + for (int i=0; i<m_functions.size() - 1; ++i) { + if (j == i) + continue; + + mods = m_functions.at(i)->modifications(m_functions.at(i)->implementingClass()); + bool removed = false; + foreach (const FunctionModification &mod, mods) { + if (mod.isRemoveModifier()) { + removed = true; + break ; + } + } + if (removed) + continue ; + + uint cmp = m_functions.at(i)->compareTo(m_functions.at(j)); + if ((cmp & AbstractMetaFunction::EqualName) && (cmp & AbstractMetaFunction::EqualArguments)) { + printf("%s.%s mostly equal to %s.%s\n", + qPrintable(m_functions.at(i)->implementingClass()->typeEntry()->qualifiedCppName()), + qPrintable(m_functions.at(i)->signature()), + qPrintable(m_functions.at(j)->implementingClass()->typeEntry()->qualifiedCppName()), + qPrintable(m_functions.at(j)->signature())); + duplicate_function = true; + } + } + } + //Q_ASSERT(!duplicate_function); +#endif +} + +bool AbstractMetaClass::hasFieldAccessors() const +{ + foreach (const AbstractMetaField *field, fields()) { + if (field->getter() || field->setter()) + return true; + } + + return false; +} + +bool AbstractMetaClass::hasDefaultToStringFunction() const +{ + foreach (AbstractMetaFunction *f, queryFunctionsByName("toString")) { + if (f->actualMinimumArgumentCount() == 0) { + return true; + } + + } + return false; +} + +void AbstractMetaClass::addFunction(AbstractMetaFunction *function) +{ + function->setOwnerClass(this); + + if (!function->isDestructor()) { + m_functions << function; + qSort(m_functions.begin(), m_functions.end(), function_sorter); + } + + + m_has_virtual_slots |= function->isVirtualSlot(); + m_has_virtuals |= !function->isFinal() || function->isVirtualSlot(); + m_has_nonpublic |= !function->isPublic(); +} + +bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const +{ + if (!other->isSignal()) + return false; + + foreach (const AbstractMetaFunction *f, functions()) { + if (f->isSignal() && f->compareTo(other) & AbstractMetaFunction::EqualName) + return other->modifiedName() == f->modifiedName(); + } + + return false; +} + + +QString AbstractMetaClass::name() const +{ + return QString(m_type_entry->targetLangName()).replace("::", "_"); +} + +bool AbstractMetaClass::hasFunction(const QString &str) const +{ + foreach (const AbstractMetaFunction *f, functions()) + if (f->name() == str) + return true; + return false; +} + +/* Returns true if this class has one or more functions that are + protected. If a class has protected members we need to generate a + shell class with public accessors to the protected functions, so + they can be called from the native functions. +*/ +bool AbstractMetaClass::hasProtectedFunctions() const { + foreach (AbstractMetaFunction *func, m_functions) { + if (func->isProtected()) + return true; + } + return false; +} + +bool AbstractMetaClass::generateShellClass() const +{ + return m_force_shell_class || + (!isFinal() + && (hasVirtualFunctions() + || hasProtectedFunctions() + || hasFieldAccessors() + || typeEntry()->isObject())); // qtd2 for being more consistent +} + +QPropertySpec *AbstractMetaClass::propertySpecForRead(const QString &name) const +{ + for (int i=0; i<m_property_specs.size(); ++i) + if (name == m_property_specs.at(i)->read()) + return m_property_specs.at(i); + return 0; +} + +QPropertySpec *AbstractMetaClass::propertySpecForWrite(const QString &name) const +{ + for (int i=0; i<m_property_specs.size(); ++i) + if (name == m_property_specs.at(i)->write()) + return m_property_specs.at(i); + return 0; +} + +QPropertySpec *AbstractMetaClass::propertySpecForReset(const QString &name) const +{ + for (int i=0; i<m_property_specs.size(); ++i) { + if (name == m_property_specs.at(i)->reset()) + return m_property_specs.at(i); + } + return 0; +} + + + +static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func) +{ + foreach (const AbstractMetaFunction *f, l) { + if ((f->compareTo(func) & AbstractMetaFunction::PrettySimilar) == AbstractMetaFunction::PrettySimilar) + return true; + } + return false; +} + +AbstractMetaField::AbstractMetaField() : m_getter(0), m_setter(0), m_class(0) +{ +} + +AbstractMetaField::~AbstractMetaField() +{ + delete m_setter; + delete m_getter; +} +ushort painters; // refcount +AbstractMetaField *AbstractMetaField::copy() const +{ + AbstractMetaField *returned = new AbstractMetaField; + returned->setEnclosingClass(0); + returned->setAttributes(attributes()); + returned->setName(name()); + returned->setType(type()->copy()); + returned->setOriginalAttributes(originalAttributes()); + + return returned; +} + +static QString upCaseFirst(const QString &str) { + Q_ASSERT(!str.isEmpty()); + QString s = str; + s[0] = s.at(0).toUpper(); + return s; +} + +static AbstractMetaFunction *createXetter(const AbstractMetaField *g, const QString &name, uint type) { + AbstractMetaFunction *f = new AbstractMetaFunction; + + + + f->setName(name); + f->setOriginalName(name); + f->setOwnerClass(g->enclosingClass()); + f->setImplementingClass(g->enclosingClass()); + f->setDeclaringClass(g->enclosingClass()); + + uint attr = AbstractMetaAttributes::Native + | AbstractMetaAttributes::Final + | type; + if (g->isStatic()) + attr |= AbstractMetaAttributes::Static; + if (g->isPublic()) + attr |= AbstractMetaAttributes::Public; + else if (g->isProtected()) + attr |= AbstractMetaAttributes::Protected; + else + attr |= AbstractMetaAttributes::Private; + f->setAttributes(attr); + f->setOriginalAttributes(attr); + + FieldModificationList mods = g->modifications(); + foreach (FieldModification mod, mods) { + if (mod.isRenameModifier()) + f->setName(mod.renamedTo()); + if (mod.isAccessModifier()) { + if (mod.isPrivate()) + f->setVisibility(AbstractMetaAttributes::Private); + else if (mod.isProtected()) + f->setVisibility(AbstractMetaAttributes::Protected); + else if (mod.isPublic()) + f->setVisibility(AbstractMetaAttributes::Public); + else if (mod.isFriendly()) + f->setVisibility(AbstractMetaAttributes::Friendly); + } + + } + return f; +} + +FieldModificationList AbstractMetaField::modifications() const +{ + FieldModificationList mods = enclosingClass()->typeEntry()->fieldModifications(); + FieldModificationList returned; + + foreach (FieldModification mod, mods) { + if (mod.name == name()) + returned += mod; + } + + return returned; +} + +const AbstractMetaFunction *AbstractMetaField::setter() const +{ + if (m_setter == 0) { + m_setter = createXetter(this, + "set" + upCaseFirst(name()), + AbstractMetaAttributes::SetterFunction); + AbstractMetaArgumentList arguments; + AbstractMetaArgument *argument = new AbstractMetaArgument; + argument->setType(type()->copy()); + argument->setName(name()); + arguments.append(argument); + m_setter->setArguments(arguments); + } + return m_setter; +} + +const AbstractMetaFunction *AbstractMetaField::getter() const +{ + if (m_getter == 0) { + m_getter = createXetter(this, + name(), + AbstractMetaAttributes::GetterFunction); + m_getter->setType(type()); + } + + return m_getter; +} + + +bool AbstractMetaClass::hasConstructors() const +{ + return queryFunctions(Constructors).size() != 0; +} + +void AbstractMetaClass::addDefaultConstructor() +{ + AbstractMetaFunction *f = new AbstractMetaFunction; + f->setName(name()); + f->setOwnerClass(this); + f->setFunctionType(AbstractMetaFunction::ConstructorFunction); + f->setArguments(AbstractMetaArgumentList()); + f->setDeclaringClass(this); + + uint attr = AbstractMetaAttributes::Native; + attr |= AbstractMetaAttributes::Public; + attr |= AbstractMetaAttributes::Final; // qtd otherwise added constructor is virtual which in fact it is not + f->setAttributes(attr); + f->setImplementingClass(this); + f->setOriginalAttributes(f->attributes()); + + addFunction(f); +} + +bool AbstractMetaClass::hasFunction(const AbstractMetaFunction *f) const +{ + return functions_contains(m_functions, f); +} + +/* Goes through the list of functions and returns a list of all + functions matching all of the criteria in \a query. + */ + +AbstractMetaFunctionList AbstractMetaClass::queryFunctions(uint query) const +{ + AbstractMetaFunctionList functions; + + foreach (AbstractMetaFunction *f, m_functions) { + + if ((query & VirtualSlots) && !f->isVirtualSlot()) + continue; + + if ((query & NotRemovedFromTargetLang) && f->isRemovedFrom(f->implementingClass(), TypeSystem::TargetLangCode)) { + continue; + } + + if ((query & NotRemovedFromTargetLang) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::TargetLangCode)) { + continue; + } + + if ((query & NotRemovedFromShell) && f->isRemovedFrom(f->implementingClass(), TypeSystem::ShellCode)) { + continue; + } + + if ((query & NotRemovedFromShell) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::ShellCode)) { + continue; + } + + if ((query & Visible) && f->isPrivate()) { + continue; + } + + if ((query & VirtualInTargetLangFunctions) && f->isFinalInTargetLang()) { + continue; + } + + if ((query & Invisible) && !f->isPrivate()) { + continue; + } + + if ((query & Empty) && !f->isEmptyFunction()) { + continue; + } + + if ((query & WasPublic) && !f->wasPublic()) { + continue; + } + + if ((query & WasVisible) && f->wasPrivate()) { + continue; + } + + if ((query & WasProtected) && !f->wasProtected()) { + continue; + } + + if ((query & ClassImplements) && f->ownerClass() != f->implementingClass()) { + continue; + } + + if ((query & Inconsistent) && (f->isFinalInTargetLang() || !f->isFinalInCpp() || f->isStatic())) { + continue; + } + + if ((query & FinalInTargetLangFunctions) && !f->isFinalInTargetLang()) { + continue; + } + + if ((query & FinalInCppFunctions) && !f->isFinalInCpp()) { + continue; + } + + if ((query & VirtualInCppFunctions) && f->isFinalInCpp()) { + continue; + } + + if ((query & Signals) && (!f->isSignal())) { + continue; + } + + if ((query & ForcedShellFunctions) + && (!f->isForcedShellImplementation() + || !f->isFinal())) { + continue; + } + + if ((query & Constructors) && (!f->isConstructor() + || f->ownerClass() != f->implementingClass()) + || f->isConstructor() && (query & Constructors) == 0) { + continue; + } + + // Destructors are never included in the functions of a class currently + /* + if ((query & Destructors) && (!f->isDestructor() + || f->ownerClass() != f->implementingClass()) + || f->isDestructor() && (query & Destructors) == 0) { + continue; + }*/ + + if ((query & VirtualFunctions) && (f->isFinal() || f->isSignal() || f->isStatic())) { + continue; + } + + if ((query & StaticFunctions) && (!f->isStatic() || f->isSignal())) { + continue; + } + + if ((query & NonStaticFunctions) && (f->isStatic())) { + continue; + } + + if ((query & NonEmptyFunctions) && (f->isEmptyFunction())) { + continue; + } + + if ((query & NormalFunctions) && (f->isSignal())) { + continue; + } + + if ((query & AbstractFunctions) && !f->isAbstract()) { + continue; + } + + functions << f; + } + +// qDebug() << "queried" << m_type_entry->qualifiedCppName() << "got" << functions.size() << "out of" << m_functions.size(); + + return functions; +} + + +bool AbstractMetaClass::hasInconsistentFunctions() const +{ + return cppInconsistentFunctions().size() > 0; +} + +bool AbstractMetaClass::hasSignals() const +{ + return cppSignalFunctions().size() > 0; +} + + +/** + * Adds the specified interface to this class by adding all the + * functions in the interface to this class. + */ +void AbstractMetaClass::addInterface(AbstractMetaClass *interface) +{ + Q_ASSERT(!m_interfaces.contains(interface)); + m_interfaces << interface; + + if (m_extracted_interface != 0 && m_extracted_interface != interface) + m_extracted_interface->addInterface(interface); + + foreach (AbstractMetaFunction *function, interface->functions()) + if (!hasFunction(function) && !function->isConstructor()) { + AbstractMetaFunction *cpy = function->copy(); + cpy->setImplementingClass(this); + + // Setup that this function is an interface class. + cpy->setInterfaceClass(interface); + *cpy += AbstractMetaAttributes::InterfaceFunction; + + // Copy the modifications in interface into the implementing classes. + FunctionModificationList mods = function->modifications(interface); + foreach (const FunctionModification &mod, mods) { + m_type_entry->addFunctionModification(mod); + } + + // It should be mostly safe to assume that when we implement an interface + // we don't "pass on" pure virtual functions to our sublcasses... +// *cpy -= AbstractMetaAttributes::Abstract; + + addFunction(cpy); + } +} + + +void AbstractMetaClass::setInterfaces(const AbstractMetaClassList &interfaces) +{ + m_interfaces = interfaces; +} + + +AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName) +{ + foreach (AbstractMetaEnum *e, m_enums) { + if (e->name() == enumName) + return e; + } + + if (typeEntry()->designatedInterface()) + return extractInterface()->findEnum(enumName); + + return 0; +} + + + + +/*! Recursivly searches for the enum value named \a enumValueName in + this class and its superclasses and interfaces. Values belonging to + \a meta_enum are excluded from the search. +*/ +AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValueName, AbstractMetaEnum *meta_enum) +{ + foreach (AbstractMetaEnum *e, m_enums) { + if (e == meta_enum) + continue; + foreach (AbstractMetaEnumValue *v, e->values()) { + if (v->name() == enumValueName) + return v; + } + } + + if (typeEntry()->designatedInterface()) + return extractInterface()->findEnumValue(enumValueName, meta_enum); + + if (baseClass() != 0) + return baseClass()->findEnumValue(enumValueName, meta_enum); + + return 0; +} + + +/*! + * Searches through all of this class' enums for a value matching the + * name \a enumValueName. The name is excluding the class/namespace + * prefix. The function recursivly searches interfaces and baseclasses + * of this class. + */ +AbstractMetaEnum *AbstractMetaClass::findEnumForValue(const QString &enumValueName) +{ + foreach (AbstractMetaEnum *e, m_enums) { + foreach (AbstractMetaEnumValue *v, e->values()) { + if (v->name() == enumValueName) + return e; + } + } + + if (typeEntry()->designatedInterface()) + return extractInterface()->findEnumForValue(enumValueName); + + if (baseClass() != 0) + return baseClass()->findEnumForValue(enumValueName); + + return 0; +} + + +static void add_extra_include_for_type(AbstractMetaClass *meta_class, const AbstractMetaType *type) +{ + + if (type == 0) + return; + + Q_ASSERT(meta_class != 0); + const TypeEntry *entry = (type ? type->typeEntry() : 0); + if (entry != 0 && entry->isComplex()) { + const ComplexTypeEntry *centry = static_cast<const ComplexTypeEntry *>(entry); + ComplexTypeEntry *class_entry = meta_class->typeEntry(); + if (class_entry != 0 && centry->include().isValid()) + class_entry->addExtraInclude(centry->include()); + } + + if (type->hasInstantiations()) { + QList<AbstractMetaType *> instantiations = type->instantiations(); + foreach (AbstractMetaType *instantiation, instantiations) + add_extra_include_for_type(meta_class, instantiation); + } +} + +static void add_extra_includes_for_function(AbstractMetaClass *meta_class, const AbstractMetaFunction *meta_function) +{ + Q_ASSERT(meta_class != 0); + Q_ASSERT(meta_function != 0); + add_extra_include_for_type(meta_class, meta_function->type()); + + AbstractMetaArgumentList arguments = meta_function->arguments(); + foreach (AbstractMetaArgument *argument, arguments) + add_extra_include_for_type(meta_class, argument->type()); +} + +void AbstractMetaClass::fixFunctions() +{ + if (m_functions_fixed) + return; + else + m_functions_fixed = true; + + AbstractMetaClass *super_class = baseClass(); + AbstractMetaFunctionList funcs = functions(); + +// printf("fix functions for %s\n", qPrintable(name())); + + if (super_class != 0) + super_class->fixFunctions(); + int iface_idx = 0; + while (super_class || iface_idx < interfaces().size()) { +// printf(" - base: %s\n", qPrintable(super_class->name())); + + // Since we always traverse the complete hierarchy we are only + // interrested in what each super class implements, not what + // we may have propagated from their base classes again. + AbstractMetaFunctionList super_funcs; + if (super_class) { + + // Super classes can never be final + if (super_class->isFinalInTargetLang()) { + ReportHandler::warning("Final class '" + super_class->name() + "' set to non-final, as it is extended by other classes"); + *super_class -= AbstractMetaAttributes::FinalInTargetLang; + } + super_funcs = super_class->queryFunctions(AbstractMetaClass::ClassImplements); + } else { + super_funcs = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::NormalFunctions); + } + + QSet<AbstractMetaFunction *> funcs_to_add; + for (int sfi=0; sfi<super_funcs.size(); ++sfi) { + AbstractMetaFunction *sf = super_funcs.at(sfi); + + if (sf->isRemovedFromAllLanguages(sf->implementingClass())) + continue; + + // we generally don't care about private functions, but we have to get the ones that are + // virtual in case they override abstract functions. + bool add = (sf->isNormal() || sf->isSignal() || sf->isEmptyFunction()); + for (int fi=0; fi<funcs.size(); ++fi) { + AbstractMetaFunction *f = funcs.at(fi); + if (f->isRemovedFromAllLanguages(f->implementingClass())) + continue; + + uint cmp = f->compareTo(sf); + + if (cmp & AbstractMetaFunction::EqualModifiedName) { +// printf(" - %s::%s similar to %s::%s %x vs %x\n", +// qPrintable(sf->implementingClass()->typeEntry()->qualifiedCppName()), +// qPrintable(sf->name()), +// qPrintable(f->implementingClass()->typeEntry()->qualifiedCppName()), +// qPrintable(f->name()), +// sf->attributes(), +// f->attributes()); + + add = false; + if (cmp & AbstractMetaFunction::EqualArguments) { + +// if (!(cmp & AbstractMetaFunction::EqualReturnType)) { +// ReportHandler::warning(QString("%1::%2 and %3::%4 differ in retur type") +// .arg(sf->implementingClass()->name()) +// .arg(sf->name()) +// .arg(f->implementingClass()->name()) +// .arg(f->name())); +// } + + // Same function, propegate virtual... + if (!(cmp & AbstractMetaFunction::EqualAttributes)) { + if (!f->isEmptyFunction()) { + if (!sf->isFinalInCpp() && f->isFinalInCpp()) { + *f -= AbstractMetaAttributes::FinalInCpp; + // printf(" --- inherit virtual\n"); + } + if (!sf->isFinalInTargetLang() && f->isFinalInTargetLang()) { + *f -= AbstractMetaAttributes::FinalInTargetLang; + // printf(" --- inherit virtual\n"); + } + if (!f->isFinalInTargetLang() && f->isPrivate()) { + f->setFunctionType(AbstractMetaFunction::EmptyFunction); + f->setVisibility(AbstractMetaAttributes::Protected); + *f += AbstractMetaAttributes::FinalInTargetLang; + ReportHandler::warning(QString("private virtual function '%1' in '%2'") + .arg(f->signature()) + .arg(f->implementingClass()->name())); + } + } + } + + if (f->visibility() != sf->visibility()) { + QString warn = QString("visibility of function '%1' modified in class '%2'") + .arg(f->name()).arg(name()); + ReportHandler::warning(warn); + + // If new visibility is private, we can't + // do anything. If it isn't, then we + // prefer the parent class's visibility + // setting for the function. + if (!f->isPrivate() && !sf->isPrivate()) + f->setVisibility(sf->visibility()); + + // Private overrides of abstract functions have to go into the class or + // the subclasses will not compile as non-abstract classes. + // But they don't need to be implemented, since they can never be called. + if (f->isPrivate() && sf->isAbstract()) { + f->setFunctionType(AbstractMetaFunction::EmptyFunction); + f->setVisibility(sf->visibility()); + *f += AbstractMetaAttributes::FinalInTargetLang; + *f += AbstractMetaAttributes::FinalInCpp; + } + } + + // Set the class which first declares this function, afawk + f->setDeclaringClass(sf->declaringClass()); + + if (sf->isFinalInTargetLang() && !sf->isPrivate() && !f->isPrivate() && !sf->isStatic() && !f->isStatic()) { + // Shadowed funcion, need to make base class + // function non-virtual + if (f->implementingClass() != sf->implementingClass() && f->implementingClass()->inheritsFrom(sf->implementingClass())) { + + // Check whether the superclass method has been redefined to non-final + + bool hasNonFinalModifier = false; + bool isBaseImplPrivate = false; + FunctionModificationList mods = sf->modifications(sf->implementingClass()); + foreach (FunctionModification mod, mods) { + if (mod.isNonFinal()) { + hasNonFinalModifier = true; + break; + } else if (mod.isPrivate()) { + isBaseImplPrivate = true; + break; + } + } + + if (!hasNonFinalModifier && !isBaseImplPrivate) { + ReportHandler::warning(QString::fromLatin1("Shadowing: %1::%2 and %3::%4; Java code will not compile") + .arg(sf->implementingClass()->name()) + .arg(sf->signature()) + .arg(f->implementingClass()->name()) + .arg(f->signature())); + } + } + } + + } + + if (cmp & AbstractMetaFunction::EqualDefaultValueOverload) { + AbstractMetaArgumentList arguments; + if (f->arguments().size() < sf->arguments().size()) + arguments = sf->arguments(); + else + arguments = f->arguments(); +/* qtd + for (int i=0; i<arguments.size(); ++i) + arguments[i]->setDefaultValueExpression(QString()); +*/ } + + + // Otherwise we have function shadowing and we can + // skip the thing... + } else if (cmp & AbstractMetaFunction::EqualName && !sf->isSignal()) { + + // In the case of function shadowing where the function name has been altered to + // avoid conflict, we don't copy in the original. + add = false; + } + + } + + if (add) + funcs_to_add << sf; + } + + foreach (AbstractMetaFunction *f, funcs_to_add) + funcs << f->copy(); + + if (super_class) + super_class = super_class->baseClass(); + else + iface_idx++; + } + + bool hasPrivateConstructors = false; + bool hasPublicConstructors = false; + foreach (AbstractMetaFunction *func, funcs) { + FunctionModificationList mods = func->modifications(this); + foreach (const FunctionModification &mod, mods) { + if (mod.isRenameModifier()) { +// qDebug() << name() << func->originalName() << func << " from " +// << func->implementingClass()->name() << "renamed to" << mod.renamedTo(); + func->setName(mod.renamedTo()); + } + } + + // Make sure class is abstract if one of the functions is + if (func->isAbstract()) { + (*this) += AbstractMetaAttributes::Abstract; + (*this) -= AbstractMetaAttributes::Final; + } + + if (func->isConstructor()) { + if (func->isPrivate()) + hasPrivateConstructors = true; + else + hasPublicConstructors = true; + } + + + + // Make sure that we include files for all classes that are in use + + if (!func->isRemovedFrom(this, TypeSystem::ShellCode)) + add_extra_includes_for_function(this, func); + } + + if (hasPrivateConstructors && !hasPublicConstructors) { + (*this) += AbstractMetaAttributes::Abstract; + (*this) -= AbstractMetaAttributes::Final; + } + + foreach (AbstractMetaFunction *f1, funcs) { + foreach (AbstractMetaFunction *f2, funcs) { + if (f1 != f2) { + uint cmp = f1->compareTo(f2); + if ((cmp & AbstractMetaFunction::EqualName) + && !f1->isFinalInCpp() + && f2->isFinalInCpp()) { + *f2 += AbstractMetaAttributes::FinalOverload; +// qDebug() << f2 << f2->implementingClass()->name() << "::" << f2->name() << f2->arguments().size() << " vs " << f1 << f1->implementingClass()->name() << "::" << f1->name() << f1->arguments().size(); +// qDebug() << " " << f2; +// AbstractMetaArgumentList f2Args = f2->arguments(); +// foreach (AbstractMetaArgument *a, f2Args) +// qDebug() << " " << a->type()->name() << a->name(); +// qDebug() << " " << f1; +// AbstractMetaArgumentList f1Args = f1->arguments(); +// foreach (AbstractMetaArgument *a, f1Args) +// qDebug() << " " << a->type()->name() << a->name(); + + } + } + } + } + + setFunctions(funcs); +} + + +QString AbstractMetaType::minimalSignature() const +{ + QString minimalSignature; + if (isConstant()) + minimalSignature += "const "; + minimalSignature += typeEntry()->qualifiedCppName(); + if (hasInstantiations()) { + QList<AbstractMetaType *> instantiations = this->instantiations(); + minimalSignature += "<"; + for (int i=0;i<instantiations.size();++i) { + if (i > 0) + minimalSignature += ","; + minimalSignature += instantiations.at(i)->minimalSignature(); + } + minimalSignature += ">"; + } + + if (isReference()) + minimalSignature += "&"; + for (int j=0; j<indirections(); ++j) + minimalSignature += "*"; + + return minimalSignature; +} + +bool AbstractMetaType::hasNativeId() const +{ + return (isQObject() || isValue() || isObject()) && typeEntry()->isNativeIdBased(); +} + + +/******************************************************************************* + * Other stuff... + */ + + +AbstractMetaEnum *AbstractMetaClassList::findEnum(const EnumTypeEntry *entry) const +{ + Q_ASSERT(entry->isEnum()); + + QString qualified_name = entry->qualifiedCppName(); + int pos = qualified_name.lastIndexOf("::"); + + QString enum_name; + QString class_name; + + if (pos > 0) { + enum_name = qualified_name.mid(pos + 2); + class_name = qualified_name.mid(0, pos); + } else { + enum_name = qualified_name; + class_name = TypeDatabase::globalNamespaceClassName(entry); + } + + AbstractMetaClass *meta_class = findClass(class_name); + if (!meta_class) { + ReportHandler::warning(QString("AbstractMeta::findEnum(), unknown class '%1' in '%2'") + .arg(class_name).arg(entry->qualifiedCppName())); + return 0; + } + + return meta_class->findEnum(enum_name); +} + +AbstractMetaEnumValue *AbstractMetaEnumValueList::find(const QString &name) const +{ + for (int i=0; i<size(); ++i) { + if (name == at(i)->name()) + return at(i); + } + return 0; +} + +AbstractMetaEnumValue *AbstractMetaClassList::findEnumValue(const QString &name) const +{ + QStringList lst = name.split(QLatin1String("::")); + + Q_ASSERT_X(lst.size() == 2, "AbstractMetaClassList::findEnumValue()", "Expected qualified enum"); + + + QString prefixName = lst.at(0); + QString enumName = lst.at(1); + + AbstractMetaClass *cl = findClass(prefixName); + if (cl) + return cl->findEnumValue(enumName, 0); + + ReportHandler::warning(QString("no matching enum '%1'").arg(name)); + return 0; +} + +/*! + * Searches the list after a class that mathces \a name; either as + * C++, Java base name or complete Java package.class name. + */ + +AbstractMetaClass *AbstractMetaClassList::findClass(const QString &name) const +{ + if (name.isEmpty()) + return 0; + + foreach (AbstractMetaClass *c, *this) { + if (c->qualifiedCppName() == name) + return c; + } + + foreach (AbstractMetaClass *c, *this) { + if (c->fullName() == name) + return c; + } + + foreach (AbstractMetaClass *c, *this) { + if (c->name() == name) + return c; + } + + return 0; +} + +ArgumentReplace *ArgumentReplace::m_instance = 0; + +ArgumentReplace::ArgumentReplace() +{ +} + +void ArgumentReplace::init() +{ + if (m_instance) + return; + + m_instance = new ArgumentReplace(); + m_instance->data["version"] = "_version"; + m_instance->data["parent"] = "_parent"; + m_instance->data["delegate"] = "_delegate"; + m_instance->data["align"] = "_align"; + m_instance->data["in"] = "_in"; + m_instance->data["out"] = "_out"; + m_instance->data["scope"] = "_scope"; + m_instance->data["default"] = "_default"; +} + +QString ArgumentReplace::translate(QString arg) +{ + if (m_instance->data.contains(arg)) + return m_instance->data[arg]; + else + return arg; +}