diff options
65 files changed, 1739 insertions, 1009 deletions
diff --git a/sources/pyside2/cmake/Macros/PySideModules.cmake b/sources/pyside2/cmake/Macros/PySideModules.cmake index dca00ec11..14707f964 100644 --- a/sources/pyside2/cmake/Macros/PySideModules.cmake +++ b/sources/pyside2/cmake/Macros/PySideModules.cmake @@ -91,7 +91,10 @@ macro(create_pyside_module) list(REMOVE_DUPLICATES total_type_system_files) # Contains include directories to pass to shiboken's preprocessor. - set(shiboken_include_dirs ${pyside2_SOURCE_DIR}${PATH_SEP}${QT_INCLUDE_DIR}) + # Workaround: Added ${QT_INCLUDE_DIR}/QtCore until + # qtdeclarative/8d560d1bf0a747bf62f73fad6b6774095442d9d2 has reached qt5.git + string(REPLACE ";" ${PATH_SEP} core_includes "${Qt5Core_INCLUDE_DIRS}") + set(shiboken_include_dirs ${pyside2_SOURCE_DIR}${PATH_SEP}${QT_INCLUDE_DIR}${PATH_SEP}${core_includes}) set(shiboken_framework_include_dirs_option "") if(CMAKE_HOST_APPLE) set(shiboken_framework_include_dirs "${QT_FRAMEWORK_INCLUDE_DIR}") diff --git a/sources/pyside2/pyside_version.py b/sources/pyside2/pyside_version.py index 0e0943143..c022fc803 100644 --- a/sources/pyside2/pyside_version.py +++ b/sources/pyside2/pyside_version.py @@ -38,8 +38,8 @@ ############################################################################# major_version = "5" -minor_version = "14" -patch_version = "2" +minor_version = "15" +patch_version = "0" # For example: "a", "b", "rc" # (which means "alpha", "beta", "release candidate"). diff --git a/sources/pyside2/tests/registry/init_platform.py b/sources/pyside2/tests/registry/init_platform.py index a690a3120..e80c3b69f 100644 --- a/sources/pyside2/tests/registry/init_platform.py +++ b/sources/pyside2/tests/registry/init_platform.py @@ -141,8 +141,8 @@ Shiboken.__name__ = "Shiboken" sys.modules["Shiboken"] = sys.modules.pop("shiboken2") all_modules.append("Shiboken") -# 'sample' seems to be needed by 'other', so import it first. -for modname in "minimal sample other smart".split(): +# 'sample/smart' are needed by 'other', so import them first. +for modname in "minimal sample smart other".split(): sys.path.insert(0, os.path.join(shiboken_build_dir, "tests", modname + "binding")) __import__(modname) all_modules.append(modname) diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 4566ed3bc..f0e5da8da 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -270,7 +270,7 @@ void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelI const ArgumentModelItem &arg = arguments.at(1); if (AbstractMetaClass *cls = argumentToClass(arg, currentClass)) { if (arg->type().indirections() < 2) - cls->setToStringCapability(true, arg->type().indirections()); + cls->setToStringCapability(true, int(arg->type().indirections())); } } } @@ -410,6 +410,7 @@ FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments, unsigned clangFlags) { clang::Builder builder; + builder.setSystemIncludes(TypeDatabase::instance()->systemIncludes()); if (level == LanguageLevel::Default) level = clang::emulatedCompilerLanguageLevel(); arguments.prepend(QByteArrayLiteral("-std=") @@ -512,7 +513,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) ReportHandler::startProgress("Fixing class inheritance..."); for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) { - if (!cls->isInterface() && !cls->isNamespace()) { + if (!cls->isNamespace()) { setupInheritance(cls); if (!cls->hasVirtualDestructor() && cls->baseClass() && cls->baseClass()->hasVirtualDestructor()) @@ -530,7 +531,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) .arg(cls->name()); } else { const bool couldAddDefaultCtors = cls->isConstructible() - && !cls->isInterface() && !cls->isNamespace() + && !cls->isNamespace() && (cls->attributes() & AbstractMetaAttributes::HasRejectedConstructor) == 0; if (couldAddDefaultCtors) { if (!cls->hasConstructors()) @@ -549,11 +550,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) if (!entry->isPrimitive()) { if ((entry->isValue() || entry->isObject()) && !types->shouldDropTypeEntry(entry->qualifiedCppName()) - && !entry->isString() - && !entry->isChar() && !entry->isContainer() && !entry->isCustom() - && !entry->isVariant() && (entry->generateCode() & TypeEntry::GenerateTargetLang) && !AbstractMetaClass::findClass(m_metaClasses, entry)) { qCWarning(lcShiboken).noquote().nospace() @@ -729,12 +727,6 @@ void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls, m_smartPointers << cls; } else { m_metaClasses << cls; - if (cls->typeEntry()->designatedInterface()) { - AbstractMetaClass *interface = cls->extractInterface(); - m_metaClasses << interface; - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) - qCDebug(lcShiboken) << QStringLiteral(" -> interface '%1'").arg(interface->name()); - } } } @@ -758,6 +750,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel return nullptr; } + if (namespaceItem->type() == NamespaceType::Inline) { + type->setInlineNamespace(true); + TypeDatabase::instance()->addInlineNamespaceLookups(type); + } + // Continue populating namespace? AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, type); if (!metaClass) { @@ -1215,7 +1212,7 @@ AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(const VariableModel metaField->setType(metaType); - AbstractMetaAttributes::Attributes attr = nullptr; + AbstractMetaAttributes::Attributes attr; if (field->isStatic()) attr |= AbstractMetaAttributes::Static; @@ -1284,46 +1281,11 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF metaFunction->replaceType(metaType); } -static bool _compareAbstractMetaTypes(const AbstractMetaType *type, - const AbstractMetaType *other, - AbstractMetaType::ComparisonFlags flags = {}) -{ - return (type != nullptr) == (other != nullptr) - && (type == nullptr || type->compare(*other, flags)); -} - -static bool _compareAbstractMetaFunctions(const AbstractMetaFunction *func, - const AbstractMetaFunction *other, - AbstractMetaType::ComparisonFlags argumentFlags = {}) -{ - if (!func && !other) - return true; - if (!func || !other) - return false; - if (func->name() != other->name()) - return false; - const int argumentsCount = func->arguments().count(); - if (argumentsCount != other->arguments().count() - || func->isConstant() != other->isConstant() - || func->isStatic() != other->isStatic() - || !_compareAbstractMetaTypes(func->type(), other->type())) { - return false; - } - for (int i = 0; i < argumentsCount; ++i) { - if (!_compareAbstractMetaTypes(func->arguments().at(i)->type(), - other->arguments().at(i)->type(), - argumentFlags)) { - return false; - } - } - return true; -} - AbstractMetaFunctionList AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem, AbstractMetaClass::Attributes *constructorAttributes, AbstractMetaClass *currentClass) { - *constructorAttributes = nullptr; + *constructorAttributes = {}; AbstractMetaFunctionList result; const FunctionList &scopeFunctionList = scopeItem->functions(); result.reserve(scopeFunctionList.size()); @@ -1464,8 +1426,6 @@ void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) { - Q_ASSERT(!metaClass->isInterface()); - if (m_setupInheritanceDone.contains(metaClass)) return true; @@ -1505,61 +1465,23 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) TypeDatabase* types = TypeDatabase::instance(); - int primary = -1; - int primaries = 0; - for (int i = 0; i < baseClasses.size(); ++i) { - - if (types->isClassRejected(baseClasses.at(i))) - continue; - - TypeEntry* baseClassEntry = types->findType(baseClasses.at(i)); - if (!baseClassEntry) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("class '%1' inherits from unknown base class '%2'") - .arg(metaClass->name(), baseClasses.at(i)); - } else if (!baseClassEntry->designatedInterface()) { // true for primary base class - primaries++; - primary = i; - } - } - - if (primary >= 0) { - AbstractMetaClass *baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClasses.at(primary)); - if (!baseClass) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("unknown baseclass for '%1': '%2'") - .arg(metaClass->name(), baseClasses.at(primary)); - return false; - } - metaClass->setBaseClass(baseClass); - } - - for (int i = 0; i < baseClasses.size(); ++i) { - if (types->isClassRejected(baseClasses.at(i))) - continue; - - if (i != primary) { - AbstractMetaClass *baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClasses.at(i)); - if (!baseClass) { + for (const auto &baseClassName : baseClasses) { + if (!types->isClassRejected(baseClassName)) { + if (!types->findType(baseClassName)) { qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("class not found for setup inheritance '%1'").arg(baseClasses.at(i)); + << QStringLiteral("class '%1' inherits from unknown base class '%2'") + .arg(metaClass->name(), baseClassName); return false; } - - setupInheritance(baseClass); - - QString interfaceName = baseClass->isInterface() ? InterfaceTypeEntry::interfaceName(baseClass->name()) : baseClass->name(); - AbstractMetaClass *iface = AbstractMetaClass::findClass(m_metaClasses, interfaceName); - if (!iface) { + auto baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClassName); + if (!baseClass) { qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("unknown interface for '%1': '%2'").arg(metaClass->name(), interfaceName); + << QStringLiteral("class not found for setup inheritance '%1'").arg(baseClassName); return false; } - metaClass->addInterface(iface); + metaClass->addBaseClass(baseClass); - const AbstractMetaClassList &interfaces = iface->interfaces(); - for (AbstractMetaClass* iface : interfaces) - metaClass->addInterface(iface); + setupInheritance(baseClass); } } @@ -2092,6 +2014,7 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const AddedFunction: qFatal("%s", qPrintable(msg)); } + // These are only implicit and should not appear in code... auto *metaType = new AbstractMetaType; metaType->setTypeEntry(type); metaType->setIndirections(typeInfo.indirections); @@ -2120,6 +2043,52 @@ static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaC return type; } +// Helper for translateTypeStatic() +TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualifiedName, + const QString &name, + AbstractMetaClass *currentClass, + AbstractMetaBuilderPrivate *d) +{ + // 5.1 - Try first using the current scope + if (currentClass) { + if (auto type = findTypeEntryUsingContext(currentClass, qualifiedName)) + return {type}; + + // 5.1.1 - Try using the class parents' scopes + if (d && !currentClass->baseClassNames().isEmpty()) { + const AbstractMetaClassList &baseClasses = d->getBaseClasses(currentClass); + for (const AbstractMetaClass *cls : baseClasses) { + if (auto type = findTypeEntryUsingContext(cls, qualifiedName)) + return {type}; + } + } + } + + // 5.2 - Try without scope + auto types = TypeDatabase::instance()->findCppTypes(qualifiedName); + if (!types.isEmpty()) + return types; + + // 6. No? Try looking it up as a flags type + if (auto type = TypeDatabase::instance()->findFlagsType(qualifiedName)) + return {type}; + + // 7. No? Try looking it up as a container type + if (auto type = TypeDatabase::instance()->findContainerType(name)) + return {type}; + + // 8. No? Check if the current class is a template and this type is one + // of the parameters. + if (currentClass) { + const QVector<TypeEntry *> &template_args = currentClass->templateArguments(); + for (TypeEntry *te : template_args) { + if (te->name() == qualifiedName) + return {te}; + } + } + return {}; +} + AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei, AbstractMetaClass *currentClass, TranslateTypeFlags flags, @@ -2252,47 +2221,8 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo typeInfo.clearInstantiations(); } - const TypeEntry *type = nullptr; - // 5. Try to find the type - - // 5.1 - Try first using the current scope - if (currentClass) { - type = findTypeEntryUsingContext(currentClass, qualifiedName); - - // 5.1.1 - Try using the class parents' scopes - if (!type && d && !currentClass->baseClassNames().isEmpty()) { - const AbstractMetaClassList &baseClasses = d->getBaseClasses(currentClass); - for (const AbstractMetaClass *cls : baseClasses) { - type = findTypeEntryUsingContext(cls, qualifiedName); - if (type) - break; - } - } - } - - // 5.2 - Try without scope - if (!type) - type = TypeDatabase::instance()->findType(qualifiedName); - - // 6. No? Try looking it up as a flags type - if (!type) - type = TypeDatabase::instance()->findFlagsType(qualifiedName); - - // 7. No? Try looking it up as a container type - if (!type) - type = TypeDatabase::instance()->findContainerType(name); - - // 8. No? Check if the current class is a template and this type is one - // of the parameters. - if (!type && currentClass) { - const QVector<TypeEntry *> &template_args = currentClass->templateArguments(); - for (TypeEntry *te : template_args) { - if (te->name() == qualifiedName) - type = te; - } - } - - if (!type) { + const TypeEntries types = findTypeEntries(qualifiedName, name, currentClass, d); + if (types.isEmpty()) { if (errorMessageIn) { *errorMessageIn = msgUnableToTranslateType(_typei, msgCannotFindTypeEntry(qualifiedName)); @@ -2300,11 +2230,10 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo return nullptr; } - // These are only implicit and should not appear in code... - Q_ASSERT(!type->isInterface()); + const TypeEntry *type = types.constFirst(); + const TypeEntry::Type typeEntryType = type->type(); - auto *metaType = new AbstractMetaType; - metaType->setTypeEntry(type); + QScopedPointer<AbstractMetaType> metaType(new AbstractMetaType); metaType->setIndirectionsV(typeInfo.indirectionsV()); metaType->setReferenceType(typeInfo.referenceType()); metaType->setConstant(typeInfo.isConstant()); @@ -2318,20 +2247,66 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo if (!targType) { if (errorMessageIn) *errorMessageIn = msgCannotTranslateTemplateArgument(t, ti, errorMessage); - delete metaType; return nullptr; } metaType->addInstantiation(targType, true); } + if (types.size() > 1) { + const bool sameType = std::all_of(types.cbegin() + 1, types.cend(), + [typeEntryType](const TypeEntry *e) { + return e->type() == typeEntryType; }); + if (!sameType) { + if (errorMessageIn) + *errorMessageIn = msgAmbiguousVaryingTypesFound(qualifiedName, types); + return nullptr; + } + // Ambiguous primitive/smart pointer types are possible (when + // including type systems). + if (typeEntryType != TypeEntry::PrimitiveType + && typeEntryType != TypeEntry::SmartPointerType) { + if (errorMessageIn) + *errorMessageIn = msgAmbiguousTypesFound(qualifiedName, types); + return nullptr; + } + } + + if (typeEntryType == TypeEntry::SmartPointerType) { + // Find a matching instantiation + if (metaType->instantiations().size() != 1) { + if (errorMessageIn) + *errorMessageIn = msgInvalidSmartPointerType(_typei); + return nullptr; + } + auto instantiationType = metaType->instantiations().constFirst()->typeEntry(); + if (instantiationType->type() == TypeEntry::TemplateArgumentType) { + // Member functions of the template itself, SharedPtr(const SharedPtr &) + type = instantiationType; + } else { + auto it = std::find_if(types.cbegin(), types.cend(), + [instantiationType](const TypeEntry *e) { + auto smartPtr = static_cast<const SmartPointerTypeEntry *>(e); + return smartPtr->matchesInstantiation(instantiationType); + }); + if (it == types.cend()) { + if (errorMessageIn) + *errorMessageIn = msgCannotFindSmartPointerInstantion(_typei); + return nullptr; + } + type =*it; + } + } + + metaType->setTypeEntry(type); + // The usage pattern *must* be decided *after* the possible template // instantiations have been determined, or else the absence of // such instantiations will break the caching scheme of // AbstractMetaType::cppSignature(). metaType->decideUsagePattern(); - return metaType; + return metaType.take(); } AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei, @@ -2786,7 +2761,6 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, subclass->setTemplateBaseClass(templateClass); subclass->setTemplateBaseClassInstantiations(templateTypes); - subclass->setInterfaces(templateClass->interfaces()); subclass->setBaseClass(templateClass->baseClass()); return true; @@ -2864,11 +2838,9 @@ void AbstractMetaBuilderPrivate::setupClonable(AbstractMetaClass *cls) QQueue<AbstractMetaClass*> baseClasses; if (cls->baseClass()) baseClasses.enqueue(cls->baseClass()); - baseClasses << cls->interfaces().toList(); while (!baseClasses.isEmpty()) { AbstractMetaClass* currentClass = baseClasses.dequeue(); - baseClasses << currentClass->interfaces().toList(); if (currentClass->baseClass()) baseClasses.enqueue(currentClass->baseClass()); @@ -2913,7 +2885,7 @@ static void writeRejectLogFile(const QString &name, for (int reason = 0; reason < AbstractMetaBuilder::NoReason; ++reason) { - s << QString(72, QLatin1Char('*')) << endl; + s << QString(72, QLatin1Char('*')) << Qt::endl; switch (reason) { case AbstractMetaBuilder::NotInTypeSystem: s << "Not in type system"; @@ -2946,16 +2918,16 @@ static void writeRejectLogFile(const QString &name, break; } - s << endl; + s << Qt::endl; for (QMap<QString, AbstractMetaBuilder::RejectReason>::const_iterator it = rejects.constBegin(); it != rejects.constEnd(); ++it) { if (it.value() != reason) continue; - s << " - " << it.key() << endl; + s << " - " << it.key() << Qt::endl; } - s << QString(72, QLatin1Char('*')) << endl << endl; + s << QString(72, QLatin1Char('*')) << Qt::endl << Qt::endl; } } @@ -3064,8 +3036,7 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const } else { for (int i : qAsConst(unmappedResult)) { Q_ASSERT(reverseMap.contains(i)); - if (!reverseMap[i]->isInterface()) - result << reverseMap[i]; + result << reverseMap[i]; } } diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index b381a62cd..e3c9e1a72 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -146,6 +146,9 @@ public: AbstractMetaBuilderPrivate *d = nullptr, TranslateTypeFlags flags = {}, QString *errorMessageIn = nullptr); + static TypeEntries findTypeEntries(const QString &qualifiedName, const QString &name, + AbstractMetaClass *currentClass = nullptr, + AbstractMetaBuilderPrivate *d = nullptr); qint64 findOutValueFromString(const QString &stringValue, bool &ok); diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index 5ae671d87..e6590e2dc 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -80,15 +80,10 @@ const AbstractMetaClass *recurseClassHierarchy(const AbstractMetaClass *klass, { if (pred(klass)) return klass; - if (auto base = klass->baseClass()) { + for (auto base : klass->baseClasses()) { if (auto r = recurseClassHierarchy(base, pred)) return r; } - const auto interfaces = klass->interfaces(); - for (auto i : interfaces) { - if (auto r = recurseClassHierarchy(i, pred)) - return r; - } return nullptr; } @@ -268,7 +263,7 @@ QString AbstractMetaType::pythonSignature() const // PYSIDE-921: Handle container returntypes correctly. // This is now a clean reimplementation. if (m_cachedPythonSignature.isEmpty()) - m_cachedPythonSignature = formatPythonSignature(false); + m_cachedPythonSignature = formatPythonSignature(); return m_cachedPythonSignature; } @@ -531,7 +526,7 @@ bool AbstractMetaFunction::operator<(const AbstractMetaFunction &other) const */ AbstractMetaFunction::CompareResult AbstractMetaFunction::compareTo(const AbstractMetaFunction *other) const { - CompareResult result = nullptr; + CompareResult result; // Enclosing class... if (ownerClass() == other->ownerClass()) @@ -948,9 +943,6 @@ FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaC (implementor == implementingClass() && !mods.isEmpty())) { break; } - const AbstractMetaClassList &interfaces = implementor->interfaces(); - for (const AbstractMetaClass *interface : interfaces) - mods += this->modifications(interface); implementor = implementor->baseClass(); } return mods; @@ -1365,44 +1357,6 @@ bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const } /******************************************************************************* - * Constructs an interface based on the functions and enums in this - * class and returns it... - */ -AbstractMetaClass *AbstractMetaClass::extractInterface() -{ - Q_ASSERT(typeEntry()->designatedInterface()); - - if (!m_extractedInterface) { - auto *iface = new AbstractMetaClass; - iface->setAttributes(attributes()); - iface->setBaseClass(nullptr); - - iface->setTypeEntry(typeEntry()->designatedInterface()); - - for (AbstractMetaFunction *function : qAsConst(m_functions)) { - if (!function->isConstructor()) - iface->addFunction(function->copy()); - } - -// iface->setEnums(enums()); -// setEnums(AbstractMetaEnumList()); - - for (const AbstractMetaField *field : qAsConst(m_fields)) { - if (field->isPublic()) { - AbstractMetaField *new_field = field->copy(); - new_field->setEnclosingClass(iface); - iface->addField(new_field); - } - } - - m_extractedInterface = iface; - addInterface(iface); - } - - return m_extractedInterface; -} - -/******************************************************************************* * Returns a list of all the functions with a given name */ AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString &name) const @@ -1424,10 +1378,6 @@ AbstractMetaFunctionList AbstractMetaClass::functionsInTargetLang() const { FunctionQueryOptions default_flags = NormalFunctions | Visible | NotRemovedFromTargetLang; - // Interfaces don't implement functions - if (isInterface()) - default_flags |= ClassImplements; - // Only public functions in final classes // default_flags |= isFinal() ? WasPublic : 0; FunctionQueryOptions public_flags; @@ -1604,11 +1554,19 @@ QString AbstractMetaClass::name() const return m_typeEntry->targetLangEntryName(); } +void AbstractMetaClass::addBaseClass(AbstractMetaClass *baseClass) +{ + Q_ASSERT(baseClass); + m_baseClasses.append(baseClass); + m_isPolymorphic |= baseClass->isPolymorphic(); +} + void AbstractMetaClass::setBaseClass(AbstractMetaClass *baseClass) { - m_baseClass = baseClass; - if (baseClass) + if (baseClass) { + m_baseClasses.prepend(baseClass); m_isPolymorphic |= baseClass->isPolymorphic(); + } } QString AbstractMetaClass::package() const @@ -1616,11 +1574,6 @@ QString AbstractMetaClass::package() const return m_typeEntry->targetLangPackage(); } -bool AbstractMetaClass::isInterface() const -{ - return m_typeEntry->isInterface(); -} - bool AbstractMetaClass::isNamespace() const { return m_typeEntry->isNamespace(); @@ -1729,7 +1682,7 @@ void AbstractMetaClass::setTemplateBaseClassInstantiations(AbstractMetaTypeList bool AbstractMetaClass::deleteInMainThread() const { return typeEntry()->deleteInMainThread() - || (m_baseClass && m_baseClass->deleteInMainThread()); + || (!m_baseClasses.isEmpty() && m_baseClasses.constFirst()->deleteInMainThread()); } static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func) @@ -1858,6 +1811,14 @@ const AbstractMetaFunction *AbstractMetaField::setter() const return m_setter; } +const AbstractMetaClass *EnclosingClassMixin::targetLangEnclosingClass() const +{ + auto result = m_enclosingClass; + while (result && !NamespaceTypeEntry::isVisibleScope(result->typeEntry())) + result = result->enclosingClass(); + return result; +} + const AbstractMetaFunction *AbstractMetaField::getter() const { if (!m_getter) { @@ -2139,57 +2100,6 @@ AbstractMetaFunctionList AbstractMetaClass::cppSignalFunctions() const return queryFunctions(Signals | Visible | NotRemovedFromTargetLang); } -/** - * Adds the specified interface to this class by adding all the - * functions in the interface to this class. - */ -void AbstractMetaClass::addInterface(AbstractMetaClass *interface) -{ - Q_ASSERT(!m_interfaces.contains(interface)); - m_interfaces << interface; - - m_isPolymorphic |= interface->isPolymorphic(); - - if (m_extractedInterface && m_extractedInterface != interface) - m_extractedInterface->addInterface(interface); - - -#if 0 - const AbstractMetaFunctionList &funcs = interface->functions(); - for (AbstractMetaFunction *function : funcs) - if (!hasFunction(function) && !function->isConstructor()) { - AbstractMetaFunction *cpy = function->copy(); - cpy->setImplementingClass(this); - - // Setup that this function is an interface class. - cpy->setInterfaceClass(interface); - *cpy += AbstractMetaAttributes::InterfaceFunction; - - // Copy the modifications in interface into the implementing classes. - const FunctionModificationList &mods = function->modifications(interface); - for (const FunctionModification &mod : mods) - m_typeEntry->addFunctionModification(mod); - - // It should be mostly safe to assume that when we implement an interface - // we don't "pass on" pure virtual functions to our sublcasses... -// *cpy -= AbstractMetaAttributes::Abstract; - - addFunction(cpy); - } -#endif - -} - - -void AbstractMetaClass::setInterfaces(const AbstractMetaClassList &interfaces) -{ - m_interfaces = interfaces; - for (const AbstractMetaClass *interface : interfaces) { - if (interface) - m_isPolymorphic |= interface->isPolymorphic(); - } -} - AbstractMetaField *AbstractMetaClass::findField(const QString &name) const { return AbstractMetaField::find(m_fields, name); @@ -2199,10 +2109,6 @@ AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName) { if (AbstractMetaEnum *e = findByName(m_enums, enumName)) return e; - - if (typeEntry()->designatedInterface()) - return extractInterface()->findEnum(enumName); - return nullptr; } @@ -2215,10 +2121,6 @@ AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValue if (AbstractMetaEnumValue *v = e->findEnumValue(enumValueName)) return v; } - - if (typeEntry()->designatedInterface()) - return extractInterface()->findEnumValue(enumValueName); - if (baseClass()) return baseClass()->findEnumValue(enumValueName); @@ -2265,32 +2167,23 @@ void AbstractMetaClass::fixFunctions() m_functionsFixed = true; - AbstractMetaClass *superClass = baseClass(); AbstractMetaFunctionList funcs = functions(); - if (superClass) + for (auto superClass : m_baseClasses) { superClass->fixFunctions(); - int iface_idx = 0; - while (superClass || iface_idx < interfaces().size()) { // Since we always traverse the complete hierarchy we are only // interrested in what each super class implements, not what // we may have propagated from their base classes again. AbstractMetaFunctionList superFuncs; - if (superClass) { - // Super classes can never be final - if (superClass->isFinalInTargetLang()) { - qCWarning(lcShiboken).noquote().nospace() - << "Final class '" << superClass->name() << "' set to non-final, as it is extended by other classes"; - *superClass -= AbstractMetaAttributes::FinalInTargetLang; - } - superFuncs = superClass->queryFunctions(AbstractMetaClass::ClassImplements); - AbstractMetaFunctionList virtuals = superClass->queryFunctions(AbstractMetaClass::VirtualInCppFunctions); - superFuncs += virtuals; - } else { - superFuncs = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::NormalFunctions); - AbstractMetaFunctionList virtuals = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::VirtualInCppFunctions); - superFuncs += virtuals; + // Super classes can never be final + if (superClass->isFinalInTargetLang()) { + qCWarning(lcShiboken).noquote().nospace() + << "Final class '" << superClass->name() << "' set to non-final, as it is extended by other classes"; + *superClass -= AbstractMetaAttributes::FinalInTargetLang; } + superFuncs = superClass->queryFunctions(AbstractMetaClass::ClassImplements); + AbstractMetaFunctionList virtuals = superClass->queryFunctions(AbstractMetaClass::VirtualInCppFunctions); + superFuncs += virtuals; QSet<AbstractMetaFunction *> funcsToAdd; for (auto sf : qAsConst(superFuncs)) { @@ -2419,11 +2312,6 @@ void AbstractMetaClass::fixFunctions() (*copy) += AddedMethod; funcs.append(copy); } - - if (superClass) - superClass = superClass->baseClass(); - else - iface_idx++; } bool hasPrivateConstructors = false; @@ -2522,7 +2410,7 @@ QString AbstractMetaType::formatSignature(bool minimal) const return result; } -QString AbstractMetaType::formatPythonSignature(bool minimal) const +QString AbstractMetaType::formatPythonSignature() const { /* * This is a version of the above, more suitable for Python. @@ -2545,7 +2433,7 @@ QString AbstractMetaType::formatPythonSignature(bool minimal) const result += package() + QLatin1Char('.'); if (isArray()) { // Build nested array dimensions a[2][3] in correct order - result += m_arrayElementType->formatPythonSignature(true); + result += m_arrayElementType->formatPythonSignature(); const int arrayPos = result.indexOf(QLatin1Char('[')); if (arrayPos != -1) result.insert(arrayPos, formatArraySize(m_arrayElementCount)); @@ -2559,7 +2447,7 @@ QString AbstractMetaType::formatPythonSignature(bool minimal) const for (int i = 0, size = m_instantiations.size(); i < size; ++i) { if (i > 0) result += QLatin1String(", "); - result += m_instantiations.at(i)->formatPythonSignature(true); + result += m_instantiations.at(i)->formatPythonSignature(); } result += QLatin1Char(']'); } @@ -2676,6 +2564,63 @@ AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &cla } #ifndef QT_NO_DEBUG_STREAM + +void AbstractMetaClass::format(QDebug &d) const +{ + if (d.verbosity() > 2) + d << static_cast<const void *>(this) << ", "; + d << '"' << qualifiedCppName(); + if (const int count = m_templateArgs.size()) { + for (int i = 0; i < count; ++i) + d << (i ? ',' : '<') << m_templateArgs.at(i)->qualifiedCppName(); + d << '>'; + } + d << '"'; + if (isNamespace()) + d << " [namespace]"; + if (attributes() & AbstractMetaAttributes::FinalCppClass) + d << " [final]"; + if (attributes().testFlag(AbstractMetaAttributes::Deprecated)) + d << " [deprecated]"; + if (!m_baseClasses.isEmpty()) { + d << ", inherits "; + for (auto b : m_baseClasses) + d << " \"" << b->name() << '"'; + } + if (auto templateBase = templateBaseClass()) { + const auto instantiatedTypes = templateBaseClassInstantiations(); + d << ", instantiates \"" << templateBase->name(); + for (int i = 0, count = instantiatedTypes.size(); i < count; ++i) + d << (i ? ',' : '<') << instantiatedTypes.at(i)->name(); + d << ">\""; + } +} + +void AbstractMetaClass::formatMembers(QDebug &d) const +{ + if (!m_enums.isEmpty()) + d << ", enums[" << m_enums.size() << "]=" << m_enums; + if (!m_functions.isEmpty()) { + const int count = m_functions.size(); + d << ", functions=[" << count << "]("; + for (int i = 0; i < count; ++i) { + if (i) + d << ", "; + formatMetaFunctionBrief(d, m_functions.at(i)); + } + d << ')'; + } + if (const int count = m_fields.size()) { + d << ", fields=[" << count << "]("; + for (int i = 0; i < count; ++i) { + if (i) + d << ", "; + formatMetaField(d, m_fields.at(i)); + } + d << ')'; + } +} + QDebug operator<<(QDebug d, const AbstractMetaClass *ac) { QDebugStateSaver saver(d); @@ -2683,57 +2628,9 @@ QDebug operator<<(QDebug d, const AbstractMetaClass *ac) d.nospace(); d << "AbstractMetaClass("; if (ac) { - d << '"' << ac->fullName() << '"'; - if (ac->attributes() & AbstractMetaAttributes::FinalCppClass) - d << " [final]"; - if (ac->attributes().testFlag(AbstractMetaAttributes::Deprecated)) - d << " [deprecated]"; - if (ac->m_baseClass) - d << ", inherits \"" << ac->m_baseClass->name() << '"'; - if (ac->m_templateBaseClass) - d << ", inherits template \"" << ac->m_templateBaseClass->name() << '"'; - const AbstractMetaEnumList &enums = ac->enums(); - if (!enums.isEmpty()) - d << ", enums[" << enums.size() << "]=" << enums; - const AbstractMetaFunctionList &functions = ac->functions(); - if (!functions.isEmpty()) { - const int count = functions.size(); - d << ", functions=[" << count << "]("; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; -#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) - if (d.verbosity() > 2) - d << functions.at(i); - else -#endif - formatMetaFunctionBrief(d, functions.at(i)); - } - d << ')'; - } - const AbstractMetaFieldList &fields = ac->fields(); - if (!fields.isEmpty()) { - const int count = fields.size(); - d << ", fields=[" << count << "]("; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; - formatMetaField(d, fields.at(i)); - } - d << ')'; - } - const auto &templateArguments = ac->templateArguments(); - if (const int count = templateArguments.size()) { - d << ", templateArguments=[" << count << "]("; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; - d << templateArguments.at(i); - } - d << ')'; - } - - + ac->format(d); + if (d.verbosity() > 2) + ac->formatMembers(d); } else { d << '0'; } diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 2ae1b6d21..3e17a713b 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -538,7 +538,7 @@ public: private: TypeUsagePattern determineUsagePattern() const; QString formatSignature(bool minimal) const; - QString formatPythonSignature(bool minimal) const; + QString formatPythonSignature() const; const TypeEntry *m_typeEntry = nullptr; AbstractMetaTypeList m_instantiations; @@ -704,25 +704,26 @@ private: friend class AbstractMetaClass; }; +class EnclosingClassMixin { +public: + const AbstractMetaClass *enclosingClass() const { return m_enclosingClass; } + void setEnclosingClass(const AbstractMetaClass *cls) { m_enclosingClass = cls; } + const AbstractMetaClass *targetLangEnclosingClass() const; + +private: + const AbstractMetaClass *m_enclosingClass = nullptr; +}; + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const AbstractMetaArgument *aa); #endif -class AbstractMetaField : public AbstractMetaVariable, public AbstractMetaAttributes +class AbstractMetaField : public AbstractMetaVariable, public AbstractMetaAttributes, public EnclosingClassMixin { public: AbstractMetaField(); ~AbstractMetaField(); - const AbstractMetaClass *enclosingClass() const - { - return m_class; - } - void setEnclosingClass(const AbstractMetaClass *cls) - { - m_class = cls; - } - const AbstractMetaFunction *getter() const; const AbstractMetaFunction *setter() const; @@ -741,7 +742,6 @@ public: private: mutable AbstractMetaFunction *m_getter = nullptr; mutable AbstractMetaFunction *m_setter = nullptr; - const AbstractMetaClass *m_class = nullptr; }; #ifndef QT_NO_DEBUG_STREAM @@ -1179,7 +1179,7 @@ private: Documentation m_doc; }; -class AbstractMetaEnum : public AbstractMetaAttributes +class AbstractMetaEnum : public AbstractMetaAttributes, public EnclosingClassMixin { public: AbstractMetaEnum(); @@ -1234,23 +1234,12 @@ public: m_typeEntry = entry; } - AbstractMetaClass *enclosingClass() const - { - return m_class; - } - - void setEnclosingClass(AbstractMetaClass *c) - { - m_class = c; - } - bool isSigned() const { return m_signed; } void setSigned(bool s) { m_signed = s; } private: AbstractMetaEnumValueList m_enumValues; EnumTypeEntry *m_typeEntry = nullptr; - AbstractMetaClass *m_class = nullptr; EnumKind m_enumKind = CEnum; uint m_hasQenumsDeclaration : 1; @@ -1261,7 +1250,7 @@ private: QDebug operator<<(QDebug d, const AbstractMetaEnum *ae); #endif -class AbstractMetaClass : public AbstractMetaAttributes +class AbstractMetaClass : public AbstractMetaAttributes, public EnclosingClassMixin { Q_GADGET public: @@ -1306,7 +1295,6 @@ public: AbstractMetaClass(); ~AbstractMetaClass(); - AbstractMetaClass *extractInterface(); void fixFunctions(); AbstractMetaFunctionList functions() const @@ -1447,13 +1435,6 @@ public: AbstractMetaEnum *findEnum(const QString &enumName); AbstractMetaEnumValue *findEnumValue(const QString &enumName); - AbstractMetaClassList interfaces() const - { - return m_interfaces; - } - void addInterface(AbstractMetaClass *interface); - void setInterfaces(const AbstractMetaClassList &interface); - QString fullName() const { return package() + QLatin1Char('.') + name(); @@ -1467,32 +1448,24 @@ public: QString baseClassName() const { - return m_baseClass ? m_baseClass->name() : QString(); + return m_baseClasses.isEmpty() ? QString() : m_baseClasses.constFirst()->name(); } AbstractMetaClass *baseClass() const { - return m_baseClass; + return m_baseClasses.value(0, nullptr); } + const AbstractMetaClassList &baseClasses() const { return m_baseClasses; } + void addBaseClass(AbstractMetaClass *base_class); void setBaseClass(AbstractMetaClass *base_class); - const AbstractMetaClass *enclosingClass() const - { - return m_enclosingClass; - } - /** * \return the namespace from another package which this namespace extends. */ AbstractMetaClass *extendedNamespace() const { return m_extendedNamespace; } void setExtendedNamespace(AbstractMetaClass *e) { m_extendedNamespace = e; } - void setEnclosingClass(AbstractMetaClass *cl) - { - m_enclosingClass = cl; - } - const AbstractMetaClassList& innerClasses() const { return m_innerClasses; @@ -1510,8 +1483,6 @@ public: QString package() const; - bool isInterface() const; - bool isNamespace() const; bool isQObject() const; @@ -1712,6 +1683,8 @@ public: private: #ifndef QT_NO_DEBUG_STREAM + void format(QDebug &d) const; + void formatMembers(QDebug &d) const; friend QDebug operator<<(QDebug d, const AbstractMetaClass *ac); #endif uint m_hasVirtuals : 1; @@ -1730,21 +1703,19 @@ private: uint m_hasToStringCapability : 1; const AbstractMetaClass *m_enclosingClass = nullptr; - AbstractMetaClass *m_baseClass = nullptr; + AbstractMetaClassList m_baseClasses; // Real base classes after setting up inheritance AbstractMetaClass *m_extendedNamespace = nullptr; const AbstractMetaClass *m_templateBaseClass = nullptr; AbstractMetaFunctionList m_functions; AbstractMetaFieldList m_fields; AbstractMetaEnumList m_enums; - AbstractMetaClassList m_interfaces; - AbstractMetaClass *m_extractedInterface = nullptr; QVector<QPropertySpec *> m_propertySpecs; AbstractMetaClassList m_innerClasses; AbstractMetaFunctionList m_externalConversionOperators; - QStringList m_baseClassNames; + QStringList m_baseClassNames; // Base class names from C++, including rejected QVector<TypeEntry *> m_templateArgs; ComplexTypeEntry *m_typeEntry = nullptr; // FunctionModelItem m_qDebugStreamFunction; diff --git a/sources/shiboken2/ApiExtractor/apiextractor.cpp b/sources/shiboken2/ApiExtractor/apiextractor.cpp index 78fa9e313..6d29ed1e0 100644 --- a/sources/shiboken2/ApiExtractor/apiextractor.cpp +++ b/sources/shiboken2/ApiExtractor/apiextractor.cpp @@ -166,24 +166,6 @@ ContainerTypeEntryList ApiExtractor::containerTypes() const return TypeDatabase::instance()->containerTypes(); } -static const AbstractMetaEnum* findEnumOnClasses(AbstractMetaClassList metaClasses, const EnumTypeEntry* typeEntry) -{ - const AbstractMetaEnum *result = nullptr; - for (const AbstractMetaClass* metaClass : qAsConst(metaClasses)) { - const AbstractMetaEnumList &enums = metaClass->enums(); - for (const AbstractMetaEnum *metaEnum : enums) { - if (metaEnum->typeEntry() == typeEntry) { - result = metaEnum; - break; - } - } - if (result) - break; - result = findEnumOnClasses(metaClass->innerClasses(), typeEntry); - } - return result; -} - const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const TypeEntry* typeEntry) const { return m_builder->findEnum(typeEntry); diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp index d52e4672b..7c188535f 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp @@ -222,6 +222,7 @@ public: FunctionModelItem m_currentFunction; ArgumentModelItem m_currentArgument; VariableModelItem m_currentField; + QByteArrayList m_systemIncludes; int m_anonymousEnumCount = 0; CodeModel::FunctionType m_currentFunctionType = CodeModel::Normal; @@ -721,6 +722,12 @@ bool BuilderPrivate::visitHeader(const char *cFileName) const return true; } #endif // Q_OS_MACOS + if (baseName) { + for (const auto &systemInclude : m_systemIncludes) { + if (systemInclude == baseName) + return true; + } + } return false; } @@ -743,6 +750,11 @@ bool Builder::visitLocation(const CXSourceLocation &location) const return result; } +void Builder::setSystemIncludes(const QByteArrayList &systemIncludes) +{ + d->m_systemIncludes = systemIncludes; +} + FileModelItem Builder::dom() const { Q_ASSERT(!d->m_scopeStack.isEmpty()); @@ -766,6 +778,17 @@ static CodeModel::ClassType codeModelClassTypeFromCursor(CXCursorKind kind) return result; } +static NamespaceType namespaceType(const CXCursor &cursor) +{ + if (clang_Cursor_isAnonymous(cursor)) + return NamespaceType::Anonymous; +#if CINDEX_VERSION_MAJOR > 0 || CINDEX_VERSION_MINOR >= 59 + if (clang_Cursor_isInlineNamespace(cursor)) + return NamespaceType::Inline; +#endif + return NamespaceType::Default; +} + static QString enumType(const CXCursor &cursor) { QString name = getCursorSpelling(cursor); // "enum Foo { v1, v2 };" @@ -904,6 +927,9 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) d->m_scopeStack.back()->addFunction(d->m_currentFunction); break; case CXCursor_Namespace: { + const auto type = namespaceType(cursor); + if (type == NamespaceType::Anonymous) + return Skip; const QString name = getCursorSpelling(cursor); const NamespaceModelItem parentNamespaceItem = qSharedPointerDynamicCast<_NamespaceModelItem>(d->m_scopeStack.back()); if (parentNamespaceItem.isNull()) { @@ -920,6 +946,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) namespaceItem.reset(new _NamespaceModelItem(d->m_model, name)); setFileName(cursor, namespaceItem.data()); namespaceItem->setScope(d->m_scope); + namespaceItem->setType(type); parentNamespaceItem->addNamespace(namespaceItem); d->pushScope(namespaceItem); } diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h index fa79acb2a..dc37dff0f 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h @@ -44,6 +44,8 @@ public: Builder(); ~Builder(); + void setSystemIncludes(const QByteArrayList &systemIncludes); + bool visitLocation(const CXSourceLocation &location) const override; StartTokenResult startToken(const CXCursor &cursor) override; diff --git a/sources/shiboken2/ApiExtractor/graph.cpp b/sources/shiboken2/ApiExtractor/graph.cpp index 95a80197e..53e20ebba 100644 --- a/sources/shiboken2/ApiExtractor/graph.cpp +++ b/sources/shiboken2/ApiExtractor/graph.cpp @@ -101,7 +101,7 @@ bool Graph::containsEdge(int from, int to) void Graph::addEdge(int from, int to) { - Q_ASSERT(to < (int)m_d->edges.size()); + Q_ASSERT(to < m_d->edges.size()); m_d->edges[from].insert(to); } diff --git a/sources/shiboken2/ApiExtractor/include.cpp b/sources/shiboken2/ApiExtractor/include.cpp index d6a451992..82cb1d95b 100644 --- a/sources/shiboken2/ApiExtractor/include.cpp +++ b/sources/shiboken2/ApiExtractor/include.cpp @@ -49,7 +49,7 @@ uint qHash(const Include& inc) QTextStream& operator<<(QTextStream& out, const Include& include) { if (include.isValid()) - out << include.toString() << endl; + out << include.toString() << Qt::endl; return out; } diff --git a/sources/shiboken2/ApiExtractor/messages.cpp b/sources/shiboken2/ApiExtractor/messages.cpp index 546e9c4ed..0c29249d3 100644 --- a/sources/shiboken2/ApiExtractor/messages.cpp +++ b/sources/shiboken2/ApiExtractor/messages.cpp @@ -28,6 +28,7 @@ #include "messages.h" #include "abstractmetalang.h" +#include "typedatabase.h" #include "typesystem.h" #include <codemodel.h> @@ -130,6 +131,22 @@ QString msgNoEnumTypeConflict(const EnumModelItem &enumItem, return result; } +QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te) +{ + QString result = QLatin1String("Ambiguous types of varying types found for \"") + qualifiedName + + QLatin1String("\": "); + QDebug(&result) << te; + return result; +} + +QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te) +{ + QString result = QLatin1String("Ambiguous types found for \"") + qualifiedName + + QLatin1String("\": "); + QDebug(&result) << te; + return result; +} + QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n, const QString &why) { @@ -196,6 +213,23 @@ QString msgCannotFindTypeEntry(const QString &t) return QLatin1String("Cannot find type entry for \"") + t + QLatin1String("\"."); } +QString msgCannotFindTypeEntryForSmartPointer(const QString &t, const QString &smartPointerType) +{ + return QLatin1String("Cannot find type entry \"") + t + + QLatin1String("\" for instantiation of \"") + smartPointerType + QLatin1String("\"."); +} + +QString msgInvalidSmartPointerType(const TypeInfo &i) +{ + return QLatin1String("Invalid smart pointer type \"") + i.toString() + QLatin1String("\"."); +} + +QString msgCannotFindSmartPointerInstantion(const TypeInfo &i) +{ + return QLatin1String("Cannot find instantiation of smart pointer type for \"") + + i.toString() + QLatin1String("\"."); +} + QString msgCannotTranslateTemplateArgument(int i, const TypeInfo &typeInfo, const QString &why) @@ -334,8 +368,10 @@ QString msgCannotFindSmartPointer(const QString &instantiationType, QString result; QTextStream str(&result); str << "Unable to find smart pointer type for " << instantiationType << " (known types:"; - for (auto t : pointers) - str << ' ' << t->fullName(); + for (auto t : pointers) { + auto typeEntry = t->typeEntry(); + str << ' ' << typeEntry->targetLangName() << '/' << typeEntry->qualifiedCppName(); + } str << ")."; return result; } diff --git a/sources/shiboken2/ApiExtractor/messages.h b/sources/shiboken2/ApiExtractor/messages.h index 2b7b75ba0..321a4a538 100644 --- a/sources/shiboken2/ApiExtractor/messages.h +++ b/sources/shiboken2/ApiExtractor/messages.h @@ -59,6 +59,9 @@ QString msgNoEnumTypeConflict(const EnumModelItem &enumItem, const QString &className, const TypeEntry *t); +QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te); +QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te); + QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n, const QString &why); @@ -79,6 +82,10 @@ QString msgUnableToTranslateType(const TypeInfo &typeInfo, QString msgCannotFindTypeEntry(const QString &t); +QString msgCannotFindTypeEntryForSmartPointer(const QString &t, const QString &smartPointerType); +QString msgInvalidSmartPointerType(const TypeInfo &i); +QString msgCannotFindSmartPointerInstantion(const TypeInfo &i); + QString msgCannotTranslateTemplateArgument(int i, const TypeInfo &typeInfo, const QString &why); diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp index 099ab8860..892a20bb7 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp @@ -923,6 +923,16 @@ void _NamespaceModelItem::appendNamespace(const _NamespaceModelItem &other) void _NamespaceModelItem::formatDebug(QDebug &d) const { _ScopeModelItem::formatDebug(d); + switch (m_type) { + case NamespaceType::Default: + break; + case NamespaceType::Anonymous: + d << ", anonymous"; + break; + case NamespaceType::Inline: + d << ", inline"; + break; + } formatScopeList(d, ", namespaces=", m_namespaces); } #endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h index 80db2cce5..2e33d6cd0 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h @@ -438,6 +438,9 @@ public: const NamespaceList &namespaces() const { return m_namespaces; } + NamespaceType type() const { return m_type; } + void setType(NamespaceType t) { m_type = t; } + void addNamespace(NamespaceModelItem item); NamespaceModelItem findNamespace(const QString &name) const; @@ -450,6 +453,7 @@ public: private: NamespaceList m_namespaces; + NamespaceType m_type = NamespaceType::Default; }; class _FileModelItem: public _NamespaceModelItem diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h index 1713ba42f..aebd59879 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h @@ -54,4 +54,11 @@ enum class ExceptionSpecification Throws }; +enum class NamespaceType +{ + Default, + Anonymous, + Inline +}; + #endif // CODEMODEL_ENUMS_H diff --git a/sources/shiboken2/ApiExtractor/reporthandler.cpp b/sources/shiboken2/ApiExtractor/reporthandler.cpp index ee70a8e9b..63091cb54 100644 --- a/sources/shiboken2/ApiExtractor/reporthandler.cpp +++ b/sources/shiboken2/ApiExtractor/reporthandler.cpp @@ -35,7 +35,7 @@ #include <cstdarg> #include <cstdio> -#if _WINDOWS || NOCOLOR +#if defined(_WINDOWS) || defined(NOCOLOR) #define COLOR_END "" #define COLOR_WHITE "" #define COLOR_YELLOW "" diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index f393bf3bf..775ed2f81 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -144,6 +144,25 @@ IncludeList TypeDatabase::extraIncludes(const QString& className) const return typeEntry ? typeEntry->extraIncludes() : IncludeList(); } +void TypeDatabase::addSystemInclude(const QString &name) +{ + m_systemIncludes.append(name.toUtf8()); +} + +// Add a lookup for the short name excluding inline namespaces +// so that "std::shared_ptr" finds "std::__1::shared_ptr" as well. +// Note: This inserts duplicate TypeEntry * into m_entries. +void TypeDatabase::addInlineNamespaceLookups(const NamespaceTypeEntry *n) +{ + QVector<TypeEntry *> additionalEntries; // Store before modifying the hash + for (TypeEntry *entry : m_entries) { + if (entry->isChildOf(n)) + additionalEntries.append(entry); + } + for (const auto &ae : additionalEntries) + m_entries.insert(ae->shortName(), ae); +} + ContainerTypeEntry* TypeDatabase::findContainerType(const QString &name) const { QString template_name = name; @@ -166,7 +185,7 @@ static bool inline useType(const TypeEntry *t) FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry->type() == TypeEntry::FunctionType && useType(entry)) return static_cast<FunctionTypeEntry*>(entry); @@ -201,7 +220,7 @@ QString TypeDatabase::defaultPackageName() const TypeEntry* TypeDatabase::findType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (useType(entry)) return entry; @@ -209,7 +228,53 @@ TypeEntry* TypeDatabase::findType(const QString& name) const return nullptr; } -TypeEntryMultiMapConstIteratorRange TypeDatabase::findTypes(const QString &name) const +template <class Predicate> +TypeEntries TypeDatabase::findTypesHelper(const QString &name, Predicate pred) const +{ + TypeEntries result; + const auto entries = findTypeRange(name); + for (TypeEntry *entry : entries) { + if (pred(entry)) + result.append(entry); + } + return result; +} + +TypeEntries TypeDatabase::findTypes(const QString &name) const +{ + return findTypesHelper(name, useType); +} + +static bool useCppType(const TypeEntry *t) +{ + bool result = false; + switch (t->type()) { + case TypeEntry::PrimitiveType: + case TypeEntry::VoidType: + case TypeEntry::FlagsType: + case TypeEntry::EnumType: + case TypeEntry::TemplateArgumentType: + case TypeEntry::BasicValueType: + case TypeEntry::ContainerType: + case TypeEntry::ObjectType: + case TypeEntry::ArrayType: + case TypeEntry::CustomType: + case TypeEntry::SmartPointerType: + case TypeEntry::TypedefType: + result = useType(t); + break; + default: + break; + } + return result; +} + +TypeEntries TypeDatabase::findCppTypes(const QString &name) const +{ + return findTypesHelper(name, useCppType); +} + +TypeEntryMultiMapConstIteratorRange TypeDatabase::findTypeRange(const QString &name) const { const auto range = m_entries.equal_range(name); return {range.first, range.second}; @@ -322,11 +387,10 @@ TypeEntry *TypeDatabase::resolveTypeDefEntry(TypedefEntry *typedefEntry, if (lessThanPos != -1) sourceName.truncate(lessThanPos); ComplexTypeEntry *source = nullptr; - for (TypeEntry *e : findTypes(sourceName)) { + for (TypeEntry *e : findTypeRange(sourceName)) { switch (e->type()) { case TypeEntry::BasicValueType: case TypeEntry::ContainerType: - case TypeEntry::InterfaceType: case TypeEntry::ObjectType: case TypeEntry::SmartPointerType: source = dynamic_cast<ComplexTypeEntry *>(e); @@ -581,7 +645,7 @@ bool TypeDatabase::parseFile(QIODevice* device, bool generate) PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry->isPrimitive()) { auto *pe = static_cast<PrimitiveTypeEntry *>(entry); @@ -595,7 +659,7 @@ PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry->isComplex() && useType(entry)) return static_cast<ComplexTypeEntry*>(entry); @@ -605,7 +669,7 @@ ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry && entry->isObject() && useType(entry)) return static_cast<ObjectTypeEntry*>(entry); @@ -616,7 +680,7 @@ ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const NamespaceTypeEntryList TypeDatabase::findNamespaceTypes(const QString& name) const { NamespaceTypeEntryList result; - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry->isNamespace()) result.append(static_cast<NamespaceTypeEntry*>(entry)); @@ -698,6 +762,35 @@ static void _computeTypeIndexes() computeTypeIndexes = false; } +// Build the C++ name excluding any inline namespaces +// ("std::__1::shared_ptr" -> "std::shared_ptr" +QString TypeEntry::shortName() const +{ + if (m_cachedShortName.isEmpty()) { + QVarLengthArray<const TypeEntry *> parents; + bool foundInlineNamespace = false; + for (auto p = m_parent; p != nullptr && p->type() != TypeEntry::TypeSystemType; p = p->parent()) { + if (p->type() == TypeEntry::NamespaceType + && static_cast<const NamespaceTypeEntry *>(p)->isInlineNamespace()) { + foundInlineNamespace = true; + } else { + parents.append(p); + } + } + if (foundInlineNamespace) { + m_cachedShortName.reserve(m_name.size()); + for (int i = parents.size() - 1; i >= 0; --i) { + m_cachedShortName.append(parents.at(i)->entryName()); + m_cachedShortName.append(QLatin1String("::")); + } + m_cachedShortName.append(m_entryName); + } else { + m_cachedShortName = m_name; + } + } + return m_cachedShortName; +} + void TypeEntry::setRevision(int r) { if (m_revision != r) { @@ -794,7 +887,7 @@ void TypeEntry::formatDebug(QDebug &d) const if (m_name != cppName) d << "\", cppName=\"" << cppName << '"'; d << ", type=" << m_type << ", codeGeneration=0x" - << hex << m_codeGeneration << dec + << Qt::hex << m_codeGeneration << Qt::dec << ", target=\"" << targetLangName() << '"'; FORMAT_NONEMPTY_STRING("package", m_targetLangPackage) FORMAT_BOOL("stream", m_stream) @@ -849,6 +942,9 @@ void NamespaceTypeEntry::formatDebug(QDebug &d) const ComplexTypeEntry::formatDebug(d); auto pattern = m_filePattern.pattern(); FORMAT_NONEMPTY_STRING("pattern", pattern) + d << ",visibility=" << m_visibility; + if (m_inlineNamespace) + d << "[inline]"; } void ContainerTypeEntry::formatDebug(QDebug &d) const @@ -857,6 +953,17 @@ void ContainerTypeEntry::formatDebug(QDebug &d) const d << ", type=" << m_type << ",\"" << typeName() << '"'; } +void SmartPointerTypeEntry::formatDebug(QDebug &d) const +{ + ComplexTypeEntry::formatDebug(d); + if (!m_instantiations.isEmpty()) { + d << ", instantiations[" << m_instantiations.size() << "]=("; + for (auto i : m_instantiations) + d << i->name() << ','; + d << ')'; + } +} + QDebug operator<<(QDebug d, const TypeEntry *te) { QDebugStateSaver saver(d); diff --git a/sources/shiboken2/ApiExtractor/typedatabase.h b/sources/shiboken2/ApiExtractor/typedatabase.h index f615b623d..0a0a4eed5 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.h +++ b/sources/shiboken2/ApiExtractor/typedatabase.h @@ -96,6 +96,11 @@ public: IncludeList extraIncludes(const QString &className) const; + const QByteArrayList &systemIncludes() const { return m_systemIncludes; } + void addSystemInclude(const QString &name); + + void addInlineNamespaceLookups(const NamespaceTypeEntry *n); + PrimitiveTypeEntry *findPrimitiveType(const QString &name) const; ComplexTypeEntry *findComplexType(const QString &name) const; ObjectTypeEntry *findObjectType(const QString &name) const; @@ -108,6 +113,8 @@ public: QString defaultPackageName() const; TypeEntry *findType(const QString &name) const; + TypeEntries findTypes(const QString &name) const; + TypeEntries findCppTypes(const QString &name) const; const TypeEntryMultiMap &entries() const { return m_entries; } const TypedefEntryMap &typedefEntries() const { return m_typedefEntries; } @@ -179,11 +186,13 @@ public: void formatDebug(QDebug &d) const; #endif private: - TypeEntryMultiMapConstIteratorRange findTypes(const QString &name) const; + TypeEntryMultiMapConstIteratorRange findTypeRange(const QString &name) const; + template <class Predicate> + TypeEntries findTypesHelper(const QString &name, Predicate pred) const; TypeEntry *resolveTypeDefEntry(TypedefEntry *typedefEntry, QString *errorMessage); bool m_suppressWarnings = true; - TypeEntryMultiMap m_entries; + TypeEntryMultiMap m_entries; // Contains duplicate entries (cf addInlineNamespaceLookups). TypeEntryMap m_flagsEntries; TypedefEntryMap m_typedefEntries; TemplateEntryMap m_templates; @@ -201,6 +210,7 @@ private: QVector<TypeRejection> m_rejections; QStringList m_dropTypeEntries; + QByteArrayList m_systemIncludes; }; #ifndef QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index abd2bfb07..0ec158ae1 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -433,7 +433,7 @@ QDebug operator<<(QDebug d, const CodeSnip &s) void Modification::formatDebug(QDebug &d) const { - d << "modifiers=" << hex << showbase << modifiers << noshowbase << dec; + d << "modifiers=" << Qt::hex << Qt::showbase << modifiers << Qt::noshowbase << Qt::dec; if (removal) d << ", removal"; if (!renamedToName.isEmpty()) @@ -684,6 +684,15 @@ TypeEntry::~TypeEntry() delete m_customConversion; } +bool TypeEntry::isChildOf(const TypeEntry *p) const +{ + for (auto e = m_parent; e; e = e->parent()) { + if (e == p) + return true; + } + return false; +} + const TypeSystemTypeEntry *TypeEntry::typeSystemTypeEntry() const { for (auto e = this; e; e = e->parent()) { @@ -693,6 +702,16 @@ const TypeSystemTypeEntry *TypeEntry::typeSystemTypeEntry() const return nullptr; } +const TypeEntry *TypeEntry::targetLangEnclosingEntry() const +{ + auto result = m_parent; + while (result && result->type() != TypeEntry::TypeSystemType + && !NamespaceTypeEntry::isVisibleScope(result)) { + result = result->parent(); + } + return result; +} + QString TypeEntry::targetLangName() const { if (m_cachedTargetLangName.isEmpty()) @@ -704,11 +723,13 @@ QString TypeEntry::buildTargetLangName() const { QString result = m_entryName; for (auto p = parent(); p && p->type() != TypeEntry::TypeSystemType; p = p->parent()) { - if (!result.isEmpty()) - result.prepend(QLatin1Char('.')); - QString n = p->m_entryName; - n.replace(QLatin1String("::"), QLatin1String(".")); // Primitive types may have "std::" - result.prepend(n); + if (NamespaceTypeEntry::isVisibleScope(p)) { + if (!result.isEmpty()) + result.prepend(QLatin1Char('.')); + QString n = p->m_entryName; + n.replace(QLatin1String("::"), QLatin1String(".")); // Primitive types may have "std::" + result.prepend(n); + } } return result; } @@ -752,6 +773,8 @@ TypeEntry *TypeEntry::clone() const // Take over parameters relevant for typedefs void TypeEntry::useAsTypedef(const TypeEntry *source) { + // XML Typedefs are in the global namespace for now. + m_parent = source->typeSystemTypeEntry(); m_entryName = source->m_entryName; m_name = source->m_name; m_targetLangPackage = source->m_targetLangPackage; @@ -933,6 +956,11 @@ TypeEntry *SmartPointerTypeEntry::clone() const SmartPointerTypeEntry::SmartPointerTypeEntry(const SmartPointerTypeEntry &) = default; +bool SmartPointerTypeEntry::matchesInstantiation(const TypeEntry *e) const +{ + return m_instantiations.isEmpty() || m_instantiations.contains(e); +} + NamespaceTypeEntry::NamespaceTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) : ComplexTypeEntry(entryName, NamespaceType, vr, parent) @@ -959,6 +987,18 @@ bool NamespaceTypeEntry::matchesFile(const QString &needle) const return m_filePattern.match(needle).hasMatch(); } +bool NamespaceTypeEntry::isVisible() const +{ + return m_visibility == TypeSystem::Visibility::Visible + || (m_visibility == TypeSystem::Visibility::Auto && !m_inlineNamespace); +} + +bool NamespaceTypeEntry::isVisibleScope(const TypeEntry *e) +{ + return e->type() != TypeEntry::NamespaceType + || static_cast<const NamespaceTypeEntry *>(e)->isVisible(); +} + ValueTypeEntry::ValueTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) : ComplexTypeEntry(entryName, BasicValueType, vr, parent) @@ -970,11 +1010,6 @@ bool ValueTypeEntry::isValue() const return true; } -bool ValueTypeEntry::isNativeIdBased() const -{ - return true; -} - TypeEntry *ValueTypeEntry::clone() const { return new ValueTypeEntry(*this); @@ -1122,30 +1157,6 @@ void CustomConversion::TargetToNativeConversion::setConversion(const QString& co m_d->conversion = conversion; } -InterfaceTypeEntry::InterfaceTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent) : - ComplexTypeEntry(entryName, InterfaceType, vr, parent) -{ -} - -bool InterfaceTypeEntry::isNativeIdBased() const -{ - return true; -} - -QString InterfaceTypeEntry::qualifiedCppName() const -{ - const int len = ComplexTypeEntry::qualifiedCppName().length() - interfaceName(QString()).length(); - return ComplexTypeEntry::qualifiedCppName().left(len); -} - -TypeEntry *InterfaceTypeEntry::clone() const -{ - return new InterfaceTypeEntry(*this); -} - -InterfaceTypeEntry::InterfaceTypeEntry(const InterfaceTypeEntry &) = default; - FunctionTypeEntry::FunctionTypeEntry(const QString &entryName, const QString &signature, const QVersionNumber &vr, const TypeEntry *parent) : @@ -1167,16 +1178,6 @@ ObjectTypeEntry::ObjectTypeEntry(const QString &entryName, const QVersionNumber { } -InterfaceTypeEntry *ObjectTypeEntry::designatedInterface() const -{ - return m_interface; -} - -bool ObjectTypeEntry::isNativeIdBased() const -{ - return true; -} - TypeEntry *ObjectTypeEntry::clone() const { return new ObjectTypeEntry(*this); diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index 8d8d60f3f..2324e8b78 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -228,7 +228,7 @@ struct ArgumentModification struct Modification { - enum Modifiers { + enum Modifiers : uint { InvalidModifier = 0x0000, Private = 0x0001, Protected = 0x0002, @@ -499,7 +499,6 @@ QDebug operator<<(QDebug d, const AddedFunction::Argument &a); QDebug operator<<(QDebug d, const AddedFunction &af); #endif -class InterfaceTypeEntry; class ObjectTypeEntry; class DocModification @@ -562,20 +561,13 @@ public: EnumValue, ConstantValueType, TemplateArgumentType, - ThreadType, BasicValueType, - StringType, ContainerType, - InterfaceType, ObjectType, NamespaceType, - VariantType, - JObjectWrapperType, - CharType, ArrayType, TypeSystemType, CustomType, - TargetLangType, FunctionType, SmartPointerType, TypedefType @@ -605,7 +597,10 @@ public: const TypeEntry *parent() const { return m_parent; } void setParent(const TypeEntry *p) { m_parent = p; } + bool isChildOf(const TypeEntry *p) const; const TypeSystemTypeEntry *typeSystemTypeEntry() const; + // cf AbstractMetaClass::targetLangEnclosingClass() + const TypeEntry *targetLangEnclosingEntry() const; bool isPrimitive() const { @@ -619,22 +614,10 @@ public: { return m_type == FlagsType; } - bool isInterface() const - { - return m_type == InterfaceType; - } bool isObject() const { return m_type == ObjectType; } - bool isString() const - { - return m_type == StringType; - } - bool isChar() const - { - return m_type == CharType; - } bool isNamespace() const { return m_type == NamespaceType; @@ -647,14 +630,6 @@ public: { return m_type == SmartPointerType; } - bool isVariant() const - { - return m_type == VariantType; - } - bool isJObjectWrapper() const - { - return m_type == JObjectWrapperType; - } bool isArray() const { return m_type == ArrayType; @@ -671,18 +646,10 @@ public: { return m_type == VarargsType; } - bool isThread() const - { - return m_type == ThreadType; - } bool isCustom() const { return m_type == CustomType; } - bool isBasicValue() const - { - return m_type == BasicValueType; - } bool isTypeSystem() const { return m_type == TypeSystemType; @@ -708,6 +675,8 @@ public: // The type's name in C++, fully qualified QString name() const { return m_name; } + // C++ excluding inline namespaces + QString shortName() const; // Name as specified in XML QString entryName() const { return m_entryName; } @@ -766,11 +735,6 @@ public: QString qualifiedTargetLangName() const; - virtual InterfaceTypeEntry *designatedInterface() const - { - return nullptr; - } - void setCustomConstructor(const CustomFunction &func) { m_customConstructor = func; @@ -798,11 +762,6 @@ public: return false; } - virtual bool isNativeIdBased() const - { - return false; - } - CodeSnipList codeSnips() const; void setCodeSnips(const CodeSnipList &codeSnips) { @@ -896,7 +855,8 @@ protected: private: const TypeEntry *m_parent; - QString m_name; // fully qualified + QString m_name; // C++ fully qualified + mutable QString m_cachedShortName; // C++ excluding inline namespaces QString m_entryName; QString m_targetLangPackage; mutable QString m_cachedTargetLangName; // "Foo.Bar" @@ -1490,6 +1450,8 @@ private: class SmartPointerTypeEntry : public ComplexTypeEntry { public: + using Instantiations = QVector<const TypeEntry *>; + explicit SmartPointerTypeEntry(const QString &entryName, const QString &getterName, const QString &smartPointerType, @@ -1509,6 +1471,13 @@ public: TypeEntry *clone() const override; + Instantiations instantiations() const { return m_instantiations; } + void setInstantiations(const Instantiations &i) { m_instantiations = i; } + bool matchesInstantiation(const TypeEntry *e) const; + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const override; +#endif protected: SmartPointerTypeEntry(const SmartPointerTypeEntry &); @@ -1516,6 +1485,7 @@ private: QString m_getterName; QString m_smartPointerType; QString m_refCountMethodName; + Instantiations m_instantiations; }; class NamespaceTypeEntry : public ComplexTypeEntry @@ -1536,6 +1506,15 @@ public: bool matchesFile(const QString &needle) const; + bool isVisible() const; + void setVisibility(TypeSystem::Visibility v) { m_visibility = v; } + + // C++ 11 inline namespace, from code model + bool isInlineNamespace() const { return m_inlineNamespace; } + void setInlineNamespace(bool i) { m_inlineNamespace = i; } + + static bool isVisibleScope(const TypeEntry *e); + #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; #endif @@ -1546,7 +1525,9 @@ protected: private: QRegularExpression m_filePattern; const NamespaceTypeEntry *m_extends = nullptr; + TypeSystem::Visibility m_visibility = TypeSystem::Visibility::Auto; bool m_hasPattern = false; + bool m_inlineNamespace = false; }; class ValueTypeEntry : public ComplexTypeEntry @@ -1557,8 +1538,6 @@ public: bool isValue() const override; - bool isNativeIdBased() const override; - TypeEntry *clone() const override; protected: @@ -1567,39 +1546,6 @@ protected: ValueTypeEntry(const ValueTypeEntry &); }; -class InterfaceTypeEntry : public ComplexTypeEntry -{ -public: - explicit InterfaceTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent); - - static QString interfaceName(const QString &name) - { - return name + QLatin1String("Interface"); - } - - ObjectTypeEntry *origin() const - { - return m_origin; - } - void setOrigin(ObjectTypeEntry *origin) - { - m_origin = origin; - } - - bool isNativeIdBased() const override; - QString qualifiedCppName() const override; - - TypeEntry *clone() const override; - -protected: - InterfaceTypeEntry(const InterfaceTypeEntry &); - -private: - ObjectTypeEntry *m_origin = nullptr; -}; - - class FunctionTypeEntry : public TypeEntry { public: @@ -1636,21 +1582,10 @@ public: explicit ObjectTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent); - InterfaceTypeEntry *designatedInterface() const override; - void setDesignatedInterface(InterfaceTypeEntry *entry) - { - m_interface = entry; - } - - bool isNativeIdBased() const override; - TypeEntry *clone() const override; protected: ObjectTypeEntry(const ObjectTypeEntry &); - -private: - InterfaceTypeEntry *m_interface = nullptr; }; struct TypeRejection diff --git a/sources/shiboken2/ApiExtractor/typesystem_enums.h b/sources/shiboken2/ApiExtractor/typesystem_enums.h index df83429d0..120c9417f 100644 --- a/sources/shiboken2/ApiExtractor/typesystem_enums.h +++ b/sources/shiboken2/ApiExtractor/typesystem_enums.h @@ -98,6 +98,13 @@ enum class ExceptionHandling { On }; +enum Visibility { // For namespaces + Unspecified, + Visible, + Invisible, + Auto +}; + } // namespace TypeSystem #endif // TYPESYSTEM_ENUMS_H diff --git a/sources/shiboken2/ApiExtractor/typesystem_typedefs.h b/sources/shiboken2/ApiExtractor/typesystem_typedefs.h index fd702793e..73f92b294 100644 --- a/sources/shiboken2/ApiExtractor/typesystem_typedefs.h +++ b/sources/shiboken2/ApiExtractor/typesystem_typedefs.h @@ -40,6 +40,7 @@ class DocModification; struct AddedFunction; struct FieldModification; struct FunctionModification; +class TypeEntry; using AddedFunctionPtr = QSharedPointer<AddedFunction>; using AddedFunctionList = QVector<AddedFunctionPtr>; @@ -47,5 +48,6 @@ using CodeSnipList = QVector<CodeSnip>; using DocModificationList = QVector<DocModification>; using FieldModificationList = QVector<FieldModification>; using FunctionModificationList = QVector<FunctionModification>; +using TypeEntries = QVector<const TypeEntry *>; #endif // TYPESYSTEM_TYPEDEFS_H diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.cpp b/sources/shiboken2/ApiExtractor/typesystemparser.cpp index 5252ac00a..efdab8be3 100644 --- a/sources/shiboken2/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken2/ApiExtractor/typesystemparser.cpp @@ -63,6 +63,7 @@ static inline QString deprecatedAttribute() { return QStringLiteral("deprecated" static inline QString noOverrideCachingAttribute() { return QStringLiteral("no-override-caching"); } static inline QString exceptionHandlingAttribute() { return QStringLiteral("exception-handling"); } static inline QString extensibleAttribute() { return QStringLiteral("extensible"); } +static inline QString fileNameAttribute() { return QStringLiteral("file-name"); } static inline QString flagsAttribute() { return QStringLiteral("flags"); } static inline QString forceAbstractAttribute() { return QStringLiteral("force-abstract"); } static inline QString forceIntegerAttribute() { return QStringLiteral("force-integer"); } @@ -95,6 +96,7 @@ static inline QString sourceAttribute() { return QStringLiteral("source"); } static inline QString streamAttribute() { return QStringLiteral("stream"); } static inline QString xPathAttribute() { return QStringLiteral("xpath"); } static inline QString virtualSlotAttribute() { return QStringLiteral("virtual-slot"); } +static inline QString visibleAttribute() { return QStringLiteral("visible"); } static inline QString enumIdentifiedByValueAttribute() { return QStringLiteral("identified-by-value"); } static inline QString noAttributeValue() { return QStringLiteral("no"); } @@ -383,6 +385,7 @@ ENUM_LOOKUP_BEGIN(StackElement::ElementType, Qt::CaseInsensitive, {u"replace-type", StackElement::ReplaceType}, {u"smart-pointer-type", StackElement::SmartPointerTypeEntry}, {u"suppress-warning", StackElement::SuppressedWarning}, + {u"system-include", StackElement::SystemInclude}, {u"target-to-native", StackElement::TargetToNative}, {u"template", StackElement::Template}, {u"typedef-type", StackElement::TypedefTypeEntry}, @@ -391,6 +394,17 @@ ENUM_LOOKUP_BEGIN(StackElement::ElementType, Qt::CaseInsensitive, }; ENUM_LOOKUP_BINARY_SEARCH() +ENUM_LOOKUP_BEGIN(TypeSystem::Visibility, Qt::CaseSensitive, + visibilityFromAttribute, TypeSystem::Visibility::Unspecified) +{ + {u"no", TypeSystem::Visibility::Invisible}, + {u"false", TypeSystem::Visibility::Invisible}, + {u"auto", TypeSystem::Visibility::Auto}, + {u"yes", TypeSystem::Visibility::Visible}, + {u"true", TypeSystem::Visibility::Visible}, +}; +ENUM_LOOKUP_LINEAR_SEARCH() + static int indexOfAttribute(const QXmlStreamAttributes &atts, QStringView name) { @@ -637,6 +651,14 @@ bool TypeSystemParser::parse(QXmlStreamReader &reader) { m_error.clear(); m_currentPath.clear(); + m_smartPointerInstantiations.clear(); + const bool result = parseXml(reader) && setupSmartPointerInstantiations(); + m_smartPointerInstantiations.clear(); + return result; +} + +bool TypeSystemParser::parseXml(QXmlStreamReader &reader) +{ const QString fileName = readerFileName(reader); if (!fileName.isEmpty()) m_currentPath = QFileInfo(fileName).absolutePath(); @@ -680,6 +702,62 @@ bool TypeSystemParser::parse(QXmlStreamReader &reader) return true; } +// Split a type list potentially with template types +// "A<B,C>,D" -> ("A<B,C>", "D") +static QStringList splitTypeList(const QString &s) +{ + QStringList result; + int templateDepth = 0; + int lastPos = 0; + const int size = s.size(); + for (int i = 0; i < size; ++i) { + switch (s.at(i).toLatin1()) { + case '<': + ++templateDepth; + break; + case '>': + --templateDepth; + break; + case ',': + if (templateDepth == 0) { + result.append(s.mid(lastPos, i - lastPos).trimmed()); + lastPos = i + 1; + } + break; + } + } + if (lastPos < size) + result.append(s.mid(lastPos, size - lastPos).trimmed()); + return result; +} + +bool TypeSystemParser::setupSmartPointerInstantiations() +{ + for (auto it = m_smartPointerInstantiations.cbegin(), + end = m_smartPointerInstantiations.cend(); it != end; ++it) { + auto smartPointerEntry = it.key(); + const auto instantiationNames = splitTypeList(it.value()); + SmartPointerTypeEntry::Instantiations instantiations; + instantiations.reserve(instantiationNames.size()); + for (const auto &instantiationName : instantiationNames) { + const auto types = m_database->findCppTypes(instantiationName); + if (types.isEmpty()) { + m_error = + msgCannotFindTypeEntryForSmartPointer(instantiationName, + smartPointerEntry->name()); + return false; + } + if (types.size() > 1) { + m_error = msgAmbiguousTypesFound(instantiationName, types); + return false; + } + instantiations.append(types.constFirst()); + } + smartPointerEntry->setInstantiations(instantiations); + } + return true; +} + bool TypeSystemParser::endElement(const QStringRef &localName) { if (m_ignoreDepth) { @@ -727,11 +805,6 @@ bool TypeSystemParser::endElement(const QStringRef &localName) centry->setFieldModifications(m_contextStack.top()->fieldMods); centry->setCodeSnips(m_contextStack.top()->codeSnips); centry->setDocModification(m_contextStack.top()->docModifications); - - if (centry->designatedInterface()) { - centry->designatedInterface()->setCodeSnips(m_contextStack.top()->codeSnips); - centry->designatedInterface()->setFunctionModifications(m_contextStack.top()->functionMods); - } } break; case StackElement::AddFunction: { @@ -814,7 +887,7 @@ bool TypeSystemParser::endElement(const QStringRef &localName) break; default: break; // nada - }; + } break; default: break; @@ -890,7 +963,7 @@ bool TypeSystemParser::characters(const String &ch) break; default: Q_ASSERT(false); - }; + } return true; } } @@ -1122,6 +1195,7 @@ SmartPointerTypeEntry * QString smartPointerType; QString getter; QString refCountMethodName; + QString instantiations; for (int i = attributes->size() - 1; i >= 0; --i) { const QStringRef name = attributes->at(i).qualifiedName(); if (name == QLatin1String("type")) { @@ -1130,6 +1204,8 @@ SmartPointerTypeEntry * getter = attributes->takeAt(i).value().toString(); } else if (name == QLatin1String("ref-count-method")) { refCountMethodName = attributes->takeAt(i).value().toString(); + } else if (name == QLatin1String("instantiations")) { + instantiations = attributes->takeAt(i).value().toString(); } } @@ -1164,6 +1240,7 @@ SmartPointerTypeEntry * auto *type = new SmartPointerTypeEntry(name, getter, smartPointerType, refCountMethodName, since, currentParentTypeEntry()); applyCommonAttributes(type, attributes); + m_smartPointerInstantiations.insert(type, instantiations); return type; } @@ -1263,40 +1340,6 @@ EnumTypeEntry * return entry; } -ObjectTypeEntry * - TypeSystemParser::parseInterfaceTypeEntry(const QXmlStreamReader &, - const QString &name, const QVersionNumber &since, - QXmlStreamAttributes *attributes) -{ - if (!checkRootElement()) - return nullptr; - auto *otype = new ObjectTypeEntry(name, since, currentParentTypeEntry()); - applyCommonAttributes(otype, attributes); - QString targetLangName = name; - bool generate = true; - for (int i = attributes->size() - 1; i >= 0; --i) { - const QStringRef name = attributes->at(i).qualifiedName(); - if (name == targetLangNameAttribute()) { - targetLangName = attributes->takeAt(i).value().toString(); - } else if (name == generateAttribute()) { - generate = convertBoolean(attributes->takeAt(i).value(), - generateAttribute(), true); - } - } - - auto itype = new InterfaceTypeEntry(InterfaceTypeEntry::interfaceName(targetLangName), - since, currentParentTypeEntry()); - itype->setTargetLangName(targetLangName); - - if (generate) - itype->setCodeGeneration(m_generate); - else - itype->setCodeGeneration(TypeEntry::GenerateForSubclass); - - otype->setDesignatedInterface(itype); - itype->setOrigin(otype); - return otype; -} NamespaceTypeEntry * TypeSystemParser::parseNamespaceTypeEntry(const QXmlStreamReader &reader, @@ -1306,8 +1349,8 @@ NamespaceTypeEntry * if (!checkRootElement()) return nullptr; QScopedPointer<NamespaceTypeEntry> result(new NamespaceTypeEntry(name, since, currentParentTypeEntry())); + auto visibility = TypeSystem::Visibility::Unspecified; applyCommonAttributes(result.data(), attributes); - applyComplexTypeAttributes(reader, result.data(), attributes); for (int i = attributes->size() - 1; i >= 0; --i) { const QStringRef attributeName = attributes->at(i).qualifiedName(); if (attributeName == QLatin1String("files")) { @@ -1330,9 +1373,24 @@ NamespaceTypeEntry * return nullptr; } result->setExtends(*extendsIt); + } else if (attributeName == visibleAttribute()) { + const auto attribute = attributes->takeAt(i); + visibility = visibilityFromAttribute(attribute.value()); + if (visibility == TypeSystem::Visibility::Unspecified) { + qCWarning(lcShiboken, "%s", + qPrintable(msgInvalidAttributeValue(attribute))); + } + } else if (attributeName == generateAttribute()) { + if (!convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true)) + visibility = TypeSystem::Visibility::Invisible; } } + if (visibility != TypeSystem::Visibility::Unspecified) + result->setVisibility(visibility); + // Handle legacy "generate" before the common handling + applyComplexTypeAttributes(reader, result.data(), attributes); + if (result->extends() && !result->hasPattern()) { m_error = msgExtendingNamespaceRequiresPattern(name); return nullptr; @@ -1497,9 +1555,6 @@ void TypeSystemParser::applyComplexTypeAttributes(const QXmlStreamReader &reader if (ctype->type() != TypeEntry::ContainerType) ctype->setTargetLangPackage(package); - if (InterfaceTypeEntry *di = ctype->designatedInterface()) - di->setTargetLangPackage(package); - if (generate) ctype->setCodeGeneration(m_generate); else @@ -2514,7 +2569,7 @@ bool TypeSystemParser::parseInclude(const QXmlStreamReader &, QString location; for (int i = attributes->size() - 1; i >= 0; --i) { const QStringRef name = attributes->at(i).qualifiedName(); - if (name == QLatin1String("file-name")) + if (name == fileNameAttribute()) fileName = attributes->takeAt(i).value().toString(); else if (name == locationAttribute()) location = attributes->takeAt(i).value().toString(); @@ -2535,10 +2590,18 @@ bool TypeSystemParser::parseInclude(const QXmlStreamReader &, m_error = QLatin1String("Only supported parent tags are primitive-type, complex types or extra-includes"); return false; } - if (InterfaceTypeEntry *di = entry->designatedInterface()) { - di->setInclude(entry->include()); - di->setExtraIncludes(entry->extraIncludes()); + return true; +} + +bool TypeSystemParser::parseSystemInclude(const QXmlStreamReader &, + QXmlStreamAttributes *attributes) +{ + const int index = indexOfAttribute(*attributes, fileNameAttribute()); + if (index == -1) { + m_error = msgMissingAttribute(fileNameAttribute()); + return false; } + TypeDatabase::instance()->addSystemInclude(attributes->takeAt(index).value().toString()); return true; } @@ -2776,14 +2839,6 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) element->entry = m_currentEnum; break; - case StackElement::InterfaceTypeEntry: - if (ObjectTypeEntry *oe = parseInterfaceTypeEntry(reader, name, versionRange.since, &attributes)) { - applyComplexTypeAttributes(reader, oe, &attributes); - element->entry = oe; - } else { - return false; - } - break; case StackElement::ValueTypeEntry: if (ValueTypeEntry *ve = parseValueTypeEntry(reader, name, versionRange.since, &attributes)) { applyComplexTypeAttributes(reader, ve, &attributes); @@ -2799,6 +2854,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) return false; break; case StackElement::ObjectTypeEntry: + case StackElement::InterfaceTypeEntry: if (!checkRootElement()) return false; element->entry = new ObjectTypeEntry(name, versionRange.since, currentParentTypeEntry()); @@ -2820,7 +2876,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) break; default: Q_ASSERT(false); - }; + } if (element->entry) { if (!m_database->addType(element->entry, &m_error)) @@ -2843,6 +2899,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) || element->type == StackElement::LoadTypesystem || element->type == StackElement::InjectCode || element->type == StackElement::ExtraIncludes + || element->type == StackElement::SystemInclude || element->type == StackElement::ConversionRule || element->type == StackElement::AddFunction || element->type == StackElement::Template; @@ -2995,6 +3052,10 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) if (!addRejection(m_database, &attributes, &m_error)) return false; break; + case StackElement::SystemInclude: + if (!parseSystemInclude(reader, &attributes)) + return false; + break; case StackElement::Template: { const int nameIndex = indexOfAttribute(attributes, nameAttribute()); if (nameIndex == -1) { diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.h b/sources/shiboken2/ApiExtractor/typesystemparser.h index d3ea54fc6..b4be2765c 100644 --- a/sources/shiboken2/ApiExtractor/typesystemparser.h +++ b/sources/shiboken2/ApiExtractor/typesystemparser.h @@ -31,6 +31,7 @@ #include "typesystem.h" #include <QtCore/QStack> +#include <QtCore/QHash> #include <QtCore/QScopedPointer> QT_FORWARD_DECLARE_CLASS(QXmlStreamAttributes) @@ -86,6 +87,7 @@ class StackElement NativeToTarget = 0x1100, TargetToNative = 0x1200, AddConversion = 0x1300, + SystemInclude = 0x1400, SimpleMask = 0x3f00, // Code snip tags (0x1000, 0x2000, ... , 0xf000) @@ -151,6 +153,8 @@ public: QString errorString() const { return m_error; } private: + bool parseXml(QXmlStreamReader &reader); + bool setupSmartPointerInstantiations(); bool startElement(const QXmlStreamReader &reader); SmartPointerTypeEntry *parseSmartPointerEntry(const QXmlStreamReader &, const QString &name, @@ -184,9 +188,6 @@ private: const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes); - ObjectTypeEntry * - parseInterfaceTypeEntry(const QXmlStreamReader &, const QString &name, - const QVersionNumber &since, QXmlStreamAttributes *); ValueTypeEntry * parseValueTypeEntry(const QXmlStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *); @@ -247,6 +248,7 @@ private: StackElement* element, QXmlStreamAttributes *); bool parseInclude(const QXmlStreamReader &, const StackElement &topElement, TypeEntry *entry, QXmlStreamAttributes *); + bool parseSystemInclude(const QXmlStreamReader &, QXmlStreamAttributes *); TemplateInstance *parseTemplateInstanceEnum(const QXmlStreamReader &, const StackElement &topElement, QXmlStreamAttributes *); @@ -271,6 +273,7 @@ private: QString m_currentSignature; QString m_currentPath; QScopedPointer<TypeSystemEntityResolver> m_entityResolver; + QHash<SmartPointerTypeEntry *, QString> m_smartPointerInstantiations; }; #endif // TYPESYSTEMPARSER_H diff --git a/sources/shiboken2/doc/typesystem_specifying_types.rst b/sources/shiboken2/doc/typesystem_specifying_types.rst index 3ab6adbd6..d296ccc80 100644 --- a/sources/shiboken2/doc/typesystem_specifying_types.rst +++ b/sources/shiboken2/doc/typesystem_specifying_types.rst @@ -153,6 +153,7 @@ namespace-type <typesystem> <namespace-type name="..." + visible="true | auto | false" generate="yes | no" package="..." since="..." @@ -161,8 +162,16 @@ namespace-type The **name** attribute is the name of the namespace, e.g., "Qt". - The *optional* **generate** attribute is used to inform if you need to prepend - the given namespace into each generated class. Its default value is **yes**. + The *optional* **visible** attribute is used specify whether the + namespace is visible in the target language name. Its default value is + **auto**. It means that normal namespaces are visible, but inline namespaces + (as introduced in C++ 11) will not be visible. + + The detection of inline namespaces requires shiboken to be built + using LLVM 9.0. + + The *optional* **generate** is a legacy attribute. Specifying + **no** is equivalent to **visible="false"**. The **package** attribute can be used to override the package of the type system. @@ -331,30 +340,7 @@ object-type interface-type ^^^^^^^^^^^^^^ - The interface-type node indicates that the given class is replaced by an - interface pattern when mapping from C++ to the target language. Using the - interface-type node implicitly makes the given type an :ref:`object-type`. - - .. code-block:: xml - - <typesystem> - <interface-type name="..." - since="..." - package ="..." - default-superclass ="..." - revision="..." /> - </typesystem> - - The **name** attribute is the fully qualified C++ class name. The *optional* - **package** attribute can be used to override the package of the type system. - If there is no C++ base class, the *optional* **default-superclass** attribute - can be used to specify a superclass in the generated target language API, for - the given class. - - The *optional* **since** value is used to specify the API version of this interface. - - The **revision** attribute can be used to specify a revision for each type, easing the - production of ABI compatible bindings. + This type is deprecated and no longer has any effect. Use object-type instead. .. _container-type: @@ -441,6 +427,14 @@ smart-pointer-type to function return values. **ref-count-method** specifies the name of the method used to do reference counting. + The *optional* attribute **instantiations** specifies for which instantiations + of the smart pointer wrappers will be generated (comma-separated list). + By default, this will happen for all instantiations found by code parsing. + This might be a problem when linking different modules, since wrappers for the + same instantiation might be generated into different modules, which then clash. + Providing an instantiations list makes it possible to specify which wrappers + will be generated into specific modules. + .. code-block:: xml <typesystem> @@ -448,7 +442,8 @@ smart-pointer-type since="..." type="..." getter="..." - ref-count-method="..."/> + ref-count-method="..." + instantiations="..."/> </typesystem> .. _function: @@ -472,3 +467,18 @@ function The function tag has two *optional* attributes: **since**, whose value is used to specify the API version of this function, and **rename**, to modify the function name. +.. _system_include: + +system-include +^^^^^^^^^^^^^^ + + The optional **system-include** specifies the name of a system include + file to be parsed. Normally, include files considered to be system + include files are skipped by the C++ code parser. Its primary use case + is exposing classes from the STL library. + + .. code-block:: xml + + <typesystem> + <system-include file-name="memory"/> + </typesystem> diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp index 484b1f641..3cc625488 100644 --- a/sources/shiboken2/generator/generator.cpp +++ b/sources/shiboken2/generator/generator.cpp @@ -159,7 +159,6 @@ struct Generator::GeneratorPrivate QString licenseComment; QString moduleName; QStringList instantiatedContainersNames; - QStringList instantiatedSmartPointerNames; QVector<const AbstractMetaType *> instantiatedContainers; QVector<const AbstractMetaType *> instantiatedSmartPointers; @@ -211,6 +210,31 @@ QString Generator::getSimplifiedContainerTypeName(const AbstractMetaType *type) 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) { @@ -244,18 +268,15 @@ void Generator::addInstantiatedContainersAndSmartPointers(const AbstractMetaType m_d->instantiatedContainers.append(type); } } else { - // Is smart pointer. - if (!m_d->instantiatedSmartPointerNames.contains(typeName)) { - m_d->instantiatedSmartPointerNames.append(typeName); - if (type->isConstant() || type->referenceType() != NoReference) { - // Strip a "const QSharedPtr<Foo> &" or similar to "QSharedPtr<Foo>" (PYSIDE-1016) - auto fixedType = type->copy(); - fixedType->setReferenceType(NoReference); - fixedType->setConstant(false); - type = fixedType; - } - m_d->instantiatedSmartPointers.append(type); - } + // 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)); } } @@ -449,7 +470,8 @@ bool Generator::generate() bool Generator::shouldGenerateTypeEntry(const TypeEntry *type) const { - return type->codeGeneration() & TypeEntry::GenerateTargetLang; + return (type->codeGeneration() & TypeEntry::GenerateTargetLang) + && NamespaceTypeEntry::isVisibleScope(type); } bool Generator::shouldGenerate(const AbstractMetaClass *metaClass) const @@ -529,7 +551,7 @@ QTextStream &formatCode(QTextStream &s, const QString &code, Indentor &indentor) s << indentor << line.remove(0, limit); } - s << endl; + s << Qt::endl; } return s; } @@ -670,6 +692,9 @@ DefaultValue Generator::minimalConstructor(const AbstractMetaType *type) const 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()) @@ -724,6 +749,9 @@ DefaultValue Generator::minimalConstructor(const TypeEntry *type) const : DefaultValue(DefaultValue::Custom, ctor); } + if (type->isSmartPointer()) + return DefaultValue(DefaultValue::DefaultConstructor, type->qualifiedCppName()); + if (type->isComplex()) return minimalConstructor(AbstractMetaClass::findClass(classes(), type)); @@ -893,8 +921,12 @@ static QString getClassTargetFullName_(const T *t, bool includePackageName) QString name = t->name(); const AbstractMetaClass *context = t->enclosingClass(); while (context) { - name.prepend(QLatin1Char('.')); - name.prepend(context->name()); + // 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) { diff --git a/sources/shiboken2/generator/main.cpp b/sources/shiboken2/generator/main.cpp index 700dc00bb..e4d86f489 100644 --- a/sources/shiboken2/generator/main.cpp +++ b/sources/shiboken2/generator/main.cpp @@ -73,11 +73,11 @@ static void printOptions(QTextStream &s, const OptionDescriptions &options) if (od.second.isEmpty()) { s << ", "; } else { - s << endl; + s << Qt::endl; const auto lines = od.second.splitRef(QLatin1Char('\n')); for (const auto &line : lines) - s << " " << line << endl; - s << endl; + s << " " << line << Qt::endl; + s << Qt::endl; } } } @@ -343,7 +343,7 @@ void printUsage() for (const GeneratorPtr &generator : generators) { const OptionDescriptions options = generator->options(); if (!options.isEmpty()) { - s << endl << generator->name() << " options:\n\n"; + s << Qt::endl << generator->name() << " options:\n\n"; printOptions(s, generator->options()); } } diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp index f4efc293f..40cc255f0 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp @@ -172,7 +172,7 @@ static QChar lastChar(const QTextStream &str) static QTextStream &ensureEndl(QTextStream &s) { if (lastChar(s) != QLatin1Char('\n')) - s << endl; + s << Qt::endl; return s; } @@ -502,10 +502,10 @@ QString QtXmlToSphinx::transform(const QString& doc) if (!m_inlineImages.isEmpty()) { // Write out inline image definitions stored in handleInlineImageTag(). - m_output << endl; + m_output << Qt::endl; for (const InlineImage &img : qAsConst(m_inlineImages)) - m_output << ".. |" << img.tag << "| image:: " << img.href << endl; - m_output << endl; + m_output << ".. |" << img.tag << "| image:: " << img.href << Qt::endl; + m_output << Qt::endl; m_inlineImages.clear(); } @@ -608,11 +608,11 @@ void QtXmlToSphinx::handleHeadingTag(QXmlStreamReader& reader) else type = types[typeIdx]; } else if (token == QXmlStreamReader::EndElement) { - m_output << Pad(type, headingSize) << endl << endl; + m_output << Pad(type, headingSize) << Qt::endl << Qt::endl; } else if (token == QXmlStreamReader::Characters) { - m_output << endl << endl; + m_output << Qt::endl << Qt::endl; headingSize = writeEscapedRstText(m_output, reader.text().trimmed()); - m_output << endl; + m_output << Qt::endl; } } @@ -628,7 +628,7 @@ void QtXmlToSphinx::handleParaTag(QXmlStreamReader& reader) else if (result.startsWith(QLatin1String("**Note:**"))) result.replace(0, 9, QLatin1String(".. note:: ")); - m_output << INDENT << result << endl << endl; + m_output << INDENT << result << Qt::endl << Qt::endl; } else if (token == QXmlStreamReader::Characters) { const QStringRef text = reader.text(); const QChar end = lastChar(m_output); @@ -726,7 +726,7 @@ void QtXmlToSphinx::handleSeeAlsoTag(QXmlStreamReader& reader) handleLinkEnd(m_seeAlsoContext.data()); m_seeAlsoContext.reset(); } - m_output << endl << endl; + m_output << Qt::endl << Qt::endl; break; default: break; @@ -747,7 +747,7 @@ void formatSnippet(QTextStream &str, Indent indent, const QString &snippet) for (const QStringRef &line : lines) { if (!line.trimmed().isEmpty()) str << indent << line; - str << endl; + str << Qt::endl; } } @@ -811,7 +811,7 @@ void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader) m_output << INDENT << "<Code snippet \"" << location << ':' << identifier << "\" not found>\n"; else formatSnippet(m_output, INDENT, code); - m_output << endl; + m_output << Qt::endl; } } void QtXmlToSphinx::handleDotsTag(QXmlStreamReader& reader) @@ -930,16 +930,16 @@ void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader) switch (listType) { case BulletList: case OrderedList: { - m_output << endl; + m_output << Qt::endl; const char *separator = listType == BulletList ? "* " : "#. "; const char *indent = listType == BulletList ? " " : " "; for (const TableCell &cell : m_currentTable.constFirst()) { const QVector<QStringRef> itemLines = cell.data.splitRef(QLatin1Char('\n')); - m_output << INDENT << separator << itemLines.constFirst() << endl; + m_output << INDENT << separator << itemLines.constFirst() << Qt::endl; for (int i = 1, max = itemLines.count(); i < max; ++i) - m_output << INDENT << indent << itemLines[i] << endl; + m_output << INDENT << indent << itemLines[i] << Qt::endl; } - m_output << endl; + m_output << Qt::endl; } break; case EnumeratedList: @@ -1144,7 +1144,7 @@ void QtXmlToSphinx::handleImageTag(QXmlStreamReader& reader) return; const QString href = reader.attributes().value(QLatin1String("href")).toString(); if (copyImage(href)) - m_output << INDENT << ".. image:: " << href << endl << endl; + m_output << INDENT << ".. image:: " << href << Qt::endl << Qt::endl; } void QtXmlToSphinx::handleInlineImageTag(QXmlStreamReader& reader) @@ -1174,13 +1174,13 @@ void QtXmlToSphinx::handleRawTag(QXmlStreamReader& reader) QXmlStreamReader::TokenType token = reader.tokenType(); if (token == QXmlStreamReader::StartElement) { QString format = reader.attributes().value(QLatin1String("format")).toString(); - m_output << INDENT << ".. raw:: " << format.toLower() << endl << endl; + m_output << INDENT << ".. raw:: " << format.toLower() << Qt::endl << Qt::endl; } else if (token == QXmlStreamReader::Characters) { const QVector<QStringRef> lst(reader.text().split(QLatin1Char('\n'))); for (const QStringRef &row : lst) - m_output << INDENT << INDENT << row << endl; + m_output << INDENT << INDENT << row << Qt::endl; } else if (token == QXmlStreamReader::EndElement) { - m_output << endl << endl; + m_output << Qt::endl << Qt::endl; } } @@ -1193,9 +1193,9 @@ void QtXmlToSphinx::handleCodeTag(QXmlStreamReader& reader) } else if (token == QXmlStreamReader::Characters) { const QVector<QStringRef> lst(reader.text().split(QLatin1Char('\n'))); for (const QStringRef &row : lst) - m_output << INDENT << INDENT << row << endl; + m_output << INDENT << INDENT << row << Qt::endl; } else if (token == QXmlStreamReader::EndElement) { - m_output << endl << endl; + m_output << Qt::endl << Qt::endl; INDENT.indent--; } } @@ -1235,7 +1235,7 @@ void QtXmlToSphinx::handlePageTag(QXmlStreamReader &reader) ? writeEscapedRstText(m_output, title) : writeEscapedRstText(m_output, fullTitle); - m_output << endl << Pad('*', size) << endl << endl; + m_output << Qt::endl << Pad('*', size) << Qt::endl << Qt::endl; } void QtXmlToSphinx::handleTargetTag(QXmlStreamReader &reader) @@ -1299,7 +1299,7 @@ void QtXmlToSphinx::handleQuoteFileTag(QXmlStreamReader& reader) m_output << INDENT << "<Code snippet \"" << location << "\" not found>\n"; else formatCode(m_output, code, INDENT); - m_output << endl; + m_output << Qt::endl; } } @@ -1435,7 +1435,7 @@ void QtXmlToSphinx::Table::format (QTextStream& s) const c = '-'; s << Pad(c, colWidths.at(col)) << '+'; } - s << endl; + s << Qt::endl; // Print the table cells @@ -1452,7 +1452,7 @@ void QtXmlToSphinx::Table::format (QTextStream& s) const else s << ' '; if (rowLine < rowLines.count()) - s << qSetFieldWidth(colWidths[j]) << left << rowLines.at(rowLine) << qSetFieldWidth(0); + s << qSetFieldWidth(colWidths[j]) << Qt::left << rowLines.at(rowLine) << qSetFieldWidth(0); else s << Pad(' ', colWidths.at(j)); } @@ -1461,7 +1461,7 @@ void QtXmlToSphinx::Table::format (QTextStream& s) const s << "|\n"; } } - s << INDENT << horizontalLine << endl << endl; + s << INDENT << horizontalLine << Qt::endl << Qt::endl; } static QString getFuncName(const AbstractMetaFunction* cppFunc) { @@ -1562,11 +1562,11 @@ void QtDocGenerator::writeFormattedText(QTextStream &s, const Documentation &doc s << INDENT << (typesystemIndentation > 0 && typesystemIndentation < line.size() ? line.right(line.size() - typesystemIndentation) : line) - << endl; + << Qt::endl; } } - s << endl; + s << Qt::endl; } static void writeInheritedByList(QTextStream& s, const AbstractMetaClass* metaClass, const AbstractMetaClassList& allClasses) @@ -1584,7 +1584,7 @@ static void writeInheritedByList(QTextStream& s, const AbstractMetaClass* metaCl QStringList classes; for (AbstractMetaClass *c : qAsConst(res)) classes << QLatin1String(":ref:`") + getClassTargetFullName(c, false) + QLatin1Char('`'); - s << classes.join(QLatin1String(", ")) << endl << endl; + s << classes.join(QLatin1String(", ")) << Qt::endl << Qt::endl; } // Extract the <brief> section from a WebXML (class) documentation and remove it @@ -1625,15 +1625,15 @@ void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContex s << ".. _" << className << ":" << "\n\n"; s << ".. currentmodule:: " << metaClass->package() << "\n\n\n"; - s << className << endl; - s << Pad('*', className.count()) << endl << endl; + s << className << Qt::endl; + s << Pad('*', className.count()) << Qt::endl << Qt::endl; auto documentation = metaClass->documentation(); Documentation brief; if (extractBrief(&documentation, &brief)) writeFormattedText(s, brief, metaClass); - s << ".. inheritance-diagram:: " << getClassTargetFullName(metaClass, true) << endl + s << ".. inheritance-diagram:: " << getClassTargetFullName(metaClass, true) << Qt::endl << " :parts: 2\n\n"; // TODO: This would be a parameter in the future... @@ -1740,17 +1740,17 @@ void QtDocGenerator::writeFunctionList(QTextStream& s, const AbstractMetaClass* void QtDocGenerator::writeFunctionBlock(QTextStream& s, const QString& title, QStringList& functions) { if (!functions.isEmpty()) { - s << title << endl - << QString(title.size(), QLatin1Char('^')) << endl; + s << title << Qt::endl + << QString(title.size(), QLatin1Char('^')) << Qt::endl; std::sort(functions.begin(), functions.end()); s << ".. container:: function_list\n\n"; Indentation indentation(INDENT); for (const QString &func : qAsConst(functions)) - s << INDENT << '*' << ' ' << func << endl; + s << INDENT << '*' << ' ' << func << Qt::endl; - s << endl << endl; + s << Qt::endl << Qt::endl; } } @@ -1760,7 +1760,7 @@ void QtDocGenerator::writeEnums(QTextStream& s, const AbstractMetaClass* cppClas const AbstractMetaEnumList &enums = cppClass->enums(); for (AbstractMetaEnum *en : enums) { - s << section_title << getClassTargetFullName(cppClass) << '.' << en->name() << endl << endl; + s << section_title << getClassTargetFullName(cppClass) << '.' << en->name() << Qt::endl << Qt::endl; writeFormattedText(s, en->documentation(), cppClass); const auto version = versionOf(en->typeEntry()); if (!version.isNull()) @@ -1775,7 +1775,7 @@ void QtDocGenerator::writeFields(QTextStream& s, const AbstractMetaClass* cppCla const AbstractMetaFieldList &fields = cppClass->fields(); for (AbstractMetaField *field : fields) { - s << section_title << getClassTargetFullName(cppClass) << "." << field->name() << endl << endl; + s << section_title << getClassTargetFullName(cppClass) << "." << field->name() << Qt::endl << Qt::endl; //TODO: request for member ‘documentation’ is ambiguous writeFormattedText(s, field->AbstractMetaAttributes::documentation(), cppClass); } @@ -1819,14 +1819,14 @@ void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass* } } - s << endl; + s << Qt::endl; for (QHash<QString, AbstractMetaArgument*>::const_iterator it = arg_map.cbegin(), end = arg_map.cend(); it != end; ++it) { Indentation indentation(INDENT, 2); writeParameterType(s, cppClass, it.value()); } - s << endl; + s << Qt::endl; for (AbstractMetaFunction *func : qAsConst(lst)) writeFormattedText(s, func->documentation(), cppClass); @@ -1917,7 +1917,7 @@ void QtDocGenerator::writeDocSnips(QTextStream &s, if (row.trimmed().size() == 0) { if (currentRow == 0) continue; - s << endl; + s << Qt::endl; } if (currentRow == 0) { @@ -1931,7 +1931,7 @@ void QtDocGenerator::writeDocSnips(QTextStream &s, break; } } - s << row.midRef(offset) << endl; + s << row.midRef(offset) << Qt::endl; currentRow++; } @@ -1971,7 +1971,7 @@ bool QtDocGenerator::writeInjectDocumentation(QTextStream& s, } } - s << endl; + s << Qt::endl; // TODO: Deprecate the use of doc string on glue code. // This is pre "add-function" and "inject-documentation" tags. @@ -2046,13 +2046,13 @@ QString QtDocGenerator::translateToPythonType(const AbstractMetaType* type, cons void QtDocGenerator::writeParameterType(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaArgument* arg) { s << INDENT << ":param " << arg->name() << ": " - << translateToPythonType(arg->type(), cppClass) << endl; + << translateToPythonType(arg->type(), cppClass) << Qt::endl; } void QtDocGenerator::writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction *func) { - s << endl; + s << Qt::endl; const AbstractMetaArgumentList &funcArgs = func->arguments(); for (AbstractMetaArgument *arg : funcArgs) { @@ -2078,9 +2078,9 @@ void QtDocGenerator::writeFunctionParametersType(QTextStream &s, const AbstractM if (retType.isEmpty()) retType = translateToPythonType(func->type(), cppClass); - s << INDENT << ":rtype: " << retType << endl; + s << INDENT << ":rtype: " << retType << Qt::endl; } - s << endl; + s << Qt::endl; } void QtDocGenerator::writeFunction(QTextStream& s, const AbstractMetaClass* cppClass, @@ -2134,7 +2134,7 @@ static void writeFancyToc(QTextStream& s, const QStringList& items, int cols = 4 std::sort(it.value().begin(), it.value().end()); if (i) - ss << endl; + ss << Qt::endl; ss << "**" << it.key() << "**\n\n"; i += 2; // a letter title is equivalent to two entries in space @@ -2184,11 +2184,11 @@ void QtDocGenerator::writeModuleDocumentation() FileOut output(outputDir + QLatin1String("/index.rst")); QTextStream& s = output.stream; - s << ".. module:: " << it.key() << endl << endl; + s << ".. module:: " << it.key() << Qt::endl << Qt::endl; const QString &title = it.key(); - s << title << endl; - s << Pad('*', title.length()) << endl << endl; + s << title << Qt::endl; + s << Pad('*', title.length()) << Qt::endl << Qt::endl; /* Avoid showing "Detailed Description for *every* class in toc tree */ Indentation indentation(INDENT); @@ -2230,8 +2230,8 @@ void QtDocGenerator::writeModuleDocumentation() Indentation deeperIndentation(INDENT); s << INDENT << ":maxdepth: 1\n\n"; for (const QString &className : qAsConst(it.value())) - s << INDENT << className << endl; - s << endl << endl; + s << INDENT << className << Qt::endl; + s << Qt::endl << Qt::endl; } s << "Detailed Description\n--------------------\n\n"; diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 6b29272e0..9e7b96c7f 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -44,8 +44,7 @@ #include <QMetaType> #include <algorithm> - -#include <algorithm> +#include <cstring> static const char CPP_ARG0[] = "cppArg0"; @@ -300,7 +299,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) qCDebug(lcShiboken) << "Generating wrapper implementation for " << metaClass->fullName(); // write license comment - s << licenseComment() << endl; + s << licenseComment() << Qt::endl; if (!avoidProtectedHack() && !metaClass->isNamespace() && !metaClass->hasPrivateDestructor()) { s << "//workaround to access protected functions\n"; @@ -339,11 +338,11 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h")); s << "\n// main header\n" << "#include \"" << headerfile << "\"\n"; - s << endl << "// inner classes\n"; + s << Qt::endl << "// inner classes\n"; const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); for (AbstractMetaClass *innerClass : innerClasses) { GeneratorContext innerClassContext(innerClass); - if (shouldGenerate(innerClass)) { + if (shouldGenerate(innerClass) && !innerClass->typeEntry()->isSmartPointer()) { QString headerfile = fileNameForContext(innerClassContext); headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h")); s << "#include \"" << headerfile << "\"\n"; @@ -361,8 +360,8 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) includes.append(cppEnum->typeEntry()->extraIncludes()); std::sort(includes.begin(), includes.end()); for (const Include &inc : qAsConst(includes)) - s << inc.toString() << endl; - s << endl; + s << inc.toString() << Qt::endl; + s << Qt::endl; s << "\n#include <cctype>\n#include <cstring>\n"; @@ -381,7 +380,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) } } - s << endl << endl << typeNameFunc << endl; + s << Qt::endl << Qt::endl << typeNameFunc << Qt::endl; // Create string literal for smart pointer getter method. if (classContext.forSmartPointer()) { @@ -395,13 +394,13 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) // class inject-code native/beginning if (!metaClass->typeEntry()->codeSnips().isEmpty()) { writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, metaClass); - s << endl; + s << Qt::endl; } // python conversion rules if (metaClass->typeEntry()->hasTargetConversionRule()) { s << "// Python Conversion\n"; - s << metaClass->typeEntry()->conversionRule() << endl; + s << metaClass->typeEntry()->conversionRule() << Qt::endl; } if (shouldGenerateCppWrapper(metaClass)) { @@ -553,7 +552,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) // Write methods definition s << "static PyMethodDef " << className << "_methods[] = {\n"; - s << methodsDefinitions << endl; + s << methodsDefinitions << Qt::endl; if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) { s << INDENT << "{\"__copy__\", reinterpret_cast<PyCFunction>(" << className << "___copy__)" << ", METH_NOARGS},\n"; @@ -580,9 +579,9 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) writeCppSelfDefinition(s, classContext); if (f->allowThread()) { s << INDENT << "int result;\n"; - s << INDENT << BEGIN_ALLOW_THREADS << endl; + s << INDENT << BEGIN_ALLOW_THREADS << Qt::endl; s << INDENT << "result = !" << CPP_SELF_VAR << "->isNull();\n"; - s << INDENT << END_ALLOW_THREADS << endl; + s << INDENT << END_ALLOW_THREADS << Qt::endl; s << INDENT << "return result;\n"; } else { s << INDENT << "return !" << CPP_SELF_VAR << "->isNull();\n"; @@ -635,10 +634,10 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) writeGetterFunction(s, metaField, classContext); if (canGenerateFieldSetter(metaField)) writeSetterFunction(s, metaField, classContext); - s << endl; + s << Qt::endl; } - s << "// Getters and Setters for " << metaClass->name() << endl; + s << "// Getters and Setters for " << metaClass->name() << Qt::endl; s << "static PyGetSetDef " << cpythonGettersSettersDefinitionName(metaClass) << "[] = {\n"; for (const AbstractMetaField *metaField : fields) { if (metaField->isStatic()) @@ -666,7 +665,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) writeTpClearFunction(s, metaClass); writeClassDefinition(s, metaClass, classContext); - s << endl; + s << Qt::endl; if (metaClass->isPolymorphic() && metaClass->baseClass()) writeTypeDiscoveryFunction(s, metaClass); @@ -680,10 +679,10 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) if (hasFlags) { writeFlagsMethods(s, cppEnum); writeFlagsNumberMethodsDefinition(s, cppEnum); - s << endl; + s << Qt::endl; } } - s << endl; + s << Qt::endl; writeConverterFunctions(s, metaClass, classContext); writeClassRegister(s, metaClass, classContext, signatureStream); @@ -691,7 +690,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) // class inject-code native/end if (!metaClass->typeEntry()->codeSnips().isEmpty()) { writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, metaClass); - s << endl; + s << Qt::endl; } } @@ -750,11 +749,14 @@ QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunctio return QLatin1Char('"') + func->typeReplaced(0) + QLatin1Char('"'); // SbkType would return null when the type is a container. - if (func->type()->typeEntry()->isContainer()) { + auto typeEntry = func->type()->typeEntry(); + if (typeEntry->isContainer()) { return QLatin1Char('"') - + reinterpret_cast<const ContainerTypeEntry *>(func->type()->typeEntry())->typeName() + + reinterpret_cast<const ContainerTypeEntry *>(typeEntry)->typeName() + QLatin1Char('"'); } + if (typeEntry->isSmartPointer()) + return QLatin1Char('"') + typeEntry->qualifiedCppName() + QLatin1Char('"'); if (avoidProtectedHack()) { const AbstractMetaEnum *metaEnum = findAbstractMetaEnum(func->type()); @@ -765,7 +767,8 @@ QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunctio if (func->type()->isPrimitive()) return QLatin1Char('"') + func->type()->name() + QLatin1Char('"'); - return QString::fromLatin1("reinterpret_cast<PyTypeObject *>(Shiboken::SbkType< %1 >())->tp_name").arg(func->type()->typeEntry()->qualifiedCppName()); + return QLatin1String("reinterpret_cast<PyTypeObject *>(Shiboken::SbkType< ") + + typeEntry->qualifiedCppName() + QLatin1String(" >())->tp_name"); } void CppGenerator::writeVirtualMethodNative(QTextStream &s, @@ -821,7 +824,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, errorMsg += func->signature(); errorMsg = msgCouldNotFindMinimalConstructor(errorMsg, func->type()->cppSignature()); qCWarning(lcShiboken).noquote().nospace() << errorMsg; - s << endl << INDENT << "#error " << errorMsg << endl; + s << Qt::endl << INDENT << "#error " << errorMsg << Qt::endl; } } else { defaultReturnExpr.setType(DefaultValue::Void); @@ -832,7 +835,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, << 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 << returnStatement(defaultReturnExpr.returnValue()) << endl; + s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; s << "}\n\n"; return; } @@ -842,7 +845,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, CodeSnipList snips = func->injectedCodeSnips(); const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast(); writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionDeclaration, TypeSystem::NativeCode, func, lastArg); - s << endl; + s << Qt::endl; } // PYSIDE-803: Build a boolean cache for unused overrides. @@ -873,7 +876,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, s << INDENT << "if (PyErr_Occurred())\n"; { Indentation indentation(INDENT); - s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl; + s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; } s << INDENT << "Shiboken::AutoDecRef " << PYTHON_OVERRIDE_VAR << "(Shiboken::BindingManager::instance().getOverride(this, \""; @@ -887,7 +890,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, snips = func->injectedCodeSnips(); const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast(); writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::ShellCode, func, lastArg); - s << endl; + s << Qt::endl; } if (func->isAbstract()) { @@ -962,7 +965,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, } s << "Py_BuildValue(\"(" << getFormatUnitString(func, false) << ")\",\n"; - s << argConversions.join(QLatin1String(",\n")) << endl; + s << argConversions.join(QLatin1String(",\n")) << Qt::endl; s << INDENT << "));\n"; } @@ -980,7 +983,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, } } } - s << endl; + s << Qt::endl; CodeSnipList snips; if (func->hasInjectedCode()) { @@ -991,7 +994,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast(); writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, func, lastArg); - s << endl; + s << Qt::endl; } if (!injectedCodeCallsPythonOverride(func)) { @@ -1004,7 +1007,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, { Indentation indent(INDENT); s << INDENT << "PyErr_Print();\n"; - s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl; + s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; } s << INDENT << "}\n"; @@ -1026,7 +1029,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, "\"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);\n"; - s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl; + s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; } s << INDENT << "}\n"; @@ -1047,7 +1050,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, "\"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);\n"; - s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl; + s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; } s << INDENT << "}\n"; @@ -1090,7 +1093,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, } if (func->hasInjectedCode()) { - s << endl; + s << Qt::endl; const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast(); writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, func, lastArg); } @@ -1215,7 +1218,7 @@ void CppGenerator::writeEnumConverterFunctions(QTextStream &s, const TypeEntry * } c << ";\n"; writeCppToPythonFunction(s, code, typeName, typeName); - s << endl; + s << Qt::endl; if (enumType->isFlags()) return; @@ -1295,7 +1298,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla const QString pyTypeCheck = QLatin1String("PyObject_TypeCheck(pyIn, reinterpret_cast<PyTypeObject *>(") + cpythonType + QLatin1String("))"); writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, pyTypeCheck, QString(), true); - s << endl; + s << Qt::endl; // C++ pointer to a Python wrapper, keeping identity. s << "// C++ to Python pointer conversion - tries to find the Python wrapper for the C++ object (keeps object identity).\n"; @@ -1332,12 +1335,12 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla // The conversions for an Object Type end here. if (!metaClass->typeEntry()->isValue() && !metaClass->typeEntry()->isSmartPointer()) { - s << endl; + s << Qt::endl; return; } // Always copies C++ value (not pointer, and not reference) to a new Python wrapper. - s << endl << "// C++ to Python copy conversion.\n"; + s << Qt::endl << "// C++ to Python copy conversion.\n"; if (!classContext.forSmartPointer()) targetTypeName = metaClass->name(); else @@ -1357,7 +1360,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla << ", new ::" << computedWrapperName << "(*reinterpret_cast<const " << typeName << " *>(cppIn)), true, true);"; writeCppToPythonFunction(s, code, sourceTypeName, targetTypeName); - s << endl; + s << Qt::endl; // Python to C++ copy conversion. s << "// Python to C++ copy conversion.\n"; @@ -1382,7 +1385,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla // "Is convertible" function for the Python object to C++ value copy conversion. writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, pyTypeCheck); - s << endl; + s << Qt::endl; // User provided implicit conversions. CustomConversion *customConversion = metaClass->typeEntry()->customConversion(); @@ -1477,7 +1480,7 @@ void CppGenerator::writeCustomConverterFunctions(QTextStream &s, const CustomCon s << "// Python to C++ conversions for type '" << customConversion->ownerType()->qualifiedCppName() << "'.\n"; for (CustomConversion::TargetToNativeConversion *toNative : toCppConversions) writePythonToCppConversionFunctions(s, toNative, customConversion->ownerType()); - s << endl; + s << Qt::endl; } void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClass *metaClass, @@ -1487,24 +1490,24 @@ void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClas return; s << INDENT << "// Register Converter\n"; s << INDENT << "SbkConverter *converter = Shiboken::Conversions::createConverter("; - s << cpythonTypeName(metaClass) << ',' << endl; + s << cpythonTypeName(metaClass) << ',' << Qt::endl; { Indentation indent(INDENT); QString sourceTypeName = metaClass->name(); QString targetTypeName = sourceTypeName + QLatin1String("_PTR"); - s << INDENT << pythonToCppFunctionName(sourceTypeName, targetTypeName) << ',' << endl; - s << INDENT << convertibleToCppFunctionName(sourceTypeName, targetTypeName) << ',' << endl; + s << INDENT << pythonToCppFunctionName(sourceTypeName, targetTypeName) << ',' << Qt::endl; + s << INDENT << convertibleToCppFunctionName(sourceTypeName, targetTypeName) << ',' << Qt::endl; std::swap(targetTypeName, sourceTypeName); s << INDENT << cppToPythonFunctionName(sourceTypeName, targetTypeName); if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) { - s << ',' << endl; + s << ',' << Qt::endl; sourceTypeName = metaClass->name() + QLatin1String("_COPY"); s << INDENT << cppToPythonFunctionName(sourceTypeName, targetTypeName); } } s << ");\n"; - s << endl; + s << Qt::endl; QStringList cppSignature; if (!classContext.forSmartPointer()) { @@ -1536,7 +1539,7 @@ void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClas s << wrapperName(metaClass) << ").name());\n"; } - s << endl; + s << Qt::endl; if (!metaClass->typeEntry()->isValue() && !metaClass->typeEntry()->isSmartPointer()) return; @@ -1631,7 +1634,7 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &over s << qualifiedCppName << " >()))\n"; Indentation indent(INDENT); - s << INDENT << returnStatement(m_currentErrorCode) << endl << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl << Qt::endl; } // Declare pointer for the underlying C++ object. s << INDENT << "::"; @@ -1736,7 +1739,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun s << INDENT << "\"'" << metaClass->qualifiedCppName(); } s << "' represents a C++ abstract class and cannot be instantiated\");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT<< "}\n\n"; } @@ -1755,24 +1758,24 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun writeMethodWrapperPreamble(s, overloadData, classContext); - s << endl; + s << Qt::endl; if (overloadData.maxArgs() > 0) writeOverloadedFunctionDecisor(s, overloadData); writeFunctionCalls(s, overloadData, classContext); - s << endl; + s << Qt::endl; s << INDENT << "if (PyErr_Occurred() || !Shiboken::Object::setCppPointer(sbkSelf, Shiboken::SbkType< ::" << metaClass->qualifiedCppName() << " >(), cptr)) {\n"; { Indentation indent(INDENT); s << INDENT << "delete cptr;\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << "}\n"; if (overloadData.maxArgs() > 0) { s << INDENT << "if (!cptr) goto " << cpythonFunctionName(rfunc) << "_TypeError;\n"; - s << endl; + s << Qt::endl; } s << INDENT << "Shiboken::Object::setValidCpp(sbkSelf, true);\n"; @@ -1794,13 +1797,13 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun // Create metaObject and register signal/slot if (metaClass->isQObject() && usePySideExtensions()) { - s << endl << INDENT << "// QObject setup\n"; + s << Qt::endl << INDENT << "// QObject setup\n"; s << INDENT << "PySide::Signal::updateSourceObject(self);\n"; s << INDENT << "metaObject = cptr->metaObject(); // <- init python qt properties\n"; s << INDENT << "if (kwds && !PySide::fillQtProperties(self, metaObject, kwds, argNames, " << argNamesSet.count() << "))\n"; { Indentation indentation(INDENT); - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } } @@ -1823,7 +1826,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun const CodeSnipList &injectedCodeSnips = func->injectedCodeSnips(); for (const CodeSnip &cs : injectedCodeSnips) { if (cs.position == TypeSystem::CodeSnipPositionEnd) { - s << INDENT << "case " << metaClass->functions().indexOf(func) << ':' << endl; + s << INDENT << "case " << metaClass->functions().indexOf(func) << ':' << Qt::endl; s << INDENT << "{\n"; { Indentation indent(INDENT); @@ -1837,8 +1840,8 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun s << "}\n"; } - s << endl; - s << endl << INDENT << "return 1;\n"; + s << Qt::endl; + s << Qt::endl << INDENT << "return 1;\n"; if (overloadData.maxArgs() > 0) writeErrorSection(s, overloadData); s<< "}\n\n"; @@ -1863,7 +1866,7 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction writeMethodWrapperPreamble(s, overloadData, classContext); - s << endl; + s << Qt::endl; /* * This code is intended for shift operations only: @@ -1926,9 +1929,9 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction writeFunctionCalls(s, overloadData, classContext); if (callExtendedReverseOperator) - s << endl << INDENT << "} // End of \"if (!" << PYTHON_RETURN_VAR << ")\"\n"; + s << Qt::endl << INDENT << "} // End of \"if (!" << PYTHON_RETURN_VAR << ")\"\n"; - s << endl; + s << Qt::endl; writeFunctionReturnErrorCheckSection(s, hasReturnValue && !rfunc->isInplaceOperator()); @@ -1962,7 +1965,7 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl s << PYTHON_ARGS << "[] = {" << QString(maxArgs, QLatin1Char('0')).split(QLatin1String(""), Qt::SkipEmptyParts).join(QLatin1String(", ")) << "};\n"; - s << endl; + s << Qt::endl; if (overloadData.hasVarargs()) { maxArgs--; @@ -1973,7 +1976,7 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl s << INDENT << "Shiboken::AutoDecRef auto_nonvarargs(nonvarargs);\n"; s << INDENT << PYTHON_ARGS << '[' << maxArgs << "] = PyTuple_GetSlice(args, " << maxArgs << ", numArgs);\n"; s << INDENT << "Shiboken::AutoDecRef auto_varargs(" << PYTHON_ARGS << "[" << maxArgs << "]);\n"; - s << endl; + s << Qt::endl; } bool usesNamedArguments = overloadData.hasArgumentWithDefaultValue(); @@ -1986,7 +1989,7 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl { Indentation indent(INDENT); s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): too many arguments\");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << '}'; } @@ -1999,7 +2002,7 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl { Indentation indent(INDENT); s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): not enough arguments\");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << '}'; } @@ -2017,7 +2020,7 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl Indentation indent(INDENT); s << INDENT << "goto " << cpythonFunctionName(rfunc) << "_TypeError;"; } - s << endl << endl; + s << Qt::endl << Qt::endl; QString funcName; if (rfunc->isOperatorOverload()) @@ -2036,9 +2039,9 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl s << "))\n"; { Indentation indent(INDENT); - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } - s << endl; + s << Qt::endl; } void CppGenerator::writeCppSelfAssigment(QTextStream &s, const GeneratorContext &context, @@ -2128,7 +2131,7 @@ void CppGenerator::writeCppSelfDefinition(QTextStream &s, void CppGenerator::writeErrorSection(QTextStream &s, OverloadData &overloadData) { const AbstractMetaFunction *rfunc = overloadData.referenceFunction(); - s << endl << INDENT << cpythonFunctionName(rfunc) << "_TypeError:\n"; + s << Qt::endl << INDENT << cpythonFunctionName(rfunc) << "_TypeError:\n"; Indentation indentation(INDENT); QString funcName = fullPythonFunctionName(rfunc); @@ -2148,7 +2151,7 @@ void CppGenerator::writeFunctionReturnErrorCheckSection(QTextStream &s, bool has Indentation indent(INDENT); if (hasReturnValue) s << INDENT << "Py_XDECREF(" << PYTHON_RETURN_VAR << ");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << "}\n"; } @@ -2157,7 +2160,7 @@ void CppGenerator::writeInvalidPyObjectCheck(QTextStream &s, const QString &pyOb { s << INDENT << "if (!Shiboken::Object::isValid(" << pyObj << "))\n"; Indentation indent(INDENT); - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } static QString pythonToCppConverterForArgumentName(const QString &argumentName) @@ -2423,7 +2426,7 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream &s, if (!defaultValue.isEmpty()) s << INDENT << '}'; - s << endl; + s << Qt::endl; } static void addConversionRuleCodeSnippet(CodeSnipList &snippetList, QString &rule, @@ -2486,10 +2489,10 @@ void CppGenerator::writeOverloadedFunctionDecisor(QTextStream &s, const Overload s << "static "; if (const auto *decl = func->declaringClass()) s << decl->name() << "::"; - s << func->minimalSignature() << endl; + s << func->minimalSignature() << Qt::endl; } writeOverloadedFunctionDecisorEngine(s, &overloadData); - s << endl; + s << Qt::endl; // Ensure that the direct overload that called this reverse // is called. @@ -2505,7 +2508,7 @@ void CppGenerator::writeOverloadedFunctionDecisor(QTextStream &s, const Overload s << INDENT << "// Function signature not found.\n"; s << INDENT << "if (overloadId == -1) goto " << cpythonFunctionName(overloadData.referenceFunction()) << "_TypeError;\n"; - s << endl; + s << Qt::endl; } void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const OverloadData *parentOverloadData) @@ -2536,7 +2539,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov // Functions without arguments are identified right away. if (maxArgs == 0) { s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(referenceFunction); - s << "; // " << referenceFunction->minimalSignature() << endl; + s << "; // " << referenceFunction->minimalSignature() << Qt::endl; return; } @@ -2552,7 +2555,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov if (isLastArgument || (signatureFound && !hasDefaultCall)) { const AbstractMetaFunction *func = parentOverloadData->referenceFunction(); s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func); - s << "; // " << func->minimalSignature() << endl; + s << "; // " << func->minimalSignature() << Qt::endl; return; } } @@ -2578,7 +2581,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov } } s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func); - s << "; // " << func->minimalSignature() << endl; + s << "; // " << func->minimalSignature() << Qt::endl; } s << INDENT << '}'; } @@ -2635,9 +2638,11 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov if (usePyArgs && signatureFound) { AbstractMetaArgumentList args = refFunc->arguments(); - int lastArgIsVarargs = (int) (args.size() > 1 && args.constLast()->type()->isVarargs()); - int numArgs = args.size() - OverloadData::numberOfRemovedArguments(refFunc) - lastArgIsVarargs; - typeChecks.prepend(QString::fromLatin1("numArgs %1 %2").arg(lastArgIsVarargs ? QLatin1String(">=") : QLatin1String("==")).arg(numArgs)); + const bool isVarargs = args.size() > 1 && args.constLast()->type()->isVarargs(); + int numArgs = args.size() - OverloadData::numberOfRemovedArguments(refFunc); + if (isVarargs) + --numArgs; + typeChecks.prepend(QString::fromLatin1("numArgs %1 %2").arg(isVarargs ? QLatin1String(">=") : QLatin1String("==")).arg(numArgs)); } else if (sequenceArgCount > 1) { typeChecks.prepend(QString::fromLatin1("numArgs >= %1").arg(startArg + sequenceArgCount)); } else if (refFunc->isOperatorOverload() && !refFunc->isCallOperator()) { @@ -2657,7 +2662,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov Indentation indent(INDENT); QString separator; QTextStream sep(&separator); - sep << endl << INDENT << "&& "; + sep << Qt::endl << INDENT << "&& "; s << typeChecks.join(separator); } s << ") {\n"; @@ -2667,7 +2672,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov } s << INDENT << "}"; } - s << endl; + s << Qt::endl; } void CppGenerator::writeFunctionCalls(QTextStream &s, const OverloadData &overloadData, @@ -2683,7 +2688,7 @@ void CppGenerator::writeFunctionCalls(QTextStream &s, const OverloadData &overlo } else { for (int i = 0; i < overloads.count(); i++) { const AbstractMetaFunction *func = overloads.at(i); - s << INDENT << "case " << i << ": // " << func->signature() << endl; + s << INDENT << "case " << i << ": // " << func->signature() << Qt::endl; s << INDENT << "{\n"; { Indentation indent(INDENT); @@ -2718,7 +2723,7 @@ void CppGenerator::writeSingleFunctionCall(QTextStream &s, s << INDENT << "PyErr_Format(PyExc_TypeError, \"%s is a private method.\", \"" << func->signature().replace(QLatin1String("::"), QLatin1String(".")) << "\");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; return; } @@ -2761,7 +2766,7 @@ void CppGenerator::writeSingleFunctionCall(QTextStream &s, writeArgumentConversion(s, argType, argName, pyArgName, func->implementingClass(), defaultValue, func->isUserAdded()); } - s << endl; + s << Qt::endl; int numRemovedArgs = OverloadData::numberOfRemovedArguments(func); @@ -2916,7 +2921,7 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s, if (conversion.isEmpty()) conversion = QLatin1Char('*') + cpythonWrapperCPtr(sourceType->typeEntry(), QLatin1String("pyIn")); if (!preConversion.isEmpty()) - c << INDENT << preConversion << endl; + c << INDENT << preConversion << Qt::endl; const QString fullTypeName = getFullTypeName(targetType->typeEntry()); c << INDENT << "*reinterpret_cast<" << fullTypeName << " *>(cppOut) = " << fullTypeName << '(' << conversion << ");"; @@ -2928,7 +2933,7 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s, if (typeCheck.isEmpty()) typeCheck = QString::fromLatin1("PyObject_TypeCheck(pyIn, %1)").arg(sourcePyType); writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, typeCheck); - s << endl; + s << Qt::endl; } void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s, @@ -3036,15 +3041,15 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s, const Abs else typeCheck = QString::fromLatin1("%1pyIn)").arg(typeCheck); writeIsPythonConvertibleToCppFunction(s, typeName, typeName, typeCheck); - s << endl; + s << Qt::endl; } void CppGenerator::writeAddPythonToCppConversion(QTextStream &s, const QString &converterVar, const QString &pythonToCppFunc, const QString &isConvertibleFunc) { - s << INDENT << "Shiboken::Conversions::addPythonToCppValueConversion(" << converterVar << ',' << endl; + s << INDENT << "Shiboken::Conversions::addPythonToCppValueConversion(" << converterVar << ',' << Qt::endl; { Indentation indent(INDENT); - s << INDENT << pythonToCppFunc << ',' << endl; + s << INDENT << pythonToCppFunc << ',' << Qt::endl; s << INDENT << isConvertibleFunc; } s << ");\n"; @@ -3075,8 +3080,8 @@ void CppGenerator::writeNamedArgumentResolution(QTextStream &s, const AbstractMe s << INDENT << "if (value && " << pyArgName << ") {\n"; { Indentation indent(INDENT); - s << INDENT << pyErrString.arg(arg->name()) << endl; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << pyErrString.arg(arg->name()) << Qt::endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << "}\n"; s << INDENT << "if (value) {\n"; @@ -3151,7 +3156,7 @@ static QStringList defaultExceptionHandling() void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *func, GeneratorContext &context, int maxArgs) { - s << INDENT << "// " << func->minimalSignature() << (func->isReverseOperator() ? " [reverse operator]": "") << endl; + s << INDENT << "// " << func->minimalSignature() << (func->isReverseOperator() ? " [reverse operator]": "") << Qt::endl; if (func->isConstructor()) { const CodeSnipList &snips = func->injectedCodeSnips(); for (const CodeSnip &cs : snips) { @@ -3168,7 +3173,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f Indentation indent(INDENT); s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"; s << func->ownerClass()->name() << '.' << func->name() << "()' not implemented.\");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << "}\n"; } @@ -3195,7 +3200,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f } writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode, func, lastArg); - s << endl; + s << Qt::endl; } writeConversionRule(s, func, TypeSystem::NativeCode); @@ -3280,14 +3285,14 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f std::swap(firstArg, secondArg); QString op = func->originalName(); - op = op.right(op.size() - (sizeof("operator")/sizeof(char)-1)); + op.remove(0, int(std::strlen("operator"))); if (func->isBinaryOperator()) { if (func->isReverseOperator()) std::swap(firstArg, secondArg); if (((op == QLatin1String("++")) || (op == QLatin1String("--"))) && !func->isReverseOperator()) { - s << endl << INDENT << "for (int i=0; i < " << secondArg << "; i++, " << firstArg << op << ");\n"; + s << Qt::endl << INDENT << "for (int i=0; i < " << secondArg << "; i++, " << firstArg << op << ");\n"; mc << firstArg; } else { mc << firstArg << ' ' << op << ' ' << secondArg; @@ -3314,7 +3319,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f << ctorCall << ";\n" << INDENT << "PySide::setNextQObjectMemoryAddr(0);" - << endl; + << Qt::endl; } uva << INDENT << "} else {\n"; { @@ -3418,12 +3423,12 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f << INDENT << "threadSaver.save();\n"; } } else if (allowThread) { - s << INDENT << BEGIN_ALLOW_THREADS << endl; + s << INDENT << BEGIN_ALLOW_THREADS << Qt::endl; } s << INDENT; if (isCtor) { s << (useVAddr.isEmpty() ? - QString::fromLatin1("cptr = %1;").arg(methodCall) : useVAddr) << endl; + QString::fromLatin1("cptr = %1;").arg(methodCall) : useVAddr) << Qt::endl; } else if (func->type() && !func->isInplaceOperator()) { bool writeReturnType = true; if (avoidProtectedHack()) { @@ -3484,7 +3489,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f } if (func->hasInjectedCode() && !func->isConstructor()) { - s << endl; + s << Qt::endl; writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode, func, lastArg); } @@ -3509,12 +3514,12 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f hasReturnPolicy = true; if (!ownership_mods.isEmpty()) { - s << endl << INDENT << "// Ownership transferences.\n"; + s << Qt::endl << INDENT << "// Ownership transferences.\n"; for (const ArgumentModification &arg_mod : qAsConst(ownership_mods)) { const AbstractMetaClass *wrappedClass = nullptr; QString pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass); if (!wrappedClass) { - s << "#error Invalid ownership modification for argument " << arg_mod.index << '(' << pyArgName << ")\n" << endl; + s << "#error Invalid ownership modification for argument " << arg_mod.index << '(' << pyArgName << ")\n" << Qt::endl; break; } @@ -3537,7 +3542,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f } else { s << "invalidate(" << pyArgName << ");"; } - s << endl; + s << Qt::endl; } } else if (!refcount_mods.isEmpty()) { @@ -3557,7 +3562,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f } else { pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass); if (pyArgName.isEmpty()) { - s << "#error Invalid reference count modification for argument " << arg_mod.index << endl << endl; + s << "#error Invalid reference count modification for argument " << arg_mod.index << Qt::endl << Qt::endl; break; } } @@ -3628,9 +3633,9 @@ void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream &s, c for (const QString &ancestor : ancestors) s << INDENT << "offsets.insert(int(" << ancestor << "));\n"; - s << endl; + s << Qt::endl; s << INDENT << "offsets.erase(0);\n"; - s << endl; + s << Qt::endl; s << INDENT << "std::copy(offsets.cbegin(), offsets.cend(), mi_offsets);\n"; } @@ -3698,7 +3703,7 @@ void CppGenerator::writeEnumConverterInitialization(QTextStream &s, const TypeEn { Indentation indent(INDENT); QString typeName = fixedCppTypeName(enumType); - s << INDENT << "SbkConverter *converter = Shiboken::Conversions::createConverter(" << enumPythonType << ',' << endl; + s << INDENT << "SbkConverter *converter = Shiboken::Conversions::createConverter(" << enumPythonType << ',' << Qt::endl; { Indentation indent(INDENT); s << INDENT << cppToPythonFunctionName(typeName, typeName) << ");\n"; @@ -3783,7 +3788,7 @@ void CppGenerator::writeContainerConverterInitialization(QTextStream &s, const A void CppGenerator::writeExtendedConverterInitialization(QTextStream &s, const TypeEntry *externalType, const QVector<const AbstractMetaClass *>& conversions) { - s << INDENT << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl; + s << INDENT << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << Qt::endl; for (const AbstractMetaClass *sourceClass : conversions) { const QString converterVar = QLatin1String("reinterpret_cast<SbkObjectType *>(") + cppApiVariableName(externalType->targetLangPackage()) + QLatin1Char('[') @@ -3971,7 +3976,7 @@ void CppGenerator::writeClassDefinition(QTextStream &s, if (metaClass == miClass) writeMultipleInheritanceInitializerFunction(s, metaClass); writeSpecialCastFunction(s, metaClass); - s << endl; + s << Qt::endl; } s << "// Class Definition -----------------------------------------------\n"; @@ -4000,7 +4005,7 @@ void CppGenerator::writeClassDefinition(QTextStream &s, s << "{\n"; s << INDENT << "return " << typePtr << ";\n"; s << "}\n"; - s << endl; + s << Qt::endl; s << "static PyType_Slot " << className << "_slots[] = {\n"; s << INDENT << "{Py_tp_base, nullptr}, // inserted by introduceWrapperType\n"; s << INDENT << pyTypeSlotEntry("Py_tp_dealloc", tp_dealloc) @@ -4041,8 +4046,8 @@ void CppGenerator::writeClassDefinition(QTextStream &s, s << INDENT << tp_flags << ",\n"; s << INDENT << className << "_slots\n"; s << "};\n"; - s << endl; - s << "} //extern \"C\"" << endl; + s << Qt::endl; + s << "} //extern \"C\"" << Qt::endl; } void CppGenerator::writeMappingMethods(QTextStream &s, @@ -4090,7 +4095,7 @@ void CppGenerator::writeSequenceMethods(QTextStream &s, writeCppSelfDefinition(s, func, context); - const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? 0 : func->arguments().constLast(); + const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast(); writeCodeSnips(s, snips,TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, lastArg); s<< "}\n\n"; } @@ -4275,7 +4280,7 @@ void CppGenerator::writeCopyFunction(QTextStream &s, GeneratorContext &context) writeFunctionReturnErrorCheckSection(s); s << INDENT << "return " << PYTHON_RETURN_VAR << ";\n"; s << "}\n"; - s << endl; + s << Qt::endl; } void CppGenerator::writeGetterFunction(QTextStream &s, @@ -4414,7 +4419,7 @@ void CppGenerator::writeSetterFunction(QTextStream &s, s << cppField << ";\n"; s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut_ptr)"; } - s << ";\n" << endl; + s << ";\n" << Qt::endl; if (isPointerToWrapperType(fieldType)) { s << INDENT << "Shiboken::Object::keepReference(reinterpret_cast<SbkObject *>(self), \""; @@ -4437,7 +4442,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co s << INDENT << "PyObject *" << PYTHON_RETURN_VAR << "{};\n"; s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ";\n"; writeUnusedVariableCast(s, QLatin1String(PYTHON_TO_CPP_VAR)); - s << endl; + s << Qt::endl; s << INDENT << "switch (op) {\n"; { @@ -4447,7 +4452,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co const AbstractMetaFunction *rfunc = overloads[0]; QString operatorId = ShibokenGenerator::pythonRichCompareOperatorId(rfunc); - s << INDENT << "case " << operatorId << ':' << endl; + s << INDENT << "case " << operatorId << ':' << Qt::endl; Indentation indent(INDENT); @@ -4482,7 +4487,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co s << ") {\n"; { Indentation indent(INDENT); - s << INDENT << "// " << func->signature() << endl; + s << INDENT << "// " << func->signature() << Qt::endl; writeArgumentConversion(s, argType, QLatin1String(CPP_ARG0), QLatin1String(PYTHON_ARG), metaClass, QString(), func->isUserAdded()); @@ -4542,7 +4547,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co } s << INDENT << baseName << "_RichComparison_TypeError:\n"; s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"operator not implemented.\");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl << Qt::endl; s<< "}\n\n"; } @@ -4586,7 +4591,7 @@ void CppGenerator::writeMethodDefinition(QTextStream &s, const AbstractMetaFunct writeMethodDefinitionEntry(s, overloads); s << '}'; } - s << ',' << endl; + s << ',' << Qt::endl; } void CppGenerator::writeSignatureInfo(QTextStream &s, const AbstractMetaFunctionList &overloads) @@ -4619,7 +4624,7 @@ void CppGenerator::writeSignatureInfo(QTextStream &s, const AbstractMetaFunction s << funcName << '(' << args.join(QLatin1Char(',')) << ')'; if (f->type()) s << "->" << f->type()->pythonSignature(); - s << endl; + s << Qt::endl; } } @@ -4646,9 +4651,8 @@ static QString mangleName(QString name) void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnum *cppEnum) { - const AbstractMetaClass *enclosingClass = getProperEnclosingClassForEnum(cppEnum); - const AbstractMetaClass *upper = enclosingClass ? enclosingClass->enclosingClass() : nullptr; - bool hasUpperEnclosingClass = upper && upper->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass; + const AbstractMetaClass *enclosingClass = cppEnum->targetLangEnclosingClass(); + bool hasUpperEnclosingClass = enclosingClass && enclosingClass->targetLangEnclosingClass() != nullptr; const EnumTypeEntry *enumTypeEntry = cppEnum->typeEntry(); QString enclosingObjectVariable; if (enclosingClass) @@ -4679,7 +4683,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu s << INDENT << enumVarTypeObj << " = Shiboken::Enum::"; s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnum" : "createGlobalEnum"); - s << '(' << enclosingObjectVariable << ',' << endl; + s << '(' << enclosingObjectVariable << ',' << Qt::endl; { Indentation indent(INDENT); s << INDENT << '"' << cppEnum->name() << "\",\n"; @@ -4687,13 +4691,13 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu s << INDENT << '"' << (cppEnum->enclosingClass() ? (cppEnum->enclosingClass()->qualifiedCppName() + QLatin1String("::")) : QString()); s << cppEnum->name() << '"'; if (flags) - s << ',' << endl << INDENT << cpythonTypeNameExt(flags); + s << ',' << Qt::endl << INDENT << cpythonTypeNameExt(flags); s << ");\n"; } s << INDENT << "if (!" << cpythonTypeNameExt(cppEnum->typeEntry()) << ")\n"; { Indentation indent(INDENT); - s << INDENT << returnStatement(m_currentErrorCode) << endl << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl << Qt::endl; } } @@ -4726,7 +4730,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu << "))->tp_dict, \"" << mangleName(enumValue->name()) << "\", anonEnumItem) < 0)\n"; { Indentation indent(INDENT); - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << "Py_DECREF(anonEnumItem);\n"; } @@ -4736,27 +4740,27 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu s << enumValueText << ") < 0)\n"; { Indentation indent(INDENT); - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } } break; case CEnum: { s << INDENT << "if (!Shiboken::Enum::"; s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnumItem" : "createGlobalEnumItem"); - s << '(' << enumVarTypeObj << ',' << endl; + s << '(' << enumVarTypeObj << ',' << Qt::endl; Indentation indent(INDENT); s << INDENT << enclosingObjectVariable << ", \"" << mangleName(enumValue->name()) << "\", "; s << enumValueText << "))\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } break; case EnumClass: { s << INDENT << "if (!Shiboken::Enum::createScopedEnumItem(" - << enumVarTypeObj << ',' << endl; + << enumVarTypeObj << ',' << Qt::endl; Indentation indent(INDENT); s << INDENT << enumVarTypeObj<< ", \"" << mangleName(enumValue->name()) << "\", " << enumValueText << "))\n" - << INDENT << returnStatement(m_currentErrorCode) << endl; + << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } break; } @@ -4767,7 +4771,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu s << INDENT << "// End of '" << cppEnum->name() << "' enum"; if (cppEnum->typeEntry()->flags()) s << "/flags"; - s << '.' << endl << endl; + s << '.' << Qt::endl << Qt::endl; } void CppGenerator::writeSignalInitialization(QTextStream &s, const AbstractMetaClass *metaClass) @@ -4835,7 +4839,7 @@ void CppGenerator::writeFlagsMethods(QTextStream &s, const AbstractMetaEnum *cpp writeFlagsToLong(s, cppEnum); writeFlagsNonZero(s, cppEnum); - s << endl; + s << Qt::endl; } void CppGenerator::writeFlagsNumberMethodsDefinition(QTextStream &s, const AbstractMetaEnum *cppEnum) @@ -4859,7 +4863,7 @@ void CppGenerator::writeFlagsNumberMethodsDefinition(QTextStream &s, const Abstr s << INDENT << "{Py_nb_long, (void *)" << cpythonName << "_long},\n"; s << "#endif\n"; s << INDENT << "{0, " << NULL_PTR << "} // sentinel\n"; - s << "};" << endl << endl; + s << "};\n\n"; } void CppGenerator::writeFlagsBinaryOperator(QTextStream &s, const AbstractMetaEnum *cppEnum, @@ -4944,9 +4948,8 @@ void CppGenerator::writeClassRegister(QTextStream &s, { const ComplexTypeEntry *classTypeEntry = metaClass->typeEntry(); - const AbstractMetaClass *enc = metaClass->enclosingClass(); - bool hasEnclosingClass = enc && enc->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass; - QString enclosingObjectVariable = hasEnclosingClass ? QLatin1String("enclosingClass") : QLatin1String("module"); + const AbstractMetaClass *enc = metaClass->targetLangEnclosingClass(); + QString enclosingObjectVariable = enc ? QLatin1String("enclosingClass") : QLatin1String("module"); QString pyTypeName = cpythonTypeName(metaClass); QString initFunctionName = getInitFunctionName(classContext); @@ -4967,7 +4970,7 @@ void CppGenerator::writeClassRegister(QTextStream &s, const AbstractMetaClassList baseClasses = getBaseClasses(metaClass); if (metaClass->baseClassNames().size() > 1) { s << INDENT << "PyObject *" << pyTypeBasesVariable - << " = PyTuple_Pack(" << baseClasses.size() << ',' << endl; + << " = PyTuple_Pack(" << baseClasses.size() << ',' << Qt::endl; Indentation indent(INDENT); for (int i = 0, size = baseClasses.size(); i < size; ++i) { if (i) @@ -5039,13 +5042,13 @@ void CppGenerator::writeClassRegister(QTextStream &s, // 8:baseTypes if (metaClass->baseClassNames().size() > 1) - s << INDENT << pyTypeBasesVariable << ',' << endl; + s << INDENT << pyTypeBasesVariable << ',' << Qt::endl; else s << INDENT << "0,\n"; // 9:wrapperflags QByteArrayList wrapperFlags; - if (hasEnclosingClass) + if (enc) wrapperFlags.append(QByteArrayLiteral("Shiboken::ObjectType::WrapperFlags::InnerClass")); if (metaClass->deleteInMainThread()) wrapperFlags.append(QByteArrayLiteral("Shiboken::ObjectType::WrapperFlags::DeleteInMainThread")); @@ -5055,23 +5058,23 @@ void CppGenerator::writeClassRegister(QTextStream &s, s << INDENT << wrapperFlags.join(" | "); } s << INDENT << ");\n"; - s << INDENT << endl; + s << INDENT << Qt::endl; if (!classContext.forSmartPointer()) - s << INDENT << cpythonTypeNameExt(classTypeEntry) << endl; + s << INDENT << cpythonTypeNameExt(classTypeEntry) << Qt::endl; else - s << INDENT << cpythonTypeNameExt(classContext.preciseType()) << endl; + s << INDENT << cpythonTypeNameExt(classContext.preciseType()) << Qt::endl; s << INDENT << " = reinterpret_cast<PyTypeObject *>(" << pyTypeName << ");\n"; - s << endl; + s << Qt::endl; // Register conversions for the type. writeConverterRegister(s, metaClass, classContext); - s << endl; + s << Qt::endl; // class inject-code target/beginning if (!classTypeEntry->codeSnips().isEmpty()) { writeCodeSnips(s, classTypeEntry->codeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode, metaClass); - s << endl; + s << Qt::endl; } // Fill multiple inheritance data, if needed. @@ -5117,11 +5120,11 @@ void CppGenerator::writeClassRegister(QTextStream &s, writeToPythonConversion(s, field->type(), metaClass, metaClass->qualifiedCppName() + QLatin1String("::") + field->name()); s << ");\n"; } - s << endl; + s << Qt::endl; // class inject-code target/end if (!classTypeEntry->codeSnips().isEmpty()) { - s << endl; + s << Qt::endl; writeCodeSnips(s, classTypeEntry->codeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode, metaClass); } @@ -5439,6 +5442,25 @@ void CppGenerator::writeSmartPointerGetattroFunction(QTextStream &s, GeneratorCo s << INDENT << "return tmp;\n}\n\n"; } +// Write declaration and invocation of the init function for the module init +// function. +void CppGenerator::writeInitFunc(QTextStream &declStr, QTextStream &callStr, + const Indentor &indent, const QString &initFunctionName, + const TypeEntry *enclosingEntry) +{ + const bool hasParent = + enclosingEntry && enclosingEntry->type() != TypeEntry::TypeSystemType; + declStr << "void init_" << initFunctionName << "(PyObject *" + << (hasParent ? "enclosingClass" : "module") << ");\n"; + callStr << indent << "init_" << initFunctionName; + if (hasParent) { + callStr << "(reinterpret_cast<PyTypeObject *>(" + << cpythonTypeNameExt(enclosingEntry) << ")->tp_dict);\n"; + } else { + callStr << "(module);\n"; + } +} + bool CppGenerator::finishGeneration() { //Generate CPython wrapper file @@ -5493,33 +5515,20 @@ bool CppGenerator::finishGeneration() const AbstractMetaClassList lst = classesTopologicalSorted(additionalDependencies); for (const AbstractMetaClass *cls : lst){ - if (!shouldGenerate(cls)) - continue; - - const QString initFunctionName = QLatin1String("init_") + getSimpleClassInitFunctionName(cls); - - s_classInitDecl << "void " << initFunctionName << "(PyObject *module);" << endl; - - s_classPythonDefines << INDENT << initFunctionName; - if (cls->enclosingClass() - && (cls->enclosingClass()->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass)) { - s_classPythonDefines << "(reinterpret_cast<PyTypeObject *>(" - << cpythonTypeNameExt(cls->enclosingClass()->typeEntry()) << ")->tp_dict);"; - } else { - s_classPythonDefines << "(module);"; + if (shouldGenerate(cls)) { + writeInitFunc(s_classInitDecl, s_classPythonDefines, INDENT, + getSimpleClassInitFunctionName(cls), + cls->typeEntry()->targetLangEnclosingEntry()); } - s_classPythonDefines << endl; } // Initialize smart pointer types. const QVector<const AbstractMetaType *> &smartPtrs = instantiatedSmartPointers(); for (const AbstractMetaType *metaType : smartPtrs) { GeneratorContext context(nullptr, metaType, true); - QString initFunctionName = getInitFunctionName(context); - s_classInitDecl << "void init_" << initFunctionName << "(PyObject *module);" << endl; - QString defineStr = QLatin1String("init_") + initFunctionName; - defineStr += QLatin1String("(module);"); - s_classPythonDefines << INDENT << defineStr << endl; + writeInitFunc(s_classInitDecl, s_classPythonDefines, INDENT, + getInitFunctionName(context), + metaType->typeEntry()->targetLangEnclosingEntry()); } QString moduleFileName(outputDirectory() + QLatin1Char('/') + subDirectoryForPackage(packageName())); @@ -5532,7 +5541,7 @@ bool CppGenerator::finishGeneration() QTextStream &s = file.stream; // write license comment - s << licenseComment() << endl; + s << licenseComment() << Qt::endl; s << "#include <sbkpython.h>\n"; s << "#include <shiboken.h>\n"; @@ -5544,19 +5553,18 @@ bool CppGenerator::finishGeneration() s << "#include <qapp_macro.h>\n"; } - s << "#include \"" << getModuleHeaderFileName() << '"' << endl << endl; + s << "#include \"" << getModuleHeaderFileName() << '"' << Qt::endl << Qt::endl; for (const Include &include : qAsConst(includes)) s << include; - s << endl; + s << Qt::endl; // Global enums AbstractMetaEnumList globalEnums = this->globalEnums(); const AbstractMetaClassList &classList = classes(); for (const AbstractMetaClass *metaClass : classList) { const AbstractMetaClass *encClass = metaClass->enclosingClass(); - if (encClass && encClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) - continue; - lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass); + if (!encClass || !NamespaceTypeEntry::isVisibleScope(encClass->typeEntry())) + lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass); } TypeDatabase *typeDb = TypeDatabase::instance(); @@ -5564,14 +5572,14 @@ bool CppGenerator::finishGeneration() Q_ASSERT(moduleEntry); //Extra includes - s << endl << "// Extra includes\n"; + s << Qt::endl << "// Extra includes\n"; QVector<Include> extraIncludes = moduleEntry->extraIncludes(); for (AbstractMetaEnum *cppEnum : qAsConst(globalEnums)) extraIncludes.append(cppEnum->typeEntry()->extraIncludes()); std::sort(extraIncludes.begin(), extraIncludes.end()); for (const Include &inc : qAsConst(extraIncludes)) s << inc; - s << endl; + s << Qt::endl; s << "// Current module's type array.\n"; s << "PyTypeObject **" << cppApiVariableName() << " = nullptr;\n"; @@ -5587,7 +5595,7 @@ bool CppGenerator::finishGeneration() // module inject-code native/beginning if (!snips.isEmpty()) { writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode); - s << endl; + s << Qt::endl; } // cleanup staticMetaObject attribute @@ -5612,7 +5620,7 @@ bool CppGenerator::finishGeneration() s << "// Global functions "; s << "------------------------------------------------------------\n"; - s << globalFunctionImpl << endl; + s << globalFunctionImpl << Qt::endl; s << "static PyMethodDef " << moduleName() << "_methods[] = {\n"; s << globalFunctionDecl; @@ -5620,7 +5628,7 @@ bool CppGenerator::finishGeneration() s << "// Classes initialization functions "; s << "------------------------------------------------------------\n"; - s << classInitDecl << endl; + s << classInitDecl << Qt::endl; if (!globalEnums.isEmpty()) { QString converterImpl; @@ -5632,14 +5640,14 @@ bool CppGenerator::finishGeneration() if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; writeEnumConverterFunctions(s, cppEnum); - s << endl; + s << Qt::endl; } if (!converterImpl.isEmpty()) { s << "// Enum converters "; s << "------------------------------------------------------------\n"; s << "namespace Shiboken\n{\n"; - s << converterImpl << endl; + s << converterImpl << Qt::endl; s << "} // namespace Shiboken\n\n"; } } @@ -5651,16 +5659,16 @@ bool CppGenerator::finishGeneration() s << "PyTypeObject **" << cppApiVariableName(requiredModule) << ";\n"; s << "SbkConverter **" << convertersVariableName(requiredModule) << ";\n"; } - s << endl; + s << Qt::endl; s << "// Module initialization "; s << "------------------------------------------------------------\n"; ExtendedConverterData extendedConverters = getExtendedConverters(); if (!extendedConverters.isEmpty()) { - s << endl << "// Extended Converters.\n\n"; + s << Qt::endl << "// Extended Converters.\n\n"; for (ExtendedConverterData::const_iterator it = extendedConverters.cbegin(), end = extendedConverters.cend(); it != end; ++it) { const TypeEntry *externalType = it.key(); - s << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl; + s << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << Qt::endl; for (const AbstractMetaClass *sourceClass : it.value()) { AbstractMetaType *sourceType = buildAbstractMetaTypeFromAbstractMetaClass(sourceClass); AbstractMetaType *targetType = buildAbstractMetaTypeFromTypeEntry(externalType); @@ -5671,13 +5679,13 @@ bool CppGenerator::finishGeneration() const QVector<const CustomConversion *> &typeConversions = getPrimitiveCustomConversions(); if (!typeConversions.isEmpty()) { - s << endl << "// Primitive Type converters.\n\n"; + s << Qt::endl << "// Primitive Type converters.\n\n"; for (const CustomConversion *conversion : typeConversions) { s << "// C++ to Python conversion for type '" << conversion->ownerType()->qualifiedCppName() << "'.\n"; writeCppToPythonFunction(s, conversion); writeCustomConverterFunctions(s, conversion); } - s << endl; + s << Qt::endl; } const QVector<const AbstractMetaType *> &containers = instantiatedContainers(); @@ -5687,7 +5695,7 @@ bool CppGenerator::finishGeneration() s << "// C++ to Python conversion for type '" << container->cppSignature() << "'.\n"; writeContainerConverterFunctions(s, container); } - s << endl; + s << Qt::endl; } s << "#if defined _WIN32 || defined __CYGWIN__\n"; @@ -5727,7 +5735,7 @@ bool CppGenerator::finishGeneration() // module inject-code target/beginning if (!snips.isEmpty()) { writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode); - s << endl; + s << Qt::endl; } for (const QString &requiredModule : requiredModules) { @@ -5774,26 +5782,26 @@ bool CppGenerator::finishGeneration() s << classPythonDefines; if (!typeConversions.isEmpty()) { - s << endl; + s << Qt::endl; for (const CustomConversion *conversion : typeConversions) { writePrimitiveConverterInitialization(s, conversion); - s << endl; + s << Qt::endl; } } if (!containers.isEmpty()) { - s << endl; + s << Qt::endl; for (const AbstractMetaType *container : containers) { writeContainerConverterInitialization(s, container); - s << endl; + s << Qt::endl; } } if (!extendedConverters.isEmpty()) { - s << endl; + s << Qt::endl; for (ExtendedConverterData::const_iterator it = extendedConverters.cbegin(), end = extendedConverters.cend(); it != end; ++it) { writeExtendedConverterInitialization(s, it.key(), it.value()); - s << endl; + s << Qt::endl; } } @@ -5816,12 +5824,12 @@ bool CppGenerator::finishGeneration() } } - s << endl; + s << Qt::endl; if (maxTypeIndex) s << INDENT << "Shiboken::Module::registerTypes(module, " << cppApiVariableName() << ");\n"; s << INDENT << "Shiboken::Module::registerTypeConverters(module, " << convertersVariableName() << ");\n"; - s << endl << INDENT << "if (PyErr_Occurred()) {\n"; + s << Qt::endl << INDENT << "if (PyErr_Occurred()) {\n"; { Indentation indentation(INDENT); s << INDENT << "PyErr_Print();\n"; @@ -5832,13 +5840,13 @@ bool CppGenerator::finishGeneration() // module inject-code target/end if (!snips.isEmpty()) { writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode); - s << endl; + s << Qt::endl; } // module inject-code native/end if (!snips.isEmpty()) { writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode); - s << endl; + s << Qt::endl; } if (usePySideExtensions()) { @@ -5855,7 +5863,7 @@ bool CppGenerator::finishGeneration() s << INDENT << "FinishSignatureInitialization(module, " << moduleName() << "_SignatureStrings);\n"; - s << endl; + s << Qt::endl; s << "SBK_MODULE_INIT_FUNCTION_END\n"; return file.done() != FileOut::Failure; @@ -6031,7 +6039,7 @@ void CppGenerator::writeIndexError(QTextStream &s, const QString &errorMsg) { Indentation indent(INDENT); s << INDENT << "PyErr_SetString(PyExc_IndexError, \"" << errorMsg << "\");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << "}\n"; } diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.cpp b/sources/shiboken2/generator/shiboken2/headergenerator.cpp index 34bba408a..af56d944a 100644 --- a/sources/shiboken2/generator/shiboken2/headergenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/headergenerator.cpp @@ -119,7 +119,7 @@ void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classConte s << "#define protected public\n\n"; //Includes - s << metaClass->typeEntry()->include() << endl; + s << metaClass->typeEntry()->include() << Qt::endl; if (shouldGenerateCppWrapper(metaClass) && usePySideExtensions() && metaClass->isQObject()) @@ -337,7 +337,8 @@ void HeaderGenerator::writeTypeIndexValueLine(QTextStream &s, const TypeEntry *t void HeaderGenerator::writeTypeIndexValueLines(QTextStream &s, const AbstractMetaClass *metaClass) { - if (!metaClass->typeEntry()->generateCode()) + auto typeEntry = metaClass->typeEntry(); + if (!typeEntry->generateCode() || !NamespaceTypeEntry::isVisibleScope(typeEntry)) return; writeTypeIndexValueLine(s, metaClass->typeEntry()); const AbstractMetaEnumList &enums = metaClass->enums(); @@ -411,9 +412,17 @@ bool HeaderGenerator::finishGeneration() int smartPointerCount = 0; const QVector<const AbstractMetaType *> &instantiatedSmartPtrs = instantiatedSmartPointers(); for (const AbstractMetaType *metaType : instantiatedSmartPtrs) { - _writeTypeIndexValue(macrosStream, getTypeIndexVariableName(metaType), - smartPointerCountIndex); - macrosStream << ", // " << metaType->cppSignature() << endl; + QString indexName = getTypeIndexVariableName(metaType); + _writeTypeIndexValue(macrosStream, indexName, smartPointerCountIndex); + macrosStream << ", // " << metaType->cppSignature() << Qt::endl; + // Add a the same value for const pointees (shared_ptr<const Foo>). + const auto ptrName = metaType->typeEntry()->entryName(); + int pos = indexName.indexOf(ptrName, 0, Qt::CaseInsensitive); + if (pos >= 0) { + indexName.insert(pos + ptrName.size() + 1, QLatin1String("CONST")); + _writeTypeIndexValue(macrosStream, indexName, smartPointerCountIndex); + macrosStream << ", // (const)\n"; + } ++smartPointerCountIndex; ++smartPointerCount; } @@ -449,7 +458,7 @@ bool HeaderGenerator::finishGeneration() const QVector<const AbstractMetaType *> &containers = instantiatedContainers(); for (const AbstractMetaType *container : containers) { _writeTypeIndexValue(macrosStream, getTypeIndexVariableName(container), pCount); - macrosStream << ", // " << container->cppSignature() << endl; + macrosStream << ", // " << container->cppSignature() << Qt::endl; pCount++; } @@ -517,10 +526,10 @@ bool HeaderGenerator::finishGeneration() FileOut file(moduleHeaderFileName); QTextStream &s = file.stream; // write license comment - s << licenseComment() << endl << endl; + s << licenseComment() << Qt::endl << Qt::endl; - s << "#ifndef " << includeShield << endl; - s << "#define " << includeShield << endl << endl; + s << "#ifndef " << includeShield << Qt::endl; + s << "#define " << includeShield << Qt::endl << Qt::endl; if (!avoidProtectedHack()) { s << "//workaround to access protected functions\n"; s << "#define protected public\n\n"; @@ -534,7 +543,7 @@ bool HeaderGenerator::finishGeneration() s << "// Module Includes\n"; for (const QString &requiredModule : qAsConst(requiredTargetImports)) s << "#include <" << getModuleHeaderFileName(requiredModule) << ">\n"; - s << endl; + s << Qt::endl; } s << "// Bound library includes\n"; @@ -546,7 +555,7 @@ bool HeaderGenerator::finishGeneration() const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); for (const PrimitiveTypeEntry *ptype : primitiveTypeList) s << ptype->include(); - s << endl; + s << Qt::endl; } if (!containerTypes().isEmpty()) { @@ -554,24 +563,24 @@ bool HeaderGenerator::finishGeneration() const ContainerTypeEntryList &containerTypeList = containerTypes(); for (const ContainerTypeEntry *ctype : containerTypeList) s << ctype->include(); - s << endl; + s << Qt::endl; } - s << macros << endl; + s << macros << Qt::endl; if (!protectedEnumSurrogates.isEmpty()) { s << "// Protected enum surrogates\n"; - s << protectedEnumSurrogates << endl; + s << protectedEnumSurrogates << Qt::endl; } s << "namespace Shiboken\n{\n\n"; s << "// PyType functions, to get the PyObjectType for a type T\n"; - s << sbkTypeFunctions << endl; + s << sbkTypeFunctions << Qt::endl; s << "} // namespace Shiboken\n\n"; - s << "#endif // " << includeShield << endl << endl; + s << "#endif // " << includeShield << Qt::endl << Qt::endl; return file.done() != FileOut::Failure; } diff --git a/sources/shiboken2/generator/shiboken2/overloaddata.cpp b/sources/shiboken2/generator/shiboken2/overloaddata.cpp index 56b64bbd5..bd39e9444 100644 --- a/sources/shiboken2/generator/shiboken2/overloaddata.cpp +++ b/sources/shiboken2/generator/shiboken2/overloaddata.cpp @@ -106,7 +106,7 @@ struct OverloadSortData return; map[typeName] = counter; if (!reverseMap.contains(counter)) - reverseMap[counter] = 0; + reverseMap[counter] = nullptr; counter++; } diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp index fbd3c314b..170cbd74e 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp @@ -335,7 +335,7 @@ void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumLi { Q_ASSERT(metaClass); // if a scope is not to be generated, collect its enums into the parent scope - if (metaClass->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass) { + if (!NamespaceTypeEntry::isVisibleScope(metaClass->typeEntry())) { const AbstractMetaEnumList &enums = metaClass->enums(); for (AbstractMetaEnum *metaEnum : enums) { if (!metaEnum->isPrivate() && metaEnum->typeEntry()->generateCode() @@ -346,22 +346,6 @@ void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumLi } } -static const AbstractMetaClass *getProperEnclosingClass(const AbstractMetaClass *metaClass) -{ - if (!metaClass) - return nullptr; - - if (metaClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) - return metaClass; - - return getProperEnclosingClass(metaClass->enclosingClass()); -} - -const AbstractMetaClass *ShibokenGenerator::getProperEnclosingClassForEnum(const AbstractMetaEnum *metaEnum) -{ - return getProperEnclosingClass(metaEnum->enclosingClass()); -} - QString ShibokenGenerator::wrapperName(const AbstractMetaClass *metaClass) const { if (shouldGenerateCppWrapper(metaClass)) { @@ -394,7 +378,8 @@ QString ShibokenGenerator::fullPythonClassName(const AbstractMetaClass *metaClas QString fullClassName = metaClass->name(); const AbstractMetaClass *enclosing = metaClass->enclosingClass(); while (enclosing) { - fullClassName.prepend(enclosing->name() + QLatin1Char('.')); + if (NamespaceTypeEntry::isVisibleScope(enclosing->typeEntry())) + fullClassName.prepend(enclosing->name() + QLatin1Char('.')); enclosing = enclosing->enclosingClass(); } fullClassName.prepend(packageName() + QLatin1Char('.')); @@ -2393,7 +2378,7 @@ static bool isGroupable(const AbstractMetaFunction *func) return false; // weird operator overloads if (func->name() == QLatin1String("operator[]") || func->name() == QLatin1String("operator->")) // FIXME: what about cast operators? - return false;; + return false; return true; } @@ -2594,13 +2579,19 @@ void ShibokenGenerator::collectContainerTypesFromConverterMacros(const QString & QString convMacro = toPythonMacro ? QLatin1String("%CONVERTTOPYTHON[") : QLatin1String("%CONVERTTOCPP["); int offset = toPythonMacro ? sizeof("%CONVERTTOPYTHON") : sizeof("%CONVERTTOCPP"); int start = 0; + QString errorMessage; while ((start = code.indexOf(convMacro, start)) != -1) { int end = code.indexOf(QLatin1Char(']'), start); start += offset; if (code.at(start) != QLatin1Char('%')) { QString typeString = code.mid(start, end - start); - AbstractMetaType *type = buildAbstractMetaTypeFromString(typeString); - addInstantiatedContainersAndSmartPointers(type, type->originalTypeDescription()); + if (AbstractMetaType *type = + buildAbstractMetaTypeFromString(typeString, &errorMessage)) { + addInstantiatedContainersAndSmartPointers(type, type->originalTypeDescription()); + } else { + qFatal("%s: Cannot translate type \"%s\": %s", __FUNCTION__, + qPrintable(typeString), qPrintable(errorMessage)); + } } start = end; } @@ -2773,7 +2764,7 @@ void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream &s, const } else { const QString message = msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__), type->qualifiedCppName()); qCWarning(lcShiboken()).noquote() << message; - s << ";\n#error " << message << endl; + s << ";\n#error " << message << Qt::endl; } } diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.h b/sources/shiboken2/generator/shiboken2/shibokengenerator.h index 24c1374ae..d0e9073c8 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.h +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h @@ -219,8 +219,6 @@ protected: /// Adds enums eligible for generation from classes/namespaces marked not to be generated. static void lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList &enumList, const AbstractMetaClass *metaClass); - /// Returns the enclosing class for an enum, or nullptr if it should be global. - const AbstractMetaClass *getProperEnclosingClassForEnum(const AbstractMetaEnum *metaEnum); QString wrapperName(const AbstractMetaClass *metaClass) const; QString wrapperName(const AbstractMetaType *metaType) const; diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp index b0d453cc5..29ee1b185 100644 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ b/sources/shiboken2/libshiboken/basewrapper.cpp @@ -58,6 +58,8 @@ #include "qapp_macro.h" #include "voidptr.h" +#include <iostream> + #if defined(__APPLE__) #include <dlfcn.h> #endif @@ -919,8 +921,11 @@ introduceWrapperType(PyObject *enclosingObject, } } // PYSIDE-510: Here is the single change to support signatures. - if (SbkSpecial_Type_Ready(enclosingObject, reinterpret_cast<PyTypeObject *>(type), signatureStrings) < 0) + if (SbkSpecial_Type_Ready(enclosingObject, reinterpret_cast<PyTypeObject *>(type), signatureStrings) < 0) { + std::cerr << "Warning: " << __FUNCTION__ << " returns nullptr for " + << typeName << '/' << originalName << " due to SbkSpecial_Type_Ready() failing\n"; return nullptr; + } initPrivateData(type); auto sotp = PepType_SOTP(type); @@ -936,7 +941,13 @@ introduceWrapperType(PyObject *enclosingObject, // PyModule_AddObject steals type's reference. Py_INCREF(ob_type); - return PyModule_AddObject(enclosingObject, typeName, ob_type) == 0 ? type : nullptr; + if (PyModule_AddObject(enclosingObject, typeName, ob_type) != 0) { + std::cerr << "Warning: " << __FUNCTION__ << " returns nullptr for " + << typeName << '/' << originalName << " due to PyModule_AddObject(enclosingObject=" + << enclosingObject << ",ob_type=" << ob_type << ") failing\n"; + return nullptr; + } + return type; } void setSubTypeInitHook(SbkObjectType *type, SubTypeInitHook func) diff --git a/sources/shiboken2/libshiboken/helper.cpp b/sources/shiboken2/libshiboken/helper.cpp index 013080b6e..c14bde15c 100644 --- a/sources/shiboken2/libshiboken/helper.cpp +++ b/sources/shiboken2/libshiboken/helper.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt for Python. @@ -40,6 +40,10 @@ #include "helper.h" #include "sbkstring.h" #include "sbkstaticstrings.h" + +#include <iomanip> +#include <iostream> + #include <stdarg.h> #ifdef _WIN32 @@ -48,9 +52,88 @@ # include <pthread.h> #endif +static void formatPyTypeObject(const PyTypeObject *obj, std::ostream &str) +{ + if (obj) { + str << '"' << obj->tp_name << "\", 0x" << std::hex + << obj->tp_flags << std::dec; + if (obj->tp_flags & Py_TPFLAGS_HEAPTYPE) + str << " [heaptype]"; + if (obj->tp_flags & Py_TPFLAGS_BASETYPE) + str << " [base]"; + if (obj->tp_flags & Py_TPFLAGS_HAVE_GC) + str << " [gc]"; + if (obj->tp_flags & Py_TPFLAGS_LONG_SUBCLASS) + str << " [long]"; + if (obj->tp_flags & Py_TPFLAGS_LIST_SUBCLASS) + str << " [list]"; + if (obj->tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS) + str << " [tuple]"; + if (obj->tp_flags & Py_TPFLAGS_BYTES_SUBCLASS) + str << " [bytes]"; + if (obj->tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS) + str << " [unicode]"; + if (obj->tp_flags & Py_TPFLAGS_DICT_SUBCLASS) + str << " [dict]"; + if (obj->tp_flags & Py_TPFLAGS_TYPE_SUBCLASS) + str << " [type]"; + if (obj->tp_flags & Py_TPFLAGS_IS_ABSTRACT) + str << " [abstract]"; + } else { + str << '0'; + } +} + +static void formatPyObject(PyObject *obj, std::ostream &str) +{ + if (obj) { + formatPyTypeObject(obj->ob_type, str); + str << ", "; + if (PyLong_Check(obj)) + str << PyLong_AsLong(obj); + else if (PyFloat_Check(obj)) + str << PyFloat_AsDouble(obj); +#ifdef IS_PY3K + else if (PyUnicode_Check(obj)) + str << '"' << _PepUnicode_AsString(obj) << '"'; +#else + else if (PyString_Check(obj)) + str << '"' << PyString_AsString(obj) << '"'; +#endif + else + str << "<unknown>"; + } else { + str << '0'; + } +} + namespace Shiboken { +debugPyObject::debugPyObject(PyObject *o) : m_object(o) +{ +} + +debugPyTypeObject::debugPyTypeObject(const PyTypeObject *o) : m_object(o) +{ +} + +std::ostream &operator<<(std::ostream &str, const debugPyTypeObject &o) +{ + str << "PyTypeObject("; + formatPyTypeObject(o.m_object, str); + str << ')'; + return str; +} + +std::ostream &operator<<(std::ostream &str, const debugPyObject &o) +{ + str << "PyObject("; + formatPyObject(o.m_object, str); + str << ')'; + return str; +} + // PySide-510: Changed from PySequence to PyList, which is correct. bool listToArgcArgv(PyObject *argList, int *argc, char ***argv, const char *defaultAppName) { @@ -125,7 +208,7 @@ int warning(PyObject *category, int stacklevel, const char *format, ...) { va_list args; va_start(args, format); -#if _WIN32 +#ifdef _WIN32 va_list args2 = args; #else va_list args2; diff --git a/sources/shiboken2/libshiboken/helper.h b/sources/shiboken2/libshiboken/helper.h index 14aae8028..7e46f3d93 100644 --- a/sources/shiboken2/libshiboken/helper.h +++ b/sources/shiboken2/libshiboken/helper.h @@ -44,6 +44,8 @@ #include "shibokenmacros.h" #include "autodecref.h" +#include <iosfwd> + #define SBK_UNUSED(x) (void)(x); namespace Shiboken @@ -99,6 +101,24 @@ LIBSHIBOKEN_API ThreadId mainThreadId(); */ LIBSHIBOKEN_API int warning(PyObject *category, int stacklevel, const char *format, ...); +struct LIBSHIBOKEN_API debugPyObject +{ + explicit debugPyObject(PyObject *o); + + PyObject *m_object; +}; + +struct LIBSHIBOKEN_API debugPyTypeObject +{ + explicit debugPyTypeObject(const PyTypeObject *o); + + const PyTypeObject *m_object; +}; + +LIBSHIBOKEN_API std::ostream &operator<<(std::ostream &str, const debugPyObject &o); +LIBSHIBOKEN_API std::ostream &operator<<(std::ostream &str, const debugPyTypeObject &o); + } // namespace Shiboken + #endif // HELPER_H diff --git a/sources/shiboken2/shiboken_version.py b/sources/shiboken2/shiboken_version.py index 0e0943143..c022fc803 100644 --- a/sources/shiboken2/shiboken_version.py +++ b/sources/shiboken2/shiboken_version.py @@ -38,8 +38,8 @@ ############################################################################# major_version = "5" -minor_version = "14" -patch_version = "2" +minor_version = "15" +patch_version = "0" # For example: "a", "b", "rc" # (which means "alpha", "beta", "release candidate"). diff --git a/sources/shiboken2/tests/helper.py b/sources/shiboken2/tests/helper.py new file mode 100644 index 000000000..2564c91d4 --- /dev/null +++ b/sources/shiboken2/tests/helper.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2019 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite 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$ +## +############################################################################# + + +def objectFullname(t): + module = t.__module__ + if module is None or module == str.__class__.__module__: + return t.__name__ + else: + return module + '.' + t.__name__ diff --git a/sources/shiboken2/tests/libother/CMakeLists.txt b/sources/shiboken2/tests/libother/CMakeLists.txt index 6aba91e13..d1e4c4354 100644 --- a/sources/shiboken2/tests/libother/CMakeLists.txt +++ b/sources/shiboken2/tests/libother/CMakeLists.txt @@ -5,12 +5,13 @@ number.cpp otherderived.cpp otherobjecttype.cpp othermultiplederived.cpp +smartptrtester.cpp ) add_library(libother SHARED ${libother_SRC}) target_include_directories(libother PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(libother PRIVATE LIBOTHER_BUILD) -target_link_libraries(libother PUBLIC libsample) +target_link_libraries(libother PUBLIC libsample libsmart) set_property(TARGET libother PROPERTY PREFIX "") diff --git a/sources/shiboken2/tests/libother/otherobjecttype.cpp b/sources/shiboken2/tests/libother/otherobjecttype.cpp index ca356ce94..1f782ecd8 100644 --- a/sources/shiboken2/tests/libother/otherobjecttype.cpp +++ b/sources/shiboken2/tests/libother/otherobjecttype.cpp @@ -34,3 +34,13 @@ operator<<(Collector& collector, const OtherObjectType& obj) collector << obj.identifier()*2; return collector; } + +int OtherObjectType::enumAsInt(SampleNamespace::SomeClass::PublicScopedEnum value) +{ + return static_cast<int>(value); +} + +int OtherObjectType::enumAsIntForInvisibleNamespace(Invisible::EnumOnNamespace value) +{ + return static_cast<int>(value); +} diff --git a/sources/shiboken2/tests/libother/otherobjecttype.h b/sources/shiboken2/tests/libother/otherobjecttype.h index 22687c8bd..efd394347 100644 --- a/sources/shiboken2/tests/libother/otherobjecttype.h +++ b/sources/shiboken2/tests/libother/otherobjecttype.h @@ -35,11 +35,14 @@ #include "libothermacros.h" #include "objecttype.h" #include "collector.h" +#include "samplenamespace.h" -class OtherObjectType : public ObjectType + +class LIBOTHER_API OtherObjectType : public ObjectType { public: - + static int enumAsInt(SampleNamespace::SomeClass::PublicScopedEnum value); + static int enumAsIntForInvisibleNamespace(Invisible::EnumOnNamespace value); }; diff --git a/sources/shiboken2/tests/libother/smartptrtester.cpp b/sources/shiboken2/tests/libother/smartptrtester.cpp new file mode 100644 index 000000000..9636c7521 --- /dev/null +++ b/sources/shiboken2/tests/libother/smartptrtester.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite 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 "smartptrtester.h" + +SharedPtr<Str> SmartPtrTester::createSharedPtrStr(const char *what) +{ + return SharedPtr<Str>(new Str(what)); +} + +std::string SmartPtrTester::valueOfSharedPtrStr(const SharedPtr<Str> &str) +{ + return str->cstring(); +} + +SharedPtr<Integer> SmartPtrTester::createSharedPtrInteger(int v) +{ + auto i = SharedPtr<Integer>(new Integer); + i->m_int = v; + return i; +} + +int SmartPtrTester::valueOfSharedPtrInteger(const SharedPtr<Integer> &v) +{ + return v->m_int; +} + +void SmartPtrTester::fiddleInt(const SharedPtr<int> &) // no binding, should not cause errors +{ +} diff --git a/sources/shiboken2/tests/libother/smartptrtester.h b/sources/shiboken2/tests/libother/smartptrtester.h new file mode 100644 index 000000000..a560bcf2f --- /dev/null +++ b/sources/shiboken2/tests/libother/smartptrtester.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + +#ifndef SMARTPTRTESTER_H +#define SMARTPTRTESTER_H + +#include "libothermacros.h" + +#include <smart.h> +#include <str.h> + +class LIBOTHER_API SmartPtrTester +{ +public: + SharedPtr<Str> createSharedPtrStr(const char *what); + std::string valueOfSharedPtrStr(const SharedPtr<Str> &); + + SharedPtr<Integer> createSharedPtrInteger(int v); + int valueOfSharedPtrInteger(const SharedPtr<Integer> &); + + void fiddleInt(const SharedPtr<int> &); +}; + +#endif // SMARTPTRTESTER_H diff --git a/sources/shiboken2/tests/libsample/CMakeLists.txt b/sources/shiboken2/tests/libsample/CMakeLists.txt index 170829fbc..ae13cd9f2 100644 --- a/sources/shiboken2/tests/libsample/CMakeLists.txt +++ b/sources/shiboken2/tests/libsample/CMakeLists.txt @@ -36,6 +36,7 @@ pointf.cpp polygon.cpp protected.cpp reference.cpp +renaming.cpp sample.cpp samplenamespace.cpp sbkdate.cpp diff --git a/sources/shiboken2/tests/libsample/renaming.cpp b/sources/shiboken2/tests/libsample/renaming.cpp new file mode 100644 index 000000000..30586e1db --- /dev/null +++ b/sources/shiboken2/tests/libsample/renaming.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite 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 "renaming.h" + +#include <iostream> + +int ToBeRenamedValue::value() const +{ + return m_value; +} + +void ToBeRenamedValue::setValue(int v) +{ + m_value = v; +} + +void RenamedUser::useRenamedValue(const ToBeRenamedValue &v) +{ + std::cout << __FUNCTION__ << ' ' << v.value() << '\n'; +} diff --git a/sources/shiboken2/tests/libsample/renaming.h b/sources/shiboken2/tests/libsample/renaming.h new file mode 100644 index 000000000..cd88b36bf --- /dev/null +++ b/sources/shiboken2/tests/libsample/renaming.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + +#ifndef RENAMING_H +#define RENAMING_H + +#include "libsamplemacros.h" + +class LIBSAMPLE_API ToBeRenamedValue +{ +public: + int value() const; + void setValue(int v); + +private: + int m_value = 42; +}; + +class LIBSAMPLE_API RenamedUser +{ +public: + void useRenamedValue(const ToBeRenamedValue &v); +}; + +#endif // POINT_H diff --git a/sources/shiboken2/tests/libsample/samplenamespace.h b/sources/shiboken2/tests/libsample/samplenamespace.h index 6868b5f0a..9e46b2ad6 100644 --- a/sources/shiboken2/tests/libsample/samplenamespace.h +++ b/sources/shiboken2/tests/libsample/samplenamespace.h @@ -51,6 +51,13 @@ enum EnumOnNamespace { Option3 = 3 }; +struct ObjectOnInvisibleNamespace +{ + bool exists() const { return true; } + static int toInt(EnumOnNamespace e) { return static_cast<int>(e); } + static ObjectOnInvisibleNamespace consume(const ObjectOnInvisibleNamespace &other) { return other; } +}; + }; namespace SampleNamespace @@ -137,6 +144,8 @@ protected: PublicScopedEnum protectedMethodReturningPublicScopedEnum() const; }; +LIBSAMPLE_API inline int enumAsInt(SomeClass::PublicScopedEnum value) { return static_cast<int>(value); } + class DerivedFromNamespace : public SomeClass::SomeInnerClass::OkThisIsRecursiveEnough { public: diff --git a/sources/shiboken2/tests/libsmart/smart.cpp b/sources/shiboken2/tests/libsmart/smart.cpp index 6a4deb50a..81fa30c7e 100644 --- a/sources/shiboken2/tests/libsmart/smart.cpp +++ b/sources/shiboken2/tests/libsmart/smart.cpp @@ -93,7 +93,7 @@ Obj::~Obj() void Obj::printObj() { if (shouldPrint()) { std::cout << "integer value: " << m_integer - << " internal integer value: " << m_internalInteger->m_int << '\n'; + << " internal integer value: " << m_internalInteger->value() << '\n'; } } @@ -134,6 +134,17 @@ int Obj::takeSharedPtrToObj(SharedPtr<Obj> pObj) int Obj::takeSharedPtrToInteger(SharedPtr<Integer> pInt) { pInt->printInteger(); + return pInt->value(); +} + +SharedPtr<const Integer> Obj::giveSharedPtrToConstInteger() +{ + SharedPtr<const Integer> co(new Integer); + return co; +} + +int Obj::takeSharedPtrToConstInteger(SharedPtr<const Integer> pInt) +{ return pInt->m_int; } @@ -173,7 +184,17 @@ Integer::~Integer() std::cout << "Integer destructor " << this << '\n'; } -void Integer::printInteger() +int Integer::value() const +{ + return m_int; +} + +void Integer::setValue(int v) +{ + m_int = v; +} + +void Integer::printInteger() const { if (shouldPrint()) std::cout << "Integer value for object " << this << " is " << m_int << '\n'; diff --git a/sources/shiboken2/tests/libsmart/smart_integer.h b/sources/shiboken2/tests/libsmart/smart_integer.h index 3756f68b0..126894120 100644 --- a/sources/shiboken2/tests/libsmart/smart_integer.h +++ b/sources/shiboken2/tests/libsmart/smart_integer.h @@ -37,8 +37,12 @@ public: Integer(const Integer &other); Integer &operator=(const Integer &other); ~Integer(); - void printInteger(); - int m_int; + void printInteger() const; + + int value() const; + void setValue(int v); + + int m_int; // public for testing member field access. }; namespace Smart { diff --git a/sources/shiboken2/tests/libsmart/smart_obj.h b/sources/shiboken2/tests/libsmart/smart_obj.h index 12425366e..8fe45993f 100644 --- a/sources/shiboken2/tests/libsmart/smart_obj.h +++ b/sources/shiboken2/tests/libsmart/smart_obj.h @@ -48,12 +48,14 @@ public: Integer takeInteger(Integer val); SharedPtr<Obj> giveSharedPtrToObj(); std::vector<SharedPtr<Obj> > giveSharedPtrToObjList(int size); - SharedPtr<Integer> giveSharedPtrToInteger(); + virtual SharedPtr<Integer> giveSharedPtrToInteger(); // virtual for PYSIDE-1188 + SharedPtr<const Integer> giveSharedPtrToConstInteger(); + int takeSharedPtrToConstInteger(SharedPtr<const Integer> pInt); SharedPtr<Smart::Integer2> giveSharedPtrToInteger2(); int takeSharedPtrToObj(SharedPtr<Obj> pObj); int takeSharedPtrToInteger(SharedPtr<Integer> pInt); - int m_integer; + int m_integer; // public for testing member field access. Integer *m_internalInteger; }; diff --git a/sources/shiboken2/tests/otherbinding/CMakeLists.txt b/sources/shiboken2/tests/otherbinding/CMakeLists.txt index bc5c4bdad..05a282838 100644 --- a/sources/shiboken2/tests/otherbinding/CMakeLists.txt +++ b/sources/shiboken2/tests/otherbinding/CMakeLists.txt @@ -10,6 +10,8 @@ ${CMAKE_CURRENT_BINARY_DIR}/other/number_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/other/otherderived_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/other/othermultiplederived_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/other/otherobjecttype_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/other/sharedptr_str_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/other/smartptrtester_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/other/other_module_wrapper.cpp ) @@ -28,8 +30,9 @@ COMMENT "Running generator for 'other' test binding..." add_library(other MODULE ${other_SRC}) target_include_directories(other PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} - ${sample_BINARY_DIR}/sample) -target_link_libraries(other PUBLIC libother libsample libshiboken) + ${sample_BINARY_DIR}/sample + ${smart_BINARY_DIR}/smart) +target_link_libraries(other PUBLIC libother libsample libsmart libshiboken) set_property(TARGET other PROPERTY PREFIX "") set_property(TARGET other PROPERTY OUTPUT_NAME "other${PYTHON_EXTENSION_SUFFIX}") @@ -38,6 +41,6 @@ if(WIN32) endif() -add_dependencies(other sample) +add_dependencies(other sample smart) create_generator_target(other) diff --git a/sources/shiboken2/tests/otherbinding/global.h b/sources/shiboken2/tests/otherbinding/global.h index 0fccabb92..763566ae0 100644 --- a/sources/shiboken2/tests/otherbinding/global.h +++ b/sources/shiboken2/tests/otherbinding/global.h @@ -32,4 +32,5 @@ #include "otherderived.h" #include "otherobjecttype.h" #include "othermultiplederived.h" +#include "smartptrtester.h" diff --git a/sources/shiboken2/tests/otherbinding/other-binding.txt.in b/sources/shiboken2/tests/otherbinding/other-binding.txt.in index a17b70fc1..dbe935a9f 100644 --- a/sources/shiboken2/tests/otherbinding/other-binding.txt.in +++ b/sources/shiboken2/tests/otherbinding/other-binding.txt.in @@ -8,11 +8,13 @@ typesystem-file = @other_TYPESYSTEM@ output-directory = @CMAKE_CURRENT_BINARY_DIR@ include-path = @libother_SOURCE_DIR@ +include-path = @libsmart_SOURCE_DIR@ include-path = @libsample_SOURCE_DIR@ include-path = @libsample_SOURCE_DIR@/.. typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@ typesystem-path = @sample_SOURCE_DIR@ +typesystem-path = @smart_SOURCE_DIR@ enable-parent-ctor-heuristic diff --git a/sources/shiboken2/tests/otherbinding/signature_test.py b/sources/shiboken2/tests/otherbinding/signature_test.py new file mode 100644 index 000000000..06894eaf8 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/signature_test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2019 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite 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$ +## +############################################################################# + +'''Test cases for functions signature''' + +import os +import sys +import unittest + +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from shiboken_paths import init_paths +init_paths() + +from other import OtherObjectType +from helper import objectFullname + +class SignatureTest(unittest.TestCase): + + # Check if the argument of 'OtherObjectType::enumAsInt(SampleNamespace::SomeClass::PublicScopedEnum value)' + # has the correct representation + def testNamespaceFromOtherModule(self): + argType = OtherObjectType.enumAsInt.__signature__.parameters['value'].annotation + self.assertEqual(objectFullname(argType), 'sample.SampleNamespace.SomeClass.PublicScopedEnum') + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/otherbinding/smartptr_test.py b/sources/shiboken2/tests/otherbinding/smartptr_test.py new file mode 100644 index 000000000..04f657757 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/smartptr_test.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite 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$ +## +############################################################################# + +'''Test cases for the SmartPtrTester class''' + +import os +import sys +import unittest + +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from shiboken_paths import init_paths +init_paths() + +from smart import Integer +from sample import Str +from other import SmartPtrTester + + +class SmartPtrTest(unittest.TestCase): + '''Test case for the SmartPtrTester class''' + + def test(self): + tester = SmartPtrTester() + + integerPtr = tester.createSharedPtrInteger(42) + self.assertEqual(tester.valueOfSharedPtrInteger(integerPtr), 42) + + strPtr = tester.createSharedPtrStr('hello') + self.assertEqual(tester.valueOfSharedPtrStr(strPtr), 'hello') + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/otherbinding/typesystem_other.xml b/sources/shiboken2/tests/otherbinding/typesystem_other.xml index 2932dafb3..78c4dd016 100644 --- a/sources/shiboken2/tests/otherbinding/typesystem_other.xml +++ b/sources/shiboken2/tests/otherbinding/typesystem_other.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <typesystem package="other"> <load-typesystem name="typesystem_sample.xml" generate="no" /> + <load-typesystem name="typesystem_smart.xml" generate="no" /> <object-type name="OtherObjectType" /> <object-type name="OtherDerived" /> @@ -9,6 +10,10 @@ <value-type name="ExtendsNoImplicitConversion" /> <value-type name="Number" /> + <smart-pointer-type name="SharedPtr" type="shared" getter="data" ref-count-method="useCount" + instantiations="Str"/> + <value-type name="SmartPtrTester"/> + <suppress-warning text="signature 'operator!=(ByteArray,const char*)' for function modification in 'ByteArray' not found." /> <suppress-warning text="signature 'operator+(ByteArray,const char*)' for function modification in 'ByteArray' not found." /> <suppress-warning text="signature 'operator==(ByteArray,const char*)' for function modification in 'ByteArray' not found." /> diff --git a/sources/shiboken2/tests/samplebinding/CMakeLists.txt b/sources/shiboken2/tests/samplebinding/CMakeLists.txt index 61090d30e..b65068dc3 100644 --- a/sources/shiboken2/tests/samplebinding/CMakeLists.txt +++ b/sources/shiboken2/tests/samplebinding/CMakeLists.txt @@ -94,6 +94,8 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/rect_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/rectf_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/reference_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/referentmodelindex_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/toberenamedvalue_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/renameduser_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/sample_module_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/sample_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/sample_sample_wrapper.cpp @@ -123,6 +125,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/filter_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/data_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/intersection_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/union_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/invisible_objectoninvisiblenamespace_wrapper.cpp ) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/sample-binding.txt.in" diff --git a/sources/shiboken2/tests/samplebinding/global.h b/sources/shiboken2/tests/samplebinding/global.h index 3984102a8..f4e20b74f 100644 --- a/sources/shiboken2/tests/samplebinding/global.h +++ b/sources/shiboken2/tests/samplebinding/global.h @@ -75,6 +75,7 @@ #include "protected.h" #include "rect.h" #include "reference.h" +#include "renaming.h" #include "removednamespaces.h" #include "sample.h" #include "samplenamespace.h" diff --git a/sources/shiboken2/tests/samplebinding/namespace_test.py b/sources/shiboken2/tests/samplebinding/namespace_test.py index aeaf81cff..b1977cf6f 100644 --- a/sources/shiboken2/tests/samplebinding/namespace_test.py +++ b/sources/shiboken2/tests/samplebinding/namespace_test.py @@ -40,12 +40,17 @@ from shiboken_paths import init_paths init_paths() from sample import * +from helper import objectFullname class TestEnumUnderNamespace(unittest.TestCase): def testInvisibleNamespace(self): o1 = EnumOnNamespace.Option1 self.assertEqual(o1, 1) + def testTpNames(self): + self.assertEqual(objectFullname(EnumOnNamespace), "sample.EnumOnNamespace") + self.assertEqual(str(EnumOnNamespace.Option1), + "sample.EnumOnNamespace.Option1") class TestClassesUnderNamespace(unittest.TestCase): def testIt(self): @@ -72,5 +77,19 @@ class TestClassesUnderNamespace(unittest.TestCase): self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum), "<class 'sample.SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum'>") + # Test if enum inside of class is correct represented + self.assertEqual(objectFullname(SampleNamespace.enumInEnumOut.__signature__.parameters['in_'].annotation), + "sample.SampleNamespace.InValue") + self.assertEqual(objectFullname(SampleNamespace.enumAsInt.__signature__.parameters['value'].annotation), + "sample.SampleNamespace.SomeClass.PublicScopedEnum") + self.assertEqual(objectFullname(ObjectOnInvisibleNamespace.toInt.__signature__.parameters['e'].annotation), + "sample.EnumOnNamespace") + + # Test if enum on namespace that was marked as not gerenated does not appear on type name + self.assertEqual(objectFullname(ObjectOnInvisibleNamespace), + "sample.ObjectOnInvisibleNamespace") + self.assertEqual(objectFullname(ObjectOnInvisibleNamespace.consume.__signature__.parameters['other'].annotation), + "sample.ObjectOnInvisibleNamespace") + if __name__ == '__main__': unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/renaming_test.py b/sources/shiboken2/tests/samplebinding/renaming_test.py new file mode 100644 index 000000000..cb59dce3a --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/renaming_test.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2019 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite 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$ +## +############################################################################# + +'''Test cases for renaming using target-lang-name attribute.''' + +import os +import re +import sys +import unittest + +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from shiboken_paths import init_paths +init_paths() + +from sample import RenamedValue, RenamedUser + +class RenamingTest(unittest.TestCase): + def test(self): + '''Tests whether the C++ class ToBeRenamedValue renamed via attribute + target-lang-name to RenamedValue shows up in consuming function + signature strings correctly. + ''' + renamed_value = RenamedValue() + self.assertEqual(str(type(renamed_value)), + "<class 'sample.RenamedValue'>") + rename_user = RenamedUser() + rename_user.useRenamedValue(renamed_value) + actual_signature = str(rename_user.useRenamedValue.__signature__) + self.assertTrue(re.match(r"^\(self,\s*v:\s*sample.RenamedValue\)$", + actual_signature)) + + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml index 30ad5def7..c3db91324 100644 --- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml +++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml @@ -543,8 +543,9 @@ <enum-type identified-by-value="AnonymousGlobalEnum_Value0"/> - <namespace-type name="Invisible" generate="no"> + <namespace-type name="Invisible" visible="no"> <enum-type name="EnumOnNamespace" /> + <value-type name="ObjectOnInvisibleNamespace" /> </namespace-type> <namespace-type name="SampleNamespace"> @@ -2432,6 +2433,9 @@ <modify-function signature="dummy(std::list<std::pair<BlackBox *, BlackBox *> > &)" rename="dummy_method" /> </object-type> + <value-type name="ToBeRenamedValue" target-lang-name="RenamedValue"/> + <value-type name="RenamedUser"/> + <suppress-warning text="horribly broken type '__off64_t'" /> <suppress-warning text="enum '__codecvt_result' does not have a type entry or is not an enum" /> <suppress-warning text="Pure virtual method "Abstract::hideFunction(HideType*)" must be implement but was completely removed on typesystem." /> diff --git a/sources/shiboken2/tests/smartbinding/smart_pointer_test.py b/sources/shiboken2/tests/smartbinding/smart_pointer_test.py index 6210916d3..50b2120a2 100644 --- a/sources/shiboken2/tests/smartbinding/smart_pointer_test.py +++ b/sources/shiboken2/tests/smartbinding/smart_pointer_test.py @@ -128,6 +128,10 @@ class SmartPointerTests(unittest.TestCase): self.assertEqual(integer.m_int, 50) # Set and get a member value via shared pointer (like operator->). + ptrToInteger.setValue(150) + self.assertEqual(ptrToInteger.value(), 150) + + # Set and get a member field via shared pointer (like operator->). ptrToInteger.m_int = 100 self.assertEqual(ptrToInteger.m_int, 100) @@ -155,6 +159,18 @@ class SmartPointerTests(unittest.TestCase): self.assertEqual(objCount(), 0) self.assertEqual(integerCount(), 0) + def testConstIntegerSmartPointer(self): + # Uncomment to see more debug info about creation of objects and ref counts. + # Registry.getInstance().setShouldPrint(True) + + # Create Obj. + o = Obj() + ptrToConstInteger = o.giveSharedPtrToConstInteger() + self.assertEqual(ptrToConstInteger.m_int, 456) + result = o.takeSharedPtrToConstInteger(ptrToConstInteger) + self.assertEqual(result, 456) + self.assertEqual(ptrToConstInteger.value(), 456) + def testSmartPointersWithNamespace(self): # Create the main object o = Obj() diff --git a/sources/shiboken2/tests/smartbinding/typesystem_smart.xml b/sources/shiboken2/tests/smartbinding/typesystem_smart.xml index 0bb485957..8fb3082a0 100644 --- a/sources/shiboken2/tests/smartbinding/typesystem_smart.xml +++ b/sources/shiboken2/tests/smartbinding/typesystem_smart.xml @@ -43,7 +43,8 @@ possible to explicitly instantiate a new shared pointer in python e.g. o = SharedPtr_Foo() won't work. --> - <smart-pointer-type name="SharedPtr" type="shared" getter="data" ref-count-method="useCount" /> + <smart-pointer-type name="SharedPtr" type="shared" getter="data" ref-count-method="useCount" + instantiations="Integer,Smart::Integer2,Obj"/> <object-type name="Obj" /> <value-type name="Integer" /> |