summaryrefslogtreecommitdiffstats
path: root/generator/abstractmetalang.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'generator/abstractmetalang.cpp')
-rw-r--r--generator/abstractmetalang.cpp1957
1 files changed, 1957 insertions, 0 deletions
diff --git a/generator/abstractmetalang.cpp b/generator/abstractmetalang.cpp
new file mode 100644
index 0000000..59006ac
--- /dev/null
+++ b/generator/abstractmetalang.cpp
@@ -0,0 +1,1957 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the Qt Script Generator project on Trolltech Labs.
+**
+** This file may be used under the terms of the GNU General Public
+** License version 2.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.trolltech.com/products/qt/opensource.html
+**
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://www.trolltech.com/products/qt/licensing.html or contact the
+** sales department at sales@trolltech.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"
+
+/*******************************************************************************
+ * 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();
+ 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;
+
+ 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() const
+{
+ QString returned = "__qt_" + name();
+ AbstractMetaArgumentList arguments = this->arguments();
+ foreach (const AbstractMetaArgument *arg, arguments) {
+ returned += "_";
+ if (arg->type()->isNativePointer()) {
+ returned += "nativepointer";
+ } 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::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 0 // jambi
+ 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 ";
+#endif
+ // Return type
+ if (type())
+ s += type()->name() + " ";
+ else
+ s += "void ";
+ }
+
+ s += modifiedName();
+ s += "(";
+
+ int j = 0;
+ for (int i=0; i<m_arguments.size(); ++i) {
+ if (argumentRemoved(i+1))
+ continue;
+ if (j != 0) {
+ s += ",";
+ if (!minimal)
+ s += QLatin1Char(' ');
+ }
+ s += m_arguments.at(i)->type()->name();
+
+ if (!minimal) {
+ s += " ";
+ s += m_arguments.at(i)->argumentName();
+ }
+ ++j;
+ }
+
+ 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()));
+}
+
+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;
+ 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();
+
+ 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;
+}