aboutsummaryrefslogtreecommitdiffstats
path: root/shibokengenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'shibokengenerator.cpp')
-rw-r--r--shibokengenerator.cpp829
1 files changed, 829 insertions, 0 deletions
diff --git a/shibokengenerator.cpp b/shibokengenerator.cpp
new file mode 100644
index 000000000..89b5e7b4e
--- /dev/null
+++ b/shibokengenerator.cpp
@@ -0,0 +1,829 @@
+/*
+ * This file is part of the Shiboken Python Binding Generator project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "shibokengenerator.h"
+#include <reporthandler.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+
+#define NULL_VALUE "NULL"
+#define COMMENT_LINE_WIDTH 77
+
+static Indentor INDENT;
+static void dumpFunction(AbstractMetaFunctionList lst);
+
+QHash<QString, QString> ShibokenGenerator::m_pythonPrimitiveTypeName = QHash<QString, QString>();
+QHash<QString, QString> ShibokenGenerator::m_pythonOperators = QHash<QString, QString>();
+QHash<QString, QString> ShibokenGenerator::m_formatUnits = QHash<QString, QString>();
+
+ShibokenGenerator::ShibokenGenerator() : Generator()
+{
+ if (m_pythonPrimitiveTypeName.isEmpty())
+ ShibokenGenerator::initPrimitiveTypesCorrespondences();
+}
+
+void ShibokenGenerator::initPrimitiveTypesCorrespondences()
+{
+ // Python primitive types names
+ m_pythonPrimitiveTypeName.clear();
+
+ // PyBool
+ m_pythonPrimitiveTypeName["bool"] = "PyBool";
+
+ // PyInt
+ m_pythonPrimitiveTypeName["char"] = "PyInt";
+ m_pythonPrimitiveTypeName["unsigned char"] = "PyInt";
+ m_pythonPrimitiveTypeName["int"] = "PyInt";
+ m_pythonPrimitiveTypeName["unsigned int"] = "PyInt";
+ m_pythonPrimitiveTypeName["short"] = "PyInt";
+ m_pythonPrimitiveTypeName["unsigned short"] = "PyInt";
+ m_pythonPrimitiveTypeName["long"] = "PyInt";
+
+ // PyFloat
+ m_pythonPrimitiveTypeName["double"] = "PyFloat";
+ m_pythonPrimitiveTypeName["float"] = "PyFloat";
+
+ // PyLong
+ m_pythonPrimitiveTypeName["unsigned long"] = "PyLong";
+ m_pythonPrimitiveTypeName["long long"] = "PyLong";
+ m_pythonPrimitiveTypeName["__int64"] = "PyLong";
+ m_pythonPrimitiveTypeName["unsigned long long"] = "PyLong";
+ m_pythonPrimitiveTypeName["unsigned __int64"] = "PyLong";
+
+ // Python operators
+ m_pythonOperators.clear();
+
+ // Arithmetic operators
+ m_pythonOperators["operator+"] = "add";
+ m_pythonOperators["operator-"] = "sub";
+ m_pythonOperators["operator*"] = "mul";
+ m_pythonOperators["operator/"] = "div";
+ m_pythonOperators["operator%"] = "mod";
+
+ // Inplace arithmetic operators
+ m_pythonOperators["operator+="] = "iadd";
+ m_pythonOperators["operator-="] = "isub";
+ m_pythonOperators["operator*="] = "imul";
+ m_pythonOperators["operator/="] = "idiv";
+ m_pythonOperators["operator%="] = "imod";
+
+ // Bitwise operators
+ m_pythonOperators["operator&"] = "and";
+ m_pythonOperators["operator^"] = "xor";
+ m_pythonOperators["operator|"] = "or";
+ m_pythonOperators["operator<<"] = "lshift";
+ m_pythonOperators["operator>>"] = "rshift";
+ m_pythonOperators["operator~"] = "invert";
+
+ // Inplace bitwise operators
+ m_pythonOperators["operator&="] = "iand";
+ m_pythonOperators["operator^="] = "ixor";
+ m_pythonOperators["operator|="] = "ior";
+ m_pythonOperators["operator<<="] = "ilshift";
+ m_pythonOperators["operator>>="] = "irshift";
+
+ // Comparison operators
+ m_pythonOperators["operator=="] = "eq";
+ m_pythonOperators["operator!="] = "ne";
+ m_pythonOperators["operator<"] = "lt";
+ m_pythonOperators["operator>"] = "gt";
+ m_pythonOperators["operator<="] = "le";
+ m_pythonOperators["operator>="] = "ge";
+
+ // Initialize format units for C++->Python->C++ conversion
+ m_formatUnits.clear();
+ m_formatUnits.insert("bool", "i");
+ m_formatUnits.insert("char", "b");
+ m_formatUnits.insert("unsigned char", "B");
+ m_formatUnits.insert("int", "i");
+ m_formatUnits.insert("unsigned int", "I");
+ m_formatUnits.insert("short", "h");
+ m_formatUnits.insert("unsigned short", "H");
+ m_formatUnits.insert("long", "l");
+ m_formatUnits.insert("unsigned long", "k");
+ m_formatUnits.insert("long long", "L");
+ m_formatUnits.insert("__int64", "L");
+ m_formatUnits.insert("unsigned long long", "K");
+ m_formatUnits.insert("unsigned __int64", "K");
+ m_formatUnits.insert("double", "d");
+ m_formatUnits.insert("float", "f");
+}
+
+FunctionModificationList ShibokenGenerator::functionModifications(const AbstractMetaFunction* func)
+{
+ FunctionModificationList mods;
+ const AbstractMetaClass *cls = func->ownerClass();
+ while (cls) {
+ mods += func->modifications(cls);
+ if (cls == cls->baseClass())
+ break;
+ cls = cls->baseClass();
+ }
+ return mods;
+}
+
+QString ShibokenGenerator::translateType(const AbstractMetaType* cType,
+ const AbstractMetaClass* context,
+ int option) const
+{
+ QString s;
+
+ if (context != 0
+ && cType != 0
+ && context->typeEntry()->isGenericClass()
+ && cType->originalTemplateType())
+ {
+ cType = cType->originalTemplateType();
+ }
+
+ if (!cType) {
+ s = "void";
+ } else if (cType->isArray()) {
+ s = translateType(cType->arrayElementType(), context) + "[]";
+ } else if (cType->isEnum() || cType->isFlags()) {
+ if (option & Generator::EnumAsInts)
+ s = "int";
+ else
+ s = cType->cppSignature();
+ } else if (cType->isValue() || cType->isObject() || cType->isReference()) {
+ s = cType->typeEntry()->qualifiedCppName();
+ if (cType->isObject())
+ s.append('*');
+ } else {
+ s = cType->cppSignature();
+ if (cType->isConstant() && (option & Generator::ExcludeConst))
+ s.replace("const", "");
+ if (cType->isReference() && (option & Generator::ExcludeReference))
+ s.replace("&", "");
+ }
+
+ return s;
+}
+
+QString ShibokenGenerator::wrapperName(const AbstractMetaClass* metaClass)
+{
+ QString result = metaClass->name();
+ if (metaClass->enclosingClass()) // is a inner class
+ result.replace("::", "_");
+ result +="Wrapper";
+ return result;
+}
+
+QString ShibokenGenerator::cpythonFunctionName(const AbstractMetaFunction* func)
+{
+ QString result = QLatin1String("Py");
+
+ if (func->ownerClass()) {
+ result += func->ownerClass()->name();
+ if (func->ownerClass()->enclosingClass()) // is a inner class
+ result.replace("::", "_");
+
+ result += '_';
+
+ if (func->isConstructor() || func->isCopyConstructor())
+ result += "New";
+ else if (func->isOperatorOverload())
+ result += ShibokenGenerator::pythonOperatorFunctionName(func);
+ else
+ result += func->name();
+ } else {
+ result += moduleName() + "Module_" + func->name();
+ }
+
+ return result;
+}
+
+QString ShibokenGenerator::cpythonEnumName(const EnumTypeEntry* enumEntry)
+{
+ QString result = QString("Py") + moduleName() + '_'
+ + enumEntry->qualifiedCppName();
+ result.replace("::", "_");
+ return result;
+}
+
+QString ShibokenGenerator::getFunctionReturnType(const AbstractMetaFunction* func) const
+{
+ if (func->ownerClass() && (func->isConstructor() || func->isCopyConstructor()))
+ return func->ownerClass()->qualifiedCppName() + '*';
+
+ return translateType(func->type(), func->implementingClass());
+
+ //TODO: check these lines
+ //QString modifiedReturnType = QString(func->typeReplaced(0));
+ //return modifiedReturnType.isNull() ?
+ //translateType(func->type(), func->implementingClass()) : modifiedReturnType;
+}
+
+QString ShibokenGenerator::writeBaseConversion(QTextStream& s, const AbstractMetaType* type,
+ const AbstractMetaClass* context)
+{
+ QString typeName;
+ if (type->isPrimitive()) {
+ const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) type->typeEntry();
+ if (ptype->basicAliasedTypeEntry())
+ ptype = ptype->basicAliasedTypeEntry();
+ typeName = ptype->name();
+ } else {
+ typeName = translateType(type, context);
+ }
+ s << "Shiboken::Converter< " << typeName << " >::";
+ return typeName;
+}
+
+void ShibokenGenerator::writeToPythonConversion(QTextStream& s, const AbstractMetaType* type,
+ const AbstractMetaClass* context, QString argumentName)
+{
+ QString typeName = writeBaseConversion(s, type, context);
+ s << "toPython(Shiboken::ValueHolder< " << typeName << " >(" << argumentName << "))";
+}
+
+void ShibokenGenerator::writeToCppConversion(QTextStream& s, const AbstractMetaType* type,
+ const AbstractMetaClass* context, QString argumentName)
+{
+ writeBaseConversion(s, type, context);
+ s << "toCpp(" << argumentName << ')';
+}
+
+QString ShibokenGenerator::getFormatUnitString(const AbstractMetaArgumentList arguments) const
+{
+ QString result;
+ foreach (const AbstractMetaArgument *arg, arguments) {
+ if ((arg->type()->isQObject() || arg->type()->isObject() || arg->type()->isValue())) { // &&
+// !arg->type()->isReference()) {
+ result += "O&";
+ } else if (arg->type()->isPrimitive()) {
+ const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) arg->type()->typeEntry();
+ if (ptype->basicAliasedTypeEntry())
+ ptype = ptype->basicAliasedTypeEntry();
+ result += m_formatUnits[ptype->name()];
+ } else if (arg->type()->isNativePointer() && arg->type()->name() == "char") {
+ result += 'z';
+ } else {
+ result += 'Y';
+ }
+ }
+ return result;
+}
+
+QString ShibokenGenerator::cpythonBaseName(const AbstractMetaType* type)
+{
+ if (type->name() == "char" && type->isNativePointer())
+ return QString("PyString");
+ return cpythonBaseName(type->typeEntry());
+}
+
+QString ShibokenGenerator::cpythonBaseName(const TypeEntry* type)
+{
+ QString baseName;
+ if ((type->isObject() || type->isValue())) { // && !type->isReference()) {
+ baseName = QString("Py") + type->name();
+ } else if (type->isPrimitive()) {
+ const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) type;
+ if (ptype->basicAliasedTypeEntry())
+ ptype = ptype->basicAliasedTypeEntry();
+ if (ptype->targetLangApiName() == ptype->name())
+ baseName = m_pythonPrimitiveTypeName[ptype->name()];
+ else
+ baseName = ptype->targetLangApiName();
+ } else if (type->isEnum()) {
+ baseName = cpythonEnumName((const EnumTypeEntry*) type);
+ } else if (type->isContainer()) {
+ const ContainerTypeEntry* ctype = (const ContainerTypeEntry*) type;
+ switch (ctype->type()) {
+ case ContainerTypeEntry::ListContainer:
+ case ContainerTypeEntry::StringListContainer:
+ case ContainerTypeEntry::LinkedListContainer:
+ case ContainerTypeEntry::VectorContainer:
+ case ContainerTypeEntry::StackContainer:
+ case ContainerTypeEntry::QueueContainer:
+ baseName = "PyList";
+ break;
+ case ContainerTypeEntry::PairContainer:
+ baseName = "PyTuple";
+ break;
+ case ContainerTypeEntry::SetContainer:
+ baseName = "PySet";
+ break;
+ case ContainerTypeEntry::MapContainer:
+ case ContainerTypeEntry::MultiMapContainer:
+ case ContainerTypeEntry::HashContainer:
+ case ContainerTypeEntry::MultiHashContainer:
+ baseName = "PyDict";
+ break;
+ }
+ } else {
+ baseName = "PyObject";
+ }
+ return baseName;
+}
+
+QString ShibokenGenerator::cpythonTypeName(const TypeEntry* type)
+{
+ return cpythonBaseName(type) + "_Type";
+}
+
+QString ShibokenGenerator::cpythonOperatorFunctionName(const AbstractMetaFunction* func)
+{
+ if (!func->isOperatorOverload())
+ return QString();
+ return QString("Py") + func->ownerClass()->name()
+ + '_' + pythonOperatorFunctionName(func->originalName());
+}
+
+QString ShibokenGenerator::pythonPrimitiveTypeName(QString cppTypeName)
+{
+ return ShibokenGenerator::m_pythonPrimitiveTypeName.value(cppTypeName, QString());
+}
+
+QString ShibokenGenerator::pythonPrimitiveTypeName(const PrimitiveTypeEntry* type)
+{
+ if (type->basicAliasedTypeEntry())
+ type = type->basicAliasedTypeEntry();
+ return pythonPrimitiveTypeName(type->name());
+}
+
+QString ShibokenGenerator::pythonOperatorFunctionName(const AbstractMetaFunction* func)
+{
+ QString op = pythonOperatorFunctionName(func->originalName());
+ if (func->arguments().isEmpty()) {
+ if (op == "__sub__")
+ op = QString("__neg__");
+ else if (op == "__add__")
+ op = QString("__pos__");
+ } else if (func->isStatic() && func->arguments().size() == 2) {
+ // If a operator overload function has 2 arguments and
+ // is static we assume that it is a reverse operator.
+ op = op.insert(2, 'r');
+ }
+ return op;
+}
+
+bool ShibokenGenerator::isNumber(QString cpythonApiName)
+{
+ return cpythonApiName == "PyInt"
+ || cpythonApiName == "PyFloat"
+ || cpythonApiName == "PyLong";
+}
+
+bool ShibokenGenerator::isNumber(const TypeEntry* type)
+{
+ if (!type->isPrimitive())
+ return false;
+ return isNumber(pythonPrimitiveTypeName((const PrimitiveTypeEntry*) type));
+}
+
+bool ShibokenGenerator::isNumber(const AbstractMetaType* type)
+{
+ return isNumber(type->typeEntry());
+}
+
+bool ShibokenGenerator::isPyInt(const TypeEntry* type)
+{
+ if (!type->isPrimitive())
+ return false;
+ return pythonPrimitiveTypeName((const PrimitiveTypeEntry*) type) == "PyInt";
+}
+
+bool ShibokenGenerator::isPyInt(const AbstractMetaType* type)
+{
+ return isPyInt(type->typeEntry());
+}
+
+bool ShibokenGenerator::isReverseOperator(const AbstractMetaFunction* func)
+{
+ if (!func->isOperatorOverload())
+ return false;
+
+ const AbstractMetaClass* cppClass = func->ownerClass();
+ AbstractMetaArgumentList args = func->arguments();
+ // Here we expect static operator overloads with
+ // 2 arguments to represent reverse operators.
+ // e.g. static operator*(double,TYPE) => double * TYPE => TYPE.__rmul__(double).
+ return args.size() == 2 && cppClass &&
+ args[1]->type()->typeEntry() == cppClass->typeEntry();
+}
+
+static QString checkFunctionName(QString baseName, bool genericNumberType)
+{
+ if (genericNumberType && ShibokenGenerator::isNumber(baseName))
+ baseName = "PyNumber";
+ return baseName + "_Check";
+}
+
+QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* type, bool genericNumberType)
+{
+ return checkFunctionName(cpythonBaseName(type), genericNumberType);
+}
+
+QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry* type, bool genericNumberType)
+{
+ return checkFunctionName(cpythonBaseName(type), genericNumberType);
+}
+
+QString ShibokenGenerator::argumentString(const AbstractMetaFunction *func,
+ const AbstractMetaArgument *argument,
+ uint options) const
+{
+ QString modified_type = func->typeReplaced(argument->argumentIndex() + 1);
+ QString arg;
+
+ if (modified_type.isEmpty())
+ arg = translateType(argument->type(), func->implementingClass(), (Generator::Option) options);
+ else
+ arg = modified_type.replace('$', '.');
+
+ if (!(options & Generator::SkipName)) {
+ arg += " ";
+ arg += argument->argumentName();
+ }
+
+ QList<ReferenceCount> referenceCounts;
+ referenceCounts = func->referenceCounts(func->implementingClass(), argument->argumentIndex() + 1);
+ if ((options & Generator::SkipDefaultValues) != Generator::SkipDefaultValues &&
+ !argument->originalDefaultValueExpression().isEmpty())
+ {
+ QString default_value = argument->originalDefaultValueExpression();
+ if (default_value == "NULL")
+ default_value = NULL_VALUE;
+
+ //WORKAROUND: fix this please
+ if (default_value.startsWith("new "))
+ default_value.remove(0, 4);
+
+ arg += " = " + default_value;
+ }
+
+ return arg;
+}
+
+void ShibokenGenerator::writeArgument(QTextStream &s,
+ const AbstractMetaFunction *func,
+ const AbstractMetaArgument *argument,
+ uint options) const
+{
+ s << argumentString(func, argument, options);
+}
+
+void ShibokenGenerator::writeFunctionArguments(QTextStream &s,
+ const AbstractMetaFunction *func,
+ uint options) const
+{
+ AbstractMetaArgumentList arguments = func->arguments();
+
+ if (options & Generator::WriteSelf) {
+ s << func->implementingClass()->name() << '&';
+ if (!(options & SkipName))
+ s << " self";
+ }
+
+ int argUsed = 0;
+ for (int i = 0; i < arguments.size(); ++i) {
+ if ((options & Generator::SkipRemovedArguments) && func->argumentRemoved(i+1))
+ continue;
+
+ if ((options & Generator::WriteSelf) || argUsed != 0)
+ s << ", ";
+ writeArgument(s, func, arguments[i], options);
+ argUsed++;
+ }
+}
+
+QString ShibokenGenerator::functionReturnType(const AbstractMetaFunction* func, int option) const
+{
+ QString modifiedReturnType = QString(func->typeReplaced(0));
+ if (!modifiedReturnType.isNull() && !(option & OriginalTypeDescription))
+ return modifiedReturnType;
+ else
+ return translateType(func->type(), func->implementingClass(), option);
+}
+
+QString ShibokenGenerator::functionSignature(const AbstractMetaFunction *func,
+ QString prepend,
+ QString append,
+ int option,
+ int argCount) const
+{
+ AbstractMetaArgumentList arguments = func->arguments();
+ int argumentCount = argCount < 0 ? arguments.size() : argCount;
+
+ QString result;
+ QTextStream s(&result);
+ // The actual function
+ if (!(func->isEmptyFunction() ||
+ func->isNormal() ||
+ func->isSignal())) {
+ option = Option(option | Generator::SkipReturnType);
+ } else {
+ s << functionReturnType(func, option) << ' ';
+ }
+
+ // name
+ QString name(func->originalName());
+ if (func->isConstructor())
+ name = wrapperName(func->ownerClass());
+
+ s << prepend << name << append << '(';
+ writeFunctionArguments(s, func, option);
+ s << ')';
+
+ if (func->isConstant() && !(option & Generator::ExcludeMethodConst))
+ s << " const";
+
+ return result;
+}
+
+QString ShibokenGenerator::signatureForDefaultVirtualMethod(const AbstractMetaFunction *func,
+ QString prepend,
+ QString append,
+ int option,
+ int argCount) const
+{
+ QString defaultMethodSignature = functionSignature(func, prepend, append, option, argCount);
+ QString staticSelf("(");
+ if (func->isConstant())
+ staticSelf += "const ";
+ staticSelf += func->ownerClass()->qualifiedCppName()+"& self";
+ if (!func->arguments().isEmpty())
+ staticSelf += ", ";
+ defaultMethodSignature.replace(defaultMethodSignature.lastIndexOf(") const"), 7, ")");
+ defaultMethodSignature.replace(defaultMethodSignature.indexOf('('), 1, staticSelf);
+ return defaultMethodSignature;
+}
+
+bool ShibokenGenerator::hasInjectedCodeOrSignatureModification(const AbstractMetaFunction* func)
+{
+ foreach (FunctionModification mod, functionModifications(func)) {
+ if (mod.isCodeInjection() || mod.isRenameModifier())
+ return true;
+ }
+ return false;
+}
+
+void ShibokenGenerator::writeArgumentNames(QTextStream &s,
+ const AbstractMetaFunction *func,
+ uint options) const
+{
+ AbstractMetaArgumentList arguments = func->arguments();
+ int argCount = 0;
+ for (int j = 0, max = arguments.size(); j < max; j++) {
+
+ if ((options & Generator::SkipRemovedArguments) &&
+ (func->argumentRemoved(arguments.at(j)->argumentIndex() +1)))
+ continue;
+
+ if (argCount > 0)
+ s << ", ";
+
+ QString argName;
+
+ if ((options & Generator::BoxedPrimitive) &&
+ !arguments.at(j)->type()->isReference() &&
+ (arguments.at(j)->type()->isQObject() ||
+ arguments.at(j)->type()->isObject())) {
+ //s << "brian::wrapper_manager::instance()->retrieve( " << arguments.at(j)->argumentName() << " )";
+ // TODO: replace boost thing
+ s << "python::ptr( " << arguments.at(j)->argumentName() << " )";
+ } else {
+ s << arguments.at(j)->argumentName();
+ }
+ argCount++;
+ }
+}
+
+AbstractMetaFunctionList ShibokenGenerator::queryGlobalOperators(const AbstractMetaClass *metaClass)
+{
+ AbstractMetaFunctionList result;
+
+ foreach (AbstractMetaFunction *func, metaClass->functions()) {
+ if (func->isInGlobalScope() && func->isOperatorOverload())
+ result.append(func);
+ }
+ return result;
+}
+
+AbstractMetaFunctionList ShibokenGenerator::sortContructor(AbstractMetaFunctionList list)
+{
+ AbstractMetaFunctionList result;
+
+ foreach (AbstractMetaFunction *func, list) {
+ bool inserted = false;
+ foreach (AbstractMetaArgument *arg, func->arguments()) {
+ if (arg->type()->isFlags() || arg->type()->isEnum()) {
+ result.push_back(func);
+ inserted = true;
+ break;
+ }
+ }
+ if (!inserted)
+ result.push_front(func);
+ }
+
+ return result;
+}
+
+AbstractMetaFunctionList ShibokenGenerator::queryFunctions(const AbstractMetaClass *metaClass, bool allFunctions)
+{
+ AbstractMetaFunctionList result;
+
+ if (allFunctions) {
+ int defaultFlags = AbstractMetaClass::NormalFunctions | AbstractMetaClass::Visible;
+ defaultFlags |= metaClass->isInterface() ? 0 : AbstractMetaClass::ClassImplements;
+
+ // Constructors
+ result = metaClass->queryFunctions(AbstractMetaClass::Constructors
+ | defaultFlags);
+
+ // put enum constructor first to avoid conflict with int contructor
+ result = sortContructor(result);
+
+ // Final functions
+ result += metaClass->queryFunctions(AbstractMetaClass::FinalInTargetLangFunctions
+ | AbstractMetaClass::NonStaticFunctions
+ | defaultFlags);
+
+ //virtual
+ result += metaClass->queryFunctions(AbstractMetaClass::VirtualInTargetLangFunctions
+ | AbstractMetaClass::NonStaticFunctions
+ | defaultFlags);
+
+ // Static functions
+ result += metaClass->queryFunctions(AbstractMetaClass::StaticFunctions | defaultFlags);
+
+ // Empty, private functions, since they aren't caught by the other ones
+ result += metaClass->queryFunctions(AbstractMetaClass::Empty
+ | AbstractMetaClass::Invisible
+ | defaultFlags);
+ // Signals
+ result += metaClass->queryFunctions(AbstractMetaClass::Signals | defaultFlags);
+ } else {
+ result = metaClass->functionsInTargetLang();
+ }
+
+ return result;
+}
+
+void ShibokenGenerator::writeFunctionCall(QTextStream& s,
+ const AbstractMetaFunction* func,
+ uint options) const
+{
+ if (!(options & Generator::SkipName))
+ s << (func->isConstructor() ? func->ownerClass()->qualifiedCppName() : func->originalName());
+ s << '(';
+ writeArgumentNames(s, func, options);
+ s << ')';
+}
+
+AbstractMetaFunctionList ShibokenGenerator::filterFunctions(const AbstractMetaClass* metaClass)
+{
+ AbstractMetaFunctionList lst = queryFunctions(metaClass, true);
+ foreach (AbstractMetaFunction *func, lst) {
+ //skip signals
+ if (func->isSignal()
+ || func->isDestructor()
+ || (func->isModifiedRemoved() && !func->isAbstract()))
+ lst.removeOne(func);
+ }
+
+ //virtual not implemented in current class
+ AbstractMetaFunctionList virtualLst = metaClass->queryFunctions(AbstractMetaClass::VirtualFunctions);
+ foreach (AbstractMetaFunction* func, virtualLst) {
+ if ((func->implementingClass() != metaClass) && !lst.contains(func))
+ lst.append(func);
+ }
+
+ //append global operators
+ lst += queryGlobalOperators(metaClass);
+
+ return lst;
+ //return metaClass->functions();
+}
+
+CodeSnipList ShibokenGenerator::getCodeSnips(const AbstractMetaFunction *func)
+{
+ CodeSnipList result;
+ const AbstractMetaClass* metaClass = func->implementingClass();
+ while (!metaClass) {
+ foreach (FunctionModification mod, func->modifications(metaClass)) {
+ if (mod.isCodeInjection())
+ result << mod.snips;
+ }
+
+ if (metaClass == metaClass->baseClass())
+ break;
+ metaClass = metaClass->baseClass();
+ }
+
+ return result;
+}
+
+void ShibokenGenerator::writeCodeSnips(QTextStream& s,
+ const CodeSnipList& codeSnips,
+ CodeSnip::Position position,
+ TypeSystem::Language language,
+ const AbstractMetaFunction* func)
+{
+ foreach (CodeSnip snip, codeSnips) {
+ if ((snip.position != position) || !(snip.language & language))
+ continue;
+
+ QString code;
+ QTextStream tmpStream(&code);
+ Indentation indent1(INDENT);
+ Indentation indent2(INDENT);
+ snip.formattedCode(tmpStream, INDENT);
+
+ if (func) {
+ // replace template variable for return variable name
+ code.replace("%0", retvalVariableName());
+
+ // replace template variables for individual arguments
+ int removed = 0;
+ for (int i = 0; i < func->arguments().size(); i++) {
+ if (func->argumentRemoved(i+1))
+ removed++;
+ code.replace("%" + QString::number(i+1), QString("cpp_arg%1").arg(i - removed));
+ }
+
+ // replace template variables for not removed arguments
+ int i = 0;
+ QString argumentNames;
+ foreach (const AbstractMetaArgument* arg, func->arguments()) {
+ if (func->argumentRemoved(arg->argumentIndex()+1))
+ continue;
+ if (i > 0)
+ argumentNames += ", ";
+ argumentNames += QString("cpp_arg%1").arg(i++);
+ }
+ code.replace("%ARGUMENT_NAMES", argumentNames);
+
+ replaceTemplateVariables(code, func);
+ }
+
+ s << code;
+ }
+}
+
+bool ShibokenGenerator::canCreateWrapperFor(const AbstractMetaClass* metaClass)
+{
+ return !metaClass->hasPrivateDestructor();
+}
+
+QStringList ShibokenGenerator::getBaseClasses(const AbstractMetaClass* metaClass)
+{
+ QStringList baseClass;
+
+ if (!metaClass->baseClassName().isEmpty() &&
+ (metaClass->name() != metaClass->baseClassName()))
+ baseClass.append(metaClass->baseClassName());
+
+ foreach (AbstractMetaClass* interface, metaClass->interfaces()) {
+ AbstractMetaClass* aux = interface->primaryInterfaceImplementor();
+ if (!aux)
+ continue;
+
+ //skip templates
+ if (!aux->templateArguments().isEmpty())
+ continue;
+
+ if (!aux->name().isEmpty() && (metaClass->name() != aux->name()))
+ baseClass.append(aux->name());
+ }
+
+ return baseClass;
+}
+
+static void dumpFunction(AbstractMetaFunctionList lst)
+{
+ qDebug() << "DUMP FUNCTIONS: ";
+ foreach (AbstractMetaFunction *func, lst)
+ qDebug() << "*" << func->ownerClass()->name()
+ << func->signature()
+ << "Private: " << func->isPrivate()
+ << "Empty: " << func->isEmptyFunction()
+ << "Static:" << func->isStatic()
+ << "Signal:" << func->isSignal()
+ << "ClassImplements: " << (func->ownerClass() != func->implementingClass())
+ << "is operator:" << func->isOperatorOverload()
+ << "is global:" << func->isInGlobalScope();
+}