aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/generator/shiboken/shibokengenerator.cpp')
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.cpp2556
1 files changed, 1277 insertions, 1279 deletions
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
index dc4648875..a1417e5d9 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
@@ -1,134 +1,119 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "shibokengenerator.h"
+#include "generatorstrings.h"
+#include "generatorargument.h"
+#include "defaultvalue.h"
+#include "generatorcontext.h"
#include "apiextractorresult.h"
+#include "codesnip.h"
+#include "customconversion.h"
#include "ctypenames.h"
+#include <abstractmetabuilder.h>
#include <abstractmetaenum.h>
#include <abstractmetafield.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
+#include <abstractmetalang_helpers.h>
+#include <usingmember.h>
+#include <exception.h>
#include <messages.h>
#include <modifications.h>
#include "overloaddata.h"
+#include <optionsparser.h>
#include "propertyspec.h"
#include "pytypenames.h"
#include <reporthandler.h>
#include <textstream.h>
#include <typedatabase.h>
-#include <abstractmetabuilder.h>
+#include <containertypeentry.h>
+#include <customtypenentry.h>
+#include <enumtypeentry.h>
+#include <flagstypeentry.h>
+#include <namespacetypeentry.h>
+#include <primitivetypeentry.h>
+#include <pythontypeentry.h>
+#include <smartpointertypeentry.h>
+#include <valuetypeentry.h>
+
#include <iostream>
+#include "qtcompat.h"
+
#include <QtCore/QDir>
#include <QtCore/QDebug>
#include <QtCore/QRegularExpression>
+
+#include <algorithm>
#include <limits>
#include <memory>
+#include <utility>
-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";
-
-// 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;
-}
+using namespace Qt::StringLiterals;
+
+static constexpr auto PARENT_CTOR_HEURISTIC = "enable-parent-ctor-heuristic"_L1;
+static constexpr auto RETURN_VALUE_HEURISTIC = "enable-return-value-heuristic"_L1;
+static constexpr auto DISABLE_VERBOSE_ERROR_MESSAGES = "disable-verbose-error-messages"_L1;
+static constexpr auto USE_ISNULL_AS_NB_BOOL = "use-isnull-as-nb-bool"_L1;
+// FIXME PYSIDE 7: Remove USE_ISNULL_AS_NB_NONZERO/USE_OPERATOR_BOOL_AS_NB_NONZERO
+static constexpr auto USE_ISNULL_AS_NB_NONZERO = "use-isnull-as-nb_nonzero"_L1;
+static constexpr auto USE_OPERATOR_BOOL_AS_NB_BOOL = "use-operator-bool-as-nb-bool"_L1;
+static constexpr auto USE_OPERATOR_BOOL_AS_NB_NONZERO = "use-operator-bool-as-nb-nonzero"_L1;
+static constexpr auto WRAPPER_DIAGNOSTICS = "wrapper-diagnostics"_L1;
+static constexpr auto NO_IMPLICIT_CONVERSIONS = "no-implicit-conversions"_L1;
+static constexpr auto LEAN_HEADERS = "lean-headers"_L1;
-static inline QStringList splitClassScope(const AbstractMetaClass *scope)
+QString CPP_ARG_N(int i)
{
- return scope->qualifiedCppName().split(QLatin1String("::"), Qt::SkipEmptyParts);
+ return CPP_ARG + QString::number(i);
}
-static QString resolveScopePrefix(const AbstractMetaClass *scope, const QString &value)
+constexpr auto CPP_ARG_REMOVED_PREFIX = "removed_cppArg"_L1;
+
+QString CPP_ARG_REMOVED(int i)
{
- return scope
- ? resolveScopePrefix(splitClassScope(scope), value)
- : QString();
+ return CPP_ARG_REMOVED_PREFIX + QString::number(i);
}
-static QString resolveScopePrefix(const AbstractMetaEnum &metaEnum,
- const QString &value)
+const char *const METHOD_DEF_SENTINEL = "{nullptr, nullptr, 0, nullptr} // Sentinel\n";
+const char *const PYTHON_TO_CPPCONVERSION_STRUCT = "Shiboken::Conversions::PythonToCppConversion";
+
+const char *const openTargetExternC = R"(
+// Target ---------------------------------------------------------
+
+extern "C" {
+)";
+const char *const closeExternC = "} // extern \"C\"\n\n";
+const char *const richCompareComment =
+ "// PYSIDE-74: By default, we redirect to object's tp_richcompare (which is `==`, `!=`).\n";
+
+struct ShibokenGeneratorOptions
{
- 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);
-}
+ bool useCtorHeuristic = false;
+ bool userReturnValueHeuristic = false;
+ bool verboseErrorMessagesDisabled = false;
+ bool useIsNullAsNbBool = false;
+ // FIXME PYSIDE 7 Flip m_leanHeaders default or remove?
+ bool leanHeaders = false;
+ bool useOperatorBoolAsNbBool = false;
+ // FIXME PYSIDE 7 Flip generateImplicitConversions default or remove?
+ bool generateImplicitConversions = true;
+ bool wrapperDiagnostics = false;
+};
struct GeneratorClassInfoCacheEntry
{
ShibokenGenerator::FunctionGroups functionGroups;
+ QList<AbstractMetaFunctionCList> numberProtocolOperators;
+ BoolCastFunctionOptional boolCastFunctionO;
bool needsGetattroFunction = false;
};
-using GeneratorClassInfoCache = QHash<const AbstractMetaClass *, GeneratorClassInfoCacheEntry>;
+using GeneratorClassInfoCache = QHash<AbstractMetaClassCPtr, GeneratorClassInfoCacheEntry>;
Q_GLOBAL_STATIC(GeneratorClassInfoCache, generatorClassInfoCache)
-using AbstractMetaTypeCache = QHash<QString, AbstractMetaType>;
-
-Q_GLOBAL_STATIC(AbstractMetaTypeCache, metaTypeFromStringCache)
-
static const char CHECKTYPE_REGEX[] = R"(%CHECKTYPE\[([^\[]*)\]\()";
static const char ISCONVERTIBLE_REGEX[] = R"(%ISCONVERTIBLE\[([^\[]*)\]\()";
static const char CONVERTTOPYTHON_REGEX[] = R"(%CONVERTTOPYTHON\[([^\[]*)\]\()";
@@ -141,14 +126,18 @@ const ShibokenGenerator::TypeSystemConverterRegExps &
ShibokenGenerator::typeSystemConvRegExps()
{
static const TypeSystemConverterRegExps result = {
- QRegularExpression(QLatin1String(CHECKTYPE_REGEX)),
- QRegularExpression(QLatin1String(ISCONVERTIBLE_REGEX)),
- QRegularExpression(QLatin1String(CONVERTTOCPP_REGEX)),
- QRegularExpression(QLatin1String(CONVERTTOPYTHON_REGEX))
+ QRegularExpression(QLatin1StringView(CHECKTYPE_REGEX)),
+ QRegularExpression(QLatin1StringView(ISCONVERTIBLE_REGEX)),
+ QRegularExpression(QLatin1StringView(CONVERTTOCPP_REGEX)),
+ QRegularExpression(QLatin1StringView(CONVERTTOPYTHON_REGEX))
};
return result;
}
+// Options are static to avoid duplicated handling since ShibokenGenerator
+// is instantiated for HeaderGenerator and CppGenerator.
+ShibokenGeneratorOptions ShibokenGenerator::m_options;
+
ShibokenGenerator::ShibokenGenerator() = default;
ShibokenGenerator::~ShibokenGenerator() = default;
@@ -157,64 +146,65 @@ ShibokenGenerator::~ShibokenGenerator() = default;
static const QHash<QString, QString> &primitiveTypesCorrespondences()
{
static const QHash<QString, QString> result = {
- {QLatin1String("bool"), pyBoolT()},
- {QLatin1String("char"), sbkCharT()},
- {QLatin1String("signed char"), sbkCharT()},
- {QLatin1String("unsigned char"), sbkCharT()},
- {intT(), pyIntT()},
- {QLatin1String("signed int"), pyIntT()},
- {QLatin1String("uint"), pyIntT()},
- {QLatin1String("unsigned int"), pyIntT()},
- {shortT(), pyIntT()},
- {QLatin1String("ushort"), pyIntT()},
- {QLatin1String("signed short"), pyIntT()},
- {QLatin1String("signed short int"), pyIntT()},
- {unsignedShortT(), pyIntT()},
- {QLatin1String("unsigned short int"), pyIntT()},
- {longT(), pyIntT()},
- {doubleT(), pyFloatT()},
- {floatT(), pyFloatT()},
- {QLatin1String("unsigned long"), pyLongT()},
- {QLatin1String("signed long"), pyLongT()},
- {QLatin1String("ulong"), pyLongT()},
- {QLatin1String("unsigned long int"), pyLongT()},
- {QLatin1String("long long"), pyLongT()},
- {QLatin1String("__int64"), pyLongT()},
- {QLatin1String("unsigned long long"), pyLongT()},
- {QLatin1String("unsigned __int64"), pyLongT()},
- {QLatin1String("size_t"), pyLongT()}
+ {u"bool"_s, pyBoolT},
+ {u"char"_s, sbkCharT},
+ {u"signed char"_s, sbkCharT},
+ {u"unsigned char"_s, sbkCharT},
+ {intT, pyLongT},
+ {u"signed int"_s, pyLongT},
+ {u"uint"_s, pyLongT},
+ {u"unsigned int"_s, pyLongT},
+ {shortT, pyLongT},
+ {u"ushort"_s, pyLongT},
+ {u"signed short"_s, pyLongT},
+ {u"signed short int"_s, pyLongT},
+ {unsignedShortT, pyLongT},
+ {u"unsigned short int"_s, pyLongT},
+ {longT, pyLongT},
+ {doubleT, pyFloatT},
+ {floatT, pyFloatT},
+ {u"unsigned long"_s, pyLongT},
+ {u"signed long"_s, pyLongT},
+ {u"ulong"_s, pyLongT},
+ {u"unsigned long int"_s, pyLongT},
+ {u"long long"_s, pyLongT},
+ {u"__int64"_s, pyLongT},
+ {u"unsigned long long"_s, pyLongT},
+ {u"unsigned __int64"_s, pyLongT},
+ {u"size_t"_s, pyLongT}
};
return result;
}
-// Format units for C++->Python->C++ conversion
-const QHash<QString, QString> &ShibokenGenerator::formatUnits()
-{
- static const QHash<QString, QString> result = {
- {QLatin1String("char"), QLatin1String("b")},
- {QLatin1String("unsigned char"), QLatin1String("B")},
- {intT(), QLatin1String("i")},
- {QLatin1String("unsigned int"), QLatin1String("I")},
- {shortT(), QLatin1String("h")},
- {unsignedShortT(), QLatin1String("H")},
- {longT(), QLatin1String("l")},
- {unsignedLongLongT(), QLatin1String("k")},
- {longLongT(), QLatin1String("L")},
- {QLatin1String("__int64"), QLatin1String("L")},
- {unsignedLongLongT(), QLatin1String("K")},
- {QLatin1String("unsigned __int64"), QLatin1String("K")},
- {doubleT(), QLatin1String("d")},
- {floatT(), QLatin1String("f")},
+const QHash<QString, QChar> &ShibokenGenerator::formatUnits()
+{
+ static const QHash<QString, QChar> result = {
+ {u"char"_s, u'b'},
+ {u"unsigned char"_s, u'B'},
+ {intT, u'i'},
+ {u"unsigned int"_s, u'I'},
+ {shortT, u'h'},
+ {unsignedShortT, u'H'},
+ {longT, u'l'},
+ {unsignedLongLongT, u'k'},
+ {longLongT, u'L'},
+ {u"__int64"_s, u'L'},
+ {unsignedLongLongT, u'K'},
+ {u"unsigned __int64"_s, u'K'},
+ {doubleT, u'd'},
+ {floatT, u'f'},
};
return result;
}
QString ShibokenGenerator::translateTypeForWrapperMethod(const AbstractMetaType &cType,
- const AbstractMetaClass *context,
+ const AbstractMetaClassCPtr &context,
Options options) const
{
- if (cType.isArray())
- return translateTypeForWrapperMethod(*cType.arrayElementType(), context, options) + QLatin1String("[]");
+ if (cType.isArray()) {
+ return translateTypeForWrapperMethod(*cType.arrayElementType(), context, options)
+ + u"[]"_s;
+ }
if (avoidProtectedHack() && cType.isEnum()) {
auto metaEnum = api().findAbstractMetaEnum(cType.typeEntry());
@@ -225,7 +215,7 @@ QString ShibokenGenerator::translateTypeForWrapperMethod(const AbstractMetaType
return translateType(cType, context, options);
}
-bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass *metaClass) const
+bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClassCPtr &metaClass)
{
const auto wrapper = metaClass->cppWrapper();
return wrapper.testFlag(AbstractMetaClass::CppVirtualMethodWrapper)
@@ -233,37 +223,158 @@ bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass *metaCl
&& wrapper.testFlag(AbstractMetaClass::CppProtectedHackWrapper));
}
-bool ShibokenGenerator::shouldWriteVirtualMethodNative(const AbstractMetaFunctionCPtr &func) const
+bool ShibokenGenerator::shouldGenerateMetaObjectFunctions(const AbstractMetaClassCPtr &metaClass)
+{
+ return usePySideExtensions()
+ && (!avoidProtectedHack() || !metaClass->hasPrivateDestructor())
+ && !metaClass->typeEntry()->typeFlags()
+ .testFlag(ComplexTypeEntry::DisableQtMetaObjectFunctions)
+ && isQObject(metaClass);
+}
+
+ShibokenGenerator::FunctionGeneration ShibokenGenerator::functionGeneration(
+ const AbstractMetaFunctionCPtr &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().testFlag(AbstractMetaFunction::FinalCppMethod));
+ FunctionGeneration result;
+
+ const auto functionType = func->functionType();
+ switch (functionType) {
+ case AbstractMetaFunction::ConversionOperator:
+ case AbstractMetaFunction::AssignmentOperatorFunction:
+ case AbstractMetaFunction::MoveAssignmentOperatorFunction:
+ case AbstractMetaFunction::DestructorFunction:
+ case AbstractMetaFunction::SignalFunction:
+ case AbstractMetaFunction::GetAttroFunction:
+ case AbstractMetaFunction::SetAttroFunction:
+ return result;
+ default:
+ if (func->isUserAdded() || func->usesRValueReferences() || !func->isWhiteListed())
+ return result;
+ break;
+ }
+
+ const bool notModifiedRemoved = !func->isModifiedRemoved();
+ const bool isPrivate = func->isPrivate() && !func->isVisibilityModifiedToPrivate();
+ switch (functionType) {
+ case AbstractMetaFunction::ConstructorFunction:
+ if (!isPrivate && notModifiedRemoved)
+ result.setFlag(FunctionGenerationFlag::WrapperConstructor);
+ return result;
+ case AbstractMetaFunction::CopyConstructorFunction:
+ if (!isPrivate && notModifiedRemoved)
+ result.setFlag(FunctionGenerationFlag::WrapperSpecialCopyConstructor);
+ return result;
+ case AbstractMetaFunction::NormalFunction:
+ case AbstractMetaFunction::SlotFunction:
+ if (avoidProtectedHack() && func->isProtected())
+ result.setFlag(FunctionGenerationFlag::ProtectedWrapper);
+ break;
+ default:
+ break;
+ }
+
+ // Check on virtuals (including operators).
+ const bool isAbstract = func->isAbstract();
+ if (!(isAbstract || func->isVirtual())
+ || func->cppAttributes().testFlag(FunctionAttribute::Final)
+ || func->isModifiedFinal()) {
+ return result;
+ }
+
+ // MetaObject virtuals only need to be declared; CppGenerator creates a
+ // special implementation.
+ if (functionType == AbstractMetaFunction::NormalFunction
+ && usePySideExtensions() && isQObject(func->ownerClass())) {
+ const QString &name = func->name();
+ if (name == u"metaObject"_s || name == u"qt_metacall") {
+ result.setFlag(FunctionGenerationFlag::QMetaObjectMethod);
+ return result;
+ }
+ }
+
+ // Pure virtual functions need a default implementation even if private.
+ if (isAbstract || (notModifiedRemoved && !isPrivate))
+ result.setFlag(FunctionGenerationFlag::VirtualMethod);
+
+ return result;
}
-QString ShibokenGenerator::wrapperName(const AbstractMetaClass *metaClass) const
+AbstractMetaFunctionCList ShibokenGenerator::implicitConversions(const TypeEntryCPtr &t) const
+{
+ if (!generateImplicitConversions() || !t->isValue())
+ return {};
+ auto vte = std::static_pointer_cast<const ValueTypeEntry>(t);
+ auto customConversion = vte->customConversion();
+ if (customConversion && customConversion->replaceOriginalTargetToNativeConversions())
+ return {};
+
+ auto result = api().implicitConversions(t);
+ auto end = std::remove_if(result.begin(), result.end(),
+ [](const AbstractMetaFunctionCPtr &f) {
+ return f->isUserAdded();
+ });
+ result.erase(end, result.end());
+ return result;
+}
+
+QString ShibokenGenerator::wrapperName(const AbstractMetaClassCPtr &metaClass)
{
Q_ASSERT(shouldGenerateCppWrapper(metaClass));
QString result = metaClass->name();
if (metaClass->enclosingClass()) // is a inner class
- result.replace(QLatin1String("::"), QLatin1String("_"));
- return result + QLatin1String("Wrapper");
+ result.replace(u"::"_s, u"_"_s);
+ return result + u"Wrapper"_s;
}
-QString ShibokenGenerator::fullPythonClassName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::fullPythonClassName(const AbstractMetaClassCPtr &metaClass)
{
QString fullClassName = metaClass->name();
- const AbstractMetaClass *enclosing = metaClass->enclosingClass();
+ auto enclosing = metaClass->enclosingClass();
while (enclosing) {
if (NamespaceTypeEntry::isVisibleScope(enclosing->typeEntry()))
- fullClassName.prepend(enclosing->name() + QLatin1Char('.'));
+ fullClassName.prepend(enclosing->name() + u'.');
enclosing = enclosing->enclosingClass();
}
- fullClassName.prepend(packageName() + QLatin1Char('.'));
+ fullClassName.prepend(metaClass->typeEntry()->targetLangPackage() + u'.');
return fullClassName;
}
+QString ShibokenGenerator::headerFileNameForContext(const GeneratorContext &context)
+{
+ return fileNameForContextHelper(context, u"_wrapper.h"_s);
+}
+
+// PYSIDE-500: When avoiding the protected hack, also include the inherited
+// wrapper classes of the *current* module, because without the protected hack,
+// we sometimes need to cast inherited wrappers. Inherited classes
+// of *other* modules are completely regenerated by the header generator
+// since the wrapper headers are not installed.
+
+IncludeGroup ShibokenGenerator::baseWrapperIncludes(const GeneratorContext &classContext) const
+{
+ IncludeGroup result{u"Wrappers"_s, {}};
+ if (!classContext.useWrapper() || !avoidProtectedHack()
+ || classContext.forSmartPointer()) {
+ return result;
+ }
+
+ const auto moduleEntry = TypeDatabase::instance()->defaultTypeSystemType();
+ const auto &baseClasses = allBaseClasses(classContext.metaClass());
+ for (const auto &base : baseClasses) {
+ const auto te = base->typeEntry();
+ if (te->codeGeneration() == TypeEntry::GenerateCode) { // current module
+ const auto context = contextForClass(base);
+ if (context.useWrapper()) {
+ const QString header = headerFileNameForContext(context);
+ const auto type = typeSystemTypeEntry(te) == moduleEntry
+ ? Include::LocalPath : Include::IncludePath;
+ result.append(Include(type, header));
+ }
+ }
+ }
+ return result;
+}
+
QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunctionCPtr &func, bool forceFunc)
{
QString funcName;
@@ -276,24 +387,29 @@ QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunctionCPtr
if (func->isConstructor()) {
funcName = fullClassName;
if (forceFunc)
- funcName.append(QLatin1String(".__init__"));
+ funcName.append(u".__init__"_s);
}
else {
- funcName.prepend(fullClassName + QLatin1Char('.'));
+ funcName.prepend(fullClassName + u'.');
}
}
else {
- funcName = packageName() + QLatin1Char('.') + func->name();
+ funcName = packageName() + u'.' + func->name();
}
return funcName;
}
+bool ShibokenGenerator::wrapperDiagnostics()
+{
+ return m_options.wrapperDiagnostics;
+}
+
QString ShibokenGenerator::protectedEnumSurrogateName(const AbstractMetaEnum &metaEnum)
{
QString result = metaEnum.fullName();
- result.replace(QLatin1Char('.'), QLatin1Char('_'));
- result.replace(QLatin1String("::"), QLatin1String("_"));
- return result + QLatin1String("_Surrogate");
+ result.replace(u'.', u'_');
+ result.replace(u"::"_s, u"_"_s);
+ return result + u"_Surrogate"_s;
}
QString ShibokenGenerator::cpythonFunctionName(const AbstractMetaFunctionCPtr &func)
@@ -305,16 +421,16 @@ QString ShibokenGenerator::cpythonFunctionName(const AbstractMetaFunctionCPtr &f
if (func->implementingClass()) {
result = cpythonBaseName(func->implementingClass()->typeEntry());
if (func->isConstructor()) {
- result += QLatin1String("_Init");
+ result += u"_Init"_s;
} else {
- result += QLatin1String("Func_");
+ result += u"Func_"_s;
if (func->isOperatorOverload())
result += ShibokenGenerator::pythonOperatorFunctionName(func);
else
result += func->name();
}
} else {
- result = QLatin1String("Sbk") + moduleName() + QLatin1String("Module_") + func->name();
+ result = u"Sbk"_s + moduleName() + u"Module_"_s + func->name();
}
return result;
@@ -323,37 +439,37 @@ QString ShibokenGenerator::cpythonFunctionName(const AbstractMetaFunctionCPtr &f
QString ShibokenGenerator::cpythonMethodDefinitionName(const AbstractMetaFunctionCPtr &func)
{
if (!func->ownerClass())
- return QString();
- return cpythonBaseName(func->ownerClass()->typeEntry()) + QLatin1String("Method_")
+ return {};
+ return cpythonBaseName(func->ownerClass()->typeEntry()) + u"Method_"_s
+ func->name();
}
-QString ShibokenGenerator::cpythonGettersSettersDefinitionName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonGettersSettersDefinitionName(const AbstractMetaClassCPtr &metaClass)
{
- return cpythonBaseName(metaClass) + QLatin1String("_getsetlist");
+ return cpythonBaseName(metaClass) + u"_getsetlist"_s;
}
-QString ShibokenGenerator::cpythonSetattroFunctionName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonSetattroFunctionName(const AbstractMetaClassCPtr &metaClass)
{
- return cpythonBaseName(metaClass) + QLatin1String("_setattro");
+ return cpythonBaseName(metaClass) + u"_setattro"_s;
}
-QString ShibokenGenerator::cpythonGetattroFunctionName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonGetattroFunctionName(const AbstractMetaClassCPtr &metaClass)
{
- return cpythonBaseName(metaClass) + QLatin1String("_getattro");
+ return cpythonBaseName(metaClass) + u"_getattro"_s;
}
QString ShibokenGenerator::cpythonGetterFunctionName(const QString &name,
- const AbstractMetaClass *enclosingClass)
+ const AbstractMetaClassCPtr &enclosingClass)
{
- return cpythonBaseName(enclosingClass) + QStringLiteral("_get_") + name;
+ return cpythonBaseName(enclosingClass) + "_get_"_L1 + name;
}
QString ShibokenGenerator::cpythonSetterFunctionName(const QString &name,
- const AbstractMetaClass *enclosingClass)
+ const AbstractMetaClassCPtr &enclosingClass)
{
- return cpythonBaseName(enclosingClass) + QStringLiteral("_set_") + name;
+ return cpythonBaseName(enclosingClass) + "_set_"_L1 + name;
}
QString ShibokenGenerator::cpythonGetterFunctionName(const AbstractMetaField &metaField)
@@ -367,13 +483,13 @@ QString ShibokenGenerator::cpythonSetterFunctionName(const AbstractMetaField &me
}
QString ShibokenGenerator::cpythonGetterFunctionName(const QPropertySpec &property,
- const AbstractMetaClass *metaClass)
+ const AbstractMetaClassCPtr &metaClass)
{
return cpythonGetterFunctionName(property.name(), metaClass);
}
QString ShibokenGenerator::cpythonSetterFunctionName(const QPropertySpec &property,
- const AbstractMetaClass *metaClass)
+ const AbstractMetaClassCPtr &metaClass)
{
return cpythonSetterFunctionName(property.name(), metaClass);
}
@@ -381,159 +497,15 @@ QString ShibokenGenerator::cpythonSetterFunctionName(const QPropertySpec &proper
static QString cpythonEnumFlagsName(const QString &moduleName,
const QString &qualifiedCppName)
{
- QString result = QLatin1String("Sbk") + moduleName + QLatin1Char('_') + qualifiedCppName;
- result.replace(QLatin1String("::"), QLatin1String("_"));
+ QString result = u"Sbk"_s + moduleName + u'_' + qualifiedCppName;
+ result.replace(u"::"_s, u"_"_s);
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();
- for (const AbstractMetaEnum &metaEnum : metaClass->enums()) {
- auto v = metaEnum.findEnumValue(value);
- if (v.has_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 AbstractMetaFunctionCPtr &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 AbstractMetaFunctionCPtr &func,
- const AbstractMetaArgument &arg) const
-{
- QString value = arg.defaultValueExpression();
-
- if (value.isEmpty() || value == QLatin1String("{}")
- || arg.hasModifiedDefaultValueExpression()
- || arg.type().isPointer()) {
- 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()) {
- auto metaEnum = api().findAbstractMetaEnum(arg.type().typeEntry());
- if (metaEnum.has_value())
- prefix = resolveScopePrefix(metaEnum.value(), value);
- } else if (arg.type().isFlags()) {
- value = guessScopeForDefaultFlagsValue(func, arg, value);
- } else if (arg.type().typeEntry()->isValue()) {
- auto metaClass = AbstractMetaClass::findClass(api().classes(),
- arg.type().typeEntry());
- if (enumValueRegEx.match(value).hasMatch() && value != QLatin1String("NULL"))
- prefix = resolveScopePrefix(metaClass, value);
- } else if (arg.type().isPrimitive() && arg.type().name() == intT()) {
- 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()) {
- for (const AbstractMetaField &field : func->implementingClass()->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 ShibokenGenerator::cpythonEnumName(const EnumTypeEntryCPtr &enumEntry)
{
QString p = enumEntry->targetLangPackage();
- p.replace(QLatin1Char('.'), QLatin1Char('_'));
+ p.replace(u'.', u'_');
return cpythonEnumFlagsName(p, enumEntry->qualifiedCppName());
}
@@ -542,27 +514,25 @@ QString ShibokenGenerator::cpythonEnumName(const AbstractMetaEnum &metaEnum)
return cpythonEnumName(metaEnum.typeEntry());
}
-QString ShibokenGenerator::cpythonFlagsName(const FlagsTypeEntry *flagsEntry)
+QString ShibokenGenerator::cpythonFlagsName(const FlagsTypeEntryCPtr &flagsEntry)
{
QString p = flagsEntry->targetLangPackage();
- p.replace(QLatin1Char('.'), QLatin1Char('_'));
+ p.replace(u'.', u'_');
return cpythonEnumFlagsName(p, flagsEntry->originalName());
}
QString ShibokenGenerator::cpythonFlagsName(const AbstractMetaEnum *metaEnum)
{
- const FlagsTypeEntry *flags = metaEnum->typeEntry()->flags();
- if (!flags)
- return QString();
- return cpythonFlagsName(flags);
+ const auto flags = metaEnum->typeEntry()->flags();
+ return flags ? cpythonFlagsName(flags) : QString{};
}
-QString ShibokenGenerator::cpythonSpecialCastFunctionName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonSpecialCastFunctionName(const AbstractMetaClassCPtr &metaClass)
{
- return cpythonBaseName(metaClass->typeEntry()) + QLatin1String("SpecialCastFunction");
+ return cpythonBaseName(metaClass->typeEntry()) + u"SpecialCastFunction"_s;
}
-QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClass *metaClass,
+QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClassCPtr &metaClass,
const QString &argName)
{
return cpythonWrapperCPtr(metaClass->typeEntry(), argName);
@@ -572,57 +542,58 @@ QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType &metaType,
const QString &argName)
{
if (!metaType.isWrapperType())
- return QString();
- return QLatin1String("reinterpret_cast< ::") + metaType.cppSignature()
- + QLatin1String(" *>(Shiboken::Conversions::cppPointer(") + cpythonTypeNameExt(metaType)
- + QLatin1String(", reinterpret_cast<SbkObject *>(") + argName + QLatin1String(")))");
+ return {};
+ return u"reinterpret_cast< ::"_s + metaType.cppSignature()
+ + u" *>(Shiboken::Conversions::cppPointer("_s + cpythonTypeNameExt(metaType)
+ + u", reinterpret_cast<SbkObject *>("_s + argName + u")))"_s;
}
-QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntry *type,
+QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntryCPtr &type,
const QString &argName)
{
if (!type->isWrapperType())
return QString();
- return QLatin1String("reinterpret_cast< ::") + type->qualifiedCppName()
- + QLatin1String(" *>(Shiboken::Conversions::cppPointer(") + cpythonTypeNameExt(type)
- + QLatin1String(", reinterpret_cast<SbkObject *>(") + argName + QLatin1String(")))");
+ return u"reinterpret_cast< "_s + getFullTypeName(type)
+ + u" *>(Shiboken::Conversions::cppPointer("_s + cpythonTypeNameExt(type)
+ + u", reinterpret_cast<SbkObject *>("_s + argName + u")))"_s;
}
void ShibokenGenerator::writeToPythonConversion(TextStream & s, const AbstractMetaType &type,
- const AbstractMetaClass * /* context */,
+ const AbstractMetaClassCPtr & /* context */,
const QString &argumentName)
{
s << cpythonToPythonConversionFunction(type) << argumentName << ')';
}
-void ShibokenGenerator::writeToCppConversion(TextStream &s, const AbstractMetaClass *metaClass,
+void ShibokenGenerator::writeToCppConversion(TextStream &s,
+ const AbstractMetaClassCPtr &metaClass,
const QString &inArgName, const QString &outArgName)
{
s << cpythonToCppConversionFunction(metaClass) << inArgName << ", &" << outArgName << ')';
}
void ShibokenGenerator::writeToCppConversion(TextStream &s, const AbstractMetaType &type,
- const AbstractMetaClass *context, const QString &inArgName,
+ const QString &inArgName,
const QString &outArgName)
{
- s << cpythonToCppConversionFunction(type, context) << inArgName << ", &" << outArgName << ')';
+ s << cpythonToCppConversionFunction(type) << inArgName << ", &" << outArgName << ')';
}
-bool ShibokenGenerator::shouldRejectNullPointerArgument(const ApiExtractorResult &api,
- const AbstractMetaFunctionCPtr &func, int argIndex)
+bool ShibokenGenerator::shouldRejectNullPointerArgument(const AbstractMetaFunctionCPtr &func,
+ int argIndex)
{
- if (argIndex < 0 || argIndex >= func->arguments().count())
+ if (argIndex < 0 || argIndex >= func->arguments().size())
return false;
const AbstractMetaArgument &arg = func->arguments().at(argIndex);
- if (isValueTypeWithCopyConstructorOnly(api, arg.type()))
+ if (arg.type().isValueTypeWithCopyConstructorOnly())
return true;
// Argument type is not a pointer, a None rejection should not be
// necessary because the type checking would handle that already.
if (!arg.type().isPointer())
return false;
- if (func->argumentRemoved(argIndex + 1))
+ if (arg.isModifiedRemoved())
return false;
for (const auto &funcMod : func->modifications()) {
for (const ArgumentModification &argMod : funcMod.argument_mods()) {
@@ -633,192 +604,152 @@ bool ShibokenGenerator::shouldRejectNullPointerArgument(const ApiExtractorResult
return false;
}
-QString ShibokenGenerator::getFormatUnitString(const AbstractMetaFunctionCPtr &func, bool incRef)
-{
- 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;
-
- const auto &type = arg.type();
- if (!func->typeReplaced(arg.argumentIndex() + 1).isEmpty()) {
- result += QLatin1Char(objType);
- } else if (arg.type().isObject()
- || type.isValue()
- || type.isValuePointer()
- || type.isNativePointer()
- || type.isEnum()
- || type.isFlags()
- || type.isContainer()
- || type.isSmartPointer()
- || type.referenceType() == LValueReference) {
- result += QLatin1Char(objType);
- } else if (type.isPrimitive()) {
- const auto *ptype =
- static_cast<const PrimitiveTypeEntry *>(type.typeEntry());
- if (ptype->basicReferencedTypeEntry())
- ptype = ptype->basicReferencedTypeEntry();
- const auto it = formatUnits().constFind(ptype->name());
- if (it != formatUnits().cend())
- result += it.value();
- else
- result += QLatin1Char(objType);
- } else if (type.isCString()) {
- 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 (type.isCString())
- return QLatin1String("PyString");
+ return u"PyString"_s;
return cpythonBaseName(type.typeEntry());
}
-QString ShibokenGenerator::cpythonBaseName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonBaseName(const AbstractMetaClassCPtr &metaClass)
{
return cpythonBaseName(metaClass->typeEntry());
}
-QString ShibokenGenerator::cpythonBaseName(const TypeEntry *type)
+QString ShibokenGenerator::containerCpythonBaseName(const ContainerTypeEntryCPtr &ctype)
+{
+ switch (ctype->containerKind()) {
+ case ContainerTypeEntry::SetContainer:
+ return u"PySet"_s;
+ case ContainerTypeEntry::MapContainer:
+ case ContainerTypeEntry::MultiMapContainer:
+ return u"PyDict"_s;
+ case ContainerTypeEntry::ListContainer:
+ case ContainerTypeEntry::PairContainer:
+ case ContainerTypeEntry::SpanContainer:
+ break;
+ default:
+ Q_ASSERT(false);
+ }
+ return cPySequenceT;
+}
+
+QString ShibokenGenerator::cpythonBaseName(const TypeEntryCPtr &type)
{
QString baseName;
if (type->isWrapperType() || type->isNamespace()) { // && type->referenceType() == NoReference) {
- baseName = QLatin1String("Sbk_") + type->name();
+ baseName = u"Sbk_"_s + 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();
+ const auto ptype = basicReferencedTypeEntry(type);
+ baseName = ptype->hasTargetLangApiType()
+ ? ptype->targetLangApiName() : pythonPrimitiveTypeName(ptype->name());
} else if (type->isEnum()) {
- baseName = cpythonEnumName(static_cast<const EnumTypeEntry *>(type));
+ baseName = cpythonEnumName(std::static_pointer_cast<const EnumTypeEntry>(type));
} else if (type->isFlags()) {
- baseName = cpythonFlagsName(static_cast<const FlagsTypeEntry *>(type));
+ baseName = cpythonFlagsName(std::static_pointer_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 = cPySequenceT();
- 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);
- }
+ const auto ctype = std::static_pointer_cast<const ContainerTypeEntry>(type);
+ baseName = containerCpythonBaseName(ctype);
} else {
- baseName = cPyObjectT();
+ baseName = cPyObjectT;
}
- return baseName.replace(QLatin1String("::"), QLatin1String("_"));
+ return baseName.replace(u"::"_s, u"_"_s);
}
-QString ShibokenGenerator::cpythonTypeName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonTypeName(const AbstractMetaClassCPtr &metaClass)
{
return cpythonTypeName(metaClass->typeEntry());
}
-QString ShibokenGenerator::cpythonTypeName(const TypeEntry *type)
+QString ShibokenGenerator::cpythonTypeName(const TypeEntryCPtr &type)
{
- return cpythonBaseName(type) + QLatin1String("_TypeF()");
-}
-
-QString ShibokenGenerator::cpythonTypeNameExt(const TypeEntry *type)
-{
- return cppApiVariableName(type->targetLangPackage()) + QLatin1Char('[')
- + getTypeIndexVariableName(type) + QLatin1Char(']');
+ return cpythonBaseName(type) + u"_TypeF()"_s;
}
QString ShibokenGenerator::converterObject(const AbstractMetaType &type)
{
if (type.isCString())
- return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter<const char *>()");
+ return u"Shiboken::Conversions::PrimitiveTypeConverter<const char *>()"_s;
if (type.isVoidPointer())
- return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter<void *>()");
+ return u"Shiboken::Conversions::PrimitiveTypeConverter<void *>()"_s;
const AbstractMetaTypeList nestedArrayTypes = type.nestedArrayTypes();
if (!nestedArrayTypes.isEmpty() && nestedArrayTypes.constLast().isCppPrimitive()) {
- return QStringLiteral("Shiboken::Conversions::ArrayTypeConverter<")
+ return "Shiboken::Conversions::ArrayTypeConverter<"_L1
+ nestedArrayTypes.constLast().minimalSignature()
- + QLatin1String(">(") + QString::number(nestedArrayTypes.size())
- + QLatin1Char(')');
+ + u">("_s + QString::number(nestedArrayTypes.size())
+ + u')';
}
auto typeEntry = type.typeEntry();
if (typeEntry->isContainer() || typeEntry->isSmartPointer()) {
return convertersVariableName(typeEntry->targetLangPackage())
- + QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']');
+ + u'[' + getTypeIndexVariableName(type) + u']';
}
return converterObject(typeEntry);
}
-QString ShibokenGenerator::converterObject(const TypeEntry *type)
+QString ShibokenGenerator::converterObject(const TypeEntryCPtr &type)
{
- if (type->isExtendedCppPrimitive())
- return QString::fromLatin1("Shiboken::Conversions::PrimitiveTypeConverter<%1>()").arg(type->qualifiedCppName());
- if (type->isWrapperType() || type->isEnum() || type->isFlags())
- return QString::fromLatin1("*PepType_SGTP(%1)->converter").arg(cpythonTypeNameExt(type));
+ if (isExtendedCppPrimitive(type))
+ return QString::fromLatin1("Shiboken::Conversions::PrimitiveTypeConverter<%1>()")
+ .arg(type->qualifiedCppName());
+ if (type->isWrapperType())
+ return QString::fromLatin1("PepType_SOTP(reinterpret_cast<PyTypeObject *>(%1))->converter")
+ .arg(cpythonTypeNameExt(type));
+ if (type->isEnum() || type->isFlags())
+ return QString::fromLatin1("PepType_SETP(reinterpret_cast<SbkEnumType *>(%1))->converter")
+ .arg(cpythonTypeNameExt(type));
if (type->isArray()) {
qDebug() << "Warning: no idea how to handle the Qt5 type " << type->qualifiedCppName();
- return QString();
+ return {};
}
/* the typedef'd primitive types case */
- const auto *pte = dynamic_cast<const PrimitiveTypeEntry *>(type);
+ auto pte = std::dynamic_pointer_cast<const PrimitiveTypeEntry>(type);
if (!pte) {
qDebug() << "Warning: the Qt5 primitive type is unknown" << type->qualifiedCppName();
- return QString();
+ return {};
+ }
+ pte = basicReferencedTypeEntry(pte);
+ if (pte->isPrimitive() && !isCppPrimitive(pte) && !pte->customConversion()) {
+ return u"Shiboken::Conversions::PrimitiveTypeConverter<"_s
+ + pte->qualifiedCppName() + u">()"_s;
}
- 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(']');
+ + u'[' + getTypeIndexVariableName(type) + u']';
}
-QString ShibokenGenerator::cpythonTypeNameExt(const AbstractMetaType &type)
+QString ShibokenGenerator::cpythonTypeNameExtSet(const TypeEntryCPtr &type)
+{
+ return cppApiVariableName(type->targetLangPackage()) + u'['
+ + getTypeIndexVariableName(type) + "].type"_L1;
+}
+
+QString ShibokenGenerator::cpythonTypeNameExtSet(const AbstractMetaType &type)
+{
+ return cppApiVariableName(type.typeEntry()->targetLangPackage()) + u'['
+ + getTypeIndexVariableName(type) + "].type"_L1;
+}
+
+QString ShibokenGenerator::cpythonTypeNameExt(const TypeEntryCPtr &type)
{
- return cppApiVariableName(type.typeEntry()->targetLangPackage()) + QLatin1Char('[')
- + getTypeIndexVariableName(type) + QLatin1Char(']');
+ return "Shiboken::Module::get("_L1 + cppApiVariableName(type->targetLangPackage())
+ + u'[' + getTypeIndexVariableName(type) + "])"_L1;
}
-static inline QString unknownOperator() { return QStringLiteral("__UNKNOWN_OPERATOR__"); }
+QString ShibokenGenerator::cpythonTypeNameExt(const AbstractMetaType &type)
+{
+ return u"Shiboken::Module::get("_s + cppApiVariableName(type.typeEntry()->targetLangPackage())
+ + u'[' + getTypeIndexVariableName(type) + "])"_L1;
+}
-QString ShibokenGenerator::fixedCppTypeName(const CustomConversion::TargetToNativeConversion *toNative)
+QString ShibokenGenerator::fixedCppTypeName(const TargetToNativeConversion &toNative)
{
- if (toNative->sourceType())
- return fixedCppTypeName(toNative->sourceType());
- return toNative->sourceTypeName();
+ if (toNative.sourceType())
+ return fixedCppTypeName(toNative.sourceType());
+ return toNative.sourceTypeName();
}
QString ShibokenGenerator::fixedCppTypeName(const AbstractMetaType &type)
{
@@ -827,22 +758,22 @@ QString ShibokenGenerator::fixedCppTypeName(const AbstractMetaType &type)
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"));
+ typeName.remove(u' ');
+ typeName.replace(u'.', u'_');
+ typeName.replace(u',', u'_');
+ typeName.replace(u'<', u'_');
+ typeName.replace(u'>', u'_');
+ typeName.replace(u"::"_s, u"_"_s);
+ typeName.replace(u"*"_s, u"PTR"_s);
+ typeName.replace(u"&"_s, u"REF"_s);
return typeName;
}
-QString ShibokenGenerator::fixedCppTypeName(const TypeEntry *type, QString typeName)
+QString ShibokenGenerator::fixedCppTypeName(const TypeEntryCPtr &type, QString typeName)
{
if (typeName.isEmpty())
typeName = type->qualifiedCppName();
if (!type->generateCode()) {
- typeName.prepend(QLatin1Char('_'));
+ typeName.prepend(u'_');
typeName.prepend(type->targetLangPackage());
}
return _fixedCppTypeName(typeName);
@@ -850,120 +781,66 @@ QString ShibokenGenerator::fixedCppTypeName(const TypeEntry *type, QString typeN
QString ShibokenGenerator::pythonPrimitiveTypeName(const QString &cppTypeName)
{
- QString rv = primitiveTypesCorrespondences().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());
-}
-
-static const QHash<QString, QString> &pythonOperators()
-{
- static const QHash<QString, QString> result = {
- // call operator
- {QLatin1String("operator()"), QLatin1String("call")},
- // Arithmetic operators
- {QLatin1String("operator+"), QLatin1String("add")},
- {QLatin1String("operator-"), QLatin1String("sub")},
- {QLatin1String("operator*"), QLatin1String("mul")},
- {QLatin1String("operator/"), QLatin1String("div")},
- {QLatin1String("operator%"), QLatin1String("mod")},
- // Inplace arithmetic operators
- {QLatin1String("operator+="), QLatin1String("iadd")},
- {QLatin1String("operator-="), QLatin1String("isub")},
- {QLatin1String("operator++"), QLatin1String("iadd")},
- {QLatin1String("operator--"), QLatin1String("isub")},
- {QLatin1String("operator*="), QLatin1String("imul")},
- {QLatin1String("operator/="), QLatin1String("idiv")},
- {QLatin1String("operator%="), QLatin1String("imod")},
- // Bitwise operators
- {QLatin1String("operator&"), QLatin1String("and")},
- {QLatin1String("operator^"), QLatin1String("xor")},
- {QLatin1String("operator|"), QLatin1String("or")},
- {QLatin1String("operator<<"), QLatin1String("lshift")},
- {QLatin1String("operator>>"), QLatin1String("rshift")},
- {QLatin1String("operator~"), QLatin1String("invert")},
- // Inplace bitwise operators
- {QLatin1String("operator&="), QLatin1String("iand")},
- {QLatin1String("operator^="), QLatin1String("ixor")},
- {QLatin1String("operator|="), QLatin1String("ior")},
- {QLatin1String("operator<<="), QLatin1String("ilshift")},
- {QLatin1String("operator>>="), QLatin1String("irshift")},
- // Comparison operators
- {QLatin1String("operator=="), QLatin1String("eq")},
- {QLatin1String("operator!="), QLatin1String("ne")},
- {QLatin1String("operator<"), QLatin1String("lt")},
- {QLatin1String("operator>"), QLatin1String("gt")},
- {QLatin1String("operator<="), QLatin1String("le")},
- {QLatin1String("operator>="), QLatin1String("ge")},
- };
- return result;
-}
-
-QString ShibokenGenerator::pythonOperatorFunctionName(const QString &cppOpFuncName)
-{
- QString value = pythonOperators().value(cppOpFuncName);
- if (value.isEmpty())
- return unknownOperator();
- value.prepend(QLatin1String("__"));
- value.append(QLatin1String("__"));
- return value;
+ const auto &mapping = primitiveTypesCorrespondences();
+ const auto it = mapping.constFind(cppTypeName);
+ if (it == mapping.cend())
+ throw Exception(u"Primitive type not found: "_s + cppTypeName);
+ return it.value();
}
QString ShibokenGenerator::pythonOperatorFunctionName(const AbstractMetaFunctionCPtr &func)
{
- QString op = pythonOperatorFunctionName(func->originalName());
- if (op == unknownOperator())
- qCWarning(lcShiboken).noquote().nospace() << msgUnknownOperator(func.data());
+ QString op = Generator::pythonOperatorFunctionName(func->originalName());
+ if (op.isEmpty()) {
+ qCWarning(lcShiboken).noquote().nospace() << msgUnknownOperator(func.get());
+ return "__UNKNOWN_OPERATOR__"_L1;
+ }
if (func->arguments().isEmpty()) {
- if (op == QLatin1String("__sub__"))
- op = QLatin1String("__neg__");
- else if (op == QLatin1String("__add__"))
- op = QLatin1String("__pos__");
+ if (op == u"__sub__")
+ op = u"__neg__"_s;
+ else if (op == u"__add__")
+ op = u"__pos__"_s;
} 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'));
+ op = op.insert(2, u'r');
}
return op;
}
-QString ShibokenGenerator::pythonRichCompareOperatorId(const QString &cppOpFuncName)
-{
- return QLatin1String("Py_") + pythonOperators().value(cppOpFuncName).toUpper();
-}
-
-QString ShibokenGenerator::pythonRichCompareOperatorId(const AbstractMetaFunctionCPtr &func)
+bool ShibokenGenerator::isNumber(const QString &cpythonApiName)
{
- return pythonRichCompareOperatorId(func->originalName());
+ return cpythonApiName == pyFloatT || cpythonApiName == pyLongT
+ || cpythonApiName == pyBoolT;
}
-bool ShibokenGenerator::isNumber(const QString &cpythonApiName)
+static std::optional<TypeSystem::CPythonType>
+ targetLangApiCPythonType(const PrimitiveTypeEntryCPtr &t)
{
- return cpythonApiName == pyIntT()
- || cpythonApiName == pyFloatT() || cpythonApiName == pyLongT()
- || cpythonApiName == pyBoolT();
+ if (!t->hasTargetLangApiType())
+ return {};
+ const auto cte = t->targetLangApiType();
+ if (cte->type() != TypeEntry::PythonType)
+ return {};
+ return std::static_pointer_cast<const PythonTypeEntry>(cte)->cPythonType();
}
-bool ShibokenGenerator::isNumber(const TypeEntry *type)
+bool ShibokenGenerator::isNumber(const TypeEntryCPtr &type)
{
if (!type->isPrimitive())
return false;
- return isNumber(pythonPrimitiveTypeName(static_cast<const PrimitiveTypeEntry *>(type)));
+ const auto pte = basicReferencedTypeEntry(type);
+ const auto cPythonTypeOpt = targetLangApiCPythonType(pte);
+ // FIXME PYSIDE-1660: Return false here after making primitive types built-in?
+ if (!cPythonTypeOpt.has_value()) {
+ const auto &mapping = primitiveTypesCorrespondences();
+ const auto it = mapping.constFind(pte->name());
+ return it != mapping.cend() && isNumber(it.value());
+ }
+ const auto cPythonType = cPythonTypeOpt.value();
+ return cPythonType == TypeSystem::CPythonType::Bool
+ || cPythonType == TypeSystem::CPythonType::Float
+ || cPythonType == TypeSystem::CPythonType::Integer;
}
bool ShibokenGenerator::isNumber(const AbstractMetaType &type)
@@ -971,12 +848,19 @@ bool ShibokenGenerator::isNumber(const AbstractMetaType &type)
return isNumber(type.typeEntry());
}
-bool ShibokenGenerator::isPyInt(const TypeEntry *type)
+bool ShibokenGenerator::isPyInt(const TypeEntryCPtr &type)
{
if (!type->isPrimitive())
return false;
- return pythonPrimitiveTypeName(static_cast<const PrimitiveTypeEntry *>(type))
- == QLatin1String("PyInt");
+ const auto pte = basicReferencedTypeEntry(type);
+ const auto cPythonTypeOpt = targetLangApiCPythonType(pte);
+ // FIXME PYSIDE-1660: Return false here after making primitive types built-in?
+ if (!cPythonTypeOpt.has_value()) {
+ const auto &mapping = primitiveTypesCorrespondences();
+ const auto it = mapping.constFind(pte->name());
+ return it != mapping.cend() && it.value() == pyLongT;
+ }
+ return cPythonTypeOpt.value() == TypeSystem::CPythonType::Integer;
}
bool ShibokenGenerator::isPyInt(const AbstractMetaType &type)
@@ -984,305 +868,267 @@ bool ShibokenGenerator::isPyInt(const AbstractMetaType &type)
return isPyInt(type.typeEntry());
}
-bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const ApiExtractorResult &api,
- const TypeEntry *type)
-{
- if (!type || !type->isValue())
- return false;
- auto klass = AbstractMetaClass::findClass(api.classes(), type);
- return klass != nullptr && klass->isValueTypeWithCopyConstructorOnly();
-}
-
-bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const ApiExtractorResult &api,
- const AbstractMetaType &type)
-{
- return type.typeEntry()->isValue()
- && isValueTypeWithCopyConstructorOnly(api, type.typeEntry());
-}
-
-bool ShibokenGenerator::valueTypeWithCopyConstructorOnlyPassed(const ApiExtractorResult &api,
- const AbstractMetaType &type)
-{
- return (type.passByValue() || type.passByConstRef())
- && isValueTypeWithCopyConstructorOnly(api, type);
-}
-
bool ShibokenGenerator::isNullPtr(const QString &value)
{
- return value == QLatin1String("0") || value == QLatin1String("nullptr")
- || value == QLatin1String("NULLPTR") || value == QLatin1String("{}");
+ return value == u"0" || value == u"nullptr"
+ || value == u"NULLPTR" || value == u"{}";
}
-QString ShibokenGenerator::cpythonCheckFunction(AbstractMetaType metaType,
- bool genericNumberType) const
+QString ShibokenGenerator::cpythonCheckFunction(AbstractMetaType metaType)
{
- if (metaType.typeEntry()->isCustom()) {
- auto customCheckResult = guessCPythonCheckFunction(metaType.typeEntry()->name());
- if (!customCheckResult.checkFunction.isEmpty())
- return customCheckResult.checkFunction;
- if (customCheckResult.type.has_value())
- metaType = customCheckResult.type.value();
+ const auto typeEntry = metaType.typeEntry();
+ if (typeEntry->isCustom()) {
+ const auto cte = std::static_pointer_cast<const CustomTypeEntry>(typeEntry);
+ if (cte->hasCheckFunction())
+ return cte->checkFunction();
+ throw Exception(msgUnknownCheckFunction(typeEntry));
}
if (metaType.isExtendedCppPrimitive()) {
if (metaType.isCString())
- return QLatin1String("Shiboken::String::check");
+ return u"Shiboken::String::check"_s;
if (metaType.isVoidPointer())
- return QLatin1String("PyObject_Check");
- return cpythonCheckFunction(metaType.typeEntry(), genericNumberType);
+ return u"true"_s;
+ return cpythonCheckFunction(typeEntry);
}
- auto typeEntry = metaType.typeEntry();
+
if (typeEntry->isContainer()) {
- QString typeCheck = QLatin1String("Shiboken::Conversions::");
+ QString typeCheck = u"Shiboken::Conversions::"_s;
ContainerTypeEntry::ContainerKind type =
- static_cast<const ContainerTypeEntry *>(typeEntry)->containerKind();
+ std::static_pointer_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) {
+ || type == ContainerTypeEntry::SetContainer) {
+ const QString containerType = type == ContainerTypeEntry::SetContainer
+ ? u"Iterable"_s : u"Sequence"_s;
const AbstractMetaType &type = metaType.instantiations().constFirst();
if (type.isPointerToWrapperType()) {
- typeCheck += QString::fromLatin1("checkSequenceTypes(%1, ").arg(cpythonTypeNameExt(type));
+ typeCheck += u"check"_s + containerType + u"Types("_s
+ + cpythonTypeNameExt(type) + u", "_s;
} else if (type.isWrapperType()) {
- typeCheck += QLatin1String("convertibleSequenceTypes(reinterpret_cast<SbkObjectType *>(");
- typeCheck += cpythonTypeNameExt(type);
- typeCheck += QLatin1String("), ");
+ typeCheck += u"convertible"_s + containerType
+ + u"Types("_s + cpythonTypeNameExt(type) + u", "_s;
} else {
- typeCheck += QString::fromLatin1("convertibleSequenceTypes(%1, ").arg(converterObject(type));
+ typeCheck += u"convertible"_s + containerType
+ + u"Types("_s + converterObject(type) + u", "_s;
}
} 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");
+
+ QString pyType;
+ if (type == ContainerTypeEntry::PairContainer)
+ pyType = u"Pair"_s;
+ else if (type == ContainerTypeEntry::MultiMapContainer)
+ pyType = u"MultiDict"_s;
+ else
+ pyType = u"Dict"_s;
+
const AbstractMetaType &firstType = metaType.instantiations().constFirst();
const AbstractMetaType &secondType = metaType.instantiations().constLast();
if (firstType.isPointerToWrapperType() && secondType.isPointerToWrapperType()) {
- typeCheck += QString::fromLatin1("check%1Types(%2, %3, ")
- .arg(pyType, cpythonTypeNameExt(firstType), cpythonTypeNameExt(secondType));
+ QTextStream(&typeCheck) << "check" << pyType << "Types("
+ << cpythonTypeNameExt(firstType) << ", "
+ << cpythonTypeNameExt(secondType) << ", ";
} else {
- typeCheck += QString::fromLatin1("convertible%1Types(%2, %3, %4, %5, ")
- .arg(pyType, converterObject(firstType),
- firstType.isPointerToWrapperType() ? QLatin1String("true") : QLatin1String("false"),
- converterObject(secondType),
- secondType.isPointerToWrapperType() ? QLatin1String("true") : QLatin1String("false"));
+ QTextStream(&typeCheck) << "convertible" << pyType << "Types("
+ << converterObject(firstType) << ", "
+ << (firstType.isPointerToWrapperType() ? "true" : "false")
+ << ", " << converterObject(secondType) << ", "
+ << (secondType.isPointerToWrapperType() ? "true" :"false")
+ << ", ";
}
}
return typeCheck;
}
- return cpythonCheckFunction(typeEntry, genericNumberType);
+ return cpythonCheckFunction(typeEntry);
}
-QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry *type, bool genericNumberType) const
+QString ShibokenGenerator::cpythonCheckFunction(TypeEntryCPtr type)
{
if (type->isCustom()) {
- AbstractMetaType metaType;
- auto customCheckResult = guessCPythonCheckFunction(type->name());
- if (customCheckResult.type.has_value())
- return cpythonCheckFunction(customCheckResult.type.value(), genericNumberType);
- return customCheckResult.checkFunction;
+ const auto cte = std::static_pointer_cast<const CustomTypeEntry>(type);
+ if (cte->hasCheckFunction())
+ return cte->checkFunction();
+ throw Exception(msgUnknownCheckFunction(type));
}
if (type->isEnum() || type->isFlags() || type->isWrapperType())
- return QString::fromLatin1("SbkObject_TypeCheck(%1, ").arg(cpythonTypeNameExt(type));
- if (type->isExtendedCppPrimitive()) {
- return pythonPrimitiveTypeName(static_cast<const PrimitiveTypeEntry *>(type))
- + QLatin1String("_Check");
- }
- QString typeCheck;
- if (type->targetLangApiName() == type->name())
- typeCheck = cpythonIsConvertibleFunction(api(), type);
- else if (type->targetLangApiName() == QLatin1String("PyUnicode"))
- typeCheck = QLatin1String("Shiboken::String::check");
- else
- typeCheck = type->targetLangApiName() + QLatin1String("_Check");
- return typeCheck;
-}
-
-ShibokenGenerator::CPythonCheckFunctionResult
- ShibokenGenerator::guessCPythonCheckFunction(const QString &type)
-{
- // PYSIDE-795: We abuse PySequence for iterables.
- // This part handles the overrides in the XML files.
- if (type == cPySequenceT())
- return {QLatin1String("Shiboken::String::checkIterable"), {}};
+ return u"SbkObject_TypeCheck("_s + cpythonTypeNameExt(type) + u", "_s;
- if (type == cPyTypeObjectT())
- return {QLatin1String("PyType_Check"), {}};
+ if (type->isPrimitive())
+ type = basicReferencedTypeEntry(type);
- if (type == cPyBufferT())
- return {QLatin1String("Shiboken::Buffer::checkType"), {}};
+ if (auto tla = type->targetLangApiType()) {
+ if (tla->hasCheckFunction())
+ return tla->checkFunction();
+ }
- if (type == pyStrT())
- return {QLatin1String("Shiboken::String::check"), {}};
+ if (isExtendedCppPrimitive(type))
+ return pythonPrimitiveTypeName(type->name()) + u"_Check"_s;
- CPythonCheckFunctionResult result;
- result.type = buildAbstractMetaTypeFromString(type);
- if (!result.type.has_value() || result.type->typeEntry()->isCustom())
- result.checkFunction = type + QLatin1String("_Check");
- return result;
+ return cpythonIsConvertibleFunction(type);
}
-QString ShibokenGenerator::cpythonIsConvertibleFunction(const ApiExtractorResult &api, const TypeEntry *type,
- bool /* genericNumberType */,
- bool /* checkExact */)
+QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntryCPtr &type)
{
if (type->isWrapperType()) {
- QString result = QLatin1String("Shiboken::Conversions::");
- result += (type->isValue() && !isValueTypeWithCopyConstructorOnly(api, type))
- ? QLatin1String("isPythonToCppValueConvertible")
- : QLatin1String("isPythonToCppPointerConvertible");
- result += QLatin1String("(reinterpret_cast<SbkObjectType *>(")
- + cpythonTypeNameExt(type) + QLatin1String("), ");
+ QString result = u"Shiboken::Conversions::"_s;
+ bool isValue = false;
+ if (type->isValue()) {
+ const auto cte = std::static_pointer_cast<const ComplexTypeEntry>(type);
+ isValue = !cte->isValueTypeWithCopyConstructorOnly();
+ }
+ result += isValue ? u"isPythonToCppValueConvertible"_s
+ : u"isPythonToCppPointerConvertible"_s;
+ result += u"("_s + cpythonTypeNameExt(type) + u", "_s;
return result;
}
return QString::fromLatin1("Shiboken::Conversions::isPythonToCppConvertible(%1, ")
.arg(converterObject(type));
}
-QString ShibokenGenerator::cpythonIsConvertibleFunction(AbstractMetaType metaType,
- bool /* genericNumberType */) const
+
+QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType &metaType)
{
- if (metaType.typeEntry()->isCustom()) {
- auto customCheckResult = guessCPythonCheckFunction(metaType.typeEntry()->name());
- if (!customCheckResult.checkFunction.isEmpty())
- return customCheckResult.checkFunction;
- if (customCheckResult.type.has_value())
- metaType = customCheckResult.type.value();
+ const auto typeEntry = metaType.typeEntry();
+ if (typeEntry->isCustom()) {
+ const auto cte = std::static_pointer_cast<const CustomTypeEntry>(typeEntry);
+ if (cte->hasCheckFunction())
+ return cte->checkFunction();
+ throw Exception(msgUnknownCheckFunction(typeEntry));
}
- QString result = QLatin1String("Shiboken::Conversions::");
+ QString result = u"Shiboken::Conversions::"_s;
+ if (metaType.generateOpaqueContainer()) {
+ result += u"pythonToCppReferenceConversion("_s
+ + converterObject(metaType) + u", "_s;
+ return result;
+ }
if (metaType.isWrapperType()) {
- if (metaType.isPointer() || isValueTypeWithCopyConstructorOnly(api(), metaType))
- result += QLatin1String("isPythonToCppPointerConvertible");
- else if (metaType.referenceType() == LValueReference)
- result += QLatin1String("isPythonToCppReferenceConvertible");
- else
- result += QLatin1String("isPythonToCppValueConvertible");
- result += QLatin1String("(reinterpret_cast<SbkObjectType *>(")
- + cpythonTypeNameExt(metaType) + QLatin1String("), ");
+ if (metaType.isPointer() || metaType.isValueTypeWithCopyConstructorOnly()) {
+ result += u"pythonToCppPointerConversion"_s;
+ } else if (metaType.referenceType() == LValueReference
+ || (metaType.referenceType() == RValueReference && typeEntry->isObject())) {
+ result += u"pythonToCppReferenceConversion"_s;
+ } else {
+ result += u"pythonToCppValueConversion"_s;
+ }
+ result += u'(' + cpythonTypeNameExt(metaType) + u", "_s;
return result;
}
- result += QLatin1String("isPythonToCppConvertible(") + converterObject(metaType);
+ result += u"pythonToCppConversion("_s + converterObject(metaType);
// Write out array sizes if known
const AbstractMetaTypeList 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 += u", "_s + QString::number(dim1)
+ + u", "_s + QString::number(dim2);
}
- result += QLatin1String(", ");
+ result += u", "_s;
return result;
}
-QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaArgument &metaArg,
- bool genericNumberType) const
+QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaArgument &metaArg)
{
- return cpythonIsConvertibleFunction(metaArg.type(), genericNumberType);
+ return cpythonIsConvertibleFunction(metaArg.type());
}
-QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaClassCPtr &metaClass)
{
- return QLatin1String("Shiboken::Conversions::pythonToCppPointer(reinterpret_cast<SbkObjectType *>(")
- + cpythonTypeNameExt(metaClass->typeEntry()) + QLatin1String("), ");
+ return u"Shiboken::Conversions::pythonToCppPointer("_s
+ + cpythonTypeNameExt(metaClass->typeEntry()) + u", "_s;
}
-QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaType &type,
- const AbstractMetaClass * /* context */)
+QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaType &type)
{
if (type.isWrapperType()) {
- return QLatin1String("Shiboken::Conversions::pythonToCpp")
- + (type.isPointer() ? QLatin1String("Pointer") : QLatin1String("Copy"))
- + QLatin1String("(reinterpret_cast<SbkObjectType *>(")
- + cpythonTypeNameExt(type) + QLatin1String("), ");
+ return u"Shiboken::Conversions::pythonToCpp"_s
+ + (type.isPointer() ? u"Pointer"_s : u"Copy"_s)
+ + u'(' + cpythonTypeNameExt(type) + u", "_s;
}
- return QStringLiteral("Shiboken::Conversions::pythonToCppCopy(%1, ")
- .arg(converterObject(type));
+ return "Shiboken::Conversions::pythonToCppCopy("_L1
+ + converterObject(type) + ", "_L1;
}
-QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaType &type,
- const AbstractMetaClass * /* context */)
+QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaType &type)
{
if (type.isWrapperType()) {
QString conversion;
if (type.referenceType() == LValueReference
&& !(type.isValue() && type.isConstant()) && !type.isPointer()) {
- conversion = QLatin1String("reference");
+ conversion = u"reference"_s;
} else if (type.isValue() || type.isSmartPointer()) {
- conversion = QLatin1String("copy");
+ conversion = u"copy"_s;
} else {
- conversion = QLatin1String("pointer");
+ conversion = u"pointer"_s;
}
- QString result = QLatin1String("Shiboken::Conversions::") + conversion
- + QLatin1String("ToPython(reinterpret_cast<SbkObjectType *>(")
- + cpythonTypeNameExt(type) + QLatin1String("), ");
- if (conversion != QLatin1String("pointer"))
- result += QLatin1Char('&');
+ QString result = u"Shiboken::Conversions::"_s + conversion
+ + u"ToPython("_s
+ + cpythonTypeNameExt(type) + u", "_s;
+ if (conversion != u"pointer")
+ result += u'&';
return result;
}
- return QStringLiteral("Shiboken::Conversions::copyToPython(%1, %2")
- .arg(converterObject(type),
- (type.isCString() || type.isVoidPointer()) ? QString() : QLatin1String("&"));
+
+ const auto indirections = type.indirections() - 1;
+ return u"Shiboken::Conversions::copyToPython("_s + converterObject(type)
+ + u", "_s + AbstractMetaType::dereferencePrefix(indirections);
}
-QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaClassCPtr &metaClass)
{
return cpythonToPythonConversionFunction(metaClass->typeEntry());
}
-QString ShibokenGenerator::cpythonToPythonConversionFunction(const TypeEntry *type)
+QString ShibokenGenerator::cpythonToPythonConversionFunction(const TypeEntryCPtr &type)
{
if (type->isWrapperType()) {
- 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('&');
+ const QString conversion = type->isValue() ? u"copy"_s : u"pointer"_s;
+ QString result = u"Shiboken::Conversions::"_s + conversion
+ + u"ToPython("_s + cpythonTypeNameExt(type)
+ + u", "_s;
+ if (conversion != u"pointer")
+ result += u'&';
return result;
}
- return QStringLiteral("Shiboken::Conversions::copyToPython(%1, &").arg(converterObject(type));
+ return u"Shiboken::Conversions::copyToPython("_s
+ + converterObject(type) + u", &"_s;
}
QString ShibokenGenerator::argumentString(const AbstractMetaFunctionCPtr &func,
const AbstractMetaArgument &argument,
Options options) const
{
- QString modified_type;
- if (!(options & OriginalTypeDescription))
- modified_type = func->typeReplaced(argument.argumentIndex() + 1);
- QString arg;
+ auto type = options.testFlag(OriginalTypeDescription)
+ ? argument.type() : argument.modifiedType();
- if (modified_type.isEmpty())
- arg = translateType(argument.type(), func->implementingClass(), options);
- else
- arg = modified_type.replace(QLatin1Char('$'), QLatin1Char('.'));
+
+ QString arg = translateType(type, func->implementingClass(), options);
+
+ if (argument.isTypeModified())
+ arg.replace(u'$', u'.'); // Haehh?
// "int a", "int a[]"
- const int arrayPos = arg.indexOf(QLatin1Char('['));
+ const auto arrayPos = arg.indexOf(u'[');
if (arrayPos != -1)
- arg.insert(arrayPos, QLatin1Char(' ') + argument.name());
+ arg.insert(arrayPos, u' ' + argument.name());
else
- arg.append(QLatin1Char(' ') + argument.name());
+ arg.append(u' ' + 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);
+ if (default_value == u"NULL")
+ default_value = NULL_PTR;
//WORKAROUND: fix this please
- if (default_value.startsWith(QLatin1String("new ")))
+ if (default_value.startsWith(u"new "))
default_value.remove(0, 4);
- arg += QLatin1String(" = ") + default_value;
+ arg += u" = "_s + default_value;
}
return arg;
@@ -1300,21 +1146,23 @@ void ShibokenGenerator::writeFunctionArguments(TextStream &s,
const AbstractMetaFunctionCPtr &func,
Options options) const
{
- AbstractMetaArgumentList arguments = func->arguments();
-
int argUsed = 0;
- for (int i = 0; i < arguments.size(); ++i) {
- if ((options & Generator::SkipRemovedArguments) && func->argumentRemoved(i+1))
+ if (func->isUserAddedPythonOverride()) {
+ s << "Shiboken::GilState &gil, PyObject *" << PYTHON_OVERRIDE_VAR;
+ argUsed += 2;
+ }
+ for (const auto &arg : func->arguments()) {
+ if (options.testFlag(Generator::SkipRemovedArguments) && arg.isModifiedRemoved())
continue;
if (argUsed != 0)
s << ", ";
- writeArgument(s, func, arguments[i], options);
+ writeArgument(s, func, arg, options);
argUsed++;
}
}
-GeneratorContext ShibokenGenerator::contextForClass(const AbstractMetaClass *c) const
+GeneratorContext ShibokenGenerator::contextForClass(const AbstractMetaClassCPtr &c) const
{
GeneratorContext result = Generator::contextForClass(c);
if (shouldGenerateCppWrapper(c)) {
@@ -1326,9 +1174,8 @@ GeneratorContext ShibokenGenerator::contextForClass(const AbstractMetaClass *c)
QString ShibokenGenerator::functionReturnType(const AbstractMetaFunctionCPtr &func, Options options) const
{
- QString modifiedReturnType = QString(func->typeReplaced(0));
- if (!modifiedReturnType.isEmpty() && !(options & OriginalTypeDescription))
- return modifiedReturnType;
+ if (func->isTypeModified() && !options.testFlag(OriginalTypeDescription))
+ return func->modifiedTypeName();
return translateType(func->type(), func->implementingClass(), options);
}
@@ -1340,6 +1187,8 @@ QString ShibokenGenerator::functionSignature(const AbstractMetaFunctionCPtr &fun
{
StringStream s(TextStream::Language::Cpp);
// The actual function
+ if (!options.testFlag(Option::SkipDefaultValues) && func->isStatic()) // Declaration
+ s << "static ";
if (func->isEmptyFunction() || func->needsReturnType())
s << functionReturnType(func, options) << ' ';
else
@@ -1371,14 +1220,18 @@ void ShibokenGenerator::writeArgumentNames(TextStream &s,
int argCount = 0;
for (const auto &argument : arguments) {
const int index = argument.argumentIndex() + 1;
- if ((options & Generator::SkipRemovedArguments) && (func->argumentRemoved(index)))
+ if (options.testFlag(Generator::SkipRemovedArguments) && argument.isModifiedRemoved())
continue;
+ const auto &type = argument.type();
+ if (argCount > 0)
+ s << ", ";
+ const bool isVirtualCall = options.testFlag(Option::VirtualCall);
+ const bool useStdMove = isVirtualCall && type.isUniquePointer() && type.passByValue();
+ s << (useStdMove ? stdMove(argument.name()) : argument.name());
- s << ((argCount > 0) ? ", " : "") << argument.name();
-
- if (((options & Generator::VirtualCall) == 0)
- && (!func->conversionRule(TypeSystem::NativeCode, index).isEmpty()
- || !func->conversionRule(TypeSystem::TargetLangCode, index).isEmpty())
+ if (!isVirtualCall
+ && (func->hasConversionRule(TypeSystem::NativeCode, index)
+ || func->hasConversionRule(TypeSystem::TargetLangCode, index))
&& !func->isConstructor()) {
s << CONV_RULE_OUT_VAR_SUFFIX;
}
@@ -1397,55 +1250,18 @@ void ShibokenGenerator::writeFunctionCall(TextStream &s,
s << ')';
}
-void ShibokenGenerator::writeUnusedVariableCast(TextStream &s, const QString &variableName)
-{
- s << "SBK_UNUSED(" << variableName<< ")\n";
-}
-
-static bool filterFunction(const AbstractMetaFunctionCPtr &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;
-}
-
-AbstractMetaFunctionCList ShibokenGenerator::filterFunctions(const AbstractMetaClass *metaClass) const
-{
- AbstractMetaFunctionCList result;
- const AbstractMetaFunctionCList &funcs = metaClass->functions();
- result.reserve(funcs.size());
- for (const auto &func : funcs) {
- if (filterFunction(func, avoidProtectedHack()))
- result.append(func);
- }
- return result;
-}
-
ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverters() const
{
ExtendedConverterData extConvs;
- for (auto metaClass : api().classes()) {
+ for (const auto &metaClass : api().classes()) {
// Use only the classes for the current module.
- if (!shouldGenerate(metaClass))
+ if (!shouldGenerate(metaClass->typeEntry()))
continue;
const auto &overloads = metaClass->operatorOverloads(OperatorQueryOption::ConversionOp);
for (const auto &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();
+ const auto convType = convOp->type().typeEntry();
if (convType->generateCode() || !convType->isValue()
|| convOp->isModifiedRemoved())
continue;
@@ -1455,15 +1271,13 @@ ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverter
return extConvs;
}
-QList<const CustomConversion *> ShibokenGenerator::getPrimitiveCustomConversions()
+QList<CustomConversionPtr> ShibokenGenerator::getPrimitiveCustomConversions()
{
- QList<const CustomConversion *> conversions;
- const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes();
- for (const PrimitiveTypeEntry *type : primitiveTypeList) {
- if (!shouldGenerateTypeEntry(type) || !type->isUserPrimitive() || !type->customConversion())
- continue;
-
- conversions << type->customConversion();
+ QList<CustomConversionPtr> conversions;
+ const auto &primitiveTypeList = primitiveTypes();
+ for (const auto &type : primitiveTypeList) {
+ if (type->shouldGenerate() && isUserPrimitive(type) && type->hasCustomConversion())
+ conversions << type->customConversion();
}
return conversions;
}
@@ -1476,20 +1290,20 @@ static QString getArgumentsFromMethodCall(const QString &str)
// 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);
+ auto pos = str.indexOf(funcCall);
if (pos == -1)
return QString();
pos = pos + funcCall.size();
- while (str.at(pos) == QLatin1Char(' ') || str.at(pos) == QLatin1Char('\t'))
+ while (str.at(pos) == u' ' || str.at(pos) == u'\t')
++pos;
- if (str.at(pos) == QLatin1Char('('))
+ if (str.at(pos) == u'(')
++pos;
int begin = pos;
int counter = 1;
while (counter != 0) {
- if (str.at(pos) == QLatin1Char('('))
+ if (str.at(pos) == u'(')
++counter;
- else if (str.at(pos) == QLatin1Char(')'))
+ else if (str.at(pos) == u')')
--counter;
++pos;
}
@@ -1514,14 +1328,13 @@ void ShibokenGenerator::processClassCodeSnip(QString &code, const GeneratorConte
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());
+ code.replace(u"%PYTHONTYPEOBJECT"_s,
+ u"(*"_s + cpythonTypeName(metaClass) + u')');
+ const QString className = context.effectiveClassName();
+ code.replace(u"%TYPE"_s, className);
+ code.replace(u"%CPPTYPE"_s, metaClass->name());
- processCodeSnip(code);
+ processCodeSnip(code, context.effectiveClassName());
}
void ShibokenGenerator::processCodeSnip(QString &code) const
@@ -1539,6 +1352,15 @@ void ShibokenGenerator::processCodeSnip(QString &code) const
replaceTypeCheckTypeSystemVariable(code);
}
+void ShibokenGenerator::processCodeSnip(QString &code, const QString &context) const
+{
+ try {
+ processCodeSnip(code);
+ } catch (const std::exception &e) {
+ throw Exception(msgSnippetError(context, e.what()));
+ }
+}
+
ShibokenGenerator::ArgumentVarReplacementList
ShibokenGenerator::getArgumentReplacement(const AbstractMetaFunctionCPtr &func,
bool usePyArgs, TypeSystem::Language language,
@@ -1548,38 +1370,30 @@ ShibokenGenerator::ArgumentVarReplacementList
TypeSystem::Language convLang = (language == TypeSystem::TargetLangCode)
? TypeSystem::NativeCode : TypeSystem::TargetLangCode;
int removed = 0;
- for (int i = 0; i < func->arguments().size(); ++i) {
+ for (qsizetype 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);
+ const bool hasConversionRule = func->hasConversionRule(convLang, i + 1);
+ const bool argRemoved = arg.isModifiedRemoved();
if (argRemoved)
++removed;
if (argRemoved && hasConversionRule)
- argValue = arg.name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX);
+ argValue = arg.name() + CONV_RULE_OUT_VAR_SUFFIX;
else if (argRemoved || (lastArg && arg.argumentIndex() > lastArg->argumentIndex()))
- argValue = QLatin1String(CPP_ARG_REMOVED) + QString::number(i);
+ argValue = CPP_ARG_REMOVED(i);
if (!argRemoved && argValue.isEmpty()) {
int argPos = i - removed;
- AbstractMetaType type = arg.type();
- QString typeReplaced = func->typeReplaced(arg.argumentIndex() + 1);
- if (!typeReplaced.isEmpty()) {
- auto builtType = buildAbstractMetaTypeFromString(typeReplaced);
- if (builtType.has_value())
- type = builtType.value();
- }
+ AbstractMetaType type = arg.modifiedType();
if (type.typeEntry()->isCustom()) {
argValue = usePyArgs
- ? pythonArgsAt(argPos) : QLatin1String(PYTHON_ARG);
+ ? pythonArgsAt(argPos) : PYTHON_ARG;
} else {
argValue = hasConversionRule
- ? arg.name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX)
- : QLatin1String(CPP_ARG) + QString::number(argPos);
- if (type.isWrapperType()) {
- if (type.referenceType() == LValueReference && !type.isPointer())
- argValue.prepend(QLatin1Char('*'));
- }
+ ? arg.name() + CONV_RULE_OUT_VAR_SUFFIX
+ : CPP_ARG_N(argPos);
+ const auto generatorArg = GeneratorArgument::fromMetaType(type);
+ AbstractMetaType::applyDereference(&argValue, generatorArg.indirections);
}
}
} else {
@@ -1617,138 +1431,153 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
s << "// Begin code injection\n" << code << "// End of code injection\n\n";
}
+static void replacePyArg0(TypeSystem::Language language, QString *code)
+{
+ static constexpr auto pyArg0 = "%PYARG_0"_L1;
+
+ if (!code->contains(pyArg0))
+ return;
+ if (language != TypeSystem::NativeCode) {
+ code->replace(pyArg0, PYTHON_RETURN_VAR);
+ return;
+ }
+
+ // pyResult is an AutoDecRef in overridden methods of wrapper classes which
+ // has a cast operator for PyObject *. This may however not work in all
+ // situations (fex _PyVarObject_CAST(op) defined as ((PyVarObject*)(op))).
+ // Append ".object()" unless it is followed by a '.' indicating explicit
+ // AutoDecRef member invocation.
+ static const QString pyObject = PYTHON_RETURN_VAR + u".object()"_s;
+ qsizetype pos{};
+ while ( (pos = code->indexOf(pyArg0)) >= 0) {
+ const auto next = pos + pyArg0.size();
+ const bool memberInvocation = next < code->size() && code->at(next) == u'.';
+ code->replace(pos, pyArg0.size(),
+ memberInvocation ? PYTHON_RETURN_VAR : pyObject);
+ }
+}
+
void ShibokenGenerator::writeCodeSnips(TextStream &s,
const CodeSnipList &codeSnips,
TypeSystem::CodeSnipPosition position,
TypeSystem::Language language,
const AbstractMetaFunctionCPtr &func,
+ bool usePyArgs,
const AbstractMetaArgument *lastArg) const
{
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()], api());
- bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(od);
-
// Replace %PYARG_# variables.
- code.replace(QLatin1String("%PYARG_0"), QLatin1String(PYTHON_RETURN_VAR));
+ replacePyArg0(language, &code);
- static const QRegularExpression pyArgsRegex(QStringLiteral("%PYARG_(\\d+)"));
+ static const QRegularExpression pyArgsRegex("%PYARG_(\\d+)"_L1);
Q_ASSERT(pyArgsRegex.isValid());
if (language == TypeSystem::TargetLangCode) {
if (usePyArgs) {
- code.replace(pyArgsRegex, QLatin1String(PYTHON_ARGS) + QLatin1String("[\\1-1]"));
+ code.replace(pyArgsRegex, PYTHON_ARGS + u"[\\1-1]"_s);
} else {
- static const QRegularExpression pyArgsRegexCheck(QStringLiteral("%PYARG_([2-9]+)"));
+ static const QRegularExpression pyArgsRegexCheck("%PYARG_([2-9]+)"_L1);
Q_ASSERT(pyArgsRegexCheck.isValid());
const QRegularExpressionMatch match = pyArgsRegexCheck.match(code);
if (match.hasMatch()) {
qCWarning(lcShiboken).noquote().nospace()
- << msgWrongIndex("%PYARG", match.captured(1), func.data());
+ << msgWrongIndex("%PYARG", match.captured(1), func.get());
return;
}
- code.replace(QLatin1String("%PYARG_1"), QLatin1String(PYTHON_ARG));
+ code.replace(u"%PYARG_1"_s, 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*([^;]+)"));
+ static const QRegularExpression pyArgsAttributionRegex("%PYARG_(\\d+)\\s*=[^=]\\s*([^;]+)"_L1);
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)"));
+ code.replace(pyArgsAttributionRegex, u"PyTuple_SET_ITEM("_s
+ + PYTHON_ARGS + u".object(), \\1-1, \\2)"_s);
+ code.replace(pyArgsRegex, u"PyTuple_GET_ITEM("_s
+ + PYTHON_ARGS + u".object(), \\1-1)"_s);
}
// 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 argTypeVar = u"%ARG"_s + QString::number(arg.argumentIndex() + 1)
+ + u"_TYPE"_s;
QString argTypeVal = arg.type().cppSignature();
code.replace(argTypeVar, argTypeVal);
}
- static const QRegularExpression cppArgTypeRegexCheck(QStringLiteral("%ARG(\\d+)_TYPE"));
+ static const QRegularExpression cppArgTypeRegexCheck("%ARG(\\d+)_TYPE"_L1);
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.data());
+ << msgWrongIndex("%ARG#_TYPE", match.captured(1), func.get());
}
// Replace template variable for return variable name.
if (func->isConstructor()) {
- code.replace(QLatin1String("%0."), QLatin1String("cptr->"));
- code.replace(QLatin1String("%0"), QLatin1String("cptr"));
+ code.replace(u"%0."_s, u"cptr->"_s);
+ code.replace(u"%0"_s, u"cptr"_s);
} else if (!func->isVoid()) {
QString returnValueOp = func->type().isPointerToWrapperType()
- ? QLatin1String("%1->") : QLatin1String("%1.");
+ ? u"%1->"_s : u"%1."_s;
if (func->type().isWrapperType())
- code.replace(QLatin1String("%0."), returnValueOp.arg(QLatin1String(CPP_RETURN_VAR)));
- code.replace(QLatin1String("%0"), QLatin1String(CPP_RETURN_VAR));
+ code.replace(u"%0."_s, returnValueOp.arg(CPP_RETURN_VAR));
+ code.replace(u"%0"_s, CPP_RETURN_VAR);
}
// Replace template variable for self Python object.
QString pySelf = language == TypeSystem::NativeCode
- ? QLatin1String("pySelf") : QLatin1String("self");
- code.replace(QLatin1String("%PYSELF"), pySelf);
+ ? u"pySelf"_s : u"self"_s;
+ code.replace(u"%PYSELF"_s, pySelf);
// Replace template variable for a pointer to C++ of this object.
if (func->implementingClass()) {
- QString replacement = func->isStatic() ? QLatin1String("%1::") : QLatin1String("%1->");
+ QString replacement = func->isStatic() ? u"%1::"_s : u"%1->"_s;
QString cppSelf;
if (func->isStatic())
cppSelf = func->ownerClass()->qualifiedCppName();
else if (language == TypeSystem::NativeCode)
- cppSelf = QLatin1String("this");
+ cppSelf = u"this"_s;
else
- cppSelf = QLatin1String(CPP_SELF_VAR);
+ cppSelf = CPP_SELF_VAR;
// On comparison operator CPP_SELF_VAR is always a reference.
if (func->isComparisonOperator())
- replacement = QLatin1String("%1.");
+ replacement = u"%1."_s;
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")) {
+ const QString pattern = u"%CPPSELF.%FUNCTION_NAME("_s + methodCallArgs + u')';
+ QString replacement = u"(Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject *>("_s
+ + pySelf + u")) ? "_s;
+ if (func->name() == u"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));
+ ? u"%CPPSELF"_s
+ : u"reinterpret_cast<"_s + wrapperClassName + u" *>(%CPPSELF)"_s;
+ replacement += cppSelfVar + u"->::"_s + wrapperClassName
+ + u"::%FUNCTION_NAME("_s + methodCallArgs
+ + u") : %CPPSELF.%FUNCTION_NAME("_s + methodCallArgs + u"))"_s;
} 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));
+ replacement += u"%CPPSELF->::%TYPE::%FUNCTION_NAME("_s + methodCallArgs
+ + u") : %CPPSELF.%FUNCTION_NAME("_s + methodCallArgs + u"))"_s;
}
+ code.replace(pattern, replacement);
}
}
- code.replace(QLatin1String("%CPPSELF."), replacement.arg(cppSelf));
- code.replace(QLatin1String("%CPPSELF"), cppSelf);
+ code.replace(u"%CPPSELF."_s, replacement.arg(cppSelf));
+ code.replace(u"%CPPSELF"_s, 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));
+ if (code.indexOf(u"%BEGIN_ALLOW_THREADS") > -1) {
+ if (code.count(u"%BEGIN_ALLOW_THREADS"_s) == code.count(u"%END_ALLOW_THREADS"_s)) {
+ code.replace(u"%BEGIN_ALLOW_THREADS"_s, BEGIN_ALLOW_THREADS);
+ code.replace(u"%END_ALLOW_THREADS"_s, END_ALLOW_THREADS);
} else {
qCWarning(lcShiboken) << "%BEGIN_ALLOW_THREADS and %END_ALLOW_THREADS mismatch";
}
@@ -1757,11 +1586,11 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
// 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"));
+ code.replace(u"%PYTHONTYPEOBJECT"_s,
+ u"(*"_s + cpythonTypeName(func->implementingClass()) + u')');
} else {
- code.replace(QLatin1String("%PYTHONTYPEOBJECT."), pySelf + QLatin1String("->ob_type->"));
- code.replace(QLatin1String("%PYTHONTYPEOBJECT"), pySelf + QLatin1String("->ob_type"));
+ code.replace(u"%PYTHONTYPEOBJECT."_s, pySelf + u"->ob_type->"_s);
+ code.replace(u"%PYTHONTYPEOBJECT"_s, pySelf + u"->ob_type"_s);
}
}
@@ -1771,28 +1600,23 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
QStringList args;
for (const ArgumentVarReplacementPair &pair : argReplacements) {
- if (pair.second.startsWith(QLatin1String(CPP_ARG_REMOVED)))
+ if (pair.second.startsWith(CPP_ARG_REMOVED_PREFIX))
continue;
args << pair.second;
}
- code.replace(QLatin1String("%ARGUMENT_NAMES"), args.join(QLatin1String(", ")));
+ code.replace(u"%ARGUMENT_NAMES"_s, args.join(u", "_s));
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()) {
- auto builtType = buildAbstractMetaTypeFromString(typeReplaced);
- if (builtType.has_value())
- type = builtType.value();
- }
+ AbstractMetaType type = arg.modifiedType();
if (type.isWrapperType()) {
QString replacement = pair.second;
- if (type.referenceType() == LValueReference && !type.isPointer())
- replacement.remove(0, 1);
+ const auto generatorArg = GeneratorArgument::fromMetaType(type);
+ if (generatorArg.indirections > 0)
+ AbstractMetaType::stripDereference(&replacement);
if (type.referenceType() == LValueReference || type.isPointer())
- code.replace(QString::fromLatin1("%%1.").arg(idx), replacement + QLatin1String("->"));
+ code.replace(u'%' + QString::number(idx) + u'.', replacement + u"->"_s);
}
code.replace(CodeSnipAbstract::placeHolderRegex(idx), pair.second);
}
@@ -1801,11 +1625,11 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
// 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));
+ code.replace(u"%PYTHON_ARGUMENTS"_s, 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));
+ code.replace(u"%PYTHON_METHOD_OVERRIDE"_s, PYTHON_OVERRIDE_VAR);
}
if (avoidProtectedHack()) {
@@ -1814,31 +1638,34 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
// 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 auto &funcs = getFunctionOverloads(func->ownerClass(), func->name());
- for (const auto &f : funcs)
- hasProtectedOverload |= f->isProtected();
+ bool isProtected = func->isProtected();
+ auto owner = func->ownerClass();
+ if (!isProtected && func->isUserAdded() && owner != nullptr) {
+ const auto &funcs = getFunctionGroups(owner).value(func->name());
+ isProtected = std::any_of(funcs.cbegin(), funcs.cend(),
+ [](const AbstractMetaFunctionCPtr &f) {
+ return 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 (isProtected) {
+ code.replace(u"%TYPE::%FUNCTION_NAME"_s,
+ wrapperName(func->ownerClass()) + "::"_L1
+ + func->originalName() + "_protected"_L1);
+ code.replace(u"%FUNCTION_NAME"_s,
+ func->originalName() + u"_protected"_s);
}
}
if (func->isConstructor() && shouldGenerateCppWrapper(func->ownerClass()))
- code.replace(QLatin1String("%TYPE"), wrapperName(func->ownerClass()));
+ code.replace(u"%TYPE"_s, wrapperName(func->ownerClass()));
if (func->ownerClass())
- code.replace(QLatin1String("%CPPTYPE"), func->ownerClass()->name());
+ code.replace(u"%CPPTYPE"_s, func->ownerClass()->name());
replaceTemplateVariables(code, func);
- processCodeSnip(code);
+ processCodeSnip(code, func->classQualifiedSignature());
s << "// Begin code injection\n" << code << "// End of code injection\n\n";
}
@@ -1846,7 +1673,7 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
// 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*(?:\\[[^\\[]+\\])*$"));
+ static const QRegularExpression expr("^\\s*\\*?\\s*[A-Za-z_][A-Za-z_0-9.]*\\s*(?:\\[[^\\[]+\\])*$"_L1);
Q_ASSERT(expr.isValid());
return expr.match(code.trimmed()).hasMatch();
}
@@ -1859,15 +1686,15 @@ static QString miniNormalizer(const QString &varType)
QString normalized = varType.trimmed();
if (normalized.isEmpty())
return normalized;
- if (normalized.startsWith(QLatin1String("::")))
+ if (normalized.startsWith(u"::"))
normalized.remove(0, 2);
QString suffix;
- while (normalized.endsWith(QLatin1Char('*')) || normalized.endsWith(QLatin1Char('&'))) {
- suffix.prepend(normalized.at(normalized.count() - 1));
+ while (normalized.endsWith(u'*') || normalized.endsWith(u'&')) {
+ suffix.prepend(normalized.at(normalized.size() - 1));
normalized.chop(1);
normalized = normalized.trimmed();
}
- const QString result = normalized + QLatin1Char(' ') + suffix;
+ const QString result = normalized + u' ' + suffix;
return result.trimmed();
}
// The position must indicate the first character after the opening '('.
@@ -1878,7 +1705,7 @@ static QString getConverterTypeSystemVariableArgument(const QString &code, int p
QString arg;
int parenthesisDepth = 0;
int count = 0;
- while (pos + count < code.count()) {
+ while (pos + count < code.size()) {
char c = code.at(pos+count).toLatin1(); // toAscii is gone
if (c == '(') {
++parenthesisDepth;
@@ -1892,22 +1719,22 @@ static QString getConverterTypeSystemVariableArgument(const QString &code, int p
++count;
}
if (parenthesisDepth != 0)
- qFatal("Unbalanced parenthesis on type system converter variable call.");
+ throw Exception("Unbalanced parenthesis on type system converter variable call.");
return arg;
}
const QHash<int, QString> &ShibokenGenerator::typeSystemConvName()
{
static const QHash<int, QString> result = {
- {TypeSystemCheckFunction, QLatin1String("checkType")},
- {TypeSystemIsConvertibleFunction, QLatin1String("isConvertible")},
- {TypeSystemToCppFunction, QLatin1String("toCpp")},
- {TypeSystemToPythonFunction, QLatin1String("toPython")}
+ {TypeSystemCheckFunction, u"checkType"_s},
+ {TypeSystemIsConvertibleFunction, u"isConvertible"_s},
+ {TypeSystemToCppFunction, u"toCpp"_s},
+ {TypeSystemToPythonFunction, u"toPython"_s}
};
return result;
}
-using StringPair = QPair<QString, QString>;
+using StringPair = std::pair<QString, QString>;
void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable,
QString &code) const
@@ -1920,11 +1747,11 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
QString conversionString = list.constFirst();
const QString &conversionTypeName = list.constLast();
QString message;
- const auto conversionTypeO = buildAbstractMetaTypeFromString(conversionTypeName, &message);
+ const auto conversionTypeO = AbstractMetaType::fromString(conversionTypeName, &message);
if (!conversionTypeO.has_value()) {
- qFatal("%s", qPrintable(msgCannotFindType(conversionTypeName,
- typeSystemConvName().value(converterVariable),
- message)));
+ throw Exception(msgCannotFindType(conversionTypeName,
+ typeSystemConvName().value(converterVariable),
+ message));
}
const auto conversionType = conversionTypeO.value();
QString conversion;
@@ -1933,7 +1760,7 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
StringStream c(TextStream::Language::Cpp);
int end = match.capturedStart();
int start = end;
- while (start > 0 && code.at(start) != QLatin1Char('\n'))
+ while (start > 0 && code.at(start) != u'\n')
--start;
while (code.at(start).isSpace())
++start;
@@ -1942,21 +1769,13 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
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, api(), conversionType);
- c << ";\n";
+ c << getFullTypeName(conversionType) << ' ' << varName
+ << minimalConstructorExpression(api(), conversionType) << ";\n";
}
c << cpythonToCppConversionFunction(conversionType);
QString prefix;
- if (varName.startsWith(QLatin1Char('*'))) {
- varName.remove(0, 1);
- varName = varName.trimmed();
- } else {
- prefix = QLatin1Char('&');
- }
+ if (!AbstractMetaType::stripDereference(&varName))
+ prefix = u'&';
QString arg = getConverterTypeSystemVariableArgument(code, match.capturedEnd());
conversionString += arg;
c << arg << ", " << prefix << '(' << varName << ')';
@@ -1966,8 +1785,8 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
case TypeSystemCheckFunction:
conversion = cpythonCheckFunction(conversionType);
if (conversionType.typeEntry()->isPrimitive()
- && (conversionType.typeEntry()->name() == cPyObjectT()
- || !conversion.endsWith(QLatin1Char(' ')))) {
+ && (conversionType.typeEntry()->name() == cPyObjectT
+ || !conversion.endsWith(u' '))) {
conversion += u'(';
break;
}
@@ -1984,20 +1803,22 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
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));
+ QString m;
+ QTextStream(&m) << "Only variables are acceptable as argument to %%CONVERTTOPYTHON type system variable on code snippet: '"
+ << code << '\'';
+ throw Exception(m);
}
- if (conversion.contains(QLatin1String("%in"))) {
- conversion.prepend(QLatin1Char('('));
- conversion.replace(QLatin1String("%in"), arg);
+ if (conversion.contains(u"%in")) {
+ conversion.prepend(u'(');
+ conversion.replace(u"%in"_s, arg);
} else {
conversion += arg;
}
}
}
- replacements.append(qMakePair(conversionString, conversion));
+ replacements.append(std::make_pair(conversionString, conversion));
}
- for (const StringPair &rep : qAsConst(replacements))
+ for (const StringPair &rep : std::as_const(replacements))
code.replace(rep.first, rep.second);
}
@@ -2006,9 +1827,9 @@ bool ShibokenGenerator::injectedCodeCallsCppFunction(const GeneratorContext &con
{
if (func->injectedCodeContains(u"%FUNCTION_NAME("))
return true;
- QString funcCall = func->originalName() + QLatin1Char('(');
+ QString funcCall = func->originalName() + u'(';
if (func->isConstructor())
- funcCall.prepend(QLatin1String("new "));
+ funcCall.prepend(u"new "_s);
if (func->injectedCodeContains(funcCall))
return true;
if (!func->isConstructor())
@@ -2018,18 +1839,17 @@ bool ShibokenGenerator::injectedCodeCallsCppFunction(const GeneratorContext &con
const auto owner = func->ownerClass();
if (!owner->isPolymorphic())
return false;
- const QString className = context.useWrapper()
- ? context.wrapperName() : owner->qualifiedCppName();
- const QString wrappedCtorCall = QLatin1String("new ") + className + QLatin1Char('(');
+ const QString wrappedCtorCall = u"new "_s + context.effectiveClassName() + u'(';
return func->injectedCodeContains(wrappedCtorCall);
}
-bool ShibokenGenerator::useOverrideCaching(const AbstractMetaClass *metaClass)
+bool ShibokenGenerator::useOverrideCaching(const AbstractMetaClassCPtr &metaClass)
{
return metaClass->isPolymorphic();
}
-ShibokenGenerator::AttroCheck ShibokenGenerator::checkAttroFunctionNeeds(const AbstractMetaClass *metaClass) const
+ShibokenGenerator::AttroCheck ShibokenGenerator::checkAttroFunctionNeeds(
+ const AbstractMetaClassCPtr &metaClass)
{
AttroCheck result;
if (metaClass->typeEntry()->isSmartPointer()) {
@@ -2041,7 +1861,7 @@ ShibokenGenerator::AttroCheck ShibokenGenerator::checkAttroFunctionNeeds(const A
FunctionQueryOption::GetAttroFunction)) {
result |= AttroCheckFlag::GetattroUser;
}
- if (usePySideExtensions() && metaClass->qualifiedCppName() == qObjectT())
+ if (usePySideExtensions() && metaClass->qualifiedCppName() == qObjectT)
result |= AttroCheckFlag::SetattroQObject;
if (useOverrideCaching(metaClass))
result |= AttroCheckFlag::SetattroMethodOverride;
@@ -2053,14 +1873,14 @@ ShibokenGenerator::AttroCheck ShibokenGenerator::checkAttroFunctionNeeds(const A
// QObject, the property code needs to be generated, too.
if ((result & AttroCheckFlag::SetattroMask) != 0
&& !result.testFlag(AttroCheckFlag::SetattroQObject)
- && metaClass->isQObject()) {
+ && isQObject(metaClass)) {
result |= AttroCheckFlag::SetattroQObject;
}
}
return result;
}
-bool ShibokenGenerator::classNeedsGetattroFunctionImpl(const AbstractMetaClass *metaClass)
+bool ShibokenGenerator::classNeedsGetattroFunctionImpl(const AbstractMetaClassCPtr &metaClass)
{
if (!metaClass)
return false;
@@ -2069,7 +1889,7 @@ bool ShibokenGenerator::classNeedsGetattroFunctionImpl(const AbstractMetaClass *
const auto &functionGroup = getFunctionGroups(metaClass);
for (auto it = functionGroup.cbegin(), end = functionGroup.cend(); it != end; ++it) {
AbstractMetaFunctionCList overloads;
- for (const auto &func : qAsConst(it.value())) {
+ for (const auto &func : std::as_const(it.value())) {
if (func->isAssignmentOperator() || func->isConversionOperator()
|| func->isModifiedRemoved()
|| func->isPrivate() || func->ownerClass() != func->implementingClass()
@@ -2086,14 +1906,14 @@ bool ShibokenGenerator::classNeedsGetattroFunctionImpl(const AbstractMetaClass *
}
AbstractMetaFunctionCList
- ShibokenGenerator::getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClass *metaClass)
+ ShibokenGenerator::getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClassCPtr &metaClass)
{
AbstractMetaFunctionCList methods;
if (metaClass) {
const auto &functionGroups = getFunctionGroups(metaClass);
for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
AbstractMetaFunctionCList overloads;
- for (const auto &func : qAsConst(it.value())) {
+ for (const auto &func : std::as_const(it.value())) {
if (func->isAssignmentOperator() || func->isConversionOperator()
|| func->isModifiedRemoved()
|| func->isPrivate() || func->ownerClass() != func->implementingClass()
@@ -2110,7 +1930,8 @@ AbstractMetaFunctionCList
return methods;
}
-const AbstractMetaClass *ShibokenGenerator::getMultipleInheritingClass(const AbstractMetaClass *metaClass)
+AbstractMetaClassCPtr
+ ShibokenGenerator::getMultipleInheritingClass(const AbstractMetaClassCPtr &metaClass)
{
if (!metaClass || metaClass->baseClassNames().isEmpty())
return nullptr;
@@ -2119,64 +1940,50 @@ const AbstractMetaClass *ShibokenGenerator::getMultipleInheritingClass(const Abs
return getMultipleInheritingClass(metaClass->baseClass());
}
-QString ShibokenGenerator::getModuleHeaderFileName(const QString &moduleName)
+QString ShibokenGenerator::getModuleHeaderFileBaseName(const QString &moduleName)
{
- return moduleCppPrefix(moduleName).toLower() + QLatin1String("_python.h");
+ return moduleCppPrefix(moduleName).toLower() + "_python"_L1;
}
-std::optional<AbstractMetaType>
- ShibokenGenerator::buildAbstractMetaTypeFromString(QString typeSignature,
- QString *errorMessage)
+QString ShibokenGenerator::getModuleHeaderFileName(const QString &moduleName)
{
- typeSignature = typeSignature.trimmed();
- if (typeSignature.startsWith(QLatin1String("::")))
- typeSignature.remove(0, 2);
-
- auto &cache = *metaTypeFromStringCache();
- auto it = cache.find(typeSignature);
- if (it == cache.end()) {
- auto metaType =
- AbstractMetaBuilder::translateType(typeSignature, nullptr, {}, errorMessage);
- if (Q_UNLIKELY(!metaType.has_value())) {
- if (errorMessage)
- errorMessage->prepend(msgCannotBuildMetaType(typeSignature));
- return {};
- }
- it = cache.insert(typeSignature, metaType.value());
- }
- return it.value();
+ return getModuleHeaderFileBaseName(moduleName) + ".h"_L1;
}
-AbstractMetaType
- ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(const TypeEntry *typeEntry)
+QString ShibokenGenerator::getPrivateModuleHeaderFileName(const QString &moduleName)
{
- QString typeName = typeEntry->qualifiedCppName();
- if (typeName.startsWith(QLatin1String("::")))
- typeName.remove(0, 2);
- auto &cache = *metaTypeFromStringCache();
- auto it = cache.find(typeName);
- if (it != cache.end())
- return it.value();
- AbstractMetaType metaType(typeEntry);
- metaType.clearIndirections();
- metaType.setReferenceType(NoReference);
- metaType.setConstant(false);
- metaType.decideUsagePattern();
- cache.insert(typeName, metaType);
- return metaType;
+ return getModuleHeaderFileBaseName(moduleName) + "_p.h"_L1;
}
-AbstractMetaType
- ShibokenGenerator::buildAbstractMetaTypeFromAbstractMetaClass(const AbstractMetaClass *metaClass)
+IncludeGroupList ShibokenGenerator::classIncludes(const AbstractMetaClassCPtr &metaClass) const
{
- return ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(metaClass->typeEntry());
+ IncludeGroupList result;
+ const auto typeEntry = metaClass->typeEntry();
+ //Extra includes
+ result.append(IncludeGroup{u"Extra includes"_s,
+ typeEntry->extraIncludes()});
+
+ result.append({u"Enum includes"_s, {}});
+ for (const auto &cppEnum : metaClass->enums())
+ result.back().includes.append(cppEnum.typeEntry()->extraIncludes());
+
+ result.append({u"Argument includes"_s, typeEntry->argumentIncludes()});
+ const auto implicitConvs = implicitConversions(typeEntry);
+ for (const auto &f : implicitConvs) {
+ if (f->isConversionOperator()) {
+ const auto source = f->ownerClass();
+ Q_ASSERT(source);
+ result.back().append(source->typeEntry()->include());
+ }
+ }
+ return result;
}
/*
static void dumpFunction(AbstractMetaFunctionList lst)
{
qDebug() << "DUMP FUNCTIONS: ";
- for (AbstractMetaFunction *func : qAsConst(lst))
+ for (AbstractMetaFunction *func : std::as_const(lst))
qDebug() << "*" << func->ownerClass()->name()
<< func->signature()
<< "Private: " << func->isPrivate()
@@ -2220,40 +2027,78 @@ ShibokenGenerator::FunctionGroups ShibokenGenerator::getGlobalFunctionGroups() c
{
FunctionGroups results;
insertIntoFunctionGroups(api().globalFunctions(), &results);
- for (auto nsp : invisibleTopNamespaces())
+ for (const auto &nsp : invisibleTopNamespaces())
insertIntoFunctionGroups(nsp->functions(), &results);
return results;
}
-const GeneratorClassInfoCacheEntry &ShibokenGenerator::getGeneratorClassInfo(const AbstractMetaClass *scope)
+const GeneratorClassInfoCacheEntry &
+ ShibokenGenerator::getGeneratorClassInfo(const AbstractMetaClassCPtr &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);
+ auto &entry = it.value();
+ entry.functionGroups = getFunctionGroupsImpl(scope);
+ entry.needsGetattroFunction = classNeedsGetattroFunctionImpl(scope);
+ entry.numberProtocolOperators = getNumberProtocolOperators(scope);
+ entry.boolCastFunctionO = getBoolCast(scope);
}
return it.value();
}
-ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroups(const AbstractMetaClass *scope)
+ShibokenGenerator::FunctionGroups
+ ShibokenGenerator::getFunctionGroups(const AbstractMetaClassCPtr &scope)
{
Q_ASSERT(scope);
return getGeneratorClassInfo(scope).functionGroups;
}
-ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroupsImpl(const AbstractMetaClass *scope)
+QList<AbstractMetaFunctionCList>
+ ShibokenGenerator::numberProtocolOperators(const AbstractMetaClassCPtr &scope)
+{
+ Q_ASSERT(scope);
+ return getGeneratorClassInfo(scope).numberProtocolOperators;
+}
+
+BoolCastFunctionOptional ShibokenGenerator::boolCast(const AbstractMetaClassCPtr &scope)
+{
+ Q_ASSERT(scope);
+ return getGeneratorClassInfo(scope).boolCastFunctionO;
+}
+
+// Use non-const overloads only, for example, "foo()" and "foo()const"
+// the second is removed.
+static void removeConstOverloads(AbstractMetaFunctionCList *overloads)
+{
+ for (qsizetype i = overloads->size() - 1; i >= 0; --i) {
+ const auto &f = overloads->at(i);
+ if (f->isConstant()) {
+ for (qsizetype c = 0, size = overloads->size(); c < size; ++c) {
+ if (f->isConstOverloadOf(overloads->at(c).get())) {
+ overloads->removeAt(i);
+ break;
+ }
+ }
+ }
+ }
+}
+
+ShibokenGenerator::FunctionGroups
+ ShibokenGenerator::getFunctionGroupsImpl(const AbstractMetaClassCPtr &scope)
{
AbstractMetaFunctionCList lst = scope->functions();
scope->getFunctionsFromInvisibleNamespacesToBeGenerated(&lst);
FunctionGroups results;
for (const auto &func : lst) {
- if (isGroupable(func)) {
+ if (isGroupable(func)
+ && func->ownerClass() == func->implementingClass()
+ && func->generateBinding()) {
auto it = results.find(func->name());
if (it == results.end()) {
- results.insert(func->name(), AbstractMetaFunctionCList(1, func));
+ it = results.insert(func->name(), AbstractMetaFunctionCList(1, func));
} else {
// If there are virtuals methods in the mix (PYSIDE-570,
// QFileSystemModel::index(QString,int) and
@@ -2265,387 +2110,540 @@ ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroupsImpl(const
else
it.value().append(func);
}
+ getInheritedOverloads(scope, &it.value());
+ removeConstOverloads(&it.value());
}
}
return results;
}
-AbstractMetaFunctionCList
- ShibokenGenerator::getInheritedOverloads(const AbstractMetaFunctionCPtr &func, QSet<QString> *seen)
-{
- AbstractMetaFunctionCList results;
- AbstractMetaClass *basis;
- if (func->ownerClass() && (basis = func->ownerClass()->baseClass())) {
- for (; basis; basis = basis->baseClass()) {
- const auto inFunc = basis->findFunction(func->name());
- if (!inFunc.isNull() && !seen->contains(inFunc->minimalSignature())) {
- seen->insert(inFunc->minimalSignature());
- AbstractMetaFunction *newFunc = inFunc->copy();
- newFunc->setImplementingClass(func->implementingClass());
- results << AbstractMetaFunctionCPtr(newFunc);
- }
- }
- }
- return results;
+static bool removeNumberProtocolOperator(const AbstractMetaFunctionCPtr &f)
+{
+ return !f->generateBinding()
+ || (f->ownerClass() != f->implementingClass() && !f->isAbstract());
}
-AbstractMetaFunctionCList
- ShibokenGenerator::getFunctionAndInheritedOverloads(const AbstractMetaFunctionCPtr &func,
- QSet<QString> *seen)
+QList<AbstractMetaFunctionCList>
+ ShibokenGenerator::getNumberProtocolOperators(const AbstractMetaClassCPtr &metaClass)
{
- AbstractMetaFunctionCList results;
- seen->insert(func->minimalSignature());
- results << func << getInheritedOverloads(func, seen);
- return results;
+ QList<AbstractMetaFunctionCList> result;
+ if (metaClass->isNamespace())
+ return result;
+ result = filterGroupedOperatorFunctions(
+ metaClass,
+ OperatorQueryOption::ArithmeticOp
+ | OperatorQueryOption::IncDecrementOp
+ | OperatorQueryOption::LogicalOp
+ | OperatorQueryOption::BitwiseOp
+ | OperatorQueryOption::ConversionOp);
+
+ for (auto i = result.size() - 1; i >= 0; --i) {
+ AbstractMetaFunctionCList &l = result[i];
+ auto rend = std::remove_if(l.begin(), l.end(), removeNumberProtocolOperator);
+ l.erase(rend, l.end());
+ if (l.isEmpty())
+ result.removeAt(i);
+ }
+
+ return result;
}
-AbstractMetaFunctionCList ShibokenGenerator::getFunctionOverloads(const AbstractMetaClass *scope,
- const QString &functionName) const
+BoolCastFunctionOptional
+ShibokenGenerator::getBoolCast(const AbstractMetaClassCPtr &metaClass)
{
- const auto &lst = scope ? scope->functions() : api().globalFunctions();
+ if (metaClass->isNamespace())
+ return std::nullopt;
- AbstractMetaFunctionCList results;
- QSet<QString> seenSignatures;
- for (const auto &func : qAsConst(lst)) {
- if (func->name() != functionName)
- continue;
- if (isGroupable(func)) {
- // PYSIDE-331: look also into base classes.
- results << getFunctionAndInheritedOverloads(func, &seenSignatures);
+ const auto te = metaClass->typeEntry();
+ if (te->isSmartPointer()) {
+ auto ste = std::static_pointer_cast<const SmartPointerTypeEntry>(te);
+
+ auto valueCheckMethod = ste->valueCheckMethod();
+ if (!valueCheckMethod.isEmpty()) {
+ const auto func = metaClass->findFunction(valueCheckMethod);
+ if (!func)
+ throw Exception(msgMethodNotFound(metaClass, valueCheckMethod));
+ return BoolCastFunction{func, false};
+ }
+
+ auto nullCheckMethod = ste->nullCheckMethod();
+ if (!nullCheckMethod.isEmpty()) {
+ const auto func = metaClass->findFunction(nullCheckMethod);
+ if (!func)
+ throw Exception(msgMethodNotFound(metaClass, nullCheckMethod));
+ return BoolCastFunction{func, true};
}
}
- return results;
+
+ auto mode = te->operatorBoolMode();
+ if (useOperatorBoolAsNbBool()
+ ? mode != TypeSystem::BoolCast::Disabled : mode == TypeSystem::BoolCast::Enabled) {
+ const auto func = metaClass->findOperatorBool();
+ if (func)
+ return BoolCastFunction{func, false};
+ }
+
+ mode = te->isNullMode();
+ if (useIsNullAsNbBool()
+ ? mode != TypeSystem::BoolCast::Disabled : mode == TypeSystem::BoolCast::Enabled) {
+ const auto func = metaClass->findQtIsNullMethod();
+ if (func)
+ return BoolCastFunction{func, true};
+ }
+ return std::nullopt;
}
-Generator::OptionDescriptions ShibokenGenerator::options() const
+static bool isInplaceAdd(const AbstractMetaFunctionCPtr &func)
{
- return {
- {QLatin1String(AVOID_PROTECTED_HACK),
- QLatin1String("Avoid the use of the '#define protected public' hack.")},
- {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.")},
- {QLatin1String(PARENT_CTOR_HEURISTIC),
- QLatin1String("Enable heuristics to detect parent relationship on constructors.")},
- {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.")},
- {QLatin1String(RETURN_VALUE_HEURISTIC),
- QLatin1String("Enable heuristics to detect parent relationship on return values\n"
- "(USE WITH CAUTION!)")},
- {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")},
- {QLatin1String(WRAPPER_DIAGNOSTICS),
- QLatin1String("Generate diagnostic code around wrappers")}
- };
+ return func->name() == u"operator+=";
}
-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 bool isIncrementOperator(const AbstractMetaFunctionCPtr &func)
+{
+ return func->functionType() == AbstractMetaFunction::IncrementOperator;
}
-static void getCode(QStringList &code, const CodeSnipList &codeSnips)
+static bool isDecrementOperator(const AbstractMetaFunctionCPtr &func)
{
- for (const CodeSnip &snip : qAsConst(codeSnips))
- code.append(snip.code());
+ return func->functionType() == AbstractMetaFunction::DecrementOperator;
}
-static void getCode(QStringList &code, const TypeEntry *type)
+// Filter predicate for operator functions
+static bool skipOperatorFunc(const AbstractMetaFunctionCPtr &func)
{
- getCode(code, type->codeSnips());
+ if (func->isModifiedRemoved() || func->usesRValueReferences())
+ return true;
+ const auto &name = func->name();
+ return name == u"operator[]" || name == u"operator->" || name == u"operator!"
+ || name == u"operator/="; // __idiv__ is not needed in Python3
+}
+
+QList<AbstractMetaFunctionCList>
+ShibokenGenerator::filterGroupedOperatorFunctions(const AbstractMetaClassCPtr &metaClass,
+ OperatorQueryOptions query)
+{
+ // ( func_name, num_args ) => func_list
+ QMap<std::pair<QString, int>, AbstractMetaFunctionCList> results;
+ auto funcs = metaClass->operatorOverloads(query);
+ auto end = std::remove_if(funcs.begin(), funcs.end(), skipOperatorFunc);
+ funcs.erase(end, funcs.end());
+ // If we have operator+=, we remove the operator++/-- which would
+ // otherwise be used for emulating __iadd__, __isub__.
+ if (std::any_of(funcs.cbegin(), funcs.cend(), isInplaceAdd)) {
+ end = std::remove_if(funcs.begin(), funcs.end(),
+ [] (const AbstractMetaFunctionCPtr &func) {
+ return func->isIncDecrementOperator();
+ });
+ funcs.erase(end, funcs.end());
+ } else {
+ // If both prefix/postfix ++/-- are present, remove one
+ if (std::count_if(funcs.begin(), funcs.end(), isIncrementOperator) > 1)
+ funcs.erase(std::find_if(funcs.begin(), funcs.end(), isIncrementOperator));
+ if (std::count_if(funcs.begin(), funcs.end(), isDecrementOperator) > 1)
+ funcs.erase(std::find_if(funcs.begin(), funcs.end(), isDecrementOperator));
+ }
+ for (const auto &func : funcs) {
+ int args;
+ if (func->isComparisonOperator()) {
+ args = -1;
+ } else {
+ args = func->arguments().size();
+ }
+ auto op = std::make_pair(func->name(), args);
+ results[op].append(func);
+ }
+ QList<AbstractMetaFunctionCList> result;
+ result.reserve(results.size());
+ for (auto it = results.cbegin(), end = results.cend(); it != end; ++it)
+ result.append(it.value());
+ return result;
+}
+
+static bool hidesBaseClassFunctions(const AbstractMetaFunctionCPtr &f)
+{
+ auto attributes = f->cppAttributes();
+ return !attributes.testFlag(FunctionAttribute::Override)
+ && !attributes.testFlag(FunctionAttribute::Final);
+}
- CustomConversion *customConversion = type->customConversion();
- if (!customConversion)
+void ShibokenGenerator::getInheritedOverloads(const AbstractMetaClassCPtr &scope,
+ AbstractMetaFunctionCList *overloads)
+{
+ if (overloads->isEmpty() || scope->isNamespace() || scope->baseClasses().isEmpty())
return;
- if (!customConversion->nativeToTargetConversion().isEmpty())
- code.append(customConversion->nativeToTargetConversion());
+ // PYSIDE-331: look also into base classes. Check for any non-overriding
+ // function hiding the base class functions.
+ const bool hideBaseClassFunctions =
+ std::any_of(overloads->cbegin(), overloads->cend(), hidesBaseClassFunctions);
- const CustomConversion::TargetToNativeConversions &toCppConversions = customConversion->targetToNativeConversions();
- if (toCppConversions.isEmpty())
- return;
+ const QString &functionName = overloads->constFirst()->name();
+ const bool hasUsingDeclarations = scope->hasUsingMemberFor(functionName);
+ if (hideBaseClassFunctions && !hasUsingDeclarations)
+ return; // No base function is visible
- for (CustomConversion::TargetToNativeConversion *toNative : qAsConst(toCppConversions))
- code.append(toNative->conversion());
+ // Collect base candidates by name and signature
+ bool staticEncountered = false;
+ QSet<QString> seenSignatures;
+ for (const auto &func : *overloads) {
+ seenSignatures.insert(func->minimalSignature());
+ staticEncountered |= func->isStatic();
+ }
+
+ AbstractMetaFunctionCList baseCandidates;
+
+ auto basePredicate = [&functionName, &seenSignatures, &baseCandidates]
+ (const AbstractMetaClassCPtr &b) {
+ for (const auto &f : b->functions()) {
+ if (f->generateBinding() && f->name() == functionName) {
+ const QString signature = f->minimalSignature();
+ if (!seenSignatures.contains(signature)) {
+ seenSignatures.insert(signature);
+ baseCandidates.append(f);
+ }
+ }
+ }
+ return false; // Keep going
+ };
+
+ for (const auto &baseClass : scope->baseClasses())
+ recurseClassHierarchy(baseClass, basePredicate);
+
+ // Remove the ones that are not made visible with using declarations
+ if (hideBaseClassFunctions && hasUsingDeclarations) {
+ const auto pred = [scope](const AbstractMetaFunctionCPtr &f) {
+ return !scope->isUsingMember(f->ownerClass(), f->name(), f->access());
+ };
+ auto end = std::remove_if(baseCandidates.begin(), baseCandidates.end(), pred);
+ baseCandidates.erase(end, baseCandidates.end());
+ }
+
+ // PYSIDE-886: If the method does not have any static overloads declared
+ // in the class in question, remove all inherited static methods as setting
+ // METH_STATIC in that case can cause crashes for the instance methods.
+ // Manifested as crash when calling QPlainTextEdit::find() (clash with
+ // static QWidget::find(WId)).
+ if (!staticEncountered) {
+ auto end = std::remove_if(baseCandidates.begin(), baseCandidates.end(),
+ [](const AbstractMetaFunctionCPtr &f) { return f->isStatic(); });
+ baseCandidates.erase(end, baseCandidates.end());
+ }
+
+ for (const auto &baseCandidate : baseCandidates) {
+ AbstractMetaFunction *newFunc = baseCandidate->copy();
+ newFunc->setImplementingClass(scope);
+ overloads->append(AbstractMetaFunctionCPtr(newFunc));
+ }
}
-bool ShibokenGenerator::doSetup()
+QList<OptionDescription> ShibokenGenerator::options()
+{
+ return {
+ {DISABLE_VERBOSE_ERROR_MESSAGES,
+ u"Disable verbose error messages. Turn the python code hard to debug\n"
+ "but safe few kB on the generated bindings."_s},
+ {PARENT_CTOR_HEURISTIC,
+ u"Enable heuristics to detect parent relationship on constructors."_s},
+ {RETURN_VALUE_HEURISTIC,
+ u"Enable heuristics to detect parent relationship on return values\n"
+ "(USE WITH CAUTION!)"_s},
+ {USE_ISNULL_AS_NB_BOOL,
+ u"If a class have an isNull() const method, it will be used to compute\n"
+ "the value of boolean casts"_s},
+ {LEAN_HEADERS,
+ u"Forward declare classes in module headers"_s},
+ {USE_OPERATOR_BOOL_AS_NB_BOOL,
+ u"If a class has an operator bool, it will be used to compute\n"
+ "the value of boolean casts"_s},
+ {NO_IMPLICIT_CONVERSIONS,
+ u"Do not generate implicit_conversions for function arguments."_s},
+ {WRAPPER_DIAGNOSTICS,
+ u"Generate diagnostic code around wrappers"_s}
+ };
+}
+
+class ShibokenGeneratorOptionsParser : public OptionsParser
{
- 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);
- for (auto metaClass : api().classes())
- getCode(snips, metaClass->typeEntry());
+public:
+ explicit ShibokenGeneratorOptionsParser(ShibokenGeneratorOptions *o) : m_options(o) {}
- const TypeSystemTypeEntry *moduleEntry = TypeDatabase::instance()->defaultTypeSystemType();
- Q_ASSERT(moduleEntry);
- getCode(snips, moduleEntry);
+ bool handleBoolOption(const QString & key, OptionSource source) override;
- const auto &functionGroups = getGlobalFunctionGroups();
- for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
- for (const auto &func : it.value())
- getCode(snips, func->injectedCodeSnips());
- }
+private:
+ ShibokenGeneratorOptions *m_options;
+};
- for (const QString &code : qAsConst(snips)) {
- collectContainerTypesFromConverterMacros(code, true);
- collectContainerTypesFromConverterMacros(code, false);
+bool ShibokenGeneratorOptionsParser::handleBoolOption(const QString &key, OptionSource source)
+{
+ if (source == OptionSource::CommandLineSingleDash)
+ return false;
+ if (key == PARENT_CTOR_HEURISTIC)
+ return (m_options->useCtorHeuristic = true);
+ if (key == RETURN_VALUE_HEURISTIC)
+ return (m_options->userReturnValueHeuristic = true);
+ if (key == DISABLE_VERBOSE_ERROR_MESSAGES)
+ return (m_options->verboseErrorMessagesDisabled = true);
+ if (key == USE_ISNULL_AS_NB_BOOL || key == USE_ISNULL_AS_NB_NONZERO) {
+ return (m_options->useIsNullAsNbBool = true);
+ }
+ if (key == LEAN_HEADERS)
+ return (m_options->leanHeaders= true);
+ if (key == USE_OPERATOR_BOOL_AS_NB_BOOL || key == USE_OPERATOR_BOOL_AS_NB_NONZERO) {
+ return (m_options->useOperatorBoolAsNbBool = true);
+ }
+ if (key == NO_IMPLICIT_CONVERSIONS) {
+ m_options->generateImplicitConversions = false;
+ return true;
}
+ if (key == WRAPPER_DIAGNOSTICS)
+ return (m_options->wrapperDiagnostics = true);
+ return false;
+}
+std::shared_ptr<OptionsParser> ShibokenGenerator::createOptionsParser()
+{
+ return std::make_shared<ShibokenGeneratorOptionsParser>(&m_options);
+}
+
+bool ShibokenGenerator::doSetup()
+{
return true;
}
-void ShibokenGenerator::collectContainerTypesFromConverterMacros(const QString &code, bool toPythonMacro)
+bool ShibokenGenerator::useCtorHeuristic()
{
- 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);
- auto type = buildAbstractMetaTypeFromString(typeString, &errorMessage);
- if (type.has_value()) {
- addInstantiatedContainersAndSmartPointers(type.value(), type->originalTypeDescription());
- } else {
- qFatal("%s: Cannot translate type \"%s\": %s", __FUNCTION__,
- qPrintable(typeString), qPrintable(errorMessage));
- }
- }
- start = end;
- }
+ return m_options.useCtorHeuristic;
}
-bool ShibokenGenerator::useCtorHeuristic() const
+bool ShibokenGenerator::useReturnValueHeuristic()
{
- return m_useCtorHeuristic;
+ return m_options.userReturnValueHeuristic;
}
-bool ShibokenGenerator::useReturnValueHeuristic() const
+bool ShibokenGenerator::useIsNullAsNbBool()
{
- return m_userReturnValueHeuristic;
+ return m_options.useIsNullAsNbBool;
}
-bool ShibokenGenerator::usePySideExtensions() const
+bool ShibokenGenerator::leanHeaders()
{
- return m_usePySideExtensions;
+ return m_options.leanHeaders;
}
-bool ShibokenGenerator::useIsNullAsNbNonZero() const
+bool ShibokenGenerator::useOperatorBoolAsNbBool()
{
- return m_useIsNullAsNbNonZero;
+ return m_options.useOperatorBoolAsNbBool;
}
-bool ShibokenGenerator::avoidProtectedHack() const
+bool ShibokenGenerator::generateImplicitConversions()
{
- return m_avoidProtectedHack;
+ return m_options.generateImplicitConversions;
}
QString ShibokenGenerator::moduleCppPrefix(const QString &moduleName)
{
QString result = moduleName.isEmpty() ? packageName() : moduleName;
- result.replace(QLatin1Char('.'), QLatin1Char('_'));
+ result.replace(u'.', u'_');
return result;
}
+QString ShibokenGenerator::cppApiVariableNameOld(const QString &moduleName)
+{
+ return "Sbk"_L1 + moduleCppPrefix(moduleName) + "Types"_L1;
+}
+
QString ShibokenGenerator::cppApiVariableName(const QString &moduleName)
{
- return QLatin1String("Sbk") + moduleCppPrefix(moduleName)
- + QLatin1String("Types");
+ return "Sbk"_L1 + moduleCppPrefix(moduleName) + "TypeStructs"_L1;
}
QString ShibokenGenerator::pythonModuleObjectName(const QString &moduleName)
{
- return QLatin1String("Sbk") + moduleCppPrefix(moduleName)
- + QLatin1String("ModuleObject");
+ return "Sbk"_L1 + moduleCppPrefix(moduleName) + "ModuleObject"_L1;
}
QString ShibokenGenerator::convertersVariableName(const QString &moduleName)
{
- QString result = cppApiVariableName(moduleName);
+ QString result = cppApiVariableNameOld(moduleName);
result.chop(1);
- result.append(QLatin1String("Converters"));
+ result.append(u"Converters"_s);
return result;
}
static QString processInstantiationsVariableName(const AbstractMetaType &type)
{
- QString res = QLatin1Char('_') + _fixedCppTypeName(type.typeEntry()->qualifiedCppName()).toUpper();
+ QString res = u'_' + _fixedCppTypeName(type.typeEntry()->qualifiedCppName());
for (const auto &instantiation : type.instantiations()) {
res += instantiation.isContainer()
? processInstantiationsVariableName(instantiation)
- : QLatin1Char('_') + _fixedCppTypeName(instantiation.cppSignature()).toUpper();
+ : u'_' + _fixedCppTypeName(instantiation.cppSignature());
}
return res;
}
static void appendIndexSuffix(QString *s)
{
- if (!s->endsWith(QLatin1Char('_')))
- s->append(QLatin1Char('_'));
- s->append(QStringLiteral("IDX"));
+ if (!s->endsWith(u'_'))
+ s->append(u'_');
+ s->append("IDX"_L1);
}
-QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass *metaClass,
- bool alternativeTemplateName)
+QString
+ ShibokenGenerator::getTypeAlternateTemplateIndexVariableName(const AbstractMetaClassCPtr &metaClass)
+{
+ const auto templateBaseClass = metaClass->templateBaseClass();
+ Q_ASSERT(templateBaseClass);
+ QString result = u"SBK_"_s
+ + _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName());
+ for (const auto &instantiation : metaClass->templateBaseClassInstantiations())
+ result += processInstantiationsVariableName(instantiation);
+ appendIndexSuffix(&result);
+ return result;
+}
+
+QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClassCPtr &metaClass)
{
- if (alternativeTemplateName) {
- const AbstractMetaClass *templateBaseClass = metaClass->templateBaseClass();
- if (!templateBaseClass)
- return QString();
- QString result = QLatin1String("SBK_")
- + _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName()).toUpper();
- for (const auto &instantiation : metaClass->templateBaseClassInstantiations())
- result += processInstantiationsVariableName(instantiation);
- appendIndexSuffix(&result);
- return result;
- }
return getTypeIndexVariableName(metaClass->typeEntry());
}
-QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry *type)
+QString ShibokenGenerator::getTypeIndexVariableName(TypeEntryCPtr type)
{
- if (type->isCppPrimitive()) {
- const auto *trueType = static_cast<const PrimitiveTypeEntry *>(type);
- if (trueType->basicReferencedTypeEntry())
- type = trueType->basicReferencedTypeEntry();
- }
- QString result = QLatin1String("SBK_");
+ if (isCppPrimitive(type))
+ type = basicReferencedTypeEntry(type);
+ QString result = u"SBK_"_s;
// Disambiguate namespaces per module to allow for extending them.
if (type->isNamespace()) {
QString package = type->targetLangPackage();
- const int dot = package.lastIndexOf(QLatin1Char('.'));
+ const int dot = package.lastIndexOf(u'.');
result += QStringView{package}.right(package.size() - (dot + 1));
}
- result += _fixedCppTypeName(type->qualifiedCppName()).toUpper();
+ result += _fixedCppTypeName(type->qualifiedCppName());
appendIndexSuffix(&result);
return result;
}
QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaType &type)
{
- QString result = QLatin1String("SBK");
+ QString result = u"SBK"_s;
if (type.typeEntry()->isContainer())
- result += QLatin1Char('_') + moduleName().toUpper();
+ result += u'_' + moduleName();
result += processInstantiationsVariableName(type);
appendIndexSuffix(&result);
return result;
}
-bool ShibokenGenerator::verboseErrorMessagesDisabled() const
+void collectfromTypeEntry(TypeEntryCPtr entry, QStringList &typeNames)
{
- return m_verboseErrorMessagesDisabled;
+ if (entry->shouldGenerate()) {
+ typeNames[entry->sbkIndex()] = entry->qualifiedTargetLangName();
+ if (entry->isEnum()) {
+ auto ete = std::static_pointer_cast<const EnumTypeEntry>(entry);
+ if (ete->flags()) {
+ auto entry = ete->flags();
+ typeNames[entry->sbkIndex()] = entry->qualifiedTargetLangName();
+ }
+ }
+ }
}
-bool ShibokenGenerator::pythonFunctionWrapperUsesListOfArguments(const OverloadData &overloadData)
+void ShibokenGenerator::collectFullTypeNamesArray(QStringList &typeNames)
{
- 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();
+ for (const auto &metaClass : api().classes()) {
+ collectfromTypeEntry(metaClass->typeEntry(), typeNames);
+
+ for (const AbstractMetaEnum &metaEnum : metaClass->enums())
+ collectfromTypeEntry(metaEnum.typeEntry(), typeNames);
+
+ int smartPointerCountIndex = getMaxTypeIndex();
+ for (const auto &smp : api().instantiatedSmartPointers()) {
+ auto entry = smp.type.typeEntry();
+ typeNames[smartPointerCountIndex] = entry->qualifiedTargetLangName();
+ ++smartPointerCountIndex;
+ }
+ }
+ for (const AbstractMetaEnum &metaEnum : api().globalEnums())
+ collectfromTypeEntry(metaEnum.typeEntry(), typeNames);
}
-void ShibokenGenerator::writeMinimalConstructorExpression(TextStream &s,
- const ApiExtractorResult &api,
- const AbstractMetaType &type,
- const QString &defaultCtor)
+bool ShibokenGenerator::verboseErrorMessagesDisabled()
+{
+ return m_options.verboseErrorMessagesDisabled;
+}
+
+bool ShibokenGenerator::pythonFunctionWrapperUsesListOfArguments(const AbstractMetaFunctionCPtr &func) const
+{
+ const auto &groups = func->implementingClass()
+ ? getFunctionGroups(func->implementingClass())
+ : getGlobalFunctionGroups();
+ OverloadData od(groups.value(func->name()), api());
+ return od.pythonFunctionWrapperUsesListOfArguments();
+}
+
+QString ShibokenGenerator::minimalConstructorExpression(const ApiExtractorResult &api,
+ const AbstractMetaType &type)
{
- if (!defaultCtor.isEmpty()) {
- s << " = " << defaultCtor;
- return;
- }
if (type.isExtendedCppPrimitive() || type.isSmartPointer())
- return;
+ return {};
QString errorMessage;
const auto ctor = minimalConstructor(api, type, &errorMessage);
- if (ctor.has_value()) {
- s << ctor->initialization();
- } else {
- const QString message =
- msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__),
- type.cppSignature(), errorMessage);
- qCWarning(lcShiboken()).noquote() << message;
- s << ";\n#error " << message << '\n';
- }
+ if (ctor.has_value())
+ return ctor->initialization();
+
+ const QString message =
+ msgCouldNotFindMinimalConstructor(QLatin1StringView(__FUNCTION__),
+ type.cppSignature(), errorMessage);
+ qCWarning(lcShiboken()).noquote() << message;
+ return u";\n#error "_s + message + u'\n';
}
-void ShibokenGenerator::writeMinimalConstructorExpression(TextStream &s,
- const ApiExtractorResult &api,
- const TypeEntry *type,
- const QString &defaultCtor)
+QString ShibokenGenerator::minimalConstructorExpression(const ApiExtractorResult &api,
+ const TypeEntryCPtr &type)
{
- if (!defaultCtor.isEmpty()) {
- s << " = " << defaultCtor;
- return;
- }
- if (type->isExtendedCppPrimitive())
- return;
+ if (isExtendedCppPrimitive(type))
+ return {};
const auto ctor = minimalConstructor(api, type);
- if (ctor.has_value()) {
- s << ctor->initialization();
- } else {
- const QString message = msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__), type->qualifiedCppName());
- qCWarning(lcShiboken()).noquote() << message;
- s << ";\n#error " << message << '\n';
- }
+ if (ctor.has_value())
+ return ctor->initialization();
+
+ const QString message =
+ msgCouldNotFindMinimalConstructor(QLatin1StringView(__FUNCTION__),
+ type->qualifiedCppName());
+ qCWarning(lcShiboken()).noquote() << message;
+ return u";\n#error "_s + message + u'\n';
}
QString ShibokenGenerator::pythonArgsAt(int i)
{
- return QLatin1String(PYTHON_ARGS) + QLatin1Char('[')
- + QString::number(i) + QLatin1Char(']');
+ return PYTHON_ARGS + u'[' + QString::number(i) + u']';
}
void ShibokenGenerator::replaceTemplateVariables(QString &code,
const AbstractMetaFunctionCPtr &func) const
{
- const AbstractMetaClass *cpp_class = func->ownerClass();
+ const auto cpp_class = func->ownerClass();
if (cpp_class)
- code.replace(QLatin1String("%TYPE"), cpp_class->name());
+ code.replace(u"%TYPE"_s, cpp_class->name());
const AbstractMetaArgumentList &argument = func->arguments();
for (const AbstractMetaArgument &arg : argument)
- code.replace(QLatin1Char('%') + QString::number(arg.argumentIndex() + 1), arg.name());
+ code.replace(u'%' + QString::number(arg.argumentIndex() + 1), arg.name());
//template values
- code.replace(QLatin1String("%RETURN_TYPE"), translateType(func->type(), cpp_class));
- code.replace(QLatin1String("%FUNCTION_NAME"), func->originalName());
+ code.replace(u"%RETURN_TYPE"_s, translateType(func->type(), cpp_class));
+ code.replace(u"%FUNCTION_NAME"_s, func->originalName());
- if (code.contains(QLatin1String("%ARGUMENT_NAMES"))) {
+ if (code.contains(u"%ARGUMENT_NAMES")) {
StringStream aux_stream;
writeArgumentNames(aux_stream, func, Generator::SkipRemovedArguments);
- code.replace(QLatin1String("%ARGUMENT_NAMES"), aux_stream);
+ code.replace(u"%ARGUMENT_NAMES"_s, aux_stream);
}
- if (code.contains(QLatin1String("%ARGUMENTS"))) {
+ if (code.contains(u"%ARGUMENTS")) {
StringStream aux_stream;
writeFunctionArguments(aux_stream, func, Options(SkipDefaultValues) | SkipRemovedArguments);
- code.replace(QLatin1String("%ARGUMENTS"), aux_stream);
+ code.replace(u"%ARGUMENTS"_s, aux_stream);
}
}
+
+QString ShibokenGenerator::stdMove(const QString &c)
+{
+ return u"std::move("_s + c + u')';
+}