aboutsummaryrefslogtreecommitdiffstats
path: root/generators
diff options
context:
space:
mode:
authorHugo Parente Lima <hugo.pl@gmail.com>2012-02-28 23:44:50 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-09 19:06:21 -0300
commitbd2df4ea6fd11f1285c07591367259f3900a93fc (patch)
tree9a61c0af4eb09e18682bfaf20d8b2ad58dbee5e3 /generators
parent363d1104a92a8d4a9bb7eb5838dcf941d710d042 (diff)
generators directory renamed to generator.
This makes sense as now there only one generator that you can tweak it into different modes (a.k.a. generator sets). Reviewer: Trust me
Diffstat (limited to 'generators')
-rw-r--r--generators/CMakeLists.txt32
-rw-r--r--generators/generator.cpp708
-rw-r--r--generators/generator.h341
-rw-r--r--generators/main.cpp443
-rw-r--r--generators/qtdoc/CMakeLists.txt21
-rw-r--r--generators/qtdoc/qtdocgenerator.cpp1652
-rw-r--r--generators/qtdoc/qtdocgenerator.h226
-rw-r--r--generators/shiboken/CMakeLists.txt30
-rw-r--r--generators/shiboken/cppgenerator.cpp5125
-rw-r--r--generators/shiboken/cppgenerator.h334
-rw-r--r--generators/shiboken/headergenerator.cpp494
-rw-r--r--generators/shiboken/headergenerator.h56
-rw-r--r--generators/shiboken/overloaddata.cpp1002
-rw-r--r--generators/shiboken/overloaddata.h147
-rw-r--r--generators/shiboken/shibokengenerator.cpp2466
-rw-r--r--generators/shiboken/shibokengenerator.h536
-rw-r--r--generators/shiboken/shibokennormalize.cpp274
-rw-r--r--generators/shiboken/shibokennormalize_p.h41
-rw-r--r--generators/shibokenconfig.h.in7
19 files changed, 0 insertions, 13935 deletions
diff --git a/generators/CMakeLists.txt b/generators/CMakeLists.txt
deleted file mode 100644
index 37a6f3cc9..000000000
--- a/generators/CMakeLists.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-project(shibokengenerator)
-
-set(shiboken_SRC
-generator.cpp
-shiboken/cppgenerator.cpp
-shiboken/headergenerator.cpp
-shiboken/overloaddata.cpp
-shiboken/shibokengenerator.cpp
-shiboken/shibokennormalize.cpp
-qtdoc/qtdocgenerator.cpp
-main.cpp
-)
-
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}/shiboken
- ${CMAKE_CURRENT_SOURCE_DIR}/qtdoc
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_CURRENT_BINARY_DIR}
- ${APIEXTRACTOR_INCLUDE_DIR}
- ${QT_INCLUDE_DIR}
- ${QT_QTCORE_INCLUDE_DIR}
- ${QT_QTXML_INCLUDE_DIR})
-
-add_executable(shiboken ${shiboken_SRC})
-set_target_properties(shiboken PROPERTIES OUTPUT_NAME shiboken${shiboken_SUFFIX})
-target_link_libraries(shiboken
- ${APIEXTRACTOR_LIBRARY}
- ${QT_QTCORE_LIBRARY}
- ${QT_QTXML_LIBRARY})
-
-configure_file(shibokenconfig.h.in "${CMAKE_CURRENT_BINARY_DIR}/shibokenconfig.h" @ONLY)
-
-install(TARGETS shiboken DESTINATION bin)
diff --git a/generators/generator.cpp b/generators/generator.cpp
deleted file mode 100644
index 9f81b93ad..000000000
--- a/generators/generator.cpp
+++ /dev/null
@@ -1,708 +0,0 @@
-/*
- * This file is part of the API Extractor 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 "generator.h"
-#include "reporthandler.h"
-#include "fileout.h"
-#include "apiextractor.h"
-
-#include <QtCore/QDir>
-#include <QtCore/QFile>
-#include <QtCore/QFileInfo>
-#include <QDebug>
-#include <typedatabase.h>
-
-struct Generator::GeneratorPrivate {
- const ApiExtractor* apiextractor;
- QString outDir;
- // License comment
- QString licenseComment;
- QString packageName;
- int numGenerated;
- int numGeneratedWritten;
- QStringList instantiatedContainersNames;
- QList<const AbstractMetaType*> instantiatedContainers;
-};
-
-Generator::Generator() : m_d(new GeneratorPrivate)
-{
- m_d->numGenerated = 0;
- m_d->numGeneratedWritten = 0;
- m_d->instantiatedContainers = QList<const AbstractMetaType*>();
- m_d->instantiatedContainersNames = QStringList();
-}
-
-Generator::~Generator()
-{
- delete m_d;
-}
-
-bool Generator::setup(const ApiExtractor& extractor, const QMap< QString, QString > args)
-{
- m_d->apiextractor = &extractor;
- TypeEntryHash allEntries = TypeDatabase::instance()->allEntries();
- TypeEntry* entryFound = 0;
- foreach (QList<TypeEntry*> entryList, allEntries.values()) {
- foreach (TypeEntry* entry, entryList) {
- if (entry->type() == TypeEntry::TypeSystemType && entry->generateCode()) {
- entryFound = entry;
- break;
- }
- }
- if (entryFound)
- break;
- }
- if (entryFound)
- m_d->packageName = entryFound->name();
- else
- ReportHandler::warning("Couldn't find the package name!!");
-
- collectInstantiatedContainers();
-
- return doSetup(args);
-}
-
-QString Generator::getSimplifiedContainerTypeName(const AbstractMetaType* type)
-{
- if (!type->typeEntry()->isContainer())
- return type->cppSignature();
- QString typeName = type->cppSignature();
- if (type->isConstant())
- typeName.remove(0, sizeof("const ") / sizeof(char) - 1);
- if (type->isReference())
- typeName.chop(1);
- while (typeName.endsWith('*') || typeName.endsWith(' '))
- typeName.chop(1);
- return typeName;
-}
-
-void Generator::addInstantiatedContainers(const AbstractMetaType* type)
-{
- if (!type)
- return;
- foreach (const AbstractMetaType* t, type->instantiations())
- addInstantiatedContainers(t);
- if (!type->typeEntry()->isContainer())
- return;
- QString typeName = getSimplifiedContainerTypeName(type);
- if (!m_d->instantiatedContainersNames.contains(typeName)) {
- m_d->instantiatedContainersNames.append(typeName);
- m_d->instantiatedContainers.append(type);
- }
-}
-
-void Generator::collectInstantiatedContainers(const AbstractMetaFunction* func)
-{
- addInstantiatedContainers(func->type());
- foreach (const AbstractMetaArgument* arg, func->arguments())
- addInstantiatedContainers(arg->type());
-}
-
-void Generator::collectInstantiatedContainers(const AbstractMetaClass* metaClass)
-{
- if (!metaClass->typeEntry()->generateCode())
- return;
- foreach (const AbstractMetaFunction* func, metaClass->functions())
- collectInstantiatedContainers(func);
- foreach (const AbstractMetaField* field, metaClass->fields())
- addInstantiatedContainers(field->type());
- foreach (AbstractMetaClass* innerClass, metaClass->innerClasses())
- collectInstantiatedContainers(innerClass);
-}
-
-void Generator::collectInstantiatedContainers()
-{
- foreach (const AbstractMetaFunction* func, globalFunctions())
- collectInstantiatedContainers(func);
- foreach (const AbstractMetaClass* metaClass, classes())
- collectInstantiatedContainers(metaClass);
-}
-
-QList<const AbstractMetaType*> Generator::instantiatedContainers() const
-{
- return m_d->instantiatedContainers;
-}
-
-QMap< QString, QString > Generator::options() const
-{
- return QMap<QString, QString>();
-}
-
-AbstractMetaClassList Generator::classes() const
-{
- return m_d->apiextractor->classes();
-}
-
-AbstractMetaFunctionList Generator::globalFunctions() const
-{
- return m_d->apiextractor->globalFunctions();
-}
-
-AbstractMetaEnumList Generator::globalEnums() const
-{
- return m_d->apiextractor->globalEnums();
-}
-
-QList<const PrimitiveTypeEntry*> Generator::primitiveTypes() const
-{
- return m_d->apiextractor->primitiveTypes();
-}
-
-QList<const ContainerTypeEntry*> Generator::containerTypes() const
-{
- return m_d->apiextractor->containerTypes();
-}
-
-const AbstractMetaEnum* Generator::findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const
-{
- return m_d->apiextractor->findAbstractMetaEnum(typeEntry);
-}
-
-const AbstractMetaEnum* Generator::findAbstractMetaEnum(const TypeEntry* typeEntry) const
-{
- return m_d->apiextractor->findAbstractMetaEnum(typeEntry);
-}
-
-const AbstractMetaEnum* Generator::findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const
-{
- return m_d->apiextractor->findAbstractMetaEnum(typeEntry);
-}
-
-const AbstractMetaEnum* Generator::findAbstractMetaEnum(const AbstractMetaType* metaType) const
-{
- return m_d->apiextractor->findAbstractMetaEnum(metaType);
-}
-
-QSet< QString > Generator::qtMetaTypeDeclaredTypeNames() const
-{
- return m_d->apiextractor->qtMetaTypeDeclaredTypeNames();
-}
-
-QString Generator::licenseComment() const
-{
- return m_d->licenseComment;
-}
-
-void Generator::setLicenseComment(const QString& licenseComment)
-{
- m_d->licenseComment = licenseComment;
-}
-
-QString Generator::packageName() const
-{
- return m_d->packageName;
-}
-
-QString Generator::moduleName() const
-{
- QString& pkgName = m_d->packageName;
- return QString(pkgName).remove(0, pkgName.lastIndexOf('.') + 1);
-}
-
-QString Generator::outputDirectory() const
-{
- return m_d->outDir;
-}
-
-void Generator::setOutputDirectory(const QString &outDir)
-{
- m_d->outDir = outDir;
-}
-
-int Generator::numGenerated() const
-{
- return m_d->numGenerated;
-}
-
-int Generator::numGeneratedAndWritten() const
-{
- return m_d->numGeneratedWritten;
-}
-
-void Generator::generate()
-{
- foreach (AbstractMetaClass *cls, m_d->apiextractor->classes()) {
- if (!shouldGenerate(cls))
- continue;
-
- QString fileName = fileNameForClass(cls);
- if (fileName.isNull())
- continue;
- ReportHandler::debugSparse(QString("generating: %1").arg(fileName));
-
- FileOut fileOut(outputDirectory() + '/' + subDirectoryForClass(cls) + '/' + fileName);
- generateClass(fileOut.stream, cls);
-
- if (fileOut.done())
- ++m_d->numGeneratedWritten;
- ++m_d->numGenerated;
- }
- finishGeneration();
-}
-
-bool Generator::shouldGenerateTypeEntry(const TypeEntry* type) const
-{
- return type->codeGeneration() & TypeEntry::GenerateTargetLang;
-}
-
-bool Generator::shouldGenerate(const AbstractMetaClass* metaClass) const
-{
- return shouldGenerateTypeEntry(metaClass->typeEntry());
-}
-
-void verifyDirectoryFor(const QFile &file)
-{
- QDir dir = QFileInfo(file).dir();
- if (!dir.exists()) {
- if (!dir.mkpath(dir.absolutePath()))
- ReportHandler::warning(QString("unable to create directory '%1'")
- .arg(dir.absolutePath()));
- }
-}
-
-void Generator::replaceTemplateVariables(QString &code, const AbstractMetaFunction *func)
-{
- const AbstractMetaClass *cpp_class = func->ownerClass();
- if (cpp_class)
- code.replace("%TYPE", cpp_class->name());
-
- foreach (AbstractMetaArgument *arg, func->arguments())
- code.replace("%" + QString::number(arg->argumentIndex() + 1), arg->name());
-
- //template values
- code.replace("%RETURN_TYPE", translateType(func->type(), cpp_class));
- code.replace("%FUNCTION_NAME", func->originalName());
-
- if (code.contains("%ARGUMENT_NAMES")) {
- QString str;
- QTextStream aux_stream(&str);
- writeArgumentNames(aux_stream, func, Generator::SkipRemovedArguments);
- code.replace("%ARGUMENT_NAMES", str);
- }
-
- if (code.contains("%ARGUMENTS")) {
- QString str;
- QTextStream aux_stream(&str);
- writeFunctionArguments(aux_stream, func, Options(SkipDefaultValues) | SkipRemovedArguments);
- code.replace("%ARGUMENTS", str);
- }
-}
-
-QTextStream& formatCode(QTextStream &s, const QString& code, Indentor &indentor)
-{
- // detect number of spaces before the first character
- QStringList lst(code.split("\n"));
- QRegExp nonSpaceRegex("[^\\s]");
- int spacesToRemove = 0;
- foreach(QString line, lst) {
- if (!line.trimmed().isEmpty()) {
- spacesToRemove = line.indexOf(nonSpaceRegex);
- if (spacesToRemove == -1)
- spacesToRemove = 0;
- break;
- }
- }
-
- static QRegExp emptyLine("\\s*[\\r]?[\\n]?\\s*");
-
- foreach(QString line, lst) {
- if (!line.isEmpty() && !emptyLine.exactMatch(line)) {
- while (line.end()->isSpace())
- line.chop(1);
- int limit = 0;
- for(int i = 0; i < spacesToRemove; ++i) {
- if (!line[i].isSpace())
- break;
- limit++;
- }
-
- s << indentor << line.remove(0, limit);
- }
- s << endl;
- }
- return s;
-}
-
-AbstractMetaFunctionList Generator::implicitConversions(const TypeEntry* type) const
-{
- if (type->isValue()) {
- const AbstractMetaClass* metaClass = classes().findClass(type);
- if (metaClass)
- return metaClass->implicitConversions();
- }
- return AbstractMetaFunctionList();
-}
-
-AbstractMetaFunctionList Generator::implicitConversions(const AbstractMetaType* metaType) const
-{
- return implicitConversions(metaType->typeEntry());
-}
-
-bool Generator::isObjectType(const TypeEntry* type)
-{
- if (type->isComplex())
- return Generator::isObjectType((const ComplexTypeEntry*)type);
- return type->isObject();
-}
-bool Generator::isObjectType(const ComplexTypeEntry* type)
-{
- return type->isObject() || type->isQObject();
-}
-bool Generator::isObjectType(const AbstractMetaClass* metaClass)
-{
- return Generator::isObjectType(metaClass->typeEntry());
-}
-bool Generator::isObjectType(const AbstractMetaType* metaType)
-{
- return isObjectType(metaType->typeEntry());
-}
-
-bool Generator::isPointer(const AbstractMetaType* type)
-{
- return type->indirections() > 0
- || type->isNativePointer()
- || type->isValuePointer();
-}
-
-bool Generator::isCString(const AbstractMetaType* type)
-{
- return type->isNativePointer()
- && type->indirections() == 1
- && type->name() == "char";
-}
-
-bool Generator::isVoidPointer(const AbstractMetaType* type)
-{
- return type->isNativePointer()
- && type->indirections() == 1
- && type->name() == "void";
-}
-
-QString Generator::getFullTypeName(const TypeEntry* type) const
-{
- return QString("%1%2").arg(type->isCppPrimitive() ? "" : "::").arg(type->qualifiedCppName());
-}
-
-QString Generator::getFullTypeName(const AbstractMetaType* type) const
-{
- if (isCString(type))
- return "const char*";
- if (isVoidPointer(type))
- return "void*";
- if (type->typeEntry()->isContainer())
- return QString("::%1").arg(type->cppSignature());
- QString typeName;
- if (type->typeEntry()->isComplex() && type->hasInstantiations())
- typeName = getFullTypeNameWithoutModifiers(type);
- else
- typeName = getFullTypeName(type->typeEntry());
- return typeName + QString("*").repeated(type->indirections());
-}
-
-QString Generator::getFullTypeName(const AbstractMetaClass* metaClass) const
-{
- return QString("::%1").arg(metaClass->qualifiedCppName());
-}
-
-QString Generator::getFullTypeNameWithoutModifiers(const AbstractMetaType* type) const
-{
- if (isCString(type))
- return "const char*";
- if (isVoidPointer(type))
- return "void*";
- if (!type->hasInstantiations())
- return getFullTypeName(type->typeEntry());
- QString typeName = type->cppSignature();
- if (type->isConstant())
- typeName.remove(0, sizeof("const ") / sizeof(char) - 1);
- if (type->isReference())
- typeName.chop(1);
- while (typeName.endsWith('*') || typeName.endsWith(' '))
- typeName.chop(1);
- return QString("::%1").arg(typeName);
-}
-
-QString Generator::minimalConstructor(const AbstractMetaType* type) const
-{
- if (!type || (type->isReference() && Generator::isObjectType(type)))
- return QString();
-
- if (type->isContainer()) {
- QString ctor = type->cppSignature();
- if (ctor.endsWith("*"))
- return QString("0");
- if (ctor.startsWith("const "))
- ctor.remove(0, sizeof("const ") / sizeof(char) - 1);
- if (ctor.endsWith("&")) {
- ctor.chop(1);
- ctor = ctor.trimmed();
- }
- return QString("::%1()").arg(ctor);
- }
-
- if (type->isNativePointer())
- return QString("((%1*)0)").arg(type->typeEntry()->qualifiedCppName());
-
- if (Generator::isPointer(type))
- return QString("((::%1*)0)").arg(type->typeEntry()->qualifiedCppName());
-
- if (type->typeEntry()->isComplex()) {
- const ComplexTypeEntry* cType = reinterpret_cast<const ComplexTypeEntry*>(type->typeEntry());
- QString ctor = cType->defaultConstructor();
- if (!ctor.isEmpty())
- return ctor;
- ctor = minimalConstructor(classes().findClass(cType));
- if (type->hasInstantiations())
- ctor = ctor.replace(getFullTypeName(cType), getFullTypeNameWithoutModifiers(type));
- return ctor;
- }
-
- return minimalConstructor(type->typeEntry());
-}
-
-QString Generator::minimalConstructor(const TypeEntry* type) const
-{
- if (!type)
- return QString();
-
- if (type->isCppPrimitive())
- return QString("((%1)0)").arg(type->qualifiedCppName());
-
- if (type->isEnum() || type->isFlags())
- return QString("((::%1)0)").arg(type->qualifiedCppName());
-
- if (type->isPrimitive()) {
- QString ctor = reinterpret_cast<const PrimitiveTypeEntry*>(type)->defaultConstructor();
- // If a non-C++ (i.e. defined by the user) primitive type does not have
- // a default constructor defined by the user, the empty constructor is
- // heuristically returned. If this is wrong the build of the generated
- // bindings will tell.
- return (ctor.isEmpty()) ? QString("::%1()").arg(type->qualifiedCppName()) : ctor;
- }
-
- if (type->isComplex())
- return minimalConstructor(classes().findClass(type));
-
- return QString();
-}
-
-QString Generator::minimalConstructor(const AbstractMetaClass* metaClass) const
-{
- if (!metaClass)
- return QString();
-
- const ComplexTypeEntry* cType = reinterpret_cast<const ComplexTypeEntry*>(metaClass->typeEntry());
- if (cType->hasDefaultConstructor())
- return cType->defaultConstructor();
-
- AbstractMetaFunctionList constructors = metaClass->queryFunctions(AbstractMetaClass::Constructors);
- int maxArgs = 0;
- foreach (const AbstractMetaFunction* ctor, constructors) {
- if (ctor->isUserAdded() || ctor->isPrivate() || ctor->isCopyConstructor())
- continue;
- int numArgs = ctor->arguments().size();
- if (numArgs == 0) {
- maxArgs = 0;
- break;
- }
- if (numArgs > maxArgs)
- maxArgs = numArgs;
- }
-
- QString qualifiedCppName = metaClass->typeEntry()->qualifiedCppName();
- QStringList templateTypes;
- foreach (TypeEntry* templateType, metaClass->templateArguments())
- templateTypes << templateType->qualifiedCppName();
- QString fixedTypeName = QString("%1<%2 >").arg(qualifiedCppName).arg(templateTypes.join(", "));
-
- // Empty constructor.
- if (maxArgs == 0)
- return QString("::%1()").arg(qualifiedCppName);
-
- QList<const AbstractMetaFunction*> candidates;
-
- // Constructors with C++ primitive types, enums or pointers only.
- // Start with the ones with fewer arguments.
- for (int i = 1; i <= maxArgs; ++i) {
- foreach (const AbstractMetaFunction* ctor, constructors) {
- if (ctor->isUserAdded() || ctor->isPrivate() || ctor->isCopyConstructor())
- continue;
-
- AbstractMetaArgumentList arguments = ctor->arguments();
- if (arguments.size() != i)
- continue;
-
- QStringList args;
- foreach (const AbstractMetaArgument* arg, arguments) {
- const TypeEntry* type = arg->type()->typeEntry();
- if (type == metaClass->typeEntry()) {
- args.clear();
- break;
- }
-
- if (!arg->originalDefaultValueExpression().isEmpty()) {
- if (!arg->defaultValueExpression().isEmpty()
- && arg->defaultValueExpression() != arg->originalDefaultValueExpression()) {
- args << arg->defaultValueExpression();
- }
- break;
- }
-
- if (type->isCppPrimitive() || type->isEnum() || isPointer(arg->type())) {
- QString argValue = minimalConstructor(arg->type());
- if (argValue.isEmpty()) {
- args.clear();
- break;
- }
- args << argValue;
- } else {
- args.clear();
- break;
- }
- }
-
- if (!args.isEmpty())
- return QString("::%1(%2)").arg(qualifiedCppName).arg(args.join(", "));
-
- candidates << ctor;
- }
- }
-
- // Constructors with C++ primitive types, enums, pointers, value types,
- // and user defined primitive types.
- // Builds the minimal constructor recursively.
- foreach (const AbstractMetaFunction* ctor, candidates) {
- QStringList args;
- foreach (const AbstractMetaArgument* arg, ctor->arguments()) {
- if (arg->type()->typeEntry() == metaClass->typeEntry()) {
- args.clear();
- break;
- }
- QString argValue = minimalConstructor(arg->type());
- if (argValue.isEmpty()) {
- args.clear();
- break;
- }
- args << argValue;
- }
- if (!args.isEmpty()) {
- return QString("::%1(%2)").arg(qualifiedCppName)
- .arg(args.join(", "));
- }
- }
-
- return QString();
-}
-
-QString Generator::translateType(const AbstractMetaType *cType,
- const AbstractMetaClass *context,
- Options options) const
-{
- QString s;
- static int constLen = strlen("const");
-
- if (context && cType &&
- context->typeEntry()->isGenericClass() &&
- cType->originalTemplateType()) {
- cType = cType->originalTemplateType();
- }
-
- if (!cType) {
- s = "void";
- } else if (cType->isArray()) {
- s = translateType(cType->arrayElementType(), context, options) + "[]";
- } else if (options & Generator::EnumAsInts && (cType->isEnum() || cType->isFlags())) {
- s = "int";
- } else {
- if (options & Generator::OriginalName) {
- s = cType->originalTypeDescription().trimmed();
- if ((options & Generator::ExcludeReference) && s.endsWith("&"))
- s = s.left(s.size()-1);
-
- // remove only the last const (avoid remove template const)
- if (options & Generator::ExcludeConst) {
- int index = s.lastIndexOf("const");
-
- if (index >= (s.size() - (constLen + 1))) // (VarType const) or (VarType const[*|&])
- s = s.remove(index, constLen);
- }
- } else if (options & Generator::ExcludeConst || options & Generator::ExcludeReference) {
- AbstractMetaType* copyType = cType->copy();
-
- if (options & Generator::ExcludeConst)
- copyType->setConstant(false);
-
- if (options & Generator::ExcludeReference)
- copyType->setReference(false);
-
- s = copyType->cppSignature();
- if (!copyType->typeEntry()->isVoid() && !copyType->typeEntry()->isCppPrimitive())
- s.prepend("::");
- delete copyType;
- } else {
- s = cType->cppSignature();
- }
- }
-
- return s;
-}
-
-
-QString Generator::subDirectoryForClass(const AbstractMetaClass* clazz) const
-{
- return subDirectoryForPackage(clazz->package());
-}
-
-QString Generator::subDirectoryForPackage(QString packageName) const
-{
- if (packageName.isEmpty())
- packageName = m_d->packageName;
- return QString(packageName).replace(".", QDir::separator());
-}
-
-template<typename T>
-static QString getClassTargetFullName_(const T* t, bool includePackageName)
-{
- QString name = t->name();
- const AbstractMetaClass* context = t->enclosingClass();
- while (context) {
- name.prepend('.');
- name.prepend(context->name());
- context = context->enclosingClass();
- }
- if (includePackageName) {
- name.prepend('.');
- name.prepend(t->package());
- }
- return name;
-}
-
-QString getClassTargetFullName(const AbstractMetaClass* metaClass, bool includePackageName)
-{
- return getClassTargetFullName_(metaClass, includePackageName);
-}
-
-QString getClassTargetFullName(const AbstractMetaEnum* metaEnum, bool includePackageName)
-{
- return getClassTargetFullName_(metaEnum, includePackageName);
-}
diff --git a/generators/generator.h b/generators/generator.h
deleted file mode 100644
index 92f7219ca..000000000
--- a/generators/generator.h
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * This file is part of the API Extractor 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
- *
- */
-
-#ifndef GENERATOR_H
-#define GENERATOR_H
-
-#include <QtCore/QObject>
-#include <QtCore/QDir>
-#include <QtCore/QLinkedList>
-#include <abstractmetalang.h>
-
-class ApiExtractor;
-class AbstractMetaBuilder;
-class QFile;
-
-QTextStream& formatCode(QTextStream &s, const QString& code, Indentor &indentor);
-void verifyDirectoryFor(const QFile &file);
-
-QString getClassTargetFullName(const AbstractMetaClass* metaClass, bool includePackageName = true);
-QString getClassTargetFullName(const AbstractMetaEnum* metaEnum, bool includePackageName = true);
-
-/**
- * Base class for all generators. The default implementations does nothing,
- * you must subclass this to create your own generators.
- */
-class Generator
-{
-public:
- /// Optiosn used around the generator code
- enum Option {
- NoOption = 0x00000000,
- BoxedPrimitive = 0x00000001,
- ExcludeConst = 0x00000002,
- ExcludeReference = 0x00000004,
- UseNativeIds = 0x00000008,
-
- EnumAsInts = 0x00000010,
- SkipName = 0x00000020,
- NoCasts = 0x00000040,
- SkipReturnType = 0x00000080,
- OriginalName = 0x00000100,
- ShowStatic = 0x00000200,
- UnderscoreSpaces = 0x00000400,
- ForceEnumCast = 0x00000800,
- ArrayAsPointer = 0x00001000,
- VirtualCall = 0x00002000,
- SkipTemplateParameters = 0x00004000,
- SkipAttributes = 0x00008000,
- OriginalTypeDescription = 0x00010000,
- SkipRemovedArguments = 0x00020000,
- IncludeDefaultExpression = 0x00040000,
- NoReturnStatement = 0x00080000,
- NoBlockedSlot = 0x00100000,
-
- SuperCall = 0x00200000,
-
- GlobalRefJObject = 0x00100000,
-
- SkipDefaultValues = 0x00400000,
-
- WriteSelf = 0x00800000,
- ExcludeMethodConst = 0x01000000,
-
- ForceValueType = ExcludeReference | ExcludeConst
- };
- Q_DECLARE_FLAGS(Options, Option)
-
- Generator();
- virtual ~Generator();
-
- bool setup(const ApiExtractor& extractor, const QMap<QString, QString> args);
-
- virtual QMap<QString, QString> options() const;
-
- /// Returns the classes used to generate the binding code.
- AbstractMetaClassList classes() const;
-
- /// Returns all global functions found by APIExtractor
- AbstractMetaFunctionList globalFunctions() const;
-
- /// Returns all global enums found by APIExtractor
- AbstractMetaEnumList globalEnums() const;
-
- /// Returns all primitive types found by APIExtractor
- QList<const PrimitiveTypeEntry*> primitiveTypes() const;
-
- /// Returns all container types found by APIExtractor
- QList<const ContainerTypeEntry*> containerTypes() const;
-
- /// Returns an AbstractMetaEnum for a given EnumTypeEntry, or NULL if not found.
- const AbstractMetaEnum* findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const;
-
- /// Returns an AbstractMetaEnum for a given TypeEntry that is an EnumTypeEntry, or NULL if not found.
- const AbstractMetaEnum* findAbstractMetaEnum(const TypeEntry* typeEntry) const;
-
- /// Returns an AbstractMetaEnum for the enum related to a given FlagsTypeEntry, or NULL if not found.
- const AbstractMetaEnum* findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const;
-
- /// Returns an AbstractMetaEnum for a given AbstractMetaType that holds an EnumTypeEntry, or NULL if not found.
- const AbstractMetaEnum* findAbstractMetaEnum(const AbstractMetaType* metaType) const;
-
- /// Returns the output directory
- QString outputDirectory() const;
-
- /// Set the output directory
- void setOutputDirectory(const QString &outDir);
-
- /**
- * Start the code generation, be sure to call setClasses before callign this method.
- * For each class it creates a QTextStream, call the write method with the current
- * class and the associated text stream, then write the text stream contents if needed.
- * \see #write
- */
- void generate();
-
- /// Returns the number of generated items
- int numGenerated() const;
-
- /// Returns the number of generated items written
- int numGeneratedAndWritten() const;
-
- /// Returns the generator's name. Used for cosmetic purposes.
- virtual const char* name() const = 0;
-
- /// Returns true if the generator should generate any code for the TypeEntry.
- bool shouldGenerateTypeEntry(const TypeEntry*) const;
-
- /// Returns true if the generator should generate any code for the AbstractMetaClass.
- virtual bool shouldGenerate(const AbstractMetaClass *) const;
-
- /// Returns the subdirectory used to write the binding code of an AbstractMetaClass.
- virtual QString subDirectoryForClass(const AbstractMetaClass* clazz) const;
-
- /**
- * Translate metatypes to binding source format.
- * \param metatype a pointer to metatype
- * \param context the current meta class
- * \param option some extra options
- * \return the metatype translated to binding source format
- */
- QString translateType(const AbstractMetaType *metatype,
- const AbstractMetaClass *context,
- Options options = NoOption) const;
-
- /**
- * Function used to write the fucntion arguments on the class buffer.
- * \param s the class output buffer
- * \param metafunction the pointer to metafunction information
- * \param count the number of function arguments
- * \param options some extra options used during the parser
- */
- virtual void writeFunctionArguments(QTextStream &s,
- const AbstractMetaFunction *metafunction,
- Options options = NoOption) const = 0;
-
- virtual void writeArgumentNames(QTextStream &s,
- const AbstractMetaFunction *metafunction,
- Options options = NoOption) const = 0;
-
- void replaceTemplateVariables(QString &code, const AbstractMetaFunction *func);
-
- // QtScript
- QSet<QString> qtMetaTypeDeclaredTypeNames() const;
-
- /**
- * Returns the license comment to be prepended to each source file generated.
- */
- QString licenseComment() const;
-
- /**
- * Sets the license comment to be prepended to each source file generated.
- */
- void setLicenseComment(const QString &licenseComment);
-
- /**
- * Returns the package name.
- */
- QString packageName() const;
-
- /**
- * Retrieves the name of the currently processed module.
- * While package name is a complete package idetification, e.g. 'PySide.QtCore',
- * a module name represents the last part of the package, e.g. 'QtCore'.
- * If the target language separates the modules with characters other than
- * dots ('.') the generator subclass must overload this method.
- * \return a string representing the last part of a package name
- */
- virtual QString moduleName() const;
-
- /**
- * Retrieves a list of constructors used in implicit conversions
- * available on the given type. The TypeEntry must be a value-type
- * or else it will return an empty list.
- * \param type a TypeEntry that is expected to be a value-type
- * \return a list of constructors that could be used as implicit converters
- */
- AbstractMetaFunctionList implicitConversions(const TypeEntry* type) const;
-
- /// Convenience function for implicitConversions(const TypeEntry* type).
- AbstractMetaFunctionList implicitConversions(const AbstractMetaType* metaType) const;
-
- /// Check if type is a pointer.
- static bool isPointer(const AbstractMetaType* type);
-
- /// Tells if the type or class is an Object (or QObject) Type.
- static bool isObjectType(const TypeEntry* type);
- static bool isObjectType(const ComplexTypeEntry* type);
- static bool isObjectType(const AbstractMetaType* metaType);
- static bool isObjectType(const AbstractMetaClass* metaClass);
-
- /// Returns true if the type is a C string (const char*).
- static bool isCString(const AbstractMetaType* type);
- /// Returns true if the type is a void pointer.
- static bool isVoidPointer(const AbstractMetaType* type);
-
- // Returns the full name of the type.
- QString getFullTypeName(const TypeEntry* type) const;
- QString getFullTypeName(const AbstractMetaType* type) const;
- QString getFullTypeName(const AbstractMetaClass* metaClass) const;
-
- /**
- * Returns the full qualified C++ name for an AbstractMetaType, but removing modifiers
- * as 'const', '&', and '*' (except if the class is not derived from a template).
- * This is useful for instantiated templates.
- */
- QString getFullTypeNameWithoutModifiers(const AbstractMetaType* type) const;
-
- /**
- * Tries to build a minimal constructor for the type.
- * It will check first for a user defined default constructor.
- * Returns a null string if it fails.
- */
- QString minimalConstructor(const TypeEntry* type) const;
- QString minimalConstructor(const AbstractMetaType* type) const;
- QString minimalConstructor(const AbstractMetaClass* metaClass) const;
-protected:
- /**
- * Returns the file name used to write the binding code of an AbstractMetaClass.
- * \param metaClass the AbstractMetaClass for which the file name must be
- * returned
- * \return the file name used to write the binding code for the class
- */
- virtual QString fileNameForClass(const AbstractMetaClass* metaClass) const = 0;
-
-
- virtual bool doSetup(const QMap<QString, QString>& args) = 0;
-
- /**
- * Write the bindding code for an AbstractMetaClass.
- * This is called by generate method.
- * \param s text stream to write the generated output
- * \param metaClass the class that should be generated
- */
- virtual void generateClass(QTextStream& s, const AbstractMetaClass* metaClass) = 0;
- virtual void finishGeneration() = 0;
-
- /**
- * Returns the subdirectory path for a given package
- * (aka module, aka library) name.
- * If the target language separates the package modules with characters other
- * than dots ('.') the generator subclass must overload this method.
- * /param packageName complete package name for which to return the subdirectory path
- * or nothing the use the name of the currently processed package
- * /return a string representing the subdirectory path for the given package
- */
- virtual QString subDirectoryForPackage(QString packageName = QString()) const;
-
- QList<const AbstractMetaType*> instantiatedContainers() const;
-
- static QString getSimplifiedContainerTypeName(const AbstractMetaType* type);
- void addInstantiatedContainers(const AbstractMetaType* type);
-
-private:
- struct GeneratorPrivate;
- GeneratorPrivate* m_d;
- void collectInstantiatedContainers(const AbstractMetaFunction* func);
- void collectInstantiatedContainers(const AbstractMetaClass* metaClass);
- void collectInstantiatedContainers();
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(Generator::Options)
-typedef QLinkedList<Generator*> GeneratorList;
-
-/**
-* Utility class to store the identation level, use it in a QTextStream.
-*/
-class Indentor
-{
-public:
- Indentor() : indent(0) {}
- int indent;
-};
-
-/**
-* Class that use the RAII idiom to set and unset the identation level.
-*/
-class Indentation
-{
-public:
- Indentation(Indentor &indentor) : indentor(indentor)
- {
- indentor.indent++;
- }
- ~Indentation()
- {
- indentor.indent--;
- }
-
-private:
- Indentor &indentor;
-};
-
-inline QTextStream &operator <<(QTextStream &s, const Indentor &indentor)
-{
- for (int i = 0; i < indentor.indent; ++i)
- s << " ";
- return s;
-}
-
-#endif // GENERATOR_H
-
diff --git a/generators/main.cpp b/generators/main.cpp
deleted file mode 100644
index f9f94f7ac..000000000
--- a/generators/main.cpp
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * This file is part of the PySide project.
- *
- * Copyright (C) 2009-2012 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 <QCoreApplication>
-#include <QLinkedList>
-#include <QLibrary>
-#include <QDomDocument>
-#include <iostream>
-#include <apiextractor.h>
-#include "generator.h"
-#include "shibokenconfig.h"
-#include "cppgenerator.h"
-#include "headergenerator.h"
-#include "qtdocgenerator.h"
-
-#ifdef _WINDOWS
- #define PATH_SPLITTER ";"
-#else
- #define PATH_SPLITTER ":"
-#endif
-
-namespace {
-
-class ArgsHandler
-{
-public:
- explicit ArgsHandler(const QMap<QString, QString>& other);
- virtual ~ArgsHandler();
-
- inline QMap<QString, QString>& args() const
- {
- return *m_args;
- }
-
- inline bool argExists(const QString& s) const
- {
- return m_args->contains(s);
- }
-
- QString removeArg(const QString& s);
- bool argExistsRemove(const QString& s);
-
- inline QString argValue(const QString& s) const
- {
- return m_args->value(s);
- }
-
- inline bool noArgs() const
- {
- return m_args->isEmpty();
- }
-
-private:
- QMap<QString, QString>* m_args;
-};
-
-ArgsHandler::ArgsHandler(const QMap<QString, QString>& other)
- : m_args(new QMap<QString, QString>(other))
-{
-}
-
-ArgsHandler::~ArgsHandler()
-{
- delete m_args;
-}
-
-QString ArgsHandler::removeArg(const QString& s)
-{
- QString retval;
-
- if (argExists(s)) {
- retval = argValue(s);
- m_args->remove(s);
- }
-
- return retval;
-}
-
-bool ArgsHandler::argExistsRemove(const QString& s)
-{
- bool retval = false;
-
- if (argExists(s)) {
- retval = true;
- m_args->remove(s);
- }
-
- return retval;
-}
-
-}
-
-static void printOptions(QTextStream& s, const QMap<QString, QString>& options)
-{
- QMap<QString, QString>::const_iterator it = options.constBegin();
- s.setFieldAlignment(QTextStream::AlignLeft);
- for (; it != options.constEnd(); ++it) {
- s << " --";
- s.setFieldWidth(38);
- s << it.key() << it.value();
- s.setFieldWidth(0);
- s << endl;
- }
-}
-
-typedef void (*getGeneratorsFunc)(QLinkedList<Generator*>*);
-
-static bool processProjectFile(QFile& projectFile, QMap<QString, QString>& args)
-{
- QByteArray line = projectFile.readLine().trimmed();
- if (line.isEmpty() || line != "[generator-project]")
- return false;
-
- QStringList includePaths;
- QStringList typesystemPaths;
- QStringList apiVersions;
-
- while (!projectFile.atEnd()) {
- line = projectFile.readLine().trimmed();
- if (line.isEmpty())
- continue;
-
- int split = line.indexOf("=");
- QString key;
- QString value;
- if (split > 0) {
- key = line.left(split - 1).trimmed();
- value = line.mid(split + 1).trimmed();
- } else {
- key = line;
- }
-
- if (key == "include-path")
- includePaths << QDir::toNativeSeparators(value);
- else if (key == "typesystem-path")
- typesystemPaths << QDir::toNativeSeparators(value);
- else if (key == "api-version")
- apiVersions << value;
- else if (key == "header-file")
- args["arg-1"] = value;
- else if (key == "typesystem-file")
- args["arg-2"] = value;
- else
- args[key] = value;
- }
-
- if (!includePaths.isEmpty())
- args["include-paths"] = includePaths.join(PATH_SPLITTER);
-
- if (!typesystemPaths.isEmpty())
- args["typesystem-paths"] = typesystemPaths.join(PATH_SPLITTER);
- if (!apiVersions.isEmpty())
- args["api-version"] = apiVersions.join("|");
- return true;
-}
-
-static QMap<QString, QString> getInitializedArguments()
-{
- QMap<QString, QString> args;
- QStringList arguments = QCoreApplication::arguments();
- QString appName = arguments.first();
- arguments.removeFirst();
-
- QString projectFileName;
- foreach (const QString& arg, arguments) {
- if (arg.startsWith("--project-file")) {
- int split = arg.indexOf("=");
- if (split > 0)
- projectFileName = arg.mid(split + 1).trimmed();
- break;
- }
- }
-
- if (projectFileName.isNull())
- return args;
-
- if (!QFile::exists(projectFileName)) {
- std::cerr << qPrintable(appName) << ": Project file \"";
- std::cerr << qPrintable(projectFileName) << "\" not found.";
- std::cerr << std::endl;
- return args;
- }
-
- QFile projectFile(projectFileName);
- if (!projectFile.open(QIODevice::ReadOnly))
- return args;
-
- if (!processProjectFile(projectFile, args)) {
- std::cerr << qPrintable(appName) << ": first line of project file \"";
- std::cerr << qPrintable(projectFileName) << "\" must be the string \"[generator-project]\"";
- std::cerr << std::endl;
- return args;
- }
-
- return args;
-}
-
-static QMap<QString, QString> getCommandLineArgs()
-{
- QMap<QString, QString> args = getInitializedArguments();
- QStringList arguments = QCoreApplication::arguments();
- arguments.removeFirst();
-
- int argNum = 0;
- foreach (QString arg, arguments) {
- arg = arg.trimmed();
- if (arg.startsWith("--")) {
- int split = arg.indexOf("=");
- if (split > 0)
- args[arg.mid(2).left(split-2)] = arg.mid(split + 1).trimmed();
- else
- args[arg.mid(2)] = QString();
- } else if (arg.startsWith("-")) {
- args[arg.mid(1)] = QString();
- } else {
- argNum++;
- args[QString("arg-%1").arg(argNum)] = arg;
- }
- }
- return args;
-}
-
-void printUsage(const GeneratorList& generators)
-{
- QTextStream s(stdout);
- s << "Usage:\n "
- << "shiboken [options] header-file typesystem-file\n\n"
- << "General options:\n";
- QMap<QString, QString> generalOptions;
- generalOptions.insert("project-file=<file>", "text file containing a description of the binding project. Replaces and overrides command line arguments");
- generalOptions.insert("debug-level=[sparse|medium|full]", "Set the debug level");
- generalOptions.insert("silent", "Avoid printing any message");
- generalOptions.insert("help", "Display this help and exit");
- generalOptions.insert("no-suppress-warnings", "Show all warnings");
- generalOptions.insert("output-directory=<path>", "The directory where the generated files will be written");
- generalOptions.insert("include-paths=<path>[" PATH_SPLITTER "<path>" PATH_SPLITTER "...]", "Include paths used by the C++ parser");
- generalOptions.insert("typesystem-paths=<path>[" PATH_SPLITTER "<path>" PATH_SPLITTER "...]", "Paths used when searching for typesystems");
- generalOptions.insert("documentation-only", "Do not generates any code, just the documentation");
- generalOptions.insert("license-file=<license-file>", "File used for copyright headers of generated files");
- generalOptions.insert("version", "Output version information and exit");
- generalOptions.insert("generator-set=<\"generator module\">", "generator-set to be used. e.g. qtdoc");
- generalOptions.insert("api-version=<\"package mask\">,<\"version\">", "Specify the supported api version used to generate the bindings");
- generalOptions.insert("drop-type-entries=\"<TypeEntry0>[;TypeEntry1;...]\"", "Semicolon separated list of type system entries (classes, namespaces, global functions and enums) to be dropped from generation.");
- printOptions(s, generalOptions);
-
- foreach (Generator* generator, generators) {
- QMap<QString, QString> options = generator->options();
- if (!options.isEmpty()) {
- s << endl << generator->name() << " options:\n";
- printOptions(s, generator->options());
- }
- }
-}
-
-static inline void printVerAndBanner()
-{
- std::cout << "shiboken v" SHIBOKEN_VERSION << std::endl;
- std::cout << "Copyright (C) 2009-2012 Nokia Corporation and/or its subsidiary(-ies)" << std::endl;
-}
-
-static inline void errorPrint(const QString& s,
- const bool& verAndBanner = false)
-{
- if (verAndBanner)
- printVerAndBanner();
-
- std::cerr << s.toAscii().constData() << std::endl;
-}
-
-int main(int argc, char *argv[])
-{
- // needed by qxmlpatterns
- QCoreApplication app(argc, argv);
-
- // Store command arguments in a map
- QMap<QString, QString> args = getCommandLineArgs();
- ArgsHandler argsHandler(args);
- GeneratorList generators;
-
- if (argsHandler.argExistsRemove("version")) {
- printVerAndBanner();
- return EXIT_SUCCESS;
- }
-
- QString generatorSet = argsHandler.removeArg("generator-set");
- // Also check "generatorSet" command line argument for backward compatibility.
- if (generatorSet.isEmpty())
- generatorSet = argsHandler.removeArg("generatorSet");
-
- // Pre-defined generator sets.
- if (generatorSet == "qtdoc") {
- generators << new QtDocGenerator;
- } else if (generatorSet.isEmpty() || generatorSet == "shiboken") {
- generators << new CppGenerator << new HeaderGenerator;
- } else {
- errorPrint("shiboken: Unknown generator set, try \"shiboken\" or \"qtdoc\".");
- return EXIT_FAILURE;
- }
-
- if (argsHandler.argExistsRemove("help")) {
- printUsage(generators);
- return EXIT_SUCCESS;
- }
-
- QString licenseComment;
- QString licenseFileName = argsHandler.removeArg("license-file");
- if (!licenseFileName.isEmpty()) {
- if (QFile::exists(licenseFileName)) {
- QFile licenseFile(licenseFileName);
- if (licenseFile.open(QIODevice::ReadOnly))
- licenseComment = licenseFile.readAll();
- } else {
- errorPrint(QString("Couldn't find the file containing the license heading: %1").
- arg(qPrintable(licenseFileName)));
- return EXIT_FAILURE;
- }
- }
-
- QString outputDirectory = argsHandler.removeArg("output-directory");
- if (outputDirectory.isEmpty())
- outputDirectory = "out";
-
- if (!QDir(outputDirectory).exists()) {
- if (!QDir().mkpath(outputDirectory)) {
- ReportHandler::warning("Can't create output directory: "+outputDirectory);
- return EXIT_FAILURE;
- }
- }
-
- // Create and set-up API Extractor
- ApiExtractor extractor;
- extractor.setLogDirectory(outputDirectory);
-
- if (argsHandler.argExistsRemove("silent")) {
- extractor.setSilent(true);
- } else {
- QString level = argsHandler.removeArg("debug-level");
- if (!level.isEmpty()) {
- if (level == "sparse")
- extractor.setDebugLevel(ReportHandler::SparseDebug);
- else if (level == "medium")
- extractor.setDebugLevel(ReportHandler::MediumDebug);
- else if (level == "full")
- extractor.setDebugLevel(ReportHandler::FullDebug);
- }
- }
- if (argsHandler.argExistsRemove("no-suppress-warnings"))
- extractor.setSuppressWarnings(false);
-
- if (argsHandler.argExists("api-version")) {
- QStringList versions = argsHandler.removeArg("api-version").split("|");
- foreach (QString fullVersion, versions) {
- QStringList parts = fullVersion.split(",");
- QString package;
- QString version;
- package = parts.count() == 1 ? "*" : parts.first();
- version = parts.last();
- extractor.setApiVersion(package, version.toAscii());
- }
- }
-
- if (argsHandler.argExists("drop-type-entries"))
- extractor.setDropTypeEntries(argsHandler.removeArg("drop-type-entries"));
-
- QString path = argsHandler.removeArg("typesystem-paths");
- if (!path.isEmpty())
- extractor.addTypesystemSearchPath(path.split(PATH_SPLITTER));
-
- path = argsHandler.removeArg("include-paths");
- if (!path.isEmpty())
- extractor.addIncludePath(path.split(PATH_SPLITTER));
-
- QString cppFileName = argsHandler.removeArg("arg-1");
- QString typeSystemFileName = argsHandler.removeArg("arg-2");
-
- /* Make sure to remove the project file's arguments (if any) and
- * --project-file, also the arguments of each generator before
- * checking if there isn't any existing arguments in argsHandler.
- */
- argsHandler.removeArg("project-file");
- QMap<QString, QString> projectFileArgs = getInitializedArguments();
- if (!projectFileArgs.isEmpty()) {
- QMap<QString, QString>::const_iterator it =
- projectFileArgs.constBegin();
- for ( ; it != projectFileArgs.constEnd(); ++it)
- argsHandler.removeArg(it.key());
- }
- foreach (Generator* generator, generators) {
- QMap<QString, QString> options = generator->options();
- if (!options.isEmpty()) {
- QMap<QString, QString>::const_iterator it = options.constBegin();
- for ( ; it != options.constEnd(); ++it)
- argsHandler.removeArg(it.key());
- }
- }
-
- if (!argsHandler.noArgs()) {
- errorPrint("shiboken: Called with wrong arguments.");
- std::cout << "Note: use --help option for more information." << std::endl;
- return EXIT_FAILURE;
- }
-
- extractor.setCppFileName(cppFileName);
- extractor.setTypeSystem(typeSystemFileName);
- if (!extractor.run())
- return EXIT_FAILURE;
-
- if (!extractor.classCount())
- ReportHandler::warning("No C++ classes found!");
-
- foreach (Generator* g, generators) {
- g->setOutputDirectory(outputDirectory);
- g->setLicenseComment(licenseComment);
- if (g->setup(extractor, args))
- g->generate();
- }
- qDeleteAll(generators);
-
- ReportHandler::flush();
- std::cout << "Done, " << ReportHandler::warningCount();
- std::cout << " warnings (" << ReportHandler::suppressedCount() << " known issues)";
- std::cout << std::endl;
-}
diff --git a/generators/qtdoc/CMakeLists.txt b/generators/qtdoc/CMakeLists.txt
deleted file mode 100644
index 541e7c6ee..000000000
--- a/generators/qtdoc/CMakeLists.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-project(qtdoc_generator)
-
-set(qtdoc_generator_SRC
-qtdocgenerator.cpp
-)
-
-include_directories(${generators_SOURCE_DIR}
- ${QT_QTCORE_INCLUDE_DIR}
- ${APIEXTRACTOR_INCLUDE_DIR})
-add_executable(docgenerator main.cpp)
-set_target_properties(docgenerator PROPERTIES OUTPUT_NAME docgenerator${generator_SUFFIX})
-
-target_link_libraries(docgenerator ${QT_QTCORE_LIBRARY})
-
-add_library(qtdoc_generator SHARED ${qtdoc_generator_SRC})
-target_link_libraries(qtdoc_generator ${APIEXTRACTOR_LIBRARY} ${QT_QTCORE_LIBRARY} genrunner)
-set_property(TARGET qtdoc_generator PROPERTY PREFIX "")
-
-install(TARGETS qtdoc_generator DESTINATION ${generator_plugin_DIR})
-install(TARGETS docgenerator DESTINATION bin)
-
diff --git a/generators/qtdoc/qtdocgenerator.cpp b/generators/qtdoc/qtdocgenerator.cpp
deleted file mode 100644
index 593456405..000000000
--- a/generators/qtdoc/qtdocgenerator.cpp
+++ /dev/null
@@ -1,1652 +0,0 @@
-/*
- * This file is part of the PySide 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 "qtdocgenerator.h"
-#include <reporthandler.h>
-#include <qtdocparser.h>
-#include <doxygenparser.h>
-#include <typedatabase.h>
-#include <algorithm>
-#include <QtCore/QStack>
-#include <QtCore/QTextStream>
-#include <QtCore/QXmlStreamReader>
-#include <QtCore/QFile>
-#include <QtCore/QDir>
-#include <fileout.h>
-#include <limits>
-
-static Indentor INDENT;
-
-static bool shouldSkip(const AbstractMetaFunction* func)
-{
- bool skipable = func->isConstructor()
- || func->isModifiedRemoved()
- || func->declaringClass() != func->ownerClass()
- || func->isCastOperator()
- || func->name() == "operator=";
-
- // Search a const clone
- if (!skipable && !func->isConstant()) {
- const AbstractMetaArgumentList funcArgs = func->arguments();
- foreach (AbstractMetaFunction* f, func->ownerClass()->functions()) {
- if (f != func
- && f->isConstant()
- && f->name() == func->name()
- && f->arguments().count() == funcArgs.count()) {
- // Compare each argument
- bool cloneFound = true;
-
- const AbstractMetaArgumentList fargs = f->arguments();
- for (int i = 0, max = funcArgs.count(); i < max; ++i) {
- if (funcArgs.at(i)->type()->typeEntry() != fargs.at(i)->type()->typeEntry()) {
- cloneFound = false;
- break;
- }
- }
- if (cloneFound)
- return true;
- }
- }
- }
- return skipable;
-}
-
-static bool functionSort(const AbstractMetaFunction* func1, const AbstractMetaFunction* func2)
-{
- return func1->name() < func2->name();
-}
-
-static QString createRepeatedChar(int i, char c)
-{
- QString out;
- for (int j = 0; j < i; ++j)
- out += c;
-
- return out;
-}
-
-static QString escape(QString& str)
-{
- return str
- .replace("*", "\\*")
- .replace("_", "\\_");
-}
-
-static QString escape(const QStringRef& strref)
-{
- QString str = strref.toString();
- return escape(str);
-}
-
-
-QtXmlToSphinx::QtXmlToSphinx(QtDocGenerator* generator, const QString& doc, const QString& context)
- : m_context(context), m_generator(generator), m_insideBold(false), m_insideItalic(false)
-{
- m_handlerMap.insert("heading", &QtXmlToSphinx::handleHeadingTag);
- m_handlerMap.insert("brief", &QtXmlToSphinx::handleParaTag);
- m_handlerMap.insert("para", &QtXmlToSphinx::handleParaTag);
- m_handlerMap.insert("italic", &QtXmlToSphinx::handleItalicTag);
- m_handlerMap.insert("bold", &QtXmlToSphinx::handleBoldTag);
- m_handlerMap.insert("see-also", &QtXmlToSphinx::handleSeeAlsoTag);
- m_handlerMap.insert("snippet", &QtXmlToSphinx::handleSnippetTag);
- m_handlerMap.insert("dots", &QtXmlToSphinx::handleDotsTag);
- m_handlerMap.insert("codeline", &QtXmlToSphinx::handleDotsTag);
- m_handlerMap.insert("table", &QtXmlToSphinx::handleTableTag);
- m_handlerMap.insert("header", &QtXmlToSphinx::handleRowTag);
- m_handlerMap.insert("row", &QtXmlToSphinx::handleRowTag);
- m_handlerMap.insert("item", &QtXmlToSphinx::handleItemTag);
- m_handlerMap.insert("argument", &QtXmlToSphinx::handleArgumentTag);
- m_handlerMap.insert("teletype", &QtXmlToSphinx::handleArgumentTag);
- m_handlerMap.insert("link", &QtXmlToSphinx::handleLinkTag);
- m_handlerMap.insert("inlineimage", &QtXmlToSphinx::handleImageTag);
- m_handlerMap.insert("image", &QtXmlToSphinx::handleImageTag);
- m_handlerMap.insert("list", &QtXmlToSphinx::handleListTag);
- m_handlerMap.insert("term", &QtXmlToSphinx::handleTermTag);
- m_handlerMap.insert("raw", &QtXmlToSphinx::handleRawTag);
- m_handlerMap.insert("underline", &QtXmlToSphinx::handleItalicTag);
- m_handlerMap.insert("superscript", &QtXmlToSphinx::handleSuperScriptTag);
- m_handlerMap.insert("code", &QtXmlToSphinx::handleCodeTag);
- m_handlerMap.insert("badcode", &QtXmlToSphinx::handleCodeTag);
- m_handlerMap.insert("legalese", &QtXmlToSphinx::handleCodeTag);
- m_handlerMap.insert("section", &QtXmlToSphinx::handleAnchorTag);
- m_handlerMap.insert("quotefile", &QtXmlToSphinx::handleQuoteFileTag);
-
- // ignored tags
- m_handlerMap.insert("generatedlist", &QtXmlToSphinx::handleIgnoredTag);
- m_handlerMap.insert("tableofcontents", &QtXmlToSphinx::handleIgnoredTag);
- m_handlerMap.insert("quotefromfile", &QtXmlToSphinx::handleIgnoredTag);
- m_handlerMap.insert("skipto", &QtXmlToSphinx::handleIgnoredTag);
- m_handlerMap.insert("target", &QtXmlToSphinx::handleIgnoredTag);
-
- // useless tags
- m_handlerMap.insert("description", &QtXmlToSphinx::handleUselessTag);
- m_handlerMap.insert("definition", &QtXmlToSphinx::handleUselessTag);
- m_handlerMap.insert("printuntil", &QtXmlToSphinx::handleUselessTag);
- m_handlerMap.insert("relation", &QtXmlToSphinx::handleUselessTag);
-
- // Doxygen tags
- m_handlerMap.insert("title", &QtXmlToSphinx::handleHeadingTag);
- m_handlerMap.insert("ref", &QtXmlToSphinx::handleParaTag);
- m_handlerMap.insert("computeroutput", &QtXmlToSphinx::handleParaTag);
- m_handlerMap.insert("detaileddescription", &QtXmlToSphinx::handleParaTag);
- m_handlerMap.insert("name", &QtXmlToSphinx::handleParaTag);
- m_handlerMap.insert("listitem", &QtXmlToSphinx::handleItemTag);
- m_handlerMap.insert("parametername", &QtXmlToSphinx::handleItemTag);
- m_handlerMap.insert("parameteritem", &QtXmlToSphinx::handleItemTag);
- m_handlerMap.insert("ulink", &QtXmlToSphinx::handleLinkTag);
- m_handlerMap.insert("itemizedlist", &QtXmlToSphinx::handleListTag);
- m_handlerMap.insert("parameternamelist", &QtXmlToSphinx::handleListTag);
- m_handlerMap.insert("parameterlist", &QtXmlToSphinx::handleListTag);
-
- // Doxygen ignored tags
- m_handlerMap.insert("highlight", &QtXmlToSphinx::handleIgnoredTag);
- m_handlerMap.insert("linebreak", &QtXmlToSphinx::handleIgnoredTag);
- m_handlerMap.insert("programlisting", &QtXmlToSphinx::handleIgnoredTag);
- m_handlerMap.insert("xreftitle", &QtXmlToSphinx::handleIgnoredTag);
- m_handlerMap.insert("sp", &QtXmlToSphinx::handleIgnoredTag);
- m_handlerMap.insert("entry", &QtXmlToSphinx::handleIgnoredTag);
- m_handlerMap.insert("simplesect", &QtXmlToSphinx::handleIgnoredTag);
- m_handlerMap.insert("verbatim", &QtXmlToSphinx::handleIgnoredTag);
- m_handlerMap.insert("xrefsect", &QtXmlToSphinx::handleIgnoredTag);
- m_handlerMap.insert("xrefdescription", &QtXmlToSphinx::handleIgnoredTag);
-
- m_result = transform(doc);
-}
-
-void QtXmlToSphinx::pushOutputBuffer()
-{
- QString* buffer = new QString();
- m_buffers << buffer;
- m_output.setString(buffer);
-}
-
-QString QtXmlToSphinx::popOutputBuffer()
-{
- Q_ASSERT(!m_buffers.isEmpty());
- QString* str = m_buffers.pop();
- QString strcpy(*str);
- delete str;
- m_output.setString(m_buffers.isEmpty() ? 0 : m_buffers.top());
- return strcpy;
-}
-
-QString QtXmlToSphinx::expandFunction(const QString& function)
-{
- QStringList functionSpec = function.split('.');
- QString className = functionSpec.first();
- const AbstractMetaClass* metaClass = 0;
- foreach (const AbstractMetaClass* cls, m_generator->classes()) {
- if (cls->name() == className) {
- metaClass = cls;
- break;
- }
- }
-
- if (metaClass) {
- functionSpec.removeFirst();
- return metaClass->typeEntry()->qualifiedTargetLangName() + "." + functionSpec.join(".");
- } else {
- return function;
- }
-}
-
-QString QtXmlToSphinx::resolveContextForMethod(const QString& methodName)
-{
- QString currentClass = m_context.split(".").last();
-
- const AbstractMetaClass* metaClass = 0;
- foreach (const AbstractMetaClass* cls, m_generator->classes()) {
- if (cls->name() == currentClass) {
- metaClass = cls;
- break;
- }
- }
-
- if (metaClass) {
- QList<const AbstractMetaFunction*> funcList;
- foreach (const AbstractMetaFunction* func, metaClass->queryFunctionsByName(methodName)) {
- if (methodName == func->name())
- funcList.append(func);
- }
-
- const AbstractMetaClass* implementingClass = 0;
- foreach (const AbstractMetaFunction* func, funcList) {
- implementingClass = func->implementingClass();
- if (implementingClass->name() == currentClass)
- break;
- }
-
- if (implementingClass)
- return implementingClass->typeEntry()->qualifiedTargetLangName();
- }
-
- return QLatin1String("~") + m_context;
-}
-
-QString QtXmlToSphinx::transform(const QString& doc)
-{
- Q_ASSERT(m_buffers.isEmpty());
- Indentation indentation(INDENT);
- if (doc.trimmed().isEmpty())
- return doc;
-
- pushOutputBuffer();
-
- QXmlStreamReader reader(doc);
-
- while (!reader.atEnd()) {
- QXmlStreamReader::TokenType token = reader.readNext();
- if (reader.hasError()) {
- m_output << INDENT << "XML Error: " + reader.errorString() + "\n" + doc;
- ReportHandler::warning("XML Error: " + reader.errorString() + "\n" + doc);
- break;
- }
-
- if (token == QXmlStreamReader::StartElement) {
- QStringRef tagName = reader.name();
- TagHandler handler = m_handlerMap.value(tagName.toString(), &QtXmlToSphinx::handleUnknownTag);
- if (!m_handlers.isEmpty() && ( (m_handlers.top() == &QtXmlToSphinx::handleIgnoredTag) ||
- (m_handlers.top() == &QtXmlToSphinx::handleRawTag)) )
- handler = &QtXmlToSphinx::handleIgnoredTag;
-
- m_handlers.push(handler);
- }
- if (!m_handlers.isEmpty())
- (this->*(m_handlers.top()))(reader);
-
- if (token == QXmlStreamReader::EndElement) {
- m_handlers.pop();
- m_lastTagName = reader.name().toString();
- }
- }
- m_output.flush();
- QString retval = popOutputBuffer();
- Q_ASSERT(m_buffers.isEmpty());
- return retval;
-}
-
-QString QtXmlToSphinx::readFromLocations(const QStringList& locations, const QString& path, const QString& identifier)
-{
- QString result;
- bool ok;
- foreach (QString location, locations) {
- location.append('/');
- location.append(path);
- result = readFromLocation(location, identifier, &ok);
- if (ok)
- break;
- }
- if (!ok)
- ReportHandler::warning("Couldn't read code snippet file: {"+ locations.join("|") + '}' + path);
- return result;
-}
-
-QString QtXmlToSphinx::readFromLocation(const QString& location, const QString& identifier, bool* ok)
-{
- QFile inputFile;
- inputFile.setFileName(location);
- if (!inputFile.open(QIODevice::ReadOnly)) {
- if (!ok)
- ReportHandler::warning("Couldn't read code snippet file: "+inputFile.fileName());
- else
- *ok = false;
- return QString();
- }
-
- QRegExp searchString("//!\\s*\\[" + identifier + "\\]");
- QRegExp codeSnippetCode("//!\\s*\\[[\\w\\d\\s]+\\]");
- QString code;
- QString line;
- bool identifierIsEmpty = identifier.isEmpty();
- bool getCode = false;
-
- while (!inputFile.atEnd()) {
- line = inputFile.readLine();
- if (identifierIsEmpty) {
- code += line;
- } else if (getCode && !line.contains(searchString)) {
- code += line.replace(codeSnippetCode, "");
- } else if (line.contains(searchString)) {
- if (getCode)
- break;
- else
- getCode = true;
- }
- }
-
- if (!identifierIsEmpty && !getCode)
- ReportHandler::warning("Code snippet file found ("+location+"), but snippet "+ identifier +" not found.");
-
- if (ok)
- *ok = true;
- return code;
-}
-
-void QtXmlToSphinx::handleHeadingTag(QXmlStreamReader& reader)
-{
- static QString heading;
- static char type;
- static char types[] = { '-', '^' };
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- uint typeIdx = reader.attributes().value("level").toString().toInt();
- if (typeIdx >= sizeof(types))
- type = types[sizeof(types)-1];
- else
- type = types[typeIdx];
- } else if (token == QXmlStreamReader::EndElement) {
- m_output << createRepeatedChar(heading.length(), type) << endl << endl;
- } else if (token == QXmlStreamReader::Characters) {
- heading = escape(reader.text()).trimmed();
- m_output << endl << endl << heading << endl;
- }
-}
-
-void QtXmlToSphinx::handleParaTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- pushOutputBuffer();
- } else if (token == QXmlStreamReader::EndElement) {
- QString result = popOutputBuffer().simplified();
- if (result.startsWith("**Warning:**"))
- result.replace(0, 12, ".. warning:: ");
- else if (result.startsWith("**Note:**"))
- result.replace(0, 9, ".. note:: ");
-
- m_output << INDENT << result << endl << endl;
- } else if (token == QXmlStreamReader::Characters) {
- QString text = escape(reader.text());
- if (!m_output.string()->isEmpty()) {
- QChar start = text[0];
- QChar end = m_output.string()->at(m_output.string()->length() - 1);
- if ((end == '*' || end == '`') && start != ' ' && !start.isPunct())
- m_output << '\\';
- }
- m_output << INDENT << text;
- }
-}
-
-void QtXmlToSphinx::handleItalicTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement) {
- m_insideItalic = !m_insideItalic;
- m_output << '*';
- } else if (token == QXmlStreamReader::Characters) {
- m_output << escape(reader.text()).trimmed();
- }
-}
-
-void QtXmlToSphinx::handleBoldTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement) {
- m_insideBold = !m_insideBold;
- m_output << "**";
- } else if (token == QXmlStreamReader::Characters) {
- m_output << escape(reader.text()).trimmed();
- }
-}
-
-void QtXmlToSphinx::handleArgumentTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement)
- m_output << "``";
- else if (token == QXmlStreamReader::Characters)
- m_output << reader.text().toString().trimmed();
-}
-
-void QtXmlToSphinx::handleSeeAlsoTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement)
- m_output << INDENT << ".. seealso:: ";
- else if (token == QXmlStreamReader::EndElement)
- m_output << endl;
-}
-
-void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- bool consecutiveSnippet = m_lastTagName == "snippet" || m_lastTagName == "dots" || m_lastTagName == "codeline";
- if (consecutiveSnippet) {
- m_output.flush();
- m_output.string()->chop(2);
- }
- QString location = reader.attributes().value("location").toString();
- QString identifier = reader.attributes().value("identifier").toString();
- QString code = readFromLocations(m_generator->codeSnippetDirs(), location, identifier);
- if (!consecutiveSnippet)
- m_output << INDENT << "::\n\n";
-
- Indentation indentation(INDENT);
- if (code.isEmpty()) {
- m_output << INDENT << "<Code snippet \"" << location << ':' << identifier << "\" not found>" << endl;
- } else {
- foreach (QString line, code.split("\n")) {
- if (!QString(line).trimmed().isEmpty())
- m_output << INDENT << line;
-
- m_output << endl;
- }
- }
- m_output << endl;
- }
-}
-void QtXmlToSphinx::handleDotsTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- bool consecutiveSnippet = m_lastTagName == "snippet" || m_lastTagName == "dots" || m_lastTagName == "codeline";
- if (consecutiveSnippet) {
- m_output.flush();
- m_output.string()->chop(2);
- }
- Indentation indentation(INDENT);
- pushOutputBuffer();
- m_output << INDENT;
- int indent = reader.attributes().value("indent").toString().toInt();
- for (int i = 0; i < indent; ++i)
- m_output << ' ';
- } else if (token == QXmlStreamReader::Characters) {
- m_output << reader.text().toString();
- } else if (token == QXmlStreamReader::EndElement) {
- m_output << popOutputBuffer() << "\n\n\n";
- }
-}
-
-void QtXmlToSphinx::handleTableTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- m_currentTable.clear();
- m_tableHasHeader = false;
- } else if (token == QXmlStreamReader::EndElement) {
- // write the table on m_output
- m_currentTable.enableHeader(m_tableHasHeader);
- m_currentTable.normalize();
- m_output << m_currentTable;
- m_currentTable.clear();
- }
-}
-
-void QtXmlToSphinx::handleTermTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- pushOutputBuffer();
- } else if (token == QXmlStreamReader::Characters) {
- m_output << reader.text().toString().replace("::", ".");
- } else if (token == QXmlStreamReader::EndElement) {
- TableCell cell;
- cell.data = popOutputBuffer().trimmed();
- m_currentTable << (TableRow() << cell);
- }
-}
-
-
-void QtXmlToSphinx::handleItemTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- if (m_currentTable.isEmpty())
- m_currentTable << TableRow();
- TableRow& row = m_currentTable.last();
- TableCell cell;
- cell.colSpan = reader.attributes().value("colspan").toString().toShort();
- cell.rowSpan = reader.attributes().value("rowspan").toString().toShort();
- row << cell;
- pushOutputBuffer();
- } else if (token == QXmlStreamReader::EndElement) {
- QString data = popOutputBuffer().trimmed();
- if (!m_currentTable.isEmpty()) {
- TableRow& row = m_currentTable.last();
- if (!row.isEmpty())
- row.last().data = data;
- }
- }
-}
-
-void QtXmlToSphinx::handleRowTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- m_tableHasHeader = reader.name() == "header";
- m_currentTable << TableRow();
- }
-}
-
-void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader)
-{
- // BUG We do not support a list inside a table cell
- static QString listType;
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- listType = reader.attributes().value("type").toString();
- if (listType == "enum") {
- m_currentTable << (TableRow() << "Constant" << "Description");
- m_tableHasHeader = true;
- }
- INDENT.indent--;
- } else if (token == QXmlStreamReader::EndElement) {
- INDENT.indent++;
- if (!m_currentTable.isEmpty()) {
- if (listType == "bullet") {
- m_output << endl;
- foreach (TableCell cell, m_currentTable.first()) {
- QStringList itemLines = cell.data.split('\n');
- m_output << INDENT << "* " << itemLines.first() << endl;
- for (int i = 1, max = itemLines.count(); i < max; ++i)
- m_output << INDENT << " " << itemLines[i] << endl;
- }
- m_output << endl;
- } else if (listType == "enum") {
- m_currentTable.enableHeader(m_tableHasHeader);
- m_currentTable.normalize();
- m_output << m_currentTable;
- }
- }
- m_currentTable.clear();
- }
-}
-
-void QtXmlToSphinx::handleLinkTag(QXmlStreamReader& reader)
-{
- static QString l_linktag;
- static QString l_linkref;
- static QString l_linktext;
- static QString l_linktagending;
- static QString l_type;
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- l_linktagending = "` ";
- if (m_insideBold) {
- l_linktag.prepend("**");
- l_linktagending.append("**");
- } else if (m_insideItalic) {
- l_linktag.prepend('*');
- l_linktagending.append('*');
- }
- l_type = reader.attributes().value("type").toString();
-
- // TODO: create a flag PROPERTY-AS-FUNCTION to ask if the properties
- // are recognized as such or not in the binding
- if (l_type == "property")
- l_type = "function";
-
- if (l_type == "typedef")
- l_type = "class";
-
- QString linkSource;
- if (l_type == "function" || l_type == "class") {
- linkSource = "raw";
- } else if (l_type == "enum") {
- linkSource = "enum";
- } else if (l_type == "page") {
- linkSource = "page";
- } else {
- linkSource = "href";
- }
-
- l_linkref = reader.attributes().value(linkSource).toString();
- l_linkref.replace("::", ".");
- l_linkref.remove("()");
-
- if (l_type == "function" && !m_context.isEmpty()) {
- l_linktag = " :meth:`";
- QStringList rawlinklist = l_linkref.split(".");
- if (rawlinklist.size() == 1 || rawlinklist.first() == m_context) {
- QString context = resolveContextForMethod(rawlinklist.last());
- if (!l_linkref.startsWith(context))
- l_linkref.prepend(context + '.');
- } else {
- l_linkref = expandFunction(l_linkref);
- }
- } else if (l_type == "function" && m_context.isEmpty()) {
- l_linktag = " :func:`";
- } else if (l_type == "class") {
- l_linktag = " :class:`";
- TypeEntry* type = TypeDatabase::instance()->findType(l_linkref);
- if (type) {
- l_linkref = type->qualifiedTargetLangName();
- } else { // fall back to the old heuristic if the type wasn't found.
- QStringList rawlinklist = l_linkref.split(".");
- QStringList splittedContext = m_context.split(".");
- if (rawlinklist.size() == 1 || rawlinklist.first() == splittedContext.last()) {
- splittedContext.removeLast();
- l_linkref.prepend('~' + splittedContext.join(".") + '.');
- }
- }
- } else if (l_type == "enum") {
- l_linktag = " :attr:`";
- } else if (l_type == "page" && l_linkref == m_generator->moduleName()) {
- l_linktag = " :mod:`";
- } else {
- l_linktag = " :ref:`";
- }
-
- } else if (token == QXmlStreamReader::Characters) {
- QString linktext = reader.text().toString();
- linktext.replace("::", ".");
- QString item = l_linkref.split(".").last();
- if (l_linkref == linktext
- || (l_linkref + "()") == linktext
- || item == linktext
- || (item + "()") == linktext)
- l_linktext.clear();
- else
- l_linktext = linktext + QLatin1String("<");
- } else if (token == QXmlStreamReader::EndElement) {
- if (!l_linktext.isEmpty())
- l_linktagending.prepend('>');
- m_output << l_linktag << l_linktext << escape(l_linkref) << l_linktagending;
- }
-}
-
-void QtXmlToSphinx::handleImageTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- QString href = reader.attributes().value("href").toString();
- QDir dir(m_generator->outputDirectory() + '/' + m_generator->packageName().replace(".", "/"));
- QString imgPath = dir.relativeFilePath(m_generator->libSourceDir() + "/doc/src/") + '/' + href;
-
- if (reader.name() == "image")
- m_output << INDENT << ".. image:: " << imgPath << endl << endl;
- else
- m_output << ".. image:: " << imgPath << ' ';
- }
-}
-
-void QtXmlToSphinx::handleRawTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- QString format = reader.attributes().value("format").toString();
- m_output << INDENT << ".. raw:: " << format.toLower() << endl << endl;
- } else if (token == QXmlStreamReader::Characters) {
- QStringList lst(reader.text().toString().split("\n"));
- foreach(QString row, lst)
- m_output << INDENT << INDENT << row << endl;
- } else if (token == QXmlStreamReader::EndElement) {
- m_output << endl << endl;
- }
-}
-
-void QtXmlToSphinx::handleCodeTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- QString format = reader.attributes().value("format").toString();
- m_output << INDENT << "::" << endl << endl;
- INDENT.indent++;
- } else if (token == QXmlStreamReader::Characters) {
- QStringList lst(reader.text().toString().split("\n"));
- foreach(QString row, lst)
- m_output << INDENT << INDENT << row << endl;
- } else if (token == QXmlStreamReader::EndElement) {
- m_output << endl << endl;
- INDENT.indent--;
- }
-}
-
-void QtXmlToSphinx::handleUnknownTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement)
- ReportHandler::warning("Unknow QtDoc tag: \"" + reader.name().toString() + "\".");
-}
-
-void QtXmlToSphinx::handleSuperScriptTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- m_output << " :sup:`";
- pushOutputBuffer();
- } else if (token == QXmlStreamReader::Characters) {
- m_output << reader.text().toString();
- } else if (token == QXmlStreamReader::EndElement) {
- m_output << popOutputBuffer();
- m_output << '`';
- }
-}
-
-void QtXmlToSphinx::handleIgnoredTag(QXmlStreamReader&)
-{
-}
-
-void QtXmlToSphinx::handleUselessTag(QXmlStreamReader&)
-{
- // Tag "description" just marks the init of "Detailed description" title.
- // Tag "definition" just marks enums. We have a different way to process them.
-}
-
-void QtXmlToSphinx::handleAnchorTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement) {
- QString anchor;
- if (reader.attributes().hasAttribute("id"))
- anchor = reader.attributes().value("id").toString();
- else if (reader.attributes().hasAttribute("name"))
- anchor = reader.attributes().value("name").toString();
- if (!anchor.isEmpty() && m_opened_anchor != anchor) {
- m_opened_anchor = anchor;
- m_output << INDENT << ".. _" << m_context << "_" << anchor.toLower() << ":" << endl << endl;
- }
- } else if (token == QXmlStreamReader::EndElement) {
- m_opened_anchor = "";
- }
-}
-
-void QtXmlToSphinx::handleQuoteFileTag(QXmlStreamReader& reader)
-{
- QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::Characters) {
- QString location = reader.text().toString();
- QString identifier = "";
- location.prepend(m_generator->libSourceDir() + '/');
- QString code = readFromLocation(location, identifier);
-
- m_output << INDENT << "::\n\n";
- Indentation indentation(INDENT);
- if (code.isEmpty()) {
- m_output << INDENT << "<Code snippet \"" << location << "\" not found>" << endl;
- } else {
- foreach (QString line, code.split("\n")) {
- if (!QString(line).trimmed().isEmpty())
- m_output << INDENT << line;
-
- m_output << endl;
- }
- }
- m_output << endl;
- }
-}
-
-void QtXmlToSphinx::Table::normalize()
-{
- if (m_normalized || isEmpty())
- return;
-
- int row;
- int col;
- QtXmlToSphinx::Table& self = *this;
-
- //QDoc3 generates tables with wrong number of columns. We have to
- //check and if necessary, merge the last columns.
- int maxCols = self.at(0).count();
- // add col spans
- for (row = 0; row < count(); ++row) {
- for (col = 0; col < at(row).count(); ++col) {
- QtXmlToSphinx::TableCell& cell = self[row][col];
- bool mergeCols = (col >= maxCols);
- if (cell.colSpan > 0) {
- QtXmlToSphinx::TableCell newCell;
- newCell.colSpan = -1;
- for (int i = 0, max = cell.colSpan-1; i < max; ++i) {
- self[row].insert(col+1, newCell);
- }
- cell.colSpan = 0;
- col++;
- } else if (mergeCols) {
- self[row][maxCols - 1].data += " " + cell.data;
- }
- }
- }
-
- // row spans
- const int numCols = first().count();
- for (col = 0; col < numCols; ++col) {
- for (row = 0; row < count(); ++row) {
- if (col < self[row].count()) {
- QtXmlToSphinx::TableCell& cell = self[row][col];
- if (cell.rowSpan > 0) {
- QtXmlToSphinx::TableCell newCell;
- newCell.rowSpan = -1;
- int max = std::min(cell.rowSpan - 1, count());
- cell.rowSpan = 0;
- for (int i = 0; i < max; ++i) {
- self[row+i+1].insert(col, newCell);
- }
- row++;
- }
- }
- }
- }
- m_normalized = true;
-}
-
-QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table)
-{
- if (table.isEmpty())
- return s;
-
- if (!table.isNormalized()) {
- ReportHandler::warning("Attempt to print an unnormalized table!");
- return s;
- }
-
- // calc width and height of each column and row
- QVector<int> colWidths(table.first().count());
- QVector<int> rowHeights(table.count());
- for (int i = 0, maxI = table.count(); i < maxI; ++i) {
- const QtXmlToSphinx::TableRow& row = table[i];
- for (int j = 0, maxJ = std::min(row.count(), colWidths.size()); j < maxJ; ++j) {
- QStringList rowLines = row[j].data.split('\n'); // cache this would be a good idea
- foreach (QString str, rowLines)
- colWidths[j] = std::max(colWidths[j], str.count());
- rowHeights[i] = std::max(rowHeights[i], row[j].data.count('\n') + 1);
- }
- }
-
- if (!*std::max_element(colWidths.begin(), colWidths.end()))
- return s; // empty table (table with empty cells)
-
- // create a horizontal line to be used later.
- QString horizontalLine("+");
- for (int i = 0, max = colWidths.count(); i < max; ++i) {
- horizontalLine += createRepeatedChar(colWidths[i], '-');
- horizontalLine += '+';
- }
-
- // write table rows
- for (int i = 0, maxI = table.count(); i < maxI; ++i) { // for each row
- const QtXmlToSphinx::TableRow& row = table[i];
-
- // print line
- s << INDENT << '+';
- for (int col = 0, max = colWidths.count(); col < max; ++col) {
- char c;
- if (col >= row.length() || row[col].rowSpan == -1)
- c = ' ';
- else if (i == 1 && table.hasHeader())
- c = '=';
- else
- c = '-';
- s << createRepeatedChar(colWidths[col], c) << '+';
- }
- s << endl;
-
-
- // Print the table cells
- for (int rowLine = 0; rowLine < rowHeights[i]; ++rowLine) { // for each line in a row
- for (int j = 0, maxJ = std::min(row.count(), colWidths.size()); j < maxJ; ++j) { // for each column
- const QtXmlToSphinx::TableCell& cell = row[j];
- QStringList rowLines = cell.data.split('\n'); // FIXME: Cache this!!!
- if (!j) // First column, so we need print the identation
- s << INDENT;
-
- if (!j || !cell.colSpan)
- s << '|';
- else
- s << ' ';
- s << qSetFieldWidth(colWidths[j]) << left;
- s << (rowLine < rowLines.count() ? rowLines[rowLine] : "");
- s << qSetFieldWidth(0);
- }
- s << '|' << endl;
- }
- }
- s << INDENT << horizontalLine << endl;
- s << endl;
- return s;
-}
-
-static QString getFuncName(const AbstractMetaFunction* cppFunc) {
- static bool hashInitialized = false;
- static QHash<QString, QString> operatorsHash;
- if (!hashInitialized) {
- operatorsHash.insert("operator+", "__add__");
- operatorsHash.insert("operator+=", "__iadd__");
- operatorsHash.insert("operator-", "__sub__");
- operatorsHash.insert("operator-=", "__isub__");
- operatorsHash.insert("operator*", "__mul__");
- operatorsHash.insert("operator*=", "__imul__");
- operatorsHash.insert("operator/", "__div__");
- operatorsHash.insert("operator/=", "__idiv__");
- operatorsHash.insert("operator%", "__mod__");
- operatorsHash.insert("operator%=", "__imod__");
- operatorsHash.insert("operator<<", "__lshift__");
- operatorsHash.insert("operator<<=", "__ilshift__");
- operatorsHash.insert("operator>>", "__rshift__");
- operatorsHash.insert("operator>>=", "__irshift__");
- operatorsHash.insert("operator&", "__and__");
- operatorsHash.insert("operator&=", "__iand__");
- operatorsHash.insert("operator|", "__or__");
- operatorsHash.insert("operator|=", "__ior__");
- operatorsHash.insert("operator^", "__xor__");
- operatorsHash.insert("operator^=", "__ixor__");
- operatorsHash.insert("operator==", "__eq__");
- operatorsHash.insert("operator!=", "__ne__");
- operatorsHash.insert("operator<", "__lt__");
- operatorsHash.insert("operator<=", "__le__");
- operatorsHash.insert("operator>", "__gt__");
- operatorsHash.insert("operator>=", "__ge__");
- hashInitialized = true;
- }
-
- QHash<QString, QString>::const_iterator it = operatorsHash.find(cppFunc->name());
- QString result = it != operatorsHash.end() ? it.value() : cppFunc->name();
- return result.replace("::", ".");
-}
-
-QtDocGenerator::QtDocGenerator() : m_docParser(0)
-{
-}
-
-QtDocGenerator::~QtDocGenerator()
-{
- delete m_docParser;
-}
-
-QString QtDocGenerator::fileNameForClass(const AbstractMetaClass* cppClass) const
-{
- return QString("%1.rst").arg(getClassTargetFullName(cppClass, false));
-}
-
-void QtDocGenerator::writeFormatedText(QTextStream& s, const Documentation& doc, const AbstractMetaClass* metaClass)
-{
- QString metaClassName;
-
- if (metaClass)
- metaClassName = getClassTargetFullName(metaClass);
-
- if (doc.format() == Documentation::Native) {
- QtXmlToSphinx x(this, doc.value(), metaClassName);
- s << x;
- } else {
- QStringList lines = doc.value().split("\n");
- QRegExp regex("\\S"); // non-space character
- int typesystemIndentation = std::numeric_limits<int>().max();
- // check how many spaces must be removed from the begining of each line
- foreach (QString line, lines) {
- int idx = line.indexOf(regex);
- if (idx >= 0)
- typesystemIndentation = qMin(typesystemIndentation, idx);
- }
- foreach (QString line, lines)
- s << INDENT << line.remove(0, typesystemIndentation) << endl;
- }
-
- s << endl;
-}
-
-static void writeInheritedByList(QTextStream& s, const AbstractMetaClass* metaClass, const AbstractMetaClassList& allClasses)
-{
- AbstractMetaClassList res;
- foreach (AbstractMetaClass* c, allClasses) {
- if (c != metaClass && c->inheritsFrom(metaClass))
- res << c;
- }
-
- if (res.isEmpty())
- return;
-
- s << "**Inherited by:** ";
- QStringList classes;
- foreach (AbstractMetaClass* c, res)
- classes << QString(":ref:`%1`").arg(getClassTargetFullName(c, false));
- s << classes.join(", ") << endl << endl;
-}
-
-void QtDocGenerator::generateClass(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- ReportHandler::debugSparse("Generating Documentation for " + metaClass->fullName());
-
- m_packages[metaClass->package()] << fileNameForClass(metaClass);
-
- m_docParser->setPackageName(metaClass->package());
- m_docParser->fillDocumentation(const_cast<AbstractMetaClass*>(metaClass));
-
- s << ".. module:: " << metaClass->package() << endl;
- QString className = getClassTargetFullName(metaClass, false);
- s << ".. _" << className << ":" << endl << endl;
-
- s << className << endl;
- s << createRepeatedChar(className.count(), '*') << endl << endl;
-
- s << ".. inheritance-diagram:: " << className << endl
- << " :parts: 2" << endl << endl; // TODO: This would be a parameter in the future...
-
-
- writeInheritedByList(s, metaClass, classes());
-
- if (metaClass->typeEntry() && (metaClass->typeEntry()->version() != 0))
- s << ".. note:: This class was introduced in Qt " << metaClass->typeEntry()->version() << endl;
-
- writeFunctionList(s, metaClass);
-
- //Function list
- AbstractMetaFunctionList functionList = metaClass->functions();
- qSort(functionList.begin(), functionList.end(), functionSort);
-
- s << "Detailed Description\n"
- "--------------------\n\n";
-
- writeInjectDocumentation(s, DocModification::Prepend, metaClass, 0);
- if (!writeInjectDocumentation(s, DocModification::Replace, metaClass, 0))
- writeFormatedText(s, metaClass->documentation(), metaClass);
-
- if (!metaClass->isNamespace())
- writeConstructors(s, metaClass);
- writeEnums(s, metaClass);
- if (!metaClass->isNamespace())
- writeFields(s, metaClass);
-
-
- foreach (AbstractMetaFunction* func, functionList) {
- if (shouldSkip(func))
- continue;
-
- if (func->isStatic())
- s << ".. staticmethod:: ";
- else
- s << ".. method:: ";
-
- writeFunction(s, true, metaClass, func);
- }
-
- writeInjectDocumentation(s, DocModification::Append, metaClass, 0);
-}
-
-void QtDocGenerator::writeFunctionList(QTextStream& s, const AbstractMetaClass* cppClass)
-{
- QStringList functionList;
- QStringList virtualList;
- QStringList signalList;
- QStringList slotList;
- QStringList staticFunctionList;
-
- foreach (AbstractMetaFunction* func, cppClass->functions()) {
- if (shouldSkip(func))
- continue;
-
- QString className;
- if (!func->isConstructor())
- className = getClassTargetFullName(cppClass) + '.';
- else if (func->implementingClass() && func->implementingClass()->enclosingClass())
- className = getClassTargetFullName(func->implementingClass()->enclosingClass()) + '.';
- QString funcName = getFuncName(func);
-
- QString str("def :meth:`");
-
- str += funcName;
- str += '<';
- if (!funcName.startsWith(className))
- str += className;
- str += funcName;
- str += ">` (";
- str += parseArgDocStyle(cppClass, func);
- str += ')';
-
- if (func->isStatic())
- staticFunctionList << str;
- else if (func->isVirtual())
- virtualList << str;
- else if (func->isSignal())
- signalList << str;
- else if (func->isSlot())
- slotList << str;
- else
- functionList << str;
- }
-
- if ((functionList.size() > 0) || (staticFunctionList.size() > 0)) {
- QtXmlToSphinx::Table functionTable;
- QtXmlToSphinx::TableRow row;
-
- s << "Synopsis" << endl
- << "--------" << endl << endl;
-
- writeFunctionBlock(s, "Functions", functionList);
- writeFunctionBlock(s, "Virtual functions", virtualList);
- writeFunctionBlock(s, "Slots", slotList);
- writeFunctionBlock(s, "Signals", signalList);
- writeFunctionBlock(s, "Static functions", staticFunctionList);
- }
-}
-
-void QtDocGenerator::writeFunctionBlock(QTextStream& s, const QString& title, QStringList& functions)
-{
- if (functions.size() > 0) {
- s << title << endl
- << QString('^').repeated(title.size()) << endl;
-
- qSort(functions);
-
- s << ".. container:: function_list" << endl << endl;
- Indentation indentation(INDENT);
- foreach (QString func, functions)
- s << '*' << INDENT << func << endl;
-
- s << endl << endl;
- }
-}
-
-void QtDocGenerator::writeEnums(QTextStream& s, const AbstractMetaClass* cppClass)
-{
- static const QString section_title(".. attribute:: ");
-
- foreach (AbstractMetaEnum* en, cppClass->enums()) {
- s << section_title << getClassTargetFullName(cppClass) << "." << en->name() << endl << endl;
- writeFormatedText(s, en->documentation(), cppClass);
-
- if (en->typeEntry() && (en->typeEntry()->version() != 0))
- s << ".. note:: This enum was introduced or modified in Qt " << en->typeEntry()->version() << endl;
- }
-
-}
-
-void QtDocGenerator::writeFields(QTextStream& s, const AbstractMetaClass* cppClass)
-{
- static const QString section_title(".. attribute:: ");
-
- foreach (AbstractMetaField* field, cppClass->fields()) {
- s << section_title << getClassTargetFullName(cppClass) << "." << field->name() << endl << endl;
- //TODO: request for member ‘documentation’ is ambiguous
- writeFormatedText(s, field->AbstractMetaAttributes::documentation(), cppClass);
- }
-}
-
-void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass* cppClass)
-{
- static const QString sectionTitle = ".. class:: ";
- static const QString sectionTitleSpace = QString(sectionTitle.size(), ' ');
-
- AbstractMetaFunctionList lst = cppClass->queryFunctions(AbstractMetaClass::Constructors | AbstractMetaClass::Visible);
-
- bool first = true;
- QHash<QString, AbstractMetaArgument*> arg_map;
-
- foreach(AbstractMetaFunction* func, lst) {
- if (func->isModifiedRemoved())
- continue;
-
- if (first) {
- first = false;
- s << sectionTitle;
- } else {
- s << sectionTitleSpace;
- }
- writeFunction(s, false, cppClass, func);
- foreach(AbstractMetaArgument* arg, func->arguments())
- {
- if (!arg_map.contains(arg->name())) {
- arg_map.insert(arg->name(), arg);
- }
- }
- }
-
- s << endl;
-
- foreach (AbstractMetaArgument* arg, arg_map.values()) {
- Indentation indentation(INDENT);
- writeParamerteType(s, cppClass, arg);
- }
-
- s << endl;
-
- foreach (AbstractMetaFunction* func, lst) {
- writeFormatedText(s, func->documentation(), cppClass);
- }
-}
-
-QString QtDocGenerator::parseArgDocStyle(const AbstractMetaClass* cppClass, const AbstractMetaFunction* func)
-{
- QString ret;
- int optArgs = 0;
-
- foreach (AbstractMetaArgument* arg, func->arguments()) {
-
- if (func->argumentRemoved(arg->argumentIndex() + 1))
- continue;
-
- bool thisIsoptional = !arg->defaultValueExpression().isEmpty();
- if (optArgs || thisIsoptional) {
- ret += '[';
- optArgs++;
- }
-
- if (arg->argumentIndex() > 0)
- ret += ", ";
-
- ret += arg->name();
-
- if (thisIsoptional) {
- QString defValue = arg->defaultValueExpression();
- if (defValue == "QString()") {
- defValue = "\"\"";
- } else if (defValue == "QStringList()" || defValue.startsWith("QVector") || defValue.startsWith("QList")) {
- defValue = "list()";
- } else if (defValue == "QVariant()") {
- defValue = "None";
- } else {
- defValue.replace("::", ".");
- if (defValue == "0" && (arg->type()->isQObject() || arg->type()->isObject()))
- defValue = "None";
- }
- ret += "=" + defValue;
- }
- }
-
- ret += QString(']').repeated(optArgs);
- return ret;
-}
-
-void QtDocGenerator::writeDocSnips(QTextStream &s,
- const CodeSnipList &codeSnips,
- CodeSnip::Position position,
- TypeSystem::Language language)
-{
- Indentation indentation(INDENT);
- QStringList invalidStrings;
- const static QString startMarkup("[sphinx-begin]");
- const static QString endMarkup("[sphinx-end]");
-
- invalidStrings << "*" << "//" << "/*" << "*/";
-
- foreach (CodeSnip snip, codeSnips) {
- if ((snip.position != position) ||
- !(snip.language & language))
- continue;
-
- QString code = snip.code();
- while (code.contains(startMarkup) && code.contains(endMarkup)) {
- int startBlock = code.indexOf(startMarkup) + startMarkup.size();
- int endBlock = code.indexOf(endMarkup);
-
- if ((startBlock == -1) || (endBlock == -1))
- break;
-
- QString codeBlock = code.mid(startBlock, endBlock - startBlock);
- QStringList rows = codeBlock.split("\n");
- int currenRow = 0;
- int offset = 0;
-
- foreach(QString row, rows) {
- foreach(QString invalidString, invalidStrings) {
- row = row.remove(invalidString);
- }
-
- if (row.trimmed().size() == 0) {
- if (currenRow == 0)
- continue;
- else
- s << endl;
- }
-
- if (currenRow == 0) {
- //find offset
- for (int i=0, i_max = row.size(); i < i_max; i++) {
- if (row[i] == ' ')
- offset++;
- else if (row[i] == '\n')
- offset = 0;
- else
- break;
- }
- }
- row = row.mid(offset);
- s << row << endl;
- currenRow++;
- }
-
- code = code.mid(endBlock+endMarkup.size());
- }
- }
-}
-
-bool QtDocGenerator::writeInjectDocumentation(QTextStream& s,
- DocModification::Mode mode,
- const AbstractMetaClass* cppClass,
- const AbstractMetaFunction* func)
-{
- Indentation indentation(INDENT);
- bool didSomething = false;
-
- foreach (DocModification mod, cppClass->typeEntry()->docModifications()) {
- if (mod.mode() == mode) {
- bool modOk = func ? mod.signature() == func->minimalSignature() : mod.signature().isEmpty();
-
- if (modOk) {
- Documentation doc;
- Documentation::Format fmt;
-
- if (mod.format == TypeSystem::NativeCode)
- fmt = Documentation::Native;
- else if (mod.format == TypeSystem::TargetLangCode)
- fmt = Documentation::Target;
- else
- continue;
-
- doc.setValue(mod.code() , fmt);
- writeFormatedText(s, doc, cppClass);
- didSomething = true;
- }
- }
- }
-
- s << endl;
-
- // TODO: Deprecate the use of doc string on glue code.
- // This is pre "add-function" and "inject-documentation" tags.
- if (func) {
- writeDocSnips(s, func->injectedCodeSnips(),
- (mode == DocModification::Prepend ? CodeSnip::Beginning : CodeSnip::End),
- TypeSystem::TargetLangCode);
- } else {
- writeDocSnips(s, cppClass->typeEntry()->codeSnips(),
- (mode == DocModification::Prepend ? CodeSnip::Beginning : CodeSnip::End),
- TypeSystem::TargetLangCode);
- }
- return didSomething;
-}
-
-void QtDocGenerator::writeFunctionSignature(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func)
-{
- QString className;
- if (!func->isConstructor())
- className = getClassTargetFullName(cppClass) + '.';
- else if (func->implementingClass() && func->implementingClass()->enclosingClass())
- className = getClassTargetFullName(func->implementingClass()->enclosingClass()) + '.';
-
- QString funcName = getFuncName(func);
- if (!funcName.startsWith(className))
- funcName = className + funcName;
-
- s << funcName << "(" << parseArgDocStyle(cppClass, func) << ")";
-}
-
-QString QtDocGenerator::translateToPythonType(const AbstractMetaType* type, const AbstractMetaClass* cppClass)
-{
- QString strType;
- if (type->name() == "QString") {
- strType = "unicode";
- } else if (type->name() == "QVariant") {
- strType = "object";
- } else if (type->name() == "QStringList") {
- strType = "list of strings";
- } else if (type->isConstant() && type->name() == "char" && type->indirections() == 1) {
- strType = "str";
- } else if (type->name().startsWith("unsigned short")) {
- strType = "int";
- } else if (type->name().startsWith("unsigned ")) { // uint and ulong
- strType = "long";
- } else if (type->isContainer()) {
- QString strType = translateType(type, cppClass, Options(ExcludeConst) | ExcludeReference);
- strType.remove("*");
- strType.remove(">");
- strType.remove("<");
- strType.replace("::", ".");
- if (strType.contains("QList") || strType.contains("QVector")) {
- strType.replace("QList", "list of ");
- strType.replace("QVector", "list of ");
- } else if (strType.contains("QHash") || strType.contains("QMap")) {
- strType.remove("QHash");
- strType.remove("QMap");
- QStringList types = strType.split(",");
- strType = QString("Dictionary with keys of type %1 and values of type %2.")
- .arg(types[0]).arg(types[1]);
- }
- } else {
- QString refTag;
- if (type->isEnum())
- refTag = "attr";
- else
- refTag = "class";
- strType = ':' + refTag + ":`" + type->fullName() + '`';
- }
- return strType;
-}
-
-void QtDocGenerator::writeParamerteType(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaArgument* arg)
-{
- s << INDENT << ":param " << arg->name() << ": "
- << translateToPythonType(arg->type(), cppClass) << endl;
-}
-
-void QtDocGenerator::writeFunctionParametersType(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func)
-{
- Indentation indentation(INDENT);
-
- s << endl;
- foreach (AbstractMetaArgument* arg, func->arguments()) {
-
- if (func->argumentRemoved(arg->argumentIndex() + 1))
- continue;
-
- writeParamerteType(s, cppClass, arg);
- }
-
- if (!func->isConstructor() && func->type()) {
-
- QString retType;
- // check if the return type was modified
- foreach (FunctionModification mod, func->modifications()) {
- foreach (ArgumentModification argMod, mod.argument_mods) {
- if (argMod.index == 0) {
- retType = argMod.modified_type;
- break;
- }
- }
- }
-
- if (retType.isEmpty())
- retType = translateToPythonType(func->type(), cppClass);
- s << INDENT << ":rtype: " << retType << endl;
- }
- s << endl;
-}
-
-void QtDocGenerator::writeFunction(QTextStream& s, bool writeDoc, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func)
-{
- writeFunctionSignature(s, cppClass, func);
- s << endl;
-
- if (func->typeEntry() && (func->typeEntry()->version() != 0))
- s << ".. note:: This method was introduced in Qt " << func->typeEntry()->version() << endl;
-
- if (writeDoc) {
- s << endl;
- writeFunctionParametersType(s, cppClass, func);
- s << endl;
- writeInjectDocumentation(s, DocModification::Prepend, cppClass, func);
- if (!writeInjectDocumentation(s, DocModification::Replace, cppClass, func))
- writeFormatedText(s, func->documentation(), cppClass);
- writeInjectDocumentation(s, DocModification::Append, cppClass, func);
- }
-}
-
-static void writeFancyToc(QTextStream& s, const QStringList& items, int cols = 4)
-{
- typedef QMap<QChar, QStringList> TocMap;
- TocMap tocMap;
- QChar Q('Q');
- QChar idx;
- foreach (QString item, items) {
- if (item.isEmpty())
- continue;
- if (item.startsWith(Q) && item.length() > 1)
- idx = item[1];
- item.chop(4); // Remove the .rst extension
- tocMap[idx] << item;
- }
- QtXmlToSphinx::Table table;
- QtXmlToSphinx::TableRow row;
-
- int itemsPerCol = (items.size() + tocMap.size()*2) / cols;
- QString currentColData;
- int i = 0;
- QTextStream ss(&currentColData);
- QMutableMapIterator<QChar, QStringList> it(tocMap);
- while (it.hasNext()) {
- it.next();
- qSort(it.value());
-
- if (i)
- ss << endl;
-
- ss << "**" << it.key() << "**" << endl << endl;
- i += 2; // a letter title is equivalent to two entries in space
- foreach (QString item, it.value()) {
- ss << "* :doc:`" << item << "`" << endl;
- ++i;
-
- // end of column detected!
- if (i > itemsPerCol) {
- ss.flush();
- QtXmlToSphinx::TableCell cell(currentColData);
- row << cell;
- currentColData.clear();
- i = 0;
- }
- }
- }
- if (i) {
- ss.flush();
- QtXmlToSphinx::TableCell cell(currentColData);
- row << cell;
- currentColData.clear();
- i = 0;
- }
- table << row;
- table.normalize();
- s << ".. container:: pysidetoc" << endl << endl;
- s << table;
-}
-
-void QtDocGenerator::finishGeneration()
-{
- if (classes().isEmpty())
- return;
-
- QMap<QString, QStringList>::iterator it = m_packages.begin();
- for (; it != m_packages.end(); ++it) {
- QString outputDir = outputDirectory() + '/' + QString(it.key()).replace(".", "/");
- FileOut output(outputDir + "/index.rst");
- QTextStream& s = output.stream;
-
- s << ".. module:: " << it.key() << endl << endl;
-
- QString title = it.key();
- s << title << endl;
- s << createRepeatedChar(title.length(), '*') << endl << endl;
-
- /* Avoid showing "Detailed Description for *every* class in toc tree */
- Indentation indentation(INDENT);
-
- // Search for extra-sections
- if (!m_extraSectionDir.isEmpty()) {
- QDir extraSectionDir(m_extraSectionDir);
- QStringList fileList = extraSectionDir.entryList(QStringList() << (it.key() + "?*.rst"), QDir::Files);
- QStringList::iterator it2 = fileList.begin();
- for (; it2 != fileList.end(); ++it2) {
- QString origFileName(*it2);
- it2->remove(0, it.key().count() + 1);
- QString newFilePath = outputDir + '/' + *it2;
- if (QFile::exists(newFilePath))
- QFile::remove(newFilePath);
- if (!QFile::copy(m_extraSectionDir + '/' + origFileName, newFilePath)) {
- ReportHandler::warning("Error copying extra doc " + (m_extraSectionDir + '/' + origFileName)
- + " to " + newFilePath);
- }
- }
- it.value().append(fileList);
- }
-
- writeFancyToc(s, it.value());
-
- s << INDENT << ".. container:: hide" << endl << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << ".. toctree::" << endl;
- Indentation deeperIndentation(INDENT);
- s << INDENT << ":maxdepth: 1" << endl << endl;
- foreach (QString className, it.value())
- s << INDENT << className << endl;
- s << endl << endl;
- }
-
- s << "Detailed Description" << endl;
- s << "--------------------" << endl << endl;
-
- // module doc is always wrong and C++istic, so go straight to the extra directory!
- QFile moduleDoc(m_extraSectionDir + '/' + it.key() + ".rst");
- if (moduleDoc.open(QIODevice::ReadOnly | QIODevice::Text)) {
- s << moduleDoc.readAll();
- moduleDoc.close();
- } else {
- // try the normal way
- Documentation moduleDoc = m_docParser->retrieveModuleDocumentation(it.key());
- if (moduleDoc.format() == Documentation::Native) {
- QtXmlToSphinx x(this, moduleDoc.value(), QString(it.key()).remove(0, it.key().lastIndexOf('.') + 1));
- s << x;
- } else {
- s << moduleDoc.value();
- }
- }
- }
-}
-
-bool QtDocGenerator::doSetup(const QMap<QString, QString>& args)
-{
- m_libSourceDir = args.value("library-source-dir");
- m_docDataDir = args.value("documentation-data-dir");
-#ifdef __WIN32__
-# define PATH_SEP ";"
-#else
-# define PATH_SEP ":"
-#endif
- m_codeSnippetDirs = args.value("documentation-code-snippets-dir", m_libSourceDir).split(PATH_SEP);
- m_extraSectionDir = args.value("documentation-extra-sections-dir");
-
- m_docParser = args.value("doc-parser") == "doxygen" ? reinterpret_cast<DocParser*>(new DoxygenParser) : reinterpret_cast<DocParser*>(new QtDocParser);
- ReportHandler::warning("doc-parser: " + args.value("doc-parser"));
-
- if (m_libSourceDir.isEmpty() || m_docDataDir.isEmpty()) {
- ReportHandler::warning("Documentation data dir and/or Qt source dir not informed, "
- "documentation will not be extracted from Qt sources.");
- return false;
- } else {
- m_docParser->setDocumentationDataDirectory(m_docDataDir);
- m_docParser->setLibrarySourceDirectory(m_libSourceDir);
- }
- return true;
-}
-
-
-QMap<QString, QString> QtDocGenerator::options() const
-{
- QMap<QString, QString> options;
- options.insert("doc-parser", "The documentation parser used to interpret the documentaion input files (qdoc3|doxygen)");
- options.insert("library-source-dir", "Directory where library source code is located");
- options.insert("documentation-data-dir", "Directory with XML files generated by documentation tool (qdoc3 or Doxygen)");
- options.insert("documentation-code-snippets-dir", "Directory used to search code snippets used by the documentation");
- options.insert("documentation-extra-sections-dir", "Directory used to search for extra documentation sections");
- return options;
-}
-
diff --git a/generators/qtdoc/qtdocgenerator.h b/generators/qtdoc/qtdocgenerator.h
deleted file mode 100644
index 247b48363..000000000
--- a/generators/qtdoc/qtdocgenerator.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * This file is part of the PySide 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
- *
- */
-#ifndef DOCGENERATOR_H
-#define DOCGENERATOR_H
-
-#include <QtCore/QStack>
-#include <QtCore/QHash>
-#include <QtCore/QTextStream>
-#include <QXmlStreamReader>
-#include <abstractmetalang.h>
-#include "generator.h"
-#include "docparser.h"
-
-class QtDocParser;
-class AbstractMetaFunction;
-class AbstractMetaClass;
-class QXmlStreamReader;
-class QtDocGenerator;
-
-class QtXmlToSphinx
-{
-public:
- struct TableCell
- {
- short rowSpan;
- short colSpan;
- QString data;
-
- TableCell(const QString& text = QString()) : rowSpan(0), colSpan(0), data(text) {}
- TableCell(const char* text) : rowSpan(0), colSpan(0), data(text) {}
- };
-
- typedef QList<TableCell> TableRow;
- class Table : public QList<TableRow>
- {
- public:
- Table() : m_hasHeader(false), m_normalized(false)
- {
- }
-
- void enableHeader(bool enable)
- {
- m_hasHeader = enable;
- }
-
- bool hasHeader() const
- {
- return m_hasHeader;
- }
-
- void normalize();
-
- bool isNormalized() const
- {
- return m_normalized;
- }
-
- void clear() {
- m_normalized = false;
- QList<TableRow>::clear();
- }
-
- private:
- bool m_hasHeader;
- bool m_normalized;
- };
-
- QtXmlToSphinx(QtDocGenerator* generator, const QString& doc, const QString& context = QString());
-
- QString result() const
- {
- return m_result;
- }
-
-private:
- QString resolveContextForMethod(const QString& methodName);
- QString expandFunction(const QString& function);
- QString transform(const QString& doc);
-
- void handleHeadingTag(QXmlStreamReader& reader);
- void handleParaTag(QXmlStreamReader& reader);
- void handleItalicTag(QXmlStreamReader& reader);
- void handleBoldTag(QXmlStreamReader& reader);
- void handleArgumentTag(QXmlStreamReader& reader);
- void handleSeeAlsoTag(QXmlStreamReader& reader);
- void handleSnippetTag(QXmlStreamReader& reader);
- void handleDotsTag(QXmlStreamReader& reader);
- void handleLinkTag(QXmlStreamReader& reader);
- void handleImageTag(QXmlStreamReader& reader);
- void handleListTag(QXmlStreamReader& reader);
- void handleTermTag(QXmlStreamReader& reader);
- void handleSuperScriptTag(QXmlStreamReader& reader);
- void handleQuoteFileTag(QXmlStreamReader& reader);
-
- // table tagsvoid QtXmlToSphinx::handleValueTag(QXmlStreamReader& reader)
-
- void handleTableTag(QXmlStreamReader& reader);
- void handleRowTag(QXmlStreamReader& reader);
- void handleItemTag(QXmlStreamReader& reader);
- void handleRawTag(QXmlStreamReader& reader);
- void handleCodeTag(QXmlStreamReader& reader);
-
- void handleIgnoredTag(QXmlStreamReader& reader);
- void handleUnknownTag(QXmlStreamReader& reader);
- void handleUselessTag(QXmlStreamReader& reader);
- void handleAnchorTag(QXmlStreamReader& reader);
-
- typedef void (QtXmlToSphinx::*TagHandler)(QXmlStreamReader&);
- QHash<QString, TagHandler> m_handlerMap;
- QStack<TagHandler> m_handlers;
- QTextStream m_output;
- QString m_result;
-
- QStack<QString*> m_buffers;
-
-
- Table m_currentTable;
- bool m_tableHasHeader;
- QString m_context;
- QtDocGenerator* m_generator;
- bool m_insideBold;
- bool m_insideItalic;
- QString m_lastTagName;
- QString m_opened_anchor;
-
- QString readFromLocations(const QStringList& locations, const QString& path, const QString& identifier);
- QString readFromLocation(const QString& location, const QString& identifier, bool* ok = 0);
- void pushOutputBuffer();
- QString popOutputBuffer();
- void writeTable(Table& table);
-};
-
-inline QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx& xmlToSphinx)
-{
- return s << xmlToSphinx.result();
-}
-
-QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table);
-
-/**
-* The DocGenerator generates documentation from library being binded.
-*/
-class QtDocGenerator : public Generator
-{
-public:
- QtDocGenerator();
- ~QtDocGenerator();
-
- QString libSourceDir() const
- {
- return m_libSourceDir;
- }
-
- bool doSetup(const QMap<QString, QString>& args);
-
- const char* name() const
- {
- return "QtDocGenerator";
- }
-
- QMap<QString, QString> options() const;
-
- QStringList codeSnippetDirs() const
- {
- return m_codeSnippetDirs;
- }
-
-protected:
- QString fileNameForClass(const AbstractMetaClass* cppClass) const;
- void generateClass(QTextStream& s, const AbstractMetaClass* metaClass);
- void finishGeneration();
-
- void writeFunctionArguments(QTextStream&, const AbstractMetaFunction*, Options) const {}
- void writeArgumentNames(QTextStream&, const AbstractMetaFunction*, Options) const {}
-
-private:
- void writeEnums(QTextStream& s, const AbstractMetaClass* cppClass);
-
- void writeFields(QTextStream &s, const AbstractMetaClass *cppClass);
- void writeArguments(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction *func);
- void writeFunctionSignature(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func);
- void writeFunction(QTextStream& s, bool writeDoc, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func);
- void writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction* func);
- void writeFunctionList(QTextStream& s, const AbstractMetaClass* cppClass);
- void writeFunctionBlock(QTextStream& s, const QString& title, QStringList& functions);
- void writeParamerteType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaArgument *arg);
-
- void writeConstructors(QTextStream &s, const AbstractMetaClass *cppClass);
- void writeFormatedText(QTextStream& s, const Documentation& doc, const AbstractMetaClass* metaclass = 0);
- bool writeInjectDocumentation(QTextStream& s, DocModification::Mode mode, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func);
- void writeDocSnips(QTextStream &s, const CodeSnipList &codeSnips, CodeSnip::Position position, TypeSystem::Language language);
-
-
- QString parseArgDocStyle(const AbstractMetaClass *cppClass, const AbstractMetaFunction *func);
- QString translateToPythonType(const AbstractMetaType *type, const AbstractMetaClass *cppClass);
-
- QString m_docDataDir;
- QString m_libSourceDir;
- QStringList m_codeSnippetDirs;
- QString m_extraSectionDir;
- QStringList m_functionList;
- QMap<QString, QStringList> m_packages;
- DocParser* m_docParser;
-};
-
-#endif // DOCGENERATOR_H
diff --git a/generators/shiboken/CMakeLists.txt b/generators/shiboken/CMakeLists.txt
deleted file mode 100644
index 57aac33ad..000000000
--- a/generators/shiboken/CMakeLists.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-project(shibokengenerator)
-
-set(shiboken_SRC
-../generator.cpp
-cppgenerator.cpp
-headergenerator.cpp
-overloaddata.cpp
-shibokengenerator.cpp
-shibokennormalize.cpp
-main.cpp
-)
-
-include_directories(${generators_SOURCE_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_CURRENT_BINARY_DIR}
- ${APIEXTRACTOR_INCLUDE_DIR}
- ${QT_INCLUDE_DIR}
- ${QT_QTCORE_INCLUDE_DIR}
- ${QT_QTXML_INCLUDE_DIR})
-
-add_executable(shiboken ${shiboken_SRC})
-set_target_properties(shiboken PROPERTIES OUTPUT_NAME shiboken${shiboken_SUFFIX})
-target_link_libraries(shiboken
- ${APIEXTRACTOR_LIBRARY}
- ${QT_QTCORE_LIBRARY}
- ${QT_QTXML_LIBRARY})
-
-configure_file(shibokenconfig.h.in "${CMAKE_CURRENT_BINARY_DIR}/shibokenconfig.h" @ONLY)
-
-install(TARGETS shiboken DESTINATION bin)
diff --git a/generators/shiboken/cppgenerator.cpp b/generators/shiboken/cppgenerator.cpp
deleted file mode 100644
index fa19f7a3d..000000000
--- a/generators/shiboken/cppgenerator.cpp
+++ /dev/null
@@ -1,5125 +0,0 @@
-/*
- * This file is part of the Shiboken Python Bindings Generator project.
- *
- * Copyright (C) 2009-2012 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 <memory>
-
-#include "cppgenerator.h"
-#include "shibokennormalize_p.h"
-#include <reporthandler.h>
-#include <typedatabase.h>
-
-#include <QtCore/QDir>
-#include <QtCore/QTextStream>
-#include <QtCore/QDebug>
-#include <QMetaType>
-
-QHash<QString, QString> CppGenerator::m_nbFuncs = QHash<QString, QString>();
-QHash<QString, QString> CppGenerator::m_sqFuncs = QHash<QString, QString>();
-QHash<QString, QString> CppGenerator::m_mpFuncs = QHash<QString, QString>();
-QString CppGenerator::m_currentErrorCode("0");
-
-// utility functions
-inline AbstractMetaType* getTypeWithoutContainer(AbstractMetaType* arg)
-{
- if (arg && arg->typeEntry()->isContainer()) {
- AbstractMetaTypeList lst = arg->instantiations();
- // only support containers with 1 type
- if (lst.size() == 1)
- return lst[0];
- }
- return arg;
-}
-
-CppGenerator::CppGenerator()
-{
- // Number protocol structure members names
- m_nbFuncs["__add__"] = "nb_add";
- m_nbFuncs["__sub__"] = "nb_subtract";
- m_nbFuncs["__mul__"] = "nb_multiply";
- m_nbFuncs["__div__"] = "nb_divide";
- m_nbFuncs["__mod__"] = "nb_remainder";
- m_nbFuncs["__neg__"] = "nb_negative";
- m_nbFuncs["__pos__"] = "nb_positive";
- m_nbFuncs["__invert__"] = "nb_invert";
- m_nbFuncs["__lshift__"] = "nb_lshift";
- m_nbFuncs["__rshift__"] = "nb_rshift";
- m_nbFuncs["__and__"] = "nb_and";
- m_nbFuncs["__xor__"] = "nb_xor";
- m_nbFuncs["__or__"] = "nb_or";
- m_nbFuncs["__iadd__"] = "nb_inplace_add";
- m_nbFuncs["__isub__"] = "nb_inplace_subtract";
- m_nbFuncs["__imul__"] = "nb_multiply";
- m_nbFuncs["__idiv__"] = "nb_divide";
- m_nbFuncs["__imod__"] = "nb_remainder";
- m_nbFuncs["__ilshift__"] = "nb_inplace_lshift";
- m_nbFuncs["__irshift__"] = "nb_inplace_rshift";
- m_nbFuncs["__iand__"] = "nb_inplace_and";
- m_nbFuncs["__ixor__"] = "nb_inplace_xor";
- m_nbFuncs["__ior__"] = "nb_inplace_or";
- m_nbFuncs["bool"] = "nb_nonzero";
-
- // sequence protocol functions
- typedef QPair<QString, QString> StrPair;
- m_sequenceProtocol.insert("__len__", StrPair("PyObject* " PYTHON_SELF_VAR, "Py_ssize_t"));
- m_sequenceProtocol.insert("__getitem__", StrPair("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i", "PyObject*"));
- m_sequenceProtocol.insert("__setitem__", StrPair("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i, PyObject* _value", "int"));
- m_sequenceProtocol.insert("__getslice__", StrPair("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i1, Py_ssize_t _i2", "PyObject*"));
- m_sequenceProtocol.insert("__setslice__", StrPair("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i1, Py_ssize_t _i2, PyObject* _value", "int"));
- m_sequenceProtocol.insert("__contains__", StrPair("PyObject* " PYTHON_SELF_VAR ", PyObject* _value", "int"));
- m_sequenceProtocol.insert("__concat__", StrPair("PyObject* " PYTHON_SELF_VAR ", PyObject* _other", "PyObject*"));
-
- // Sequence protocol structure members names
- m_sqFuncs["__concat__"] = "sq_concat";
- m_sqFuncs["__contains__"] = "sq_contains";
- m_sqFuncs["__getitem__"] = "sq_item";
- m_sqFuncs["__getslice__"] = "sq_slice";
- m_sqFuncs["__len__"] = "sq_length";
- m_sqFuncs["__setitem__"] = "sq_ass_item";
- m_sqFuncs["__setslice__"] = "sq_ass_slice";
-
- // mapping protocol function
- m_mappingProtocol.insert("__mlen__", StrPair("PyObject* " PYTHON_SELF_VAR, "Py_ssize_t"));
- m_mappingProtocol.insert("__mgetitem__", StrPair("PyObject* " PYTHON_SELF_VAR ", PyObject* _key", "PyObject*"));
- m_mappingProtocol.insert("__msetitem__", StrPair("PyObject* " PYTHON_SELF_VAR ", PyObject* _key, PyObject* _value", "int"));
-
- // Sequence protocol structure members names
- m_mpFuncs["__mlen__"] = "mp_length";
- m_mpFuncs["__mgetitem__"] = "mp_subscript";
- m_mpFuncs["__msetitem__"] = "mp_ass_subscript";
-}
-
-QString CppGenerator::fileNameForClass(const AbstractMetaClass *metaClass) const
-{
- return metaClass->qualifiedCppName().toLower().replace("::", "_") + QLatin1String("_wrapper.cpp");
-}
-
-QList<AbstractMetaFunctionList> CppGenerator::filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass,
- uint query)
-{
- // ( func_name, num_args ) => func_list
- QMap<QPair<QString, int >, AbstractMetaFunctionList> results;
- foreach (AbstractMetaFunction* func, metaClass->operatorOverloads(query)) {
- if (func->isModifiedRemoved() || func->name() == "operator[]" || func->name() == "operator->")
- continue;
- int args;
- if (func->isComparisonOperator()) {
- args = -1;
- } else {
- args = func->arguments().size();
- }
- QPair<QString, int > op(func->name(), args);
- results[op].append(func);
- }
- return results.values();
-}
-
-bool CppGenerator::hasBoolCast(const AbstractMetaClass* metaClass) const
-{
- if (!useIsNullAsNbNonZero())
- return false;
- // TODO: This could be configurable someday
- const AbstractMetaFunction* func = metaClass->findFunction("isNull");
- if (!func || !func->type() || !func->type()->typeEntry()->isPrimitive() || !func->isPublic())
- return false;
- const PrimitiveTypeEntry* pte = static_cast<const PrimitiveTypeEntry*>(func->type()->typeEntry());
- while (pte->aliasedTypeEntry())
- pte = pte->aliasedTypeEntry();
- return func && func->isConstant() && pte->name() == "bool" && func->arguments().isEmpty();
-}
-
-/*!
- Function used to write the class generated binding code on the buffer
- \param s the output buffer
- \param metaClass the pointer to metaclass information
-*/
-void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaClass)
-{
- ReportHandler::debugSparse("Generating wrapper implementation for " + metaClass->fullName());
-
- // write license comment
- s << licenseComment() << endl;
-
- if (!avoidProtectedHack() && !metaClass->isNamespace() && !metaClass->hasPrivateDestructor()) {
- s << "//workaround to access protected functions" << endl;
- s << "#define protected public" << endl << endl;
- }
-
- // headers
- s << "// default includes" << endl;
- s << "#include <shiboken.h>" << endl;
- if (usePySideExtensions()) {
- s << "#include <pysidesignal.h>" << endl;
- s << "#include <pysideproperty.h>" << endl;
- s << "#include <pyside.h>" << endl;
- s << "#include <destroylistener.h>" << endl;
- }
-
- s << "#include <typeresolver.h>" << endl;
- s << "#include <typeinfo>" << endl;
- if (usePySideExtensions() && metaClass->isQObject()) {
- s << "#include <signalmanager.h>" << endl;
- s << "#include <pysidemetafunction.h>" << endl;
- }
-
- // The multiple inheritance initialization function
- // needs the 'set' class from C++ STL.
- if (hasMultipleInheritanceInAncestry(metaClass))
- s << "#include <set>" << endl;
-
- s << "#include \"" << getModuleHeaderFileName() << '"' << endl << endl;
-
- QString headerfile = fileNameForClass(metaClass);
- headerfile.replace(".cpp", ".h");
- s << "#include \"" << headerfile << '"' << endl;
- foreach (AbstractMetaClass* innerClass, metaClass->innerClasses()) {
- if (shouldGenerate(innerClass)) {
- QString headerfile = fileNameForClass(innerClass);
- headerfile.replace(".cpp", ".h");
- s << "#include \"" << headerfile << '"' << endl;
- }
- }
-
- AbstractMetaEnumList classEnums = metaClass->enums();
- foreach (AbstractMetaClass* innerClass, metaClass->innerClasses())
- lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass);
-
- //Extra includes
- s << endl << "// Extra includes" << endl;
- QList<Include> includes = metaClass->typeEntry()->extraIncludes();
- foreach (AbstractMetaEnum* cppEnum, classEnums)
- includes.append(cppEnum->typeEntry()->extraIncludes());
- qSort(includes.begin(), includes.end());
- foreach (Include inc, includes)
- s << inc.toString() << endl;
- s << endl;
-
- if (metaClass->typeEntry()->typeFlags() & ComplexTypeEntry::Deprecated)
- s << "#Deprecated" << endl;
-
- //Use class base namespace
- const AbstractMetaClass *context = metaClass->enclosingClass();
- while(context) {
- if (context->isNamespace() && !context->enclosingClass()) {
- s << "using namespace " << context->qualifiedCppName() << ";" << endl;
- break;
- }
- context = context->enclosingClass();
- }
-
- s << endl;
-
- // class inject-code native/beginning
- if (!metaClass->typeEntry()->codeSnips().isEmpty()) {
- writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::Beginning, TypeSystem::NativeCode, metaClass);
- s << endl;
- }
-
- // python conversion rules
- if (metaClass->typeEntry()->hasTargetConversionRule()) {
- s << "// Python Conversion" << endl;
- s << metaClass->typeEntry()->conversionRule() << endl;
- }
-
- if (shouldGenerateCppWrapper(metaClass)) {
- s << "// Native ---------------------------------------------------------" << endl;
- s << endl;
-
- if (avoidProtectedHack() && usePySideExtensions()) {
- s << "void " << wrapperName(metaClass) << "::pysideInitQtMetaTypes()\n{\n";
- Indentation indent(INDENT);
- writeInitQtMetaTypeFunctionBody(s, metaClass);
- s << "}\n\n";
- }
-
- foreach (const AbstractMetaFunction* func, filterFunctions(metaClass)) {
- if ((func->isPrivate() && !visibilityModifiedToPrivate(func))
- || (func->isModifiedRemoved() && !func->isAbstract()))
- continue;
- if (func->isConstructor() && !func->isCopyConstructor() && !func->isUserAdded())
- writeConstructorNative(s, func);
- else if ((!avoidProtectedHack() || !metaClass->hasPrivateDestructor())
- && (func->isVirtual() || func->isAbstract()))
- writeVirtualMethodNative(s, func);
- }
-
- if (!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) {
- if (usePySideExtensions() && metaClass->isQObject())
- writeMetaObjectMethod(s, metaClass);
- writeDestructorNative(s, metaClass);
- }
- }
-
- Indentation indentation(INDENT);
-
- QString methodsDefinitions;
- QTextStream md(&methodsDefinitions);
- QString singleMethodDefinitions;
- QTextStream smd(&singleMethodDefinitions);
-
- s << endl << "// Target ---------------------------------------------------------" << endl << endl;
- s << "extern \"C\" {" << endl;
- foreach (AbstractMetaFunctionList allOverloads, getFunctionGroups(metaClass).values()) {
- AbstractMetaFunctionList overloads;
- foreach (AbstractMetaFunction* func, allOverloads) {
- if (!func->isAssignmentOperator()
- && !func->isCastOperator()
- && !func->isModifiedRemoved()
- && (!func->isPrivate() || func->functionType() == AbstractMetaFunction::EmptyFunction)
- && func->ownerClass() == func->implementingClass()
- && (func->name() != "qt_metacall"))
- overloads.append(func);
- }
-
- if (overloads.isEmpty())
- continue;
-
- const AbstractMetaFunction* rfunc = overloads.first();
- if (m_sequenceProtocol.contains(rfunc->name()) || m_mappingProtocol.contains(rfunc->name()))
- continue;
-
- if (rfunc->isConstructor())
- writeConstructorWrapper(s, overloads);
- // call operators
- else if (rfunc->name() == "operator()")
- writeMethodWrapper(s, overloads);
- else if (!rfunc->isOperatorOverload()) {
- writeMethodWrapper(s, overloads);
- if (OverloadData::hasStaticAndInstanceFunctions(overloads)) {
- QString methDefName = cpythonMethodDefinitionName(rfunc);
- smd << "static PyMethodDef " << methDefName << " = {" << endl;
- smd << INDENT;
- writeMethodDefinitionEntry(smd, overloads);
- smd << endl << "};" << endl << endl;
- }
- writeMethodDefinition(md, overloads);
- }
- }
-
- QString className = cpythonTypeName(metaClass).replace(QRegExp("_Type$"), "");
-
- if (metaClass->typeEntry()->isValue())
- writeCopyFunction(s, metaClass);
-
- // Write single method definitions
- s << singleMethodDefinitions;
-
- // Write methods definition
- s << "static PyMethodDef " << className << "_methods[] = {" << endl;
- s << methodsDefinitions << endl;
- if (metaClass->typeEntry()->isValue())
- s << INDENT << "{\"__copy__\", (PyCFunction)" << className << "___copy__" << ", METH_NOARGS}," << endl;
- s << INDENT << "{0} // Sentinel" << endl;
- s << "};" << endl << endl;
-
- // Write tp_getattro function
- if (usePySideExtensions() && metaClass->qualifiedCppName() == "QObject") {
- writeGetattroFunction(s, metaClass);
- s << endl;
- writeSetattroFunction(s, metaClass);
- s << endl;
- } else if (classNeedsGetattroFunction(metaClass)) {
- writeGetattroFunction(s, metaClass);
- s << endl;
- }
-
- if (hasBoolCast(metaClass)) {
- ErrorCode errorCode(-1);
- s << "static int " << cpythonBaseName(metaClass) << "___nb_bool(PyObject* " PYTHON_SELF_VAR ")" << endl;
- s << '{' << endl;
- writeCppSelfDefinition(s, metaClass);
- s << INDENT << "int result;" << endl;
- s << INDENT << BEGIN_ALLOW_THREADS << endl;
- s << INDENT << "result = !" CPP_SELF_VAR "->isNull();" << endl;
- s << INDENT << END_ALLOW_THREADS << endl;
- s << INDENT << "return result;" << endl;
- s << '}' << endl << endl;
- }
-
- if (supportsNumberProtocol(metaClass)) {
- QList<AbstractMetaFunctionList> opOverloads = filterGroupedOperatorFunctions(
- metaClass,
- AbstractMetaClass::ArithmeticOp
- | AbstractMetaClass::LogicalOp
- | AbstractMetaClass::BitwiseOp);
-
- foreach (AbstractMetaFunctionList allOverloads, opOverloads) {
- AbstractMetaFunctionList overloads;
- foreach (AbstractMetaFunction* func, allOverloads) {
- if (!func->isModifiedRemoved()
- && !func->isPrivate()
- && (func->ownerClass() == func->implementingClass() || func->isAbstract()))
- overloads.append(func);
- }
-
- if (overloads.isEmpty())
- continue;
-
- writeMethodWrapper(s, overloads);
- }
- }
-
- if (supportsSequenceProtocol(metaClass)) {
- writeSequenceMethods(s, metaClass);
- }
-
- if (supportsMappingProtocol(metaClass)) {
- writeMappingMethods(s, metaClass);
- }
-
- if (metaClass->hasComparisonOperatorOverload()) {
- s << "// Rich comparison" << endl;
- writeRichCompareFunction(s, metaClass);
- }
-
- if (shouldGenerateGetSetList(metaClass)) {
- foreach (const AbstractMetaField* metaField, metaClass->fields()) {
- if (metaField->isStatic())
- continue;
- writeGetterFunction(s, metaField);
- if (!metaField->type()->isConstant())
- writeSetterFunction(s, metaField);
- s << endl;
- }
-
- s << "// Getters and Setters for " << metaClass->name() << endl;
- s << "static PyGetSetDef " << cpythonGettersSettersDefinitionName(metaClass) << "[] = {" << endl;
- foreach (const AbstractMetaField* metaField, metaClass->fields()) {
- if (metaField->isStatic())
- continue;
-
- bool hasSetter = !metaField->type()->isConstant();
- s << INDENT << "{const_cast<char*>(\"" << metaField->name() << "\"), ";
- s << cpythonGetterFunctionName(metaField);
- s << ", " << (hasSetter ? cpythonSetterFunctionName(metaField) : "0");
- s << "}," << endl;
- }
- s << INDENT << "{0} // Sentinel" << endl;
- s << "};" << endl << endl;
- }
-
- s << "} // extern \"C\"" << endl << endl;
-
- if (!metaClass->typeEntry()->hashFunction().isEmpty())
- writeHashFunction(s, metaClass);
-
- // Write tp_traverse and tp_clear functions.
- writeTpTraverseFunction(s, metaClass);
- writeTpClearFunction(s, metaClass);
-
- writeClassDefinition(s, metaClass);
- s << endl;
-
- if (metaClass->isPolymorphic() && metaClass->baseClass())
- writeTypeDiscoveryFunction(s, metaClass);
-
-
- foreach (AbstractMetaEnum* cppEnum, classEnums) {
- if (cppEnum->isAnonymous() || cppEnum->isPrivate())
- continue;
-
- bool hasFlags = cppEnum->typeEntry()->flags();
- if (hasFlags) {
- writeFlagsMethods(s, cppEnum);
- writeFlagsNumberMethodsDefinition(s, cppEnum);
- s << endl;
- }
- }
- s << endl;
-
- writeConverterFunctions(s, metaClass);
- writeClassRegister(s, metaClass);
-
- // class inject-code native/end
- if (!metaClass->typeEntry()->codeSnips().isEmpty()) {
- writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::End, TypeSystem::NativeCode, metaClass);
- s << endl;
- }
-}
-
-void CppGenerator::writeConstructorNative(QTextStream& s, const AbstractMetaFunction* func)
-{
- Indentation indentation(INDENT);
- s << functionSignature(func, wrapperName(func->ownerClass()) + "::", "",
- OriginalTypeDescription | SkipDefaultValues);
- s << " : ";
- writeFunctionCall(s, func);
- s << " {" << endl;
- const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last();
- writeCodeSnips(s, func->injectedCodeSnips(), CodeSnip::Beginning, TypeSystem::NativeCode, func, lastArg);
- s << INDENT << "// ... middle" << endl;
- writeCodeSnips(s, func->injectedCodeSnips(), CodeSnip::End, TypeSystem::NativeCode, func, lastArg);
- s << '}' << endl << endl;
-}
-
-void CppGenerator::writeDestructorNative(QTextStream &s, const AbstractMetaClass *metaClass)
-{
- Indentation indentation(INDENT);
- s << wrapperName(metaClass) << "::~" << wrapperName(metaClass) << "()" << endl << '{' << endl;
- // kill pyobject
- s << INDENT << "SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl;
- s << INDENT << "Shiboken::Object::destroy(wrapper, this);" << endl;
- s << '}' << endl;
-}
-
-static bool allArgumentsRemoved(const AbstractMetaFunction* func)
-{
- if (func->arguments().isEmpty())
- return false;
- foreach (const AbstractMetaArgument* arg, func->arguments()) {
- if (!func->argumentRemoved(arg->argumentIndex() + 1))
- return false;
- }
- return true;
-}
-
-QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunction* func)
-{
- if (!func->type())
- return "\"\"";
-
- if (!func->typeReplaced(0).isEmpty())
- return '"' + func->typeReplaced(0) + '"';
-
- // SbkType would return null when the type is a container.
- if (func->type()->typeEntry()->isContainer())
- return '"' + reinterpret_cast<const ContainerTypeEntry*>(func->type()->typeEntry())->typeName() + '"';
-
- if (avoidProtectedHack()) {
- const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(func->type());
- if (metaEnum && metaEnum->isProtected())
- return '"' + protectedEnumSurrogateName(metaEnum) + '"';
- }
-
- if (func->type()->isPrimitive())
- return '"' + func->type()->name() + '"';
-
- return QString("Shiboken::SbkType< %1 >()->tp_name").arg(func->type()->typeEntry()->qualifiedCppName());
-}
-
-void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFunction* func)
-{
- //skip metaObject function, this will be written manually ahead
- if (usePySideExtensions() && func->ownerClass() && func->ownerClass()->isQObject() &&
- ((func->name() == "metaObject") || (func->name() == "qt_metacall")))
- return;
-
- const TypeEntry* retType = func->type() ? func->type()->typeEntry() : 0;
- const QString funcName = func->isOperatorOverload() ? pythonOperatorFunctionName(func) : func->name();
-
- QString prefix = QString("%1::").arg(wrapperName(func->ownerClass()));
- s << functionSignature(func, prefix, "", Generator::SkipDefaultValues|Generator::OriginalTypeDescription) << endl;
- s << '{' << endl;
-
- Indentation indentation(INDENT);
-
- QString defaultReturnExpr;
- if (retType) {
- foreach (FunctionModification mod, func->modifications()) {
- foreach (ArgumentModification argMod, mod.argument_mods) {
- if (argMod.index == 0 && !argMod.replacedDefaultExpression.isEmpty()) {
- QRegExp regex("%(\\d+)");
- defaultReturnExpr = argMod.replacedDefaultExpression;
- int offset = 0;
- while ((offset = regex.indexIn(defaultReturnExpr, offset)) != -1) {
- int argId = regex.cap(1).toInt() - 1;
- if (argId < 0 || argId > func->arguments().count()) {
- ReportHandler::warning("The expression used in return value contains an invalid index.");
- break;
- }
- defaultReturnExpr.replace(regex.cap(0), func->arguments()[argId]->name());
- }
- }
- }
- }
- if (defaultReturnExpr.isEmpty())
- defaultReturnExpr = minimalConstructor(func->type());
- if (defaultReturnExpr.isEmpty()) {
- QString errorMsg = QString(MIN_CTOR_ERROR_MSG).arg(func->type()->cppSignature());
- ReportHandler::warning(errorMsg);
- s << endl << INDENT << "#error " << errorMsg << endl;
- }
- }
-
- if (func->isAbstract() && func->isModifiedRemoved()) {
- ReportHandler::warning(QString("Pure virtual method '%1::%2' must be implement but was "\
- "completely removed on type system.")
- .arg(func->ownerClass()->name())
- .arg(func->minimalSignature()));
- s << INDENT << "return " << defaultReturnExpr << ';' << endl;
- s << '}' << endl << endl;
- return;
- }
-
- //Write declaration/native injected code
- if (func->hasInjectedCode()) {
- CodeSnipList snips = func->injectedCodeSnips();
- const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last();
- writeCodeSnips(s, snips, CodeSnip::Declaration, TypeSystem::NativeCode, func, lastArg);
- s << endl;
- }
-
- s << INDENT << "Shiboken::GilState gil;" << endl;
-
- // Get out of virtual method call if someone already threw an error.
- s << INDENT << "if (PyErr_Occurred())" << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "return " << defaultReturnExpr << ';' << endl;
- }
-
- s << INDENT << "Shiboken::AutoDecRef " PYTHON_OVERRIDE_VAR "(Shiboken::BindingManager::instance().getOverride(this, \"";
- s << funcName << "\"));" << endl;
-
- s << INDENT << "if (" PYTHON_OVERRIDE_VAR ".isNull()) {" << endl;
- {
- Indentation indentation(INDENT);
- CodeSnipList snips;
- if (func->hasInjectedCode()) {
- snips = func->injectedCodeSnips();
- const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last();
- writeCodeSnips(s, snips, CodeSnip::Beginning, TypeSystem::ShellCode, func, lastArg);
- s << endl;
- }
-
- if (func->isAbstract()) {
- s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '";
- s << func->ownerClass()->name() << '.' << funcName;
- s << "()' not implemented.\");" << endl;
- s << INDENT << "return " << (retType ? defaultReturnExpr : "");
- } else {
- s << INDENT << "gil.release();" << endl;
- s << INDENT << "return this->::" << func->implementingClass()->qualifiedCppName() << "::";
- writeFunctionCall(s, func, Generator::VirtualCall);
- }
- }
- s << ';' << endl;
- s << INDENT << '}' << endl << endl;
-
- writeConversionRule(s, func, TypeSystem::TargetLangCode);
-
- s << INDENT << "Shiboken::AutoDecRef " PYTHON_ARGS "(";
-
- if (func->arguments().isEmpty() || allArgumentsRemoved(func)) {
- s << "PyTuple_New(0));" << endl;
- } else {
- QStringList argConversions;
- foreach (const AbstractMetaArgument* arg, func->arguments()) {
- if (func->argumentRemoved(arg->argumentIndex() + 1))
- continue;
-
- QString argConv;
- QTextStream ac(&argConv);
- const PrimitiveTypeEntry* argType = (const PrimitiveTypeEntry*) arg->type()->typeEntry();
- bool convert = argType->isObject()
- || arg->type()->isQObject()
- || argType->isValue()
- || arg->type()->isValuePointer()
- || arg->type()->isNativePointer()
- || argType->isFlags()
- || argType->isEnum()
- || argType->isContainer()
- || arg->type()->isReference();
-
- if (!convert && argType->isPrimitive()) {
- if (argType->basicAliasedTypeEntry())
- argType = argType->basicAliasedTypeEntry();
- convert = !m_formatUnits.contains(argType->name());
- }
-
- Indentation indentation(INDENT);
- ac << INDENT;
- if (!func->conversionRule(TypeSystem::TargetLangCode, arg->argumentIndex() + 1).isEmpty()) {
- // Has conversion rule.
- ac << QString("%1"CONV_RULE_OUT_VAR_SUFFIX).arg(arg->name());
- } else {
- QString argName = arg->name();
- if (convert)
- writeToPythonConversion(ac, arg->type(), func->ownerClass(), argName);
- else
- ac << argName;
- }
-
- argConversions << argConv;
- }
-
- s << "Py_BuildValue(\"(" << getFormatUnitString(func, false) << ")\"," << endl;
- s << argConversions.join(",\n") << endl;
- s << INDENT << "));" << endl;
- }
-
- bool invalidateReturn = false;
- foreach (FunctionModification funcMod, func->modifications()) {
- foreach (ArgumentModification argMod, funcMod.argument_mods) {
- if (argMod.resetAfterUse) {
- s << INDENT << "bool invalidateArg" << argMod.index;
- s << " = PyTuple_GET_ITEM(" PYTHON_ARGS ", " << argMod.index - 1 << ")->ob_refcnt == 1;" << endl;
- } else if (argMod.index == 0 && argMod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::CppOwnership) {
- invalidateReturn = true;
- }
- }
- }
- s << endl;
-
- CodeSnipList snips;
- if (func->hasInjectedCode()) {
- snips = func->injectedCodeSnips();
-
- if (injectedCodeUsesPySelf(func))
- s << INDENT << "PyObject* pySelf = BindingManager::instance().retrieveWrapper(this);" << endl;
-
- const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last();
- writeCodeSnips(s, snips, CodeSnip::Beginning, TypeSystem::NativeCode, func, lastArg);
- s << endl;
- }
-
- if (!injectedCodeCallsPythonOverride(func)) {
- s << INDENT;
- s << "Shiboken::AutoDecRef " PYTHON_RETURN_VAR "(PyObject_Call(" PYTHON_OVERRIDE_VAR ", " PYTHON_ARGS ", NULL));" << endl;
-
- s << INDENT << "// An error happened in python code!" << endl;
- s << INDENT << "if (" PYTHON_RETURN_VAR ".isNull()) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_Print();" << endl;
- s << INDENT << "return " << defaultReturnExpr << ';' << endl;
- }
- s << INDENT << '}' << endl;
-
- if (retType) {
- if (invalidateReturn)
- s << INDENT << "bool invalidateArg0 = " PYTHON_RETURN_VAR "->ob_refcnt == 1;" << endl;
-
- if (func->typeReplaced(0) != "PyObject") {
-
- s << INDENT << "// Check return type" << endl;
- s << INDENT;
- if (func->typeReplaced(0).isEmpty()) {
- s << "PythonToCppFunc " PYTHON_TO_CPP_VAR " = " << cpythonIsConvertibleFunction(func->type());
- s << PYTHON_RETURN_VAR ");" << endl;
- s << INDENT << "if (!" PYTHON_TO_CPP_VAR ") {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "Shiboken::warning(PyExc_RuntimeWarning, 2, "\
- "\"Invalid return value in function %s, expected %s, got %s.\", \"";
- s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func);
- s << ", " PYTHON_RETURN_VAR "->ob_type->tp_name);" << endl;
- s << INDENT << "return " << defaultReturnExpr << ';' << endl;
- }
- s << INDENT << '}' << endl;
-
- } else {
-
- s << INDENT << "// Check return type" << endl;
- s << INDENT << "bool typeIsValid = ";
- writeTypeCheck(s, func->type(), PYTHON_RETURN_VAR,
- isNumber(func->type()->typeEntry()), func->typeReplaced(0));
- s << ';' << endl;
- s << INDENT << "if (!typeIsValid";
- s << (isPointerToWrapperType(func->type()) ? " && " PYTHON_RETURN_VAR " != Py_None" : "");
- s << ") {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "Shiboken::warning(PyExc_RuntimeWarning, 2, "\
- "\"Invalid return value in function %s, expected %s, got %s.\", \"";
- s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func);
- s << ", " PYTHON_RETURN_VAR "->ob_type->tp_name);" << endl;
- s << INDENT << "return " << defaultReturnExpr << ';' << endl;
- }
- s << INDENT << '}' << endl;
-
- }
- }
-
- if (!func->conversionRule(TypeSystem::NativeCode, 0).isEmpty()) {
- // Has conversion rule.
- writeConversionRule(s, func, TypeSystem::NativeCode, CPP_RETURN_VAR);
- } else if (!injectedCodeHasReturnValueAttribution(func, TypeSystem::NativeCode)) {
- writePythonToCppTypeConversion(s, func->type(), PYTHON_RETURN_VAR, CPP_RETURN_VAR, func->implementingClass());
- }
- }
- }
-
- if (invalidateReturn) {
- s << INDENT << "if (invalidateArg0)" << endl;
- Indentation indentation(INDENT);
- s << INDENT << "Shiboken::Object::releaseOwnership(" << PYTHON_RETURN_VAR ".object());" << endl;
- }
-
- foreach (FunctionModification funcMod, func->modifications()) {
- foreach (ArgumentModification argMod, funcMod.argument_mods) {
- if (argMod.resetAfterUse) {
- s << INDENT << "if (invalidateArg" << argMod.index << ')' << endl;
- Indentation indentation(INDENT);
- s << INDENT << "Shiboken::Object::invalidate(PyTuple_GET_ITEM(" PYTHON_ARGS ", ";
- s << (argMod.index - 1) << "));" << endl;
- } else if (argMod.ownerships.contains(TypeSystem::NativeCode)
- && argMod.index == 0 && argMod.ownerships[TypeSystem::NativeCode] == TypeSystem::CppOwnership) {
- s << INDENT << "if (Shiboken::Object::checkType(" PYTHON_RETURN_VAR "))" << endl;
- Indentation indent(INDENT);
- s << INDENT << "Shiboken::Object::releaseOwnership(" PYTHON_RETURN_VAR ");" << endl;
- }
- }
- }
-
- if (func->hasInjectedCode()) {
- s << endl;
- const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last();
- writeCodeSnips(s, snips, CodeSnip::End, TypeSystem::NativeCode, func, lastArg);
- }
-
- if (retType) {
- s << INDENT << "return ";
- if (avoidProtectedHack() && retType->isEnum()) {
- const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(retType);
- bool isProtectedEnum = metaEnum && metaEnum->isProtected();
- if (isProtectedEnum) {
- QString typeCast;
- if (metaEnum->enclosingClass())
- typeCast += QString("::%1").arg(metaEnum->enclosingClass()->qualifiedCppName());
- typeCast += QString("::%1").arg(metaEnum->name());
- s << '(' << typeCast << ')';
- }
- }
- if (func->type()->isReference() && !isPointer(func->type()))
- s << '*';
- s << CPP_RETURN_VAR ";" << endl;
- }
-
- s << '}' << endl << endl;
-}
-
-void CppGenerator::writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- Indentation indentation(INDENT);
- QString wrapperClassName = wrapperName(metaClass);
- s << "const QMetaObject* " << wrapperClassName << "::metaObject() const" << endl;
- s << '{' << endl;
- s << INDENT << "#if QT_VERSION >= 0x040700" << endl;
- s << INDENT << "if (QObject::d_ptr->metaObject) return QObject::d_ptr->metaObject;" << endl;
- s << INDENT << "#endif" << endl;
- s << INDENT << "SbkObject* pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl;
- s << INDENT << "return PySide::SignalManager::retriveMetaObject(reinterpret_cast<PyObject*>(pySelf));" << endl;
- s << '}' << endl << endl;
-
- // qt_metacall function
- s << "int " << wrapperClassName << "::qt_metacall(QMetaObject::Call call, int id, void** args)" << endl;
- s << "{" << endl;
-
- AbstractMetaFunction *func = NULL;
- AbstractMetaFunctionList list = metaClass->queryFunctionsByName("qt_metacall");
- if (list.size() == 1)
- func = list[0];
-
- CodeSnipList snips;
- if (func) {
- snips = func->injectedCodeSnips();
- if (func->isUserAdded()) {
- CodeSnipList snips = func->injectedCodeSnips();
- writeCodeSnips(s, snips, CodeSnip::Any, TypeSystem::NativeCode, func);
- }
- }
-
- s << INDENT << "int result = " << metaClass->qualifiedCppName() << "::qt_metacall(call, id, args);" << endl;
- s << INDENT << "return result < 0 ? result : PySide::SignalManager::qt_metacall(this, call, id, args);" << endl;
- s << "}" << endl << endl;
-
- // qt_metacast function
- writeMetaCast(s, metaClass);
-}
-
-void CppGenerator::writeMetaCast(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- Indentation indentation(INDENT);
- QString wrapperClassName = wrapperName(metaClass);
- s << "void* " << wrapperClassName << "::qt_metacast(const char* _clname)" << endl;
- s << '{' << endl;
- s << INDENT << "if (!_clname) return 0;" << endl;
- s << INDENT << "SbkObject* pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl;
- s << INDENT << "if (pySelf && PySide::inherits(Py_TYPE(pySelf), _clname))" << endl;
- s << INDENT << INDENT << "return static_cast<void*>(const_cast< " << wrapperClassName << "* >(this));" << endl;
- s << INDENT << "return " << metaClass->qualifiedCppName() << "::qt_metacast(_clname);" << endl;
- s << "}" << endl << endl;
-}
-
-void CppGenerator::writeEnumConverterFunctions(QTextStream& s, const AbstractMetaEnum* metaEnum)
-{
- if (metaEnum->isPrivate() || metaEnum->isAnonymous())
- return;
- writeEnumConverterFunctions(s, metaEnum->typeEntry());
-}
-
-void CppGenerator::writeEnumConverterFunctions(QTextStream& s, const TypeEntry* enumType)
-{
- if (!enumType)
- return;
- QString enumFlagName = enumType->isFlags() ? "flag" : "enum";
- QString typeName = fixedCppTypeName(enumType);
- QString enumPythonType = cpythonTypeNameExt(enumType);
- QString cppTypeName = getFullTypeName(enumType).trimmed();
- if (avoidProtectedHack()) {
- const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(enumType);
- if (metaEnum && metaEnum->isProtected())
- cppTypeName = protectedEnumSurrogateName(metaEnum);
- }
- QString code;
- QTextStream c(&code);
- c << INDENT << "*((" << cppTypeName << "*)cppOut) = ";
- if (enumType->isFlags())
- c << cppTypeName << "(QFlag(PySide::QFlags::getValue(reinterpret_cast<PySideQFlagsObject*>(pyIn))))";
- else
- c << "(" << cppTypeName << ") Shiboken::Enum::getValue(pyIn)";
- c << ';' << endl;
- writePythonToCppFunction(s, code, typeName, typeName);
-
- QString pyTypeCheck = QString("PyObject_TypeCheck(pyIn, %1)").arg(enumPythonType);
- writeIsPythonConvertibleToCppFunction(s, typeName, typeName, pyTypeCheck);
-
- code.clear();
-
- c << INDENT << "int castCppIn = *((" << cppTypeName << "*)cppIn);" << endl;
- c << INDENT;
- c << "return ";
- if (enumType->isFlags())
- c << "reinterpret_cast<PyObject*>(PySide::QFlags::newObject(castCppIn, " << enumPythonType << "))";
-
- else
- c << "Shiboken::Enum::newItem(" << enumPythonType << ", castCppIn)";
- c << ';' << endl;
- writeCppToPythonFunction(s, code, typeName, typeName);
- s << endl;
-
- if (enumType->isFlags())
- return;
-
- const FlagsTypeEntry* flags = reinterpret_cast<const EnumTypeEntry*>(enumType)->flags();
- if (!flags)
- return;
-
- // QFlags part.
-
- writeEnumConverterFunctions(s, flags);
-
- code.clear();
- cppTypeName = getFullTypeName(flags).trimmed();
- c << INDENT << "*((" << cppTypeName << "*)cppOut) = " << cppTypeName;
- c << "(QFlag(Shiboken::Enum::getValue(pyIn)));" << endl;
-
- QString flagsTypeName = fixedCppTypeName(flags);
- writePythonToCppFunction(s, code, typeName, flagsTypeName);
- writeIsPythonConvertibleToCppFunction(s, typeName, flagsTypeName, pyTypeCheck);
-
- code.clear();
- c << INDENT << "Shiboken::AutoDecRef pyLong(PyNumber_Long(pyIn));" << endl;
- c << INDENT << "*((" << cppTypeName << "*)cppOut) = " << cppTypeName;
- c << "(QFlag(PyLong_AsLong(pyLong.object())));" << endl;
- writePythonToCppFunction(s, code, "number", flagsTypeName);
- writeIsPythonConvertibleToCppFunction(s, "number", flagsTypeName, "PyNumber_Check(pyIn)");
-}
-
-void CppGenerator::writeConverterFunctions(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- s << "// Type conversion functions." << endl << endl;
-
- AbstractMetaEnumList classEnums = metaClass->enums();
- foreach (AbstractMetaClass* innerClass, metaClass->innerClasses())
- lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass);
- if (!classEnums.isEmpty())
- s << "// Python to C++ enum conversion." << endl;
- foreach (const AbstractMetaEnum* metaEnum, classEnums)
- writeEnumConverterFunctions(s, metaEnum);
-
- if (metaClass->isNamespace())
- return;
-
- QString typeName = getFullTypeName(metaClass);
- QString cpythonType = cpythonTypeName(metaClass);
-
- // Returns the C++ pointer of the Python wrapper.
- s << "// Python to C++ pointer conversion - returns the C++ object of the Python wrapper (keeps object identity)." << endl;
-
- QString sourceTypeName = metaClass->name();
- QString targetTypeName = QString("%1_PTR").arg(metaClass->name());
- QString code;
- QTextStream c(&code);
- c << INDENT << "Shiboken::Conversions::pythonToCppPointer(&" << cpythonType << ", pyIn, cppOut);";
- writePythonToCppFunction(s, code, sourceTypeName, targetTypeName);
-
- // "Is convertible" function for the Python object to C++ pointer conversion.
- QString pyTypeCheck = QString("PyObject_TypeCheck(pyIn, (PyTypeObject*)&%1)").arg(cpythonType);
- writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, pyTypeCheck, QString(), true);
- s << endl;
-
- // C++ pointer to a Python wrapper, keeping identity.
- s << "// C++ to Python pointer conversion - tries to find the Python wrapper for the C++ object (keeps object identity)." << endl;
- code.clear();
- c << INDENT << "PyObject* pyOut = (PyObject*)Shiboken::BindingManager::instance().retrieveWrapper(cppIn);" << endl;
- c << INDENT << "if (pyOut) {" << endl;
- {
- Indentation indent(INDENT);
- c << INDENT << "Py_INCREF(pyOut);" << endl;
- c << INDENT << "return pyOut;" << endl;
- }
- c << INDENT << '}' << endl;
- c << INDENT << "const char* typeName = typeid(*((" << typeName << "*)cppIn)).name();" << endl;
- c << INDENT << "return Shiboken::Object::newObject(&" << cpythonType;
- c << ", const_cast<void*>(cppIn), false, false, typeName);";
- std::swap(targetTypeName, sourceTypeName);
- writeCppToPythonFunction(s, code, sourceTypeName, targetTypeName);
-
- // The conversions for an Object Type end here.
- if (!metaClass->typeEntry()->isValue()) {
- s << endl;
- return;
- }
-
- // Always copies C++ value (not pointer, and not reference) to a new Python wrapper.
- s << endl << "// C++ to Python copy conversion." << endl;
- sourceTypeName = QString("%1_COPY").arg(metaClass->name());
- targetTypeName = metaClass->name();
- code.clear();
- c << INDENT << "return Shiboken::Object::newObject(&" << cpythonType << ", new ::" << wrapperName(metaClass);
- c << "(*((" << typeName << "*)cppIn)), true, true);";
- writeCppToPythonFunction(s, code, sourceTypeName, targetTypeName);
- s << endl;
-
- // Python to C++ copy conversion.
- s << "// Python to C++ copy conversion." << endl;
- sourceTypeName = metaClass->name();
- targetTypeName = QString("%1_COPY").arg(sourceTypeName);
- code.clear();
- c << INDENT << "*((" << typeName << "*)cppOut) = *" << cpythonWrapperCPtr(metaClass->typeEntry(), "pyIn") << ';';
- writePythonToCppFunction(s, code, sourceTypeName, targetTypeName);
-
- // "Is convertible" function for the Python object to C++ value copy conversion.
- writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, pyTypeCheck);
- s << endl;
-
- // User provided implicit conversions.
- CustomConversion* customConversion = metaClass->typeEntry()->customConversion();
-
- // Implicit conversions.
- AbstractMetaFunctionList implicitConvs;
- if (!customConversion || !customConversion->replaceOriginalTargetToNativeConversions()) {
- foreach (AbstractMetaFunction* func, implicitConversions(metaClass->typeEntry())) {
- if (!func->isUserAdded())
- implicitConvs << func;
- }
- }
-
- if (!implicitConvs.isEmpty())
- s << "// Implicit conversions." << endl;
-
- AbstractMetaType* targetType = buildAbstractMetaTypeFromAbstractMetaClass(metaClass);
- foreach (const AbstractMetaFunction* conv, implicitConvs) {
- if (conv->isModifiedRemoved())
- continue;
-
- QString typeCheck;
- QString toCppConv;
- QString toCppPreConv;
- if (conv->isConversionOperator()) {
- const AbstractMetaClass* sourceClass = conv->ownerClass();
- typeCheck = QString("PyObject_TypeCheck(pyIn, %1)").arg(cpythonTypeNameExt(sourceClass->typeEntry()));
- toCppConv = QString("*%1").arg(cpythonWrapperCPtr(sourceClass->typeEntry(), "pyIn"));
-
- } else {
- // Constructor that does implicit conversion.
- if (!conv->typeReplaced(1).isEmpty())
- continue;
- const AbstractMetaType* sourceType = conv->arguments().first()->type();
- typeCheck = cpythonCheckFunction(sourceType);
- bool isUserPrimitiveWithoutTargetLangName = isUserPrimitive(sourceType)
- && sourceType->typeEntry()->targetLangApiName() == sourceType->typeEntry()->name();
- if (!isWrapperType(sourceType)
- && !isUserPrimitiveWithoutTargetLangName
- && !sourceType->typeEntry()->isEnum()
- && !sourceType->typeEntry()->isFlags()
- && !sourceType->typeEntry()->isContainer()) {
- typeCheck += '(';
- }
- if (isWrapperType(sourceType)) {
- typeCheck = QString("%1pyIn)").arg(typeCheck);
- toCppConv = QString("%1%2")
- .arg((sourceType->isReference() || !isPointerToWrapperType(sourceType)) ? "*" : "")
- .arg(cpythonWrapperCPtr(sourceType->typeEntry(), "pyIn"));
- } else if (typeCheck.contains("%in")) {
- typeCheck.replace("%in", "pyIn");
- typeCheck = QString("%1)").arg(typeCheck);
- } else {
- typeCheck = QString("%1pyIn)").arg(typeCheck);
- }
-
- if (isUserPrimitive(sourceType)
- || isCppPrimitive(sourceType)
- || sourceType->typeEntry()->isContainer()
- || sourceType->typeEntry()->isEnum()
- || sourceType->typeEntry()->isFlags()) {
- QTextStream pc(&toCppPreConv);
- pc << INDENT << getFullTypeNameWithoutModifiers(sourceType) << " cppIn";
- writeMinimalConstructorExpression(pc, sourceType);
- pc << ';' << endl;
- writeToCppConversion(pc, sourceType, 0, "pyIn", "cppIn");
- pc << ';';
- toCppConv.append("cppIn");
- } else if (!isWrapperType(sourceType)) {
- QTextStream tcc(&toCppConv);
- writeToCppConversion(tcc, sourceType, metaClass, "pyIn", "/*BOZO-1061*/");
- }
-
-
- }
- const AbstractMetaType* sourceType = conv->isConversionOperator()
- ? buildAbstractMetaTypeFromAbstractMetaClass(conv->ownerClass())
- : conv->arguments().first()->type();
- writePythonToCppConversionFunctions(s, sourceType, targetType, typeCheck, toCppConv, toCppPreConv);
- }
-
- writeCustomConverterFunctions(s, customConversion);
-}
-
-void CppGenerator::writeCustomConverterFunctions(QTextStream& s, const CustomConversion* customConversion)
-{
- if (!customConversion)
- return;
- const CustomConversion::TargetToNativeConversions& toCppConversions = customConversion->targetToNativeConversions();
- if (toCppConversions.isEmpty())
- return;
- s << "// Python to C++ conversions for type '" << customConversion->ownerType()->qualifiedCppName() << "'." << endl;
- foreach (CustomConversion::TargetToNativeConversion* toNative, toCppConversions)
- writePythonToCppConversionFunctions(s, toNative, customConversion->ownerType());
- s << endl;
-}
-
-void CppGenerator::writeConverterRegister(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- if (metaClass->isNamespace())
- return;
- s << INDENT << "// Register Converter" << endl;
- s << INDENT << "SbkConverter* converter = Shiboken::Conversions::createConverter(&";
- s << cpythonTypeName(metaClass) << ',' << endl;
- {
- Indentation indent(INDENT);
- QString sourceTypeName = metaClass->name();
- QString targetTypeName = QString("%1_PTR").arg(metaClass->name());
- s << INDENT << pythonToCppFunctionName(sourceTypeName, targetTypeName) << ',' << endl;
- s << INDENT << convertibleToCppFunctionName(sourceTypeName, targetTypeName) << ',' << endl;
- std::swap(targetTypeName, sourceTypeName);
- s << INDENT << cppToPythonFunctionName(sourceTypeName, targetTypeName);
- if (metaClass->typeEntry()->isValue()) {
- s << ',' << endl;
- sourceTypeName = QString("%1_COPY").arg(metaClass->name());
- s << INDENT << cppToPythonFunctionName(sourceTypeName, targetTypeName);
- }
- }
- s << ");" << endl;
-
- s << endl;
-
- QStringList cppSignature = metaClass->qualifiedCppName().split("::", QString::SkipEmptyParts);
- while (!cppSignature.isEmpty()) {
- QString signature = cppSignature.join("::");
- s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "\");" << endl;
- s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "*\");" << endl;
- s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "&\");" << endl;
- cppSignature.removeFirst();
- }
-
- s << INDENT << "Shiboken::Conversions::registerConverterName(converter, typeid(::";
- s << metaClass->qualifiedCppName() << ").name());" << endl;
- if (shouldGenerateCppWrapper(metaClass)) {
- s << INDENT << "Shiboken::Conversions::registerConverterName(converter, typeid(::";
- s << wrapperName(metaClass) << ").name());" << endl;
- }
-
- s << endl;
-
- if (!metaClass->typeEntry()->isValue())
- return;
-
- // Python to C++ copy (value, not pointer neither reference) conversion.
- s << INDENT << "// Add Python to C++ copy (value, not pointer neither reference) conversion to type converter." << endl;
- QString sourceTypeName = metaClass->name();
- QString targetTypeName = QString("%1_COPY").arg(metaClass->name());
- QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName);
- QString isConv = convertibleToCppFunctionName(sourceTypeName, targetTypeName);
- writeAddPythonToCppConversion(s, "converter", toCpp, isConv);
-
- // User provided implicit conversions.
- CustomConversion* customConversion = metaClass->typeEntry()->customConversion();
-
- // Add implicit conversions.
- AbstractMetaFunctionList implicitConvs;
- if (!customConversion || !customConversion->replaceOriginalTargetToNativeConversions()) {
- foreach (AbstractMetaFunction* func, implicitConversions(metaClass->typeEntry())) {
- if (!func->isUserAdded())
- implicitConvs << func;
- }
- }
-
- if (!implicitConvs.isEmpty())
- s << INDENT << "// Add implicit conversions to type converter." << endl;
-
- AbstractMetaType* targetType = buildAbstractMetaTypeFromAbstractMetaClass(metaClass);
- foreach (const AbstractMetaFunction* conv, implicitConvs) {
- if (conv->isModifiedRemoved())
- continue;
- const AbstractMetaType* sourceType;
- if (conv->isConversionOperator()) {
- sourceType = buildAbstractMetaTypeFromAbstractMetaClass(conv->ownerClass());
- } else {
- // Constructor that does implicit conversion.
- if (!conv->typeReplaced(1).isEmpty())
- continue;
- sourceType = conv->arguments().first()->type();
- }
- QString toCpp = pythonToCppFunctionName(sourceType, targetType);
- QString isConv = convertibleToCppFunctionName(sourceType, targetType);
- writeAddPythonToCppConversion(s, "converter", toCpp, isConv);
- }
-
- writeCustomConverterRegister(s, customConversion, "converter");
-}
-
-void CppGenerator::writeCustomConverterRegister(QTextStream& s, const CustomConversion* customConversion, const QString& converterVar)
-{
- if (!customConversion)
- return;
- const CustomConversion::TargetToNativeConversions& toCppConversions = customConversion->targetToNativeConversions();
- if (toCppConversions.isEmpty())
- return;
- s << INDENT << "// Add user defined implicit conversions to type converter." << endl;
- foreach (CustomConversion::TargetToNativeConversion* toNative, toCppConversions) {
- QString toCpp = pythonToCppFunctionName(toNative, customConversion->ownerType());
- QString isConv = convertibleToCppFunctionName(toNative, customConversion->ownerType());
- writeAddPythonToCppConversion(s, converterVar, toCpp, isConv);
- }
-}
-
-void CppGenerator::writeContainerConverterRegister(QTextStream& s, const AbstractMetaType* container, const QString& converterVar)
-{
- s << INDENT << "// Add user defined container conversion to type converter." << endl;
- QString typeName = fixedCppTypeName(container);
- QString toCpp = pythonToCppFunctionName(typeName, typeName);
- QString isConv = convertibleToCppFunctionName(typeName, typeName);
- writeAddPythonToCppConversion(s, converterVar, toCpp, isConv);
-}
-
-void CppGenerator::writeContainerConverterFunctions(QTextStream& s, const AbstractMetaType* containerType)
-{
- writeCppToPythonFunction(s, containerType);
- writePythonToCppConversionFunctions(s, containerType);
-}
-
-void CppGenerator::writeMethodWrapperPreamble(QTextStream& s, OverloadData& overloadData)
-{
- const AbstractMetaFunction* rfunc = overloadData.referenceFunction();
- const AbstractMetaClass* ownerClass = rfunc->ownerClass();
- int minArgs = overloadData.minArgs();
- int maxArgs = overloadData.maxArgs();
- bool initPythonArguments;
- bool usesNamedArguments;
-
- // If method is a constructor...
- if (rfunc->isConstructor()) {
- // Check if the right constructor was called.
- if (!ownerClass->hasPrivateDestructor()) {
- s << INDENT;
- s << "if (Shiboken::Object::isUserType(" PYTHON_SELF_VAR ") && !Shiboken::ObjectType::canCallConstructor(" PYTHON_SELF_VAR "->ob_type, Shiboken::SbkType< ::";
- s << ownerClass->qualifiedCppName() << " >()))" << endl;
- Indentation indent(INDENT);
- s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl;
- }
- // Declare pointer for the underlying C++ object.
- s << INDENT << "::";
- s << (shouldGenerateCppWrapper(ownerClass) ? wrapperName(ownerClass) : ownerClass->qualifiedCppName());
- s << "* cptr = 0;" << endl;
-
- initPythonArguments = maxArgs > 0;
- usesNamedArguments = !ownerClass->isQObject() && overloadData.hasArgumentWithDefaultValue();
-
- } else {
- if (rfunc->implementingClass() &&
- (!rfunc->implementingClass()->isNamespace() && overloadData.hasInstanceFunction())) {
- writeCppSelfDefinition(s, rfunc, overloadData.hasStaticFunction());
- }
- if (!rfunc->isInplaceOperator() && overloadData.hasNonVoidReturnType())
- s << INDENT << "PyObject* " PYTHON_RETURN_VAR " = 0;" << endl;
-
- initPythonArguments = minArgs != maxArgs || maxArgs > 1;
- usesNamedArguments = rfunc->isCallOperator() || overloadData.hasArgumentWithDefaultValue();
- }
-
- if (maxArgs > 0) {
- s << INDENT << "int overloadId = -1;" << endl;
- s << INDENT << "PythonToCppFunc " PYTHON_TO_CPP_VAR;
- if (pythonFunctionWrapperUsesListOfArguments(overloadData))
- s << "[] = { 0" << QString(", 0").repeated(maxArgs-1) << " }";
- s << ';' << endl;
- writeUnusedVariableCast(s, PYTHON_TO_CPP_VAR);
- }
-
- if (usesNamedArguments && !rfunc->isCallOperator())
- s << INDENT << "int numNamedArgs = (kwds ? PyDict_Size(kwds) : 0);" << endl;
-
- if (initPythonArguments) {
- s << INDENT << "int numArgs = ";
- if (minArgs == 0 && maxArgs == 1 && !rfunc->isConstructor() && !pythonFunctionWrapperUsesListOfArguments(overloadData))
- s << "(" PYTHON_ARG " == 0 ? 0 : 1);" << endl;
- else
- writeArgumentsInitializer(s, overloadData);
- }
-}
-
-void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFunctionList overloads)
-{
- ErrorCode errorCode(-1);
- OverloadData overloadData(overloads, this);
-
- const AbstractMetaFunction* rfunc = overloadData.referenceFunction();
- const AbstractMetaClass* metaClass = rfunc->ownerClass();
-
- s << "static int" << endl;
- s << cpythonFunctionName(rfunc) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* args, PyObject* kwds)" << endl;
- s << '{' << endl;
-
- QSet<QString> argNamesSet;
- if (usePySideExtensions() && metaClass->isQObject()) {
- // Write argNames variable with all known argument names.
- foreach (const AbstractMetaFunction* func, overloadData.overloads()) {
- foreach (const AbstractMetaArgument* arg, func->arguments()) {
- if (arg->defaultValueExpression().isEmpty() || func->argumentRemoved(arg->argumentIndex() + 1))
- continue;
- argNamesSet << arg->name();
- }
- }
- QStringList argNamesList = argNamesSet.toList();
- qSort(argNamesList.begin(), argNamesList.end());
- if (argNamesList.isEmpty())
- s << INDENT << "const char** argNames = 0;" << endl;
- else
- s << INDENT << "const char* argNames[] = {\"" << argNamesList.join("\", \"") << "\"};" << endl;
- s << INDENT << "const QMetaObject* metaObject;" << endl;
- }
-
- s << INDENT << "SbkObject* sbkSelf = reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR ");" << endl;
-
- if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) {
- s << INDENT << "SbkObjectType* type = reinterpret_cast<SbkObjectType*>(" PYTHON_SELF_VAR "->ob_type);" << endl;
- s << INDENT << "SbkObjectType* myType = reinterpret_cast<SbkObjectType*>(" << cpythonTypeNameExt(metaClass->typeEntry()) << ");" << endl;
- }
-
- if (metaClass->isAbstract()) {
- s << INDENT << "if (type == myType) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_NotImplementedError," << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "\"'" << metaClass->qualifiedCppName();
- }
- s << "' represents a C++ abstract class and cannot be instantiated\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
- }
- s << INDENT << '}' << endl << endl;
- }
-
- if (metaClass->baseClassNames().size() > 1) {
- if (!metaClass->isAbstract()) {
- s << INDENT << "if (type != myType) {" << endl;
- }
- {
- Indentation indentation(INDENT);
- s << INDENT << "Shiboken::ObjectType::copyMultimpleheritance(type, myType);" << endl;
- }
- if (!metaClass->isAbstract())
- s << INDENT << '}' << endl << endl;
- }
-
- writeMethodWrapperPreamble(s, overloadData);
-
- s << endl;
-
- if (overloadData.maxArgs() > 0)
- writeOverloadedFunctionDecisor(s, overloadData);
-
- writeFunctionCalls(s, overloadData);
- s << endl;
-
- s << INDENT << "if (PyErr_Occurred() || !Shiboken::Object::setCppPointer(sbkSelf, Shiboken::SbkType< ::" << metaClass->qualifiedCppName() << " >(), cptr)) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "delete cptr;" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
- }
- s << INDENT << '}' << endl;
- if (overloadData.maxArgs() > 0) {
- s << INDENT << "if (!cptr) goto " << cpythonFunctionName(rfunc) << "_TypeError;" << endl;
- s << endl;
- }
-
- s << INDENT << "Shiboken::Object::setValidCpp(sbkSelf, true);" << endl;
- // If the created C++ object has a C++ wrapper the ownership is assigned to Python
- // (first "1") and the flag indicating that the Python wrapper holds an C++ wrapper
- // is marked as true (the second "1"). Otherwise the default values apply:
- // Python owns it and C++ wrapper is false.
- if (shouldGenerateCppWrapper(overloads.first()->ownerClass()))
- s << INDENT << "Shiboken::Object::setHasCppWrapper(sbkSelf, true);" << endl;
- s << INDENT << "Shiboken::BindingManager::instance().registerWrapper(sbkSelf, cptr);" << endl;
-
- // Create metaObject and register signal/slot
- if (metaClass->isQObject() && usePySideExtensions()) {
- s << endl << INDENT << "// QObject setup" << endl;
- s << INDENT << "PySide::Signal::updateSourceObject(" PYTHON_SELF_VAR ");" << endl;
- s << INDENT << "metaObject = cptr->metaObject(); // <- init python qt properties" << endl;
- s << INDENT << "if (kwds && !PySide::fillQtProperties(" PYTHON_SELF_VAR ", metaObject, kwds, argNames, " << argNamesSet.count() << "))" << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
- }
- }
-
- // Constructor code injections, position=end
- bool hasCodeInjectionsAtEnd = false;
- foreach(AbstractMetaFunction* func, overloads) {
- foreach (CodeSnip cs, func->injectedCodeSnips()) {
- if (cs.position == CodeSnip::End) {
- hasCodeInjectionsAtEnd = true;
- break;
- }
- }
- }
- if (hasCodeInjectionsAtEnd) {
- // FIXME: C++ arguments are not available in code injection on constructor when position = end.
- s << INDENT << "switch(overloadId) {" << endl;
- foreach(AbstractMetaFunction* func, overloads) {
- Indentation indent(INDENT);
- foreach (CodeSnip cs, func->injectedCodeSnips()) {
- if (cs.position == CodeSnip::End) {
- s << INDENT << "case " << metaClass->functions().indexOf(func) << ':' << endl;
- s << INDENT << '{' << endl;
- {
- Indentation indent(INDENT);
- writeCodeSnips(s, func->injectedCodeSnips(), CodeSnip::End, TypeSystem::TargetLangCode, func);
- }
- s << INDENT << '}' << endl;
- break;
- }
- }
- }
- s << '}' << endl;
- }
-
- s << endl;
- s << endl << INDENT << "return 1;" << endl;
- if (overloadData.maxArgs() > 0)
- writeErrorSection(s, overloadData);
- s << '}' << endl << endl;
-}
-
-void CppGenerator::writeMethodWrapper(QTextStream& s, const AbstractMetaFunctionList overloads)
-{
- OverloadData overloadData(overloads, this);
- const AbstractMetaFunction* rfunc = overloadData.referenceFunction();
-
- int maxArgs = overloadData.maxArgs();
-
- s << "static PyObject* ";
- s << cpythonFunctionName(rfunc) << "(PyObject* " PYTHON_SELF_VAR;
- if (maxArgs > 0) {
- s << ", PyObject* " << (pythonFunctionWrapperUsesListOfArguments(overloadData) ? "args" : PYTHON_ARG);
- if (overloadData.hasArgumentWithDefaultValue() || rfunc->isCallOperator())
- s << ", PyObject* kwds";
- }
- s << ')' << endl << '{' << endl;
-
- writeMethodWrapperPreamble(s, overloadData);
-
- s << endl;
-
- /*
- * Make sure reverse <</>> operators defined in other classes (specially from other modules)
- * are called. A proper and generic solution would require an reengineering in the operator
- * system like the extended converters.
- *
- * Solves #119 - QDataStream <</>> operators not working for QPixmap
- * http://bugs.openbossa.org/show_bug.cgi?id=119
- */
- bool hasReturnValue = overloadData.hasNonVoidReturnType();
- bool callExtendedReverseOperator = hasReturnValue
- && !rfunc->isInplaceOperator()
- && !rfunc->isCallOperator()
- && rfunc->isOperatorOverload();
- if (callExtendedReverseOperator) {
- QString revOpName = ShibokenGenerator::pythonOperatorFunctionName(rfunc).insert(2, 'r');
- if (rfunc->isBinaryOperator()) {
- s << INDENT << "if (!isReverse" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "&& Shiboken::Object::checkType(" PYTHON_ARG ")" << endl;
- s << INDENT << "&& !PyObject_TypeCheck(" PYTHON_ARG ", " PYTHON_SELF_VAR "->ob_type)" << endl;
- s << INDENT << "&& PyObject_HasAttrString(" PYTHON_ARG ", const_cast<char*>(\"" << revOpName << "\"))) {" << endl;
-
- // This PyObject_CallMethod call will emit lots of warnings like
- // "deprecated conversion from string constant to char *" during compilation
- // due to the method name argument being declared as "char*" instead of "const char*"
- // issue 6952 http://bugs.python.org/issue6952
- s << INDENT << "PyObject* revOpMethod = PyObject_GetAttrString(" PYTHON_ARG ", const_cast<char*>(\"" << revOpName << "\"));" << endl;
- s << INDENT << "if (revOpMethod && PyCallable_Check(revOpMethod)) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << PYTHON_RETURN_VAR " = PyObject_CallFunction(revOpMethod, const_cast<char*>(\"O\"), " PYTHON_SELF_VAR ");" << endl;
- s << INDENT << "if (PyErr_Occurred() && (PyErr_ExceptionMatches(PyExc_NotImplementedError)";
- s << " || PyErr_ExceptionMatches(PyExc_AttributeError))) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_Clear();" << endl;
- s << INDENT << "Py_XDECREF(" PYTHON_RETURN_VAR ");" << endl;
- s << INDENT << PYTHON_RETURN_VAR " = 0;" << endl;
- }
- s << INDENT << '}' << endl;
- }
- s << INDENT << "}" << endl;
- s << INDENT << "Py_XDECREF(revOpMethod);" << endl << endl;
- }
- s << INDENT << "}" << endl;
- }
- s << INDENT << "// Do not enter here if other object has implemented a reverse operator." << endl;
- s << INDENT << "if (!" PYTHON_RETURN_VAR ") {" << endl << endl;
- }
-
- if (maxArgs > 0)
- writeOverloadedFunctionDecisor(s, overloadData);
-
- writeFunctionCalls(s, overloadData);
-
- if (callExtendedReverseOperator)
- s << endl << INDENT << "} // End of \"if (!" PYTHON_RETURN_VAR ")\"" << endl;
-
- s << endl;
-
- writeFunctionReturnErrorCheckSection(s, hasReturnValue && !rfunc->isInplaceOperator());
-
- if (hasReturnValue) {
- if (rfunc->isInplaceOperator()) {
- s << INDENT << "Py_INCREF(" PYTHON_SELF_VAR ");\n";
- s << INDENT << "return " PYTHON_SELF_VAR ";\n";
- } else {
- s << INDENT << "return " PYTHON_RETURN_VAR ";\n";
- }
- } else {
- s << INDENT << "Py_RETURN_NONE;" << endl;
- }
-
- if (maxArgs > 0)
- writeErrorSection(s, overloadData);
-
- s << '}' << endl << endl;
-}
-
-void CppGenerator::writeArgumentsInitializer(QTextStream& s, OverloadData& overloadData)
-{
- const AbstractMetaFunction* rfunc = overloadData.referenceFunction();
- s << "PyTuple_GET_SIZE(args);" << endl;
-
- int minArgs = overloadData.minArgs();
- int maxArgs = overloadData.maxArgs();
-
- s << INDENT << "PyObject* ";
- s << PYTHON_ARGS "[] = {" << QString(maxArgs, '0').split("", QString::SkipEmptyParts).join(", ") << "};" << endl;
- s << endl;
-
- if (overloadData.hasVarargs()) {
- maxArgs--;
- if (minArgs > maxArgs)
- minArgs = maxArgs;
-
- s << INDENT << "PyObject* nonvarargs = PyTuple_GetSlice(args, 0, " << maxArgs << ");" << endl;
- s << INDENT << "Shiboken::AutoDecRef auto_nonvarargs(nonvarargs);" << endl;
- s << INDENT << PYTHON_ARGS "[" << maxArgs << "] = PyTuple_GetSlice(args, " << maxArgs << ", numArgs);" << endl;
- s << INDENT << "Shiboken::AutoDecRef auto_varargs(" PYTHON_ARGS "[" << maxArgs << "]);" << endl;
- s << endl;
- }
-
- bool usesNamedArguments = overloadData.hasArgumentWithDefaultValue();
-
- s << INDENT << "// invalid argument lengths" << endl;
- bool ownerClassIsQObject = rfunc->ownerClass() && rfunc->ownerClass()->isQObject() && rfunc->isConstructor();
- if (usesNamedArguments) {
- if (!ownerClassIsQObject) {
- s << INDENT << "if (numArgs" << (overloadData.hasArgumentWithDefaultValue() ? " + numNamedArgs" : "") << " > " << maxArgs << ") {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): too many arguments\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
- }
- s << INDENT << '}';
- }
- if (minArgs > 0) {
- if (ownerClassIsQObject)
- s << INDENT;
- else
- s << " else ";
- s << "if (numArgs < " << minArgs << ") {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): not enough arguments\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
- }
- s << INDENT << '}';
- }
- }
- QList<int> invalidArgsLength = overloadData.invalidArgumentLengths();
- if (!invalidArgsLength.isEmpty()) {
- QStringList invArgsLen;
- foreach (int i, invalidArgsLength)
- invArgsLen << QString("numArgs == %1").arg(i);
- if (usesNamedArguments && (!ownerClassIsQObject || minArgs > 0))
- s << " else ";
- else
- s << INDENT;
- s << "if (" << invArgsLen.join(" || ") << ")" << endl;
- Indentation indent(INDENT);
- s << INDENT << "goto " << cpythonFunctionName(rfunc) << "_TypeError;";
- }
- s << endl << endl;
-
- QString funcName;
- if (rfunc->isOperatorOverload())
- funcName = ShibokenGenerator::pythonOperatorFunctionName(rfunc);
- else
- funcName = rfunc->name();
-
- QString argsVar = overloadData.hasVarargs() ? "nonvarargs" : "args";
- s << INDENT << "if (!";
- if (usesNamedArguments)
- s << "PyArg_ParseTuple(" << argsVar << ", \"|" << QByteArray(maxArgs, 'O') << ':' << funcName << '"';
- else
- s << "PyArg_UnpackTuple(" << argsVar << ", \"" << funcName << "\", " << minArgs << ", " << maxArgs;
- QStringList palist;
- for (int i = 0; i < maxArgs; i++)
- palist << QString("&(" PYTHON_ARGS "[%1])").arg(i);
- s << ", " << palist.join(", ") << "))" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
- }
- s << endl;
-}
-
-void CppGenerator::writeCppSelfDefinition(QTextStream& s, const AbstractMetaClass* metaClass, bool hasStaticOverload, bool cppSelfAsReference)
-{
- bool useWrapperClass = avoidProtectedHack() && metaClass->hasProtectedMembers();
- QString className = useWrapperClass ? wrapperName(metaClass) : QString("::%1").arg(metaClass->qualifiedCppName());
-
- QString cppSelfAttribution;
- if (cppSelfAsReference) {
- QString cast = useWrapperClass ? QString("(%1*)").arg(className) : QString();
- cppSelfAttribution = QString("%1& %2 = *(%3%4)")
- .arg(className)
- .arg(CPP_SELF_VAR)
- .arg(cast)
- .arg(cpythonWrapperCPtr(metaClass, PYTHON_SELF_VAR));
- } else {
- s << INDENT << className << "* " CPP_SELF_VAR " = 0;" << endl;
- writeUnusedVariableCast(s, CPP_SELF_VAR);
- cppSelfAttribution = QString("%1 = %2%3")
- .arg(CPP_SELF_VAR)
- .arg(useWrapperClass ? QString("(%1*)").arg(className) : "")
- .arg(cpythonWrapperCPtr(metaClass, PYTHON_SELF_VAR));
- }
-
- // Checks if the underlying C++ object is valid.
- if (hasStaticOverload && !cppSelfAsReference) {
- s << INDENT << "if (" PYTHON_SELF_VAR ") {" << endl;
- {
- Indentation indent(INDENT);
- writeInvalidPyObjectCheck(s, PYTHON_SELF_VAR);
- s << INDENT << cppSelfAttribution << ';' << endl;
- }
- s << INDENT << '}' << endl;
- return;
- }
-
- writeInvalidPyObjectCheck(s, PYTHON_SELF_VAR);
- s << INDENT << cppSelfAttribution << ';' << endl;
-}
-
-void CppGenerator::writeCppSelfDefinition(QTextStream& s, const AbstractMetaFunction* func, bool hasStaticOverload)
-{
- if (!func->ownerClass() || func->isConstructor())
- return;
-
- if (func->isOperatorOverload() && func->isBinaryOperator()) {
- QString checkFunc = cpythonCheckFunction(func->ownerClass()->typeEntry());
- s << INDENT << "bool isReverse = " << checkFunc << PYTHON_ARG ")" << endl;
- {
- Indentation indent1(INDENT);
- Indentation indent2(INDENT);
- Indentation indent3(INDENT);
- Indentation indent4(INDENT);
- s << INDENT << "&& !" << checkFunc << PYTHON_SELF_VAR ");" << endl;
- }
- s << INDENT << "if (isReverse)" << endl;
- Indentation indent(INDENT);
- s << INDENT << "std::swap(" PYTHON_SELF_VAR ", " PYTHON_ARG ");" << endl;
- }
-
- writeCppSelfDefinition(s, func->ownerClass(), hasStaticOverload);
-}
-
-void CppGenerator::writeErrorSection(QTextStream& s, OverloadData& overloadData)
-{
- const AbstractMetaFunction* rfunc = overloadData.referenceFunction();
- s << endl << INDENT << cpythonFunctionName(rfunc) << "_TypeError:" << endl;
- Indentation indentation(INDENT);
- QString funcName = fullPythonFunctionName(rfunc);
-
- QString argsVar = pythonFunctionWrapperUsesListOfArguments(overloadData) ? "args" : PYTHON_ARG;
- if (verboseErrorMessagesDisabled()) {
- s << INDENT << "Shiboken::setErrorAboutWrongArguments(" << argsVar << ", \"" << funcName << "\", 0);" << endl;
- } else {
- QStringList overloadSignatures;
- foreach (const AbstractMetaFunction* f, overloadData.overloads()) {
- QStringList args;
- foreach(AbstractMetaArgument* arg, f->arguments()) {
- QString strArg;
- AbstractMetaType* argType = arg->type();
- if (isCString(argType)) {
- strArg = "\"SBK_STR_NAME\"";
- } else if (argType->isPrimitive()) {
- const PrimitiveTypeEntry* ptp = reinterpret_cast<const PrimitiveTypeEntry*>(argType->typeEntry());
- while (ptp->aliasedTypeEntry())
- ptp = ptp->aliasedTypeEntry();
- strArg = ptp->name();
- if (strArg == "QString") {
- strArg = "unicode";
- } else if (strArg == "QChar") {
- strArg = "1-unicode";
- } else {
- strArg = ptp->name().replace(QRegExp("^signed\\s+"), "");
- if (strArg == "double")
- strArg = "float";
- }
- } else if (argType->typeEntry()->isContainer()) {
- strArg = argType->fullName();
- if (strArg == "QList" || strArg == "QVector"
- || strArg == "QLinkedList" || strArg == "QStack"
- || strArg == "QQueue") {
- strArg = "list";
- } else if (strArg == "QMap" || strArg == "QHash"
- || strArg == "QMultiMap" || strArg == "QMultiHash") {
- strArg = "dict";
- } else if (strArg == "QPair") {
- strArg == "2-tuple";
- }
- } else {
- strArg = argType->fullName();
- if (strArg == "PyUnicode")
- strArg = "unicode";
- else if (strArg == "PyString")
- strArg = "str";
- else if (strArg == "PyBytes")
- strArg = "\"SBK_STR_NAME\"";
- else if (strArg == "PySequece")
- strArg = "list";
- else if (strArg == "PyTuple")
- strArg = "tuple";
- else if (strArg == "PyDict")
- strArg = "dict";
- else if (strArg == "PyObject")
- strArg = "object";
- else if (strArg == "PyCallable")
- strArg = "callable";
- else if (strArg == "uchar")
- strArg = "buffer"; // This depends on an inject code to be true, but if it's not true
- // the function wont work at all, so it must be true.
- }
- if (!arg->defaultValueExpression().isEmpty()) {
- strArg += " = ";
- if ((isCString(argType) || isPointerToWrapperType(argType))
- && arg->defaultValueExpression() == "0") {
- strArg += "None";
- } else {
- strArg += arg->defaultValueExpression().replace("::", ".").replace("\"", "\\\"");
- }
- }
- args << strArg;
- }
- overloadSignatures << "\""+args.join(", ")+"\"";
- }
- s << INDENT << "const char* overloads[] = {" << overloadSignatures.join(", ") << ", 0};" << endl;
- s << INDENT << "Shiboken::setErrorAboutWrongArguments(" << argsVar << ", \"" << funcName << "\", overloads);" << endl;
- }
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
-}
-
-void CppGenerator::writeFunctionReturnErrorCheckSection(QTextStream& s, bool hasReturnValue)
-{
- s << INDENT << "if (PyErr_Occurred()" << (hasReturnValue ? " || !" PYTHON_RETURN_VAR : "") << ") {" << endl;
- {
- Indentation indent(INDENT);
- if (hasReturnValue)
- s << INDENT << "Py_XDECREF(" PYTHON_RETURN_VAR ");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
- }
- s << INDENT << '}' << endl;
-}
-
-void CppGenerator::writeInvalidPyObjectCheck(QTextStream& s, const QString& pyObj)
-{
- s << INDENT << "if (!Shiboken::Object::isValid(" << pyObj << "))" << endl;
- Indentation indent(INDENT);
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
-}
-
-static QString pythonToCppConverterForArgumentName(const QString& argumentName)
-{
- static QRegExp pyArgsRegex(PYTHON_ARGS"(\\[\\d+[-]?\\d*\\])");
- pyArgsRegex.indexIn(argumentName);
- return QString(PYTHON_TO_CPP_VAR"%1").arg(pyArgsRegex.cap(1));
-}
-
-void CppGenerator::writeTypeCheck(QTextStream& s, const AbstractMetaType* argType, QString argumentName, bool isNumber, QString customType, bool rejectNull)
-{
- QString customCheck;
- if (!customType.isEmpty()) {
- AbstractMetaType* metaType;
- customCheck = guessCPythonCheckFunction(customType, &metaType);
- if (metaType)
- argType = metaType;
- }
-
- // TODO-CONVERTER: merge this with the code below.
- QString typeCheck;
- if (customCheck.isEmpty())
- typeCheck = cpythonIsConvertibleFunction(argType, argType->isEnum() ? false : isNumber);
- else
- typeCheck = customCheck;
- typeCheck.append(QString("(%1)").arg(argumentName));
-
- // TODO-CONVERTER -----------------------------------------------------------------------
- if (customCheck.isEmpty() && !argType->typeEntry()->isCustom()) {
- typeCheck = QString("(%1 = %2))").arg(pythonToCppConverterForArgumentName(argumentName)).arg(typeCheck);
- if (!isNumber && argType->typeEntry()->isCppPrimitive())
- typeCheck.prepend(QString("%1(%2) && ").arg(cpythonCheckFunction(argType)).arg(argumentName));
- }
- // TODO-CONVERTER -----------------------------------------------------------------------
-
- if (rejectNull)
- typeCheck = QString("(%1 != Py_None && %2)").arg(argumentName).arg(typeCheck);
-
- s << typeCheck;
-}
-
-static void checkTypeViability(const AbstractMetaFunction* func, const AbstractMetaType* type, int argIdx)
-{
- if (!type
- || !type->typeEntry()->isPrimitive()
- || type->indirections() == 0
- || ShibokenGenerator::isCString(type)
- || func->argumentRemoved(argIdx)
- || !func->typeReplaced(argIdx).isEmpty()
- || !func->conversionRule(TypeSystem::All, argIdx).isEmpty()
- || func->hasInjectedCode())
- return;
- QString prefix;
- if (func->ownerClass())
- prefix = QString("%1::").arg(func->ownerClass()->qualifiedCppName());
- ReportHandler::warning(QString("There's no user provided way (conversion rule, argument removal, custom code, etc) "
- "to handle the primitive %1 type '%2' in function '%3%4'.")
- .arg(argIdx == 0 ? "return" : "argument")
- .arg(type->cppSignature())
- .arg(prefix)
- .arg(func->signature()));
-}
-
-static void checkTypeViability(const AbstractMetaFunction* func)
-{
- if (func->isUserAdded())
- return;
- const AbstractMetaType* type = func->type();
- checkTypeViability(func, type, 0);
- for (int i = 0; i < func->arguments().count(); ++i)
- checkTypeViability(func, func->arguments().at(i)->type(), i + 1);
-}
-
-void CppGenerator::writeTypeCheck(QTextStream& s, const OverloadData* overloadData, QString argumentName)
-{
- QSet<const TypeEntry*> numericTypes;
-
- foreach (OverloadData* od, overloadData->previousOverloadData()->nextOverloadData()) {
- foreach (const AbstractMetaFunction* func, od->overloads()) {
- checkTypeViability(func);
- const AbstractMetaType* argType = od->argument(func)->type();
- if (!argType->isPrimitive())
- continue;
- if (ShibokenGenerator::isNumber(argType->typeEntry()))
- numericTypes << argType->typeEntry();
- }
- }
-
- // This condition trusts that the OverloadData object will arrange for
- // PyInt type to come after the more precise numeric types (e.g. float and bool)
- const AbstractMetaType* argType = overloadData->argType();
- bool numberType = numericTypes.count() == 1 || ShibokenGenerator::isPyInt(argType);
- QString customType = (overloadData->hasArgumentTypeReplace() ? overloadData->argumentTypeReplaced() : "");
- bool rejectNull = shouldRejectNullPointerArgument(overloadData->referenceFunction(), overloadData->argPos());
- writeTypeCheck(s, argType, argumentName, numberType, customType, rejectNull);
-}
-
-void CppGenerator::writeArgumentConversion(QTextStream& s,
- const AbstractMetaType* argType,
- const QString& argName, const QString& pyArgName,
- const AbstractMetaClass* context,
- const QString& defaultValue,
- bool castArgumentAsUnused)
-{
- if (argType->typeEntry()->isCustom() || argType->typeEntry()->isVarargs())
- return;
- if (isWrapperType(argType))
- writeInvalidPyObjectCheck(s, pyArgName);
- writePythonToCppTypeConversion(s, argType, pyArgName, argName, context, defaultValue);
- if (castArgumentAsUnused)
- writeUnusedVariableCast(s, argName);
-}
-
-const AbstractMetaType* CppGenerator::getArgumentType(const AbstractMetaFunction* func, int argPos)
-{
- if (argPos < 0 || argPos > func->arguments().size()) {
- ReportHandler::warning(QString("Argument index for function '%1' out of range.").arg(func->signature()));
- return 0;
- }
-
- const AbstractMetaType* argType = 0;
- QString typeReplaced = func->typeReplaced(argPos);
- if (typeReplaced.isEmpty())
- argType = (argPos == 0) ? func->type() : func->arguments().at(argPos-1)->type();
- else
- argType = buildAbstractMetaTypeFromString(typeReplaced);
- if (!argType && !m_knownPythonTypes.contains(typeReplaced)) {
- ReportHandler::warning(QString("Unknown type '%1' used as argument type replacement "\
- "in function '%2', the generated code may be broken.")
- .arg(typeReplaced)
- .arg(func->signature()));
- }
- return argType;
-}
-
-void CppGenerator::writePythonToCppTypeConversion(QTextStream& s,
- const AbstractMetaType* type,
- const QString& pyIn,
- const QString& cppOut,
- const AbstractMetaClass* context,
- const QString& defaultValue)
-{
- const TypeEntry* typeEntry = type->typeEntry();
- if (typeEntry->isCustom() || typeEntry->isVarargs())
- return;
-
- QString cppOutAux = QString("%1_local").arg(cppOut);
-
- bool treatAsPointer = isValueTypeWithCopyConstructorOnly(type);
- bool isPointerOrObjectType = (isObjectType(type) || isPointer(type)) && !isUserPrimitive(type) && !isCppPrimitive(type);
- bool isNotContainerEnumOrFlags = !typeEntry->isContainer() && !typeEntry->isEnum() && !typeEntry->isFlags();
- bool mayHaveImplicitConversion = type->isReference()
- && !isUserPrimitive(type)
- && !isCppPrimitive(type)
- && isNotContainerEnumOrFlags
- && !(treatAsPointer || isPointerOrObjectType);
- QString typeName = getFullTypeNameWithoutModifiers(type);
-
- bool isProtectedEnum = false;
-
- if (mayHaveImplicitConversion) {
- s << INDENT << typeName << ' ' << cppOutAux;
- writeMinimalConstructorExpression(s, type, defaultValue);
- s << ';' << endl;
- } else if (avoidProtectedHack() && type->typeEntry()->isEnum()) {
- const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(type);
- if (metaEnum && metaEnum->isProtected()) {
- typeName = "long";
- isProtectedEnum = true;
- }
- }
-
- s << INDENT << typeName;
- if (treatAsPointer || isPointerOrObjectType) {
- s << "* " << cppOut << (defaultValue.isEmpty() ? "" : QString(" = %1").arg(defaultValue));
- } else if (type->isReference() && !typeEntry->isPrimitive() && isNotContainerEnumOrFlags) {
- s << "* " << cppOut << " = &" << cppOutAux;
- } else {
- s << ' ' << cppOut;
- if (isProtectedEnum && avoidProtectedHack()) {
- s << " = ";
- if (defaultValue.isEmpty())
- s << "0";
- else
- s << "(long)" << defaultValue;
- } else if (isUserPrimitive(type) || typeEntry->isEnum() || typeEntry->isFlags()) {
- writeMinimalConstructorExpression(s, typeEntry, defaultValue);
- } else if (!type->isContainer()) {
- writeMinimalConstructorExpression(s, type, defaultValue);
- }
- }
- s << ';' << endl;
-
- QString pythonToCppFunc = pythonToCppConverterForArgumentName(pyIn);
-
- s << INDENT;
- if (!defaultValue.isEmpty())
- s << "if (" << pythonToCppFunc << ") ";
-
- QString pythonToCppCall = QString("%1(%2, &%3)").arg(pythonToCppFunc).arg(pyIn).arg(cppOut);
- if (!mayHaveImplicitConversion) {
- s << pythonToCppCall << ';' << endl;
- return;
- }
-
- if (!defaultValue.isEmpty())
- s << '{' << endl << INDENT;
-
- s << "if (Shiboken::Conversions::isImplicitConversion((SbkObjectType*)";
- s << cpythonTypeNameExt(type) << ", " << pythonToCppFunc << "))" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << pythonToCppFunc << '(' << pyIn << ", &" << cppOutAux << ");" << endl;
- }
- s << INDENT << "else" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << pythonToCppCall << ';' << endl;
- }
-
- if (!defaultValue.isEmpty())
- s << INDENT << '}';
- s << endl;
-}
-
-static void addConversionRuleCodeSnippet(CodeSnipList& snippetList, QString& rule,
- TypeSystem::Language conversionLanguage,
- TypeSystem::Language snippetLanguage,
- QString outputName = QString(),
- QString inputName = QString())
-{
- if (rule.isEmpty())
- return;
- if (snippetLanguage == TypeSystem::TargetLangCode) {
- rule.replace("%in", inputName);
- rule.replace("%out", QString("%1_out").arg(outputName));
- } else {
- rule.replace("%out", outputName);
- }
- CodeSnip snip(0, snippetLanguage);
- snip.position = (snippetLanguage == TypeSystem::NativeCode) ? CodeSnip::Any : CodeSnip::Beginning;
- snip.addCode(rule);
- snippetList << snip;
-}
-
-void CppGenerator::writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language)
-{
- CodeSnipList snippets;
- foreach (AbstractMetaArgument* arg, func->arguments()) {
- QString rule = func->conversionRule(language, arg->argumentIndex() + 1);
- addConversionRuleCodeSnippet(snippets, rule, language, TypeSystem::TargetLangCode,
- arg->name(), arg->name());
- }
- writeCodeSnips(s, snippets, CodeSnip::Beginning, TypeSystem::TargetLangCode, func);
-}
-
-void CppGenerator::writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language, const QString& outputVar)
-{
- CodeSnipList snippets;
- QString rule = func->conversionRule(language, 0);
- addConversionRuleCodeSnippet(snippets, rule, language, language, outputVar);
- writeCodeSnips(s, snippets, CodeSnip::Any, language, func);
-}
-
-void CppGenerator::writeNoneReturn(QTextStream& s, const AbstractMetaFunction* func, bool thereIsReturnValue)
-{
- if (thereIsReturnValue && (!func->type() || func->argumentRemoved(0)) && !injectedCodeHasReturnValueAttribution(func)) {
- s << INDENT << PYTHON_RETURN_VAR " = Py_None;" << endl;
- s << INDENT << "Py_INCREF(Py_None);" << endl;
- }
-}
-
-void CppGenerator::writeOverloadedFunctionDecisor(QTextStream& s, const OverloadData& overloadData)
-{
- s << INDENT << "// Overloaded function decisor" << endl;
- const AbstractMetaFunction* rfunc = overloadData.referenceFunction();
- QList<const AbstractMetaFunction*> functionOverloads = overloadData.overloadsWithoutRepetition();
- for (int i = 0; i < functionOverloads.count(); i++)
- s << INDENT << "// " << i << ": " << functionOverloads.at(i)->minimalSignature() << endl;
- writeOverloadedFunctionDecisorEngine(s, &overloadData);
- s << endl;
-
- // Ensure that the direct overload that called this reverse
- // is called.
- if (rfunc->isOperatorOverload() && !rfunc->isCallOperator()) {
- s << INDENT << "if (isReverse && overloadId == -1) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"reverse operator not implemented.\");" << endl;
- s << INDENT << "return 0;" << endl;
- }
- s << INDENT << "}" << endl << endl;
- }
-
- s << INDENT << "// Function signature not found." << endl;
- s << INDENT << "if (overloadId == -1) goto " << cpythonFunctionName(overloadData.referenceFunction()) << "_TypeError;" << endl;
- s << endl;
-}
-
-void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const OverloadData* parentOverloadData)
-{
- bool hasDefaultCall = parentOverloadData->nextArgumentHasDefaultValue();
- const AbstractMetaFunction* referenceFunction = parentOverloadData->referenceFunction();
-
- // If the next argument has not an argument with a default value, it is still possible
- // that one of the overloads for the current overload data has its final occurrence here.
- // If found, the final occurrence of a method is attributed to the referenceFunction
- // variable to be used further on this method on the conditional that identifies default
- // method calls.
- if (!hasDefaultCall) {
- foreach (const AbstractMetaFunction* func, parentOverloadData->overloads()) {
- if (parentOverloadData->isFinalOccurrence(func)) {
- referenceFunction = func;
- hasDefaultCall = true;
- break;
- }
- }
- }
-
- int maxArgs = parentOverloadData->maxArgs();
- // Python constructors always receive multiple arguments.
- bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(*parentOverloadData);
-
- // Functions without arguments are identified right away.
- if (maxArgs == 0) {
- s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(referenceFunction);
- s << "; // " << referenceFunction->minimalSignature() << endl;
- return;
-
- // To decide if a method call is possible at this point the current overload
- // data object cannot be the head, since it is just an entry point, or a root,
- // for the tree of arguments and it does not represent a valid method call.
- } else if (!parentOverloadData->isHeadOverloadData()) {
- bool isLastArgument = parentOverloadData->nextOverloadData().isEmpty();
- bool signatureFound = parentOverloadData->overloads().size() == 1;
-
- // The current overload data describes the last argument of a signature,
- // so the method can be identified right now.
- if (isLastArgument || (signatureFound && !hasDefaultCall)) {
- const AbstractMetaFunction* func = parentOverloadData->referenceFunction();
- s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func);
- s << "; // " << func->minimalSignature() << endl;
- return;
- }
- }
-
- bool isFirst = true;
-
- // If the next argument has a default value the decisor can perform a method call;
- // it just need to check if the number of arguments received from Python are equal
- // to the number of parameters preceding the argument with the default value.
- if (hasDefaultCall) {
- isFirst = false;
- int numArgs = parentOverloadData->argPos() + 1;
- s << INDENT << "if (numArgs == " << numArgs << ") {" << endl;
- {
- Indentation indent(INDENT);
- const AbstractMetaFunction* func = referenceFunction;
- foreach (OverloadData* overloadData, parentOverloadData->nextOverloadData()) {
- const AbstractMetaFunction* defValFunc = overloadData->getFunctionWithDefaultValue();
- if (defValFunc) {
- func = defValFunc;
- break;
- }
- }
- s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func);
- s << "; // " << func->minimalSignature() << endl;
- }
- s << INDENT << '}';
- }
-
- foreach (OverloadData* overloadData, parentOverloadData->nextOverloadData()) {
- bool signatureFound = overloadData->overloads().size() == 1
- && !overloadData->getFunctionWithDefaultValue()
- && !overloadData->findNextArgWithDefault();
-
- const AbstractMetaFunction* refFunc = overloadData->referenceFunction();
-
- QStringList typeChecks;
- QString pyArgName = (usePyArgs && maxArgs > 1) ? QString(PYTHON_ARGS "[%1]").arg(overloadData->argPos()) : PYTHON_ARG;
- OverloadData* od = overloadData;
- int startArg = od->argPos();
- int sequenceArgCount = 0;
- while (od && !od->argType()->isVarargs()) {
- bool typeReplacedByPyObject = od->argumentTypeReplaced() == "PyObject";
- if (!typeReplacedByPyObject) {
- if (usePyArgs)
- pyArgName = QString(PYTHON_ARGS "[%1]").arg(od->argPos());
- QString typeCheck;
- QTextStream tck(&typeCheck);
- const AbstractMetaFunction* func = od->referenceFunction();
-
- if (func->isConstructor() && func->arguments().count() == 1) {
- const AbstractMetaClass* ownerClass = func->ownerClass();
- const ComplexTypeEntry* baseContainerType = ownerClass->typeEntry()->baseContainerType();
- if (baseContainerType && baseContainerType == func->arguments().first()->type()->typeEntry() && isCopyable(ownerClass)) {
- tck << '!' << cpythonCheckFunction(ownerClass->typeEntry()) << pyArgName << ')' << endl;
- Indentation indent(INDENT);
- tck << INDENT << "&& ";
- }
- }
- writeTypeCheck(tck, od, pyArgName);
- typeChecks << typeCheck;
- }
-
- sequenceArgCount++;
-
- if (od->nextOverloadData().isEmpty()
- || od->nextArgumentHasDefaultValue()
- || od->nextOverloadData().size() != 1
- || od->overloads().size() != od->nextOverloadData().first()->overloads().size()) {
- overloadData = od;
- od = 0;
- } else {
- od = od->nextOverloadData().first();
- }
- }
-
- if (usePyArgs && signatureFound) {
- AbstractMetaArgumentList args = refFunc->arguments();
- int lastArgIsVarargs = (int) (args.size() > 1 && args.last()->type()->isVarargs());
- int numArgs = args.size() - OverloadData::numberOfRemovedArguments(refFunc) - lastArgIsVarargs;
- typeChecks.prepend(QString("numArgs %1 %2").arg(lastArgIsVarargs ? ">=" : "==").arg(numArgs));
- } else if (sequenceArgCount > 1) {
- typeChecks.prepend(QString("numArgs >= %1").arg(startArg + sequenceArgCount));
- } else if (refFunc->isOperatorOverload() && !refFunc->isCallOperator()) {
- typeChecks.prepend(QString("%1isReverse").arg(refFunc->isReverseOperator() ? "" : "!"));
- }
-
- if (isFirst) {
- isFirst = false;
- s << INDENT;
- } else {
- s << " else ";
- }
- s << "if (";
- if (typeChecks.isEmpty()) {
- s << "true";
- } else {
- Indentation indent(INDENT);
- QString separator;
- QTextStream sep(&separator);
- sep << endl << INDENT << "&& ";
- s << typeChecks.join(separator);
- }
- s << ") {" << endl;
- {
- Indentation indent(INDENT);
- writeOverloadedFunctionDecisorEngine(s, overloadData);
- }
- s << INDENT << "}";
- }
- s << endl;
-}
-
-void CppGenerator::writeFunctionCalls(QTextStream& s, const OverloadData& overloadData)
-{
- QList<const AbstractMetaFunction*> overloads = overloadData.overloadsWithoutRepetition();
- s << INDENT << "// Call function/method" << endl;
- s << INDENT << (overloads.count() > 1 ? "switch (overloadId) " : "") << '{' << endl;
- {
- Indentation indent(INDENT);
- if (overloads.count() == 1) {
- writeSingleFunctionCall(s, overloadData, overloads.first());
- } else {
- for (int i = 0; i < overloads.count(); i++) {
- const AbstractMetaFunction* func = overloads.at(i);
- s << INDENT << "case " << i << ": // " << func->signature() << endl;
- s << INDENT << '{' << endl;
- {
- Indentation indent(INDENT);
- writeSingleFunctionCall(s, overloadData, func);
- s << INDENT << "break;" << endl;
- }
- s << INDENT << '}' << endl;
- }
- }
- }
- s << INDENT << '}' << endl;
-}
-
-void CppGenerator::writeSingleFunctionCall(QTextStream& s, const OverloadData& overloadData, const AbstractMetaFunction* func)
-{
- if (func->isDeprecated()) {
- s << INDENT << "Shiboken::warning(PyExc_DeprecationWarning, 1, \"Function: '"
- << func->signature().replace("::", ".")
- << "' is marked as deprecated, please check the documentation for more information.\");" << endl;
- }
-
- if (func->functionType() == AbstractMetaFunction::EmptyFunction) {
- s << INDENT << "PyErr_Format(PyExc_TypeError, \"%s is a private method.\", \"" << func->signature().replace("::", ".") << "\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
- return;
- }
-
- bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(overloadData);
-
- // Handle named arguments.
- writeNamedArgumentResolution(s, func, usePyArgs);
-
- bool injectCodeCallsFunc = injectedCodeCallsCppFunction(func);
- bool mayHaveUnunsedArguments = !func->isUserAdded() && func->hasInjectedCode() && injectCodeCallsFunc;
- int removedArgs = 0;
- for (int argIdx = 0; argIdx < func->arguments().count(); ++argIdx) {
- bool hasConversionRule = !func->conversionRule(TypeSystem::NativeCode, argIdx + 1).isEmpty();
- const AbstractMetaArgument* arg = func->arguments().at(argIdx);
- if (func->argumentRemoved(argIdx + 1)) {
- if (!arg->defaultValueExpression().isEmpty()) {
- QString cppArgRemoved = QString(CPP_ARG_REMOVED"%1").arg(argIdx);
- s << INDENT << getFullTypeName(arg->type()) << ' ' << cppArgRemoved;
- s << " = " << guessScopeForDefaultValue(func, arg) << ';' << endl;
- writeUnusedVariableCast(s, cppArgRemoved);
- } else if (!injectCodeCallsFunc && !func->isUserAdded() && !hasConversionRule) {
- // When an argument is removed from a method signature and no other means of calling
- // the method are provided (as with code injection) the generator must abort.
- qFatal(qPrintable(QString("No way to call '%1::%2' with the modifications described in the type system.")
- .arg(func->ownerClass()->name())
- .arg(func->signature())), NULL);
- }
- removedArgs++;
- continue;
- }
- if (hasConversionRule)
- continue;
- const AbstractMetaType* argType = getArgumentType(func, argIdx + 1);
- if (!argType || (mayHaveUnunsedArguments && !injectedCodeUsesArgument(func, argIdx)))
- continue;
- int argPos = argIdx - removedArgs;
- QString argName = QString(CPP_ARG"%1").arg(argPos);
- QString pyArgName = usePyArgs ? QString(PYTHON_ARGS "[%1]").arg(argPos) : PYTHON_ARG;
- QString defaultValue = guessScopeForDefaultValue(func, arg);
- writeArgumentConversion(s, argType, argName, pyArgName, func->implementingClass(), defaultValue, func->isUserAdded());
- }
-
- s << endl;
-
- int numRemovedArgs = OverloadData::numberOfRemovedArguments(func);
-
- s << INDENT << "if (!PyErr_Occurred()) {" << endl;
- {
- Indentation indentation(INDENT);
- writeMethodCall(s, func, func->arguments().size() - numRemovedArgs);
- if (!func->isConstructor())
- writeNoneReturn(s, func, overloadData.hasNonVoidReturnType());
- }
- s << INDENT << '}' << endl;
-}
-
-QString CppGenerator::cppToPythonFunctionName(const QString& sourceTypeName, QString targetTypeName)
-{
- if (targetTypeName.isEmpty())
- targetTypeName = sourceTypeName;
- return QString("%1_CppToPython_%2").arg(sourceTypeName).arg(targetTypeName);
-}
-
-QString CppGenerator::pythonToCppFunctionName(const QString& sourceTypeName, const QString& targetTypeName)
-{
- return QString("%1_PythonToCpp_%2").arg(sourceTypeName).arg(targetTypeName);
-}
-QString CppGenerator::pythonToCppFunctionName(const AbstractMetaType* sourceType, const AbstractMetaType* targetType)
-{
- return pythonToCppFunctionName(fixedCppTypeName(sourceType), fixedCppTypeName(targetType));
-}
-QString CppGenerator::pythonToCppFunctionName(const CustomConversion::TargetToNativeConversion* toNative,
- const TypeEntry* targetType)
-{
- return pythonToCppFunctionName(fixedCppTypeName(toNative), fixedCppTypeName(targetType));
-}
-
-QString CppGenerator::convertibleToCppFunctionName(const QString& sourceTypeName, const QString& targetTypeName)
-{
- return QString("is_%1_PythonToCpp_%2_Convertible").arg(sourceTypeName).arg(targetTypeName);
-}
-QString CppGenerator::convertibleToCppFunctionName(const AbstractMetaType* sourceType, const AbstractMetaType* targetType)
-{
- return convertibleToCppFunctionName(fixedCppTypeName(sourceType), fixedCppTypeName(targetType));
-}
-QString CppGenerator::convertibleToCppFunctionName(const CustomConversion::TargetToNativeConversion* toNative,
- const TypeEntry* targetType)
-{
- return convertibleToCppFunctionName(fixedCppTypeName(toNative), fixedCppTypeName(targetType));
-}
-
-void CppGenerator::writeCppToPythonFunction(QTextStream& s, const QString& code, const QString& sourceTypeName, QString targetTypeName)
-{
- QString prettyCode;
- QTextStream c(&prettyCode);
- formatCode(c, code, INDENT);
- processCodeSnip(prettyCode);
-
- s << "static PyObject* " << cppToPythonFunctionName(sourceTypeName, targetTypeName);
- s << "(const void* cppIn) {" << endl;
- s << prettyCode;
- s << '}' << endl;
-}
-
-static void replaceCppToPythonVariables(QString& code, const QString& typeName)
-{
- code.prepend(QString("%1& cppInRef = *((%1*)cppIn);\n").arg(typeName));
- code.replace("%INTYPE", typeName);
- code.replace("%OUTTYPE", "PyObject*");
- code.replace("%in", "cppInRef");
- code.replace("%out", "pyOut");
-}
-void CppGenerator::writeCppToPythonFunction(QTextStream& s, const CustomConversion* customConversion)
-{
- QString code = customConversion->nativeToTargetConversion();
- replaceCppToPythonVariables(code, getFullTypeName(customConversion->ownerType()));
- writeCppToPythonFunction(s, code, fixedCppTypeName(customConversion->ownerType()));
-}
-void CppGenerator::writeCppToPythonFunction(QTextStream& s, const AbstractMetaType* containerType)
-{
- const CustomConversion* customConversion = containerType->typeEntry()->customConversion();
- if (!customConversion) {
- qFatal(qPrintable(QString("Can't write the C++ to Python conversion function for container type '%1' - "\
- "no conversion rule was defined for it in the type system.")
- .arg(containerType->typeEntry()->qualifiedCppName())), NULL);
- }
- if (!containerType->typeEntry()->isContainer()) {
- writeCppToPythonFunction(s, customConversion);
- return;
- }
- QString code = customConversion->nativeToTargetConversion();
- for (int i = 0; i < containerType->instantiations().count(); ++i)
- code.replace(QString("%INTYPE_%1").arg(i), getFullTypeName(containerType->instantiations().at(i)));
- replaceCppToPythonVariables(code, getFullTypeNameWithoutModifiers(containerType));
- processCodeSnip(code);
- writeCppToPythonFunction(s, code, fixedCppTypeName(containerType));
-}
-
-void CppGenerator::writePythonToCppFunction(QTextStream& s, const QString& code, const QString& sourceTypeName, const QString& targetTypeName)
-{
- QString prettyCode;
- QTextStream c(&prettyCode);
- formatCode(c, code, INDENT);
- processCodeSnip(prettyCode);
- s << "static void " << pythonToCppFunctionName(sourceTypeName, targetTypeName);
- s << "(PyObject* pyIn, void* cppOut) {" << endl;
- s << prettyCode;
- s << '}' << endl;
-}
-
-void CppGenerator::writeIsPythonConvertibleToCppFunction(QTextStream& s,
- const QString& sourceTypeName,
- const QString& targetTypeName,
- const QString& condition,
- QString pythonToCppFuncName,
- bool acceptNoneAsCppNull)
-{
- if (pythonToCppFuncName.isEmpty())
- pythonToCppFuncName = pythonToCppFunctionName(sourceTypeName, targetTypeName);
-
- s << "static PythonToCppFunc " << convertibleToCppFunctionName(sourceTypeName, targetTypeName);
- s << "(PyObject* pyIn) {" << endl;
- if (acceptNoneAsCppNull) {
- s << INDENT << "if (pyIn == Py_None)" << endl;
- Indentation indent(INDENT);
- s << INDENT << "return Shiboken::Conversions::nonePythonToCppNullPtr;" << endl;
- }
- s << INDENT << "if (" << condition << ')' << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "return " << pythonToCppFuncName << ';' << endl;
- }
- s << INDENT << "return 0;" << endl;
- s << '}' << endl;
-}
-
-void CppGenerator::writePythonToCppConversionFunctions(QTextStream& s,
- const AbstractMetaType* sourceType,
- const AbstractMetaType* targetType,
- QString typeCheck,
- QString conversion,
- QString preConversion)
-{
- QString sourcePyType = cpythonTypeNameExt(sourceType);
-
- // Python to C++ conversion function.
- QString code;
- QTextStream c(&code);
- if (conversion.isEmpty())
- conversion = QString("*%1").arg(cpythonWrapperCPtr(sourceType->typeEntry(), "pyIn"));
- if (!preConversion.isEmpty())
- c << INDENT << preConversion << endl;
- c << INDENT << QString("*((%1*)cppOut) = %1(%2);")
- .arg(getFullTypeName(targetType->typeEntry()))
- .arg(conversion);
- QString sourceTypeName = fixedCppTypeName(sourceType);
- QString targetTypeName = fixedCppTypeName(targetType);
- writePythonToCppFunction(s, code, sourceTypeName, targetTypeName);
-
- // Python to C++ convertible check function.
- if (typeCheck.isEmpty())
- typeCheck = QString("PyObject_TypeCheck(pyIn, %1)").arg(sourcePyType);
- writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, typeCheck);
- s << endl;
-}
-
-void CppGenerator::writePythonToCppConversionFunctions(QTextStream& s,
- const CustomConversion::TargetToNativeConversion* toNative,
- const TypeEntry* targetType)
-{
- // Python to C++ conversion function.
- QString code = toNative->conversion();
- QString inType;
- if (toNative->sourceType())
- inType = cpythonTypeNameExt(toNative->sourceType());
- else
- inType = QString("(&%1_Type)").arg(toNative->sourceTypeName());
- code.replace("%INTYPE", inType);
- code.replace("%OUTTYPE", targetType->qualifiedCppName());
- code.replace("%in", "pyIn");
- code.replace("%out", QString("*((%1*)cppOut)").arg(getFullTypeName(targetType)));
-
- QString sourceTypeName = fixedCppTypeName(toNative);
- QString targetTypeName = fixedCppTypeName(targetType);
- writePythonToCppFunction(s, code, sourceTypeName, targetTypeName);
-
- // Python to C++ convertible check function.
- QString typeCheck = toNative->sourceTypeCheck();
- if (typeCheck.isEmpty()) {
- QString pyTypeName = toNative->sourceTypeName();
- if (pyTypeName == "Py_None" || pyTypeName == "PyNone")
- typeCheck = "%in == Py_None";
- else if (pyTypeName == "SbkEnumType")
- typeCheck = "Shiboken::isShibokenEnum(%in)";
- else if (pyTypeName == "SbkObject")
- typeCheck = "Shiboken::Object::checkType(%in)";
- else if (pyTypeName == "PyTypeObject")
- typeCheck = "PyType_Check(%in)";
- else if (pyTypeName == "PyObject")
- typeCheck = "PyObject_TypeCheck(%in, &PyBaseObject_Type)";
- else if (pyTypeName.startsWith("Py"))
- typeCheck= QString("%1_Check(%in)").arg(pyTypeName);
- }
- if (typeCheck.isEmpty()) {
- if (!toNative->sourceType() || toNative->sourceType()->isPrimitive()) {
- qFatal(qPrintable(QString("User added implicit conversion for C++ type '%1' must provide either an input "\
- "type check function or a non primitive type entry.")
- .arg(targetType->qualifiedCppName())), NULL);
-
- }
- typeCheck = QString("PyObject_TypeCheck(%in, %1)").arg(cpythonTypeNameExt(toNative->sourceType()));
- }
- typeCheck.replace("%in", "pyIn");
- processCodeSnip(typeCheck);
- writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, typeCheck);
-}
-
-void CppGenerator::writePythonToCppConversionFunctions(QTextStream& s, const AbstractMetaType* containerType)
-{
- const CustomConversion* customConversion = containerType->typeEntry()->customConversion();
- if (!customConversion) {
- //qFatal
- return;
- }
- const CustomConversion::TargetToNativeConversions& toCppConversions = customConversion->targetToNativeConversions();
- if (toCppConversions.isEmpty()) {
- //qFatal
- return;
- }
- // Python to C++ conversion function.
- QString cppTypeName = getFullTypeNameWithoutModifiers(containerType);
- QString code;
- QTextStream c(&code);
- c << INDENT << QString("%1& cppOutRef = *((%1*)cppOut);").arg(cppTypeName) << endl;
- code.append(toCppConversions.first()->conversion());
- for (int i = 0; i < containerType->instantiations().count(); ++i) {
- const AbstractMetaType* type = containerType->instantiations().at(i);
- QString typeName = getFullTypeName(type);
- if (type->isValue() && isValueTypeWithCopyConstructorOnly(type)) {
- static QRegExp regex(CONVERTTOCPP_REGEX);
- int pos = 0;
- while ((pos = regex.indexIn(code, pos)) != -1) {
- pos += regex.matchedLength();
- QStringList list = regex.capturedTexts();
- QString varName = list.at(1);
- QString leftCode = code.left(pos);
- QString rightCode = code.mid(pos);
- rightCode.replace(varName, "*"+varName);
- code = leftCode + rightCode;
- }
- typeName.append('*');
- }
- code.replace(QString("%OUTTYPE_%1").arg(i), typeName);
- }
- code.replace("%OUTTYPE", cppTypeName);
- code.replace("%in", "pyIn");
- code.replace("%out", "cppOutRef");
- QString typeName = fixedCppTypeName(containerType);
- writePythonToCppFunction(s, code, typeName, typeName);
-
- // Python to C++ convertible check function.
- QString typeCheck = cpythonCheckFunction(containerType);
- if (typeCheck.isEmpty())
- typeCheck = "false";
- else
- typeCheck = QString("%1pyIn)").arg(typeCheck);
- writeIsPythonConvertibleToCppFunction(s, typeName, typeName, typeCheck);
- s << endl;
-}
-
-void CppGenerator::writeAddPythonToCppConversion(QTextStream& s, const QString& converterVar, const QString& pythonToCppFunc, const QString& isConvertibleFunc)
-{
- s << INDENT << "Shiboken::Conversions::addPythonToCppValueConversion(" << converterVar << ',' << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << pythonToCppFunc << ',' << endl;
- s << INDENT << isConvertibleFunc;
- }
- s << ");" << endl;
-}
-
-void CppGenerator::writeNamedArgumentResolution(QTextStream& s, const AbstractMetaFunction* func, bool usePyArgs)
-{
- AbstractMetaArgumentList args = OverloadData::getArgumentsWithDefaultValues(func);
- if (args.isEmpty())
- return;
-
- QString pyErrString("PyErr_SetString(PyExc_TypeError, \"" + fullPythonFunctionName(func)
- + "(): got multiple values for keyword argument '%1'.\");");
-
- s << INDENT << "if (kwds) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyObject* ";
- foreach (const AbstractMetaArgument* arg, args) {
- int pyArgIndex = arg->argumentIndex() - OverloadData::numberOfRemovedArguments(func, arg->argumentIndex());
- QString pyArgName = usePyArgs ? QString(PYTHON_ARGS "[%1]").arg(pyArgIndex) : PYTHON_ARG;
- s << "value = PyDict_GetItemString(kwds, \"" << arg->name() << "\");" << endl;
- s << INDENT << "if (value && " << pyArgName << ") {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << pyErrString.arg(arg->name()) << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
- }
- s << INDENT << "} else if (value) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << pyArgName << " = value;" << endl;
- s << INDENT << "if (!";
- writeTypeCheck(s, arg->type(), pyArgName, isNumber(arg->type()->typeEntry()), func->typeReplaced(arg->argumentIndex() + 1));
- s << ')' << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "goto " << cpythonFunctionName(func) << "_TypeError;" << endl;
- }
- }
- s << INDENT << '}' << endl;
- if (arg != args.last())
- s << INDENT;
- }
- }
- s << INDENT << '}' << endl;
-}
-
-QString CppGenerator::argumentNameFromIndex(const AbstractMetaFunction* func, int argIndex, const AbstractMetaClass** wrappedClass)
-{
- *wrappedClass = 0;
- QString pyArgName;
- if (argIndex == -1) {
- pyArgName = QString(PYTHON_SELF_VAR);
- *wrappedClass = func->implementingClass();
- } else if (argIndex == 0) {
- AbstractMetaType* returnType = getTypeWithoutContainer(func->type());
- if (returnType) {
- pyArgName = PYTHON_RETURN_VAR;
- *wrappedClass = classes().findClass(returnType->typeEntry()->name());
- } else {
- ReportHandler::warning("Invalid Argument index on function modification: " + func->name());
- }
- } else {
- int realIndex = argIndex - 1 - OverloadData::numberOfRemovedArguments(func, argIndex - 1);
- AbstractMetaType* argType = getTypeWithoutContainer(func->arguments().at(realIndex)->type());
-
- if (argType) {
- *wrappedClass = classes().findClass(argType->typeEntry()->name());
- if (argIndex == 1
- && !func->isConstructor()
- && OverloadData::isSingleArgument(getFunctionGroups(func->implementingClass())[func->name()]))
- pyArgName = QString(PYTHON_ARG);
- else
- pyArgName = QString(PYTHON_ARGS "[%1]").arg(argIndex - 1);
- }
- }
- return pyArgName;
-}
-
-void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* func, int maxArgs)
-{
- s << INDENT << "// " << func->minimalSignature() << (func->isReverseOperator() ? " [reverse operator]": "") << endl;
- if (func->isConstructor()) {
- foreach (CodeSnip cs, func->injectedCodeSnips()) {
- if (cs.position == CodeSnip::End) {
- s << INDENT << "overloadId = " << func->ownerClass()->functions().indexOf(const_cast<AbstractMetaFunction* const>(func)) << ';' << endl;
- break;
- }
- }
- }
-
- if (func->isAbstract()) {
- s << INDENT << "if (Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR "))) {\n";
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '";
- s << func->ownerClass()->name() << '.' << func->name() << "()' not implemented.\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
- }
- s << INDENT << "}\n";
- }
-
- // Used to provide contextual information to custom code writer function.
- const AbstractMetaArgument* lastArg = 0;
-
- CodeSnipList snips;
- if (func->hasInjectedCode()) {
- snips = func->injectedCodeSnips();
-
- // Find the last argument available in the method call to provide
- // the injected code writer with information to avoid invalid replacements
- // on the %# variable.
- if (maxArgs > 0 && maxArgs < func->arguments().size() - OverloadData::numberOfRemovedArguments(func)) {
- int removedArgs = 0;
- for (int i = 0; i < maxArgs + removedArgs; i++) {
- lastArg = func->arguments().at(i);
- if (func->argumentRemoved(i + 1))
- removedArgs++;
- }
- } else if (maxArgs != 0 && !func->arguments().isEmpty()) {
- lastArg = func->arguments().last();
- }
-
- writeCodeSnips(s, snips, CodeSnip::Beginning, TypeSystem::TargetLangCode, func, lastArg);
- s << endl;
- }
-
- writeConversionRule(s, func, TypeSystem::NativeCode);
-
- if (!func->isUserAdded()) {
- QStringList userArgs;
- if (!func->isCopyConstructor()) {
- int removedArgs = 0;
- for (int i = 0; i < maxArgs + removedArgs; i++) {
- const AbstractMetaArgument* arg = func->arguments().at(i);
- bool hasConversionRule = !func->conversionRule(TypeSystem::NativeCode, arg->argumentIndex() + 1).isEmpty();
- if (func->argumentRemoved(i + 1)) {
- // If some argument with default value is removed from a
- // method signature, the said value must be explicitly
- // added to the method call.
- removedArgs++;
-
- // If have conversion rules I will use this for removed args
- if (hasConversionRule)
- userArgs << QString("%1"CONV_RULE_OUT_VAR_SUFFIX).arg(arg->name());
- else if (!arg->defaultValueExpression().isEmpty())
- userArgs << QString(CPP_ARG_REMOVED"%1").arg(i);
- } else {
- int idx = arg->argumentIndex() - removedArgs;
- bool deRef = isValueTypeWithCopyConstructorOnly(arg->type())
- || isObjectTypeUsedAsValueType(arg->type())
- || (arg->type()->isReference() && isWrapperType(arg->type()) && !isPointer(arg->type()));
- QString argName = hasConversionRule
- ? QString("%1"CONV_RULE_OUT_VAR_SUFFIX).arg(arg->name())
- : QString("%1"CPP_ARG"%2").arg(deRef ? "*" : "").arg(idx);
- userArgs << argName;
- }
- }
-
- // If any argument's default value was modified the method must be called
- // with this new value whenever the user doesn't pass an explicit value to it.
- // Also, any unmodified default value coming after the last user specified
- // argument and before the modified argument must be explicitly stated.
- QStringList otherArgs;
- bool otherArgsModified = false;
- bool argsClear = true;
- for (int i = func->arguments().size() - 1; i >= maxArgs + removedArgs; i--) {
- const AbstractMetaArgument* arg = func->arguments().at(i);
- bool defValModified = arg->defaultValueExpression() != arg->originalDefaultValueExpression();
- bool hasConversionRule = !func->conversionRule(TypeSystem::NativeCode, arg->argumentIndex() + 1).isEmpty();
- if (argsClear && !defValModified && !hasConversionRule)
- continue;
- else
- argsClear = false;
- otherArgsModified |= defValModified || hasConversionRule || func->argumentRemoved(i + 1);
- if (hasConversionRule)
- otherArgs.prepend(QString("%1"CONV_RULE_OUT_VAR_SUFFIX).arg(arg->name()));
- else
- otherArgs.prepend(QString(CPP_ARG_REMOVED"%1").arg(i));
- }
- if (otherArgsModified)
- userArgs << otherArgs;
- }
-
- bool isCtor = false;
- QString methodCall;
- QTextStream mc(&methodCall);
- QString useVAddr;
- QTextStream uva(&useVAddr);
- if (func->isOperatorOverload() && !func->isCallOperator()) {
- QString firstArg("(*" CPP_SELF_VAR ")");
- if (func->isPointerOperator())
- firstArg.remove(1, 1); // remove the de-reference operator
-
- QString secondArg(CPP_ARG0);
- if (!func->isUnaryOperator() && shouldDereferenceArgumentPointer(func->arguments().first())) {
- secondArg.prepend("(*");
- secondArg.append(')');
- }
-
- if (func->isUnaryOperator())
- std::swap(firstArg, secondArg);
-
- QString op = func->originalName();
- op = op.right(op.size() - (sizeof("operator")/sizeof(char)-1));
-
- if (func->isBinaryOperator()) {
- if (func->isReverseOperator())
- std::swap(firstArg, secondArg);
-
- if (((op == "++") || (op == "--")) && !func->isReverseOperator()) {
- s << endl << INDENT << "for(int i=0; i < " << secondArg << "; i++, " << firstArg << op << ");" << endl;
- mc << firstArg;
- } else {
- mc << firstArg << ' ' << op << ' ' << secondArg;
- }
- } else {
- mc << op << ' ' << secondArg;
- }
- } else if (!injectedCodeCallsCppFunction(func)) {
- if (func->isConstructor() || func->isCopyConstructor()) {
- isCtor = true;
- QString className = wrapperName(func->ownerClass());
-
- if (func->isCopyConstructor() && maxArgs == 1) {
- mc << "new ::" << className << "(*" << CPP_ARG0 << ')';
- } else {
- QString ctorCall = className + '(' + userArgs.join(", ") + ')';
- if (usePySideExtensions() && func->ownerClass()->isQObject()) {
- s << INDENT << "void* addr = PySide::nextQObjectMemoryAddr();" << endl;
- uva << "if (addr) {" << endl;
- {
- Indentation indent(INDENT);
-
- uva << INDENT << "cptr = " << "new (addr) ::"
- << ctorCall << ';' << endl
- << INDENT
- << "PySide::setNextQObjectMemoryAddr(0);"
- << endl;
- }
- uva << INDENT << "} else {" << endl;
- {
- Indentation indent(INDENT);
-
- uva << INDENT << "cptr = " << "new ::"
- << ctorCall << ';' << endl;
- }
- uva << INDENT << "}" << endl;
- } else {
- mc << "new ::" << ctorCall;
- }
- }
- } else {
- if (func->ownerClass()) {
- if (!avoidProtectedHack() || !func->isProtected()) {
- if (func->isStatic()) {
- mc << "::" << func->ownerClass()->qualifiedCppName() << "::";
- } else {
- if (func->isConstant()) {
- if (avoidProtectedHack()) {
- mc << "const_cast<const ::";
- if (func->ownerClass()->hasProtectedMembers())
- mc << wrapperName(func->ownerClass());
- else
- mc << func->ownerClass()->qualifiedCppName();
- mc << "*>(" CPP_SELF_VAR ")->";
- } else {
- mc << "const_cast<const ::" << func->ownerClass()->qualifiedCppName();
- mc << "*>(" CPP_SELF_VAR ")->";
- }
- } else {
- mc << CPP_SELF_VAR "->";
- }
- }
-
- if (!func->isAbstract() && func->isVirtual())
- mc << "::%CLASS_NAME::";
-
- mc << func->originalName();
- } else {
- if (!func->isStatic())
- mc << "((::" << wrapperName(func->ownerClass()) << "*) " << CPP_SELF_VAR << ")->";
-
- if (!func->isAbstract())
- mc << (func->isProtected() ? wrapperName(func->ownerClass()) : "::" + func->ownerClass()->qualifiedCppName()) << "::";
- mc << func->originalName() << "_protected";
- }
- } else {
- mc << func->originalName();
- }
- mc << '(' << userArgs.join(", ") << ')';
- if (!func->isAbstract() && func->isVirtual()) {
- mc.flush();
- if (!avoidProtectedHack() || !func->isProtected()) {
- QString virtualCall(methodCall);
- QString normalCall(methodCall);
- virtualCall = virtualCall.replace("%CLASS_NAME", func->ownerClass()->qualifiedCppName());
- normalCall = normalCall.replace("::%CLASS_NAME::", "");
- methodCall = "";
- mc << "Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR ")) ? ";
- mc << virtualCall << " : " << normalCall;
- }
- }
- }
- }
-
- if (!injectedCodeCallsCppFunction(func)) {
- s << INDENT << BEGIN_ALLOW_THREADS << endl << INDENT;
- if (isCtor) {
- s << (useVAddr.isEmpty() ?
- QString("cptr = %1;").arg(methodCall) : useVAddr) << endl;
- } else if (func->type() && !func->isInplaceOperator()) {
- bool writeReturnType = true;
- if (avoidProtectedHack()) {
- const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(func->type());
- if (metaEnum) {
- QString enumName;
- if (metaEnum->isProtected())
- enumName = protectedEnumSurrogateName(metaEnum);
- else
- enumName = func->type()->cppSignature();
- methodCall.prepend(enumName + '(');
- methodCall.append(')');
- s << enumName;
- writeReturnType = false;
- }
- }
- if (writeReturnType) {
- s << func->type()->cppSignature();
- if (isObjectTypeUsedAsValueType(func->type())) {
- s << '*';
- methodCall.prepend(QString("new %1(").arg(func->type()->typeEntry()->qualifiedCppName()));
- methodCall.append(')');
- }
- }
- s << " " CPP_RETURN_VAR " = ";
- s << methodCall << ';' << endl;
- } else {
- s << methodCall << ';' << endl;
- }
- s << INDENT << END_ALLOW_THREADS << endl;
-
- if (!func->conversionRule(TypeSystem::TargetLangCode, 0).isEmpty()) {
- writeConversionRule(s, func, TypeSystem::TargetLangCode, PYTHON_RETURN_VAR);
- } else if (!isCtor && !func->isInplaceOperator() && func->type()
- && !injectedCodeHasReturnValueAttribution(func, TypeSystem::TargetLangCode)) {
- s << INDENT << PYTHON_RETURN_VAR " = ";
- if (isObjectTypeUsedAsValueType(func->type())) {
- s << "Shiboken::Object::newObject((SbkObjectType*)" << cpythonTypeNameExt(func->type()->typeEntry());
- s << ", " << CPP_RETURN_VAR << ", true, true)";
- } else {
- writeToPythonConversion(s, func->type(), func->ownerClass(), CPP_RETURN_VAR);
- }
- s << ';' << endl;
- }
- }
- }
-
- if (func->hasInjectedCode() && !func->isConstructor()) {
- s << endl;
- writeCodeSnips(s, snips, CodeSnip::End, TypeSystem::TargetLangCode, func, lastArg);
- }
-
- bool hasReturnPolicy = false;
-
- // Ownership transference between C++ and Python.
- QList<ArgumentModification> ownership_mods;
- // Python object reference management.
- QList<ArgumentModification> refcount_mods;
- foreach (FunctionModification func_mod, func->modifications()) {
- foreach (ArgumentModification arg_mod, func_mod.argument_mods) {
- if (!arg_mod.ownerships.isEmpty() && arg_mod.ownerships.contains(TypeSystem::TargetLangCode))
- ownership_mods.append(arg_mod);
- else if (!arg_mod.referenceCounts.isEmpty())
- refcount_mods.append(arg_mod);
- }
- }
-
- // If there's already a setParent(return, me), don't use the return heuristic!
- if (func->argumentOwner(func->ownerClass(), -1).index == 0)
- hasReturnPolicy = true;
-
- if (!ownership_mods.isEmpty()) {
- s << endl << INDENT << "// Ownership transferences." << endl;
- foreach (ArgumentModification arg_mod, ownership_mods) {
- const AbstractMetaClass* wrappedClass = 0;
- QString pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass);
- if (!wrappedClass) {
- s << "#error Invalid ownership modification for argument " << arg_mod.index << '(' << pyArgName << ')' << endl << endl;
- break;
- }
-
- if (arg_mod.index == 0 || arg_mod.owner.index == 0)
- hasReturnPolicy = true;
-
- // The default ownership does nothing. This is useful to avoid automatic heuristically
- // based generation of code defining parenting.
- if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::DefaultOwnership)
- continue;
-
- s << INDENT << "Shiboken::Object::";
- if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::TargetLangOwnership) {
- s << "getOwnership(" << pyArgName << ");";
- } else if (wrappedClass->hasVirtualDestructor()) {
- if (arg_mod.index == 0)
- s << "releaseOwnership(" PYTHON_RETURN_VAR ");";
- else
- s << "releaseOwnership(" << pyArgName << ");";
- } else {
- s << "invalidate(" << pyArgName << ");";
- }
- s << endl;
- }
-
- } else if (!refcount_mods.isEmpty()) {
- foreach (ArgumentModification arg_mod, refcount_mods) {
- ReferenceCount refCount = arg_mod.referenceCounts.first();
- if (refCount.action != ReferenceCount::Set
- && refCount.action != ReferenceCount::Remove
- && refCount.action != ReferenceCount::Add) {
- ReportHandler::warning("\"set\", \"add\" and \"remove\" are the only values supported by Shiboken for action attribute of reference-count tag.");
- continue;
- }
- const AbstractMetaClass* wrappedClass = 0;
-
- QString pyArgName;
- if (refCount.action == ReferenceCount::Remove) {
- pyArgName = "Py_None";
- } else {
- pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass);
- if (pyArgName.isEmpty()) {
- s << "#error Invalid reference count modification for argument " << arg_mod.index << endl << endl;
- break;
- }
- }
-
- if (refCount.action == ReferenceCount::Add || refCount.action == ReferenceCount::Set)
- s << INDENT << "Shiboken::Object::keepReference(";
- else
- s << INDENT << "Shiboken::Object::removeReference(";
-
- s << "reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR "), \"";
- QString varName = arg_mod.referenceCounts.first().varName;
- if (varName.isEmpty())
- varName = func->minimalSignature() + QString().number(arg_mod.index);
-
- s << varName << "\", " << pyArgName
- << (refCount.action == ReferenceCount::Add ? ", true" : "")
- << ");" << endl;
-
- if (arg_mod.index == 0)
- hasReturnPolicy = true;
- }
- }
- writeParentChildManagement(s, func, !hasReturnPolicy);
-}
-
-QStringList CppGenerator::getAncestorMultipleInheritance(const AbstractMetaClass* metaClass)
-{
- QStringList result;
- AbstractMetaClassList baseClases = getBaseClasses(metaClass);
- if (!baseClases.isEmpty()) {
- foreach (const AbstractMetaClass* baseClass, baseClases) {
- result.append(QString("((size_t) static_cast<const %1*>(class_ptr)) - base").arg(baseClass->qualifiedCppName()));
- result.append(QString("((size_t) static_cast<const %1*>((%2*)((void*)class_ptr))) - base").arg(baseClass->qualifiedCppName()).arg(metaClass->qualifiedCppName()));
- }
- foreach (const AbstractMetaClass* baseClass, baseClases)
- result.append(getAncestorMultipleInheritance(baseClass));
- }
- return result;
-}
-
-void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- QString className = metaClass->qualifiedCppName();
- QStringList ancestors = getAncestorMultipleInheritance(metaClass);
- s << "static int mi_offsets[] = { ";
- for (int i = 0; i < ancestors.size(); i++)
- s << "-1, ";
- s << "-1 };" << endl;
- s << "int*" << endl;
- s << multipleInheritanceInitializerFunctionName(metaClass) << "(const void* cptr)" << endl;
- s << '{' << endl;
- s << INDENT << "if (mi_offsets[0] == -1) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "std::set<int> offsets;" << endl;
- s << INDENT << "std::set<int>::iterator it;" << endl;
- s << INDENT << "const " << className << "* class_ptr = reinterpret_cast<const " << className << "*>(cptr);" << endl;
- s << INDENT << "size_t base = (size_t) class_ptr;" << endl;
-
- foreach (QString ancestor, ancestors)
- s << INDENT << "offsets.insert(" << ancestor << ");" << endl;
-
- s << endl;
- s << INDENT << "offsets.erase(0);" << endl;
- s << endl;
-
- s << INDENT << "int i = 0;" << endl;
- s << INDENT << "for (it = offsets.begin(); it != offsets.end(); it++) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "mi_offsets[i] = *it;" << endl;
- s << INDENT << "i++;" << endl;
- }
- s << INDENT << '}' << endl;
- }
- s << INDENT << '}' << endl;
- s << INDENT << "return mi_offsets;" << endl;
- s << '}' << endl;
-}
-
-void CppGenerator::writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- QString className = metaClass->qualifiedCppName();
- s << "static void* " << cpythonSpecialCastFunctionName(metaClass) << "(void* obj, SbkObjectType* desiredType)\n";
- s << "{\n";
- s << INDENT << className << "* me = reinterpret_cast< ::" << className << "*>(obj);\n";
- bool firstClass = true;
- foreach (const AbstractMetaClass* baseClass, getAllAncestors(metaClass)) {
- s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == reinterpret_cast<SbkObjectType*>(" << cpythonTypeNameExt(baseClass->typeEntry()) << "))\n";
- Indentation indent(INDENT);
- s << INDENT << "return static_cast< ::" << baseClass->qualifiedCppName() << "*>(me);\n";
- firstClass = false;
- }
- s << INDENT << "return me;\n";
- s << "}\n\n";
-}
-
-void CppGenerator::writePrimitiveConverterInitialization(QTextStream& s, const CustomConversion* customConversion)
-{
- const TypeEntry* type = customConversion->ownerType();
- QString converter = converterObject(type);
- s << INDENT << "// Register converter for type '" << type->qualifiedTargetLangName() << "'." << endl;
- s << INDENT << converter << " = Shiboken::Conversions::createConverter(";
- if (type->targetLangApiName() == type->name())
- s << '0';
- else if (type->targetLangApiName() == "PyObject")
- s << "&PyBaseObject_Type";
- else
- s << '&' << type->targetLangApiName() << "_Type";
- QString typeName = fixedCppTypeName(type);
- s << ", " << cppToPythonFunctionName(typeName, typeName) << ");" << endl;
- s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << type->qualifiedCppName() << "\");" << endl;
- writeCustomConverterRegister(s, customConversion, converter);
-}
-
-void CppGenerator::writeEnumConverterInitialization(QTextStream& s, const AbstractMetaEnum* metaEnum)
-{
- if (metaEnum->isPrivate() || metaEnum->isAnonymous())
- return;
- writeEnumConverterInitialization(s, metaEnum->typeEntry());
-}
-
-void CppGenerator::writeEnumConverterInitialization(QTextStream& s, const TypeEntry* enumType)
-{
- if (!enumType)
- return;
- QString enumFlagName = enumType->isFlags() ? "flag" : "enum";
- QString enumPythonType = cpythonTypeNameExt(enumType);
-
- const FlagsTypeEntry* flags = 0;
- if (enumType->isFlags())
- flags = reinterpret_cast<const FlagsTypeEntry*>(enumType);
-
- s << INDENT << "// Register converter for " << enumFlagName << " '" << enumType->qualifiedCppName() << "'." << endl;
- s << INDENT << '{' << endl;
- {
- Indentation indent(INDENT);
- QString typeName = fixedCppTypeName(enumType);
- s << INDENT << "SbkConverter* converter = Shiboken::Conversions::createConverter(" << enumPythonType << ',' << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << cppToPythonFunctionName(typeName, typeName) << ");" << endl;
- }
-
- if (flags) {
- QString enumTypeName = fixedCppTypeName(flags->originator());
- QString toCpp = pythonToCppFunctionName(enumTypeName, typeName);
- QString isConv = convertibleToCppFunctionName(enumTypeName, typeName);
- writeAddPythonToCppConversion(s, "converter", toCpp, isConv);
- }
-
- QString toCpp = pythonToCppFunctionName(typeName, typeName);
- QString isConv = convertibleToCppFunctionName(typeName, typeName);
- writeAddPythonToCppConversion(s, "converter", toCpp, isConv);
-
- if (flags) {
- QString toCpp = pythonToCppFunctionName("number", typeName);
- QString isConv = convertibleToCppFunctionName("number", typeName);
- writeAddPythonToCppConversion(s, "converter", toCpp, isConv);
- }
-
- s << INDENT << "Shiboken::Enum::setTypeConverter(" << enumPythonType << ", converter);" << endl;
- s << INDENT << "Shiboken::Enum::setTypeConverter(" << enumPythonType << ", converter);" << endl;
- QStringList cppSignature = enumType->qualifiedCppName().split("::", QString::SkipEmptyParts);
- while (!cppSignature.isEmpty()) {
- QString signature = cppSignature.join("::");
- s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"";
- if (flags)
- s << "QFlags<";
- s << signature << "\");" << endl;
- cppSignature.removeFirst();
- }
- }
- s << INDENT << '}' << endl;
-
- if (!flags)
- writeEnumConverterInitialization(s, reinterpret_cast<const EnumTypeEntry*>(enumType)->flags());
-}
-
-void CppGenerator::writeContainerConverterInitialization(QTextStream& s, const AbstractMetaType* type)
-{
- QByteArray cppSignature = QMetaObject::normalizedSignature(type->cppSignature().toAscii());
- s << INDENT << "// Register converter for type '" << cppSignature << "'." << endl;
- QString converter = converterObject(type);
- s << INDENT << converter << " = Shiboken::Conversions::createConverter(";
- if (type->typeEntry()->targetLangApiName() == "PyObject") {
- s << "&PyBaseObject_Type";
- } else {
- QString baseName = cpythonBaseName(type->typeEntry());
- if (baseName == "PySequence")
- baseName = "PyList";
- s << '&' << baseName << "_Type";
- }
- QString typeName = fixedCppTypeName(type);
- s << ", " << cppToPythonFunctionName(typeName, typeName) << ");" << endl;
- QString toCpp = pythonToCppFunctionName(typeName, typeName);
- QString isConv = convertibleToCppFunctionName(typeName, typeName);
- s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << cppSignature << "\");" << endl;
- if (usePySideExtensions() && cppSignature.startsWith("const ") && cppSignature.endsWith("&")) {
- cppSignature.chop(1);
- cppSignature.remove(0, sizeof("const ") / sizeof(char) - 1);
- s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << cppSignature << "\");" << endl;
- }
- writeAddPythonToCppConversion(s, converterObject(type), toCpp, isConv);
-}
-
-void CppGenerator::writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QList<const AbstractMetaClass*>& conversions)
-{
- s << INDENT << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl;
- foreach (const AbstractMetaClass* sourceClass, conversions) {
- QString converterVar = QString("(SbkObjectType*)%1[%2]")
- .arg(cppApiVariableName(externalType->targetLangPackage()))
- .arg(getTypeIndexVariableName(externalType));
- QString sourceTypeName = fixedCppTypeName(sourceClass->typeEntry());
- QString targetTypeName = fixedCppTypeName(externalType);
- QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName);
- QString isConv = convertibleToCppFunctionName(sourceTypeName, targetTypeName);
- writeAddPythonToCppConversion(s, converterVar, toCpp, isConv);
- }
-}
-
-QString CppGenerator::multipleInheritanceInitializerFunctionName(const AbstractMetaClass* metaClass)
-{
- if (!hasMultipleInheritanceInAncestry(metaClass))
- return QString();
- return QString("%1_mi_init").arg(cpythonBaseName(metaClass->typeEntry()));
-}
-
-bool CppGenerator::supportsMappingProtocol(const AbstractMetaClass* metaClass)
-{
- foreach(QString funcName, m_mappingProtocol.keys()) {
- if (metaClass->hasFunction(funcName))
- return true;
- }
-
- return false;
-}
-
-bool CppGenerator::supportsNumberProtocol(const AbstractMetaClass* metaClass)
-{
- return metaClass->hasArithmeticOperatorOverload()
- || metaClass->hasLogicalOperatorOverload()
- || metaClass->hasBitwiseOperatorOverload()
- || hasBoolCast(metaClass);
-}
-
-bool CppGenerator::supportsSequenceProtocol(const AbstractMetaClass* metaClass)
-{
- foreach(QString funcName, m_sequenceProtocol.keys()) {
- if (metaClass->hasFunction(funcName))
- return true;
- }
-
- const ComplexTypeEntry* baseType = metaClass->typeEntry()->baseContainerType();
- if (baseType && baseType->isContainer())
- return true;
-
- return false;
-}
-
-bool CppGenerator::shouldGenerateGetSetList(const AbstractMetaClass* metaClass)
-{
- foreach (AbstractMetaField* f, metaClass->fields()) {
- if (!f->isStatic())
- return true;
- }
- return false;
-}
-
-void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- QString tp_flags;
- QString tp_init;
- QString tp_new;
- QString tp_dealloc;
- QString tp_hash('0');
- QString tp_call('0');
- QString cppClassName = metaClass->qualifiedCppName();
- QString className = cpythonTypeName(metaClass).replace(QRegExp("_Type$"), "");
- QString baseClassName('0');
- AbstractMetaFunctionList ctors;
- foreach (AbstractMetaFunction* f, metaClass->queryFunctions(AbstractMetaClass::Constructors)) {
- if (!f->isPrivate() && !f->isModifiedRemoved())
- ctors.append(f);
- }
-
- if (!metaClass->baseClass())
- baseClassName = "reinterpret_cast<PyTypeObject*>(&SbkObject_Type)";
-
- bool onlyPrivCtor = !metaClass->hasNonPrivateConstructor();
-
- if (metaClass->isNamespace() || metaClass->hasPrivateDestructor()) {
- tp_flags = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_GC";
- tp_dealloc = metaClass->hasPrivateDestructor() ?
- "SbkDeallocWrapperWithPrivateDtor" : "0";
- tp_init = "0";
- } else {
- if (onlyPrivCtor)
- tp_flags = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_GC";
- else
- tp_flags = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_GC";
-
- QString deallocClassName;
- if (shouldGenerateCppWrapper(metaClass))
- deallocClassName = wrapperName(metaClass);
- else
- deallocClassName = cppClassName;
- tp_dealloc = "&SbkDeallocWrapper";
- tp_init = onlyPrivCtor || ctors.isEmpty() ? "0" : cpythonFunctionName(ctors.first());
- }
-
- QString tp_getattro('0');
- QString tp_setattro('0');
- if (usePySideExtensions() && (metaClass->qualifiedCppName() == "QObject")) {
- tp_getattro = cpythonGetattroFunctionName(metaClass);
- tp_setattro = cpythonSetattroFunctionName(metaClass);
- } else if (classNeedsGetattroFunction(metaClass)) {
- tp_getattro = cpythonGetattroFunctionName(metaClass);
- }
-
- if (metaClass->hasPrivateDestructor() || onlyPrivCtor)
- tp_new = "0";
- else
- tp_new = "SbkObjectTpNew";
-
- QString tp_richcompare = QString('0');
- if (metaClass->hasComparisonOperatorOverload())
- tp_richcompare = cpythonBaseName(metaClass) + "_richcompare";
-
- QString tp_getset = QString('0');
- if (shouldGenerateGetSetList(metaClass))
- tp_getset = cpythonGettersSettersDefinitionName(metaClass);
-
- // search for special functions
- ShibokenGenerator::clearTpFuncs();
- foreach (AbstractMetaFunction* func, metaClass->functions()) {
- if (m_tpFuncs.contains(func->name()))
- m_tpFuncs[func->name()] = cpythonFunctionName(func);
- }
- if (m_tpFuncs["__repr__"] == "0"
- && !metaClass->isQObject()
- && metaClass->hasToStringCapability()) {
- m_tpFuncs["__repr__"] = writeReprFunction(s, metaClass);
- }
-
- // class or some ancestor has multiple inheritance
- const AbstractMetaClass* miClass = getMultipleInheritingClass(metaClass);
- if (miClass) {
- if (metaClass == miClass)
- writeMultipleInheritanceInitializerFunction(s, metaClass);
- writeSpecialCastFunction(s, metaClass);
- s << endl;
- }
-
- if (!metaClass->typeEntry()->hashFunction().isEmpty())
- tp_hash = '&' + cpythonBaseName(metaClass) + "_HashFunc";
-
- const AbstractMetaFunction* callOp = metaClass->findFunction("operator()");
- if (callOp && !callOp->isModifiedRemoved())
- tp_call = '&' + cpythonFunctionName(callOp);
-
-
- s << "// Class Definition -----------------------------------------------" << endl;
- s << "extern \"C\" {" << endl;
- s << "static SbkObjectType " << className + "_Type" << " = { { {" << endl;
- s << INDENT << "PyVarObject_HEAD_INIT(&SbkObjectType_Type, 0)" << endl;
- s << INDENT << "/*tp_name*/ \"" << getClassTargetFullName(metaClass) << "\"," << endl;
- s << INDENT << "/*tp_basicsize*/ sizeof(SbkObject)," << endl;
- s << INDENT << "/*tp_itemsize*/ 0," << endl;
- s << INDENT << "/*tp_dealloc*/ " << tp_dealloc << ',' << endl;
- s << INDENT << "/*tp_print*/ 0," << endl;
- s << INDENT << "/*tp_getattr*/ 0," << endl;
- s << INDENT << "/*tp_setattr*/ 0," << endl;
- s << INDENT << "/*tp_compare*/ 0," << endl;
- s << INDENT << "/*tp_repr*/ " << m_tpFuncs["__repr__"] << "," << endl;
- s << INDENT << "/*tp_as_number*/ 0," << endl;
- s << INDENT << "/*tp_as_sequence*/ 0," << endl;
- s << INDENT << "/*tp_as_mapping*/ 0," << endl;
- s << INDENT << "/*tp_hash*/ " << tp_hash << ',' << endl;
- s << INDENT << "/*tp_call*/ " << tp_call << ',' << endl;
- s << INDENT << "/*tp_str*/ " << m_tpFuncs["__str__"] << ',' << endl;
- s << INDENT << "/*tp_getattro*/ " << tp_getattro << ',' << endl;
- s << INDENT << "/*tp_setattro*/ " << tp_setattro << ',' << endl;
- s << INDENT << "/*tp_as_buffer*/ 0," << endl;
- s << INDENT << "/*tp_flags*/ " << tp_flags << ',' << endl;
- s << INDENT << "/*tp_doc*/ 0," << endl;
- s << INDENT << "/*tp_traverse*/ " << className << "_traverse," << endl;
- s << INDENT << "/*tp_clear*/ " << className << "_clear," << endl;
- s << INDENT << "/*tp_richcompare*/ " << tp_richcompare << ',' << endl;
- s << INDENT << "/*tp_weaklistoffset*/ 0," << endl;
- s << INDENT << "/*tp_iter*/ " << m_tpFuncs["__iter__"] << ',' << endl;
- s << INDENT << "/*tp_iternext*/ " << m_tpFuncs["__next__"] << ',' << endl;
- s << INDENT << "/*tp_methods*/ " << className << "_methods," << endl;
- s << INDENT << "/*tp_members*/ 0," << endl;
- s << INDENT << "/*tp_getset*/ " << tp_getset << ',' << endl;
- s << INDENT << "/*tp_base*/ " << baseClassName << ',' << endl;
- s << INDENT << "/*tp_dict*/ 0," << endl;
- s << INDENT << "/*tp_descr_get*/ 0," << endl;
- s << INDENT << "/*tp_descr_set*/ 0," << endl;
- s << INDENT << "/*tp_dictoffset*/ 0," << endl;
- s << INDENT << "/*tp_init*/ " << tp_init << ',' << endl;
- s << INDENT << "/*tp_alloc*/ 0," << endl;
- s << INDENT << "/*tp_new*/ " << tp_new << ',' << endl;
- s << INDENT << "/*tp_free*/ 0," << endl;
- s << INDENT << "/*tp_is_gc*/ 0," << endl;
- s << INDENT << "/*tp_bases*/ 0," << endl;
- s << INDENT << "/*tp_mro*/ 0," << endl;
- s << INDENT << "/*tp_cache*/ 0," << endl;
- s << INDENT << "/*tp_subclasses*/ 0," << endl;
- s << INDENT << "/*tp_weaklist*/ 0" << endl;
- s << "}, }," << endl;
- s << INDENT << "/*priv_data*/ 0" << endl;
- s << "};" << endl;
- QString suffix;
- if (isObjectType(metaClass))
- suffix = "*";
- s << "} //extern" << endl;
-}
-
-void CppGenerator::writeMappingMethods(QTextStream& s, const AbstractMetaClass* metaClass)
-{
-
- QMap<QString, QString> funcs;
-
- QHash< QString, QPair< QString, QString > >::const_iterator it = m_mappingProtocol.begin();
- for (; it != m_mappingProtocol.end(); ++it) {
- const AbstractMetaFunction* func = metaClass->findFunction(it.key());
- if (!func)
- continue;
- QString funcName = cpythonFunctionName(func);
- QString funcArgs = it.value().first;
- QString funcRetVal = it.value().second;
-
- CodeSnipList snips = func->injectedCodeSnips(CodeSnip::Any, TypeSystem::TargetLangCode);
- s << funcRetVal << ' ' << funcName << '(' << funcArgs << ')' << endl << '{' << endl;
- writeInvalidPyObjectCheck(s, PYTHON_SELF_VAR);
-
- writeCppSelfDefinition(s, func);
-
- const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last();
- writeCodeSnips(s, snips, CodeSnip::Any, TypeSystem::TargetLangCode, func, lastArg);
- s << '}' << endl << endl;
- }
-}
-
-void CppGenerator::writeSequenceMethods(QTextStream& s, const AbstractMetaClass* metaClass)
-{
-
- QMap<QString, QString> funcs;
- bool injectedCode = false;
-
- QHash< QString, QPair< QString, QString > >::const_iterator it = m_sequenceProtocol.begin();
- for (; it != m_sequenceProtocol.end(); ++it) {
- const AbstractMetaFunction* func = metaClass->findFunction(it.key());
- if (!func)
- continue;
- injectedCode = true;
- QString funcName = cpythonFunctionName(func);
- QString funcArgs = it.value().first;
- QString funcRetVal = it.value().second;
-
- CodeSnipList snips = func->injectedCodeSnips(CodeSnip::Any, TypeSystem::TargetLangCode);
- s << funcRetVal << ' ' << funcName << '(' << funcArgs << ')' << endl << '{' << endl;
- writeInvalidPyObjectCheck(s, PYTHON_SELF_VAR);
-
- writeCppSelfDefinition(s, func);
-
- const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last();
- writeCodeSnips(s, snips,CodeSnip::Any, TypeSystem::TargetLangCode, func, lastArg);
- s << '}' << endl << endl;
- }
-
- if (!injectedCode)
- writeStdListWrapperMethods(s, metaClass);
-}
-
-void CppGenerator::writeTypeAsSequenceDefinition(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- bool hasFunctions = false;
- QMap<QString, QString> funcs;
- foreach(QString funcName, m_sequenceProtocol.keys()) {
- const AbstractMetaFunction* func = metaClass->findFunction(funcName);
- funcs[funcName] = func ? cpythonFunctionName(func).prepend("&") : QString();
- if (!hasFunctions && func)
- hasFunctions = true;
- }
-
- QString baseName = cpythonBaseName(metaClass);
-
- //use default implementation
- if (!hasFunctions) {
- funcs["__len__"] = baseName + "__len__";
- funcs["__getitem__"] = baseName + "__getitem__";
- funcs["__setitem__"] = baseName + "__setitem__";
- }
-
- s << INDENT << "memset(&" << baseName << "_Type.super.as_sequence, 0, sizeof(PySequenceMethods));" << endl;
- foreach (const QString& sqName, m_sqFuncs.keys()) {
- if (funcs[sqName].isEmpty())
- continue;
- if (m_sqFuncs[sqName] == "sq_slice")
- s << "#ifndef IS_PY3K" << endl;
- s << INDENT << baseName << "_Type.super.as_sequence." << m_sqFuncs[sqName] << " = " << funcs[sqName] << ';' << endl;
- if (m_sqFuncs[sqName] == "sq_slice")
- s << "#endif" << endl;
- }
-}
-
-void CppGenerator::writeTypeAsMappingDefinition(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- bool hasFunctions = false;
- QMap<QString, QString> funcs;
- foreach(QString funcName, m_mappingProtocol.keys()) {
- const AbstractMetaFunction* func = metaClass->findFunction(funcName);
- funcs[funcName] = func ? cpythonFunctionName(func).prepend("&") : "0";
- if (!hasFunctions && func)
- hasFunctions = true;
- }
-
- //use default implementation
- if (!hasFunctions) {
- funcs["__mlen__"] = QString();
- funcs["__mgetitem__"] = QString();
- funcs["__msetitem__"] = QString();
- }
-
- QString baseName = cpythonBaseName(metaClass);
- s << INDENT << "memset(&" << baseName << "_Type.super.as_mapping, 0, sizeof(PyMappingMethods));" << endl;
- foreach (const QString& mpName, m_mpFuncs.keys()) {
- if (funcs[mpName].isEmpty())
- continue;
- s << INDENT << baseName << "_Type.super.as_mapping." << m_mpFuncs[mpName] << " = " << funcs[mpName] << ';' << endl;
- }
-}
-
-void CppGenerator::writeTypeAsNumberDefinition(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- QMap<QString, QString> nb;
-
- nb["__add__"] = QString();
- nb["__sub__"] = QString();
- nb["__mul__"] = QString();
- nb["__div__"] = QString();
- nb["__mod__"] = QString();
- nb["__neg__"] = QString();
- nb["__pos__"] = QString();
- nb["__invert__"] = QString();
- nb["__lshift__"] = QString();
- nb["__rshift__"] = QString();
- nb["__and__"] = QString();
- nb["__xor__"] = QString();
- nb["__or__"] = QString();
- nb["__iadd__"] = QString();
- nb["__isub__"] = QString();
- nb["__imul__"] = QString();
- nb["__idiv__"] = QString();
- nb["__imod__"] = QString();
- nb["__ilshift__"] = QString();
- nb["__irshift__"] = QString();
- nb["__iand__"] = QString();
- nb["__ixor__"] = QString();
- nb["__ior__"] = QString();
-
- QList<AbstractMetaFunctionList> opOverloads =
- filterGroupedOperatorFunctions(metaClass,
- AbstractMetaClass::ArithmeticOp
- | AbstractMetaClass::LogicalOp
- | AbstractMetaClass::BitwiseOp);
-
- foreach (AbstractMetaFunctionList opOverload, opOverloads) {
- const AbstractMetaFunction* rfunc = opOverload[0];
- QString opName = ShibokenGenerator::pythonOperatorFunctionName(rfunc);
- nb[opName] = cpythonFunctionName(rfunc);
- }
-
- QString baseName = cpythonBaseName(metaClass);
-
- nb["bool"] = hasBoolCast(metaClass) ? baseName + "___nb_bool" : QString();
-
- s << INDENT << "memset(&" << baseName << "_Type.super.as_number, 0, sizeof(PyNumberMethods));" << endl;
- foreach (const QString& nbName, m_nbFuncs.keys()) {
- if (nb[nbName].isEmpty())
- continue;
-
- // bool is special because the field name differs on Python 2 and 3 (nb_nonzero vs nb_bool)
- // so a shiboken macro is used.
- if (nbName == "bool") {
- s << INDENT << "SBK_NB_BOOL(" << baseName << "_Type.super.as_number) = " << nb[nbName] << ';' << endl;
- } else {
- bool excludeFromPy3K = nbName == "__div__" || nbName == "__idiv__";
- if (excludeFromPy3K)
- s << "#ifndef IS_PY3K" << endl;
- s << INDENT << baseName << "_Type.super.as_number." << m_nbFuncs[nbName] << " = " << nb[nbName] << ';' << endl;
- if (excludeFromPy3K)
- s << "#endif" << endl;
- }
- }
- if (!nb["__div__"].isEmpty())
- s << INDENT << baseName << "_Type.super.as_number.nb_true_divide = " << nb["__div__"] << ';' << endl;
-}
-
-void CppGenerator::writeTpTraverseFunction(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- QString baseName = cpythonBaseName(metaClass);
- s << "static int ";
- s << baseName << "_traverse(PyObject* " PYTHON_SELF_VAR ", visitproc visit, void* arg)" << endl;
- s << '{' << endl;
- s << INDENT << "return reinterpret_cast<PyTypeObject*>(&SbkObject_Type)->tp_traverse(" PYTHON_SELF_VAR ", visit, arg);" << endl;
- s << '}' << endl;
-}
-
-void CppGenerator::writeTpClearFunction(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- QString baseName = cpythonBaseName(metaClass);
- s << "static int ";
- s << baseName << "_clear(PyObject* " PYTHON_SELF_VAR ")" << endl;
- s << '{' << endl;
- s << INDENT << "return reinterpret_cast<PyTypeObject*>(&SbkObject_Type)->tp_clear(" PYTHON_SELF_VAR ");" << endl;
- s << '}' << endl;
-}
-
-void CppGenerator::writeCopyFunction(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- QString className = cpythonTypeName(metaClass).replace(QRegExp("_Type$"), "");
- s << "static PyObject* " << className << "___copy__(PyObject* " PYTHON_SELF_VAR ")" << endl;
- s << "{" << endl;
- writeCppSelfDefinition(s, metaClass, false, true);
- s << INDENT << "PyObject* " << PYTHON_RETURN_VAR << " = " << cpythonToPythonConversionFunction(metaClass);
- s << CPP_SELF_VAR ");" << endl;
- writeFunctionReturnErrorCheckSection(s);
- s << INDENT << "return " PYTHON_RETURN_VAR ";" << endl;
- s << "}" << endl;
- s << endl;
-}
-
-void CppGenerator::writeGetterFunction(QTextStream& s, const AbstractMetaField* metaField)
-{
- ErrorCode errorCode(0);
- s << "static PyObject* " << cpythonGetterFunctionName(metaField) << "(PyObject* " PYTHON_SELF_VAR ", void*)" << endl;
- s << '{' << endl;
-
- writeCppSelfDefinition(s, metaField->enclosingClass());
-
- AbstractMetaType* fieldType = metaField->type();
- // Force use of pointer to return internal variable memory
- bool newWrapperSameObject = !fieldType->isConstant() && isWrapperType(fieldType) && !isPointer(fieldType);
-
- QString cppField;
- if (avoidProtectedHack() && metaField->isProtected()) {
- cppField = QString("((%1*)%2)->%3()").arg(wrapperName(metaField->enclosingClass()))
- .arg(CPP_SELF_VAR)
- .arg(protectedFieldGetterName(metaField));
- } else {
- cppField = QString("%2->%3").arg(CPP_SELF_VAR).arg(metaField->name());
- if (newWrapperSameObject) {
- cppField.prepend("&(");
- cppField.append(')');
- }
- }
- if (isCppIntegralPrimitive(fieldType) || fieldType->isEnum()) {
- s << INDENT << getFullTypeNameWithoutModifiers(fieldType) << " cppOut_local = " << cppField << ';' << endl;
- cppField = "cppOut_local";
- } else if (avoidProtectedHack() && metaField->isProtected()) {
- s << INDENT << getFullTypeNameWithoutModifiers(fieldType);
- if (fieldType->isContainer() || fieldType->isFlags()) {
- s << '&';
- cppField.prepend('*');
- } else if ((!fieldType->isConstant() && !fieldType->isEnum() && !fieldType->isPrimitive()) || fieldType->indirections() == 1) {
- s << '*';
- }
- s << " fieldValue = " << cppField << ';' << endl;
- cppField = "fieldValue";
- }
-
- s << INDENT << "PyObject* pyOut = ";
- if (newWrapperSameObject) {
- s << "Shiboken::Object::newObject((SbkObjectType*)" << cpythonTypeNameExt(fieldType);
- s << ", " << cppField << ", false, true);" << endl;
- s << INDENT << "Shiboken::Object::setParent(" PYTHON_SELF_VAR ", pyOut)";
- } else {
- writeToPythonConversion(s, fieldType, metaField->enclosingClass(), cppField);
- }
- s << ';' << endl;
-
- s << INDENT << "return pyOut;" << endl;
- s << '}' << endl;
-}
-
-void CppGenerator::writeSetterFunction(QTextStream& s, const AbstractMetaField* metaField)
-{
- ErrorCode errorCode(0);
- s << "static int " << cpythonSetterFunctionName(metaField) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* pyIn, void*)" << endl;
- s << '{' << endl;
-
- writeCppSelfDefinition(s, metaField->enclosingClass());
-
- s << INDENT << "if (pyIn == 0) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_TypeError, \"'";
- s << metaField->name() << "' may not be deleted\");" << endl;
- s << INDENT << "return -1;" << endl;
- }
- s << INDENT << '}' << endl;
-
- AbstractMetaType* fieldType = metaField->type();
-
- s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ';' << endl;
- s << INDENT << "if (!";
- writeTypeCheck(s, fieldType, "pyIn", isNumber(fieldType->typeEntry()));
- s << ") {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_TypeError, \"wrong type attributed to '";
- s << metaField->name() << "', '" << fieldType->name() << "' or convertible type expected\");" << endl;
- s << INDENT << "return -1;" << endl;
- }
- s << INDENT << '}' << endl << endl;
-
- QString cppField = QString("%1->%2").arg(CPP_SELF_VAR).arg(metaField->name());
- s << INDENT;
- if (avoidProtectedHack() && metaField->isProtected()) {
- s << getFullTypeNameWithoutModifiers(fieldType);
- s << (fieldType->indirections() == 1 ? "*" : "") << " cppOut;" << endl;
- s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut);" << endl;
- s << INDENT << QString("((%1*)%2)->%3(cppOut)").arg(wrapperName(metaField->enclosingClass()))
- .arg(CPP_SELF_VAR)
- .arg(protectedFieldSetterName(metaField));
- } else if (isCppIntegralPrimitive(fieldType) || fieldType->typeEntry()->isEnum() || fieldType->typeEntry()->isFlags()) {
- s << getFullTypeNameWithoutModifiers(fieldType) << " cppOut_local = " << cppField << ';' << endl;
- s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut_local);" << endl;
- s << INDENT << cppField << " = cppOut_local";
- } else {
- s << getFullTypeNameWithoutModifiers(fieldType);
- s << QString("*").repeated(fieldType->indirections()) << "& cppOut_ptr = ";
- s << cppField << ';' << endl;
- s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut_ptr)";
- }
- s << ';' << endl << endl;
-
- if (isPointerToWrapperType(fieldType)) {
- s << INDENT << "Shiboken::Object::keepReference(reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR "), \"";
- s << metaField->name() << "\", pyIn);" << endl;
- }
-
- s << INDENT << "return 0;" << endl;
- s << '}' << endl;
-}
-
-void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- QString baseName = cpythonBaseName(metaClass);
- s << "static PyObject* ";
- s << baseName << "_richcompare(PyObject* " PYTHON_SELF_VAR ", PyObject* " PYTHON_ARG ", int op)" << endl;
- s << '{' << endl;
- writeCppSelfDefinition(s, metaClass, false, true);
- writeUnusedVariableCast(s, CPP_SELF_VAR);
- s << INDENT << "PyObject* " PYTHON_RETURN_VAR " = 0;" << endl;
- s << INDENT << "PythonToCppFunc " PYTHON_TO_CPP_VAR << ';' << endl;
- writeUnusedVariableCast(s, PYTHON_TO_CPP_VAR);
- s << endl;
-
- s << INDENT << "switch (op) {" << endl;
- {
- Indentation indent(INDENT);
- foreach (AbstractMetaFunctionList overloads, filterGroupedOperatorFunctions(metaClass, AbstractMetaClass::ComparisonOp)) {
- const AbstractMetaFunction* rfunc = overloads[0];
-
- QString operatorId = ShibokenGenerator::pythonRichCompareOperatorId(rfunc);
- s << INDENT << "case " << operatorId << ':' << endl;
-
- Indentation indent(INDENT);
-
- QString op = rfunc->originalName();
- op = op.right(op.size() - QString("operator").size());
-
- int alternativeNumericTypes = 0;
- foreach (const AbstractMetaFunction* func, overloads) {
- if (!func->isStatic() &&
- ShibokenGenerator::isNumber(func->arguments()[0]->type()->typeEntry()))
- alternativeNumericTypes++;
- }
-
- bool first = true;
- OverloadData overloadData(overloads, this);
- foreach (OverloadData* od, overloadData.nextOverloadData()) {
- const AbstractMetaFunction* func = od->referenceFunction();
- if (func->isStatic())
- continue;
- const AbstractMetaType* argType = getArgumentType(func, 1);
- if (!argType)
- continue;
- if (!first) {
- s << " else ";
- } else {
- first = false;
- s << INDENT;
- }
- s << "if (";
- writeTypeCheck(s, argType, PYTHON_ARG, alternativeNumericTypes == 1 || isPyInt(argType));
- s << ") {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "// " << func->signature() << endl;
- writeArgumentConversion(s, argType, CPP_ARG0, PYTHON_ARG, metaClass, QString(), func->isUserAdded());
-
- // If the function is user added, use the inject code
- if (func->isUserAdded()) {
- CodeSnipList snips = func->injectedCodeSnips();
- writeCodeSnips(s, snips, CodeSnip::Any, TypeSystem::TargetLangCode, func, func->arguments().last());
- } else {
- QString expression = QString("%1%2 %3 (%4" CPP_ARG0 ")")
- .arg(func->isPointerOperator() ? "&" : "")
- .arg(CPP_SELF_VAR).arg(op)
- .arg(shouldDereferenceAbstractMetaTypePointer(argType) ? "*" : "");
- s << INDENT;
- if (func->type())
- s << func->type()->cppSignature() << " " CPP_RETURN_VAR " = ";
- s << expression << ';' << endl;
- s << INDENT << PYTHON_RETURN_VAR " = ";
- if (func->type())
- writeToPythonConversion(s, func->type(), metaClass, CPP_RETURN_VAR);
- else
- s << "Py_None;" << endl << INDENT << "Py_INCREF(Py_None)";
- s << ';' << endl;
- }
- }
- s << INDENT << '}';
- }
-
- s << " else {" << endl;
- if (operatorId == "Py_EQ" || operatorId == "Py_NE") {
- Indentation indent(INDENT);
- s << INDENT << PYTHON_RETURN_VAR " = " << (operatorId == "Py_EQ" ? "Py_False" : "Py_True") << ';' << endl;
- s << INDENT << "Py_INCREF(" PYTHON_RETURN_VAR ");" << endl;
- } else {
- Indentation indent(INDENT);
- s << INDENT << "goto " << baseName << "_RichComparison_TypeError;" << endl;
- }
- s << INDENT << '}' << endl << endl;
-
- s << INDENT << "break;" << endl;
- }
- s << INDENT << "default:" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "goto " << baseName << "_RichComparison_TypeError;" << endl;
- }
- }
- s << INDENT << '}' << endl << endl;
-
- s << INDENT << "if (" PYTHON_RETURN_VAR " && !PyErr_Occurred())" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "return " PYTHON_RETURN_VAR ";" << endl;
- }
- s << INDENT << baseName << "_RichComparison_TypeError:" << endl;
- s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"operator not implemented.\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl;
- s << '}' << endl << endl;
-}
-
-void CppGenerator::writeMethodDefinitionEntry(QTextStream& s, const AbstractMetaFunctionList overloads)
-{
- Q_ASSERT(!overloads.isEmpty());
- OverloadData overloadData(overloads, this);
- bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(overloadData);
- const AbstractMetaFunction* func = overloadData.referenceFunction();
- int min = overloadData.minArgs();
- int max = overloadData.maxArgs();
-
- s << '"' << func->name() << "\", (PyCFunction)" << cpythonFunctionName(func) << ", ";
- if ((min == max) && (max < 2) && !usePyArgs) {
- if (max == 0)
- s << "METH_NOARGS";
- else
- s << "METH_O";
- } else {
- s << "METH_VARARGS";
- if (overloadData.hasArgumentWithDefaultValue())
- s << "|METH_KEYWORDS";
- }
- if (func->ownerClass() && overloadData.hasStaticFunction())
- s << "|METH_STATIC";
-}
-
-void CppGenerator::writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList overloads)
-{
- Q_ASSERT(!overloads.isEmpty());
- const AbstractMetaFunction* func = overloads.first();
- if (m_tpFuncs.contains(func->name()))
- return;
-
- s << INDENT;
- if (OverloadData::hasStaticAndInstanceFunctions(overloads)) {
- s << cpythonMethodDefinitionName(func);
- } else {
- s << '{';
- writeMethodDefinitionEntry(s, overloads);
- s << '}';
- }
- s << ',' << endl;
-}
-
-void CppGenerator::writeEnumsInitialization(QTextStream& s, AbstractMetaEnumList& enums)
-{
- if (enums.isEmpty())
- return;
- s << INDENT << "// Initialization of enums." << endl << endl;
- foreach (const AbstractMetaEnum* cppEnum, enums) {
- if (cppEnum->isPrivate())
- continue;
- writeEnumInitialization(s, cppEnum);
- }
-}
-
-void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnum* cppEnum)
-{
- const AbstractMetaClass* enclosingClass = getProperEnclosingClassForEnum(cppEnum);
- const AbstractMetaClass* upper = enclosingClass ? enclosingClass->enclosingClass() : 0;
- bool hasUpperEnclosingClass = upper && upper->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass;
- QString enclosingObjectVariable;
- if (enclosingClass)
- enclosingObjectVariable = '&' + cpythonTypeName(enclosingClass);
- else if (hasUpperEnclosingClass)
- enclosingObjectVariable = "enclosingClass";
- else
- enclosingObjectVariable = "module";
-
- s << INDENT << "// Initialization of ";
- s << (cppEnum->isAnonymous() ? "anonymous enum identified by enum value" : "enum");
- s << " '" << cppEnum->name() << "'." << endl;
-
- if (!cppEnum->isAnonymous()) {
- FlagsTypeEntry* flags = cppEnum->typeEntry()->flags();
- if (flags) {
- s << INDENT << cpythonTypeNameExt(flags) << " = PySide::QFlags::create(\"" << flags->flagsName() << "\", &"
- << cpythonEnumName(cppEnum) << "_as_number);" << endl;
- }
-
- s << INDENT << cpythonTypeNameExt(cppEnum->typeEntry()) << " = Shiboken::Enum::";
- s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnum" : "createGlobalEnum");
- s << '(' << enclosingObjectVariable << ',' << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << '"' << cppEnum->name() << "\"," << endl;
- s << INDENT << '"' << getClassTargetFullName(cppEnum) << "\"," << endl;
- s << INDENT << '"' << (cppEnum->enclosingClass() ? cppEnum->enclosingClass()->qualifiedCppName() + "::" : "");
- s << cppEnum->name() << '"';
- if (flags)
- s << ',' << endl << INDENT << cpythonTypeNameExt(flags);
- s << ");" << endl;
- }
- s << INDENT << "if (!" << cpythonTypeNameExt(cppEnum->typeEntry()) << ')' << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl;
- }
- }
-
- foreach (const AbstractMetaEnumValue* enumValue, cppEnum->values()) {
- if (cppEnum->typeEntry()->isEnumValueRejected(enumValue->name()))
- continue;
-
- QString enumValueText;
- if (!avoidProtectedHack() || !cppEnum->isProtected()) {
- enumValueText = "(long) ";
- if (cppEnum->enclosingClass())
- enumValueText += cppEnum->enclosingClass()->qualifiedCppName() + "::";
- enumValueText += enumValue->name();
- } else {
- enumValueText += QString::number(enumValue->value());
- }
-
- if (cppEnum->isAnonymous()) {
- if (enclosingClass || hasUpperEnclosingClass) {
- s << INDENT << '{' << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyObject* anonEnumItem = PyInt_FromLong(" << enumValueText << ");" << endl;
- s << INDENT << "if (PyDict_SetItemString(((SbkObjectType*)" << enclosingObjectVariable;
- s << ")->super.ht_type.tp_dict, \"" << enumValue->name() << "\", anonEnumItem) < 0)" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
- }
- s << INDENT << "Py_DECREF(anonEnumItem);" << endl;
- }
- s << INDENT << '}' << endl;
- } else {
- s << INDENT << "if (PyModule_AddIntConstant(module, \"" << enumValue->name() << "\", ";
- s << enumValueText << ") < 0)" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
- }
- }
- } else {
- s << INDENT << "if (!Shiboken::Enum::";
- s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnumItem" : "createGlobalEnumItem");
- s << '(' << cpythonTypeNameExt(cppEnum->typeEntry()) << ',' << endl;
- Indentation indent(INDENT);
- s << INDENT << enclosingObjectVariable << ", \"" << enumValue->name() << "\", ";
- s << enumValueText << "))" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
- }
- }
-
- writeEnumConverterInitialization(s, cppEnum);
-
- s << INDENT << "// End of '" << cppEnum->name() << "' enum";
- if (cppEnum->typeEntry()->flags())
- s << "/flags";
- s << '.' << endl << endl;
-}
-
-void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- // Try to check something and print some warnings
- foreach (const AbstractMetaFunction* cppSignal, metaClass->cppSignalFunctions()) {
- if (cppSignal->declaringClass() != metaClass)
- continue;
- foreach (AbstractMetaArgument* arg, cppSignal->arguments()) {
- AbstractMetaType* metaType = arg->type();
- QByteArray origType = SBK_NORMALIZED_TYPE(qPrintable(metaType->originalTypeDescription()));
- QByteArray cppSig = SBK_NORMALIZED_TYPE(qPrintable(metaType->cppSignature()));
- if ((origType != cppSig) && (!metaType->isFlags()))
- ReportHandler::warning("Typedef used on signal " + metaClass->qualifiedCppName() + "::" + cppSignal->signature());
- }
- }
-
- s << INDENT << "PySide::Signal::registerSignals(&" << cpythonTypeName(metaClass) << ", &::"
- << metaClass->qualifiedCppName() << "::staticMetaObject);" << endl;
-}
-
-void CppGenerator::writeFlagsToLong(QTextStream& s, const AbstractMetaEnum* cppEnum)
-{
- FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags();
- if (!flagsEntry)
- return;
- s << "static PyObject* " << cpythonEnumName(cppEnum) << "_long(PyObject* " PYTHON_SELF_VAR ")" << endl;
- s << "{" << endl;
- s << INDENT << "int val;" << endl;
- AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry);
- s << INDENT << cpythonToCppConversionFunction(flagsType) << PYTHON_SELF_VAR << ", &val);" << endl;
- s << INDENT << "return Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter<int>(), &val);" << endl;
- s << "}" << endl;
-}
-
-void CppGenerator::writeFlagsNonZero(QTextStream& s, const AbstractMetaEnum* cppEnum)
-{
- FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags();
- if (!flagsEntry)
- return;
- s << "static int " << cpythonEnumName(cppEnum) << "__nonzero(PyObject* " PYTHON_SELF_VAR ")" << endl;
- s << "{" << endl;
-
- s << INDENT << "int val;" << endl;
- AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry);
- s << INDENT << cpythonToCppConversionFunction(flagsType) << PYTHON_SELF_VAR << ", &val);" << endl;
- s << INDENT << "return val != 0;" << endl;
- s << "}" << endl;
-}
-
-void CppGenerator::writeFlagsMethods(QTextStream& s, const AbstractMetaEnum* cppEnum)
-{
- writeFlagsBinaryOperator(s, cppEnum, "and", "&");
- writeFlagsBinaryOperator(s, cppEnum, "or", "|");
- writeFlagsBinaryOperator(s, cppEnum, "xor", "^");
-
- writeFlagsUnaryOperator(s, cppEnum, "invert", "~");
- writeFlagsToLong(s, cppEnum);
- writeFlagsNonZero(s, cppEnum);
-
- s << endl;
-}
-
-void CppGenerator::writeFlagsNumberMethodsDefinition(QTextStream& s, const AbstractMetaEnum* cppEnum)
-{
- QString cpythonName = cpythonEnumName(cppEnum);
-
- s << "static PyNumberMethods " << cpythonName << "_as_number = {" << endl;
- s << INDENT << "/*nb_add*/ 0," << endl;
- s << INDENT << "/*nb_subtract*/ 0," << endl;
- s << INDENT << "/*nb_multiply*/ 0," << endl;
- s << INDENT << "#ifndef IS_PY3K" << endl;
- s << INDENT << "/* nb_divide */ 0," << endl;
- s << INDENT << "#endif" << endl;
- s << INDENT << "/*nb_remainder*/ 0," << endl;
- s << INDENT << "/*nb_divmod*/ 0," << endl;
- s << INDENT << "/*nb_power*/ 0," << endl;
- s << INDENT << "/*nb_negative*/ 0," << endl;
- s << INDENT << "/*nb_positive*/ 0," << endl;
- s << INDENT << "/*nb_absolute*/ 0," << endl;
- s << INDENT << "/*nb_nonzero*/ " << cpythonName << "__nonzero," << endl;
- s << INDENT << "/*nb_invert*/ (unaryfunc)" << cpythonName << "___invert__," << endl;
- s << INDENT << "/*nb_lshift*/ 0," << endl;
- s << INDENT << "/*nb_rshift*/ 0," << endl;
- s << INDENT << "/*nb_and*/ (binaryfunc)" << cpythonName << "___and__," << endl;
- s << INDENT << "/*nb_xor*/ (binaryfunc)" << cpythonName << "___xor__," << endl;
- s << INDENT << "/*nb_or*/ (binaryfunc)" << cpythonName << "___or__," << endl;
- s << INDENT << "#ifndef IS_PY3K" << endl;
- s << INDENT << "/* nb_coerce */ 0," << endl;
- s << INDENT << "#endif" << endl;
- s << INDENT << "/*nb_int*/ " << cpythonName << "_long," << endl;
- s << INDENT << "#ifdef IS_PY3K" << endl;
- s << INDENT << "/*nb_reserved*/ 0," << endl;
- s << INDENT << "/*nb_float*/ 0," << endl;
- s << INDENT << "#else" << endl;
- s << INDENT << "/*nb_long*/ " << cpythonName << "_long," << endl;
- s << INDENT << "/*nb_float*/ 0," << endl;
- s << INDENT << "/*nb_oct*/ 0," << endl;
- s << INDENT << "/*nb_hex*/ 0," << endl;
- s << INDENT << "#endif" << endl;
- s << INDENT << "/*nb_inplace_add*/ 0," << endl;
- s << INDENT << "/*nb_inplace_subtract*/ 0," << endl;
- s << INDENT << "/*nb_inplace_multiply*/ 0," << endl;
- s << INDENT << "#ifndef IS_PY3K" << endl;
- s << INDENT << "/*nb_inplace_divide*/ 0," << endl;
- s << INDENT << "#endif" << endl;
- s << INDENT << "/*nb_inplace_remainder*/ 0," << endl;
- s << INDENT << "/*nb_inplace_power*/ 0," << endl;
- s << INDENT << "/*nb_inplace_lshift*/ 0," << endl;
- s << INDENT << "/*nb_inplace_rshift*/ 0," << endl;
- s << INDENT << "/*nb_inplace_and*/ 0," << endl;
- s << INDENT << "/*nb_inplace_xor*/ 0," << endl;
- s << INDENT << "/*nb_inplace_or*/ 0," << endl;
- s << INDENT << "/*nb_floor_divide*/ 0," << endl;
- s << INDENT << "/*nb_true_divide*/ 0," << endl;
- s << INDENT << "/*nb_inplace_floor_divide*/ 0," << endl;
- s << INDENT << "/*nb_inplace_true_divide*/ 0," << endl;
- s << INDENT << "/*nb_index*/ 0" << endl;
- s << "};" << endl << endl;
-}
-
-void CppGenerator::writeFlagsBinaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum,
- QString pyOpName, QString cppOpName)
-{
- FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags();
- Q_ASSERT(flagsEntry);
-
- s << "PyObject* " << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject* " PYTHON_SELF_VAR ", PyObject* " PYTHON_ARG ")" << endl;
- s << '{' << endl;
-
- AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry);
- s << INDENT << "::" << flagsEntry->originalName() << " cppResult, " CPP_SELF_VAR ", cppArg;" << endl;
- s << "#ifdef IS_PY3K" << endl;
- s << INDENT << CPP_SELF_VAR " = (::" << flagsEntry->originalName() << ")PyLong_AsLong(" PYTHON_SELF_VAR ");" << endl;
- s << INDENT << "cppArg = (" << flagsEntry->originalName() << ")PyLong_AsLong(" PYTHON_ARG ");" << endl;
- s << "#else" << endl;
- s << INDENT << CPP_SELF_VAR " = (::" << flagsEntry->originalName() << ")PyInt_AsLong(" PYTHON_SELF_VAR ");" << endl;
- s << INDENT << "cppArg = (" << flagsEntry->originalName() << ")PyInt_AsLong(" PYTHON_ARG ");" << endl;
- s << "#endif" << endl << endl;
- s << INDENT << "cppResult = " CPP_SELF_VAR " " << cppOpName << " cppArg;" << endl;
- s << INDENT << "return ";
- writeToPythonConversion(s, flagsType, 0, "cppResult");
- s << ';' << endl;
- s << '}' << endl << endl;
-}
-
-void CppGenerator::writeFlagsUnaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum,
- QString pyOpName, QString cppOpName, bool boolResult)
-{
- FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags();
- Q_ASSERT(flagsEntry);
-
- s << "PyObject* " << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject* " PYTHON_SELF_VAR ", PyObject* " PYTHON_ARG ")" << endl;
- s << '{' << endl;
-
- AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry);
- s << INDENT << "::" << flagsEntry->originalName() << " " CPP_SELF_VAR ";" << endl;
- s << INDENT << cpythonToCppConversionFunction(flagsType) << PYTHON_SELF_VAR << ", &" CPP_SELF_VAR ");" << endl;
- s << INDENT;
- if (boolResult)
- s << "bool";
- else
- s << "::" << flagsEntry->originalName();
- s << " cppResult = " << cppOpName << CPP_SELF_VAR ";" << endl;
- s << INDENT << "return ";
- if (boolResult)
- s << "PyBool_FromLong(cppResult)";
- else
- writeToPythonConversion(s, flagsType, 0, "cppResult");
- s << ';' << endl;
- s << '}' << endl << endl;
-}
-
-void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- const ComplexTypeEntry* classTypeEntry = metaClass->typeEntry();
-
- const AbstractMetaClass* enc = metaClass->enclosingClass();
- bool hasEnclosingClass = enc && enc->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass;
- QString enclosingObjectVariable = hasEnclosingClass ? "enclosingClass" : "module";
-
- QString pyTypeName = cpythonTypeName(metaClass);
- s << "void init_" << metaClass->qualifiedCppName().replace("::", "_");
- s << "(PyObject* " << enclosingObjectVariable << ")" << endl;
- s << '{' << endl;
-
- if (supportsNumberProtocol(metaClass)) {
- s << INDENT << "// type has number operators" << endl;
- writeTypeAsNumberDefinition(s, metaClass);
- s << INDENT << pyTypeName << ".super.ht_type.tp_as_number = &" << pyTypeName << ".super.as_number;" << endl;
- s << endl;
- }
-
- if (supportsSequenceProtocol(metaClass)) {
- s << INDENT << "// type supports sequence protocol" << endl;
- writeTypeAsSequenceDefinition(s, metaClass);
- s << INDENT << pyTypeName << ".super.ht_type.tp_as_sequence = &" << pyTypeName << ".super.as_sequence;" << endl;
- s << endl;
- }
-
- if (supportsMappingProtocol(metaClass)) {
- s << INDENT << "// type supports mapping protocol" << endl;
- writeTypeAsMappingDefinition(s, metaClass);
- s << INDENT << pyTypeName << ".super.ht_type.tp_as_mapping = &" << pyTypeName << ".super.as_mapping;" << endl;
- s << endl;
- }
-
- s << INDENT << cpythonTypeNameExt(classTypeEntry);
- s << " = reinterpret_cast<PyTypeObject*>(&" << pyTypeName << ");" << endl;
- s << endl;
-
- // Multiple inheritance
- QString pyTypeBasesVariable = QString("%1_bases").arg(pyTypeName);
- const AbstractMetaClassList baseClasses = getBaseClasses(metaClass);
- if (metaClass->baseClassNames().size() > 1) {
- s << INDENT << "PyObject* " << pyTypeBasesVariable << " = PyTuple_Pack(" << baseClasses.size() << ',' << endl;
- QStringList bases;
- foreach (const AbstractMetaClass* base, baseClasses)
- bases << "(PyObject*)" + cpythonTypeNameExt(base->typeEntry());
- Indentation indent(INDENT);
- QString separator;
- QTextStream sep(&separator);
- sep << "," << endl << INDENT;
- s << INDENT << bases.join(separator) << ");" << endl << endl;
- }
-
- // Create type and insert it in the module or enclosing class.
- s << INDENT << "if (!Shiboken::ObjectType::introduceWrapperType(" << enclosingObjectVariable;
- s << ", \"" << metaClass->name() << "\", \"";
- // Original name
- s << metaClass->qualifiedCppName() << (isObjectType(classTypeEntry) ? "*" : "");
- s << "\"," << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "&" << pyTypeName;
-
- // Set destructor function
- if (!metaClass->isNamespace() && !metaClass->hasPrivateDestructor()) {
- QString dtorClassName = metaClass->qualifiedCppName();
- if ((avoidProtectedHack() && metaClass->hasProtectedDestructor()) || classTypeEntry->isValue())
- dtorClassName = wrapperName(metaClass);
- s << ", &Shiboken::callCppDestructor< ::" << dtorClassName << " >";
- } else if (metaClass->baseClass() || hasEnclosingClass) {
- s << ", 0";
- }
-
- // Base type
- if (metaClass->baseClass()) {
- s << ", (SbkObjectType*)" << cpythonTypeNameExt(metaClass->baseClass()->typeEntry());
- // The other base types
- if (metaClass->baseClassNames().size() > 1)
- s << ", " << pyTypeBasesVariable;
- else if (hasEnclosingClass)
- s << ", 0";
- } else if (hasEnclosingClass) {
- s << ", 0, 0";
- }
- if (hasEnclosingClass)
- s << ", true";
- s << ")) {" << endl;
- s << INDENT << "return;" << endl;
- }
- s << INDENT << '}' << endl << endl;
-
- // Register conversions for the type.
- writeConverterRegister(s, metaClass);
- s << endl;
-
- // class inject-code target/beginning
- if (!classTypeEntry->codeSnips().isEmpty()) {
- writeCodeSnips(s, classTypeEntry->codeSnips(), CodeSnip::Beginning, TypeSystem::TargetLangCode, metaClass);
- s << endl;
- }
-
- // Fill multiple inheritance data, if needed.
- const AbstractMetaClass* miClass = getMultipleInheritingClass(metaClass);
- if (miClass) {
- s << INDENT << "MultipleInheritanceInitFunction func = ";
- if (miClass == metaClass) {
- s << multipleInheritanceInitializerFunctionName(miClass) << ";" << endl;
- } else {
- s << "Shiboken::ObjectType::getMultipleIheritanceFunction(reinterpret_cast<SbkObjectType*>(";
- s << cpythonTypeNameExt(miClass->typeEntry()) << "));" << endl;
- }
- s << INDENT << "Shiboken::ObjectType::setMultipleIheritanceFunction(&";
- s << cpythonTypeName(metaClass) << ", func);" << endl;
- s << INDENT << "Shiboken::ObjectType::setCastFunction(&" << cpythonTypeName(metaClass);
- s << ", &" << cpythonSpecialCastFunctionName(metaClass) << ");" << endl;
- }
-
- // Set typediscovery struct or fill the struct of another one
- if (metaClass->isPolymorphic() && metaClass->baseClass()) {
- s << INDENT << "Shiboken::ObjectType::setTypeDiscoveryFunctionV2(&" << cpythonTypeName(metaClass);
- s << ", &" << cpythonBaseName(metaClass) << "_typeDiscovery);" << endl << endl;
- }
-
- AbstractMetaEnumList classEnums = metaClass->enums();
- foreach (AbstractMetaClass* innerClass, metaClass->innerClasses())
- lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass);
-
- ErrorCode errorCode("");
- writeEnumsInitialization(s, classEnums);
-
- if (metaClass->hasSignals())
- writeSignalInitialization(s, metaClass);
-
- // Write static fields
- foreach (const AbstractMetaField* field, metaClass->fields()) {
- if (!field->isStatic())
- continue;
- s << INDENT << "PyDict_SetItemString(" + cpythonTypeName(metaClass) + ".super.ht_type.tp_dict, \"";
- s << field->name() << "\", ";
- writeToPythonConversion(s, field->type(), metaClass, metaClass->qualifiedCppName() + "::" + field->name());
- s << ");" << endl;
- }
- s << endl;
-
- // class inject-code target/end
- if (!classTypeEntry->codeSnips().isEmpty()) {
- s << endl;
- writeCodeSnips(s, classTypeEntry->codeSnips(), CodeSnip::End, TypeSystem::TargetLangCode, metaClass);
- }
-
- if (usePySideExtensions()) {
- if (avoidProtectedHack() && shouldGenerateCppWrapper(metaClass))
- s << INDENT << wrapperName(metaClass) << "::pysideInitQtMetaTypes();\n";
- else
- writeInitQtMetaTypeFunctionBody(s, metaClass);
- }
-
- if (usePySideExtensions() && metaClass->isQObject()) {
- s << INDENT << "Shiboken::ObjectType::setSubTypeInitHook(&" << pyTypeName << ", &PySide::initQObjectSubType);" << endl;
- s << INDENT << "PySide::initDynamicMetaObject(&" << pyTypeName << ", &::" << metaClass->qualifiedCppName()
- << "::staticMetaObject, sizeof(::" << metaClass->qualifiedCppName() << "));" << endl;
- }
-
- s << '}' << endl;
-}
-
-void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream& s, const AbstractMetaClass* metaClass) const
-{
- // Gets all class name variants used on different possible scopes
- QStringList nameVariants;
- nameVariants << metaClass->name();
- const AbstractMetaClass* enclosingClass = metaClass->enclosingClass();
- while (enclosingClass) {
- if (enclosingClass->typeEntry()->generateCode())
- nameVariants << (enclosingClass->name() + "::" + nameVariants.last());
- enclosingClass = enclosingClass->enclosingClass();
- }
-
- const QString className = metaClass->qualifiedCppName();
- if (!metaClass->isNamespace() && !metaClass->isAbstract()) {
- // Qt metatypes are registered only on their first use, so we do this now.
- bool canBeValue = false;
- if (!isObjectType(metaClass)) {
- // check if there's a empty ctor
- foreach (AbstractMetaFunction* func, metaClass->functions()) {
- if (func->isConstructor() && !func->arguments().count()) {
- canBeValue = true;
- break;
- }
- }
- }
-
- if (canBeValue) {
- foreach (QString name, nameVariants)
- s << INDENT << "qRegisterMetaType< ::" << className << " >(\"" << name << "\");" << endl;
- }
- }
-
- foreach (AbstractMetaEnum* metaEnum, metaClass->enums()) {
- if (!metaEnum->isPrivate() && !metaEnum->isAnonymous()) {
- foreach (QString name, nameVariants)
- s << INDENT << "qRegisterMetaType< ::" << metaEnum->typeEntry()->qualifiedCppName() << " >(\"" << name << "::" << metaEnum->name() << "\");" << endl;
-
- if (metaEnum->typeEntry()->flags()) {
- QString n = metaEnum->typeEntry()->flags()->originalName();
- s << INDENT << "qRegisterMetaType< ::" << n << " >(\"" << n << "\");" << endl;
- }
- }
- }
-}
-
-void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- QString polymorphicExpr = metaClass->typeEntry()->polymorphicIdValue();
-
- s << "static void* " << cpythonBaseName(metaClass) << "_typeDiscovery(void* cptr, SbkObjectType* instanceType)\n{" << endl;
-
- if (!polymorphicExpr.isEmpty()) {
- polymorphicExpr = polymorphicExpr.replace("%1", " reinterpret_cast< ::" + metaClass->qualifiedCppName() + "*>(cptr)");
- s << INDENT << " if (" << polymorphicExpr << ")" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "return cptr;" << endl;
- }
- } else if (metaClass->isPolymorphic()) {
- AbstractMetaClassList ancestors = getAllAncestors(metaClass);
- foreach (AbstractMetaClass* ancestor, ancestors) {
- if (ancestor->baseClass())
- continue;
- if (ancestor->isPolymorphic()) {
- s << INDENT << "if (instanceType == reinterpret_cast<SbkObjectType*>(Shiboken::SbkType< ::"
- << ancestor->qualifiedCppName() << " >()))" << endl;
- Indentation indent(INDENT);
- s << INDENT << "return dynamic_cast< ::" << metaClass->qualifiedCppName()
- << "*>(reinterpret_cast< ::"<< ancestor->qualifiedCppName() << "*>(cptr));" << endl;
- } else {
- ReportHandler::warning(metaClass->qualifiedCppName() + " inherits from a non polymorphic type ("
- + ancestor->qualifiedCppName() + "), type discovery based on RTTI is "
- "impossible, write a polymorphic-id-expression for this type.");
- }
-
- }
- }
- s << INDENT << "return 0;" << endl;
- s << "}\n\n";
-}
-
-void CppGenerator::writeSetattroFunction(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- s << "static int " << cpythonSetattroFunctionName(metaClass) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* name, PyObject* value)" << endl;
- s << '{' << endl;
- if (usePySideExtensions()) {
- s << INDENT << "Shiboken::AutoDecRef pp(reinterpret_cast<PyObject*>(PySide::Property::getObject(" PYTHON_SELF_VAR ", name)));" << endl;
- s << INDENT << "if (!pp.isNull())" << endl;
- Indentation indent(INDENT);
- s << INDENT << "return PySide::Property::setValue(reinterpret_cast<PySideProperty*>(pp.object()), " PYTHON_SELF_VAR ", value);" << endl;
- }
- s << INDENT << "return PyObject_GenericSetAttr(" PYTHON_SELF_VAR ", name, value);" << endl;
- s << '}' << endl;
-}
-
-void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- s << "static PyObject* " << cpythonGetattroFunctionName(metaClass) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* name)" << endl;
- s << '{' << endl;
-
- QString getattrFunc;
- if (usePySideExtensions() && metaClass->isQObject()) {
- AbstractMetaClass* qobjectClass = classes().findClass("QObject");
- getattrFunc = QString("PySide::getMetaDataFromQObject(%1, " PYTHON_SELF_VAR ", name)")
- .arg(cpythonWrapperCPtr(qobjectClass, PYTHON_SELF_VAR));
- } else {
- getattrFunc = "PyObject_GenericGetAttr(" PYTHON_SELF_VAR ", name)";
- }
-
- if (classNeedsGetattroFunction(metaClass)) {
- s << INDENT << "if (" PYTHON_SELF_VAR ") {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "// Search the method in the instance dict" << endl;
- s << INDENT << "if (reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR ")->ob_dict) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyObject* meth = PyDict_GetItem(reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR ")->ob_dict, name);" << endl;
- s << INDENT << "if (meth) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "Py_INCREF(meth);" << endl;
- s << INDENT << "return meth;" << endl;
- }
- s << INDENT << '}' << endl;
- }
- s << INDENT << '}' << endl;
- s << INDENT << "// Search the method in the type dict" << endl;
- s << INDENT << "if (Shiboken::Object::isUserType(" PYTHON_SELF_VAR ")) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyObject* meth = PyDict_GetItem(" PYTHON_SELF_VAR "->ob_type->tp_dict, name);" << endl;
- s << INDENT << "if (meth)" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "return PyFunction_Check(meth) ? SBK_PyMethod_New(meth, " PYTHON_SELF_VAR ") : " << getattrFunc << ';' << endl;
- }
- }
- s << INDENT << '}' << endl;
-
- foreach (const AbstractMetaFunction* func, getMethodsWithBothStaticAndNonStaticMethods(metaClass)) {
- s << INDENT << "if (Shiboken::String::compare(name, \"" << func->name() << "\") == 0)" << endl;
- Indentation indent(INDENT);
- s << INDENT << "return PyCFunction_NewEx(&" << cpythonMethodDefinitionName(func) << ", " PYTHON_SELF_VAR ", 0);" << endl;
- }
- }
- s << INDENT << '}' << endl;
- }
- s << INDENT << "return " << getattrFunc << ';' << endl;
- s << '}' << endl;
-}
-
-void CppGenerator::finishGeneration()
-{
- //Generate CPython wrapper file
- QString classInitDecl;
- QTextStream s_classInitDecl(&classInitDecl);
- QString classPythonDefines;
- QTextStream s_classPythonDefines(&classPythonDefines);
-
- QSet<Include> includes;
- QString globalFunctionImpl;
- QTextStream s_globalFunctionImpl(&globalFunctionImpl);
- QString globalFunctionDecl;
- QTextStream s_globalFunctionDef(&globalFunctionDecl);
-
- Indentation indent(INDENT);
-
- foreach (AbstractMetaFunctionList globalOverloads, getFunctionGroups().values()) {
- AbstractMetaFunctionList overloads;
- foreach (AbstractMetaFunction* func, globalOverloads) {
- if (!func->isModifiedRemoved()) {
- overloads.append(func);
- if (func->typeEntry())
- includes << func->typeEntry()->include();
- }
- }
-
- if (overloads.isEmpty())
- continue;
-
- writeMethodWrapper(s_globalFunctionImpl, overloads);
- writeMethodDefinition(s_globalFunctionDef, overloads);
- }
-
- //this is a temporary solution before new type revison implementation
- //We need move QMetaObject register before QObject
- AbstractMetaClassList lst = classes();
- AbstractMetaClass* klassQObject = lst.findClass("QObject");
- AbstractMetaClass* klassQMetaObject = lst.findClass("QMetaObject");
- if (klassQObject && klassQMetaObject) {
- lst.removeAll(klassQMetaObject);
- int indexOf = lst.indexOf(klassQObject);
- lst.insert(indexOf, klassQMetaObject);
- }
-
- foreach (const AbstractMetaClass* cls, lst) {
- if (!shouldGenerate(cls))
- continue;
-
- s_classInitDecl << "void init_" << cls->qualifiedCppName().replace("::", "_") << "(PyObject* module);" << endl;
-
- QString defineStr = "init_" + cls->qualifiedCppName().replace("::", "_");
-
- if (cls->enclosingClass() && (cls->enclosingClass()->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass))
- defineStr += "(" + cpythonTypeNameExt(cls->enclosingClass()->typeEntry()) +"->tp_dict);";
- else
- defineStr += "(module);";
- s_classPythonDefines << INDENT << defineStr << endl;
- }
-
- QString moduleFileName(outputDirectory() + "/" + subDirectoryForPackage(packageName()));
- moduleFileName += "/" + moduleName().toLower() + "_module_wrapper.cpp";
-
- QFile file(moduleFileName);
- verifyDirectoryFor(file);
- if (!file.open(QFile::WriteOnly)) {
- ReportHandler::warning("Error writing file: " + moduleFileName);
- return;
- }
-
- QTextStream s(&file);
-
- // write license comment
- s << licenseComment() << endl;
-
- s << "#include <sbkpython.h>" << endl;
- s << "#include <shiboken.h>" << endl;
- s << "#include <algorithm>" << endl;
- if (usePySideExtensions())
- s << "#include <pyside.h>" << endl;
-
- s << "#include \"" << getModuleHeaderFileName() << '"' << endl << endl;
- foreach (const Include& include, includes)
- s << include;
- s << endl;
-
- // Global enums
- AbstractMetaEnumList globalEnums = this->globalEnums();
- foreach (const AbstractMetaClass* metaClass, classes()) {
- const AbstractMetaClass* encClass = metaClass->enclosingClass();
- if (encClass && encClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass)
- continue;
- lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass);
- }
-
- TypeDatabase* typeDb = TypeDatabase::instance();
- TypeSystemTypeEntry* moduleEntry = reinterpret_cast<TypeSystemTypeEntry*>(typeDb->findType(packageName()));
-
- //Extra includes
- s << endl << "// Extra includes" << endl;
- QList<Include> extraIncludes;
- if (moduleEntry)
- extraIncludes = moduleEntry->extraIncludes();
- foreach (AbstractMetaEnum* cppEnum, globalEnums)
- extraIncludes.append(cppEnum->typeEntry()->extraIncludes());
- qSort(extraIncludes.begin(), extraIncludes.end());
- foreach (const Include& inc, extraIncludes)
- s << inc;
- s << endl;
-
- s << "// Current module's type array." << endl;
- s << "PyTypeObject** " << cppApiVariableName() << ';' << endl;
-
- s << "// Current module's converter array." << endl;
- s << "SbkConverter** " << convertersVariableName() << ';' << endl;
-
- CodeSnipList snips;
- if (moduleEntry)
- snips = moduleEntry->codeSnips();
-
- // module inject-code native/beginning
- if (!snips.isEmpty()) {
- writeCodeSnips(s, snips, CodeSnip::Beginning, TypeSystem::NativeCode);
- s << endl;
- }
-
- // cleanup staticMetaObject attribute
- if (usePySideExtensions()) {
- s << "void cleanTypesAttributes(void) {" << endl;
- s << INDENT << "for (int i = 0, imax = SBK_" << moduleName() << "_IDX_COUNT; i < imax; i++) {" << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "PyObject *pyType = reinterpret_cast<PyObject*>(" << cppApiVariableName() << "[i]);" << endl;
- s << INDENT << "if (pyType && PyObject_HasAttrString(pyType, \"staticMetaObject\"))"<< endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "PyObject_SetAttrString(pyType, \"staticMetaObject\", Py_None);" << endl;
- }
- }
- s << INDENT << "}" << endl;
- s << "}" << endl;
- }
-
- s << "// Global functions ";
- s << "------------------------------------------------------------" << endl;
- s << globalFunctionImpl << endl;
-
- s << "static PyMethodDef " << moduleName() << "_methods[] = {" << endl;
- s << globalFunctionDecl;
- s << INDENT << "{0} // Sentinel" << endl << "};" << endl << endl;
-
- s << "// Classes initialization functions ";
- s << "------------------------------------------------------------" << endl;
- s << classInitDecl << endl;
-
- if (!globalEnums.isEmpty()) {
- QString converterImpl;
- QTextStream convImpl(&converterImpl);
-
- s << "// Enum definitions ";
- s << "------------------------------------------------------------" << endl;
- foreach (const AbstractMetaEnum* cppEnum, globalEnums) {
- if (cppEnum->isAnonymous() || cppEnum->isPrivate())
- continue;
- writeEnumConverterFunctions(s, cppEnum);
- s << endl;
- }
-
- if (!converterImpl.isEmpty()) {
- s << "// Enum converters ";
- s << "------------------------------------------------------------" << endl;
- s << "namespace Shiboken" << endl << '{' << endl;
- s << converterImpl << endl;
- s << "} // namespace Shiboken" << endl << endl;
- }
- }
-
- QStringList requiredModules = typeDb->requiredTargetImports();
- if (!requiredModules.isEmpty())
- s << "// Required modules' type and converter arrays." << endl;
- foreach (const QString& requiredModule, requiredModules) {
- s << "PyTypeObject** " << cppApiVariableName(requiredModule) << ';' << endl;
- s << "SbkConverter** " << convertersVariableName(requiredModule) << ';' << endl;
- }
- s << endl;
-
- s << "// Module initialization ";
- s << "------------------------------------------------------------" << endl;
- ExtendedConverterData extendedConverters = getExtendedConverters();
- if (!extendedConverters.isEmpty()) {
- s << endl << "// Extended Converters." << endl << endl;
- foreach (const TypeEntry* externalType, extendedConverters.keys()) {
- s << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl;
- foreach (const AbstractMetaClass* sourceClass, extendedConverters[externalType]) {
- AbstractMetaType* sourceType = buildAbstractMetaTypeFromAbstractMetaClass(sourceClass);
- AbstractMetaType* targetType = buildAbstractMetaTypeFromTypeEntry(externalType);
- writePythonToCppConversionFunctions(s, sourceType, targetType);
- }
- }
- }
-
- QList<const CustomConversion*> typeConversions = getPrimitiveCustomConversions();
- if (!typeConversions.isEmpty()) {
- s << endl << "// Primitive Type converters." << endl << endl;
- foreach (const CustomConversion* conversion, typeConversions) {
- s << "// C++ to Python conversion for type '" << conversion->ownerType()->qualifiedCppName() << "'." << endl;
- writeCppToPythonFunction(s, conversion);
- writeCustomConverterFunctions(s, conversion);
- }
- s << endl;
- }
-
- QList<const AbstractMetaType*> containers = instantiatedContainers();
- if (!containers.isEmpty()) {
- s << "// Container Type converters." << endl << endl;
- foreach (const AbstractMetaType* container, containers) {
- s << "// C++ to Python conversion for type '" << container->cppSignature() << "'." << endl;
- writeContainerConverterFunctions(s, container);
- }
- s << endl;
- }
-
- s << "#if defined _WIN32 || defined __CYGWIN__" << endl;
- s << " #define SBK_EXPORT_MODULE __declspec(dllexport)" << endl;
- s << "#elif __GNUC__ >= 4" << endl;
- s << " #define SBK_EXPORT_MODULE __attribute__ ((visibility(\"default\")))" << endl;
- s << "#else" << endl;
- s << " #define SBK_EXPORT_MODULE" << endl;
- s << "#endif" << endl << endl;
-
- s << "#ifdef IS_PY3K" << endl;
- s << "static struct PyModuleDef moduledef = {" << endl;
- s << " /* m_base */ PyModuleDef_HEAD_INIT," << endl;
- s << " /* m_name */ \"" << moduleName() << "\"," << endl;
- s << " /* m_doc */ 0," << endl;
- s << " /* m_size */ -1," << endl;
- s << " /* m_methods */ " << moduleName() << "_methods," << endl;
- s << " /* m_reload */ 0," << endl;
- s << " /* m_traverse */ 0," << endl;
- s << " /* m_clear */ 0," << endl;
- s << " /* m_free */ 0" << endl;
- s << "};" << endl << endl;
- s << "#endif" << endl;
- s << "SBK_MODULE_INIT_FUNCTION_BEGIN(" << moduleName() << ")" << endl;
-
- ErrorCode errorCode("SBK_MODULE_INIT_ERROR");
- // module inject-code target/beginning
- if (!snips.isEmpty()) {
- writeCodeSnips(s, snips, CodeSnip::Beginning, TypeSystem::TargetLangCode);
- s << endl;
- }
-
- foreach (const QString& requiredModule, typeDb->requiredTargetImports()) {
- s << INDENT << "{" << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "Shiboken::AutoDecRef requiredModule(Shiboken::Module::import(\"" << requiredModule << "\"));" << endl;
- s << INDENT << "if (requiredModule.isNull())" << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "SBK_MODULE_INIT_ERROR;" << endl;
- }
- s << INDENT << cppApiVariableName(requiredModule) << " = Shiboken::Module::getTypes(requiredModule);" << endl;
- s << INDENT << convertersVariableName(requiredModule) << " = Shiboken::Module::getTypeConverters(requiredModule);" << endl;
- }
- s << INDENT << "}" << endl << endl;
- }
-
- int maxTypeIndex = getMaxTypeIndex();
- if (maxTypeIndex) {
- s << INDENT << "// Create an array of wrapper types for the current module." << endl;
- s << INDENT << "static PyTypeObject* cppApi[SBK_" << moduleName() << "_IDX_COUNT];" << endl;
- s << INDENT << cppApiVariableName() << " = cppApi;" << endl << endl;
- }
-
- s << INDENT << "// Create an array of primitive type converters for the current module." << endl;
- s << INDENT << "static SbkConverter* sbkConverters[SBK_" << moduleName() << "_CONVERTERS_IDX_COUNT" << "];" << endl;
- s << INDENT << convertersVariableName() << " = sbkConverters;" << endl << endl;
-
- s << "#ifdef IS_PY3K" << endl;
- s << INDENT << "PyObject* module = Shiboken::Module::create(\"" << moduleName() << "\", &moduledef);" << endl;
- s << "#else" << endl;
- s << INDENT << "PyObject* module = Shiboken::Module::create(\"" << moduleName() << "\", ";
- s << moduleName() << "_methods);" << endl;
- s << "#endif" << endl << endl;
-
- //s << INDENT << "// Initialize converters for primitive types." << endl;
- //s << INDENT << "initConverters();" << endl << endl;
-
- s << INDENT << "// Initialize classes in the type system" << endl;
- s << classPythonDefines;
-
- if (!typeConversions.isEmpty()) {
- s << endl;
- foreach (const CustomConversion* conversion, typeConversions) {
- writePrimitiveConverterInitialization(s, conversion);
- s << endl;
- }
- }
-
- if (!containers.isEmpty()) {
- s << endl;
- foreach (const AbstractMetaType* container, containers) {
- writeContainerConverterInitialization(s, container);
- s << endl;
- }
- }
-
- if (!extendedConverters.isEmpty()) {
- s << endl;
- foreach (const TypeEntry* externalType, extendedConverters.keys()) {
- writeExtendedConverterInitialization(s, externalType, extendedConverters[externalType]);
- s << endl;
- }
- }
-
- writeEnumsInitialization(s, globalEnums);
-
- s << INDENT << "// Register primitive types converters." << endl;
- foreach(const PrimitiveTypeEntry* pte, primitiveTypes()) {
- if (!pte->generateCode() || !pte->isCppPrimitive())
- continue;
- const TypeEntry* alias = pte->basicAliasedTypeEntry();
- if (!alias)
- continue;
- QString converter = converterObject(alias);
- QStringList cppSignature = pte->qualifiedCppName().split("::", QString::SkipEmptyParts);
- while (!cppSignature.isEmpty()) {
- QString signature = cppSignature.join("::");
- s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << signature << "\");" << endl;
- cppSignature.removeFirst();
- }
- }
- // Register type resolver for all containers found in signals.
- QSet<QByteArray> typeResolvers;
- foreach (AbstractMetaClass* metaClass, classes()) {
- if (!metaClass->isQObject() || !metaClass->typeEntry()->generateCode())
- continue;
- foreach (AbstractMetaFunction* func, metaClass->functions()) {
- if (func->isSignal()) {
- foreach (AbstractMetaArgument* arg, func->arguments()) {
- if (arg->type()->isContainer()) {
- QString value = translateType(arg->type(), metaClass, ExcludeConst | ExcludeReference);
- if (value.startsWith("::"))
- value.remove(0, 2);
- typeResolvers << SBK_NORMALIZED_TYPE(value.toAscii().constData());
- }
- }
- }
- }
- }
-
- s << endl;
- if (maxTypeIndex)
- s << INDENT << "Shiboken::Module::registerTypes(module, " << cppApiVariableName() << ");" << endl;
- s << INDENT << "Shiboken::Module::registerTypeConverters(module, " << convertersVariableName() << ");" << endl;
-
- s << endl << INDENT << "if (PyErr_Occurred()) {" << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "PyErr_Print();" << endl;
- s << INDENT << "Py_FatalError(\"can't initialize module " << moduleName() << "\");" << endl;
- }
- s << INDENT << '}' << endl;
-
- // module inject-code target/end
- if (!snips.isEmpty()) {
- writeCodeSnips(s, snips, CodeSnip::End, TypeSystem::TargetLangCode);
- s << endl;
- }
-
- // module inject-code native/end
- if (!snips.isEmpty()) {
- writeCodeSnips(s, snips, CodeSnip::End, TypeSystem::NativeCode);
- s << endl;
- }
-
- if (usePySideExtensions()) {
- foreach (AbstractMetaEnum* metaEnum, globalEnums)
- if (!metaEnum->isAnonymous()) {
- s << INDENT << "qRegisterMetaType< ::" << metaEnum->typeEntry()->qualifiedCppName() << " >(\"" << metaEnum->name() << "\");" << endl;
- }
-
- // cleanup staticMetaObject attribute
- s << INDENT << "PySide::registerCleanupFunction(cleanTypesAttributes);" << endl;
- }
-
- s << "SBK_MODULE_INIT_FUNCTION_END" << endl;
-}
-
-static ArgumentOwner getArgumentOwner(const AbstractMetaFunction* func, int argIndex)
-{
- ArgumentOwner argOwner = func->argumentOwner(func->ownerClass(), argIndex);
- if (argOwner.index == ArgumentOwner::InvalidIndex)
- argOwner = func->argumentOwner(func->declaringClass(), argIndex);
- return argOwner;
-}
-
-bool CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool useHeuristicPolicy)
-{
- const int numArgs = func->arguments().count();
- bool ctorHeuristicEnabled = func->isConstructor() && useCtorHeuristic() && useHeuristicPolicy;
-
- bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(OverloadData(getFunctionGroups(func->implementingClass())[func->name()], this));
-
- ArgumentOwner argOwner = getArgumentOwner(func, argIndex);
- ArgumentOwner::Action action = argOwner.action;
- int parentIndex = argOwner.index;
- int childIndex = argIndex;
- if (ctorHeuristicEnabled && argIndex > 0 && numArgs) {
- AbstractMetaArgument* arg = func->arguments().at(argIndex-1);
- if (arg->name() == "parent" && isObjectType(arg->type())) {
- action = ArgumentOwner::Add;
- parentIndex = argIndex;
- childIndex = -1;
- }
- }
-
- QString parentVariable;
- QString childVariable;
- if (action != ArgumentOwner::Invalid) {
- if (!usePyArgs && argIndex > 1)
- ReportHandler::warning("Argument index for parent tag out of bounds: "+func->signature());
-
- if (action == ArgumentOwner::Remove) {
- parentVariable = "Py_None";
- } else {
- if (parentIndex == 0)
- parentVariable = PYTHON_RETURN_VAR;
- else if (parentIndex == -1)
- parentVariable = PYTHON_SELF_VAR;
- else
- parentVariable = usePyArgs ? QString(PYTHON_ARGS "[%1]").arg(QString::number(parentIndex-1)) : PYTHON_ARG;
- }
-
- if (childIndex == 0)
- childVariable = PYTHON_RETURN_VAR;
- else if (childIndex == -1)
- childVariable = PYTHON_SELF_VAR;
- else
- childVariable = usePyArgs ? QString(PYTHON_ARGS "[%1]").arg(QString::number(childIndex-1)) : PYTHON_ARG;
-
- s << INDENT << "Shiboken::Object::setParent(" << parentVariable << ", " << childVariable << ");\n";
- return true;
- }
-
- return false;
-}
-
-void CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool useHeuristicForReturn)
-{
- const int numArgs = func->arguments().count();
-
- // -1 = return value
- // 0 = self
- // 1..n = func. args.
- for (int i = -1; i <= numArgs; ++i)
- writeParentChildManagement(s, func, i, useHeuristicForReturn);
-
- if (useHeuristicForReturn)
- writeReturnValueHeuristics(s, func);
-}
-
-void CppGenerator::writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self)
-{
- AbstractMetaType *type = func->type();
- if (!useReturnValueHeuristic()
- || !func->ownerClass()
- || !type
- || func->isStatic()
- || func->isConstructor()
- || !func->typeReplaced(0).isEmpty()) {
- return;
- }
-
- ArgumentOwner argOwner = getArgumentOwner(func, ArgumentOwner::ReturnIndex);
- if (argOwner.action == ArgumentOwner::Invalid || argOwner.index != ArgumentOwner::ThisIndex) {
- if (isPointerToWrapperType(type))
- s << INDENT << "Shiboken::Object::setParent(" << self << ", " PYTHON_RETURN_VAR ");" << endl;
- }
-}
-
-void CppGenerator::writeHashFunction(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- s << "static Py_hash_t " << cpythonBaseName(metaClass) << "_HashFunc(PyObject* self) {" << endl;
- writeCppSelfDefinition(s, metaClass);
- s << INDENT << "return " << metaClass->typeEntry()->hashFunction() << '(';
- s << (isObjectType(metaClass) ? "" : "*") << CPP_SELF_VAR << ");" << endl;
- s << '}' << endl << endl;
-}
-
-void CppGenerator::writeStdListWrapperMethods(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- ErrorCode errorCode(0);
-
- // __len__
- s << "Py_ssize_t " << cpythonBaseName(metaClass->typeEntry()) << "__len__(PyObject* " PYTHON_SELF_VAR ")" << endl;
- s << '{' << endl;
- writeCppSelfDefinition(s, metaClass);
- s << INDENT << "return " CPP_SELF_VAR "->size();" << endl;
- s << '}' << endl;
-
- // __getitem__
- s << "PyObject* " << cpythonBaseName(metaClass->typeEntry()) << "__getitem__(PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i)" << endl;
- s << '{' << endl;
- writeCppSelfDefinition(s, metaClass);
- writeIndexError(s, "index out of bounds");
-
- s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " CPP_SELF_VAR "->begin();" << endl;
- s << INDENT << "for (Py_ssize_t pos = 0; pos < _i; pos++) _item++;" << endl;
-
- const AbstractMetaType* itemType = metaClass->templateBaseClassInstantiations().first();
-
- s << INDENT << "return ";
- writeToPythonConversion(s, itemType, metaClass, "*_item");
- s << ';' << endl;
- s << '}' << endl;
-
- // __setitem__
- ErrorCode errorCode2(-1);
- s << "int " << cpythonBaseName(metaClass->typeEntry()) << "__setitem__(PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i, PyObject* pyArg)" << endl;
- s << '{' << endl;
- writeCppSelfDefinition(s, metaClass);
- writeIndexError(s, "list assignment index out of range");
-
- s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ';' << endl;
- s << INDENT << "if (!";
- writeTypeCheck(s, itemType, "pyArg", isNumber(itemType->typeEntry()));
- s << ") {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_TypeError, \"attributed value with wrong type, '";
- s << itemType->name() << "' or other convertible type expected\");" << endl;
- s << INDENT << "return -1;" << endl;
- }
- s << INDENT << '}' << endl;
- writeArgumentConversion(s, itemType, "cppValue", "pyArg", metaClass);
-
- s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " CPP_SELF_VAR "->begin();" << endl;
- s << INDENT << "for (Py_ssize_t pos = 0; pos < _i; pos++) _item++;" << endl;
- s << INDENT << "*_item = cppValue;" << endl;
- s << INDENT << "return 0;" << endl;
- s << '}' << endl;
-}
-void CppGenerator::writeIndexError(QTextStream& s, const QString& errorMsg)
-{
- s << INDENT << "if (_i < 0 || _i >= (Py_ssize_t) " CPP_SELF_VAR "->size()) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_IndexError, \"" << errorMsg << "\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
- }
- s << INDENT << '}' << endl;
-}
-
-QString CppGenerator::writeReprFunction(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- QString funcName = cpythonBaseName(metaClass) + "__repr__";
- s << "extern \"C\"" << endl;
- s << '{' << endl;
- s << "static PyObject* " << funcName << "(PyObject* self)" << endl;
- s << '{' << endl;
- writeCppSelfDefinition(s, metaClass);
- s << INDENT << "QBuffer buffer;" << endl;
- s << INDENT << "buffer.open(QBuffer::ReadWrite);" << endl;
- s << INDENT << "QDebug dbg(&buffer);" << endl;
- s << INDENT << "dbg << " << (metaClass->typeEntry()->isValue() ? "*" : "") << CPP_SELF_VAR ";" << endl;
- s << INDENT << "buffer.close();" << endl;
- s << INDENT << "QByteArray str = buffer.data();" << endl;
- s << INDENT << "int idx = str.indexOf('(');" << endl;
- s << INDENT << "if (idx >= 0)" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "str.replace(0, idx, Py_TYPE(self)->tp_name);" << endl;
- }
- s << INDENT << "PyObject* mod = PyDict_GetItemString(Py_TYPE(self)->tp_dict, \"__module__\");" << endl;
- s << INDENT << "if (mod)" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "return Shiboken::String::fromFormat(\"<%s.%s at %p>\", Shiboken::String::toCString(mod), str.constData(), self);" << endl;
- }
- s << INDENT << "else" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "return Shiboken::String::fromFormat(\"<%s at %p>\", str.constData(), self);" << endl;
- }
- s << '}' << endl;
- s << "} // extern C" << endl << endl;;
- return funcName;
-}
diff --git a/generators/shiboken/cppgenerator.h b/generators/shiboken/cppgenerator.h
deleted file mode 100644
index 625514996..000000000
--- a/generators/shiboken/cppgenerator.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * This file is part of the Shiboken Python Bindings Generator project.
- *
- * Copyright (C) 2009-2010 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
- *
- */
-
-#ifndef CPPGENERATOR_H
-#define CPPGENERATOR_H
-
-#include "shibokengenerator.h"
-#include "overloaddata.h"
-
-/**
- * The CppGenerator generate the implementations of C++ bindings classes.
- */
-class CppGenerator : public ShibokenGenerator
-{
-public:
- CppGenerator();
-protected:
- QString fileNameForClass(const AbstractMetaClass* metaClass) const;
- QList<AbstractMetaFunctionList> filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass,
- uint query);
- void generateClass(QTextStream& s, const AbstractMetaClass* metaClass);
- void finishGeneration();
-
-private:
- void writeConstructorNative(QTextStream& s, const AbstractMetaFunction* func);
- void writeDestructorNative(QTextStream& s, const AbstractMetaClass* metaClass);
-
- QString getVirtualFunctionReturnTypeName(const AbstractMetaFunction* func);
- void writeVirtualMethodNative(QTextStream& s, const AbstractMetaFunction* func);
-
- void writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeMetaCast(QTextStream& s, const AbstractMetaClass* metaClass);
-
- void writeEnumConverterFunctions(QTextStream& s, const TypeEntry* enumType);
- void writeEnumConverterFunctions(QTextStream& s, const AbstractMetaEnum* metaEnum);
- void writeConverterFunctions(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeCustomConverterFunctions(QTextStream& s, const CustomConversion* customConversion);
- void writeConverterRegister(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeCustomConverterRegister(QTextStream& s, const CustomConversion* customConversion, const QString& converterVar);
- void writeContainerConverterRegister(QTextStream& s, const AbstractMetaType* container, const QString& converterVar);
-
- void writeContainerConverterFunctions(QTextStream& s, const AbstractMetaType* containerType);
-
- void writeMethodWrapperPreamble(QTextStream& s, OverloadData& overloadData);
- void writeConstructorWrapper(QTextStream& s, const AbstractMetaFunctionList overloads);
- void writeDestructorWrapper(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeMethodWrapper(QTextStream& s, const AbstractMetaFunctionList overloads);
- void writeArgumentsInitializer(QTextStream& s, OverloadData& overloadData);
- void writeCppSelfDefinition(QTextStream& s, const AbstractMetaFunction* func, bool hasStaticOverload = false);
- void writeCppSelfDefinition(QTextStream& s, const AbstractMetaClass* metaClass, bool hasStaticOverload = false, bool cppSelfAsReference = false);
-
- void writeErrorSection(QTextStream& s, OverloadData& overloadData);
- void writeFunctionReturnErrorCheckSection(QTextStream& s, bool hasReturnValue = true);
-
- /// Writes the check section for the validity of wrapped C++ objects.
- void writeInvalidPyObjectCheck(QTextStream& s, const QString& pyObj);
-
- void writeTypeCheck(QTextStream& s, const AbstractMetaType* argType, QString argumentName, bool isNumber = false, QString customType = "", bool rejectNull = false);
- void writeTypeCheck(QTextStream& s, const OverloadData* overloadData, QString argumentName);
-
- void writeTypeDiscoveryFunction(QTextStream& s, const AbstractMetaClass* metaClass);
-
- void writeSetattroFunction(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeGetattroFunction(QTextStream& s, const AbstractMetaClass* metaClass);
-
- /**
- * Writes Python to C++ conversions for arguments on Python wrappers.
- * If implicit conversions, and thus new object allocation, are needed,
- * code to deallocate a possible new instance is also generated.
- * \param s text stream to write
- * \param argType a pointer to the argument type to be converted
- * \param argName C++ argument name
- * \param pyArgName Python argument name
- * \param context the current meta class
- * \param defaultValue an optional default value to be used instead of the conversion result
- * \param castArgumentAsUnused if true the converted argument is cast as unused to avoid compiler warnings
- */
- void writeArgumentConversion(QTextStream& s, const AbstractMetaType* argType,
- const QString& argName, const QString& pyArgName,
- const AbstractMetaClass* context = 0,
- const QString& defaultValue = QString(),
- bool castArgumentAsUnused = false);
-
- /**
- * Returns the AbstractMetaType for a function argument.
- * If the argument type was modified in the type system, this method will
- * try to build a new type based on the type name defined in the type system.
- * \param func The function which owns the argument.
- * \param argPos Argument position in the function signature.
- * Note that the position 0 represents the return value, and the function
- * parameters start counting on 1.
- * \param newType It is set to true if the type returned is a new object that must be deallocated.
- * \return The type of the argument indicated by \p argPos.
- */
- const AbstractMetaType* getArgumentType(const AbstractMetaFunction* func, int argPos);
-
- void writePythonToCppTypeConversion(QTextStream& s,
- const AbstractMetaType* type,
- const QString& pyIn,
- const QString& cppOut,
- const AbstractMetaClass* context = 0,
- const QString& defaultValue = QString());
-
- /// Writes the conversion rule for arguments of regular and virtual methods.
- void writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language);
- /// Writes the conversion rule for the return value of a method.
- void writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language, const QString& outputVar);
-
- /**
- * Set the Python method wrapper return value variable to Py_None if
- * there are return types different from void in any of the other overloads
- * for the function passed as parameter.
- * \param s text stream to write
- * \param func a pointer to the function that will possibly return Py_None
- * \param thereIsReturnValue indicates if the return type of any of the other overloads
- * for this function is different from 'void'
- */
- void writeNoneReturn(QTextStream& s, const AbstractMetaFunction* func, bool thereIsReturnValue);
-
- /**
- * Writes the Python function wrapper overload decisor that selects which C++
- * method/function to call with the received Python arguments.
- * \param s text stream to write
- * \param overloadData the overload data describing all the possible overloads for the function/method
- */
- void writeOverloadedFunctionDecisor(QTextStream& s, const OverloadData& overloadData);
- /// Recursive auxiliar method to the other writeOverloadedFunctionDecisor.
- void writeOverloadedFunctionDecisorEngine(QTextStream& s, const OverloadData* parentOverloadData);
-
- /// Writes calls to all the possible method/function overloads.
- void writeFunctionCalls(QTextStream& s, const OverloadData& overloadData);
-
- /// Writes the call to a single function usually from a collection of overloads.
- void writeSingleFunctionCall(QTextStream& s, const OverloadData& overloadData, const AbstractMetaFunction* func);
-
- /// Returns the name of a C++ to Python conversion function.
- static QString cppToPythonFunctionName(const QString& sourceTypeName, QString targetTypeName = QString());
-
- /// Returns the name of a Python to C++ conversion function.
- static QString pythonToCppFunctionName(const QString& sourceTypeName, const QString& targetTypeName);
- static QString pythonToCppFunctionName(const AbstractMetaType* sourceType, const AbstractMetaType* targetType);
- static QString pythonToCppFunctionName(const CustomConversion::TargetToNativeConversion* toNative, const TypeEntry* targetType);
-
- /// Returns the name of a Python to C++ convertible check function.
- static QString convertibleToCppFunctionName(const QString& sourceTypeName, const QString& targetTypeName);
- static QString convertibleToCppFunctionName(const AbstractMetaType* sourceType, const AbstractMetaType* targetType);
- static QString convertibleToCppFunctionName(const CustomConversion::TargetToNativeConversion* toNative, const TypeEntry* targetType);
-
- /// Writes a C++ to Python conversion function.
- void writeCppToPythonFunction(QTextStream& s, const QString& code, const QString& sourceTypeName, QString targetTypeName = QString());
- void writeCppToPythonFunction(QTextStream& s, const CustomConversion* customConversion);
- void writeCppToPythonFunction(QTextStream& s, const AbstractMetaType* containerType);
-
- /// Writes a Python to C++ conversion function.
- void writePythonToCppFunction(QTextStream& s, const QString& code, const QString& sourceTypeName, const QString& targetTypeName);
-
- /// Writes a Python to C++ convertible check function.
- void writeIsPythonConvertibleToCppFunction(QTextStream& s,
- const QString& sourceTypeName,
- const QString& targetTypeName,
- const QString& condition,
- QString pythonToCppFuncName = QString(),
- bool acceptNoneAsCppNull = false);
-
- /// Writes a pair of Python to C++ conversion and check functions.
- void writePythonToCppConversionFunctions(QTextStream& s,
- const AbstractMetaType* sourceType,
- const AbstractMetaType* targetType,
- QString typeCheck = QString(),
- QString conversion = QString(),
- QString preConversion = QString());
- /// Writes a pair of Python to C++ conversion and check functions for implicit conversions.
- void writePythonToCppConversionFunctions(QTextStream& s,
- const CustomConversion::TargetToNativeConversion* toNative,
- const TypeEntry* targetType);
-
- /// Writes a pair of Python to C++ conversion and check functions for instantiated container types.
- void writePythonToCppConversionFunctions(QTextStream& s, const AbstractMetaType* containerType);
-
- void writeAddPythonToCppConversion(QTextStream& s, const QString& converterVar, const QString& pythonToCppFunc, const QString& isConvertibleFunc);
-
- void writeNamedArgumentResolution(QTextStream& s, const AbstractMetaFunction* func, bool usePyArgs);
-
- /// Returns a string containing the name of an argument for the given function and argument index.
- QString argumentNameFromIndex(const AbstractMetaFunction* func, int argIndex, const AbstractMetaClass** wrappedClass);
- void writeMethodCall(QTextStream& s, const AbstractMetaFunction* func, int maxArgs = 0);
-
- void writeClassRegister(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeClassDefinition(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeMethodDefinitionEntry(QTextStream& s, const AbstractMetaFunctionList overloads);
- void writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList overloads);
-
- /// Writes the implementation of all methods part of python sequence protocol
- void writeSequenceMethods(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeTypeAsSequenceDefinition(QTextStream& s, const AbstractMetaClass* metaClass);
-
- /// Writes the PyMappingMethods structure for types that supports the python mapping protocol.
- void writeTypeAsMappingDefinition(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeMappingMethods(QTextStream& s, const AbstractMetaClass* metaClass);
-
- void writeTypeAsNumberDefinition(QTextStream& s, const AbstractMetaClass* metaClass);
-
- void writeTpTraverseFunction(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeTpClearFunction(QTextStream& s, const AbstractMetaClass* metaClass);
-
- void writeCopyFunction(QTextStream& s, const AbstractMetaClass *metaClass);
-
- void writeGetterFunction(QTextStream& s, const AbstractMetaField* metaField);
- void writeSetterFunction(QTextStream& s, const AbstractMetaField* metaField);
-
- void writeRichCompareFunction(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeToPythonFunction(QTextStream& s, const AbstractMetaClass* metaClass);
-
- void writeEnumsInitialization(QTextStream& s, AbstractMetaEnumList& enums);
- void writeEnumInitialization(QTextStream& s, const AbstractMetaEnum* metaEnum);
-
- void writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass);
-
- void writeFlagsMethods(QTextStream& s, const AbstractMetaEnum* cppEnum);
- void writeFlagsToLong(QTextStream& s, const AbstractMetaEnum* cppEnum);
- void writeFlagsNonZero(QTextStream& s, const AbstractMetaEnum* cppEnum);
- void writeFlagsNumberMethodsDefinition(QTextStream& s, const AbstractMetaEnum* cppEnum);
- void writeFlagsBinaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum,
- QString pyOpName, QString cppOpName);
- void writeFlagsUnaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum,
- QString pyOpName, QString cppOpName, bool boolResult = false);
-
- /// Writes the function that registers the multiple inheritance information for the classes that need it.
- void writeMultipleInheritanceInitializerFunction(QTextStream& s, const AbstractMetaClass* metaClass);
- /// Writes the implementation of special cast functions, used when we need to cast a class with multiple inheritance.
- void writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass);
-
- void writePrimitiveConverterInitialization(QTextStream& s, const CustomConversion* customConversion);
- void writeEnumConverterInitialization(QTextStream& s, const TypeEntry* enumType);
- void writeEnumConverterInitialization(QTextStream& s, const AbstractMetaEnum* metaEnum);
- void writeContainerConverterInitialization(QTextStream& s, const AbstractMetaType* type);
- void writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QList<const AbstractMetaClass*>& conversions);
-
- void writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool userHeuristicForReturn);
- bool writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool userHeuristicPolicy);
- void writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self = PYTHON_SELF_VAR);
- void writeInitQtMetaTypeFunctionBody(QTextStream& s, const AbstractMetaClass* metaClass) const;
-
- /**
- * Returns the multiple inheritance initializer function for the given class.
- * \param metaClass the class for whom the function name must be generated.
- * \return name of the multiple inheritance information initializer function or
- * an empty string if there is no multiple inheritance in its ancestry.
- */
- QString multipleInheritanceInitializerFunctionName(const AbstractMetaClass* metaClass);
-
- /// Returns a list of all classes to which the given class could be cast.
- QStringList getAncestorMultipleInheritance(const AbstractMetaClass* metaClass);
-
- /// Returns true if the given class supports the python number protocol
- bool supportsNumberProtocol(const AbstractMetaClass* metaClass);
-
- /// Returns true if the given class supports the python sequence protocol
- bool supportsSequenceProtocol(const AbstractMetaClass* metaClass);
-
- /// Returns true if the given class supports the python mapping protocol
- bool supportsMappingProtocol(const AbstractMetaClass* metaClass);
-
- /// Returns true if generator should produce getters and setters for the given class.
- bool shouldGenerateGetSetList(const AbstractMetaClass* metaClass);
-
- void writeHashFunction(QTextStream& s, const AbstractMetaClass* metaClass);
-
- /// Write default implementations for sequence protocol
- void writeStdListWrapperMethods(QTextStream& s, const AbstractMetaClass* metaClass);
- /// Helper function for writeStdListWrapperMethods.
- void writeIndexError(QTextStream& s, const QString& errorMsg);
-
- QString writeReprFunction(QTextStream& s, const AbstractMetaClass* metaClass);
-
- bool hasBoolCast(const AbstractMetaClass* metaClass) const;
-
- // Number protocol structure members names.
- static QHash<QString, QString> m_nbFuncs;
-
- // Maps special function names to function parameters and return types
- // used by CPython API in the sequence protocol.
- QHash<QString, QPair<QString, QString> > m_sequenceProtocol;
- // Sequence protocol structure members names.
- static QHash<QString, QString> m_sqFuncs;
-
- // Maps special function names to function parameters and return types
- // used by CPython API in the mapping protocol.
- QHash<QString, QPair<QString, QString> > m_mappingProtocol;
- // Mapping protocol structure members names.
- static QHash<QString, QString> m_mpFuncs;
-
- static QString m_currentErrorCode;
-
- /// Helper class to set and restore the current error code.
- class ErrorCode {
- public:
- explicit ErrorCode(QString errorCode) {
- m_savedErrorCode = CppGenerator::m_currentErrorCode;
- CppGenerator::m_currentErrorCode = errorCode;
- }
- explicit ErrorCode(int errorCode) {
- m_savedErrorCode = CppGenerator::m_currentErrorCode;
- CppGenerator::m_currentErrorCode = QString::number(errorCode);
- }
- ~ErrorCode() {
- CppGenerator::m_currentErrorCode = m_savedErrorCode;
- }
- private:
- QString m_savedErrorCode;
- };
-};
-
-#endif // CPPGENERATOR_H
diff --git a/generators/shiboken/headergenerator.cpp b/generators/shiboken/headergenerator.cpp
deleted file mode 100644
index 9be272067..000000000
--- a/generators/shiboken/headergenerator.cpp
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * This file is part of the Shiboken Python Bindings Generator project.
- *
- * Copyright (C) 2009-2012 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 "headergenerator.h"
-#include <typedatabase.h>
-#include <reporthandler.h>
-#include <fileout.h>
-
-#include <QtCore/QDir>
-#include <QtCore/QTextStream>
-#include <QtCore/QVariant>
-#include <QtCore/QRegExp>
-#include <QtCore/QDebug>
-
-QString HeaderGenerator::fileNameForClass(const AbstractMetaClass* metaClass) const
-{
- return metaClass->qualifiedCppName().toLower().replace("::", "_") + QLatin1String("_wrapper.h");
-}
-
-void HeaderGenerator::writeCopyCtor(QTextStream& s, const AbstractMetaClass* metaClass) const
-{
- s << INDENT << wrapperName(metaClass) << "(const " << metaClass->qualifiedCppName() << "& self)";
- s << " : " << metaClass->qualifiedCppName() << "(self)" << endl;
- s << INDENT << "{" << endl;
- s << INDENT << "}" << endl << endl;
-}
-
-void HeaderGenerator::writeProtectedFieldAccessors(QTextStream& s, const AbstractMetaField* field) const
-{
- AbstractMetaType *metaType = field->type();
- QString fieldType = metaType->cppSignature();
- QString fieldName = field->enclosingClass()->qualifiedCppName() + "::" + field->name();
-
- // Force use of pointer to return internal variable memory
- bool useReference = (!metaType->isConstant() &&
- !metaType->isEnum() &&
- !metaType->isPrimitive() &&
- metaType->indirections() == 0);
-
-
- // Get function
- s << INDENT << "inline " << fieldType
- << (useReference ? '*' : ' ')
- << ' ' << protectedFieldGetterName(field) << "()"
- << " { return "
- << (useReference ? '&' : ' ') << "this->" << fieldName << "; }" << endl;
-
- // Set function
- s << INDENT << "inline void " << protectedFieldSetterName(field) << '(' << fieldType << " value)"
- << " { " << fieldName << " = value; }" << endl;
-}
-
-void HeaderGenerator::generateClass(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- ReportHandler::debugSparse("Generating header for " + metaClass->fullName());
- m_inheritedOverloads.clear();
- Indentation indent(INDENT);
-
- // write license comment
- s << licenseComment();
-
- QString wrapperName = HeaderGenerator::wrapperName(metaClass);
- QString headerGuard = wrapperName.replace("::", "_").toUpper();
-
- // Header
- s << "#ifndef SBK_" << headerGuard << "_H" << endl;
- s << "#define SBK_" << headerGuard << "_H" << endl<< endl;
-
- if (!avoidProtectedHack())
- s << "#define protected public" << endl << endl;
-
- s << "#include <shiboken.h>" << endl << endl;
-
- //Includes
- s << metaClass->typeEntry()->include() << endl;
-
- if (shouldGenerateCppWrapper(metaClass)) {
-
- if (usePySideExtensions() && metaClass->isQObject())
- s << "namespace PySide { class DynamicQMetaObject; }\n\n";
-
- // Class
- s << "class " << wrapperName;
- s << " : public " << metaClass->qualifiedCppName();
-
- s << endl << '{' << endl << "public:" << endl;
-
- bool hasVirtualFunction = false;
- foreach (AbstractMetaFunction *func, filterFunctions(metaClass)) {
- if (func->isVirtual())
- hasVirtualFunction = true;
- writeFunction(s, func);
- }
-
- if (avoidProtectedHack() && metaClass->hasProtectedFields()) {
- foreach (AbstractMetaField* field, metaClass->fields()) {
- if (!field->isProtected())
- continue;
- writeProtectedFieldAccessors(s, field);
- }
- }
-
- //destructor
- if (!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) {
- s << INDENT;
- if (metaClass->hasVirtualDestructor() || hasVirtualFunction)
- s << "virtual ";
- s << "~" << wrapperName << "();" << endl;
- }
-
- writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::Declaration, TypeSystem::NativeCode);
-
- if ((!avoidProtectedHack() || !metaClass->hasPrivateDestructor())
- && usePySideExtensions() && metaClass->isQObject()) {
- s << "public:\n";
- s << INDENT << "virtual int qt_metacall(QMetaObject::Call call, int id, void** args);" << endl;
- s << INDENT << "virtual void* qt_metacast(const char* _clname);" << endl;
- }
-
- if (m_inheritedOverloads.size()) {
- s << INDENT << "// Inherited overloads, because the using keyword sux" << endl;
- writeInheritedOverloads(s);
- }
-
- if (usePySideExtensions())
- s << INDENT << "static void pysideInitQtMetaTypes();" << endl;
-
- s << "};" << endl << endl;
- }
-
- s << "#endif // SBK_" << headerGuard << "_H" << endl << endl;
-}
-
-void HeaderGenerator::writeFunction(QTextStream& s, const AbstractMetaFunction* func)
-{
-
- // do not write copy ctors here.
- if (!func->isPrivate() && func->isCopyConstructor()) {
- writeCopyCtor(s, func->ownerClass());
- return;
- }
- if (func->isUserAdded())
- return;
-
- if (avoidProtectedHack() && func->isProtected() && !func->isConstructor() && !func->isOperatorOverload()) {
- s << INDENT << "inline " << (func->isStatic() ? "static " : "");
- s << functionSignature(func, "", "_protected", Generator::EnumAsInts|Generator::OriginalTypeDescription) << " { ";
- s << (func->type() ? "return " : "");
- if (!func->isAbstract())
- s << func->ownerClass()->qualifiedCppName() << "::";
- s << func->originalName() << '(';
- QStringList args;
- foreach (const AbstractMetaArgument* arg, func->arguments()) {
- QString argName = arg->name();
- const TypeEntry* enumTypeEntry = 0;
- if (arg->type()->isFlags())
- enumTypeEntry = reinterpret_cast<const FlagsTypeEntry*>(arg->type()->typeEntry())->originator();
- else if (arg->type()->isEnum())
- enumTypeEntry = arg->type()->typeEntry();
- if (enumTypeEntry)
- argName = QString("%1(%2)").arg(arg->type()->cppSignature()).arg(argName);
- args << argName;
- }
- s << args.join(", ") << ')';
- s << "; }" << endl;
- }
-
- // pure virtual functions need a default implementation
- if ((func->isPrivate() && !visibilityModifiedToPrivate(func))
- || (func->isModifiedRemoved() && !func->isAbstract()))
- return;
-
- if (avoidProtectedHack() && func->ownerClass()->hasPrivateDestructor()
- && (func->isAbstract() || func->isVirtual()))
- return;
-
- if (func->isConstructor() || func->isAbstract() || func->isVirtual()) {
- s << INDENT;
- Options virtualOption = Generator::OriginalTypeDescription;
-
- if (func->isVirtual() || func->isAbstract())
- s << "virtual ";
- else if (!func->hasSignatureModifications())
- virtualOption = Generator::NoOption;
-
- s << functionSignature(func, "", "", virtualOption) << ';' << endl;
-
- // Check if this method hide other methods in base classes
- foreach (const AbstractMetaFunction* f, func->ownerClass()->functions()) {
- if (f != func
- && !f->isConstructor()
- && !f->isPrivate()
- && !f->isVirtual()
- && !f->isAbstract()
- && !f->isStatic()
- && f->name() == func->name()) {
- m_inheritedOverloads << f;
- break;
- }
- }
-
- // TODO: when modified an abstract method ceases to be virtual but stays abstract
- //if (func->isModifiedRemoved() && func->isAbstract()) {
- //}
- }
-}
-
-static void _writeTypeIndexDefineLine(QTextStream& s, const QString& variableName, int typeIndex)
-{
- s << "#define ";
- s.setFieldWidth(60);
- s << variableName;
- s.setFieldWidth(0);
- s << ' ' << typeIndex << endl;
-}
-void HeaderGenerator::writeTypeIndexDefineLine(QTextStream& s, const TypeEntry* typeEntry)
-{
- if (!typeEntry || !typeEntry->generateCode())
- return;
- s.setFieldAlignment(QTextStream::AlignLeft);
- int typeIndex = getTypeIndex(typeEntry);
- _writeTypeIndexDefineLine(s, getTypeIndexVariableName(typeEntry), typeIndex);
- if (typeEntry->isComplex()) {
- const ComplexTypeEntry* cType = reinterpret_cast<const ComplexTypeEntry*>(typeEntry);
- if (cType->baseContainerType()) {
- const AbstractMetaClass* metaClass = classes().findClass(cType);
- if (metaClass->templateBaseClass())
- _writeTypeIndexDefineLine(s, getTypeIndexVariableName(metaClass, true), typeIndex);
- }
- }
- if (typeEntry->isEnum()) {
- const EnumTypeEntry* ete = reinterpret_cast<const EnumTypeEntry*>(typeEntry);
- if (ete->flags())
- writeTypeIndexDefineLine(s, ete->flags());
- }
-}
-
-void HeaderGenerator::writeTypeIndexDefine(QTextStream& s, const AbstractMetaClass* metaClass)
-{
- if (!metaClass->typeEntry()->generateCode())
- return;
- writeTypeIndexDefineLine(s, metaClass->typeEntry());
- foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) {
- if (metaEnum->isPrivate())
- continue;
- writeTypeIndexDefineLine(s, metaEnum->typeEntry());
- }
-}
-
-void HeaderGenerator::finishGeneration()
-{
- // Generate the main header for this module.
- // This header should be included by binding modules
- // extendind on top of this one.
- QSet<Include> includes;
- QString macros;
- QTextStream macrosStream(&macros);
- QString sbkTypeFunctions;
- QTextStream typeFunctions(&sbkTypeFunctions);
- QString protectedEnumSurrogates;
- QTextStream protEnumsSurrogates(&protectedEnumSurrogates);
-
- Indentation indent(INDENT);
-
- macrosStream << "// Type indices" << endl;
- AbstractMetaEnumList globalEnums = this->globalEnums();
- foreach (const AbstractMetaClass* metaClass, classes()) {
- writeTypeIndexDefine(macrosStream, metaClass);
- lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass);
- }
- foreach (const AbstractMetaEnum* metaEnum, globalEnums)
- writeTypeIndexDefineLine(macrosStream, metaEnum->typeEntry());
- macrosStream << "#define ";
- macrosStream.setFieldWidth(60);
- macrosStream << "SBK_"+moduleName()+"_IDX_COUNT";
- macrosStream.setFieldWidth(0);
- macrosStream << ' ' << getMaxTypeIndex() << endl << endl;
- macrosStream << "// This variable stores all Python types exported by this module." << endl;
- macrosStream << "extern PyTypeObject** " << cppApiVariableName() << ';' << endl << endl;
- macrosStream << "// This variable stores all type converters exported by this module." << endl;
- macrosStream << "extern SbkConverter** " << convertersVariableName() << ';' << endl << endl;;
-
- // TODO-CONVERTER ------------------------------------------------------------------------------
- // Using a counter would not do, a fix must be made to APIExtractor's getTypeIndex().
- macrosStream << "// Converter indices" << endl;
- QList<const PrimitiveTypeEntry*> primitives = primitiveTypes();
- int pCount = 0;
- foreach (const PrimitiveTypeEntry* ptype, primitives) {
- /* Note: do not generate indices for typedef'd primitive types
- * as they'll use the primitive type converters instead, so we
- * don't need to create any other.
- */
- if (!ptype->generateCode() || !ptype->customConversion())
- continue;
-
- _writeTypeIndexDefineLine(macrosStream, getTypeIndexVariableName(ptype), pCount++);
- }
-
- foreach (const AbstractMetaType* container, instantiatedContainers()) {
- //_writeTypeIndexDefineLine(macrosStream, getTypeIndexVariableName(container), pCount);
- // DEBUG
- QString variableName = getTypeIndexVariableName(container);
- macrosStream << "#define ";
- macrosStream.setFieldWidth(60);
- macrosStream << variableName;
- macrosStream.setFieldWidth(0);
- macrosStream << ' ' << pCount << " // " << container->cppSignature() << endl;
- // DEBUG
- pCount++;
- }
-
- // Because on win32 the compiler will not accept a zero length array.
- if (pCount == 0)
- pCount++;
- _writeTypeIndexDefineLine(macrosStream, QString("SBK_%1_CONVERTERS_IDX_COUNT").arg(moduleName()), pCount);
- macrosStream << endl;
- // TODO-CONVERTER ------------------------------------------------------------------------------
-
- macrosStream << "// Macros for type check" << endl;
- foreach (const AbstractMetaEnum* cppEnum, globalEnums) {
- if (cppEnum->isAnonymous() || cppEnum->isPrivate())
- continue;
- includes << cppEnum->typeEntry()->include();
- writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum);
- writeSbkTypeFunction(typeFunctions, cppEnum);
- }
-
- foreach (AbstractMetaClass* metaClass, classes()) {
- if (!shouldGenerate(metaClass))
- continue;
-
- //Includes
- const TypeEntry* classType = metaClass->typeEntry();
- includes << classType->include();
-
- foreach (const AbstractMetaEnum* cppEnum, metaClass->enums()) {
- if (cppEnum->isAnonymous() || cppEnum->isPrivate())
- continue;
- EnumTypeEntry* enumType = cppEnum->typeEntry();
- includes << enumType->include();
- writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum);
- writeSbkTypeFunction(typeFunctions, cppEnum);
- }
-
- if (!metaClass->isNamespace())
- writeSbkTypeFunction(typeFunctions, metaClass);
- }
-
- QString moduleHeaderFileName(outputDirectory()
- + QDir::separator() + subDirectoryForPackage(packageName())
- + QDir::separator() + getModuleHeaderFileName());
-
- QString includeShield("SBK_" + moduleName().toUpper() + "_PYTHON_H");
-
- FileOut file(moduleHeaderFileName);
- QTextStream& s = file.stream;
- // write license comment
- s << licenseComment() << endl << endl;
-
- s << "#ifndef " << includeShield << endl;
- s << "#define " << includeShield << endl<< endl;
- if (!avoidProtectedHack()) {
- s << "//workaround to access protected functions" << endl;
- s << "#define protected public" << endl << endl;
- }
-
- s << "#include <sbkpython.h>" << endl;
- s << "#include <conversions.h>" << endl;
- s << "#include <sbkenum.h>" << endl;
- s << "#include <basewrapper.h>" << endl;
- s << "#include <bindingmanager.h>" << endl;
- s << "#include <memory>" << endl << endl;
- if (usePySideExtensions())
- s << "#include <pysidesignal.h>" << endl;
-
- QStringList requiredTargetImports = TypeDatabase::instance()->requiredTargetImports();
- if (!requiredTargetImports.isEmpty()) {
- s << "// Module Includes" << endl;
- foreach (const QString& requiredModule, requiredTargetImports)
- s << "#include <" << getModuleHeaderFileName(requiredModule) << ">" << endl;
- s << endl;
- }
-
- s << "// Binded library includes" << endl;
- foreach (const Include& include, includes)
- s << include;
-
- if (!primitiveTypes().isEmpty()) {
- s << "// Conversion Includes - Primitive Types" << endl;
- foreach (const PrimitiveTypeEntry* ptype, primitiveTypes())
- s << ptype->include();
- s << endl;
- }
-
- if (!containerTypes().isEmpty()) {
- s << "// Conversion Includes - Container Types" << endl;
- foreach (const ContainerTypeEntry* ctype, containerTypes())
- s << ctype->include();
- s << endl;
- }
-
- s << macros << endl;
-
- if (!protectedEnumSurrogates.isEmpty()) {
- s << "// Protected enum surrogates" << endl;
- s << protectedEnumSurrogates << endl;
- }
-
- s << "namespace Shiboken" << endl << '{' << endl << endl;
-
- s << "// PyType functions, to get the PyObjectType for a type T\n";
- s << sbkTypeFunctions << endl;
-
- s << "} // namespace Shiboken" << endl << endl;
-
- s << "#endif // " << includeShield << endl << endl;
-}
-
-void HeaderGenerator::writeProtectedEnumSurrogate(QTextStream& s, const AbstractMetaEnum* cppEnum)
-{
- if (avoidProtectedHack() && cppEnum->isProtected())
- s << "enum " << protectedEnumSurrogateName(cppEnum) << " {};" << endl;
-}
-
-void HeaderGenerator::writeSbkTypeFunction(QTextStream& s, const AbstractMetaEnum* cppEnum)
-{
- QString enumName;
- if (avoidProtectedHack() && cppEnum->isProtected()) {
- enumName = protectedEnumSurrogateName(cppEnum);
- } else {
- enumName = cppEnum->name();
- if (cppEnum->enclosingClass())
- enumName = cppEnum->enclosingClass()->qualifiedCppName() + "::" + enumName;
- }
-
- s << "template<> inline PyTypeObject* SbkType< ::" << enumName << " >() ";
- s << "{ return " << cpythonTypeNameExt(cppEnum->typeEntry()) << "; }\n";
-
- FlagsTypeEntry* flag = cppEnum->typeEntry()->flags();
- if (flag) {
- s << "template<> inline PyTypeObject* SbkType< ::" << flag->name() << " >() "
- << "{ return " << cpythonTypeNameExt(flag) << "; }\n";
- }
-}
-
-void HeaderGenerator::writeSbkTypeFunction(QTextStream& s, const AbstractMetaClass* cppClass)
-{
- s << "template<> inline PyTypeObject* SbkType< ::" << cppClass->qualifiedCppName() << " >() "
- << "{ return reinterpret_cast<PyTypeObject*>(" << cpythonTypeNameExt(cppClass->typeEntry()) << "); }\n";
-}
-
-void HeaderGenerator::writeInheritedOverloads(QTextStream& s)
-{
- foreach (const AbstractMetaFunction* func, m_inheritedOverloads) {
- s << INDENT << "inline ";
- s << functionSignature(func, "", "", Generator::EnumAsInts|Generator::OriginalTypeDescription) << " { ";
- s << (func->type() ? "return " : "");
- s << func->ownerClass()->qualifiedCppName() << "::" << func->originalName() << '(';
- QStringList args;
- foreach (const AbstractMetaArgument* arg, func->arguments()) {
- QString argName = arg->name();
- const TypeEntry* enumTypeEntry = 0;
- if (arg->type()->isFlags())
- enumTypeEntry = reinterpret_cast<const FlagsTypeEntry*>(arg->type()->typeEntry())->originator();
- else if (arg->type()->isEnum())
- enumTypeEntry = arg->type()->typeEntry();
- if (enumTypeEntry)
- argName = QString("%1(%2)").arg(arg->type()->cppSignature()).arg(argName);
- args << argName;
- }
- s << args.join(", ") << ')';
- s << "; }" << endl;
- }
-}
diff --git a/generators/shiboken/headergenerator.h b/generators/shiboken/headergenerator.h
deleted file mode 100644
index e830efaee..000000000
--- a/generators/shiboken/headergenerator.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * This file is part of the Shiboken Python Bindings 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
- *
- */
-
-#ifndef HEADERGENERATOR_H
-#define HEADERGENERATOR_H
-
-#include "shibokengenerator.h"
-
-/**
- * The HeaderGenerator generate the declarations of C++ bindings classes.
- */
-class HeaderGenerator : public ShibokenGenerator
-{
-public:
- QMap<QString, QString> options() const { return QMap<QString, QString>(); }
-protected:
- QString fileNameForClass(const AbstractMetaClass* metaClass) const;
- void generateClass(QTextStream& s, const AbstractMetaClass* metaClass);
- void finishGeneration();
-
-private:
- void writeCopyCtor(QTextStream &s, const AbstractMetaClass* metaClass) const;
- void writeProtectedFieldAccessors(QTextStream& s, const AbstractMetaField* field) const;
- void writeFunction(QTextStream& s, const AbstractMetaFunction* func);
- void writeSbkTypeFunction(QTextStream& s, const AbstractMetaEnum* cppEnum);
- void writeSbkTypeFunction(QTextStream& s, const AbstractMetaClass* cppClass);
- void writeTypeIndexDefineLine(QTextStream& s, const TypeEntry* typeEntry);
- void writeTypeIndexDefine(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeProtectedEnumSurrogate(QTextStream& s, const AbstractMetaEnum* cppEnum);
- void writeInheritedOverloads(QTextStream& s);
-
- QSet<const AbstractMetaFunction*> m_inheritedOverloads;
-};
-
-#endif // HEADERGENERATOR_H
-
diff --git a/generators/shiboken/overloaddata.cpp b/generators/shiboken/overloaddata.cpp
deleted file mode 100644
index 57084558e..000000000
--- a/generators/shiboken/overloaddata.cpp
+++ /dev/null
@@ -1,1002 +0,0 @@
-/*
- * This file is part of the Shiboken Python Bindings 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 <QtCore/QFile>
-#include <reporthandler.h>
-#include <graph.h>
-#include "overloaddata.h"
-#include "shibokengenerator.h"
-#include <QTemporaryFile>
-
-static const TypeEntry* getAliasedTypeEntry(const TypeEntry* typeEntry)
-{
- if (typeEntry->isPrimitive()) {
- const PrimitiveTypeEntry* pte = reinterpret_cast<const PrimitiveTypeEntry*>(typeEntry);
- while (pte->aliasedTypeEntry())
- pte = pte->aliasedTypeEntry();
- typeEntry = pte;
- }
- return typeEntry;
-}
-
-static QString getTypeName(const AbstractMetaType* type)
-{
- const TypeEntry* typeEntry = getAliasedTypeEntry(type->typeEntry());
- QString typeName = typeEntry->name();
- if (typeEntry->isContainer()) {
- QStringList types;
- foreach (const AbstractMetaType* cType, type->instantiations()) {
- const TypeEntry* typeEntry = getAliasedTypeEntry(cType->typeEntry());
- types << typeEntry->name();
- }
- typeName += QString("<%1 >").arg(types.join(","));
- }
- return typeName;
-}
-
-static QString getTypeName(const OverloadData* ov)
-{
- return ov->hasArgumentTypeReplace() ? ov->argumentTypeReplaced() : getTypeName(ov->argType());
-}
-
-static bool typesAreEqual(const AbstractMetaType* typeA, const AbstractMetaType* typeB)
-{
- if (typeA->typeEntry() == typeB->typeEntry()) {
- if (typeA->isContainer()) {
- if (typeA->instantiations().size() != typeB->instantiations().size())
- return false;
-
- for (int i = 0; i < typeA->instantiations().size(); ++i) {
- if (!typesAreEqual(typeA->instantiations().at(i), typeB->instantiations().at(i)))
- return false;
- }
- return true;
- }
-
- return !(ShibokenGenerator::isCString(typeA) ^ ShibokenGenerator::isCString(typeB));
- }
- return false;
-}
-
-
-/**
- * OverloadSortData just helps writing clearer code in the
- * OverloadData::sortNextOverloads method.
- */
-struct OverloadSortData
-{
- OverloadSortData() : counter(0) {};
-
- /**
- * Adds a typeName into the type map without associating it with
- * a OverloadData. This is done to express type dependencies that could
- * or could not appear in overloaded signatures not processed yet.
- */
- void mapType(const QString& typeName)
- {
- if (map.contains(typeName))
- return;
- map[typeName] = counter;
- if (!reverseMap.contains(counter))
- reverseMap[counter] = 0;
- counter++;
- }
-
- void mapType(OverloadData* overloadData)
- {
- QString typeName = getTypeName(overloadData);
- map[typeName] = counter;
- reverseMap[counter] = overloadData;
- counter++;
- }
-
- int lastProcessedItemId() { return counter - 1; }
-
- int counter;
- QHash<QString, int> map; // typeName -> id
- QHash<int, OverloadData*> reverseMap; // id -> OverloadData;
-};
-
-/**
- * Helper function that returns the name of a container get from containerType argument and
- * an instantiation taken either from an implicit conversion expressed by the function argument,
- * or from the string argument implicitConvTypeName.
- */
-static QString getImplicitConversionTypeName(const AbstractMetaType* containerType,
- const AbstractMetaType* instantiation,
- const AbstractMetaFunction* function,
- const QString& implicitConvTypeName = QString())
-{
- QString impConv;
- if (!implicitConvTypeName.isEmpty())
- impConv = implicitConvTypeName;
- else if (function->isConversionOperator())
- impConv = function->ownerClass()->typeEntry()->name();
- else
- impConv = getTypeName(function->arguments().first()->type());
-
- QStringList types;
- foreach (const AbstractMetaType* otherType, containerType->instantiations())
- types << (otherType == instantiation ? impConv : getTypeName(otherType));
-
- const ContainerTypeEntry* containerTypeEntry = reinterpret_cast<const ContainerTypeEntry*>(containerType->typeEntry());
- return containerTypeEntry->qualifiedCppName() + '<' + types.join(", ") + " >";
-}
-
-/**
- * Topologically sort the overloads by implicit convertion order
- *
- * This avoids using an implicit conversion if there's an explicit
- * overload for the convertible type. So, if there's an implicit convert
- * like TargetType(ConvertibleType foo) and both are in the overload list,
- * ConvertibleType is checked before TargetType.
- *
- * Side effects: Modifies m_nextOverloadData
- */
-void OverloadData::sortNextOverloads()
-{
- OverloadSortData sortData;
- bool checkPyObject = false;
- int pyobjectIndex = 0;
- bool checkPySequence = false;
- int pySeqIndex = 0;
- bool checkQString = false;
- int qstringIndex = 0;
- bool checkQVariant = false;
- int qvariantIndex = 0;
- bool checkPyBuffer = false;
- int pyBufferIndex = 0;
-
- // Primitive types that are not int, long, short,
- // char and their respective unsigned counterparts.
- QStringList nonIntegerPrimitives;
- nonIntegerPrimitives << "float" << "double" << "bool";
-
- // Signed integer primitive types.
- QStringList signedIntegerPrimitives;
- signedIntegerPrimitives << "int" << "short" << "long";
-
- // sort the children overloads
- foreach(OverloadData *ov, m_nextOverloadData)
- ov->sortNextOverloads();
-
- if (m_nextOverloadData.size() <= 1)
- return;
-
- // Populates the OverloadSortData object containing map and reverseMap, to map type names to ids,
- // these ids will be used by the topological sort algorithm, because is easier and faster to work
- // with graph sorting using integers.
- foreach(OverloadData* ov, m_nextOverloadData) {
- sortData.mapType(ov);
-
- const QString typeName(getTypeName(ov));
-
- if (!checkPyObject && typeName.contains("PyObject")) {
- checkPyObject = true;
- pyobjectIndex = sortData.lastProcessedItemId();
- } else if (!checkPySequence && typeName == "PySequence") {
- checkPySequence = true;
- pySeqIndex = sortData.lastProcessedItemId();
- } else if (!checkPyBuffer && typeName == "PyBuffer") {
- checkPyBuffer = true;
- pyBufferIndex = sortData.lastProcessedItemId();
- } else if (!checkQVariant && typeName == "QVariant") {
- checkQVariant = true;
- qvariantIndex = sortData.lastProcessedItemId();
- } else if (!checkQString && typeName == "QString") {
- checkQString = true;
- qstringIndex = sortData.lastProcessedItemId();
- }
-
- foreach (const AbstractMetaType* instantiation, ov->argType()->instantiations()) {
- // Add dependencies for type instantiation of container.
- QString typeName = getTypeName(instantiation);
- sortData.mapType(typeName);
-
- // Build dependency for implicit conversion types instantiations for base container.
- // For example, considering signatures "method(list<PointF>)" and "method(list<Point>)",
- // and being PointF implicitly convertible from Point, an list<T> instantiation with T
- // as Point must come before the PointF instantiation, or else list<Point> will never
- // be called. In the case of primitive types, list<double> must come before list<int>.
- if (instantiation->isPrimitive() && (signedIntegerPrimitives.contains(instantiation->name()))) {
- foreach (const QString& primitive, nonIntegerPrimitives)
- sortData.mapType(getImplicitConversionTypeName(ov->argType(), instantiation, 0, primitive));
- } else {
- foreach (const AbstractMetaFunction* function, m_generator->implicitConversions(instantiation))
- sortData.mapType(getImplicitConversionTypeName(ov->argType(), instantiation, function));
- }
- }
- }
-
-
- // Create the graph of type dependencies based on implicit conversions.
- Graph graph(sortData.reverseMap.count());
- // All C++ primitive types, add any forgotten type AT THE END OF THIS LIST!
- const char* primitiveTypes[] = {"int",
- "unsigned int",
- "long",
- "unsigned long",
- "short",
- "unsigned short",
- "bool",
- "unsigned char",
- "char",
- "float",
- "double",
- "const char*"
- };
- const int numPrimitives = sizeof(primitiveTypes)/sizeof(const char*);
- bool hasPrimitive[numPrimitives];
- for (int i = 0; i < numPrimitives; ++i)
- hasPrimitive[i] = sortData.map.contains(primitiveTypes[i]);
-
- if (checkPySequence && checkPyObject)
- graph.addEdge(pySeqIndex, pyobjectIndex);
-
- QStringList classesWithIntegerImplicitConversion;
-
- foreach(OverloadData* ov, m_nextOverloadData) {
- const AbstractMetaType* targetType = ov->argType();
- const QString targetTypeEntryName(getTypeName(ov));
- int targetTypeId = sortData.map[targetTypeEntryName];
-
- // Process implicit conversions
- foreach(AbstractMetaFunction* function, m_generator->implicitConversions(targetType)) {
- QString convertibleType;
- if (function->isConversionOperator())
- convertibleType = function->ownerClass()->typeEntry()->name();
- else
- convertibleType = getTypeName(function->arguments().first()->type());
-
- if (convertibleType == "int" || convertibleType == "unsigned int")
- classesWithIntegerImplicitConversion << targetTypeEntryName;
-
- if (!sortData.map.contains(convertibleType))
- continue;
-
- int convertibleTypeId = sortData.map[convertibleType];
-
- // If a reverse pair already exists, remove it. Probably due to the
- // container check (This happened to QVariant and QHash)
- graph.removeEdge(targetTypeId, convertibleTypeId);
- graph.addEdge(convertibleTypeId, targetTypeId);
- }
-
- // Process inheritance relationships
- if (targetType->isValue() || targetType->isObject()) {
- const AbstractMetaClass* metaClass = m_generator->classes().findClass(targetType->typeEntry());
- foreach (const AbstractMetaClass* ancestor, m_generator->getAllAncestors(metaClass)) {
- QString ancestorTypeName = ancestor->typeEntry()->name();
- if (!sortData.map.contains(ancestorTypeName))
- continue;
- int ancestorTypeId = sortData.map[ancestorTypeName];
- graph.removeEdge(ancestorTypeId, targetTypeId);
- graph.addEdge(targetTypeId, ancestorTypeId);
- }
- }
-
- // Process template instantiations
- foreach (const AbstractMetaType* instantiation, targetType->instantiations()) {
- if (sortData.map.contains(getTypeName(instantiation))) {
- int convertible = sortData.map[getTypeName(instantiation)];
-
- if (!graph.containsEdge(targetTypeId, convertible)) // Avoid cyclic dependency.
- graph.addEdge(convertible, targetTypeId);
-
- if (instantiation->isPrimitive() && (signedIntegerPrimitives.contains(instantiation->name()))) {
- foreach (const QString& primitive, nonIntegerPrimitives) {
- QString convertibleTypeName = getImplicitConversionTypeName(ov->argType(), instantiation, 0, primitive);
- if (!graph.containsEdge(targetTypeId, sortData.map[convertibleTypeName])) // Avoid cyclic dependency.
- graph.addEdge(sortData.map[convertibleTypeName], targetTypeId);
- }
-
- } else {
- foreach (const AbstractMetaFunction* function, m_generator->implicitConversions(instantiation)) {
- QString convertibleTypeName = getImplicitConversionTypeName(ov->argType(), instantiation, function);
- if (!graph.containsEdge(targetTypeId, sortData.map[convertibleTypeName])) // Avoid cyclic dependency.
- graph.addEdge(sortData.map[convertibleTypeName], targetTypeId);
- }
- }
- }
- }
-
-
- if ((checkPySequence || checkPyObject || checkPyBuffer)
- && !targetTypeEntryName.contains("PyObject")
- && !targetTypeEntryName.contains("PyBuffer")
- && !targetTypeEntryName.contains("PySequence")) {
- if (checkPySequence) {
- // PySequence will be checked after all more specific types, but before PyObject.
- graph.addEdge(targetTypeId, pySeqIndex);
- } else if (checkPyBuffer) {
- // PySequence will be checked after all more specific types, but before PyObject.
- graph.addEdge(targetTypeId, pyBufferIndex);
- } else {
- // Add dependency on PyObject, so its check is the last one (too generic).
- graph.addEdge(targetTypeId, pyobjectIndex);
- }
- } else if (checkQVariant && targetTypeEntryName != "QVariant") {
- if (!graph.containsEdge(qvariantIndex, targetTypeId)) // Avoid cyclic dependency.
- graph.addEdge(targetTypeId, qvariantIndex);
- } else if (checkQString && ShibokenGenerator::isPointer(ov->argType())
- && targetTypeEntryName != "QString"
- && targetTypeEntryName != "QByteArray"
- && (!checkPyObject || targetTypeId != pyobjectIndex)) {
- if (!graph.containsEdge(qstringIndex, targetTypeId)) // Avoid cyclic dependency.
- graph.addEdge(targetTypeId, qstringIndex);
- }
-
- if (targetType->isEnum()) {
- // Enum values must precede primitive types.
- for (int i = 0; i < numPrimitives; ++i) {
- if (hasPrimitive[i])
- graph.addEdge(targetTypeId, sortData.map[primitiveTypes[i]]);
- }
- }
- }
-
- // QByteArray args need to be checked after QString args
- if (sortData.map.contains("QString") && sortData.map.contains("QByteArray"))
- graph.addEdge(sortData.map["QString"], sortData.map["QByteArray"]);
-
- foreach(OverloadData* ov, m_nextOverloadData) {
- const AbstractMetaType* targetType = ov->argType();
- if (!targetType->isEnum())
- continue;
-
- QString targetTypeEntryName = getTypeName(targetType);
- // Enum values must precede types implicitly convertible from "int" or "unsigned int".
- foreach (const QString& implicitFromInt, classesWithIntegerImplicitConversion)
- graph.addEdge(sortData.map[targetTypeEntryName], sortData.map[implicitFromInt]);
- }
-
-
- // Special case for double(int i) (not tracked by m_generator->implicitConversions
- foreach (const QString& signedIntegerName, signedIntegerPrimitives) {
- if (sortData.map.contains(signedIntegerName)) {
- foreach (const QString& nonIntegerName, nonIntegerPrimitives) {
- if (sortData.map.contains(nonIntegerName))
- graph.addEdge(sortData.map[nonIntegerName], sortData.map[signedIntegerName]);
- }
- }
- }
-
- // sort the overloads topologically based on the dependency graph.
- QLinkedList<int> unmappedResult = graph.topologicalSort();
- if (unmappedResult.isEmpty()) {
- QString funcName = referenceFunction()->name();
- if (referenceFunction()->ownerClass())
- funcName.prepend(referenceFunction()->ownerClass()->name() + '.');
-
- // Dump overload graph
- QString graphName = QDir::tempPath() + '/' + funcName + ".dot";
- QHash<QString, int>::const_iterator it = sortData.map.begin();
- QHash<int, QString> nodeNames;
- for (; it != sortData.map.end(); ++it)
- nodeNames.insert(it.value(), it.key());
- graph.dumpDot(nodeNames, graphName);
- ReportHandler::warning(QString("Cyclic dependency found on overloaddata for '%1' method! The graph boy saved the graph at %2.").arg(qPrintable(funcName)).arg(qPrintable(graphName)));
- }
-
- m_nextOverloadData.clear();
- foreach(int i, unmappedResult) {
- if (!sortData.reverseMap[i])
- continue;
- m_nextOverloadData << sortData.reverseMap[i];
- }
-}
-
-/**
- * Root constructor for OverloadData
- *
- * This constructor receives the list of overloads for a given function and iterates generating
- * the graph of OverloadData instances. Each OverloadData instance references an argument/type
- * combination.
- *
- * Example:
- * addStuff(double, PyObject *)
- * addStuff(double, int)
- *
- * Given these two overloads, there will be the following graph:
- *
- * addStuff - double - PyObject*
- * \- int
- *
- */
-OverloadData::OverloadData(const AbstractMetaFunctionList& overloads, const ShibokenGenerator* generator)
- : m_minArgs(256), m_maxArgs(0), m_argPos(-1), m_argType(0),
- m_headOverloadData(this), m_previousOverloadData(0), m_generator(generator)
-{
- foreach (const AbstractMetaFunction* func, overloads) {
- m_overloads.append(func);
- int argSize = func->arguments().size() - numberOfRemovedArguments(func);
- if (m_minArgs > argSize)
- m_minArgs = argSize;
- else if (m_maxArgs < argSize)
- m_maxArgs = argSize;
- OverloadData* currentOverloadData = this;
- foreach (const AbstractMetaArgument* arg, func->arguments()) {
- if (func->argumentRemoved(arg->argumentIndex() + 1))
- continue;
- currentOverloadData = currentOverloadData->addOverloadData(func, arg);
- }
- }
-
- // Sort the overload possibilities so that the overload decisor code goes for the most
- // important cases first, based on the topological order of the implicit conversions
- sortNextOverloads();
-
- // Fix minArgs
- if (minArgs() > maxArgs())
- m_headOverloadData->m_minArgs = maxArgs();
-}
-
-OverloadData::OverloadData(OverloadData* headOverloadData, const AbstractMetaFunction* func,
- const AbstractMetaType* argType, int argPos)
- : m_minArgs(256), m_maxArgs(0), m_argPos(argPos), m_argType(argType),
- m_headOverloadData(headOverloadData), m_previousOverloadData(0)
-{
- if (func)
- this->addOverload(func);
-}
-
-void OverloadData::addOverload(const AbstractMetaFunction* func)
-{
- int origNumArgs = func->arguments().size();
- int removed = numberOfRemovedArguments(func);
- int numArgs = origNumArgs - removed;
-
- if (numArgs > m_headOverloadData->m_maxArgs)
- m_headOverloadData->m_maxArgs = numArgs;
-
- if (numArgs < m_headOverloadData->m_minArgs)
- m_headOverloadData->m_minArgs = numArgs;
-
- for (int i = 0; m_headOverloadData->m_minArgs > 0 && i < origNumArgs; i++) {
- if (func->argumentRemoved(i + 1))
- continue;
- if (!ShibokenGenerator::getDefaultValue(func, func->arguments()[i]).isEmpty()) {
- int fixedArgIndex = i - removed;
- if (fixedArgIndex < m_headOverloadData->m_minArgs)
- m_headOverloadData->m_minArgs = fixedArgIndex;
- }
- }
-
- m_overloads.append(func);
-}
-
-OverloadData* OverloadData::addOverloadData(const AbstractMetaFunction* func,
- const AbstractMetaArgument* arg)
-{
- const AbstractMetaType* argType = arg->type();
- OverloadData* overloadData = 0;
- if (!func->isOperatorOverload()) {
- foreach (OverloadData* tmp, m_nextOverloadData) {
- // TODO: 'const char *', 'char *' and 'char' will have the same TypeEntry?
-
- // If an argument have a type replacement, then we should create a new overloaddata
- // for it, unless the next argument also have a identical type replacement.
- QString replacedArg = func->typeReplaced(tmp->m_argPos + 1);
- bool argsReplaced = !replacedArg.isEmpty() || !tmp->m_argTypeReplaced.isEmpty();
- if ((!argsReplaced && typesAreEqual(tmp->m_argType, argType))
- || (argsReplaced && replacedArg == tmp->argumentTypeReplaced())) {
- tmp->addOverload(func);
- overloadData = tmp;
- }
- }
- }
-
- if (!overloadData) {
- overloadData = new OverloadData(m_headOverloadData, func, argType, m_argPos + 1);
- overloadData->m_previousOverloadData = this;
- overloadData->m_generator = this->m_generator;
- QString typeReplaced = func->typeReplaced(arg->argumentIndex() + 1);
-
- if (!typeReplaced.isEmpty())
- overloadData->m_argTypeReplaced = typeReplaced;
- m_nextOverloadData.append(overloadData);
- }
-
- return overloadData;
-}
-
-QStringList OverloadData::returnTypes() const
-{
- QSet<QString> retTypes;
- foreach (const AbstractMetaFunction* func, m_overloads) {
- if (!func->typeReplaced(0).isEmpty())
- retTypes << func->typeReplaced(0);
- else if (func->type() && !func->argumentRemoved(0))
- retTypes << func->type()->cppSignature();
- else
- retTypes << "void";
- }
- return QStringList(retTypes.toList());
-}
-
-bool OverloadData::hasNonVoidReturnType() const
-{
- QStringList retTypes = returnTypes();
- return !retTypes.contains("void") || retTypes.size() > 1;
-}
-
-bool OverloadData::hasVarargs() const
-{
- foreach (const AbstractMetaFunction* func, m_overloads) {
- AbstractMetaArgumentList args = func->arguments();
- if (args.size() > 1 && args.last()->type()->isVarargs())
- return true;
- }
- return false;
-}
-
-bool OverloadData::hasAllowThread() const
-{
- foreach (const AbstractMetaFunction* func, m_overloads) {
- if (func->allowThread())
- return true;
- }
- return false;
-}
-
-bool OverloadData::hasStaticFunction(const AbstractMetaFunctionList& overloads)
-{
- foreach (const AbstractMetaFunction* func, overloads) {
- if (func->isStatic())
- return true;
- }
- return false;
-}
-
-bool OverloadData::hasStaticFunction() const
-{
- foreach (const AbstractMetaFunction* func, m_overloads) {
- if (func->isStatic())
- return true;
- }
- return false;
-}
-
-bool OverloadData::hasInstanceFunction(const AbstractMetaFunctionList& overloads)
-{
- foreach (const AbstractMetaFunction* func, overloads) {
- if (!func->isStatic())
- return true;
- }
- return false;
-}
-
-bool OverloadData::hasInstanceFunction() const
-{
- foreach (const AbstractMetaFunction* func, m_overloads) {
- if (!func->isStatic())
- return true;
- }
- return false;
-}
-
-bool OverloadData::hasStaticAndInstanceFunctions(const AbstractMetaFunctionList& overloads)
-{
- return OverloadData::hasStaticFunction(overloads) && OverloadData::hasInstanceFunction(overloads);
-}
-
-bool OverloadData::hasStaticAndInstanceFunctions() const
-{
- return OverloadData::hasStaticFunction() && OverloadData::hasInstanceFunction();
-}
-
-const AbstractMetaFunction* OverloadData::referenceFunction() const
-{
- return m_overloads.first();
-}
-
-const AbstractMetaArgument* OverloadData::argument(const AbstractMetaFunction* func) const
-{
- if (isHeadOverloadData() || !m_overloads.contains(func))
- return 0;
-
- int argPos = 0;
- int removed = 0;
- for (int i = 0; argPos <= m_argPos; i++) {
- if (func->argumentRemoved(i + 1))
- removed++;
- else
- argPos++;
- }
-
- return func->arguments()[m_argPos + removed];
-}
-
-OverloadDataList OverloadData::overloadDataOnPosition(OverloadData* overloadData, int argPos) const
-{
- OverloadDataList overloadDataList;
- if (overloadData->argPos() == argPos) {
- overloadDataList.append(overloadData);
- } else if (overloadData->argPos() < argPos) {
- foreach (OverloadData* pd, overloadData->nextOverloadData())
- overloadDataList += overloadDataOnPosition(pd, argPos);
- }
- return overloadDataList;
-}
-
-OverloadDataList OverloadData::overloadDataOnPosition(int argPos) const
-{
- OverloadDataList overloadDataList;
- overloadDataList += overloadDataOnPosition(m_headOverloadData, argPos);
- return overloadDataList;
-}
-
-bool OverloadData::nextArgumentHasDefaultValue() const
-{
- foreach (OverloadData* overloadData, m_nextOverloadData) {
- if (overloadData->getFunctionWithDefaultValue())
- return true;
- }
- return false;
-}
-
-static OverloadData* _findNextArgWithDefault(OverloadData* overloadData)
-{
- if (overloadData->getFunctionWithDefaultValue())
- return overloadData;
-
- OverloadData* result = 0;
- foreach (OverloadData* odata, overloadData->nextOverloadData()) {
- OverloadData* tmp = _findNextArgWithDefault(odata);
- if (!result || (tmp && result->argPos() > tmp->argPos()))
- result = tmp;
- }
- return result;
-}
-
-OverloadData* OverloadData::findNextArgWithDefault()
-{
- return _findNextArgWithDefault(this);
-}
-
-bool OverloadData::isFinalOccurrence(const AbstractMetaFunction* func) const
-{
- foreach (const OverloadData* pd, m_nextOverloadData) {
- if (pd->overloads().contains(func))
- return false;
- }
- return true;
-}
-
-QList<const AbstractMetaFunction*> OverloadData::overloadsWithoutRepetition() const
-{
- QList<const AbstractMetaFunction*> overloads = m_overloads;
- foreach (const AbstractMetaFunction* func, m_overloads) {
- if (func->minimalSignature().endsWith("const"))
- continue;
- foreach (const AbstractMetaFunction* f, overloads) {
- if ((func->minimalSignature() + "const") == f->minimalSignature()) {
- overloads.removeOne(f);
- break;
- }
- }
- }
- return overloads;
-}
-
-const AbstractMetaFunction* OverloadData::getFunctionWithDefaultValue() const
-{
- foreach (const AbstractMetaFunction* func, m_overloads) {
- int removedArgs = 0;
- for (int i = 0; i <= m_argPos + removedArgs; i++) {
- if (func->argumentRemoved(i + 1))
- removedArgs++;
- }
- if (!ShibokenGenerator::getDefaultValue(func, func->arguments()[m_argPos + removedArgs]).isEmpty())
- return func;
- }
- return 0;
-}
-
-QList<int> OverloadData::invalidArgumentLengths() const
-{
- QSet<int> validArgLengths;
-
- foreach (const AbstractMetaFunction* func, m_headOverloadData->m_overloads) {
- const AbstractMetaArgumentList args = func->arguments();
- int offset = 0;
- for (int i = 0; i < args.size(); ++i) {
- if (func->argumentRemoved(i+1)) {
- offset++;
- } else {
- if (!ShibokenGenerator::getDefaultValue(func, args[i]).isEmpty())
- validArgLengths << i-offset;
- }
- }
- validArgLengths << args.size() - offset;
- }
-
- QList<int> invalidArgLengths;
- for (int i = minArgs() + 1; i < maxArgs(); i++) {
- if (!validArgLengths.contains(i))
- invalidArgLengths.append(i);
- }
-
- return invalidArgLengths;
-}
-
-int OverloadData::numberOfRemovedArguments(const AbstractMetaFunction* func, int finalArgPos)
-{
- int removed = 0;
- if (finalArgPos < 0) {
- for (int i = 0; i < func->arguments().size(); i++) {
- if (func->argumentRemoved(i + 1))
- removed++;
- }
- } else {
- for (int i = 0; i < finalArgPos + removed; i++) {
- if (func->argumentRemoved(i + 1))
- removed++;
- }
- }
- return removed;
-}
-
-QPair<int, int> OverloadData::getMinMaxArguments(const AbstractMetaFunctionList& overloads)
-{
- int minArgs = 10000;
- int maxArgs = 0;
- for (int i = 0; i < overloads.size(); i++) {
- const AbstractMetaFunction* func = overloads[i];
- int origNumArgs = func->arguments().size();
- int removed = numberOfRemovedArguments(func);
- int numArgs = origNumArgs - removed;
- if (maxArgs < numArgs)
- maxArgs = numArgs;
- if (minArgs > numArgs)
- minArgs = numArgs;
- for (int j = 0; j < origNumArgs; j++) {
- if (func->argumentRemoved(j + 1))
- continue;
- int fixedArgIndex = j - removed;
- if (fixedArgIndex < minArgs && !ShibokenGenerator::getDefaultValue(func, func->arguments()[j]).isEmpty())
- minArgs = fixedArgIndex;
- }
- }
- return QPair<int, int>(minArgs, maxArgs);
-}
-
-bool OverloadData::isSingleArgument(const AbstractMetaFunctionList& overloads)
-{
- bool singleArgument = true;
- foreach (const AbstractMetaFunction* func, overloads) {
- if (func->arguments().size() - numberOfRemovedArguments(func) != 1) {
- singleArgument = false;
- break;
- }
- }
- return singleArgument;
-}
-
-void OverloadData::dumpGraph(QString filename) const
-{
- QFile file(filename);
- if (file.open(QFile::WriteOnly)) {
- QTextStream s(&file);
- s << m_headOverloadData->dumpGraph();
- }
-}
-
-QString OverloadData::dumpGraph() const
-{
- QString indent(4, ' ');
- QString result;
- QTextStream s(&result);
- if (m_argPos == -1) {
- const AbstractMetaFunction* rfunc = referenceFunction();
- s << "digraph OverloadedFunction {" << endl;
- s << indent << "graph [fontsize=12 fontname=freemono labelloc=t splines=true overlap=false rankdir=LR];" << endl;
-
- // Shows all function signatures
- s << "legend [fontsize=9 fontname=freemono shape=rect label=\"";
- foreach (const AbstractMetaFunction* func, overloads()) {
- s << "f" << functionNumber(func) << " : ";
- if (func->type())
- s << func->type()->cppSignature().replace('<', "&lt;").replace('>', "&gt;");
- else
- s << "void";
- s << ' ' << func->minimalSignature().replace('<', "&lt;").replace('>', "&gt;") << "\\l";
- }
- s << "\"];" << endl;
-
- // Function box title
- s << indent << '"' << rfunc->name() << "\" [shape=plaintext style=\"filled,bold\" margin=0 fontname=freemono fillcolor=white penwidth=1 ";
- s << "label=<<table border=\"0\" cellborder=\"0\" cellpadding=\"3\" bgcolor=\"white\">";
- s << "<tr><td bgcolor=\"black\" align=\"center\" cellpadding=\"6\" colspan=\"2\"><font color=\"white\">";
- if (rfunc->ownerClass())
- s << rfunc->ownerClass()->name() << "::";
- s << rfunc->name().replace('<', "&lt;").replace('>', "&gt;") << "</font>";
- if (rfunc->isVirtual()) {
- s << "<br/><font color=\"white\" point-size=\"10\">&lt;&lt;";
- if (rfunc->isAbstract())
- s << "pure ";
- s << "virtual&gt;&gt;</font>";
- }
- s << "</td></tr>";
-
- // Function return type
- s << "<tr><td bgcolor=\"gray\" align=\"right\">original type</td><td bgcolor=\"gray\" align=\"left\">";
- if (rfunc->type())
- s << rfunc->type()->cppSignature().replace('<', "&lt;").replace('>', "&gt;");
- else
- s << "void";
- s << "</td></tr>";
-
- // Shows type changes for all function signatures
- foreach (const AbstractMetaFunction* func, overloads()) {
- if (func->typeReplaced(0).isEmpty())
- continue;
- s << "<tr><td bgcolor=\"gray\" align=\"right\">f" << functionNumber(func);
- s << "-type</td><td bgcolor=\"gray\" align=\"left\">";
- s << func->typeReplaced(0).replace('<', "&lt;").replace('>', "&gt;") << "</td></tr>";
- }
-
- // Minimum and maximum number of arguments
- s << "<tr><td bgcolor=\"gray\" align=\"right\">minArgs</td><td bgcolor=\"gray\" align=\"left\">";
- s << minArgs() << "</td></tr>";
- s << "<tr><td bgcolor=\"gray\" align=\"right\">maxArgs</td><td bgcolor=\"gray\" align=\"left\">";
- s << maxArgs() << "</td></tr>";
-
- if (rfunc->ownerClass()) {
- if (rfunc->implementingClass() != rfunc->ownerClass())
- s << "<tr><td align=\"right\">implementor</td><td align=\"left\">" << rfunc->implementingClass()->name() << "</td></tr>";
- if (rfunc->declaringClass() != rfunc->ownerClass() && rfunc->declaringClass() != rfunc->implementingClass())
- s << "<tr><td align=\"right\">declarator</td><td align=\"left\">" << rfunc->declaringClass()->name() << "</td></tr>";
- }
-
- // Overloads for the signature to present point
- s << "<tr><td bgcolor=\"gray\" align=\"right\">overloads</td><td bgcolor=\"gray\" align=\"left\">";
- foreach (const AbstractMetaFunction* func, overloads())
- s << 'f' << functionNumber(func) << ' ';
- s << "</td></tr>";
-
- s << "</table>> ];" << endl;
-
- foreach (const OverloadData* pd, nextOverloadData())
- s << indent << '"' << rfunc->name() << "\" -> " << pd->dumpGraph();
-
- s << "}" << endl;
- } else {
- QString argId = QString("arg_%1").arg((ulong)this);
- s << argId << ';' << endl;
-
- s << indent << '"' << argId << "\" [shape=\"plaintext\" style=\"filled,bold\" margin=\"0\" fontname=\"freemono\" fillcolor=\"white\" penwidth=1 ";
- s << "label=<<table border=\"0\" cellborder=\"0\" cellpadding=\"3\" bgcolor=\"white\">";
-
- // Argument box title
- s << "<tr><td bgcolor=\"black\" align=\"left\" cellpadding=\"2\" colspan=\"2\">";
- s << "<font color=\"white\" point-size=\"11\">arg #" << argPos() << "</font></td></tr>";
-
- // Argument type information
- QString type = hasArgumentTypeReplace() ? argumentTypeReplaced() : argType()->cppSignature();
- s << "<tr><td bgcolor=\"gray\" align=\"right\">type</td><td bgcolor=\"gray\" align=\"left\">";
- s << type.replace("&", "&amp;") << "</td></tr>";
- if (hasArgumentTypeReplace()) {
- s << "<tr><td bgcolor=\"gray\" align=\"right\">orig. type</td><td bgcolor=\"gray\" align=\"left\">";
- s << argType()->cppSignature().replace("&", "&amp;") << "</td></tr>";
- }
-
- // Overloads for the signature to present point
- s << "<tr><td bgcolor=\"gray\" align=\"right\">overloads</td><td bgcolor=\"gray\" align=\"left\">";
- foreach (const AbstractMetaFunction* func, overloads())
- s << 'f' << functionNumber(func) << ' ';
- s << "</td></tr>";
-
- // Show default values (original and modified) for various functions
- foreach (const AbstractMetaFunction* func, overloads()) {
- const AbstractMetaArgument* arg = argument(func);
- if (!arg)
- continue;
- QString argDefault = ShibokenGenerator::getDefaultValue(func, arg);
- if (!argDefault.isEmpty() ||
- argDefault != arg->originalDefaultValueExpression()) {
- s << "<tr><td bgcolor=\"gray\" align=\"right\">f" << functionNumber(func);
- s << "-default</td><td bgcolor=\"gray\" align=\"left\">";
- s << argDefault << "</td></tr>";
- }
- if (argDefault != arg->originalDefaultValueExpression()) {
- s << "<tr><td bgcolor=\"gray\" align=\"right\">f" << functionNumber(func);
- s << "-orig-default</td><td bgcolor=\"gray\" align=\"left\">";
- s << arg->originalDefaultValueExpression() << "</td></tr>";
- }
- }
-
- s << "</table>>];" << endl;
-
- foreach (const OverloadData* pd, nextOverloadData())
- s << indent << argId << " -> " << pd->dumpGraph();
- }
- return result;
-}
-
-int OverloadData::functionNumber(const AbstractMetaFunction* func) const
-{
- return m_headOverloadData->m_overloads.indexOf(func);
-}
-
-OverloadData::~OverloadData()
-{
- while (!m_nextOverloadData.isEmpty())
- delete m_nextOverloadData.takeLast();
-}
-
-bool OverloadData::hasArgumentTypeReplace() const
-{
- return !m_argTypeReplaced.isEmpty();
-}
-
-QString OverloadData::argumentTypeReplaced() const
-{
- return m_argTypeReplaced;
-}
-
-bool OverloadData::hasArgumentWithDefaultValue(const AbstractMetaFunctionList& overloads)
-{
- if (OverloadData::getMinMaxArguments(overloads).second == 0)
- return false;
- foreach (const AbstractMetaFunction* func, overloads) {
- if (hasArgumentWithDefaultValue(func))
- return true;
- }
- return false;
-}
-
-bool OverloadData::hasArgumentWithDefaultValue() const
-{
- if (maxArgs() == 0)
- return false;
- foreach (const AbstractMetaFunction* func, overloads()) {
- if (hasArgumentWithDefaultValue(func))
- return true;
- }
- return false;
-}
-
-bool OverloadData::hasArgumentWithDefaultValue(const AbstractMetaFunction* func)
-{
- foreach (const AbstractMetaArgument* arg, func->arguments()) {
- if (func->argumentRemoved(arg->argumentIndex() + 1))
- continue;
- if (!ShibokenGenerator::getDefaultValue(func, arg).isEmpty())
- return true;
- }
- return false;
-}
-
-AbstractMetaArgumentList OverloadData::getArgumentsWithDefaultValues(const AbstractMetaFunction* func)
-{
- AbstractMetaArgumentList args;
- foreach (AbstractMetaArgument* arg, func->arguments()) {
- if (ShibokenGenerator::getDefaultValue(func, arg).isEmpty()
- || func->argumentRemoved(arg->argumentIndex() + 1))
- continue;
- args << arg;
- }
- return args;
-}
-
diff --git a/generators/shiboken/overloaddata.h b/generators/shiboken/overloaddata.h
deleted file mode 100644
index a0bd4640c..000000000
--- a/generators/shiboken/overloaddata.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * This file is part of the Shiboken Python Bindings 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
- *
- */
-
-#ifndef OVERLOADDATA_H
-#define OVERLOADDATA_H
-
-#include <abstractmetalang.h>
-#include <QtCore/QList>
-#include <QtCore/QBitArray>
-
-class ShibokenGenerator;
-
-class OverloadData;
-typedef QList<OverloadData*> OverloadDataList;
-
-class OverloadData
-{
-public:
- OverloadData(const AbstractMetaFunctionList& overloads, const ShibokenGenerator* generator);
- ~OverloadData();
-
- int minArgs() const { return m_headOverloadData->m_minArgs; }
- int maxArgs() const { return m_headOverloadData->m_maxArgs; }
- int argPos() const { return m_argPos; }
-
- const AbstractMetaType* argType() const { return m_argType; }
-
- /// Returns a string list containing all the possible return types (including void) for the current OverloadData.
- QStringList returnTypes() const;
-
- /// Returns true if any of the overloads for the current OverloadData has a return type different from void.
- bool hasNonVoidReturnType() const;
-
- /// Returns true if any of the overloads for the current OverloadData has a varargs argument.
- bool hasVarargs() const;
-
- /// Returns true if any of the overloads for the current OverloadData allows threads when called.
- bool hasAllowThread() const;
-
- /// Returns true if any of the overloads for the current OverloadData is static.
- bool hasStaticFunction() const;
-
- /// Returns true if any of the overloads passed as argument is static.
- static bool hasStaticFunction(const AbstractMetaFunctionList& overloads);
-
- /// Returns true if any of the overloads for the current OverloadData is not static.
- bool hasInstanceFunction() const;
-
- /// Returns true if any of the overloads passed as argument is not static.
- static bool hasInstanceFunction(const AbstractMetaFunctionList& overloads);
-
- /// Returns true if among the overloads for the current OverloadData there are static and non-static methods altogether.
- bool hasStaticAndInstanceFunctions() const;
-
- /// Returns true if among the overloads passed as argument there are static and non-static methods altogether.
- static bool hasStaticAndInstanceFunctions(const AbstractMetaFunctionList& overloads);
-
- const AbstractMetaFunction* referenceFunction() const;
- const AbstractMetaArgument* argument(const AbstractMetaFunction* func) const;
- OverloadDataList overloadDataOnPosition(int argPos) const;
-
- bool isHeadOverloadData() const { return this == m_headOverloadData; }
-
- /// Returns the root OverloadData object that represents all the overloads.
- OverloadData* headOverloadData() const { return m_headOverloadData; }
-
- /// Returns the function that has a default value at the current OverloadData argument position, otherwise returns null.
- const AbstractMetaFunction* getFunctionWithDefaultValue() const;
-
- bool nextArgumentHasDefaultValue() const;
- /// Returns the nearest occurrence, including this instance, of an argument with a default value.
- OverloadData* findNextArgWithDefault();
- bool isFinalOccurrence(const AbstractMetaFunction* func) const;
-
- /// Returns the list of overloads removing repeated constant functions (ex.: "foo()" and "foo()const", the second is removed).
- QList<const AbstractMetaFunction*> overloadsWithoutRepetition() const;
- const QList<const AbstractMetaFunction*>& overloads() const { return m_overloads; }
- OverloadDataList nextOverloadData() const { return m_nextOverloadData; }
- OverloadData* previousOverloadData() const { return m_previousOverloadData; }
-
- QList<int> invalidArgumentLengths() const;
-
- static int numberOfRemovedArguments(const AbstractMetaFunction* func, int finalArgPos = -1);
- static QPair<int, int> getMinMaxArguments(const AbstractMetaFunctionList& overloads);
- /// Returns true if all overloads have no more than one argument.
- static bool isSingleArgument(const AbstractMetaFunctionList& overloads);
-
- void dumpGraph(QString filename) const;
- QString dumpGraph() const;
-
- bool hasArgumentTypeReplace() const;
- QString argumentTypeReplaced() const;
-
- bool hasArgumentWithDefaultValue() const;
- static bool hasArgumentWithDefaultValue(const AbstractMetaFunctionList& overloads);
- static bool hasArgumentWithDefaultValue(const AbstractMetaFunction* func);
-
- /// Returns a list of function arguments which have default values and were not removed.
- static AbstractMetaArgumentList getArgumentsWithDefaultValues(const AbstractMetaFunction* func);
-
-private:
- OverloadData(OverloadData* headOverloadData, const AbstractMetaFunction* func,
- const AbstractMetaType* argType, int argPos);
-
- void addOverload(const AbstractMetaFunction* func);
- OverloadData* addOverloadData(const AbstractMetaFunction* func, const AbstractMetaArgument* arg);
-
- void sortNextOverloads();
-
- int functionNumber(const AbstractMetaFunction* func) const;
- OverloadDataList overloadDataOnPosition(OverloadData* overloadData, int argPos) const;
-
- int m_minArgs;
- int m_maxArgs;
- int m_argPos;
- const AbstractMetaType* m_argType;
- QString m_argTypeReplaced;
- QList<const AbstractMetaFunction*> m_overloads;
-
- OverloadData* m_headOverloadData;
- OverloadDataList m_nextOverloadData;
- OverloadData* m_previousOverloadData;
- const ShibokenGenerator* m_generator;
-};
-
-
-#endif // OVERLOADDATA_H
diff --git a/generators/shiboken/shibokengenerator.cpp b/generators/shiboken/shibokengenerator.cpp
deleted file mode 100644
index 2ae213dbb..000000000
--- a/generators/shiboken/shibokengenerator.cpp
+++ /dev/null
@@ -1,2466 +0,0 @@
-/*
- * This file is part of the Shiboken Python Bindings Generator project.
- *
- * Copyright (C) 2009-2012 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 "overloaddata.h"
-#include <reporthandler.h>
-#include <typedatabase.h>
-
-#include <QtCore/QDir>
-#include <QtCore/QDebug>
-#include <limits>
-#include <memory>
-
-#define NULL_VALUE "NULL"
-#define AVOID_PROTECTED_HACK "avoid-protected-hack"
-#define PARENT_CTOR_HEURISTIC "enable-parent-ctor-heuristic"
-#define RETURN_VALUE_HEURISTIC "enable-return-value-heuristic"
-#define ENABLE_PYSIDE_EXTENSIONS "enable-pyside-extensions"
-#define DISABLE_VERBOSE_ERROR_MESSAGES "disable-verbose-error-messages"
-#define USE_ISNULL_AS_NB_NONZERO "use-isnull-as-nb_nonzero"
-
-//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>();
-QHash<QString, QString> ShibokenGenerator::m_tpFuncs = QHash<QString, QString>();
-QStringList ShibokenGenerator::m_knownPythonTypes = QStringList();
-
-static QString resolveScopePrefix(const AbstractMetaClass* scope, const QString& value)
-{
- if (!scope)
- return QString();
-
- QString name;
- QStringList parts = scope->qualifiedCppName().split("::", QString::SkipEmptyParts);
- for(int i = (parts.size() - 1) ; i >= 0; i--) {
- if (!value.startsWith(parts[i] + "::"))
- name = parts[i] + "::" + name;
- else
- name = "";
- }
-
- return name;
-}
-ShibokenGenerator::ShibokenGenerator() : Generator()
-{
- if (m_pythonPrimitiveTypeName.isEmpty())
- ShibokenGenerator::initPrimitiveTypesCorrespondences();
-
- if (m_tpFuncs.isEmpty())
- ShibokenGenerator::clearTpFuncs();
-
- if (m_knownPythonTypes.isEmpty())
- ShibokenGenerator::initKnownPythonTypes();
-
- m_metaTypeFromStringCache = AbstractMetaTypeCache();
-
- m_typeSystemConvName[TypeSystemCheckFunction] = "checkType";
- m_typeSystemConvName[TypeSystemIsConvertibleFunction] = "isConvertible";
- m_typeSystemConvName[TypeSystemToCppFunction] = "toCpp";
- m_typeSystemConvName[TypeSystemToPythonFunction] = "toPython";
- m_typeSystemConvRegEx[TypeSystemCheckFunction] = QRegExp(CHECKTYPE_REGEX);
- m_typeSystemConvRegEx[TypeSystemIsConvertibleFunction] = QRegExp(ISCONVERTIBLE_REGEX);
- m_typeSystemConvRegEx[TypeSystemToPythonFunction] = QRegExp(CONVERTTOPYTHON_REGEX);
- m_typeSystemConvRegEx[TypeSystemToCppFunction] = QRegExp(CONVERTTOCPP_REGEX);
-}
-
-ShibokenGenerator::~ShibokenGenerator()
-{
- // TODO-CONVERTER: it must be caching types that were not created here.
- //qDeleteAll(m_metaTypeFromStringCache.values());
-}
-
-void ShibokenGenerator::clearTpFuncs()
-{
- m_tpFuncs["__str__"] = QString("0");
- m_tpFuncs["__repr__"] = QString("0");
- m_tpFuncs["__iter__"] = QString("0");
- m_tpFuncs["__next__"] = QString("0");
-}
-
-void ShibokenGenerator::initPrimitiveTypesCorrespondences()
-{
- // Python primitive types names
- m_pythonPrimitiveTypeName.clear();
-
- // PyBool
- m_pythonPrimitiveTypeName["bool"] = "PyBool";
-
- // PyInt
- m_pythonPrimitiveTypeName["char"] = "SbkChar";
- m_pythonPrimitiveTypeName["signed char"] = "SbkChar";
- m_pythonPrimitiveTypeName["unsigned char"] = "SbkChar";
- m_pythonPrimitiveTypeName["int"] = "PyInt";
- m_pythonPrimitiveTypeName["signed int"] = "PyInt";
- m_pythonPrimitiveTypeName["uint"] = "PyInt";
- m_pythonPrimitiveTypeName["unsigned int"] = "PyInt";
- m_pythonPrimitiveTypeName["short"] = "PyInt";
- m_pythonPrimitiveTypeName["ushort"] = "PyInt";
- m_pythonPrimitiveTypeName["signed short"] = "PyInt";
- m_pythonPrimitiveTypeName["signed short int"] = "PyInt";
- m_pythonPrimitiveTypeName["unsigned short"] = "PyInt";
- m_pythonPrimitiveTypeName["unsigned short int"] = "PyInt";
- m_pythonPrimitiveTypeName["long"] = "PyInt";
-
- // PyFloat
- m_pythonPrimitiveTypeName["double"] = "PyFloat";
- m_pythonPrimitiveTypeName["float"] = "PyFloat";
-
- // PyLong
- m_pythonPrimitiveTypeName["unsigned long"] = "PyLong";
- m_pythonPrimitiveTypeName["signed long"] = "PyLong";
- m_pythonPrimitiveTypeName["ulong"] = "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();
-
- // call operator
- m_pythonOperators["operator()"] = "call";
-
- // 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++"] = "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("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");
-}
-
-void ShibokenGenerator::initKnownPythonTypes()
-{
- m_knownPythonTypes.clear();
- m_knownPythonTypes << "PyBool" << "PyInt" << "PyFloat" << "PyLong";
- m_knownPythonTypes << "PyObject" << "PyString" << "PyBuffer";
- m_knownPythonTypes << "PySequence" << "PyTuple" << "PyList" << "PyDict";
- m_knownPythonTypes << "PyObject*" << "PyObject *" << "PyTupleObject*";
-}
-
-QString ShibokenGenerator::translateTypeForWrapperMethod(const AbstractMetaType* cType,
- const AbstractMetaClass* context,
- Options options) const
-{
- if (cType->isArray())
- return translateTypeForWrapperMethod(cType->arrayElementType(), context, options) + "[]";
-
- if (avoidProtectedHack() && cType->isEnum()) {
- const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(cType);
- if (metaEnum && metaEnum->isProtected())
- return protectedEnumSurrogateName(metaEnum);
- }
-
- return translateType(cType, context, options);
-}
-
-bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass* metaClass) const
-{
- bool result = metaClass->isPolymorphic() || metaClass->hasVirtualDestructor();
- if (avoidProtectedHack()) {
- result = result || metaClass->hasProtectedFields() || metaClass->hasProtectedDestructor();
- if (!result && metaClass->hasProtectedFunctions()) {
- int protectedFunctions = 0;
- int protectedOperators = 0;
- foreach (const AbstractMetaFunction* func, metaClass->functions()) {
- if (!func->isProtected() || func->isSignal() || func->isModifiedRemoved())
- continue;
- else if (func->isOperatorOverload())
- protectedOperators++;
- else
- protectedFunctions++;
- }
- result = result || (protectedFunctions > protectedOperators);
- }
- } else {
- result = result && !metaClass->hasPrivateDestructor();
- }
- return result && !metaClass->isNamespace();
-}
-
-void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList& enumList, const AbstractMetaClass* metaClass)
-{
- if (!metaClass)
- return;
-
- if (metaClass->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass) {
- foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) {
- if (metaEnum->isPrivate() || metaEnum->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass)
- continue;
- if (!enumList.contains(const_cast<AbstractMetaEnum*>(metaEnum)))
- enumList.append(const_cast<AbstractMetaEnum*>(metaEnum));
- }
- lookForEnumsInClassesNotToBeGenerated(enumList, metaClass->enclosingClass());
- }
-}
-
-static const AbstractMetaClass* getProperEnclosingClass(const AbstractMetaClass* metaClass)
-{
- if (!metaClass)
- return 0;
-
- if (metaClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass)
- return metaClass;
-
- return getProperEnclosingClass(metaClass->enclosingClass());
-}
-
-const AbstractMetaClass* ShibokenGenerator::getProperEnclosingClassForEnum(const AbstractMetaEnum* metaEnum)
-{
- return getProperEnclosingClass(metaEnum->enclosingClass());
-}
-
-QString ShibokenGenerator::wrapperName(const AbstractMetaClass* metaClass) const
-{
- if (shouldGenerateCppWrapper(metaClass)) {
- QString result = metaClass->name();
- if (metaClass->enclosingClass()) // is a inner class
- result.replace("::", "_");
-
- result +="Wrapper";
- return result;
- } else {
- return metaClass->qualifiedCppName();
- }
-}
-
-QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction* func)
-{
- QString funcName;
- if (func->isOperatorOverload())
- funcName = ShibokenGenerator::pythonOperatorFunctionName(func);
- else
- funcName = func->name();
- if (func->ownerClass()) {
- QString fullName = func->ownerClass()->fullName();
- if (func->isConstructor())
- funcName = fullName;
- else
- funcName.prepend(fullName + '.');
- }
- return funcName;
-}
-
-QString ShibokenGenerator::protectedEnumSurrogateName(const AbstractMetaEnum* metaEnum)
-{
- return metaEnum->fullName().replace(".", "_") + "_Surrogate";
-}
-
-QString ShibokenGenerator::protectedFieldGetterName(const AbstractMetaField* field)
-{
- return QString("protected_%1_getter").arg(field->name());
-}
-
-QString ShibokenGenerator::protectedFieldSetterName(const AbstractMetaField* field)
-{
- return QString("protected_%1_setter").arg(field->name());
-}
-
-QString ShibokenGenerator::cpythonFunctionName(const AbstractMetaFunction* func)
-{
- QString result;
-
- if (func->ownerClass()) {
- result = cpythonBaseName(func->ownerClass()->typeEntry());
- if (func->isConstructor() || func->isCopyConstructor()) {
- result += "_Init";
- } else {
- result += "Func_";
- if (func->isOperatorOverload())
- result += ShibokenGenerator::pythonOperatorFunctionName(func);
- else
- result += func->name();
- }
- } else {
- result = "Sbk" + moduleName() + "Module_" + func->name();
- }
-
- return result;
-}
-
-QString ShibokenGenerator::cpythonMethodDefinitionName(const AbstractMetaFunction* func)
-{
- if (!func->ownerClass())
- return QString();
- return QString("%1Method_%2").arg(cpythonBaseName(func->ownerClass()->typeEntry())).arg(func->name());
-}
-
-QString ShibokenGenerator::cpythonGettersSettersDefinitionName(const AbstractMetaClass* metaClass)
-{
- return QString("%1_getsetlist").arg(cpythonBaseName(metaClass));
-}
-
-QString ShibokenGenerator::cpythonSetattroFunctionName(const AbstractMetaClass* metaClass)
-{
- return QString("%1_setattro").arg(cpythonBaseName(metaClass));
-}
-
-
-QString ShibokenGenerator::cpythonGetattroFunctionName(const AbstractMetaClass* metaClass)
-{
- return QString("%1_getattro").arg(cpythonBaseName(metaClass));
-}
-
-QString ShibokenGenerator::cpythonGetterFunctionName(const AbstractMetaField* metaField)
-{
- return QString("%1_get_%2").arg(cpythonBaseName(metaField->enclosingClass())).arg(metaField->name());
-}
-
-QString ShibokenGenerator::cpythonSetterFunctionName(const AbstractMetaField* metaField)
-{
- return QString("%1_set_%2").arg(cpythonBaseName(metaField->enclosingClass())).arg(metaField->name());
-}
-
-static QString cpythonEnumFlagsName(QString moduleName, QString qualifiedCppName)
-{
- QString result = QString("Sbk%1_%2").arg(moduleName).arg(qualifiedCppName);
- result.replace("::", "_");
- return result;
-}
-
-static QString searchForEnumScope(const AbstractMetaClass* metaClass, const QString& value)
-{
- QString enumValueName = value.trimmed();
-
- if (!metaClass)
- return QString();
-
- foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) {
- foreach (const AbstractMetaEnumValue* enumValue, metaEnum->values()) {
- if (enumValueName == enumValue->name())
- return metaClass->qualifiedCppName();
- }
- }
-
- return searchForEnumScope(metaClass->enclosingClass(), enumValueName);
-}
-
-/*
- * This function uses some heuristics to find out the scope for a given
- * argument default value. New situations may arise in the future and
- * this method should be updated, do it with care.
- */
-QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg)
-{
- QString value = getDefaultValue(func, arg);
- if (value.isEmpty())
- return QString();
-
- static QRegExp enumValueRegEx("^([A-Za-z_]\\w*)?$");
- QString prefix;
- QString suffix;
-
- if (arg->type()->isEnum()) {
- const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(arg->type());
- if (metaEnum)
- prefix = resolveScopePrefix(metaEnum->enclosingClass(), value);
- } else if (arg->type()->isFlags()) {
- static QRegExp numberRegEx("^\\d+$"); // Numbers to flags
- if (numberRegEx.exactMatch(value)) {
- QString typeName = translateTypeForWrapperMethod(arg->type(), func->implementingClass());
- if (arg->type()->isConstant())
- typeName.remove(0, sizeof("const ") / sizeof(char) - 1);
- if (arg->type()->isReference())
- typeName.chop(1);
- prefix = typeName + '(';
- suffix = ')';
- }
-
- static QRegExp enumCombinationRegEx("^([A-Za-z_][\\w:]*)\\(([^,\\(\\)]*)\\)$"); // FlagName(EnumItem|EnumItem|...)
- if (prefix.isEmpty() && enumCombinationRegEx.indexIn(value) != -1) {
- QString flagName = enumCombinationRegEx.cap(1);
- QStringList enumItems = enumCombinationRegEx.cap(2).split("|");
- QString scope = searchForEnumScope(func->implementingClass(), enumItems.first());
- if (!scope.isEmpty())
- scope.append("::");
-
- QStringList fixedEnumItems;
- foreach (const QString& enumItem, enumItems)
- fixedEnumItems << QString(scope + enumItem);
-
- if (!fixedEnumItems.isEmpty()) {
- prefix = flagName + '(';
- value = fixedEnumItems.join("|");
- suffix = ')';
- }
- }
- } else if (arg->type()->typeEntry()->isValue()) {
- const AbstractMetaClass* metaClass = classes().findClass(arg->type()->typeEntry());
- if (enumValueRegEx.exactMatch(value))
- prefix = resolveScopePrefix(metaClass, value);
- } else if (arg->type()->isPrimitive() && arg->type()->name() == "int") {
- if (enumValueRegEx.exactMatch(value) && func->implementingClass())
- prefix = resolveScopePrefix(func->implementingClass(), value);
- } else if(arg->type()->isPrimitive()) {
- static QRegExp unknowArgumentRegEx("^(?:[A-Za-z_][\\w:]*\\()?([A-Za-z_]\\w*)(?:\\))?$"); // [PrimitiveType(] DESIREDNAME [)]
- if (unknowArgumentRegEx.indexIn(value) != -1 && func->implementingClass()) {
- foreach (const AbstractMetaField* field, func->implementingClass()->fields()) {
- if (unknowArgumentRegEx.cap(1).trimmed() == field->name()) {
- QString fieldName = field->name();
- if (field->isStatic()) {
- prefix = resolveScopePrefix(func->implementingClass(), value);
- fieldName.prepend(prefix);
- prefix= "";
- } else {
- fieldName.prepend(CPP_SELF_VAR "->");
- }
- value.replace(unknowArgumentRegEx.cap(1), fieldName);
- break;
- }
- }
- }
- }
-
- if (!prefix.isEmpty())
- value.prepend(prefix);
- if (!suffix.isEmpty())
- value.append(suffix);
-
- return value;
-}
-
-QString ShibokenGenerator::cpythonEnumName(const EnumTypeEntry* enumEntry)
-{
- return cpythonEnumFlagsName(enumEntry->targetLangPackage().replace(".", "_"), enumEntry->qualifiedCppName());
-}
-
-QString ShibokenGenerator::cpythonFlagsName(const FlagsTypeEntry* flagsEntry)
-{
- return cpythonEnumFlagsName(flagsEntry->targetLangPackage().replace(".", "_"), flagsEntry->originalName());
-}
-
-QString ShibokenGenerator::cpythonSpecialCastFunctionName(const AbstractMetaClass* metaClass)
-{
- return cpythonBaseName(metaClass->typeEntry())+"SpecialCastFunction";
-}
-
-QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClass* metaClass, QString argName)
-{
- return cpythonWrapperCPtr(metaClass->typeEntry(), argName);
-}
-
-QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType* metaType, QString argName)
-{
- return cpythonWrapperCPtr(metaType->typeEntry(), argName);
-}
-
-QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntry* type, QString argName)
-{
- if (!ShibokenGenerator::isWrapperType(type))
- return QString();
- return QString("((::%1*)Shiboken::Conversions::cppPointer(%2, (SbkObject*)%3))")
- .arg(type->qualifiedCppName())
- .arg(cpythonTypeNameExt(type))
- .arg(argName);
-}
-
-QString ShibokenGenerator::getFunctionReturnType(const AbstractMetaFunction* func, Options options) const
-{
- if (func->ownerClass() && (func->isConstructor() || func->isCopyConstructor()))
- return func->ownerClass()->qualifiedCppName() + '*';
-
- return translateTypeForWrapperMethod(func->type(), func->implementingClass());
-}
-
-void ShibokenGenerator::writeToPythonConversion(QTextStream& s, const AbstractMetaType* type,
- const AbstractMetaClass* context, const QString& argumentName)
-{
- s << cpythonToPythonConversionFunction(type) << argumentName << ')';
-}
-
-void ShibokenGenerator::writeToCppConversion(QTextStream& s, const AbstractMetaClass* metaClass,
- const QString& inArgName, const QString& outArgName)
-{
- s << cpythonToCppConversionFunction(metaClass) << inArgName << ", &" << outArgName << ')';
-}
-
-void ShibokenGenerator::writeToCppConversion(QTextStream& s, const AbstractMetaType* type, const AbstractMetaClass* context,
- const QString& inArgName, const QString& outArgName)
-{
- s << cpythonToCppConversionFunction(type, context) << inArgName << ", &" << outArgName << ')';
-}
-
-bool ShibokenGenerator::shouldRejectNullPointerArgument(const AbstractMetaFunction* func, int argIndex)
-{
- if (argIndex < 0 || argIndex >= func->arguments().count())
- return false;
-
- const AbstractMetaArgument* arg = func->arguments().at(argIndex);
- if (isValueTypeWithCopyConstructorOnly(arg->type()))
- return true;
-
- // Argument type is not a pointer, a None rejection should not be
- // necessary because the type checking would handle that already.
- if (!isPointer(arg->type()))
- return false;
- if (func->argumentRemoved(argIndex + 1))
- return false;
- foreach (FunctionModification funcMod, func->modifications()) {
- foreach (ArgumentModification argMod, funcMod.argument_mods) {
- if (argMod.index == argIndex + 1 && argMod.noNullPointers)
- return true;
- }
- }
- return false;
-}
-
-QString ShibokenGenerator::getFormatUnitString(const AbstractMetaFunction* func, bool incRef) const
-{
- QString result;
- const char objType = (incRef ? 'O' : 'N');
- foreach (const AbstractMetaArgument* arg, func->arguments()) {
- if (func->argumentRemoved(arg->argumentIndex() + 1))
- continue;
-
- if (!func->typeReplaced(arg->argumentIndex() + 1).isEmpty()) {
- result += objType;
- } else if (arg->type()->isQObject()
- || arg->type()->isObject()
- || arg->type()->isValue()
- || arg->type()->isValuePointer()
- || arg->type()->isNativePointer()
- || arg->type()->isEnum()
- || arg->type()->isFlags()
- || arg->type()->isContainer()
- || arg->type()->isReference()) {
- result += objType;
- } else if (arg->type()->isPrimitive()) {
- const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) arg->type()->typeEntry();
- if (ptype->basicAliasedTypeEntry())
- ptype = ptype->basicAliasedTypeEntry();
- if (m_formatUnits.contains(ptype->name()))
- result += m_formatUnits[ptype->name()];
- else
- result += objType;
- } else if (isCString(arg->type())) {
- result += 'z';
- } else {
- QString report;
- QTextStream(&report) << "Method: " << func->ownerClass()->qualifiedCppName()
- << "::" << func->signature() << " => Arg:"
- << arg->name() << "index: " << arg->argumentIndex()
- << " - cannot be handled properly. Use an inject-code to fix it!";
- ReportHandler::warning(report);
- result += '?';
- }
- }
- return result;
-}
-
-QString ShibokenGenerator::cpythonBaseName(const AbstractMetaType* type)
-{
- if (isCString(type))
- return QString("PyString");
- return cpythonBaseName(type->typeEntry());
-}
-
-QString ShibokenGenerator::cpythonBaseName(const AbstractMetaClass* metaClass)
-{
- return cpythonBaseName(metaClass->typeEntry());
-}
-
-QString ShibokenGenerator::cpythonBaseName(const TypeEntry* type)
-{
- QString baseName;
- if (ShibokenGenerator::isWrapperType(type) || type->isNamespace()) { // && !type->isReference()) {
- baseName = "Sbk_" + type->name();
- } else if (type->isPrimitive()) {
- const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) type;
- while (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->isFlags()) {
- baseName = cpythonFlagsName((const FlagsTypeEntry*) 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";
- baseName = "PySequence";
- break;
- case ContainerTypeEntry::SetContainer:
- baseName = "PySet";
- break;
- case ContainerTypeEntry::MapContainer:
- case ContainerTypeEntry::MultiMapContainer:
- case ContainerTypeEntry::HashContainer:
- case ContainerTypeEntry::MultiHashContainer:
- baseName = "PyDict";
- break;
- default:
- Q_ASSERT(false);
- }
- } else {
- baseName = "PyObject";
- }
- return baseName.replace("::", "_");
-}
-
-QString ShibokenGenerator::cpythonTypeName(const AbstractMetaClass* metaClass)
-{
- return cpythonTypeName(metaClass->typeEntry());
-}
-
-QString ShibokenGenerator::cpythonTypeName(const TypeEntry* type)
-{
- return cpythonBaseName(type) + "_Type";
-}
-
-QString ShibokenGenerator::cpythonTypeNameExt(const TypeEntry* type)
-{
- return cppApiVariableName(type->targetLangPackage()) + '[' + getTypeIndexVariableName(type) + ']';
-}
-
-QString ShibokenGenerator::converterObject(const AbstractMetaType* type)
-{
- if (isCString(type))
- return "Shiboken::Conversions::PrimitiveTypeConverter<const char*>()";
- if (isVoidPointer(type))
- return "Shiboken::Conversions::PrimitiveTypeConverter<void*>()";
- if (type->typeEntry()->isContainer())
- return QString("%1[%2]").arg(convertersVariableName(type->typeEntry()->targetLangPackage())).arg(getTypeIndexVariableName(type));
-
- return converterObject(type->typeEntry());
-}
-
-QString ShibokenGenerator::converterObject(const TypeEntry* type)
-{
- if (isCppPrimitive(type))
- return QString("Shiboken::Conversions::PrimitiveTypeConverter<%1>()").arg(type->qualifiedCppName());
- if (isWrapperType(type) || type->isEnum() || type->isFlags())
- return QString("SBK_CONVERTER(%1)").arg(cpythonTypeNameExt(type));
-
- /* the typedef'd primitive types case */
- const PrimitiveTypeEntry* pte = reinterpret_cast<const PrimitiveTypeEntry*>(type);
- if (pte->basicAliasedTypeEntry())
- pte = pte->basicAliasedTypeEntry();
- if (pte->isPrimitive() && !pte->isCppPrimitive() && !pte->customConversion())
- return QString("Shiboken::Conversions::PrimitiveTypeConverter<%1>()").arg(pte->qualifiedCppName());
-
- return QString("%1[%2]").arg(convertersVariableName(type->targetLangPackage())).arg(getTypeIndexVariableName(type));
-}
-
-QString ShibokenGenerator::cpythonTypeNameExt(const AbstractMetaType* type)
-{
- return cppApiVariableName(type->typeEntry()->targetLangPackage()) + '[' + getTypeIndexVariableName(type) + ']';
-}
-
-QString ShibokenGenerator::cpythonOperatorFunctionName(const AbstractMetaFunction* func)
-{
- if (!func->isOperatorOverload())
- return QString();
- return QString("Sbk") + func->ownerClass()->name()
- + '_' + pythonOperatorFunctionName(func->originalName());
-}
-
-QString ShibokenGenerator::fixedCppTypeName(const CustomConversion::TargetToNativeConversion* toNative)
-{
- if (toNative->sourceType())
- return fixedCppTypeName(toNative->sourceType());
- return toNative->sourceTypeName();
-}
-QString ShibokenGenerator::fixedCppTypeName(const AbstractMetaType* type)
-{
- return fixedCppTypeName(type->typeEntry(), type->cppSignature());
-}
-
-static QString _fixedCppTypeName(QString typeName)
-{
- return typeName.replace(" ", "")
- .replace(".", "_")
- .replace(",", "_")
- .replace("<", "_")
- .replace(">", "_")
- .replace("::", "_")
- .replace("*", "PTR")
- .replace("&", "REF");
-}
-QString ShibokenGenerator::fixedCppTypeName(const TypeEntry* type, QString typeName)
-{
- if (typeName.isEmpty())
- typeName = type->qualifiedCppName();
- if (!(type->codeGeneration() & TypeEntry::GenerateTargetLang))
- typeName.prepend(QString("%1_").arg(type->targetLangPackage()));
- return _fixedCppTypeName(typeName);
-}
-
-QString ShibokenGenerator::pythonPrimitiveTypeName(const QString& cppTypeName)
-{
- return ShibokenGenerator::m_pythonPrimitiveTypeName.value(cppTypeName, QString());
-}
-
-QString ShibokenGenerator::pythonPrimitiveTypeName(const PrimitiveTypeEntry* type)
-{
- while (type->basicAliasedTypeEntry())
- type = type->basicAliasedTypeEntry();
- return pythonPrimitiveTypeName(type->name());
-}
-
-QString ShibokenGenerator::pythonOperatorFunctionName(QString cppOpFuncName)
-{
- QString value = m_pythonOperators.value(cppOpFuncName);
- if (value.isEmpty()) {
- ReportHandler::warning("Unknown operator: "+cppOpFuncName);
- value = "UNKNOWN_OPERATOR";
- }
- value.prepend("__").append("__");
- return value;
-}
-
-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;
-}
-
-QString ShibokenGenerator::pythonRichCompareOperatorId(QString cppOpFuncName)
-{
- return QString("Py_%1").arg(m_pythonOperators.value(cppOpFuncName).toUpper());
-}
-
-QString ShibokenGenerator::pythonRichCompareOperatorId(const AbstractMetaFunction* func)
-{
- return pythonRichCompareOperatorId(func->originalName());
-}
-
-bool ShibokenGenerator::isNumber(QString cpythonApiName)
-{
- return cpythonApiName == "PyInt"
- || cpythonApiName == "PyFloat"
- || cpythonApiName == "PyLong"
- || cpythonApiName == "PyBool";
-}
-
-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::isPairContainer(const AbstractMetaType* type)
-{
- return type->isContainer()
- && ((ContainerTypeEntry*)type->typeEntry())->type() == ContainerTypeEntry::PairContainer;
-}
-
-bool ShibokenGenerator::isWrapperType(const TypeEntry* type)
-{
- if (type->isComplex())
- return ShibokenGenerator::isWrapperType((const ComplexTypeEntry*)type);
- return type->isObject() || type->isValue();
-}
-bool ShibokenGenerator::isWrapperType(const ComplexTypeEntry* type)
-{
- return isObjectType(type) || type->isValue();
-}
-bool ShibokenGenerator::isWrapperType(const AbstractMetaType* metaType)
-{
- return isObjectType(metaType)
- || metaType->typeEntry()->isValue();
-}
-
-bool ShibokenGenerator::isPointerToWrapperType(const AbstractMetaType* type)
-{
- return (isObjectType(type) && type->indirections() == 1) || type->isValuePointer();
-}
-
-bool ShibokenGenerator::isObjectTypeUsedAsValueType(const AbstractMetaType* type)
-{
- return type->typeEntry()->isObject() && !type->isReference() && type->indirections() == 0;
-}
-
-bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const AbstractMetaClass* metaClass)
-{
- if (!metaClass || !metaClass->typeEntry()->isValue())
- return false;
- AbstractMetaFunctionList ctors = metaClass->queryFunctions(AbstractMetaClass::Constructors);
- if (ctors.count() != 1)
- return false;
- return ctors.first()->isCopyConstructor();
-}
-
-bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const TypeEntry* type) const
-{
- if (!type || !type->isValue())
- return false;
- return isValueTypeWithCopyConstructorOnly(classes().findClass(type));
-}
-
-bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const AbstractMetaType* type) const
-{
- if (!type || !type->typeEntry()->isValue())
- return false;
- return isValueTypeWithCopyConstructorOnly(type->typeEntry());
-}
-
-bool ShibokenGenerator::isUserPrimitive(const TypeEntry* type)
-{
- if (!type->isPrimitive())
- return false;
- const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type;
- if (trueType->basicAliasedTypeEntry())
- trueType = trueType->basicAliasedTypeEntry();
- return trueType->isPrimitive() && !trueType->isCppPrimitive() && trueType->qualifiedCppName() != "std::string";
-}
-
-bool ShibokenGenerator::isUserPrimitive(const AbstractMetaType* type)
-{
- if (type->indirections() != 0)
- return false;
- return isUserPrimitive(type->typeEntry());
-}
-
-bool ShibokenGenerator::isCppPrimitive(const TypeEntry* type)
-{
- if (type->isCppPrimitive())
- return true;
- if (!type->isPrimitive())
- return false;
- const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type;
- if (trueType->basicAliasedTypeEntry())
- trueType = trueType->basicAliasedTypeEntry();
- return trueType->qualifiedCppName() == "std::string";
-}
-
-bool ShibokenGenerator::isCppPrimitive(const AbstractMetaType* type)
-{
- if (isCString(type) || isVoidPointer(type))
- return true;
- if (type->indirections() != 0)
- return false;
- return isCppPrimitive(type->typeEntry());
-}
-
-bool ShibokenGenerator::shouldDereferenceArgumentPointer(const AbstractMetaArgument* arg)
-{
- return shouldDereferenceAbstractMetaTypePointer(arg->type());
-}
-
-bool ShibokenGenerator::shouldDereferenceAbstractMetaTypePointer(const AbstractMetaType* metaType)
-{
- return metaType->isReference() && isWrapperType(metaType) && !isPointer(metaType);
-}
-
-bool ShibokenGenerator::visibilityModifiedToPrivate(const AbstractMetaFunction* func)
-{
- foreach (FunctionModification mod, func->modifications()) {
- if (mod.modifiers & Modification::Private)
- return true;
- }
- return false;
-}
-
-QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType, bool genericNumberType)
-{
- QString customCheck;
- if (metaType->typeEntry()->isCustom()) {
- AbstractMetaType* type;
- customCheck = guessCPythonCheckFunction(metaType->typeEntry()->name(), &type);
- if (type)
- metaType = type;
- if (!customCheck.isEmpty())
- return customCheck;
- }
-
- if (isCppPrimitive(metaType)) {
- if (isCString(metaType))
- return "Shiboken::String::check";
- if (isVoidPointer(metaType))
- return "PyObject_Check";
- return cpythonCheckFunction(metaType->typeEntry(), genericNumberType);
- } else if (metaType->typeEntry()->isContainer()) {
- QString typeCheck = "Shiboken::Conversions::";
- ContainerTypeEntry::Type type = ((const ContainerTypeEntry*)metaType->typeEntry())->type();
- if (type == ContainerTypeEntry::ListContainer
- || type == ContainerTypeEntry::StringListContainer
- || type == ContainerTypeEntry::LinkedListContainer
- || type == ContainerTypeEntry::VectorContainer
- || type == ContainerTypeEntry::StackContainer
- || type == ContainerTypeEntry::SetContainer
- || type == ContainerTypeEntry::QueueContainer) {
- const AbstractMetaType* type = metaType->instantiations().first();
- if (isPointerToWrapperType(type))
- typeCheck += QString("checkSequenceTypes(%1, ").arg(cpythonTypeNameExt(type));
- else if (isWrapperType(type))
- typeCheck += QString("convertibleSequenceTypes((SbkObjectType*)%1, ").arg(cpythonTypeNameExt(type));
- else
- typeCheck += QString("convertibleSequenceTypes(%1, ").arg(converterObject(type));
- } else if (type == ContainerTypeEntry::MapContainer
- || type == ContainerTypeEntry::MultiMapContainer
- || type == ContainerTypeEntry::HashContainer
- || type == ContainerTypeEntry::MultiHashContainer
- || type == ContainerTypeEntry::PairContainer) {
- QString pyType = (type == ContainerTypeEntry::PairContainer) ? "Pair" : "Dict";
- const AbstractMetaType* firstType = metaType->instantiations().first();
- const AbstractMetaType* secondType = metaType->instantiations().last();
- if (isPointerToWrapperType(firstType) && isPointerToWrapperType(secondType)) {
- typeCheck += QString("check%1Types(%2, %3, ").arg(pyType)
- .arg(cpythonTypeNameExt(firstType))
- .arg(cpythonTypeNameExt(secondType));
- } else {
- typeCheck += QString("convertible%1Types(%2, %3, %4, %5, ").arg(pyType)
- .arg(converterObject(firstType))
- .arg(isPointerToWrapperType(firstType) ? "true" : "false")
- .arg(converterObject(secondType))
- .arg(isPointerToWrapperType(secondType) ? "true" : "false");
- }
- }
- return typeCheck;
- }
- return cpythonCheckFunction(metaType->typeEntry(), genericNumberType);
-}
-
-QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry* type, bool genericNumberType)
-{
- QString customCheck;
- if (type->isCustom()) {
- AbstractMetaType* metaType;
- customCheck = guessCPythonCheckFunction(type->name(), &metaType);
- if (metaType)
- return cpythonCheckFunction(metaType, genericNumberType);
- return customCheck;
- }
-
- if (type->isEnum() || type->isFlags() || isWrapperType(type))
- return QString("SbkObject_TypeCheck(%1, ").arg(cpythonTypeNameExt(type));
- else if (isCppPrimitive(type))
- return QString("%1_Check").arg(pythonPrimitiveTypeName((const PrimitiveTypeEntry*)type));
- QString typeCheck;
- if (type->targetLangApiName() == type->name())
- typeCheck = cpythonIsConvertibleFunction(type);
- else if (type->targetLangApiName() == "PyUnicode")
- typeCheck = "Shiboken::String::check";
- else
- typeCheck = QString("%1_Check").arg(type->targetLangApiName());
- return typeCheck;
-}
-
-QString ShibokenGenerator::guessCPythonCheckFunction(const QString& type, AbstractMetaType** metaType)
-{
- *metaType = 0;
- if (type == "PyTypeObject")
- return "PyType_Check";
-
- if (type == "PyBuffer")
- return "Shiboken::Buffer::checkType";
-
- if (type == "str")
- return "Shiboken::String::check";
-
- *metaType = buildAbstractMetaTypeFromString(type);
- if (*metaType && !(*metaType)->typeEntry()->isCustom())
- return QString();
-
- return QString("%1_Check").arg(type);
-}
-
-QString ShibokenGenerator::guessCPythonIsConvertible(const QString& type)
-{
- if (type == "PyTypeObject")
- return "PyType_Check";
-
- AbstractMetaType* metaType = buildAbstractMetaTypeFromString(type);
- if (metaType && !metaType->typeEntry()->isCustom())
- return cpythonIsConvertibleFunction(metaType);
-
- return QString("%1_Check").arg(type);
-}
-
-QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntry* type, bool genericNumberType, bool checkExact)
-{
- if (isWrapperType(type)) {
- QString isConv = (type->isValue() && !isValueTypeWithCopyConstructorOnly(type))
- ? "isPythonToCppValueConvertible"
- : "isPythonToCppPointerConvertible";
- return QString("Shiboken::Conversions::%1((SbkObjectType*)%2, ")
- .arg(isConv).arg(cpythonTypeNameExt(type));
- }
- return QString("Shiboken::Conversions::isPythonToCppConvertible(%1, ")
- .arg(converterObject(type));
-}
-QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType* metaType, bool genericNumberType)
-{
- QString customCheck;
- if (metaType->typeEntry()->isCustom()) {
- AbstractMetaType* type;
- customCheck = guessCPythonCheckFunction(metaType->typeEntry()->name(), &type);
- if (type)
- metaType = type;
- if (!customCheck.isEmpty())
- return customCheck;
- }
-
- if (isWrapperType(metaType)) {
- QString isConv;
- if (isPointer(metaType) || isValueTypeWithCopyConstructorOnly(metaType))
- isConv = "isPythonToCppPointerConvertible";
- else if (metaType->isReference())
- isConv = "isPythonToCppReferenceConvertible";
- else
- isConv = "isPythonToCppValueConvertible";
- return QString("Shiboken::Conversions::%1((SbkObjectType*)%2, ")
- .arg(isConv).arg(cpythonTypeNameExt(metaType));
- }
- return QString("Shiboken::Conversions::isPythonToCppConvertible(%1, ")
- .arg(converterObject(metaType));
-}
-
-QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaClass* metaClass)
-{
- return QString("Shiboken::Conversions::pythonToCppPointer((SbkObjectType*)%1, ")
- .arg(cpythonTypeNameExt(metaClass->typeEntry()));
-}
-QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaType* type, const AbstractMetaClass* context)
-{
- if (isWrapperType(type)) {
- return QString("Shiboken::Conversions::pythonToCpp%1((SbkObjectType*)%2, ")
- .arg(isPointer(type) ? "Pointer" : "Copy")
- .arg(cpythonTypeNameExt(type));
- }
- return QString("Shiboken::Conversions::pythonToCppCopy(%1, ")
- .arg(converterObject(type));
-}
-
-QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaType* type, const AbstractMetaClass* context)
-{
- if (isWrapperType(type)) {
- QString conversion;
- if (type->isReference() && !(type->isValue() && type->isConstant()) && !isPointer(type))
- conversion = "reference";
- else if (type->isValue())
- conversion = "copy";
- else
- conversion = "pointer";
- return QString("Shiboken::Conversions::%1ToPython((SbkObjectType*)%2, %3")
- .arg(conversion).arg(cpythonTypeNameExt(type)).arg(conversion == "pointer" ? "" : "&");
- }
- return QString("Shiboken::Conversions::copyToPython(%1, %2")
- .arg(converterObject(type))
- .arg((isCString(type) || isVoidPointer(type)) ? "" : "&");
-}
-
-QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaClass* metaClass)
-{
- return cpythonToPythonConversionFunction(metaClass->typeEntry());
-}
-
-QString ShibokenGenerator::cpythonToPythonConversionFunction(const TypeEntry* type)
-{
- if (isWrapperType(type)) {
- QString conversion;
- if (type->isValue())
- conversion = "copy";
- else
- conversion = "pointer";
- return QString("Shiboken::Conversions::%1ToPython((SbkObjectType*)%2, %3")
- .arg(conversion).arg(cpythonTypeNameExt(type)).arg(conversion == "pointer" ? "" : "&");
- }
-
- return QString("Shiboken::Conversions::copyToPython(%1, &").arg(converterObject(type));
-}
-
-QString ShibokenGenerator::argumentString(const AbstractMetaFunction *func,
- const AbstractMetaArgument *argument,
- Options options) const
-{
- QString modified_type;
- if (!(options & OriginalTypeDescription))
- modified_type = func->typeReplaced(argument->argumentIndex() + 1);
- QString arg;
-
- if (modified_type.isEmpty())
- arg = translateType(argument->type(), func->implementingClass(), options);
- else
- arg = modified_type.replace('$', '.');
-
- if (!(options & Generator::SkipName)) {
- arg += " ";
- arg += argument->name();
- }
-
- 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,
- Options options) const
-{
- s << argumentString(func, argument, options);
-}
-
-void ShibokenGenerator::writeFunctionArguments(QTextStream &s,
- const AbstractMetaFunction *func,
- Options options) const
-{
- AbstractMetaArgumentList arguments = func->arguments();
-
- if (options & Generator::WriteSelf) {
- s << func->implementingClass()->name() << '&';
- if (!(options & SkipName))
- s << " " PYTHON_SELF_VAR;
- }
-
- 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, Options options) const
-{
- QString modifiedReturnType = QString(func->typeReplaced(0));
- if (!modifiedReturnType.isNull() && !(options & OriginalTypeDescription))
- return modifiedReturnType;
- else
- return translateType(func->type(), func->implementingClass(), options);
-}
-
-QString ShibokenGenerator::functionSignature(const AbstractMetaFunction *func,
- QString prepend,
- QString append,
- Options options,
- int argCount) const
-{
- QString result;
- QTextStream s(&result);
- // The actual function
- if (!(func->isEmptyFunction() ||
- func->isNormal() ||
- func->isSignal())) {
- options |= Generator::SkipReturnType;
- } else {
- s << functionReturnType(func, options) << ' ';
- }
-
- // name
- QString name(func->originalName());
- if (func->isConstructor())
- name = wrapperName(func->ownerClass());
-
- s << prepend << name << append << '(';
- writeFunctionArguments(s, func, options);
- s << ')';
-
- if (func->isConstant() && !(options & Generator::ExcludeMethodConst))
- s << " const";
-
- return result;
-}
-
-void ShibokenGenerator::writeArgumentNames(QTextStream &s,
- const AbstractMetaFunction *func,
- Options 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;
-
- s << ((argCount > 0) ? ", " : "") << arguments.at(j)->name();
-
- if (((options & Generator::VirtualCall) == 0)
- && (!func->conversionRule(TypeSystem::NativeCode, arguments.at(j)->argumentIndex() + 1).isEmpty()
- || !func->conversionRule(TypeSystem::TargetLangCode, arguments.at(j)->argumentIndex() + 1).isEmpty())
- && !func->isConstructor()) {
- s << CONV_RULE_OUT_VAR_SUFFIX;
- }
-
- argCount++;
- }
-}
-
-void ShibokenGenerator::writeFunctionCall(QTextStream& s,
- const AbstractMetaFunction* func,
- Options options) const
-{
- if (!(options & Generator::SkipName))
- s << (func->isConstructor() ? func->ownerClass()->qualifiedCppName() : func->originalName());
- s << '(';
- writeArgumentNames(s, func, options);
- s << ')';
-}
-
-void ShibokenGenerator::writeUnusedVariableCast(QTextStream& s, const QString& variableName)
-{
- s << INDENT << "SBK_UNUSED(" << variableName<< ')' << endl;
-}
-
-AbstractMetaFunctionList ShibokenGenerator::filterFunctions(const AbstractMetaClass* metaClass)
-{
- AbstractMetaFunctionList result;
- foreach (AbstractMetaFunction *func, metaClass->functions()) {
- //skip signals
- if (func->isSignal() || func->isDestructor()
- || (func->isModifiedRemoved() && !func->isAbstract()
- && (!avoidProtectedHack() || !func->isProtected())))
- continue;
- result << func;
- }
- return result;
-}
-
-ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverters() const
-{
- ExtendedConverterData extConvs;
- foreach (const AbstractMetaClass* metaClass, classes()) {
- // Use only the classes for the current module.
- if (!shouldGenerate(metaClass))
- continue;
- foreach (AbstractMetaFunction* convOp, metaClass->operatorOverloads(AbstractMetaClass::ConversionOp)) {
- // Get only the conversion operators that return a type from another module,
- // that are value-types and were not removed in the type system.
- const TypeEntry* convType = convOp->type()->typeEntry();
- if ((convType->codeGeneration() & TypeEntry::GenerateTargetLang)
- || !convType->isValue()
- || convOp->isModifiedRemoved())
- continue;
- extConvs[convType].append(convOp->ownerClass());
- }
- }
- return extConvs;
-}
-
-QList<const CustomConversion*> ShibokenGenerator::getPrimitiveCustomConversions()
-{
- QList<const CustomConversion*> conversions;
- foreach (const PrimitiveTypeEntry* type, primitiveTypes()) {
- if (!shouldGenerateTypeEntry(type) || !isUserPrimitive(type) || !type->customConversion())
- continue;
-
- conversions << type->customConversion();
- }
- return conversions;
-}
-
-static QString getArgumentsFromMethodCall(const QString& str)
-{
- // It would be way nicer to be able to use a Perl like
- // regular expression that accepts temporary variables
- // to count the parenthesis.
- // For more information check this:
- // http://perl.plover.com/yak/regex/samples/slide083.html
- static QString funcCall("%CPPSELF.%FUNCTION_NAME");
- int pos = str.indexOf(funcCall);
- if (pos == -1)
- return QString();
- pos = pos + funcCall.count();
- while (str.at(pos) == ' ' || str.at(pos) == '\t')
- ++pos;
- if (str.at(pos) == '(')
- ++pos;
- int begin = pos;
- int counter = 1;
- while (counter != 0) {
- if (str.at(pos) == '(')
- ++counter;
- else if (str.at(pos) == ')')
- --counter;
- ++pos;
- }
- return str.mid(begin, pos-begin-1);
-}
-
-QString ShibokenGenerator::getCodeSnippets(const CodeSnipList& codeSnips,
- CodeSnip::Position position,
- TypeSystem::Language language)
-{
- QString code;
- QTextStream c(&code);
- foreach (CodeSnip snip, codeSnips) {
- if ((position != CodeSnip::Any && snip.position != position) || !(snip.language & language))
- continue;
- QString snipCode;
- QTextStream sc(&snipCode);
- formatCode(sc, snip.code(), INDENT);
- c << snipCode;
- }
- return code;
-}
-void ShibokenGenerator::processCodeSnip(QString& code, const AbstractMetaClass* context)
-{
- if (context) {
- // Replace template variable by the Python Type object
- // for the class context in which the variable is used.
- code.replace("%PYTHONTYPEOBJECT", cpythonTypeName(context) + ".super.ht_type");
- code.replace("%TYPE", wrapperName(context));
- code.replace("%CPPTYPE", context->name());
- }
-
- // replace "toPython" converters
- replaceConvertToPythonTypeSystemVariable(code);
-
- // replace "toCpp" converters
- replaceConvertToCppTypeSystemVariable(code);
-
- // replace "isConvertible" check
- replaceIsConvertibleToCppTypeSystemVariable(code);
-
- // replace "checkType" check
- replaceTypeCheckTypeSystemVariable(code);
-}
-
-ShibokenGenerator::ArgumentVarReplacementList ShibokenGenerator::getArgumentReplacement(const AbstractMetaFunction* func,
- bool usePyArgs, TypeSystem::Language language,
- const AbstractMetaArgument* lastArg)
-{
- ArgumentVarReplacementList argReplacements;
- TypeSystem::Language convLang = (language == TypeSystem::TargetLangCode)
- ? TypeSystem::NativeCode : TypeSystem::TargetLangCode;
- int removed = 0;
- for (int i = 0; i < func->arguments().size(); ++i) {
- const AbstractMetaArgument* arg = func->arguments().at(i);
- QString argValue;
- if (language == TypeSystem::TargetLangCode) {
- bool hasConversionRule = !func->conversionRule(convLang, i+1).isEmpty();
- bool argRemoved = func->argumentRemoved(i+1);
- removed = removed + (int) argRemoved;
- if (argRemoved && hasConversionRule)
- argValue = QString("%1"CONV_RULE_OUT_VAR_SUFFIX).arg(arg->name());
- else if (argRemoved || (lastArg && arg->argumentIndex() > lastArg->argumentIndex()))
- argValue = QString(CPP_ARG_REMOVED"%1").arg(i);
- if (!argRemoved && argValue.isEmpty()) {
- int argPos = i - removed;
- const AbstractMetaType* type = arg->type();
- QString typeReplaced = func->typeReplaced(arg->argumentIndex() + 1);
- if (!typeReplaced.isEmpty()) {
- AbstractMetaType* builtType = buildAbstractMetaTypeFromString(typeReplaced);
- if (builtType)
- type = builtType;
- }
- if (type->typeEntry()->isCustom()) {
- argValue = usePyArgs ? QString(PYTHON_ARGS"[%1]").arg(argPos) : PYTHON_ARG;
- } else {
- argValue = hasConversionRule
- ? QString("%1"CONV_RULE_OUT_VAR_SUFFIX).arg(arg->name())
- : QString(CPP_ARG"%1").arg(argPos);
- if (isWrapperType(type)) {
- if (type->isReference() && !isPointer(type))
- argValue.prepend('*');
- }
- }
- }
- } else {
- argValue = arg->name();
- }
- if (!argValue.isEmpty())
- argReplacements << ArgumentVarReplacementPair(arg, argValue);
-
- }
- return argReplacements;
-}
-
-void ShibokenGenerator::writeCodeSnips(QTextStream& s,
- const CodeSnipList& codeSnips,
- CodeSnip::Position position,
- TypeSystem::Language language,
- const AbstractMetaClass* context)
-{
- QString code = getCodeSnippets(codeSnips, position, language);
- if (code.isEmpty())
- return;
- processCodeSnip(code, context);
- s << INDENT << "// Begin code injection" << endl;
- s << code;
- s << INDENT << "// End of code injection" << endl;
-}
-
-void ShibokenGenerator::writeCodeSnips(QTextStream& s,
- const CodeSnipList& codeSnips,
- CodeSnip::Position position,
- TypeSystem::Language language,
- const AbstractMetaFunction* func,
- const AbstractMetaArgument* lastArg)
-{
- QString code = getCodeSnippets(codeSnips, position, language);
- if (code.isEmpty())
- return;
-
- // Calculate the real number of arguments.
- int argsRemoved = 0;
- for (int i = 0; i < func->arguments().size(); i++) {
- if (func->argumentRemoved(i+1))
- argsRemoved++;
- }
-
- OverloadData od(getFunctionGroups(func->implementingClass())[func->name()], this);
- bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(od);
-
- // Replace %PYARG_# variables.
- code.replace("%PYARG_0", PYTHON_RETURN_VAR);
-
- static QRegExp pyArgsRegex("%PYARG_(\\d+)");
- if (language == TypeSystem::TargetLangCode) {
- if (usePyArgs) {
- code.replace(pyArgsRegex, PYTHON_ARGS"[\\1-1]");
- } else {
- static QRegExp pyArgsRegexCheck("%PYARG_([2-9]+)");
- if (pyArgsRegexCheck.indexIn(code) != -1) {
- ReportHandler::warning("Wrong index for %PYARG variable ("+pyArgsRegexCheck.cap(1)+") on "+func->signature());
- return;
- }
- code.replace("%PYARG_1", PYTHON_ARG);
- }
- } else {
- // Replaces the simplest case of attribution to a
- // Python argument on the binding virtual method.
- static QRegExp pyArgsAttributionRegex("%PYARG_(\\d+)\\s*=[^=]\\s*([^;]+)");
- code.replace(pyArgsAttributionRegex, "PyTuple_SET_ITEM(" PYTHON_ARGS ", \\1-1, \\2)");
- code.replace(pyArgsRegex, "PyTuple_GET_ITEM(" PYTHON_ARGS ", \\1-1)");
- }
-
- // Replace %ARG#_TYPE variables.
- foreach (const AbstractMetaArgument* arg, func->arguments()) {
- QString argTypeVar = QString("%ARG%1_TYPE").arg(arg->argumentIndex() + 1);
- QString argTypeVal = arg->type()->cppSignature();
- code.replace(argTypeVar, argTypeVal);
- }
-
- int pos = 0;
- static QRegExp cppArgTypeRegexCheck("%ARG(\\d+)_TYPE");
- while ((pos = cppArgTypeRegexCheck.indexIn(code, pos)) != -1) {
- ReportHandler::warning("Wrong index for %ARG#_TYPE variable ("+cppArgTypeRegexCheck.cap(1)+") on "+func->signature());
- pos += cppArgTypeRegexCheck.matchedLength();
- }
-
- // Replace template variable for return variable name.
- if (func->isConstructor()) {
- code.replace("%0.", QString("%1->").arg("cptr"));
- code.replace("%0", "cptr");
- } else if (func->type()) {
- QString returnValueOp = isPointerToWrapperType(func->type()) ? "%1->" : "%1.";
- if (ShibokenGenerator::isWrapperType(func->type()))
- code.replace("%0.", returnValueOp.arg(CPP_RETURN_VAR));
- code.replace("%0", CPP_RETURN_VAR);
- }
-
- // Replace template variable for self Python object.
- QString pySelf = (language == TypeSystem::NativeCode) ? "pySelf" : PYTHON_SELF_VAR;
- code.replace("%PYSELF", pySelf);
-
- // Replace template variable for a pointer to C++ of this object.
- if (func->implementingClass()) {
- QString replacement = func->isStatic() ? "%1::" : "%1->";
- QString cppSelf;
- if (func->isStatic())
- cppSelf = func->ownerClass()->qualifiedCppName();
- else if (language == TypeSystem::NativeCode)
- cppSelf = "this";
- else
- cppSelf = CPP_SELF_VAR;
-
- // On comparison operator CPP_SELF_VAR is always a reference.
- if (func->isComparisonOperator())
- replacement = "%1.";
-
- if (func->isVirtual() && !func->isAbstract() && (!avoidProtectedHack() || !func->isProtected())) {
- QString methodCallArgs = getArgumentsFromMethodCall(code);
- if (!methodCallArgs.isNull()) {
- if (func->name() == "metaObject") {
- QString wrapperClassName = wrapperName(func->ownerClass());
- QString cppSelfVar = avoidProtectedHack() ? QString("%CPPSELF") : QString("reinterpret_cast<%1*>(%CPPSELF)").arg(wrapperClassName);
- code.replace(QString("%CPPSELF.%FUNCTION_NAME(%1)").arg(methodCallArgs),
- QString("(Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject*>(%1))"
- " ? %2->::%3::%FUNCTION_NAME(%4)"
- " : %CPPSELF.%FUNCTION_NAME(%4))").arg(pySelf).arg(cppSelfVar).arg(wrapperClassName).arg(methodCallArgs));
- } else {
- code.replace(QString("%CPPSELF.%FUNCTION_NAME(%1)").arg(methodCallArgs),
- QString("(Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject*>(%1))"
- " ? %CPPSELF->::%TYPE::%FUNCTION_NAME(%2)"
- " : %CPPSELF.%FUNCTION_NAME(%2))").arg(pySelf).arg(methodCallArgs));
- }
- }
- }
-
- code.replace("%CPPSELF.", replacement.arg(cppSelf));
- code.replace("%CPPSELF", cppSelf);
-
- if (code.indexOf("%BEGIN_ALLOW_THREADS") > -1) {
- if (code.count("%BEGIN_ALLOW_THREADS") == code.count("%END_ALLOW_THREADS")) {
- code.replace("%BEGIN_ALLOW_THREADS", BEGIN_ALLOW_THREADS);
- code.replace("%END_ALLOW_THREADS", END_ALLOW_THREADS);
- } else {
- ReportHandler::warning("%BEGIN_ALLOW_THREADS and %END_ALLOW_THREADS mismatch");
- }
- }
-
- // replace template variable for the Python Type object for the
- // class implementing the method in which the code snip is written
- if (func->isStatic()) {
- code.replace("%PYTHONTYPEOBJECT", cpythonTypeName(func->implementingClass()) + ".super.ht_type");
- } else {
- code.replace("%PYTHONTYPEOBJECT.", QString("%1->ob_type->").arg(pySelf));
- code.replace("%PYTHONTYPEOBJECT", QString("%1->ob_type").arg(pySelf));
- }
- }
-
- // Replaces template %ARGUMENT_NAMES and %# variables by argument variables and values.
- // Replaces template variables %# for individual arguments.
- ArgumentVarReplacementList argReplacements = getArgumentReplacement(func, usePyArgs, language, lastArg);
-
- QStringList args;
- foreach (ArgumentVarReplacementPair pair, argReplacements) {
- if (pair.second.startsWith(CPP_ARG_REMOVED))
- continue;
- args << pair.second;
- }
- code.replace("%ARGUMENT_NAMES", args.join(", "));
-
- foreach (ArgumentVarReplacementPair pair, argReplacements) {
- const AbstractMetaArgument* arg = pair.first;
- int idx = arg->argumentIndex() + 1;
- AbstractMetaType* type = arg->type();
- QString typeReplaced = func->typeReplaced(arg->argumentIndex() + 1);
- if (!typeReplaced.isEmpty()) {
- AbstractMetaType* builtType = buildAbstractMetaTypeFromString(typeReplaced);
- if (builtType)
- type = builtType;
- }
- if (isWrapperType(type)) {
- QString replacement = pair.second;
- if (type->isReference() && !isPointer(type))
- replacement.remove(0, 1);
- if (type->isReference() || isPointer(type))
- code.replace(QString("%%1.").arg(idx), QString("%1->").arg(replacement));
- }
- code.replace(QString("%%1").arg(idx), pair.second);
- }
-
- if (language == TypeSystem::NativeCode) {
- // Replaces template %PYTHON_ARGUMENTS variable with a pointer to the Python tuple
- // containing the converted virtual method arguments received from C++ to be passed
- // to the Python override.
- code.replace("%PYTHON_ARGUMENTS", PYTHON_ARGS);
-
- // replace variable %PYTHON_METHOD_OVERRIDE for a pointer to the Python method
- // override for the C++ virtual method in which this piece of code was inserted
- code.replace("%PYTHON_METHOD_OVERRIDE", PYTHON_OVERRIDE_VAR);
- }
-
- if (avoidProtectedHack()) {
- // If the function being processed was added by the user via type system,
- // Shiboken needs to find out if there are other overloads for the same method
- // name and if any of them is of the protected visibility. This is used to replace
- // calls to %FUNCTION_NAME on user written custom code for calls to the protected
- // dispatcher.
- bool hasProtectedOverload = false;
- if (func->isUserAdded()) {
- foreach (const AbstractMetaFunction* f, getFunctionOverloads(func->ownerClass(), func->name()))
- hasProtectedOverload |= f->isProtected();
- }
-
- if (func->isProtected() || hasProtectedOverload) {
- code.replace("%TYPE::%FUNCTION_NAME",
- QString("%1::%2_protected")
- .arg(wrapperName(func->ownerClass()))
- .arg(func->originalName()));
- code.replace("%FUNCTION_NAME", QString("%1_protected").arg(func->originalName()));
- }
- }
-
- if (func->isConstructor() && shouldGenerateCppWrapper(func->ownerClass()))
- code.replace("%TYPE", wrapperName(func->ownerClass()));
-
- if (func->ownerClass())
- code.replace("%CPPTYPE", func->ownerClass()->name());
-
- replaceTemplateVariables(code, func);
-
- processCodeSnip(code);
- s << INDENT << "// Begin code injection" << endl;
- s << code;
- s << INDENT << "// End of code injection" << endl;
-}
-
-// Returns true if the string is an expression,
-// and false if it is a variable.
-static bool isVariable(const QString& code)
-{
- static QRegExp expr("\\s*\\*?\\s*[A-Za-z_][A-Za-z_0-9.]*\\s*(?:\\[[^\\[]+\\])*");
- return expr.exactMatch(code.trimmed());
-}
-
-// A miniature normalizer that puts a type string into a format
-// suitable for comparison with AbstractMetaType::cppSignature()
-// result.
-static QString miniNormalizer(const QString& varType)
-{
- QString normalized = varType.trimmed();
- if (normalized.isEmpty())
- return normalized;
- if (normalized.startsWith("::"))
- normalized.remove(0, 2);
- QString suffix;
- while (normalized.endsWith('*') || normalized.endsWith('&')) {
- suffix.prepend(normalized.at(normalized.count() - 1));
- normalized.chop(1);
- normalized = normalized.trimmed();
- }
- return QString("%1 %2").arg(normalized).arg(suffix).trimmed();
-}
-// The position must indicate the first character after the opening '('.
-// ATTENTION: do not modify this function to trim any resulting string!
-// This must be done elsewhere.
-static QString getConverterTypeSystemVariableArgument(const QString& code, int pos)
-{
- QString arg;
- int parenthesisDepth = 0;
- int count = 0;
- while (pos + count < code.count()) {
- char c = code.at(pos+count).toAscii();
- if (c == '(') {
- ++parenthesisDepth;
- } else if (c == ')') {
- if (parenthesisDepth == 0) {
- arg = code.mid(pos, count).trimmed();
- break;
- }
- --parenthesisDepth;
- }
- ++count;
- }
- if (parenthesisDepth != 0)
- qFatal("Unbalanced parenthesis on type system converter variable call.");
- return arg;
-}
-typedef QPair<QString, QString> StringPair;
-void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable, QString& code)
-{
- QRegExp& regex = m_typeSystemConvRegEx[converterVariable];
- int pos = 0;
- QList<StringPair> replacements;
- while ((pos = regex.indexIn(code, pos)) != -1) {
- pos += regex.matchedLength();
- QStringList list = regex.capturedTexts();
- QString conversionString = list.first();
- QString conversionTypeName = list.last();
- const AbstractMetaType* conversionType = buildAbstractMetaTypeFromString(conversionTypeName);
- if (!conversionType) {
- qFatal(qPrintable(QString("Could not find type '%1' for use in '%2' conversion. "
- "Make sure to use the full C++ name, e.g. 'Namespace::Class'.")
- .arg(conversionTypeName).arg(m_typeSystemConvName[converterVariable])), NULL);
-
- }
- QString conversion;
- QTextStream c(&conversion);
- switch (converterVariable) {
- case TypeSystemToCppFunction: {
- int end = pos - list.first().count();
- int start = end;
- while (start > 0 && code.at(start) != '\n')
- --start;
- while (code.at(start).isSpace())
- ++start;
- QString varType = code.mid(start, end - start);
- conversionString = varType + list.first();
- varType = miniNormalizer(varType);
- QString varName = list.at(1).trimmed();
- if (!varType.isEmpty()) {
- if (varType != conversionType->cppSignature()) {
- qFatal(qPrintable(QString("Types of receiver variable ('%1') and %CONVERTTOCPP type system variable ('%2') differ.")
- .arg(varType).arg(conversionType->cppSignature())), NULL);
- }
- c << getFullTypeName(conversionType) << ' ' << varName;
- writeMinimalConstructorExpression(c, conversionType);
- c << ';' << endl;
- Indentation indent(INDENT);
- c << INDENT;
- }
- c << cpythonToCppConversionFunction(conversionType);
- QString prefix;
- if (varName.startsWith('*')) {
- varName.remove(0, 1);
- varName = varName.trimmed();
- } else {
- prefix = '&';
- }
- QString arg = getConverterTypeSystemVariableArgument(code, pos);
- conversionString += arg;
- c << arg << ", " << prefix << '(' << varName << ')';
- break;
- }
- case TypeSystemCheckFunction:
- conversion = cpythonCheckFunction(conversionType);
- if (conversionType->typeEntry()->isPrimitive() && (conversionType->typeEntry()->name() == "PyObject" || !conversion.endsWith(' '))) {
- c << '(';
- break;
- }
- case TypeSystemIsConvertibleFunction:
- if (conversion.isEmpty())
- conversion = cpythonIsConvertibleFunction(conversionType);
- case TypeSystemToPythonFunction:
- if (conversion.isEmpty())
- conversion = cpythonToPythonConversionFunction(conversionType);
- default: {
- QString arg = getConverterTypeSystemVariableArgument(code, pos);
- conversionString += arg;
- if (converterVariable == TypeSystemToPythonFunction && !isVariable(arg)) {
- qFatal(qPrintable(QString("Only variables are acceptable as argument to %%CONVERTTOPYTHON type system variable on code snippet: '%1'")
- .arg(code)), NULL);
- }
- if (conversion.contains("%in")) {
- conversion.prepend('(');
- conversion.replace("%in", arg);
- } else {
- c << arg;
- }
- }
- }
- replacements.append(qMakePair(conversionString, conversion));
- }
- foreach (StringPair rep, replacements)
- code.replace(rep.first, rep.second);
-}
-
-bool ShibokenGenerator::injectedCodeUsesCppSelf(const AbstractMetaFunction* func)
-{
- CodeSnipList snips = func->injectedCodeSnips(CodeSnip::Any, TypeSystem::TargetLangCode);
- foreach (CodeSnip snip, snips) {
- if (snip.code().contains("%CPPSELF"))
- return true;
- }
- return false;
-}
-
-bool ShibokenGenerator::injectedCodeUsesPySelf(const AbstractMetaFunction* func)
-{
- CodeSnipList snips = func->injectedCodeSnips(CodeSnip::Any, TypeSystem::NativeCode);
- foreach (CodeSnip snip, snips) {
- if (snip.code().contains("%PYSELF"))
- return true;
- }
- return false;
-}
-
-bool ShibokenGenerator::injectedCodeCallsCppFunction(const AbstractMetaFunction* func)
-{
- QString funcCall = QString("%1(").arg(func->originalName());
- QString wrappedCtorCall;
- if (func->isConstructor()) {
- funcCall.prepend("new ");
- wrappedCtorCall = QString("new %1(").arg(wrapperName(func->ownerClass()));
- }
- CodeSnipList snips = func->injectedCodeSnips(CodeSnip::Any, TypeSystem::TargetLangCode);
- foreach (CodeSnip snip, snips) {
- if (snip.code().contains("%FUNCTION_NAME(") || snip.code().contains(funcCall)
- || (func->isConstructor()
- && ((func->ownerClass()->isPolymorphic() && snip.code().contains(wrappedCtorCall))
- || snip.code().contains("new %TYPE(")))
- )
- return true;
- }
- return false;
-}
-
-bool ShibokenGenerator::injectedCodeCallsPythonOverride(const AbstractMetaFunction* func)
-{
- static QRegExp overrideCallRegexCheck("PyObject_Call\\s*\\(\\s*%PYTHON_METHOD_OVERRIDE\\s*,");
- CodeSnipList snips = func->injectedCodeSnips(CodeSnip::Any, TypeSystem::NativeCode);
- foreach (CodeSnip snip, snips) {
- if (overrideCallRegexCheck.indexIn(snip.code()) != -1)
- return true;
- }
- return false;
-}
-
-bool ShibokenGenerator::injectedCodeHasReturnValueAttribution(const AbstractMetaFunction* func, TypeSystem::Language language)
-{
- static QRegExp retValAttributionRegexCheck_native("%0\\s*=[^=]\\s*.+");
- static QRegExp retValAttributionRegexCheck_target("%PYARG_0\\s*=[^=]\\s*.+");
- CodeSnipList snips = func->injectedCodeSnips(CodeSnip::Any, language);
- foreach (CodeSnip snip, snips) {
- if (language == TypeSystem::TargetLangCode) {
- if (retValAttributionRegexCheck_target.indexIn(snip.code()) != -1)
- return true;
- } else {
- if (retValAttributionRegexCheck_native.indexIn(snip.code()) != -1)
- return true;
- }
- }
- return false;
-}
-
-bool ShibokenGenerator::injectedCodeUsesArgument(const AbstractMetaFunction* func, int argumentIndex)
-{
- CodeSnipList snips = func->injectedCodeSnips(CodeSnip::Any);
- foreach (CodeSnip snip, snips) {
- QString code = snip.code();
- if (code.contains("%ARGUMENT_NAMES"))
- return true;
- if (code.contains(QString("%%1").arg(argumentIndex + 1)))
- return true;
- }
- return false;
-}
-
-bool ShibokenGenerator::hasMultipleInheritanceInAncestry(const AbstractMetaClass* metaClass)
-{
- if (!metaClass || metaClass->baseClassNames().isEmpty())
- return false;
- if (metaClass->baseClassNames().size() > 1)
- return true;
- return hasMultipleInheritanceInAncestry(metaClass->baseClass());
-}
-
-bool ShibokenGenerator::classNeedsGetattroFunction(const AbstractMetaClass* metaClass)
-{
- if (!metaClass)
- return false;
- foreach (AbstractMetaFunctionList allOverloads, getFunctionGroups(metaClass).values()) {
- AbstractMetaFunctionList overloads;
- foreach (AbstractMetaFunction* func, allOverloads) {
- if (func->isAssignmentOperator() || func->isCastOperator() || func->isModifiedRemoved()
- || func->isPrivate() || func->ownerClass() != func->implementingClass()
- || func->isConstructor() || func->isOperatorOverload())
- continue;
- overloads.append(func);
- }
- if (overloads.isEmpty())
- continue;
- if (OverloadData::hasStaticAndInstanceFunctions(overloads))
- return true;
- }
- return false;
-}
-
-AbstractMetaFunctionList ShibokenGenerator::getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClass* metaClass)
-{
- AbstractMetaFunctionList methods;
- if (metaClass) {
- foreach (AbstractMetaFunctionList allOverloads, getFunctionGroups(metaClass).values()) {
- AbstractMetaFunctionList overloads;
- foreach (AbstractMetaFunction* func, allOverloads) {
- if (func->isAssignmentOperator() || func->isCastOperator() || func->isModifiedRemoved()
- || func->isPrivate() || func->ownerClass() != func->implementingClass()
- || func->isConstructor() || func->isOperatorOverload())
- continue;
- overloads.append(func);
- }
- if (overloads.isEmpty())
- continue;
- if (OverloadData::hasStaticAndInstanceFunctions(overloads))
- methods.append(overloads.first());
- }
- }
- return methods;
-}
-
-AbstractMetaClassList ShibokenGenerator::getBaseClasses(const AbstractMetaClass* metaClass) const
-{
- AbstractMetaClassList baseClasses;
- if (metaClass) {
- foreach (QString parent, metaClass->baseClassNames()) {
- AbstractMetaClass* clazz = classes().findClass(parent);
- if (clazz)
- baseClasses << clazz;
- }
- }
- return baseClasses;
-}
-
-const AbstractMetaClass* ShibokenGenerator::getMultipleInheritingClass(const AbstractMetaClass* metaClass)
-{
- if (!metaClass || metaClass->baseClassNames().isEmpty())
- return 0;
- if (metaClass->baseClassNames().size() > 1)
- return metaClass;
- return getMultipleInheritingClass(metaClass->baseClass());
-}
-
-AbstractMetaClassList ShibokenGenerator::getAllAncestors(const AbstractMetaClass* metaClass) const
-{
- AbstractMetaClassList result;
- if (metaClass) {
- AbstractMetaClassList baseClasses = getBaseClasses(metaClass);
- foreach (AbstractMetaClass* base, baseClasses) {
- result.append(base);
- result.append(getAllAncestors(base));
- }
- }
- return result;
-}
-
-QString ShibokenGenerator::getModuleHeaderFileName(const QString& moduleName) const
-{
- QString result = moduleName.isEmpty() ? packageName() : moduleName;
- result.replace(".", "_");
- return QString("%1_python.h").arg(result.toLower());
-}
-
-QString ShibokenGenerator::extendedIsConvertibleFunctionName(const TypeEntry* targetType) const
-{
- return QString("ExtendedIsConvertible_%1_%2").arg(targetType->targetLangPackage().replace('.', '_')).arg(targetType->name());
-}
-
-QString ShibokenGenerator::extendedToCppFunctionName(const TypeEntry* targetType) const
-{
- return QString("ExtendedToCpp_%1_%2").arg(targetType->targetLangPackage().replace('.', '_')).arg(targetType->name());
-}
-
-bool ShibokenGenerator::isCopyable(const AbstractMetaClass *metaClass)
-
-{
- if (metaClass->isNamespace() || isObjectType(metaClass))
- return false;
- else if (metaClass->typeEntry()->copyable() == ComplexTypeEntry::Unknown)
- return metaClass->hasCloneOperator();
- else
- return (metaClass->typeEntry()->copyable() == ComplexTypeEntry::CopyableSet);
-
- return false;
-}
-
-AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromString(QString typeSignature)
-{
- typeSignature = typeSignature.trimmed();
- if (typeSignature.startsWith("::"))
- typeSignature = typeSignature.mid(2);
-
- if (m_metaTypeFromStringCache.contains(typeSignature))
- return m_metaTypeFromStringCache.value(typeSignature);
-
- QString typeString = typeSignature;
- bool isConst = typeString.startsWith("const ");
- if (isConst)
- typeString.remove(0, sizeof("const ") / sizeof(char) - 1);
-
- int indirections = typeString.count("*");
- while (typeString.endsWith("*")) {
- typeString.chop(1);
- typeString = typeString.trimmed();
- }
-
- bool isReference = typeString.endsWith("&");
- if (isReference) {
- typeString.chop(1);
- typeString = typeString.trimmed();
- }
-
- if (typeString.startsWith("::"))
- typeString.remove(0, 2);
-
- QString adjustedTypeName = typeString;
- QStringList instantiatedTypes;
- int lpos = typeString.indexOf('<');
- if (lpos > -1) {
- int rpos = typeString.lastIndexOf('>');
- if ((lpos != -1) && (rpos != -1)) {
- QString type = typeString.mid(lpos + 1, rpos - lpos - 1);
- int depth = 0;
- int start = 0;
- for (int i = 0; i < type.count(); ++i) {
- if (type.at(i) == '<') {
- ++depth;
- } else if (type.at(i) == '>') {
- --depth;
- } else if (type.at(i) == ',' && depth == 0) {
- instantiatedTypes << type.mid(start, i - start).trimmed();
- start = i + 1;
- }
- }
- instantiatedTypes << type.mid(start).trimmed();
- adjustedTypeName = adjustedTypeName.left(lpos);
- }
- }
-
- TypeEntry* typeEntry = TypeDatabase::instance()->findType(adjustedTypeName);
-
- AbstractMetaType* metaType = 0;
- if (typeEntry) {
- metaType = new AbstractMetaType();
- metaType->setTypeEntry(typeEntry);
- metaType->setIndirections(indirections);
- metaType->setReference(isReference);
- metaType->setConstant(isConst);
- metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
- foreach (const QString& instantiation, instantiatedTypes) {
- AbstractMetaType* tmplArgType = buildAbstractMetaTypeFromString(instantiation);
- metaType->addInstantiation(tmplArgType);
- }
- metaType->decideUsagePattern();
- m_metaTypeFromStringCache.insert(typeSignature, metaType);
- }
- return metaType;
-}
-
-AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(const TypeEntry* typeEntry)
-{
- QString typeName = typeEntry->qualifiedCppName();
- if (typeName.startsWith("::"))
- typeName = typeName.mid(2);
- if (m_metaTypeFromStringCache.contains(typeName))
- return m_metaTypeFromStringCache.value(typeName);
- AbstractMetaType* metaType = new AbstractMetaType;
- metaType->setTypeEntry(typeEntry);
- metaType->setIndirections(0);
- metaType->setReference(false);
- metaType->setConstant(false);
- metaType->decideUsagePattern();
- m_metaTypeFromStringCache.insert(typeName, metaType);
- return metaType;
-}
-AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromAbstractMetaClass(const AbstractMetaClass* metaClass)
-{
- return ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(metaClass->typeEntry());
-}
-
-/*
-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();
-}
-*/
-
-static bool isGroupable(const AbstractMetaFunction* func)
-{
- if (func->isSignal() || func->isDestructor() || (func->isModifiedRemoved() && !func->isAbstract()))
- return false;
- // weird operator overloads
- if (func->name() == "operator[]" || func->name() == "operator->") // FIXME: what about cast operators?
- return false;;
- return true;
-}
-
-QMap< QString, AbstractMetaFunctionList > ShibokenGenerator::getFunctionGroups(const AbstractMetaClass* scope)
-{
- AbstractMetaFunctionList lst = scope ? scope->functions() : globalFunctions();
-
- QMap<QString, AbstractMetaFunctionList> results;
- foreach (AbstractMetaFunction* func, lst) {
- if (isGroupable(func))
- results[func->name()].append(func);
- }
- return results;
-}
-
-AbstractMetaFunctionList ShibokenGenerator::getFunctionOverloads(const AbstractMetaClass* scope, const QString& functionName)
-{
- AbstractMetaFunctionList lst = scope ? scope->functions() : globalFunctions();
-
- AbstractMetaFunctionList results;
- foreach (AbstractMetaFunction* func, lst) {
- if (func->name() != functionName)
- continue;
- if (isGroupable(func))
- results << func;
- }
- return results;
-
-}
-
-QPair< int, int > ShibokenGenerator::getMinMaxArguments(const AbstractMetaFunction* metaFunction)
-{
- AbstractMetaFunctionList overloads = getFunctionOverloads(metaFunction->ownerClass(), metaFunction->name());
-
- int minArgs = std::numeric_limits<int>::max();
- int maxArgs = 0;
- foreach (const AbstractMetaFunction* func, overloads) {
- int numArgs = 0;
- foreach (const AbstractMetaArgument* arg, func->arguments()) {
- if (!func->argumentRemoved(arg->argumentIndex() + 1))
- numArgs++;
- }
- maxArgs = std::max(maxArgs, numArgs);
- minArgs = std::min(minArgs, numArgs);
- }
- return qMakePair(minArgs, maxArgs);
-}
-
-QMap<QString, QString> ShibokenGenerator::options() const
-{
- QMap<QString, QString> opts(Generator::options());
- opts.insert(AVOID_PROTECTED_HACK, "Avoid the use of the '#define protected public' hack.");
- opts.insert(PARENT_CTOR_HEURISTIC, "Enable heuristics to detect parent relationship on constructors.");
- opts.insert(RETURN_VALUE_HEURISTIC, "Enable heuristics to detect parent relationship on return values (USE WITH CAUTION!)");
- opts.insert(ENABLE_PYSIDE_EXTENSIONS, "Enable PySide extensions, such as support for signal/slots, use this if you are creating a binding for a Qt-based library.");
- opts.insert(DISABLE_VERBOSE_ERROR_MESSAGES, "Disable verbose error messages. Turn the python code hard to debug but safe few kB on the generated bindings.");
- opts.insert(USE_ISNULL_AS_NB_NONZERO, "If a class have an isNull()const method, it will be used to compute the value of boolean casts");
- return opts;
-}
-
-static void getCode(QStringList& code, const CodeSnipList& codeSnips)
-{
- foreach (const CodeSnip& snip, codeSnips)
- code.append(snip.code());
-}
-
-static void getCode(QStringList& code, const TypeEntry* type)
-{
- getCode(code, type->codeSnips());
-
- CustomConversion* customConversion = type->customConversion();
- if (!customConversion)
- return;
-
- if (!customConversion->nativeToTargetConversion().isEmpty())
- code.append(customConversion->nativeToTargetConversion());
-
- const CustomConversion::TargetToNativeConversions& toCppConversions = customConversion->targetToNativeConversions();
- if (toCppConversions.isEmpty())
- return;
-
- foreach (CustomConversion::TargetToNativeConversion* toNative, toCppConversions)
- code.append(toNative->conversion());
-}
-
-bool ShibokenGenerator::doSetup(const QMap<QString, QString>& args)
-{
- m_useCtorHeuristic = args.contains(PARENT_CTOR_HEURISTIC);
- m_usePySideExtensions = args.contains(ENABLE_PYSIDE_EXTENSIONS);
- m_userReturnValueHeuristic = args.contains(RETURN_VALUE_HEURISTIC);
- m_verboseErrorMessagesDisabled = args.contains(DISABLE_VERBOSE_ERROR_MESSAGES);
- m_useIsNullAsNbNonZero = args.contains(USE_ISNULL_AS_NB_NONZERO);
- m_avoidProtectedHack = args.contains(AVOID_PROTECTED_HACK);
-
- TypeDatabase* td = TypeDatabase::instance();
- QStringList snips;
- foreach (const PrimitiveTypeEntry* type, primitiveTypes())
- getCode(snips, type);
- foreach (const ContainerTypeEntry* type, containerTypes())
- getCode(snips, type);
- foreach (const AbstractMetaClass* metaClass, classes())
- getCode(snips, metaClass->typeEntry());
- getCode(snips, td->findType(packageName()));
- foreach (AbstractMetaFunctionList globalOverloads, getFunctionGroups().values()) {
- foreach (AbstractMetaFunction* func, globalOverloads)
- getCode(snips, func->injectedCodeSnips());
- }
-
- foreach (const QString& code, snips) {
- collectContainerTypesFromConverterMacros(code, true);
- collectContainerTypesFromConverterMacros(code, false);
- }
-
- return true;
-}
-
-void ShibokenGenerator::collectContainerTypesFromConverterMacros(const QString& code, bool toPythonMacro)
-{
- QString convMacro = toPythonMacro ? "%CONVERTTOPYTHON[" : "%CONVERTTOCPP[";
- int offset = toPythonMacro ? sizeof("%CONVERTTOPYTHON") : sizeof("%CONVERTTOCPP");
- int start = 0;
- while ((start = code.indexOf(convMacro, start)) != -1) {
- int end = code.indexOf("]", start);
- start += offset;
- if (code.at(start) != '%') {
- QString typeString = code.mid(start, end - start);
- AbstractMetaType* type = buildAbstractMetaTypeFromString(typeString);
- addInstantiatedContainers(type);
- }
- start = end;
- }
-}
-
-bool ShibokenGenerator::useCtorHeuristic() const
-{
- return m_useCtorHeuristic;
-}
-
-bool ShibokenGenerator::useReturnValueHeuristic() const
-{
- return m_userReturnValueHeuristic;
-}
-
-bool ShibokenGenerator::usePySideExtensions() const
-{
- return m_usePySideExtensions;
-}
-
-bool ShibokenGenerator::useIsNullAsNbNonZero() const
-{
- return m_useIsNullAsNbNonZero;
-}
-
-bool ShibokenGenerator::avoidProtectedHack() const
-{
- return m_avoidProtectedHack;
-}
-
-QString ShibokenGenerator::cppApiVariableName(const QString& moduleName) const
-{
- QString result = moduleName.isEmpty() ? ShibokenGenerator::packageName() : moduleName;
- result.replace(".", "_");
- result.prepend("Sbk");
- result.append("Types");
- return result;
-}
-
-QString ShibokenGenerator::convertersVariableName(const QString& moduleName) const
-{
- QString result = cppApiVariableName(moduleName);
- result.chop(1);
- result.append("Converters");
- return result;
-}
-
-static QString processInstantiationsVariableName(const AbstractMetaType* type)
-{
- QString res = QString("_%1").arg(_fixedCppTypeName(type->typeEntry()->qualifiedCppName()).toUpper());
- foreach (const AbstractMetaType* instantiation, type->instantiations()) {
- res += instantiation->isContainer()
- ? processInstantiationsVariableName(instantiation)
- : QString("_%1").arg(_fixedCppTypeName(instantiation->cppSignature()).toUpper());
- }
- return res;
-}
-QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass* metaClass, bool alternativeTemplateName)
-{
- if (alternativeTemplateName) {
- const AbstractMetaClass* templateBaseClass = metaClass->templateBaseClass();
- if (!templateBaseClass)
- return QString();
- QString base = _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName()).toUpper();
- QString instantiations;
- foreach (const AbstractMetaType* instantiation, metaClass->templateBaseClassInstantiations())
- instantiations += processInstantiationsVariableName(instantiation);
- return QString("SBK_%1%2_IDX").arg(base).arg(instantiations);
- }
- return getTypeIndexVariableName(metaClass->typeEntry());
-}
-QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry* type)
-{
- if (type->isCppPrimitive()) {
- const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type;
- if (trueType->basicAliasedTypeEntry())
- type = trueType->basicAliasedTypeEntry();
- }
- return QString("SBK_%1_IDX").arg(_fixedCppTypeName(type->qualifiedCppName()).toUpper());
-}
-QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaType* type)
-{
- return QString("SBK%1%2_IDX")
- .arg(type->typeEntry()->isContainer() ? "_"+moduleName().toUpper() : "")
- .arg(processInstantiationsVariableName(type));
-}
-
-bool ShibokenGenerator::verboseErrorMessagesDisabled() const
-{
- return m_verboseErrorMessagesDisabled;
-}
-
-bool ShibokenGenerator::pythonFunctionWrapperUsesListOfArguments(const OverloadData& overloadData)
-{
- if (overloadData.referenceFunction()->isCallOperator())
- return true;
- if (overloadData.referenceFunction()->isOperatorOverload())
- return false;
- int maxArgs = overloadData.maxArgs();
- int minArgs = overloadData.minArgs();
- return (minArgs != maxArgs)
- || (maxArgs > 1)
- || overloadData.referenceFunction()->isConstructor()
- || overloadData.hasArgumentWithDefaultValue();
-}
-
-Generator::Options ShibokenGenerator::getConverterOptions(const AbstractMetaType* metaType)
-{
- // exclude const on Objects
- Options flags;
- const TypeEntry* type = metaType->typeEntry();
- bool isCStr = isCString(metaType);
- if (metaType->indirections() && !isCStr) {
- flags = ExcludeConst;
- } else if (metaType->isContainer()
- || (type->isPrimitive() && !isCStr)
- // const refs become just the value, but pure refs must remain pure.
- || (type->isValue() && metaType->isConstant() && metaType->isReference())) {
- flags = ExcludeConst | ExcludeReference;
- }
- return flags;
-}
-
-QString ShibokenGenerator::getDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg)
-{
- if (!arg->defaultValueExpression().isEmpty())
- return arg->defaultValueExpression();
-
- //Check modifications
- foreach(FunctionModification m, func->modifications()) {
- foreach(ArgumentModification am, m.argument_mods) {
- if (am.index == (arg->argumentIndex() + 1))
- return am.replacedDefaultExpression;
- }
- }
- return QString();
-}
-
-void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream& s, const AbstractMetaType* type, const QString& defaultCtor)
-{
- if (defaultCtor.isEmpty() && isCppPrimitive(type))
- return;
- QString ctor = defaultCtor.isEmpty() ? minimalConstructor(type) : defaultCtor;
- if (ctor.isEmpty())
- qFatal(qPrintable(QString(MIN_CTOR_ERROR_MSG).arg(type->cppSignature())), NULL);
- s << " = " << ctor;
-}
-
-void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream& s, const TypeEntry* type, const QString& defaultCtor)
-{
- if (defaultCtor.isEmpty() && isCppPrimitive(type))
- return;
- QString ctor = defaultCtor.isEmpty() ? minimalConstructor(type) : defaultCtor;
- if (ctor.isEmpty())
- qFatal(qPrintable(QString(MIN_CTOR_ERROR_MSG).arg(type->qualifiedCppName())), NULL);
- s << " = " << ctor;
-}
-
-bool ShibokenGenerator::isCppIntegralPrimitive(const TypeEntry* type)
-{
- if (!type->isCppPrimitive())
- return false;
- const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type;
- if (trueType->basicAliasedTypeEntry())
- trueType = trueType->basicAliasedTypeEntry();
- QString typeName = trueType->qualifiedCppName();
- return !typeName.contains("double") && !typeName.contains("float") && !typeName.contains("wchar");
-}
-bool ShibokenGenerator::isCppIntegralPrimitive(const AbstractMetaType* type)
-{
- return isCppIntegralPrimitive(type->typeEntry());
-}
diff --git a/generators/shiboken/shibokengenerator.h b/generators/shiboken/shibokengenerator.h
deleted file mode 100644
index 4a73cbc9d..000000000
--- a/generators/shiboken/shibokengenerator.h
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * This file is part of the Shiboken Python Bindings Generator project.
- *
- * Copyright (C) 2009-2012 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
- *
- */
-
-#ifndef SHIBOKENGENERATOR_H
-#define SHIBOKENGENERATOR_H
-
-#define CONV_RULE_OUT_VAR_SUFFIX "_out"
-#define CPP_ARG "cppArg"
-#define CPP_ARG0 CPP_ARG"0"
-#define CPP_ARG_REMOVED "removed_"CPP_ARG
-#define CPP_RETURN_VAR "cppResult"
-#define CPP_SELF_VAR "cppSelf"
-#define PYTHON_ARG "pyArg"
-#define PYTHON_ARGS PYTHON_ARG"s"
-#define PYTHON_OVERRIDE_VAR "pyOverride"
-#define PYTHON_RETURN_VAR "pyResult"
-#define PYTHON_SELF_VAR "self"
-#define THREAD_STATE_SAVER_VAR "threadStateSaver"
-#define BEGIN_ALLOW_THREADS "PyThreadState* _save = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS"
-#define END_ALLOW_THREADS "PyEval_RestoreThread(_save); // Py_END_ALLOW_THREADS"
-#define MIN_CTOR_ERROR_MSG "Could not find a minimal constructor for type '%1'. "\
- "This will result in a compilation error."
-#define PYTHON_TO_CPP_VAR "pythonToCpp"
-
-#define CHECKTYPE_REGEX "%CHECKTYPE\\[([^\\[]*)\\]\\("
-#define ISCONVERTIBLE_REGEX "%ISCONVERTIBLE\\[([^\\[]*)\\]\\("
-#define CONVERTTOPYTHON_REGEX "%CONVERTTOPYTHON\\[([^\\[]*)\\]\\("
-#define CONVERTTOCPP_REGEX "(\\*?%?[a-zA-Z_][\\w\\.]*(?:\\[[^\\[^<^>]+\\])*)"\
- "(?:\\s+)=(?:\\s+)%CONVERTTOCPP\\[([^\\[]*)\\]\\("
-
-#include <generator.h>
-#include <QtCore/QTextStream>
-
-#include "overloaddata.h"
-
-class DocParser;
-
-/**
- * Abstract generator that contains common methods used in CppGenerator and HeaderGenerator.
- */
-class ShibokenGenerator : public Generator
-{
-public:
- ShibokenGenerator();
- virtual ~ShibokenGenerator();
-
- QString translateTypeForWrapperMethod(const AbstractMetaType* cType,
- const AbstractMetaClass* context, Options opt = NoOption) const;
-
- /**
- * Returns a map with all functions grouped, the function name is used as key.
- * Example ofg return value: { "foo" -> ["foo(int)", "foo(int, long)], "bar" -> "bar(double)"}
- * \param scope Where to search for functions, null means all global functions.
- */
- QMap<QString, AbstractMetaFunctionList> getFunctionGroups(const AbstractMetaClass* scope = 0);
- /**
- * Returns all overloads for a function named \p functionName.
- * \param scope scope used to search for overloads.
- * \param functionName the function name.
- */
- AbstractMetaFunctionList getFunctionOverloads(const AbstractMetaClass* scope, const QString& functionName);
- /**
- * Returns the minimun and maximun number of arguments which this function and all overloads
- * can accept. Arguments removed by typesystem are considered as well.
- */
- QPair<int, int> getMinMaxArguments(const AbstractMetaFunction* metaFunction);
- /**
- * Write a function argument in the C++ in the text stream \p s.
- * This function just call \code s << argumentString(); \endcode
- * \param s text stream used to write the output.
- * \param func the current metafunction.
- * \param argument metaargument information to be parsed.
- * \param options some extra options.
- */
- void writeArgument(QTextStream &s,
- const AbstractMetaFunction* func,
- const AbstractMetaArgument* argument,
- Options options = NoOption) const;
- /**
- * Create a QString in the C++ format to an function argument.
- * \param func the current metafunction.
- * \param argument metaargument information to be parsed.
- * \param options some extra options.
- */
- QString argumentString(const AbstractMetaFunction* func,
- const AbstractMetaArgument* argument,
- Options options = NoOption) const;
-
- void writeArgumentNames(QTextStream &s,
- const AbstractMetaFunction* func,
- Options options = NoOption) const;
-
- /**
- * Function used to write the fucntion arguments on the class buffer.
- * \param s the class output buffer
- * \param func the pointer to metafunction information
- * \param count the number of function arguments
- * \param options some extra options used during the parser
- */
- void writeFunctionArguments(QTextStream &s,
- const AbstractMetaFunction* func,
- Options options = NoOption) const;
- QString functionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const;
-
- /// Utility function for writeCodeSnips.
- typedef QPair<const AbstractMetaArgument*, QString> ArgumentVarReplacementPair;
- typedef QList<ArgumentVarReplacementPair> ArgumentVarReplacementList;
- ArgumentVarReplacementList getArgumentReplacement(const AbstractMetaFunction* func,
- bool usePyArgs, TypeSystem::Language language,
- const AbstractMetaArgument* lastArg);
-
- /// Write user's custom code snippets at class or module level.
- void writeCodeSnips(QTextStream& s,
- const CodeSnipList& codeSnips,
- CodeSnip::Position position,
- TypeSystem::Language language,
- const AbstractMetaClass* context = 0);
- /// Write user's custom code snippets at function level.
- void writeCodeSnips(QTextStream& s,
- const CodeSnipList& codeSnips,
- CodeSnip::Position position,
- TypeSystem::Language language,
- const AbstractMetaFunction* func,
- const AbstractMetaArgument* lastArg = 0);
-
- /// Returns a string with the user's custom code snippets that comply with \p position and \p language.
- QString getCodeSnippets(const CodeSnipList& codeSnips, CodeSnip::Position position, TypeSystem::Language language);
-
- /// Replaces variables for the user's custom code at global or class level.
- void processCodeSnip(QString& code, const AbstractMetaClass* context = 0);
-
- /// Replaces the %CONVERTTOPYTHON type system variable.
- inline void replaceConvertToPythonTypeSystemVariable(QString& code)
- {
- replaceConverterTypeSystemVariable(TypeSystemToPythonFunction, code);
- }
- /// Replaces the %CONVERTTOCPP type system variable.
- inline void replaceConvertToCppTypeSystemVariable(QString& code)
- {
- replaceConverterTypeSystemVariable(TypeSystemToCppFunction, code);
- }
- /// Replaces the %ISCONVERTIBLE type system variable.
- inline void replaceIsConvertibleToCppTypeSystemVariable(QString& code)
- {
- replaceConverterTypeSystemVariable(TypeSystemIsConvertibleFunction, code);
- }
- /// Replaces the %CHECKTYPE type system variable.
- inline void replaceTypeCheckTypeSystemVariable(QString& code)
- {
- replaceConverterTypeSystemVariable(TypeSystemCheckFunction, code);
- }
-
- /**
- * Verifies if any of the function's code injections of the "target"
- * type needs the type system variable "%CPPSELF".
- * \param func the function to check
- * \return true if the function's target code snippets use "%CPPSELF"
- */
- bool injectedCodeUsesCppSelf(const AbstractMetaFunction* func);
-
- /**
- * Verifies if any of the function's code injections of the "native"
- * type needs the type system variable "%PYSELF".
- * \param func the function to check
- * \return true if the function's native code snippets use "%PYSELF"
- */
- bool injectedCodeUsesPySelf(const AbstractMetaFunction* func);
-
- /**
- * Verifies if any of the function's code injections makes a call
- * to the C++ method. This is used by the generator to avoid writing calls
- * to C++ when the user custom code already does this.
- * \param func the function to check
- * \return true if the function's code snippets call the wrapped C++ function
- */
- bool injectedCodeCallsCppFunction(const AbstractMetaFunction* func);
-
- /**
- * Verifies if any of the function's code injections of the "native" class makes a
- * call to the C++ method. This is used by the generator to avoid writing calls to
- * Python overrides of C++ virtual methods when the user custom code already does this.
- * \param func the function to check
- * \return true if the function's code snippets call the Python override for a C++ virtual method
- */
- bool injectedCodeCallsPythonOverride(const AbstractMetaFunction* func);
-
- /**
- * Verifies if any of the function's code injections attributes values to
- * the return variable (%0 or %PYARG_0).
- * \param func the function to check
- * \param language the kind of code snip
- * \return true if the function's code attributes values to "%0" or "%PYARG_0"
- */
- bool injectedCodeHasReturnValueAttribution(const AbstractMetaFunction* func, TypeSystem::Language language = TypeSystem::TargetLangCode);
-
- /**
- * Verifies if any of the function's code injections uses the type system variable
- * for function arguments of a given index.
- */
- bool injectedCodeUsesArgument(const AbstractMetaFunction* func, int argumentIndex);
-
- /**
- * Function which parse the metafunction information
- * \param func the function witch will be parserd
- * \param option some extra options
- * \param arg_count the number of function arguments
- */
- QString functionSignature(const AbstractMetaFunction* func,
- QString prepend = "",
- QString append = "",
- Options options = NoOption,
- int arg_count = -1) const;
-
- /// Returns true if there are cases of multiple inheritance in any of its ancestors.
- bool hasMultipleInheritanceInAncestry(const AbstractMetaClass* metaClass);
-
- /// Returns true if the class needs to have a getattro function.
- bool classNeedsGetattroFunction(const AbstractMetaClass* metaClass);
-
- /// Returns a list of methods of the given class where each one is part of a different overload with both static and non-static method.
- AbstractMetaFunctionList getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClass* metaClass);
-
- /// Returns a list of parent classes for a given class.
- AbstractMetaClassList getBaseClasses(const AbstractMetaClass* metaClass) const;
-
- /// Returns a list of all ancestor classes for the given class.
- AbstractMetaClassList getAllAncestors(const AbstractMetaClass* metaClass) const;
-
- const AbstractMetaClass* getMultipleInheritingClass(const AbstractMetaClass* metaClass);
-
- void writeToPythonConversion(QTextStream& s, const AbstractMetaType* type,
- const AbstractMetaClass* context, const QString& argumentName);
- void writeToCppConversion(QTextStream& s, const AbstractMetaType* type, const AbstractMetaClass* context, const QString& inArgName, const QString& outArgName);
- void writeToCppConversion(QTextStream& s, const AbstractMetaClass* metaClass, const QString& inArgName, const QString& outArgName);
-
- /// Returns true if the argument is a pointer that rejects NULL values.
- bool shouldRejectNullPointerArgument(const AbstractMetaFunction* func, int argIndex);
-
- /// Verifies if the class should have a C++ wrapper generated for it, instead of only a Python wrapper.
- bool shouldGenerateCppWrapper(const AbstractMetaClass* metaClass) const;
-
- /// Adds enums eligible for generation from classes/namespaces marked not to be generated.
- static void lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList& enumList, const AbstractMetaClass* metaClass);
- /// Returns the enclosing class for an enum, or NULL if it should be global.
- const AbstractMetaClass* getProperEnclosingClassForEnum(const AbstractMetaEnum* metaEnum);
-
- QString wrapperName(const AbstractMetaClass* metaClass) const;
-
- static QString fullPythonFunctionName(const AbstractMetaFunction* func);
- static QString protectedEnumSurrogateName(const AbstractMetaEnum* metaEnum);
- static QString protectedFieldGetterName(const AbstractMetaField* field);
- static QString protectedFieldSetterName(const AbstractMetaField* field);
-
- static QString pythonPrimitiveTypeName(const QString& cppTypeName);
- static QString pythonPrimitiveTypeName(const PrimitiveTypeEntry* type);
-
- static QString pythonOperatorFunctionName(QString cppOpFuncName);
- static QString pythonOperatorFunctionName(const AbstractMetaFunction* func);
- static QString pythonRichCompareOperatorId(QString cppOpFuncName);
- static QString pythonRichCompareOperatorId(const AbstractMetaFunction* func);
-
- static QString cpythonOperatorFunctionName(const AbstractMetaFunction* func);
-
- static QString fixedCppTypeName(const CustomConversion::TargetToNativeConversion* toNative);
- static QString fixedCppTypeName(const AbstractMetaType* type);
- static QString fixedCppTypeName(const TypeEntry* type, QString typeName = QString());
-
- static bool isNumber(QString cpythonApiName);
- static bool isNumber(const TypeEntry* type);
- static bool isNumber(const AbstractMetaType* type);
- static bool isPyInt(const TypeEntry* type);
- static bool isPyInt(const AbstractMetaType* type);
- static bool isPairContainer(const AbstractMetaType* type);
-
- /**
- * Returns true if the type passed has a Python wrapper for it.
- * Although namespace has a Python wrapper, it's not considered a type.
- */
- static bool isWrapperType(const TypeEntry* type);
- static bool isWrapperType(const ComplexTypeEntry* type);
- static bool isWrapperType(const AbstractMetaType* metaType);
-
- /**
- * Checks if the type is an Object/QObject or pointer to Value Type.
- * In other words, tells if the type is "T*" and T has a Python wrapper.
- */
- static bool isPointerToWrapperType(const AbstractMetaType* type);
-
- /**
- * Returns true if \p type is an Object Type used as a value.
- */
- static bool isObjectTypeUsedAsValueType(const AbstractMetaType* type);
-
- static bool isValueTypeWithCopyConstructorOnly(const AbstractMetaClass* metaClass);
- bool isValueTypeWithCopyConstructorOnly(const TypeEntry* type) const;
- bool isValueTypeWithCopyConstructorOnly(const AbstractMetaType* type) const;
-
- /// Returns true if the type is a primitive but not a C++ primitive.
- static bool isUserPrimitive(const TypeEntry* type);
- static bool isUserPrimitive(const AbstractMetaType* type);
-
- /// Returns true if the type is a C++ primitive, a void*, a const char*, or a std::string.
- static bool isCppPrimitive(const TypeEntry* type);
- static bool isCppPrimitive(const AbstractMetaType* type);
-
- /// Returns true if the type is a C++ integral primitive, i.e. bool, char, int, long, and their unsigned counterparts.
- static bool isCppIntegralPrimitive(const TypeEntry* type);
- static bool isCppIntegralPrimitive(const AbstractMetaType* type);
-
- /// Checks if an argument type should be dereferenced by the Python method wrapper before calling the C++ method.
- static bool shouldDereferenceArgumentPointer(const AbstractMetaArgument* arg);
- /// Checks if a meta type should be dereferenced by the Python method wrapper passing it to C++.
- static bool shouldDereferenceAbstractMetaTypePointer(const AbstractMetaType* metaType);
-
- static bool visibilityModifiedToPrivate(const AbstractMetaFunction* func);
-
- QString converterObject(const AbstractMetaType* type);
- QString converterObject(const TypeEntry* type);
-
- QString cpythonBaseName(const AbstractMetaClass* metaClass);
- QString cpythonBaseName(const TypeEntry* type);
- QString cpythonBaseName(const AbstractMetaType* type);
- QString cpythonTypeName(const AbstractMetaClass* metaClass);
- QString cpythonTypeName(const TypeEntry* type);
- QString cpythonTypeNameExt(const TypeEntry* type);
- QString cpythonTypeNameExt(const AbstractMetaType* type);
- QString cpythonCheckFunction(const TypeEntry* type, bool genericNumberType = false);
- QString cpythonCheckFunction(const AbstractMetaType* metaType, bool genericNumberType = false);
- /**
- * Receives the argument \p type and tries to find the appropriate AbstractMetaType for it
- * or a custom type check.
- * \param type A string representing the type to be discovered.
- * \param metaType A pointer to an AbstractMetaType pointer, to where write a new meta type object
- * if one is produced from the \p type string. This object must be deallocated by
- * the caller. It will set the target variable to NULL, is \p type is a Python type.
- * \return A custom check if \p type is a custom type, or an empty string if \p metaType
- * receives an existing type object.
- */
- QString guessCPythonCheckFunction(const QString& type, AbstractMetaType** metaType);
- QString cpythonIsConvertibleFunction(const TypeEntry* type, bool genericNumberType = false, bool checkExact = false);
- QString cpythonIsConvertibleFunction(const AbstractMetaType* metaType, bool genericNumberType = false);
- inline QString cpythonIsConvertibleFunction(const AbstractMetaArgument* metaArg, bool genericNumberType = false)
- {
- return cpythonIsConvertibleFunction(metaArg->type(), genericNumberType);
- }
- QString guessCPythonIsConvertible(const QString& type);
-
- QString cpythonToCppConversionFunction(const AbstractMetaClass* metaClass);
- QString cpythonToCppConversionFunction(const AbstractMetaType* type, const AbstractMetaClass* context = 0);
- QString cpythonToPythonConversionFunction(const AbstractMetaType* type, const AbstractMetaClass* context = 0);
- QString cpythonToPythonConversionFunction(const AbstractMetaClass* metaClass);
- QString cpythonToPythonConversionFunction(const TypeEntry* type);
-
- QString cpythonFunctionName(const AbstractMetaFunction* func);
- QString cpythonMethodDefinitionName(const AbstractMetaFunction* func);
- QString cpythonGettersSettersDefinitionName(const AbstractMetaClass* metaClass);
- QString cpythonGetattroFunctionName(const AbstractMetaClass* metaClass);
- QString cpythonSetattroFunctionName(const AbstractMetaClass* metaClass);
- QString cpythonGetterFunctionName(const AbstractMetaField* metaField);
- QString cpythonSetterFunctionName(const AbstractMetaField* metaField);
- QString cpythonWrapperCPtr(const AbstractMetaClass* metaClass, QString argName = PYTHON_SELF_VAR);
- QString cpythonWrapperCPtr(const AbstractMetaType* metaType, QString argName);
- QString cpythonWrapperCPtr(const TypeEntry* type, QString argName);
-
- /// Guesses the scope to where belongs an argument's default value.
- QString guessScopeForDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg);
-
- QString cpythonEnumName(const EnumTypeEntry* enumEntry);
- inline QString cpythonEnumName(const AbstractMetaEnum* metaEnum)
- {
- return cpythonEnumName(metaEnum->typeEntry());
- }
-
- QString cpythonFlagsName(const FlagsTypeEntry* flagsEntry);
- inline QString cpythonFlagsName(const AbstractMetaEnum* metaEnum)
- {
- FlagsTypeEntry* flags = metaEnum->typeEntry()->flags();
- if (!flags)
- return QString();
- return cpythonFlagsName(flags);
- }
- /// Returns the special cast function name, the function used to proper cast class with multiple inheritance.
- QString cpythonSpecialCastFunctionName(const AbstractMetaClass* metaClass);
-
- QString getFunctionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const;
- QString getFormatUnitString(const AbstractMetaFunction* func, bool incRef = false) const;
-
- /// Returns the file name for the module global header. If no module name is provided the current will be used.
- QString getModuleHeaderFileName(const QString& moduleName = QString()) const;
-
- QString extendedIsConvertibleFunctionName(const TypeEntry* targetType) const;
- QString extendedToCppFunctionName(const TypeEntry* targetType) const;
-
- QMap< QString, QString > options() const;
-
- /// Returns true if the user enabled the so called "parent constructor heuristic".
- bool useCtorHeuristic() const;
- /// Returns true if the user enabled the so called "return value heuristic".
- bool useReturnValueHeuristic() const;
- /// Returns true if the user enabled PySide extensions.
- bool usePySideExtensions() const;
- /// Returns true if the generator should use the result of isNull()const to compute boolean casts.
- bool useIsNullAsNbNonZero() const;
- /// Returns true if the generated code should use the "#define protected public" hack.
- bool avoidProtectedHack() const;
- QString cppApiVariableName(const QString& moduleName = QString()) const;
- QString convertersVariableName(const QString& moduleName = QString()) const;
- /**
- * Returns the type index variable name for a given class. If \p alternativeTemplateName is true
- * and the class is a typedef for a template class instantiation, it will return an alternative name
- * made of the template class and the instantiation values, or an empty string if the class isn't
- * derived from a template class at all.
- */
- QString getTypeIndexVariableName(const AbstractMetaClass* metaClass, bool alternativeTemplateName = false);
- QString getTypeIndexVariableName(const TypeEntry* type);
- QString getTypeIndexVariableName(const AbstractMetaType* type);
-
- /// Returns true if the user don't want verbose error messages on the generated bindings.
- bool verboseErrorMessagesDisabled() const;
-
- /**
- * Builds an AbstractMetaType object from a QString.
- * Returns NULL if no type could be built from the string.
- * \param typeSignature The string describing the type to be built.
- * \return A new AbstractMetaType object that must be deleted by the caller, or a NULL pointer in case of failure.
- */
- AbstractMetaType* buildAbstractMetaTypeFromString(QString typeSignature);
-
- /// Creates an AbstractMetaType object from a TypeEntry.
- AbstractMetaType* buildAbstractMetaTypeFromTypeEntry(const TypeEntry* typeEntry);
- /// Creates an AbstractMetaType object from an AbstractMetaClass.
- AbstractMetaType* buildAbstractMetaTypeFromAbstractMetaClass(const AbstractMetaClass* metaClass);
-
- void writeMinimalConstructorExpression(QTextStream& s, const AbstractMetaType* type, const QString& defaultCtor = QString());
- void writeMinimalConstructorExpression(QTextStream& s, const TypeEntry* type, const QString& defaultCtor = QString());
-
- /**
- * Helper function to return the flags to be used by a meta type when
- * it needs to write some converter code.
- */
- static Options getConverterOptions(const AbstractMetaType* metaType);
-
- /**
- * Helper function to find for argument default value
- */
- static QString getDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg);
-protected:
- bool doSetup(const QMap<QString, QString>& args);
- void collectContainerTypesFromConverterMacros(const QString& code, bool toPythonMacro);
- // verify whether the class is copyable
- bool isCopyable(const AbstractMetaClass* metaClass);
-
- bool m_native_jump_table;
- static QHash<QString, QString> m_pythonPrimitiveTypeName;
- static QHash<QString, QString> m_pythonOperators;
- static QHash<QString, QString> m_formatUnits;
- static QHash<QString, QString> m_tpFuncs;
- static QStringList m_knownPythonTypes;
-
- void clearTpFuncs();
-
- const char* name() const { return "Shiboken"; }
-
- /// Initializes correspondences between primitive and Python types.
- static void initPrimitiveTypesCorrespondences();
- /// Initializes a list of Python known type names.
- static void initKnownPythonTypes();
-
- void writeFunctionCall(QTextStream& s,
- const AbstractMetaFunction* metaFunc,
- Options options = NoOption) const;
-
- void writeUnusedVariableCast(QTextStream& s, const QString& variableName);
-
- AbstractMetaFunctionList filterFunctions(const AbstractMetaClass* metaClass);
-
- // All data about extended converters: the type entries of the target type, and a
- // list of AbstractMetaClasses accepted as argument for the conversion.
- typedef QHash<const TypeEntry*, QList<const AbstractMetaClass*> > ExtendedConverterData;
- /// Returns all extended conversions for the current module.
- ExtendedConverterData getExtendedConverters() const;
-
- /// Returns a list of converters for the non wrapper types of the current module.
- QList<const CustomConversion*> getPrimitiveCustomConversions();
-
- /// Returns true if the Python wrapper for the received OverloadData must accept a list of arguments.
- static bool pythonFunctionWrapperUsesListOfArguments(const OverloadData& overloadData);
-
- Indentor INDENT;
-
- enum TypeSystemConverterVariable {
- TypeSystemCheckFunction = 0,
- TypeSystemIsConvertibleFunction,
- TypeSystemToCppFunction,
- TypeSystemToPythonFunction,
- TypeSystemConverterVariables
- };
- void replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable, QString& code);
-
-private:
- bool m_useCtorHeuristic;
- bool m_userReturnValueHeuristic;
- bool m_usePySideExtensions;
- bool m_verboseErrorMessagesDisabled;
- bool m_useIsNullAsNbNonZero;
- bool m_avoidProtectedHack;
-
- typedef QHash<QString, AbstractMetaType*> AbstractMetaTypeCache;
- AbstractMetaTypeCache m_metaTypeFromStringCache;
-
- /// Type system converter variable replacement names and regular expressions.
- QString m_typeSystemConvName[TypeSystemConverterVariables];
- QRegExp m_typeSystemConvRegEx[TypeSystemConverterVariables];
-};
-
-#endif // SHIBOKENGENERATOR_H
diff --git a/generators/shiboken/shibokennormalize.cpp b/generators/shiboken/shibokennormalize.cpp
deleted file mode 100644
index 01aad9732..000000000
--- a/generators/shiboken/shibokennormalize.cpp
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * This file is part of the PySide project.
- * This code was extracted from qmetaobject_p.h present on Qt4.7.
- *
- * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Contact: PySide team <contact@pyside.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "shibokennormalize_p.h"
-#include <QVarLengthArray>
-
-#if (QT_VERSION < QT_VERSION_CHECK(4, 7, 0))
-
-// mirrored in moc's utils.h
-static inline bool is_ident_char(char s)
-{
- return ((s >= 'a' && s <= 'z')
- || (s >= 'A' && s <= 'Z')
- || (s >= '0' && s <= '9')
- || s == '_'
- );
-}
-
-static inline bool is_space(char s)
-{
- return (s == ' ' || s == '\t');
-}
-
-static void qRemoveWhitespace(const char *s, char *d)
-{
- char last = 0;
- while (*s && is_space(*s))
- s++;
- while (*s) {
- while (*s && !is_space(*s))
- last = *d++ = *s++;
- while (*s && is_space(*s))
- s++;
- if (*s && ((is_ident_char(*s) && is_ident_char(last))
- || ((*s == ':') && (last == '<')))) {
- last = *d++ = ' ';
- }
- }
- *d = '\0';
-}
-
-// This code is shared with moc.cpp
-static QByteArray normalizeTypeInternalQt47(const char *t, const char *e, bool fixScope = false, bool adjustConst = true)
-{
- int len = e - t;
- /*
- Convert 'char const *' into 'const char *'. Start at index 1,
- not 0, because 'const char *' is already OK.
- */
- QByteArray constbuf;
- for (int i = 1; i < len; i++) {
- if ( t[i] == 'c'
- && strncmp(t + i + 1, "onst", 4) == 0
- && (i + 5 >= len || !is_ident_char(t[i + 5]))
- && !is_ident_char(t[i-1])
- ) {
- constbuf = QByteArray(t, len);
- if (is_space(t[i-1]))
- constbuf.remove(i-1, 6);
- else
- constbuf.remove(i, 5);
- constbuf.prepend("const ");
- t = constbuf.data();
- e = constbuf.data() + constbuf.length();
- break;
- }
- /*
- We musn't convert 'char * const *' into 'const char **'
- and we must beware of 'Bar<const Bla>'.
- */
- if (t[i] == '&' || t[i] == '*' ||t[i] == '<')
- break;
- }
- if (adjustConst && e > t + 6 && strncmp("const ", t, 6) == 0) {
- if (*(e-1) == '&') { // treat const reference as value
- t += 6;
- --e;
- } else if (is_ident_char(*(e-1)) || *(e-1) == '>') { // treat const value as value
- t += 6;
- }
- }
- QByteArray result;
- result.reserve(len);
-
-#if 1
- // consume initial 'const '
- if (strncmp("const ", t, 6) == 0) {
- t+= 6;
- result += "const ";
- }
-#endif
-
- // some type substitutions for 'unsigned x'
- if (strncmp("unsigned", t, 8) == 0) {
- // make sure "unsigned" is an isolated word before making substitutions
- if (!t[8] || !is_ident_char(t[8])) {
- if (strncmp(" int", t+8, 4) == 0) {
- t += 8+4;
- result += "uint";
- } else if (strncmp(" long", t+8, 5) == 0) {
- if ((strlen(t + 8 + 5) < 4 || strncmp(t + 8 + 5, " int", 4) != 0) // preserve '[unsigned] long int'
- && (strlen(t + 8 + 5) < 5 || strncmp(t + 8 + 5, " long", 5) != 0) // preserve '[unsigned] long long'
- ) {
- t += 8+5;
- result += "ulong";
- }
- } else if (strncmp(" short", t+8, 6) != 0 // preserve unsigned short
- && strncmp(" char", t+8, 5) != 0) { // preserve unsigned char
- // treat rest (unsigned) as uint
- t += 8;
- result += "uint";
- }
- }
- } else {
- // discard 'struct', 'class', and 'enum'; they are optional
- // and we don't want them in the normalized signature
- struct {
- const char *keyword;
- int len;
- } optional[] = {
- { "struct ", 7 },
- { "class ", 6 },
- { "enum ", 5 },
- { 0, 0 }
- };
- int i = 0;
- do {
- if (strncmp(optional[i].keyword, t, optional[i].len) == 0) {
- t += optional[i].len;
- break;
- }
- } while (optional[++i].keyword != 0);
- }
-
- bool star = false;
- while (t != e) {
- char c = *t++;
- if (fixScope && c == ':' && *t == ':' ) {
- ++t;
- c = *t++;
- int i = result.size() - 1;
- while (i >= 0 && is_ident_char(result.at(i)))
- --i;
- result.resize(i + 1);
- }
- star = star || c == '*';
- result += c;
- if (c == '<') {
- //template recursion
- const char* tt = t;
- int templdepth = 1;
- while (t != e) {
- c = *t++;
- if (c == '<')
- ++templdepth;
- if (c == '>')
- --templdepth;
- if (templdepth == 0 || (templdepth == 1 && c == ',')) {
- result += normalizeTypeInternalQt47(tt, t-1, fixScope, false);
- result += c;
- if (templdepth == 0) {
- if (*t == '>')
- result += ' '; // avoid >>
- break;
- }
- tt = t;
- }
- }
- }
-
- // cv qualifers can appear after the type as well
- if (!is_ident_char(c) && t != e && (e - t >= 5 && strncmp("const", t, 5) == 0)
- && (e - t == 5 || !is_ident_char(t[5]))) {
- t += 5;
- while (t != e && is_space(*t))
- ++t;
- if (adjustConst && t != e && *t == '&') {
- // treat const ref as value
- ++t;
- } else if (adjustConst && !star) {
- // treat const as value
- } else if (!star) {
- // move const to the front (but not if const comes after a *)
- result.prepend("const ");
- } else {
- // keep const after a *
- result += "const";
- }
- }
- }
-
- return result;
-}
-
-static char *qNormalizeTypeQt47(char *d, int &templdepth, QByteArray &result)
-{
- const char *t = d;
- while (*d && (templdepth
- || (*d != ',' && *d != ')'))) {
- if (*d == '<')
- ++templdepth;
- if (*d == '>')
- --templdepth;
- ++d;
- }
- if (strncmp("void", t, d - t) != 0)
- result += normalizeTypeInternalQt47(t, d);
-
- return d;
-}
-
-
-QByteArray QMetaObject_normalizedTypeQt47(const char *type)
-{
- QByteArray result;
-
- if (!type || !*type)
- return result;
-
- QVarLengthArray<char> stackbuf(qstrlen(type) + 1);
- qRemoveWhitespace(type, stackbuf.data());
- int templdepth = 0;
- qNormalizeTypeQt47(stackbuf.data(), templdepth, result);
-
- return result;
-}
-
-QByteArray QMetaObject_normalizedSignatureQt47(const char *method)
-{
- QByteArray result;
- if (!method || !*method)
- return result;
- int len = int(strlen(method));
- QVarLengthArray<char> stackbuf(len + 1);
- char *d = stackbuf.data();
- qRemoveWhitespace(method, d);
-
- result.reserve(len);
-
- int argdepth = 0;
- int templdepth = 0;
- while (*d) {
- if (argdepth == 1)
- d = qNormalizeTypeQt47(d, templdepth, result);
- if (*d == '(')
- ++argdepth;
- if (*d == ')')
- --argdepth;
- result += *d++;
- }
-
- return result;
-}
-#endif
diff --git a/generators/shiboken/shibokennormalize_p.h b/generators/shiboken/shibokennormalize_p.h
deleted file mode 100644
index 0a55b5075..000000000
--- a/generators/shiboken/shibokennormalize_p.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * This file is part of the PySide project.
- *
- * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Contact: PySide team <contact@pyside.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef SHIBOKENNORMALIZE_P_H
-#define SHIBOKENNORMALIZE_P_H
-
-#include <QMetaObject>
-#include <QByteArray>
-
-
-#if (QT_VERSION < QT_VERSION_CHECK(4, 7, 0))
- QByteArray QMetaObject_normalizedTypeQt47(const char *type);
- QByteArray QMetaObject_normalizedSignatureQt47(const char *type);
-
- #define SBK_NORMALIZED_TYPE(x) QMetaObject_normalizedTypeQt47(x)
- #define SBK_NORMALIZED_SIGNATURE(x) QMetaObject_normalizedSignatureQt47(x)
-#else
- #define SBK_NORMALIZED_TYPE(x) QMetaObject::normalizedType(x)
- #define SBK_NORMALIZED_SIGNATURE(x) QMetaObject::normalizedSignature(x)
-#endif
-
-#endif //SHIBOKENNORMALIZE_P_H
diff --git a/generators/shibokenconfig.h.in b/generators/shibokenconfig.h.in
deleted file mode 100644
index 7d844a940..000000000
--- a/generators/shibokenconfig.h.in
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef SHIBOKENCONFIG_H
-#define SHIBOKENCONFIG_H
-
-#define GENERATOR_BINARY "@GENERATORRUNNER_BINARY@"
-#define SHIBOKEN_VERSION "@shiboken_VERSION@"
-
-#endif