mandel@1: /**************************************************************************** mandel@1: ** mandel@1: ** Copyright (C) 1992-2008 Nokia. All rights reserved. mandel@1: ** mandel@1: ** This file is part of Qt Jambi. mandel@1: ** mandel@1: ** * Commercial Usage mandel@1: * Licensees holding valid Qt Commercial licenses may use this file in mandel@1: * accordance with the Qt Commercial License Agreement provided with the mandel@1: * Software or, alternatively, in accordance with the terms contained in mandel@1: * a written agreement between you and Nokia. mandel@1: * mandel@1: * mandel@1: * GNU General Public License Usage mandel@1: * Alternatively, this file may be used under the terms of the GNU mandel@1: * General Public License versions 2.0 or 3.0 as published by the Free mandel@1: * Software Foundation and appearing in the file LICENSE.GPL included in mandel@1: * the packaging of this file. Please review the following information mandel@1: * to ensure GNU General Public Licensing requirements will be met: mandel@1: * http://www.fsf.org/licensing/licenses/info/GPLv2.html and mandel@1: * http://www.gnu.org/copyleft/gpl.html. In addition, as a special mandel@1: * exception, Nokia gives you certain additional rights. These rights mandel@1: * are described in the Nokia Qt GPL Exception version 1.2, included in mandel@1: * the file GPL_EXCEPTION.txt in this package. mandel@1: * mandel@1: * Qt for Windows(R) Licensees mandel@1: * As a special exception, Nokia, as the sole copyright holder for Qt mandel@1: * Designer, grants users of the Qt/Eclipse Integration plug-in the mandel@1: * right for the Qt/Eclipse Integration to link to functionality mandel@1: * provided by Qt Designer and its related libraries. mandel@1: * mandel@1: * mandel@1: * If you are unsure which license is appropriate for your use, please mandel@1: * contact the sales department at qt-sales@nokia.com. mandel@1: mandel@1: ** mandel@1: ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE mandel@1: ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. mandel@1: ** mandel@1: ****************************************************************************/ mandel@1: mandel@1: #include "dgenerator.h" mandel@1: #include "reporthandler.h" mandel@1: #include "docparser.h" mandel@1: #include "jumptable.h" mandel@1: #include "fileout.h" mandel@1: mandel@1: #include mandel@1: #include mandel@1: #include mandel@1: #include mandel@1: #include mandel@1: mandel@1: #include mandel@1: mandel@1: mandel@1: static Indentor INDENT; mandel@1: mandel@1: DGenerator::DGenerator() mandel@1: : m_doc_parser(0), mandel@1: m_docs_enabled(false), mandel@1: m_native_jump_table(false), mandel@1: m_recursive(0), mandel@1: m_isRecursive(false) mandel@1: { eldar@288: excludedTypes << "qint64" << "bool" << "int" << "QString" << "char" << "WId" mandel@1: << "unsigned char" << "uint" << "double" << "short" << "float" mandel@1: << "signed char" << "unsigned short" << "QBool" << "unsigned int" mandel@1: << "Qt::HANDLE" << "QChar" << "java.lang.JObjectWrapper" << "void" mandel@1: << "QLatin1String" << "unsigned long long" << "signed int" mandel@1: << "signed short" << "Array" << "GLuint" << "GLenum" << "GLint" mandel@1: << "unsigned long" << "ulong" << "long" << "QByteRef" eldar@297: << "QStringList" << "QVector" << "QPair" eldar@39: << "QSet" << "QStringRef" << "quintptr"; mandel@1: } mandel@1: mandel@1: QString DGenerator::fileNameForClass(const AbstractMetaClass *d_class) const mandel@1: { mandel@1: return QString("%1.d").arg(d_class->name()); mandel@1: } mandel@1: mandel@1: void DGenerator::writeFieldAccessors(QTextStream &s, const AbstractMetaField *field) mandel@1: { mandel@1: Q_ASSERT(field->isPublic() || field->isProtected()); mandel@1: mandel@1: const AbstractMetaClass *declaringClass = field->enclosingClass(); mandel@1: mandel@1: FieldModification mod = declaringClass->typeEntry()->fieldModification(field->name()); mandel@1: mandel@1: // Set function mandel@1: if (mod.isWritable() && !field->type()->isConstant()) { mandel@1: const AbstractMetaFunction *setter = field->setter(); mandel@1: if (declaringClass->hasFunction(setter)) { mandel@1: QString warning = mandel@1: QString("class '%1' already has setter '%2' for public field '%3'") mandel@1: .arg(declaringClass->name()).arg(setter->name()).arg(field->name()); mandel@1: ReportHandler::warning(warning); mandel@1: } else { mandel@1: if (!notWrappedYet(setter)) // qtd2 mandel@1: writeFunction(s, setter); mandel@1: } mandel@1: } mandel@1: mandel@1: // Get function mandel@1: const AbstractMetaFunction *getter = field->getter(); mandel@1: if (mod.isReadable()) { mandel@1: if (declaringClass->hasFunction(getter)) { mandel@1: QString warning = mandel@1: QString("class '%1' already has getter '%2' for public field '%3'") mandel@1: .arg(declaringClass->name()).arg(getter->name()).arg(field->name()); mandel@1: ReportHandler::warning(warning); mandel@1: } else { mandel@1: if (!notWrappedYet(getter)) // qtd2 mandel@1: writeFunction(s, getter); mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: QString DGenerator::translateType(const AbstractMetaType *d_type, const AbstractMetaClass *context, Option option) mandel@1: { mandel@1: QString s; mandel@1: mandel@1: if (context != 0 && d_type != 0 && context->typeEntry()->isGenericClass() && d_type->originalTemplateType() != 0) mandel@1: d_type = d_type->originalTemplateType(); mandel@1: eldar@188: QString constPrefix, constPostfix; eldar@188: if (d_type && d_type->isConstant() && dVersion == 2) { eldar@188: constPrefix = "const("; eldar@288: constPostfix = ")"; eldar@188: } eldar@188: mandel@1: if (!d_type) { mandel@1: s = "void"; eldar@81: } else if (d_type->typeEntry()->qualifiedCppName() == "QChar") { eldar@33: s = "wchar" + QString(d_type->actualIndirections(), '*'); eldar@81: } else if (d_type->typeEntry() && d_type->typeEntry()->qualifiedCppName() == "QString") { mandel@1: s = "string"; mandel@1: } else if (d_type->isArray()) { mandel@1: s = translateType(d_type->arrayElementType(), context) + "[]"; mandel@1: } else if (d_type->isEnum() /* qtd2 || d_type->isFlags() */) { mandel@1: if (( d_type->isEnum() && ((EnumTypeEntry *)d_type->typeEntry())->forceInteger() ) mandel@1: || ( d_type->isFlags() && ((FlagsTypeEntry *)d_type->typeEntry())->forceInteger() ) ) { mandel@1: if (option & BoxedPrimitive) mandel@1: s = "java.lang.Integer"; mandel@1: else mandel@1: s = "int"; mandel@1: } else { mandel@1: if (option & EnumAsInts) mandel@1: s = "int"; mandel@1: else maxter@363: { maxter@363: // Hack around forward-referencing the implementing class in an interface. maxter@363: if (context->typeEntry()->designatedInterface() && d_type->typeEntry()->javaQualifier() == context->name()) maxter@363: s = d_type->name(); maxter@363: else maxter@363: s = d_type->typeEntry()->qualifiedTargetLangName(); maxter@363: } maxter@363: mandel@1: } mandel@1: } else if (d_type->isFlags()) { // qtd2 begin mandel@1: if (d_type->isFlags() && ((FlagsTypeEntry *)d_type->typeEntry())->forceInteger()) { mandel@1: if (option & BoxedPrimitive) mandel@1: s = "java.lang.Integer"; mandel@1: else mandel@1: s = "int"; mandel@1: } else mandel@1: s = "int"; mandel@1: } else { mandel@1: /* qtd if (d_type->isPrimitive() && (option & BoxedPrimitive)) { mandel@1: s = static_cast(d_type->typeEntry())->javaObjectName(); mandel@1: } else */ if (d_type->isVariant()) { mandel@1: s = "QVariant"; mandel@1: } else if (d_type->isNativePointer()) { mandel@1: if (d_type->typeEntry()->isValue() && !d_type->typeEntry()->isStructInD()) mandel@1: s = d_type->typeEntry()->lookupName(); mandel@1: else if (d_type->typeEntry()->isEnum()) mandel@1: s = "int" + QString(d_type->actualIndirections(), '*'); mandel@1: else eldar@188: s = constPrefix + d_type->typeEntry()->lookupName() + QString(d_type->actualIndirections(), '*') + constPostfix; mandel@1: } else if (d_type->isContainer()) { mandel@1: const ContainerTypeEntry* c_entry = static_cast(d_type->typeEntry()); mandel@1: Q_ASSERT(c_entry); mandel@1: mandel@1: if ((option & SkipTemplateParameters) == 0) { mandel@1: QList args = d_type->instantiations(); eldar@298: const ContainerTypeEntry *cte = eldar@298: static_cast(d_type->typeEntry()); eldar@297: if (args.size() == 1) { // QVector or QList eldar@298: if(cte->isQList()) eldar@297: s = "QList!(" + translateType(args.at(0), context, BoxedPrimitive) + ")"; eldar@297: else eldar@297: s = translateType(args.at(0), context, BoxedPrimitive) + "[]"; eldar@297: } mandel@1: else if(args.size() == 2) { // all sorts of maps mandel@1: s = translateType(args.at(1), context, BoxedPrimitive); // value mandel@1: bool isMultiMap = static_cast(d_type->typeEntry())->type() == ContainerTypeEntry::MultiMapContainer; mandel@1: if (isMultiMap) mandel@1: s += "[]"; mandel@1: s += "[" + translateType(args.at(0), context, BoxedPrimitive) + "]"; mandel@1: } else { mandel@1: s = d_type->typeEntry()->qualifiedTargetLangName(); mandel@1: mandel@1: for (int i=0; i(d_type->typeEntry())->type() == ContainerTypeEntry::MultiMapContainer mandel@1: && i == 1; mandel@1: if (isMultiMap) mandel@1: s += "java.util.List<"; mandel@1: s += translateType(args.at(i), context, BoxedPrimitive); mandel@1: if (isMultiMap) mandel@1: s += ">"; mandel@1: } mandel@1: s += '>'; mandel@1: } mandel@1: } mandel@1: mandel@1: } else { mandel@1: const TypeEntry *type = d_type->typeEntry(); mandel@1: if (type->designatedInterface()) mandel@1: type = type->designatedInterface(); mandel@1: if (type->isString()) mandel@1: s = "string"; eldar@188: else if (type->isObject()) { mandel@1: s = type->name(); eldar@188: } else if (type->isValue()){ eldar@188: s = constPrefix + type->lookupName() + constPostfix; mandel@1: } else { mandel@1: s = type->lookupName(); mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: return s; mandel@1: } mandel@1: mandel@1: QString DGenerator::argumentString(const AbstractMetaFunction *d_function, mandel@1: const AbstractMetaArgument *d_argument, mandel@1: uint options) mandel@1: { mandel@1: QString modified_type = d_function->typeReplaced(d_argument->argumentIndex() + 1); mandel@1: QString arg; mandel@1: mandel@1: AbstractMetaType *type = d_argument->type(); eldar@288: // qtd2 if argument is "QString &" ref attribute needed FIXME maybe we need this not only for QString, but for other Value types?? mandel@1: if (type->typeEntry()->isValue() && type->isNativePointer() && type->typeEntry()->name() == "QString") mandel@1: arg = "ref "; mandel@1: mandel@1: if (modified_type.isEmpty()) mandel@1: arg += translateType(d_argument->type(), d_function->implementingClass(), (Option) options); mandel@1: else mandel@1: arg += modified_type.replace('$', '.'); mandel@1: mandel@1: if ((options & SkipName) == 0) { mandel@1: arg += " "; mandel@1: arg += d_argument->argumentName(); mandel@1: } mandel@1: mandel@1: if (!d_argument->defaultValueExpression().isEmpty()) // qtd mandel@1: arg += " = " + d_argument->defaultValueExpression(); mandel@1: mandel@1: return arg; mandel@1: } mandel@1: mandel@1: void DGenerator::writeArgument(QTextStream &s, mandel@1: const AbstractMetaFunction *d_function, mandel@1: const AbstractMetaArgument *d_argument, mandel@1: uint options) mandel@1: { mandel@1: s << argumentString(d_function, d_argument, options); mandel@1: } mandel@1: mandel@1: mandel@1: void DGenerator::writeIntegerEnum(QTextStream &s, const AbstractMetaEnum *d_enum) mandel@1: { mandel@1: const AbstractMetaEnumValueList &values = d_enum->values(); mandel@1: mandel@1: s << " public static class " << d_enum->name() << "{" << endl; mandel@1: for (int i=0; itypeEntry()->isEnumValueRejected(value->name())) mandel@1: continue; mandel@1: mandel@1: if (m_doc_parser) mandel@1: s << m_doc_parser->documentation(value); mandel@1: mandel@1: s << " public static final int " << value->name() << " = " << value->value(); mandel@1: s << ";"; mandel@1: s << endl; mandel@1: } mandel@1: mandel@1: s << " } // end of enum " << d_enum->name() << endl << endl; mandel@1: } mandel@1: maxter@341: void DGenerator::writeEnumAliases(QTextStream &s, const AbstractMetaEnum *d_enum) mandel@1: { mandel@1: const AbstractMetaEnumValueList &values = d_enum->values(); mandel@1: for (int i=0; itypeEntry()->isEnumValueRejected(enum_value->name())) maxter@341: s << INDENT << QString("alias %1.%2 %2;").arg(d_enum->name()).arg(enum_value->name()) << endl; mandel@1: } mandel@1: s << endl; mandel@1: } mandel@1: maxter@341: void DGenerator::writeEnum(QTextStream &s, const AbstractMetaEnum *d_enum, bool withAliases) mandel@1: { mandel@1: if (m_doc_parser) { mandel@1: s << m_doc_parser->documentation(d_enum); mandel@1: } mandel@1: mandel@1: /* qtd mandel@1: mandel@1: if (d_enum->typeEntry()->forceInteger()) { mandel@1: writeIntegerEnum(s, d_enum); mandel@1: return; mandel@1: } mandel@1: mandel@1: // Check if enums in QObjects are declared in the meta object. If not mandel@1: if ( (d_enum->enclosingClass()->isQObject() || d_enum->enclosingClass()->isQtNamespace()) mandel@1: && !d_enum->hasQEnumsDeclaration()) { mandel@1: s << " @QtBlockedEnum" << endl; mandel@1: } mandel@1: */ mandel@1: // Generates Java 1.5 type enums maxter@341: s << INDENT << "public enum " << d_enum->name() << " {" << endl; mandel@1: const AbstractMetaEnumValueList &values = d_enum->values(); mandel@1: EnumTypeEntry *entry = d_enum->typeEntry(); mandel@1: maxter@341: mandel@1: for (int i=0; itypeEntry()->isEnumValueRejected(enum_value->name())) mandel@1: continue; mandel@1: mandel@1: if (m_doc_parser) mandel@1: s << m_doc_parser->documentation(enum_value); mandel@1: maxter@341: s << INDENT << enum_value->name() << " = " << enum_value->value(); mandel@1: mandel@1: if (i != values.size() - 1) { mandel@1: AbstractMetaEnumValue *next_value = values.at(i+1); // qtd mandel@1: if (!(d_enum->typeEntry()->isEnumValueRejected(next_value->name()) && i == values.size() - 2)) // qtd mandel@1: s << "," << endl; mandel@1: } mandel@1: } mandel@1: /* qtd mandel@1: if (entry->isExtensible()) mandel@1: s << " CustomEnum = 0"; mandel@1: */ mandel@1: s << endl << INDENT << "}" << endl << endl; // qtd mandel@1: mandel@1: mandel@1: /* qtd s << ";" << endl << endl; mandel@1: mandel@1: s << " " << d_enum->name() << "(int value) { this.value = value; }" << endl mandel@1: << " public int value() { return value; }" << endl mandel@1: << endl; mandel@1: mandel@1: // Write out the createQFlags() function if its a QFlags enum mandel@1: if (entry->flags()) { mandel@1: FlagsTypeEntry *flags_entry = entry->flags(); mandel@1: s << " public static " << flags_entry->targetLangName() << " createQFlags(" mandel@1: << entry->targetLangName() << " ... values) {" << endl mandel@1: << " return new " << flags_entry->targetLangName() << "(values);" << endl mandel@1: << " }" << endl; mandel@1: } mandel@1: mandel@1: // The resolve functions. The public one that returns the right mandel@1: // type and an internal one that has a generic signature. Makes it mandel@1: // easier to find the right one from JNI. mandel@1: s << " public static " << d_enum->name() << " resolve(int value) {" << endl mandel@1: << " return (" << d_enum->name() << ") resolve_internal(value);" << endl mandel@1: << " }" << endl mandel@1: << " private static Object resolve_internal(int value) {" << endl mandel@1: << " switch (value) {" << endl; mandel@1: mandel@1: for (int i=0; itypeEntry()->isEnumValueRejected(e->name())) mandel@1: continue; mandel@1: mandel@1: s << " case " << e->value() << ": return " << e->name() << ";" << endl; mandel@1: } mandel@1: mandel@1: s << " }" << endl; mandel@1: mandel@1: if (entry->isExtensible()) { mandel@1: s << " if (enumCache == null)" << endl mandel@1: << " enumCache = new java.util.HashMapname() mandel@1: << ">();" << endl mandel@1: << " " << d_enum->name() << " e = enumCache.get(value);" << endl mandel@1: << " if (e == null) {" << endl mandel@1: << " e = (" << d_enum->name() << ") qt.GeneratorUtilities.createExtendedEnum(" mandel@1: << "value, CustomEnum.ordinal(), " << d_enum->name() << ".class, CustomEnum.name());" mandel@1: << endl mandel@1: << " enumCache.put(value, e);" << endl mandel@1: << " }" << endl mandel@1: << " return e;" << endl; mandel@1: } else { mandel@1: s << " throw new qt.QNoSuchEnumValueException(value);" << endl; mandel@1: } mandel@1: mandel@1: mandel@1: s << " }" << endl; mandel@1: mandel@1: s << " private final int value;" << endl mandel@1: << endl; mandel@1: if (entry->isExtensible()) { mandel@1: s << " private static java.util.HashMapname() mandel@1: << "> enumCache;"; mandel@1: } mandel@1: s << " }" << endl; mandel@1: */ mandel@1: // Write out the QFlags if present... mandel@1: /* FlagsTypeEntry *flags_entry = entry->flags(); mandel@1: if (flags_entry) { mandel@1: QString flagsName = flags_entry->targetLangName(); mandel@1: s << INDENT << "alias QFlags!(" << d_enum->name() << ") " << flagsName << ";" << endl << endl; mandel@1: }*/ maxter@341: maxter@341: if (withAliases) maxter@341: writeEnumAliases(s, d_enum); mandel@1: } mandel@1: mandel@1: void DGenerator::writePrivateNativeFunction(QTextStream &s, const AbstractMetaFunction *d_function) mandel@1: { mandel@1: int exclude_attributes = AbstractMetaAttributes::Public | AbstractMetaAttributes::Protected; mandel@1: int include_attributes = 0; mandel@1: mandel@1: if (d_function->isEmptyFunction()) mandel@1: exclude_attributes |= AbstractMetaAttributes::Native; mandel@1: else mandel@1: include_attributes |= AbstractMetaAttributes::Native; mandel@1: mandel@1: // if (!d_function->isConstructor()) mandel@1: // include_attributes |= AbstractMetaAttributes::Static; mandel@1: mandel@1: writeFunctionAttributes(s, d_function, include_attributes, exclude_attributes, mandel@1: EnumAsInts | ExternC mandel@1: | (d_function->isEmptyFunction() mandel@1: || d_function->isNormal() mandel@1: || d_function->isSignal() ? 0 : SkipReturnType)); mandel@1: mandel@1: if (d_function->isConstructor()) mandel@1: s << "void* "; mandel@1: mandel@1: mandel@1: s << d_function->marshalledName(); mandel@1: /* qtd mandel@1: s << "("; mandel@1: mandel@1: AbstractMetaArgumentList arguments = d_function->arguments(); mandel@1: mandel@1: if (!d_function->isStatic() && !d_function->isConstructor()) mandel@1: s << "void *__this__nativeId"; mandel@1: for (int i=0; iargumentRemoved(i+1)) { mandel@1: if (i > 0 || (!d_function->isStatic() && !d_function->isConstructor())) mandel@1: s << ", "; mandel@1: mandel@1: if (!arg->type()->hasNativeId()) mandel@1: writeArgument(s, d_function, arg, EnumAsInts); mandel@1: else mandel@1: s << "void *" << arg->argumentName(); mandel@1: } mandel@1: } mandel@1: s << ")"; mandel@1: */ mandel@1: mandel@1: CppImplGenerator::writeFinalFunctionArguments(s, d_function, true); // qtd mandel@1: mandel@1: // Make sure people don't call the private functions eldar@33: // qtd remember name QNoImplementationException mandel@1: if (d_function->isEmptyFunction()) { mandel@1: s << endl mandel@1: << INDENT << "{" << endl eldar@33: << INDENT << " throw new Exception(\"No Implementation Exception\");" << endl mandel@1: << INDENT << "}" << endl << endl; mandel@1: } else { mandel@1: s << ";" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: static QString function_call_for_ownership(TypeSystem::Ownership owner) spambox@342: { mandel@1: if (owner == TypeSystem::CppOwnership) { maxter@253: return "__setFlags(QtdObjectFlags.nativeOwnership, true)"; mandel@1: } else /* qtd 2 if (owner == TypeSystem::TargetLangOwnership) */ { maxter@253: return "__setFlags(QtdObjectFlags.nativeOwnership, false)"; mandel@1: }/* else if (owner == TypeSystem::DefaultOwnership) { mandel@1: return "__no_real_delete = false"; mandel@1: mandel@1: } else { mandel@1: Q_ASSERT(false); mandel@1: return "bogus()"; mandel@1: }*/ mandel@1: } mandel@1: mandel@1: void DGenerator::writeOwnershipForContainer(QTextStream &s, TypeSystem::Ownership owner, mandel@1: AbstractMetaType *type, const QString &arg_name) mandel@1: { mandel@1: Q_ASSERT(type->isContainer()); mandel@1: mandel@1: s << INDENT << "for (" << type->instantiations().at(0)->fullName() << " i : " mandel@1: << arg_name << ")" << endl mandel@1: << INDENT << " if (i != null) i." << function_call_for_ownership(owner) << ";" << endl; mandel@1: mandel@1: } mandel@1: mandel@1: void DGenerator::writeOwnershipForContainer(QTextStream &s, TypeSystem::Ownership owner, mandel@1: AbstractMetaArgument *arg) mandel@1: { mandel@1: writeOwnershipForContainer(s, owner, arg->type(), arg->argumentName()); mandel@1: } mandel@1: mandel@1: static FunctionModificationList get_function_modifications_for_class_hierarchy(const AbstractMetaFunction *d_function) mandel@1: { mandel@1: FunctionModificationList mods; mandel@1: const AbstractMetaClass *cls = d_function->implementingClass(); mandel@1: while (cls != 0) { mandel@1: mods += d_function->modifications(cls); mandel@1: mandel@1: if (cls == cls->baseClass()) mandel@1: break; mandel@1: cls = cls->baseClass(); mandel@1: } mandel@1: return mods; mandel@1: } mandel@1: mandel@1: void DGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaFunction *d_function, mandel@1: CodeSnip::Position position) mandel@1: { mandel@1: FunctionModificationList mods = get_function_modifications_for_class_hierarchy(d_function); mandel@1: foreach (FunctionModification mod, mods) { mandel@1: if (mod.snips.count() <= 0) mandel@1: continue ; mandel@1: mandel@1: foreach (CodeSnip snip, mod.snips) { mandel@1: if (snip.position != position) mandel@1: continue ; mandel@1: mandel@1: if (snip.language != TypeSystem::TargetLangCode) mandel@1: continue ; mandel@1: mandel@1: QString code; mandel@1: QTextStream tmpStream(&code); mandel@1: snip.formattedCode(tmpStream, INDENT); mandel@1: ArgumentMap map = snip.argumentMap; mandel@1: ArgumentMap::iterator it = map.begin(); mandel@1: for (;it!=map.end();++it) { mandel@1: int pos = it.key() - 1; mandel@1: QString meta_name = it.value(); mandel@1: mandel@1: if (pos >= 0 && pos < d_function->arguments().count()) { mandel@1: code = code.replace(meta_name, d_function->arguments().at(pos)->argumentName()); mandel@1: } else { mandel@1: QString debug = QString("argument map specifies invalid argument index %1" mandel@1: "for function '%2'") mandel@1: .arg(pos + 1).arg(d_function->name()); mandel@1: ReportHandler::warning(debug); mandel@1: } mandel@1: mandel@1: } mandel@1: s << code << endl; mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: void DGenerator::writeJavaCallThroughContents(QTextStream &s, const AbstractMetaFunction *d_function, uint attributes) mandel@1: { mandel@1: Q_UNUSED(attributes); mandel@1: writeInjectedCode(s, d_function, CodeSnip::Beginning); mandel@1: /* qtd mandel@1: if (d_function->implementingClass()->isQObject() mandel@1: && !d_function->isStatic() mandel@1: && !d_function->isConstructor() mandel@1: && d_function->name() != QLatin1String("thread") mandel@1: && d_function->name() != QLatin1String("disposeLater")) { mandel@1: s << INDENT << "qt.GeneratorUtilities.threadCheck(this);" << endl; mandel@1: } mandel@1: */ mandel@1: AbstractMetaArgumentList arguments = d_function->arguments(); mandel@1: mandel@1: if (!d_function->isConstructor()) { mandel@1: TypeSystem::Ownership owner = d_function->ownership(d_function->implementingClass(), TypeSystem::TargetLangCode, -1); mandel@1: if (owner != TypeSystem::InvalidOwnership) mandel@1: s << INDENT << "this." << function_call_for_ownership(owner) << ";" << endl; mandel@1: } mandel@1: mandel@1: for (int i=0; iargumentRemoved(i+1)) { mandel@1: TypeSystem::Ownership owner = d_function->ownership(d_function->implementingClass(), TypeSystem::TargetLangCode, i+1); mandel@1: if (owner != TypeSystem::InvalidOwnership) { eldar@298: QString empty_condition = " !is null"; eldar@298: if (arg->type()->isContainer()) eldar@298: empty_condition = ".length != 0"; eldar@298: s << INDENT << "if (" << arg->argumentName() << empty_condition << ") {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: if (arg->type()->isContainer()) mandel@1: ;// qtd2 writeOwnershipForContainer(s, owner, arg); mandel@1: else mandel@1: s << INDENT << arg->argumentName() << "." << function_call_for_ownership(owner) << ";" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: } mandel@1: /* mandel@1: if (type->isArray()) { mandel@1: s << INDENT << "if (" << arg->argumentName() << ".length != " << type->arrayElementCount() << ")" << endl mandel@1: << INDENT << " " << "throw new IllegalArgumentException(\"Wrong number of elements in array. Found: \" + " mandel@1: << arg->argumentName() << ".length + \", expected: " << type->arrayElementCount() << "\");" mandel@1: << endl << endl; mandel@1: } mandel@1: mandel@1: if (type->isEnum()) { mandel@1: EnumTypeEntry *et = (EnumTypeEntry *) type->typeEntry(); mandel@1: if (et->forceInteger()) { mandel@1: if (!et->lowerBound().isEmpty()) { mandel@1: s << INDENT << "if (" << arg->argumentName() << " < " << et->lowerBound() << ")" << endl mandel@1: << INDENT << " throw new IllegalArgumentException(\"Argument " << arg->argumentName() mandel@1: << " is less than lowerbound " << et->lowerBound() << "\");" << endl; mandel@1: } mandel@1: if (!et->upperBound().isEmpty()) { mandel@1: s << INDENT << "if (" << arg->argumentName() << " > " << et->upperBound() << ")" << endl mandel@1: << INDENT << " throw new IllegalArgumentException(\"Argument " << arg->argumentName() mandel@1: << " is greated than upperbound " << et->upperBound() << "\");" << endl; mandel@1: } mandel@1: } mandel@1: } mandel@1: */ mandel@1: } mandel@1: } mandel@1: mandel@1: /* qtd2 mandel@1: if (!d_function->isConstructor() && !d_function->isStatic()) { mandel@1: s << INDENT << "if (nativeId() == 0)" << endl mandel@1: << INDENT << " throw new QNoNativeResourcesException(\"Function call on incomplete object of type: \" +getClass().getName());" << endl; mandel@1: } mandel@1: */ mandel@1: for (int i=0; inullPointersDisabled(d_function->implementingClass(), i + 1)) { mandel@1: s << INDENT << "/*if (" << arguments.at(i)->argumentName() << " is null)" << endl mandel@1: << INDENT << " throw new NullPointerException(\"Argument '" << arguments.at(i)->argumentName() << "': null not expected.\"); */" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: QList referenceCounts; mandel@1: for (int i=0; ireferenceCounts(d_function->implementingClass(), mandel@1: i == 0 ? -1 : i); mandel@1: mandel@1: foreach (ReferenceCount refCount, referenceCounts) eldar@298: writeReferenceCount(s, refCount, i == 0 ? "this" : arguments.at(i-1)->argumentName(), arguments.at(i-1)->type()); mandel@1: } mandel@1: mandel@1: referenceCounts = d_function->referenceCounts(d_function->implementingClass(), 0); mandel@1: AbstractMetaType *return_type = d_function->type(); mandel@1: QString new_return_type = QString(d_function->typeReplaced(0)).replace('$', '.'); mandel@1: bool has_return_type = new_return_type != "void" mandel@1: && (!new_return_type.isEmpty() || return_type != 0); mandel@1: // qtd TypeSystem::Ownership owner = d_function->ownership(d_function->implementingClass(), TypeSystem::TargetLangCode, 0); mandel@1: mandel@1: bool has_code_injections_at_the_end = false; mandel@1: FunctionModificationList mods = get_function_modifications_for_class_hierarchy(d_function); mandel@1: foreach (FunctionModification mod, mods) { mandel@1: foreach (CodeSnip snip, mod.snips) { mandel@1: if (snip.position == CodeSnip::End && snip.language == TypeSystem::TargetLangCode) { mandel@1: has_code_injections_at_the_end = true; mandel@1: break; mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: // bool needs_return_variable = has_return_type mandel@1: // && (owner != TypeSystem::InvalidOwnership || referenceCounts.size() > 0 || has_code_injections_at_the_end); mandel@1: eldar@33: if(return_type) { // qtd eldar@33: if (return_type->isTargetLangString()) mandel@1: s << INDENT << "string res;" << endl; mandel@1: eldar@33: if(return_type->name() == "QModelIndex") mandel@1: s << INDENT << "QModelIndex res;" << endl; eldar@81: else if (return_type->typeEntry()->isStructInD()) eldar@81: s << INDENT << return_type->name() << " res;" << endl; mandel@1: eldar@33: if(return_type->isContainer()) eldar@297: { eldar@298: const ContainerTypeEntry *type = eldar@298: static_cast(return_type->typeEntry()); eldar@298: if(type->isQList()) // QList is a native type now eldar@297: s << INDENT << "auto res = " << this->translateType(d_function->type(), d_function->ownerClass(), NoOption) << ".opCall();" << endl; eldar@297: else eldar@297: s << INDENT << this->translateType(d_function->type(), d_function->ownerClass(), NoOption) << " res;" << endl; eldar@297: } mandel@1: } mandel@1: eldar@130: // returning string or a struct eldar@81: bool return_in_arg = return_type && (return_type->isTargetLangString() || eldar@81: return_type->name() == "QModelIndex" || eldar@81: return_type->isContainer() || eldar@81: return_type->typeEntry()->isStructInD()); eldar@81: eldar@130: // bool flag showing if we return value immediately, without any conversions eldar@130: // which is commpon for primitive types, initially set up to return_in_arg, because in that case eldar@130: // we don't need type conversions eldar@130: bool returnImmediately = return_in_arg; eldar@81: mandel@1: s << INDENT; mandel@1: if ( (has_return_type && d_function->argumentReplaced(0).isEmpty() ) || d_function->isConstructor()) { //qtd mandel@1: if(d_function->type() && d_function->type()->isQObject()) { // qtd maxter@253: s << "void *ret = "; eldar@81: } else if(return_in_arg) // qtd mandel@1: ; eldar@81: else if (d_function->isConstructor()) { // qtd maxter@253: s << "void* ret = "; eldar@81: } else if (return_type && return_type->isValue() && !return_type->typeEntry()->isStructInD()) { maxter@253: s << "void* ret = "; eldar@33: } else if (return_type && return_type->isVariant()) { maxter@253: s << "void* ret = "; eldar@33: } else if (return_type && ( return_type->isObject() || eldar@33: (return_type->isNativePointer() && return_type->typeEntry()->isValue()) || eldar@33: return_type->typeEntry()->isInterface()) ) { maxter@253: s << "void* ret = "; eldar@33: } else if (return_type && return_type->isArray()) { maxter@253: s << return_type->arrayElementType()->name() + "* ret = "; mandel@1: } else { eldar@130: returnImmediately = true; mandel@1: s << "return "; mandel@1: } mandel@1: mandel@1: if (return_type && return_type->isTargetLangEnum()) { mandel@1: s << "cast(" << return_type->typeEntry()->qualifiedTargetLangName() << ") "; mandel@1: }/* qtd2 flags else if (return_type && return_type->isTargetLangFlags()) { mandel@1: s << "new " << return_type->typeEntry()->qualifiedTargetLangName() << "("; mandel@1: }*/ mandel@1: } mandel@1: mandel@1: bool useJumpTable = d_function->jumpTableId() != -1; mandel@1: if (useJumpTable) { mandel@1: // The native function returns the correct type, we only have mandel@1: // java.lang.Object so we may have to cast... mandel@1: QString signature = JumpTablePreprocessor::signature(d_function); mandel@1: mandel@1: // printf("return: %s::%s return=%p, replace-value=%s, replace-type=%s signature: %s\n", mandel@1: // qPrintable(d_function->ownerClass()->name()), mandel@1: // qPrintable(d_function->signature()), mandel@1: // return_type, mandel@1: // qPrintable(d_function->argumentReplaced(0)), mandel@1: // qPrintable(new_return_type), mandel@1: // qPrintable(signature)); mandel@1: mandel@1: if (has_return_type && signature.at(0) == 'L') { mandel@1: if (new_return_type.length() > 0) { mandel@1: // printf(" ---> replace-type: %s\n", qPrintable(new_return_type)); mandel@1: s << "(" << new_return_type << ") "; mandel@1: } else if (d_function->argumentReplaced(0).isEmpty()) { mandel@1: // printf(" ---> replace-value\n"); mandel@1: s << "(" << translateType(return_type, d_function->implementingClass()) << ") "; mandel@1: } mandel@1: } mandel@1: mandel@1: s << "JTbl." << JumpTablePreprocessor::signature(d_function) << "(" mandel@1: << d_function->jumpTableId() << ", "; mandel@1: mandel@1: // Constructors and static functions don't have native id, but mandel@1: // the functions expect them anyway, hence add '0'. Normal mandel@1: // functions get their native ids added just below... mandel@1: if (d_function->isConstructor() || d_function->isStatic()) mandel@1: s << "0, "; mandel@1: mandel@1: } else { mandel@1: /* qtd if (attributes & SuperCall) { mandel@1: s << "super."; mandel@1: }*/ mandel@1: s << d_function->marshalledName() << "("; mandel@1: } mandel@1: maxter@355: bool arg_written = false; maxter@355: eldar@188: if (!d_function->isConstructor() && !d_function->isStatic()) { maxter@355: s << "(cast(" << d_function->ownerClass()->name() << ")this).__nativeId"; maxter@355: arg_written = true; eldar@188: } mandel@1: mandel@1: if (d_function->isConstructor() && maxter@355: ( d_function->ownerClass()->isPolymorphic() mandel@1: || d_function->implementingClass()->typeEntry()->isObject() ) ) { // qtd maxter@355: if (arg_written) mandel@1: s << ", "; maxter@355: s << "cast(void*) this"; maxter@355: arg_written = true; mandel@1: } mandel@1: maxter@355: if(return_in_arg) { maxter@355: if (arg_written) mandel@1: s << ", "; mandel@1: s << "&res"; maxter@355: arg_written = true; mandel@1: } mandel@1: mandel@1: for (int i=0; itype(); mandel@1: const TypeEntry *te = type->typeEntry(); mandel@1: mandel@1: if (!d_function->argumentRemoved(i+1)) { maxter@355: if (arg_written) mandel@1: s << ", "; maxter@355: arg_written = true; mandel@1: mandel@1: // qtd mandel@1: QString modified_type = d_function->typeReplaced(arg->argumentIndex() + 1); mandel@1: if (!modified_type.isEmpty()) mandel@1: modified_type = modified_type.replace('$', '.'); mandel@1: mandel@1: QString arg_name = arg->argumentName(); mandel@1: mandel@1: if (type->isVariant()) maxter@253: s << arg_name << " is null ? null : " << arg_name << ".__nativeId"; mandel@1: else if (te->designatedInterface()) mandel@1: s << arg_name << " is null ? null : " << arg_name << ".__ptr_" << te->designatedInterface()->name(); mandel@1: else if (modified_type == "string" /* && type->fullName() == "char" */) { mandel@1: s << "toStringz(" << arg_name << ")"; eldar@81: } else if (type->isArray()) { eldar@33: s << arg_name << ".ptr"; eldar@81: } else if(type->isContainer()) { mandel@1: const ContainerTypeEntry *cte = mandel@1: static_cast(te); mandel@1: if(isLinearContainer(cte)) eldar@298: s << QString("&%1").arg(arg_name); eldar@81: } else if (type->typeEntry()->qualifiedCppName() == "QChar") { eldar@33: s << arg_name; eldar@81: } else if (type->isTargetLangString() || (te && te->qualifiedCppName() == "QString")) { eldar@33: s << arg_name; eldar@81: } else if (type->isTargetLangEnum() || type->isTargetLangFlags()) { mandel@1: s << arg_name; mandel@1: // qtd s << arg->argumentName() << ".value()"; mandel@1: } else if (!type->hasNativeId() && !(te->isValue() && type->isNativePointer())) { // qtd2 hack for QStyleOption not being a nativeId based for some reason mandel@1: s << arg_name; mandel@1: } else if (te->isStructInD()) { mandel@1: s << arg_name; mandel@1: } else { mandel@1: bool force_abstract = te->isComplex() && (((static_cast(te))->typeFlags() & ComplexTypeEntry::ForceAbstract) != 0); mandel@1: if (!force_abstract) { mandel@1: s << arg_name << " is null ? null : "; mandel@1: } // else if (value type is abstract) then we will get a null pointer exception, which is all right mandel@1: eldar@188: if(dVersion == 2 && type->isConstant()) maxter@253: s << "(cast(" << type->name() << ")" << arg_name << ").__nativeId"; eldar@188: else maxter@253: s << arg_name << ".__nativeId"; mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: if (useJumpTable) { maxter@355: if (arg_written) mandel@1: s << ", "; mandel@1: mandel@1: if (d_function->isStatic()) mandel@1: s << "null"; mandel@1: else mandel@1: s << "this"; maxter@355: arg_written = true; mandel@1: } mandel@1: mandel@1: s << ")"; mandel@1: mandel@1: if ( !d_function->argumentReplaced(0).isEmpty() ) { mandel@1: s << ";" << endl; mandel@1: s << INDENT << "return " << d_function->argumentReplaced(0) << ";" << endl; mandel@1: return; mandel@1: } mandel@1: mandel@1: // qtd2 if (return_type && (/* qtdreturn_type->isTargetLangEnum() ||*/ return_type->isTargetLangFlags())) mandel@1: // s << ")"; mandel@1: mandel@1: s << ";" << endl; mandel@1: mandel@1: /* qtd2 mandel@1: if (needs_return_variable) { mandel@1: if (owner != TypeSystem::InvalidOwnership) { maxter@253: s << INDENT << "if (ret != null) {" << endl; mandel@1: if (return_type->isContainer()) maxter@253: writeOwnershipForContainer(s, owner, return_type, "ret"); mandel@1: else maxter@253: s << INDENT << " ret." << function_call_for_ownership(owner) << ";" << endl; mandel@1: s << INDENT << "}" << endl; mandel@1: } maxter@253: s << INDENT << "return ret;" << endl; mandel@1: } mandel@1: */ mandel@1: if (d_function->isConstructor()) { mandel@1: TypeSystem::Ownership owner = d_function->ownership(d_function->implementingClass(), TypeSystem::TargetLangCode, -1); mandel@1: if (owner != TypeSystem::InvalidOwnership && d_function->isConstructor()) mandel@1: s << INDENT << "this." << function_call_for_ownership(owner) << ";" << endl; mandel@1: } mandel@1: maxter@341: // return value marshalling eldar@130: if(return_type) { eldar@295: if (!returnImmediately) { eldar@130: s << INDENT; eldar@130: QString modified_type = d_function->typeReplaced(0); eldar@130: if (modified_type.isEmpty()) eldar@130: s << translateType(d_function->type(), d_function->implementingClass()); eldar@130: else eldar@130: s << modified_type.replace('$', '.'); eldar@130: s << " __d_return_value = "; eldar@130: } eldar@130: eldar@130: if ( ( has_return_type && d_function->argumentReplaced(0).isEmpty() )) // qtd maxter@253: { eldar@130: if(return_type->isQObject()) maxter@253: s << return_type->name() << ".__getObject(ret);" << endl; maxter@253: } eldar@130: eldar@130: if (return_type->isValue() && !return_type->typeEntry()->isStructInD()) maxter@253: s << "new " << return_type->name() << "(ret);" << endl; eldar@130: eldar@130: if (return_type->isVariant()) maxter@253: s << "new QVariant(ret);" << endl; eldar@130: eldar@130: if (return_type->isNativePointer() && return_type->typeEntry()->isValue()) maxter@253: s << "new " << return_type->name() << "(ret, QtdObjectFlags.nativeOwnership);" << endl; eldar@130: eldar@130: if (return_type->isObject()) { eldar@295: s << "qtd_" << return_type->name() << "_from_ptr(ret);" << endl << endl; eldar@130: } eldar@130: eldar@130: if (return_type->isArray()) { maxter@253: s << "ret[0 .. " << return_type->arrayElementCount() << "];" << endl; eldar@130: } eldar@130: eldar@130: foreach (ReferenceCount referenceCount, referenceCounts) { eldar@298: writeReferenceCount(s, referenceCount, "__d_return_value", return_type); eldar@130: } eldar@130: eldar@295: if (!returnImmediately) eldar@130: s << INDENT << "return __d_return_value;" << endl; eldar@130: } eldar@130: writeInjectedCode(s, d_function, CodeSnip::End); eldar@130: mandel@1: if(return_in_arg) // qtd mandel@1: s << INDENT << "return res;" << endl; mandel@1: } mandel@1: mandel@1: void DGenerator::retrieveModifications(const AbstractMetaFunction *d_function, mandel@1: const AbstractMetaClass *d_class, mandel@1: uint *exclude_attributes, mandel@1: uint *include_attributes) const mandel@1: { mandel@1: FunctionModificationList mods = d_function->modifications(d_class); mandel@1: // printf("name: %s has %d mods\n", qPrintable(d_function->signature()), mods.size()); mandel@1: foreach (FunctionModification mod, mods) { mandel@1: if (mod.isAccessModifier()) { mandel@1: // printf(" -> access mod to %x\n", mod.modifiers); mandel@1: *exclude_attributes |= AbstractMetaAttributes::Public mandel@1: | AbstractMetaAttributes::Protected mandel@1: | AbstractMetaAttributes::Private mandel@1: | AbstractMetaAttributes::Friendly; mandel@1: mandel@1: if (mod.isPublic()) mandel@1: *include_attributes |= AbstractMetaAttributes::Public; mandel@1: else if (mod.isProtected()) mandel@1: *include_attributes |= AbstractMetaAttributes::Protected; mandel@1: else if (mod.isPrivate()) mandel@1: *include_attributes |= AbstractMetaAttributes::Private; mandel@1: else if (mod.isFriendly()) mandel@1: *include_attributes |= AbstractMetaAttributes::Friendly; mandel@1: } mandel@1: mandel@1: if (mod.isFinal()) { mandel@1: *include_attributes |= AbstractMetaAttributes::FinalInTargetLang; mandel@1: } else if (mod.isNonFinal()) { mandel@1: *exclude_attributes |= AbstractMetaAttributes::FinalInTargetLang; mandel@1: } mandel@1: } mandel@1: mandel@1: *exclude_attributes &= ~(*include_attributes); mandel@1: } mandel@1: mandel@1: QString DGenerator::functionSignature(const AbstractMetaFunction *d_function, mandel@1: uint included_attributes, uint excluded_attributes, mandel@1: Option option, mandel@1: int arg_count) mandel@1: { mandel@1: AbstractMetaArgumentList arguments = d_function->arguments(); mandel@1: int argument_count = arg_count < 0 ? arguments.size() : arg_count; mandel@1: mandel@1: QString result; mandel@1: QTextStream s(&result); mandel@1: QString functionName = d_function->isConstructor() ? "this" : d_function->name(); // qtd mandel@1: // The actual function mandel@1: if (!(d_function->isEmptyFunction() || d_function->isNormal() || d_function->isSignal())) mandel@1: option = Option(option | SkipReturnType); mandel@1: writeFunctionAttributes(s, d_function, included_attributes, excluded_attributes, option); eldar@288: mandel@1: s << functionName << "("; mandel@1: writeFunctionArguments(s, d_function, argument_count, option); mandel@1: s << ")"; mandel@1: eldar@295: if(d_function->isConstant()) eldar@295: s << " const"; eldar@295: mandel@1: return result; mandel@1: } mandel@1: mandel@1: void DGenerator::setupForFunction(const AbstractMetaFunction *d_function, mandel@1: uint *included_attributes, mandel@1: uint *excluded_attributes) const mandel@1: { mandel@1: *excluded_attributes |= d_function->ownerClass()->isInterface() || d_function->isConstructor() mandel@1: ? AbstractMetaAttributes::Native | AbstractMetaAttributes::Final mandel@1: : 0; mandel@1: if (d_function->ownerClass()->isInterface()) mandel@1: *excluded_attributes |= AbstractMetaAttributes::Abstract; mandel@1: if (d_function->needsCallThrough()) mandel@1: *excluded_attributes |= AbstractMetaAttributes::Native; mandel@1: mandel@1: const AbstractMetaClass *d_class = d_function->ownerClass(); mandel@1: retrieveModifications(d_function, d_class, excluded_attributes, included_attributes); mandel@1: } mandel@1: mandel@1: void DGenerator::writeReferenceCount(QTextStream &s, const ReferenceCount &refCount, eldar@298: const QString &argumentName, AbstractMetaType *argumentType) mandel@1: { mandel@1: if (refCount.action == ReferenceCount::Ignore) mandel@1: return; mandel@1: mandel@1: QString refCountVariableName = refCount.variableName; mandel@1: if (!refCount.declareVariable.isEmpty() && refCount.action != ReferenceCount::Set) { mandel@1: s << INDENT << "auto __rcTmp = " << refCountVariableName << ";" << endl; mandel@1: refCountVariableName = "__rcTmp"; mandel@1: } eldar@298: QString empty_condition = " !is null"; eldar@298: if (argumentType && argumentType->isContainer()) eldar@298: // if (((const ContainerTypeEntry *)argumentType->typeEntry())->isQList()) eldar@298: empty_condition = ".length != 0"; mandel@1: mandel@1: if (refCount.action != ReferenceCount::Set) { eldar@298: s << INDENT << "if (" << argumentName << empty_condition; mandel@1: mandel@1: if (!refCount.conditional.isEmpty()) mandel@1: s << " && " << refCount.conditional; mandel@1: mandel@1: s << ") {" << endl; mandel@1: } else { mandel@1: if (!refCount.conditional.isEmpty()) mandel@1: s << INDENT << "if (" << refCount.conditional << ") "; mandel@1: s << INDENT << "{" << endl; mandel@1: } mandel@1: mandel@1: { mandel@1: Indentation indent(INDENT); eldar@298: QString summand = argumentName; mandel@1: switch (refCount.action) { mandel@1: case ReferenceCount::Add: eldar@33: s << INDENT << refCountVariableName << " ~= cast(Object) " << argumentName << ";" << endl; eldar@33: break; mandel@1: case ReferenceCount::AddAll: eldar@298: if(isNativeContainer(argumentType)) eldar@298: summand = argumentName + ".toArray()"; eldar@298: s << INDENT << refCountVariableName << " ~= " << summand << ";" << endl; mandel@1: break; mandel@1: case ReferenceCount::Remove: mandel@1: s << INDENT << "remove(" << refCountVariableName eldar@33: << ", cast(Object) " << argumentName << ");" << endl; mandel@1: break; mandel@1: case ReferenceCount::Set: mandel@1: { mandel@1: if (refCount.declareVariable.isEmpty()) mandel@1: s << INDENT << refCount.variableName << " = cast(Object) " << argumentName << ";" << endl; mandel@1: else mandel@1: s << INDENT << refCountVariableName << " = cast(Object) " << argumentName << ";" << endl; mandel@1: } mandel@1: default: mandel@1: break; mandel@1: }; mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: } mandel@1: mandel@1: void DGenerator::writeFunction(QTextStream &s, const AbstractMetaFunction *d_function, mandel@1: uint included_attributes, uint excluded_attributes) mandel@1: { mandel@1: s << endl; mandel@1: mandel@1: if (d_function->isModifiedRemoved(TypeSystem::TargetLangCode)) mandel@1: return ; mandel@1: QString functionName = d_function->name(); mandel@1: setupForFunction(d_function, &included_attributes, &excluded_attributes); mandel@1: mandel@1: if (!d_function->ownerClass()->isInterface()) { mandel@1: // qtd2 writeEnumOverload(s, d_function, included_attributes, excluded_attributes); mandel@1: // qtd writeFunctionOverloads(s, d_function, included_attributes, excluded_attributes); mandel@1: } mandel@1: /* qtd mandel@1: static QRegExp regExp("^(insert|set|take|add|remove|install).*"); mandel@1: mandel@1: if (regExp.exactMatch(d_function->name())) { mandel@1: AbstractMetaArgumentList arguments = d_function->arguments(); mandel@1: mandel@1: const AbstractMetaClass *c = d_function->implementingClass(); mandel@1: bool hasObjectTypeArgument = false; mandel@1: foreach (AbstractMetaArgument *argument, arguments) { mandel@1: TypeSystem::Ownership d_ownership = d_function->ownership(c, TypeSystem::TargetLangCode, argument->argumentIndex()+1); mandel@1: TypeSystem::Ownership shell_ownership = d_function->ownership(c, TypeSystem::ShellCode, argument->argumentIndex()+1); mandel@1: mandel@1: if (argument->type()->typeEntry()->isObject() mandel@1: && d_ownership == TypeSystem::InvalidOwnership mandel@1: && shell_ownership == TypeSystem::InvalidOwnership) { mandel@1: hasObjectTypeArgument = true; mandel@1: break; mandel@1: } mandel@1: } mandel@1: mandel@1: if (hasObjectTypeArgument mandel@1: && !d_function->isAbstract() mandel@1: && d_function->referenceCounts(d_function->implementingClass()).size() == 0) { mandel@1: m_reference_count_candidate_functions.append(d_function); mandel@1: } mandel@1: } mandel@1: mandel@1: mandel@1: if (m_doc_parser) { mandel@1: QString signature = functionSignature(d_function, mandel@1: included_attributes | NoBlockedSlot, mandel@1: excluded_attributes); mandel@1: s << m_doc_parser->documentationForFunction(signature) << endl; mandel@1: } mandel@1: mandel@1: const QPropertySpec *spec = d_function->propertySpec(); mandel@1: if (spec && d_function->modifiedName() == d_function->originalName()) { mandel@1: if (d_function->isPropertyReader()) { mandel@1: s << " @qt.QtPropertyReader(name=\"" << spec->name() << "\")" << endl; mandel@1: if (!spec->designable().isEmpty()) mandel@1: s << " @qt.QtPropertyDesignable(\"" << spec->designable() << "\")" << endl; mandel@1: } else if (d_function->isPropertyWriter()) { mandel@1: s << " @qt.QtPropertyWriter(name=\"" << spec->name() << "\")" << endl; mandel@1: } else if (d_function->isPropertyResetter()) { mandel@1: s << " @qt.QtPropertyResetter(name=\"" << spec->name() << "\")" mandel@1: << endl; mandel@1: } mandel@1: } mandel@1: */ mandel@1: s << functionSignature(d_function, included_attributes, excluded_attributes); mandel@1: mandel@1: if (d_function->isConstructor()) { mandel@1: writeConstructorContents(s, d_function); mandel@1: } else if (d_function->needsCallThrough() || d_function->isStatic()) { // qtd mandel@1: if (d_function->isAbstract()) { mandel@1: s << ";" << endl; mandel@1: } else { mandel@1: s << " {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: writeJavaCallThroughContents(s, d_function); mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: } mandel@1: mandel@1: /* qtd mandel@1: if (d_function->jumpTableId() == -1) { mandel@1: writePrivateNativeFunction(s, d_function); mandel@1: } mandel@1: */ mandel@1: } else { mandel@1: s << ";" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: static void write_equals_parts(QTextStream &s, const AbstractMetaFunctionList &lst, char prefix, bool *first) { mandel@1: foreach (AbstractMetaFunction *f, lst) { mandel@1: AbstractMetaArgument *arg = f->arguments().at(0); mandel@1: QString type = f->typeReplaced(1); mandel@1: if (type.isEmpty()) mandel@1: type = arg->type()->typeEntry()->qualifiedTargetLangName(); mandel@1: s << INDENT << (*first ? "if" : "else if") << " (other instanceof " << type << ")" << endl mandel@1: << INDENT << " return "; mandel@1: if (prefix != 0) s << prefix; mandel@1: s << f->name() << "((" << type << ") other);" << endl; mandel@1: *first = false; mandel@1: } mandel@1: } mandel@1: mandel@1: static void write_compareto_parts(QTextStream &s, const AbstractMetaFunctionList &lst, int value, bool *first) { mandel@1: foreach (AbstractMetaFunction *f, lst) { mandel@1: AbstractMetaArgument *arg = f->arguments().at(0); mandel@1: QString type = f->typeReplaced(1); mandel@1: if (type.isEmpty()) mandel@1: type = arg->type()->typeEntry()->qualifiedTargetLangName(); mandel@1: s << INDENT << (*first ? "if" : "else if") << " (other instanceof " << type << ") {" << endl mandel@1: << INDENT << " if (" << f->name() << "((" << type << ") other)) return " << value << ";" << endl mandel@1: << INDENT << " else return " << -value << ";" << endl mandel@1: << INDENT << "}" << endl; mandel@1: *first = false; mandel@1: } mandel@1: s << INDENT << "throw new ClassCastException();" << endl; mandel@1: } mandel@1: mandel@1: bool DGenerator::isComparable(const AbstractMetaClass *cls) const mandel@1: { mandel@1: AbstractMetaFunctionList eq_functions = cls->equalsFunctions(); mandel@1: AbstractMetaFunctionList neq_functions = cls->notEqualsFunctions(); mandel@1: mandel@1: // Write the comparable functions mandel@1: AbstractMetaFunctionList ge_functions = cls->greaterThanFunctions(); mandel@1: AbstractMetaFunctionList geq_functions = cls->greaterThanEqFunctions(); mandel@1: AbstractMetaFunctionList le_functions = cls->lessThanFunctions(); mandel@1: AbstractMetaFunctionList leq_functions = cls->lessThanEqFunctions(); mandel@1: mandel@1: bool hasEquals = eq_functions.size() || neq_functions.size(); mandel@1: bool isComparable = hasEquals mandel@1: ? ge_functions.size() || geq_functions.size() || le_functions.size() || leq_functions.size() mandel@1: : geq_functions.size() == 1 && leq_functions.size() == 1; mandel@1: mandel@1: return isComparable; mandel@1: } mandel@1: mandel@1: mandel@1: void DGenerator::writeJavaLangObjectOverrideFunctions(QTextStream &s, mandel@1: const AbstractMetaClass *cls) mandel@1: { mandel@1: AbstractMetaFunctionList eq_functions = cls->equalsFunctions(); mandel@1: AbstractMetaFunctionList neq_functions = cls->notEqualsFunctions(); mandel@1: mandel@1: if (eq_functions.size() || neq_functions.size()) { mandel@1: s << endl mandel@1: << INDENT << "@SuppressWarnings(\"unchecked\")" << endl mandel@1: << INDENT << "@Override" << endl mandel@1: << INDENT << "public boolean equals(Object other) {" << endl; mandel@1: bool first = true; mandel@1: write_equals_parts(s, eq_functions, (char) 0, &first); mandel@1: write_equals_parts(s, neq_functions, '!', &first); mandel@1: s << INDENT << " return false;" << endl mandel@1: << INDENT << "}" << endl << endl; mandel@1: } mandel@1: mandel@1: // Write the comparable functions mandel@1: AbstractMetaFunctionList ge_functions = cls->greaterThanFunctions(); mandel@1: AbstractMetaFunctionList geq_functions = cls->greaterThanEqFunctions(); mandel@1: AbstractMetaFunctionList le_functions = cls->lessThanFunctions(); mandel@1: AbstractMetaFunctionList leq_functions = cls->lessThanEqFunctions(); mandel@1: mandel@1: bool hasEquals = eq_functions.size() || neq_functions.size(); mandel@1: bool comparable = isComparable(cls); mandel@1: if (comparable) { mandel@1: s << INDENT << "public int compareTo(Object other) {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: if (hasEquals) { mandel@1: s << INDENT << "if (equals(other)) return 0;" << endl; mandel@1: bool first = false; mandel@1: if (le_functions.size()) { mandel@1: write_compareto_parts(s, le_functions, -1, &first); mandel@1: } else if (ge_functions.size()) { mandel@1: write_compareto_parts(s, ge_functions, 1, &first); mandel@1: } else if (leq_functions.size()) { mandel@1: write_compareto_parts(s, leq_functions, -1, &first); mandel@1: } else if (geq_functions.size()) { mandel@1: write_compareto_parts(s, geq_functions, 1, &first); mandel@1: } mandel@1: mandel@1: } else if (le_functions.size() == 1) { mandel@1: QString className = cls->typeEntry()->qualifiedTargetLangName(); mandel@1: s << INDENT << "if (operator_less((" << className << ") other)) return -1;" << endl mandel@1: << INDENT << "else if (((" << className << ") other).operator_less(this)) return 1;" << endl mandel@1: << INDENT << "else return 0;" << endl; mandel@1: mandel@1: } else if (geq_functions.size() == 1 && leq_functions.size()) { mandel@1: QString className = cls->typeEntry()->qualifiedTargetLangName(); mandel@1: s << INDENT << "boolean less = operator_less_or_equal((" << className << ") other);" << endl mandel@1: << INDENT << "boolean greater = operator_greater_or_equal((" << className << ") other);" << endl mandel@1: << INDENT << "if (less && greater) return 0;" << endl mandel@1: << INDENT << "else if (less) return -1;" << endl mandel@1: << INDENT << "else return 1;" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: s << INDENT << "}" << endl; mandel@1: } mandel@1: mandel@1: mandel@1: if (cls->hasHashFunction()) { mandel@1: AbstractMetaFunctionList hashcode_functions = cls->queryFunctionsByName("hashCode"); mandel@1: bool found = false; mandel@1: foreach (const AbstractMetaFunction *function, hashcode_functions) { mandel@1: if (function->actualMinimumArgumentCount() == 0) { mandel@1: found = true; mandel@1: break; mandel@1: } mandel@1: } mandel@1: mandel@1: if (!found) { mandel@1: s << endl mandel@1: << INDENT << "@Override" << endl mandel@1: << INDENT << "public int hashCode() {" << endl mandel@1: << INDENT << " if (nativeId() == 0)" << endl mandel@1: << INDENT << " throw new QNoNativeResourcesException(\"Function call on incomplete object of type: \" +getClass().getName());" << endl mandel@1: << INDENT << " return __qt_hashCode(nativeId());" << endl mandel@1: << INDENT << "}" << endl mandel@1: << INDENT << "native int __qt_hashCode(long __this_nativeId);" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: // Qt has a standard toString() conversion in QVariant? mandel@1: QVariant::Type type = QVariant::nameToType(cls->qualifiedCppName().toLatin1()); mandel@1: if (QVariant(type).canConvert(QVariant::String) && !cls->hasToStringCapability()) { mandel@1: AbstractMetaFunctionList tostring_functions = cls->queryFunctionsByName("toString"); mandel@1: bool found = false; mandel@1: foreach (const AbstractMetaFunction *function, tostring_functions) { mandel@1: if (function->actualMinimumArgumentCount() == 0) { mandel@1: found = true; mandel@1: break; mandel@1: } mandel@1: } mandel@1: mandel@1: if (!found) { mandel@1: s << endl mandel@1: << INDENT << "@Override" << endl mandel@1: << INDENT << "public String toString() {" << endl mandel@1: << INDENT << " if (nativeId() == 0)" << endl mandel@1: << INDENT << " throw new QNoNativeResourcesException(\"Function call on incomplete object of type: \" +getClass().getName());" << endl mandel@1: << INDENT << " return __qt_toString(nativeId());" << endl mandel@1: << INDENT << "}" << endl mandel@1: << INDENT << "native String __qt_toString(long __this_nativeId);" << endl; mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: void DGenerator::writeEnumOverload(QTextStream &s, const AbstractMetaFunction *d_function, mandel@1: uint include_attributes, uint exclude_attributes) mandel@1: { mandel@1: AbstractMetaArgumentList arguments = d_function->arguments(); mandel@1: mandel@1: if ((d_function->implementingClass() != d_function->declaringClass()) mandel@1: || ((!d_function->isNormal() && !d_function->isConstructor()) || d_function->isEmptyFunction() || d_function->isAbstract())) { mandel@1: return ; mandel@1: } mandel@1: mandel@1: mandel@1: int option = 0; mandel@1: if (d_function->isConstructor()) mandel@1: option = Option(option | SkipReturnType); mandel@1: else mandel@1: include_attributes |= AbstractMetaAttributes::FinalInTargetLang; mandel@1: mandel@1: int generate_enum_overload = -1; mandel@1: for (int i=0; itype()->isTargetLangFlags() ? i : -1; mandel@1: mandel@1: if (generate_enum_overload >= 0) { mandel@1: if (m_doc_parser) { mandel@1: // steal documentation from main function mandel@1: QString signature = functionSignature(d_function, mandel@1: include_attributes | NoBlockedSlot, mandel@1: exclude_attributes); mandel@1: s << m_doc_parser->documentationForFunction(signature) << endl; mandel@1: } mandel@1: mandel@1: s << endl; mandel@1: mandel@1: writeFunctionAttributes(s, d_function, include_attributes, exclude_attributes, option); mandel@1: s << d_function->name() << "("; mandel@1: if (generate_enum_overload > 0) { mandel@1: writeFunctionArguments(s, d_function, generate_enum_overload); mandel@1: s << ", "; mandel@1: } mandel@1: mandel@1: // Write the ellipsis convenience argument mandel@1: AbstractMetaArgument *affected_arg = arguments.at(generate_enum_overload); mandel@1: EnumTypeEntry *originator = ((FlagsTypeEntry *)affected_arg->type()->typeEntry())->originator(); mandel@1: mandel@1: s << originator->javaPackage() << "." << originator->javaQualifier() << "." << originator->targetLangName() mandel@1: << " ... " << affected_arg->argumentName() << ") {" << endl; mandel@1: mandel@1: s << " "; mandel@1: QString new_return_type = d_function->typeReplaced(0); mandel@1: if (new_return_type != "void" && (!new_return_type.isEmpty() || d_function->type() != 0)) mandel@1: s << "return "; mandel@1: mandel@1: if (d_function->isConstructor()) { mandel@1: s << "this"; mandel@1: } else { mandel@1: if (d_function->isStatic()) mandel@1: s << d_function->implementingClass()->fullName() << "."; mandel@1: else mandel@1: s << "this."; mandel@1: s << d_function->name(); mandel@1: } mandel@1: mandel@1: s << "("; mandel@1: for (int i=0; iargumentName() << ", "; mandel@1: } mandel@1: s << "new " << affected_arg->type()->fullName() << "(" << affected_arg->argumentName() << "));" << endl mandel@1: << " }" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: void DGenerator::writeInstantiatedType(QTextStream &s, const AbstractMetaType *abstractMetaType) const mandel@1: { mandel@1: Q_ASSERT(abstractMetaType != 0); mandel@1: mandel@1: const TypeEntry *type = abstractMetaType->typeEntry(); mandel@1: s << type->qualifiedTargetLangName(); mandel@1: mandel@1: if (abstractMetaType->hasInstantiations()) { mandel@1: s << "<"; mandel@1: QList instantiations = abstractMetaType->instantiations(); mandel@1: for(int i=0; i 0) mandel@1: s << ", "; mandel@1: mandel@1: writeInstantiatedType(s, instantiations.at(i)); mandel@1: } mandel@1: s << ">"; mandel@1: } mandel@1: } mandel@1: mandel@1: void DGenerator::writeFunctionOverloads(QTextStream &s, const AbstractMetaFunction *d_function, mandel@1: uint include_attributes, uint exclude_attributes) mandel@1: { mandel@1: AbstractMetaArgumentList arguments = d_function->arguments(); mandel@1: int argument_count = arguments.size(); mandel@1: mandel@1: // We only create the overloads for the class that actually declares the function mandel@1: // unless this is an interface, in which case we create the overloads for all mandel@1: // classes that directly implement the interface. mandel@1: const AbstractMetaClass *decl_class = d_function->declaringClass(); mandel@1: if (decl_class->isInterface()) { mandel@1: AbstractMetaClassList interfaces = d_function->implementingClass()->interfaces(); mandel@1: foreach (AbstractMetaClass *iface, interfaces) { mandel@1: if (iface == decl_class) { mandel@1: decl_class = d_function->implementingClass(); mandel@1: break; mandel@1: } mandel@1: } mandel@1: } mandel@1: if (decl_class != d_function->implementingClass()) mandel@1: return; mandel@1: mandel@1: // Figure out how many functions we need to write out, mandel@1: // One extra for each default argument. mandel@1: int overload_count = 0; mandel@1: uint excluded_attributes = AbstractMetaAttributes::Abstract mandel@1: | AbstractMetaAttributes::Native mandel@1: | exclude_attributes; mandel@1: uint included_attributes = (d_function->isConstructor() ? 0 : AbstractMetaAttributes::Final) | include_attributes; mandel@1: mandel@1: for (int i=0; idefaultValueExpression().isEmpty() && !d_function->argumentRemoved(i+1)) mandel@1: ++overload_count; mandel@1: } mandel@1: Q_ASSERT(overload_count <= argument_count); mandel@1: for (int i=0; iisEmptyFunction() mandel@1: || d_function->isNormal() mandel@1: || d_function->isSignal() ? NoOption mandel@1: : SkipReturnType, mandel@1: used_arguments); mandel@1: mandel@1: s << endl; mandel@1: if (m_doc_parser) { mandel@1: s << m_doc_parser->documentationForFunction(signature) << endl; mandel@1: } mandel@1: mandel@1: s << signature << " {\n "; mandel@1: QString new_return_type = d_function->typeReplaced(0); mandel@1: if (new_return_type != "void" && (!new_return_type.isEmpty() || d_function->type())) mandel@1: s << "return "; mandel@1: if (d_function->isConstructor()) mandel@1: s << "this"; mandel@1: else mandel@1: s << d_function->name(); mandel@1: s << "("; mandel@1: mandel@1: int written_arguments = 0; mandel@1: for (int j=0; jargumentRemoved(j+1)) { mandel@1: if (written_arguments++ > 0) mandel@1: s << ", "; mandel@1: mandel@1: if (j < used_arguments) { mandel@1: s << arguments.at(j)->argumentName(); mandel@1: } else { mandel@1: AbstractMetaType *arg_type = 0; mandel@1: QString modified_type = d_function->typeReplaced(j+1); mandel@1: if (modified_type.isEmpty()) { mandel@1: arg_type = arguments.at(j)->type(); mandel@1: if (arg_type->isNativePointer()) { mandel@1: s << "(qt.QNativePointer)"; mandel@1: } else { mandel@1: const AbstractMetaType *abstractMetaType = arguments.at(j)->type(); mandel@1: const TypeEntry *type = abstractMetaType->typeEntry(); mandel@1: if (type->designatedInterface()) mandel@1: type = type->designatedInterface(); mandel@1: if (!type->isEnum() && !type->isFlags()) { mandel@1: s << "("; mandel@1: writeInstantiatedType(s, abstractMetaType); mandel@1: s << ")"; mandel@1: } mandel@1: } mandel@1: } else { mandel@1: s << "(" << modified_type.replace('$', '.') << ")"; mandel@1: } mandel@1: mandel@1: QString defaultExpr = arguments.at(j)->defaultValueExpression(); mandel@1: mandel@1: int pos = defaultExpr.indexOf("."); mandel@1: if (pos > 0) { mandel@1: QString someName = defaultExpr.left(pos); mandel@1: ComplexTypeEntry *ctype = mandel@1: TypeDatabase::instance()->findComplexType(someName); mandel@1: QString replacement; mandel@1: if (ctype != 0 && ctype->isVariant()) mandel@1: replacement = "qt.QVariant."; mandel@1: else if (ctype != 0) mandel@1: replacement = ctype->javaPackage() + "." + ctype->targetLangName() + "."; mandel@1: else mandel@1: replacement = someName + "."; mandel@1: defaultExpr = defaultExpr.replace(someName + ".", replacement); mandel@1: } mandel@1: mandel@1: if (arg_type != 0 && arg_type->isFlags()) { mandel@1: s << "new " << arg_type->fullName() << "(" << defaultExpr << ")"; mandel@1: } else { mandel@1: s << defaultExpr; mandel@1: } mandel@1: } mandel@1: } mandel@1: } mandel@1: s << ");\n }" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: const TypeEntry* DGenerator::fixedTypeEntry(const TypeEntry *type) mandel@1: { mandel@1: if (!type) mandel@1: return NULL; mandel@1: if (type->designatedInterface()) mandel@1: return type; mandel@1: else if (type->isEnum()) { mandel@1: const EnumTypeEntry *te = static_cast(type); mandel@1: TypeEntry *ownerTe = TypeDatabase::instance()->findType(te->qualifier()); eldar@33: if(ownerTe) eldar@33: typeEntriesEnums << ownerTe; mandel@1: return NULL; mandel@1: // return ownerTe; mandel@1: } else if (type->isFlags()) { mandel@1: const FlagsTypeEntry *te = static_cast(type); mandel@1: TypeEntry *ownerTe = TypeDatabase::instance()->findType(te->qualifier()); mandel@1: return NULL; mandel@1: // return ownerTe; mandel@1: } else //if (type->isObject()) mandel@1: return type; mandel@1: // else return NULL; mandel@1: } mandel@1: mandel@1: void DGenerator::addInstantiations(const AbstractMetaType* d_type) mandel@1: { mandel@1: if (d_type->isContainer()) { mandel@1: QList args = d_type->instantiations(); mandel@1: for (int i=0; itypeEntry()); mandel@1: if (type) mandel@1: typeEntries.insert(type); mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: void DGenerator::addTypeEntry(const AbstractMetaClass *d_class, const AbstractMetaFunction *function, QSet &typeEntries) mandel@1: { mandel@1: // If a method in an interface class is modified to be private, this should mandel@1: // not be present in the interface at all, only in the implementation. mandel@1: if (d_class->isInterface()) { mandel@1: uint includedAttributes = 0; mandel@1: uint excludedAttributes = 0; mandel@1: retrieveModifications(function, d_class, &excludedAttributes, &includedAttributes); mandel@1: if (includedAttributes & AbstractMetaAttributes::Private) mandel@1: return; mandel@1: } mandel@1: mandel@1: if (notWrappedYet(function)) // qtd2 mandel@1: return; mandel@1: mandel@1: // return type for function mandel@1: if (function->type()) { mandel@1: addInstantiations(function->type()); mandel@1: const TypeEntry *type = fixedTypeEntry(function->type()->typeEntry()); mandel@1: if (type) mandel@1: typeEntries.insert(type); mandel@1: } mandel@1: mandel@1: AbstractMetaArgumentList arguments = function->arguments(); mandel@1: for (int i=0; itype()); mandel@1: const TypeEntry *type = fixedTypeEntry(arg->type()->typeEntry()); mandel@1: if (type) mandel@1: typeEntries.insert(type); mandel@1: } mandel@1: } mandel@1: mandel@1: void DGenerator::fillRequiredImports(const AbstractMetaClass *d_class) mandel@1: { mandel@1: if (m_recursive < 2) { mandel@1: typeEntries.clear(); mandel@1: typeEntriesEnums.clear(); mandel@1: } mandel@1: mandel@1: // import for base class mandel@1: if(d_class->baseClass()) mandel@1: typeEntries << d_class->baseClass()->typeEntry(); mandel@1: mandel@1: //interfaces mandel@1: AbstractMetaClassList interfaces = d_class->interfaces(); mandel@1: if (!interfaces.isEmpty()) { mandel@1: for (int i=0; itypeEntry(); mandel@1: typeEntries << te->origin(); mandel@1: } mandel@1: } mandel@1: mandel@1: AbstractMetaFunctionList d_funcs = d_class->functionsInTargetLang(); mandel@1: mandel@1: // in case of ConcreteWrapper - adding extra functions mandel@1: if (!d_class->isInterface() && d_class->isAbstract()) { mandel@1: AbstractMetaFunctionList functions_add = d_class->queryFunctions(AbstractMetaClass::NormalFunctions | AbstractMetaClass::AbstractFunctions | AbstractMetaClass::NonEmptyFunctions | AbstractMetaClass::NotRemovedFromTargetLang); mandel@1: d_funcs << functions_add; mandel@1: } mandel@1: mandel@1: for (int i=0; ivirtualFunctions(); mandel@1: for (int i=0; ifields(); mandel@1: foreach (const AbstractMetaField *field, fields) { mandel@1: if (field->wasPublic() || (field->wasProtected() && !d_class->isFinal())) { mandel@1: addTypeEntry(d_class, field->setter(), typeEntries); mandel@1: addTypeEntry(d_class, field->getter(), typeEntries); mandel@1: } mandel@1: } mandel@1: mandel@1: // signals mandel@1: AbstractMetaFunctionList signal_funcs = d_class->queryFunctions(AbstractMetaClass::Signals mandel@1: | AbstractMetaClass::Visible mandel@1: | AbstractMetaClass::NotRemovedFromTargetLang); mandel@1: for (int i=0; iisQObject() && d_class->name() != "QObject") mandel@1: typeEntries << TypeDatabase::instance()->findType("QObject"); mandel@1: mandel@1: if(m_recursive == 1) mandel@1: m_recursive++; mandel@1: } mandel@1: mandel@1: void DGenerator::writeImportString(QTextStream &s, const TypeEntry* typeEntry) mandel@1: { mandel@1: /* QString visibility = "private"; mandel@1: if (typeEntry->isNamespace() || typeEntry->name() == "QObject") mandel@1: visibility = "public"; mandel@1: if(d_class->baseClass() && d_class->baseClass()->typeEntry() == typeEntry) mandel@1: visibility = "public";*/ mandel@1: QString visibility = "public"; eldar@33: s << QString("%1 import ").arg(visibility) << typeEntry->javaPackage() << "." << typeEntry->targetLangName() << ";" << endl; mandel@1: } mandel@1: mandel@1: void DGenerator::writeRequiredImports(QTextStream &s, const AbstractMetaClass *d_class) mandel@1: { mandel@1: foreach (const TypeEntry *typeEntry, typeEntriesEnums) { mandel@1: if (!excludedTypes.contains(typeEntry->name()) && d_class->typeEntry() != typeEntry mandel@1: && typeEntry->javaQualifier() != typeEntry->name() mandel@1: /*also*/ && !excludedTypes2.contains(typeEntry->name())) mandel@1: writeImportString(s, typeEntry); mandel@1: } mandel@1: mandel@1: foreach (const TypeEntry *typeEntry, typeEntries) { mandel@1: if (!excludedTypes.contains(typeEntry->name()) && d_class->typeEntry() != typeEntry mandel@1: && typeEntry->javaQualifier() != typeEntry->name() mandel@1: /*also*/ && !excludedTypes2.contains(typeEntry->name())) mandel@1: writeImportString(s, typeEntry); mandel@1: } mandel@1: excludedTypes2.clear(); mandel@1: } mandel@1: mandel@1: void DGenerator::writeDestructor(QTextStream &s, const AbstractMetaClass *d_class) mandel@1: { mandel@1: if (!d_class->hasConstructors()) mandel@1: return; mandel@1: maxter@354: if (d_class->isDestructorBase()) maxter@253: { maxter@253: s << INDENT << "protected override void __deleteNative() {" << endl; mandel@1: { maxter@354: s << INDENT << "qtd_" << d_class->name() << "_delete(__nativeId);" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl << endl; maxter@354: maxter@354: s << INDENT << "static void __deleteNativeObject(void* ptr) {" << endl maxter@354: << INDENT << " qtd_" << d_class->name() << "_delete(ptr);" << endl eldar@294: << INDENT << "}" << endl << endl; maxter@354: maxter@354: s << INDENT << "static void __callNativeDestructor(void* nativeId) {" << endl maxter@354: << INDENT << " qtd_" << d_class->name() << "_destroy(nativeId);" << endl eldar@294: << INDENT << "}" << endl << endl; eldar@294: } mandel@1: } mandel@1: maxter@253: void DGenerator::writeFlagsSetter(QTextStream &s, const AbstractMetaClass *d_class) mandel@1: { maxter@361: if (d_class->isInterface()) maxter@253: s << INDENT << "void __setFlags(QtdObjectFlags flags, bool val);"; maxter@361: else if (!d_class->isNamespace()) // COMPILER BUG: maxter@253: s << INDENT << "void __setFlags(QtdObjectFlags flags, bool val) { super.__setFlags(flags, val); }"; mandel@1: } mandel@1: mandel@1: void DGenerator::writeSignalHandlers(QTextStream &s, const AbstractMetaClass *d_class) mandel@1: { mandel@1: AbstractMetaFunctionList signal_funcs = signalFunctions(d_class); mandel@1: mandel@1: QString attr; mandel@1: eldar@288: // return; // #TODO Don't need handlers for now. Restore in conversion functions later eldar@288: mandel@1: s << "// signal handlers" << endl; mandel@1: foreach(AbstractMetaFunction *signal, signal_funcs) { mandel@1: QString sigExternName = signalExternName(d_class, signal); mandel@1: eldar@167: /* mandel@1: QString extra_args; mandel@1: mandel@1: foreach (AbstractMetaArgument *argument, arguments) { mandel@1: if(argument->type()->isContainer()) { mandel@1: QString arg_name = argument->indexedName(); mandel@1: const AbstractMetaType *arg_type = argument->type(); mandel@1: QString type_string = translateType(argument->type(), signal->implementingClass(), BoxedPrimitive); mandel@1: extra_args += ", " + type_string + " " + arg_name; mandel@1: } mandel@1: } eldar@167: */ eldar@167: AbstractMetaArgumentList arguments = signal->arguments(); eldar@167: maxter@355: s << "/*private extern(C) void " << sigExternName << "_handle(void* dId, void** args) {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); maxter@355: s << INDENT << "auto d_object = cast(" << d_class->name() << ") dId;" << endl; mandel@1: int sz = arguments.count(); mandel@1: mandel@1: for (int j=0; jindexedName(); mandel@1: AbstractMetaType *type = argument->type(); mandel@1: // if has QString argument we have to pass char* and str.length to QString constructor mandel@1: mandel@1: QString arg_ptr = QString("args[%1]").arg(argument->argumentIndex() + 1); mandel@1: eldar@167: if (type->isContainer()) { eldar@167: s << INDENT << translateType(type, signal->implementingClass(), BoxedPrimitive) << " " << arg_name << ";" << endl eldar@270: << INDENT << cppContainerConversionName(d_class, type, FromCpp) << "(" << arg_ptr << ", &" << arg_name << ");" << endl; eldar@167: } else if (type->isTargetLangString()) { mandel@1: s << INDENT << "auto " << arg_name << "_ptr = " << arg_ptr << ";" << endl eldar_ins@302: << INDENT << "string " << arg_name << " = QStringUtil.toNativeString(" << arg_name << "_ptr);"; eldar@167: } else if(type->isPrimitive() || type->isEnum() || type->isFlags() || type->typeEntry()->isStructInD()) { mandel@1: QString type_name = argument->type()->typeEntry()->qualifiedTargetLangName(); mandel@1: s << INDENT << "auto " << arg_name << " = *(cast(" << type_name << "*)" << arg_ptr << ");"; mandel@1: } else if(type->isObject() || type->isQObject() mandel@1: || (type->typeEntry()->isValue() && type->isNativePointer()) mandel@1: || type->isValue()) { eldar@167: QString type_name = type->name(); eldar@167: const ComplexTypeEntry *ctype = static_cast(type->typeEntry()); eldar@167: if(ctype->isAbstract()) eldar@167: type_name = type_name + "_ConcreteWrapper"; eldar@167: s << INDENT << "scope " << arg_name << " = new " << type_name maxter@253: << "(cast(void*)(" << arg_ptr << "), QtdObjectFlags.nativeOwnership);" << endl; eldar@167: } mandel@1: s << endl; mandel@1: } mandel@1: // s << INDENT << "Stdout(\"" << d_class->name() << "\", \"" << signal->name() << "\").newline;" << endl; eldar@288: s << INDENT << "//d_object." << signal->name() << "_emit("; mandel@1: for (int j = 0; jindexedName(); mandel@1: if (j != 0) mandel@1: s << ", "; mandel@1: s << arg_name; mandel@1: } mandel@1: mandel@1: s << ");" << endl; mandel@1: } eldar@293: s << "}*/" << endl; mandel@1: } mandel@1: } mandel@1: eldar@288: AbstractMetaFunctionList DGenerator::generatedClassFunctions(const AbstractMetaClass *d_class) eldar@288: { eldar@288: AbstractMetaFunctionList r; eldar@288: AbstractMetaFunctionList d_funcs = d_class->functionsInTargetLang(); eldar@288: for (int i=0; iisInterface()) { eldar@288: uint includedAttributes = 0; eldar@288: uint excludedAttributes = 0; eldar@288: retrieveModifications(function, d_class, &excludedAttributes, &includedAttributes); eldar@288: if (includedAttributes & AbstractMetaAttributes::Private) eldar@288: continue; eldar@288: } eldar@288: eldar@288: if (!notWrappedYet(function)) // qtd2 eldar@288: r += function; eldar@288: } eldar@288: return r; eldar@288: } eldar@288: mandel@1: void DGenerator::write(QTextStream &s, const AbstractMetaClass *d_class) mandel@1: { mandel@1: ReportHandler::debugSparse("Generating class: " + d_class->fullName()); mandel@1: mandel@1: bool fakeClass = d_class->attributes() & AbstractMetaAttributes::Fake; mandel@1: maxter@253: maxter@253: QString auxModName = d_class->package() + "." + d_class->name() + "_aux"; maxter@253: FileOut auxFile(outputDirectory() + "/" + subDirectoryForClass(d_class) + "/" + d_class->name() + "_aux.d"); maxter@253: auxFile.isDone = true; maxter@253: auxFile.stream << "module " << auxModName << ";" << endl << endl; maxter@253: maxter@361: bool staticInit = d_class->isQObject() || d_class->typeEntry()->isValue() maxter@361: || (cpp_shared && d_class->generateShellClass() && !d_class->isInterface() && !d_class->isNamespace()); maxter@253: if (staticInit) maxter@253: { maxter@253: auxFile.isDone = false; maxter@253: auxFile.stream << "extern(C) void static_init_" << d_class->name() << "();" << endl; eldar1@331: auxFile.stream << "shared static this() { static_init_" << d_class->name() << "; }" << endl << endl; maxter@253: } maxter@253: mandel@1: if (m_docs_enabled) { mandel@1: m_doc_parser = new DocParser(m_doc_directory + "/" + d_class->name().toLower() + ".jdoc"); mandel@1: } mandel@1: if (!m_isRecursive) mandel@1: s << "module " << d_class->package() << "." << d_class->name() <<";" << endl << endl; mandel@1: eldar@39: /* mandel@1: s << "// some type info" << endl; mandel@1: QString hasVirtuals = d_class->hasVirtualFunctions() ? "has" : "doesn't have"; mandel@1: QString isFinal = d_class->isFinal() ? "is" : "is not"; mandel@1: QString isNativeId = d_class->typeEntry()->isNativeIdBased() ? "is" : "is not"; mandel@1: s << "// " << hasVirtuals << " virtual functions" << endl mandel@1: << "// " << isFinal << " final" << endl mandel@1: << "// " << isNativeId << " native id based" << endl << endl mandel@1: << "// " << d_class->generateShellClass() << " shell class" << endl mandel@1: << "// " << d_class->hasVirtualFunctions() << endl mandel@1: << "// " << d_class->hasProtectedFunctions() << endl mandel@1: << "// " << d_class->hasFieldAccessors() << endl mandel@1: << "// " << d_class->typeEntry()->isObject() << endl; eldar@39: */ mandel@1: mandel@1: const ComplexTypeEntry *ctype = d_class->typeEntry(); mandel@1: if (!ctype->addedTo.isEmpty() && !m_isRecursive) { mandel@1: ComplexTypeEntry *ctype_parent = TypeDatabase::instance()->findComplexType(ctype->addedTo); mandel@1: s << "public import " << ctype_parent->javaPackage() << "." << ctype_parent->name() << ";" << endl; mandel@1: return; mandel@1: } mandel@1: mandel@1: if(d_class->isInterface() && !m_isRecursive) { mandel@1: s << "public import " << ctype->javaPackage() << "." << ctype->qualifiedCppName() << ";" << endl; mandel@1: return; mandel@1: } mandel@1: AbstractMetaClassList includedClassesList; mandel@1: mandel@1: /* m_recursive is increasing by 1 each time we fill the import for a class mandel@1: if it equals to 0 or 1 imports Set is cleared before a filling cycle - if there mandel@1: is only one class as usual or if there are many classes in module, but before mandel@1: filling for first class we need to clear Set. Wow :) mandel@1: */ mandel@1: if(ctype->includedClasses.size() > 0) mandel@1: m_recursive = 1; mandel@1: else mandel@1: m_recursive = 0; mandel@1: mandel@1: foreach(QString child, ctype->includedClasses) { mandel@1: ComplexTypeEntry *ctype_child = TypeDatabase::instance()->findComplexType(child); mandel@1: foreach (AbstractMetaClass *cls, m_classes) { mandel@1: if ( cls->name() == ctype_child->name() ) { mandel@1: includedClassesList << cls; mandel@1: fillRequiredImports(cls); mandel@1: excludedTypes2 << cls->name(); mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: QString interface; mandel@1: if(d_class->typeEntry()->designatedInterface()) mandel@1: interface = d_class->typeEntry()->designatedInterface()->name(); mandel@1: mandel@1: if(d_class->typeEntry()->designatedInterface()) { mandel@1: foreach (AbstractMetaClass *cls, m_classes) { mandel@1: if ( cls->name() == interface ) { mandel@1: includedClassesList << cls; mandel@1: fillRequiredImports(cls); mandel@1: excludedTypes2 << cls->name(); mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: fillRequiredImports(d_class); mandel@1: excludedTypes2 << d_class->name(); mandel@1: if(ctype->includedClasses.size() > 0) mandel@1: m_recursive = 0; mandel@1: mandel@1: QList includes = d_class->typeEntry()->extraIncludes(); mandel@1: foreach (const Include &inc, includes) { mandel@1: if (inc.type == Include::TargetLangImport) { mandel@1: s << inc.toString() << endl; mandel@1: } mandel@1: } mandel@1: maxter@253: // Auxiliary file contents should have been written at this point maxter@253: if (!auxFile.isDone) maxter@253: { maxter@253: s << "public import " << auxModName << ";" << endl; maxter@253: auxFile.done(); maxter@253: } maxter@253: mandel@1: if (!m_isRecursive) { mandel@1: s << "public import qt.QGlobal;" << endl mandel@1: << "public import qt.core.Qt;" << endl maxter@344: << "private import qtd.QtdObject;" << endl eldar@81: << "private import qt.core.QString;" << endl maxter@344: << "private import qtd.Array;" << endl eldar@298: << "private import qt.core.QList;" << endl; mandel@1: if (d_class->isQObject()) { maxter@344: s << "public import qtd.Signal;" << endl maxter@344: << "public import qtd.MOC;" << endl maxter@344: << "public import qtd.Traits;" << endl maxter@344: << "public import qt.core.QMetaObject;" << endl; maxter@253: mandel@1: if (d_class->name() != "QObject") mandel@1: s << "public import qt.core.QObject;" << endl; mandel@1: } mandel@1: mandel@1: // qtd2 hack! mandel@1: if (d_class->name() == "QCoreApplication") mandel@1: s << "private import qt.core.ArrayOps;" << endl; mandel@1: else if (d_class->name() == "QApplication") mandel@1: s << "private import qt.gui.ArrayOps;" << endl; mandel@1: eldar@187: /* eldar@187: we don't need to import ArrayOps2 for anything else than QObjects, eldar@187: for example if it is done in the namespaces, it may cause circular eldar@187: imports forward references and shit. If ArrayOps2 is expanded later eldar@187: for other usages - then restrict it just for namespaces/interfaces eldar@187: */ eldar@187: if(d_class->isQObject()) eldar@187: s << "private import " << d_class->package() << ".ArrayOps2;" << endl; eldar@167: mandel@1: s << "// automatic imports-------------" << endl; mandel@1: writeRequiredImports(s, d_class); mandel@1: s << endl; mandel@1: if (dPhobos) mandel@1: { mandel@1: s << "import std.stdio;" << endl eldar_ins@321: << "import std.string : toStringz;" << endl mandel@1: << "import std.utf;" << endl maxter@253: << "import core.memory;" << endl; mandel@1: } mandel@1: else mandel@1: { mandel@1: s << "import tango.io.Stdout;" << endl mandel@1: << "import tango.stdc.stringz;" << endl mandel@1: << "import tango.text.convert.Utf;" << endl maxter@253: << "import tango.core.Memory;" << endl; mandel@1: } maxter@253: maxter@253: s << endl << endl; mandel@1: } mandel@1: mandel@1: if (m_doc_parser) { mandel@1: s << m_doc_parser->documentation(d_class) << endl << endl; mandel@1: } mandel@1: eldar@188: /* qtd s << "@QtJambiGeneratedClass" << endl; eldar@188: eldar@188: if ((d_class->typeEntry()->typeFlags() & ComplexTypeEntry::Deprecated) != 0) { eldar@188: s << "@Deprecated" << endl; eldar@188: } eldar@188: */ eldar@188: eldar@188: mandel@1: if (d_class->isInterface()) { mandel@1: s << "public interface "; mandel@1: } else { mandel@1: if (d_class->isPublic()) mandel@1: s << "public "; mandel@1: // else friendly mandel@1: mandel@1: bool force_abstract = (d_class->typeEntry()->typeFlags() & ComplexTypeEntry::ForceAbstract) != 0; mandel@1: if (d_class->isFinal() && !force_abstract) mandel@1: s << "final "; mandel@1: if ((d_class->isAbstract() && !d_class->isNamespace()) || force_abstract) mandel@1: s << "abstract "; mandel@1: mandel@1: if (!d_class->typeEntry()->targetType().isEmpty()) { mandel@1: s << d_class->typeEntry()->targetType() << " "; mandel@1: } else if (d_class->isNamespace() && d_class->functionsInTargetLang().size() == 0) { mandel@1: s << "interface "; mandel@1: } else if (d_class->isNamespace()) { mandel@1: s << "class "; mandel@1: } else { mandel@1: s << "class "; mandel@1: } mandel@1: mandel@1: } mandel@1: mandel@1: const ComplexTypeEntry *type = d_class->typeEntry(); mandel@1: mandel@1: s << d_class->name(); mandel@1: mandel@1: if (type->isGenericClass()) { mandel@1: s << "<"; mandel@1: QList templateArguments = d_class->templateBaseClass()->templateArguments(); mandel@1: for (int i=0; i 0) mandel@1: s << ", "; mandel@1: s << templateArgument->name(); mandel@1: } mandel@1: s << ">"; mandel@1: } mandel@1: maxter@355: AbstractMetaClassList interfaces = d_class->interfaces(); maxter@355: bool implements = false; mandel@1: if (!d_class->isNamespace() && !d_class->isInterface()) { mandel@1: if (!d_class->baseClassName().isEmpty()) { mandel@1: s << " : " << d_class->baseClass()->name(); maxter@355: implements = true; mandel@1: } else { maxter@355: maxter@355: /* mandel@1: QString sc = type->defaultSuperclass(); maxter@355: if ((sc != d_class->name()) && !sc.isEmpty()) { mandel@1: s << " : " << sc; maxter@355: implements = true; maxter@355: } maxter@355: */ maxter@355: if (d_class->isQObject()) maxter@355: s << " : QtdObject"; maxter@355: else maxter@355: s << " : QtdObject"; maxter@355: implements = true; mandel@1: } mandel@1: }/* qtd else if (d_class->isInterface()) { mandel@1: s << " extends QtJambiInterface"; mandel@1: }*/ mandel@1: mandel@1: // implementing interfaces... maxter@355: for (int i=0; iname(); mandel@1: } maxter@355: mandel@1: /* qtd mandel@1: if (isComparable(d_class)) { mandel@1: if (!implements) { mandel@1: implements = true; mandel@1: s << endl << " implements "; mandel@1: } mandel@1: else mandel@1: s << "," << endl << " "; mandel@1: s << "java.lang.Comparable"; mandel@1: } mandel@1: mandel@1: if (d_class->hasCloneOperator()) { mandel@1: if (!implements) { mandel@1: implements = true; mandel@1: s << endl << " implements "; mandel@1: } mandel@1: else mandel@1: s << "," << endl << " "; mandel@1: s << "java.lang.Cloneable"; mandel@1: } mandel@1: */ mandel@1: s << endl << "{" << endl; mandel@1: mandel@1: Indentation indent(INDENT); mandel@1: spambox@337: // Enums maxter@341: if (!d_class->typeEntry()->designatedInterface() && !d_class->enums().isEmpty()) { spambox@337: foreach (AbstractMetaEnum *d_enum, d_class->enums()) maxter@341: writeEnum(s, d_enum, true); maxter@341: } maxter@341: maxter@341: // Enums in designated interfaces maxter@341: if (d_class->isInterface() && d_class->primaryInterfaceImplementor()) { maxter@341: foreach (AbstractMetaEnum *d_enum, d_class->primaryInterfaceImplementor()->enums()) maxter@341: writeEnum(s, d_enum, true); spambox@337: } spambox@337: mandel@1: // Define variables for reference count mechanism mandel@1: if (!d_class->isInterface() && !d_class->isNamespace()) { mandel@1: QHash variables; mandel@1: foreach (AbstractMetaFunction *function, d_class->functions()) { mandel@1: QList referenceCounts = function->referenceCounts(d_class); mandel@1: foreach (ReferenceCount refCount, referenceCounts) { mandel@1: variables[refCount.variableName] |= refCount.action mandel@1: | refCount.access mandel@1: | (refCount.threadSafe ? ReferenceCount::ThreadSafe : 0) mandel@1: | (function->isStatic() ? ReferenceCount::Static : 0) mandel@1: | (refCount.declareVariable.isEmpty() ? ReferenceCount::DeclareVariable : 0); mandel@1: } mandel@1: } mandel@1: mandel@1: foreach (QString variableName, variables.keys()) { mandel@1: int actions = variables.value(variableName) & ReferenceCount::ActionsMask; mandel@1: // bool threadSafe = variables.value(variableName) & ReferenceCount::ThreadSafe; mandel@1: bool isStatic = variables.value(variableName) & ReferenceCount::Static; mandel@1: bool declareVariable = variables.value(variableName) & ReferenceCount::DeclareVariable; mandel@1: int access = variables.value(variableName) & ReferenceCount::AccessMask; mandel@1: mandel@1: if (actions == ReferenceCount::Ignore || !declareVariable) mandel@1: continue; mandel@1: mandel@1: if (((actions & ReferenceCount::Add) == 0) != ((actions & ReferenceCount::Remove) == 0)) { mandel@1: QString warn = QString("either add or remove specified for reference count variable '%1' in '%2' but not both") mandel@1: .arg(variableName).arg(d_class->fullName()); mandel@1: ReportHandler::warning(warn); mandel@1: } mandel@1: s << endl; mandel@1: /* qtd mandel@1: if (TypeDatabase::instance()->includeEclipseWarnings()) mandel@1: s << INDENT << "@SuppressWarnings(\"unused\")" << endl; mandel@1: */ mandel@1: if (actions != ReferenceCount::Set && actions != ReferenceCount::Ignore) { // qtd2 mandel@1: mandel@1: s << INDENT; mandel@1: switch (access) { mandel@1: case ReferenceCount::Private: mandel@1: s << "package "; break; // qtd mandel@1: case ReferenceCount::Protected: mandel@1: s << "protected "; break; mandel@1: case ReferenceCount::Public: mandel@1: s << "public "; break; mandel@1: default: mandel@1: s << "protected"; // friendly mandel@1: } mandel@1: eldar@33: } // qtd2 eldar@33: mandel@1: if (isStatic) mandel@1: s << "static "; mandel@1: mandel@1: if (actions != ReferenceCount::Set && actions != ReferenceCount::Ignore) { mandel@1: s << "Object[] " << variableName << ";" << endl; mandel@1: /* mandel@1: if (threadSafe) mandel@1: s << "java.util.Collections.synchronizedCollection("; mandel@1: s << "new java.util.ArrayList()"; mandel@1: if (threadSafe) mandel@1: s << ")"; mandel@1: s << ";" << endl;*/ mandel@1: } else if (actions != ReferenceCount::Ignore) { mandel@1: /* qtd2 if (threadSafe) mandel@1: s << "synchronized ";*/ mandel@1: s << "Object " << variableName << " = null;" << endl; mandel@1: } mandel@1: } mandel@1: s << endl; mandel@1: } mandel@1: mandel@1: /* qtd2 mandel@1: if (!d_class->isInterface() && (!d_class->isNamespace() || d_class->functionsInTargetLang().size() > 0) mandel@1: && (d_class->baseClass() == 0 || d_class->package() != d_class->baseClass()->package())) { mandel@1: s << endl mandel@1: << INDENT << "static {" << endl; mandel@1: mandel@1: if (d_class->isNamespace()) { mandel@1: s << INDENT << " qt.QtJambi_LibraryInitializer.init();" << endl; mandel@1: } mandel@1: mandel@1: s << INDENT << " " << d_class->package() << ".QtJambi_LibraryInitializer.init();" << endl mandel@1: << INDENT << "}" << endl; mandel@1: } mandel@1: */ mandel@1: eldar@288: // Signals maxter@253: if (d_class->isQObject()) mandel@1: { maxter@253: AbstractMetaFunctionList signal_funcs = signalFunctions(d_class, false); maxter@253: writeSignalSignatures(s, d_class, signal_funcs); spambox@342: mandel@1: foreach (AbstractMetaFunction *signal, signal_funcs) eldar@270: { maxter@253: writeSignal(s, signal); eldar@270: if(!signal->isPrivate()) eldar@270: writeFunction(s, signal); eldar@270: } mandel@1: } mandel@1: mandel@1: // Class has subclasses but also only private constructors mandel@1: if (!d_class->isFinalInTargetLang() && d_class->isFinalInCpp()) { mandel@1: s << endl << INDENT << "/**" << endl mandel@1: << INDENT << " * This constructor is a place holder intended to prevent" << endl mandel@1: << INDENT << " * users from subclassing the class. Certain classes can" << endl mandel@1: << INDENT << " * unfortunately only be subclasses internally. The constructor" << endl mandel@1: << INDENT << " * will indiscriminately throw an exception if called. If the" << endl mandel@1: << INDENT << " * exception is ignored, any use of the constructed object will" << endl mandel@1: << INDENT << " * cause an exception to occur." << endl << endl mandel@1: << INDENT << " * @throws QClassCannotBeSubclassedException" << endl mandel@1: << INDENT << " **/" << endl mandel@1: << INDENT << "protected " << d_class->name() << "() throws QClassCannotBeSubclassedException {" << endl mandel@1: << INDENT << " throw new QClassCannotBeSubclassedException(" << d_class->name() << ".class);" << endl mandel@1: << INDENT << "}" << endl << endl; mandel@1: } mandel@1: s << "// Functions" << endl; mandel@1: mandel@1: // Functions mandel@1: AbstractMetaFunctionList d_funcs = d_class->functionsInTargetLang(); eldar@288: AbstractMetaFunctionList d_funcs_gen = generatedClassFunctions(d_class); eldar@288: for (int i=0; iisSlot()) eldar@288: // writeSlot(s, function); eldar@288: writeFunction(s, function); eldar@288: // qtd s << function->minimalSignature() << endl; mandel@1: } mandel@1: if(d_class->isInterface()) mandel@1: s << endl << INDENT << "public void* __ptr_" << d_class->name() << "();" << endl << endl; mandel@1: mandel@1: mandel@1: s << "// Field accessors" << endl; mandel@1: // Field accessors mandel@1: AbstractMetaFieldList fields = d_class->fields(); mandel@1: foreach (const AbstractMetaField *field, fields) { mandel@1: if (field->wasPublic() || (field->wasProtected() && !d_class->isFinal())) mandel@1: writeFieldAccessors(s, field); mandel@1: } mandel@1: maxter@253: if (d_class->isQObject()) maxter@253: writeQObjectFunctions(s, d_class); maxter@253: eldar@293: if (ctype->isObject() && !ctype->isQObject()) // conversion function wrapper to be consistent with QObject eldar@293: { // some code duplication, remove when there is a better mechanism for Object type conversions eldar@293: QString class_name = ctype->name(); eldar@293: QString return_type_name = class_name; eldar@293: if(ctype->designatedInterface()) eldar@293: return_type_name = ctype->designatedInterface()->name(); eldar@293: s << " static " << return_type_name << " __getObject(void* nativeId) {" << endl eldar@293: << " return qtd_" << class_name << "_from_ptr(nativeId);" << endl eldar@293: << " }" << endl << endl; eldar@293: } eldar@293: eldar@288: // flag to mark the type of class (to use in templates to convert arguments) eldar@288: if (d_class->baseClassName().isEmpty()) eldar@288: { eldar@288: if (d_class->typeEntry()->isQObject()) eldar@292: s << INDENT << "public alias void __isQObjectType;" << endl << endl; eldar@288: else if (d_class->typeEntry()->isObject()) eldar@292: s << INDENT << "public alias void __isObjectType;" << endl << endl; eldar@288: else if (d_class->typeEntry()->isValue()) eldar@292: s << INDENT << "public alias void __isValueType;" << endl << endl; eldar@288: } eldar@288: eldar@292: s << INDENT << "public alias void __isQtType_" << d_class->name() << ";" << endl << endl; eldar@292: eldar@293: // construction of a native copy of a Value eldar@298: if (d_class->typeEntry()->isValue()) eldar@293: { eldar_ins@304: AbstractMetaFunction *copy_ctor = d_class->copyConstructor(); eldar_ins@304: if (!d_class->typeEntry()->hasPrivateCopyConstructor()) // can do a copy if we have a public ctor or don't have any eldar@293: s << INDENT << "static void* __constructNativeCopy(const void* orig) {" << endl eldar@298: << INDENT << " return qtd_" << d_class->name() << "_native_copy(orig);" << endl eldar@293: << INDENT << "}" << endl << endl eldar@293: eldar@298: << INDENT << "static void __constructPlacedNativeCopy(const void* orig, void* place) {" << endl eldar@298: << INDENT << " qtd_" << d_class->name() << "_placed_copy(orig, place);" << endl eldar@293: << INDENT << "}" << endl << endl; eldar@293: } eldar@293: mandel@1: // Add dummy constructor for use when constructing subclasses mandel@1: if (!d_class->isNamespace() && !d_class->isInterface() && !fakeClass) { mandel@1: s << endl mandel@1: << INDENT << "public " mandel@1: << "this"; mandel@1: maxter@253: maxter@253: Indentation indent(INDENT); maxter@253: maxter@253: s << "(void* native_id, QtdObjectFlags flags = QtdObjectFlags.none) {" << endl maxter@253: << INDENT << "super(native_id, flags);" << endl; maxter@253: maxter@253: if (d_class->name() == "QObject") mandel@1: { maxter@253: // To prevent GC from collecting the object, add it to the statically rooted linked list maxter@253: s << INDENT << " __next = __root;" << endl maxter@253: << INDENT << " __root = this;" << endl maxter@253: << INDENT << " if (__next) {" << endl maxter@253: << INDENT << " __next.__prev = this;" << endl maxter@253: << INDENT << " }" << endl << endl; mandel@1: } maxter@253: maxter@253: /* eldar@223: if (cpp_shared) { eldar@223: if (d_class->generateShellClass() && !d_class->isInterface()) maxter@253: s << INDENT << "if (!static_inited)" << endl eldar@223: << INDENT << " static_init_" << d_class->name() << "();" << endl << endl; eldar@223: } maxter@253: */ maxter@253: mandel@1: mandel@1: // pointers to native interface objects for classes that implement interfaces mandel@1: // initializing mandel@1: interfaces = d_class->interfaces(); mandel@1: if (!interfaces.isEmpty()) { mandel@1: for (int i=0; iname() << " = qtd_" << d_class->name() << "_cast_to_" << iface->qualifiedCppName() maxter@253: << "(__nativeId);" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: mandel@1: s << INDENT << "}" << endl << endl; mandel@1: mandel@1: // pointers to native interface objects for classes that implement interfaces mandel@1: // initializing mandel@1: interfaces = d_class->interfaces(); mandel@1: if (!interfaces.isEmpty()) { mandel@1: for (int i=0; iname() << ";" << endl mandel@1: << INDENT << "public void* __ptr_" << iface->name() << "() { return __m_ptr_" << iface->name() << "; }" << endl << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: writeDestructor(s, d_class); mandel@1: } mandel@1: eldar@292: if (d_class->typeEntry()->isValue()) eldar@292: writeValueFunctions(s, d_class); mandel@1: /* qtd mandel@1: // Add a function that converts an array of the value type to a QNativePointer mandel@1: if (d_class->typeEntry()->isValue() && !fakeClass) { mandel@1: s << endl mandel@1: << INDENT << "public static native QNativePointer nativePointerArray(" << d_class->name() mandel@1: << " array[]);" << endl; mandel@1: } mandel@1: mandel@1: // write the cast to this function.... mandel@1: if (d_class->isInterface()) { mandel@1: s << endl mandel@1: << " public long __qt_cast_to_" mandel@1: << static_cast(type)->origin()->targetLangName() mandel@1: << "(long ptr);" << endl; mandel@1: } else { mandel@1: foreach (AbstractMetaClass *cls, interfaces) { mandel@1: s << endl mandel@1: << " @QtBlockedSlot public native long __qt_cast_to_" mandel@1: << static_cast(cls->typeEntry())->origin()->targetLangName() mandel@1: << "(long ptr);" << endl; mandel@1: } mandel@1: } mandel@1: */ mandel@1: mandel@1: /* qtd writeJavaLangObjectOverrideFunctions(s, d_class); mandel@1: */ maxter@253: writeFlagsSetter(s, d_class); mandel@1: s << "// Injected code in class" << endl; mandel@1: writeExtraFunctions(s, d_class); mandel@1: // qtd2 writeToStringFunction(s, d_class); mandel@1: /* qtd mandel@1: if (d_class->hasCloneOperator()) { mandel@1: writeCloneFunction(s, d_class); mandel@1: } mandel@1: */ eldar@292: s << "}" << endl; // end of class scope mandel@1: spambox@342: /* ---------------- injected free code ----------------*/ spambox@342: const ComplexTypeEntry *class_type = d_class->typeEntry(); spambox@342: Q_ASSERT(class_type); spambox@342: spambox@342: CodeSnipList code_snips = class_type->codeSnips(); spambox@342: foreach (const CodeSnip &snip, code_snips) { spambox@342: if (!d_class->isInterface() && snip.language == TypeSystem::TargetLangFreeCode) { spambox@342: s << endl; spambox@342: snip.formattedCode(s, INDENT); spambox@342: } spambox@342: } eldar@105: /* --------------------------------------------------- */ eldar@14: mandel@1: interfaces = d_class->interfaces(); mandel@1: if (!interfaces.isEmpty()) { mandel@1: for (int i=0; iname() << "_cast_to_" << iface->qualifiedCppName() mandel@1: << "(void* nativeId);" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: if (!d_class->isInterface() && d_class->isAbstract()) { mandel@1: s << endl; eldar@105: mandel@1: s << INDENT << "public class " << d_class->name() << "_ConcreteWrapper : " << d_class->name() << " {" << endl; mandel@1: mandel@1: { mandel@1: Indentation indent(INDENT); maxter@253: QString hasShellFlag = d_class->generateShellClass() ? " | QtdObjectFlags.hasShell" : ""; maxter@253: s << INDENT << "public this(void* native_id, QtdObjectFlags flags = QtdObjectFlags.nativeOwnership) {" << endl maxter@253: << INDENT << " super(native_id, flags);" << endl << endl; spambox@342: mandel@1: s << INDENT << "}" << endl << endl; mandel@1: mandel@1: uint exclude_attributes = AbstractMetaAttributes::Native | AbstractMetaAttributes::Abstract; mandel@1: uint include_attributes = 0; mandel@1: AbstractMetaFunctionList functions = d_class->queryFunctions(AbstractMetaClass::NormalFunctions | AbstractMetaClass::AbstractFunctions | AbstractMetaClass::NonEmptyFunctions | AbstractMetaClass::NotRemovedFromTargetLang); mandel@1: foreach (const AbstractMetaFunction *d_function, functions) { mandel@1: retrieveModifications(d_function, d_class, &exclude_attributes, &include_attributes); mandel@1: if (notWrappedYet(d_function)) mandel@1: continue; eldar@295: s << endl eldar@295: << INDENT << "override "; mandel@1: writeFunctionAttributes(s, d_function, include_attributes, exclude_attributes, mandel@1: d_function->isNormal() || d_function->isSignal() ? 0 : SkipReturnType); mandel@1: mandel@1: s << d_function->name() << "("; mandel@1: writeFunctionArguments(s, d_function, d_function->arguments().count()); eldar@295: s << ")"; eldar@295: eldar@295: if(d_function->isConstant()) eldar@295: s << " const"; eldar@295: eldar@295: s << " {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: writeJavaCallThroughContents(s, d_function, SuperCall); mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: } mandel@1: } mandel@1: s << INDENT << "}" << endl << endl; mandel@1: } mandel@1: mandel@1: if (d_class->generateShellClass()) { // qtd2 maxter@355: if (d_class->isPolymorphic() maxter@253: && (d_class->typeEntry()->isObject() && !d_class->typeEntry()->isQObject()) ) mandel@1: s << endl << "extern (C) void *__" << d_class->name() << "_entity(void *q_ptr);" << endl << endl; mandel@1: } eldar@105: eldar@298: if (d_class->typeEntry()->isValue()) eldar@293: { eldar_ins@304: AbstractMetaFunction *copy_ctor = d_class->copyConstructor(); eldar_ins@304: if (!d_class->typeEntry()->hasPrivateCopyConstructor()) // can do a copy if we have a public ctor or don't have any eldar@298: { eldar@298: s << "private extern(C) void qtd_" << d_class->name() << "_placed_copy(const void* orig, void* place);" << endl eldar@298: << "private extern(C) void* qtd_" << d_class->name() << "_native_copy(const void* orig);" << endl; eldar@298: } eldar@293: } eldar@110: eldar@152: // if (d_class->needsConversionFunc) eldar@110: writeConversionFunction(s, d_class); mandel@1: maxter@354: if (d_class->hasConstructors() && d_class->isDestructorBase()) maxter@354: s << "extern (C) void qtd_" << d_class->name() << "_delete(void *ptr);" << endl maxter@354: << "extern (C) void qtd_" << d_class->name() << "_destroy(void *ptr);" << endl << endl; mandel@1: mandel@1: // qtd eldar@270: eldar@270: s << endl << "// C wrappers for signal emitters" << endl; eldar@270: eldar@270: if (d_class->isQObject()) eldar@270: { eldar@270: AbstractMetaFunctionList signal_funcs = signalFunctions(d_class, false); eldar@270: eldar@270: foreach (AbstractMetaFunction *signal, signal_funcs) eldar@270: if(!signal->isPrivate()) eldar@270: writePrivateNativeFunction(s, signal); eldar@270: } eldar@270: mandel@1: s << endl << "// C wrappers" << endl; mandel@1: d_funcs = d_class->functionsInTargetLang(); mandel@1: if (!d_class->isInterface()) mandel@1: for (int i=0; ijumpTableId() == -1) mandel@1: writePrivateNativeFunction(s, function); mandel@1: } mandel@1: mandel@1: mandel@1: s << "// Just the private functions for abstract functions implemeneted in superclasses" << endl; mandel@1: // Just the private functions for abstract functions implemeneted in superclasses mandel@1: if (!d_class->isInterface() && d_class->isAbstract()) { mandel@1: d_funcs = d_class->queryFunctions(AbstractMetaClass::NormalFunctions | AbstractMetaClass::AbstractFunctions | AbstractMetaClass::NotRemovedFromTargetLang); mandel@1: foreach (AbstractMetaFunction *d_function, d_funcs) { mandel@1: if (d_function->implementingClass() != d_class) { mandel@1: s << endl; mandel@1: writePrivateNativeFunction(s, d_function); mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: mandel@1: foreach (const AbstractMetaField *field, fields) { mandel@1: if (field->wasPublic() || (field->wasProtected() && !d_class->isFinal())) mandel@1: writeNativeField(s, field); mandel@1: } mandel@1: s << endl << endl; mandel@1: mandel@1: // qtd mandel@1: s << endl << "// Virtual Dispatch functions" << endl; mandel@1: AbstractMetaFunctionList virtualFunctions = d_class->virtualFunctions(); mandel@1: for (int pos = 0; posgenerateShellClass()) maxter@253: { maxter@253: initArgs = "void* virtuals"; maxter@357: if (d_class->name() == "QObject") maxter@253: initArgs += ", void* signals"; mandel@1: mandel@1: s << "private extern (C) void qtd_" << d_class->name() maxter@357: << QString("_initCallBacks(%1);").arg(initArgs) << endl << endl; maxter@253: } maxter@253: maxter@253: s << "extern(C) void static_init_" << d_class->name() << "() {" << endl; maxter@253: eldar@292: if (d_class->typeEntry()->isValue()) eldar@292: s << INDENT << d_class->name() << ".QTypeInfo.init();" << endl; eldar@292: maxter@253: if (d_class->isQObject()) { maxter@350: // ensure meta-object is created at static construction maxter@350: s << INDENT << d_class->name() << ".staticMetaObject();" << endl; maxter@253: } maxter@253: eldar@279: if (cpp_shared && d_class->generateShellClass()) { maxter@357: maxter@357: AbstractMetaFunction::Options opts(AbstractMetaFunction::DeclaringClass | AbstractMetaFunction::NoExternNamespace); maxter@357: maxter@357: // virtual functions maxter@253: s << INDENT << "void*[" << virtualFunctions.size() << "] virt_arr;" << endl; mandel@1: for (int pos = 0; posdeclaringClass()) { maxter@357: QString mName = function->marshalledName(opts); maxter@357: s << INDENT << "virt_arr[" << pos << "] = &qtd_export_" << mName << "_dispatch;" <name() == "QObject") { eldar_ins@303: // qt_metacall, metaObject eldar_ins@303: s << endl << INDENT << "void*[2] sign_arr;" << endl; maxter@357: s << INDENT << "sign_arr[0] = &qtd_export_QObject_qt_metacall_dispatch;" << endl; maxter@357: s << INDENT << "sign_arr[1] = &qtd_export_QObject_metaObject_dispatch;" << endl; eldar@301: initArgs += ", sign_arr.ptr"; mandel@1: } mandel@1: maxter@253: s << INDENT << "qtd_" << d_class->name() << QString("_initCallBacks(%1);").arg(initArgs) << endl; mandel@1: } maxter@253: maxter@253: s << "}" << endl << endl; mandel@1: } mandel@1: mandel@1: writeSignalHandlers(s, d_class); mandel@1: s << endl; mandel@1: mandel@1: if (m_docs_enabled) { mandel@1: delete m_doc_parser; mandel@1: m_doc_parser = 0; mandel@1: } mandel@1: mandel@1: // qtd multiple classes mandel@1: foreach (AbstractMetaClass *cls, includedClassesList) { mandel@1: m_isRecursive = true; mandel@1: write(s, cls); mandel@1: m_isRecursive = false; mandel@1: } maxter@253: maxter@253: if (d_class->isQObject()) eldar@288: writeQObjectFreeFunctions(s, d_class); eldar@292: eldar@292: if (d_class->typeEntry()->isValue()) eldar@292: writeValueFreeFunctions(s, d_class); eldar@292: } eldar@292: eldar@292: void DGenerator::writeValueFunctions(QTextStream &s, const AbstractMetaClass *d_class) eldar@292: { eldar@292: s << INDENT << "struct QTypeInfo {" << endl; eldar@292: s << INDENT << " static __gshared bool isComplex;" << endl; eldar@292: s << INDENT << " static __gshared bool isStatic;" << endl; eldar@292: s << INDENT << " static __gshared bool isLarge;" << endl; eldar@292: s << INDENT << " static __gshared bool isPointer;" << endl; eldar@292: s << INDENT << " static __gshared bool isDummy;" << endl << endl; eldar@292: eldar@292: s << INDENT << " static init() {" << endl; eldar@292: eldar@292: s << QString(" isComplex = qtd_%1_QTypeInfo_isComplex();\n" eldar@292: " isStatic = qtd_%1_QTypeInfo_isStatic();\n" eldar@292: " isLarge = qtd_%1_QTypeInfo_isLarge();\n" eldar@292: " isPointer = qtd_%1_QTypeInfo_isPointer();\n" eldar@292: " isDummy = qtd_%1_QTypeInfo_isDummy();\n").arg(d_class->name()) eldar@292: << " }" << endl eldar@292: << " }" << endl << endl; eldar@292: } eldar@292: eldar@292: void DGenerator::writeValueFreeFunctions(QTextStream &s, const AbstractMetaClass *d_class) eldar@292: { eldar@292: s << QString("private extern (C) bool qtd_%1_QTypeInfo_isComplex();\n").arg(d_class->name()); eldar@292: s << QString("private extern (C) bool qtd_%1_QTypeInfo_isStatic();\n").arg(d_class->name()); eldar@292: s << QString("private extern (C) bool qtd_%1_QTypeInfo_isLarge();\n").arg(d_class->name()); eldar@292: s << QString("private extern (C) bool qtd_%1_QTypeInfo_isPointer();\n").arg(d_class->name()); eldar@292: s << QString("private extern (C) bool qtd_%1_QTypeInfo_isDummy();\n").arg(d_class->name()); mandel@1: } mandel@1: eldar@110: void DGenerator::writeConversionFunction(QTextStream &s, const AbstractMetaClass *d_class) eldar@110: { eldar@110: const ComplexTypeEntry *ctype = d_class->typeEntry(); maxter@253: if(ctype->isQObject() || !ctype->isObject()) eldar@152: return; eldar@110: QString class_name = ctype->name(); eldar@111: QString return_type_name = class_name; eldar@111: if(ctype->designatedInterface()) eldar@111: return_type_name = ctype->designatedInterface()->name(); maxter@253: maxter@253: s << return_type_name << " qtd_" << class_name << "_from_ptr(void* ret) {" << endl; maxter@253: maxter@253: maxter@253: QString type_name = class_name; maxter@253: if(ctype->isAbstract()) maxter@253: type_name = ctype->targetLangName() + "_ConcreteWrapper"; maxter@253: maxter@253: // if class has virtual functions then it has classname_entity function so maxter@253: // we can look for D Object pointer. otherwise create new wrapper maxter@253: if (d_class->hasVirtualFunctions()) { maxter@253: s << INDENT << "void* d_obj = __" << ctype->targetLangName() << "_entity(ret);" << endl maxter@253: << INDENT << "if (d_obj !is null) {" << endl maxter@253: << INDENT << " auto d_obj_ref = cast (Object) d_obj;" << endl maxter@253: << INDENT << " return cast(" << return_type_name << ") d_obj_ref;" << endl maxter@253: << INDENT << "} else {" << endl maxter@253: << INDENT << " auto return_value = new " << type_name << "(ret, QtdObjectFlags.nativeOwnership);" << endl maxter@253: << INDENT << " return return_value;" << endl maxter@253: << INDENT << "}" << endl; maxter@253: } else { maxter@253: s << INDENT << "auto return_value = new " << type_name << "(ret, QtdObjectFlags.nativeOwnership);" << endl maxter@253: << INDENT << "return return_value;" << endl; eldar@111: } eldar@111: s << "}" << endl << endl; eldar@110: } eldar@110: eldar@288: void DGenerator::writeQObjectFreeFunctions(QTextStream &s, const AbstractMetaClass *d_class) eldar@288: { maxter@357: s << "extern(C) QMetaObjectNative* qtd_" << d_class->name() << "_staticMetaObject();" << endl << endl maxter@357: << "extern(C) void qtd_" << d_class->name() << "_createEntity(void* nativeId, void* dId);" << endl << endl maxter@357: << "extern(C) int qtd_" << d_class->name() << "_qt_metacall(void *nativeId, QMetaObject.Call _c, int _id, void **_a);" << endl; maxter@357: maxter@357: QString prefix = cpp_shared ? "qtd_export_" : "qtd_"; maxter@357: maxter@357: if (d_class->name() == "QObject") { maxter@357: s << "extern(C) int " << prefix << "QObject_qt_metacall_dispatch(void *d_entity, QMetaObject.Call _c, int _id, void **_a) {" << endl maxter@357: << " auto d_object = cast(QObject) d_entity;" << endl maxter@357: << " return d_object.qt_metacall(_c, _id, _a);" << endl maxter@357: << "};" << endl << endl; maxter@357: maxter@357: s << "extern(C) void* " << prefix << "QObject_metaObject_dispatch(void *d_entity) {" << endl maxter@357: << " auto d_object = cast(QObject) d_entity;" << endl maxter@357: << " return d_object.metaObject().nativeId();" << endl maxter@357: << "};" << endl << endl; maxter@357: } maxter@357: } eldar@288: eldar@288: void writeMetaMethodSignatures(QTextStream &s, const QString &var_name, AbstractMetaFunctionList meta_funcs) eldar@288: { eldar@288: s << INDENT << "private static const string[] " << var_name << " = ["; eldar@288: { eldar@288: Indentation indent(INDENT); eldar@288: for (int i = 0; i < meta_funcs.size(); ++i) eldar@288: { eldar@288: if (i) eldar@288: s << ", "; eldar@288: int j = 0; eldar@288: bool hasDefault = false; eldar@288: do // need this to look for default arguments and generate extra signatures eldar@288: { eldar_ins@309: if (j) eldar@288: s << ", "; eldar@288: s << endl << INDENT << " \"" << meta_funcs.at(i)->minimalSignature(j) << "\""; eldar@288: AbstractMetaArgumentList args = meta_funcs.at(i)->arguments(); eldar@288: if(args.size() && jdefaultValueExpression().isEmpty(); eldar@288: else eldar@288: hasDefault = false; eldar@288: j++; eldar@288: } while (hasDefault); eldar@288: } eldar@288: } eldar@288: s << INDENT << "];" << endl << endl; eldar@288: } eldar@288: eldar@105: void DGenerator::writeQObjectFunctions(QTextStream &s, const AbstractMetaClass *d_class) eldar@105: { maxter@357: AbstractMetaFunctionList d_funcs_gen = generatedClassFunctions(d_class); maxter@357: AbstractMetaFunctionList slot_funcs; maxter@357: for (int i=0; iisSlot()) eldar@288: slot_funcs += function; maxter@357: } maxter@357: writeMetaMethodSignatures(s, "__slotSignatures", slot_funcs); maxter@357: maxter@357: if (d_class->isAbstract()) maxter@357: s << "alias " << d_class->name() << "_ConcreteWrapper ConcreteType;" << endl; maxter@357: maxter@357: if (!d_class->isFinal()) { maxter@357: s << " int qt_metacall(QMetaObject.Call _c, int _id, void **_a) {" << endl maxter@357: << " return qtd_" << d_class->name() << "_qt_metacall(__nativeId, _c, _id, _a);" << endl maxter@357: << " }" << endl << endl; maxter@357: } maxter@357: maxter@358: s << " private static __gshared QMetaObject staticMetaObject_;" << endl maxter@357: << " protected static void setStaticMetaObject(QMetaObject m) {" << endl maxter@358: << " staticMetaObject_ = m;" << endl maxter@357: << " }" << endl << endl maxter@357: maxter@357: << " @property QMetaObject metaObject() {" << endl maxter@358: << " return staticMetaObject_;" << endl maxter@357: << " }" << endl << endl maxter@357: maxter@357: << " @property static QMetaObject staticMetaObject() {" << endl maxter@358: << " if (!staticMetaObject_)" << endl maxter@357: << " QMetaObject.create!(typeof(this))(qtd_" << d_class->name() << "_staticMetaObject());" << endl maxter@358: << " return staticMetaObject_;" << endl maxter@357: << " }" << endl << endl maxter@357: maxter@357: << " static " << d_class->name() << " __getObject(void* nativeId) {" << endl maxter@358: << " return static_cast!(" << d_class->name() << ")(staticMetaObject_.getObject(nativeId));" << endl maxter@357: << " }" << endl << endl maxter@357: maxter@357: << " /* internal */ static void __createEntity(void* nativeId, void* dId) {" << endl maxter@357: << " return qtd_" << d_class->name() << "_createEntity(nativeId, dId);" << endl maxter@357: << " }" << endl << endl maxter@357: maxter@357: << " /* internal */ static void _populateMetaInfo() {" << endl maxter@357: << " int index;" << endl << endl; maxter@357: maxter@357: AbstractMetaFunctionList signal_funcs = signalFunctions(d_class, false); maxter@357: maxter@357: int staticId = 0; maxter@357: for (int i = 0; i < signal_funcs.size(); ++i) maxter@357: { eldar@288: int j = 0; eldar@288: bool hasDefault = false; eldar@288: do // need this to look for default arguments and generate extra signatures eldar@288: { eldar@288: AbstractMetaFunction *fn = signal_funcs.at(i); maxter@358: s << " index = staticMetaObject_.indexOfMethod_Cpp(__signalSignatures[" << staticId << "]);" << endl maxter@358: << " staticMetaObject_.addMethod(new QMetaSignal(signature!("; eldar@288: writeMetaMethodArguments(s, fn, j); maxter@357: s << ")(\"" << fn->name() << "\"), index));" << endl << endl; eldar@288: AbstractMetaArgumentList args = fn->arguments(); eldar@288: if(args.size() && jdefaultValueExpression().isEmpty(); eldar@288: else eldar@288: hasDefault = false; eldar@288: j++; eldar@288: staticId++; eldar@288: } while (hasDefault); maxter@357: } maxter@357: maxter@357: staticId = 0; maxter@357: for (int i = 0; i < slot_funcs.size(); ++i) maxter@357: { eldar@288: int j = 0; eldar@288: bool hasDefault = false; eldar@288: do // need this to look for default arguments and generate extra signatures eldar@288: { eldar@288: AbstractMetaFunction *fn = slot_funcs.at(i); maxter@358: s << " index = staticMetaObject_.indexOfMethod_Cpp(__slotSignatures[" << staticId << "]);" << endl maxter@358: << " staticMetaObject_.addMethod(new QMetaSlot(signature!("; eldar@288: writeMetaMethodArguments(s, fn, j); maxter@357: s << ")(\"" << fn->name() << "\"), index));" << endl << endl; eldar@288: AbstractMetaArgumentList args = fn->arguments(); eldar@288: if(args.size() && jdefaultValueExpression().isEmpty(); eldar@288: else eldar@288: hasDefault = false; eldar@288: j++; eldar@288: staticId++; eldar@288: } while (hasDefault); maxter@357: } maxter@357: maxter@357: s << " }" << endl << endl; maxter@357: maxter@357: s << INDENT << "mixin Q_OBJECT_BIND;" << endl << endl; eldar@105: } eldar@105: maxter@355: void DGenerator::marshalFromCppToD(QTextStream &s, const ComplexTypeEntry* ctype) mandel@1: { mandel@1: if(ctype->isQObject()) { mandel@1: QString type_name = ctype->name(); maxter@253: if (ctype->isAbstract()) maxter@253: type_name += "_ConcreteWrapper"; maxter@253: s << "return " << type_name << ".__getObject(ret);" << endl; eldar@152: } else if (ctype->isValue() && !ctype->isStructInD()) { maxter@253: s << INDENT << "return new " << ctype->name() << "(ret);" << endl; eldar@152: } else if (ctype->isVariant()) { maxter@253: s << INDENT << "return new QVariant(ret);" << endl; eldar@152: } else if (ctype->name() == "QModelIndex" || ctype->isStructInD()) { maxter@253: s << INDENT << "return ret;" << endl; eldar@152: } else if (ctype->isObject()) { mandel@1: QString type_name = ctype->name(); maxter@253: s << "return qtd_" << type_name << "_from_ptr(ret);" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: void DGenerator::writeNativeField(QTextStream &s, const AbstractMetaField *field) mandel@1: { mandel@1: Q_ASSERT(field->isPublic() || field->isProtected()); mandel@1: mandel@1: const AbstractMetaClass *declaringClass = field->enclosingClass(); mandel@1: mandel@1: FieldModification mod = declaringClass->typeEntry()->fieldModification(field->name()); mandel@1: mandel@1: // Set function mandel@1: if (mod.isWritable() && !field->type()->isConstant()) { mandel@1: const AbstractMetaFunction *setter = field->setter(); mandel@1: if (declaringClass->hasFunction(setter)) { mandel@1: QString warning = mandel@1: QString("class '%1' already has setter '%2' for public field '%3'") mandel@1: .arg(declaringClass->name()).arg(setter->name()).arg(field->name()); mandel@1: ReportHandler::warning(warning); mandel@1: } else { mandel@1: if (!notWrappedYet(setter)) mandel@1: writePrivateNativeFunction(s, setter); mandel@1: } mandel@1: } mandel@1: mandel@1: // Get function mandel@1: const AbstractMetaFunction *getter = field->getter(); mandel@1: if (mod.isReadable()) { mandel@1: if (declaringClass->hasFunction(getter)) { mandel@1: QString warning = mandel@1: QString("class '%1' already has getter '%2' for public field '%3'") mandel@1: .arg(declaringClass->name()).arg(getter->name()).arg(field->name()); mandel@1: ReportHandler::warning(warning); mandel@1: } else { mandel@1: if (!notWrappedYet(getter)) mandel@1: writePrivateNativeFunction(s, getter); mandel@1: } mandel@1: } mandel@1: } mandel@1: maxter@253: void DGenerator::writeSignalSignatures(QTextStream &s, const AbstractMetaClass *d_class, AbstractMetaFunctionList signal_funcs) mandel@1: { eldar@288: writeMetaMethodSignatures(s, "__signalSignatures", signal_funcs); maxter@253: maxter@253: s << INDENT << "int signalSignature(int signalId, ref stringz signature) {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); spambox@342: maxter@253: if (d_class->name() != "QObject") maxter@253: { maxter@253: s << INDENT << "signalId = super.signalSignature(signalId, signature);" << endl maxter@253: << INDENT << "if (signature)" << endl spambox@342: << INDENT << " return signalId;" << endl; maxter@253: } spambox@342: maxter@253: s << INDENT << "if (signalId < __signalSignatures.length)" << endl maxter@253: << INDENT << " signature = __signalSignatures[signalId].ptr;" << endl maxter@253: << INDENT << "else" << endl maxter@253: << INDENT << " signalId -= __signalSignatures.length;" << endl maxter@253: << INDENT << "return signalId;" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: } mandel@1: eldar@288: void DGenerator::writeMetaMethodArguments(QTextStream &s, const AbstractMetaFunction *d_function, int reduce) eldar@288: { eldar@288: bool withDefArgs = false; eldar@288: if(reduce == -1) { eldar@288: reduce = 0; eldar@288: withDefArgs = true; eldar@288: } eldar@288: eldar@288: AbstractMetaArgumentList arguments = d_function->arguments(); eldar@288: int sz = arguments.count() - reduce; eldar@288: eldar@288: for (int i=0; itypeReplaced(i+1); eldar@288: eldar@288: if (modifiedType.isEmpty()) eldar@288: s << translateType(arguments.at(i)->type(), d_function->implementingClass(), BoxedPrimitive); eldar@288: else eldar@288: s << modifiedType; eldar@288: eldar@288: if (!arguments.at(i)->defaultValueExpression().isEmpty() && withDefArgs) // qtd eldar@288: s << " = " + arguments.at(i)->defaultValueExpression(); eldar@288: } eldar@288: } eldar@288: mandel@1: void DGenerator::writeSignal(QTextStream &s, const AbstractMetaFunction *d_function) mandel@1: { mandel@1: Q_ASSERT(d_function->isSignal()); eldar_ins@320: /* eldar@288: s << INDENT << "mixin BindQtSignal!(\"" << d_function->name() << "("; eldar@288: eldar@288: writeMetaMethodArguments(s, d_function); eldar@288: eldar@288: s << ")\");" << endl; eldar_ins@320: */ mandel@1: } mandel@1: mandel@1: void DGenerator::writeShellVirtualFunction(QTextStream &s, const AbstractMetaFunction *d_function, mandel@1: const AbstractMetaClass *implementor, int id) mandel@1: { mandel@1: Q_UNUSED(id); mandel@1: Q_UNUSED(implementor); mandel@1: maxter@355: if (implementor != d_function->declaringClass()) maxter@355: return; maxter@355: maxter@355: CppImplGenerator::writeVirtualDispatchFunction(s, d_function, implementor, true); mandel@1: s << "{" << endl; mandel@1: mandel@1: const AbstractMetaClass *own_class = d_function->ownerClass(); mandel@1: maxter@355: InterfaceTypeEntry *ite = own_class->typeEntry()->designatedInterface(); maxter@355: if (ite) maxter@355: s << INDENT << "auto d_object = cast(" << ite->name() << ")cast(Object) dId;" << endl; maxter@355: else maxter@355: s << INDENT << "auto d_object = cast(" << own_class->name() << ") dId;" << endl; mandel@1: mandel@1: // the function arguments mandel@1: AbstractMetaArgumentList arguments = d_function->arguments(); mandel@1: foreach (const AbstractMetaArgument *argument, arguments) mandel@1: if (!d_function->argumentRemoved(argument->argumentIndex() + 1)) { mandel@1: QString arg_name = argument->indexedName(); mandel@1: AbstractMetaType *type = argument->type(); mandel@1: // if has QString argument we have to pass char* and str.length to QString constructor mandel@1: { eldar@298: if (type->isContainer()) eldar@298: { eldar@298: if ( ((const ContainerTypeEntry *)type->typeEntry())->isQList() ) { eldar@298: s << INDENT; eldar@298: s << "auto " << arg_name << "_d_ref = cast(" << translateType(type, implementor) << "*)" << arg_name << ";" << endl; eldar@298: } eldar@298: } else if(type->isEnum()) mandel@1: s << INDENT << "auto " << arg_name << "_enum = cast(" mandel@1: << type->typeEntry()->qualifiedTargetLangName() << ") " << arg_name << ";"; eldar@33: else if (type->typeEntry()->qualifiedCppName() == "QChar") eldar@33: s << INDENT << "auto " << arg_name << "_d_ref = cast(wchar" << QString(type->actualIndirections(), '*') eldar@33: << ") " << arg_name << ";"; mandel@1: else if (type->isTargetLangString()) eldar@188: s << INDENT << "string " << arg_name << "_d_ref = toUTF8(" mandel@1: << arg_name << "[0.." << arg_name << "_size]);"; mandel@1: else if (type->typeEntry()->isValue() && type->isNativePointer() && type->typeEntry()->name() == "QString") { eldar_ins@302: s << INDENT << "auto " << arg_name << "_d_qstr = QStringUtil(" << arg_name << ", true);" << endl mandel@1: << INDENT << "string " << arg_name << "_d_ref = " << arg_name << "_d_qstr.toNativeString();"; mandel@1: } else if(type->isVariant()) maxter@253: s << INDENT << "scope " << arg_name << "_d_ref = new QVariant(" << arg_name << ", QtdObjectFlags.nativeOwnership);"; mandel@1: else if (type->typeEntry()->isStructInD()) mandel@1: continue; mandel@1: else if (!type->hasNativeId() && !(type->typeEntry()->isValue() && type->isNativePointer())) mandel@1: continue; mandel@1: else if(type->isObject() mandel@1: || (type->typeEntry()->isValue() && type->isNativePointer()) mandel@1: || type->isValue() || type->isVariant()) { mandel@1: QString type_name = type->typeEntry()->name(); mandel@1: const ComplexTypeEntry *ctype = static_cast(type->typeEntry()); mandel@1: if(ctype->isAbstract()) mandel@1: type_name = type_name + "_ConcreteWrapper"; maxter@253: s << INDENT << "scope " << arg_name << "_d_ref = new " << type_name << "(" << arg_name << ", QtdObjectFlags.nativeOwnership);"; mandel@1: } mandel@1: else if (type->isQObject()) { mandel@1: QString type_name = type->name(); mandel@1: const ComplexTypeEntry *ctype = static_cast(type->typeEntry()); mandel@1: if(ctype->isAbstract()) mandel@1: type_name = type_name + "_ConcreteWrapper"; eldar@184: maxter@253: s << INDENT << "scope " << arg_name << "_d_ref = new " << type_name << "(" << arg_name << ", QtdObjectFlags.nativeOwnership);" << endl; mandel@1: } mandel@1: s << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: s << INDENT; mandel@1: AbstractMetaType *return_type = d_function->type(); mandel@1: QString new_return_type = QString(d_function->typeReplaced(0)).replace('$', '.'); mandel@1: bool has_return_type = new_return_type != "void" mandel@1: && (!new_return_type.isEmpty() || return_type != 0); mandel@1: if(has_return_type) { mandel@1: AbstractMetaType *f_type = d_function->type(); mandel@1: if(f_type && (f_type->isObject() || f_type->isQObject() || f_type->isVariant() || mandel@1: (f_type->isValue() && !f_type->typeEntry()->isStructInD()))) mandel@1: { mandel@1: QString f_type_name = f_type->name(); mandel@1: if(f_type->typeEntry()->designatedInterface()) mandel@1: f_type_name = f_type->typeEntry()->designatedInterface()->name(); mandel@1: s << f_type_name << " ret_value = "; mandel@1: } mandel@1: else if (f_type && f_type->isTargetLangString()) mandel@1: s << "string _d_str = "; eldar@81: else if (f_type && (f_type->name() == "QModelIndex" || f_type->typeEntry()->isStructInD())) mandel@1: s << "*__d_return_value = "; mandel@1: else mandel@1: s << "auto return_value = "; mandel@1: } mandel@1: s << "d_object." << d_function->name() << "("; mandel@1: mandel@1: uint nativeArgCount = 0; mandel@1: foreach (const AbstractMetaArgument *argument, arguments) mandel@1: if (!d_function->argumentRemoved(argument->argumentIndex() + 1)) { mandel@1: QString arg_name = argument->indexedName(); mandel@1: const AbstractMetaType *type = argument->type(); mandel@1: mandel@1: if (nativeArgCount > 0) mandel@1: s << "," << " "; mandel@1: mandel@1: QString modified_type = d_function->typeReplaced(argument->argumentIndex() + 1); mandel@1: if (!modified_type.isEmpty()) mandel@1: modified_type = modified_type.replace('$', '.'); mandel@1: mandel@1: if (modified_type == "string" /* && type->fullName() == "char" */) mandel@1: s << "fromStringz(" << arg_name << ")"; eldar@298: else eldar@298: { mandel@1: if(type->isContainer() mandel@1: || (type->isReference() && type->typeEntry()->isStructInD())) mandel@1: s << "*"; mandel@1: s << arg_name; eldar@298: if (type->isContainer() && ((const ContainerTypeEntry *)type->typeEntry())->isQList() ) eldar@298: s << "_d_ref"; mandel@1: } mandel@1: if (type->typeEntry()->isStructInD()) ; mandel@1: else if (type->isQObject() || type->isObject() mandel@1: || (type->typeEntry()->isValue() && type->isNativePointer()) mandel@1: || type->isValue() mandel@1: || type->isTargetLangString() || type->isVariant()) mandel@1: s << "_d_ref"; mandel@1: else if(type->isEnum()) mandel@1: s << "_enum"; mandel@1: mandel@1: nativeArgCount++; mandel@1: } mandel@1: s << ");" << endl; mandel@1: mandel@1: // check for arguments that may return value mandel@1: foreach (const AbstractMetaArgument *argument, arguments) mandel@1: if (!d_function->argumentRemoved(argument->argumentIndex() + 1)) { mandel@1: QString arg_name = argument->indexedName(); mandel@1: AbstractMetaType *type = argument->type(); mandel@1: mandel@1: if (type->typeEntry()->isValue() && type->isNativePointer() && type->typeEntry()->name() == "QString") mandel@1: s << INDENT << arg_name << "_d_qstr.assign(" << arg_name << "_d_ref);" << endl; mandel@1: } mandel@1: mandel@1: if(has_return_type) { mandel@1: AbstractMetaType *f_type = d_function->type(); mandel@1: if(f_type) { mandel@1: if(f_type->isObject() || f_type->isQObject() || f_type->isVariant() || mandel@1: (f_type->isValue() && !f_type->typeEntry()->isStructInD())) { maxter@253: QString native_id = "__nativeId"; mandel@1: if (f_type->typeEntry()->designatedInterface()) mandel@1: native_id = "__ptr_" + f_type->typeEntry()->designatedInterface()->name(); mandel@1: s << INDENT << "return ret_value is null? null : ret_value." << native_id << ";" << endl; mandel@1: } else if (f_type->isTargetLangString()) eldar@104: s << INDENT << "*ret_str = _d_str;" << endl; eldar@298: else if (f_type->isContainer()) { eldar@298: if (isNativeContainer(f_type)) eldar@298: s << INDENT << "*__d_arr = return_value;" << endl; eldar@298: else eldar@298: s << INDENT << "*__d_arr_ptr = return_value.ptr;" << endl eldar@298: << INDENT << "*__d_arr_size = return_value.length;" << endl; eldar@298: } else if (f_type->name() == "QModelIndex" || f_type->typeEntry()->isStructInD()) mandel@1: ; mandel@1: else mandel@1: s << INDENT << "return return_value;" << endl; mandel@1: } else mandel@1: s << INDENT << "return return_value;" << endl; mandel@1: mandel@1: } mandel@1: mandel@1: s << "}" << endl << endl; mandel@1: } mandel@1: mandel@1: void DGenerator::generate() mandel@1: { mandel@1: // qtd mandel@1: // code for including classses in 1 module for avoiding circular imports mandel@1: foreach (AbstractMetaClass *cls, m_classes) { mandel@1: const ComplexTypeEntry *ctype = cls->typeEntry(); mandel@1: mandel@1: if (!cls->isInterface() && cls->isAbstract()) { mandel@1: ComplexTypeEntry *ctype_m = (ComplexTypeEntry *)ctype; mandel@1: ctype_m->setAbstract(true); mandel@1: } mandel@1: mandel@1: foreach(QString child, ctype->includedClasses) { mandel@1: ComplexTypeEntry *ctype_child = TypeDatabase::instance()->findComplexType(child); mandel@1: ctype_child->addedTo = cls->name(); mandel@1: } mandel@1: eldar@152: /* we don't need this anymore eldar@110: // generate QObject conversion functions only those that are required eldar@110: AbstractMetaFunctionList d_funcs = cls->functionsInTargetLang(); eldar@110: for (int i=0; itype(); eldar@110: if (!f_type) eldar@110: continue; eldar@110: if (f_type->isQObject() || f_type->isObject()) { eldar@110: const ComplexTypeEntry* cte = static_cast(f_type->typeEntry()); eldar@110: AbstractMetaClass* d_class = ClassFromEntry::get(cte); eldar@110: if (d_class) eldar@110: d_class->needsConversionFunc = true; eldar@110: } eldar@152: }*/ mandel@1: } mandel@1: mandel@1: Generator::generate(); mandel@1: mandel@1: { mandel@1: const AbstractMetaClass *last_class = 0; mandel@1: QFile file("mjb_nativepointer_api.log"); mandel@1: if (file.open(QFile::WriteOnly)) { mandel@1: QTextStream s(&file); mandel@1: mandel@1: AbstractMetaFunctionList nativepointer_functions; mandel@1: for (int i=0; i(m_nativepointer_functions[i]); mandel@1: if (f->ownerClass() == f->declaringClass() || f->isFinal()) mandel@1: nativepointer_functions.append(f); mandel@1: } mandel@1: mandel@1: s << "Number of public or protected functions with QNativePointer API: " << nativepointer_functions.size() << endl; mandel@1: foreach (const AbstractMetaFunction *f, nativepointer_functions) { mandel@1: if (last_class != f->ownerClass()) { mandel@1: last_class = f->ownerClass(); mandel@1: s << endl << endl<< "Class " << last_class->name() << ":" << endl; mandel@1: s << "---------------------------------------------------------------------------------" mandel@1: << endl; mandel@1: } mandel@1: mandel@1: s << f->minimalSignature() << endl; mandel@1: } mandel@1: mandel@1: m_nativepointer_functions.clear(); } mandel@1: } mandel@1: mandel@1: { mandel@1: const AbstractMetaClass *last_class = 0; mandel@1: QFile file("mjb_object_type_usage.log"); mandel@1: if (file.open(QFile::WriteOnly)) { mandel@1: QTextStream s(&file); mandel@1: mandel@1: AbstractMetaFunctionList resettable_object_functions; mandel@1: for (int i=0; i(m_resettable_object_functions[i]); mandel@1: if (f->ownerClass() == f->declaringClass() || f->isFinal()) mandel@1: resettable_object_functions.append(f); mandel@1: } mandel@1: mandel@1: s << "Number of public or protected functions that return a non-QObject object type, or that are virtual and take a non-QObject object type argument: " << resettable_object_functions.size() << endl; mandel@1: foreach (const AbstractMetaFunction *f, resettable_object_functions) { mandel@1: if (last_class != f->ownerClass()) { mandel@1: last_class = f->ownerClass(); mandel@1: s << endl << endl<< "Class " << last_class->name() << ":" << endl; mandel@1: s << "---------------------------------------------------------------------------------" mandel@1: << endl; mandel@1: } mandel@1: mandel@1: s << f->minimalSignature() << endl; mandel@1: } mandel@1: mandel@1: m_resettable_object_functions.clear(); } mandel@1: } mandel@1: mandel@1: { mandel@1: QFile file("mjb_reference_count_candidates.log"); mandel@1: if (file.open(QFile::WriteOnly)) { mandel@1: QTextStream s(&file); mandel@1: mandel@1: s << "The following functions have a signature pattern which may imply that" << endl mandel@1: << "they need to apply reference counting to their arguments (" mandel@1: << m_reference_count_candidate_functions.size() << " functions) : " << endl; mandel@1: mandel@1: foreach (const AbstractMetaFunction *f, m_reference_count_candidate_functions) { mandel@1: s << f->implementingClass()->fullName() << " : " << f->minimalSignature() << endl; mandel@1: } mandel@1: } mandel@1: file.close(); mandel@1: } mandel@1: } mandel@1: mandel@1: void DGenerator::writeFunctionAttributes(QTextStream &s, const AbstractMetaFunction *d_function, mandel@1: uint included_attributes, uint excluded_attributes, mandel@1: uint options) mandel@1: { mandel@1: uint attr = d_function->attributes() & (~excluded_attributes) | included_attributes; mandel@1: mandel@1: if ((attr & AbstractMetaAttributes::Public) || (attr & AbstractMetaAttributes::Protected)) { mandel@1: mandel@1: // Does the function use native pointer API? mandel@1: bool nativePointer = d_function->type() && d_function->type()->isNativePointer() mandel@1: && d_function->typeReplaced(0).isEmpty(); mandel@1: mandel@1: // Does the function need to be considered for resetting the Java objects after use? mandel@1: bool resettableObject = false; mandel@1: mandel@1: if (!nativePointer mandel@1: && d_function->type() mandel@1: && d_function->type()->hasInstantiations() mandel@1: && d_function->typeReplaced(0).isEmpty()) { mandel@1: mandel@1: QList instantiations = d_function->type()->instantiations(); mandel@1: mandel@1: foreach (const AbstractMetaType *type, instantiations) { mandel@1: if (type && type->isNativePointer()) { mandel@1: nativePointer = true; mandel@1: break; mandel@1: } mandel@1: } mandel@1: mandel@1: } mandel@1: mandel@1: AbstractMetaArgumentList arguments = d_function->arguments(); mandel@1: if (!nativePointer || (!resettableObject && !d_function->isFinal())) { mandel@1: foreach (const AbstractMetaArgument *argument, arguments) { mandel@1: if (!d_function->argumentRemoved(argument->argumentIndex()+1) mandel@1: && d_function->typeReplaced(argument->argumentIndex()+1).isEmpty()) { mandel@1: mandel@1: if (argument->type()->isNativePointer()) { mandel@1: mandel@1: nativePointer = true; mandel@1: if (resettableObject) break ; mandel@1: mandel@1: } else if (!d_function->isFinalInTargetLang() mandel@1: && argument->type()->isObject() mandel@1: && !argument->type()->isQObject() mandel@1: && !d_function->resetObjectAfterUse(argument->argumentIndex()+1) mandel@1: && d_function->ownership(d_function->declaringClass(), TypeSystem::ShellCode, argument->argumentIndex()+1) == TypeSystem::InvalidOwnership) { mandel@1: mandel@1: resettableObject = true; mandel@1: if (nativePointer) break ; mandel@1: mandel@1: } else if (argument->type()->hasInstantiations()) { mandel@1: mandel@1: QList instantiations = argument->type()->instantiations(); mandel@1: foreach (AbstractMetaType *type, instantiations) { mandel@1: if (type && type->isNativePointer()) { mandel@1: nativePointer = true; mandel@1: if (resettableObject) break; mandel@1: } else if (!d_function->isFinal() mandel@1: && type mandel@1: && type->isObject() mandel@1: && !type->isQObject() mandel@1: && !d_function->resetObjectAfterUse(argument->argumentIndex()+1)) { mandel@1: resettableObject = true; mandel@1: if (nativePointer) break ; mandel@1: } mandel@1: } mandel@1: mandel@1: if (nativePointer && resettableObject) mandel@1: break; mandel@1: mandel@1: } mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: if (nativePointer && !m_nativepointer_functions.contains(d_function)) mandel@1: m_nativepointer_functions.append(d_function); mandel@1: if (resettableObject && !m_resettable_object_functions.contains(d_function)) mandel@1: m_resettable_object_functions.append(d_function); mandel@1: } mandel@1: mandel@1: if ((options & SkipAttributes) == 0) { mandel@1: if (d_function->isEmptyFunction() mandel@1: || d_function->isDeprecated()) s << INDENT << "deprecated "; mandel@1: /* mandel@1: bool needsSuppressUnusedWarning = TypeDatabase::instance()->includeEclipseWarnings() mandel@1: && d_function->isSignal() mandel@1: && (((excluded_attributes & AbstractMetaAttributes::Private) == 0) mandel@1: && (d_function->isPrivate() mandel@1: || ((included_attributes & AbstractMetaAttributes::Private) != 0))); mandel@1: mandel@1: if (needsSuppressUnusedWarning && d_function->needsSuppressUncheckedWarning()) { mandel@1: s << INDENT<< "@SuppressWarnings({\"unchecked\", \"unused\"})" << endl; mandel@1: } else if (d_function->needsSuppressUncheckedWarning()) { mandel@1: s << INDENT<< "@SuppressWarnings(\"unchecked\")" << endl; mandel@1: } else if (needsSuppressUnusedWarning) { mandel@1: s << INDENT<< "@SuppressWarnings(\"unused\")" << endl; mandel@1: } mandel@1: mandel@1: if (!(attr & NoBlockedSlot) mandel@1: && !d_function->isConstructor() mandel@1: && !d_function->isSlot() mandel@1: && !d_function->isSignal() mandel@1: && !d_function->isStatic() mandel@1: && !(included_attributes & AbstractMetaAttributes::Static)) mandel@1: s << INDENT << "@QtBlockedSlot" << endl; mandel@1: */ mandel@1: if (!(options & ExternC)) mandel@1: s << INDENT; mandel@1: mandel@1: if (attr & AbstractMetaAttributes::Public) s << "public "; mandel@1: else if (attr & AbstractMetaAttributes::Protected) s << "protected "; mandel@1: else if (attr & AbstractMetaAttributes::Private) s << "private "; mandel@1: else if (attr & AbstractMetaAttributes::Native) s << "private extern(C) "; mandel@1: bool isStatic = (attr & AbstractMetaAttributes::Static); mandel@1: mandel@1: if (attr & AbstractMetaAttributes::Native) ; mandel@1: else if (!isStatic && (attr & AbstractMetaAttributes::FinalInTargetLang)) s << "final "; mandel@1: else if (!isStatic && (attr & AbstractMetaAttributes::Abstract)) s << "abstract "; mandel@1: mandel@1: if (isStatic && !(options & ExternC)) s << "static "; mandel@1: } mandel@1: mandel@1: if ((options & SkipReturnType) == 0) { mandel@1: QString modified_type = d_function->typeReplaced(0); mandel@1: if (options & ExternC) { mandel@1: uint options = 0x0004; // qtd externC mandel@1: s << CppImplGenerator::jniReturnName(d_function, options, true) << " "; mandel@1: } mandel@1: else if (modified_type.isEmpty()) mandel@1: s << translateType(d_function->type(), d_function->implementingClass(), (Option) options); mandel@1: else mandel@1: s << modified_type.replace('$', '.'); mandel@1: s << " "; mandel@1: } mandel@1: mandel@1: } mandel@1: mandel@1: void DGenerator::writeConstructorContents(QTextStream &s, const AbstractMetaFunction *d_function) mandel@1: { mandel@1: // Write constructor mandel@1: s << " {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: bool shellClass = d_function->ownerClass()->generateShellClass(); eldar@223: mandel@1: writeJavaCallThroughContents(s, d_function); mandel@1: mandel@1: // Write out expense checks if present... mandel@1: const AbstractMetaClass *d_class = d_function->implementingClass(); mandel@1: const ComplexTypeEntry *te = d_class->typeEntry(); mandel@1: if (te->expensePolicy().isValid()) { mandel@1: s << endl; mandel@1: const ExpensePolicy &ep = te->expensePolicy(); mandel@1: s << INDENT << "qt.GeneratorUtilities.countExpense(" << d_class->fullName() mandel@1: << ".class, " << ep.cost << ", " << ep.limit << ");" << endl; mandel@1: } mandel@1: mandel@1: foreach (CodeSnip snip, te->codeSnips()) { mandel@1: if (snip.language == TypeSystem::Constructors) { mandel@1: snip.formattedCode(s, INDENT); mandel@1: } mandel@1: } mandel@1: maxter@253: s << INDENT << "this(ret);" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl << endl; mandel@1: mandel@1: /* qtd // Write native constructor mandel@1: if (d_function->jumpTableId() == -1) mandel@1: writePrivateNativeFunction(s, d_function); mandel@1: */ mandel@1: } mandel@1: mandel@1: void DGenerator::writeFunctionArguments(QTextStream &s, const AbstractMetaFunction *d_function, mandel@1: int argument_count, uint options) mandel@1: { mandel@1: AbstractMetaArgumentList arguments = d_function->arguments(); mandel@1: mandel@1: if (argument_count == -1) mandel@1: argument_count = arguments.size(); mandel@1: mandel@1: for (int i=0; iargumentRemoved(i+1)) { mandel@1: if (i != 0) mandel@1: s << ", "; mandel@1: writeArgument(s, d_function, arguments.at(i), options); mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: mandel@1: void DGenerator::writeExtraFunctions(QTextStream &s, const AbstractMetaClass *d_class) mandel@1: { mandel@1: const ComplexTypeEntry *class_type = d_class->typeEntry(); mandel@1: Q_ASSERT(class_type); mandel@1: mandel@1: CodeSnipList code_snips = class_type->codeSnips(); mandel@1: foreach (const CodeSnip &snip, code_snips) { mandel@1: if ((!d_class->isInterface() && snip.language == TypeSystem::TargetLangCode) mandel@1: || (d_class->isInterface() && snip.language == TypeSystem::Interface)) { mandel@1: s << endl; mandel@1: snip.formattedCode(s, INDENT); mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: mandel@1: void DGenerator::writeToStringFunction(QTextStream &s, const AbstractMetaClass *d_class) mandel@1: { mandel@1: bool generate = d_class->hasToStringCapability() && !d_class->hasDefaultToStringFunction(); mandel@1: bool core = d_class->package() == QLatin1String("qt.core"); mandel@1: bool qevent = false; mandel@1: mandel@1: const AbstractMetaClass *cls = d_class; mandel@1: while (cls) { mandel@1: if (cls->name() == "QEvent") { mandel@1: qevent = true; mandel@1: break; mandel@1: } mandel@1: cls = cls->baseClass(); mandel@1: } mandel@1: mandel@1: if (generate || qevent) { mandel@1: mandel@1: if (qevent && core) { mandel@1: s << endl mandel@1: << " @Override" << endl mandel@1: << " public String toString() {" << endl mandel@1: << " return getClass().getSimpleName() + \"(type=\" + type().name() + \")\";" << endl mandel@1: << " }" << endl; mandel@1: } else { mandel@1: s << endl mandel@1: << " @Override" << endl mandel@1: << " public String toString() {" << endl maxter@253: << " if (__nativeId == 0)" << endl mandel@1: << " throw new QNoNativeResourcesException(\"Function call on incomplete object of type: \" +getClass().getName());" << endl mandel@1: << " return __qt_toString(nativeId());" << endl mandel@1: << " }" << endl mandel@1: << " native String __qt_toString(long __this_nativeId);" << endl; mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: void DGenerator::writeCloneFunction(QTextStream &s, const AbstractMetaClass *d_class) mandel@1: { mandel@1: s << endl mandel@1: << " @Override" << endl mandel@1: << " public " << d_class->name() << " clone() {" << endl mandel@1: << " if (nativeId() == 0)" << endl mandel@1: << " throw new QNoNativeResourcesException(\"Function call on incomplete object of type: \" +getClass().getName());" << endl mandel@1: << " return __qt_clone(nativeId());" << endl mandel@1: << " }" << endl mandel@1: << " native " << d_class->name() << " __qt_clone(long __this_nativeId);" << endl; mandel@1: } mandel@1: maxter@357: void DGenerator::writeDExport(QTextStream &s, QString retType, QString name, QString args, QString funcBody) maxter@357: { maxter@357: QString qtdExtern = "extern (C)"; // TODO: should be settable via a generator switch maxter@357: if (cpp_shared) { maxter@357: s << QString( maxter@357: " %5 %1 qtd_export_%2(%3) { %4 }\n" maxter@357: " %5 export void qtd_set_%2(VoidFunc func);\n" maxter@357: " static this() { qtd_set_%2(cast(VoidFunc)&qtd_export_%2); }\n") maxter@357: .arg(retType, name, args, funcBody, qtdExtern); maxter@357: } else { maxter@357: s << QString("%5 %1 qtd_%2(%3) { %4 }\n") maxter@357: .arg(retType, name, args, funcBody, qtdExtern); maxter@357: } maxter@357: } maxter@357: mandel@1: ClassFromEntry* ClassFromEntry::m_instance = NULL; mandel@1: mandel@1: ClassFromEntry::ClassFromEntry() mandel@1: { eldar@110: } eldar@110: eldar@110: AbstractMetaClass* ClassFromEntry::get(const TypeEntry *ctype) eldar@110: { eldar@110: if(!m_instance) eldar@110: return NULL; eldar@110: eldar@110: return m_instance->classFromEntry[ctype]; eldar@110: } eldar@110: eldar@110: void ClassFromEntry::construct(const AbstractMetaClassList &classes) eldar@110: { eldar@110: if(!m_instance) { eldar@110: m_instance = new ClassFromEntry; eldar@110: m_instance->setClasses(classes); eldar@110: m_instance->buildHash(); eldar@110: } eldar@110: } eldar@110: eldar@110: void ClassFromEntry::buildHash() eldar@110: { mandel@1: foreach (AbstractMetaClass *cls, m_classes) { mandel@1: const ComplexTypeEntry *ctype = cls->typeEntry(); mandel@1: classFromEntry[ctype] = cls; mandel@1: } mandel@1: } mandel@1: eldar@110: void ClassFromEntry::print(QTextStream &s) mandel@1: { maxter@357: s << m_instance->m_classes.size(); eldar@110: foreach (AbstractMetaClass *cls, m_instance->m_classes) { eldar@110: s << cls->name() << endl; eldar@110: } mandel@1: } eldar@110: