aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/generator/shiboken2/shibokengenerator.cpp')
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp2855
1 files changed, 0 insertions, 2855 deletions
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
deleted file mode 100644
index 0e8809e97..000000000
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
+++ /dev/null
@@ -1,2855 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt for Python.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "shibokengenerator.h"
-#include <abstractmetalang.h>
-#include <messages.h>
-#include "overloaddata.h"
-#include <reporthandler.h>
-#include <typedatabase.h>
-#include <abstractmetabuilder.h>
-#include <iostream>
-
-#include <QtCore/QDir>
-#include <QtCore/QDebug>
-#include <QtCore/QRegularExpression>
-#include <limits>
-#include <memory>
-
-static const char AVOID_PROTECTED_HACK[] = "avoid-protected-hack";
-static const char PARENT_CTOR_HEURISTIC[] = "enable-parent-ctor-heuristic";
-static const char RETURN_VALUE_HEURISTIC[] = "enable-return-value-heuristic";
-static const char ENABLE_PYSIDE_EXTENSIONS[] = "enable-pyside-extensions";
-static const char DISABLE_VERBOSE_ERROR_MESSAGES[] = "disable-verbose-error-messages";
-static const char USE_ISNULL_AS_NB_NONZERO[] = "use-isnull-as-nb_nonzero";
-static const char WRAPPER_DIAGNOSTICS[] = "wrapper-diagnostics";
-
-const char *CPP_ARG = "cppArg";
-const char *CPP_ARG_REMOVED = "removed_cppArg";
-const char *CPP_RETURN_VAR = "cppResult";
-const char *CPP_SELF_VAR = "cppSelf";
-const char *NULL_PTR = "nullptr";
-const char *PYTHON_ARG = "pyArg";
-const char *PYTHON_ARGS = "pyArgs";
-const char *PYTHON_OVERRIDE_VAR = "pyOverride";
-const char *PYTHON_RETURN_VAR = "pyResult";
-const char *PYTHON_TO_CPP_VAR = "pythonToCpp";
-const char *SMART_POINTER_GETTER = "kSmartPointerGetter";
-
-const char *CONV_RULE_OUT_VAR_SUFFIX = "_out";
-const char *BEGIN_ALLOW_THREADS =
- "PyThreadState *_save = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS";
-const char *END_ALLOW_THREADS = "PyEval_RestoreThread(_save); // Py_END_ALLOW_THREADS";
-
-//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 QRegularExpression placeHolderRegex(int index)
-{
- return QRegularExpression(QLatin1Char('%') + QString::number(index) + QStringLiteral("\\b"));
-}
-
-// Return a prefix to fully qualify value, eg:
-// resolveScopePrefix("Class::NestedClass::Enum::Value1", "Enum::Value1")
-// -> "Class::NestedClass::")
-static QString resolveScopePrefix(const QStringList &scopeList, const QString &value)
-{
- QString name;
- for (int i = scopeList.size() - 1 ; i >= 0; --i) {
- const QString prefix = scopeList.at(i) + QLatin1String("::");
- if (value.startsWith(prefix))
- name.clear();
- else
- name.prepend(prefix);
- }
- return name;
-}
-
-static inline QStringList splitClassScope(const AbstractMetaClass *scope)
-{
- return scope->qualifiedCppName().split(QLatin1String("::"), Qt::SkipEmptyParts);
-}
-
-static QString resolveScopePrefix(const AbstractMetaClass *scope, const QString &value)
-{
- return scope
- ? resolveScopePrefix(splitClassScope(scope), value)
- : QString();
-}
-
-static QString resolveScopePrefix(const AbstractMetaEnum *metaEnum,
- const QString &value)
-{
- QStringList parts;
- if (const AbstractMetaClass *scope = metaEnum->enclosingClass())
- parts.append(splitClassScope(scope));
- // Fully qualify the value which is required for C++ 11 enum classes.
- if (!metaEnum->isAnonymous())
- parts.append(metaEnum->name());
- return resolveScopePrefix(parts, value);
-}
-
-struct GeneratorClassInfoCacheEntry
-{
- ShibokenGenerator::FunctionGroups functionGroups;
- bool needsGetattroFunction = false;
-};
-
-using GeneratorClassInfoCache = QHash<const AbstractMetaClass *, GeneratorClassInfoCacheEntry>;
-
-Q_GLOBAL_STATIC(GeneratorClassInfoCache, generatorClassInfoCache)
-
-ShibokenGenerator::ShibokenGenerator()
-{
- if (m_pythonPrimitiveTypeName.isEmpty())
- ShibokenGenerator::initPrimitiveTypesCorrespondences();
-
- if (m_tpFuncs.isEmpty())
- ShibokenGenerator::clearTpFuncs();
-
- if (m_knownPythonTypes.isEmpty())
- ShibokenGenerator::initKnownPythonTypes();
-
- m_metaTypeFromStringCache = AbstractMetaTypeCache();
-
- m_typeSystemConvName[TypeSystemCheckFunction] = QLatin1String("checkType");
- m_typeSystemConvName[TypeSystemIsConvertibleFunction] = QLatin1String("isConvertible");
- m_typeSystemConvName[TypeSystemToCppFunction] = QLatin1String("toCpp");
- m_typeSystemConvName[TypeSystemToPythonFunction] = QLatin1String("toPython");
-
- const char CHECKTYPE_REGEX[] = R"(%CHECKTYPE\[([^\[]*)\]\()";
- const char ISCONVERTIBLE_REGEX[] = R"(%ISCONVERTIBLE\[([^\[]*)\]\()";
- const char CONVERTTOPYTHON_REGEX[] = R"(%CONVERTTOPYTHON\[([^\[]*)\]\()";
- // Capture a '*' leading the variable name into the target
- // so that "*valuePtr = %CONVERTTOCPP..." works as expected.
- const char CONVERTTOCPP_REGEX[] =
- R"((\*?%?[a-zA-Z_][\w\.]*(?:\[[^\[^<^>]+\])*)(?:\s+)=(?:\s+)%CONVERTTOCPP\[([^\[]*)\]\()";
- m_typeSystemConvRegEx[TypeSystemCheckFunction] = QRegularExpression(QLatin1String(CHECKTYPE_REGEX));
- m_typeSystemConvRegEx[TypeSystemIsConvertibleFunction] = QRegularExpression(QLatin1String(ISCONVERTIBLE_REGEX));
- m_typeSystemConvRegEx[TypeSystemToPythonFunction] = QRegularExpression(QLatin1String(CONVERTTOPYTHON_REGEX));
- m_typeSystemConvRegEx[TypeSystemToCppFunction] = QRegularExpression(QLatin1String(CONVERTTOCPP_REGEX));
-}
-
-ShibokenGenerator::~ShibokenGenerator() = default;
-
-void ShibokenGenerator::clearTpFuncs()
-{
- m_tpFuncs.insert(QLatin1String("__str__"), QString());
- m_tpFuncs.insert(QLatin1String("__repr__"), QString());
- m_tpFuncs.insert(QLatin1String("__iter__"), QString());
- m_tpFuncs.insert(QLatin1String("__next__"), QString());
-}
-
-void ShibokenGenerator::initPrimitiveTypesCorrespondences()
-{
- // Python primitive types names
- m_pythonPrimitiveTypeName.clear();
-
- // PyBool
- m_pythonPrimitiveTypeName.insert(QLatin1String("bool"), QLatin1String("PyBool"));
-
- const char *charTypes[] = {
- "char", "signed char", "unsigned char"
- };
- for (const char *charType : charTypes)
- m_pythonPrimitiveTypeName.insert(QLatin1String(charType), QStringLiteral("SbkChar"));
-
- // PyInt
- const char *intTypes[] = {
- "int", "signed int", "uint", "unsigned int",
- "short", "ushort", "signed short", "signed short int",
- "unsigned short", "unsigned short", "unsigned short int",
- "long"
- };
- for (const char *intType : intTypes)
- m_pythonPrimitiveTypeName.insert(QLatin1String(intType), QStringLiteral("PyInt"));
-
- // PyFloat
- m_pythonPrimitiveTypeName.insert(QLatin1String("double"), QLatin1String("PyFloat"));
- m_pythonPrimitiveTypeName.insert(QLatin1String("float"), QLatin1String("PyFloat"));
-
- // PyLong
- const char *longTypes[] = {
- "unsigned long", "signed long", "ulong", "unsigned long int",
- "long long", "__int64",
- "unsigned long long", "unsigned __int64", "size_t"
- };
- for (const char *longType : longTypes)
- m_pythonPrimitiveTypeName.insert(QLatin1String(longType), QStringLiteral("PyLong"));
-
- // Python operators
- m_pythonOperators.clear();
-
- // call operator
- m_pythonOperators.insert(QLatin1String("operator()"), QLatin1String("call"));
-
- // Arithmetic operators
- m_pythonOperators.insert(QLatin1String("operator+"), QLatin1String("add"));
- m_pythonOperators.insert(QLatin1String("operator-"), QLatin1String("sub"));
- m_pythonOperators.insert(QLatin1String("operator*"), QLatin1String("mul"));
- m_pythonOperators.insert(QLatin1String("operator/"), QLatin1String("div"));
- m_pythonOperators.insert(QLatin1String("operator%"), QLatin1String("mod"));
-
- // Inplace arithmetic operators
- m_pythonOperators.insert(QLatin1String("operator+="), QLatin1String("iadd"));
- m_pythonOperators.insert(QLatin1String("operator-="), QLatin1String("isub"));
- m_pythonOperators.insert(QLatin1String("operator++"), QLatin1String("iadd"));
- m_pythonOperators.insert(QLatin1String("operator--"), QLatin1String("isub"));
- m_pythonOperators.insert(QLatin1String("operator*="), QLatin1String("imul"));
- m_pythonOperators.insert(QLatin1String("operator/="), QLatin1String("idiv"));
- m_pythonOperators.insert(QLatin1String("operator%="), QLatin1String("imod"));
-
- // Bitwise operators
- m_pythonOperators.insert(QLatin1String("operator&"), QLatin1String("and"));
- m_pythonOperators.insert(QLatin1String("operator^"), QLatin1String("xor"));
- m_pythonOperators.insert(QLatin1String("operator|"), QLatin1String("or"));
- m_pythonOperators.insert(QLatin1String("operator<<"), QLatin1String("lshift"));
- m_pythonOperators.insert(QLatin1String("operator>>"), QLatin1String("rshift"));
- m_pythonOperators.insert(QLatin1String("operator~"), QLatin1String("invert"));
-
- // Inplace bitwise operators
- m_pythonOperators.insert(QLatin1String("operator&="), QLatin1String("iand"));
- m_pythonOperators.insert(QLatin1String("operator^="), QLatin1String("ixor"));
- m_pythonOperators.insert(QLatin1String("operator|="), QLatin1String("ior"));
- m_pythonOperators.insert(QLatin1String("operator<<="), QLatin1String("ilshift"));
- m_pythonOperators.insert(QLatin1String("operator>>="), QLatin1String("irshift"));
-
- // Comparison operators
- m_pythonOperators.insert(QLatin1String("operator=="), QLatin1String("eq"));
- m_pythonOperators.insert(QLatin1String("operator!="), QLatin1String("ne"));
- m_pythonOperators.insert(QLatin1String("operator<"), QLatin1String("lt"));
- m_pythonOperators.insert(QLatin1String("operator>"), QLatin1String("gt"));
- m_pythonOperators.insert(QLatin1String("operator<="), QLatin1String("le"));
- m_pythonOperators.insert(QLatin1String("operator>="), QLatin1String("ge"));
-
- // Initialize format units for C++->Python->C++ conversion
- m_formatUnits.clear();
- m_formatUnits.insert(QLatin1String("char"), QLatin1String("b"));
- m_formatUnits.insert(QLatin1String("unsigned char"), QLatin1String("B"));
- m_formatUnits.insert(QLatin1String("int"), QLatin1String("i"));
- m_formatUnits.insert(QLatin1String("unsigned int"), QLatin1String("I"));
- m_formatUnits.insert(QLatin1String("short"), QLatin1String("h"));
- m_formatUnits.insert(QLatin1String("unsigned short"), QLatin1String("H"));
- m_formatUnits.insert(QLatin1String("long"), QLatin1String("l"));
- m_formatUnits.insert(QLatin1String("unsigned long"), QLatin1String("k"));
- m_formatUnits.insert(QLatin1String("long long"), QLatin1String("L"));
- m_formatUnits.insert(QLatin1String("__int64"), QLatin1String("L"));
- m_formatUnits.insert(QLatin1String("unsigned long long"), QLatin1String("K"));
- m_formatUnits.insert(QLatin1String("unsigned __int64"), QLatin1String("K"));
- m_formatUnits.insert(QLatin1String("double"), QLatin1String("d"));
- m_formatUnits.insert(QLatin1String("float"), QLatin1String("f"));
-}
-
-void ShibokenGenerator::initKnownPythonTypes()
-{
- m_knownPythonTypes.clear();
- m_knownPythonTypes << QLatin1String("PyBool") << QLatin1String("PyInt")
- << QLatin1String("PyFloat") << QLatin1String("PyLong") << QLatin1String("PyObject")
- << QLatin1String("PyString") << QLatin1String("PyBuffer") << QLatin1String("PySequence")
- << QLatin1String("PyTuple") << QLatin1String("PyList") << QLatin1String("PyDict")
- << QLatin1String("PyObject*") << QLatin1String("PyObject *") << QLatin1String("PyTupleObject*");
-}
-
-QString ShibokenGenerator::translateTypeForWrapperMethod(const AbstractMetaType *cType,
- const AbstractMetaClass *context,
- Options options) const
-{
- if (cType->isArray())
- return translateTypeForWrapperMethod(cType->arrayElementType(), context, options) + QLatin1String("[]");
-
- 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
-{
- if (metaClass->isNamespace() || (metaClass->attributes() & AbstractMetaAttributes::FinalCppClass))
- return false;
- bool result = metaClass->isPolymorphic() || metaClass->hasVirtualDestructor();
- if (avoidProtectedHack()) {
- result = result || metaClass->hasProtectedFields() || metaClass->hasProtectedDestructor();
- if (!result && metaClass->hasProtectedFunctions()) {
- int protectedFunctions = 0;
- int protectedOperators = 0;
- const AbstractMetaFunctionList &funcs = metaClass->functions();
- for (const AbstractMetaFunction *func : funcs) {
- if (!func->isProtected() || func->isSignal() || func->isModifiedRemoved())
- continue;
- if (func->isOperatorOverload())
- protectedOperators++;
- else
- protectedFunctions++;
- }
- result = result || (protectedFunctions > protectedOperators);
- }
- } else {
- result = result && !metaClass->hasPrivateDestructor();
- }
- return result;
-}
-
-bool ShibokenGenerator::shouldWriteVirtualMethodNative(const AbstractMetaFunction *func)
-{
- // PYSIDE-803: Extracted this because it is used multiple times.
- const AbstractMetaClass *metaClass = func->ownerClass();
- return (!avoidProtectedHack() || !metaClass->hasPrivateDestructor())
- && ((func->isVirtual() || func->isAbstract())
- && (func->attributes() & AbstractMetaAttributes::FinalCppMethod) == 0);
-}
-
-void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList &enumList, const AbstractMetaClass *metaClass)
-{
- Q_ASSERT(metaClass);
- // if a scope is not to be generated, collect its enums into the parent scope
- if (!NamespaceTypeEntry::isVisibleScope(metaClass->typeEntry())) {
- const AbstractMetaEnumList &enums = metaClass->enums();
- for (AbstractMetaEnum *metaEnum : enums) {
- if (!metaEnum->isPrivate() && metaEnum->typeEntry()->generateCode()
- && !enumList.contains(metaEnum)) {
- enumList.append(metaEnum);
- }
- }
- }
-}
-
-QString ShibokenGenerator::wrapperName(const AbstractMetaClass *metaClass) const
-{
- Q_ASSERT(shouldGenerateCppWrapper(metaClass));
- QString result = metaClass->name();
- if (metaClass->enclosingClass()) // is a inner class
- result.replace(QLatin1String("::"), QLatin1String("_"));
- return result + QLatin1String("Wrapper");
-}
-
-QString ShibokenGenerator::fullPythonClassName(const AbstractMetaClass *metaClass)
-{
- QString fullClassName = metaClass->name();
- const AbstractMetaClass *enclosing = metaClass->enclosingClass();
- while (enclosing) {
- if (NamespaceTypeEntry::isVisibleScope(enclosing->typeEntry()))
- fullClassName.prepend(enclosing->name() + QLatin1Char('.'));
- enclosing = enclosing->enclosingClass();
- }
- fullClassName.prepend(packageName() + QLatin1Char('.'));
- return fullClassName;
-}
-
-QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction *func)
-{
- QString funcName;
- if (func->isOperatorOverload())
- funcName = ShibokenGenerator::pythonOperatorFunctionName(func);
- else
- funcName = func->name();
- if (func->ownerClass()) {
- QString fullClassName = fullPythonClassName(func->ownerClass());
- if (func->isConstructor())
- funcName = fullClassName;
- else
- funcName.prepend(fullClassName + QLatin1Char('.'));
- }
- else {
- funcName = packageName() + QLatin1Char('.') + func->name();
- }
- return funcName;
-}
-
-QString ShibokenGenerator::protectedEnumSurrogateName(const AbstractMetaEnum *metaEnum)
-{
- return metaEnum->fullName().replace(QLatin1Char('.'), QLatin1Char('_')).replace(QLatin1String("::"), QLatin1String("_")) + QLatin1String("_Surrogate");
-}
-
-QString ShibokenGenerator::protectedFieldGetterName(const AbstractMetaField *field)
-{
- return QStringLiteral("protected_%1_getter").arg(field->name());
-}
-
-QString ShibokenGenerator::protectedFieldSetterName(const AbstractMetaField *field)
-{
- return QStringLiteral("protected_%1_setter").arg(field->name());
-}
-
-QString ShibokenGenerator::cpythonFunctionName(const AbstractMetaFunction *func)
-{
- QString result;
-
- // PYSIDE-331: For inherited functions, we need to find the same labels.
- // Therefore we use the implementing class.
- if (func->implementingClass()) {
- result = cpythonBaseName(func->implementingClass()->typeEntry());
- if (func->isConstructor()) {
- result += QLatin1String("_Init");
- } else {
- result += QLatin1String("Func_");
- if (func->isOperatorOverload())
- result += ShibokenGenerator::pythonOperatorFunctionName(func);
- else
- result += func->name();
- }
- } else {
- result = QLatin1String("Sbk") + moduleName() + QLatin1String("Module_") + func->name();
- }
-
- return result;
-}
-
-QString ShibokenGenerator::cpythonMethodDefinitionName(const AbstractMetaFunction *func)
-{
- if (!func->ownerClass())
- return QString();
- return QStringLiteral("%1Method_%2").arg(cpythonBaseName(func->ownerClass()->typeEntry()), func->name());
-}
-
-QString ShibokenGenerator::cpythonGettersSettersDefinitionName(const AbstractMetaClass *metaClass)
-{
- return cpythonBaseName(metaClass) + QLatin1String("_getsetlist");
-}
-
-QString ShibokenGenerator::cpythonSetattroFunctionName(const AbstractMetaClass *metaClass)
-{
- return cpythonBaseName(metaClass) + QLatin1String("_setattro");
-}
-
-
-QString ShibokenGenerator::cpythonGetattroFunctionName(const AbstractMetaClass *metaClass)
-{
- return cpythonBaseName(metaClass) + QLatin1String("_getattro");
-}
-
-QString ShibokenGenerator::cpythonGetterFunctionName(const AbstractMetaField *metaField)
-{
- return QStringLiteral("%1_get_%2").arg(cpythonBaseName(metaField->enclosingClass()), metaField->name());
-}
-
-QString ShibokenGenerator::cpythonSetterFunctionName(const AbstractMetaField *metaField)
-{
- return QStringLiteral("%1_set_%2").arg(cpythonBaseName(metaField->enclosingClass()), metaField->name());
-}
-
-static QString cpythonEnumFlagsName(const QString &moduleName,
- const QString &qualifiedCppName)
-{
- QString result = QStringLiteral("Sbk%1_%2").arg(moduleName, qualifiedCppName);
- result.replace(QLatin1String("::"), QLatin1String("_"));
- return result;
-}
-
-// Return the scope for fully qualifying the enumeration including trailing "::".
-static QString searchForEnumScope(const AbstractMetaClass *metaClass, const QString &value)
-{
- if (!metaClass)
- return QString();
- const AbstractMetaEnumList &enums = metaClass->enums();
- for (const AbstractMetaEnum *metaEnum : enums) {
- if (metaEnum->findEnumValue(value))
- return resolveScopePrefix(metaEnum, value);
- }
- // PYSIDE-331: We need to also search the base classes.
- QString ret = searchForEnumScope(metaClass->enclosingClass(), value);
- if (ret.isEmpty())
- ret = searchForEnumScope(metaClass->baseClass(), value);
- return ret;
-}
-
-// Handle QFlags<> for guessScopeForDefaultValue()
-QString ShibokenGenerator::guessScopeForDefaultFlagsValue(const AbstractMetaFunction *func,
- const AbstractMetaArgument *arg,
- const QString &value) const
-{
- // Numeric values -> "Options(42)"
- static const QRegularExpression numberRegEx(QStringLiteral("^\\d+$")); // Numbers to flags
- Q_ASSERT(numberRegEx.isValid());
- if (numberRegEx.match(value).hasMatch()) {
- QString typeName = translateTypeForWrapperMethod(arg->type(), func->implementingClass());
- if (arg->type()->isConstant())
- typeName.remove(0, sizeof("const ") / sizeof(char) - 1);
- switch (arg->type()->referenceType()) {
- case NoReference:
- break;
- case LValueReference:
- typeName.chop(1);
- break;
- case RValueReference:
- typeName.chop(2);
- break;
- }
- return typeName + QLatin1Char('(') + value + QLatin1Char(')');
- }
-
- // "Options(Option1 | Option2)" -> "Options(Class::Enum::Option1 | Class::Enum::Option2)"
- static const QRegularExpression enumCombinationRegEx(QStringLiteral("^([A-Za-z_][\\w:]*)\\(([^,\\(\\)]*)\\)$")); // FlagName(EnumItem|EnumItem|...)
- Q_ASSERT(enumCombinationRegEx.isValid());
- const QRegularExpressionMatch match = enumCombinationRegEx.match(value);
- if (match.hasMatch()) {
- const QString expression = match.captured(2).trimmed();
- if (expression.isEmpty())
- return value;
- const QStringList enumItems = expression.split(QLatin1Char('|'));
- const QString scope = searchForEnumScope(func->implementingClass(),
- enumItems.constFirst().trimmed());
- if (scope.isEmpty())
- return value;
- QString result;
- QTextStream str(&result);
- str << match.captured(1) << '('; // Flag name
- for (int i = 0, size = enumItems.size(); i < size; ++i) {
- if (i)
- str << '|';
- str << scope << enumItems.at(i).trimmed();
- }
- str << ')';
- return result;
- }
- // A single flag "Option1" -> "Class::Enum::Option1"
- return searchForEnumScope(func->implementingClass(), value) + value;
-}
-
-/*
- * This function uses some heuristics to find out the scope for a given
- * argument default value since they must be fully qualified when used outside the class:
- * class A {
- * enum Enum { e1, e1 };
- * void foo(Enum e = e1);
- * }
- * should be qualified to:
- * A::Enum cppArg0 = A::Enum::e1;
- *
- * 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) const
-{
- QString value = arg->defaultValueExpression();
-
- if (value.isEmpty()
- || arg->hasModifiedDefaultValueExpression()
- || isPointer(arg->type())) {
- return value;
- }
-
- static const QRegularExpression enumValueRegEx(QStringLiteral("^([A-Za-z_]\\w*)?$"));
- Q_ASSERT(enumValueRegEx.isValid());
- // Do not qualify macros by class name, eg QSGGeometry(..., int t = GL_UNSIGNED_SHORT);
- static const QRegularExpression macroRegEx(QStringLiteral("^[A-Z_][A-Z0-9_]*$"));
- Q_ASSERT(macroRegEx.isValid());
- if (arg->type()->isPrimitive() && macroRegEx.match(value).hasMatch())
- return value;
-
- QString prefix;
- if (arg->type()->isEnum()) {
- if (const AbstractMetaEnum *metaEnum = findAbstractMetaEnum(arg->type()))
- prefix = resolveScopePrefix(metaEnum, value);
- } else if (arg->type()->isFlags()) {
- value = guessScopeForDefaultFlagsValue(func, arg, value);
- } else if (arg->type()->typeEntry()->isValue()) {
- const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes(), arg->type()->typeEntry());
- if (enumValueRegEx.match(value).hasMatch() && value != QLatin1String("NULL"))
- prefix = resolveScopePrefix(metaClass, value);
- } else if (arg->type()->isPrimitive() && arg->type()->name() == QLatin1String("int")) {
- if (enumValueRegEx.match(value).hasMatch() && func->implementingClass())
- prefix = resolveScopePrefix(func->implementingClass(), value);
- } else if(arg->type()->isPrimitive()) {
- static const QRegularExpression unknowArgumentRegEx(QStringLiteral("^(?:[A-Za-z_][\\w:]*\\()?([A-Za-z_]\\w*)(?:\\))?$")); // [PrimitiveType(] DESIREDNAME [)]
- Q_ASSERT(unknowArgumentRegEx.isValid());
- const QRegularExpressionMatch match = unknowArgumentRegEx.match(value);
- if (match.hasMatch() && func->implementingClass()) {
- const AbstractMetaFieldList &fields = func->implementingClass()->fields();
- for (const AbstractMetaField *field : fields) {
- if (match.captured(1).trimmed() == field->name()) {
- QString fieldName = field->name();
- if (field->isStatic()) {
- prefix = resolveScopePrefix(func->implementingClass(), value);
- fieldName.prepend(prefix);
- prefix.clear();
- } else {
- fieldName.prepend(QLatin1String(CPP_SELF_VAR) + QLatin1String("->"));
- }
- value.replace(match.captured(1), fieldName);
- break;
- }
- }
- }
- }
-
- if (!prefix.isEmpty())
- value.prepend(prefix);
- return value;
-}
-
-QString ShibokenGenerator::cpythonEnumName(const EnumTypeEntry *enumEntry)
-{
- QString p = enumEntry->targetLangPackage();
- p.replace(QLatin1Char('.'), QLatin1Char('_'));
- return cpythonEnumFlagsName(p, enumEntry->qualifiedCppName());
-}
-
-QString ShibokenGenerator::cpythonEnumName(const AbstractMetaEnum *metaEnum)
-{
- return cpythonEnumName(metaEnum->typeEntry());
-}
-
-QString ShibokenGenerator::cpythonFlagsName(const FlagsTypeEntry *flagsEntry)
-{
- QString p = flagsEntry->targetLangPackage();
- p.replace(QLatin1Char('.'), QLatin1Char('_'));
- return cpythonEnumFlagsName(p, flagsEntry->originalName());
-}
-
-QString ShibokenGenerator::cpythonFlagsName(const AbstractMetaEnum *metaEnum)
-{
- const FlagsTypeEntry *flags = metaEnum->typeEntry()->flags();
- if (!flags)
- return QString();
- return cpythonFlagsName(flags);
-}
-
-QString ShibokenGenerator::cpythonSpecialCastFunctionName(const AbstractMetaClass *metaClass)
-{
- return cpythonBaseName(metaClass->typeEntry()) + QLatin1String("SpecialCastFunction");
-}
-
-QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClass *metaClass,
- const QString &argName) const
-{
- return cpythonWrapperCPtr(metaClass->typeEntry(), argName);
-}
-
-QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType *metaType,
- const QString &argName) const
-{
- if (!ShibokenGenerator::isWrapperType(metaType->typeEntry()))
- return QString();
- return QLatin1String("reinterpret_cast< ::") + metaType->cppSignature()
- + QLatin1String(" *>(Shiboken::Conversions::cppPointer(") + cpythonTypeNameExt(metaType)
- + QLatin1String(", reinterpret_cast<SbkObject *>(") + argName + QLatin1String(")))");
-}
-
-QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntry *type,
- const QString &argName) const
-{
- if (!ShibokenGenerator::isWrapperType(type))
- return QString();
- return QLatin1String("reinterpret_cast< ::") + type->qualifiedCppName()
- + QLatin1String(" *>(Shiboken::Conversions::cppPointer(") + cpythonTypeNameExt(type)
- + QLatin1String(", reinterpret_cast<SbkObject *>(") + argName + QLatin1String(")))");
-}
-
-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;
- const FunctionModificationList &mods = func->modifications();
- for (const FunctionModification &funcMod : mods) {
- for (const 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');
- const AbstractMetaArgumentList &arguments = func->arguments();
- for (const AbstractMetaArgument *arg : arguments) {
- if (func->argumentRemoved(arg->argumentIndex() + 1))
- continue;
-
- if (!func->typeReplaced(arg->argumentIndex() + 1).isEmpty()) {
- result += QLatin1Char(objType);
- } else if (arg->type()->isObject()
- || arg->type()->isValue()
- || arg->type()->isValuePointer()
- || arg->type()->isNativePointer()
- || arg->type()->isEnum()
- || arg->type()->isFlags()
- || arg->type()->isContainer()
- || arg->type()->isSmartPointer()
- || arg->type()->referenceType() == LValueReference) {
- result += QLatin1Char(objType);
- } else if (arg->type()->isPrimitive()) {
- const auto *ptype =
- static_cast<const PrimitiveTypeEntry *>(arg->type()->typeEntry());
- if (ptype->basicReferencedTypeEntry())
- ptype = ptype->basicReferencedTypeEntry();
- if (m_formatUnits.contains(ptype->name()))
- result += m_formatUnits[ptype->name()];
- else
- result += QLatin1Char(objType);
- } else if (isCString(arg->type())) {
- result += QLatin1Char('z');
- } else {
- qCWarning(lcShiboken).noquote().nospace()
- << "Method: " << func->ownerClass()->qualifiedCppName()
- << "::" << func->signature() << " => Arg:"
- << arg->name() << "index: " << arg->argumentIndex()
- << " - cannot be handled properly. Use an inject-code to fix it!";
- result += QLatin1Char('?');
- }
- }
- return result;
-}
-
-QString ShibokenGenerator::cpythonBaseName(const AbstractMetaType *type)
-{
- if (isCString(type))
- return QLatin1String("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->referenceType() == NoReference) {
- baseName = QLatin1String("Sbk_") + type->name();
- } else if (type->isPrimitive()) {
- const auto *ptype = static_cast<const PrimitiveTypeEntry *>(type);
- while (ptype->basicReferencedTypeEntry())
- ptype = ptype->basicReferencedTypeEntry();
- if (ptype->targetLangApiName() == ptype->name())
- baseName = pythonPrimitiveTypeName(ptype->name());
- else
- baseName = ptype->targetLangApiName();
- } else if (type->isEnum()) {
- baseName = cpythonEnumName(static_cast<const EnumTypeEntry *>(type));
- } else if (type->isFlags()) {
- baseName = cpythonFlagsName(static_cast<const FlagsTypeEntry *>(type));
- } else if (type->isContainer()) {
- const auto *ctype = static_cast<const ContainerTypeEntry *>(type);
- switch (ctype->containerKind()) {
- 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 = QLatin1String("PySequence");
- break;
- case ContainerTypeEntry::SetContainer:
- baseName = QLatin1String("PySet");
- break;
- case ContainerTypeEntry::MapContainer:
- case ContainerTypeEntry::MultiMapContainer:
- case ContainerTypeEntry::HashContainer:
- case ContainerTypeEntry::MultiHashContainer:
- baseName = QLatin1String("PyDict");
- break;
- default:
- Q_ASSERT(false);
- }
- } else {
- baseName = QLatin1String("PyObject");
- }
- return baseName.replace(QLatin1String("::"), QLatin1String("_"));
-}
-
-QString ShibokenGenerator::cpythonTypeName(const AbstractMetaClass *metaClass)
-{
- return cpythonTypeName(metaClass->typeEntry());
-}
-
-QString ShibokenGenerator::cpythonTypeName(const TypeEntry *type)
-{
- return cpythonBaseName(type) + QLatin1String("_TypeF()");
-}
-
-QString ShibokenGenerator::cpythonTypeNameExt(const TypeEntry *type) const
-{
- return cppApiVariableName(type->targetLangPackage()) + QLatin1Char('[')
- + getTypeIndexVariableName(type) + QLatin1Char(']');
-}
-
-QString ShibokenGenerator::converterObject(const AbstractMetaType *type)
-{
- if (isCString(type))
- return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter<const char *>()");
- if (isVoidPointer(type))
- return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter<void *>()");
- const AbstractMetaTypeCList nestedArrayTypes = type->nestedArrayTypes();
- if (!nestedArrayTypes.isEmpty() && nestedArrayTypes.constLast()->isCppPrimitive()) {
- return QStringLiteral("Shiboken::Conversions::ArrayTypeConverter<")
- + nestedArrayTypes.constLast()->minimalSignature()
- + QLatin1String(">(") + QString::number(nestedArrayTypes.size())
- + QLatin1Char(')');
- }
- if (type->typeEntry()->isContainer()) {
- return convertersVariableName(type->typeEntry()->targetLangPackage())
- + QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']');
- }
- return converterObject(type->typeEntry());
-}
-
-QString ShibokenGenerator::converterObject(const TypeEntry *type)
-{
- if (isCppPrimitive(type))
- return QString::fromLatin1("Shiboken::Conversions::PrimitiveTypeConverter<%1>()").arg(type->qualifiedCppName());
- if (isWrapperType(type) || type->isEnum() || type->isFlags())
- return QString::fromLatin1("*PepType_SGTP(%1)->converter").arg(cpythonTypeNameExt(type));
-
- if (type->isArray()) {
- qDebug() << "Warning: no idea how to handle the Qt5 type " << type->qualifiedCppName();
- return QString();
- }
-
- /* the typedef'd primitive types case */
- const auto *pte = dynamic_cast<const PrimitiveTypeEntry *>(type);
- if (!pte) {
- qDebug() << "Warning: the Qt5 primitive type is unknown" << type->qualifiedCppName();
- return QString();
- }
- if (pte->basicReferencedTypeEntry())
- pte = pte->basicReferencedTypeEntry();
- if (pte->isPrimitive() && !pte->isCppPrimitive() && !pte->customConversion())
- return QString::fromLatin1("Shiboken::Conversions::PrimitiveTypeConverter<%1>()").arg(pte->qualifiedCppName());
-
- return convertersVariableName(type->targetLangPackage())
- + QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']');
-}
-
-QString ShibokenGenerator::cpythonTypeNameExt(const AbstractMetaType *type) const
-{
- return cppApiVariableName(type->typeEntry()->targetLangPackage()) + QLatin1Char('[')
- + getTypeIndexVariableName(type) + QLatin1Char(']');
-}
-
-static inline QString unknownOperator() { return QStringLiteral("__UNKNOWN_OPERATOR__"); }
-
-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)
-{
- typeName.remove(QLatin1Char(' '));
- typeName.replace(QLatin1Char('.'), QLatin1Char('_'));
- typeName.replace(QLatin1Char(','), QLatin1Char('_'));
- typeName.replace(QLatin1Char('<'), QLatin1Char('_'));
- typeName.replace(QLatin1Char('>'), QLatin1Char('_'));
- typeName.replace(QLatin1String("::"), QLatin1String("_"));
- typeName.replace(QLatin1String("*"), QLatin1String("PTR"));
- typeName.replace(QLatin1String("&"), QLatin1String("REF"));
- return typeName;
-}
-QString ShibokenGenerator::fixedCppTypeName(const TypeEntry *type, QString typeName)
-{
- if (typeName.isEmpty())
- typeName = type->qualifiedCppName();
- if (!(type->codeGeneration() & TypeEntry::GenerateTargetLang)) {
- typeName.prepend(QLatin1Char('_'));
- typeName.prepend(type->targetLangPackage());
- }
- return _fixedCppTypeName(typeName);
-}
-
-QString ShibokenGenerator::pythonPrimitiveTypeName(const QString &cppTypeName)
-{
- QString rv = ShibokenGenerator::m_pythonPrimitiveTypeName.value(cppTypeName, QString());
- if (rv.isEmpty()) {
- // activate this when some primitive types are missing,
- // i.e. when shiboken itself fails to build.
- // In general, this is valid while just called by isNumeric()
- // used on Qt5, 2015-09-20
- if (false) {
- std::cerr << "primitive type not found: " << qPrintable(cppTypeName) << std::endl;
- abort();
- }
- }
- return rv;
-}
-
-QString ShibokenGenerator::pythonPrimitiveTypeName(const PrimitiveTypeEntry *type)
-{
- while (type->basicReferencedTypeEntry())
- type = type->basicReferencedTypeEntry();
- return pythonPrimitiveTypeName(type->name());
-}
-
-QString ShibokenGenerator::pythonOperatorFunctionName(const QString &cppOpFuncName)
-{
- QString value = m_pythonOperators.value(cppOpFuncName);
- if (value.isEmpty())
- return unknownOperator();
- value.prepend(QLatin1String("__"));
- value.append(QLatin1String("__"));
- return value;
-}
-
-QString ShibokenGenerator::pythonOperatorFunctionName(const AbstractMetaFunction *func)
-{
- QString op = pythonOperatorFunctionName(func->originalName());
- if (op == unknownOperator())
- qCWarning(lcShiboken).noquote().nospace() << msgUnknownOperator(func);
- if (func->arguments().isEmpty()) {
- if (op == QLatin1String("__sub__"))
- op = QLatin1String("__neg__");
- else if (op == QLatin1String("__add__"))
- op = QLatin1String("__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, QLatin1Char('r'));
- }
- return op;
-}
-
-QString ShibokenGenerator::pythonRichCompareOperatorId(const QString &cppOpFuncName)
-{
- return QLatin1String("Py_") + m_pythonOperators.value(cppOpFuncName).toUpper();
-}
-
-QString ShibokenGenerator::pythonRichCompareOperatorId(const AbstractMetaFunction *func)
-{
- return pythonRichCompareOperatorId(func->originalName());
-}
-
-bool ShibokenGenerator::isNumber(const QString &cpythonApiName)
-{
- return cpythonApiName == QLatin1String("PyInt")
- || cpythonApiName == QLatin1String("PyFloat")
- || cpythonApiName == QLatin1String("PyLong")
- || cpythonApiName == QLatin1String("PyBool");
-}
-
-bool ShibokenGenerator::isNumber(const TypeEntry *type)
-{
- if (!type->isPrimitive())
- return false;
- return isNumber(pythonPrimitiveTypeName(static_cast<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(static_cast<const PrimitiveTypeEntry *>(type))
- == QLatin1String("PyInt");
-}
-
-bool ShibokenGenerator::isPyInt(const AbstractMetaType *type)
-{
- return isPyInt(type->typeEntry());
-}
-
-bool ShibokenGenerator::isWrapperType(const TypeEntry *type)
-{
- if (type->isComplex())
- return ShibokenGenerator::isWrapperType(static_cast<const ComplexTypeEntry *>(type));
- return type->isObject() || type->isValue() || type->isSmartPointer();
-}
-bool ShibokenGenerator::isWrapperType(const ComplexTypeEntry *type)
-{
- return isObjectType(type) || type->isValue() || type->isSmartPointer();
-}
-bool ShibokenGenerator::isWrapperType(const AbstractMetaType *metaType)
-{
- return isObjectType(metaType)
- || metaType->typeEntry()->isValue()
- || metaType->typeEntry()->isSmartPointer();
-}
-
-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->referenceType() == NoReference && type->indirections() == 0;
-}
-
-bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const AbstractMetaClass *metaClass)
-{
- if (!metaClass || !metaClass->typeEntry()->isValue())
- return false;
- if (metaClass->attributes().testFlag(AbstractMetaAttributes::HasRejectedDefaultConstructor))
- return false;
- const AbstractMetaFunctionList ctors =
- metaClass->queryFunctions(AbstractMetaClass::Constructors);
- bool copyConstructorFound = false;
- for (auto ctor : ctors) {
- switch (ctor->functionType()) {
- case AbstractMetaFunction::ConstructorFunction:
- return false;
- case AbstractMetaFunction::CopyConstructorFunction:
- copyConstructorFound = true;
- break;
- case AbstractMetaFunction::MoveConstructorFunction:
- break;
- default:
- Q_ASSERT(false);
- break;
- }
- }
- return copyConstructorFound;
-}
-
-bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const TypeEntry *type) const
-{
- if (!type || !type->isValue())
- return false;
- return isValueTypeWithCopyConstructorOnly(AbstractMetaClass::findClass(classes(), 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 auto *trueType = static_cast<const PrimitiveTypeEntry *>(type);
- if (trueType->basicReferencedTypeEntry())
- trueType = trueType->basicReferencedTypeEntry();
- return trueType->isPrimitive() && !trueType->isCppPrimitive()
- && trueType->qualifiedCppName() != QLatin1String("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 auto *trueType = static_cast<const PrimitiveTypeEntry *>(type);
- if (trueType->basicReferencedTypeEntry())
- trueType = trueType->basicReferencedTypeEntry();
- return trueType->qualifiedCppName() == QLatin1String("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->referenceType() == LValueReference && isWrapperType(metaType) && !isPointer(metaType);
-}
-
-bool ShibokenGenerator::visibilityModifiedToPrivate(const AbstractMetaFunction *func)
-{
- const FunctionModificationList &mods = func->modifications();
- for (const FunctionModification &mod : mods) {
- 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 QLatin1String("Shiboken::String::check");
- if (isVoidPointer(metaType))
- return QLatin1String("PyObject_Check");
- return cpythonCheckFunction(metaType->typeEntry(), genericNumberType);
- }
- auto typeEntry = metaType->typeEntry();
- if (typeEntry->isContainer()) {
- QString typeCheck = QLatin1String("Shiboken::Conversions::");
- ContainerTypeEntry::ContainerKind type =
- static_cast<const ContainerTypeEntry *>(typeEntry)->containerKind();
- 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().constFirst();
- if (isPointerToWrapperType(type)) {
- typeCheck += QString::fromLatin1("checkSequenceTypes(%1, ").arg(cpythonTypeNameExt(type));
- } else if (isWrapperType(type)) {
- typeCheck += QLatin1String("convertibleSequenceTypes(reinterpret_cast<SbkObjectType *>(");
- typeCheck += cpythonTypeNameExt(type);
- typeCheck += QLatin1String("), ");
- } else {
- typeCheck += QString::fromLatin1("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) ? QLatin1String("Pair") : QLatin1String("Dict");
- const AbstractMetaType *firstType = metaType->instantiations().constFirst();
- const AbstractMetaType *secondType = metaType->instantiations().constLast();
- if (isPointerToWrapperType(firstType) && isPointerToWrapperType(secondType)) {
- typeCheck += QString::fromLatin1("check%1Types(%2, %3, ")
- .arg(pyType, cpythonTypeNameExt(firstType), cpythonTypeNameExt(secondType));
- } else {
- typeCheck += QString::fromLatin1("convertible%1Types(%2, %3, %4, %5, ")
- .arg(pyType, converterObject(firstType),
- isPointerToWrapperType(firstType) ? QLatin1String("true") : QLatin1String("false"),
- converterObject(secondType),
- isPointerToWrapperType(secondType) ? QLatin1String("true") : QLatin1String("false"));
- }
- }
- return typeCheck;
- }
- return cpythonCheckFunction(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::fromLatin1("SbkObject_TypeCheck(%1, ").arg(cpythonTypeNameExt(type));
- if (isCppPrimitive(type)) {
- return pythonPrimitiveTypeName(static_cast<const PrimitiveTypeEntry *>(type))
- + QLatin1String("_Check");
- }
- QString typeCheck;
- if (type->targetLangApiName() == type->name())
- typeCheck = cpythonIsConvertibleFunction(type);
- else if (type->targetLangApiName() == QLatin1String("PyUnicode"))
- typeCheck = QLatin1String("Shiboken::String::check");
- else
- typeCheck = type->targetLangApiName() + QLatin1String("_Check");
- return typeCheck;
-}
-
-QString ShibokenGenerator::guessCPythonCheckFunction(const QString &type, AbstractMetaType **metaType)
-{
- *metaType = nullptr;
- // PYSIDE-795: We abuse PySequence for iterables.
- // This part handles the overrides in the XML files.
- if (type == QLatin1String("PySequence"))
- return QLatin1String("Shiboken::String::checkIterable");
-
- if (type == QLatin1String("PyTypeObject"))
- return QLatin1String("PyType_Check");
-
- if (type == QLatin1String("PyBuffer"))
- return QLatin1String("Shiboken::Buffer::checkType");
-
- if (type == QLatin1String("str"))
- return QLatin1String("Shiboken::String::check");
-
- *metaType = buildAbstractMetaTypeFromString(type);
- if (*metaType && !(*metaType)->typeEntry()->isCustom())
- return QString();
-
- return type + QLatin1String("_Check");
-}
-
-QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntry *type,
- bool /* genericNumberType */,
- bool /* checkExact */)
-{
- if (isWrapperType(type)) {
- QString result = QLatin1String("Shiboken::Conversions::");
- result += (type->isValue() && !isValueTypeWithCopyConstructorOnly(type))
- ? QLatin1String("isPythonToCppValueConvertible")
- : QLatin1String("isPythonToCppPointerConvertible");
- result += QLatin1String("(reinterpret_cast<SbkObjectType *>(")
- + cpythonTypeNameExt(type) + QLatin1String("), ");
- return result;
- }
- return QString::fromLatin1("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;
- }
-
- QString result = QLatin1String("Shiboken::Conversions::");
- if (isWrapperType(metaType)) {
- if (isPointer(metaType) || isValueTypeWithCopyConstructorOnly(metaType))
- result += QLatin1String("isPythonToCppPointerConvertible");
- else if (metaType->referenceType() == LValueReference)
- result += QLatin1String("isPythonToCppReferenceConvertible");
- else
- result += QLatin1String("isPythonToCppValueConvertible");
- result += QLatin1String("(reinterpret_cast<SbkObjectType *>(")
- + cpythonTypeNameExt(metaType) + QLatin1String("), ");
- return result;
- }
- result += QLatin1String("isPythonToCppConvertible(") + converterObject(metaType);
- // Write out array sizes if known
- const AbstractMetaTypeCList nestedArrayTypes = metaType->nestedArrayTypes();
- if (!nestedArrayTypes.isEmpty() && nestedArrayTypes.constLast()->isCppPrimitive()) {
- const int dim1 = metaType->arrayElementCount();
- const int dim2 = nestedArrayTypes.constFirst()->isArray()
- ? nestedArrayTypes.constFirst()->arrayElementCount() : -1;
- result += QLatin1String(", ") + QString::number(dim1)
- + QLatin1String(", ") + QString::number(dim2);
- }
- result += QLatin1String(", ");
- return result;
-}
-
-QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaArgument *metaArg, bool genericNumberType)
-{
- return cpythonIsConvertibleFunction(metaArg->type(), genericNumberType);
-}
-
-QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaClass *metaClass)
-{
- return QLatin1String("Shiboken::Conversions::pythonToCppPointer(reinterpret_cast<SbkObjectType *>(")
- + cpythonTypeNameExt(metaClass->typeEntry()) + QLatin1String("), ");
-}
-
-QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaType *type,
- const AbstractMetaClass * /* context */)
-{
- if (isWrapperType(type)) {
- return QLatin1String("Shiboken::Conversions::pythonToCpp")
- + (isPointer(type) ? QLatin1String("Pointer") : QLatin1String("Copy"))
- + QLatin1String("(reinterpret_cast<SbkObjectType *>(")
- + cpythonTypeNameExt(type) + QLatin1String("), ");
- }
- return QStringLiteral("Shiboken::Conversions::pythonToCppCopy(%1, ")
- .arg(converterObject(type));
-}
-
-QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaType *type,
- const AbstractMetaClass * /* context */)
-{
- if (isWrapperType(type)) {
- QString conversion;
- if (type->referenceType() == LValueReference && !(type->isValue() && type->isConstant()) && !isPointer(type))
- conversion = QLatin1String("reference");
- else if (type->isValue() || type->isSmartPointer())
- conversion = QLatin1String("copy");
- else
- conversion = QLatin1String("pointer");
- QString result = QLatin1String("Shiboken::Conversions::") + conversion
- + QLatin1String("ToPython(reinterpret_cast<SbkObjectType *>(")
- + cpythonTypeNameExt(type) + QLatin1String("), ");
- if (conversion != QLatin1String("pointer"))
- result += QLatin1Char('&');
- return result;
- }
- return QStringLiteral("Shiboken::Conversions::copyToPython(%1, %2")
- .arg(converterObject(type),
- (isCString(type) || isVoidPointer(type)) ? QString() : QLatin1String("&"));
-}
-
-QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaClass *metaClass)
-{
- return cpythonToPythonConversionFunction(metaClass->typeEntry());
-}
-
-QString ShibokenGenerator::cpythonToPythonConversionFunction(const TypeEntry *type)
-{
- if (isWrapperType(type)) {
- const QString conversion = type->isValue() ? QLatin1String("copy") : QLatin1String("pointer");
- QString result = QLatin1String("Shiboken::Conversions::") + conversion
- + QLatin1String("ToPython(reinterpret_cast<SbkObjectType *>(") + cpythonTypeNameExt(type)
- + QLatin1String("), ");
- if (conversion != QLatin1String("pointer"))
- result += QLatin1Char('&');
- return result;
- }
-
- return QStringLiteral("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(QLatin1Char('$'), QLatin1Char('.'));
-
- if (!(options & Generator::SkipName)) {
- // "int a", "int a[]"
- const int arrayPos = arg.indexOf(QLatin1Char('['));
- if (arrayPos != -1)
- arg.insert(arrayPos, QLatin1Char(' ') + argument->name());
- else
- arg.append(QLatin1Char(' ') + argument->name());
- }
-
- if ((options & Generator::SkipDefaultValues) != Generator::SkipDefaultValues &&
- !argument->originalDefaultValueExpression().isEmpty())
- {
- QString default_value = argument->originalDefaultValueExpression();
- if (default_value == QLatin1String("NULL"))
- default_value = QLatin1String(NULL_PTR);
-
- //WORKAROUND: fix this please
- if (default_value.startsWith(QLatin1String("new ")))
- default_value.remove(0, 4);
-
- arg += QLatin1String(" = ") + 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 << " self";
- }
-
- int argUsed = 0;
- for (int i = 0; i < arguments.size(); ++i) {
- if ((options & Generator::SkipRemovedArguments) && func->argumentRemoved(i+1))
- continue;
-
- if ((options & Generator::WriteSelf) || argUsed != 0)
- s << ", ";
- writeArgument(s, func, arguments[i], options);
- argUsed++;
- }
-}
-
-GeneratorContext ShibokenGenerator::contextForClass(const AbstractMetaClass *c) const
-{
- GeneratorContext result = Generator::contextForClass(c);
- if (shouldGenerateCppWrapper(c)) {
- result.m_type = GeneratorContext::WrappedClass;
- result.m_wrappername = wrapperName(c);
- }
- return result;
-}
-
-QString ShibokenGenerator::functionReturnType(const AbstractMetaFunction *func, Options options) const
-{
- QString modifiedReturnType = QString(func->typeReplaced(0));
- if (!modifiedReturnType.isEmpty() && !(options & OriginalTypeDescription))
- return modifiedReturnType;
- return translateType(func->type(), func->implementingClass(), options);
-}
-
-QString ShibokenGenerator::functionSignature(const AbstractMetaFunction *func,
- const QString &prepend,
- const 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";
-
- if (func->exceptionSpecification() == ExceptionSpecification::NoExcept)
- s << " noexcept";
-
- return result;
-}
-
-void ShibokenGenerator::writeArgumentNames(QTextStream &s,
- const AbstractMetaFunction *func,
- Options options) const
-{
- const AbstractMetaArgumentList arguments = func->arguments();
- int argCount = 0;
- for (auto argument : arguments) {
- const int index = argument->argumentIndex() + 1;
- if ((options & Generator::SkipRemovedArguments) && (func->argumentRemoved(index)))
- continue;
-
- s << ((argCount > 0) ? ", " : "") << argument->name();
-
- if (((options & Generator::VirtualCall) == 0)
- && (!func->conversionRule(TypeSystem::NativeCode, index).isEmpty()
- || !func->conversionRule(TypeSystem::TargetLangCode, index).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<< ")\n";
-}
-
-static bool filterFunction(const AbstractMetaFunction *func, bool avoidProtectedHack)
-{
- switch (func->functionType()) {
- case AbstractMetaFunction::DestructorFunction:
- case AbstractMetaFunction::SignalFunction:
- case AbstractMetaFunction::GetAttroFunction:
- case AbstractMetaFunction::SetAttroFunction:
- return false;
- default:
- break;
- }
- if (func->usesRValueReferences())
- return false;
- if (func->isModifiedRemoved() && !func->isAbstract()
- && (!avoidProtectedHack || !func->isProtected())) {
- return false;
- }
- return true;
-}
-
-AbstractMetaFunctionList ShibokenGenerator::filterFunctions(const AbstractMetaClass *metaClass)
-{
- AbstractMetaFunctionList result;
- const AbstractMetaFunctionList &funcs = metaClass->functions();
- result.reserve(funcs.size());
- for (AbstractMetaFunction *func : funcs) {
- if (filterFunction(func, avoidProtectedHack()))
- result.append(func);
- }
- return result;
-}
-
-ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverters() const
-{
- ExtendedConverterData extConvs;
- const AbstractMetaClassList &classList = classes();
- for (const AbstractMetaClass *metaClass : classList) {
- // Use only the classes for the current module.
- if (!shouldGenerate(metaClass))
- continue;
- const AbstractMetaFunctionList &overloads = metaClass->operatorOverloads(AbstractMetaClass::ConversionOp);
- for (AbstractMetaFunction *convOp : overloads) {
- // 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;
-}
-
-QVector<const CustomConversion *> ShibokenGenerator::getPrimitiveCustomConversions()
-{
- QVector<const CustomConversion *> conversions;
- const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes();
- for (const PrimitiveTypeEntry *type : primitiveTypeList) {
- 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 QLatin1String funcCall("%CPPSELF.%FUNCTION_NAME");
- int pos = str.indexOf(funcCall);
- if (pos == -1)
- return QString();
- pos = pos + funcCall.size();
- while (str.at(pos) == QLatin1Char(' ') || str.at(pos) == QLatin1Char('\t'))
- ++pos;
- if (str.at(pos) == QLatin1Char('('))
- ++pos;
- int begin = pos;
- int counter = 1;
- while (counter != 0) {
- if (str.at(pos) == QLatin1Char('('))
- ++counter;
- else if (str.at(pos) == QLatin1Char(')'))
- --counter;
- ++pos;
- }
- return str.mid(begin, pos-begin-1);
-}
-
-QString ShibokenGenerator::getCodeSnippets(const CodeSnipList &codeSnips,
- TypeSystem::CodeSnipPosition position,
- TypeSystem::Language language)
-{
- QString code;
- QTextStream c(&code);
- for (const CodeSnip &snip : codeSnips) {
- if ((position != TypeSystem::CodeSnipPositionAny && snip.position != position) || !(snip.language & language))
- continue;
- QString snipCode;
- QTextStream sc(&snipCode);
- formatCode(sc, snip.code(), INDENT);
- c << snipCode;
- }
- return code;
-}
-
-void ShibokenGenerator::processClassCodeSnip(QString &code, const GeneratorContext &context)
-{
- auto metaClass = context.metaClass();
- // Replace template variable by the Python Type object
- // for the class context in which the variable is used.
- code.replace(QLatin1String("%PYTHONTYPEOBJECT"),
- cpythonTypeName(metaClass) + QLatin1String("->type"));
- const QString className = context.useWrapper()
- ? context.wrapperName() : metaClass->qualifiedCppName();
- code.replace(QLatin1String("%TYPE"), className);
- code.replace(QLatin1String("%CPPTYPE"), metaClass->name());
-
- processCodeSnip(code);
-}
-
-void ShibokenGenerator::processCodeSnip(QString &code)
-{
- // 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();
- const bool argRemoved = func->argumentRemoved(i+1);
- if (argRemoved)
- ++removed;
- if (argRemoved && hasConversionRule)
- argValue = arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX);
- else if (argRemoved || (lastArg && arg->argumentIndex() > lastArg->argumentIndex()))
- argValue = QLatin1String(CPP_ARG_REMOVED) + QString::number(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
- ? pythonArgsAt(argPos) : QLatin1String(PYTHON_ARG);
- } else {
- argValue = hasConversionRule
- ? arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX)
- : QLatin1String(CPP_ARG) + QString::number(argPos);
- if (isWrapperType(type)) {
- if (type->referenceType() == LValueReference && !isPointer(type))
- argValue.prepend(QLatin1Char('*'));
- }
- }
- }
- } else {
- argValue = arg->name();
- }
- if (!argValue.isEmpty())
- argReplacements << ArgumentVarReplacementPair(arg, argValue);
-
- }
- return argReplacements;
-}
-
-void ShibokenGenerator::writeClassCodeSnips(QTextStream &s,
- const CodeSnipList &codeSnips,
- TypeSystem::CodeSnipPosition position,
- TypeSystem::Language language,
- const GeneratorContext &context)
-{
- QString code = getCodeSnippets(codeSnips, position, language);
- if (code.isEmpty())
- return;
- processClassCodeSnip(code, context);
- s << INDENT << "// Begin code injection\n";
- s << code;
- s << INDENT << "// End of code injection\n";
-}
-
-void ShibokenGenerator::writeCodeSnips(QTextStream &s,
- const CodeSnipList &codeSnips,
- TypeSystem::CodeSnipPosition position,
- TypeSystem::Language language)
-{
- QString code = getCodeSnippets(codeSnips, position, language);
- if (code.isEmpty())
- return;
- processCodeSnip(code);
- s << INDENT << "// Begin code injection\n";
- s << code;
- s << INDENT << "// End of code injection\n";
-}
-
-void ShibokenGenerator::writeCodeSnips(QTextStream &s,
- const CodeSnipList &codeSnips,
- TypeSystem::CodeSnipPosition 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++;
- }
-
- const auto &groups = func->implementingClass()
- ? getFunctionGroups(func->implementingClass())
- : getGlobalFunctionGroups();
- OverloadData od(groups[func->name()], this);
- bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(od);
-
- // Replace %PYARG_# variables.
- code.replace(QLatin1String("%PYARG_0"), QLatin1String(PYTHON_RETURN_VAR));
-
- static const QRegularExpression pyArgsRegex(QStringLiteral("%PYARG_(\\d+)"));
- Q_ASSERT(pyArgsRegex.isValid());
- if (language == TypeSystem::TargetLangCode) {
- if (usePyArgs) {
- code.replace(pyArgsRegex, QLatin1String(PYTHON_ARGS) + QLatin1String("[\\1-1]"));
- } else {
- static const QRegularExpression pyArgsRegexCheck(QStringLiteral("%PYARG_([2-9]+)"));
- Q_ASSERT(pyArgsRegexCheck.isValid());
- const QRegularExpressionMatch match = pyArgsRegexCheck.match(code);
- if (match.hasMatch()) {
- qCWarning(lcShiboken).noquote().nospace()
- << msgWrongIndex("%PYARG", match.captured(1), func);
- return;
- }
- code.replace(QLatin1String("%PYARG_1"), QLatin1String(PYTHON_ARG));
- }
- } else {
- // Replaces the simplest case of attribution to a
- // Python argument on the binding virtual method.
- static const QRegularExpression pyArgsAttributionRegex(QStringLiteral("%PYARG_(\\d+)\\s*=[^=]\\s*([^;]+)"));
- Q_ASSERT(pyArgsAttributionRegex.isValid());
- code.replace(pyArgsAttributionRegex, QLatin1String("PyTuple_SET_ITEM(")
- + QLatin1String(PYTHON_ARGS) + QLatin1String(", \\1-1, \\2)"));
- code.replace(pyArgsRegex, QLatin1String("PyTuple_GET_ITEM(")
- + QLatin1String(PYTHON_ARGS) + QLatin1String(", \\1-1)"));
- }
-
- // Replace %ARG#_TYPE variables.
- const AbstractMetaArgumentList &arguments = func->arguments();
- for (const AbstractMetaArgument *arg : arguments) {
- QString argTypeVar = QStringLiteral("%ARG%1_TYPE").arg(arg->argumentIndex() + 1);
- QString argTypeVal = arg->type()->cppSignature();
- code.replace(argTypeVar, argTypeVal);
- }
-
- static const QRegularExpression cppArgTypeRegexCheck(QStringLiteral("%ARG(\\d+)_TYPE"));
- Q_ASSERT(cppArgTypeRegexCheck.isValid());
- QRegularExpressionMatchIterator rit = cppArgTypeRegexCheck.globalMatch(code);
- while (rit.hasNext()) {
- QRegularExpressionMatch match = rit.next();
- qCWarning(lcShiboken).noquote().nospace()
- << msgWrongIndex("%ARG#_TYPE", match.captured(1), func);
- }
-
- // Replace template variable for return variable name.
- if (func->isConstructor()) {
- code.replace(QLatin1String("%0."), QLatin1String("cptr->"));
- code.replace(QLatin1String("%0"), QLatin1String("cptr"));
- } else if (func->type()) {
- QString returnValueOp = isPointerToWrapperType(func->type())
- ? QLatin1String("%1->") : QLatin1String("%1.");
- if (ShibokenGenerator::isWrapperType(func->type()))
- code.replace(QLatin1String("%0."), returnValueOp.arg(QLatin1String(CPP_RETURN_VAR)));
- code.replace(QLatin1String("%0"), QLatin1String(CPP_RETURN_VAR));
- }
-
- // Replace template variable for self Python object.
- QString pySelf = language == TypeSystem::NativeCode
- ? QLatin1String("pySelf") : QLatin1String("self");
- code.replace(QLatin1String("%PYSELF"), pySelf);
-
- // Replace template variable for a pointer to C++ of this object.
- if (func->implementingClass()) {
- QString replacement = func->isStatic() ? QLatin1String("%1::") : QLatin1String("%1->");
- QString cppSelf;
- if (func->isStatic())
- cppSelf = func->ownerClass()->qualifiedCppName();
- else if (language == TypeSystem::NativeCode)
- cppSelf = QLatin1String("this");
- else
- cppSelf = QLatin1String(CPP_SELF_VAR);
-
- // On comparison operator CPP_SELF_VAR is always a reference.
- if (func->isComparisonOperator())
- replacement = QLatin1String("%1.");
-
- if (func->isVirtual() && !func->isAbstract() && (!avoidProtectedHack() || !func->isProtected())) {
- QString methodCallArgs = getArgumentsFromMethodCall(code);
- if (!methodCallArgs.isEmpty()) {
- const QString pattern = QStringLiteral("%CPPSELF.%FUNCTION_NAME(%1)").arg(methodCallArgs);
- if (func->name() == QLatin1String("metaObject")) {
- QString wrapperClassName = wrapperName(func->ownerClass());
- QString cppSelfVar = avoidProtectedHack()
- ? QLatin1String("%CPPSELF")
- : QStringLiteral("reinterpret_cast<%1 *>(%CPPSELF)").arg(wrapperClassName);
- code.replace(pattern,
- QString::fromLatin1("(Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject *>(%1))"
- " ? %2->::%3::%FUNCTION_NAME(%4)"
- " : %CPPSELF.%FUNCTION_NAME(%4))").arg(pySelf, cppSelfVar, wrapperClassName, methodCallArgs));
- } else {
- code.replace(pattern,
- QString::fromLatin1("(Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject *>(%1))"
- " ? %CPPSELF->::%TYPE::%FUNCTION_NAME(%2)"
- " : %CPPSELF.%FUNCTION_NAME(%2))").arg(pySelf, methodCallArgs));
- }
- }
- }
-
- code.replace(QLatin1String("%CPPSELF."), replacement.arg(cppSelf));
- code.replace(QLatin1String("%CPPSELF"), cppSelf);
-
- if (code.indexOf(QLatin1String("%BEGIN_ALLOW_THREADS")) > -1) {
- if (code.count(QLatin1String("%BEGIN_ALLOW_THREADS")) == code.count(QLatin1String("%END_ALLOW_THREADS"))) {
- code.replace(QLatin1String("%BEGIN_ALLOW_THREADS"), QLatin1String(BEGIN_ALLOW_THREADS));
- code.replace(QLatin1String("%END_ALLOW_THREADS"), QLatin1String(END_ALLOW_THREADS));
- } else {
- qCWarning(lcShiboken) << "%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(QLatin1String("%PYTHONTYPEOBJECT"),
- cpythonTypeName(func->implementingClass()) + QLatin1String("->type"));
- } else {
- code.replace(QLatin1String("%PYTHONTYPEOBJECT."), pySelf + QLatin1String("->ob_type->"));
- code.replace(QLatin1String("%PYTHONTYPEOBJECT"), pySelf + QLatin1String("->ob_type"));
- }
- }
-
- // Replaces template %ARGUMENT_NAMES and %# variables by argument variables and values.
- // Replaces template variables %# for individual arguments.
- const ArgumentVarReplacementList &argReplacements = getArgumentReplacement(func, usePyArgs, language, lastArg);
-
- QStringList args;
- for (const ArgumentVarReplacementPair &pair : argReplacements) {
- if (pair.second.startsWith(QLatin1String(CPP_ARG_REMOVED)))
- continue;
- args << pair.second;
- }
- code.replace(QLatin1String("%ARGUMENT_NAMES"), args.join(QLatin1String(", ")));
-
- for (const 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->referenceType() == LValueReference && !isPointer(type))
- replacement.remove(0, 1);
- if (type->referenceType() == LValueReference || isPointer(type))
- code.replace(QString::fromLatin1("%%1.").arg(idx), replacement + QLatin1String("->"));
- }
- code.replace(placeHolderRegex(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(QLatin1String("%PYTHON_ARGUMENTS"), QLatin1String(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(QLatin1String("%PYTHON_METHOD_OVERRIDE"), QLatin1String(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()) {
- const AbstractMetaFunctionList &funcs = getFunctionOverloads(func->ownerClass(), func->name());
- for (const AbstractMetaFunction *f : funcs)
- hasProtectedOverload |= f->isProtected();
- }
-
- if (func->isProtected() || hasProtectedOverload) {
- code.replace(QLatin1String("%TYPE::%FUNCTION_NAME"),
- QStringLiteral("%1::%2_protected")
- .arg(wrapperName(func->ownerClass()), func->originalName()));
- code.replace(QLatin1String("%FUNCTION_NAME"),
- func->originalName() + QLatin1String("_protected"));
- }
- }
-
- if (func->isConstructor() && shouldGenerateCppWrapper(func->ownerClass()))
- code.replace(QLatin1String("%TYPE"), wrapperName(func->ownerClass()));
-
- if (func->ownerClass())
- code.replace(QLatin1String("%CPPTYPE"), func->ownerClass()->name());
-
- replaceTemplateVariables(code, func);
-
- processCodeSnip(code);
- s << INDENT << "// Begin code injection\n";
- s << code;
- s << INDENT << "// End of code injection\n";
-}
-
-// Returns true if the string is an expression,
-// and false if it is a variable.
-static bool isVariable(const QString &code)
-{
- static const QRegularExpression expr(QStringLiteral("^\\s*\\*?\\s*[A-Za-z_][A-Za-z_0-9.]*\\s*(?:\\[[^\\[]+\\])*$"));
- Q_ASSERT(expr.isValid());
- return expr.match(code.trimmed()).hasMatch();
-}
-
-// 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(QLatin1String("::")))
- normalized.remove(0, 2);
- QString suffix;
- while (normalized.endsWith(QLatin1Char('*')) || normalized.endsWith(QLatin1Char('&'))) {
- suffix.prepend(normalized.at(normalized.count() - 1));
- normalized.chop(1);
- normalized = normalized.trimmed();
- }
- const QString result = normalized + QLatin1Char(' ') + suffix;
- return result.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).toLatin1(); // toAscii is gone
- 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;
-}
-using StringPair = QPair<QString, QString>;
-
-void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable, QString &code)
-{
- QVector<StringPair> replacements;
- QRegularExpressionMatchIterator rit = m_typeSystemConvRegEx[converterVariable].globalMatch(code);
- while (rit.hasNext()) {
- const QRegularExpressionMatch match = rit.next();
- const QStringList list = match.capturedTexts();
- QString conversionString = list.constFirst();
- const QString &conversionTypeName = list.constLast();
- QString message;
- const AbstractMetaType *conversionType = buildAbstractMetaTypeFromString(conversionTypeName, &message);
- if (!conversionType) {
- qFatal("%s", qPrintable(msgCannotFindType(conversionTypeName,
- m_typeSystemConvName[converterVariable],
- message)));
- }
- QString conversion;
- QTextStream c(&conversion);
- switch (converterVariable) {
- case TypeSystemToCppFunction: {
- int end = match.capturedStart();
- int start = end;
- while (start > 0 && code.at(start) != QLatin1Char('\n'))
- --start;
- while (code.at(start).isSpace())
- ++start;
- QString varType = code.mid(start, end - start);
- conversionString = varType + list.constFirst();
- varType = miniNormalizer(varType);
- QString varName = list.at(1).trimmed();
- if (!varType.isEmpty()) {
- const QString conversionSignature = conversionType->cppSignature();
- if (varType != QLatin1String("auto") && varType != conversionSignature)
- qFatal("%s", qPrintable(msgConversionTypesDiffer(varType, conversionSignature)));
- c << getFullTypeName(conversionType) << ' ' << varName;
- writeMinimalConstructorExpression(c, conversionType);
- c << ";\n";
- Indentation indent(INDENT);
- c << INDENT;
- }
- c << cpythonToCppConversionFunction(conversionType);
- QString prefix;
- if (varName.startsWith(QLatin1Char('*'))) {
- varName.remove(0, 1);
- varName = varName.trimmed();
- } else {
- prefix = QLatin1Char('&');
- }
- QString arg = getConverterTypeSystemVariableArgument(code, match.capturedEnd());
- conversionString += arg;
- c << arg << ", " << prefix << '(' << varName << ')';
- break;
- }
- case TypeSystemCheckFunction:
- conversion = cpythonCheckFunction(conversionType);
- if (conversionType->typeEntry()->isPrimitive()
- && (conversionType->typeEntry()->name() == QLatin1String("PyObject")
- || !conversion.endsWith(QLatin1Char(' ')))) {
- c << '(';
- break;
- }
- Q_FALLTHROUGH();
- case TypeSystemIsConvertibleFunction:
- if (conversion.isEmpty())
- conversion = cpythonIsConvertibleFunction(conversionType);
- Q_FALLTHROUGH();
- case TypeSystemToPythonFunction:
- if (conversion.isEmpty())
- conversion = cpythonToPythonConversionFunction(conversionType);
- Q_FALLTHROUGH();
- default: {
- QString arg = getConverterTypeSystemVariableArgument(code, match.capturedEnd());
- conversionString += arg;
- if (converterVariable == TypeSystemToPythonFunction && !isVariable(arg)) {
- qFatal("Only variables are acceptable as argument to %%CONVERTTOPYTHON type system variable on code snippet: '%s'",
- qPrintable(code));
- }
- if (conversion.contains(QLatin1String("%in"))) {
- conversion.prepend(QLatin1Char('('));
- conversion.replace(QLatin1String("%in"), arg);
- } else {
- c << arg;
- }
- }
- }
- replacements.append(qMakePair(conversionString, conversion));
- }
- for (const StringPair &rep : qAsConst(replacements))
- code.replace(rep.first, rep.second);
-}
-
-bool ShibokenGenerator::injectedCodeUsesPySelf(const AbstractMetaFunction *func)
-{
- CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode);
- for (const CodeSnip &snip : qAsConst(snips)) {
- if (snip.code().contains(QLatin1String("%PYSELF")))
- return true;
- }
- return false;
-}
-
-bool ShibokenGenerator::injectedCodeCallsCppFunction(const GeneratorContext &context,
- const AbstractMetaFunction *func)
-{
- QString funcCall = func->originalName() + QLatin1Char('(');
- QString wrappedCtorCall;
- if (func->isConstructor()) {
- funcCall.prepend(QLatin1String("new "));
- const auto owner = func->ownerClass();
- const QString className = context.useWrapper()
- ? context.wrapperName() : owner->qualifiedCppName();
- wrappedCtorCall = QLatin1String("new ") + className + QLatin1Char('(');
- }
- CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode);
- for (const CodeSnip &snip : qAsConst(snips)) {
- if (snip.code().contains(QLatin1String("%FUNCTION_NAME(")) || snip.code().contains(funcCall)
- || (func->isConstructor()
- && ((func->ownerClass()->isPolymorphic() && snip.code().contains(wrappedCtorCall))
- || snip.code().contains(QLatin1String("new %TYPE("))))
- )
- return true;
- }
- return false;
-}
-
-bool ShibokenGenerator::injectedCodeCallsPythonOverride(const AbstractMetaFunction *func)
-{
- static const QRegularExpression overrideCallRegexCheck(QStringLiteral("PyObject_Call\\s*\\(\\s*%PYTHON_METHOD_OVERRIDE\\s*,"));
- Q_ASSERT(overrideCallRegexCheck.isValid());
- CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode);
- for (const CodeSnip &snip : qAsConst(snips)) {
- if (snip.code().contains(overrideCallRegexCheck))
- return true;
- }
- return false;
-}
-
-bool ShibokenGenerator::injectedCodeHasReturnValueAttribution(const AbstractMetaFunction *func, TypeSystem::Language language)
-{
- static const QRegularExpression retValAttributionRegexCheck_native(QStringLiteral("%0\\s*=[^=]\\s*.+"));
- Q_ASSERT(retValAttributionRegexCheck_native.isValid());
- static const QRegularExpression retValAttributionRegexCheck_target(QStringLiteral("%PYARG_0\\s*=[^=]\\s*.+"));
- Q_ASSERT(retValAttributionRegexCheck_target.isValid());
- CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, language);
- for (const CodeSnip &snip : qAsConst(snips)) {
- if (language == TypeSystem::TargetLangCode) {
- if (snip.code().contains(retValAttributionRegexCheck_target))
- return true;
- } else {
- if (snip.code().contains(retValAttributionRegexCheck_native))
- return true;
- }
- }
- return false;
-}
-
-bool ShibokenGenerator::injectedCodeUsesArgument(const AbstractMetaFunction *func, int argumentIndex)
-{
- CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny);
- const QRegularExpression argRegEx = placeHolderRegex(argumentIndex + 1);
- for (const CodeSnip &snip : qAsConst(snips)) {
- QString code = snip.code();
- if (code.contains(QLatin1String("%ARGUMENT_NAMES")) || code.contains(argRegEx))
- return true;
- }
- return false;
-}
-
-bool ShibokenGenerator::useOverrideCaching(const AbstractMetaClass *metaClass)
-{
- return metaClass->isPolymorphic();
-}
-
-ShibokenGenerator::AttroCheck ShibokenGenerator::checkAttroFunctionNeeds(const AbstractMetaClass *metaClass) const
-{
- AttroCheck result;
- if (metaClass->typeEntry()->isSmartPointer()) {
- result |= AttroCheckFlag::GetattroSmartPointer | AttroCheckFlag::SetattroSmartPointer;
- } else {
- if (getGeneratorClassInfo(metaClass).needsGetattroFunction)
- result |= AttroCheckFlag::GetattroOverloads;
- if (metaClass->queryFirstFunction(metaClass->functions(),
- AbstractMetaClass::GetAttroFunction)) {
- result |= AttroCheckFlag::GetattroUser;
- }
- if (usePySideExtensions() && metaClass->qualifiedCppName() == QLatin1String("QObject"))
- result |= AttroCheckFlag::SetattroQObject;
- if (useOverrideCaching(metaClass))
- result |= AttroCheckFlag::SetattroMethodOverride;
- if (metaClass->queryFirstFunction(metaClass->functions(),
- AbstractMetaClass::SetAttroFunction)) {
- result |= AttroCheckFlag::SetattroUser;
- }
- // PYSIDE-1255: If setattro is generated for a class inheriting
- // QObject, the property code needs to be generated, too.
- if ((result & AttroCheckFlag::SetattroMask) != 0
- && !result.testFlag(AttroCheckFlag::SetattroQObject)
- && metaClass->isQObject()) {
- result |= AttroCheckFlag::SetattroQObject;
- }
- }
- return result;
-}
-
-bool ShibokenGenerator::classNeedsGetattroFunctionImpl(const AbstractMetaClass *metaClass)
-{
- if (!metaClass)
- return false;
- if (metaClass->typeEntry()->isSmartPointer())
- return true;
- const auto &functionGroup = getFunctionGroups(metaClass);
- for (auto it = functionGroup.cbegin(), end = functionGroup.cend(); it != end; ++it) {
- AbstractMetaFunctionList overloads;
- for (AbstractMetaFunction *func : qAsConst(it.value())) {
- 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) {
- const auto &functionGroups = getFunctionGroups(metaClass);
- for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
- AbstractMetaFunctionList overloads;
- for (AbstractMetaFunction *func : qAsConst(it.value())) {
- 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.constFirst());
- }
- }
- return methods;
-}
-
-AbstractMetaClassList ShibokenGenerator::getBaseClasses(const AbstractMetaClass *metaClass) const
-{
- AbstractMetaClassList baseClasses;
- if (metaClass) {
- QStringList baseClassNames(metaClass->baseClassNames());
- const QString defaultSuperclass = metaClass->typeEntry()->defaultSuperclass();
- if (!defaultSuperclass.isEmpty()) {
- int index = baseClassNames.indexOf(defaultSuperclass);
- if (index >= 0)
- baseClassNames.move(index, 0);
- }
- for (const QString &parent : baseClassNames) {
- AbstractMetaClass *clazz = AbstractMetaClass::findClass(classes(), parent);
- if (clazz)
- baseClasses << clazz;
- }
- }
- return baseClasses;
-}
-
-const AbstractMetaClass *ShibokenGenerator::getMultipleInheritingClass(const AbstractMetaClass *metaClass)
-{
- if (!metaClass || metaClass->baseClassNames().isEmpty())
- return nullptr;
- 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);
- for (AbstractMetaClass *base : qAsConst(baseClasses)) {
- result.append(base);
- result.append(getAllAncestors(base));
- }
- }
- return result;
-}
-
-QString ShibokenGenerator::getModuleHeaderFileName(const QString &moduleName) const
-{
- return moduleCppPrefix(moduleName).toLower() + QLatin1String("_python.h");
-}
-
-bool ShibokenGenerator::isCopyable(const AbstractMetaClass *metaClass)
-
-{
- if (metaClass->isNamespace() || isObjectType(metaClass))
- return false;
- if (metaClass->typeEntry()->copyable() == ComplexTypeEntry::Unknown)
- return metaClass->hasCloneOperator();
-
- return metaClass->typeEntry()->copyable() == ComplexTypeEntry::CopyableSet;
-}
-
-AbstractMetaType *ShibokenGenerator::buildAbstractMetaTypeFromString(QString typeSignature,
- QString *errorMessage)
-{
- typeSignature = typeSignature.trimmed();
- if (typeSignature.startsWith(QLatin1String("::")))
- typeSignature.remove(0, 2);
-
- auto it = m_metaTypeFromStringCache.find(typeSignature);
- if (it == m_metaTypeFromStringCache.end()) {
- AbstractMetaType *metaType =
- AbstractMetaBuilder::translateType(typeSignature, nullptr, {}, errorMessage);
- if (Q_UNLIKELY(!metaType)) {
- if (errorMessage)
- errorMessage->prepend(msgCannotBuildMetaType(typeSignature));
- return nullptr;
- }
- it = m_metaTypeFromStringCache.insert(typeSignature, metaType);
- }
- return it.value();
-}
-
-AbstractMetaType *ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(const TypeEntry *typeEntry)
-{
- QString typeName = typeEntry->qualifiedCppName();
- if (typeName.startsWith(QLatin1String("::")))
- typeName.remove(0, 2);
- if (m_metaTypeFromStringCache.contains(typeName))
- return m_metaTypeFromStringCache.value(typeName);
- auto *metaType = new AbstractMetaType;
- metaType->setTypeEntry(typeEntry);
- metaType->clearIndirections();
- metaType->setReferenceType(NoReference);
- 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: ";
- for (AbstractMetaFunction *func : qAsConst(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)
-{
- switch (func->functionType()) {
- case AbstractMetaFunction::DestructorFunction:
- case AbstractMetaFunction::SignalFunction:
- case AbstractMetaFunction::GetAttroFunction:
- case AbstractMetaFunction::SetAttroFunction:
- return false;
- default:
- break;
- }
- if (func->isModifiedRemoved() && !func->isAbstract())
- return false;
- // weird operator overloads
- if (func->name() == QLatin1String("operator[]") || func->name() == QLatin1String("operator->")) // FIXME: what about cast operators?
- return false;
- return true;
-}
-
-ShibokenGenerator::FunctionGroups ShibokenGenerator::getGlobalFunctionGroups() const
-{
- const AbstractMetaFunctionList &lst = globalFunctions();
- FunctionGroups results;
- for (AbstractMetaFunction *func : lst) {
- if (isGroupable(func))
- results[func->name()].append(func);
- }
- return results;
-}
-
-const GeneratorClassInfoCacheEntry &ShibokenGenerator::getGeneratorClassInfo(const AbstractMetaClass *scope)
-{
- auto cache = generatorClassInfoCache();
- auto it = cache->find(scope);
- if (it == cache->end()) {
- it = cache->insert(scope, {});
- it.value().functionGroups = getFunctionGroupsImpl(scope);
- it.value().needsGetattroFunction = classNeedsGetattroFunctionImpl(scope);
- }
- return it.value();
-}
-
-ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroups(const AbstractMetaClass *scope)
-{
- Q_ASSERT(scope);
- return getGeneratorClassInfo(scope).functionGroups;
-}
-
-ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroupsImpl(const AbstractMetaClass *scope)
-{
- const AbstractMetaFunctionList &lst = scope->functions();
-
- FunctionGroups results;
- for (AbstractMetaFunction *func : lst) {
- if (isGroupable(func)) {
- auto it = results.find(func->name());
- if (it == results.end()) {
- results.insert(func->name(), AbstractMetaFunctionList(1, func));
- } else {
- // If there are virtuals methods in the mix (PYSIDE-570,
- // QFileSystemModel::index(QString,int) and
- // QFileSystemModel::index(int,int,QModelIndex)) override, make sure
- // the overriding method of the most-derived class is seen first
- // and inserted into the "seenSignatures" set.
- if (func->isVirtual())
- it.value().prepend(func);
- else
- it.value().append(func);
- }
- }
- }
- return results;
-}
-
-AbstractMetaFunctionList ShibokenGenerator::getInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *seen)
-{
- AbstractMetaFunctionList results;
- AbstractMetaClass *basis;
- if (func->ownerClass() && (basis = func->ownerClass()->baseClass())) {
- for (; basis; basis = basis->baseClass()) {
- const AbstractMetaFunction *inFunc = basis->findFunction(func->name());
- if (inFunc && !seen->contains(inFunc->minimalSignature())) {
- seen->insert(inFunc->minimalSignature());
- AbstractMetaFunction *newFunc = inFunc->copy();
- newFunc->setImplementingClass(func->implementingClass());
- results << newFunc;
- }
- }
- }
- return results;
-}
-
-AbstractMetaFunctionList ShibokenGenerator::getFunctionAndInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *seen)
-{
- AbstractMetaFunctionList results;
- seen->insert(func->minimalSignature());
- results << const_cast<AbstractMetaFunction *>(func) << getInheritedOverloads(func, seen);
- return results;
-}
-
-AbstractMetaFunctionList ShibokenGenerator::getFunctionOverloads(const AbstractMetaClass *scope, const QString &functionName)
-{
- AbstractMetaFunctionList lst = scope ? scope->functions() : globalFunctions();
-
- AbstractMetaFunctionList results;
- QSet<QString> seenSignatures;
- for (AbstractMetaFunction *func : qAsConst(lst)) {
- if (func->name() != functionName)
- continue;
- if (isGroupable(func)) {
- // PYSIDE-331: look also into base classes.
- results << getFunctionAndInheritedOverloads(func, &seenSignatures);
- }
- }
- return results;
-}
-
-Generator::OptionDescriptions ShibokenGenerator::options() const
-{
- return OptionDescriptions()
- << qMakePair(QLatin1String(AVOID_PROTECTED_HACK),
- QLatin1String("Avoid the use of the '#define protected public' hack."))
- << qMakePair(QLatin1String(DISABLE_VERBOSE_ERROR_MESSAGES),
- QLatin1String("Disable verbose error messages. Turn the python code hard to debug\n"
- "but safe few kB on the generated bindings."))
- << qMakePair(QLatin1String(PARENT_CTOR_HEURISTIC),
- QLatin1String("Enable heuristics to detect parent relationship on constructors."))
- << qMakePair(QLatin1String(ENABLE_PYSIDE_EXTENSIONS),
- QLatin1String("Enable PySide extensions, such as support for signal/slots,\n"
- "use this if you are creating a binding for a Qt-based library."))
- << qMakePair(QLatin1String(RETURN_VALUE_HEURISTIC),
- QLatin1String("Enable heuristics to detect parent relationship on return values\n"
- "(USE WITH CAUTION!)"))
- << qMakePair(QLatin1String(USE_ISNULL_AS_NB_NONZERO),
- QLatin1String("If a class have an isNull() const method, it will be used to compute\n"
- "the value of boolean casts"))
- << qMakePair(QLatin1String(WRAPPER_DIAGNOSTICS),
- QLatin1String("Generate diagnostic code around wrappers"));
-}
-
-bool ShibokenGenerator::handleOption(const QString &key, const QString & /* value */)
-{
- if (key == QLatin1String(PARENT_CTOR_HEURISTIC))
- return (m_useCtorHeuristic = true);
- if (key == QLatin1String(ENABLE_PYSIDE_EXTENSIONS))
- return (m_usePySideExtensions = true);
- if (key == QLatin1String(RETURN_VALUE_HEURISTIC))
- return (m_userReturnValueHeuristic = true);
- if (key == QLatin1String(DISABLE_VERBOSE_ERROR_MESSAGES))
- return (m_verboseErrorMessagesDisabled = true);
- if (key == QLatin1String(USE_ISNULL_AS_NB_NONZERO))
- return (m_useIsNullAsNbNonZero = true);
- if (key == QLatin1String(AVOID_PROTECTED_HACK))
- return (m_avoidProtectedHack = true);
- if (key == QLatin1String(WRAPPER_DIAGNOSTICS))
- return (m_wrapperDiagnostics = true);
- return false;
-}
-
-static void getCode(QStringList &code, const CodeSnipList &codeSnips)
-{
- for (const CodeSnip &snip : qAsConst(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;
-
- for (CustomConversion::TargetToNativeConversion *toNative : qAsConst(toCppConversions))
- code.append(toNative->conversion());
-}
-
-bool ShibokenGenerator::doSetup()
-{
- QStringList snips;
- const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes();
- for (const PrimitiveTypeEntry *type : primitiveTypeList)
- getCode(snips, type);
- const ContainerTypeEntryList &containerTypeList = containerTypes();
- for (const ContainerTypeEntry *type : containerTypeList)
- getCode(snips, type);
- const AbstractMetaClassList &classList = classes();
- for (const AbstractMetaClass *metaClass : classList)
- getCode(snips, metaClass->typeEntry());
-
- const TypeSystemTypeEntry *moduleEntry = TypeDatabase::instance()->defaultTypeSystemType();
- Q_ASSERT(moduleEntry);
- getCode(snips, moduleEntry);
-
- const auto &functionGroups = getGlobalFunctionGroups();
- for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
- for (AbstractMetaFunction *func : it.value())
- getCode(snips, func->injectedCodeSnips());
- }
-
- for (const QString &code : qAsConst(snips)) {
- collectContainerTypesFromConverterMacros(code, true);
- collectContainerTypesFromConverterMacros(code, false);
- }
-
- return true;
-}
-
-void ShibokenGenerator::collectContainerTypesFromConverterMacros(const QString &code, bool toPythonMacro)
-{
- QString convMacro = toPythonMacro ? QLatin1String("%CONVERTTOPYTHON[") : QLatin1String("%CONVERTTOCPP[");
- int offset = toPythonMacro ? sizeof("%CONVERTTOPYTHON") : sizeof("%CONVERTTOCPP");
- int start = 0;
- QString errorMessage;
- while ((start = code.indexOf(convMacro, start)) != -1) {
- int end = code.indexOf(QLatin1Char(']'), start);
- start += offset;
- if (code.at(start) != QLatin1Char('%')) {
- QString typeString = code.mid(start, end - start);
- if (AbstractMetaType *type =
- buildAbstractMetaTypeFromString(typeString, &errorMessage)) {
- addInstantiatedContainersAndSmartPointers(type, type->originalTypeDescription());
- } else {
- qFatal("%s: Cannot translate type \"%s\": %s", __FUNCTION__,
- qPrintable(typeString), qPrintable(errorMessage));
- }
- }
- 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::moduleCppPrefix(const QString &moduleName) const
- {
- QString result = moduleName.isEmpty() ? packageName() : moduleName;
- result.replace(QLatin1Char('.'), QLatin1Char('_'));
- return result;
-}
-
-QString ShibokenGenerator::cppApiVariableName(const QString &moduleName) const
-{
- return QLatin1String("Sbk") + moduleCppPrefix(moduleName)
- + QLatin1String("Types");
-}
-
-QString ShibokenGenerator::pythonModuleObjectName(const QString &moduleName) const
-{
- return QLatin1String("Sbk") + moduleCppPrefix(moduleName)
- + QLatin1String("ModuleObject");
-}
-
-QString ShibokenGenerator::convertersVariableName(const QString &moduleName) const
-{
- QString result = cppApiVariableName(moduleName);
- result.chop(1);
- result.append(QLatin1String("Converters"));
- return result;
-}
-
-static QString processInstantiationsVariableName(const AbstractMetaType *type)
-{
- QString res = QLatin1Char('_') + _fixedCppTypeName(type->typeEntry()->qualifiedCppName()).toUpper();
- const AbstractMetaTypeList &instantiations = type->instantiations();
- for (const AbstractMetaType *instantiation : instantiations) {
- res += instantiation->isContainer()
- ? processInstantiationsVariableName(instantiation)
- : QLatin1Char('_') + _fixedCppTypeName(instantiation->cppSignature()).toUpper();
- }
- return res;
-}
-
-static void appendIndexSuffix(QString *s)
-{
- if (!s->endsWith(QLatin1Char('_')))
- s->append(QLatin1Char('_'));
- s->append(QStringLiteral("IDX"));
-}
-
-QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass *metaClass,
- bool alternativeTemplateName) const
-{
- if (alternativeTemplateName) {
- const AbstractMetaClass *templateBaseClass = metaClass->templateBaseClass();
- if (!templateBaseClass)
- return QString();
- QString result = QLatin1String("SBK_")
- + _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName()).toUpper();
- const AbstractMetaTypeList &templateBaseClassInstantiations = metaClass->templateBaseClassInstantiations();
- for (const AbstractMetaType *instantiation : templateBaseClassInstantiations)
- result += processInstantiationsVariableName(instantiation);
- appendIndexSuffix(&result);
- return result;
- }
- return getTypeIndexVariableName(metaClass->typeEntry());
-}
-QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry *type) const
-{
- if (type->isCppPrimitive()) {
- const auto *trueType = static_cast<const PrimitiveTypeEntry *>(type);
- if (trueType->basicReferencedTypeEntry())
- type = trueType->basicReferencedTypeEntry();
- }
- QString result = QLatin1String("SBK_");
- // Disambiguate namespaces per module to allow for extending them.
- if (type->isNamespace()) {
- QString package = type->targetLangPackage();
- const int dot = package.lastIndexOf(QLatin1Char('.'));
- result += package.rightRef(package.size() - (dot + 1));
- }
- result += _fixedCppTypeName(type->qualifiedCppName()).toUpper();
- appendIndexSuffix(&result);
- return result;
-}
-QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaType *type) const
-{
- QString result = QLatin1String("SBK");
- if (type->typeEntry()->isContainer())
- result += QLatin1Char('_') + moduleName().toUpper();
- result += processInstantiationsVariableName(type);
- appendIndexSuffix(&result);
- return result;
-}
-
-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();
-}
-
-void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream &s, const AbstractMetaType *type, const QString &defaultCtor)
-{
- if (!defaultCtor.isEmpty()) {
- s << " = " << defaultCtor;
- return;
- }
- if (isCppPrimitive(type) || type->isSmartPointer())
- return;
- const auto ctor = minimalConstructor(type);
- if (ctor.isValid()) {
- s << ctor.initialization();
- } else {
- const QString message = msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__), type->cppSignature());
- qCWarning(lcShiboken()).noquote() << message;
- s << ";\n#error " << message << '\n';
- }
-}
-
-void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream &s, const TypeEntry *type, const QString &defaultCtor)
-{
- if (!defaultCtor.isEmpty()) {
- s << " = " << defaultCtor;
- return;
- }
- if (isCppPrimitive(type))
- return;
- const auto ctor = minimalConstructor(type);
- if (ctor.isValid()) {
- s << ctor.initialization();
- } else {
- const QString message = msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__), type->qualifiedCppName());
- qCWarning(lcShiboken()).noquote() << message;
- s << ";\n#error " << message << Qt::endl;
- }
-}
-
-bool ShibokenGenerator::isCppIntegralPrimitive(const TypeEntry *type)
-{
- if (!type->isCppPrimitive())
- return false;
- const auto *trueType = static_cast<const PrimitiveTypeEntry *>(type);
- if (trueType->basicReferencedTypeEntry())
- trueType = trueType->basicReferencedTypeEntry();
- QString typeName = trueType->qualifiedCppName();
- return !typeName.contains(QLatin1String("double"))
- && !typeName.contains(QLatin1String("float"))
- && !typeName.contains(QLatin1String("wchar"));
-}
-bool ShibokenGenerator::isCppIntegralPrimitive(const AbstractMetaType *type)
-{
- return isCppIntegralPrimitive(type->typeEntry());
-}
-
-QString ShibokenGenerator::pythonArgsAt(int i)
-{
- return QLatin1String(PYTHON_ARGS) + QLatin1Char('[')
- + QString::number(i) + QLatin1Char(']');
-}