aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/generator/generator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/generator/generator.cpp')
-rw-r--r--sources/shiboken2/generator/generator.cpp989
1 files changed, 0 insertions, 989 deletions
diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp
deleted file mode 100644
index 88ba1f04f..000000000
--- a/sources/shiboken2/generator/generator.cpp
+++ /dev/null
@@ -1,989 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt for Python.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "generator.h"
-#include "abstractmetalang.h"
-#include "parser/codemodel.h"
-#include "messages.h"
-#include "reporthandler.h"
-#include "fileout.h"
-#include "apiextractor.h"
-#include "typesystem.h"
-
-#include <QtCore/QDir>
-#include <QtCore/QFile>
-#include <QtCore/QFileInfo>
-#include <QtCore/QRegularExpression>
-#include <QDebug>
-#include <typedatabase.h>
-
-/**
- * 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("()");
-}
-
-QString GeneratorContext::smartPointerWrapperName() const
-{
- Q_ASSERT(m_type == SmartPointer);
- return m_preciseClassType->cppSignature();
-}
-
-struct Generator::GeneratorPrivate
-{
- const ApiExtractor *apiextractor = nullptr;
- QString outDir;
- // License comment
- QString licenseComment;
- QString moduleName;
- QStringList instantiatedContainersNames;
- QVector<const AbstractMetaType *> instantiatedContainers;
- QVector<const AbstractMetaType *> instantiatedSmartPointers;
-
-};
-
-Generator::Generator() : m_d(new GeneratorPrivate)
-{
-}
-
-Generator::~Generator()
-{
- delete m_d;
-}
-
-bool Generator::setup(const ApiExtractor &extractor)
-{
- m_d->apiextractor = &extractor;
- const auto moduleEntry = TypeDatabase::instance()->defaultTypeSystemType();
- if (!moduleEntry || !moduleEntry->generateCode()) {
- qCWarning(lcShiboken) << "Couldn't find the package name!!";
- return false;
- }
-
- collectInstantiatedContainersAndSmartPointers();
-
- return doSetup();
-}
-
-QString Generator::getSimplifiedContainerTypeName(const AbstractMetaType *type)
-{
- const QString signature = type->cppSignature();
- if (!type->typeEntry()->isContainer() && !type->typeEntry()->isSmartPointer())
- return signature;
- QString typeName = signature;
- if (type->isConstant())
- typeName.remove(0, sizeof("const ") / sizeof(char) - 1);
- switch (type->referenceType()) {
- case NoReference:
- break;
- case LValueReference:
- typeName.chop(1);
- break;
- case RValueReference:
- typeName.chop(2);
- break;
- }
- while (typeName.endsWith(QLatin1Char('*')) || typeName.endsWith(QLatin1Char(' ')))
- typeName.chop(1);
- return typeName;
-}
-
-// Strip a "const QSharedPtr<const Foo> &" or similar to "QSharedPtr<Foo>" (PYSIDE-1016/454)
-const AbstractMetaType *canonicalSmartPtrInstantiation(const AbstractMetaType *type)
-{
- AbstractMetaTypeList instantiations = type->instantiations();
- Q_ASSERT(instantiations.size() == 1);
- const bool needsFix = type->isConstant() || type->referenceType() != NoReference;
- const bool pointeeNeedsFix = instantiations.constFirst()->isConstant();
- if (!needsFix && !pointeeNeedsFix)
- return type;
- auto fixedType = type->copy();
- fixedType->setReferenceType(NoReference);
- fixedType->setConstant(false);
- if (pointeeNeedsFix) {
- auto fixedPointeeType = instantiations.constFirst()->copy();
- fixedPointeeType->setConstant(false);
- fixedType->setInstantiations(AbstractMetaTypeList(1, fixedPointeeType));
- }
- return fixedType;
-}
-
-static inline const TypeEntry *pointeeTypeEntry(const AbstractMetaType *smartPtrType)
-{
- return smartPtrType->instantiations().constFirst()->typeEntry();
-}
-
-void Generator::addInstantiatedContainersAndSmartPointers(const AbstractMetaType *type,
- const QString &context)
-{
- if (!type)
- return;
- const AbstractMetaTypeList &instantiations = type->instantiations();
- for (const AbstractMetaType *t : instantiations)
- addInstantiatedContainersAndSmartPointers(t, context);
- const auto typeEntry = type->typeEntry();
- const bool isContainer = typeEntry->isContainer();
- if (!isContainer
- && !(typeEntry->isSmartPointer() && typeEntry->generateCode())) {
- return;
- }
- if (type->hasTemplateChildren()) {
- QString piece = isContainer ? QStringLiteral("container") : QStringLiteral("smart pointer");
- QString warning =
- QString::fromLatin1("Skipping instantiation of %1 '%2' because it has template"
- " arguments.").arg(piece, type->originalTypeDescription());
- if (!context.isEmpty())
- warning.append(QStringLiteral(" Calling context: %1").arg(context));
-
- qCWarning(lcShiboken).noquote().nospace() << warning;
- return;
-
- }
- QString typeName = getSimplifiedContainerTypeName(type);
- if (isContainer) {
- if (!m_d->instantiatedContainersNames.contains(typeName)) {
- m_d->instantiatedContainersNames.append(typeName);
- m_d->instantiatedContainers.append(type);
- }
- } else {
- // Is smart pointer. Check if the (const?) pointee is already known
- auto pt = pointeeTypeEntry(type);
- const bool present =
- std::any_of(m_d->instantiatedSmartPointers.cbegin(), m_d->instantiatedSmartPointers.cend(),
- [pt] (const AbstractMetaType *t) {
- return pointeeTypeEntry(t) == pt;
- });
- if (!present)
- m_d->instantiatedSmartPointers.append(canonicalSmartPtrInstantiation(type));
- }
-
-}
-
-void Generator::collectInstantiatedContainersAndSmartPointers(const AbstractMetaFunction *func)
-{
- addInstantiatedContainersAndSmartPointers(func->type(), func->signature());
- const AbstractMetaArgumentList &arguments = func->arguments();
- for (const AbstractMetaArgument *arg : arguments)
- addInstantiatedContainersAndSmartPointers(arg->type(), func->signature());
-}
-
-void Generator::collectInstantiatedContainersAndSmartPointers(const AbstractMetaClass *metaClass)
-{
- if (!metaClass->typeEntry()->generateCode())
- return;
- const AbstractMetaFunctionList &funcs = metaClass->functions();
- for (const AbstractMetaFunction *func : funcs)
- collectInstantiatedContainersAndSmartPointers(func);
- const AbstractMetaFieldList &fields = metaClass->fields();
- for (const AbstractMetaField *field : fields)
- addInstantiatedContainersAndSmartPointers(field->type(), field->name());
- const AbstractMetaClassList &innerClasses = metaClass->innerClasses();
- for (AbstractMetaClass *innerClass : innerClasses)
- collectInstantiatedContainersAndSmartPointers(innerClass);
-}
-
-void Generator::collectInstantiatedContainersAndSmartPointers()
-{
- const AbstractMetaFunctionList &funcs = globalFunctions();
- for (const AbstractMetaFunction *func : funcs)
- collectInstantiatedContainersAndSmartPointers(func);
- const AbstractMetaClassList &classList = classes();
- for (const AbstractMetaClass *metaClass : classList)
- collectInstantiatedContainersAndSmartPointers(metaClass);
-}
-
-QVector<const AbstractMetaType *> Generator::instantiatedContainers() const
-{
- return m_d->instantiatedContainers;
-}
-
-QVector<const AbstractMetaType *> Generator::instantiatedSmartPointers() const
-{
- return m_d->instantiatedSmartPointers;
-}
-
-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();
-}
-
-AbstractMetaClassList Generator::classesTopologicalSorted(const Dependencies &additionalDependencies) const
-{
- return m_d->apiextractor->classesTopologicalSorted(additionalDependencies);
-}
-
-AbstractMetaFunctionList Generator::globalFunctions() const
-{
- return m_d->apiextractor->globalFunctions();
-}
-
-AbstractMetaEnumList Generator::globalEnums() const
-{
- return m_d->apiextractor->globalEnums();
-}
-
-PrimitiveTypeEntryList Generator::primitiveTypes() const
-{
- return m_d->apiextractor->primitiveTypes();
-}
-
-ContainerTypeEntryList Generator::containerTypes() const
-{
- return m_d->apiextractor->containerTypes();
-}
-
-const AbstractMetaEnum *Generator::findAbstractMetaEnum(const TypeEntry *typeEntry) const
-{
- return m_d->apiextractor->findAbstractMetaEnum(typeEntry);
-}
-
-const AbstractMetaEnum *Generator::findAbstractMetaEnum(const AbstractMetaType *metaType) const
-{
- return m_d->apiextractor->findAbstractMetaEnum(metaType->typeEntry());
-}
-
-QString Generator::licenseComment() const
-{
- return m_d->licenseComment;
-}
-
-void Generator::setLicenseComment(const QString &licenseComment)
-{
- m_d->licenseComment = licenseComment;
-}
-
-QString Generator::packageName() const
-{
- return TypeDatabase::instance()->defaultPackageName();
-}
-
-QString Generator::moduleName() const
-{
- if (m_d->moduleName.isEmpty()) {
- m_d->moduleName = packageName();
- m_d->moduleName.remove(0, m_d->moduleName.lastIndexOf(QLatin1Char('.')) + 1);
- }
- return m_d->moduleName;
-}
-
-QString Generator::outputDirectory() const
-{
- return m_d->outDir;
-}
-
-void Generator::setOutputDirectory(const QString &outDir)
-{
- m_d->outDir = outDir;
-}
-
-bool Generator::generateFileForContext(const GeneratorContext &context)
-{
- const AbstractMetaClass *cls = context.metaClass();
-
- if (!shouldGenerate(cls))
- return true;
-
- const QString fileName = fileNameForContext(context);
- if (fileName.isEmpty())
- return true;
-
- QString filePath = outputDirectory() + QLatin1Char('/') + subDirectoryForClass(cls)
- + QLatin1Char('/') + fileName;
- FileOut fileOut(filePath);
-
- generateClass(fileOut.stream, context);
-
- return fileOut.done() != FileOut::Failure;
-}
-
-QString Generator::getFileNameBaseForSmartPointer(const AbstractMetaType *smartPointerType,
- const AbstractMetaClass *smartPointerClass) const
-{
- const AbstractMetaType *innerType = smartPointerType->getSmartPointerInnerType();
- QString fileName = smartPointerClass->qualifiedCppName().toLower();
- fileName.replace(QLatin1String("::"), QLatin1String("_"));
- fileName.append(QLatin1String("_"));
- fileName.append(innerType->name().toLower());
-
- return fileName;
-}
-
-GeneratorContext Generator::contextForClass(const AbstractMetaClass *c) const
-{
- GeneratorContext result;
- result.m_metaClass = c;
- return result;
-}
-
-GeneratorContext Generator::contextForSmartPointer(const AbstractMetaClass *c,
- const AbstractMetaType *t) const
-{
- GeneratorContext result;
- result.m_metaClass = c;
- result.m_preciseClassType = t;
- result.m_type = GeneratorContext::SmartPointer;
- return result;
-}
-
-bool Generator::generate()
-{
- const AbstractMetaClassList &classList = m_d->apiextractor->classes();
- for (AbstractMetaClass *cls : classList) {
- if (!generateFileForContext(contextForClass(cls)))
- return false;
- }
-
- const auto smartPointers = m_d->apiextractor->smartPointers();
- for (const AbstractMetaType *type : qAsConst(m_d->instantiatedSmartPointers)) {
- AbstractMetaClass *smartPointerClass =
- AbstractMetaClass::findClass(smartPointers, type->typeEntry());
- if (!smartPointerClass) {
- qCWarning(lcShiboken, "%s",
- qPrintable(msgCannotFindSmartPointer(type->cppSignature(),
- smartPointers)));
- return false;
- }
- if (!generateFileForContext(contextForSmartPointer(smartPointerClass, type)))
- return false;
- }
- return finishGeneration();
-}
-
-bool Generator::shouldGenerateTypeEntry(const TypeEntry *type) const
-{
- return (type->codeGeneration() & TypeEntry::GenerateTargetLang)
- && NamespaceTypeEntry::isVisibleScope(type);
-}
-
-bool Generator::shouldGenerate(const AbstractMetaClass *metaClass) const
-{
- return shouldGenerateTypeEntry(metaClass->typeEntry());
-}
-
-void verifyDirectoryFor(const QString &file)
-{
- QDir dir = QFileInfo(file).absoluteDir();
- if (!dir.exists()) {
- if (!dir.mkpath(dir.absolutePath())) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("unable to create directory '%1'").arg(dir.absolutePath());
- }
- }
-}
-
-void Generator::replaceTemplateVariables(QString &code, const AbstractMetaFunction *func)
-{
- const AbstractMetaClass *cpp_class = func->ownerClass();
- if (cpp_class)
- code.replace(QLatin1String("%TYPE"), cpp_class->name());
-
- const AbstractMetaArgumentList &argument = func->arguments();
- for (AbstractMetaArgument *arg : argument)
- code.replace(QLatin1Char('%') + QString::number(arg->argumentIndex() + 1), arg->name());
-
- //template values
- code.replace(QLatin1String("%RETURN_TYPE"), translateType(func->type(), cpp_class));
- code.replace(QLatin1String("%FUNCTION_NAME"), func->originalName());
-
- if (code.contains(QLatin1String("%ARGUMENT_NAMES"))) {
- QString str;
- QTextStream aux_stream(&str);
- writeArgumentNames(aux_stream, func, Generator::SkipRemovedArguments);
- code.replace(QLatin1String("%ARGUMENT_NAMES"), str);
- }
-
- if (code.contains(QLatin1String("%ARGUMENTS"))) {
- QString str;
- QTextStream aux_stream(&str);
- writeFunctionArguments(aux_stream, func, Options(SkipDefaultValues) | SkipRemovedArguments);
- code.replace(QLatin1String("%ARGUMENTS"), str);
- }
-}
-
-QTextStream &formatCode(QTextStream &s, const QString &code, Indentor &indentor)
-{
- // detect number of spaces before the first character
- const QStringList lst(code.split(QLatin1Char('\n')));
- static const QRegularExpression nonSpaceRegex(QStringLiteral("[^\\s]"));
- Q_ASSERT(nonSpaceRegex.isValid());
- int spacesToRemove = 0;
- for (const QString &line : lst) {
- if (!line.trimmed().isEmpty()) {
- spacesToRemove = line.indexOf(nonSpaceRegex);
- if (spacesToRemove == -1)
- spacesToRemove = 0;
- break;
- }
- }
-
- static const QRegularExpression emptyLine(QStringLiteral("^\\s*[\\r]?[\\n]?\\s*$"));
- Q_ASSERT(emptyLine.isValid());
-
- for (QString line : lst) {
- if (!line.isEmpty() && !emptyLine.match(line).hasMatch()) {
- while (line.constEnd()->isSpace())
- line.chop(1);
- int limit = 0;
- for(int i = 0; i < spacesToRemove; ++i) {
- if (!line[i].isSpace())
- break;
- limit++;
- }
-
- s << indentor << line.remove(0, limit);
- }
- s << Qt::endl;
- }
- return s;
-}
-
-AbstractMetaFunctionList Generator::implicitConversions(const TypeEntry *type) const
-{
- if (type->isValue()) {
- if (const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes(), type))
- return metaClass->implicitConversions();
- }
- return AbstractMetaFunctionList();
-}
-
-AbstractMetaFunctionList Generator::implicitConversions(const AbstractMetaType *metaType) const
-{
- return implicitConversions(metaType->typeEntry());
-}
-
-bool Generator::isObjectType(const TypeEntry *type)
-{
- if (type->isComplex())
- return Generator::isObjectType(static_cast<const ComplexTypeEntry *>(type));
- return type->isObject();
-}
-bool Generator::isObjectType(const ComplexTypeEntry *type)
-{
- return type->isObject();
-}
-bool Generator::isObjectType(const AbstractMetaClass *metaClass)
-{
- return Generator::isObjectType(metaClass->typeEntry());
-}
-bool Generator::isObjectType(const AbstractMetaType *metaType)
-{
- return isObjectType(metaType->typeEntry());
-}
-
-bool Generator::isPointer(const AbstractMetaType *type)
-{
- return type->indirections() > 0
- || type->isNativePointer()
- || type->isValuePointer();
-}
-
-bool Generator::isCString(const AbstractMetaType *type)
-{
- return type->isNativePointer()
- && type->indirections() == 1
- && type->name() == QLatin1String("char");
-}
-
-bool Generator::isVoidPointer(const AbstractMetaType *type)
-{
- return type->isNativePointer()
- && type->indirections() == 1
- && type->name() == QLatin1String("void");
-}
-
-QString Generator::getFullTypeName(const TypeEntry *type) const
-{
- QString result = type->qualifiedCppName();
- if (type->isArray())
- type = static_cast<const ArrayTypeEntry *>(type)->nestedTypeEntry();
- if (!type->isCppPrimitive())
- result.prepend(QLatin1String("::"));
- return result;
-}
-
-QString Generator::getFullTypeName(const AbstractMetaType *type) const
-{
- if (isCString(type))
- return QLatin1String("const char*");
- if (isVoidPointer(type))
- return QLatin1String("void*");
- if (type->typeEntry()->isContainer())
- return QLatin1String("::") + type->cppSignature();
- QString typeName;
- if (type->typeEntry()->isComplex() && type->hasInstantiations())
- typeName = getFullTypeNameWithoutModifiers(type);
- else
- typeName = getFullTypeName(type->typeEntry());
- return typeName + QString::fromLatin1("*").repeated(type->indirections());
-}
-
-QString Generator::getFullTypeName(const AbstractMetaClass *metaClass) const
-{
- return QLatin1String("::") + metaClass->qualifiedCppName();
-}
-
-QString Generator::getFullTypeNameWithoutModifiers(const AbstractMetaType *type) const
-{
- if (isCString(type))
- return QLatin1String("const char*");
- if (isVoidPointer(type))
- return QLatin1String("void*");
- if (!type->hasInstantiations())
- return getFullTypeName(type->typeEntry());
- QString typeName = type->cppSignature();
- if (type->isConstant())
- typeName.remove(0, sizeof("const ") / sizeof(char) - 1);
- switch (type->referenceType()) {
- case NoReference:
- break;
- case LValueReference:
- typeName.chop(1);
- break;
- case RValueReference:
- typeName.chop(2);
- break;
- }
- while (typeName.endsWith(QLatin1Char('*')) || typeName.endsWith(QLatin1Char(' ')))
- typeName.chop(1);
- return QLatin1String("::") + typeName;
-}
-
-DefaultValue Generator::minimalConstructor(const AbstractMetaType *type) const
-{
- if (!type || (type->referenceType() == LValueReference && Generator::isObjectType(type)))
- return DefaultValue(DefaultValue::Error);
-
- if (type->isContainer()) {
- QString ctor = type->cppSignature();
- 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 DefaultValue(DefaultValue::DefaultConstructor, QLatin1String("::") + ctor);
- }
-
- if (type->isNativePointer())
- return DefaultValue(DefaultValue::Pointer, type->typeEntry()->qualifiedCppName());
- if (Generator::isPointer(type))
- return DefaultValue(DefaultValue::Pointer, QLatin1String("::") + type->typeEntry()->qualifiedCppName());
-
- if (type->typeEntry()->isSmartPointer())
- return minimalConstructor(type->typeEntry());
-
- if (type->typeEntry()->isComplex()) {
- auto 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());
-}
-
-DefaultValue Generator::minimalConstructor(const TypeEntry *type) const
-{
- if (!type)
- return DefaultValue(DefaultValue::Error);
-
- if (type->isCppPrimitive()) {
- const QString &name = type->qualifiedCppName();
- return name == QLatin1String("bool")
- ? DefaultValue(DefaultValue::Boolean)
- : DefaultValue(DefaultValue::CppScalar, name);
- }
-
- 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 DefaultValue(DefaultValue::Custom,
- type->qualifiedCppName() + QLatin1String("(0)"));
- }
-
- if (type->isPrimitive()) {
- 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()
- ? DefaultValue(DefaultValue::DefaultConstructorWithDefaultValues, QLatin1String("::")
- + type->qualifiedCppName())
- : DefaultValue(DefaultValue::Custom, ctor);
- }
-
- if (type->isSmartPointer())
- return DefaultValue(DefaultValue::DefaultConstructor, type->qualifiedCppName());
-
- if (type->isComplex())
- return minimalConstructor(AbstractMetaClass::findClass(classes(), type));
-
- return DefaultValue(DefaultValue::Error);
-}
-
-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 DefaultValue(DefaultValue::Error);
-
- auto cType = static_cast<const ComplexTypeEntry *>(metaClass->typeEntry());
- if (cType->hasDefaultConstructor())
- 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);
- for (const AbstractMetaFunction *ctor : constructors) {
- 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);
- }
- // 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)->hasOriginalDefaultValueExpression(); ++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);
- }
- }
-
- for (auto it = candidates.cbegin(), end = candidates.cend(); it != end; ++it) {
- const AbstractMetaArgumentList &arguments = it.value()->arguments();
- QStringList args;
- bool ok = true;
- for (int i =0, size = arguments.size(); ok && i < size; ++i) {
- const AbstractMetaArgument *arg = arguments.at(i);
- if (arg->hasModifiedDefaultValueExpression()) {
- args << arg->defaultValueExpression(); // Spell out modified values
- break;
- }
- if (arg->hasOriginalDefaultValueExpression())
- break;
- auto argValue = minimalConstructor(arg->type());
- ok &= argValue.isValid();
- args << argValue.constructorParameter();
- }
- if (ok)
- return DefaultValue(DefaultValue::Custom, constructorCall(qualifiedCppName, args));
- }
-
- 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,
- const AbstractMetaClass *context,
- Options options) const
-{
- QString s;
- static int constLen = strlen("const");
-
- if (context && cType &&
- context->typeEntry()->isGenericClass() &&
- cType->originalTemplateType()) {
- cType = cType->originalTemplateType();
- }
-
- if (!cType) {
- s = QLatin1String("void");
- } else if (cType->isArray()) {
- s = translateType(cType->arrayElementType(), context, options) + QLatin1String("[]");
- } else if ((options & Generator::EnumAsInts) && useEnumAsIntForProtectedHack(cType)) {
- s = QLatin1String("int");
- } else {
- if (options & Generator::OriginalName) {
- s = cType->originalTypeDescription().trimmed();
- if ((options & Generator::ExcludeReference) && s.endsWith(QLatin1Char('&')))
- s.chop(1);
-
- // remove only the last const (avoid remove template const)
- if (options & Generator::ExcludeConst) {
- int index = s.lastIndexOf(QLatin1String("const"));
-
- if (index >= (s.size() - (constLen + 1))) // (VarType const) or (VarType const[*|&])
- s = s.remove(index, constLen);
- }
- } else if (options & Generator::ExcludeConst || options & Generator::ExcludeReference) {
- AbstractMetaType *copyType = cType->copy();
-
- if (options & Generator::ExcludeConst)
- copyType->setConstant(false);
-
- if (options & Generator::ExcludeReference)
- copyType->setReferenceType(NoReference);
-
- s = copyType->cppSignature();
- if (!copyType->typeEntry()->isVoid() && !copyType->typeEntry()->isCppPrimitive())
- s.prepend(QLatin1String("::"));
- delete copyType;
- } else {
- s = cType->cppSignature();
- }
- }
-
- return s;
-}
-
-
-QString Generator::subDirectoryForClass(const AbstractMetaClass *clazz) const
-{
- return subDirectoryForPackage(clazz->package());
-}
-
-QString Generator::subDirectoryForPackage(QString packageNameIn) const
-{
- if (packageNameIn.isEmpty())
- packageNameIn = packageName();
- packageNameIn.replace(QLatin1Char('.'), QDir::separator());
- return packageNameIn;
-}
-
-template<typename T>
-static QString getClassTargetFullName_(const T *t, bool includePackageName)
-{
- QString name = t->name();
- const AbstractMetaClass *context = t->enclosingClass();
- while (context) {
- // If the type was marked as 'visible=false' we should not use it in
- // the type name
- if (NamespaceTypeEntry::isVisibleScope(context->typeEntry())) {
- name.prepend(QLatin1Char('.'));
- name.prepend(context->name());
- }
- context = context->enclosingClass();
- }
- if (includePackageName) {
- name.prepend(QLatin1Char('.'));
- name.prepend(t->package());
- }
- return name;
-}
-
-QString getClassTargetFullName(const AbstractMetaClass *metaClass, bool includePackageName)
-{
- return getClassTargetFullName_(metaClass, includePackageName);
-}
-
-QString getClassTargetFullName(const AbstractMetaEnum *metaEnum, bool includePackageName)
-{
- return getClassTargetFullName_(metaEnum, includePackageName);
-}
-
-QString getClassTargetFullName(const AbstractMetaType *metaType, bool includePackageName)
-{
- QString name = metaType->cppSignature();
- name.replace(QLatin1String("::"), QLatin1String("_"));
- name.replace(QLatin1Char('<'), QLatin1Char('_'));
- name.remove(QLatin1Char('>'));
- name.remove(QLatin1Char(' '));
- if (includePackageName) {
- name.prepend(QLatin1Char('.'));
- name.prepend(metaType->package());
- }
- return name;
-}
-
-QString getFilteredCppSignatureString(QString signature)
-{
- signature.replace(QLatin1String("::"), QLatin1String("_"));
- signature.replace(QLatin1Char('<'), QLatin1Char('_'));
- signature.replace(QLatin1Char('>'), QLatin1Char('_'));
- signature.replace(QLatin1Char(' '), QLatin1Char('_'));
- return signature;
-}