aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/generator
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/generator')
-rw-r--r--sources/shiboken2/generator/CMakeLists.txt30
-rw-r--r--sources/shiboken2/generator/__init__.py.in2
-rw-r--r--sources/shiboken2/generator/_config.py.in9
-rw-r--r--sources/shiboken2/generator/generator.cpp413
-rw-r--r--sources/shiboken2/generator/generator.h182
-rw-r--r--sources/shiboken2/generator/main.cpp329
-rw-r--r--sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp132
-rw-r--r--sources/shiboken2/generator/qtdoc/qtdocgenerator.h6
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp706
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.h15
-rw-r--r--sources/shiboken2/generator/shiboken2/headergenerator.cpp145
-rw-r--r--sources/shiboken2/generator/shiboken2/headergenerator.h4
-rw-r--r--sources/shiboken2/generator/shiboken2/overloaddata.cpp18
-rw-r--r--sources/shiboken2/generator/shiboken2/overloaddata.h2
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp451
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.h284
16 files changed, 1483 insertions, 1245 deletions
diff --git a/sources/shiboken2/generator/CMakeLists.txt b/sources/shiboken2/generator/CMakeLists.txt
index 032118666..fb8058b2d 100644
--- a/sources/shiboken2/generator/CMakeLists.txt
+++ b/sources/shiboken2/generator/CMakeLists.txt
@@ -38,3 +38,33 @@ target_link_libraries(shiboken2
configure_file(shibokenconfig.h.in "${CMAKE_CURRENT_BINARY_DIR}/shibokenconfig.h" @ONLY)
install(TARGETS shiboken2 DESTINATION bin)
+
+set(shiboken_generator_package_name "shiboken2_generator")
+
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/_config.py.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/_config.py" @ONLY)
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/_config.py"
+ DESTINATION "${PYTHON_SITE_PACKAGES}/${shiboken_generator_package_name}")
+
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/__init__.py.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/__init__.py" @ONLY)
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/__init__.py"
+ DESTINATION "${PYTHON_SITE_PACKAGES}/${shiboken_generator_package_name}")
+
+# shiboken2 setuptools entry point
+install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../shiboken_tool.py
+ DESTINATION bin
+ PERMISSIONS
+ OWNER_EXECUTE OWNER_WRITE OWNER_READ
+ GROUP_EXECUTE GROUP_READ
+ WORLD_EXECUTE WORLD_READ)
+
+# Use absolute path instead of relative path, to avoid ninja build errors due to
+# duplicate file dependency inconsistency.
+set(shiboken_version_relative_path "${CMAKE_CURRENT_SOURCE_DIR}/../shiboken_version.py")
+get_filename_component(shiboken_version_path ${shiboken_version_relative_path} ABSOLUTE)
+configure_file("${shiboken_version_path}"
+ "${CMAKE_CURRENT_BINARY_DIR}/_git_shiboken_generator_version.py" @ONLY)
+
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/_git_shiboken_generator_version.py"
+ DESTINATION "${PYTHON_SITE_PACKAGES}/${shiboken_generator_package_name}")
diff --git a/sources/shiboken2/generator/__init__.py.in b/sources/shiboken2/generator/__init__.py.in
new file mode 100644
index 000000000..4be6a833b
--- /dev/null
+++ b/sources/shiboken2/generator/__init__.py.in
@@ -0,0 +1,2 @@
+__version__ = "@FINAL_PACKAGE_VERSION@"
+__version_info__ = (@shiboken_MAJOR_VERSION@, @shiboken_MINOR_VERSION@, @shiboken_MICRO_VERSION@, "@shiboken_PRE_RELEASE_VERSION_TYPE@", "@shiboken_PRE_RELEASE_VERSION@")
diff --git a/sources/shiboken2/generator/_config.py.in b/sources/shiboken2/generator/_config.py.in
new file mode 100644
index 000000000..985735fa4
--- /dev/null
+++ b/sources/shiboken2/generator/_config.py.in
@@ -0,0 +1,9 @@
+version = "@FINAL_PACKAGE_VERSION@"
+version_info = (@shiboken_MAJOR_VERSION@, @shiboken_MINOR_VERSION@, @shiboken_MICRO_VERSION@, "@shiboken_PRE_RELEASE_VERSION_TYPE@", "@shiboken_PRE_RELEASE_VERSION@")
+
+@PACKAGE_BUILD_DATE@
+@PACKAGE_BUILD_COMMIT_DATE@
+@PACKAGE_BUILD_COMMIT_HASH@
+@PACKAGE_BUILD_COMMIT_HASH_DESCRIBED@
+@PACKAGE_SETUP_PY_PACKAGE_TIMESTAMP_ASSIGNMENT@
+@PACKAGE_SETUP_PY_PACKAGE_VERSION_ASSIGNMENT@
diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp
index 1e2f03932..ec227bd83 100644
--- a/sources/shiboken2/generator/generator.cpp
+++ b/sources/shiboken2/generator/generator.cpp
@@ -28,6 +28,7 @@
#include "generator.h"
#include "abstractmetalang.h"
+#include "messages.h"
#include "reporthandler.h"
#include "fileout.h"
#include "apiextractor.h"
@@ -40,8 +41,118 @@
#include <QDebug>
#include <typedatabase.h>
-struct Generator::GeneratorPrivate {
- const ApiExtractor* apiextractor;
+/**
+ * DefaultValue is used for storing default values of types for which code is
+ * generated in different contexts:
+ *
+ * Context | Example: "Class *" | Example: "Class" with default Constructor
+ * --------------------+-------------------------------+------------------------------------------
+ * Variable | var{nullptr}; | var;
+ * initializations | |
+ * --------------------+-------------------------------+------------------------------------------
+ * Return values | return nullptr; | return {}
+ * --------------------+-------------------------------+------------------------------------------
+ * constructor | static_cast<Class *>(nullptr) | Class()
+ * arguments lists | |
+ * (recursive, precise | |
+ * matching). | |
+ */
+
+DefaultValue::DefaultValue(Type t, QString value) :
+ m_type(t), m_value(std::move(value))
+{
+}
+
+DefaultValue::DefaultValue(QString customValue) :
+ m_type(Custom), m_value(std::move(customValue))
+{
+}
+
+QString DefaultValue::returnValue() const
+{
+ switch (m_type) {
+ case DefaultValue::Error:
+ return QLatin1String("#error");
+ case DefaultValue::Boolean:
+ return QLatin1String("false");
+ case DefaultValue::CppScalar:
+ return QLatin1String("0");
+ case DefaultValue::Custom:
+ case DefaultValue::Enum:
+ return m_value;
+ case DefaultValue::Pointer:
+ return QLatin1String("nullptr");
+ case DefaultValue::Void:
+ return QString();
+ case DefaultValue::DefaultConstructorWithDefaultValues:
+ return m_value + QLatin1String("()");
+ case DefaultValue::DefaultConstructor:
+ break;
+ }
+ return QLatin1String("{}");
+}
+
+QString DefaultValue::initialization() const
+{
+ switch (m_type) {
+ case DefaultValue::Error:
+ return QLatin1String("#error");
+ case DefaultValue::Boolean:
+ return QLatin1String("{false}");
+ case DefaultValue::CppScalar:
+ return QLatin1String("{0}");
+ case DefaultValue::Custom:
+ return QLatin1String(" = ") + m_value;
+ case DefaultValue::Enum:
+ return QLatin1Char('{') + m_value + QLatin1Char('}');
+ case DefaultValue::Pointer:
+ return QLatin1String("{nullptr}");
+ case DefaultValue::Void:
+ Q_ASSERT(false);
+ break;
+ case DefaultValue::DefaultConstructor:
+ case DefaultValue::DefaultConstructorWithDefaultValues:
+ break;
+ }
+ return QString();
+}
+
+QString DefaultValue::constructorParameter() const
+{
+ switch (m_type) {
+ case DefaultValue::Error:
+ return QLatin1String("#error");
+ case DefaultValue::Boolean:
+ return QLatin1String("false");
+ case DefaultValue::CppScalar: {
+ // PYSIDE-846: Use static_cast in case of "unsigned long" and similar
+ const QString cast = m_value.contains(QLatin1Char(' '))
+ ? QLatin1String("static_cast<") + m_value + QLatin1Char('>')
+ : m_value;
+ return cast + QLatin1String("(0)");
+ }
+ case DefaultValue::Custom:
+ case DefaultValue::Enum:
+ return m_value;
+ case DefaultValue::Pointer:
+ // Be precise here to be able to differentiate between constructors
+ // taking different pointer types, cf
+ // QTreeWidgetItemIterator(QTreeWidget *) and
+ // QTreeWidgetItemIterator(QTreeWidgetItemIterator *).
+ return QLatin1String("static_cast<") + m_value + QLatin1String("*>(nullptr)");
+ case DefaultValue::Void:
+ Q_ASSERT(false);
+ break;
+ case DefaultValue::DefaultConstructor:
+ case DefaultValue::DefaultConstructorWithDefaultValues:
+ break;
+ }
+ return m_value + QLatin1String("()");
+}
+
+struct Generator::GeneratorPrivate
+{
+ const ApiExtractor* apiextractor = nullptr;
QString outDir;
// License comment
QString licenseComment;
@@ -62,20 +173,17 @@ Generator::~Generator()
delete m_d;
}
-bool Generator::setup(const ApiExtractor& extractor, const QMap< QString, QString > args)
+bool Generator::setup(const ApiExtractor& extractor)
{
m_d->apiextractor = &extractor;
- TypeEntryHash allEntries = TypeDatabase::instance()->allEntries();
+ const auto &allEntries = TypeDatabase::instance()->entries();
TypeEntry* entryFound = 0;
- for (TypeEntryHash::const_iterator it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) {
- for (TypeEntry *entry : it.value()) {
- if (entry->type() == TypeEntry::TypeSystemType && entry->generateCode()) {
- entryFound = entry;
- break;
- }
- }
- if (entryFound)
+ for (auto it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) {
+ TypeEntry *entry = it.value();
+ if (entry->type() == TypeEntry::TypeSystemType && entry->generateCode()) {
+ entryFound = entry;
break;
+ }
}
if (entryFound)
m_d->packageName = entryFound->name();
@@ -84,7 +192,7 @@ bool Generator::setup(const ApiExtractor& extractor, const QMap< QString, QStrin
collectInstantiatedContainersAndSmartPointers();
- return doSetup(args);
+ return doSetup();
}
QString Generator::getSimplifiedContainerTypeName(const AbstractMetaType* type)
@@ -197,6 +305,11 @@ Generator::OptionDescriptions Generator::options() const
return OptionDescriptions();
}
+bool Generator::handleOption(const QString & /* key */, const QString & /* value */)
+{
+ return false;
+}
+
AbstractMetaClassList Generator::classes() const
{
return m_d->apiextractor->classes();
@@ -227,24 +340,14 @@ ContainerTypeEntryList Generator::containerTypes() const
return m_d->apiextractor->containerTypes();
}
-const AbstractMetaEnum* Generator::findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const
-{
- return m_d->apiextractor->findAbstractMetaEnum(typeEntry);
-}
-
const AbstractMetaEnum* Generator::findAbstractMetaEnum(const TypeEntry* typeEntry) const
{
return m_d->apiextractor->findAbstractMetaEnum(typeEntry);
}
-const AbstractMetaEnum* Generator::findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const
-{
- return m_d->apiextractor->findAbstractMetaEnum(typeEntry);
-}
-
const AbstractMetaEnum* Generator::findAbstractMetaEnum(const AbstractMetaType* metaType) const
{
- return m_d->apiextractor->findAbstractMetaEnum(metaType);
+ return m_d->apiextractor->findAbstractMetaEnum(metaType->typeEntry());
}
QString Generator::licenseComment() const
@@ -278,21 +381,6 @@ void Generator::setOutputDirectory(const QString &outDir)
m_d->outDir = outDir;
}
-inline void touchFile(const QString &filePath)
-{
- QFile toucher(filePath);
- qint64 size = toucher.size();
- if (!toucher.open(QIODevice::ReadWrite)) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("Failed to touch file '%1'")
- .arg(QDir::toNativeSeparators(filePath));
- return;
- }
- toucher.resize(size+1);
- toucher.resize(size);
- toucher.close();
-}
-
bool Generator::generateFileForContext(GeneratorContext &context)
{
AbstractMetaClass *cls = context.metaClass();
@@ -312,20 +400,7 @@ bool Generator::generateFileForContext(GeneratorContext &context)
generateClass(fileOut.stream, context);
- FileOut::State state = fileOut.done();
- switch (state) {
- case FileOut::Failure:
- return false;
- case FileOut::Unchanged:
- // Even if contents is unchanged, the last file modification time should be updated,
- // so that the build system can rely on the fact the generated file is up-to-date.
- touchFile(filePath);
- break;
- case FileOut::Success:
- break;
- }
-
- return true;
+ return fileOut.done() != FileOut::Failure;
}
QString Generator::getFileNameBaseForSmartPointer(const AbstractMetaType *smartPointerType,
@@ -369,9 +444,9 @@ bool Generator::shouldGenerate(const AbstractMetaClass* metaClass) const
return shouldGenerateTypeEntry(metaClass->typeEntry());
}
-void verifyDirectoryFor(const QFile &file)
+void verifyDirectoryFor(const QString &file)
{
- QDir dir = QFileInfo(file).dir();
+ QDir dir = QFileInfo(file).absoluteDir();
if (!dir.exists()) {
if (!dir.mkpath(dir.absolutePath())) {
qCWarning(lcShiboken).noquote().nospace()
@@ -463,7 +538,7 @@ AbstractMetaFunctionList Generator::implicitConversions(const AbstractMetaType*
bool Generator::isObjectType(const TypeEntry* type)
{
if (type->isComplex())
- return Generator::isObjectType((const ComplexTypeEntry*)type);
+ return Generator::isObjectType(static_cast<const ComplexTypeEntry *>(type));
return type->isObject();
}
bool Generator::isObjectType(const ComplexTypeEntry* type)
@@ -557,184 +632,178 @@ QString Generator::getFullTypeNameWithoutModifiers(const AbstractMetaType* type)
return QLatin1String("::") + typeName;
}
-QString Generator::minimalConstructor(const AbstractMetaType* type) const
+DefaultValue Generator::minimalConstructor(const AbstractMetaType* type) const
{
if (!type || (type->referenceType() == LValueReference && Generator::isObjectType(type)))
- return QString();
+ return DefaultValue(DefaultValue::Error);
if (type->isContainer()) {
QString ctor = type->cppSignature();
- if (ctor.endsWith(QLatin1Char('*')))
- return QLatin1String("0");
+ if (ctor.endsWith(QLatin1Char('*'))) {
+ ctor.chop(1);
+ return DefaultValue(DefaultValue::Pointer, ctor.trimmed());
+ }
if (ctor.startsWith(QLatin1String("const ")))
ctor.remove(0, sizeof("const ") / sizeof(char) - 1);
if (ctor.endsWith(QLatin1Char('&'))) {
ctor.chop(1);
ctor = ctor.trimmed();
}
- return QLatin1String("::") + ctor + QLatin1String("()");
+ return DefaultValue(DefaultValue::DefaultConstructor, QLatin1String("::") + ctor);
}
if (type->isNativePointer())
- return QLatin1String("static_cast<") + type->typeEntry()->qualifiedCppName() + QLatin1String(" *>(0)");
+ return DefaultValue(DefaultValue::Pointer, type->typeEntry()->qualifiedCppName());
if (Generator::isPointer(type))
- return QLatin1String("static_cast< ::") + type->typeEntry()->qualifiedCppName() + QLatin1String(" *>(0)");
+ return DefaultValue(DefaultValue::Pointer, QLatin1String("::") + type->typeEntry()->qualifiedCppName());
if (type->typeEntry()->isComplex()) {
- const ComplexTypeEntry* cType = reinterpret_cast<const ComplexTypeEntry*>(type->typeEntry());
- QString ctor = cType->defaultConstructor();
- if (!ctor.isEmpty())
- return ctor;
- ctor = minimalConstructor(AbstractMetaClass::findClass(classes(), cType));
- if (type->hasInstantiations())
- ctor = ctor.replace(getFullTypeName(cType), getFullTypeNameWithoutModifiers(type));
+ const ComplexTypeEntry* cType = static_cast<const ComplexTypeEntry*>(type->typeEntry());
+ if (cType->hasDefaultConstructor())
+ return DefaultValue(DefaultValue::Custom, cType->defaultConstructor());
+ auto ctor = minimalConstructor(AbstractMetaClass::findClass(classes(), cType));
+ if (ctor.isValid() && type->hasInstantiations()) {
+ QString v = ctor.value();
+ v.replace(getFullTypeName(cType), getFullTypeNameWithoutModifiers(type));
+ ctor.setValue(v);
+ }
return ctor;
}
return minimalConstructor(type->typeEntry());
}
-QString Generator::minimalConstructor(const TypeEntry* type) const
+DefaultValue Generator::minimalConstructor(const TypeEntry* type) const
{
if (!type)
- return QString();
+ return DefaultValue(DefaultValue::Error);
if (type->isCppPrimitive()) {
const QString &name = type->qualifiedCppName();
return name == QLatin1String("bool")
- ? QLatin1String("false") : name + QLatin1String("(0)");
+ ? DefaultValue(DefaultValue::Boolean)
+ : DefaultValue(DefaultValue::CppScalar, name);
}
- if (type->isEnum())
- return QLatin1String("static_cast< ::") + type->qualifiedCppName() + QLatin1String(">(0)");
+ if (type->isEnum()) {
+ const auto enumEntry = static_cast<const EnumTypeEntry *>(type);
+ if (const auto *nullValue = enumEntry->nullValue())
+ return DefaultValue(DefaultValue::Enum, nullValue->name());
+ return DefaultValue(DefaultValue::Custom,
+ QLatin1String("static_cast< ::") + type->qualifiedCppName()
+ + QLatin1String(">(0)"));
+ }
- if (type->isFlags())
- return type->qualifiedCppName() + QLatin1String("(0)");
+ if (type->isFlags()) {
+ return DefaultValue(DefaultValue::Custom,
+ type->qualifiedCppName() + QLatin1String("(0)"));
+ }
if (type->isPrimitive()) {
- QString ctor = reinterpret_cast<const PrimitiveTypeEntry*>(type)->defaultConstructor();
+ QString ctor = static_cast<const PrimitiveTypeEntry*>(type)->defaultConstructor();
// If a non-C++ (i.e. defined by the user) primitive type does not have
// a default constructor defined by the user, the empty constructor is
// heuristically returned. If this is wrong the build of the generated
// bindings will tell.
return ctor.isEmpty()
- ? (QLatin1String("::") + type->qualifiedCppName() + QLatin1String("()"))
- : ctor;
+ ? DefaultValue(DefaultValue::DefaultConstructorWithDefaultValues, QLatin1String("::")
+ + type->qualifiedCppName())
+ : DefaultValue(DefaultValue::Custom, ctor);
}
if (type->isComplex())
return minimalConstructor(AbstractMetaClass::findClass(classes(), type));
- return QString();
+ return DefaultValue(DefaultValue::Error);
}
-QString Generator::minimalConstructor(const AbstractMetaClass* metaClass) const
+static QString constructorCall(const QString &qualifiedCppName, const QStringList &args)
+{
+ return QLatin1String("::") + qualifiedCppName + QLatin1Char('(')
+ + args.join(QLatin1String(", ")) + QLatin1Char(')');
+}
+
+DefaultValue Generator::minimalConstructor(const AbstractMetaClass* metaClass) const
{
if (!metaClass)
- return QString();
+ return DefaultValue(DefaultValue::Error);
- const ComplexTypeEntry* cType = reinterpret_cast<const ComplexTypeEntry*>(metaClass->typeEntry());
+ const ComplexTypeEntry* cType = static_cast<const ComplexTypeEntry*>(metaClass->typeEntry());
if (cType->hasDefaultConstructor())
- return cType->defaultConstructor();
+ return DefaultValue(DefaultValue::Custom, cType->defaultConstructor());
+ const QString qualifiedCppName = cType->qualifiedCppName();
+ // Obtain a list of constructors sorted by complexity and number of arguments
+ QMultiMap<int, const AbstractMetaFunction *> candidates;
const AbstractMetaFunctionList &constructors = metaClass->queryFunctions(AbstractMetaClass::Constructors);
- int maxArgs = 0;
for (const AbstractMetaFunction *ctor : constructors) {
- if (ctor->isUserAdded() || ctor->isPrivate() || ctor->functionType() != AbstractMetaFunction::ConstructorFunction)
- continue;
-
- int numArgs = ctor->arguments().size();
- if (numArgs == 0) {
- maxArgs = 0;
- break;
- }
- if (numArgs > maxArgs)
- maxArgs = numArgs;
- }
-
- QString qualifiedCppName = metaClass->typeEntry()->qualifiedCppName();
- QStringList templateTypes;
- const QVector<TypeEntry *> &templateArguments = metaClass->templateArguments();
- for (TypeEntry *templateType : templateArguments)
- templateTypes << templateType->qualifiedCppName();
-
- // Empty constructor.
- if (maxArgs == 0)
- return QLatin1String("::") + qualifiedCppName + QLatin1String("()");
-
- QVector<const AbstractMetaFunction *> candidates;
-
- // Constructors with C++ primitive types, enums or pointers only.
- // Start with the ones with fewer arguments.
- for (int i = 1; i <= maxArgs; ++i) {
- for (const AbstractMetaFunction *ctor : constructors) {
- if (ctor->isUserAdded() || ctor->isPrivate() || ctor->functionType() != AbstractMetaFunction::ConstructorFunction)
- continue;
-
- const AbstractMetaArgumentList &arguments = ctor->arguments();
- if (arguments.size() != i)
- continue;
-
- QStringList args;
- for (const AbstractMetaArgument *arg : arguments) {
- const TypeEntry* type = arg->type()->typeEntry();
- if (type == metaClass->typeEntry()) {
- args.clear();
- break;
- }
-
- if (!arg->originalDefaultValueExpression().isEmpty()) {
- if (!arg->defaultValueExpression().isEmpty()
- && arg->defaultValueExpression() != arg->originalDefaultValueExpression()) {
- args << arg->defaultValueExpression();
- }
- break;
- }
-
- if (type->isCppPrimitive() || type->isEnum() || isPointer(arg->type())) {
- QString argValue = minimalConstructor(arg->type());
- if (argValue.isEmpty()) {
- args.clear();
- break;
- }
- args << argValue;
- } else {
- args.clear();
- break;
- }
+ if (!ctor->isUserAdded() && !ctor->isPrivate()
+ && ctor->functionType() == AbstractMetaFunction::ConstructorFunction) {
+ // No arguments: Default constructible
+ const auto &arguments = ctor->arguments();
+ if (arguments.isEmpty()) {
+ return DefaultValue(DefaultValue::DefaultConstructor,
+ QLatin1String("::") + qualifiedCppName);
}
-
- if (!args.isEmpty())
- return QString::fromLatin1("::%1(%2)").arg(qualifiedCppName, args.join(QLatin1String(", ")));
-
- candidates << ctor;
+ // First argument has unmodified default: Default constructible with values
+ if (arguments.constFirst()->hasUnmodifiedDefaultValueExpression()) {
+ return DefaultValue(DefaultValue::DefaultConstructorWithDefaultValues,
+ QLatin1String("::") + qualifiedCppName);
+ }
+ // Examine arguments, exclude functions taking a self parameter
+ bool simple = true;
+ bool suitable = true;
+ for (int i = 0, size = arguments.size();
+ suitable && i < size && !arguments.at(i)->hasDefaultValueExpression(); ++i) {
+ const AbstractMetaArgument *arg = arguments.at(i);
+ const TypeEntry *aType = arg->type()->typeEntry();
+ suitable &= aType != cType;
+ simple &= aType->isCppPrimitive() || aType->isEnum() || isPointer(arg->type());
+ }
+ if (suitable)
+ candidates.insert(arguments.size() + (simple ? 0 : 100), ctor);
}
}
- // Constructors with C++ primitive types, enums, pointers, value types,
- // and user defined primitive types.
- // Builds the minimal constructor recursively.
- for (const AbstractMetaFunction *ctor : qAsConst(candidates)) {
+ for (auto it = candidates.cbegin(), end = candidates.cend(); it != end; ++it) {
+ const AbstractMetaArgumentList &arguments = it.value()->arguments();
QStringList args;
- const AbstractMetaArgumentList &arguments = ctor->arguments();
- for (const AbstractMetaArgument *arg : arguments) {
- if (arg->type()->typeEntry() == metaClass->typeEntry()) {
- args.clear();
- break;
- }
- QString argValue = minimalConstructor(arg->type());
- if (argValue.isEmpty()) {
- args.clear();
+ bool ok = true;
+ for (int i =0, size = arguments.size(); ok && i < size; ++i) {
+ const AbstractMetaArgument *arg = arguments.at(i);
+ if (arg->hasDefaultValueExpression()) {
+ if (arg->hasModifiedDefaultValueExpression())
+ args << arg->defaultValueExpression(); // Spell out modified values
break;
}
- args << argValue;
- }
- if (!args.isEmpty()) {
- return QString::fromLatin1("::%1(%2)").arg(qualifiedCppName, args.join(QLatin1String(", ")));
+ auto argValue = minimalConstructor(arg->type());
+ ok &= argValue.isValid();
+ args << argValue.constructorParameter();
}
+ if (ok)
+ return DefaultValue(DefaultValue::Custom, constructorCall(qualifiedCppName, args));
}
- return QString();
+ return DefaultValue(DefaultValue::Error);
+}
+
+// Should int be used for a (protected) enum when generating the public wrapper?
+bool Generator::useEnumAsIntForProtectedHack(const AbstractMetaType *metaType) const
+{
+ if (metaType->isFlags())
+ return true;
+ if (!metaType->isEnum())
+ return false;
+ const AbstractMetaEnum *metaEnum = findAbstractMetaEnum(metaType);
+ if (!metaEnum)
+ return true;
+ if (metaEnum->attributes() & AbstractMetaAttributes::Public) // No reason, type is public
+ return false;
+ // Only ordinary C-enums can be used as int, scoped enums fail when used
+ // as function arguments.
+ if (metaEnum->enumKind() == EnumKind::EnumClass)
+ qWarning(lcShiboken, "%s", qPrintable(msgCannotUseEnumAsInt(metaEnum->name())));
+ return true;
}
QString Generator::translateType(const AbstractMetaType *cType,
@@ -754,7 +823,7 @@ QString Generator::translateType(const AbstractMetaType *cType,
s = QLatin1String("void");
} else if (cType->isArray()) {
s = translateType(cType->arrayElementType(), context, options) + QLatin1String("[]");
- } else if (options & Generator::EnumAsInts && (cType->isEnum() || cType->isFlags())) {
+ } else if ((options & Generator::EnumAsInts) && useEnumAsIntForProtectedHack(cType)) {
s = QLatin1String("int");
} else {
if (options & Generator::OriginalName) {
diff --git a/sources/shiboken2/generator/generator.h b/sources/shiboken2/generator/generator.h
index 010ed868c..225e7aec7 100644
--- a/sources/shiboken2/generator/generator.h
+++ b/sources/shiboken2/generator/generator.h
@@ -57,7 +57,7 @@ class ContainerTypeEntry;
class Indentor;
QTextStream& formatCode(QTextStream &s, const QString& code, Indentor &indentor);
-void verifyDirectoryFor(const QFile &file);
+void verifyDirectoryFor(const QString &file);
QString getClassTargetFullName(const AbstractMetaClass* metaClass, bool includePackageName = true);
QString getClassTargetFullName(const AbstractMetaEnum* metaEnum, bool includePackageName = true);
@@ -95,6 +95,42 @@ const int alwaysGenerateDestructor = 1;
const int alwaysGenerateDestructor = 0;
#endif
+class DefaultValue
+{
+public:
+ enum Type
+ {
+ Error,
+ Boolean,
+ CppScalar, // A C++ scalar type (int,..) specified by value()
+ Custom, // A custom constructor/expression, uses value() as is
+ DefaultConstructor, // For classes named value()
+ DefaultConstructorWithDefaultValues, // as DefaultConstructor, but can't return {} though.
+ Enum, // Enum value as specified by value()
+ Pointer, // Pointer of type value()
+ Void // "", for return values only
+ };
+
+ explicit DefaultValue(Type t = Error, QString value = QString());
+ explicit DefaultValue(QString customValue);
+
+ bool isValid() const { return m_type != Error; }
+
+ QString returnValue() const;
+ QString initialization() const;
+ QString constructorParameter() const;
+
+ QString value() const { return m_value; }
+ void setValue(const QString &value) { m_value = value; }
+
+ Type type() const { return m_type; }
+ void setType(Type type) { m_type = type; }
+
+private:
+ Type m_type;
+ QString m_value;
+};
+
/**
* A GeneratorContext object contains a pointer to an AbstractMetaClass and/or a specialized
* AbstractMetaType, for which code is currently being generated.
@@ -166,13 +202,74 @@ public:
Generator();
virtual ~Generator();
- bool setup(const ApiExtractor& extractor, const QMap<QString, QString> args);
+ bool setup(const ApiExtractor& extractor);
virtual OptionDescriptions options() const;
+ virtual bool handleOption(const QString &key, const QString &value);
/// Returns the classes used to generate the binding code.
AbstractMetaClassList classes() const;
+ /// Returns the output directory
+ QString outputDirectory() const;
+
+ /// Set the output directory
+ void setOutputDirectory(const QString &outDir);
+
+ /**
+ * Start the code generation, be sure to call setClasses before callign this method.
+ * For each class it creates a QTextStream, call the write method with the current
+ * class and the associated text stream, then write the text stream contents if needed.
+ * \see #write
+ */
+ bool generate();
+
+ /// Returns the license comment to be prepended to each source file generated.
+ QString licenseComment() const;
+
+ /// Sets the license comment to be prepended to each source file generated.
+ void setLicenseComment(const QString &licenseComment);
+
+ /// Returns the generator's name. Used for cosmetic purposes.
+ virtual const char* name() const = 0;
+
+ /**
+ * Retrieves the name of the currently processed module.
+ * While package name is a complete package idetification, e.g. 'PySide.QtCore',
+ * a module name represents the last part of the package, e.g. 'QtCore'.
+ * If the target language separates the modules with characters other than
+ * dots ('.') the generator subclass must overload this method.
+ * \return a string representing the last part of a package name
+ */
+ QString moduleName() const;
+
+ /**
+ * Retrieves a list of constructors used in implicit conversions
+ * available on the given type. The TypeEntry must be a value-type
+ * or else it will return an empty list.
+ * \param type a TypeEntry that is expected to be a value-type
+ * \return a list of constructors that could be used as implicit converters
+ */
+ AbstractMetaFunctionList implicitConversions(const TypeEntry* type) const;
+
+ /// Convenience function for implicitConversions(const TypeEntry* type).
+ AbstractMetaFunctionList implicitConversions(const AbstractMetaType* metaType) const;
+
+ /// Check if type is a pointer.
+ static bool isPointer(const AbstractMetaType* type);
+
+ /// Tells if the type or class is an Object (or QObject) Type.
+ static bool isObjectType(const TypeEntry* type);
+ static bool isObjectType(const ComplexTypeEntry* type);
+ static bool isObjectType(const AbstractMetaType* metaType);
+ static bool isObjectType(const AbstractMetaClass* metaClass);
+
+ /// Returns true if the type is a C string (const char*).
+ static bool isCString(const AbstractMetaType* type);
+ /// Returns true if the type is a void pointer.
+ static bool isVoidPointer(const AbstractMetaType* type);
+
+protected:
/// Returns the classes, topologically ordered, used to generate the binding code.
///
/// The classes are ordered such that derived classes appear later in the list than
@@ -191,33 +288,12 @@ public:
/// Returns all container types found by APIExtractor
ContainerTypeEntryList containerTypes() const;
- /// Returns an AbstractMetaEnum for a given EnumTypeEntry, or NULL if not found.
- const AbstractMetaEnum* findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const;
-
/// Returns an AbstractMetaEnum for a given TypeEntry that is an EnumTypeEntry, or NULL if not found.
const AbstractMetaEnum* findAbstractMetaEnum(const TypeEntry* typeEntry) const;
- /// Returns an AbstractMetaEnum for the enum related to a given FlagsTypeEntry, or NULL if not found.
- const AbstractMetaEnum* findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const;
-
/// Returns an AbstractMetaEnum for a given AbstractMetaType that holds an EnumTypeEntry, or NULL if not found.
const AbstractMetaEnum* findAbstractMetaEnum(const AbstractMetaType* metaType) const;
- /// Returns the output directory
- QString outputDirectory() const;
-
- /// Set the output directory
- void setOutputDirectory(const QString &outDir);
-
- /**
- * Start the code generation, be sure to call setClasses before callign this method.
- * For each class it creates a QTextStream, call the write method with the current
- * class and the associated text stream, then write the text stream contents if needed.
- * \see #write
- */
- bool generate();
-
-
/// Generates a file for given AbstractMetaClass or AbstractMetaType (smart pointer case).
bool generateFileForContext(GeneratorContext &context);
@@ -225,9 +301,6 @@ public:
QString getFileNameBaseForSmartPointer(const AbstractMetaType *smartPointerType,
const AbstractMetaClass *smartPointerClass) const;
- /// Returns the generator's name. Used for cosmetic purposes.
- virtual const char* name() const = 0;
-
/// Returns true if the generator should generate any code for the TypeEntry.
bool shouldGenerateTypeEntry(const TypeEntry*) const;
@@ -266,56 +339,10 @@ public:
void replaceTemplateVariables(QString &code, const AbstractMetaFunction *func);
/**
- * Returns the license comment to be prepended to each source file generated.
- */
- QString licenseComment() const;
-
- /**
- * Sets the license comment to be prepended to each source file generated.
- */
- void setLicenseComment(const QString &licenseComment);
-
- /**
* Returns the package name.
*/
QString packageName() const;
- /**
- * Retrieves the name of the currently processed module.
- * While package name is a complete package idetification, e.g. 'PySide.QtCore',
- * a module name represents the last part of the package, e.g. 'QtCore'.
- * If the target language separates the modules with characters other than
- * dots ('.') the generator subclass must overload this method.
- * \return a string representing the last part of a package name
- */
- virtual QString moduleName() const;
-
- /**
- * Retrieves a list of constructors used in implicit conversions
- * available on the given type. The TypeEntry must be a value-type
- * or else it will return an empty list.
- * \param type a TypeEntry that is expected to be a value-type
- * \return a list of constructors that could be used as implicit converters
- */
- AbstractMetaFunctionList implicitConversions(const TypeEntry* type) const;
-
- /// Convenience function for implicitConversions(const TypeEntry* type).
- AbstractMetaFunctionList implicitConversions(const AbstractMetaType* metaType) const;
-
- /// Check if type is a pointer.
- static bool isPointer(const AbstractMetaType* type);
-
- /// Tells if the type or class is an Object (or QObject) Type.
- static bool isObjectType(const TypeEntry* type);
- static bool isObjectType(const ComplexTypeEntry* type);
- static bool isObjectType(const AbstractMetaType* metaType);
- static bool isObjectType(const AbstractMetaClass* metaClass);
-
- /// Returns true if the type is a C string (const char*).
- static bool isCString(const AbstractMetaType* type);
- /// Returns true if the type is a void pointer.
- static bool isVoidPointer(const AbstractMetaType* type);
-
// Returns the full name of the type.
QString getFullTypeName(const TypeEntry* type) const;
QString getFullTypeName(const AbstractMetaType* type) const;
@@ -333,11 +360,10 @@ public:
* It will check first for a user defined default constructor.
* Returns a null string if it fails.
*/
- QString minimalConstructor(const TypeEntry* type) const;
- QString minimalConstructor(const AbstractMetaType* type) const;
- QString minimalConstructor(const AbstractMetaClass* metaClass) const;
+ DefaultValue minimalConstructor(const TypeEntry* type) const;
+ DefaultValue minimalConstructor(const AbstractMetaType* type) const;
+ DefaultValue minimalConstructor(const AbstractMetaClass* metaClass) const;
-protected:
/**
* Returns the file name used to write the binding code of an AbstractMetaClass/Type.
* \param context the GeneratorContext which contains an AbstractMetaClass or AbstractMetaType
@@ -348,7 +374,7 @@ protected:
virtual QString fileNameForContext(GeneratorContext &context) const = 0;
- virtual bool doSetup(const QMap<QString, QString>& args) = 0;
+ virtual bool doSetup() = 0;
/**
* Write the bindding code for an AbstractMetaClass.
@@ -378,6 +404,8 @@ protected:
const QString &context);
private:
+ bool useEnumAsIntForProtectedHack(const AbstractMetaType *cType) const;
+
struct GeneratorPrivate;
GeneratorPrivate* m_d;
void collectInstantiatedContainersAndSmartPointers(const AbstractMetaFunction* func);
diff --git a/sources/shiboken2/generator/main.cpp b/sources/shiboken2/generator/main.cpp
index 0b7c15244..362191fd0 100644
--- a/sources/shiboken2/generator/main.cpp
+++ b/sources/shiboken2/generator/main.cpp
@@ -34,6 +34,9 @@
#include <QtCore/QDir>
#include <iostream>
#include <apiextractor.h>
+#include <fileout.h>
+#include <typedatabase.h>
+#include <messages.h>
#include "generator.h"
#include "shibokenconfig.h"
#include "cppgenerator.h"
@@ -41,9 +44,9 @@
#include "qtdocgenerator.h"
#ifdef _WINDOWS
- #define PATH_SPLITTER ";"
+static const QChar pathSplitter = QLatin1Char(';');
#else
- #define PATH_SPLITTER ":"
+static const QChar pathSplitter = QLatin1Char(':');
#endif
static inline QString languageLevelOption() { return QStringLiteral("language-level"); }
@@ -52,95 +55,12 @@ static inline QString frameworkIncludePathOption() { return QStringLiteral("fram
static inline QString systemIncludePathOption() { return QStringLiteral("system-include-paths"); }
static inline QString typesystemPathOption() { return QStringLiteral("typesystem-paths"); }
static inline QString helpOption() { return QStringLiteral("help"); }
-static const char helpHint[] = "Note: use --help or -h for more information.\n";
-
-namespace {
-
-class ArgsHandler
-{
-public:
- explicit ArgsHandler(const QMap<QString, QString>& other);
- virtual ~ArgsHandler();
-
- inline QMap<QString, QString>& args() const
- {
- return *m_args;
- }
-
- inline bool argExists(const QString& s) const
- {
- return m_args->contains(s);
- }
-
- QString removeArg(const QString& s);
- bool argExistsRemove(const QString& s);
+static inline QString diffOption() { return QStringLiteral("diff"); }
+static inline QString dryrunOption() { return QStringLiteral("dry-run"); }
- inline QString argValue(const QString& s) const
- {
- return m_args->value(s);
- }
-
- inline bool noArgs() const
- {
- return m_args->isEmpty();
- }
-
- QString errorMessage() const;
-
-private:
- QMap<QString, QString>* m_args;
-};
-
-ArgsHandler::ArgsHandler(const QMap<QString, QString>& other)
- : m_args(new QMap<QString, QString>(other))
-{
-}
-
-ArgsHandler::~ArgsHandler()
-{
- delete m_args;
-}
-
-QString ArgsHandler::removeArg(const QString& s)
-{
- QString retval;
-
- if (argExists(s)) {
- retval = argValue(s);
- m_args->remove(s);
- }
-
- return retval;
-}
-
-bool ArgsHandler::argExistsRemove(const QString& s)
-{
- bool retval = false;
-
- if (argExists(s)) {
- retval = true;
- m_args->remove(s);
- }
+static const char helpHint[] = "Note: use --help or -h for more information.\n";
- return retval;
-}
-
-QString ArgsHandler::errorMessage() const
-{
- typedef QMap<QString, QString>::ConstIterator StringMapConstIt;
-
- QString message;
- QTextStream str(&message);
- str << "shiboken: Called with wrong arguments:";
- for (StringMapConstIt it = m_args->cbegin(), end = m_args->cend(); it != end; ++it) {
- str << ' ' << it.key();
- if (!it.value().isEmpty())
- str << ' ' << it.value();
- }
- str << "\nCommand line: " << QCoreApplication::arguments().join(QLatin1Char(' '));
- return message;
-}
-}
+typedef QMap<QString, QString> CommandArgumentMap;
typedef Generator::OptionDescriptions OptionDescriptions;
@@ -214,18 +134,18 @@ static bool processProjectFile(QFile& projectFile, QMap<QString, QString>& args)
}
if (!includePaths.isEmpty())
- args.insert(includePathOption(), includePaths.join(QLatin1String(PATH_SPLITTER)));
+ args.insert(includePathOption(), includePaths.join(pathSplitter));
if (!frameworkIncludePaths.isEmpty())
args.insert(frameworkIncludePathOption(),
- frameworkIncludePaths.join(QLatin1String(PATH_SPLITTER)));
+ frameworkIncludePaths.join(pathSplitter));
if (!systemIncludePaths.isEmpty()) {
args.insert(systemIncludePathOption(),
- systemIncludePaths.join(QLatin1String(PATH_SPLITTER)));
+ systemIncludePaths.join(pathSplitter));
}
if (!typesystemPaths.isEmpty())
- args.insert(typesystemPathOption(), typesystemPaths.join(QLatin1String(PATH_SPLITTER)));
+ args.insert(typesystemPathOption(), typesystemPaths.join(pathSplitter));
if (!apiVersions.isEmpty())
args.insert(QLatin1String("api-version"), apiVersions.join(QLatin1Char('|')));
if (!languageLevel.isEmpty())
@@ -233,9 +153,9 @@ static bool processProjectFile(QFile& projectFile, QMap<QString, QString>& args)
return true;
}
-static QMap<QString, QString> getInitializedArguments()
+static CommandArgumentMap getInitializedArguments()
{
- QMap<QString, QString> args;
+ CommandArgumentMap args;
QStringList arguments = QCoreApplication::arguments();
QString appName = arguments.constFirst();
arguments.removeFirst();
@@ -277,11 +197,11 @@ static QMap<QString, QString> getInitializedArguments()
// Concatenate values of path arguments that can occur multiple times on the
// command line.
static void addPathOptionValue(const QString &option, const QString &value,
- QMap<QString, QString> &args)
+ CommandArgumentMap &args)
{
- const QMap<QString, QString>::iterator it = args.find(option);
+ const CommandArgumentMap::iterator it = args.find(option);
if (it != args.end())
- it.value().append(QLatin1String(PATH_SPLITTER) + value);
+ it.value().append(pathSplitter + value);
else
args.insert(option, value);
}
@@ -369,7 +289,9 @@ void printUsage()
s << "Usage:\n "
<< "shiboken [options] header-file typesystem-file\n\n"
<< "General options:\n";
- const QString pathSyntax = QLatin1String("<path>[" PATH_SPLITTER "<path>" PATH_SPLITTER "...]");
+ QString pathSyntax;
+ QTextStream(&pathSyntax) << "<path>[" << pathSplitter << "<path>"
+ << pathSplitter << "...]";
OptionDescriptions generalOptions = OptionDescriptions()
<< qMakePair(QLatin1String("api-version=<\"package mask\">,<\"version\">"),
QLatin1String("Specify the supported api version used to generate the bindings"))
@@ -380,18 +302,22 @@ void printUsage()
<< qMakePair(QLatin1String("drop-type-entries=\"<TypeEntry0>[;TypeEntry1;...]\""),
QLatin1String("Semicolon separated list of type system entries (classes, namespaces,\n"
"global functions and enums) to be dropped from generation."))
- << qMakePair(QLatin1String("-F") + pathSyntax, QString())
+ << qMakePair(QLatin1String("-F<path>"), QString())
<< qMakePair(QLatin1String("framework-include-paths=") + pathSyntax,
QLatin1String("Framework include paths used by the C++ parser"))
- << qMakePair(QLatin1String("-isystem") + pathSyntax, QString())
+ << qMakePair(QLatin1String("-isystem<path>"), QString())
<< qMakePair(QLatin1String("system-include-paths=") + pathSyntax,
QLatin1String("System include paths used by the C++ parser"))
<< qMakePair(QLatin1String("generator-set=<\"generator module\">"),
QLatin1String("generator-set to be used. e.g. qtdoc"))
+ << qMakePair(diffOption(),
+ QLatin1String("Print a diff of wrapper files"))
+ << qMakePair(dryrunOption(),
+ QLatin1String("Dry run, do not generate wrapper files"))
<< qMakePair(QLatin1String("-h"), QString())
<< qMakePair(helpOption(),
QLatin1String("Display this help and exit"))
- << qMakePair(QLatin1String("-I") + pathSyntax, QString())
+ << qMakePair(QLatin1String("-I<path>"), QString())
<< qMakePair(QLatin1String("include-paths=") + pathSyntax,
QLatin1String("Include paths used by the C++ parser"))
<< qMakePair(languageLevelOption() + QLatin1String("=, -std=<level>"),
@@ -407,7 +333,7 @@ void printUsage()
"Replaces and overrides command line arguments"))
<< qMakePair(QLatin1String("silent"),
QLatin1String("Avoid printing any message"))
- << qMakePair(QLatin1String("-T") + pathSyntax, QString())
+ << qMakePair(QLatin1String("-T<path>"), QString())
<< qMakePair(QLatin1String("typesystem-paths=") + pathSyntax,
QLatin1String("Paths used when searching for typesystems"))
<< qMakePair(QLatin1String("version"),
@@ -438,19 +364,15 @@ static inline void errorPrint(const QString& s)
<< "\nCommand line: " << qPrintable(arguments.join(QLatin1Char(' '))) << '\n';
}
-static QString msgInvalidVersion(const QString &package, const QString &version)
-{
- return QLatin1String("Invalid version \"") + version
- + QLatin1String("\" specified for package ") + package + QLatin1Char('.');
-}
-
static void parseIncludePathOption(const QString &option, HeaderType headerType,
- ArgsHandler &args,
+ CommandArgumentMap &args,
ApiExtractor &extractor)
{
- const QString path = args.removeArg(option);
- if (!path.isEmpty()) {
- const QStringList includePathListList = path.split(QLatin1String(PATH_SPLITTER));
+ const CommandArgumentMap::iterator it = args.find(option);
+ if (it != args.end()) {
+ const QStringList includePathListList =
+ it.value().split(pathSplitter, QString::SkipEmptyParts);
+ args.erase(it);
for (const QString &s : includePathListList)
extractor.addIncludePath(HeaderPath{QFile::encodeName(s), headerType});
}
@@ -469,19 +391,24 @@ int main(int argc, char *argv[])
qCDebug(lcShiboken()).noquote().nospace() << QCoreApplication::arguments().join(QLatin1Char(' '));
// Store command arguments in a map
- QMap<QString, QString> args = getCommandLineArgs();
- ArgsHandler argsHandler(args);
+ CommandArgumentMap args = getCommandLineArgs();
Generators generators;
- if (argsHandler.argExistsRemove(QLatin1String("version"))) {
+ CommandArgumentMap::iterator ait = args.find(QLatin1String("version"));
+ if (ait != args.end()) {
+ args.erase(ait);
printVerAndBanner();
return EXIT_SUCCESS;
}
- QString generatorSet = argsHandler.removeArg(QLatin1String("generator-set"));
- // Also check QLatin1String("generatorSet") command line argument for backward compatibility.
- if (generatorSet.isEmpty())
- generatorSet = argsHandler.removeArg(QLatin1String("generatorSet"));
+ QString generatorSet;
+ ait = args.find(QLatin1String("generator-set"));
+ if (ait == args.end()) // Also check QLatin1String("generatorSet") command line argument for backward compatibility.
+ ait = args.find(QLatin1String("generatorSet"));
+ if (ait != args.end()) {
+ generatorSet = ait.value();
+ args.erase(ait);
+ }
// Pre-defined generator sets.
if (generatorSet == QLatin1String("qtdoc")) {
@@ -497,28 +424,45 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
- if (argsHandler.argExistsRemove(QLatin1String("help"))) {
+ ait = args.find(QLatin1String("help"));
+ if (ait != args.end()) {
+ args.erase(ait);
printUsage();
return EXIT_SUCCESS;
}
+ ait = args.find(diffOption());
+ if (ait != args.end()) {
+ args.erase(ait);
+ FileOut::diff = true;
+ }
+
+ ait = args.find(dryrunOption());
+ if (ait != args.end()) {
+ args.erase(ait);
+ FileOut::dummy = true;
+ }
+
QString licenseComment;
- QString licenseFileName = argsHandler.removeArg(QLatin1String("license-file"));
- if (!licenseFileName.isEmpty()) {
- if (QFile::exists(licenseFileName)) {
- QFile licenseFile(licenseFileName);
- if (licenseFile.open(QIODevice::ReadOnly))
- licenseComment = QString::fromUtf8(licenseFile.readAll());
+ ait = args.find(QLatin1String("license-file"));
+ if (ait != args.end()) {
+ QFile licenseFile(ait.value());
+ args.erase(ait);
+ if (licenseFile.open(QIODevice::ReadOnly)) {
+ licenseComment = QString::fromUtf8(licenseFile.readAll());
} else {
- errorPrint(QStringLiteral("Couldn't find the file containing the license heading: %1").
- arg(licenseFileName));
+ errorPrint(QStringLiteral("Could not open the file \"%1\" containing the license heading: %2").
+ arg(QDir::toNativeSeparators(licenseFile.fileName()), licenseFile.errorString()));
return EXIT_FAILURE;
}
}
- QString outputDirectory = argsHandler.removeArg(QLatin1String("output-directory"));
- if (outputDirectory.isEmpty())
- outputDirectory = QLatin1String("out");
+ QString outputDirectory = QLatin1String("out");
+ ait = args.find(QLatin1String("output-directory"));
+ if (ait != args.end()) {
+ outputDirectory = ait.value();
+ args.erase(ait);
+ }
if (!QDir(outputDirectory).exists()) {
if (!QDir().mkpath(outputDirectory)) {
@@ -532,11 +476,15 @@ int main(int argc, char *argv[])
ApiExtractor extractor;
extractor.setLogDirectory(outputDirectory);
- if (argsHandler.argExistsRemove(QLatin1String("silent"))) {
+ ait = args.find(QLatin1String("silent"));
+ if (ait != args.end()) {
extractor.setSilent(true);
+ args.erase(ait);
} else {
- QString level = argsHandler.removeArg(QLatin1String("debug-level"));
- if (!level.isEmpty()) {
+ ait = args.find(QLatin1String("debug-level"));
+ if (ait != args.end()) {
+ const QString level = ait.value();
+ args.erase(ait);
if (level == QLatin1String("sparse"))
extractor.setDebugLevel(ReportHandler::SparseDebug);
else if (level == QLatin1String("medium"))
@@ -545,11 +493,15 @@ int main(int argc, char *argv[])
extractor.setDebugLevel(ReportHandler::FullDebug);
}
}
- if (argsHandler.argExistsRemove(QLatin1String("no-suppress-warnings")))
+ ait = args.find(QLatin1String("no-suppress-warnings"));
+ if (ait != args.end()) {
+ args.erase(ait);
extractor.setSuppressWarnings(false);
-
- if (argsHandler.argExists(QLatin1String("api-version"))) {
- const QStringList &versions = argsHandler.removeArg(QLatin1String("api-version")).split(QLatin1Char('|'));
+ }
+ ait = args.find(QLatin1String("api-version"));
+ if (ait != args.end()) {
+ const QStringList &versions = ait.value().split(QLatin1Char('|'));
+ args.erase(ait);
for (const QString &fullVersion : versions) {
QStringList parts = fullVersion.split(QLatin1Char(','));
QString package;
@@ -563,54 +515,65 @@ int main(int argc, char *argv[])
}
}
- if (argsHandler.argExists(QLatin1String("drop-type-entries")))
- extractor.setDropTypeEntries(argsHandler.removeArg(QLatin1String("drop-type-entries")));
+ ait = args.find(QLatin1String("drop-type-entries"));
+ if (ait != args.end()) {
+ extractor.setDropTypeEntries(ait.value());
+ args.erase(ait);
+ }
- QString path = argsHandler.removeArg(QLatin1String("typesystem-paths"));
- if (!path.isEmpty())
- extractor.addTypesystemSearchPath(path.split(QLatin1String(PATH_SPLITTER)));
+ ait = args.find(QLatin1String("typesystem-paths"));
+ if (ait != args.end()) {
+ extractor.addTypesystemSearchPath(ait.value().split(pathSplitter));
+ args.erase(ait);
+ }
parseIncludePathOption(includePathOption(), HeaderType::Standard,
- argsHandler, extractor);
+ args, extractor);
parseIncludePathOption(frameworkIncludePathOption(), HeaderType::Framework,
- argsHandler, extractor);
+ args, extractor);
parseIncludePathOption(systemIncludePathOption(), HeaderType::System,
- argsHandler, extractor);
+ args, extractor);
- QString cppFileName = argsHandler.removeArg(QLatin1String("arg-1"));
+ ait = args.find(QLatin1String("arg-1"));
+ if (ait == args.end()) {
+ errorPrint(QLatin1String("Required argument header-file is missing."));
+ return EXIT_FAILURE;
+ }
+ const QString cppFileName = ait.value();
+ args.erase(ait);
const QFileInfo cppFileNameFi(cppFileName);
if (!cppFileNameFi.isFile() && !cppFileNameFi.isSymLink()) {
errorPrint(QLatin1Char('"') + cppFileName + QLatin1String("\" does not exist."));
return EXIT_FAILURE;
}
- QString typeSystemFileName = argsHandler.removeArg(QLatin1String("arg-2"));
+ ait = args.find(QLatin1String("arg-2"));
+ if (ait == args.end()) {
+ errorPrint(QLatin1String("Required argument typesystem-file is missing."));
+ return EXIT_FAILURE;
+ }
+ const QString typeSystemFileName = ait.value();
+ args.erase(ait);
QString messagePrefix = QFileInfo(typeSystemFileName).baseName();
if (messagePrefix.startsWith(QLatin1String("typesystem_")))
messagePrefix.remove(0, 11);
ReportHandler::setPrefix(QLatin1Char('(') + messagePrefix + QLatin1Char(')'));
- /* Make sure to remove the project file's arguments (if any) and
- * --project-file, also the arguments of each generator before
- * checking if there isn't any existing arguments in argsHandler.
- */
- argsHandler.removeArg(QLatin1String("project-file"));
- QMap<QString, QString> projectFileArgs = getInitializedArguments();
- if (!projectFileArgs.isEmpty()) {
- QMap<QString, QString>::const_iterator it =
- projectFileArgs.constBegin();
- for ( ; it != projectFileArgs.constEnd(); ++it)
- argsHandler.removeArg(it.key());
- }
- for (const GeneratorPtr &generator : qAsConst(generators)) {
- const OptionDescriptions &options = generator->options();
- for (const auto &od : options)
- argsHandler.removeArg(od.first);
- }
-
- const QString languageLevel = argsHandler.removeArg(languageLevelOption());
- if (!languageLevel.isEmpty()) {
- const QByteArray languageLevelBA = languageLevel.toLatin1();
+ // Pass option to all generators (Cpp/Header generator have the same options)
+ for (ait = args.begin(); ait != args.end(); ) {
+ bool found = false;
+ for (const GeneratorPtr &generator : qAsConst(generators))
+ found |= generator->handleOption(ait.key(), ait.value());
+ if (found)
+ ait = args.erase(ait);
+ else
+ ++ait;
+ }
+
+ ait = args.find(languageLevelOption());
+ if (ait != args.end()) {
+ const QByteArray languageLevelBA = ait.value().toLatin1();
+ args.erase(ait);
const LanguageLevel level = clang::languageLevelFromOption(languageLevelBA.constData());
if (level == LanguageLevel::Default) {
std::cout << "Invalid argument for language level: \""
@@ -620,8 +583,17 @@ int main(int argc, char *argv[])
extractor.setLanguageLevel(level);
}
- if (!argsHandler.noArgs()) {
- errorPrint(argsHandler.errorMessage());
+ /* Make sure to remove the project file's arguments (if any) and
+ * --project-file, also the arguments of each generator before
+ * checking if there isn't any existing arguments in argsHandler.
+ */
+ args.remove(QLatin1String("project-file"));
+ CommandArgumentMap projectFileArgs = getInitializedArguments();
+ for (auto it = projectFileArgs.cbegin(), end = projectFileArgs.cend(); it != end; ++it)
+ args.remove(it.key());
+
+ if (!args.isEmpty()) {
+ errorPrint(msgLeftOverArguments(args));
std::cout << helpHint;
return EXIT_FAILURE;
}
@@ -642,17 +614,16 @@ int main(int argc, char *argv[])
if (!extractor.classCount())
qCWarning(lcShiboken) << "No C++ classes found!";
- qCDebug(lcShiboken) << extractor;
+ qCDebug(lcShiboken) << extractor << '\n'
+ << *TypeDatabase::instance();
for (const GeneratorPtr &g : qAsConst(generators)) {
g->setOutputDirectory(outputDirectory);
g->setLicenseComment(licenseComment);
- if (g->setup(extractor, args)) {
- if (!g->generate()) {
- errorPrint(QLatin1String("Error running generator: ")
- + QLatin1String(g->name()) + QLatin1Char('.'));
- return EXIT_FAILURE;
- }
+ if (!g->setup(extractor) || !g->generate()) {
+ errorPrint(QLatin1String("Error running generator: ")
+ + QLatin1String(g->name()) + QLatin1Char('.'));
+ return EXIT_FAILURE;
}
}
diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp
index d47ba8bd7..19ddd5f37 100644
--- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp
+++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp
@@ -28,6 +28,7 @@
#include "qtdocgenerator.h"
#include <abstractmetalang.h>
+#include <messages.h>
#include <reporthandler.h>
#include <typesystem.h>
#include <qtdocparser.h>
@@ -202,34 +203,6 @@ private:
const QString &m_label;
};
-static QString msgTagWarning(const QXmlStreamReader &reader, const QString &context,
- const QString &tag, const QString &message)
-{
- QString result;
- QTextStream str(&result);
- str << "While handling <";
- const QStringRef currentTag = reader.name();
- if (currentTag.isEmpty())
- str << tag;
- else
- str << currentTag;
- str << "> in " << context << ", line "<< reader.lineNumber()
- << ": " << message;
- return result;
-}
-
-static QString msgFallbackWarning(const QXmlStreamReader &reader, const QString &context,
- const QString &tag, const QString &location, const QString &identifier,
- const QString &fallback)
-{
- QString message = QLatin1String("Falling back to \"")
- + QDir::toNativeSeparators(fallback) + QLatin1String("\" for \"") + location
- + QLatin1Char('"');
- if (!identifier.isEmpty())
- message += QLatin1String(" [") + identifier + QLatin1Char(']');
- return msgTagWarning(reader, context, tag, message);
-}
-
struct QtXmlToSphinx::LinkContext
{
enum Type
@@ -305,7 +278,7 @@ QTextStream &operator<<(QTextStream &str, const QtXmlToSphinx::LinkContext &link
}
QtXmlToSphinx::QtXmlToSphinx(QtDocGenerator* generator, const QString& doc, const QString& context)
- : m_context(context), m_generator(generator), m_insideBold(false), m_insideItalic(false)
+ : m_tableHasHeader(false), m_context(context), m_generator(generator), m_insideBold(false), m_insideItalic(false)
{
m_handlerMap.insert(QLatin1String("heading"), &QtXmlToSphinx::handleHeadingTag);
m_handlerMap.insert(QLatin1String("brief"), &QtXmlToSphinx::handleParaTag);
@@ -1302,7 +1275,7 @@ bool QtXmlToSphinx::convertToRst(QtDocGenerator *generator,
QFile sourceFile(sourceFileName);
if (!sourceFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
if (errorMessage)
- *errorMessage = FileOut::msgCannotOpenForReading(sourceFile);
+ *errorMessage = msgCannotOpenForReading(sourceFile);
return false;
}
const QString doc = QString::fromUtf8(sourceFile.readAll());
@@ -1325,7 +1298,13 @@ void QtXmlToSphinx::Table::normalize()
//QDoc3 generates tables with wrong number of columns. We have to
//check and if necessary, merge the last columns.
- int maxCols = self.at(0).count();
+ int maxCols = -1;
+ for (const auto &row : qAsConst(self)) {
+ if (row.count() > maxCols)
+ maxCols = row.count();
+ }
+ if (maxCols <= 0)
+ return;
// add col spans
for (row = 0; row < count(); ++row) {
for (col = 0; col < at(row).count(); ++col) {
@@ -1513,11 +1492,10 @@ QString QtDocGenerator::fileNameForContext(GeneratorContext &context) const
const AbstractMetaClass *metaClass = context.metaClass();
if (!context.forSmartPointer()) {
return getClassTargetFullName(metaClass, false) + fileNameSuffix();
- } else {
- const AbstractMetaType *smartPointerType = context.preciseType();
- QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass);
- return fileNameBase + fileNameSuffix();
}
+ const AbstractMetaType *smartPointerType = context.preciseType();
+ QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass);
+ return fileNameBase + fileNameSuffix();
}
void QtDocGenerator::writeFormattedText(QTextStream &s, const Documentation &doc,
@@ -1534,7 +1512,7 @@ void QtDocGenerator::writeFormattedText(QTextStream &s, const Documentation &doc
} else {
const QString &value = doc.value();
const QVector<QStringRef> lines = value.splitRef(QLatin1Char('\n'));
- int typesystemIndentation = std::numeric_limits<int>().max();
+ int typesystemIndentation = std::numeric_limits<int>::max();
// check how many spaces must be removed from the beginning of each line
for (const QStringRef &line : lines) {
const auto it = std::find_if(line.cbegin(), line.cend(),
@@ -1542,7 +1520,7 @@ void QtDocGenerator::writeFormattedText(QTextStream &s, const Documentation &doc
if (it != line.cend())
typesystemIndentation = qMin(typesystemIndentation, int(it - line.cbegin()));
}
- if (typesystemIndentation == std::numeric_limits<int>().max())
+ if (typesystemIndentation == std::numeric_limits<int>::max())
typesystemIndentation = 0;
for (const QStringRef &line : lines) {
s << INDENT
@@ -1677,7 +1655,7 @@ void QtDocGenerator::writeFunctionList(QTextStream& s, const AbstractMetaClass*
functionList << str;
}
- if ((functionList.size() > 0) || (staticFunctionList.size() > 0)) {
+ if (!functionList.isEmpty() || !staticFunctionList.isEmpty()) {
QtXmlToSphinx::Table functionTable;
s << endl
@@ -1694,7 +1672,7 @@ void QtDocGenerator::writeFunctionList(QTextStream& s, const AbstractMetaClass*
void QtDocGenerator::writeFunctionBlock(QTextStream& s, const QString& title, QStringList& functions)
{
- if (functions.size() > 0) {
+ if (!functions.isEmpty()) {
s << title << endl
<< QString(title.size(), QLatin1Char('^')) << endl;
@@ -1777,7 +1755,8 @@ void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass*
writeFormattedText(s, func->documentation(), cppClass);
}
-QString QtDocGenerator::parseArgDocStyle(const AbstractMetaClass* cppClass, const AbstractMetaFunction* func)
+QString QtDocGenerator::parseArgDocStyle(const AbstractMetaClass* /* cppClass */,
+ const AbstractMetaFunction* func)
{
QString ret;
int optArgs = 0;
@@ -1859,8 +1838,7 @@ void QtDocGenerator::writeDocSnips(QTextStream &s,
if (row.trimmed().size() == 0) {
if (currenRow == 0)
continue;
- else
- s << endl;
+ s << endl;
}
if (currenRow == 0) {
@@ -2124,7 +2102,7 @@ void QtDocGenerator::writeModuleDocumentation()
s << ".. module:: " << it.key() << endl << endl;
- QString title = it.key();
+ const QString &title = it.key();
s << title << endl;
s << Pad('*', title.length()) << endl << endl;
@@ -2201,7 +2179,7 @@ void QtDocGenerator::writeAdditionalDocumentation()
QFile additionalDocumentationFile(m_additionalDocumentationList);
if (!additionalDocumentationFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qCWarning(lcShiboken, "%s",
- qPrintable(FileOut::msgCannotOpenForReading(additionalDocumentationFile)));
+ qPrintable(msgCannotOpenForReading(additionalDocumentationFile)));
return;
}
@@ -2261,32 +2239,28 @@ void QtDocGenerator::writeAdditionalDocumentation()
successCount, count);
}
-bool QtDocGenerator::doSetup(const QMap<QString, QString>& args)
-{
- m_libSourceDir = args.value(QLatin1String("library-source-dir"));
- m_docDataDir = args.value(QLatin1String("documentation-data-dir"));
#ifdef __WIN32__
# define PATH_SEP ';'
#else
# define PATH_SEP ':'
#endif
- m_codeSnippetDirs = args.value(QLatin1String("documentation-code-snippets-dir"), m_libSourceDir).split(QLatin1Char(PATH_SEP));
- m_extraSectionDir = args.value(QLatin1String("documentation-extra-sections-dir"));
- m_docParser = args.value(QLatin1String("doc-parser")) == QLatin1String("doxygen")
- ? static_cast<DocParser*>(new DoxygenParser)
- : static_cast<DocParser*>(new QtDocParser);
- qCDebug(lcShiboken).noquote().nospace() << "doc-parser: " << args.value(QLatin1String("doc-parser"));
+bool QtDocGenerator::doSetup()
+{
+ if (m_codeSnippetDirs.isEmpty())
+ m_codeSnippetDirs = m_libSourceDir.split(QLatin1Char(PATH_SEP));
+
+ if (!m_docParser)
+ m_docParser = new QtDocParser;
if (m_libSourceDir.isEmpty() || m_docDataDir.isEmpty()) {
qCWarning(lcShiboken) << "Documentation data dir and/or Qt source dir not informed, "
"documentation will not be extracted from Qt sources.";
return false;
- } else {
- m_docParser->setDocumentationDataDirectory(m_docDataDir);
- m_docParser->setLibrarySourceDirectory(m_libSourceDir);
}
- m_additionalDocumentationList = args.value(additionalDocumentationOption());
+
+ m_docParser->setDocumentationDataDirectory(m_docDataDir);
+ m_docParser->setLibrarySourceDirectory(m_libSourceDir);
return true;
}
@@ -2294,19 +2268,49 @@ bool QtDocGenerator::doSetup(const QMap<QString, QString>& args)
Generator::OptionDescriptions QtDocGenerator::options() const
{
return OptionDescriptions()
- << qMakePair(QLatin1String("doc-parser"),
+ << qMakePair(QLatin1String("doc-parser=<parser>"),
QLatin1String("The documentation parser used to interpret the documentation\n"
"input files (qdoc|doxygen)"))
- << qMakePair(QLatin1String("documentation-code-snippets-dir"),
+ << qMakePair(QLatin1String("documentation-code-snippets-dir=<dir>"),
QLatin1String("Directory used to search code snippets used by the documentation"))
- << qMakePair(QLatin1String("documentation-data-dir"),
+ << qMakePair(QLatin1String("documentation-data-dir=<dir>"),
QLatin1String("Directory with XML files generated by documentation tool"))
- << qMakePair(QLatin1String("documentation-extra-sections-dir"),
+ << qMakePair(QLatin1String("documentation-extra-sections-dir=<dir>"),
QLatin1String("Directory used to search for extra documentation sections"))
- << qMakePair(QLatin1String("library-source-dir"),
+ << qMakePair(QLatin1String("library-source-dir=<dir>"),
QLatin1String("Directory where library source code is located"))
- << qMakePair(additionalDocumentationOption(),
+ << qMakePair(additionalDocumentationOption() + QLatin1String("=<file>"),
QLatin1String("List of additional XML files to be converted to .rst files\n"
"(for example, tutorials)."));
}
+bool QtDocGenerator::handleOption(const QString &key, const QString &value)
+{
+ if (key == QLatin1String("library-source-dir")) {
+ m_libSourceDir = value;
+ return true;
+ }
+ if (key == QLatin1String("documentation-data-dir")) {
+ m_docDataDir = value;
+ return true;
+ }
+ if (key == QLatin1String("documentation-code-snippets-dir")) {
+ m_codeSnippetDirs = value.split(QLatin1Char(PATH_SEP));
+ return true;
+ }
+ if (key == QLatin1String("documentation-extra-sections-dir")) {
+ m_extraSectionDir = value;
+ return true;
+ }
+ if (key == QLatin1String("doc-parser")) {
+ qCDebug(lcShiboken).noquote().nospace() << "doc-parser: " << value;
+ if (value == QLatin1String("doxygen"))
+ m_docParser = new DoxygenParser;
+ return true;
+ }
+ if (key == additionalDocumentationOption()) {
+ m_additionalDocumentationList = value;
+ return true;
+ }
+ return false;
+}
diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h
index e467abe90..5545de9a9 100644
--- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h
+++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h
@@ -209,7 +209,7 @@ public:
QString docDataDir() const { return m_docDataDir; }
- bool doSetup(const QMap<QString, QString>& args) override;
+ bool doSetup() override;
const char* name() const override
{
@@ -217,15 +217,15 @@ public:
}
OptionDescriptions options() const override;
+ bool handleOption(const QString &key, const QString &value) override;
QStringList codeSnippetDirs() const
{
return m_codeSnippetDirs;
}
- bool shouldGenerate(const AbstractMetaClass *) const override;
-
protected:
+ bool shouldGenerate(const AbstractMetaClass *) const override;
QString fileNameSuffix() const override;
QString fileNameForContext(GeneratorContext &context) const override;
void generateClass(QTextStream &s, GeneratorContext &classContext) override;
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index 9e1d6926e..adec70dd7 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -29,8 +29,10 @@
#include <memory>
#include "cppgenerator.h"
+#include "fileout.h"
#include "overloaddata.h"
#include <abstractmetalang.h>
+#include <messages.h>
#include <reporthandler.h>
#include <typedatabase.h>
@@ -41,6 +43,8 @@
#include <QtCore/QDebug>
#include <QMetaType>
+static const char CPP_ARG0[] = "cppArg0";
+
QHash<QString, QString> CppGenerator::m_nbFuncs = QHash<QString, QString>();
QHash<QString, QString> CppGenerator::m_sqFuncs = QHash<QString, QString>();
QHash<QString, QString> CppGenerator::m_mpFuncs = QHash<QString, QString>();
@@ -58,6 +62,28 @@ inline AbstractMetaType* getTypeWithoutContainer(AbstractMetaType* arg)
return arg;
}
+// A helper for writing C++ return statements for either void ("return;")
+// or some return value ("return value;")
+class returnStatement
+{
+public:
+ explicit returnStatement(QString s) : m_returnValue(std::move(s)) {}
+
+ friend QTextStream &operator<<(QTextStream &s, const returnStatement &r);
+
+private:
+ const QString m_returnValue;
+};
+
+QTextStream &operator<<(QTextStream &s, const returnStatement &r)
+{
+ s << "return";
+ if (!r.m_returnValue.isEmpty())
+ s << ' ' << r.m_returnValue;
+ s << ';';
+ return s;
+}
+
CppGenerator::CppGenerator()
{
// Number protocol structure members names
@@ -87,27 +113,27 @@ CppGenerator::CppGenerator()
m_nbFuncs.insert(QLatin1String("bool"), QLatin1String("nb_nonzero"));
// sequence protocol functions
- typedef QPair<QString, QString> StrPair;
m_sequenceProtocol.insert(QLatin1String("__len__"),
- StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR), QLatin1String("Py_ssize_t")));
+ {QLatin1String("PyObject* self"),
+ QLatin1String("Py_ssize_t")});
m_sequenceProtocol.insert(QLatin1String("__getitem__"),
- StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i"),
- QLatin1String("PyObject*")));
+ {QLatin1String("PyObject* self, Py_ssize_t _i"),
+ QLatin1String("PyObject*")});
m_sequenceProtocol.insert(QLatin1String("__setitem__"),
- StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i, PyObject* _value"),
- QLatin1String("int")));
+ {QLatin1String("PyObject* self, Py_ssize_t _i, PyObject* _value"),
+ QLatin1String("int")});
m_sequenceProtocol.insert(QLatin1String("__getslice__"),
- StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i1, Py_ssize_t _i2"),
- QLatin1String("PyObject*")));
+ {QLatin1String("PyObject* self, Py_ssize_t _i1, Py_ssize_t _i2"),
+ QLatin1String("PyObject*")});
m_sequenceProtocol.insert(QLatin1String("__setslice__"),
- StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i1, Py_ssize_t _i2, PyObject* _value"),
- QLatin1String("int")));
+ {QLatin1String("PyObject* self, Py_ssize_t _i1, Py_ssize_t _i2, PyObject* _value"),
+ QLatin1String("int")});
m_sequenceProtocol.insert(QLatin1String("__contains__"),
- StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", PyObject* _value"),
- QLatin1String("int")));
+ {QLatin1String("PyObject* self, PyObject* _value"),
+ QLatin1String("int")});
m_sequenceProtocol.insert(QLatin1String("__concat__"),
- StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", PyObject* _other"),
- QLatin1String("PyObject*")));
+ {QLatin1String("PyObject* self, PyObject* _other"),
+ QLatin1String("PyObject*")});
// Sequence protocol structure members names
m_sqFuncs.insert(QLatin1String("__concat__"), QLatin1String("sq_concat"));
@@ -120,14 +146,14 @@ CppGenerator::CppGenerator()
// mapping protocol function
m_mappingProtocol.insert(QLatin1String("__mlen__"),
- StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR),
- QLatin1String("Py_ssize_t")));
+ {QLatin1String("PyObject* self"),
+ QLatin1String("Py_ssize_t")});
m_mappingProtocol.insert(QLatin1String("__mgetitem__"),
- StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", PyObject* _key"),
- QLatin1String("PyObject*")));
+ {QLatin1String("PyObject* self, PyObject* _key"),
+ QLatin1String("PyObject*")});
m_mappingProtocol.insert(QLatin1String("__msetitem__"),
- StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", PyObject* _key, PyObject* _value"),
- QLatin1String("int")));
+ {QLatin1String("PyObject* self, PyObject* _key, PyObject* _value"),
+ QLatin1String("int")});
// Sequence protocol structure members names
m_mpFuncs.insert(QLatin1String("__mlen__"), QLatin1String("mp_length"));
@@ -186,18 +212,19 @@ QVector<AbstractMetaFunctionList> CppGenerator::filterGroupedOperatorFunctions(c
return result;
}
-bool CppGenerator::hasBoolCast(const AbstractMetaClass* metaClass) const
+const AbstractMetaFunction *CppGenerator::boolCast(const AbstractMetaClass* metaClass) const
{
if (!useIsNullAsNbNonZero())
- return false;
+ return nullptr;
// TODO: This could be configurable someday
const AbstractMetaFunction* func = metaClass->findFunction(QLatin1String("isNull"));
if (!func || !func->type() || !func->type()->typeEntry()->isPrimitive() || !func->isPublic())
- return false;
+ return nullptr;
const PrimitiveTypeEntry* pte = static_cast<const PrimitiveTypeEntry*>(func->type()->typeEntry());
while (pte->referencedTypeEntry())
pte = pte->referencedTypeEntry();
- return func && func->isConstant() && pte->name() == QLatin1String("bool") && func->arguments().isEmpty();
+ return func && func->isConstant() && pte->name() == QLatin1String("bool")
+ && func->arguments().isEmpty() ? func : nullptr;
}
typedef QMap<QString, AbstractMetaFunctionList> FunctionGroupMap;
@@ -219,6 +246,21 @@ static QString chopType(QString s)
return s;
}
+// Helper for field setters: Check for "const QWidget *" (settable field),
+// but not "int *const" (read-only field).
+static bool isPointerToConst(const AbstractMetaType *t)
+{
+ const AbstractMetaType::Indirections &indirections = t->indirectionsV();
+ return t->isConstant() && !indirections.isEmpty()
+ && indirections.constLast() != Indirection::ConstPointer;
+}
+
+static inline bool canGenerateFieldSetter(const AbstractMetaField *field)
+{
+ const AbstractMetaType *type = field->type();
+ return !type->isConstant() || isPointerToConst(type);
+}
+
/*!
Function used to write the class generated binding code on the buffer
\param s the output buffer
@@ -260,6 +302,8 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
// needs the 'set' class from C++ STL.
if (hasMultipleInheritanceInAncestry(metaClass))
s << "#include <set>" << endl;
+ if (metaClass->generateExceptionHandling())
+ s << "#include <exception>" << endl;
s << endl << "// module include" << endl << "#include \"" << getModuleHeaderFileName() << '"' << endl;
@@ -315,7 +359,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
static_cast<const SmartPointerTypeEntry *>(classContext.preciseType()
->typeEntry());
QString rawGetter = typeEntry->getter();
- s << "static const char * " SMART_POINTER_GETTER " = \"" << rawGetter << "\";";
+ s << "static const char * " << SMART_POINTER_GETTER << " = \"" << rawGetter << "\";";
}
// class inject-code native/beginning
@@ -459,7 +503,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) {
writeCopyFunction(s, classContext);
- signatureStream << metaClass->fullName() << ".__copy__()" << endl;
+ signatureStream << fullPythonClassName(metaClass) << ".__copy__()" << endl;
}
// Write single method definitions
@@ -490,16 +534,20 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
}
}
- if (hasBoolCast(metaClass)) {
+ if (const AbstractMetaFunction *f = boolCast(metaClass)) {
ErrorCode errorCode(-1);
- s << "static int " << cpythonBaseName(metaClass) << "___nb_bool(PyObject* " PYTHON_SELF_VAR ")" << endl;
+ s << "static int " << cpythonBaseName(metaClass) << "___nb_bool(PyObject* self)" << endl;
s << '{' << endl;
writeCppSelfDefinition(s, classContext);
- s << INDENT << "int result;" << endl;
- s << INDENT << BEGIN_ALLOW_THREADS << endl;
- s << INDENT << "result = !" CPP_SELF_VAR "->isNull();" << endl;
- s << INDENT << END_ALLOW_THREADS << endl;
- s << INDENT << "return result;" << endl;
+ if (f->allowThread()) {
+ s << INDENT << "int result;" << endl;
+ s << INDENT << BEGIN_ALLOW_THREADS << endl;
+ s << INDENT << "result = !" << CPP_SELF_VAR << "->isNull();" << endl;
+ s << INDENT << END_ALLOW_THREADS << endl;
+ s << INDENT << "return result;" << endl;
+ } else {
+ s << INDENT << "return !" << CPP_SELF_VAR << "->isNull();" << endl;
+ }
s << '}' << endl << endl;
}
@@ -546,7 +594,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
if (metaField->isStatic())
continue;
writeGetterFunction(s, metaField, classContext);
- if (!metaField->type()->isConstant())
+ if (canGenerateFieldSetter(metaField))
writeSetterFunction(s, metaField, classContext);
s << endl;
}
@@ -557,10 +605,12 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
if (metaField->isStatic())
continue;
- bool hasSetter = !metaField->type()->isConstant();
s << INDENT << "{const_cast<char*>(\"" << metaField->name() << "\"), ";
- s << cpythonGetterFunctionName(metaField);
- s << ", " << (hasSetter ? cpythonSetterFunctionName(metaField) : QLatin1String("0"));
+ s << cpythonGetterFunctionName(metaField) << ", ";
+ if (canGenerateFieldSetter(metaField))
+ s << cpythonSetterFunctionName(metaField);
+ else
+ s << '0';
s << "}," << endl;
}
s << INDENT << "{0} // Sentinel" << endl;
@@ -686,7 +736,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
Indentation indentation(INDENT);
- QString defaultReturnExpr;
+ DefaultValue defaultReturnExpr;
if (retType) {
const FunctionModificationList &mods = func->modifications();
for (const FunctionModification &mod : mods) {
@@ -694,9 +744,9 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
if (argMod.index == 0 && !argMod.replacedDefaultExpression.isEmpty()) {
static const QRegularExpression regex(QStringLiteral("%(\\d+)"));
Q_ASSERT(regex.isValid());
- defaultReturnExpr = argMod.replacedDefaultExpression;
+ QString expr = argMod.replacedDefaultExpression;
for (int offset = 0; ; ) {
- const QRegularExpressionMatch match = regex.match(defaultReturnExpr, offset);
+ const QRegularExpressionMatch match = regex.match(expr, offset);
if (!match.hasMatch())
break;
const int argId = match.capturedRef(1).toInt() - 1;
@@ -704,23 +754,27 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
qCWarning(lcShiboken) << "The expression used in return value contains an invalid index.";
break;
}
- defaultReturnExpr.replace(match.captured(0), func->arguments().at(argId)->name());
+ expr.replace(match.captured(0), func->arguments().at(argId)->name());
offset = match.capturedStart(1);
}
+ defaultReturnExpr.setType(DefaultValue::Custom);
+ defaultReturnExpr.setValue(expr);
}
}
}
- if (defaultReturnExpr.isEmpty())
+ if (!defaultReturnExpr.isValid())
defaultReturnExpr = minimalConstructor(func->type());
- if (defaultReturnExpr.isEmpty()) {
+ if (!defaultReturnExpr.isValid()) {
QString errorMsg = QLatin1String(__FUNCTION__) + QLatin1String(": ");
if (const AbstractMetaClass *c = func->implementingClass())
errorMsg += c->qualifiedCppName() + QLatin1String("::");
errorMsg += func->signature();
- errorMsg = ShibokenGenerator::msgCouldNotFindMinimalConstructor(errorMsg, func->type()->cppSignature());
+ errorMsg = msgCouldNotFindMinimalConstructor(errorMsg, func->type()->cppSignature());
qCWarning(lcShiboken).noquote().nospace() << errorMsg;
s << endl << INDENT << "#error " << errorMsg << endl;
}
+ } else {
+ defaultReturnExpr.setType(DefaultValue::Void);
}
if (func->isAbstract() && func->isModifiedRemoved()) {
@@ -728,7 +782,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
<< QString::fromLatin1("Pure virtual method '%1::%2' must be implement but was "\
"completely removed on type system.")
.arg(func->ownerClass()->name(), func->minimalSignature());
- s << INDENT << "return " << defaultReturnExpr << ';' << endl;
+ s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl;
s << '}' << endl << endl;
return;
}
@@ -747,13 +801,13 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
s << INDENT << "if (PyErr_Occurred())" << endl;
{
Indentation indentation(INDENT);
- s << INDENT << "return " << defaultReturnExpr << ';' << endl;
+ s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl;
}
- s << INDENT << "Shiboken::AutoDecRef " PYTHON_OVERRIDE_VAR "(Shiboken::BindingManager::instance().getOverride(this, \"";
+ s << INDENT << "Shiboken::AutoDecRef " << PYTHON_OVERRIDE_VAR << "(Shiboken::BindingManager::instance().getOverride(this, \"";
s << funcName << "\"));" << endl;
- s << INDENT << "if (" PYTHON_OVERRIDE_VAR ".isNull()) {" << endl;
+ s << INDENT << "if (" << PYTHON_OVERRIDE_VAR << ".isNull()) {" << endl;
{
Indentation indentation(INDENT);
CodeSnipList snips;
@@ -768,7 +822,9 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '";
s << func->ownerClass()->name() << '.' << funcName;
s << "()' not implemented.\");" << endl;
- s << INDENT << "return " << (retType ? defaultReturnExpr : QString());
+ s << INDENT << "return";
+ if (retType)
+ s << ' ' << defaultReturnExpr.returnValue();
} else {
s << INDENT << "gil.release();" << endl;
s << INDENT;
@@ -785,7 +841,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
writeConversionRule(s, func, TypeSystem::TargetLangCode);
- s << INDENT << "Shiboken::AutoDecRef " PYTHON_ARGS "(";
+ s << INDENT << "Shiboken::AutoDecRef " << PYTHON_ARGS << "(";
if (func->arguments().isEmpty() || allArgumentsRemoved(func)) {
s << "PyTuple_New(0));" << endl;
@@ -844,7 +900,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
if (argMod.resetAfterUse && !invalidateArgs.contains(argMod.index)) {
invalidateArgs.insert(argMod.index);
s << INDENT << "bool invalidateArg" << argMod.index;
- s << " = PyTuple_GET_ITEM(" PYTHON_ARGS ", " << argMod.index - 1 << ")->ob_refcnt == 1;" << endl;
+ s << " = PyTuple_GET_ITEM(" << PYTHON_ARGS << ", " << argMod.index - 1 << ")->ob_refcnt == 1;" << endl;
} else if (argMod.index == 0 && argMod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::CppOwnership) {
invalidateReturn = true;
}
@@ -866,36 +922,36 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
if (!injectedCodeCallsPythonOverride(func)) {
s << INDENT;
- s << "Shiboken::AutoDecRef " PYTHON_RETURN_VAR "(PyObject_Call(" PYTHON_OVERRIDE_VAR ", " PYTHON_ARGS ", NULL));" << endl;
+ s << "Shiboken::AutoDecRef " << PYTHON_RETURN_VAR << "(PyObject_Call(" << PYTHON_OVERRIDE_VAR << ", " << PYTHON_ARGS << ", NULL));" << endl;
s << INDENT << "// An error happened in python code!" << endl;
- s << INDENT << "if (" PYTHON_RETURN_VAR ".isNull()) {" << endl;
+ s << INDENT << "if (" << PYTHON_RETURN_VAR << ".isNull()) {" << endl;
{
Indentation indent(INDENT);
s << INDENT << "PyErr_Print();" << endl;
- s << INDENT << "return " << defaultReturnExpr << ';' << endl;
+ s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl;
}
s << INDENT << '}' << endl;
if (retType) {
if (invalidateReturn)
- s << INDENT << "bool invalidateArg0 = " PYTHON_RETURN_VAR "->ob_refcnt == 1;" << endl;
+ s << INDENT << "bool invalidateArg0 = " << PYTHON_RETURN_VAR << "->ob_refcnt == 1;" << endl;
if (func->typeReplaced(0) != QLatin1String("PyObject")) {
s << INDENT << "// Check return type" << endl;
s << INDENT;
if (func->typeReplaced(0).isEmpty()) {
- s << "PythonToCppFunc " PYTHON_TO_CPP_VAR " = " << cpythonIsConvertibleFunction(func->type());
- s << PYTHON_RETURN_VAR ");" << endl;
- s << INDENT << "if (!" PYTHON_TO_CPP_VAR ") {" << endl;
+ s << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << " = " << cpythonIsConvertibleFunction(func->type());
+ s << PYTHON_RETURN_VAR << ");" << endl;
+ s << INDENT << "if (!" << PYTHON_TO_CPP_VAR << ") {" << endl;
{
Indentation indent(INDENT);
s << INDENT << "Shiboken::warning(PyExc_RuntimeWarning, 2, "\
"\"Invalid return value in function %s, expected %s, got %s.\", \"";
s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func);
- s << ", Py_TYPE(" PYTHON_RETURN_VAR ")->tp_name);" << endl;
- s << INDENT << "return " << defaultReturnExpr << ';' << endl;
+ s << ", Py_TYPE(" << PYTHON_RETURN_VAR << ")->tp_name);" << endl;
+ s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl;
}
s << INDENT << '}' << endl;
@@ -907,15 +963,16 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
isNumber(func->type()->typeEntry()), func->typeReplaced(0));
s << ';' << endl;
s << INDENT << "if (!typeIsValid";
- s << (isPointerToWrapperType(func->type()) ? " && " PYTHON_RETURN_VAR " != Py_None" : "");
+ if (isPointerToWrapperType(func->type()))
+ s << " && " << PYTHON_RETURN_VAR << " != Py_None";
s << ") {" << endl;
{
Indentation indent(INDENT);
s << INDENT << "Shiboken::warning(PyExc_RuntimeWarning, 2, "\
"\"Invalid return value in function %s, expected %s, got %s.\", \"";
s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func);
- s << ", Py_TYPE(" PYTHON_RETURN_VAR ")->tp_name);" << endl;
- s << INDENT << "return " << defaultReturnExpr << ';' << endl;
+ s << ", Py_TYPE(" << PYTHON_RETURN_VAR << ")->tp_name);" << endl;
+ s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl;
}
s << INDENT << '}' << endl;
@@ -935,12 +992,12 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
if (invalidateReturn) {
s << INDENT << "if (invalidateArg0)" << endl;
Indentation indentation(INDENT);
- s << INDENT << "Shiboken::Object::releaseOwnership(" << PYTHON_RETURN_VAR ".object());" << endl;
+ s << INDENT << "Shiboken::Object::releaseOwnership(" << PYTHON_RETURN_VAR << ".object());" << endl;
}
for (int argIndex : qAsConst(invalidateArgs)) {
s << INDENT << "if (invalidateArg" << argIndex << ')' << endl;
Indentation indentation(INDENT);
- s << INDENT << "Shiboken::Object::invalidate(PyTuple_GET_ITEM(" PYTHON_ARGS ", ";
+ s << INDENT << "Shiboken::Object::invalidate(PyTuple_GET_ITEM(" << PYTHON_ARGS << ", ";
s << (argIndex - 1) << "));" << endl;
}
@@ -950,9 +1007,9 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
for (const ArgumentModification &argMod : funcMod.argument_mods) {
if (argMod.ownerships.contains(TypeSystem::NativeCode)
&& argMod.index == 0 && argMod.ownerships[TypeSystem::NativeCode] == TypeSystem::CppOwnership) {
- s << INDENT << "if (Shiboken::Object::checkType(" PYTHON_RETURN_VAR "))" << endl;
+ s << INDENT << "if (Shiboken::Object::checkType(" << PYTHON_RETURN_VAR << "))" << endl;
Indentation indent(INDENT);
- s << INDENT << "Shiboken::Object::releaseOwnership(" PYTHON_RETURN_VAR ");" << endl;
+ s << INDENT << "Shiboken::Object::releaseOwnership(" << PYTHON_RETURN_VAR << ");" << endl;
}
}
}
@@ -978,7 +1035,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
}
if (func->type()->referenceType() == LValueReference && !isPointer(func->type()))
s << '*';
- s << CPP_RETURN_VAR ";" << endl;
+ s << CPP_RETURN_VAR << ';' << endl;
}
s << '}' << endl << endl;
@@ -995,7 +1052,7 @@ void CppGenerator::writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass
s << INDENT << "SbkObject* pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl;
s << INDENT << "if (pySelf == NULL)" << endl;
s << INDENT << INDENT << "return " << metaClass->qualifiedCppName() << "::metaObject();" << endl;
- s << INDENT << "return PySide::SignalManager::retriveMetaObject(reinterpret_cast<PyObject*>(pySelf));" << endl;
+ s << INDENT << "return PySide::SignalManager::retrieveMetaObject(reinterpret_cast<PyObject*>(pySelf));" << endl;
s << '}' << endl << endl;
// qt_metacall function
@@ -1259,7 +1316,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla
toCppConv = QLatin1Char('*') + cpythonWrapperCPtr(sourceClass->typeEntry(), QLatin1String("pyIn"));
} else {
// Constructor that does implicit conversion.
- if (!conv->typeReplaced(1).isEmpty())
+ if (!conv->typeReplaced(1).isEmpty() || conv->isModifiedToArray(1))
continue;
const AbstractMetaType* sourceType = conv->arguments().constFirst()->type();
typeCheck = cpythonCheckFunction(sourceType);
@@ -1419,7 +1476,7 @@ void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClas
sourceType = buildAbstractMetaTypeFromAbstractMetaClass(conv->ownerClass());
} else {
// Constructor that does implicit conversion.
- if (!conv->typeReplaced(1).isEmpty())
+ if (!conv->typeReplaced(1).isEmpty() || conv->isModifiedToArray(1))
continue;
sourceType = conv->arguments().constFirst()->type();
}
@@ -1467,7 +1524,7 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &over
// Check if the right constructor was called.
if (!ownerClass->hasPrivateDestructor()) {
s << INDENT;
- s << "if (Shiboken::Object::isUserType(" PYTHON_SELF_VAR ") && !Shiboken::ObjectType::canCallConstructor(" PYTHON_SELF_VAR "->ob_type, Shiboken::SbkType< ::";
+ s << "if (Shiboken::Object::isUserType(self) && !Shiboken::ObjectType::canCallConstructor(self->ob_type, Shiboken::SbkType< ::";
QString qualifiedCppName;
if (!context.forSmartPointer())
qualifiedCppName = ownerClass->qualifiedCppName();
@@ -1476,7 +1533,7 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &over
s << qualifiedCppName << " >()))" << endl;
Indentation indent(INDENT);
- s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl << endl;
}
// Declare pointer for the underlying C++ object.
s << INDENT << "::";
@@ -1497,7 +1554,7 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &over
writeCppSelfDefinition(s, rfunc, context, overloadData.hasStaticFunction());
}
if (!rfunc->isInplaceOperator() && overloadData.hasNonVoidReturnType())
- s << INDENT << "PyObject* " PYTHON_RETURN_VAR " = 0;" << endl;
+ s << INDENT << "PyObject* " << PYTHON_RETURN_VAR << " = 0;" << endl;
initPythonArguments = minArgs != maxArgs || maxArgs > 1;
usesNamedArguments = rfunc->isCallOperator() || overloadData.hasArgumentWithDefaultValue();
@@ -1505,7 +1562,7 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &over
if (maxArgs > 0) {
s << INDENT << "int overloadId = -1;" << endl;
- s << INDENT << "PythonToCppFunc " PYTHON_TO_CPP_VAR;
+ s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR;
if (pythonFunctionWrapperUsesListOfArguments(overloadData))
s << "[] = { 0" << QString::fromLatin1(", 0").repeated(maxArgs-1) << " }";
s << ';' << endl;
@@ -1518,7 +1575,7 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &over
if (initPythonArguments) {
s << INDENT << "int numArgs = ";
if (minArgs == 0 && maxArgs == 1 && !rfunc->isConstructor() && !pythonFunctionWrapperUsesListOfArguments(overloadData))
- s << "(" PYTHON_ARG " == 0 ? 0 : 1);" << endl;
+ s << "(" << PYTHON_ARG << " == 0 ? 0 : 1);" << endl;
else
writeArgumentsInitializer(s, overloadData);
}
@@ -1534,7 +1591,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun
const AbstractMetaClass* metaClass = rfunc->ownerClass();
s << "static int" << endl;
- s << cpythonFunctionName(rfunc) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* args, PyObject* kwds)" << endl;
+ s << cpythonFunctionName(rfunc) << "(PyObject* self, PyObject* args, PyObject* kwds)" << endl;
s << '{' << endl;
QSet<QString> argNamesSet;
@@ -1560,10 +1617,10 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun
s << INDENT << "const QMetaObject* metaObject;" << endl;
}
- s << INDENT << "SbkObject* sbkSelf = reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR ");" << endl;
+ s << INDENT << "SbkObject* sbkSelf = reinterpret_cast<SbkObject*>(self);" << endl;
if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) {
- s << INDENT << "SbkObjectType* type = reinterpret_cast<SbkObjectType*>(" PYTHON_SELF_VAR "->ob_type);" << endl;
+ s << INDENT << "SbkObjectType* type = reinterpret_cast<SbkObjectType*>(self->ob_type);" << endl;
s << INDENT << "SbkObjectType* myType = reinterpret_cast<SbkObjectType*>(" << cpythonTypeNameExt(metaClass->typeEntry()) << ");" << endl;
}
@@ -1577,7 +1634,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun
s << INDENT << "\"'" << metaClass->qualifiedCppName();
}
s << "' represents a C++ abstract class and cannot be instantiated\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
s << INDENT << '}' << endl << endl;
}
@@ -1608,7 +1665,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun
{
Indentation indent(INDENT);
s << INDENT << "delete cptr;" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
s << INDENT << '}' << endl;
if (overloadData.maxArgs() > 0) {
@@ -1636,12 +1693,12 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun
// Create metaObject and register signal/slot
if (metaClass->isQObject() && usePySideExtensions()) {
s << endl << INDENT << "// QObject setup" << endl;
- s << INDENT << "PySide::Signal::updateSourceObject(" PYTHON_SELF_VAR ");" << endl;
+ s << INDENT << "PySide::Signal::updateSourceObject(self);" << endl;
s << INDENT << "metaObject = cptr->metaObject(); // <- init python qt properties" << endl;
- s << INDENT << "if (kwds && !PySide::fillQtProperties(" PYTHON_SELF_VAR ", metaObject, kwds, argNames, " << argNamesSet.count() << "))" << endl;
+ s << INDENT << "if (kwds && !PySide::fillQtProperties(self, metaObject, kwds, argNames, " << argNamesSet.count() << "))" << endl;
{
Indentation indentation(INDENT);
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
}
@@ -1694,7 +1751,7 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction
int maxArgs = overloadData.maxArgs();
s << "static PyObject* ";
- s << cpythonFunctionName(rfunc) << "(PyObject* " PYTHON_SELF_VAR;
+ s << cpythonFunctionName(rfunc) << "(PyObject* self";
if (maxArgs > 0) {
s << ", PyObject* " << (pythonFunctionWrapperUsesListOfArguments(overloadData) ? "args" : PYTHON_ARG);
if (overloadData.hasArgumentWithDefaultValue() || rfunc->isCallOperator())
@@ -1707,6 +1764,7 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction
s << endl;
/*
+ * This code is intended for shift operations only:
* Make sure reverse <</>> operators defined in other classes (specially from other modules)
* are called. A proper and generic solution would require an reengineering in the operator
* system like the extended converters.
@@ -1721,30 +1779,32 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction
&& rfunc->isOperatorOverload();
if (callExtendedReverseOperator) {
QString revOpName = ShibokenGenerator::pythonOperatorFunctionName(rfunc).insert(2, QLatin1Char('r'));
- if (rfunc->isBinaryOperator()) {
+ // For custom classes, operations like __radd__ and __rmul__
+ // will enter an infinite loop.
+ if (rfunc->isBinaryOperator() && revOpName.contains(QLatin1String("shift"))) {
s << INDENT << "if (!isReverse" << endl;
{
Indentation indent(INDENT);
- s << INDENT << "&& Shiboken::Object::checkType(" PYTHON_ARG ")" << endl;
- s << INDENT << "&& !PyObject_TypeCheck(" PYTHON_ARG ", " PYTHON_SELF_VAR "->ob_type)" << endl;
- s << INDENT << "&& PyObject_HasAttrString(" PYTHON_ARG ", const_cast<char*>(\"" << revOpName << "\"))) {" << endl;
+ s << INDENT << "&& Shiboken::Object::checkType(" << PYTHON_ARG << ")" << endl;
+ s << INDENT << "&& !PyObject_TypeCheck(" << PYTHON_ARG << ", self->ob_type)" << endl;
+ s << INDENT << "&& PyObject_HasAttrString(" << PYTHON_ARG << ", const_cast<char*>(\"" << revOpName << "\"))) {" << endl;
// This PyObject_CallMethod call will emit lots of warnings like
// "deprecated conversion from string constant to char *" during compilation
// due to the method name argument being declared as "char*" instead of "const char*"
// issue 6952 http://bugs.python.org/issue6952
- s << INDENT << "PyObject* revOpMethod = PyObject_GetAttrString(" PYTHON_ARG ", const_cast<char*>(\"" << revOpName << "\"));" << endl;
+ s << INDENT << "PyObject* revOpMethod = PyObject_GetAttrString(" << PYTHON_ARG << ", const_cast<char*>(\"" << revOpName << "\"));" << endl;
s << INDENT << "if (revOpMethod && PyCallable_Check(revOpMethod)) {" << endl;
{
Indentation indent(INDENT);
- s << INDENT << PYTHON_RETURN_VAR " = PyObject_CallFunction(revOpMethod, const_cast<char*>(\"O\"), " PYTHON_SELF_VAR ");" << endl;
+ s << INDENT << PYTHON_RETURN_VAR << " = PyObject_CallFunction(revOpMethod, const_cast<char*>(\"O\"), self);" << endl;
s << INDENT << "if (PyErr_Occurred() && (PyErr_ExceptionMatches(PyExc_NotImplementedError)";
s << " || PyErr_ExceptionMatches(PyExc_AttributeError))) {" << endl;
{
Indentation indent(INDENT);
s << INDENT << "PyErr_Clear();" << endl;
- s << INDENT << "Py_XDECREF(" PYTHON_RETURN_VAR ");" << endl;
- s << INDENT << PYTHON_RETURN_VAR " = 0;" << endl;
+ s << INDENT << "Py_XDECREF(" << PYTHON_RETURN_VAR << ");" << endl;
+ s << INDENT << PYTHON_RETURN_VAR << " = 0;" << endl;
}
s << INDENT << '}' << endl;
}
@@ -1754,7 +1814,7 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction
s << INDENT << "}" << endl;
}
s << INDENT << "// Do not enter here if other object has implemented a reverse operator." << endl;
- s << INDENT << "if (!" PYTHON_RETURN_VAR ") {" << endl << endl;
+ s << INDENT << "if (!" << PYTHON_RETURN_VAR << ") {" << endl << endl;
}
if (maxArgs > 0)
@@ -1763,7 +1823,7 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction
writeFunctionCalls(s, overloadData, classContext);
if (callExtendedReverseOperator)
- s << endl << INDENT << "} // End of \"if (!" PYTHON_RETURN_VAR ")\"" << endl;
+ s << endl << INDENT << "} // End of \"if (!" << PYTHON_RETURN_VAR << ")\"" << endl;
s << endl;
@@ -1771,10 +1831,10 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction
if (hasReturnValue) {
if (rfunc->isInplaceOperator()) {
- s << INDENT << "Py_INCREF(" PYTHON_SELF_VAR ");\n";
- s << INDENT << "return " PYTHON_SELF_VAR ";\n";
+ s << INDENT << "Py_INCREF(self);\n";
+ s << INDENT << "return self;\n";
} else {
- s << INDENT << "return " PYTHON_RETURN_VAR ";\n";
+ s << INDENT << "return " << PYTHON_RETURN_VAR << ";\n";
}
} else {
s << INDENT << "Py_RETURN_NONE;" << endl;
@@ -1795,7 +1855,7 @@ void CppGenerator::writeArgumentsInitializer(QTextStream& s, OverloadData& overl
int maxArgs = overloadData.maxArgs();
s << INDENT << "PyObject* ";
- s << PYTHON_ARGS "[] = {"
+ s << PYTHON_ARGS << "[] = {"
<< QString(maxArgs, QLatin1Char('0')).split(QLatin1String(""), QString::SkipEmptyParts).join(QLatin1String(", "))
<< "};" << endl;
s << endl;
@@ -1807,8 +1867,8 @@ void CppGenerator::writeArgumentsInitializer(QTextStream& s, OverloadData& overl
s << INDENT << "PyObject* nonvarargs = PyTuple_GetSlice(args, 0, " << maxArgs << ");" << endl;
s << INDENT << "Shiboken::AutoDecRef auto_nonvarargs(nonvarargs);" << endl;
- s << INDENT << PYTHON_ARGS "[" << maxArgs << "] = PyTuple_GetSlice(args, " << maxArgs << ", numArgs);" << endl;
- s << INDENT << "Shiboken::AutoDecRef auto_varargs(" PYTHON_ARGS "[" << maxArgs << "]);" << endl;
+ s << INDENT << PYTHON_ARGS << '[' << maxArgs << "] = PyTuple_GetSlice(args, " << maxArgs << ", numArgs);" << endl;
+ s << INDENT << "Shiboken::AutoDecRef auto_varargs(" << PYTHON_ARGS << "[" << maxArgs << "]);" << endl;
s << endl;
}
@@ -1822,7 +1882,7 @@ void CppGenerator::writeArgumentsInitializer(QTextStream& s, OverloadData& overl
{
Indentation indent(INDENT);
s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): too many arguments\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
s << INDENT << '}';
}
@@ -1835,7 +1895,7 @@ void CppGenerator::writeArgumentsInitializer(QTextStream& s, OverloadData& overl
{
Indentation indent(INDENT);
s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): not enough arguments\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
s << INDENT << '}';
}
@@ -1867,13 +1927,12 @@ void CppGenerator::writeArgumentsInitializer(QTextStream& s, OverloadData& overl
s << "PyArg_ParseTuple(" << argsVar << ", \"|" << QByteArray(maxArgs, 'O') << ':' << funcName << '"';
else
s << "PyArg_UnpackTuple(" << argsVar << ", \"" << funcName << "\", " << minArgs << ", " << maxArgs;
- QStringList palist;
for (int i = 0; i < maxArgs; i++)
- palist << QString::fromLatin1("&(" PYTHON_ARGS "[%1])").arg(i);
- s << ", " << palist.join(QLatin1String(", ")) << "))" << endl;
+ s << ", &(" << PYTHON_ARGS << '[' << i << "])";
+ s << "))" << endl;
{
Indentation indent(INDENT);
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
s << endl;
}
@@ -1895,7 +1954,7 @@ void CppGenerator::writeCppSelfDefinition(QTextStream &s,
}
QString cppSelfAttribution;
- QString pythonSelfVar = QLatin1String(PYTHON_SELF_VAR);
+ QString pythonSelfVar = QLatin1String("self");
QString cpythonWrapperCPtrResult;
if (!context.forSmartPointer())
cpythonWrapperCPtrResult = cpythonWrapperCPtr(metaClass, pythonSelfVar);
@@ -1908,7 +1967,7 @@ void CppGenerator::writeCppSelfDefinition(QTextStream &s,
.arg(className, QLatin1String(CPP_SELF_VAR), cast,
cpythonWrapperCPtrResult);
} else {
- s << INDENT << className << "* " CPP_SELF_VAR " = 0;" << endl;
+ s << INDENT << className << "* " << CPP_SELF_VAR << " = 0;" << endl;
writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR));
cppSelfAttribution = QString::fromLatin1("%1 = %2%3")
.arg(QLatin1String(CPP_SELF_VAR),
@@ -1918,17 +1977,17 @@ void CppGenerator::writeCppSelfDefinition(QTextStream &s,
// Checks if the underlying C++ object is valid.
if (hasStaticOverload && !cppSelfAsReference) {
- s << INDENT << "if (" PYTHON_SELF_VAR ") {" << endl;
+ s << INDENT << "if (self) {" << endl;
{
Indentation indent(INDENT);
- writeInvalidPyObjectCheck(s, QLatin1String(PYTHON_SELF_VAR));
+ writeInvalidPyObjectCheck(s, QLatin1String("self"));
s << INDENT << cppSelfAttribution << ';' << endl;
}
s << INDENT << '}' << endl;
return;
}
- writeInvalidPyObjectCheck(s, QLatin1String(PYTHON_SELF_VAR));
+ writeInvalidPyObjectCheck(s, QLatin1String("self"));
s << INDENT << cppSelfAttribution << ';' << endl;
}
@@ -1942,17 +2001,17 @@ void CppGenerator::writeCppSelfDefinition(QTextStream &s,
if (func->isOperatorOverload() && func->isBinaryOperator()) {
QString checkFunc = cpythonCheckFunction(func->ownerClass()->typeEntry());
- s << INDENT << "bool isReverse = " << checkFunc << PYTHON_ARG ")" << endl;
+ s << INDENT << "bool isReverse = " << checkFunc << PYTHON_ARG << ')' << endl;
{
Indentation indent1(INDENT);
Indentation indent2(INDENT);
Indentation indent3(INDENT);
Indentation indent4(INDENT);
- s << INDENT << "&& !" << checkFunc << PYTHON_SELF_VAR ");" << endl;
+ s << INDENT << "&& !" << checkFunc << "self);" << endl;
}
s << INDENT << "if (isReverse)" << endl;
Indentation indent(INDENT);
- s << INDENT << "std::swap(" PYTHON_SELF_VAR ", " PYTHON_ARG ");" << endl;
+ s << INDENT << "std::swap(self, " << PYTHON_ARG << ");" << endl;
}
writeCppSelfDefinition(s, context, hasStaticOverload);
@@ -2053,17 +2112,20 @@ void CppGenerator::writeErrorSection(QTextStream& s, OverloadData& overloadData)
<< ", 0};" << endl;
s << INDENT << "Shiboken::setErrorAboutWrongArguments(" << argsVar << ", \"" << funcName << "\", overloads);" << endl;
}
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
void CppGenerator::writeFunctionReturnErrorCheckSection(QTextStream& s, bool hasReturnValue)
{
- s << INDENT << "if (PyErr_Occurred()" << (hasReturnValue ? " || !" PYTHON_RETURN_VAR : "") << ") {" << endl;
+ s << INDENT << "if (PyErr_Occurred()";
+ if (hasReturnValue)
+ s << " || !" << PYTHON_RETURN_VAR;
+ s << ") {" << endl;
{
Indentation indent(INDENT);
if (hasReturnValue)
- s << INDENT << "Py_XDECREF(" PYTHON_RETURN_VAR ");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << "Py_XDECREF(" << PYTHON_RETURN_VAR << ");" << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
s << INDENT << '}' << endl;
}
@@ -2072,12 +2134,13 @@ void CppGenerator::writeInvalidPyObjectCheck(QTextStream& s, const QString& pyOb
{
s << INDENT << "if (!Shiboken::Object::isValid(" << pyObj << "))" << endl;
Indentation indent(INDENT);
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
static QString pythonToCppConverterForArgumentName(const QString& argumentName)
{
- static const QRegularExpression pyArgsRegex(QLatin1String(PYTHON_ARGS"(\\[\\d+[-]?\\d*\\])"));
+ static const QRegularExpression pyArgsRegex(QLatin1String(PYTHON_ARGS)
+ + QLatin1String(R"((\[\d+[-]?\d*\]))"));
Q_ASSERT(pyArgsRegex.isValid());
const QRegularExpressionMatch match = pyArgsRegex.match(argumentName);
QString result = QLatin1String(PYTHON_TO_CPP_VAR);
@@ -2379,7 +2442,7 @@ void CppGenerator::writeConversionRule(QTextStream& s, const AbstractMetaFunctio
void CppGenerator::writeNoneReturn(QTextStream& s, const AbstractMetaFunction* func, bool thereIsReturnValue)
{
if (thereIsReturnValue && (!func->type() || func->argumentRemoved(0)) && !injectedCodeHasReturnValueAttribution(func)) {
- s << INDENT << PYTHON_RETURN_VAR " = Py_None;" << endl;
+ s << INDENT << PYTHON_RETURN_VAR << " = Py_None;" << endl;
s << INDENT << "Py_INCREF(Py_None);" << endl;
}
}
@@ -2493,8 +2556,9 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const Ov
const AbstractMetaFunction* refFunc = overloadData->referenceFunction();
QStringList typeChecks;
+
QString pyArgName = (usePyArgs && maxArgs > 1)
- ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(overloadData->argPos())
+ ? pythonArgsAt(overloadData->argPos())
: QLatin1String(PYTHON_ARG);
OverloadData* od = overloadData;
int startArg = od->argPos();
@@ -2503,7 +2567,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const Ov
bool typeReplacedByPyObject = od->argumentTypeReplaced() == QLatin1String("PyObject");
if (!typeReplacedByPyObject) {
if (usePyArgs)
- pyArgName = QString::fromLatin1(PYTHON_ARGS "[%1]").arg(od->argPos());
+ pyArgName = pythonArgsAt(od->argPos());
QString typeCheck;
QTextStream tck(&typeCheck);
const AbstractMetaFunction* func = od->referenceFunction();
@@ -2613,7 +2677,7 @@ void CppGenerator::writeSingleFunctionCall(QTextStream &s,
s << INDENT << "PyErr_Format(PyExc_TypeError, \"%s is a private method.\", \""
<< func->signature().replace(QLatin1String("::"), QLatin1String("."))
<< "\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
return;
}
@@ -2630,7 +2694,8 @@ void CppGenerator::writeSingleFunctionCall(QTextStream &s,
const AbstractMetaArgument* arg = func->arguments().at(argIdx);
if (func->argumentRemoved(argIdx + 1)) {
if (!arg->defaultValueExpression().isEmpty()) {
- QString cppArgRemoved = QString::fromLatin1(CPP_ARG_REMOVED "%1").arg(argIdx);
+ const QString cppArgRemoved = QLatin1String(CPP_ARG_REMOVED)
+ + QString::number(argIdx);
s << INDENT << getFullTypeName(arg->type()) << ' ' << cppArgRemoved;
s << " = " << guessScopeForDefaultValue(func, arg) << ';' << endl;
writeUnusedVariableCast(s, cppArgRemoved);
@@ -2649,8 +2714,8 @@ void CppGenerator::writeSingleFunctionCall(QTextStream &s,
if (!argType || (mayHaveUnunsedArguments && !injectedCodeUsesArgument(func, argIdx)))
continue;
int argPos = argIdx - removedArgs;
- QString argName = QString::fromLatin1(CPP_ARG"%1").arg(argPos);
- QString pyArgName = usePyArgs ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(argPos) : QLatin1String(PYTHON_ARG);
+ QString argName = QLatin1String(CPP_ARG) + QString::number(argPos);
+ QString pyArgName = usePyArgs ? pythonArgsAt(argPos) : QLatin1String(PYTHON_ARG);
QString defaultValue = guessScopeForDefaultValue(func, arg);
writeArgumentConversion(s, argType, argName, pyArgName, func->implementingClass(), defaultValue, func->isUserAdded());
}
@@ -2896,10 +2961,8 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream& s, const Abs
const AbstractMetaType* type = containerType->instantiations().at(i);
QString typeName = getFullTypeName(type);
if (type->isValue() && isValueTypeWithCopyConstructorOnly(type)) {
- static const QRegularExpression regex(QLatin1String(CONVERTTOCPP_REGEX));
- Q_ASSERT(regex.isValid());
for (int pos = 0; ; ) {
- const QRegularExpressionMatch match = regex.match(code, pos);
+ const QRegularExpressionMatch match = convertToCppRegEx().match(code, pos);
if (!match.hasMatch())
break;
pos = match.capturedEnd();
@@ -2954,15 +3017,13 @@ void CppGenerator::writeNamedArgumentResolution(QTextStream& s, const AbstractMe
s << INDENT << "PyObject* ";
for (const AbstractMetaArgument *arg : args) {
int pyArgIndex = arg->argumentIndex() - OverloadData::numberOfRemovedArguments(func, arg->argumentIndex());
- QString pyArgName = usePyArgs
- ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(pyArgIndex)
- : QLatin1String(PYTHON_ARG);
+ QString pyArgName = usePyArgs ? pythonArgsAt(pyArgIndex) : QLatin1String(PYTHON_ARG);
s << "value = PyDict_GetItemString(kwds, \"" << arg->name() << "\");" << endl;
s << INDENT << "if (value && " << pyArgName << ") {" << endl;
{
Indentation indent(INDENT);
s << INDENT << pyErrString.arg(arg->name()) << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
s << INDENT << "} else if (value) {" << endl;
{
@@ -2989,7 +3050,7 @@ QString CppGenerator::argumentNameFromIndex(const AbstractMetaFunction* func, in
*wrappedClass = 0;
QString pyArgName;
if (argIndex == -1) {
- pyArgName = QLatin1String(PYTHON_SELF_VAR);
+ pyArgName = QLatin1String("self");
*wrappedClass = func->implementingClass();
} else if (argIndex == 0) {
AbstractMetaType *funcType = func->type();
@@ -3016,12 +3077,23 @@ QString CppGenerator::argumentNameFromIndex(const AbstractMetaFunction* func, in
&& OverloadData::isSingleArgument(getFunctionGroups(func->implementingClass())[func->name()]))
pyArgName = QLatin1String(PYTHON_ARG);
else
- pyArgName = QString::fromLatin1(PYTHON_ARGS "[%1]").arg(argIndex - 1);
+ pyArgName = pythonArgsAt(argIndex - 1);
}
}
return pyArgName;
}
+static QStringList defaultExceptionHandling()
+{
+ static const QStringList result{
+ QLatin1String("} catch (const std::exception &e) {"),
+ QLatin1String(" PyErr_SetString(PyExc_RuntimeError, e.what());"),
+ QLatin1String("} catch (...) {"),
+ QLatin1String(" PyErr_SetString(PyExc_RuntimeError, \"An unknown exception was caught\");"),
+ QLatin1String("}")};
+ return result;
+}
+
void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *func,
GeneratorContext &context, int maxArgs)
{
@@ -3037,12 +3109,12 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
}
if (func->isAbstract()) {
- s << INDENT << "if (Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR "))) {\n";
+ s << INDENT << "if (Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject*>(self))) {\n";
{
Indentation indent(INDENT);
s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '";
s << func->ownerClass()->name() << '.' << func->name() << "()' not implemented.\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
s << INDENT << "}\n";
}
@@ -3091,16 +3163,21 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
if (hasConversionRule)
userArgs << arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX);
else if (!arg->defaultValueExpression().isEmpty())
- userArgs << QString::fromLatin1(CPP_ARG_REMOVED "%1").arg(i);
+ userArgs.append(QLatin1String(CPP_ARG_REMOVED) + QString::number(i));
} else {
int idx = arg->argumentIndex() - removedArgs;
bool deRef = isValueTypeWithCopyConstructorOnly(arg->type())
|| isObjectTypeUsedAsValueType(arg->type())
|| (arg->type()->referenceType() == LValueReference && isWrapperType(arg->type()) && !isPointer(arg->type()));
- QString argName = hasConversionRule
- ? arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX)
- : QString::fromLatin1("%1" CPP_ARG "%2").arg(deRef ? QLatin1String("*") : QString()).arg(idx);
- userArgs << argName;
+ if (hasConversionRule) {
+ userArgs.append(arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX));
+ } else {
+ QString argName;
+ if (deRef)
+ argName += QLatin1Char('*');
+ argName += QLatin1String(CPP_ARG) + QString::number(idx);
+ userArgs.append(argName);
+ }
}
}
@@ -3113,17 +3190,16 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
bool argsClear = true;
for (int i = func->arguments().size() - 1; i >= maxArgs + removedArgs; i--) {
const AbstractMetaArgument* arg = func->arguments().at(i);
- bool defValModified = arg->defaultValueExpression() != arg->originalDefaultValueExpression();
+ const bool defValModified = arg->hasModifiedDefaultValueExpression();
bool hasConversionRule = !func->conversionRule(TypeSystem::NativeCode, arg->argumentIndex() + 1).isEmpty();
if (argsClear && !defValModified && !hasConversionRule)
continue;
- else
- argsClear = false;
+ argsClear = false;
otherArgsModified |= defValModified || hasConversionRule || func->argumentRemoved(i + 1);
if (hasConversionRule)
otherArgs.prepend(arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX));
else
- otherArgs.prepend(QString::fromLatin1(CPP_ARG_REMOVED "%1").arg(i));
+ otherArgs.prepend(QLatin1String(CPP_ARG_REMOVED) + QString::number(i));
}
if (otherArgsModified)
userArgs << otherArgs;
@@ -3135,10 +3211,11 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
QString useVAddr;
QTextStream uva(&useVAddr);
if (func->isOperatorOverload() && !func->isCallOperator()) {
- QString firstArg = QLatin1String("(*" CPP_SELF_VAR ")");
- if (func->isPointerOperator())
- firstArg.remove(1, 1); // remove the de-reference operator
-
+ QString firstArg(QLatin1Char('('));
+ if (!func->isPointerOperator()) // no de-reference operator
+ firstArg += QLatin1Char('*');
+ firstArg += QLatin1String(CPP_SELF_VAR);
+ firstArg += QLatin1Char(')');
QString secondArg = QLatin1String(CPP_ARG0);
if (!func->isUnaryOperator() && shouldDereferenceArgumentPointer(func->arguments().constFirst())) {
secondArg.prepend(QLatin1String("(*"));
@@ -3211,7 +3288,8 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
} else {
const QString selfVarCast = func->ownerClass() == func->implementingClass()
? QLatin1String(CPP_SELF_VAR)
- : QLatin1String("reinterpret_cast<") + methodCallClassName + QLatin1String(" *>(" CPP_SELF_VAR ")");
+ : QLatin1String("reinterpret_cast<") + methodCallClassName
+ + QLatin1String(" *>(") + QLatin1String(CPP_SELF_VAR) + QLatin1Char(')');
if (func->isConstant()) {
if (avoidProtectedHack()) {
mc << "const_cast<const ::";
@@ -3219,7 +3297,8 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
// PYSIDE-500: Need a special wrapper cast when inherited
const QString selfWrapCast = func->ownerClass() == func->implementingClass()
? QLatin1String(CPP_SELF_VAR)
- : QLatin1String("reinterpret_cast<") + wrapperName(func->ownerClass()) + QLatin1String(" *>(" CPP_SELF_VAR ")");
+ : QLatin1String("reinterpret_cast<") + wrapperName(func->ownerClass())
+ + QLatin1String(" *>(") + QLatin1String(CPP_SELF_VAR) + QLatin1Char(')');
mc << wrapperName(func->ownerClass());
mc << "*>(" << selfWrapCast << ")->";
}
@@ -3263,7 +3342,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
methodCallClassName);
normalCall.remove(QLatin1String("::%CLASS_NAME::"));
methodCall.clear();
- mc << "Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR ")) ? ";
+ mc << "Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject*>(self)) ? ";
mc << virtualCall << " : " << normalCall;
}
}
@@ -3271,7 +3350,19 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
}
if (!injectedCodeCallsCppFunction(func)) {
- s << INDENT << BEGIN_ALLOW_THREADS << endl << INDENT;
+ const bool allowThread = func->allowThread();
+ const bool generateExceptionHandling = func->generateExceptionHandling();
+ if (generateExceptionHandling) {
+ s << INDENT << "try {\n";
+ ++INDENT.indent;
+ if (allowThread) {
+ s << INDENT << "Shiboken::ThreadStateSaver threadSaver;\n"
+ << INDENT << "threadSaver.save();\n";
+ }
+ } else if (allowThread) {
+ s << INDENT << BEGIN_ALLOW_THREADS << endl;
+ }
+ s << INDENT;
if (isCtor) {
s << (useVAddr.isEmpty() ?
QString::fromLatin1("cptr = %1;").arg(methodCall) : useVAddr) << endl;
@@ -3299,18 +3390,23 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
methodCall.append(QLatin1Char(')'));
}
}
- s << " " CPP_RETURN_VAR " = ";
+ s << " " << CPP_RETURN_VAR << " = ";
s << methodCall << ';' << endl;
} else {
s << methodCall << ';' << endl;
}
- s << INDENT << END_ALLOW_THREADS << endl;
+ if (allowThread) {
+ s << INDENT << (generateExceptionHandling
+ ? "threadSaver.restore();" : END_ALLOW_THREADS) << '\n';
+ }
+
+ // Convert result
if (!func->conversionRule(TypeSystem::TargetLangCode, 0).isEmpty()) {
writeConversionRule(s, func, TypeSystem::TargetLangCode, QLatin1String(PYTHON_RETURN_VAR));
} else if (!isCtor && !func->isInplaceOperator() && func->type()
&& !injectedCodeHasReturnValueAttribution(func, TypeSystem::TargetLangCode)) {
- s << INDENT << PYTHON_RETURN_VAR " = ";
+ s << INDENT << PYTHON_RETURN_VAR << " = ";
if (isObjectTypeUsedAsValueType(func->type())) {
s << "Shiboken::Object::newObject(reinterpret_cast<SbkObjectType *>(" << cpythonTypeNameExt(func->type()->typeEntry())
<< "), " << CPP_RETURN_VAR << ", true, true)";
@@ -3319,6 +3415,13 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
}
s << ';' << endl;
}
+
+ if (generateExceptionHandling) { // "catch" code
+ --INDENT.indent;
+ const QStringList handlingCode = defaultExceptionHandling();
+ for (const auto &line : handlingCode)
+ s << INDENT << line << '\n';
+ }
}
}
@@ -3370,7 +3473,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
s << "getOwnership(" << pyArgName << ");";
} else if (wrappedClass->hasVirtualDestructor()) {
if (arg_mod.index == 0)
- s << "releaseOwnership(" PYTHON_RETURN_VAR ");";
+ s << "releaseOwnership(" << PYTHON_RETURN_VAR << ");";
else
s << "releaseOwnership(" << pyArgName << ");";
} else {
@@ -3406,10 +3509,10 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
else
s << INDENT << "Shiboken::Object::removeReference(";
- s << "reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR "), \"";
+ s << "reinterpret_cast<SbkObject*>(self), \"";
QString varName = arg_mod.referenceCounts.constFirst().varName;
if (varName.isEmpty())
- varName = func->minimalSignature() + QString().number(arg_mod.index);
+ varName = func->minimalSignature() + QString::number(arg_mod.index);
s << varName << "\", " << pyArgName
<< (refCount.action == ReferenceCount::Add ? ", true" : "")
@@ -3531,7 +3634,7 @@ void CppGenerator::writeEnumConverterInitialization(QTextStream& s, const TypeEn
const FlagsTypeEntry* flags = 0;
if (enumType->isFlags())
- flags = reinterpret_cast<const FlagsTypeEntry*>(enumType);
+ flags = static_cast<const FlagsTypeEntry*>(enumType);
s << INDENT << "// Register converter for " << enumFlagName << " '" << enumType->qualifiedCppName() << "'." << endl;
s << INDENT << '{' << endl;
@@ -3575,7 +3678,7 @@ void CppGenerator::writeEnumConverterInitialization(QTextStream& s, const TypeEn
s << INDENT << '}' << endl;
if (!flags)
- writeEnumConverterInitialization(s, reinterpret_cast<const EnumTypeEntry*>(enumType)->flags());
+ writeEnumConverterInitialization(s, static_cast<const EnumTypeEntry*>(enumType)->flags());
}
void CppGenerator::writeContainerConverterInitialization(QTextStream& s, const AbstractMetaType* type)
@@ -3656,10 +3759,7 @@ bool CppGenerator::supportsSequenceProtocol(const AbstractMetaClass* metaClass)
}
const ComplexTypeEntry* baseType = metaClass->typeEntry()->baseContainerType();
- if (baseType && baseType->isContainer())
- return true;
-
- return false;
+ return baseType && baseType->isContainer();
}
bool CppGenerator::shouldGenerateGetSetList(const AbstractMetaClass* metaClass)
@@ -3872,7 +3972,7 @@ void CppGenerator::writeMappingMethods(QTextStream &s,
CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode);
s << funcRetVal << ' ' << funcName << '(' << funcArgs << ')' << endl << '{' << endl;
- writeInvalidPyObjectCheck(s, QLatin1String(PYTHON_SELF_VAR));
+ writeInvalidPyObjectCheck(s, QLatin1String("self"));
writeCppSelfDefinition(s, func, context);
@@ -3899,7 +3999,7 @@ void CppGenerator::writeSequenceMethods(QTextStream &s,
CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode);
s << funcRetVal << ' ' << funcName << '(' << funcArgs << ')' << endl << '{' << endl;
- writeInvalidPyObjectCheck(s, QLatin1String(PYTHON_SELF_VAR));
+ writeInvalidPyObjectCheck(s, QLatin1String("self"));
writeCppSelfDefinition(s, func, context);
@@ -3964,7 +4064,6 @@ void CppGenerator::writeTypeAsMappingDefinition(QTextStream& s, const AbstractMe
funcs.insert(QLatin1String("__msetitem__"), QString());
}
- QString baseName = cpythonBaseName(metaClass);
for (auto it = m_mpFuncs.cbegin(), end = m_mpFuncs.cend(); it != end; ++it) {
const QString &mpName = it.key();
if (funcs[mpName].isEmpty())
@@ -4015,7 +4114,8 @@ void CppGenerator::writeTypeAsNumberDefinition(QTextStream& s, const AbstractMet
QString baseName = cpythonBaseName(metaClass);
- nb[QLatin1String("bool")] = hasBoolCast(metaClass) ? baseName + QLatin1String("___nb_bool") : QString();
+ if (hasBoolCast(metaClass))
+ nb.insert(QLatin1String("bool"), baseName + QLatin1String("___nb_bool"));
for (QHash<QString, QString>::const_iterator it = m_nbFuncs.cbegin(), end = m_nbFuncs.cend(); it != end; ++it) {
const QString &nbName = it.key();
@@ -4054,9 +4154,9 @@ void CppGenerator::writeTpTraverseFunction(QTextStream& s, const AbstractMetaCla
{
QString baseName = cpythonBaseName(metaClass);
s << "static int ";
- s << baseName << "_traverse(PyObject* " PYTHON_SELF_VAR ", visitproc visit, void* arg)" << endl;
+ s << baseName << "_traverse(PyObject* self, visitproc visit, void* arg)" << endl;
s << '{' << endl;
- s << INDENT << "return reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())->tp_traverse(" PYTHON_SELF_VAR ", visit, arg);" << endl;
+ s << INDENT << "return reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())->tp_traverse(self, visit, arg);" << endl;
s << '}' << endl;
}
@@ -4064,9 +4164,9 @@ void CppGenerator::writeTpClearFunction(QTextStream& s, const AbstractMetaClass*
{
QString baseName = cpythonBaseName(metaClass);
s << "static int ";
- s << baseName << "_clear(PyObject* " PYTHON_SELF_VAR ")" << endl;
+ s << baseName << "_clear(PyObject* self)" << endl;
s << '{' << endl;
- s << INDENT << "return reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())->tp_clear(" PYTHON_SELF_VAR ");" << endl;
+ s << INDENT << "return reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())->tp_clear(self);" << endl;
s << '}' << endl;
}
@@ -4074,7 +4174,7 @@ void CppGenerator::writeCopyFunction(QTextStream &s, GeneratorContext &context)
{
const AbstractMetaClass *metaClass = context.metaClass();
const QString className = chopType(cpythonTypeName(metaClass));
- s << "static PyObject* " << className << "___copy__(PyObject* " PYTHON_SELF_VAR ")" << endl;
+ s << "static PyObject* " << className << "___copy__(PyObject* self)" << endl;
s << "{" << endl;
writeCppSelfDefinition(s, context, false, true);
QString conversionCode;
@@ -4084,9 +4184,9 @@ void CppGenerator::writeCopyFunction(QTextStream &s, GeneratorContext &context)
conversionCode = cpythonToPythonConversionFunction(context.preciseType());
s << INDENT << "PyObject* " << PYTHON_RETURN_VAR << " = " << conversionCode;
- s << CPP_SELF_VAR ");" << endl;
+ s << CPP_SELF_VAR << ");" << endl;
writeFunctionReturnErrorCheckSection(s);
- s << INDENT << "return " PYTHON_RETURN_VAR ";" << endl;
+ s << INDENT << "return " << PYTHON_RETURN_VAR << ";" << endl;
s << "}" << endl;
s << endl;
}
@@ -4096,7 +4196,7 @@ void CppGenerator::writeGetterFunction(QTextStream &s,
GeneratorContext &context)
{
ErrorCode errorCode(0);
- s << "static PyObject* " << cpythonGetterFunctionName(metaField) << "(PyObject* " PYTHON_SELF_VAR ", void*)" << endl;
+ s << "static PyObject* " << cpythonGetterFunctionName(metaField) << "(PyObject* self, void*)" << endl;
s << '{' << endl;
writeCppSelfDefinition(s, context);
@@ -4161,7 +4261,7 @@ void CppGenerator::writeGetterFunction(QTextStream &s,
s << INDENT << "pyOut = ";
s << "Shiboken::Object::newObject(reinterpret_cast<SbkObjectType *>(" << cpythonTypeNameExt(fieldType)
<< "), " << cppField << ", false, true);" << endl;
- s << INDENT << "Shiboken::Object::setParent(" PYTHON_SELF_VAR ", pyOut)";
+ s << INDENT << "Shiboken::Object::setParent(self, pyOut)";
} else {
s << INDENT << "pyOut = ";
writeToPythonConversion(s, fieldType, metaField->enclosingClass(), cppField);
@@ -4177,7 +4277,7 @@ void CppGenerator::writeSetterFunction(QTextStream &s,
GeneratorContext &context)
{
ErrorCode errorCode(0);
- s << "static int " << cpythonSetterFunctionName(metaField) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* pyIn, void*)" << endl;
+ s << "static int " << cpythonSetterFunctionName(metaField) << "(PyObject* self, PyObject* pyIn, void*)" << endl;
s << '{' << endl;
writeCppSelfDefinition(s, context);
@@ -4193,7 +4293,7 @@ void CppGenerator::writeSetterFunction(QTextStream &s,
AbstractMetaType* fieldType = metaField->type();
- s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ';' << endl;
+ s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << "{nullptr};" << endl;
s << INDENT << "if (!";
writeTypeCheck(s, fieldType, QLatin1String("pyIn"), isNumber(fieldType->typeEntry()));
s << ") {" << endl;
@@ -4219,6 +4319,8 @@ void CppGenerator::writeSetterFunction(QTextStream &s,
s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut_local);" << endl;
s << INDENT << cppField << " = cppOut_local";
} else {
+ if (isPointerToConst(fieldType))
+ s << "const ";
s << getFullTypeNameWithoutModifiers(fieldType);
s << QString::fromLatin1("*").repeated(fieldType->indirections()) << "& cppOut_ptr = ";
s << cppField << ';' << endl;
@@ -4227,7 +4329,7 @@ void CppGenerator::writeSetterFunction(QTextStream &s,
s << ';' << endl << endl;
if (isPointerToWrapperType(fieldType)) {
- s << INDENT << "Shiboken::Object::keepReference(reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR "), \"";
+ s << INDENT << "Shiboken::Object::keepReference(reinterpret_cast<SbkObject*>(self), \"";
s << metaField->name() << "\", pyIn);" << endl;
}
@@ -4240,12 +4342,12 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co
const AbstractMetaClass *metaClass = context.metaClass();
QString baseName = cpythonBaseName(metaClass);
s << "static PyObject* ";
- s << baseName << "_richcompare(PyObject* " PYTHON_SELF_VAR ", PyObject* " PYTHON_ARG ", int op)" << endl;
+ s << baseName << "_richcompare(PyObject* self, PyObject* " << PYTHON_ARG << ", int op)" << endl;
s << '{' << endl;
writeCppSelfDefinition(s, context, false, true);
writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR));
- s << INDENT << "PyObject* " PYTHON_RETURN_VAR " = 0;" << endl;
- s << INDENT << "PythonToCppFunc " PYTHON_TO_CPP_VAR << ';' << endl;
+ s << INDENT << "PyObject* " << PYTHON_RETURN_VAR << " = 0;" << endl;
+ s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ';' << endl;
writeUnusedVariableCast(s, QLatin1String(PYTHON_TO_CPP_VAR));
s << endl;
@@ -4302,15 +4404,17 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co
CodeSnipList snips = func->injectedCodeSnips();
writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, func->arguments().constLast());
} else {
- QString expression = QString::fromLatin1("%1%2 %3 (%4" CPP_ARG0 ")")
- .arg(func->isPointerOperator() ? QLatin1String("&") : QString(),
- QLatin1String(CPP_SELF_VAR), op,
- shouldDereferenceAbstractMetaTypePointer(argType) ? QLatin1String("*") : QString());
s << INDENT;
if (func->type())
- s << func->type()->cppSignature() << " " CPP_RETURN_VAR " = ";
- s << expression << ';' << endl;
- s << INDENT << PYTHON_RETURN_VAR " = ";
+ s << func->type()->cppSignature() << " " << CPP_RETURN_VAR << " = ";
+ // expression
+ if (func->isPointerOperator())
+ s << '&';
+ s << CPP_SELF_VAR << ' ' << op << '(';
+ if (shouldDereferenceAbstractMetaTypePointer(argType))
+ s << '*';
+ s << CPP_ARG0 << ");" << endl;
+ s << INDENT << PYTHON_RETURN_VAR << " = ";
if (func->type())
writeToPythonConversion(s, func->type(), metaClass, QLatin1String(CPP_RETURN_VAR));
else
@@ -4324,9 +4428,9 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co
s << " else {" << endl;
if (operatorId == QLatin1String("Py_EQ") || operatorId == QLatin1String("Py_NE")) {
Indentation indent(INDENT);
- s << INDENT << PYTHON_RETURN_VAR " = "
+ s << INDENT << PYTHON_RETURN_VAR << " = "
<< (operatorId == QLatin1String("Py_EQ") ? "Py_False" : "Py_True") << ';' << endl;
- s << INDENT << "Py_INCREF(" PYTHON_RETURN_VAR ");" << endl;
+ s << INDENT << "Py_INCREF(" << PYTHON_RETURN_VAR << ");" << endl;
} else {
Indentation indent(INDENT);
s << INDENT << "goto " << baseName << "_RichComparison_TypeError;" << endl;
@@ -4343,18 +4447,18 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co
}
s << INDENT << '}' << endl << endl;
- s << INDENT << "if (" PYTHON_RETURN_VAR " && !PyErr_Occurred())" << endl;
+ s << INDENT << "if (" << PYTHON_RETURN_VAR << " && !PyErr_Occurred())" << endl;
{
Indentation indent(INDENT);
- s << INDENT << "return " PYTHON_RETURN_VAR ";" << endl;
+ s << INDENT << "return " << PYTHON_RETURN_VAR << ";" << endl;
}
s << INDENT << baseName << "_RichComparison_TypeError:" << endl;
s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"operator not implemented.\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl << endl;
s << '}' << endl << endl;
}
-void CppGenerator::writeMethodDefinitionEntry(QTextStream& s, const AbstractMetaFunctionList overloads)
+void CppGenerator::writeMethodDefinitionEntry(QTextStream& s, const AbstractMetaFunctionList &overloads)
{
Q_ASSERT(!overloads.isEmpty());
OverloadData overloadData(overloads, this);
@@ -4378,7 +4482,7 @@ void CppGenerator::writeMethodDefinitionEntry(QTextStream& s, const AbstractMeta
s << "|METH_STATIC";
}
-void CppGenerator::writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList overloads)
+void CppGenerator::writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList &overloads)
{
Q_ASSERT(!overloads.isEmpty());
const AbstractMetaFunction* func = overloads.constFirst();
@@ -4510,7 +4614,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu
s << INDENT << "if (!" << cpythonTypeNameExt(cppEnum->typeEntry()) << ')' << endl;
{
Indentation indent(INDENT);
- s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl << endl;
}
}
@@ -4543,7 +4647,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu
<< "))->tp_dict, \"" << enumValue->name() << "\", anonEnumItem) < 0)" << endl;
{
Indentation indent(INDENT);
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
s << INDENT << "Py_DECREF(anonEnumItem);" << endl;
}
@@ -4553,7 +4657,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu
s << enumValueText << ") < 0)" << endl;
{
Indentation indent(INDENT);
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
}
break;
@@ -4564,7 +4668,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu
Indentation indent(INDENT);
s << INDENT << enclosingObjectVariable << ", \"" << enumValue->name() << "\", ";
s << enumValueText << "))" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
break;
case EnumClass: {
@@ -4573,7 +4677,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu
Indentation indent(INDENT);
s << INDENT << enumVarTypeObj<< ", \"" << enumValue->name() << "\", "
<< enumValueText << "))" << endl
- << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ << INDENT << returnStatement(m_currentErrorCode) << endl;
}
break;
}
@@ -4618,11 +4722,11 @@ void CppGenerator::writeFlagsToLong(QTextStream& s, const AbstractMetaEnum* cppE
FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags();
if (!flagsEntry)
return;
- s << "static PyObject* " << cpythonEnumName(cppEnum) << "_long(PyObject* " PYTHON_SELF_VAR ")" << endl;
+ s << "static PyObject* " << cpythonEnumName(cppEnum) << "_long(PyObject* self)" << endl;
s << "{" << endl;
s << INDENT << "int val;" << endl;
AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry);
- s << INDENT << cpythonToCppConversionFunction(flagsType) << PYTHON_SELF_VAR << ", &val);" << endl;
+ s << INDENT << cpythonToCppConversionFunction(flagsType) << "self, &val);" << endl;
s << INDENT << "return Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter<int>(), &val);" << endl;
s << "}" << endl;
}
@@ -4632,12 +4736,12 @@ void CppGenerator::writeFlagsNonZero(QTextStream& s, const AbstractMetaEnum* cpp
FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags();
if (!flagsEntry)
return;
- s << "static int " << cpythonEnumName(cppEnum) << "__nonzero(PyObject* " PYTHON_SELF_VAR ")" << endl;
+ s << "static int " << cpythonEnumName(cppEnum) << "__nonzero(PyObject* self)" << endl;
s << "{" << endl;
s << INDENT << "int val;" << endl;
AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry);
- s << INDENT << cpythonToCppConversionFunction(flagsType) << PYTHON_SELF_VAR << ", &val);" << endl;
+ s << INDENT << cpythonToCppConversionFunction(flagsType) << "self, &val);" << endl;
s << INDENT << "return val != 0;" << endl;
s << "}" << endl;
}
@@ -4679,24 +4783,24 @@ void CppGenerator::writeFlagsNumberMethodsDefinition(QTextStream& s, const Abstr
}
void CppGenerator::writeFlagsBinaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum,
- QString pyOpName, QString cppOpName)
+ const QString &pyOpName, const QString &cppOpName)
{
FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags();
Q_ASSERT(flagsEntry);
- s << "PyObject* " << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject* " PYTHON_SELF_VAR ", PyObject* " PYTHON_ARG ")" << endl;
+ s << "PyObject* " << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject* self, PyObject* " << PYTHON_ARG << ")" << endl;
s << '{' << endl;
AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry);
- s << INDENT << "::" << flagsEntry->originalName() << " cppResult, " CPP_SELF_VAR ", cppArg;" << endl;
+ s << INDENT << "::" << flagsEntry->originalName() << " cppResult, " << CPP_SELF_VAR << ", cppArg;" << endl;
s << "#ifdef IS_PY3K" << endl;
- s << INDENT << CPP_SELF_VAR " = (::" << flagsEntry->originalName() << ")(int)PyLong_AsLong(" PYTHON_SELF_VAR ");" << endl;
- s << INDENT << "cppArg = (" << flagsEntry->originalName() << ")(int)PyLong_AsLong(" PYTHON_ARG ");" << endl;
+ s << INDENT << CPP_SELF_VAR << " = (::" << flagsEntry->originalName() << ")(int)PyLong_AsLong(self);" << endl;
+ s << INDENT << "cppArg = (" << flagsEntry->originalName() << ")(int)PyLong_AsLong(" << PYTHON_ARG << ");" << endl;
s << "#else" << endl;
- s << INDENT << CPP_SELF_VAR " = (::" << flagsEntry->originalName() << ")(int)PyInt_AsLong(" PYTHON_SELF_VAR ");" << endl;
- s << INDENT << "cppArg = (" << flagsEntry->originalName() << ")(int)PyInt_AsLong(" PYTHON_ARG ");" << endl;
+ s << INDENT << CPP_SELF_VAR << " = (::" << flagsEntry->originalName() << ")(int)PyInt_AsLong(self);" << endl;
+ s << INDENT << "cppArg = (" << flagsEntry->originalName() << ")(int)PyInt_AsLong(" << PYTHON_ARG << ");" << endl;
s << "#endif" << endl << endl;
- s << INDENT << "cppResult = " CPP_SELF_VAR " " << cppOpName << " cppArg;" << endl;
+ s << INDENT << "cppResult = " << CPP_SELF_VAR << " " << cppOpName << " cppArg;" << endl;
s << INDENT << "return ";
writeToPythonConversion(s, flagsType, 0, QLatin1String("cppResult"));
s << ';' << endl;
@@ -4704,23 +4808,24 @@ void CppGenerator::writeFlagsBinaryOperator(QTextStream& s, const AbstractMetaEn
}
void CppGenerator::writeFlagsUnaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum,
- QString pyOpName, QString cppOpName, bool boolResult)
+ const QString &pyOpName,
+ const QString &cppOpName, bool boolResult)
{
FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags();
Q_ASSERT(flagsEntry);
- s << "PyObject* " << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject* " PYTHON_SELF_VAR ", PyObject* " PYTHON_ARG ")" << endl;
+ s << "PyObject* " << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject* self, PyObject* " << PYTHON_ARG << ")" << endl;
s << '{' << endl;
AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry);
- s << INDENT << "::" << flagsEntry->originalName() << " " CPP_SELF_VAR ";" << endl;
- s << INDENT << cpythonToCppConversionFunction(flagsType) << PYTHON_SELF_VAR << ", &" CPP_SELF_VAR ");" << endl;
+ s << INDENT << "::" << flagsEntry->originalName() << " " << CPP_SELF_VAR << ";" << endl;
+ s << INDENT << cpythonToCppConversionFunction(flagsType) << "self, &" << CPP_SELF_VAR << ");" << endl;
s << INDENT;
if (boolResult)
s << "bool";
else
s << "::" << flagsEntry->originalName();
- s << " cppResult = " << cppOpName << CPP_SELF_VAR ";" << endl;
+ s << " cppResult = " << cppOpName << CPP_SELF_VAR << ';' << endl;
s << INDENT << "return ";
if (boolResult)
s << "PyBool_FromLong(cppResult)";
@@ -4846,8 +4951,16 @@ void CppGenerator::writeClassRegister(QTextStream &s,
else
s << INDENT << "0," << endl;
- // 9:isInnerClass
- s << INDENT << (hasEnclosingClass ? "true" : "false") << endl;
+ // 9:wrapperflags
+ QByteArrayList wrapperFlags;
+ if (hasEnclosingClass)
+ wrapperFlags.append(QByteArrayLiteral("Shiboken::ObjectType::WrapperFlags::InnerClass"));
+ if (metaClass->deleteInMainThread())
+ wrapperFlags.append(QByteArrayLiteral("Shiboken::ObjectType::WrapperFlags::DeleteInMainThread"));
+ if (wrapperFlags.isEmpty())
+ s << INDENT << '0';
+ else
+ s << INDENT << wrapperFlags.join(" | ");
}
s << INDENT << ");" << endl;
s << INDENT << endl;
@@ -5042,25 +5155,27 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMeta
s << "}\n\n";
}
-QString CppGenerator::writeSmartPointerGetterCast() {
- return QLatin1String("const_cast<char *>(" SMART_POINTER_GETTER ")");
+QString CppGenerator::writeSmartPointerGetterCast()
+{
+ return QLatin1String("const_cast<char *>(")
+ + QLatin1String(SMART_POINTER_GETTER) + QLatin1Char(')');
}
void CppGenerator::writeSetattroFunction(QTextStream &s, GeneratorContext &context)
{
const AbstractMetaClass* metaClass = context.metaClass();
- s << "static int " << cpythonSetattroFunctionName(metaClass) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* name, PyObject* value)" << endl;
+ s << "static int " << cpythonSetattroFunctionName(metaClass) << "(PyObject* self, PyObject* name, PyObject* value)" << endl;
s << '{' << endl;
if (usePySideExtensions()) {
- s << INDENT << "Shiboken::AutoDecRef pp(reinterpret_cast<PyObject*>(PySide::Property::getObject(" PYTHON_SELF_VAR ", name)));" << endl;
+ s << INDENT << "Shiboken::AutoDecRef pp(reinterpret_cast<PyObject*>(PySide::Property::getObject(self, name)));" << endl;
s << INDENT << "if (!pp.isNull())" << endl;
Indentation indent(INDENT);
- s << INDENT << "return PySide::Property::setValue(reinterpret_cast<PySideProperty*>(pp.object()), " PYTHON_SELF_VAR ", value);" << endl;
+ s << INDENT << "return PySide::Property::setValue(reinterpret_cast<PySideProperty*>(pp.object()), self, value);" << endl;
}
if (context.forSmartPointer()) {
s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for the corresponding C++ object held by the smart pointer." << endl;
- s << INDENT << "PyObject *rawObj = PyObject_CallMethod(" PYTHON_SELF_VAR ", "
+ s << INDENT << "PyObject *rawObj = PyObject_CallMethod(self, "
<< writeSmartPointerGetterCast() << ", 0);" << endl;
s << INDENT << "if (rawObj) {" << endl;
{
@@ -5078,7 +5193,7 @@ void CppGenerator::writeSetattroFunction(QTextStream &s, GeneratorContext &conte
}
- s << INDENT << "return PyObject_GenericSetAttr(" PYTHON_SELF_VAR ", name, value);" << endl;
+ s << INDENT << "return PyObject_GenericSetAttr(self, name, value);" << endl;
s << '}' << endl;
}
@@ -5088,27 +5203,29 @@ static inline QString qMetaObjectClassName() { return QStringLiteral("QMetaObjec
void CppGenerator::writeGetattroFunction(QTextStream& s, GeneratorContext &context)
{
const AbstractMetaClass* metaClass = context.metaClass();
- s << "static PyObject* " << cpythonGetattroFunctionName(metaClass) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* name)" << endl;
+ s << "static PyObject* " << cpythonGetattroFunctionName(metaClass) << "(PyObject* self, PyObject* name)" << endl;
s << '{' << endl;
QString getattrFunc;
if (usePySideExtensions() && metaClass->isQObject()) {
AbstractMetaClass *qobjectClass = AbstractMetaClass::findClass(classes(), qObjectClassName());
- getattrFunc = QString::fromLatin1("PySide::getMetaDataFromQObject(%1, " PYTHON_SELF_VAR ", name)")
- .arg(cpythonWrapperCPtr(qobjectClass, QLatin1String(PYTHON_SELF_VAR)));
+ QTextStream(&getattrFunc) << "PySide::getMetaDataFromQObject("
+ << cpythonWrapperCPtr(qobjectClass, QLatin1String("self"))
+ << ", self, name)";
} else {
- getattrFunc = QLatin1String("PyObject_GenericGetAttr(" PYTHON_SELF_VAR ", name)");
+ getattrFunc = QLatin1String("PyObject_GenericGetAttr(") + QLatin1String("self")
+ + QLatin1String(", name)");
}
if (classNeedsGetattroFunction(metaClass)) {
- s << INDENT << "if (" PYTHON_SELF_VAR ") {" << endl;
+ s << INDENT << "if (self) {" << endl;
{
Indentation indent(INDENT);
s << INDENT << "// Search the method in the instance dict" << endl;
- s << INDENT << "if (reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR ")->ob_dict) {" << endl;
+ s << INDENT << "if (reinterpret_cast<SbkObject*>(self)->ob_dict) {" << endl;
{
Indentation indent(INDENT);
- s << INDENT << "PyObject* meth = PyDict_GetItem(reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR ")->ob_dict, name);" << endl;
+ s << INDENT << "PyObject* meth = PyDict_GetItem(reinterpret_cast<SbkObject*>(self)->ob_dict, name);" << endl;
s << INDENT << "if (meth) {" << endl;
{
Indentation indent(INDENT);
@@ -5119,16 +5236,16 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, GeneratorContext &conte
}
s << INDENT << '}' << endl;
s << INDENT << "// Search the method in the type dict" << endl;
- s << INDENT << "if (Shiboken::Object::isUserType(" PYTHON_SELF_VAR ")) {" << endl;
+ s << INDENT << "if (Shiboken::Object::isUserType(self)) {" << endl;
{
Indentation indent(INDENT);
// PYSIDE-772: Perform optimized name mangling.
- s << INDENT << "Shiboken::AutoDecRef tmp(_Pep_PrivateMangle(" PYTHON_SELF_VAR ", name));" << endl;
- s << INDENT << "PyObject *meth = PyDict_GetItem(Py_TYPE(" PYTHON_SELF_VAR ")->tp_dict, tmp);" << endl;
+ s << INDENT << "Shiboken::AutoDecRef tmp(_Pep_PrivateMangle(self, name));" << endl;
+ s << INDENT << "PyObject *meth = PyDict_GetItem(Py_TYPE(self)->tp_dict, tmp);" << endl;
s << INDENT << "if (meth)" << endl;
{
Indentation indent(INDENT);
- s << INDENT << "return PyFunction_Check(meth) ? SBK_PyMethod_New(meth, " PYTHON_SELF_VAR ") : " << getattrFunc << ';' << endl;
+ s << INDENT << "return PyFunction_Check(meth) ? SBK_PyMethod_New(meth, self) : " << getattrFunc << ';' << endl;
}
}
s << INDENT << '}' << endl;
@@ -5147,7 +5264,7 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, GeneratorContext &conte
s << INDENT << "};" << endl;
s << INDENT << "if (Shiboken::String::compare(name, \"" << func->name() << "\") == 0)" << endl;
Indentation indent(INDENT);
- s << INDENT << "return PyCFunction_NewEx(&non_static_" << defName << ", " PYTHON_SELF_VAR ", 0);" << endl;
+ s << INDENT << "return PyCFunction_NewEx(&non_static_" << defName << ", self, 0);" << endl;
}
}
s << INDENT << '}' << endl;
@@ -5168,7 +5285,7 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, GeneratorContext &conte
s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for "
"the corresponding C++ object held by the smart pointer." << endl;
- s << INDENT << "PyObject *rawObj = PyObject_CallMethod(" PYTHON_SELF_VAR ", "
+ s << INDENT << "PyObject *rawObj = PyObject_CallMethod(self, "
<< writeSmartPointerGetterCast() << ", 0);" << endl;
s << INDENT << "if (rawObj) {" << endl;
{
@@ -5289,15 +5406,11 @@ bool CppGenerator::finishGeneration()
QString moduleFileName(outputDirectory() + QLatin1Char('/') + subDirectoryForPackage(packageName()));
moduleFileName += QLatin1Char('/') + moduleName().toLower() + QLatin1String("_module_wrapper.cpp");
- QFile file(moduleFileName);
- verifyDirectoryFor(file);
- if (!file.open(QFile::WriteOnly)) {
- qCWarning(lcShiboken).noquote().nospace()
- << "Error writing file: " << QDir::toNativeSeparators(moduleFileName);
- return false;
- }
- QTextStream s(&file);
+ verifyDirectoryFor(moduleFileName);
+ FileOut file(moduleFileName);
+
+ QTextStream &s = file.stream;
// write license comment
s << licenseComment() << endl;
@@ -5305,10 +5418,10 @@ bool CppGenerator::finishGeneration()
s << "#include <sbkpython.h>" << endl;
s << "#include <shiboken.h>" << endl;
s << "#include <algorithm>" << endl;
+ s << "#include <signature.h>" << endl;
if (usePySideExtensions()) {
s << includeQDebug;
s << "#include <pyside.h>" << endl;
- s << "#include <signature.h>" << endl;
s << "#include <qapp_macro.h>" << endl;
}
@@ -5328,13 +5441,12 @@ bool CppGenerator::finishGeneration()
}
TypeDatabase* typeDb = TypeDatabase::instance();
- TypeSystemTypeEntry* moduleEntry = reinterpret_cast<TypeSystemTypeEntry*>(typeDb->findType(packageName()));
+ const TypeSystemTypeEntry *moduleEntry = typeDb->findTypeSystemType(packageName());
+ Q_ASSERT(moduleEntry);
//Extra includes
s << endl << "// Extra includes" << endl;
- QVector<Include> extraIncludes;
- if (moduleEntry)
- extraIncludes = moduleEntry->extraIncludes();
+ QVector<Include> extraIncludes = moduleEntry->extraIncludes();
for (AbstractMetaEnum *cppEnum : qAsConst(globalEnums))
extraIncludes.append(cppEnum->typeEntry()->extraIncludes());
qSort(extraIncludes.begin(), extraIncludes.end());
@@ -5343,14 +5455,15 @@ bool CppGenerator::finishGeneration()
s << endl;
s << "// Current module's type array." << endl;
- s << "PyTypeObject** " << cppApiVariableName() << ';' << endl;
+ s << "PyTypeObject** " << cppApiVariableName() << " = nullptr;" << endl;
+
+ s << "// Current module's PyObject pointer." << endl;
+ s << "PyObject* " << pythonModuleObjectName() << " = nullptr;" << endl;
s << "// Current module's converter array." << endl;
- s << "SbkConverter** " << convertersVariableName() << ';' << endl;
+ s << "SbkConverter** " << convertersVariableName() << " = nullptr;" << endl;
- CodeSnipList snips;
- if (moduleEntry)
- snips = moduleEntry->codeSnips();
+ const CodeSnipList snips = moduleEntry->codeSnips();
// module inject-code native/beginning
if (!snips.isEmpty()) {
@@ -5519,6 +5632,9 @@ bool CppGenerator::finishGeneration()
s << moduleName() << "_methods);" << endl;
s << "#endif" << endl << endl;
+ s << INDENT << "// Make module available from global scope" << endl;
+ s << INDENT << pythonModuleObjectName() << " = module;" << endl << endl;
+
//s << INDENT << "// Initialize converters for primitive types." << endl;
//s << INDENT << "initConverters();" << endl << endl;
@@ -5601,25 +5717,28 @@ bool CppGenerator::finishGeneration()
// cleanup staticMetaObject attribute
s << INDENT << "PySide::registerCleanupFunction(cleanTypesAttributes);" << endl << endl;
+ }
- // PYSIDE-510: Create a signatures string for the introspection feature.
- s << "// The signatures string for the global functions." << endl;
- s << "// Multiple signatures have their index \"n:\" in front." << endl;
- s << "const char " << moduleName() << "_SignaturesString[] = \"\"" << endl;
- QString line;
- while (signatureStream.readLineInto(&line))
- s << INDENT << '"' << line << "\\n\"" << endl;
- s << ';' << endl;
- // finish the rest of __signature__ initialization.
- s << INDENT << "FinishSignatureInitialization(module, " << moduleName()
- << "_SignaturesString);" << endl;
+ // PYSIDE-510: Create a signatures string for the introspection feature.
+ s << "// The signatures string for the global functions." << endl;
+ s << "// Multiple signatures have their index \"n:\" in front." << endl;
+ s << "const char " << moduleName() << "_SignaturesString[] = \"\"" << endl;
+ QString line;
+ while (signatureStream.readLineInto(&line))
+ s << INDENT << '"' << line << "\\n\"" << endl;
+ s << ';' << endl;
+ // finish the rest of __signature__ initialization.
+ s << INDENT << "FinishSignatureInitialization(module, " << moduleName()
+ << "_SignaturesString);" << endl;
+
+ if (usePySideExtensions()) {
// initialize the qApp module.
- s << INDENT << "NotifyModuleForQApp(module);" << endl << endl;
+ s << INDENT << "NotifyModuleForQApp(module);" << endl;
}
-
+ s << endl;
s << "SBK_MODULE_INIT_FUNCTION_END" << endl;
- return true;
+ return file.done() != FileOut::Failure;
}
static ArgumentOwner getArgumentOwner(const AbstractMetaFunction* func, int argIndex)
@@ -5663,22 +5782,20 @@ bool CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMeta
if (parentIndex == 0) {
parentVariable = QLatin1String(PYTHON_RETURN_VAR);
} else if (parentIndex == -1) {
- parentVariable = QLatin1String(PYTHON_SELF_VAR);
+ parentVariable = QLatin1String("self");
} else {
parentVariable = usePyArgs
- ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(parentIndex - 1)
- : QLatin1String(PYTHON_ARG);
+ ? pythonArgsAt(parentIndex - 1) : QLatin1String(PYTHON_ARG);
}
}
if (childIndex == 0) {
childVariable = QLatin1String(PYTHON_RETURN_VAR);
} else if (childIndex == -1) {
- childVariable = QLatin1String(PYTHON_SELF_VAR);
+ childVariable = QLatin1String("self");
} else {
childVariable = usePyArgs
- ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(childIndex - 1)
- : QLatin1String(PYTHON_ARG);
+ ? pythonArgsAt(childIndex - 1) : QLatin1String(PYTHON_ARG);
}
s << INDENT << "Shiboken::Object::setParent(" << parentVariable << ", " << childVariable << ");\n";
@@ -5717,7 +5834,7 @@ void CppGenerator::writeReturnValueHeuristics(QTextStream& s, const AbstractMeta
ArgumentOwner argOwner = getArgumentOwner(func, ArgumentOwner::ReturnIndex);
if (argOwner.action == ArgumentOwner::Invalid || argOwner.index != ArgumentOwner::ThisIndex) {
if (isPointerToWrapperType(type))
- s << INDENT << "Shiboken::Object::setParent(" << self << ", " PYTHON_RETURN_VAR ");" << endl;
+ s << INDENT << "Shiboken::Object::setParent(self, " << PYTHON_RETURN_VAR << ");" << endl;
}
}
@@ -5737,19 +5854,19 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream &s, GeneratorContext &
ErrorCode errorCode(0);
// __len__
- s << "Py_ssize_t " << cpythonBaseName(metaClass->typeEntry()) << "__len__(PyObject* " PYTHON_SELF_VAR ")" << endl;
+ s << "Py_ssize_t " << cpythonBaseName(metaClass->typeEntry()) << "__len__(PyObject* self)" << endl;
s << '{' << endl;
writeCppSelfDefinition(s, context);
- s << INDENT << "return " CPP_SELF_VAR "->size();" << endl;
+ s << INDENT << "return " << CPP_SELF_VAR << "->size();" << endl;
s << '}' << endl;
// __getitem__
- s << "PyObject* " << cpythonBaseName(metaClass->typeEntry()) << "__getitem__(PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i)" << endl;
+ s << "PyObject* " << cpythonBaseName(metaClass->typeEntry()) << "__getitem__(PyObject* self, Py_ssize_t _i)" << endl;
s << '{' << endl;
writeCppSelfDefinition(s, context);
writeIndexError(s, QLatin1String("index out of bounds"));
- s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " CPP_SELF_VAR "->begin();" << endl;
+ s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " << CPP_SELF_VAR << "->begin();" << endl;
s << INDENT << "for (Py_ssize_t pos = 0; pos < _i; pos++) _item++;" << endl;
const AbstractMetaType* itemType = metaClass->templateBaseClassInstantiations().constFirst();
@@ -5761,7 +5878,7 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream &s, GeneratorContext &
// __setitem__
ErrorCode errorCode2(-1);
- s << "int " << cpythonBaseName(metaClass->typeEntry()) << "__setitem__(PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i, PyObject* pyArg)" << endl;
+ s << "int " << cpythonBaseName(metaClass->typeEntry()) << "__setitem__(PyObject* self, Py_ssize_t _i, PyObject* pyArg)" << endl;
s << '{' << endl;
writeCppSelfDefinition(s, context);
writeIndexError(s, QLatin1String("list assignment index out of range"));
@@ -5779,7 +5896,7 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream &s, GeneratorContext &
s << INDENT << '}' << endl;
writeArgumentConversion(s, itemType, QLatin1String("cppValue"), QLatin1String("pyArg"), metaClass);
- s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " CPP_SELF_VAR "->begin();" << endl;
+ s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " << CPP_SELF_VAR << "->begin();" << endl;
s << INDENT << "for (Py_ssize_t pos = 0; pos < _i; pos++) _item++;" << endl;
s << INDENT << "*_item = cppValue;" << endl;
s << INDENT << "return 0;" << endl;
@@ -5787,11 +5904,11 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream &s, GeneratorContext &
}
void CppGenerator::writeIndexError(QTextStream& s, const QString& errorMsg)
{
- s << INDENT << "if (_i < 0 || _i >= (Py_ssize_t) " CPP_SELF_VAR "->size()) {" << endl;
+ s << INDENT << "if (_i < 0 || _i >= (Py_ssize_t) " << CPP_SELF_VAR << "->size()) {" << endl;
{
Indentation indent(INDENT);
s << INDENT << "PyErr_SetString(PyExc_IndexError, \"" << errorMsg << "\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
s << INDENT << '}' << endl;
}
@@ -5808,7 +5925,10 @@ QString CppGenerator::writeReprFunction(QTextStream &s, GeneratorContext &contex
s << INDENT << "QBuffer buffer;" << endl;
s << INDENT << "buffer.open(QBuffer::ReadWrite);" << endl;
s << INDENT << "QDebug dbg(&buffer);" << endl;
- s << INDENT << "dbg << " << (metaClass->typeEntry()->isValue() ? "*" : "") << CPP_SELF_VAR ";" << endl;
+ s << INDENT << "dbg << ";
+ if (metaClass->typeEntry()->isValue())
+ s << '*';
+ s << CPP_SELF_VAR << ';' << endl;
s << INDENT << "buffer.close();" << endl;
s << INDENT << "QByteArray str = buffer.data();" << endl;
s << INDENT << "int idx = str.indexOf('(');" << endl;
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.h b/sources/shiboken2/generator/shiboken2/cppgenerator.h
index 1b59bcda7..55a1c265d 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.h
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.h
@@ -234,8 +234,8 @@ private:
void writeClassDefinition(QTextStream &s,
const AbstractMetaClass *metaClass,
GeneratorContext &classContext);
- void writeMethodDefinitionEntry(QTextStream& s, const AbstractMetaFunctionList overloads);
- void writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList overloads);
+ void writeMethodDefinitionEntry(QTextStream& s, const AbstractMetaFunctionList &overloads);
+ void writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList &overloads);
void writeSignatureInfo(QTextStream &s, const AbstractMetaFunctionList &overloads);
/// Writes the implementation of all methods part of python sequence protocol
void writeSequenceMethods(QTextStream &s,
@@ -275,9 +275,10 @@ private:
void writeFlagsNonZero(QTextStream& s, const AbstractMetaEnum* cppEnum);
void writeFlagsNumberMethodsDefinition(QTextStream& s, const AbstractMetaEnum* cppEnum);
void writeFlagsBinaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum,
- QString pyOpName, QString cppOpName);
+ const QString &pyOpName, const QString &cppOpName);
void writeFlagsUnaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum,
- QString pyOpName, QString cppOpName, bool boolResult = false);
+ const QString &pyOpName, const QString &cppOpName,
+ bool boolResult = false);
/// Writes the function that registers the multiple inheritance information for the classes that need it.
void writeMultipleInheritanceInitializerFunction(QTextStream& s, const AbstractMetaClass* metaClass);
@@ -292,7 +293,7 @@ private:
void writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool userHeuristicForReturn);
bool writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool userHeuristicPolicy);
- void writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self = QLatin1String(PYTHON_SELF_VAR));
+ void writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self = QLatin1String("self"));
void writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorContext &context) const;
/**
@@ -327,7 +328,9 @@ private:
QString writeReprFunction(QTextStream &s, GeneratorContext &context);
- bool hasBoolCast(const AbstractMetaClass* metaClass) const;
+ const AbstractMetaFunction *boolCast(const AbstractMetaClass* metaClass) const;
+ bool hasBoolCast(const AbstractMetaClass* metaClass) const
+ { return boolCast(metaClass) != nullptr; }
// Number protocol structure members names.
static QHash<QString, QString> m_nbFuncs;
diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.cpp b/sources/shiboken2/generator/shiboken2/headergenerator.cpp
index 8fde3cd31..8881d71f4 100644
--- a/sources/shiboken2/generator/shiboken2/headergenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/headergenerator.cpp
@@ -32,6 +32,8 @@
#include <reporthandler.h>
#include <fileout.h>
+#include <algorithm>
+
#include <QtCore/QDir>
#include <QtCore/QTextStream>
#include <QtCore/QVariant>
@@ -49,11 +51,10 @@ QString HeaderGenerator::fileNameForContext(GeneratorContext &context) const
QString fileNameBase = metaClass->qualifiedCppName().toLower();
fileNameBase.replace(QLatin1String("::"), QLatin1String("_"));
return fileNameBase + fileNameSuffix();
- } else {
- const AbstractMetaType *smartPointerType = context.preciseType();
- QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass);
- return fileNameBase + fileNameSuffix();
}
+ const AbstractMetaType *smartPointerType = context.preciseType();
+ QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass);
+ return fileNameBase + fileNameSuffix();
}
void HeaderGenerator::writeCopyCtor(QTextStream& s, const AbstractMetaClass* metaClass) const
@@ -116,8 +117,6 @@ void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classConte
if (!avoidProtectedHack())
s << "#define protected public" << endl << endl;
- s << "#include <shiboken.h>" << endl << endl;
-
//Includes
s << metaClass->typeEntry()->include() << endl;
@@ -173,7 +172,7 @@ void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classConte
s << INDENT << "void* qt_metacast(const char* _clname) override;" << endl;
}
- if (m_inheritedOverloads.size()) {
+ if (!m_inheritedOverloads.isEmpty()) {
s << INDENT << "// Inherited overloads, because the using keyword sux" << endl;
writeInheritedOverloads(s);
m_inheritedOverloads.clear();
@@ -230,7 +229,7 @@ void HeaderGenerator::writeFunction(QTextStream& s, const AbstractMetaFunction*
QString argName = arg->name();
const TypeEntry* enumTypeEntry = 0;
if (arg->type()->isFlags())
- enumTypeEntry = reinterpret_cast<const FlagsTypeEntry*>(arg->type()->typeEntry())->originator();
+ enumTypeEntry = static_cast<const FlagsTypeEntry*>(arg->type()->typeEntry())->originator();
else if (arg->type()->isEnum())
enumTypeEntry = arg->type()->typeEntry();
if (enumTypeEntry)
@@ -284,49 +283,86 @@ void HeaderGenerator::writeFunction(QTextStream& s, const AbstractMetaFunction*
}
}
-static void _writeTypeIndexDefineLine(QTextStream& s, const QString& variableName, int typeIndex)
+static void _writeTypeIndexValue(QTextStream& s, const QString& variableName,
+ int typeIndex)
{
- s << "#define ";
- s.setFieldWidth(60);
+ s << " ";
+ s.setFieldWidth(56);
s << variableName;
s.setFieldWidth(0);
- s << ' ' << typeIndex << endl;
+ s << " = " << typeIndex;
+}
+
+static inline void _writeTypeIndexValueLine(QTextStream& s,
+ const QString& variableName,
+ int typeIndex)
+{
+ _writeTypeIndexValue(s, variableName, typeIndex);
+ s << ",\n";
}
-void HeaderGenerator::writeTypeIndexDefineLine(QTextStream& s, const TypeEntry* typeEntry)
+
+void HeaderGenerator::writeTypeIndexValueLine(QTextStream& s, const TypeEntry* typeEntry)
{
if (!typeEntry || !typeEntry->generateCode())
return;
s.setFieldAlignment(QTextStream::AlignLeft);
- int typeIndex = getTypeIndex(typeEntry);
- _writeTypeIndexDefineLine(s, getTypeIndexVariableName(typeEntry), typeIndex);
+ const int typeIndex = typeEntry->sbkIndex();
+ _writeTypeIndexValueLine(s, getTypeIndexVariableName(typeEntry), typeIndex);
if (typeEntry->isComplex()) {
- const ComplexTypeEntry* cType = reinterpret_cast<const ComplexTypeEntry*>(typeEntry);
+ const ComplexTypeEntry* cType = static_cast<const ComplexTypeEntry*>(typeEntry);
if (cType->baseContainerType()) {
const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes(), cType);
if (metaClass->templateBaseClass())
- _writeTypeIndexDefineLine(s, getTypeIndexVariableName(metaClass, true), typeIndex);
+ _writeTypeIndexValueLine(s, getTypeIndexVariableName(metaClass, true), typeIndex);
}
}
if (typeEntry->isEnum()) {
- const EnumTypeEntry* ete = reinterpret_cast<const EnumTypeEntry*>(typeEntry);
+ const EnumTypeEntry* ete = static_cast<const EnumTypeEntry*>(typeEntry);
if (ete->flags())
- writeTypeIndexDefineLine(s, ete->flags());
+ writeTypeIndexValueLine(s, ete->flags());
}
}
-void HeaderGenerator::writeTypeIndexDefine(QTextStream& s, const AbstractMetaClass* metaClass)
+void HeaderGenerator::writeTypeIndexValueLines(QTextStream& s, const AbstractMetaClass* metaClass)
{
if (!metaClass->typeEntry()->generateCode())
return;
- writeTypeIndexDefineLine(s, metaClass->typeEntry());
+ writeTypeIndexValueLine(s, metaClass->typeEntry());
const AbstractMetaEnumList &enums = metaClass->enums();
for (const AbstractMetaEnum *metaEnum : enums) {
if (metaEnum->isPrivate())
continue;
- writeTypeIndexDefineLine(s, metaEnum->typeEntry());
+ writeTypeIndexValueLine(s, metaEnum->typeEntry());
}
}
+// Format the typedefs for the typedef entries to be generated
+static void formatTypeDefEntries(QTextStream &s)
+{
+ QVector<const TypedefEntry *> entries;
+ const auto typeDbEntries = TypeDatabase::instance()->typedefEntries();
+ for (auto it = typeDbEntries.cbegin(), end = typeDbEntries.cend(); it != end; ++it) {
+ if (it.value()->generateCode() != 0)
+ entries.append(it.value());
+ }
+ if (entries.isEmpty())
+ return;
+ s << "\n// typedef entries\n";
+ for (const auto e : entries) {
+ const QString name = e->qualifiedCppName();
+ // Fixme: simplify by using nested namespaces in C++ 17.
+ const auto components = name.splitRef(QLatin1String("::"));
+ const int nameSpaceCount = components.size() - 1;
+ for (int n = 0; n < nameSpaceCount; ++n)
+ s << "namespace " << components.at(n) << " {\n";
+ s << "using " << components.constLast() << " = " << e->sourceType() << ";\n";
+ for (int n = 0; n < nameSpaceCount; ++n)
+ s << "}\n";
+ }
+ s << '\n';
+}
+
+
bool HeaderGenerator::finishGeneration()
{
// Generate the main header for this module.
@@ -342,47 +378,49 @@ bool HeaderGenerator::finishGeneration()
Indentation indent(INDENT);
- macrosStream << "// Type indices" << endl;
+ macrosStream << "// Type indices\nenum : int {\n";
AbstractMetaEnumList globalEnums = this->globalEnums();
- const AbstractMetaClassList &classList = classes();
+ AbstractMetaClassList classList = classes();
+
+ std::sort(classList.begin(), classList.end(), [](AbstractMetaClass *a, AbstractMetaClass* b) {
+ return a->typeEntry()->sbkIndex() < b->typeEntry()->sbkIndex();
+ });
+
for (const AbstractMetaClass *metaClass : classList) {
- writeTypeIndexDefine(macrosStream, metaClass);
+ writeTypeIndexValueLines(macrosStream, metaClass);
lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass);
}
for (const AbstractMetaEnum *metaEnum : qAsConst(globalEnums))
- writeTypeIndexDefineLine(macrosStream, metaEnum->typeEntry());
+ writeTypeIndexValueLine(macrosStream, metaEnum->typeEntry());
// Write the smart pointer define indexes.
int smartPointerCountIndex = getMaxTypeIndex();
int smartPointerCount = 0;
const QVector<const AbstractMetaType *> &instantiatedSmartPtrs = instantiatedSmartPointers();
for (const AbstractMetaType *metaType : instantiatedSmartPtrs) {
- QString variableName = getTypeIndexVariableName(metaType);
- macrosStream << "#define ";
- macrosStream.setFieldWidth(60);
- macrosStream << variableName;
- macrosStream.setFieldWidth(0);
- macrosStream << ' ' << smartPointerCountIndex << " // " << metaType->cppSignature()
- << endl;
+ _writeTypeIndexValue(macrosStream, getTypeIndexVariableName(metaType),
+ smartPointerCountIndex);
+ macrosStream << ", // " << metaType->cppSignature() << endl;
++smartPointerCountIndex;
++smartPointerCount;
}
+ _writeTypeIndexValue(macrosStream,
+ QLatin1String("SBK_") + moduleName() + QLatin1String("_IDX_COUNT"),
+ getMaxTypeIndex() + smartPointerCount);
+ macrosStream << "\n};\n";
- macrosStream << "#define ";
- macrosStream.setFieldWidth(60);
- macrosStream << QLatin1String("SBK_") + moduleName() + QLatin1String("_IDX_COUNT");
- macrosStream.setFieldWidth(0);
- macrosStream << ' ' << getMaxTypeIndex() + smartPointerCount << endl << endl;
macrosStream << "// This variable stores all Python types exported by this module." << endl;
macrosStream << "extern PyTypeObject** " << cppApiVariableName() << ';' << endl << endl;
+ macrosStream << "// This variable stores the Python module object exported by this module." << endl;
+ macrosStream << "extern PyObject* " << pythonModuleObjectName() << ';' << endl << endl;
macrosStream << "// This variable stores all type converters exported by this module." << endl;
macrosStream << "extern SbkConverter** " << convertersVariableName() << ';' << endl << endl;
// TODO-CONVERTER ------------------------------------------------------------------------------
// Using a counter would not do, a fix must be made to APIExtractor's getTypeIndex().
- macrosStream << "// Converter indices" << endl;
+ macrosStream << "// Converter indices\nenum : int {\n";
const PrimitiveTypeEntryList &primitives = primitiveTypes();
int pCount = 0;
for (const PrimitiveTypeEntry *ptype : primitives) {
@@ -393,28 +431,25 @@ bool HeaderGenerator::finishGeneration()
if (!ptype->generateCode() || !ptype->customConversion())
continue;
- _writeTypeIndexDefineLine(macrosStream, getTypeIndexVariableName(ptype), pCount++);
+ _writeTypeIndexValueLine(macrosStream, getTypeIndexVariableName(ptype), pCount++);
}
const QVector<const AbstractMetaType *> &containers = instantiatedContainers();
for (const AbstractMetaType *container : containers) {
- //_writeTypeIndexDefineLine(macrosStream, getTypeIndexVariableName(container), pCount);
- // DEBUG
- QString variableName = getTypeIndexVariableName(container);
- macrosStream << "#define ";
- macrosStream.setFieldWidth(60);
- macrosStream << variableName;
- macrosStream.setFieldWidth(0);
- macrosStream << ' ' << pCount << " // " << container->cppSignature() << endl;
- // DEBUG
+ _writeTypeIndexValue(macrosStream, getTypeIndexVariableName(container), pCount);
+ macrosStream << ", // " << container->cppSignature() << endl;
pCount++;
}
// Because on win32 the compiler will not accept a zero length array.
if (pCount == 0)
pCount++;
- _writeTypeIndexDefineLine(macrosStream, QStringLiteral("SBK_%1_CONVERTERS_IDX_COUNT").arg(moduleName()), pCount);
- macrosStream << endl;
+ _writeTypeIndexValue(macrosStream, QStringLiteral("SBK_%1_CONVERTERS_IDX_COUNT")
+ .arg(moduleName()), pCount);
+ macrosStream << "\n};\n";
+
+ formatTypeDefEntries(macrosStream);
+
// TODO-CONVERTER ------------------------------------------------------------------------------
macrosStream << "// Macros for type check" << endl;
@@ -474,12 +509,6 @@ bool HeaderGenerator::finishGeneration()
s << "#include <sbkpython.h>" << endl;
s << "#include <sbkconverter.h>" << endl;
- s << "#include <sbkenum.h>" << endl;
- s << "#include <basewrapper.h>" << endl;
- s << "#include <bindingmanager.h>" << endl;
- s << "#include <memory>" << endl << endl;
- if (usePySideExtensions())
- s << "#include <pysidesignal.h>" << endl;
QStringList requiredTargetImports = TypeDatabase::instance()->requiredTargetImports();
if (!requiredTargetImports.isEmpty()) {
@@ -580,7 +609,7 @@ void HeaderGenerator::writeInheritedOverloads(QTextStream& s)
QString argName = arg->name();
const TypeEntry* enumTypeEntry = 0;
if (arg->type()->isFlags())
- enumTypeEntry = reinterpret_cast<const FlagsTypeEntry*>(arg->type()->typeEntry())->originator();
+ enumTypeEntry = static_cast<const FlagsTypeEntry*>(arg->type()->typeEntry())->originator();
else if (arg->type()->isEnum())
enumTypeEntry = arg->type()->typeEntry();
if (enumTypeEntry)
diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.h b/sources/shiboken2/generator/shiboken2/headergenerator.h
index acf0448a7..821531aab 100644
--- a/sources/shiboken2/generator/shiboken2/headergenerator.h
+++ b/sources/shiboken2/generator/shiboken2/headergenerator.h
@@ -55,8 +55,8 @@ private:
void writeSbkTypeFunction(QTextStream& s, const AbstractMetaEnum* cppEnum);
void writeSbkTypeFunction(QTextStream& s, const AbstractMetaClass* cppClass);
void writeSbkTypeFunction(QTextStream &s, const AbstractMetaType *metaType);
- void writeTypeIndexDefineLine(QTextStream& s, const TypeEntry* typeEntry);
- void writeTypeIndexDefine(QTextStream& s, const AbstractMetaClass* metaClass);
+ void writeTypeIndexValueLine(QTextStream& s, const TypeEntry* typeEntry);
+ void writeTypeIndexValueLines(QTextStream& s, const AbstractMetaClass* metaClass);
void writeProtectedEnumSurrogate(QTextStream& s, const AbstractMetaEnum* cppEnum);
void writeInheritedOverloads(QTextStream& s);
diff --git a/sources/shiboken2/generator/shiboken2/overloaddata.cpp b/sources/shiboken2/generator/shiboken2/overloaddata.cpp
index 73198ba12..a95603754 100644
--- a/sources/shiboken2/generator/shiboken2/overloaddata.cpp
+++ b/sources/shiboken2/generator/shiboken2/overloaddata.cpp
@@ -94,8 +94,6 @@ static bool typesAreEqual(const AbstractMetaType* typeA, const AbstractMetaType*
*/
struct OverloadSortData
{
- OverloadSortData() : counter(0) {}
-
/**
* Adds a typeName into the type map without associating it with
* a OverloadData. This is done to express type dependencies that could
@@ -121,7 +119,7 @@ struct OverloadSortData
int lastProcessedItemId() { return counter - 1; }
- int counter;
+ int counter = 0;
QHash<QString, int> map; // typeName -> id
QHash<int, OverloadData*> reverseMap; // id -> OverloadData;
};
@@ -149,11 +147,11 @@ static QString getImplicitConversionTypeName(const AbstractMetaType* containerTy
for (const AbstractMetaType *otherType : instantiations)
types << (otherType == instantiation ? impConv : getTypeName(otherType));
- const ContainerTypeEntry* containerTypeEntry = dynamic_cast<const ContainerTypeEntry*>(containerType->typeEntry());
- return containerTypeEntry->qualifiedCppName() + QLatin1Char('<')
+ return containerType->typeEntry()->qualifiedCppName() + QLatin1Char('<')
+ types.join(QLatin1String(", ")) + QLatin1String(" >");
}
+// overloaddata.cpp
static QString msgCyclicDependency(const QString &funcName, const QString &graphName,
const OverloadData::MetaFunctionList &involvedConversions)
{
@@ -499,7 +497,8 @@ OverloadData::OverloadData(const AbstractMetaFunctionList& overloads, const Shib
OverloadData::OverloadData(OverloadData* headOverloadData, const AbstractMetaFunction* func,
const AbstractMetaType* argType, int argPos)
: m_minArgs(256), m_maxArgs(0), m_argPos(argPos), m_argType(argType),
- m_headOverloadData(headOverloadData), m_previousOverloadData(0)
+ m_headOverloadData(headOverloadData), m_previousOverloadData(nullptr),
+ m_generator(nullptr)
{
if (func)
this->addOverload(func);
@@ -808,8 +807,7 @@ QPair<int, int> OverloadData::getMinMaxArguments(const AbstractMetaFunctionList&
{
int minArgs = 10000;
int maxArgs = 0;
- for (int i = 0; i < overloads.size(); i++) {
- const AbstractMetaFunction* func = overloads[i];
+ for (const AbstractMetaFunction *func : overloads) {
int origNumArgs = func->arguments().size();
int removed = numberOfRemovedArguments(func);
int numArgs = origNumArgs - removed;
@@ -825,7 +823,7 @@ QPair<int, int> OverloadData::getMinMaxArguments(const AbstractMetaFunctionList&
minArgs = fixedArgIndex;
}
}
- return QPair<int, int>(minArgs, maxArgs);
+ return {minArgs, maxArgs};
}
bool OverloadData::isSingleArgument(const AbstractMetaFunctionList& overloads)
@@ -840,7 +838,7 @@ bool OverloadData::isSingleArgument(const AbstractMetaFunctionList& overloads)
return singleArgument;
}
-void OverloadData::dumpGraph(QString filename) const
+void OverloadData::dumpGraph(const QString &filename) const
{
QFile file(filename);
if (file.open(QFile::WriteOnly)) {
diff --git a/sources/shiboken2/generator/shiboken2/overloaddata.h b/sources/shiboken2/generator/shiboken2/overloaddata.h
index 435c19aa2..4759ca9c3 100644
--- a/sources/shiboken2/generator/shiboken2/overloaddata.h
+++ b/sources/shiboken2/generator/shiboken2/overloaddata.h
@@ -114,7 +114,7 @@ public:
/// Returns true if all overloads have no more than one argument.
static bool isSingleArgument(const AbstractMetaFunctionList& overloads);
- void dumpGraph(QString filename) const;
+ void dumpGraph(const QString &filename) const;
QString dumpGraph() const;
bool hasArgumentTypeReplace() const;
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
index 80096cbf2..b9eea7529 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
@@ -28,9 +28,11 @@
#include "shibokengenerator.h"
#include <abstractmetalang.h>
+#include <messages.h>
#include "overloaddata.h"
#include <reporthandler.h>
#include <typedatabase.h>
+#include <abstractmetabuilder.h>
#include <iostream>
#include <QtCore/QDir>
@@ -39,13 +41,29 @@
#include <limits>
#include <memory>
-#define NULL_VALUE "NULL"
-#define AVOID_PROTECTED_HACK "avoid-protected-hack"
-#define PARENT_CTOR_HEURISTIC "enable-parent-ctor-heuristic"
-#define RETURN_VALUE_HEURISTIC "enable-return-value-heuristic"
-#define ENABLE_PYSIDE_EXTENSIONS "enable-pyside-extensions"
-#define DISABLE_VERBOSE_ERROR_MESSAGES "disable-verbose-error-messages"
-#define USE_ISNULL_AS_NB_NONZERO "use-isnull-as-nb_nonzero"
+static const char NULL_VALUE[] = "NULL";
+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";
+
+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 *PYTHON_ARG = "pyArg";
+const char *PYTHON_ARGS = "pyArgs";
+const char *PYTHON_OVERRIDE_VAR = "pyOverride";
+const char *PYTHON_RETURN_VAR = "pyResult";
+const char *PYTHON_TO_CPP_VAR = "pythonToCpp";
+const char *SMART_POINTER_GETTER = "kSmartPointerGetter";
+
+const char *CONV_RULE_OUT_VAR_SUFFIX = "_out";
+const char *BEGIN_ALLOW_THREADS =
+ "PyThreadState* _save = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS";
+const char *END_ALLOW_THREADS = "PyEval_RestoreThread(_save); // Py_END_ALLOW_THREADS";
//static void dumpFunction(AbstractMetaFunctionList lst);
@@ -100,7 +118,7 @@ static QString resolveScopePrefix(const AbstractMetaEnum *metaEnum,
return resolveScopePrefix(parts, value);
}
-ShibokenGenerator::ShibokenGenerator() : Generator()
+ShibokenGenerator::ShibokenGenerator()
{
if (m_pythonPrimitiveTypeName.isEmpty())
ShibokenGenerator::initPrimitiveTypesCorrespondences();
@@ -117,17 +135,19 @@ ShibokenGenerator::ShibokenGenerator() : Generator()
m_typeSystemConvName[TypeSystemIsConvertibleFunction] = QLatin1String("isConvertible");
m_typeSystemConvName[TypeSystemToCppFunction] = QLatin1String("toCpp");
m_typeSystemConvName[TypeSystemToPythonFunction] = QLatin1String("toPython");
+
+ const char CHECKTYPE_REGEX[] = R"(%CHECKTYPE\[([^\[]*)\]\()";
+ const char ISCONVERTIBLE_REGEX[] = R"(%ISCONVERTIBLE\[([^\[]*)\]\()";
+ const char CONVERTTOPYTHON_REGEX[] = R"(%CONVERTTOPYTHON\[([^\[]*)\]\()";
+ const char CONVERTTOCPP_REGEX[] =
+ R"((\*?%?[a-zA-Z_][\w\.]*(?:\[[^\[^<^>]+\])*)(?:\s+)=(?:\s+)%CONVERTTOCPP\[([^\[]*)\]\()";
m_typeSystemConvRegEx[TypeSystemCheckFunction] = QRegularExpression(QLatin1String(CHECKTYPE_REGEX));
m_typeSystemConvRegEx[TypeSystemIsConvertibleFunction] = QRegularExpression(QLatin1String(ISCONVERTIBLE_REGEX));
m_typeSystemConvRegEx[TypeSystemToPythonFunction] = QRegularExpression(QLatin1String(CONVERTTOPYTHON_REGEX));
m_typeSystemConvRegEx[TypeSystemToCppFunction] = QRegularExpression(QLatin1String(CONVERTTOCPP_REGEX));
}
-ShibokenGenerator::~ShibokenGenerator()
-{
- // TODO-CONVERTER: it must be caching types that were not created here.
- //qDeleteAll(m_metaTypeFromStringCache.values());
-}
+ShibokenGenerator::~ShibokenGenerator() = default;
void ShibokenGenerator::clearTpFuncs()
{
@@ -277,7 +297,7 @@ bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass* metaCl
for (const AbstractMetaFunction *func : funcs) {
if (!func->isProtected() || func->isSignal() || func->isModifiedRemoved())
continue;
- else if (func->isOperatorOverload())
+ if (func->isOperatorOverload())
protectedOperators++;
else
protectedFunctions++;
@@ -332,9 +352,8 @@ QString ShibokenGenerator::wrapperName(const AbstractMetaClass* metaClass) const
result += QLatin1String("Wrapper");
return result;
- } else {
- return metaClass->qualifiedCppName();
}
+ return metaClass->qualifiedCppName();
}
QString ShibokenGenerator::wrapperName(const AbstractMetaType *metaType) const
@@ -342,7 +361,19 @@ QString ShibokenGenerator::wrapperName(const AbstractMetaType *metaType) const
return metaType->cppSignature();
}
-QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction* func)
+QString ShibokenGenerator::fullPythonClassName(const AbstractMetaClass *metaClass)
+{
+ QString fullClassName = metaClass->name();
+ const AbstractMetaClass *enclosing = metaClass->enclosingClass();
+ while (enclosing) {
+ fullClassName.prepend(enclosing->name() + QLatin1Char('.'));
+ enclosing = enclosing->enclosingClass();
+ }
+ fullClassName.prepend(packageName() + QLatin1Char('.'));
+ return fullClassName;
+}
+
+QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction *func) //WS
{
QString funcName;
if (func->isOperatorOverload())
@@ -350,11 +381,11 @@ QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction* fu
else
funcName = func->name();
if (func->ownerClass()) {
- QString fullName = func->ownerClass()->fullName();
+ QString fullClassName = fullPythonClassName(func->ownerClass());
if (func->isConstructor())
- funcName = fullName;
+ funcName = fullClassName;
else
- funcName.prepend(fullName + QLatin1Char('.'));
+ funcName.prepend(fullClassName + QLatin1Char('.'));
}
else {
funcName = packageName() + QLatin1Char('.') + func->name();
@@ -434,7 +465,8 @@ QString ShibokenGenerator::cpythonSetterFunctionName(const AbstractMetaField* me
return QStringLiteral("%1_set_%2").arg(cpythonBaseName(metaField->enclosingClass()), metaField->name());
}
-static QString cpythonEnumFlagsName(QString moduleName, QString qualifiedCppName)
+static QString cpythonEnumFlagsName(const QString &moduleName,
+ const QString &qualifiedCppName)
{
QString result = QStringLiteral("Sbk%1_%2").arg(moduleName, qualifiedCppName);
result.replace(QLatin1String("::"), QLatin1String("_"));
@@ -570,7 +602,7 @@ QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction
fieldName.prepend(prefix);
prefix.clear();
} else {
- fieldName.prepend(QLatin1String(CPP_SELF_VAR "->"));
+ fieldName.prepend(QLatin1String(CPP_SELF_VAR) + QLatin1String("->"));
}
value.replace(match.captured(1), fieldName);
break;
@@ -616,12 +648,14 @@ QString ShibokenGenerator::cpythonSpecialCastFunctionName(const AbstractMetaClas
return cpythonBaseName(metaClass->typeEntry()) + QLatin1String("SpecialCastFunction");
}
-QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClass* metaClass, QString argName)
+QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClass* metaClass,
+ const QString &argName)
{
return cpythonWrapperCPtr(metaClass->typeEntry(), argName);
}
-QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType *metaType, QString argName)
+QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType *metaType,
+ const QString &argName)
{
if (!ShibokenGenerator::isWrapperType(metaType->typeEntry()))
return QString();
@@ -630,7 +664,8 @@ QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType *metaType,
+ QLatin1String(", reinterpret_cast<SbkObject *>(") + argName + QLatin1String(")))");
}
-QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntry* type, QString argName)
+QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntry* type,
+ const QString &argName)
{
if (!ShibokenGenerator::isWrapperType(type))
return QString();
@@ -706,7 +741,8 @@ QString ShibokenGenerator::getFormatUnitString(const AbstractMetaFunction* func,
|| arg->type()->referenceType() == LValueReference) {
result += QLatin1Char(objType);
} else if (arg->type()->isPrimitive()) {
- const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) arg->type()->typeEntry();
+ const PrimitiveTypeEntry *ptype =
+ static_cast<const PrimitiveTypeEntry *>(arg->type()->typeEntry());
if (ptype->basicReferencedTypeEntry())
ptype = ptype->basicReferencedTypeEntry();
if (m_formatUnits.contains(ptype->name()))
@@ -745,7 +781,7 @@ QString ShibokenGenerator::cpythonBaseName(const TypeEntry* type)
if (ShibokenGenerator::isWrapperType(type) || type->isNamespace()) { // && type->referenceType() == NoReference) {
baseName = QLatin1String("Sbk_") + type->name();
} else if (type->isPrimitive()) {
- const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) type;
+ const PrimitiveTypeEntry *ptype = static_cast<const PrimitiveTypeEntry *>(type);
while (ptype->basicReferencedTypeEntry())
ptype = ptype->basicReferencedTypeEntry();
if (ptype->targetLangApiName() == ptype->name())
@@ -753,11 +789,11 @@ QString ShibokenGenerator::cpythonBaseName(const TypeEntry* type)
else
baseName = ptype->targetLangApiName();
} else if (type->isEnum()) {
- baseName = cpythonEnumName((const EnumTypeEntry*) type);
+ baseName = cpythonEnumName(static_cast<const EnumTypeEntry *>(type));
} else if (type->isFlags()) {
- baseName = cpythonFlagsName((const FlagsTypeEntry*) type);
+ baseName = cpythonFlagsName(static_cast<const FlagsTypeEntry *>(type));
} else if (type->isContainer()) {
- const ContainerTypeEntry* ctype = (const ContainerTypeEntry*) type;
+ const ContainerTypeEntry *ctype = static_cast<const ContainerTypeEntry *>(type);
switch (ctype->type()) {
case ContainerTypeEntry::ListContainer:
case ContainerTypeEntry::StringListContainer:
@@ -858,14 +894,6 @@ QString ShibokenGenerator::cpythonTypeNameExt(const AbstractMetaType* type)
+ getTypeIndexVariableName(type) + QLatin1Char(']');
}
-static QString msgUnknownOperator(const AbstractMetaFunction* func)
-{
- QString result = QLatin1String("Unknown operator: \"") + func->originalName() + QLatin1Char('"');
- if (const AbstractMetaClass *c = func->implementingClass())
- result += QLatin1String(" in class: ") + c->name();
- return result;
-}
-
static inline QString unknownOperator() { return QStringLiteral("__UNKNOWN_OPERATOR__"); }
QString ShibokenGenerator::fixedCppTypeName(const CustomConversion::TargetToNativeConversion* toNative)
@@ -925,7 +953,7 @@ QString ShibokenGenerator::pythonPrimitiveTypeName(const PrimitiveTypeEntry* typ
return pythonPrimitiveTypeName(type->name());
}
-QString ShibokenGenerator::pythonOperatorFunctionName(QString cppOpFuncName)
+QString ShibokenGenerator::pythonOperatorFunctionName(const QString &cppOpFuncName)
{
QString value = m_pythonOperators.value(cppOpFuncName);
if (value.isEmpty())
@@ -953,7 +981,7 @@ QString ShibokenGenerator::pythonOperatorFunctionName(const AbstractMetaFunction
return op;
}
-QString ShibokenGenerator::pythonRichCompareOperatorId(QString cppOpFuncName)
+QString ShibokenGenerator::pythonRichCompareOperatorId(const QString &cppOpFuncName)
{
return QLatin1String("Py_") + m_pythonOperators.value(cppOpFuncName).toUpper();
}
@@ -963,7 +991,7 @@ QString ShibokenGenerator::pythonRichCompareOperatorId(const AbstractMetaFunctio
return pythonRichCompareOperatorId(func->originalName());
}
-bool ShibokenGenerator::isNumber(QString cpythonApiName)
+bool ShibokenGenerator::isNumber(const QString &cpythonApiName)
{
return cpythonApiName == QLatin1String("PyInt")
|| cpythonApiName == QLatin1String("PyFloat")
@@ -975,7 +1003,7 @@ bool ShibokenGenerator::isNumber(const TypeEntry* type)
{
if (!type->isPrimitive())
return false;
- return isNumber(pythonPrimitiveTypeName((const PrimitiveTypeEntry*) type));
+ return isNumber(pythonPrimitiveTypeName(static_cast<const PrimitiveTypeEntry *>(type)));
}
bool ShibokenGenerator::isNumber(const AbstractMetaType* type)
@@ -987,7 +1015,8 @@ bool ShibokenGenerator::isPyInt(const TypeEntry* type)
{
if (!type->isPrimitive())
return false;
- return pythonPrimitiveTypeName((const PrimitiveTypeEntry*) type) == QLatin1String("PyInt");
+ return pythonPrimitiveTypeName(static_cast<const PrimitiveTypeEntry *>(type))
+ == QLatin1String("PyInt");
}
bool ShibokenGenerator::isPyInt(const AbstractMetaType* type)
@@ -998,7 +1027,7 @@ bool ShibokenGenerator::isPyInt(const AbstractMetaType* type)
bool ShibokenGenerator::isWrapperType(const TypeEntry* type)
{
if (type->isComplex())
- return ShibokenGenerator::isWrapperType((const ComplexTypeEntry*)type);
+ return ShibokenGenerator::isWrapperType(static_cast<const ComplexTypeEntry *>(type));
return type->isObject() || type->isValue() || type->isSmartPointer();
}
bool ShibokenGenerator::isWrapperType(const ComplexTypeEntry* type)
@@ -1052,7 +1081,7 @@ bool ShibokenGenerator::isUserPrimitive(const TypeEntry* type)
{
if (!type->isPrimitive())
return false;
- const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type;
+ const PrimitiveTypeEntry *trueType = static_cast<const PrimitiveTypeEntry *>(type);
if (trueType->basicReferencedTypeEntry())
trueType = trueType->basicReferencedTypeEntry();
return trueType->isPrimitive() && !trueType->isCppPrimitive()
@@ -1072,7 +1101,7 @@ bool ShibokenGenerator::isCppPrimitive(const TypeEntry* type)
return true;
if (!type->isPrimitive())
return false;
- const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type;
+ const PrimitiveTypeEntry *trueType = static_cast<const PrimitiveTypeEntry *>(type);
if (trueType->basicReferencedTypeEntry())
trueType = trueType->basicReferencedTypeEntry();
return trueType->qualifiedCppName() == QLatin1String("std::string");
@@ -1125,9 +1154,11 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType
if (isVoidPointer(metaType))
return QLatin1String("PyObject_Check");
return cpythonCheckFunction(metaType->typeEntry(), genericNumberType);
- } else if (metaType->typeEntry()->isContainer()) {
+ }
+ if (metaType->typeEntry()->isContainer()) {
QString typeCheck = QLatin1String("Shiboken::Conversions::");
- ContainerTypeEntry::Type type = ((const ContainerTypeEntry*)metaType->typeEntry())->type();
+ ContainerTypeEntry::Type type =
+ static_cast<const ContainerTypeEntry *>(metaType->typeEntry())->type();
if (type == ContainerTypeEntry::ListContainer
|| type == ContainerTypeEntry::StringListContainer
|| type == ContainerTypeEntry::LinkedListContainer
@@ -1154,8 +1185,8 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType
const AbstractMetaType* firstType = metaType->instantiations().constFirst();
const AbstractMetaType* secondType = metaType->instantiations().constLast();
if (isPointerToWrapperType(firstType) && isPointerToWrapperType(secondType)) {
- typeCheck += QString::fromLatin1("check%1Types(%2, %3, ").arg(pyType)
- .arg(cpythonTypeNameExt(firstType), cpythonTypeNameExt(secondType));
+ typeCheck += QString::fromLatin1("check%1Types(%2, %3, ")
+ .arg(pyType, cpythonTypeNameExt(firstType), cpythonTypeNameExt(secondType));
} else {
typeCheck += QString::fromLatin1("convertible%1Types(%2, %3, %4, %5, ")
.arg(pyType, converterObject(firstType),
@@ -1182,8 +1213,10 @@ QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry* type, bool gene
if (type->isEnum() || type->isFlags() || isWrapperType(type))
return QString::fromLatin1("SbkObject_TypeCheck(%1, ").arg(cpythonTypeNameExt(type));
- else if (isCppPrimitive(type))
- return pythonPrimitiveTypeName((const PrimitiveTypeEntry*)type) + QLatin1String("_Check");
+ if (isCppPrimitive(type)) {
+ return pythonPrimitiveTypeName(static_cast<const PrimitiveTypeEntry *>(type))
+ + QLatin1String("_Check");
+ }
QString typeCheck;
if (type->targetLangApiName() == type->name())
typeCheck = cpythonIsConvertibleFunction(type);
@@ -1392,7 +1425,7 @@ void ShibokenGenerator::writeFunctionArguments(QTextStream &s,
if (options & Generator::WriteSelf) {
s << func->implementingClass()->name() << '&';
if (!(options & SkipName))
- s << " " PYTHON_SELF_VAR;
+ s << " self";
}
int argUsed = 0;
@@ -1412,13 +1445,12 @@ QString ShibokenGenerator::functionReturnType(const AbstractMetaFunction* func,
QString modifiedReturnType = QString(func->typeReplaced(0));
if (!modifiedReturnType.isNull() && !(options & OriginalTypeDescription))
return modifiedReturnType;
- else
- return translateType(func->type(), func->implementingClass(), options);
+ return translateType(func->type(), func->implementingClass(), options);
}
QString ShibokenGenerator::functionSignature(const AbstractMetaFunction *func,
- QString prepend,
- QString append,
+ const QString &prepend,
+ const QString &append,
Options options,
int /* argCount */) const
{
@@ -1619,8 +1651,9 @@ ShibokenGenerator::ArgumentVarReplacementList ShibokenGenerator::getArgumentRepl
QString argValue;
if (language == TypeSystem::TargetLangCode) {
bool hasConversionRule = !func->conversionRule(convLang, i+1).isEmpty();
- bool argRemoved = func->argumentRemoved(i+1);
- removed = removed + (int) argRemoved;
+ const bool argRemoved = func->argumentRemoved(i+1);
+ if (argRemoved)
+ ++removed;
if (argRemoved && hasConversionRule)
argValue = arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX);
else if (argRemoved || (lastArg && arg->argumentIndex() > lastArg->argumentIndex()))
@@ -1636,8 +1669,7 @@ ShibokenGenerator::ArgumentVarReplacementList ShibokenGenerator::getArgumentRepl
}
if (type->typeEntry()->isCustom()) {
argValue = usePyArgs
- ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(argPos)
- : QLatin1String(PYTHON_ARG);
+ ? pythonArgsAt(argPos) : QLatin1String(PYTHON_ARG);
} else {
argValue = hasConversionRule
? arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX)
@@ -1673,17 +1705,6 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s,
s << INDENT << "// End of code injection" << endl;
}
-static QString msgWrongIndex(const char *varName, const QString &capture, const AbstractMetaFunction *func)
-{
- QString result;
- QTextStream str(&result);
- str << "Wrong index for " << varName << " variable (" << capture << ") on ";
- if (const AbstractMetaClass *c = func->implementingClass())
- str << c->name() << "::";
- str << func->signature();
- return result;
-}
-
void ShibokenGenerator::writeCodeSnips(QTextStream& s,
const CodeSnipList& codeSnips,
TypeSystem::CodeSnipPosition position,
@@ -1712,7 +1733,7 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s,
Q_ASSERT(pyArgsRegex.isValid());
if (language == TypeSystem::TargetLangCode) {
if (usePyArgs) {
- code.replace(pyArgsRegex, QLatin1String(PYTHON_ARGS"[\\1-1]"));
+ code.replace(pyArgsRegex, QLatin1String(PYTHON_ARGS) + QLatin1String("[\\1-1]"));
} else {
static const QRegularExpression pyArgsRegexCheck(QStringLiteral("%PYARG_([2-9]+)"));
Q_ASSERT(pyArgsRegexCheck.isValid());
@@ -1729,8 +1750,10 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s,
// Python argument on the binding virtual method.
static const QRegularExpression pyArgsAttributionRegex(QStringLiteral("%PYARG_(\\d+)\\s*=[^=]\\s*([^;]+)"));
Q_ASSERT(pyArgsAttributionRegex.isValid());
- code.replace(pyArgsAttributionRegex, QLatin1String("PyTuple_SET_ITEM(" PYTHON_ARGS ", \\1-1, \\2)"));
- code.replace(pyArgsRegex, QLatin1String("PyTuple_GET_ITEM(" PYTHON_ARGS ", \\1-1)"));
+ code.replace(pyArgsAttributionRegex, QLatin1String("PyTuple_SET_ITEM(")
+ + QLatin1String(PYTHON_ARGS) + QLatin1String(", \\1-1, \\2)"));
+ code.replace(pyArgsRegex, QLatin1String("PyTuple_GET_ITEM(")
+ + QLatin1String(PYTHON_ARGS) + QLatin1String(", \\1-1)"));
}
// Replace %ARG#_TYPE variables.
@@ -1763,7 +1786,8 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s,
}
// Replace template variable for self Python object.
- QString pySelf = (language == TypeSystem::NativeCode) ? QLatin1String("pySelf") : QLatin1String(PYTHON_SELF_VAR);
+ QString pySelf = language == TypeSystem::NativeCode
+ ? QLatin1String("pySelf") : QLatin1String("self");
code.replace(QLatin1String("%PYSELF"), pySelf);
// Replace template variable for a pointer to C++ of this object.
@@ -1960,16 +1984,6 @@ static QString getConverterTypeSystemVariableArgument(const QString& code, int p
}
typedef QPair<QString, QString> StringPair;
-static QString msgCannotFindType(const QString &type, const QString &variable,
- const QString &why)
-{
- QString result;
- QTextStream(&result) << "Could not find type '"
- << type << "' for use in '" << variable << "' conversion: " << why
- << "\nMake sure to use the full C++ name, e.g. 'Namespace::Class'.";
- return result;
-}
-
void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable, QString& code)
{
QVector<StringPair> replacements;
@@ -1978,7 +1992,7 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
const QRegularExpressionMatch match = rit.next();
const QStringList list = match.capturedTexts();
QString conversionString = list.constFirst();
- QString conversionTypeName = list.constLast();
+ const QString &conversionTypeName = list.constLast();
QString message;
const AbstractMetaType *conversionType = buildAbstractMetaTypeFromString(conversionTypeName, &message);
if (!conversionType) {
@@ -2002,8 +2016,8 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
QString varName = list.at(1).trimmed();
if (!varType.isEmpty()) {
if (varType != conversionType->cppSignature()) {
- qFatal(qPrintable(QString::fromLatin1("Types of receiver variable ('%1') and %CONVERTTOCPP type system variable ('%2') differ.")
- .arg(varType, conversionType->cppSignature())), NULL);
+ qFatal("Types of receiver variable ('%s') and %%CONVERTTOCPP type system variable ('%s') differ.",
+ qPrintable(varType), qPrintable(conversionType->cppSignature()));
}
c << getFullTypeName(conversionType) << ' ' << varName;
writeMinimalConstructorExpression(c, conversionType);
@@ -2032,18 +2046,21 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
c << '(';
break;
}
+ Q_FALLTHROUGH();
case TypeSystemIsConvertibleFunction:
if (conversion.isEmpty())
conversion = cpythonIsConvertibleFunction(conversionType);
+ Q_FALLTHROUGH();
case TypeSystemToPythonFunction:
if (conversion.isEmpty())
conversion = cpythonToPythonConversionFunction(conversionType);
+ Q_FALLTHROUGH();
default: {
QString arg = getConverterTypeSystemVariableArgument(code, match.capturedEnd());
conversionString += arg;
if (converterVariable == TypeSystemToPythonFunction && !isVariable(arg)) {
- qFatal(qPrintable(QString::fromLatin1("Only variables are acceptable as argument to %%CONVERTTOPYTHON type system variable on code snippet: '%1'")
- .arg(code)), NULL);
+ qFatal("Only variables are acceptable as argument to %%CONVERTTOPYTHON type system variable on code snippet: '%s'",
+ qPrintable(code));
}
if (conversion.contains(QLatin1String("%in"))) {
conversion.prepend(QLatin1Char('('));
@@ -2172,9 +2189,7 @@ bool ShibokenGenerator::classNeedsSetattroFunction(const AbstractMetaClass *meta
{
if (!metaClass)
return false;
- if (metaClass->typeEntry()->isSmartPointer())
- return true;
- return false;
+ return metaClass->typeEntry()->isSmartPointer();
}
AbstractMetaFunctionList ShibokenGenerator::getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClass* metaClass)
@@ -2244,9 +2259,7 @@ AbstractMetaClassList ShibokenGenerator::getAllAncestors(const AbstractMetaClass
QString ShibokenGenerator::getModuleHeaderFileName(const QString& moduleName) const
{
- QString result = moduleName.isEmpty() ? packageName() : moduleName;
- result.replace(QLatin1Char('.'), QLatin1Char('_'));
- return result.toLower() + QLatin1String("_python.h");
+ return moduleCppPrefix(moduleName).toLower() + QLatin1String("_python.h");
}
bool ShibokenGenerator::isCopyable(const AbstractMetaClass *metaClass)
@@ -2254,12 +2267,10 @@ bool ShibokenGenerator::isCopyable(const AbstractMetaClass *metaClass)
{
if (metaClass->isNamespace() || isObjectType(metaClass))
return false;
- else if (metaClass->typeEntry()->copyable() == ComplexTypeEntry::Unknown)
+ if (metaClass->typeEntry()->copyable() == ComplexTypeEntry::Unknown)
return metaClass->hasCloneOperator();
- else
- return (metaClass->typeEntry()->copyable() == ComplexTypeEntry::CopyableSet);
- return false;
+ return metaClass->typeEntry()->copyable() == ComplexTypeEntry::CopyableSet;
}
AbstractMetaType *ShibokenGenerator::buildAbstractMetaTypeFromString(QString typeSignature,
@@ -2269,110 +2280,18 @@ AbstractMetaType *ShibokenGenerator::buildAbstractMetaTypeFromString(QString typ
if (typeSignature.startsWith(QLatin1String("::")))
typeSignature.remove(0, 2);
- if (m_metaTypeFromStringCache.contains(typeSignature))
- return m_metaTypeFromStringCache.value(typeSignature);
-
- QString typeString = typeSignature;
- bool isConst = typeString.startsWith(QLatin1String("const "));
- if (isConst)
- typeString.remove(0, sizeof("const ") / sizeof(char) - 1);
-
- ReferenceType refType = NoReference;
- if (typeString.endsWith(QLatin1String("&&"))) {
- refType = RValueReference;
- typeString.chop(2);
- typeString = typeString.trimmed();
- } else if (typeString.endsWith(QLatin1Char('&'))) {
- refType = LValueReference;
- typeString.chop(1);
- typeString = typeString.trimmed();
- }
-
- int indirections = 0;
- while (typeString.endsWith(QLatin1Char('*'))) {
- ++indirections;
- typeString.chop(1);
- typeString = typeString.trimmed();
- }
-
- if (typeString.startsWith(QLatin1String("::")))
- typeString.remove(0, 2);
-
- QString adjustedTypeName = typeString;
- AbstractMetaTypeList instantiations;
- int lpos = typeString.indexOf(QLatin1Char('<'));
- if (lpos > -1) {
- QStringList instantiatedTypes;
- int rpos = typeString.lastIndexOf(QLatin1Char('>'));
- if ((lpos != -1) && (rpos != -1)) {
- QString type = typeString.mid(lpos + 1, rpos - lpos - 1);
- int depth = 0;
- int start = 0;
- for (int i = 0; i < type.count(); ++i) {
- if (type.at(i) == QLatin1Char('<')) {
- ++depth;
- } else if (type.at(i) == QLatin1Char('>')) {
- --depth;
- } else if (type.at(i) == QLatin1Char(',') && depth == 0) {
- instantiatedTypes << type.mid(start, i - start).trimmed();
- start = i + 1;
- }
- }
- instantiatedTypes << type.mid(start).trimmed();
- adjustedTypeName.truncate(lpos);
- }
- for (const QString &instantiatedType : qAsConst(instantiatedTypes)) {
- AbstractMetaType *tmplArgType = buildAbstractMetaTypeFromString(instantiatedType);
- if (!tmplArgType) {
- if (errorMessage) {
- QTextStream(errorMessage) << "Cannot find template type \""
- << instantiatedType << "\" for \"" << typeSignature << "\".";
- }
- return nullptr;
- }
- instantiations.append(tmplArgType);
- }
- }
-
- TypeEntry *typeEntry = nullptr;
- AbstractMetaType::TypeUsagePattern pattern = AbstractMetaType::InvalidPattern;
-
- if (instantiations.size() == 1
- && instantiations.at(0)->typeUsagePattern() == AbstractMetaType::EnumPattern
- && adjustedTypeName == QLatin1String("QFlags")) {
- pattern = AbstractMetaType::FlagsPattern;
- typeEntry = TypeDatabase::instance()->findType(typeSignature);
- } else {
- typeEntry = TypeDatabase::instance()->findType(adjustedTypeName);
- }
-
- if (!typeEntry) {
- if (errorMessage) {
- QTextStream(errorMessage) << "Cannot find type \"" << adjustedTypeName
- << "\" for \"" << typeSignature << "\".";
+ auto it = m_metaTypeFromStringCache.find(typeSignature);
+ if (it == m_metaTypeFromStringCache.end()) {
+ AbstractMetaType *metaType =
+ AbstractMetaBuilder::translateType(typeSignature, nullptr, true, errorMessage);
+ if (Q_UNLIKELY(!metaType)) {
+ if (errorMessage)
+ errorMessage->prepend(msgCannotBuildMetaType(typeSignature));
+ return nullptr;
}
- return nullptr;
+ it = m_metaTypeFromStringCache.insert(typeSignature, metaType);
}
-
- AbstractMetaType *metaType = new AbstractMetaType();
- metaType->setTypeEntry(typeEntry);
- metaType->setIndirections(indirections);
- metaType->setReferenceType(refType);
- metaType->setConstant(isConst);
- metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
- switch (pattern) {
- case AbstractMetaType::FlagsPattern:
- metaType->setTypeUsagePattern(pattern);
- break;
- default:
- metaType->setInstantiations(instantiations);
- metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
- metaType->decideUsagePattern();
- break;
- }
-
- m_metaTypeFromStringCache.insert(typeSignature, metaType);
- return metaType;
+ return it.value();
}
AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(const TypeEntry* typeEntry)
@@ -2384,7 +2303,7 @@ AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(const Ty
return m_metaTypeFromStringCache.value(typeName);
AbstractMetaType* metaType = new AbstractMetaType;
metaType->setTypeEntry(typeEntry);
- metaType->setIndirections(0);
+ metaType->clearIndirections();
metaType->setReferenceType(NoReference);
metaType->setConstant(false);
metaType->decideUsagePattern();
@@ -2449,7 +2368,7 @@ AbstractMetaFunctionList ShibokenGenerator::getInheritedOverloads(const Abstract
{
AbstractMetaFunctionList results;
AbstractMetaClass* basis;
- if (func->ownerClass() && (basis = func->ownerClass()->baseClass(), basis)) {
+ if (func->ownerClass() && (basis = func->ownerClass()->baseClass())) {
for (; basis; basis = basis->baseClass()) {
const AbstractMetaFunction* inFunc = basis->findFunction(func->name());
if (inFunc && !seen->contains(inFunc->minimalSignature())) {
@@ -2509,6 +2428,23 @@ Generator::OptionDescriptions ShibokenGenerator::options() const
"the value of boolean casts"));
}
+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);
+ return false;
+}
+
static void getCode(QStringList& code, const CodeSnipList& codeSnips)
{
for (const CodeSnip &snip : qAsConst(codeSnips))
@@ -2534,15 +2470,8 @@ static void getCode(QStringList& code, const TypeEntry* type)
code.append(toNative->conversion());
}
-bool ShibokenGenerator::doSetup(const QMap<QString, QString>& args)
+bool ShibokenGenerator::doSetup()
{
- m_useCtorHeuristic = args.contains(QLatin1String(PARENT_CTOR_HEURISTIC));
- m_usePySideExtensions = args.contains(QLatin1String(ENABLE_PYSIDE_EXTENSIONS));
- m_userReturnValueHeuristic = args.contains(QLatin1String(RETURN_VALUE_HEURISTIC));
- m_verboseErrorMessagesDisabled = args.contains(QLatin1String(DISABLE_VERBOSE_ERROR_MESSAGES));
- m_useIsNullAsNbNonZero = args.contains(QLatin1String(USE_ISNULL_AS_NB_NONZERO));
- m_avoidProtectedHack = args.contains(QLatin1String(AVOID_PROTECTED_HACK));
-
TypeDatabase* td = TypeDatabase::instance();
QStringList snips;
const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes();
@@ -2554,7 +2483,11 @@ bool ShibokenGenerator::doSetup(const QMap<QString, QString>& args)
const AbstractMetaClassList &classList = classes();
for (const AbstractMetaClass *metaClass : classList)
getCode(snips, metaClass->typeEntry());
- getCode(snips, td->findType(packageName()));
+
+ const TypeSystemTypeEntry *moduleEntry = td->findTypeSystemType(packageName());
+ Q_ASSERT(moduleEntry);
+ getCode(snips, moduleEntry);
+
const FunctionGroupMap &functionGroups = getFunctionGroups();
for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
for (AbstractMetaFunction *func : it.value())
@@ -2611,15 +2544,25 @@ bool ShibokenGenerator::avoidProtectedHack() const
return m_avoidProtectedHack;
}
-QString ShibokenGenerator::cppApiVariableName(const QString& moduleName) const
-{
- QString result = moduleName.isEmpty() ? ShibokenGenerator::packageName() : moduleName;
+QString ShibokenGenerator::moduleCppPrefix(const QString& moduleName) const
+ {
+ QString result = moduleName.isEmpty() ? packageName() : moduleName;
result.replace(QLatin1Char('.'), QLatin1Char('_'));
- result.prepend(QLatin1String("Sbk"));
- result.append(QLatin1String("Types"));
return result;
}
+QString ShibokenGenerator::cppApiVariableName(const QString& moduleName) const
+{
+ return QLatin1String("Sbk") + moduleCppPrefix(moduleName)
+ + QLatin1String("Types");
+}
+
+QString ShibokenGenerator::pythonModuleObjectName(const QString& moduleName) const
+{
+ return QLatin1String("Sbk") + moduleCppPrefix(moduleName)
+ + QLatin1String("ModuleObject");
+}
+
QString ShibokenGenerator::convertersVariableName(const QString& moduleName) const
{
QString result = cppApiVariableName(moduleName);
@@ -2639,35 +2582,50 @@ static QString processInstantiationsVariableName(const AbstractMetaType* type)
}
return res;
}
+
+static void appendIndexSuffix(QString *s)
+{
+ if (!s->endsWith(QLatin1Char('_')))
+ s->append(QLatin1Char('_'));
+ s->append(QStringLiteral("IDX"));
+}
+
QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass* metaClass, bool alternativeTemplateName)
{
if (alternativeTemplateName) {
const AbstractMetaClass* templateBaseClass = metaClass->templateBaseClass();
if (!templateBaseClass)
return QString();
- QString base = _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName()).toUpper();
- QString instantiations;
+ QString result = QLatin1String("SBK_")
+ + _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName()).toUpper();
const AbstractMetaTypeList &templateBaseClassInstantiations = metaClass->templateBaseClassInstantiations();
for (const AbstractMetaType *instantiation : templateBaseClassInstantiations)
- instantiations += processInstantiationsVariableName(instantiation);
- return QString::fromLatin1("SBK_%1%2_IDX").arg(base, instantiations);
+ result += processInstantiationsVariableName(instantiation);
+ appendIndexSuffix(&result);
+ return result;
}
return getTypeIndexVariableName(metaClass->typeEntry());
}
QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry* type)
{
if (type->isCppPrimitive()) {
- const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type;
+ const PrimitiveTypeEntry *trueType = static_cast<const PrimitiveTypeEntry*>(type);
if (trueType->basicReferencedTypeEntry())
type = trueType->basicReferencedTypeEntry();
}
- return QString::fromLatin1("SBK_%1_IDX").arg(_fixedCppTypeName(type->qualifiedCppName()).toUpper());
+ QString result = QLatin1String("SBK_")
+ + _fixedCppTypeName(type->qualifiedCppName()).toUpper();
+ appendIndexSuffix(&result);
+ return result;
}
QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaType* type)
{
- return QString::fromLatin1("SBK%1%2_IDX")
- .arg(type->typeEntry()->isContainer() ? QLatin1Char('_') + moduleName().toUpper() : QString(),
- processInstantiationsVariableName(type));
+ QString result = QLatin1String("SBK");
+ if (type->typeEntry()->isContainer())
+ result += QLatin1Char('_') + moduleName().toUpper();
+ result += processInstantiationsVariableName(type);
+ appendIndexSuffix(&result);
+ return result;
}
bool ShibokenGenerator::verboseErrorMessagesDisabled() const
@@ -2707,30 +2665,37 @@ QString ShibokenGenerator::getDefaultValue(const AbstractMetaFunction* func, co
void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream& s, const AbstractMetaType* type, const QString& defaultCtor)
{
- if (defaultCtor.isEmpty() && isCppPrimitive(type))
+ if (!defaultCtor.isEmpty()) {
+ s << " = " << defaultCtor;
+ return;
+ }
+ if (isCppPrimitive(type))
return;
- QString ctor = defaultCtor.isEmpty() ? minimalConstructor(type) : defaultCtor;
- if (ctor.isEmpty()) {
+ const auto ctor = minimalConstructor(type);
+ if (ctor.isValid()) {
+ s << ctor.initialization();
+ } else {
const QString message = msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__), type->cppSignature());
qCWarning(lcShiboken()).noquote() << message;
s << ";\n#error " << message << '\n';
- } else {
- s << " = " << ctor;
}
}
void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream& s, const TypeEntry* type, const QString& defaultCtor)
{
- if (defaultCtor.isEmpty() && isCppPrimitive(type))
+ if (!defaultCtor.isEmpty()) {
+ s << " = " << defaultCtor;
+ return;
+ }
+ if (isCppPrimitive(type))
return;
- QString ctor = defaultCtor.isEmpty() ? minimalConstructor(type) : defaultCtor;
-
- if (ctor.isEmpty()) {
+ const auto ctor = minimalConstructor(type);
+ if (ctor.isValid()) {
+ s << ctor.initialization();
+ } else {
const QString message = msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__), type->qualifiedCppName());
qCWarning(lcShiboken()).noquote() << message;
s << ";\n#error " << message << endl;
- } else {
- s << " = " << ctor;
}
}
@@ -2738,7 +2703,7 @@ bool ShibokenGenerator::isCppIntegralPrimitive(const TypeEntry* type)
{
if (!type->isCppPrimitive())
return false;
- const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type;
+ const PrimitiveTypeEntry *trueType = static_cast<const PrimitiveTypeEntry *>(type);
if (trueType->basicReferencedTypeEntry())
trueType = trueType->basicReferencedTypeEntry();
QString typeName = trueType->qualifiedCppName();
@@ -2751,8 +2716,8 @@ bool ShibokenGenerator::isCppIntegralPrimitive(const AbstractMetaType* type)
return isCppIntegralPrimitive(type->typeEntry());
}
-QString ShibokenGenerator::msgCouldNotFindMinimalConstructor(const QString &where, const QString &type)
+QString ShibokenGenerator::pythonArgsAt(int i)
{
- return where + QLatin1String(": Could not find a minimal constructor for type '") + type
- + QLatin1String("'. This will result in a compilation error.");
+ return QLatin1String(PYTHON_ARGS) + QLatin1Char('[')
+ + QString::number(i) + QLatin1Char(']');
}
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.h b/sources/shiboken2/generator/shiboken2/shibokengenerator.h
index cb1bdd11f..60e31a99b 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.h
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h
@@ -29,28 +29,20 @@
#ifndef SHIBOKENGENERATOR_H
#define SHIBOKENGENERATOR_H
-#define CONV_RULE_OUT_VAR_SUFFIX "_out"
-#define CPP_ARG "cppArg"
-#define CPP_ARG0 CPP_ARG"0"
-#define CPP_ARG_REMOVED "removed_" CPP_ARG
-#define CPP_RETURN_VAR "cppResult"
-#define CPP_SELF_VAR "cppSelf"
-#define PYTHON_ARG "pyArg"
-#define PYTHON_ARGS PYTHON_ARG "s"
-#define PYTHON_OVERRIDE_VAR "pyOverride"
-#define PYTHON_RETURN_VAR "pyResult"
-#define PYTHON_SELF_VAR "self"
-#define THREAD_STATE_SAVER_VAR "threadStateSaver"
-#define BEGIN_ALLOW_THREADS "PyThreadState* _save = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS"
-#define END_ALLOW_THREADS "PyEval_RestoreThread(_save); // Py_END_ALLOW_THREADS"
-#define PYTHON_TO_CPP_VAR "pythonToCpp"
-#define SMART_POINTER_GETTER "kSmartPointerGetter"
-
-#define CHECKTYPE_REGEX "%CHECKTYPE\\[([^\\[]*)\\]\\("
-#define ISCONVERTIBLE_REGEX "%ISCONVERTIBLE\\[([^\\[]*)\\]\\("
-#define CONVERTTOPYTHON_REGEX "%CONVERTTOPYTHON\\[([^\\[]*)\\]\\("
-#define CONVERTTOCPP_REGEX "(\\*?%?[a-zA-Z_][\\w\\.]*(?:\\[[^\\[^<^>]+\\])*)"\
- "(?:\\s+)=(?:\\s+)%CONVERTTOCPP\\[([^\\[]*)\\]\\("
+extern const char *CPP_ARG;
+extern const char *CPP_ARG_REMOVED;
+extern const char *CPP_RETURN_VAR;
+extern const char *CPP_SELF_VAR;
+extern const char *PYTHON_ARG;
+extern const char *PYTHON_ARGS;
+extern const char *PYTHON_OVERRIDE_VAR;
+extern const char *PYTHON_RETURN_VAR;
+extern const char *PYTHON_TO_CPP_VAR;
+extern const char *SMART_POINTER_GETTER;
+
+extern const char *CONV_RULE_OUT_VAR_SUFFIX;
+extern const char *BEGIN_ALLOW_THREADS;
+extern const char *END_ALLOW_THREADS;
#include <generator.h>
@@ -71,61 +63,20 @@ class ShibokenGenerator : public Generator
{
public:
ShibokenGenerator();
- virtual ~ShibokenGenerator();
+ ~ShibokenGenerator() override;
- QString translateTypeForWrapperMethod(const AbstractMetaType* cType,
- const AbstractMetaClass* context, Options opt = NoOption) const;
+ const char *name() const override { return "Shiboken"; }
/**
- * Returns a map with all functions grouped, the function name is used as key.
- * Example of return value: { "foo" -> ["foo(int)", "foo(int, long)], "bar" -> "bar(double)"}
- * \param scope Where to search for functions, null means all global functions.
- */
- QMap<QString, AbstractMetaFunctionList> getFunctionGroups(const AbstractMetaClass* scope = 0);
-
- /**
- * Returns all different inherited overloads of func.
- * The function can be called multiple times without duplication.
- * \param func the metafunction to be searched in subclasses.
- * \param seen the function's minimal signatures already seen.
- */
- AbstractMetaFunctionList getInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *seen);
+ * Helper function to find for argument default value
+ */
+ static QString getDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg);
- /**
- * Returns all different inherited overloads of func, and includes func as well.
- * The function can be called multiple times without duplication.
- * \param func the metafunction to be searched in subclasses.
- * \param seen the function's minimal signatures already seen.
- */
- AbstractMetaFunctionList getFunctionAndInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *seen);
+ /// Returns a list of all ancestor classes for the given class.
+ AbstractMetaClassList getAllAncestors(const AbstractMetaClass* metaClass) const;
- /**
- * Returns all overloads for a function named \p functionName.
- * \param scope scope used to search for overloads.
- * \param functionName the function name.
- */
- AbstractMetaFunctionList getFunctionOverloads(const AbstractMetaClass* scope, const QString& functionName);
- /**
- * Write a function argument in the C++ in the text stream \p s.
- * This function just call \code s << argumentString(); \endcode
- * \param s text stream used to write the output.
- * \param func the current metafunction.
- * \param argument metaargument information to be parsed.
- * \param options some extra options.
- */
- void writeArgument(QTextStream &s,
- const AbstractMetaFunction* func,
- const AbstractMetaArgument* argument,
- Options options = NoOption) const;
- /**
- * Create a QString in the C++ format to an function argument.
- * \param func the current metafunction.
- * \param argument metaargument information to be parsed.
- * \param options some extra options.
- */
- QString argumentString(const AbstractMetaFunction* func,
- const AbstractMetaArgument* argument,
- Options options = NoOption) const;
+protected:
+ bool doSetup() override;
void writeArgumentNames(QTextStream &s,
const AbstractMetaFunction* func,
@@ -141,14 +92,21 @@ public:
void writeFunctionArguments(QTextStream &s,
const AbstractMetaFunction* func,
Options options = NoOption) const override;
- QString functionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const;
- /// Utility function for writeCodeSnips.
- typedef QPair<const AbstractMetaArgument*, QString> ArgumentVarReplacementPair;
- typedef QVector<ArgumentVarReplacementPair> ArgumentVarReplacementList;
- ArgumentVarReplacementList getArgumentReplacement(const AbstractMetaFunction* func,
- bool usePyArgs, TypeSystem::Language language,
- const AbstractMetaArgument* lastArg);
+ /**
+ * Returns a map with all functions grouped, the function name is used as key.
+ * Example of return value: { "foo" -> ["foo(int)", "foo(int, long)], "bar" -> "bar(double)"}
+ * \param scope Where to search for functions, null means all global functions.
+ */
+ QMap<QString, AbstractMetaFunctionList> getFunctionGroups(const AbstractMetaClass* scope = 0);
+
+ /**
+ * Returns all different inherited overloads of func, and includes func as well.
+ * The function can be called multiple times without duplication.
+ * \param func the metafunction to be searched in subclasses.
+ * \param seen the function's minimal signatures already seen.
+ */
+ AbstractMetaFunctionList getFunctionAndInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *seen);
/// Write user's custom code snippets at class or module level.
void writeCodeSnips(QTextStream& s,
@@ -164,33 +122,9 @@ public:
const AbstractMetaFunction* func,
const AbstractMetaArgument* lastArg = 0);
- /// Returns a string with the user's custom code snippets that comply with \p position and \p language.
- QString getCodeSnippets(const QVector<CodeSnip> & codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language);
-
/// Replaces variables for the user's custom code at global or class level.
void processCodeSnip(QString& code, const AbstractMetaClass* context = 0);
- /// Replaces the %CONVERTTOPYTHON type system variable.
- inline void replaceConvertToPythonTypeSystemVariable(QString& code)
- {
- replaceConverterTypeSystemVariable(TypeSystemToPythonFunction, code);
- }
- /// Replaces the %CONVERTTOCPP type system variable.
- inline void replaceConvertToCppTypeSystemVariable(QString& code)
- {
- replaceConverterTypeSystemVariable(TypeSystemToCppFunction, code);
- }
- /// Replaces the %ISCONVERTIBLE type system variable.
- inline void replaceIsConvertibleToCppTypeSystemVariable(QString& code)
- {
- replaceConverterTypeSystemVariable(TypeSystemIsConvertibleFunction, code);
- }
- /// Replaces the %CHECKTYPE type system variable.
- inline void replaceTypeCheckTypeSystemVariable(QString& code)
- {
- replaceConverterTypeSystemVariable(TypeSystemCheckFunction, code);
- }
-
/**
* Verifies if any of the function's code injections of the "native"
* type needs the type system variable "%PYSELF".
@@ -239,8 +173,8 @@ public:
* \param arg_count the number of function arguments
*/
QString functionSignature(const AbstractMetaFunction* func,
- QString prepend = QString(),
- QString append = QString(),
+ const QString &prepend = QString(),
+ const QString &append = QString(),
Options options = NoOption,
int arg_count = -1) const;
@@ -259,9 +193,6 @@ public:
/// Returns a list of parent classes for a given class.
AbstractMetaClassList getBaseClasses(const AbstractMetaClass* metaClass) const;
- /// Returns a list of all ancestor classes for the given class.
- AbstractMetaClassList getAllAncestors(const AbstractMetaClass* metaClass) const;
-
const AbstractMetaClass* getMultipleInheritingClass(const AbstractMetaClass* metaClass);
void writeToPythonConversion(QTextStream& s, const AbstractMetaType* type,
@@ -283,7 +214,8 @@ public:
QString wrapperName(const AbstractMetaClass* metaClass) const;
QString wrapperName(const AbstractMetaType *metaType) const;
- QString fullPythonFunctionName(const AbstractMetaFunction* func);
+ QString fullPythonClassName(const AbstractMetaClass *metaClass);
+ QString fullPythonFunctionName(const AbstractMetaFunction *func); //WS
static QString protectedEnumSurrogateName(const AbstractMetaEnum* metaEnum);
static QString protectedFieldGetterName(const AbstractMetaField* field);
@@ -292,16 +224,16 @@ public:
static QString pythonPrimitiveTypeName(const QString& cppTypeName);
static QString pythonPrimitiveTypeName(const PrimitiveTypeEntry* type);
- static QString pythonOperatorFunctionName(QString cppOpFuncName);
+ static QString pythonOperatorFunctionName(const QString &cppOpFuncName);
static QString pythonOperatorFunctionName(const AbstractMetaFunction* func);
- static QString pythonRichCompareOperatorId(QString cppOpFuncName);
+ static QString pythonRichCompareOperatorId(const QString &cppOpFuncName);
static QString pythonRichCompareOperatorId(const AbstractMetaFunction* func);
static QString fixedCppTypeName(const CustomConversion::TargetToNativeConversion* toNative);
static QString fixedCppTypeName(const AbstractMetaType* type);
static QString fixedCppTypeName(const TypeEntry* type, QString typeName = QString());
- static bool isNumber(QString cpythonApiName);
+ static bool isNumber(const QString &cpythonApiName);
static bool isNumber(const TypeEntry* type);
static bool isNumber(const AbstractMetaType* type);
static bool isPyInt(const TypeEntry* type);
@@ -389,9 +321,10 @@ public:
QString cpythonSetattroFunctionName(const AbstractMetaClass* metaClass);
QString cpythonGetterFunctionName(const AbstractMetaField* metaField);
QString cpythonSetterFunctionName(const AbstractMetaField* metaField);
- QString cpythonWrapperCPtr(const AbstractMetaClass* metaClass, QString argName = QLatin1String(PYTHON_SELF_VAR));
- QString cpythonWrapperCPtr(const AbstractMetaType *metaType, QString argName);
- QString cpythonWrapperCPtr(const TypeEntry* type, QString argName);
+ QString cpythonWrapperCPtr(const AbstractMetaClass* metaClass,
+ const QString &argName = QLatin1String("self"));
+ QString cpythonWrapperCPtr(const AbstractMetaType *metaType, const QString &argName);
+ QString cpythonWrapperCPtr(const TypeEntry* type, const QString &argName);
/// Guesses the scope to where belongs an argument's default value.
QString guessScopeForDefaultValue(const AbstractMetaFunction *func,
@@ -414,6 +347,7 @@ public:
QString getModuleHeaderFileName(const QString& moduleName = QString()) const;
OptionDescriptions options() const override;
+ bool handleOption(const QString &key, const QString &value) override;
/// Returns true if the user enabled the so called "parent constructor heuristic".
bool useCtorHeuristic() const;
@@ -426,6 +360,7 @@ public:
/// Returns true if the generated code should use the "#define protected public" hack.
bool avoidProtectedHack() const;
QString cppApiVariableName(const QString& moduleName = QString()) const;
+ QString pythonModuleObjectName(const QString& moduleName = QString()) const;
QString convertersVariableName(const QString& moduleName = QString()) const;
/**
* Returns the type index variable name for a given class. If \p alternativeTemplateName is true
@@ -457,26 +392,12 @@ public:
void writeMinimalConstructorExpression(QTextStream& s, const AbstractMetaType* type, const QString& defaultCtor = QString());
void writeMinimalConstructorExpression(QTextStream& s, const TypeEntry* type, const QString& defaultCtor = QString());
- /**
- * Helper function to find for argument default value
- */
- static QString getDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg);
-protected:
- bool doSetup(const QMap<QString, QString>& args);
void collectContainerTypesFromConverterMacros(const QString& code, bool toPythonMacro);
// verify whether the class is copyable
bool isCopyable(const AbstractMetaClass* metaClass);
- bool m_native_jump_table;
- static QHash<QString, QString> m_pythonPrimitiveTypeName;
- static QHash<QString, QString> m_pythonOperators;
- static QHash<QString, QString> m_formatUnits;
- static QHash<QString, QString> m_tpFuncs;
- static QStringList m_knownPythonTypes;
-
void clearTpFuncs();
- const char* name() const { return "Shiboken"; }
/// Initializes correspondences between primitive and Python types.
static void initPrimitiveTypesCorrespondences();
@@ -505,6 +426,74 @@ protected:
Indentor INDENT;
+ const QRegularExpression &convertToCppRegEx() const
+ { return m_typeSystemConvRegEx[TypeSystemToCppFunction]; }
+
+ static QString pythonArgsAt(int i);
+
+ static QHash<QString, QString> m_pythonPrimitiveTypeName;
+ static QHash<QString, QString> m_pythonOperators;
+ static QHash<QString, QString> m_formatUnits;
+ static QHash<QString, QString> m_tpFuncs;
+ static QStringList m_knownPythonTypes;
+
+private:
+ QString translateTypeForWrapperMethod(const AbstractMetaType* cType,
+ const AbstractMetaClass* context,
+ Options opt = NoOption) const;
+
+ /**
+ * Returns all different inherited overloads of func.
+ * The function can be called multiple times without duplication.
+ * \param func the metafunction to be searched in subclasses.
+ * \param seen the function's minimal signatures already seen.
+ */
+ AbstractMetaFunctionList getInheritedOverloads(const AbstractMetaFunction *func,
+ QSet<QString> *seen);
+
+ /**
+ * Returns all overloads for a function named \p functionName.
+ * \param scope scope used to search for overloads.
+ * \param functionName the function name.
+ */
+ AbstractMetaFunctionList getFunctionOverloads(const AbstractMetaClass* scope,
+ const QString& functionName);
+ /**
+ * Write a function argument in the C++ in the text stream \p s.
+ * This function just call \code s << argumentString(); \endcode
+ * \param s text stream used to write the output.
+ * \param func the current metafunction.
+ * \param argument metaargument information to be parsed.
+ * \param options some extra options.
+ */
+ void writeArgument(QTextStream &s,
+ const AbstractMetaFunction* func,
+ const AbstractMetaArgument* argument,
+ Options options = NoOption) const;
+ /**
+ * Create a QString in the C++ format to an function argument.
+ * \param func the current metafunction.
+ * \param argument metaargument information to be parsed.
+ * \param options some extra options.
+ */
+ QString argumentString(const AbstractMetaFunction* func,
+ const AbstractMetaArgument* argument,
+ Options options = NoOption) const;
+
+ QString functionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const;
+
+ /// Utility function for writeCodeSnips.
+ typedef QPair<const AbstractMetaArgument*, QString> ArgumentVarReplacementPair;
+ typedef QVector<ArgumentVarReplacementPair> ArgumentVarReplacementList;
+ ArgumentVarReplacementList getArgumentReplacement(const AbstractMetaFunction* func,
+ bool usePyArgs, TypeSystem::Language language,
+ const AbstractMetaArgument* lastArg);
+
+ /// Returns a string with the user's custom code snippets that comply with \p position and \p language.
+ QString getCodeSnippets(const QVector<CodeSnip> & codeSnips,
+ TypeSystem::CodeSnipPosition position,
+ TypeSystem::Language language);
+
enum TypeSystemConverterVariable {
TypeSystemCheckFunction = 0,
TypeSystemIsConvertibleFunction,
@@ -514,15 +503,36 @@ protected:
};
void replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable, QString& code);
- static QString msgCouldNotFindMinimalConstructor(const QString &where, const QString &type);
+ /// Replaces the %CONVERTTOPYTHON type system variable.
+ inline void replaceConvertToPythonTypeSystemVariable(QString& code)
+ {
+ replaceConverterTypeSystemVariable(TypeSystemToPythonFunction, code);
+ }
+ /// Replaces the %CONVERTTOCPP type system variable.
+ inline void replaceConvertToCppTypeSystemVariable(QString& code)
+ {
+ replaceConverterTypeSystemVariable(TypeSystemToCppFunction, code);
+ }
+ /// Replaces the %ISCONVERTIBLE type system variable.
+ inline void replaceIsConvertibleToCppTypeSystemVariable(QString& code)
+ {
+ replaceConverterTypeSystemVariable(TypeSystemIsConvertibleFunction, code);
+ }
+ /// Replaces the %CHECKTYPE type system variable.
+ inline void replaceTypeCheckTypeSystemVariable(QString& code)
+ {
+ replaceConverterTypeSystemVariable(TypeSystemCheckFunction, code);
+ }
-private:
- bool m_useCtorHeuristic;
- bool m_userReturnValueHeuristic;
- bool m_usePySideExtensions;
- bool m_verboseErrorMessagesDisabled;
- bool m_useIsNullAsNbNonZero;
- bool m_avoidProtectedHack;
+ /// Return a prefix with '_' suitable for names in C++
+ QString moduleCppPrefix(const QString& moduleName = QString()) const;
+
+ bool m_useCtorHeuristic = false;
+ bool m_userReturnValueHeuristic = false;
+ bool m_usePySideExtensions = false;
+ bool m_verboseErrorMessagesDisabled = false;
+ bool m_useIsNullAsNbNonZero = false;
+ bool m_avoidProtectedHack = false;
typedef QHash<QString, AbstractMetaType*> AbstractMetaTypeCache;
AbstractMetaTypeCache m_metaTypeFromStringCache;