diff options
Diffstat (limited to 'sources/shiboken6/ApiExtractor')
150 files changed, 5543 insertions, 3583 deletions
diff --git a/sources/shiboken6/ApiExtractor/CMakeLists.txt b/sources/shiboken6/ApiExtractor/CMakeLists.txt index f3337edc8..7aa2fbd11 100644 --- a/sources/shiboken6/ApiExtractor/CMakeLists.txt +++ b/sources/shiboken6/ApiExtractor/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + project(apiextractor) cmake_minimum_required(VERSION 3.18) @@ -6,50 +9,78 @@ cmake_policy(VERSION 3.18) set(CMAKE_AUTOMOC ON) set(apiextractor_SRC -apiextractor.cpp -apiextractorresult.cpp -abstractmetaargument.cpp -abstractmetabuilder.cpp +abstractmetaargument.cpp abstractmetaargument.h +abstractmetabuilder.cpp abstractmetabuilder.h abstractmetabuilder_p.h abstractmetabuilder_helpers.cpp -abstractmetaenum.cpp -abstractmetafield.cpp -abstractmetafunction.cpp -abstractmetatype.cpp -abstractmetalang.cpp -addedfunction.cpp -classdocumentation.cpp -codesnip.cpp -codesniphelpers.cpp -conditionalstreamreader.cpp -customconversion.cpp -documentation.cpp -dotview.cpp -enclosingclassmixin.cpp -fileout.cpp -messages.cpp -modifications.cpp -predefined_templates.cpp -propertyspec.cpp -pymethoddefentry.cpp -reporthandler.cpp -sourcelocation.cpp -typeparser.cpp -typesystem.cpp -typesystemparser.cpp -include.cpp -typedatabase.cpp -textstream.cpp +abstractmetaenum.cpp abstractmetaenum.h +abstractmetafield.cpp abstractmetafield.h +abstractmetafunction.cpp abstractmetafunction.h +abstractmetalang.cpp abstractmetalang.h abstractmetalang_helpers.h abstractmetalang_typedefs.h +abstractmetatype.cpp abstractmetatype.h +addedfunction.cpp addedfunction.h addedfunction_p.h +anystringview_helpers.cpp anystringview_helpers.h +apiextractor.cpp apiextractor.h apiextractorflags.h +apiextractorresult.cpp apiextractorresult.h +arraytypeentry.h +classdocumentation.cpp classdocumentation.h +codesnip.cpp codesnip.h +codesniphelpers.cpp codesniphelpers.h +complextypeentry.h +conditionalstreamreader.cpp conditionalstreamreader.h +configurabletypeentry.h +constantvaluetypeentry.h +containertypeentry.h +customconversion.cpp customconversion.h customconversion_typedefs.h +customtypenentry.h +debughelpers_p.h +dependency.h +documentation.cpp documentation.h +dotview.cpp dotview.h +enclosingclassmixin.cpp enclosingclassmixin.h +enumtypeentry.h +enumvaluetypeentry.h +exception.h +fileout.cpp fileout.h +flagstypeentry.h +functiontypeentry.h +graph.h +header_paths.h +include.cpp include.h +messages.cpp messages.h +modifications.cpp modifications.h modifications_typedefs.h +namespacetypeentry.h +objecttypeentry.h +optionsparser.cpp optionsparser.h +predefined_templates.cpp predefined_templates.h +primitivetypeentry.h +propertyspec.cpp propertyspec.h +pymethoddefentry.cpp pymethoddefentry.h +pythontypeentry.h +reporthandler.cpp reporthandler.h +smartpointertypeentry.h +sourcelocation.cpp sourcelocation.h +templateargumententry.h +textstream.cpp textstream.h +typedatabase.cpp typedatabase.h typedatabase_p.h typedatabase_typedefs.h +typedefentry.h +typeparser.cpp typeparser.h +typesystem.cpp typesystem.h typesystem_enums.h typesystem_typedefs.h +typesystemparser.cpp typesystemparser_p.h +usingmember.h +valuetypeentry.h +varargstypeentry.h +voidtypeentry.h +xmlutils.cpp xmlutils.h xmlutils_libxslt.h xmlutils_qt.h # Clang -clangparser/compilersupport.cpp -clangparser/clangparser.cpp -clangparser/clangbuilder.cpp -clangparser/clangdebugutils.cpp -clangparser/clangutils.cpp +clangparser/clangbuilder.cpp clangparser/clangbuilder.h +clangparser/clangdebugutils.cpp clangparser/clangdebugutils.h +clangparser/clangparser.cpp clangparser/clangparser.h +clangparser/clangutils.cpp clangparser/clangutils.h +clangparser/compilersupport.cpp clangparser/compilersupport.h # Old parser -parser/typeinfo.cpp -parser/codemodel.cpp -parser/enumvalue.cpp -xmlutils.cpp +parser/codemodel.cpp parser/codemodel.h parser/codemodel_fwd.h parser/codemodel_enums.h +parser/enumvalue.cpp parser/enumvalue.h +parser/typeinfo.cpp parser/typeinfo.h ) find_package(LibXml2 2.6.32) @@ -87,9 +118,10 @@ if (HAS_LIBXSLT) endif() if (NOT DISABLE_DOCSTRINGS) - target_sources(apiextractor PRIVATE docparser.cpp - doxygenparser.cpp - qtdocparser.cpp) + target_sources(apiextractor PRIVATE + docparser.cpp docparser.h + doxygenparser.cpp doxygenparser.h + qtdocparser.cpp qtdocparser.h) endif() target_compile_definitions(apiextractor diff --git a/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp b/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp index bd6a80434..05cebe10a 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp @@ -38,9 +38,9 @@ AbstractMetaArgument::AbstractMetaArgument(const AbstractMetaArgument &) = defau AbstractMetaArgument &AbstractMetaArgument::operator=(const AbstractMetaArgument &) = default; -AbstractMetaArgument::AbstractMetaArgument(AbstractMetaArgument &&) = default; +AbstractMetaArgument::AbstractMetaArgument(AbstractMetaArgument &&) noexcept = default; -AbstractMetaArgument &AbstractMetaArgument::operator=(AbstractMetaArgument &&) = default; +AbstractMetaArgument &AbstractMetaArgument::operator=(AbstractMetaArgument &&) noexcept = default; const AbstractMetaType &AbstractMetaArgument::type() const { @@ -191,7 +191,7 @@ QDebug operator<<(QDebug d, const AbstractMetaArgument *aa) d.noquote(); d.nospace(); d << "AbstractMetaArgument("; - if (aa) + if (aa != nullptr) d << aa->toString(); else d << '0'; diff --git a/sources/shiboken6/ApiExtractor/abstractmetaargument.h b/sources/shiboken6/ApiExtractor/abstractmetaargument.h index 1e5e32613..38402e369 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetaargument.h +++ b/sources/shiboken6/ApiExtractor/abstractmetaargument.h @@ -19,9 +19,8 @@ public: ~AbstractMetaArgument(); AbstractMetaArgument(const AbstractMetaArgument &); AbstractMetaArgument &operator=(const AbstractMetaArgument &); - AbstractMetaArgument(AbstractMetaArgument &&); - AbstractMetaArgument &operator=(AbstractMetaArgument &&); - + AbstractMetaArgument(AbstractMetaArgument &&) noexcept; + AbstractMetaArgument &operator=(AbstractMetaArgument &&) noexcept; const AbstractMetaType &type() const; void setType(const AbstractMetaType &type); diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp index 4eff0ee62..9831f911b 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp @@ -9,6 +9,7 @@ #include "abstractmetatype.h" #include "addedfunction.h" #include "graph.h" +#include "debughelpers_p.h" #include "exception.h" #include "messages.h" #include "propertyspec.h" @@ -54,11 +55,9 @@ using namespace Qt::StringLiterals; -static inline QString colonColon() { return QStringLiteral("::"); } - static QString stripTemplateArgs(const QString &name) { - int pos = name.indexOf(u'<'); + const auto pos = name.indexOf(u'<'); return pos < 0 ? name : name.left(pos); } @@ -68,6 +67,31 @@ static void fixArgumentIndexes(AbstractMetaArgumentList *list) (*list)[i].setArgumentIndex(i); } +bool operator<(const RejectEntry &re1, const RejectEntry &re2) +{ + return re1.reason != re2.reason + ? (re1.reason < re2.reason) : (re1.sortkey < re2.sortkey); +} + +QTextStream &operator<<(QTextStream &str, const RejectEntry &re) +{ + str << re.signature; + if (!re.message.isEmpty()) + str << ": " << re.message; + return str; +} + +static void applyCachedFunctionModifications(AbstractMetaFunction *metaFunction, + const FunctionModificationList &functionMods) +{ + for (const FunctionModification &mod : functionMods) { + if (mod.exceptionHandling() != TypeSystem::ExceptionHandling::Unspecified) + metaFunction->setExceptionHandlingModification(mod.exceptionHandling()); + if (mod.allowThread() != TypeSystem::AllowThread::Unspecified) + metaFunction->setAllowThreadModification(mod.allowThread()); + } +} + bool AbstractMetaBuilderPrivate::m_useGlobalHeader = false; bool AbstractMetaBuilderPrivate::m_codeModelTestMode = false; @@ -76,13 +100,6 @@ AbstractMetaBuilderPrivate::AbstractMetaBuilderPrivate() : { } -AbstractMetaBuilderPrivate::~AbstractMetaBuilderPrivate() -{ - qDeleteAll(m_templates); - qDeleteAll(m_smartPointers); - qDeleteAll(m_metaClasses); -} - AbstractMetaBuilder::AbstractMetaBuilder() : d(new AbstractMetaBuilderPrivate) { d->q = this; @@ -144,18 +161,23 @@ const QHash<TypeEntryCPtr, AbstractMetaEnum> &AbstractMetaBuilder::typeEntryToEn return d->m_enums; } -void AbstractMetaBuilderPrivate::checkFunctionModifications() +const QMultiHash<QString, QString> &AbstractMetaBuilder::typedefTargetToName() const +{ + return d->m_typedefTargetToName; +} + +void AbstractMetaBuilderPrivate::checkFunctionModifications() const { const auto &entries = TypeDatabase::instance()->entries(); for (auto it = entries.cbegin(), end = entries.cend(); it != end; ++it) { TypeEntryCPtr entry = it.value(); - if (entry.isNull()) + if (!entry) continue; if (!entry->isComplex() || !entry->generateCode()) continue; - auto centry = qSharedPointerCast<const ComplexTypeEntry>(entry); + auto centry = std::static_pointer_cast<const ComplexTypeEntry>(entry); if (!centry->generateCode()) continue; @@ -168,7 +190,7 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications() QString name = signature.trimmed(); name.truncate(name.indexOf(u'(')); - AbstractMetaClass *clazz = AbstractMetaClass::findClass(m_metaClasses, centry); + const auto clazz = AbstractMetaClass::findClass(m_metaClasses, centry); if (!clazz) continue; @@ -198,15 +220,15 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications() } } -AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(const ArgumentModelItem &argument, - const AbstractMetaClass *currentClass) +AbstractMetaClassPtr AbstractMetaBuilderPrivate::argumentToClass(const ArgumentModelItem &argument, + const AbstractMetaClassCPtr ¤tClass) { - AbstractMetaClass *returned = nullptr; + AbstractMetaClassPtr returned; auto type = translateType(argument->type(), currentClass); if (!type.has_value()) return returned; TypeEntryCPtr entry = type->typeEntry(); - if (!entry.isNull() && entry->isComplex()) + if (entry && entry->isComplex()) returned = AbstractMetaClass::findClass(m_metaClasses, entry); return returned; } @@ -215,20 +237,20 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(const ArgumentMod * Checks the argument of a hash function and flags the type if it is a complex type */ void AbstractMetaBuilderPrivate::registerHashFunction(const FunctionModelItem &function_item, - AbstractMetaClass *currentClass) + const AbstractMetaClassPtr ¤tClass) { if (function_item->isDeleted()) return; ArgumentList arguments = function_item->arguments(); if (arguments.size() >= 1) { // (Class, Hash seed). - if (AbstractMetaClass *cls = argumentToClass(arguments.at(0), currentClass)) + if (AbstractMetaClassPtr cls = argumentToClass(arguments.at(0), currentClass)) cls->setHashFunction(function_item->name()); } } void AbstractMetaBuilderPrivate::registerToStringCapabilityIn(const NamespaceModelItem &nsItem) { - const FunctionList &streamOps = nsItem->findFunctions(u"operator<<"_s); + const FunctionList &streamOps = nsItem->findFunctions("operator<<"); for (const FunctionModelItem &item : streamOps) registerToStringCapability(item, nullptr); for (const NamespaceModelItem &ni : nsItem->namespaces()) @@ -240,13 +262,13 @@ void AbstractMetaBuilderPrivate::registerToStringCapabilityIn(const NamespaceMod */ void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelItem &function_item, - AbstractMetaClass *currentClass) + const AbstractMetaClassPtr ¤tClass) { ArgumentList arguments = function_item->arguments(); if (arguments.size() == 2) { if (arguments.at(0)->type().toString() == u"QDebug") { const ArgumentModelItem &arg = arguments.at(1); - if (AbstractMetaClass *cls = argumentToClass(arg, currentClass)) { + if (AbstractMetaClassPtr cls = argumentToClass(arg, currentClass)) { if (arg->type().indirections() < 2) cls->setToStringCapability(true, int(arg->type().indirections())); } @@ -255,7 +277,7 @@ void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelI } void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelItem &item, - AbstractMetaClass *currentClass) + const AbstractMetaClassPtr ¤tClass) { if (item->accessPolicy() != Access::Public) return; @@ -275,7 +297,7 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte } else { auto type = translateType(item->type(), currentClass); const auto retType = type.has_value() ? type->typeEntry() : TypeEntryCPtr{}; - AbstractMetaClass *otherArgClass = argumentToClass(itemArguments.at(1), currentClass); + const auto otherArgClass = argumentToClass(itemArguments.at(1), currentClass); if (otherArgClass && retType && (retType->isValue() || retType->isObject()) && retType != baseoperandClass->typeEntry() @@ -284,11 +306,14 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte firstArgumentIsSelf = false; } } - if (baseoperandClass == nullptr) + if (!baseoperandClass) { + rejectFunction(item, currentClass, AbstractMetaBuilder::UnmatchedOperator, + u"base operand class not found."_s); return; + } if (item->isSpaceshipOperator() && !item->isDeleted()) { - baseoperandClass->addSynthesizedComparisonOperators(); + AbstractMetaClass::addSynthesizedComparisonOperators(baseoperandClass); return; } @@ -325,7 +350,7 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte } metaFunction->setFlags(flags); metaFunction->setAccess(Access::Public); - baseoperandClass->addFunction(AbstractMetaFunctionCPtr(metaFunction)); + AbstractMetaClass::addFunction(baseoperandClass, AbstractMetaFunctionCPtr(metaFunction)); if (!metaFunction->arguments().isEmpty()) { const auto include = metaFunction->arguments().constFirst().type().typeEntry()->include(); baseoperandClass->typeEntry()->addArgumentInclude(include); @@ -334,7 +359,7 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte } bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem &item, - AbstractMetaClass *currentClass) + const AbstractMetaClassPtr ¤tClass) { ArgumentList itemArguments = item->arguments(); if (itemArguments.size() != 2 || item->accessPolicy() != Access::Public) @@ -361,10 +386,9 @@ bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem streamFunction->setArguments(arguments); - *streamFunction += AbstractMetaFunction::FinalInTargetLang; streamFunction->setAccess(Access::Public); - AbstractMetaClass *funcClass; + AbstractMetaClassPtr funcClass; if (!streamClass->typeEntry()->generateCode()) { AbstractMetaArgumentList reverseArgs = streamFunction->arguments(); @@ -377,7 +401,7 @@ bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem funcClass = streamClass; } - funcClass->addFunction(AbstractMetaFunctionCPtr(streamFunction)); + AbstractMetaClass::addFunction(funcClass, AbstractMetaFunctionCPtr(streamFunction)); auto funcTe = funcClass->typeEntry(); if (funcClass == streamClass) funcTe->addArgumentInclude(streamedClass->typeEntry()->include()); @@ -389,7 +413,7 @@ bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem static bool metaEnumLessThan(const AbstractMetaEnum &e1, const AbstractMetaEnum &e2) { return e1.fullName() < e2.fullName(); } -static bool metaClassLessThan(const AbstractMetaClass *c1, const AbstractMetaClass *c2) +static bool metaClassLessThan(const AbstractMetaClassCPtr &c1, const AbstractMetaClassCPtr &c2) { return c1->fullName() < c2->fullName(); } static bool metaFunctionLessThan(const AbstractMetaFunctionCPtr &f1, const AbstractMetaFunctionCPtr &f2) @@ -402,8 +426,8 @@ void AbstractMetaBuilderPrivate::sortLists() // this is a temporary solution before new type revision implementation // We need move QMetaObject register before QObject. Dependencies additionalDependencies; - if (auto qObjectClass = AbstractMetaClass::findClass(m_metaClasses, u"QObject")) { - if (auto qMetaObjectClass = AbstractMetaClass::findClass(m_metaClasses, u"QMetaObject")) { + if (auto qObjectClass = AbstractMetaClass::findClass(m_metaClasses, "QObject")) { + if (auto qMetaObjectClass = AbstractMetaClass::findClass(m_metaClasses, "QMetaObject")) { Dependency dependency; dependency.parent = qMetaObjectClass; dependency.child = qObjectClass; @@ -412,7 +436,7 @@ void AbstractMetaBuilderPrivate::sortLists() } m_metaClasses = classesTopologicalSorted(m_metaClasses, additionalDependencies); - for (AbstractMetaClass *cls : std::as_const(m_metaClasses)) + for (const auto &cls : std::as_const(m_metaClasses)) cls->sortFunctions(); // Ensure that indexes are in alphabetical order, roughly, except @@ -429,7 +453,7 @@ FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments, unsigned clangFlags) { clang::Builder builder; - builder.setSystemIncludes(TypeDatabase::instance()->systemIncludes()); + builder.setForceProcessSystemIncludes(TypeDatabase::instance()->forceProcessSystemIncludes()); if (addCompilerSupportArguments) { if (level == LanguageLevel::Default) level = clang::emulatedCompilerLanguageLevel(); @@ -437,7 +461,7 @@ FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments, + clang::languageLevelOption(level)); } FileModelItem result = clang::parse(arguments, addCompilerSupportArguments, - clangFlags, builder) + level, clangFlags, builder) ? builder.dom() : FileModelItem(); const clang::BaseVisitor::Diagnostics &diagnostics = builder.diagnostics(); if (const auto diagnosticsCount = diagnostics.size()) { @@ -456,7 +480,7 @@ static QStringList functionCandidates(const AbstractMetaFunctionCList &list, const QString &signature) { QString name = signature; - const int parenPos = name.indexOf(u'('); + const auto parenPos = name.indexOf(u'('); if (parenPos > 0) name.truncate(parenPos); QStringList result; @@ -477,18 +501,18 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, // Start the generation... const ClassList &typeValues = dom->classes(); - ReportHandler::startProgress("Generating class model (" - + QByteArray::number(typeValues.size()) + ")..."); + ReportHandler::startProgress("Generated class model (" + + QByteArray::number(typeValues.size()) + ")."); for (const ClassModelItem &item : typeValues) { - if (AbstractMetaClass *cls = traverseClass(dom, item, nullptr)) - addAbstractMetaClass(cls, item.data()); + if (const auto cls = traverseClass(dom, item, nullptr)) + addAbstractMetaClass(cls, item.get()); } // We need to know all global enums const EnumList &enums = dom->enums(); - ReportHandler::startProgress("Generating enum model (" - + QByteArray::number(enums.size()) + ")..."); + ReportHandler::startProgress("Generated enum model (" + + QByteArray::number(enums.size()) + ")."); for (const EnumModelItem &item : enums) { auto metaEnum = traverseEnum(item, nullptr, QSet<QString>()); if (metaEnum.has_value()) { @@ -498,19 +522,19 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, } const auto &namespaceTypeValues = dom->namespaces(); - ReportHandler::startProgress("Generating namespace model (" - + QByteArray::number(namespaceTypeValues.size()) + ")..."); + ReportHandler::startProgress("Generated namespace model (" + + QByteArray::number(namespaceTypeValues.size()) + ")."); for (const NamespaceModelItem &item : namespaceTypeValues) traverseNamespace(dom, item); // Go through all typedefs to see if we have defined any // specific typedefs to be used as classes. const TypeDefList typeDefs = dom->typeDefs(); - ReportHandler::startProgress("Resolving typedefs (" - + QByteArray::number(typeDefs.size()) + ")..."); + ReportHandler::startProgress("Resolved typedefs (" + + QByteArray::number(typeDefs.size()) + ")."); for (const TypeDefModelItem &typeDef : typeDefs) { - if (AbstractMetaClass *cls = traverseTypeDef(dom, typeDef, nullptr)) - addAbstractMetaClass(cls, typeDef.data()); + if (const auto cls = traverseTypeDef(dom, typeDef, nullptr)) + addAbstractMetaClass(cls, typeDef.get()); } traverseTypesystemTypedefs(); @@ -528,7 +552,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, continue; FunctionTypeEntryPtr funcEntry = types->findFunctionType(func->name()); - if (funcEntry.isNull() || !funcEntry->generateCode()) + if (!funcEntry || !funcEntry->generateCode()) continue; AbstractMetaFunction *metaFunc = traverseFunction(func, nullptr); @@ -548,8 +572,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, m_globalFunctions << metaFuncPtr; } - ReportHandler::startProgress("Fixing class inheritance..."); - for (AbstractMetaClass *cls : std::as_const(m_metaClasses)) { + ReportHandler::startProgress("Fixed class inheritance."); + for (const auto &cls : std::as_const(m_metaClasses)) { if (cls->needsInheritanceSetup()) { setupInheritance(cls); traverseUsingMembers(cls); @@ -561,14 +585,14 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, } } - ReportHandler::startProgress("Detecting inconsistencies in class model..."); - for (AbstractMetaClass *cls : std::as_const(m_metaClasses)) { - cls->fixFunctions(); + ReportHandler::startProgress("Checked for inconsistencies in class model."); + for (const auto &cls : std::as_const(m_metaClasses)) { + AbstractMetaClass::fixFunctions(cls); if (cls->canAddDefaultConstructor()) - cls->addDefaultConstructor(); + AbstractMetaClass::addDefaultConstructor(cls); if (cls->canAddDefaultCopyConstructor()) - cls->addDefaultCopyConstructor(); + AbstractMetaClass::addDefaultCopyConstructor(cls); const bool avoidProtectedHack = flags.testFlag(ApiExtractorFlag::AvoidProtectedHack); const bool vco = @@ -579,10 +603,10 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, const auto &allEntries = types->entries(); - ReportHandler::startProgress("Detecting inconsistencies in typesystem (" - + QByteArray::number(allEntries.size()) + ")..."); + ReportHandler::startProgress("Checked for inconsistencies in typesystem (" + + QByteArray::number(allEntries.size()) + ")."); for (auto it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) { - TypeEntryPtr entry = it.value(); + const TypeEntryPtr &entry = it.value(); if (!entry->isPrimitive()) { if ((entry->isValue() || entry->isObject()) && !types->shouldDropTypeEntry(entry->qualifiedCppName()) @@ -592,7 +616,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, && !AbstractMetaClass::findClass(m_metaClasses, entry)) { qCWarning(lcShiboken, "%s", qPrintable(msgTypeNotDefined(entry))); } else if (entry->generateCode() && entry->type() == TypeEntry::FunctionType) { - auto fte = qSharedPointerCast<const FunctionTypeEntry>(entry); + auto fte = std::static_pointer_cast<const FunctionTypeEntry>(entry); const QStringList &signatures = fte->signatures(); for (const QString &signature : signatures) { bool ok = false; @@ -610,9 +634,9 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, } } } else if (entry->isEnum() && entry->generateCode()) { - const auto enumEntry = qSharedPointerCast<const EnumTypeEntry>(entry); - AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses, - enumEntry->parent()); + const auto enumEntry = std::static_pointer_cast<const EnumTypeEntry>(entry); + const auto cls = AbstractMetaClass::findClass(m_metaClasses, + enumEntry->parent()); const bool enumFound = cls ? cls->findEnum(entry->targetLangEntryName()).has_value() @@ -629,7 +653,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, } { - const FunctionList &hashFunctions = dom->findFunctions(u"qHash"_s); + const FunctionList &hashFunctions = dom->findFunctions("qHash"); for (const FunctionModelItem &item : hashFunctions) registerHashFunction(item, nullptr); } @@ -652,13 +676,13 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, } } - ReportHandler::startProgress("Checking inconsistencies in function modifications..."); + ReportHandler::startProgress("Checked for inconsistencies in function modifications."); checkFunctionModifications(); - ReportHandler::startProgress("Writing log files..."); + ReportHandler::startProgress("Wrote log files."); - for (AbstractMetaClass *cls : std::as_const(m_metaClasses)) { + for (const auto &cls : std::as_const(m_metaClasses)) { // setupEquals(cls); // setupComparable(cls); setupExternalConversion(cls); @@ -702,10 +726,10 @@ bool AbstractMetaBuilder::build(const QByteArrayList &arguments, { const FileModelItem dom = d->buildDom(arguments, addCompilerSupportArguments, level, clangFlags); - if (dom.isNull()) + if (!dom) return false; if (ReportHandler::isDebug(ReportHandler::MediumDebug)) - qCDebug(lcShiboken) << dom.data(); + qCDebug(lcShiboken) << dom.get(); d->traverseDom(dom, apiExtractorFlags); return true; @@ -718,7 +742,7 @@ void AbstractMetaBuilder::setLogDirectory(const QString &logDir) d->m_logDirectory.append(QDir::separator()); } -void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls, +void AbstractMetaBuilderPrivate::addAbstractMetaClass(const AbstractMetaClassPtr &cls, const _CodeModelItem *item) { m_itemToClass.insert(item, cls); @@ -732,23 +756,27 @@ void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls, } } -AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModelItem &dom, - const NamespaceModelItem &namespaceItem) +AbstractMetaClassPtr + AbstractMetaBuilderPrivate::traverseNamespace(const FileModelItem &dom, + const NamespaceModelItem &namespaceItem) { - QString namespaceName = currentScope()->qualifiedName().join(colonColon()); + QString namespaceName = currentScope()->qualifiedName().join(u"::"_s); if (!namespaceName.isEmpty()) - namespaceName.append(colonColon()); + namespaceName.append(u"::"_s); namespaceName.append(namespaceItem->name()); if (TypeDatabase::instance()->isClassRejected(namespaceName)) { - m_rejectedClasses.insert(namespaceName, AbstractMetaBuilder::GenerationDisabled); - return nullptr; + m_rejectedClasses.insert({AbstractMetaBuilder::GenerationDisabled, + namespaceName, namespaceName, QString{}}); + return {}; } auto type = TypeDatabase::instance()->findNamespaceType(namespaceName, namespaceItem->fileName()); if (!type) { - qCWarning(lcShiboken, "%s", - qPrintable(msgNamespaceNoTypeEntry(namespaceItem, namespaceName))); + const QString rejectReason = msgNamespaceNoTypeEntry(namespaceItem, namespaceName); + qCWarning(lcShiboken, "%s", qPrintable(rejectReason)); + m_rejectedClasses.insert({AbstractMetaBuilder::GenerationDisabled, + namespaceName, namespaceName, rejectReason}); return nullptr; } @@ -758,22 +786,22 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel } // Continue populating namespace? - AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, type); + AbstractMetaClassPtr metaClass = AbstractMetaClass::findClass(m_metaClasses, type); if (!metaClass) { - metaClass = new AbstractMetaClass; + metaClass.reset(new AbstractMetaClass); metaClass->setTypeEntry(type); - addAbstractMetaClass(metaClass, namespaceItem.data()); + addAbstractMetaClass(metaClass, namespaceItem.get()); if (auto extendsType = type->extends()) { - AbstractMetaClass *extended = AbstractMetaClass::findClass(m_metaClasses, extendsType); + const auto extended = AbstractMetaClass::findClass(m_metaClasses, extendsType); if (!extended) { qCWarning(lcShiboken, "%s", qPrintable(msgNamespaceToBeExtendedNotFound(extendsType->name(), extendsType->targetLangPackage()))); - return nullptr; + return {}; } metaClass->setExtendedNamespace(extended); } } else { - m_itemToClass.insert(namespaceItem.data(), metaClass); + m_itemToClass.insert(namespaceItem.get(), metaClass); } traverseEnums(namespaceItem, metaClass, namespaceItem->enumsDeclarations()); @@ -782,11 +810,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel const ClassList &classes = namespaceItem->classes(); for (const ClassModelItem &cls : classes) { - AbstractMetaClass *mjc = traverseClass(dom, cls, metaClass); + const auto mjc = traverseClass(dom, cls, metaClass); if (mjc) { metaClass->addInnerClass(mjc); mjc->setEnclosingClass(metaClass); - addAbstractMetaClass(mjc, cls.data()); + addAbstractMetaClass(mjc, cls.get()); } } @@ -794,22 +822,22 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel // specific typedefs to be used as classes. const TypeDefList typeDefs = namespaceItem->typeDefs(); for (const TypeDefModelItem &typeDef : typeDefs) { - AbstractMetaClass *cls = traverseTypeDef(dom, typeDef, metaClass); + const auto cls = traverseTypeDef(dom, typeDef, metaClass); if (cls) { metaClass->addInnerClass(cls); cls->setEnclosingClass(metaClass); - addAbstractMetaClass(cls, typeDef.data()); + addAbstractMetaClass(cls, typeDef.get()); } } // Traverse namespaces recursively for (const NamespaceModelItem &ni : namespaceItem->namespaces()) { - AbstractMetaClass *mjc = traverseNamespace(dom, ni); + const auto mjc = traverseNamespace(dom, ni); if (mjc) { metaClass->addInnerClass(mjc); mjc->setEnclosingClass(metaClass); - m_classToItem.insert(mjc, ni.data()); // Add for enum lookup. - m_itemToClass.insert(ni.data(), mjc); + m_classToItem.insert(mjc, ni.get()); // Add for enum lookup. + m_itemToClass.insert(ni.get(), mjc); } } @@ -823,10 +851,10 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel std::optional<AbstractMetaEnum> AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &enumItem, - AbstractMetaClass *enclosing, + const AbstractMetaClassPtr &enclosing, const QSet<QString> &enumsDeclarations) { - QString qualifiedName = enumItem->qualifiedName().join(colonColon()); + QString qualifiedName = enumItem->qualifiedName().join(u"::"_s); TypeEntryPtr typeEntry; const auto enclosingTypeEntry = enclosing ? enclosing->typeEntry() : TypeEntryCPtr{}; @@ -842,7 +870,7 @@ std::optional<AbstractMetaEnum> for (const EnumeratorModelItem &enumValue : enums) { tmpQualifiedName.removeLast(); tmpQualifiedName << enumValue->name(); - qualifiedName = tmpQualifiedName.join(colonColon()); + qualifiedName = tmpQualifiedName.join(u"::"_s); typeEntry = TypeDatabase::instance()->findType(qualifiedName); if (typeEntry) break; @@ -859,66 +887,75 @@ std::optional<AbstractMetaEnum> if (TypeDatabase::instance()->isEnumRejected(className, enumName, &rejectReason)) { if (typeEntry) typeEntry->setCodeGeneration(TypeEntry::GenerateNothing); - m_rejectedEnums.insert(qualifiedName + rejectReason, AbstractMetaBuilder::GenerationDisabled); + m_rejectedEnums.insert({AbstractMetaBuilder::GenerationDisabled, qualifiedName, + qualifiedName, rejectReason}); return {}; } const bool rejectionWarning = !enclosing || enclosing->typeEntry()->generateCode(); if (!typeEntry) { + const QString rejectReason = msgNoEnumTypeEntry(enumItem, className); if (rejectionWarning) - qCWarning(lcShiboken, "%s", qPrintable(msgNoEnumTypeEntry(enumItem, className))); - m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::NotInTypeSystem); + qCWarning(lcShiboken, "%s", qPrintable(rejectReason)); + m_rejectedEnums.insert({AbstractMetaBuilder::NotInTypeSystem, qualifiedName, + qualifiedName, rejectReason}); return {}; } if (!typeEntry->isEnum()) { - if (rejectionWarning) { - qCWarning(lcShiboken, "%s", - qPrintable(msgNoEnumTypeConflict(enumItem, className, typeEntry))); - } - m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::NotInTypeSystem); + const QString rejectReason = msgNoEnumTypeConflict(enumItem, className, typeEntry); + if (rejectionWarning) + qCWarning(lcShiboken, "%s", qPrintable(rejectReason)); + m_rejectedEnums.insert({AbstractMetaBuilder::NotInTypeSystem, qualifiedName, + qualifiedName, rejectReason}); return {}; } AbstractMetaEnum metaEnum; metaEnum.setEnumKind(enumItem->enumKind()); metaEnum.setDeprecated(enumItem->isDeprecated()); + metaEnum.setUnderlyingType(enumItem->underlyingType()); metaEnum.setSigned(enumItem->isSigned()); if (enumsDeclarations.contains(qualifiedName) || enumsDeclarations.contains(enumName)) { metaEnum.setHasQEnumsDeclaration(true); } - auto enumTypeEntry = qSharedPointerCast<EnumTypeEntry>(typeEntry); + auto enumTypeEntry = std::static_pointer_cast<EnumTypeEntry>(typeEntry); metaEnum.setTypeEntry(enumTypeEntry); metaEnum.setAccess(enumItem->accessPolicy()); if (metaEnum.access() == Access::Private) typeEntry->setCodeGeneration(TypeEntry::GenerateNothing); - + // PYSIDE-2088, MSVC signedness issue in Qt + const bool castToUnsigned = enumItem->isSigned() + && enumTypeEntry->cppType().contains(u"unsigned"_s); const EnumeratorList &enums = enumItem->enumerators(); - for (const EnumeratorModelItem &value : enums) { + for (const EnumeratorModelItem &valueItem : enums) { AbstractMetaEnumValue metaEnumValue; - metaEnumValue.setName(value->name()); + metaEnumValue.setName(valueItem->name()); // Deciding the enum value... - metaEnumValue.setStringValue(value->stringValue()); - metaEnumValue.setValue(value->value()); - metaEnumValue.setDeprecated(value->isDeprecated()); + metaEnumValue.setStringValue(valueItem->stringValue()); + const auto value = valueItem->value(); + metaEnumValue.setValue(castToUnsigned ? value.toUnsigned() : value); + metaEnumValue.setDeprecated(valueItem->isDeprecated()); metaEnum.addEnumValue(metaEnumValue); } - if (!metaEnum.typeEntry()->include().isValid()) - setInclude(metaEnum.typeEntry(), enumItem->fileName()); + if (!metaEnum.typeEntry()->include().isValid()) { + auto te = std::const_pointer_cast<EnumTypeEntry>(metaEnum.typeEntry()); + setInclude(te, enumItem->fileName()); + } // Register all enum values on Type database const bool isScopedEnum = enumItem->enumKind() == EnumClass; const EnumeratorList &enumerators = enumItem->enumerators(); for (const EnumeratorModelItem &e : enumerators) { - EnumValueTypeEntryPtr enumValue(new EnumValueTypeEntry(e->name(), e->stringValue(), - enumTypeEntry, isScopedEnum, - enumTypeEntry->version())); + auto enumValue = std::make_shared<EnumValueTypeEntry>(e->name(), e->stringValue(), + enumTypeEntry, isScopedEnum, + enumTypeEntry->version()); TypeDatabase::instance()->addType(enumValue); if (e->value().isNullValue()) enumTypeEntry->setNullValue(enumValue); @@ -930,9 +967,31 @@ std::optional<AbstractMetaEnum> return metaEnum; } -AbstractMetaClass *AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &, - const TypeDefModelItem &typeDef, - AbstractMetaClass *currentClass) +AbstractMetaClassPtr + AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &dom, + const TypeDefModelItem &typeDef, + const AbstractMetaClassPtr ¤tClass) +{ + auto result = traverseTypeDefHelper(dom, typeDef, currentClass); + if (!result && typeDef->type().isPlain()) { + const auto &type = typeDef->type(); + QString fullName; + if (currentClass) + fullName += currentClass->qualifiedCppName() + "::"_L1; + fullName += typeDef->name(); + QString targetName = typeDef->type().toString(); + m_typedefTargetToName.insert(targetName, fullName); + const QByteArray normalized = QMetaObject::normalizedType(targetName.toUtf8().constData()); + if (targetName != QLatin1StringView(normalized)) + m_typedefTargetToName.insert(QString::fromUtf8(normalized), fullName); + } + return result; +} + +AbstractMetaClassPtr + AbstractMetaBuilderPrivate::traverseTypeDefHelper(const FileModelItem &, + const TypeDefModelItem &typeDef, + const AbstractMetaClassPtr ¤tClass) { TypeDatabase *types = TypeDatabase::instance(); QString className = stripTemplateArgs(typeDef->name()); @@ -941,7 +1000,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt // we have an inner class if (currentClass) { fullClassName = stripTemplateArgs(currentClass->typeEntry()->qualifiedCppName()) - + colonColon() + fullClassName; + + u"::"_s + fullClassName; } // If this is the alias for a primitive type @@ -951,7 +1010,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt const auto &targetNames = typeDef->type().qualifiedName(); const auto pTarget = targetNames.size() == 1 ? types->findPrimitiveType(targetNames.constFirst()) : PrimitiveTypeEntryPtr{}; - if (!ptype.isNull()) { + if (ptype) { ptype->setReferencedTypeEntry(pTarget); return nullptr; } @@ -960,7 +1019,8 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt // (like size_t = unsigned)? Add it to the type DB. if (pTarget && isCppPrimitive(basicReferencedNonBuiltinTypeEntry(pTarget)) && currentClass == nullptr) { - PrimitiveTypeEntryPtr pte(new PrimitiveTypeEntry(className, {}, {})); + auto pte = std::make_shared<PrimitiveTypeEntry>(className, QVersionNumber{}, + TypeEntryCPtr{}); pte->setReferencedTypeEntry(pTarget); pte->setBuiltIn(true); types->addType(pte); @@ -969,10 +1029,10 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt // If we haven't specified anything for the typedef, then we don't care auto type = types->findComplexType(fullClassName); - if (type.isNull()) + if (!type) return nullptr; - auto *metaClass = new AbstractMetaClass; + auto metaClass = std::make_shared<AbstractMetaClass>(); metaClass->setTypeDef(true); metaClass->setTypeEntry(type); metaClass->setBaseClassNames(QStringList(typeDef->type().toString())); @@ -991,8 +1051,8 @@ void AbstractMetaBuilderPrivate::traverseTypesystemTypedefs() { const auto &entries = TypeDatabase::instance()->typedefEntries(); for (auto it = entries.begin(), end = entries.end(); it != end; ++it) { - TypedefEntryPtr te = it.value(); - auto *metaClass = new AbstractMetaClass; + const TypedefEntryPtr &te = it.value(); + auto metaClass = std::make_shared<AbstractMetaClass>(); metaClass->setTypeDef(true); metaClass->setTypeEntry(te->target()); metaClass->setBaseClassNames(QStringList(te->sourceType())); @@ -1018,9 +1078,9 @@ void AbstractMetaBuilderPrivate::traverseTypesystemTypedefs() } } -AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem &dom, +AbstractMetaClassPtr AbstractMetaBuilderPrivate::traverseClass(const FileModelItem &dom, const ClassModelItem &classItem, - AbstractMetaClass *currentClass) + const AbstractMetaClassPtr ¤tClass) { QString className = stripTemplateArgs(classItem->name()); QString fullClassName = className; @@ -1028,7 +1088,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem // we have inner an class if (currentClass) { fullClassName = stripTemplateArgs(currentClass->typeEntry()->qualifiedCppName()) - + colonColon() + fullClassName; + + u"::"_s + fullClassName; } const auto type = TypeDatabase::instance()->findComplexType(fullClassName); @@ -1036,9 +1096,9 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem if (TypeDatabase::instance()->isClassRejected(fullClassName)) { reason = AbstractMetaBuilder::GenerationDisabled; - } else if (type.isNull()) { + } else if (!type) { TypeEntryPtr te = TypeDatabase::instance()->findType(fullClassName); - if (!te.isNull() && !te->isComplex()) { + if (te && !te->isComplex()) { reason = AbstractMetaBuilder::RedefinedToNotClass; // Set the default include file name if (!te->include().isValid()) @@ -1054,11 +1114,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem QTextStream(&fullClassName) << "anonymous struct at " << classItem->fileName() << ':' << classItem->startLine(); } - m_rejectedClasses.insert(fullClassName, reason); + m_rejectedClasses.insert({reason, fullClassName, fullClassName, QString{}}); return nullptr; } - auto *metaClass = new AbstractMetaClass; + auto metaClass = std::make_shared<AbstractMetaClass>(); metaClass->setSourceLocation(classItem->sourceLocation()); metaClass->setTypeEntry(type); if ((type->typeFlags() & ComplexTypeEntry::ForceAbstract) != 0) @@ -1094,7 +1154,8 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem auto argumentParent = typeSystemTypeEntry(metaClass->typeEntry()); for (qsizetype i = 0; i < template_parameters.size(); ++i) { const TemplateParameterModelItem ¶m = template_parameters.at(i); - auto param_type = new TemplateArgumentEntry(param->name(), type->version(), + auto param_type = + std::make_shared<TemplateArgumentEntry>(param->name(), type->version(), argumentParent); param_type->setOrdinal(i); template_args.append(TypeEntryCPtr(param_type)); @@ -1109,11 +1170,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem { const ClassList &innerClasses = classItem->classes(); for (const ClassModelItem &ci : innerClasses) { - AbstractMetaClass *cl = traverseClass(dom, ci, metaClass); + const auto cl = traverseClass(dom, ci, metaClass); if (cl) { cl->setEnclosingClass(metaClass); metaClass->addInnerClass(cl); - addAbstractMetaClass(cl, ci.data()); + addAbstractMetaClass(cl, ci.get()); } } @@ -1123,10 +1184,10 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem // specific typedefs to be used as classes. const TypeDefList typeDefs = classItem->typeDefs(); for (const TypeDefModelItem &typeDef : typeDefs) { - AbstractMetaClass *cls = traverseTypeDef(dom, typeDef, metaClass); + const auto cls = traverseTypeDef(dom, typeDef, metaClass); if (cls) { cls->setEnclosingClass(metaClass); - addAbstractMetaClass(cls, typeDef.data()); + addAbstractMetaClass(cls, typeDef.get()); } } @@ -1138,7 +1199,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem } void AbstractMetaBuilderPrivate::traverseScopeMembers(const ScopeModelItem &item, - AbstractMetaClass *metaClass) + const AbstractMetaClassPtr &metaClass) { // Classes/Namespace members traverseFields(item, metaClass); @@ -1152,28 +1213,25 @@ void AbstractMetaBuilderPrivate::traverseScopeMembers(const ScopeModelItem &item void AbstractMetaBuilderPrivate::traverseClassMembers(const ClassModelItem &item) { - AbstractMetaClass *metaClass = m_itemToClass.value(item.data()); - if (!metaClass) - return; - - // Class members - traverseScopeMembers(item, metaClass); + const auto metaClass = m_itemToClass.value(item.get()); + if (metaClass) // Class members + traverseScopeMembers(item, metaClass); } -void AbstractMetaBuilderPrivate::traverseUsingMembers(AbstractMetaClass *metaClass) +void AbstractMetaBuilderPrivate::traverseUsingMembers(const AbstractMetaClassPtr &metaClass) const { const _CodeModelItem *item = m_classToItem.value(metaClass); if (item == nullptr || item->kind() != _CodeModelItem::Kind_Class) return; - auto classItem = static_cast<const _ClassModelItem *>(item); + const auto *classItem = static_cast<const _ClassModelItem *>(item); for (const auto &um : classItem->usingMembers()) { QString className = um.className; - int pos = className.indexOf(u'<'); // strip "QList<value>" + auto pos = className.indexOf(u'<'); // strip "QList<value>" if (pos != -1) className.truncate(pos); - if (auto baseClass = metaClass->AbstractMetaClass::findBaseClass(className)) { + if (auto baseClass = findBaseClass(metaClass, className)) { QString name = um.memberName; - const int lastQualPos = name.lastIndexOf(colonColon()); + const auto lastQualPos = name.lastIndexOf(u"::"_s); if (lastQualPos != -1) name.remove(0, lastQualPos + 2); metaClass->addUsingMember({name, baseClass, um.access}); @@ -1187,7 +1245,7 @@ void AbstractMetaBuilderPrivate::traverseUsingMembers(AbstractMetaClass *metaCla void AbstractMetaBuilderPrivate::traverseNamespaceMembers(const NamespaceModelItem &item) { - AbstractMetaClass *metaClass = m_itemToClass.value(item.data()); + const auto metaClass = m_itemToClass.value(item.get()); if (!metaClass) return; @@ -1202,18 +1260,18 @@ void AbstractMetaBuilderPrivate::traverseNamespaceMembers(const NamespaceModelIt static inline QString fieldSignatureWithType(const VariableModelItem &field) { - return field->name() + QStringLiteral(" -> ") + field->type().toString(); + return field->name() + " -> "_L1 + field->type().toString(); } static inline QString qualifiedFieldSignatureWithType(const QString &className, const VariableModelItem &field) { - return className + colonColon() + fieldSignatureWithType(field); + return className + u"::"_s + fieldSignatureWithType(field); } std::optional<AbstractMetaField> AbstractMetaBuilderPrivate::traverseField(const VariableModelItem &field, - const AbstractMetaClass *cls) + const AbstractMetaClassCPtr &cls) { QString fieldName = field->name(); QString className = cls->typeEntry()->qualifiedCppName(); @@ -1227,8 +1285,9 @@ std::optional<AbstractMetaField> QString rejectReason; if (TypeDatabase::instance()->isFieldRejected(className, fieldName, &rejectReason)) { - m_rejectedFields.insert(qualifiedFieldSignatureWithType(className, field) + rejectReason, - AbstractMetaBuilder::GenerationDisabled); + const QString signature = qualifiedFieldSignatureWithType(className, field); + m_rejectedFields.insert({AbstractMetaBuilder::GenerationDisabled, + signature, signature, rejectReason}); return {}; } @@ -1241,7 +1300,7 @@ std::optional<AbstractMetaField> auto metaType = translateType(fieldType, cls); if (!metaType.has_value()) { - const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(colonColon()); + const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(u"::"_s); if (cls->typeEntry()->generateCode()) { qCWarning(lcShiboken, "%s", qPrintable(msgSkippingField(field, cls->name(), type))); @@ -1276,7 +1335,7 @@ static bool applyFieldModifications(AbstractMetaField *f) } void AbstractMetaBuilderPrivate::traverseFields(const ScopeModelItem &scope_item, - AbstractMetaClass *metaClass) + const AbstractMetaClassPtr &metaClass) { const VariableList &variables = scope_item->variables(); for (const VariableModelItem &field : variables) { @@ -1295,7 +1354,7 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF return; TypeDatabase *types = TypeDatabase::instance(); - static const QRegularExpression operatorRegExp(QStringLiteral("^operator ")); + static const QRegularExpression operatorRegExp("^operator "_L1); Q_ASSERT(operatorRegExp.isValid()); QString castTo = metaFunction->name().remove(operatorRegExp).trimmed(); @@ -1305,7 +1364,7 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF castTo.remove(0, 6); TypeEntryPtr retType = types->findType(castTo); - if (retType.isNull()) + if (!retType) return; AbstractMetaType metaType(retType); @@ -1316,7 +1375,7 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF AbstractMetaFunctionRawPtrList AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem, AbstractMetaClass::Attributes *constructorAttributes, - AbstractMetaClass *currentClass) + const AbstractMetaClassPtr ¤tClass) { *constructorAttributes = {}; AbstractMetaFunctionRawPtrList result; @@ -1328,7 +1387,7 @@ AbstractMetaFunctionRawPtrList traverseOperatorFunction(function, currentClass); } else if (function->isSpaceshipOperator() && !function->isDeleted()) { if (currentClass) - currentClass->addSynthesizedComparisonOperators(); + AbstractMetaClass::addSynthesizedComparisonOperators(currentClass); } else if (auto *metaFunction = traverseFunction(function, currentClass)) { result.append(metaFunction); } else if (!function->isDeleted() && function->functionType() == CodeModel::Constructor) { @@ -1341,8 +1400,8 @@ AbstractMetaFunctionRawPtrList return result; } -void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, - AbstractMetaClass *metaClass) +void AbstractMetaBuilderPrivate::traverseFunctions(const ScopeModelItem& scopeItem, + const AbstractMetaClassPtr &metaClass) { AbstractMetaClass::Attributes constructorAttributes; const AbstractMetaFunctionRawPtrList functions = @@ -1351,7 +1410,7 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, for (AbstractMetaFunction *metaFunction : functions) { if (metaClass->isNamespace()) - *metaFunction += AbstractMetaFunction::Static; + metaFunction->setCppAttribute(FunctionAttribute::Static); const auto propertyFunction = metaClass->searchPropertyFunction(metaFunction->name()); if (propertyFunction.index >= 0) { @@ -1392,18 +1451,12 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, } } - const bool isInvalidDestructor = metaFunction->isDestructor() && metaFunction->isPrivate(); - const bool isInvalidConstructor = metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction - && metaFunction->isPrivate(); - if (isInvalidConstructor) + if (metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction + && metaFunction->isPrivate()) { metaClass->setHasPrivateConstructor(true); - if ((isInvalidDestructor || isInvalidConstructor) - && !metaClass->hasNonPrivateConstructor()) { - *metaClass += AbstractMetaClass::FinalInTargetLang; - } else if (metaFunction->isConstructor() && !metaFunction->isPrivate()) { - *metaClass -= AbstractMetaClass::FinalInTargetLang; - metaClass->setHasNonPrivateConstructor(true); } + if (metaFunction->isConstructor() && !metaFunction->isPrivate()) // Including Copy CT + metaClass->setHasNonPrivateConstructor(true); if (!metaFunction->isDestructor() && !(metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction)) { @@ -1414,7 +1467,7 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, if (metaFunction->isConversionOperator()) fixReturnTypeOfConversionOperator(metaFunction); - metaClass->addFunction(AbstractMetaFunctionCPtr(metaFunction)); + AbstractMetaClass::addFunction(metaClass, AbstractMetaFunctionCPtr(metaFunction)); applyFunctionModifications(metaFunction); } else if (metaFunction->isDestructor()) { metaClass->setHasPrivateDestructor(metaFunction->isPrivate()); @@ -1430,7 +1483,7 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, fillAddedFunctions(metaClass); } -void AbstractMetaBuilderPrivate::fillAddedFunctions(AbstractMetaClass *metaClass) +void AbstractMetaBuilderPrivate::fillAddedFunctions(const AbstractMetaClassPtr &metaClass) { // Add the functions added by the typesystem QString errorMessage; @@ -1494,26 +1547,17 @@ void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction func->setOriginalName(func->name()); func->setName(mod.renamedToName()); } else if (mod.isAccessModifier()) { - funcRef -= AbstractMetaFunction::Friendly; - if (mod.isPublic()) funcRef.modifyAccess(Access::Public); else if (mod.isProtected()) funcRef.modifyAccess(Access::Protected); else if (mod.isPrivate()) funcRef.modifyAccess(Access::Private); - else if (mod.isFriendly()) - funcRef += AbstractMetaFunction::Friendly; } - - if (mod.isFinal()) - funcRef += AbstractMetaFunction::FinalInTargetLang; - else if (mod.isNonFinal()) - funcRef -= AbstractMetaFunction::FinalInTargetLang; } } -bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) +bool AbstractMetaBuilderPrivate::setupInheritance(const AbstractMetaClassPtr &metaClass) { if (metaClass->inheritanceDone()) return true; @@ -1526,11 +1570,12 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) if (baseClasses.size() == 1 && baseClasses.constFirst().contains(u'<')) { TypeInfo info; ComplexTypeEntryPtr baseContainerType; - auto *templ = findTemplateClass(baseClasses.constFirst(), metaClass, - &info, &baseContainerType); + const auto templ = findTemplateClass(baseClasses.constFirst(), metaClass, + &info, &baseContainerType); if (templ) { setupInheritance(templ); - inheritTemplate(metaClass, templ, info); + if (!inheritTemplate(metaClass, templ, info)) + return false; metaClass->typeEntry()->setBaseContainerType(templ->typeEntry()); return true; } @@ -1547,9 +1592,9 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) return true; } - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("template baseclass '%1' of '%2' is not known") - .arg(baseClasses.constFirst(), metaClass->name()); + qCWarning(lcShiboken, "template baseclass '%s' of '%s' is not known", + qPrintable(baseClasses.constFirst()), + qPrintable(metaClass->name())); return false; } @@ -1584,7 +1629,7 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) } else { QString message; QTextStream(&message) << "Class \"" << defaultSuperclassName - << "\" specified as \"default-superclass\" of \"" << metaClass->name() + << R"(" specified as "default-superclass" of ")" << metaClass->name() << "\" could not be found in the code model."; qCWarning(lcShiboken, "%s", qPrintable(message)); } @@ -1594,7 +1639,7 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) } void AbstractMetaBuilderPrivate::traverseEnums(const ScopeModelItem &scopeItem, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, const QStringList &enumsDeclarations) { const EnumList &enums = scopeItem->enums(); @@ -1642,7 +1687,7 @@ bool AbstractMetaBuilderPrivate::traverseAddedGlobalFunction(const AddedFunction AbstractMetaFunction * AbstractMetaBuilderPrivate::traverseAddedFunctionHelper(const AddedFunctionPtr &addedFunc, - AbstractMetaClass *metaClass /* = nullptr */, + const AbstractMetaClassPtr &metaClass /* = {} */, QString *errorMessage) { auto returnType = translateType(addedFunc->returnType(), metaClass, {}, errorMessage); @@ -1654,7 +1699,7 @@ AbstractMetaFunction * return nullptr; } - auto metaFunction = new AbstractMetaFunction(addedFunc); + auto *metaFunction = new AbstractMetaFunction(addedFunc); metaFunction->setType(returnType.value()); metaFunction->setFunctionType(functionTypeFromName(addedFunc->name())); @@ -1711,6 +1756,7 @@ AbstractMetaFunction * // Find the correct default values const FunctionModificationList functionMods = metaFunction->modifications(metaClass); + applyCachedFunctionModifications(metaFunction, functionMods); for (qsizetype i = 0; i < metaArguments.size(); ++i) { AbstractMetaArgument &metaArg = metaArguments[i]; @@ -1726,7 +1772,7 @@ AbstractMetaFunction * } bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunctionPtr &addedFunc, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, QString *errorMessage) { AbstractMetaFunction *metaFunction = @@ -1736,7 +1782,7 @@ bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunction const AbstractMetaArgumentList fargs = metaFunction->arguments(); if (metaClass->isNamespace()) - *metaFunction += AbstractMetaFunction::Static; + metaFunction->setCppAttribute(FunctionAttribute::Static); if (metaFunction->name() == metaClass->name()) { metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction); if (fargs.size() == 1) { @@ -1750,7 +1796,7 @@ bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunction metaFunction->setDeclaringClass(metaClass); metaFunction->setImplementingClass(metaClass); - metaClass->addFunction(AbstractMetaFunctionCPtr(metaFunction)); + AbstractMetaClass::addFunction(metaClass, AbstractMetaFunctionCPtr(metaFunction)); metaClass->setHasNonPrivateConstructor(true); return true; } @@ -1786,7 +1832,7 @@ static inline QString qualifiedFunctionSignatureWithType(const FunctionModelItem { QString result = functionItem->type().toString() + u' '; if (!className.isEmpty()) - result += className + colonColon(); + result += className + u"::"_s; result += functionSignature(functionItem); return result; } @@ -1898,9 +1944,48 @@ static bool applyArrayArgumentModifications(const FunctionModificationList &func return true; } +// Create the meta type for a view (std::string_view -> std::string) +static AbstractMetaType createViewOnType(const AbstractMetaType &metaType, + const TypeEntryCPtr &viewOnTypeEntry) +{ + auto result = metaType; + result.setTypeEntry(viewOnTypeEntry); + if (!metaType.isContainer() || !viewOnTypeEntry->isContainer()) + return result; + // For containers, when sth with several template parameters + // (std::span<T, int N>) is mapped onto a std::vector<T>, + // remove the superfluous template parameters and strip 'const'. + const auto vcte = std::static_pointer_cast<const ContainerTypeEntry>(viewOnTypeEntry); + const auto &instantiations = metaType.instantiations(); + AbstractMetaTypeList viewInstantiations; + const auto size = std::min(vcte->templateParameterCount(), instantiations.size()); + for (qsizetype i = 0; i < size; ++i) { + auto ins = instantiations.at(i); + ins.setConstant(false); + viewInstantiations.append(ins); + } + result.setInstantiations(viewInstantiations); + return result; +} + +void AbstractMetaBuilderPrivate::rejectFunction(const FunctionModelItem &functionItem, + const AbstractMetaClassPtr ¤tClass, + AbstractMetaBuilder::RejectReason reason, + const QString &rejectReason) +{ + QString sortKey; + if (currentClass) + sortKey += currentClass->typeEntry()->qualifiedCppName() + u"::"_s; + sortKey += functionSignature(functionItem); // Sort without return type + const QString signatureWithType = functionItem->type().toString() + u' ' + sortKey; + m_rejectedFunctions.insert({reason, signatureWithType, sortKey, rejectReason}); +} + AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const FunctionModelItem &functionItem, - AbstractMetaClass *currentClass) + const AbstractMetaClassPtr ¤tClass) { + const auto *tdb = TypeDatabase::instance(); + if (!functionItem->templateParameters().isEmpty()) return nullptr; @@ -1941,20 +2026,17 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio } } // PySide extensions - // Store original signature with unresolved typedefs for message/log purposes - const QString originalQualifiedSignatureWithReturn = - qualifiedFunctionSignatureWithType(functionItem, className); - QString rejectReason; - if (TypeDatabase::instance()->isFunctionRejected(className, functionName, &rejectReason)) { - m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); + if (tdb->isFunctionRejected(className, functionName, &rejectReason)) { + rejectFunction(functionItem, currentClass, + AbstractMetaBuilder::GenerationDisabled, rejectReason); return nullptr; } - const QString &signature = functionSignature(functionItem); - const bool rejected = - TypeDatabase::instance()->isFunctionRejected(className, signature, &rejectReason); - if (rejected) { + const QString &signature = functionSignature(functionItem); + if (tdb->isFunctionRejected(className, signature, &rejectReason)) { + rejectFunction(functionItem, currentClass, + AbstractMetaBuilder::GenerationDisabled, rejectReason); if (ReportHandler::isDebug(ReportHandler::MediumDebug)) { qCInfo(lcShiboken, "%s::%s was rejected by the type database (%s).", qPrintable(className), qPrintable(signature), qPrintable(rejectReason)); @@ -1965,15 +2047,17 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio if (functionItem->isFriend()) return nullptr; - const bool deprecated = functionItem->isDeprecated(); + const auto cppAttributes = functionItem->attributes(); + const bool deprecated = cppAttributes.testFlag(FunctionAttribute::Deprecated); if (deprecated && m_skipDeprecated) { - m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + u" is deprecated."_s, - AbstractMetaBuilder::GenerationDisabled); + rejectFunction(functionItem, currentClass, + AbstractMetaBuilder::GenerationDisabled, u" is deprecated."_s); return nullptr; } AbstractMetaFunction::Flags flags; auto *metaFunction = new AbstractMetaFunction(functionName); + metaFunction->setCppAttributes(cppAttributes); const QByteArray cSignature = signature.toUtf8(); const QString unresolvedSignature = QString::fromUtf8(QMetaObject::normalizedSignature(cSignature.constData())); @@ -1981,35 +2065,12 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio if (functionItem->isHiddenFriend()) flags.setFlag(AbstractMetaFunction::Flag::HiddenFriend); metaFunction->setSourceLocation(functionItem->sourceLocation()); - if (deprecated) - *metaFunction += AbstractMetaFunction::Deprecated; // Additional check for assignment/move assignment down below metaFunction->setFunctionType(functionTypeFromCodeModel(functionItem->functionType())); metaFunction->setConstant(functionItem->isConstant()); metaFunction->setExceptionSpecification(functionItem->exceptionSpecification()); - if (functionItem->isAbstract()) - *metaFunction += AbstractMetaFunction::Abstract; - - if (functionItem->isVirtual()) { - *metaFunction += AbstractMetaFunction::VirtualCppMethod; - if (functionItem->isOverride()) - *metaFunction += AbstractMetaFunction::OverriddenCppMethod; - if (functionItem->isFinal()) - *metaFunction += AbstractMetaFunction::FinalCppMethod; - } else { - *metaFunction += AbstractMetaFunction::FinalInTargetLang; - } - - if (functionItem->isInvokable()) - *metaFunction += AbstractMetaFunction::Invokable; - - if (functionItem->isStatic()) { - *metaFunction += AbstractMetaFunction::Static; - *metaFunction += AbstractMetaFunction::FinalInTargetLang; - } - // Access rights metaFunction->setAccess(functionItem->accessPolicy()); @@ -2019,25 +2080,30 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio metaFunction->setType(AbstractMetaType::createVoid()); break; case AbstractMetaFunction::ConstructorFunction: - metaFunction->setExplicit(functionItem->isExplicit()); metaFunction->setName(currentClass->name()); metaFunction->setType(AbstractMetaType::createVoid()); break; default: { TypeInfo returnType = functionItem->type(); - if (TypeDatabase::instance()->isReturnTypeRejected(className, returnType.toString(), &rejectReason)) { - m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); + if (tdb->isReturnTypeRejected(className, returnType.toString(), &rejectReason)) { + rejectFunction(functionItem, currentClass, + AbstractMetaBuilder::GenerationDisabled, rejectReason); delete metaFunction; return nullptr; } - auto type = translateType(returnType, currentClass, {}, &errorMessage); + TranslateTypeFlags flags; + if (functionItem->scopeResolution()) + flags.setFlag(AbstractMetaBuilder::NoClassScopeLookup); + auto type = translateType(returnType, currentClass, flags, &errorMessage); if (!type.has_value()) { const QString reason = msgUnmatchedReturnType(functionItem, errorMessage); + const QString signature = qualifiedFunctionSignatureWithType(functionItem, className); qCWarning(lcShiboken, "%s", - qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason))); - m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn, AbstractMetaBuilder::UnmatchedReturnType); + qPrintable(msgSkippingFunction(functionItem, signature, reason))); + rejectFunction(functionItem, currentClass, + AbstractMetaBuilder::UnmatchedReturnType, reason); delete metaFunction; return nullptr; } @@ -2067,30 +2133,37 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio for (qsizetype i = 0; i < arguments.size(); ++i) { const ArgumentModelItem &arg = arguments.at(i); - if (TypeDatabase::instance()->isArgumentTypeRejected(className, arg->type().toString(), &rejectReason)) { - m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); + if (tdb->isArgumentTypeRejected(className, arg->type().toString(), &rejectReason)) { + rejectFunction(functionItem, currentClass, + AbstractMetaBuilder::GenerationDisabled, rejectReason); delete metaFunction; return nullptr; } - auto metaTypeO = translateType(arg->type(), currentClass, {}, &errorMessage); + TranslateTypeFlags flags; + if (arg->scopeResolution()) + flags.setFlag(AbstractMetaBuilder::NoClassScopeLookup); + auto metaTypeO = translateType(arg->type(), currentClass, flags, &errorMessage); if (!metaTypeO.has_value()) { // If an invalid argument has a default value, simply remove it // unless the function is virtual (since the override in the // wrapper can then not correctly be generated). - if (arg->defaultValue() && !functionItem->isVirtual()) { + if (arg->defaultValue() + && !functionItem->attributes().testFlag(FunctionAttribute::Virtual)) { if (!currentClass || currentClass->typeEntry()->generateCode()) { + const QString signature = qualifiedFunctionSignatureWithType(functionItem, className); qCWarning(lcShiboken, "%s", - qPrintable(msgStrippingArgument(functionItem, i, originalQualifiedSignatureWithReturn, arg))); + qPrintable(msgStrippingArgument(functionItem, i, signature, + arg, errorMessage))); } break; } const QString reason = msgUnmatchedParameterType(arg, i, errorMessage); + const QString signature = qualifiedFunctionSignatureWithType(functionItem, className); qCWarning(lcShiboken, "%s", - qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason))); - const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn - + u": "_s + reason; - m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType); + qPrintable(msgSkippingFunction(functionItem, signature, reason))); + rejectFunction(functionItem, currentClass, + AbstractMetaBuilder::UnmatchedArgumentType, reason); delete metaFunction; return nullptr; } @@ -2101,10 +2174,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio auto viewOnTypeEntry = metaType.typeEntry()->viewOn(); if (viewOnTypeEntry != nullptr && metaType.indirections() == 0 && metaType.arrayElementType() == nullptr - && !metaType.hasInstantiations()) { - auto viewOn = metaType; - viewOn.setTypeEntry(viewOnTypeEntry); - metaType.setViewOn(viewOn); + && (!metaType.hasInstantiations() || metaType.isContainer())) { + metaType.setViewOn(createViewOnType(metaType, viewOnTypeEntry)); } AbstractMetaArgument metaArgument; @@ -2120,12 +2191,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio ? AbstractMetaFunction::findClassModifications(metaFunction, currentClass) : AbstractMetaFunction::findGlobalModifications(metaFunction); - for (const FunctionModification &mod : functionMods) { - if (mod.exceptionHandling() != TypeSystem::ExceptionHandling::Unspecified) - metaFunction->setExceptionHandlingModification(mod.exceptionHandling()); - if (mod.allowThread() != TypeSystem::AllowThread::Unspecified) - metaFunction->setAllowThreadModification(mod.allowThread()); - } + applyCachedFunctionModifications(metaFunction, functionMods); // Find the correct default values for (qsizetype i = 0, size = metaArguments.size(); i < size; ++i) { @@ -2186,13 +2252,13 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio return metaFunction; } -static TypeEntryCPtr findTypeEntryUsingContext(const AbstractMetaClass *metaClass, +static TypeEntryCPtr findTypeEntryUsingContext(const AbstractMetaClassCPtr &metaClass, const QString& qualifiedName) { TypeEntryCPtr type; - QStringList context = metaClass->qualifiedCppName().split(colonColon()); + QStringList context = metaClass->qualifiedCppName().split(u"::"_s); while (!type && !context.isEmpty()) { - type = TypeDatabase::instance()->findType(context.join(colonColon()) + colonColon() + qualifiedName); + type = TypeDatabase::instance()->findType(context.join(u"::"_s) + u"::"_s + qualifiedName); context.removeLast(); } return type; @@ -2201,18 +2267,20 @@ static TypeEntryCPtr findTypeEntryUsingContext(const AbstractMetaClass *metaClas // Helper for findTypeEntries/translateTypeStatic() TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qualifiedName, const QString &name, - const AbstractMetaClass *currentClass, + TranslateTypeFlags flags, + const AbstractMetaClassCPtr ¤tClass, AbstractMetaBuilderPrivate *d) { // 5.1 - Try first using the current scope - if (currentClass) { + if (currentClass != nullptr + && !flags.testFlag(AbstractMetaBuilder::NoClassScopeLookup)) { if (auto type = findTypeEntryUsingContext(currentClass, qualifiedName)) return {type}; // 5.1.1 - Try using the class parents' scopes if (d && !currentClass->baseClassNames().isEmpty()) { const auto &baseClasses = d->getBaseClasses(currentClass); - for (const AbstractMetaClass *cls : baseClasses) { + for (const auto &cls : baseClasses) { if (auto type = findTypeEntryUsingContext(cls, qualifiedName)) return {type}; } @@ -2248,11 +2316,13 @@ TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString & // and does some error checking. TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualifiedName, const QString &name, - const AbstractMetaClass *currentClass, + TranslateTypeFlags flags, + const AbstractMetaClassCPtr ¤tClass, AbstractMetaBuilderPrivate *d, QString *errorMessage) { - TypeEntryCList types = findTypeEntriesHelper(qualifiedName, name, currentClass, d); + TypeEntryCList types = findTypeEntriesHelper(qualifiedName, name, flags, + currentClass, d); if (types.isEmpty()) { if (errorMessage != nullptr) *errorMessage = msgCannotFindTypeEntry(qualifiedName); @@ -2264,7 +2334,7 @@ TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualif for (qsizetype i = 0, size = types.size(); i < size; ++i) { const auto &e = types.at(i); if (e->isPrimitive()) { - const auto pte = qSharedPointerCast<const PrimitiveTypeEntry>(e); + const auto pte = std::static_pointer_cast<const PrimitiveTypeEntry>(e); types[i] = basicReferencedNonBuiltinTypeEntry(pte); } } @@ -2297,10 +2367,10 @@ TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualif // Reverse lookup of AbstractMetaType representing a template specialization // found during traversing function arguments to its type system typedef'ed // class. -const AbstractMetaClass *AbstractMetaBuilderPrivate::resolveTypeSystemTypeDef(const AbstractMetaType &t) const +AbstractMetaClassCPtr AbstractMetaBuilderPrivate::resolveTypeSystemTypeDef(const AbstractMetaType &t) const { if (t.hasInstantiations()) { - auto pred = [t](const TypeClassEntry &e) { return e.type.equals(t); }; + auto pred = [t](const TypeClassEntry &e) { return e.type == t; }; auto it = std::find_if(m_typeSystemTypeDefs.cbegin(), m_typeSystemTypeDefs.cend(), pred); if (it != m_typeSystemTypeDefs.cend()) return it->klass; @@ -2321,30 +2391,30 @@ static void synthesizeWarning(const AbstractMetaFunctionCPtr &f) } static AbstractMetaFunctionPtr - addMethod(AbstractMetaClass *s, const AbstractMetaType &returnType, + addMethod(const AbstractMetaClassPtr &s, const AbstractMetaType &returnType, const QString &name, bool isConst = true) { - AbstractMetaFunctionPtr function(new AbstractMetaFunction(name)); + auto function = std::make_shared<AbstractMetaFunction>(name); function->setType(returnType); - s->addFunction(function); + AbstractMetaClass::addFunction(s, function); function->setConstant(isConst); synthesizeWarning(function); return function; } static AbstractMetaFunctionPtr - addMethod(AbstractMetaClass *s, const QString &returnTypeName, + addMethod(const AbstractMetaClassPtr &s, const QString &returnTypeName, const QString &name, bool isConst = true) { auto typeEntry = TypeDatabase::instance()->findPrimitiveType(returnTypeName); - Q_ASSERT(!typeEntry.isNull()); + Q_ASSERT(typeEntry); AbstractMetaType returnType(typeEntry); returnType.decideUsagePattern(); return addMethod(s, returnType, name, isConst); } // Create the instantiation type of a smart pointer -static AbstractMetaType instantiationType(const AbstractMetaClass *s, +static AbstractMetaType instantiationType(const AbstractMetaClassCPtr &s, const SmartPointerTypeEntryCPtr &ste) { AbstractMetaType type(s->templateArguments().constFirst()); @@ -2355,7 +2425,7 @@ static AbstractMetaType instantiationType(const AbstractMetaClass *s, } // Create the pointee argument of a smart pointer constructor or reset() -static AbstractMetaArgument pointeeArgument(const AbstractMetaClass *s, +static AbstractMetaArgument pointeeArgument(const AbstractMetaClassCPtr &s, const SmartPointerTypeEntryCPtr &ste) { AbstractMetaArgument pointee; @@ -2366,7 +2436,7 @@ static AbstractMetaArgument pointeeArgument(const AbstractMetaClass *s, // Add the smart pointer constructors. For MSVC, (when not specifying // <system-header>), clang only sees the default constructor. -static void fixSmartPointerConstructors(AbstractMetaClass *s, +static void fixSmartPointerConstructors(const AbstractMetaClassPtr &s, const SmartPointerTypeEntryCPtr &ste) { const auto ctors = s->queryFunctions(FunctionQueryOption::Constructors); @@ -2380,23 +2450,23 @@ static void fixSmartPointerConstructors(AbstractMetaClass *s, } if (!seenParameter) { - AbstractMetaFunctionPtr constructor(new AbstractMetaFunction(s->name())); + auto constructor = std::make_shared<AbstractMetaFunction>(s->name()); constructor->setFunctionType(AbstractMetaFunction::ConstructorFunction); constructor->addArgument(pointeeArgument(s, ste)); - s->addFunction(constructor); + AbstractMetaClass::addFunction(s, constructor); synthesizeWarning(constructor); } if (!seenDefaultConstructor) { - AbstractMetaFunctionPtr constructor(new AbstractMetaFunction(s->name())); + auto constructor = std::make_shared<AbstractMetaFunction>(s->name()); constructor->setFunctionType(AbstractMetaFunction::ConstructorFunction); - s->addFunction(constructor); + AbstractMetaClass::addFunction(s, constructor); synthesizeWarning(constructor); } } // Similarly, add the smart pointer reset() functions -static void fixSmartPointerReset(AbstractMetaClass *s, +static void fixSmartPointerReset(const AbstractMetaClassPtr &s, const SmartPointerTypeEntryCPtr &ste) { const QString resetMethodName = ste->resetMethod(); @@ -2411,21 +2481,21 @@ static void fixSmartPointerReset(AbstractMetaClass *s, } if (!seenParameter) { - AbstractMetaFunctionPtr f(new AbstractMetaFunction(resetMethodName)); + auto f = std::make_shared<AbstractMetaFunction>(resetMethodName); f->addArgument(pointeeArgument(s, ste)); - s->addFunction(f); + AbstractMetaClass::addFunction(s, f); synthesizeWarning(f); } if (!seenParameterLess) { - AbstractMetaFunctionPtr f(new AbstractMetaFunction(resetMethodName)); - s->addFunction(f); + auto f = std::make_shared<AbstractMetaFunction>(resetMethodName); + AbstractMetaClass::addFunction(s, f); synthesizeWarning(f); } } // Add the relevant missing smart pointer functions. -static void fixSmartPointerClass(AbstractMetaClass *s, +static void fixSmartPointerClass(const AbstractMetaClassPtr &s, const SmartPointerTypeEntryCPtr &ste) { fixSmartPointerConstructors(s, ste); @@ -2434,43 +2504,43 @@ static void fixSmartPointerClass(AbstractMetaClass *s, fixSmartPointerReset(s, ste); const QString getterName = ste->getter(); - if (s->findFunction(getterName).isNull()) + if (!s->findFunction(getterName)) addMethod(s, instantiationType(s, ste), getterName); const QString refCountName = ste->refCountMethodName(); - if (!refCountName.isEmpty() && s->findFunction(refCountName).isNull()) + if (!refCountName.isEmpty() && !s->findFunction(refCountName)) addMethod(s, u"int"_s, refCountName); const QString valueCheckMethod = ste->valueCheckMethod(); - if (!valueCheckMethod.isEmpty() && s->findFunction(valueCheckMethod).isNull()) { + if (!valueCheckMethod.isEmpty() && !s->findFunction(valueCheckMethod)) { auto f = addMethod(s, u"bool"_s, valueCheckMethod); if (valueCheckMethod == u"operator bool") f->setFunctionType(AbstractMetaFunction::ConversionOperator); } const QString nullCheckMethod = ste->nullCheckMethod(); - if (!nullCheckMethod.isEmpty() && s->findFunction(nullCheckMethod).isNull()) + if (!nullCheckMethod.isEmpty() && !s->findFunction(nullCheckMethod)) addMethod(s, u"bool"_s, nullCheckMethod); } // Create a missing smart pointer class -static AbstractMetaClass *createSmartPointerClass(const SmartPointerTypeEntryCPtr &ste, - const AbstractMetaClassList &allClasses) +static AbstractMetaClassPtr createSmartPointerClass(const SmartPointerTypeEntryCPtr &ste, + const AbstractMetaClassList &allClasses) { - auto *result = new AbstractMetaClass(); - result->setTypeEntry(qSharedPointerConstCast<SmartPointerTypeEntry>(ste)); - TypeEntryCPtr templateArg(new TemplateArgumentEntry(u"T"_s, ste->version(), - typeSystemTypeEntry(ste))); + auto result = std::make_shared<AbstractMetaClass>(); + result->setTypeEntry(std::const_pointer_cast<SmartPointerTypeEntry>(ste)); + auto templateArg = std::make_shared<TemplateArgumentEntry>(u"T"_s, ste->version(), + typeSystemTypeEntry(ste)); result->setTemplateArguments({templateArg}); fixSmartPointerClass(result, ste); auto enclosingTe = ste->parent(); if (!enclosingTe->isTypeSystem()) { - auto *enclosing = AbstractMetaClass::findClass(allClasses, enclosingTe); - if (enclosing == nullptr) + const auto enclosing = AbstractMetaClass::findClass(allClasses, enclosingTe); + if (!enclosing) throw Exception(msgEnclosingClassNotFound(ste)); result->setEnclosingClass(enclosing); auto inner = enclosing->innerClasses(); - inner.append(result); + inner.append(std::const_pointer_cast<const AbstractMetaClass>(result)); enclosing->setInnerClasses(inner); } return result; @@ -2480,10 +2550,11 @@ void AbstractMetaBuilderPrivate::fixSmartPointers() { const auto smartPointerTypes = TypeDatabase::instance()->smartPointerTypes(); for (const auto &ste : smartPointerTypes) { - const AbstractMetaClass *smartPointerClass = + const auto smartPointerClass = AbstractMetaClass::findClass(m_smartPointers, ste); if (smartPointerClass) { - fixSmartPointerClass(const_cast<AbstractMetaClass *>(smartPointerClass), ste); + fixSmartPointerClass(std::const_pointer_cast<AbstractMetaClass>(smartPointerClass), + ste); } else { qCWarning(lcShiboken, "Synthesizing smart pointer \"%s\"...", qPrintable(ste->qualifiedCppName())); @@ -2494,7 +2565,7 @@ void AbstractMetaBuilderPrivate::fixSmartPointers() std::optional<AbstractMetaType> AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei, - const AbstractMetaClass *currentClass, + const AbstractMetaClassCPtr ¤tClass, TranslateTypeFlags flags, QString *errorMessage) { @@ -2507,9 +2578,16 @@ static bool isNumber(const QString &s) [](QChar c) { return c.isDigit(); }); } +// A type entry relevant only for non type template "X<5>" +static bool isNonTypeTemplateArgument(const TypeEntryCPtr &te) +{ + const auto type = te->type(); + return type == TypeEntry::EnumValue || type == TypeEntry::ConstantValueType; +} + std::optional<AbstractMetaType> AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo &_typei, - const AbstractMetaClass *currentClass, + const AbstractMetaClassCPtr ¤tClass, AbstractMetaBuilderPrivate *d, TranslateTypeFlags flags, QString *errorMessageIn) @@ -2539,7 +2617,7 @@ std::optional<AbstractMetaType> qsizetype i = d ? d->m_scopes.size() - 1 : -1; while (i >= 0) { typeInfo = TypeInfo::resolveType(_typei, d->m_scopes.at(i--)); - if (typeInfo.qualifiedName().join(colonColon()) != _typei.qualifiedName().join(colonColon())) + if (typeInfo.qualifiedName().join(u"::"_s) != _typei.qualifiedName().join(u"::"_s)) break; } @@ -2563,7 +2641,7 @@ std::optional<AbstractMetaType> bool isConstCharStarCase = oneDimensionalArrayOfUnspecifiedSize && typeInfo.qualifiedName().size() == 1 - && typeInfo.qualifiedName().at(0) == QStringLiteral("char") + && typeInfo.qualifiedName().at(0) == "char"_L1 && typeInfo.indirections() == 0 && typeInfo.isConstant() && typeInfo.referenceType() == NoReference @@ -2606,8 +2684,8 @@ std::optional<AbstractMetaType> arrayType.setArrayElementCount(int(elems)); } auto elementTypeEntry = elementType->typeEntry(); - TypeEntryCPtr at(new ArrayTypeEntry(elementTypeEntry, elementTypeEntry->version(), - elementTypeEntry->parent())); + auto at = std::make_shared<ArrayTypeEntry>(elementTypeEntry, elementTypeEntry->version(), + elementTypeEntry->parent()); arrayType.setTypeEntry(at); arrayType.decideUsagePattern(); @@ -2627,7 +2705,7 @@ std::optional<AbstractMetaType> return {}; } - QString qualifiedName = qualifierList.join(colonColon()); + QString qualifiedName = qualifierList.join(u"::"_s); QString name = qualifierList.takeLast(); // 4. Special case QFlags (include instantiation in name) @@ -2636,7 +2714,16 @@ std::optional<AbstractMetaType> typeInfo.clearInstantiations(); } - const TypeEntryCList types = findTypeEntries(qualifiedName, name, currentClass, d, errorMessageIn); + TypeEntryCList types = findTypeEntries(qualifiedName, name, flags, + currentClass, d, errorMessageIn); + if (!flags.testFlag(AbstractMetaBuilder::TemplateArgument)) { + // Avoid clashes between QByteArray and enum value QMetaType::QByteArray + // unless we are looking for template arguments. + auto end = std::remove_if(types.begin(), types.end(), + isNonTypeTemplateArgument); + types.erase(end, types.end()); + } + if (types.isEmpty()) { if (errorMessageIn != nullptr) *errorMessageIn = msgUnableToTranslateType(_typei, *errorMessageIn); @@ -2656,11 +2743,13 @@ std::optional<AbstractMetaType> const auto &templateArguments = typeInfo.instantiations(); for (qsizetype t = 0, size = templateArguments.size(); t < size; ++t) { const TypeInfo &ti = templateArguments.at(t); - auto targType = translateTypeStatic(ti, currentClass, d, flags, &errorMessage); + auto targType = translateTypeStatic(ti, currentClass, d, + flags | AbstractMetaBuilder::TemplateArgument, + &errorMessage); // For non-type template parameters, create a dummy type entry on the fly // as is done for classes. if (!targType.has_value()) { - const QString value = ti.qualifiedName().join(colonColon()); + const QString value = ti.qualifiedName().join(u"::"_s); if (isNumber(value)) { auto module = typeSystemTypeEntry(type); TypeDatabase::instance()->addConstantValueTypeEntry(value, module); @@ -2690,7 +2779,7 @@ std::optional<AbstractMetaType> } else { auto it = std::find_if(types.cbegin(), types.cend(), [instantiationType](const TypeEntryCPtr &e) { - auto smartPtr = qSharedPointerCast<const SmartPointerTypeEntry>(e); + auto smartPtr = std::static_pointer_cast<const SmartPointerTypeEntry>(e); return smartPtr->matchesInstantiation(instantiationType); }); if (it == types.cend()) { @@ -2724,7 +2813,7 @@ std::optional<AbstractMetaType> std::optional<AbstractMetaType> AbstractMetaBuilder::translateType(const TypeInfo &_typei, - AbstractMetaClass *currentClass, + const AbstractMetaClassPtr ¤tClass, TranslateTypeFlags flags, QString *errorMessage) { @@ -2735,7 +2824,7 @@ std::optional<AbstractMetaType> std::optional<AbstractMetaType> AbstractMetaBuilder::translateType(const QString &t, - AbstractMetaClass *currentClass, + const AbstractMetaClassPtr ¤tClass, TranslateTypeFlags flags, QString *errorMessageIn) { @@ -2765,7 +2854,7 @@ qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringV // This is a very lame way to handle expression evaluation, // but it is not critical and will do for the time being. - static const QRegularExpression variableNameRegExp(QStringLiteral("^[a-zA-Z_][a-zA-Z0-9_]*$")); + static const QRegularExpression variableNameRegExp("^[a-zA-Z_][a-zA-Z0-9_]*$"_L1); Q_ASSERT(variableNameRegExp.isValid()); if (!variableNameRegExp.match(stringValue).hasMatch()) { ok = true; @@ -2802,9 +2891,10 @@ static bool isUnderQualifiedSpec(QStringView qualifiedType, QStringView candidat } QString AbstractMetaBuilder::fixEnumDefault(const AbstractMetaType &type, - const QString &expr) const + const QString &expr, + const AbstractMetaClassCPtr &klass) const { - return d->fixEnumDefault(type, expr); + return d->fixEnumDefault(type, expr, klass); } void AbstractMetaBuilder::setCodeModelTestMode(bool b) @@ -2815,7 +2905,7 @@ void AbstractMetaBuilder::setCodeModelTestMode(bool b) // Helper to fix a simple default value (field or enum reference) in a // class context. QString AbstractMetaBuilderPrivate::fixSimpleDefaultValue(QStringView expr, - const AbstractMetaClass *klass) const + const AbstractMetaClassCPtr &klass) const { const QString field = qualifyStaticField(klass, expr); @@ -2834,7 +2924,7 @@ QString AbstractMetaBuilderPrivate::fixSimpleDefaultValue(QStringView expr, // see TestResolveType::testFixDefaultArguments() QString AbstractMetaBuilderPrivate::fixDefaultValue(QString expr, const AbstractMetaType &type, - const AbstractMetaClass *implementingClass) const + const AbstractMetaClassCPtr &implementingClass) const { expr.replace(u'\n', u' '); // breaks signature parser @@ -2842,7 +2932,7 @@ QString AbstractMetaBuilderPrivate::fixDefaultValue(QString expr, const Abstract return expr; if (type.isFlags() || type.isEnum()) { - expr = fixEnumDefault(type, expr); + expr = fixEnumDefault(type, expr, implementingClass); } else if (type.isContainer() && expr.contains(u'<')) { // Expand a container of a nested class, fex // "QList<FormatRange>()" -> "QList<QTextLayout::FormatRange>()" @@ -2917,7 +3007,7 @@ QString AbstractMetaBuilderPrivate::fixDefaultValue(QString expr, const Abstract } QString AbstractMetaBuilder::fixDefaultValue(const QString &expr, const AbstractMetaType &type, - const AbstractMetaClass *c) const + const AbstractMetaClassCPtr &c) const { return d->fixDefaultValue(expr, type, c); } @@ -2928,23 +3018,24 @@ bool AbstractMetaBuilderPrivate::isEnum(const FileModelItem &dom, const QStringL return item && item->kind() == _EnumModelItem::__node_kind; } -AbstractMetaClass *AbstractMetaBuilderPrivate::findTemplateClass(const QString &name, - const AbstractMetaClass *context, - TypeInfo *info, - ComplexTypeEntryPtr *baseContainerType) const +AbstractMetaClassPtr + AbstractMetaBuilderPrivate::findTemplateClass(const QString &name, + const AbstractMetaClassCPtr &context, + TypeInfo *info, + ComplexTypeEntryPtr *baseContainerType) const { if (baseContainerType) baseContainerType->reset(); auto *types = TypeDatabase::instance(); - QStringList scope = context->typeEntry()->qualifiedCppName().split(colonColon()); + QStringList scope = context->typeEntry()->qualifiedCppName().split(u"::"_s); QString errorMessage; scope.removeLast(); for (auto i = scope.size(); i >= 0; --i) { - QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join(colonColon()) + colonColon() : QString(); + QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join(u"::"_s) + u"::"_s : QString(); QString completeName = prefix + name; const TypeInfo parsed = TypeParser::parse(completeName, &errorMessage); - QString qualifiedName = parsed.qualifiedName().join(colonColon()); + QString qualifiedName = parsed.qualifiedName().join(u"::"_s); if (qualifiedName.isEmpty()) { qWarning().noquote().nospace() << "Unable to parse type \"" << completeName << "\" while looking for template \"" << name << "\": " << errorMessage; @@ -2953,8 +3044,8 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::findTemplateClass(const QString & if (info) *info = parsed; - AbstractMetaClass *templ = nullptr; - for (AbstractMetaClass *c : std::as_const(m_templates)) { + AbstractMetaClassPtr templ; + for (const auto &c : std::as_const(m_templates)) { if (c->typeEntry()->name() == qualifiedName) { templ = c; break; @@ -2975,7 +3066,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::findTemplateClass(const QString & } AbstractMetaClassCList - AbstractMetaBuilderPrivate::getBaseClasses(const AbstractMetaClass *metaClass) const + AbstractMetaBuilderPrivate::getBaseClasses(const AbstractMetaClassCPtr &metaClass) const { // Shortcut if inheritance has already been set up if (metaClass->inheritanceDone() || !metaClass->needsInheritanceSetup()) @@ -2983,11 +3074,9 @@ AbstractMetaClassCList AbstractMetaClassCList baseClasses; const QStringList &baseClassNames = metaClass->baseClassNames(); for (const QString& parent : baseClassNames) { - AbstractMetaClass *cls = nullptr; - if (parent.contains(u'<')) - cls = findTemplateClass(parent, metaClass); - else - cls = AbstractMetaClass::findClass(m_metaClasses, parent); + const auto cls = parent.contains(u'<') + ? findTemplateClass(parent, metaClass) + : AbstractMetaClass::findClass(m_metaClasses, parent); if (cls) baseClasses << cls; @@ -3007,7 +3096,7 @@ std::optional<AbstractMetaType> returned.setOriginalTemplateType(metaType); if (returned.typeEntry()->isTemplateArgument()) { - const auto tae = qSharedPointerCast<const TemplateArgumentEntry>(returned.typeEntry()); + const auto tae = std::static_pointer_cast<const TemplateArgumentEntry>(returned.typeEntry()); // If the template is intantiated with void we special case this as rejecting the functions that use this // parameter from the instantiation. @@ -3037,77 +3126,104 @@ std::optional<AbstractMetaType> return returned; } -AbstractMetaClass * +AbstractMetaClassPtr AbstractMetaBuilder::inheritTemplateClass(const ComplexTypeEntryPtr &te, - const AbstractMetaClass *templateClass, + const AbstractMetaClassCPtr &templateClass, const AbstractMetaTypeList &templateTypes, InheritTemplateFlags flags) { - auto result = std::make_unique<AbstractMetaClass>(); + auto result = std::make_shared<AbstractMetaClass>(); result->setTypeDef(true); result->setTypeEntry(te); - if (!AbstractMetaBuilderPrivate::inheritTemplate(result.get(), templateClass, + if (!AbstractMetaBuilderPrivate::inheritTemplate(result, templateClass, templateTypes, flags)) { - return nullptr; + return {}; + } + AbstractMetaBuilderPrivate::inheritTemplateFunctions(result); + return result; +} + + +static std::optional<AbstractMetaType> + inheritTemplateParameter(const AbstractMetaClassPtr &subclass, + const AbstractMetaClassCPtr &templateClass, + const TypeInfo &info, QString *errorMessage) +{ + QString typeName = info.qualifiedName().join("::"_L1); + TypeDatabase *typeDb = TypeDatabase::instance(); + TypeEntryPtr t; + // Check for a non-type template integer parameter, that is, for a base + // "template <int R, int C> Matrix<R, C>" and subclass + // "typedef Matrix<2,3> Matrix2x3;". If so, create dummy entries of + // EnumValueTypeEntry for the integer values encountered on the fly. + if (isNumber(typeName)) { + t = typeDb->findType(typeName); + if (!t) { + auto parent = typeSystemTypeEntry(subclass->typeEntry()); + t = TypeDatabase::instance()->addConstantValueTypeEntry(typeName, parent); + } + } else { + QStringList possibleNames; + possibleNames << subclass->qualifiedCppName() + "::"_L1 + typeName; + possibleNames << templateClass->qualifiedCppName() + "::"_L1 + typeName; + if (subclass->enclosingClass()) + possibleNames << subclass->enclosingClass()->qualifiedCppName() + "::"_L1 + typeName; + possibleNames << typeName; + + for (const QString &possibleName : std::as_const(possibleNames)) { + t = typeDb->findType(possibleName); + if (t) + break; + } } - AbstractMetaBuilderPrivate::inheritTemplateFunctions(result.get()); - return result.release(); + + if (!t) { + *errorMessage = msgIgnoringTemplateParameter(typeName, + "The corresponding type was not found in the typesystem."); + return std::nullopt; + } + + if (t->isContainer()) { + *errorMessage = msgIgnoringTemplateParameter(typeName, + "Template inheritance from nested containers is not supported"); + return std::nullopt; + } + AbstractMetaType result(t); + result.setConstant(info.isConstant()); + result.setReferenceType(info.referenceType()); + result.setIndirectionsV(info.indirectionsV()); + result.decideUsagePattern(); + return result; } -bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, - const AbstractMetaClass *templateClass, +bool AbstractMetaBuilderPrivate::inheritTemplate(const AbstractMetaClassPtr &subclass, + const AbstractMetaClassCPtr &templateClass, const TypeInfo &info) { AbstractMetaTypeList templateTypes; + QString errorMessage; for (const TypeInfo &i : info.instantiations()) { - QString typeName = i.qualifiedName().join(colonColon()); - TypeDatabase *typeDb = TypeDatabase::instance(); - TypeEntryPtr t; - // Check for a non-type template integer parameter, that is, for a base - // "template <int R, int C> Matrix<R, C>" and subclass - // "typedef Matrix<2,3> Matrix2x3;". If so, create dummy entries of - // EnumValueTypeEntry for the integer values encountered on the fly. - if (isNumber(typeName)) { - t = typeDb->findType(typeName); - if (!t) { - auto parent = typeSystemTypeEntry(subclass->typeEntry()); - t = TypeDatabase::instance()->addConstantValueTypeEntry(typeName, parent); - } - } else { - QStringList possibleNames; - possibleNames << subclass->qualifiedCppName() + colonColon() + typeName; - possibleNames << templateClass->qualifiedCppName() + colonColon() + typeName; - if (subclass->enclosingClass()) - possibleNames << subclass->enclosingClass()->qualifiedCppName() + colonColon() + typeName; - possibleNames << typeName; - - for (const QString &possibleName : std::as_const(possibleNames)) { - t = typeDb->findType(possibleName); - if (t) - break; - } - } - - if (t) { - AbstractMetaType temporaryType(t); - temporaryType.setConstant(i.isConstant()); - temporaryType.setReferenceType(i.referenceType()); - temporaryType.setIndirectionsV(i.indirectionsV()); - temporaryType.decideUsagePattern(); - templateTypes << temporaryType; + const auto typeO = inheritTemplateParameter(subclass, templateClass, i, &errorMessage); + if (typeO.has_value()) { + templateTypes.append(typeO.value()); } else { - qCWarning(lcShiboken).noquote().nospace() - << "Ignoring template parameter " << typeName << " from " - << info.toString() << ". The corresponding type was not found in the typesystem."; + errorMessage = msgInheritTemplateIssue(subclass, info, errorMessage); + qCWarning(lcShiboken, "%s", qPrintable(errorMessage)); } } + if (templateTypes.isEmpty()) { + errorMessage = msgInheritTemplateIssue(subclass, info, + "No template parameters could be inherited"_L1); + qCWarning(lcShiboken, "%s", qPrintable(errorMessage)); + return false; + } return inheritTemplate(subclass, templateClass, templateTypes); } -bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, - const AbstractMetaClass *templateClass, +bool AbstractMetaBuilderPrivate::inheritTemplate(const AbstractMetaClassPtr &subclass, + const AbstractMetaClassCPtr &templateClass, const AbstractMetaTypeList &templateTypes, InheritTemplateFlags flags) { @@ -3157,11 +3273,11 @@ AbstractMetaFunctionPtr AbstractMetaFunctionPtr AbstractMetaBuilderPrivate::inheritTemplateMember(const AbstractMetaFunctionCPtr &function, const AbstractMetaTypeList &templateTypes, - const AbstractMetaClass *templateClass, - AbstractMetaClass *subclass) + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaClassPtr &subclass) { AbstractMetaFunctionPtr f = inheritTemplateFunction(function, templateTypes); - if (f.isNull()) + if (!f) return {}; // There is no base class in the target language to inherit from here, so @@ -3215,8 +3331,8 @@ AbstractMetaFunctionPtr AbstractMetaFunctionPtr AbstractMetaBuilder::inheritTemplateMember(const AbstractMetaFunctionCPtr &function, const AbstractMetaTypeList &templateTypes, - const AbstractMetaClass *templateClass, - AbstractMetaClass *subclass) + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaClassPtr &subclass) { return AbstractMetaBuilderPrivate::inheritTemplateMember(function, templateTypes, templateClass, subclass); @@ -3224,8 +3340,8 @@ AbstractMetaFunctionPtr static bool doInheritTemplateFunction(const AbstractMetaFunctionCPtr &function, const AbstractMetaFunctionCList &existingSubclassFuncs, - const AbstractMetaClass *templateBaseClass, - const AbstractMetaClass *subclass) + const AbstractMetaClassCPtr &templateBaseClass, + const AbstractMetaClassCPtr &subclass) { // If the function is modified or the instantiation has an equally named // function we are shadowing, so we need to skip it (unless the subclass @@ -3238,7 +3354,7 @@ static bool doInheritTemplateFunction(const AbstractMetaFunctionCPtr &function, || subclass->isUsingMember(templateBaseClass, function->name(), Access::Protected); } -void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *subclass) +void AbstractMetaBuilderPrivate::inheritTemplateFunctions(const AbstractMetaClassPtr &subclass) { auto templateClass = subclass->templateBaseClass(); @@ -3259,8 +3375,8 @@ void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *sub templateClass, subclass)) { AbstractMetaFunctionCPtr f = inheritTemplateMember(function, templateTypes, templateClass, subclass); - if (!f.isNull()) - subclass->addFunction(f); + if (f) + AbstractMetaClass::addFunction(subclass, f); } } @@ -3285,7 +3401,7 @@ void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *sub } } -void AbstractMetaBuilderPrivate::parseQ_Properties(AbstractMetaClass *metaClass, +void AbstractMetaBuilderPrivate::parseQ_Properties(const AbstractMetaClassPtr &metaClass, const QStringList &declarations) { const QStringList scopes = currentScope()->qualifiedName(); @@ -3296,7 +3412,7 @@ void AbstractMetaBuilderPrivate::parseQ_Properties(AbstractMetaClass *metaClass, if (spec.has_value()) { spec->setIndex(i); metaClass->addPropertySpec(spec.value()); - } else { + } else if (!errorMessage.isEmpty()) { QString message; QTextStream str(&message); str << metaClass->sourceLocation() << errorMessage; @@ -3325,24 +3441,35 @@ void AbstractMetaBuilderPrivate::parseQ_Properties(AbstractMetaClass *metaClass, } } -void AbstractMetaBuilderPrivate::setupExternalConversion(const AbstractMetaClass *cls) +void AbstractMetaBuilderPrivate::setupExternalConversion(const AbstractMetaClassCPtr &cls) { const auto &convOps = cls->operatorOverloads(OperatorQueryOption::ConversionOp); for (const auto &func : convOps) { if (func->isModifiedRemoved()) continue; - AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, func->type().typeEntry()); + const auto metaClass = + AbstractMetaClass::findClass(m_metaClasses, func->type().typeEntry()); if (!metaClass) continue; metaClass->addExternalConversionOperator(func); } - for (auto *innerClass : cls->innerClasses()) + for (const auto &innerClass : cls->innerClasses()) setupExternalConversion(innerClass); } static void writeRejectLogFile(const QString &name, - const QMap<QString, AbstractMetaBuilder::RejectReason> &rejects) -{ + const AbstractMetaBuilderPrivate::RejectSet &rejects) +{ + static const QHash<AbstractMetaBuilder::RejectReason, QByteArray> descriptions ={ + {AbstractMetaBuilder::NotInTypeSystem, "Not in type system"_ba}, + {AbstractMetaBuilder::GenerationDisabled, "Generation disabled by type system"_ba}, + {AbstractMetaBuilder::RedefinedToNotClass, "Type redefined to not be a class"_ba}, + {AbstractMetaBuilder::UnmatchedReturnType, "Unmatched return type"_ba}, + {AbstractMetaBuilder::UnmatchedArgumentType, "Unmatched argument type"_ba}, + {AbstractMetaBuilder::UnmatchedOperator, "Unmatched operator"_ba}, + {AbstractMetaBuilder::Deprecated, "Deprecated"_ba} + }; + QFile f(name); if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) { qCWarning(lcShiboken, "%s", qPrintable(msgCannotOpenForWriting(f))); @@ -3351,53 +3478,19 @@ static void writeRejectLogFile(const QString &name, QTextStream s(&f); - - for (int reason = 0; reason < AbstractMetaBuilder::NoReason; ++reason) { - s << QByteArray(72, '*') << '\n'; - switch (reason) { - case AbstractMetaBuilder::NotInTypeSystem: - s << "Not in type system"; - break; - case AbstractMetaBuilder::GenerationDisabled: - s << "Generation disabled by type system"; - break; - case AbstractMetaBuilder::RedefinedToNotClass: - s << "Type redefined to not be a class"; - break; - - case AbstractMetaBuilder::UnmatchedReturnType: - s << "Unmatched return type"; - break; - - case AbstractMetaBuilder::UnmatchedArgumentType: - s << "Unmatched argument type"; - break; - - case AbstractMetaBuilder::ApiIncompatible: - s << "Incompatible API"; - break; - - case AbstractMetaBuilder::Deprecated: - s << "Deprecated"; - break; - - default: - s << "unknown reason"; - break; - } - - 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() << Qt::endl; + int lastReason = -1; + for (const auto &e : rejects) { + if (e.reason != lastReason) { + const QByteArray description = descriptions.value(e.reason, "Unknown reason"_ba); + const QByteArray underline(description.size(), '*'); + if (lastReason != -1) + s << '\n'; + s << underline << '\n' << description << '\n' << underline << "\n\n"; + lastReason = e.reason; } - s << QByteArray(72, '*') << "\n\n"; + s << " - " << e << '\n'; } - } void AbstractMetaBuilderPrivate::dumpLog() const @@ -3412,10 +3505,10 @@ void AbstractMetaBuilderPrivate::dumpLog() const // AbstractMetaClassList/AbstractMetaClassCList. // Add a dependency of the class associated with typeEntry on clazz. template <class MetaClass> -static bool addClassDependency(const QList<MetaClass *> &classList, +static bool addClassDependency(const QList<std::shared_ptr<MetaClass> > &classList, const TypeEntryCPtr &typeEntry, - MetaClass *clazz, - Graph<MetaClass *> *graph) + std::shared_ptr<MetaClass> clazz, + Graph<std::shared_ptr<MetaClass> > *graph) { if (!typeEntry->isComplex() || typeEntry == clazz->typeEntry()) return false; @@ -3426,10 +3519,11 @@ static bool addClassDependency(const QList<MetaClass *> &classList, } template <class MetaClass> -static QList<MetaClass *> topologicalSortHelper(const QList<MetaClass *> &classList, - const Dependencies &additionalDependencies) +static QList<std::shared_ptr<MetaClass> > + topologicalSortHelper(const QList<std::shared_ptr<MetaClass> > &classList, + const Dependencies &additionalDependencies) { - Graph<MetaClass *> graph(classList.cbegin(), classList.cend()); + Graph<std::shared_ptr<MetaClass> > graph(classList.cbegin(), classList.cend()); for (const auto &dep : additionalDependencies) { if (!graph.addEdge(dep.parent, dep.child)) { @@ -3439,14 +3533,14 @@ static QList<MetaClass *> topologicalSortHelper(const QList<MetaClass *> &classL } } - for (auto *clazz : classList) { + for (const auto &clazz : classList) { if (auto enclosingC = clazz->enclosingClass()) { - auto enclosing = const_cast<AbstractMetaClass *>(enclosingC); + const auto enclosing = std::const_pointer_cast<MetaClass>(enclosingC); graph.addEdge(enclosing, clazz); } - for (auto baseClass : clazz->baseClasses()) - graph.addEdge(const_cast<MetaClass *>(baseClass), clazz); + for (const auto &baseClass : clazz->baseClasses()) + graph.addEdge(std::const_pointer_cast<MetaClass>(baseClass), clazz); for (const auto &func : clazz->functions()) { const AbstractMetaArgumentList &arguments = func->arguments(); @@ -3474,16 +3568,22 @@ static QList<MetaClass *> topologicalSortHelper(const QList<MetaClass *> &classL if (!result.isValid() && graph.nodeCount()) { QTemporaryFile tempFile(QDir::tempPath() + u"/cyclic_depXXXXXX.dot"_s); tempFile.setAutoRemove(false); - tempFile.open(); - graph.dumpDot(tempFile.fileName(), - [] (const AbstractMetaClass *c) { return c->name(); }); + const bool ok = tempFile.open(); + if (ok) { + graph.dumpDot(tempFile.fileName(), + [] (const AbstractMetaClassCPtr &c) { return c->name(); }); + } QString message; QTextStream str(&message); str << "Cyclic dependency of classes found:"; - for (auto c : result.cyclic) + for (const auto &c : result.cyclic) str << ' ' << c->name(); - str << ". Graph can be found at \"" << QDir::toNativeSeparators(tempFile.fileName()) << '"'; + str << '.'; + if (ok) { + str << " Graph can be found at \"" + << QDir::toNativeSeparators(tempFile.fileName()) << '"'; + } qCWarning(lcShiboken, "%s", qPrintable(message)); } @@ -3517,8 +3617,8 @@ void AbstractMetaBuilderPrivate::pushScope(const NamespaceModelItem &item) } } if (candidates.size() > 1) { - NamespaceModelItem joined(new _NamespaceModelItem(m_scopes.constLast()->model(), - name, _CodeModelItem::Kind_Namespace)); + auto joined = std::make_shared<_NamespaceModelItem>(m_scopes.constLast()->model(), + name, _CodeModelItem::Kind_Namespace); joined->setScope(item->scope()); for (const auto &n : candidates) joined->appendNamespace(*n); diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder.h index 04069cefc..cbd8c7034 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.h +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.h @@ -29,13 +29,15 @@ class TypeEntry; class AbstractMetaBuilder { public: + Q_DISABLE_COPY_MOVE(AbstractMetaBuilder) + enum RejectReason { NotInTypeSystem, GenerationDisabled, RedefinedToNotClass, UnmatchedArgumentType, UnmatchedReturnType, - ApiIncompatible, + UnmatchedOperator, Deprecated, NoReason }; @@ -52,6 +54,7 @@ public: const AbstractMetaFunctionCList &globalFunctions() const; const AbstractMetaEnumList &globalEnums() const; const QHash<TypeEntryCPtr, AbstractMetaEnum> &typeEntryToEnumsHash() const; + const QMultiHash<QString, QString> &typedefTargetToName() const; bool build(const QByteArrayList &arguments, ApiExtractorFlags apiExtractorFlags = {}, @@ -75,15 +78,17 @@ public: void setApiExtractorFlags(ApiExtractorFlags flags); enum TranslateTypeFlag { - DontResolveType = 0x1 + DontResolveType = 0x1, + TemplateArgument = 0x2, + NoClassScopeLookup = 0x4 }; Q_DECLARE_FLAGS(TranslateTypeFlags, TranslateTypeFlag); static std::optional<AbstractMetaType> - translateType(const TypeInfo &_typei, AbstractMetaClass *currentClass = nullptr, + translateType(const TypeInfo &_typei, const AbstractMetaClassPtr ¤tClass = {}, TranslateTypeFlags flags = {}, QString *errorMessage = nullptr); static std::optional<AbstractMetaType> - translateType(const QString &t, AbstractMetaClass *currentClass = nullptr, + translateType(const QString &t, const AbstractMetaClassPtr ¤tClass = {}, TranslateTypeFlags flags = {}, QString *errorMessage = nullptr); /// Performs a template specialization of the function. @@ -94,9 +99,9 @@ public: inheritTemplateFunction(const AbstractMetaFunctionCPtr &function, const AbstractMetaTypeList &templateTypes); - static AbstractMetaClass * + static AbstractMetaClassPtr inheritTemplateClass(const ComplexTypeEntryPtr &te, - const AbstractMetaClass *templateClass, + const AbstractMetaClassCPtr &templateClass, const AbstractMetaTypeList &templateTypes, InheritTemplateFlags flags = {}); @@ -109,23 +114,24 @@ public: static AbstractMetaFunctionPtr inheritTemplateMember(const AbstractMetaFunctionCPtr &function, const AbstractMetaTypeList &templateTypes, - const AbstractMetaClass *templateClass, - AbstractMetaClass *subclass); + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaClassPtr &subclass); static QString getSnakeCaseName(const QString &name); // Names under which an item will be registered to Python depending on snakeCase static QStringList definitionNames(const QString &name, TypeSystem::SnakeCase snakeCase); - static QString resolveScopePrefix(const AbstractMetaClass *scope, + static QString resolveScopePrefix(const AbstractMetaClassCPtr &scope, QStringView value); static bool dontFixDefaultValue(QStringView expr); // For testing purposes QString fixDefaultValue(const QString &expr, const AbstractMetaType &type, - const AbstractMetaClass *) const; - QString fixEnumDefault(const AbstractMetaType &type, const QString &expr) const; + const AbstractMetaClassCPtr &) const; + QString fixEnumDefault(const AbstractMetaType &type, const QString &expr, + const AbstractMetaClassCPtr & = {}) const; static void setCodeModelTestMode(bool b); diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp index 7695aabfc..68eef737a 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp @@ -30,7 +30,7 @@ static QString resolveScopePrefixHelper(const QStringViewList &scopeList, return name; } -QString AbstractMetaBuilder::resolveScopePrefix(const AbstractMetaClass *scope, +QString AbstractMetaBuilder::resolveScopePrefix(const AbstractMetaClassCPtr &scope, QStringView value) { if (!scope) @@ -45,7 +45,7 @@ QString AbstractMetaBuilder::resolveScopePrefix(const AbstractMetaClass *scope, static QString resolveEnumValueScopePrefix(const AbstractMetaEnum &metaEnum, QStringView value) { - const AbstractMetaClass *scope = metaEnum.enclosingClass(); + AbstractMetaClassCPtr scope = metaEnum.enclosingClass(); if (!scope) return {}; // global enum, value should work as is const QString &qualifiedCppName = scope->qualifiedCppName(); @@ -85,21 +85,26 @@ static bool isFloatConstant(const QStringView expr) // to the default value, making it usable from Python wrapper code outside the // owner class hierarchy. See TestEnum::testEnumDefaultValues(). QString AbstractMetaBuilderPrivate::fixEnumDefault(const AbstractMetaType &type, - const QString &expr) const + const QString &expr, + const AbstractMetaClassCPtr &klass) const { // QFlags construct from integers, do not fix that if (isIntegerConstant(expr)) return expr; + const QString field = qualifyStaticField(klass, expr); + if (!field.isEmpty()) + return field; + const auto typeEntry = type.typeEntry(); EnumTypeEntryCPtr enumTypeEntry; FlagsTypeEntryCPtr flagsTypeEntry; if (typeEntry->isFlags()) { - flagsTypeEntry = qSharedPointerCast<const FlagsTypeEntry>(typeEntry); + flagsTypeEntry = std::static_pointer_cast<const FlagsTypeEntry>(typeEntry); enumTypeEntry = flagsTypeEntry->originator(); } else { Q_ASSERT(typeEntry->isEnum()); - enumTypeEntry = qSharedPointerCast<const EnumTypeEntry>(typeEntry); + enumTypeEntry = std::static_pointer_cast<const EnumTypeEntry>(typeEntry); } // Use the enum's qualified name (would otherwise be "QFlags<Enum>") if (!enumTypeEntry->qualifiedCppName().contains(u"::")) @@ -177,7 +182,7 @@ bool AbstractMetaBuilder::dontFixDefaultValue(QStringView expr) || isIntegerConstant(expr) || isFloatConstant(expr); } -QString AbstractMetaBuilderPrivate::qualifyStaticField(const AbstractMetaClass *c, +QString AbstractMetaBuilderPrivate::qualifyStaticField(const AbstractMetaClassCPtr &c, QStringView field) { if (!c || c->fields().isEmpty()) diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h index 5a6aee3a9..d7aaba5b0 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h @@ -17,19 +17,31 @@ #include <QtCore/QFileInfo> #include <QtCore/QList> #include <QtCore/QMap> +#include <QtCore/QMultiHash> #include <QtCore/QSet> #include <optional> +#include <set> class TypeDatabase; +struct RejectEntry +{ + AbstractMetaBuilder::RejectReason reason; + QString signature; + QString sortkey; + QString message; +}; + +bool operator<(const RejectEntry &re1, const RejectEntry &re2); + class AbstractMetaBuilderPrivate { public: struct TypeClassEntry { AbstractMetaType type; - const AbstractMetaClass *klass; + AbstractMetaClassCPtr klass; }; using TranslateTypeFlags = AbstractMetaBuilder::TranslateTypeFlags; @@ -37,7 +49,6 @@ public: Q_DISABLE_COPY(AbstractMetaBuilderPrivate) AbstractMetaBuilderPrivate(); - ~AbstractMetaBuilderPrivate(); static FileModelItem buildDom(QByteArrayList arguments, bool addCompilerSupportArguments, @@ -60,57 +71,66 @@ public: NamespaceModelItem currentScope() const { return m_scopes.constLast(); } - AbstractMetaClass *argumentToClass(const ArgumentModelItem &, - const AbstractMetaClass *currentClass); + AbstractMetaClassPtr argumentToClass(const ArgumentModelItem &, + const AbstractMetaClassCPtr ¤tClass); - void addAbstractMetaClass(AbstractMetaClass *cls, const _CodeModelItem *item); - AbstractMetaClass *traverseTypeDef(const FileModelItem &dom, + void addAbstractMetaClass(const AbstractMetaClassPtr &cls, const _CodeModelItem *item); + AbstractMetaClassPtr traverseTypeDef(const FileModelItem &dom, const TypeDefModelItem &typeDef, - AbstractMetaClass *currentClass); + const AbstractMetaClassPtr ¤tClass); + AbstractMetaClassPtr traverseTypeDefHelper(const FileModelItem &dom, + const TypeDefModelItem &typeDef, + const AbstractMetaClassPtr ¤tClass); void traverseTypesystemTypedefs(); - AbstractMetaClass *traverseClass(const FileModelItem &dom, + AbstractMetaClassPtr traverseClass(const FileModelItem &dom, const ClassModelItem &item, - AbstractMetaClass *currentClass); - void traverseScopeMembers(const ScopeModelItem &item, AbstractMetaClass *metaClass); + const AbstractMetaClassPtr ¤tClass); + void traverseScopeMembers(const ScopeModelItem &item, + const AbstractMetaClassPtr &metaClass); void traverseClassMembers(const ClassModelItem &scopeItem); - void traverseUsingMembers(AbstractMetaClass *metaClass); + void traverseUsingMembers(const AbstractMetaClassPtr &metaClass) const; void traverseNamespaceMembers(const NamespaceModelItem &scopeItem); - bool setupInheritance(AbstractMetaClass *metaClass); - AbstractMetaClass *traverseNamespace(const FileModelItem &dom, + bool setupInheritance(const AbstractMetaClassPtr &metaClass); + AbstractMetaClassPtr traverseNamespace(const FileModelItem &dom, const NamespaceModelItem &item); std::optional<AbstractMetaEnum> traverseEnum(const EnumModelItem &item, - AbstractMetaClass *enclosing, + const AbstractMetaClassPtr &enclosing, const QSet<QString> &enumsDeclarations); - void traverseEnums(const ScopeModelItem &item, AbstractMetaClass *parent, + void traverseEnums(const ScopeModelItem &item, const AbstractMetaClassPtr &parent, const QStringList &enumsDeclarations); AbstractMetaFunctionRawPtrList classFunctionList(const ScopeModelItem &scopeItem, AbstractMetaClass::Attributes *constructorAttributes, - AbstractMetaClass *currentClass); - void traverseFunctions(ScopeModelItem item, AbstractMetaClass *parent); + const AbstractMetaClassPtr ¤tClass); + void traverseFunctions(const ScopeModelItem& item, + const AbstractMetaClassPtr &parent); static void applyFunctionModifications(AbstractMetaFunction *func); - void traverseFields(const ScopeModelItem &item, AbstractMetaClass *parent); + void traverseFields(const ScopeModelItem &item, const AbstractMetaClassPtr &parent); bool traverseStreamOperator(const FunctionModelItem &functionItem, - AbstractMetaClass *currentClass); + const AbstractMetaClassPtr ¤tClass); void traverseOperatorFunction(const FunctionModelItem &item, - AbstractMetaClass *currentClass); + const AbstractMetaClassPtr ¤tClass); AbstractMetaFunction *traverseAddedFunctionHelper(const AddedFunctionPtr &addedFunc, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, QString *errorMessage); bool traverseAddedGlobalFunction(const AddedFunctionPtr &addedFunc, QString *errorMessage); bool traverseAddedMemberFunction(const AddedFunctionPtr &addedFunc, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, QString *errorMessage); - AbstractMetaFunction *traverseFunction(const FunctionModelItem &function, - AbstractMetaClass *currentClass); + void rejectFunction(const FunctionModelItem &functionItem, + const AbstractMetaClassPtr ¤tClass, + AbstractMetaBuilder::RejectReason reason, + const QString &rejectReason); + AbstractMetaFunction *traverseFunction(const FunctionModelItem &function, + const AbstractMetaClassPtr ¤tClass); std::optional<AbstractMetaField> traverseField(const VariableModelItem &field, - const AbstractMetaClass *cls); - void checkFunctionModifications(); + const AbstractMetaClassCPtr &cls); + void checkFunctionModifications() const; void registerHashFunction(const FunctionModelItem &functionItem, - AbstractMetaClass *currentClass); + const AbstractMetaClassPtr ¤tClass); void registerToStringCapabilityIn(const NamespaceModelItem &namespaceItem); void registerToStringCapability(const FunctionModelItem &functionItem, - AbstractMetaClass *currentClass); + const AbstractMetaClassPtr ¤tClass); /** * A conversion operator function should not have its owner class as @@ -124,48 +144,52 @@ public: */ static void fixReturnTypeOfConversionOperator(AbstractMetaFunction *metaFunction); - void parseQ_Properties(AbstractMetaClass *metaClass, const QStringList &declarations); - void setupEquals(AbstractMetaClass *metaClass); - void setupComparable(AbstractMetaClass *metaClass); - void setupExternalConversion(const AbstractMetaClass *cls); + void parseQ_Properties(const AbstractMetaClassPtr &metaClass, + const QStringList &declarations); + void setupEquals(const AbstractMetaClassPtr &metaClass); + void setupComparable(const AbstractMetaClassPtr &metaClass); + void setupExternalConversion(const AbstractMetaClassCPtr &cls); static bool isQualifiedCppIdentifier(QStringView e); QString fixDefaultValue(QString expr, const AbstractMetaType &type, - const AbstractMetaClass *) const; + const AbstractMetaClassCPtr &) const; QString fixSimpleDefaultValue(QStringView expr, - const AbstractMetaClass *klass) const; + const AbstractMetaClassCPtr &klass) const; - QString fixEnumDefault(const AbstractMetaType &type, const QString &expr) const; + QString fixEnumDefault(const AbstractMetaType &type, const QString &expr, + const AbstractMetaClassCPtr &) const; /// Qualify a static field name for default value expressions - static QString qualifyStaticField(const AbstractMetaClass *c, QStringView field); + static QString qualifyStaticField(const AbstractMetaClassCPtr &c, QStringView field); std::optional<AbstractMetaType> - translateType(const TypeInfo &type, const AbstractMetaClass *currentClass, + translateType(const TypeInfo &type, const AbstractMetaClassCPtr ¤tClass, TranslateTypeFlags flags = {}, QString *errorMessage = nullptr); static std::optional<AbstractMetaType> - translateTypeStatic(const TypeInfo &type, const AbstractMetaClass *current, + translateTypeStatic(const TypeInfo &type, const AbstractMetaClassCPtr ¤t, AbstractMetaBuilderPrivate *d = nullptr, TranslateTypeFlags flags = {}, QString *errorMessageIn = nullptr); static TypeEntryCList findTypeEntriesHelper(const QString &qualifiedName, const QString &name, - const AbstractMetaClass *currentClass = nullptr, + TranslateTypeFlags flags = {}, + const AbstractMetaClassCPtr ¤tClass = {}, AbstractMetaBuilderPrivate *d = nullptr); static TypeEntryCList findTypeEntries(const QString &qualifiedName, const QString &name, - const AbstractMetaClass *currentClass = nullptr, + TranslateTypeFlags flags = {}, + const AbstractMetaClassCPtr ¤tClass = {}, AbstractMetaBuilderPrivate *d = nullptr, QString *errorMessage = nullptr); qint64 findOutValueFromString(const QString &stringValue, bool &ok); - AbstractMetaClass *findTemplateClass(const QString& name, const AbstractMetaClass *context, - TypeInfo *info = Q_NULLPTR, + AbstractMetaClassPtr findTemplateClass(const QString& name, const AbstractMetaClassCPtr &context, + TypeInfo *info = nullptr, ComplexTypeEntryPtr *baseContainerType = nullptr) const; - AbstractMetaClassCList getBaseClasses(const AbstractMetaClass *metaClass) const; + AbstractMetaClassCList getBaseClasses(const AbstractMetaClassCPtr &metaClass) const; - static bool inheritTemplate(AbstractMetaClass *subclass, - const AbstractMetaClass *templateClass, + static bool inheritTemplate(const AbstractMetaClassPtr &subclass, + const AbstractMetaClassCPtr &templateClass, const TypeInfo &info); - static bool inheritTemplate(AbstractMetaClass *subclass, - const AbstractMetaClass *templateClass, + static bool inheritTemplate(const AbstractMetaClassPtr &subclass, + const AbstractMetaClassCPtr &templateClass, const AbstractMetaTypeList &templateTypes, InheritTemplateFlags flags = {}); @@ -176,10 +200,10 @@ public: static AbstractMetaFunctionPtr inheritTemplateMember(const AbstractMetaFunctionCPtr &function, const AbstractMetaTypeList &templateTypes, - const AbstractMetaClass *templateClass, - AbstractMetaClass *subclass); + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaClassPtr &subclass); - static void inheritTemplateFunctions(AbstractMetaClass *subclass); + static void inheritTemplateFunctions(const AbstractMetaClassPtr &subclass); static std::optional<AbstractMetaType> inheritTemplateType(const AbstractMetaTypeList &templateTypes, const AbstractMetaType &metaType); @@ -191,26 +215,26 @@ public: void setInclude(const TypeEntryPtr &te, const QString &path) const; static void fixArgumentNames(AbstractMetaFunction *func, const FunctionModificationList &mods); - void fillAddedFunctions(AbstractMetaClass *metaClass); - const AbstractMetaClass *resolveTypeSystemTypeDef(const AbstractMetaType &t) const; + void fillAddedFunctions(const AbstractMetaClassPtr &metaClass); + AbstractMetaClassCPtr resolveTypeSystemTypeDef(const AbstractMetaType &t) const; void fixSmartPointers(); - AbstractMetaBuilder *q; + AbstractMetaBuilder *q = nullptr; AbstractMetaClassList m_metaClasses; AbstractMetaClassList m_templates; AbstractMetaClassList m_smartPointers; - QHash<const _CodeModelItem *, AbstractMetaClass *> m_itemToClass; - QHash<const AbstractMetaClass *, const _CodeModelItem *> m_classToItem; + QHash<const _CodeModelItem *, AbstractMetaClassPtr > m_itemToClass; + QHash<AbstractMetaClassCPtr, const _CodeModelItem *> m_classToItem; AbstractMetaFunctionCList m_globalFunctions; AbstractMetaEnumList m_globalEnums; - using RejectMap = QMap<QString, AbstractMetaBuilder::RejectReason>; + using RejectSet = std::set<RejectEntry>; - RejectMap m_rejectedClasses; - RejectMap m_rejectedEnums; - RejectMap m_rejectedFunctions; - RejectMap m_rejectedFields; + RejectSet m_rejectedClasses; + RejectSet m_rejectedEnums; + RejectSet m_rejectedFunctions; + RejectSet m_rejectedFields; QHash<TypeEntryCPtr, AbstractMetaEnum> m_enums; @@ -220,6 +244,7 @@ public: QFileInfoList m_globalHeaders; QStringList m_headerPaths; mutable QHash<QString, Include> m_resolveIncludeHash; + QMultiHash<QString, QString> m_typedefTargetToName; QList<TypeClassEntry> m_typeSystemTypeDefs; // look up metatype->class for type system typedefs ApiExtractorFlags m_apiExtractorFlags; bool m_skipDeprecated = false; diff --git a/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp index e44d4ef7e..780170c22 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp @@ -32,8 +32,8 @@ AbstractMetaEnumValue::AbstractMetaEnumValue() : AbstractMetaEnumValue::AbstractMetaEnumValue(const AbstractMetaEnumValue &) = default; AbstractMetaEnumValue &AbstractMetaEnumValue::operator=(const AbstractMetaEnumValue &) = default; -AbstractMetaEnumValue::AbstractMetaEnumValue(AbstractMetaEnumValue &&) = default; -AbstractMetaEnumValue &AbstractMetaEnumValue::operator=(AbstractMetaEnumValue &&) = default; +AbstractMetaEnumValue::AbstractMetaEnumValue(AbstractMetaEnumValue &&) noexcept = default; +AbstractMetaEnumValue &AbstractMetaEnumValue::operator=(AbstractMetaEnumValue &&) noexcept = default; AbstractMetaEnumValue::~AbstractMetaEnumValue() = default; EnumValue AbstractMetaEnumValue::value() const @@ -101,10 +101,14 @@ public: { } + int unsignedUsedBits() const; + int signedUsedBits() const; + AbstractMetaEnumValueList m_enumValues; - EnumTypeEntryPtr m_typeEntry; + EnumTypeEntryCPtr m_typeEntry; Documentation m_doc; + QString m_underlyingType; EnumKind m_enumKind = CEnum; Access m_access = Access::Public; @@ -113,14 +117,46 @@ public: uint m_signed : 1; }; +static int _usedBits(uint64_t v) +{ + return (v >> 32) ? 64 : (v >> 16) ? 32 : (v >> 8) ? 16 : 8; +} + +static int _usedBits(int64_t v) +{ + return (v >> 31) ? 64 : (v >> 15) ? 32 : (v >> 7) ? 16 : 8; +} + +int AbstractMetaEnumData::unsignedUsedBits() const +{ + uint64_t maxValue = 0; + for (const auto &v : m_enumValues) { + if (const auto uv = v.value().unsignedValue(); uv > maxValue) + maxValue = uv; + } + return _usedBits(maxValue); +} + +int AbstractMetaEnumData::signedUsedBits() const +{ + int64_t maxValue = 0; + for (const auto &v : m_enumValues) { + const auto sv = v.value().value(); + const auto absV = sv < 0 ? ~sv : sv; + if (absV > maxValue) + maxValue = absV; + } + return _usedBits(maxValue); +} + AbstractMetaEnum::AbstractMetaEnum() : d(new AbstractMetaEnumData) { } AbstractMetaEnum::AbstractMetaEnum(const AbstractMetaEnum &) = default; AbstractMetaEnum &AbstractMetaEnum::operator=(const AbstractMetaEnum&) = default; -AbstractMetaEnum::AbstractMetaEnum(AbstractMetaEnum &&) = default; -AbstractMetaEnum &AbstractMetaEnum::operator=(AbstractMetaEnum &&) = default; +AbstractMetaEnum::AbstractMetaEnum(AbstractMetaEnum &&) noexcept = default; +AbstractMetaEnum &AbstractMetaEnum::operator=(AbstractMetaEnum &&) noexcept = default; AbstractMetaEnum::~AbstractMetaEnum() = default; const AbstractMetaEnumValueList &AbstractMetaEnum::values() const @@ -128,6 +164,16 @@ const AbstractMetaEnumValueList &AbstractMetaEnum::values() const return d->m_enumValues; } +AbstractMetaEnumValueList AbstractMetaEnum::nonRejectedValues() const +{ + auto te = d->m_typeEntry; + AbstractMetaEnumValueList result = d->m_enumValues; + auto pred = [te](const AbstractMetaEnumValue &v) { + return te->isEnumValueRejected(v.name()); }; + result.erase(std::remove_if(result.begin(), result.end(), pred), result.end()); + return result; +} + void AbstractMetaEnum::addEnumValue(const AbstractMetaEnumValue &enumValue) { d->m_enumValues << enumValue; @@ -263,12 +309,12 @@ void AbstractMetaEnum::setHasQEnumsDeclaration(bool on) d->m_hasQenumsDeclaration = on; } -EnumTypeEntryPtr AbstractMetaEnum::typeEntry() const +EnumTypeEntryCPtr AbstractMetaEnum::typeEntry() const { return d->m_typeEntry; } -void AbstractMetaEnum::setTypeEntry(const EnumTypeEntryPtr &entry) +void AbstractMetaEnum::setTypeEntry(const EnumTypeEntryCPtr &entry) { if (d->m_typeEntry != entry) d->m_typeEntry = entry; @@ -285,12 +331,37 @@ void AbstractMetaEnum::setSigned(bool s) d->m_signed = s; } +QString AbstractMetaEnum::underlyingType() const +{ + return d->m_underlyingType; +} + +void AbstractMetaEnum::setUnderlyingType(const QString &underlyingType) +{ + if (d->m_underlyingType != underlyingType) + d->m_underlyingType = underlyingType; +} + +int AbstractMetaEnum::usedBits() const +{ + return isSigned() ? d->signedUsedBits() : d->unsignedUsedBits(); +} + +QString AbstractMetaEnum::intTypeForSize(int usedBits, bool isSigned) +{ + QString result = u"int"_s + QString::number(usedBits) + u"_t"_s; + return isSigned ? result : u'u' + result; +} + #ifndef QT_NO_DEBUG_STREAM -static void formatMetaEnumValue(QDebug &d, const AbstractMetaEnumValue &v) +static void formatMetaEnumValue(QDebug &d, const AbstractMetaEnumValue &v, bool forceHex = false) { d << v.name() << '='; - v.value().formatDebug(d); + if (forceHex) + v.value().formatDebugHex(d); + else + v.value().formatDebug(d); if (v.isDeprecated()) d << " (deprecated)"; } @@ -308,17 +379,19 @@ QDebug operator<<(QDebug d, const AbstractMetaEnumValue &v) static void formatMetaEnum(QDebug &d, const AbstractMetaEnum &e) { - d << e.fullName(); + d << '"' << e.fullName() << '"'; if (e.isDeprecated()) - d << " (deprecated) "; + d << " (deprecated)"; + d << " \"" << e.underlyingType() << '"'; if (!e.isSigned()) - d << " (unsigned) "; - d << '['; + d << " (unsigned)"; + d << " ["; const AbstractMetaEnumValueList &values = e.values(); + const bool hasFlags = e.typeEntry()->flags() != nullptr; for (qsizetype i = 0, count = values.size(); i < count; ++i) { if (i) d << ", "; - formatMetaEnumValue(d, values.at(i)); + formatMetaEnumValue(d, values.at(i), hasFlags); } d << ']'; } diff --git a/sources/shiboken6/ApiExtractor/abstractmetaenum.h b/sources/shiboken6/ApiExtractor/abstractmetaenum.h index 0e356c1aa..03d7a3082 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetaenum.h +++ b/sources/shiboken6/ApiExtractor/abstractmetaenum.h @@ -28,8 +28,8 @@ public: AbstractMetaEnumValue(); AbstractMetaEnumValue(const AbstractMetaEnumValue &); AbstractMetaEnumValue &operator=(const AbstractMetaEnumValue &); - AbstractMetaEnumValue(AbstractMetaEnumValue &&); - AbstractMetaEnumValue &operator=(AbstractMetaEnumValue &&); + AbstractMetaEnumValue(AbstractMetaEnumValue &&) noexcept; + AbstractMetaEnumValue &operator=(AbstractMetaEnumValue &&) noexcept; ~AbstractMetaEnumValue(); EnumValue value() const; @@ -47,6 +47,8 @@ public: Documentation documentation() const; void setDocumentation(const Documentation& doc); + int usedBits() const; + private: QSharedDataPointer<AbstractMetaEnumValueData> d; }; @@ -57,11 +59,12 @@ public: AbstractMetaEnum(); AbstractMetaEnum(const AbstractMetaEnum &); AbstractMetaEnum &operator=(const AbstractMetaEnum &); - AbstractMetaEnum(AbstractMetaEnum &&); - AbstractMetaEnum &operator=(AbstractMetaEnum &&); + AbstractMetaEnum(AbstractMetaEnum &&) noexcept; + AbstractMetaEnum &operator=(AbstractMetaEnum &&) noexcept; ~AbstractMetaEnum(); const AbstractMetaEnumValueList &values() const; + AbstractMetaEnumValueList nonRejectedValues() const; void addEnumValue(const AbstractMetaEnumValue &enumValue); std::optional<AbstractMetaEnumValue> findEnumValue(QStringView value) const; @@ -97,12 +100,18 @@ public: bool hasQEnumsDeclaration() const; void setHasQEnumsDeclaration(bool on); - EnumTypeEntryPtr typeEntry() const; - void setTypeEntry(const EnumTypeEntryPtr &entry); + EnumTypeEntryCPtr typeEntry() const; + void setTypeEntry(const EnumTypeEntryCPtr &entry); bool isSigned() const; void setSigned(bool s); + QString underlyingType() const; + void setUnderlyingType(const QString &underlyingType); + + static QString intTypeForSize(int usedBits, bool isSigned); + int usedBits() const; + private: QSharedDataPointer<AbstractMetaEnumData> d; }; diff --git a/sources/shiboken6/ApiExtractor/abstractmetafield.cpp b/sources/shiboken6/ApiExtractor/abstractmetafield.cpp index 06bdbee1e..27a76d04d 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetafield.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetafield.cpp @@ -36,8 +36,8 @@ AbstractMetaField::AbstractMetaField() : d(new AbstractMetaFieldData) AbstractMetaField::AbstractMetaField(const AbstractMetaField &) = default; AbstractMetaField &AbstractMetaField::operator=(const AbstractMetaField &) = default; -AbstractMetaField::AbstractMetaField(AbstractMetaField &&) = default; -AbstractMetaField &AbstractMetaField::operator=(AbstractMetaField &&) = default; +AbstractMetaField::AbstractMetaField(AbstractMetaField &&) noexcept = default; +AbstractMetaField &AbstractMetaField::operator=(AbstractMetaField &&) noexcept = default; AbstractMetaField::~AbstractMetaField() = default; // returned->setEnclosingClass(nullptr); diff --git a/sources/shiboken6/ApiExtractor/abstractmetafield.h b/sources/shiboken6/ApiExtractor/abstractmetafield.h index 7de1298f3..0fa858791 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetafield.h +++ b/sources/shiboken6/ApiExtractor/abstractmetafield.h @@ -26,8 +26,8 @@ public: AbstractMetaField(); AbstractMetaField(const AbstractMetaField &); AbstractMetaField &operator=(const AbstractMetaField &); - AbstractMetaField(AbstractMetaField &&); - AbstractMetaField &operator=(AbstractMetaField &&); + AbstractMetaField(AbstractMetaField &&) noexcept; + AbstractMetaField &operator=(AbstractMetaField &&) noexcept; ~AbstractMetaField(); FieldModificationList modifications() const; diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp index 03e795ec2..11a02f154 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp @@ -18,6 +18,7 @@ #include "sourcelocation.h" #include "typedatabase.h" #include "complextypeentry.h" +#include "containertypeentry.h" #include "functiontypeentry.h" #include "primitivetypeentry.h" #include "typesystemtypeentry.h" @@ -27,13 +28,15 @@ #include <QtCore/QDebug> #include <QtCore/QRegularExpression> +#include <algorithm> + using namespace Qt::StringLiterals; // Cache FunctionModificationList in a flat list per class (0 for global // functions, or typically owner/implementing/declaring class. struct ModificationCacheEntry { - const AbstractMetaClass *klass; + AbstractMetaClassCPtr klass; FunctionModificationList modifications; }; @@ -45,7 +48,6 @@ public: AbstractMetaFunctionPrivate() : m_constant(false), m_reverse(false), - m_explicit(false), m_pointerOperator(false), m_isCallOperator(false) { @@ -58,7 +60,7 @@ public: int overloadNumber(const AbstractMetaFunction *q) const; const FunctionModificationList &modifications(const AbstractMetaFunction *q, - const AbstractMetaClass *implementor) const; + const AbstractMetaClassCPtr &implementor) const; bool applyTypeModification(const AbstractMetaFunction *q, const QString &type, int number, QString *errorMessage); @@ -75,19 +77,19 @@ public: AbstractMetaFunction::FunctionType m_functionType = AbstractMetaFunction::NormalFunction; AbstractMetaType m_type; QString m_modifiedTypeName; - const AbstractMetaClass *m_class = nullptr; - const AbstractMetaClass *m_implementingClass = nullptr; - const AbstractMetaClass *m_declaringClass = nullptr; + AbstractMetaClassCPtr m_class; + AbstractMetaClassCPtr m_implementingClass; + AbstractMetaClassCPtr m_declaringClass; mutable ModificationCache m_modificationCache; int m_propertySpecIndex = -1; AbstractMetaArgumentList m_arguments; AddedFunctionPtr m_addedFunction; SourceLocation m_sourceLocation; AbstractMetaFunction::Attributes m_attributes; + FunctionAttributes m_cppAttributes; AbstractMetaFunction::Flags m_flags; uint m_constant : 1; uint m_reverse : 1; - uint m_explicit : 1; uint m_pointerOperator : 1; uint m_isCallOperator : 1; mutable int m_cachedOverloadNumber = TypeSystem::OverloadNumberUnset; @@ -117,9 +119,9 @@ AbstractMetaFunction::AbstractMetaFunction(const AddedFunctionPtr &addedFunc) : setAccess(Access::Public); break; } - AbstractMetaFunction::Attributes atts = AbstractMetaFunction::FinalInTargetLang; + AbstractMetaFunction::Attributes atts; if (addedFunc->isStatic()) - atts |= AbstractMetaFunction::Static; + setCppAttribute(FunctionAttribute::Static); if (addedFunc->isClassMethod()) atts |= AbstractMetaFunction::ClassMethod; setAttributes(atts); @@ -212,12 +214,12 @@ void AbstractMetaFunction::setPointerOperator(bool value) bool AbstractMetaFunction::isExplicit() const { - return d->m_explicit; + return d->m_cppAttributes.testFlag(FunctionAttribute::Explicit); } void AbstractMetaFunction::setExplicit(bool isExplicit) { - d->m_explicit = isExplicit; + d->m_cppAttributes.setFlag(FunctionAttribute::Explicit, isExplicit); } bool AbstractMetaFunction::returnsBool() const @@ -259,6 +261,21 @@ void AbstractMetaFunction::operator-=(AbstractMetaFunction::Attribute attribute) d->m_attributes.setFlag(attribute, false); } +FunctionAttributes AbstractMetaFunction::cppAttributes() const +{ + return d->m_cppAttributes; +} + +void AbstractMetaFunction::setCppAttributes(FunctionAttributes a) +{ + d->m_cppAttributes = a; +} + +void AbstractMetaFunction::setCppAttribute(FunctionAttribute a, bool on) +{ + d->m_cppAttributes.setFlag(a, on); +} + AbstractMetaFunction::Flags AbstractMetaFunction::flags() const { return d->m_flags; @@ -272,9 +289,9 @@ void AbstractMetaFunction::setFlags(Flags f) /******************************************************************************* * Indicates that this function has a modification that removes it */ -bool AbstractMetaFunction::isModifiedRemoved(const AbstractMetaClass *cls) const +bool AbstractMetaFunction::isModifiedRemoved(AbstractMetaClassCPtr cls) const { - if (!isInGlobalScope() && cls == nullptr) + if (!isInGlobalScope() && !cls) cls = d->m_implementingClass; for (const auto &mod : modifications(cls)) { if (mod.isRemoved()) @@ -284,7 +301,7 @@ bool AbstractMetaFunction::isModifiedRemoved(const AbstractMetaClass *cls) const return false; } -bool AbstractMetaFunction::isModifiedFinal(const AbstractMetaClass *cls) const +bool AbstractMetaFunction::isModifiedFinal(AbstractMetaClassCPtr cls) const { if (!isInGlobalScope() && cls == nullptr) cls = d->m_implementingClass; @@ -310,12 +327,12 @@ void AbstractMetaFunction::setType(const AbstractMetaType &type) d->m_type = type; } -const AbstractMetaClass *AbstractMetaFunction::ownerClass() const +AbstractMetaClassCPtr AbstractMetaFunction::ownerClass() const { return d->m_class; } -void AbstractMetaFunction::setOwnerClass(const AbstractMetaClass *cls) +void AbstractMetaFunction::setOwnerClass(const AbstractMetaClassCPtr &cls) { d->m_class = cls; } @@ -339,7 +356,7 @@ AbstractMetaFunction::CompareResult AbstractMetaFunction::compareTo(const Abstra result |= EqualImplementor; // Attributes - if (attributes() == other->attributes()) + if (attributes() == other->attributes() && cppAttributes() == other->cppAttributes()) result |= EqualAttributes; // Compare types @@ -424,6 +441,10 @@ AbstractMetaFunction *AbstractMetaFunction::copy() const { auto *cpy = new AbstractMetaFunction; cpy->setAttributes(attributes()); + auto ca = cppAttributes(); + // Historical bug: explicit was not copied! (causing nontypetemplate_test.py fail) + ca.setFlag(FunctionAttribute::Explicit, false); + cpy->setCppAttributes(ca); cpy->setFlags(flags()); cpy->setAccess(access()); cpy->setName(name()); @@ -461,6 +482,9 @@ bool AbstractMetaFunction::generateBinding() const { switch (d->m_functionType) { case ConversionOperator: + if (d->m_name != u"operator int" && d->m_name != u"operator double") + return false; + break; case AssignmentOperatorFunction: case MoveAssignmentOperatorFunction: case AbstractMetaFunction::MoveConstructorFunction: @@ -470,9 +494,19 @@ bool AbstractMetaFunction::generateBinding() const return false; break; } + // Can we access the wrapper in case of a protected method? If not, + // disable for consistency regardless of avoidProtectedHack. + if (isProtected()) { + const auto typeFlags = ownerClass()->typeEntry()->typeFlags(); + if (typeFlags.testFlag(ComplexTypeEntry::DisableWrapper)) + return false; + } if (isPrivate() && d->m_functionType != EmptyFunction) return false; - return d->m_name != u"qt_metacall" && !usesRValueReferences() + // RValue references only for user-specified + // functions (<add-function>/<declare-function>/<function>) + return d->m_name != u"qt_metacall" && + (!usesRValueReferences() || d->m_addedFunction || d->m_typeEntry) && !isModifiedRemoved(); } @@ -482,7 +516,7 @@ bool AbstractMetaFunction::isWhiteListed() const case NormalFunction: case SignalFunction: case SlotFunction: - if (auto *dc = declaringClass()) { + if (auto dc = declaringClass()) { const QSet<QString> &whiteList = dc->typeEntry()->generateFunctions(); return whiteList.isEmpty() || whiteList.contains(d->m_name) || whiteList.contains(minimalSignature()); @@ -555,12 +589,17 @@ void AbstractMetaFunction::setConstant(bool constant) bool AbstractMetaFunction::isUserAdded() const { - return !d->m_addedFunction.isNull() && !d->m_addedFunction->isDeclaration(); + return d->m_addedFunction && !d->m_addedFunction->isDeclaration(); +} + +bool AbstractMetaFunction::isUserAddedPythonOverride() const +{ + return d->m_addedFunction && d->m_addedFunction->isPythonOverride(); } bool AbstractMetaFunction::isUserDeclared() const { - return !d->m_addedFunction.isNull() && d->m_addedFunction->isDeclaration(); + return d->m_addedFunction && d->m_addedFunction->isDeclaration(); } int AbstractMetaFunction::actualMinimumArgumentCount() const @@ -590,7 +629,7 @@ int AbstractMetaFunction::actualArgumentIndex(int index) const } // Returns reference counts for argument at idx, or all arguments if idx == -2 -QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const +QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClassCPtr &cls, int idx) const { QList<ReferenceCount> returned; @@ -605,7 +644,7 @@ QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaCl return returned; } -ArgumentOwner AbstractMetaFunction::argumentOwner(const AbstractMetaClass *cls, int idx) const +ArgumentOwner AbstractMetaFunction::argumentOwner(const AbstractMetaClassCPtr &cls, int idx) const { for (const auto &mod : modifications(cls)) { for (const ArgumentModification &argumentMod : mod.argument_mods()) { @@ -654,28 +693,28 @@ bool AbstractMetaFunction::argumentRemoved(int key) const return false; } -const AbstractMetaClass *AbstractMetaFunction::targetLangOwner() const +AbstractMetaClassCPtr AbstractMetaFunction::targetLangOwner() const { return d->m_class && d->m_class->isInvisibleNamespace() ? d->m_class->targetLangEnclosingClass() : d->m_class; } -const AbstractMetaClass *AbstractMetaFunction::declaringClass() const +AbstractMetaClassCPtr AbstractMetaFunction::declaringClass() const { return d->m_declaringClass; } -void AbstractMetaFunction::setDeclaringClass(const AbstractMetaClass *cls) +void AbstractMetaFunction::setDeclaringClass(const AbstractMetaClassCPtr &cls) { d->m_declaringClass = cls; } -const AbstractMetaClass *AbstractMetaFunction::implementingClass() const +AbstractMetaClassCPtr AbstractMetaFunction::implementingClass() const { return d->m_implementingClass; } -void AbstractMetaFunction::setImplementingClass(const AbstractMetaClass *cls) +void AbstractMetaFunction::setImplementingClass(const AbstractMetaClassCPtr &cls) { d->m_implementingClass = cls; } @@ -700,15 +739,23 @@ void AbstractMetaFunction::addArgument(const AbstractMetaArgument &argument) d->m_arguments << argument; } +static bool modifiedDeprecated(const FunctionModification &mod) +{ + return mod.modifiers().testFlag(FunctionModification::Deprecated); +} + +static bool modifiedUndeprecated(const FunctionModification &mod) +{ + return mod.modifiers().testFlag(FunctionModification::Undeprecated); +} + bool AbstractMetaFunction::isDeprecated() const { - if (d->m_attributes.testFlag(Attribute::Deprecated)) - return true; - for (const auto &modification : modifications(declaringClass())) { - if (modification.isDeprecated()) - return true; - } - return false; + const auto &mods = modifications(declaringClass()); + + return d->m_cppAttributes.testFlag(FunctionAttribute::Deprecated) + ? std::none_of(mods.cbegin(), mods.cend(), modifiedUndeprecated) + : std::any_of(mods.cbegin(), mods.cend(), modifiedDeprecated); } bool AbstractMetaFunction::isConstructor() const @@ -799,12 +846,12 @@ void AbstractMetaFunction::setSourceLocation(const SourceLocation &sourceLocatio d->m_sourceLocation = sourceLocation; } -static inline TypeSystem::AllowThread allowThreadMod(const AbstractMetaClass *klass) +static inline TypeSystem::AllowThread allowThreadMod(const AbstractMetaClassCPtr &klass) { return klass->typeEntry()->allowThread(); } -static inline bool hasAllowThreadMod(const AbstractMetaClass *klass) +static inline bool hasAllowThreadMod(const AbstractMetaClassCPtr &klass) { return allowThreadMod(klass) != TypeSystem::AllowThread::Unspecified; } @@ -837,7 +884,7 @@ bool AbstractMetaFunction::allowThread() const return result; } -TypeSystem::Ownership AbstractMetaFunction::argumentTargetOwnership(const AbstractMetaClass *cls, int idx) const +TypeSystem::Ownership AbstractMetaFunction::argumentTargetOwnership(const AbstractMetaClassCPtr &cls, int idx) const { for (const auto &modification : modifications(cls)) { for (const ArgumentModification &argumentModification : modification.argument_mods()) { @@ -856,10 +903,15 @@ const QString &AbstractMetaFunction::modifiedTypeName() const bool AbstractMetaFunction::generateOpaqueContainerReturn() const { - return isTypeModified() - && d->m_type.typeUsagePattern() == AbstractMetaType::ContainerPattern - && d->m_type.referenceType() == LValueReference - && d->m_type.generateOpaqueContainerForGetter(d->m_modifiedTypeName); + if (!isTypeModified() || d->m_type.typeUsagePattern() != AbstractMetaType::ContainerPattern) + return false; + // Needs to be a reference to a container, allow by value only for spans + if (d->m_type.referenceType() != LValueReference) { + auto cte = std::static_pointer_cast<const ContainerTypeEntry>(d->m_type.typeEntry()); + if (cte->containerKind() != ContainerTypeEntry::SpanContainer) + return false; + } + return d->m_type.generateOpaqueContainerForGetter(d->m_modifiedTypeName); } bool AbstractMetaFunction::isModifiedToArray(int argumentIndex) const @@ -947,12 +999,14 @@ QString AbstractMetaFunctionPrivate::formatMinimalSignature(const AbstractMetaFu { QString result = m_originalName + u'('; for (qsizetype i = 0; i < m_arguments.size(); ++i) { + const auto &argument = m_arguments.at(i); if (i > 0) result += u','; - result += comment - ? m_arguments.at(i).modifiedType().minimalSignature() - : m_arguments.at(i).type().minimalSignature(); + const auto &type = comment ? argument.modifiedType() : argument.type(); + result += type.minimalSignature(); + if (comment && argument.hasDefaultValueExpression()) + result += u'='; } result += u')'; if (m_constant) @@ -990,9 +1044,10 @@ QString AbstractMetaFunction::signatureComment() const QString AbstractMetaFunction::debugSignature() const { QString result; - const bool isOverride = attributes() & AbstractMetaFunction::OverriddenCppMethod; - const bool isFinal = attributes() & AbstractMetaFunction::FinalCppMethod; - if (!isOverride && !isFinal && (attributes() & AbstractMetaFunction::VirtualCppMethod)) + const auto attributes = cppAttributes(); + const bool isOverride = attributes.testFlag(FunctionAttribute::Override); + const bool isFinal = attributes.testFlag(FunctionAttribute::Final); + if (!isOverride && !isFinal && (attributes.testFlag(FunctionAttribute::Virtual))) result += u"virtual "_s; if (d->m_implementingClass) result += d->m_implementingClass->qualifiedCppName() + u"::"_s; @@ -1005,7 +1060,7 @@ QString AbstractMetaFunction::debugSignature() const } FunctionModificationList AbstractMetaFunction::findClassModifications(const AbstractMetaFunction *f, - const AbstractMetaClass *implementor) + AbstractMetaClassCPtr implementor) { const auto signatures = f->modificationSignatures(); FunctionModificationList mods; @@ -1028,9 +1083,9 @@ FunctionModificationList AbstractMetaFunction::findGlobalModifications(const Abs const FunctionModificationList & AbstractMetaFunctionPrivate::modifications(const AbstractMetaFunction *q, - const AbstractMetaClass *implementor) const + const AbstractMetaClassCPtr &implementor) const { - if (!m_addedFunction.isNull()) + if (m_addedFunction) return m_addedFunction->modifications(); for (const auto &ce : m_modificationCache) { if (ce.klass == implementor) @@ -1045,9 +1100,9 @@ const FunctionModificationList & } const FunctionModificationList & - AbstractMetaFunction::modifications(const AbstractMetaClass *implementor) const + AbstractMetaFunction::modifications(AbstractMetaClassCPtr implementor) const { - if (implementor == nullptr) + if (!implementor) implementor = d->m_class; return d->modifications(this, implementor); } @@ -1059,13 +1114,13 @@ void AbstractMetaFunction::clearModificationsCache() const DocModificationList AbstractMetaFunction::addedFunctionDocModifications() const { - return d->m_addedFunction.isNull() - ? DocModificationList{} : d->m_addedFunction->docModifications(); + return d->m_addedFunction + ? d->m_addedFunction->docModifications() : DocModificationList{}; } QString AbstractMetaFunction::argumentName(int index, bool /* create */, - const AbstractMetaClass * /* implementor */) const + AbstractMetaClassCPtr /* implementor */) const { return d->m_arguments[--index].name(); } @@ -1090,6 +1145,17 @@ void AbstractMetaFunction::setTypeEntry(const FunctionTypeEntryPtr &typeEntry) d->m_typeEntry = typeEntry; } +QString AbstractMetaFunction::targetLangPackage() const +{ + if (d->m_addedFunction != nullptr) + return d->m_addedFunction->targetLangPackage(); + if (d->m_class != nullptr) + return d->m_class->typeEntry()->targetLangPackage(); + if (d->m_typeEntry != nullptr) + return d->m_typeEntry->targetLangPackage(); + return {}; +} + bool AbstractMetaFunction::isCallOperator() const { return d->m_name == u"operator()"; @@ -1186,12 +1252,12 @@ void AbstractMetaFunction::setExceptionSpecification(ExceptionSpecification e) d->m_exceptionSpecification = e; } -static inline TypeSystem::ExceptionHandling exceptionMod(const AbstractMetaClass *klass) +static inline TypeSystem::ExceptionHandling exceptionMod(const AbstractMetaClassCPtr &klass) { return klass->typeEntry()->exceptionHandling(); } -static inline bool hasExceptionMod(const AbstractMetaClass *klass) +static inline bool hasExceptionMod(const AbstractMetaClassCPtr &klass) { return exceptionMod(klass) != TypeSystem::ExceptionHandling::Unspecified; } @@ -1345,7 +1411,7 @@ bool AbstractMetaFunction::isInplaceOperator() const bool AbstractMetaFunction::isVirtual() const { - return d->m_attributes.testFlag(AbstractMetaFunction::VirtualCppMethod); + return d->m_cppAttributes.testFlag(FunctionAttribute::Virtual); } QString AbstractMetaFunctionPrivate::modifiedName(const AbstractMetaFunction *q) const @@ -1370,7 +1436,7 @@ QString AbstractMetaFunction::modifiedName() const AbstractMetaFunctionCPtr AbstractMetaFunction::find(const AbstractMetaFunctionCList &haystack, - QStringView needle) + QAnyStringView needle) { for (const auto &f : haystack) { if (f->name() == needle) @@ -1468,11 +1534,8 @@ TypeSystem::SnakeCase AbstractMetaFunction::snakeCase() const return mod.snakeCase(); } - if (d->m_typeEntry) { // Global function - const auto snakeCase = d->m_typeEntry->snakeCase(); - return snakeCase != TypeSystem::SnakeCase::Unspecified - ? snakeCase : typeSystemTypeEntry(d->m_typeEntry)->snakeCase(); - } + if (d->m_typeEntry) // Global function + return typeSystemTypeEntry(d->m_typeEntry)->snakeCase(); if (d->m_class) { auto typeEntry = d->m_class->typeEntry(); @@ -1492,7 +1555,7 @@ bool AbstractMetaFunction::injectedCodeUsesPySelf() const bool AbstractMetaFunction::injectedCodeCallsPythonOverride() const { static const QRegularExpression - overrideCallRegexCheck(QStringLiteral(R"(PyObject_Call\s*\(\s*%PYTHON_METHOD_OVERRIDE\s*,)")); + overrideCallRegexCheck(R"(PyObject_Call\s*\(\s*%PYTHON_METHOD_OVERRIDE\s*,)"_L1); Q_ASSERT(overrideCallRegexCheck.isValid()); return injectedCodeContains(overrideCallRegexCheck, TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode); @@ -1502,13 +1565,13 @@ bool AbstractMetaFunction::injectedCodeHasReturnValueAttribution(TypeSystem::Lan { if (language == TypeSystem::TargetLangCode) { static const QRegularExpression - retValAttributionRegexCheck_target(QStringLiteral(R"(%PYARG_0\s*=[^=]\s*.+)")); + retValAttributionRegexCheck_target(R"(%PYARG_0\s*=[^=]\s*.+)"_L1); Q_ASSERT(retValAttributionRegexCheck_target.isValid()); return injectedCodeContains(retValAttributionRegexCheck_target, TypeSystem::CodeSnipPositionAny, language); } static const QRegularExpression - retValAttributionRegexCheck_native(QStringLiteral(R"(%0\s*=[^=]\s*.+)")); + retValAttributionRegexCheck_native(R"(%0\s*=[^=]\s*.+)"_L1); Q_ASSERT(retValAttributionRegexCheck_native.isValid()); return injectedCodeContains(retValAttributionRegexCheck_native, TypeSystem::CodeSnipPositionAny, language); } @@ -1606,9 +1669,9 @@ void AbstractMetaFunction::formatDebugVerbose(QDebug &debug) const debug << " [userAdded]"; if (isUserDeclared()) debug << " [userDeclared]"; - if (d->m_explicit) + if (d->m_cppAttributes.testFlag(FunctionAttribute::Explicit)) debug << " [explicit]"; - if (attributes().testFlag(AbstractMetaFunction::Deprecated)) + if (d->m_cppAttributes.testFlag(FunctionAttribute::Deprecated)) debug << " [deprecated]"; if (d->m_pointerOperator) debug << " [operator->]"; diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.h b/sources/shiboken6/ApiExtractor/abstractmetafunction.h index e1f8e774d..e252e439d 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetafunction.h +++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.h @@ -11,6 +11,7 @@ #include "typesystem_typedefs.h" #include "parser/codemodel_enums.h" +#include <QtCore/QMetaObject> #include <QtCore/QScopedPointer> #include <optional> @@ -31,6 +32,8 @@ class AbstractMetaFunction { Q_GADGET public: + Q_DISABLE_COPY_MOVE(AbstractMetaFunction) + enum FunctionType { ConstructorFunction, CopyConstructorFunction, @@ -89,14 +92,8 @@ public: enum Attribute { None = 0x00000000, - Friendly = 0x00000001, - - Abstract = 0x00000002, - Static = 0x00000004, ClassMethod = 0x00000008, - FinalInTargetLang = 0x00000010, - GetterFunction = 0x00000020, SetterFunction = 0x00000040, @@ -105,14 +102,8 @@ public: PropertyResetter = 0x00000400, PropertyNotify = 0x00000800, - Invokable = 0x00001000, - - VirtualCppMethod = 0x00010000, - OverriddenCppMethod = 0x00020000, - FinalCppMethod = 0x00040000, // Add by meta builder (implicit constructors, inherited methods, etc) AddedMethod = 0x001000000, - Deprecated = 0x002000000 // Code annotation }; Q_DECLARE_FLAGS(Attributes, Attribute) Q_FLAG(Attribute) @@ -123,6 +114,10 @@ public: void operator+=(Attribute attribute); void operator-=(Attribute attribute); + FunctionAttributes cppAttributes() const; + void setCppAttributes(FunctionAttributes a); + void setCppAttribute(FunctionAttribute a, bool on = true); + enum class Flag { // Internal flags not relevant for comparing functions // Binary operator whose leading/trailing argument was removed by metabuilder OperatorLeadingClassArgumentRemoved = 0x1, @@ -137,11 +132,9 @@ public: Flags flags() const; void setFlags(Flags f); - bool isFinalInTargetLang() const; bool isAbstract() const; bool isClassMethod() const; bool isStatic() const; - bool isInvokable() const; bool isPropertyReader() const; bool isPropertyWriter() const; bool isPropertyResetter() const; @@ -241,8 +234,8 @@ public: QString signatureComment() const; QString debugSignature() const; // including virtual/override/final, etc., for debugging only. - bool isModifiedRemoved(const AbstractMetaClass *cls = nullptr) const; - bool isModifiedFinal(const AbstractMetaClass *cls = nullptr) const; + bool isModifiedRemoved(AbstractMetaClassCPtr cls = {}) const; + bool isModifiedFinal(AbstractMetaClassCPtr cls = {}) const; bool isVoid() const; @@ -250,19 +243,19 @@ public: void setType(const AbstractMetaType &type); // The class that has this function as a member. - const AbstractMetaClass *ownerClass() const; - void setOwnerClass(const AbstractMetaClass *cls); + AbstractMetaClassCPtr ownerClass() const; + void setOwnerClass(const AbstractMetaClassCPtr &cls); // Owner excluding invisible namespaces - const AbstractMetaClass *targetLangOwner() const; + AbstractMetaClassCPtr targetLangOwner() const; // The first class in a hierarchy that declares the function - const AbstractMetaClass *declaringClass() const; - void setDeclaringClass(const AbstractMetaClass *cls); + AbstractMetaClassCPtr declaringClass() const; + void setDeclaringClass(const AbstractMetaClassCPtr &cls); // The class that actually implements this function - const AbstractMetaClass *implementingClass() const; - void setImplementingClass(const AbstractMetaClass *cls); + AbstractMetaClassCPtr implementingClass() const; + void setImplementingClass(const AbstractMetaClassCPtr &cls); const AbstractMetaArgumentList &arguments() const; AbstractMetaArgumentList &arguments(); @@ -307,6 +300,7 @@ public: /// Returns true if the AbstractMetaFunction was added by the user via the type system description. bool isUserAdded() const; + bool isUserAddedPythonOverride() const; /// Returns true if the AbstractMetaFunction was declared by the user via /// the type system description. bool isUserDeclared() const; @@ -320,11 +314,13 @@ public: QString conversionRule(TypeSystem::Language language, int idx) const; bool hasConversionRule(TypeSystem::Language language, int idx) const; - QList<ReferenceCount> referenceCounts(const AbstractMetaClass *cls, int idx = -2) const; - ArgumentOwner argumentOwner(const AbstractMetaClass *cls, int idx) const; + QList<ReferenceCount> + referenceCounts(const AbstractMetaClassCPtr &cls, int idx = -2) const; + ArgumentOwner argumentOwner(const AbstractMetaClassCPtr &cls, int idx) const; // Returns the ownership rules for the given argument (target lang). - TypeSystem::Ownership argumentTargetOwnership(const AbstractMetaClass *cls, int idx) const; + TypeSystem::Ownership + argumentTargetOwnership(const AbstractMetaClassCPtr &cls, int idx) const; const QString &modifiedTypeName() const; bool isTypeModified() const { return !modifiedTypeName().isEmpty(); } @@ -364,31 +360,32 @@ public: */ bool hasSignatureModifications() const; - const FunctionModificationList &modifications(const AbstractMetaClass *implementor = nullptr) const; + const FunctionModificationList &modifications(AbstractMetaClassCPtr implementor = {}) const; void clearModificationsCache(); const DocModificationList addedFunctionDocModifications() const; static FunctionModificationList findClassModifications(const AbstractMetaFunction *f, - const AbstractMetaClass *implementor); + AbstractMetaClassCPtr implementor); static FunctionModificationList findGlobalModifications(const AbstractMetaFunction *f); /** * Return the argument name if there is a modification the renamed value will be returned */ - QString argumentName(int index, bool create = true, const AbstractMetaClass *cl = nullptr) const; + QString argumentName(int index, bool create = true, AbstractMetaClassCPtr cl = {}) const; int propertySpecIndex() const; void setPropertySpecIndex(int i); FunctionTypeEntryPtr typeEntry() const; - void setTypeEntry(const FunctionTypeEntryPtr &typeEntry); + QString targetLangPackage() const; + bool isCallOperator() const; static AbstractMetaFunctionCPtr - find(const AbstractMetaFunctionCList &haystack, QStringView needle); + find(const AbstractMetaFunctionCList &haystack, QAnyStringView needle); bool matches(OperatorQueryOptions) const; @@ -447,19 +444,14 @@ private: QScopedPointer<AbstractMetaFunctionPrivate> d; }; -inline bool AbstractMetaFunction::isFinalInTargetLang() const -{ - return attributes().testFlag(FinalInTargetLang); -} - inline bool AbstractMetaFunction::isAbstract() const { - return attributes().testFlag(Abstract); + return cppAttributes().testFlag(FunctionAttribute::Abstract); } inline bool AbstractMetaFunction::isStatic() const { - return attributes().testFlag(Static); + return cppAttributes().testFlag(FunctionAttribute::Static); } inline bool AbstractMetaFunction::isClassMethod() const @@ -467,11 +459,6 @@ inline bool AbstractMetaFunction::isClassMethod() const return attributes().testFlag(ClassMethod); } -inline bool AbstractMetaFunction::isInvokable() const -{ - return attributes().testFlag(Invokable); -} - inline bool AbstractMetaFunction::isPropertyReader() const { return attributes().testFlag(PropertyReader); diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp index 77d346a9d..fb49cc9d0 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "abstractmetalang.h" +#include "anystringview_helpers.h" #include "abstractmetalang_helpers.h" #include "abstractmetaargument.h" #include "abstractmetaenum.h" @@ -60,13 +61,16 @@ public: static AbstractMetaFunction * createFunction(const QString &name, AbstractMetaFunction::FunctionType t, Access access, const AbstractMetaArgumentList &arguments, - const AbstractMetaType &returnType, AbstractMetaClass *q); + const AbstractMetaType &returnType, const AbstractMetaClassPtr &q); void addConstructor(AbstractMetaFunction::FunctionType t, Access access, const AbstractMetaArgumentList &arguments, - AbstractMetaClass *q); - void addUsingConstructors(AbstractMetaClass *q); - bool isUsingMember(const AbstractMetaClass *c, const QString &memberName, + const AbstractMetaClassPtr &q); + void addUsingConstructors(const AbstractMetaClassPtr &q); + void sortFunctions(); + void setFunctions(const AbstractMetaFunctionCList &functions, + const AbstractMetaClassCPtr &q); + bool isUsingMember(const AbstractMetaClassCPtr &c, const QString &memberName, Access minimumAccess) const; bool hasConstructors() const; qsizetype indexOfProperty(const QString &name) const; @@ -90,14 +94,15 @@ public: Documentation m_doc; - const AbstractMetaClass *m_enclosingClass = nullptr; - const AbstractMetaClass *m_defaultSuperclass = nullptr; + AbstractMetaClassCPtr m_enclosingClass; + AbstractMetaClassCPtr m_defaultSuperclass; AbstractMetaClassCList m_baseClasses; // Real base classes after setting up inheritance AbstractMetaTypeList m_baseTemplateInstantiations; - const AbstractMetaClass *m_extendedNamespace = nullptr; + AbstractMetaClassCPtr m_extendedNamespace; - const AbstractMetaClass *m_templateBaseClass = nullptr; + AbstractMetaClassCPtr m_templateBaseClass; AbstractMetaFunctionCList m_functions; + AbstractMetaFunctionCList m_userAddedPythonOverrides; AbstractMetaFieldList m_fields; AbstractMetaEnumList m_enums; QList<QPropertySpec> m_propertySpecs; @@ -173,29 +178,16 @@ AbstractMetaFunctionCList AbstractMetaClass::functionsInTargetLang() const FunctionQueryOptions default_flags = FunctionQueryOption::NormalFunctions | FunctionQueryOption::Visible | FunctionQueryOption::NotRemoved; - // Only public functions in final classes - // default_flags |= isFinal() ? WasPublic : 0; - FunctionQueryOptions public_flags; - if (isFinalInTargetLang()) - public_flags |= FunctionQueryOption::WasPublic; - // Constructors AbstractMetaFunctionCList returned = queryFunctions(FunctionQueryOption::AnyConstructor - | default_flags | public_flags); - - // Final functions - returned += queryFunctions(FunctionQueryOption::FinalInTargetLangFunctions - | FunctionQueryOption::NonStaticFunctions - | default_flags | public_flags); + | default_flags); - // Virtual functions - returned += queryFunctions(FunctionQueryOption::VirtualInTargetLangFunctions - | FunctionQueryOption::NonStaticFunctions - | default_flags | public_flags); + returned += queryFunctions(FunctionQueryOption::NonStaticFunctions + | default_flags); // Static functions returned += queryFunctions(FunctionQueryOption::StaticFunctions - | default_flags | public_flags); + | default_flags); // Empty, private functions, since they aren't caught by the other ones returned += queryFunctions(FunctionQueryOption::Empty | FunctionQueryOption::Invisible); @@ -314,15 +306,15 @@ bool AbstractMetaClass::hasStaticFields() const void AbstractMetaClass::sortFunctions() { - std::sort(d->m_functions.begin(), d->m_functions.end(), function_sorter); + d->sortFunctions(); } -const AbstractMetaClass *AbstractMetaClass::templateBaseClass() const +AbstractMetaClassCPtr AbstractMetaClass::templateBaseClass() const { return d->m_templateBaseClass; } -void AbstractMetaClass::setTemplateBaseClass(const AbstractMetaClass *cls) +void AbstractMetaClass::setTemplateBaseClass(const AbstractMetaClassCPtr &cls) { d->m_templateBaseClass = cls; } @@ -332,17 +324,28 @@ const AbstractMetaFunctionCList &AbstractMetaClass::functions() const return d->m_functions; } -void AbstractMetaClass::setFunctions(const AbstractMetaFunctionCList &functions) +const AbstractMetaFunctionCList &AbstractMetaClass::userAddedPythonOverrides() const +{ + return d->m_userAddedPythonOverrides; +} + +void AbstractMetaClassPrivate::sortFunctions() +{ + std::sort(m_functions.begin(), m_functions.end(), function_sorter); +} + +void AbstractMetaClassPrivate::setFunctions(const AbstractMetaFunctionCList &functions, + const AbstractMetaClassCPtr &q) { - d->m_functions = functions; + m_functions = functions; // Functions must be sorted by name before next loop sortFunctions(); - for (const auto &f : std::as_const(d->m_functions)) { - qSharedPointerConstCast<AbstractMetaFunction>(f)->setOwnerClass(this); + for (const auto &f : std::as_const(m_functions)) { + std::const_pointer_cast<AbstractMetaFunction>(f)->setOwnerClass(q); if (!f->isPublic()) - d->m_hasNonpublic = true; + m_hasNonpublic = true; } } @@ -379,20 +382,27 @@ void AbstractMetaClassPrivate::addFunction(const AbstractMetaFunctionCPtr &funct && function->functionType() == AbstractMetaFunction::ConstructorFunction; } -void AbstractMetaClass::addFunction(const AbstractMetaFunctionCPtr &function) +void AbstractMetaClass::addFunction(const AbstractMetaClassPtr &klass, + const AbstractMetaFunctionCPtr &function) { - auto nonConstF = qSharedPointerConstCast<AbstractMetaFunction>(function); - nonConstF->setOwnerClass(this); + auto nonConstF = std::const_pointer_cast<AbstractMetaFunction>(function); + nonConstF->setOwnerClass(klass); // Set the default value of the declaring class. This may be changed // in fixFunctions later on - nonConstF->setDeclaringClass(this); + nonConstF->setDeclaringClass(klass); // Some of the queries below depend on the implementing class being set // to function properly. Such as function modifications - nonConstF->setImplementingClass(this); + nonConstF->setImplementingClass(klass); - d->addFunction(function); + if (function->isUserAddedPythonOverride()) { + nonConstF->setConstant(false); + nonConstF->setCppAttribute(FunctionAttribute::Static); + klass->d->m_userAddedPythonOverrides.append(function); + } else { + klass->d->addFunction(function); + } } bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const @@ -430,17 +440,17 @@ QString AbstractMetaClass::baseClassName() const } // Attribute "default-superclass" -const AbstractMetaClass *AbstractMetaClass::defaultSuperclass() const +AbstractMetaClassCPtr AbstractMetaClass::defaultSuperclass() const { return d->m_defaultSuperclass; } -void AbstractMetaClass::setDefaultSuperclass(AbstractMetaClass *s) +void AbstractMetaClass::setDefaultSuperclass(const AbstractMetaClassPtr &s) { d->m_defaultSuperclass = s; } -const AbstractMetaClass *AbstractMetaClass::baseClass() const +AbstractMetaClassCPtr AbstractMetaClass::baseClass() const { return d->m_baseClasses.value(0, nullptr); } @@ -455,7 +465,7 @@ const AbstractMetaClassCList &AbstractMetaClass::baseClasses() const AbstractMetaClassCList AbstractMetaClass::typeSystemBaseClasses() const { AbstractMetaClassCList result = d->m_baseClasses; - if (d->m_defaultSuperclass != nullptr) { + if (d->m_defaultSuperclass) { result.removeAll(d->m_defaultSuperclass); result.prepend(d->m_defaultSuperclass); } @@ -467,21 +477,21 @@ AbstractMetaClassCList AbstractMetaClass::allTypeSystemAncestors() const { AbstractMetaClassCList result; const auto baseClasses = typeSystemBaseClasses(); - for (auto *base : baseClasses) { + for (const auto &base : baseClasses) { result.append(base); result.append(base->allTypeSystemAncestors()); } return result; } -void AbstractMetaClass::addBaseClass(const AbstractMetaClass *baseClass) +void AbstractMetaClass::addBaseClass(const AbstractMetaClassCPtr &baseClass) { Q_ASSERT(baseClass); d->m_baseClasses.append(baseClass); d->m_isPolymorphic |= baseClass->isPolymorphic(); } -void AbstractMetaClass::setBaseClass(const AbstractMetaClass *baseClass) +void AbstractMetaClass::setBaseClass(const AbstractMetaClassCPtr &baseClass) { if (baseClass) { d->m_baseClasses.prepend(baseClass); @@ -489,12 +499,12 @@ void AbstractMetaClass::setBaseClass(const AbstractMetaClass *baseClass) } } -const AbstractMetaClass *AbstractMetaClass::extendedNamespace() const +AbstractMetaClassCPtr AbstractMetaClass::extendedNamespace() const { return d->m_extendedNamespace; } -void AbstractMetaClass::setExtendedNamespace(const AbstractMetaClass *e) +void AbstractMetaClass::setExtendedNamespace(const AbstractMetaClassCPtr &e) { d->m_extendedNamespace = e; } @@ -504,7 +514,7 @@ const AbstractMetaClassCList &AbstractMetaClass::innerClasses() const return d->m_innerClasses; } -void AbstractMetaClass::addInnerClass(AbstractMetaClass *cl) +void AbstractMetaClass::addInnerClass(const AbstractMetaClassPtr &cl) { d->m_innerClasses << cl; } @@ -536,17 +546,12 @@ bool AbstractMetaClass::isInlineNamespace() const { bool result = false; if (d->m_typeEntry->isNamespace()) { - const auto nte = qSharedPointerCast<const NamespaceTypeEntry>(d->m_typeEntry); + const auto nte = std::static_pointer_cast<const NamespaceTypeEntry>(d->m_typeEntry); result = nte->isInlineNamespace(); } return result; } -bool AbstractMetaClass::isQObject() const -{ - return inheritsFrom(u"QObject"_s); -} - bool AbstractMetaClass::isQtNamespace() const { return isNamespace() && name() == u"Qt"; @@ -559,15 +564,15 @@ QString AbstractMetaClass::qualifiedCppName() const bool AbstractMetaClass::hasFunction(const QString &str) const { - return !findFunction(str).isNull(); + return bool(findFunction(str)); } -AbstractMetaFunctionCPtr AbstractMetaClass::findFunction(QStringView functionName) const +AbstractMetaFunctionCPtr AbstractMetaClass::findFunction(QAnyStringView functionName) const { return AbstractMetaFunction::find(d->m_functions, functionName); } -AbstractMetaFunctionCList AbstractMetaClass::findFunctions(QStringView functionName) const +AbstractMetaFunctionCList AbstractMetaClass::findFunctions(QAnyStringView functionName) const { AbstractMetaFunctionCList result; std::copy_if(d->m_functions.cbegin(), d->m_functions.cend(), @@ -798,41 +803,40 @@ bool AbstractMetaClass::hasCopyConstructor() const bool AbstractMetaClass::hasPrivateCopyConstructor() const { const auto copyCt = copyConstructor(); - return !copyCt.isNull() && copyCt->isPrivate(); + return copyCt && copyCt->isPrivate(); } void AbstractMetaClassPrivate::addConstructor(AbstractMetaFunction::FunctionType t, Access access, const AbstractMetaArgumentList &arguments, - AbstractMetaClass *q) + const AbstractMetaClassPtr &q) { auto *f = createFunction(q->name(), t, access, arguments, AbstractMetaType::createVoid(), q); if (access != Access::Private) m_hasNonPrivateConstructor = true; - f->setAttributes(AbstractMetaFunction::FinalInTargetLang - | AbstractMetaFunction::AddedMethod); + f->setAttributes(AbstractMetaFunction::AddedMethod); addFunction(AbstractMetaFunctionCPtr(f)); } -void AbstractMetaClass::addDefaultConstructor() +void AbstractMetaClass::addDefaultConstructor(const AbstractMetaClassPtr &klass) { - d->addConstructor(AbstractMetaFunction::ConstructorFunction, - Access::Public, {}, this); + klass->d->addConstructor(AbstractMetaFunction::ConstructorFunction, + Access::Public, {}, klass); } -void AbstractMetaClass::addDefaultCopyConstructor() +void AbstractMetaClass::addDefaultCopyConstructor(const AbstractMetaClassPtr &klass) { - AbstractMetaType argType(typeEntry()); + AbstractMetaType argType(klass->typeEntry()); argType.setReferenceType(LValueReference); argType.setConstant(true); argType.setTypeUsagePattern(AbstractMetaType::ValuePattern); AbstractMetaArgument arg; arg.setType(argType); - arg.setName(name()); + arg.setName(klass->name()); - d->addConstructor(AbstractMetaFunction::CopyConstructorFunction, - Access::Public, {arg}, this); + klass->d->addConstructor(AbstractMetaFunction::CopyConstructorFunction, + Access::Public, {arg}, klass); } AbstractMetaFunction * @@ -841,7 +845,7 @@ AbstractMetaFunction * Access access, const AbstractMetaArgumentList &arguments, const AbstractMetaType &returnType, - AbstractMetaClass *q) + const AbstractMetaClassPtr &q) { auto *f = new AbstractMetaFunction(name); f->setType(returnType); @@ -857,7 +861,7 @@ AbstractMetaFunction * static AbstractMetaType boolType() { auto boolType = TypeDatabase::instance()->findType(u"bool"_s); - Q_ASSERT(!boolType.isNull()); + Q_ASSERT(boolType); AbstractMetaType result(boolType); result.decideUsagePattern(); return result; @@ -866,11 +870,11 @@ static AbstractMetaType boolType() // Helper to synthesize comparison operators from a spaceship operator. Since // shiboken also generates code for comparing to different types, this fits // better than of handling it in the generator code. -void AbstractMetaClass::addSynthesizedComparisonOperators() +void AbstractMetaClass::addSynthesizedComparisonOperators(const AbstractMetaClassPtr &c) { static const auto returnType = boolType(); - AbstractMetaType selfType(typeEntry()); + AbstractMetaType selfType(c->typeEntry()); selfType.setConstant(true); selfType.setReferenceType(LValueReference); selfType.decideUsagePattern(); @@ -885,8 +889,8 @@ void AbstractMetaClass::addSynthesizedComparisonOperators() auto *f = AbstractMetaClassPrivate::createFunction(QLatin1StringView(op), AbstractMetaFunction::ComparisonOperator, Access::Public, arguments, - returnType, this); - d->addFunction(AbstractMetaFunctionCPtr(f)); + returnType, c); + c->d->addFunction(AbstractMetaFunctionCPtr(f)); } } @@ -992,7 +996,7 @@ bool AbstractMetaClass::isImplicitlyDefaultConstructible() const return std::all_of(d->m_fields.cbegin(), d->m_fields.cend(), defaultConstructibleField) && std::all_of(d->m_baseClasses.cbegin(), d->m_baseClasses.cend(), - [] (const AbstractMetaClass *c) { + [] (const AbstractMetaClassCPtr &c) { return c->isDefaultConstructible(); }); } @@ -1027,7 +1031,7 @@ bool AbstractMetaClass::isImplicitlyCopyConstructible() const { // Fields are currently not considered return std::all_of(d->m_baseClasses.cbegin(), d->m_baseClasses.cend(), - [] (const AbstractMetaClass *c) { + [] (const AbstractMetaClassCPtr &c) { return c->isCopyConstructible(); }); } @@ -1042,16 +1046,16 @@ bool AbstractMetaClass::canAddDefaultCopyConstructor() const return isImplicitlyCopyConstructible(); } -static bool classHasParentManagement(const AbstractMetaClass *c) +static bool classHasParentManagement(const AbstractMetaClassCPtr &c) { const auto flags = c->typeEntry()->typeFlags(); return flags.testFlag(ComplexTypeEntry::ParentManagement); } -TypeEntryCPtr AbstractMetaClass::parentManagementEntry() const +TypeEntryCPtr parentManagementEntry(const AbstractMetaClassCPtr &klass) { - if (isObjectType()) { - if (auto *c = recurseClassHierarchy(this, classHasParentManagement)) + if (klass->typeEntry()->isObject()) { + if (auto c = recurseClassHierarchy(klass, classHasParentManagement)) return c->typeEntry(); } return nullptr; @@ -1121,7 +1125,7 @@ void AbstractMetaClass::addUsingMember(const UsingMember &um) d->m_usingMembers.append(um); } -bool AbstractMetaClassPrivate::isUsingMember(const AbstractMetaClass *c, +bool AbstractMetaClassPrivate::isUsingMember(const AbstractMetaClassCPtr &c, const QString &memberName, Access minimumAccess) const { @@ -1132,7 +1136,7 @@ bool AbstractMetaClassPrivate::isUsingMember(const AbstractMetaClass *c, return it != m_usingMembers.cend() && it->access >= minimumAccess; } -bool AbstractMetaClass::isUsingMember(const AbstractMetaClass *c, +bool AbstractMetaClass::isUsingMember(const AbstractMetaClassCPtr &c, const QString &memberName, Access minimumAccess) const { @@ -1163,24 +1167,15 @@ bool AbstractMetaClass::queryFunction(const AbstractMetaFunction *f, FunctionQue if (query.testFlag(FunctionQueryOption::Visible) && f->isPrivate()) return false; - if (query.testFlag(FunctionQueryOption::VirtualInTargetLangFunctions) && f->isFinalInTargetLang()) - return false; - if (query.testFlag(FunctionQueryOption::Invisible) && !f->isPrivate()) return false; if (query.testFlag(FunctionQueryOption::Empty) && !f->isEmptyFunction()) return false; - if (query.testFlag(FunctionQueryOption::WasPublic) && !f->wasPublic()) - return false; - if (query.testFlag(FunctionQueryOption::ClassImplements) && f->ownerClass() != f->implementingClass()) return false; - if (query.testFlag(FunctionQueryOption::FinalInTargetLangFunctions) && !f->isFinalInTargetLang()) - return false; - if (query.testFlag(FunctionQueryOption::VirtualInCppFunctions) && !f->isVirtual()) return false; @@ -1244,7 +1239,7 @@ AbstractMetaFunctionCList AbstractMetaClass::queryFunctionList(const AbstractMet { AbstractMetaFunctionCList result; for (const auto &f : list) { - if (queryFunction(f.data(), query)) + if (queryFunction(f.get(), query)) result.append(f); } return result; @@ -1254,7 +1249,7 @@ AbstractMetaFunctionCPtr AbstractMetaClass::queryFirstFunction(const AbstractMet FunctionQueryOptions query) { for (const auto &f : list) { - if (queryFunction(f.data(), query)) + if (queryFunction(f.get(), query)) return f; } return {}; @@ -1344,7 +1339,7 @@ void AbstractMetaClass::getEnumsToBeGenerated(AbstractMetaEnumList *enumList) co void AbstractMetaClass::getEnumsFromInvisibleNamespacesToBeGenerated(AbstractMetaEnumList *enumList) const { if (isNamespace()) { - invisibleNamespaceRecursion([enumList](const AbstractMetaClass *c) { + invisibleNamespaceRecursion([enumList](const AbstractMetaClassCPtr &c) { c->getEnumsToBeGenerated(enumList); }); } @@ -1353,7 +1348,7 @@ void AbstractMetaClass::getEnumsFromInvisibleNamespacesToBeGenerated(AbstractMet void AbstractMetaClass::getFunctionsFromInvisibleNamespacesToBeGenerated(AbstractMetaFunctionCList *funcList) const { if (isNamespace()) { - invisibleNamespaceRecursion([funcList](const AbstractMetaClass *c) { + invisibleNamespaceRecursion([funcList](const AbstractMetaClassCPtr &c) { funcList->append(c->functions()); }); } @@ -1364,7 +1359,8 @@ QString AbstractMetaClass::fullName() const return package() + u'.' + d->m_typeEntry->targetLangName(); } -static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractMetaType &type) +static void addExtraIncludeForType(const AbstractMetaClassPtr &metaClass, + const AbstractMetaType &type) { Q_ASSERT(metaClass); @@ -1381,7 +1377,7 @@ static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractM } } -static void addExtraIncludesForFunction(AbstractMetaClass *metaClass, +static void addExtraIncludesForFunction(const AbstractMetaClassPtr &metaClass, const AbstractMetaFunctionCPtr &meta_function) { Q_ASSERT(metaClass); @@ -1416,7 +1412,7 @@ static bool addSuperFunction(const AbstractMetaFunctionCPtr &f) // Add constructors imported via "using" from the base classes. This is not // needed for normal hidden inherited member functions since we generate a // cast to the base class to call them into binding code. -void AbstractMetaClassPrivate::addUsingConstructors(AbstractMetaClass *q) +void AbstractMetaClassPrivate::addUsingConstructors(const AbstractMetaClassPtr &q) { // Restricted to the non-constructor case currently to avoid // having to compare the parameter lists of existing constructors. @@ -1425,7 +1421,7 @@ void AbstractMetaClassPrivate::addUsingConstructors(AbstractMetaClass *q) return; } - for (auto superClass : m_baseClasses) { + for (const auto &superClass : m_baseClasses) { // Find any "using base-constructor" directives if (isUsingMember(superClass, superClass->name(), Access::Protected)) { // Add to derived class with parameter lists. @@ -1440,41 +1436,51 @@ void AbstractMetaClassPrivate::addUsingConstructors(AbstractMetaClass *q) } } -void AbstractMetaClass::fixFunctions() +static inline bool isSignal(const AbstractMetaFunctionCPtr &f) { + return f->isSignal(); +} + +void AbstractMetaClass::fixFunctions(const AbstractMetaClassPtr &klass) +{ + auto *d = klass->d.data(); if (d->m_functionsFixed) return; d->m_functionsFixed = true; - AbstractMetaFunctionCList funcs = functions(); + AbstractMetaFunctionCList funcs = klass->functions(); AbstractMetaFunctionCList nonRemovedFuncs; nonRemovedFuncs.reserve(funcs.size()); - d->addUsingConstructors(this); + d->addUsingConstructors(klass); for (const auto &f : std::as_const(funcs)) { // Fishy: Setting up of implementing/declaring/base classes changes // the applicable modifications; clear cached ones. - qSharedPointerConstCast<AbstractMetaFunction>(f)->clearModificationsCache(); + std::const_pointer_cast<AbstractMetaFunction>(f)->clearModificationsCache(); if (!f->isModifiedRemoved()) nonRemovedFuncs.append(f); } - for (auto *superClassC : d->m_baseClasses) { - auto *superClass = const_cast<AbstractMetaClass *>(superClassC); - superClass->fixFunctions(); + for (const auto &superClassC : d->m_baseClasses) { + for (const auto &pof : superClassC->userAddedPythonOverrides()) { + auto *clonedPof = pof->copy(); + clonedPof->setOwnerClass(klass); + d->m_userAddedPythonOverrides.append(AbstractMetaFunctionCPtr{clonedPof}); + } + + auto superClass = std::const_pointer_cast<AbstractMetaClass>(superClassC); + AbstractMetaClass::fixFunctions(superClass); // 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. AbstractMetaFunctionCList superFuncs; - // 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 -= AbstractMetaClass::FinalInTargetLang; - } superFuncs = superClass->queryFunctions(FunctionQueryOption::ClassImplements); + // We are not interested in signals as no bindings are generated for them; + // they cause documentation warnings. + superFuncs.erase(std::remove_if(superFuncs.begin(), superFuncs.end(), isSignal), + superFuncs.end()); const auto virtuals = superClass->queryFunctions(FunctionQueryOption::VirtualInCppFunctions); superFuncs += virtuals; @@ -1484,7 +1490,7 @@ void AbstractMetaClass::fixFunctions() continue; // skip functions added in base classes - if (sf->isUserAdded() && sf->declaringClass() != this) + if (sf->isUserAdded() && sf->declaringClass() != klass) continue; // Skip base class comparison operators declared as members (free @@ -1496,42 +1502,24 @@ void AbstractMetaClass::fixFunctions() // virtual in case they override abstract functions. bool add = addSuperFunction(sf); for (const auto &cf : std::as_const(nonRemovedFuncs)) { - AbstractMetaFunctionPtr f(qSharedPointerConstCast<AbstractMetaFunction>(cf)); - const AbstractMetaFunction::CompareResult cmp = cf->compareTo(sf.data()); + AbstractMetaFunctionPtr f(std::const_pointer_cast<AbstractMetaFunction>(cf)); + const AbstractMetaFunction::CompareResult cmp = cf->compareTo(sf.get()); if (cmp & AbstractMetaFunction::EqualModifiedName) { add = false; if (cmp & AbstractMetaFunction::EqualArguments) { // Set "override" in case it was not spelled out (since it // is then not detected by clang parsing). - const auto attributes = cf->attributes(); - if (cf->isVirtual() - && !attributes.testFlag(AbstractMetaFunction::OverriddenCppMethod) - && !attributes.testFlag(AbstractMetaFunction::FinalCppMethod)) { - *f += AbstractMetaFunction::OverriddenCppMethod; - } - // Same function, propegate virtual... - if (!(cmp & AbstractMetaFunction::EqualAttributes)) { - if (!f->isEmptyFunction()) { - if (!sf->isFinalInTargetLang() && f->isFinalInTargetLang()) { - *f -= AbstractMetaFunction::FinalInTargetLang; - } -#if 0 - if (!f->isFinalInTargetLang() && f->isPrivate()) { - f->setFunctionType(AbstractMetaFunction::EmptyFunction); - f->setVisibility(AbstractMetaAttributes::Protected); - *f += AbstractMetaAttributes::FinalInTargetLang; - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("private virtual function '%1' in '%2'") - .arg(f->signature(), f->implementingClass()->name()); - } -#endif - } + const auto attributes = cf->cppAttributes(); + if (attributes.testFlag(FunctionAttribute::Virtual) + && !attributes.testFlag(FunctionAttribute::Override) + && !attributes.testFlag(FunctionAttribute::Final)) { + f->setCppAttribute(FunctionAttribute::Override); } if (f->access() != sf->access()) { qCWarning(lcShiboken, "%s", - qPrintable(msgFunctionVisibilityModified(this, f.data()))); + qPrintable(msgFunctionVisibilityModified(klass, f.get()))); #if 0 // If new visibility is private, we can't // do anything. If it isn't, then we @@ -1543,43 +1531,12 @@ void AbstractMetaClass::fixFunctions() // Private overrides of abstract functions have to go into the class or // the subclasses will not compile as non-abstract classes. // But they don't need to be implemented, since they can never be called. - if (f->isPrivate()) { + if (f->isPrivate()) f->setFunctionType(AbstractMetaFunction::EmptyFunction); - *f += AbstractMetaFunction::FinalInTargetLang; - } } // Set the class which first declares this function, afawk f->setDeclaringClass(sf->declaringClass()); - - if (sf->isFinalInTargetLang() && !sf->isPrivate() && !f->isPrivate() && !sf->isStatic() && !f->isStatic()) { - // Shadowed funcion, need to make base class - // function non-virtual - if (f->implementingClass() != sf->implementingClass() && f->implementingClass()->inheritsFrom(sf->implementingClass())) { - - // Check whether the superclass method has been redefined to non-final - - bool hasNonFinalModifier = false; - bool isBaseImplPrivate = false; - const FunctionModificationList &mods = sf->modifications(sf->implementingClass()); - for (const FunctionModification &mod : mods) { - if (mod.isNonFinal()) { - hasNonFinalModifier = true; - break; - } - if (mod.isPrivate()) { - isBaseImplPrivate = true; - break; - } - } - - if (!hasNonFinalModifier && !isBaseImplPrivate) { - qCWarning(lcShiboken, "%s", - qPrintable(msgShadowingFunction(sf.data(), f.data()))); - } - } - } - } if (cmp & AbstractMetaFunction::EqualDefaultValueOverload) { @@ -1618,8 +1575,8 @@ void AbstractMetaClass::fixFunctions() bool hasPublicConstructors = false; // Apply modifications after the declaring class has been set for (const auto &func : std::as_const(funcs)) { - auto ncFunc = qSharedPointerConstCast<AbstractMetaFunction>(func); - for (const auto &mod : func->modifications(this)) { + auto ncFunc = std::const_pointer_cast<AbstractMetaFunction>(func); + for (const auto &mod : func->modifications(klass)) { if (mod.isRenameModifier()) ncFunc->setName(mod.renamedToName()); } @@ -1627,8 +1584,8 @@ void AbstractMetaClass::fixFunctions() // Make sure class is abstract if one of the functions is if (func->isAbstract()) { - (*this) += AbstractMetaClass::Abstract; - (*this) -= AbstractMetaClass::FinalInTargetLang; + (*klass) += AbstractMetaClass::Abstract; + (*klass) -= AbstractMetaClass::FinalInTargetLang; } if (func->isConstructor()) { @@ -1641,15 +1598,15 @@ void AbstractMetaClass::fixFunctions() // Make sure that we include files for all classes that are in use - addExtraIncludesForFunction(this, func); + addExtraIncludesForFunction(klass, func); } if (hasPrivateConstructors && !hasPublicConstructors) { - (*this) += AbstractMetaClass::Abstract; - (*this) -= AbstractMetaClass::FinalInTargetLang; + (*klass) += AbstractMetaClass::Abstract; + (*klass) -= AbstractMetaClass::FinalInTargetLang; } - setFunctions(funcs); + d->setFunctions(funcs, klass); } bool AbstractMetaClass::needsInheritanceSetup() const @@ -1658,6 +1615,7 @@ bool AbstractMetaClass::needsInheritanceSetup() const switch (d->m_typeEntry->type()) { case TypeEntry::NamespaceType: case TypeEntry::SmartPointerType: + case TypeEntry::ContainerType: return false; default: break; @@ -1689,11 +1647,11 @@ std::optional<AbstractMetaEnumValue> if (lst.size() > 1) { const auto &prefixName = lst.at(0); const auto &enumName = lst.at(1); - if (auto *cl = findClass(classes, prefixName)) + if (auto cl = findClass(classes, prefixName)) return cl->findEnumValue(enumName.toString()); } - for (AbstractMetaClass *metaClass : classes) { + for (const auto &metaClass : classes) { auto enumValue = metaClass->findEnumValue(name); if (enumValue.has_value()) return enumValue; @@ -1707,12 +1665,12 @@ std::optional<AbstractMetaEnumValue> /// Target language base name or complete Target language package.class name. template <class It> -static It findClassHelper(It begin, It end, QStringView name) +static It findClassHelper(It begin, It end, QAnyStringView name) { if (name.isEmpty() || begin == end) return end; - if (name.contains(u'.')) { // Search target lang name + if (asv_contains(name,'.')) { // Search target lang name for (auto it = begin; it != end; ++it) { if ((*it)->fullName() == name) return it; @@ -1725,7 +1683,7 @@ static It findClassHelper(It begin, It end, QStringView name) return it; } - if (name.contains(u"::")) // Qualified, cannot possibly match name + if (asv_contains(name, "::")) // Qualified, cannot possibly match name return end; for (auto it = begin; it != end; ++it) { @@ -1736,31 +1694,31 @@ static It findClassHelper(It begin, It end, QStringView name) return end; } -AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes, - QStringView name) +AbstractMetaClassPtr AbstractMetaClass::findClass(const AbstractMetaClassList &classes, + QAnyStringView name) { auto it =findClassHelper(classes.cbegin(), classes.cend(), name); return it != classes.cend() ? *it : nullptr; } -const AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassCList &classes, - QStringView name) +AbstractMetaClassCPtr AbstractMetaClass::findClass(const AbstractMetaClassCList &classes, + QAnyStringView name) { auto it = findClassHelper(classes.cbegin(), classes.cend(), name); return it != classes.cend() ? *it : nullptr; } -AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes, - const TypeEntryCPtr &typeEntry) +AbstractMetaClassPtr AbstractMetaClass::findClass(const AbstractMetaClassList &classes, + const TypeEntryCPtr &typeEntry) { - for (AbstractMetaClass *c : classes) { + for (AbstractMetaClassPtr c : classes) { if (c->typeEntry() == typeEntry) return c; } return nullptr; } -const AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassCList &classes, +AbstractMetaClassCPtr AbstractMetaClass::findClass(const AbstractMetaClassCList &classes, const TypeEntryCPtr &typeEntry) { for (auto c : classes) { @@ -1771,40 +1729,41 @@ const AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassCLi } /// Returns true if this class is a subclass of the given class -bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const +bool inheritsFrom(const AbstractMetaClassCPtr &c, const AbstractMetaClassCPtr &cls) { Q_ASSERT(cls != nullptr); - if (this == cls || d->m_templateBaseClass == cls) + if (c == cls || c->templateBaseClass() == cls) return true; - return recurseClassHierarchy(this, [cls](const AbstractMetaClass *c) { - return cls == c; - }) != nullptr; + return bool(recurseClassHierarchy(c, [cls](const AbstractMetaClassCPtr &c) { + return cls.get() == c.get(); + })); } -bool AbstractMetaClass::inheritsFrom(const QString &name) const +bool inheritsFrom(const AbstractMetaClassCPtr &c, QAnyStringView name) { - if (this->qualifiedCppName() == name) + if (c->qualifiedCppName() == name) return true; - if (d->m_templateBaseClass != nullptr - && d->m_templateBaseClass->qualifiedCppName() == name) { + if (c->templateBaseClass() != nullptr + && c->templateBaseClass()->qualifiedCppName() == name) { return true; } - return recurseClassHierarchy(this, [&name](const AbstractMetaClass *c) { + return bool(recurseClassHierarchy(c, [&name](const AbstractMetaClassCPtr &c) { return c->qualifiedCppName() == name; - }) != nullptr; + })); } -const AbstractMetaClass *AbstractMetaClass::findBaseClass(const QString &qualifiedName) const +AbstractMetaClassCPtr findBaseClass(const AbstractMetaClassCPtr &c, + const QString &qualifiedName) { - if (d->m_templateBaseClass != nullptr - && d->m_templateBaseClass->qualifiedCppName() == qualifiedName) { - return d->m_templateBaseClass; - } - return recurseClassHierarchy(this, [&qualifiedName](const AbstractMetaClass *c) { + auto tp = c->templateBaseClass(); + if (tp && tp->qualifiedCppName() == qualifiedName) + return tp; + + return recurseClassHierarchy(c, [&qualifiedName](const AbstractMetaClassCPtr &c) { return c->qualifiedCppName() == qualifiedName; }); } @@ -1834,7 +1793,7 @@ void AbstractMetaClass::setValueTypeWithCopyConstructorOnly(bool v) d->m_valueTypeWithCopyConstructorOnly = v; } -bool AbstractMetaClass::determineValueTypeWithCopyConstructorOnly(const AbstractMetaClass *c, +bool AbstractMetaClass::determineValueTypeWithCopyConstructorOnly(const AbstractMetaClassCPtr &c, bool avoidProtectedHack) { @@ -1900,7 +1859,7 @@ void AbstractMetaClass::format(QDebug &debug) const if (!d->m_baseClasses.isEmpty()) { debug << ", inherits "; - for (auto b : d->m_baseClasses) + for (const auto &b : d->m_baseClasses) debug << " \"" << b->name() << '"'; } @@ -1965,6 +1924,18 @@ void AbstractMetaClass::setSourceLocation(const SourceLocation &sourceLocation) d->m_sourceLocation = sourceLocation; } +AbstractMetaClassCList allBaseClasses(const AbstractMetaClassCPtr metaClass) +{ + AbstractMetaClassCList result; + recurseClassHierarchy(metaClass, [&result] (const AbstractMetaClassCPtr &c) { + if (!result.contains(c)) + result.append(c); + return false; + }); + result.removeFirst(); // remove self + return result; +} + QDebug operator<<(QDebug debug, const UsingMember &d) { QDebugStateSaver saver(debug); @@ -1975,20 +1946,38 @@ QDebug operator<<(QDebug debug, const UsingMember &d) return debug; } -QDebug operator<<(QDebug d, const AbstractMetaClass *ac) +void formatMetaClass(QDebug &ddebug, const AbstractMetaClass *ac) { - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaClass("; - if (ac) { - ac->format(d); - if (d.verbosity() > 2) - ac->formatMembers(d); + QDebugStateSaver saver(ddebug); + ddebug.noquote(); + ddebug.nospace(); + ddebug << "AbstractMetaClass("; + if (ac != nullptr) { + ac->format(ddebug); + if (ddebug.verbosity() > 2) + ac->formatMembers(ddebug); } else { - d << '0'; + ddebug << '0'; } - d << ')'; + ddebug << ')'; +} + +QDebug operator<<(QDebug d, const AbstractMetaClassCPtr &ac) +{ + formatMetaClass(d, ac.get()); + return d; +} + +QDebug operator<<(QDebug d, const AbstractMetaClassPtr &ac) +{ + formatMetaClass(d, ac.get()); return d; } + +QDebug operator<<(QDebug d, const AbstractMetaClass *ac) +{ + formatMetaClass(d, ac); + return d; +} + #endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.h b/sources/shiboken6/ApiExtractor/abstractmetalang.h index 526df69af..3dc876690 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken6/ApiExtractor/abstractmetalang.h @@ -66,11 +66,13 @@ public: ~AbstractMetaClass(); const AbstractMetaFunctionCList &functions() const; + const AbstractMetaFunctionCList &userAddedPythonOverrides() const; void setFunctions(const AbstractMetaFunctionCList &functions); - void addFunction(const AbstractMetaFunctionCPtr &function); + static void addFunction(const AbstractMetaClassPtr &klass, + const AbstractMetaFunctionCPtr &function); bool hasFunction(const QString &str) const; - AbstractMetaFunctionCPtr findFunction(QStringView functionName) const; - AbstractMetaFunctionCList findFunctions(QStringView functionName) const; + AbstractMetaFunctionCPtr findFunction(QAnyStringView functionName) const; + AbstractMetaFunctionCList findFunctions(QAnyStringView functionName) const; AbstractMetaFunctionCPtr findOperatorBool() const; // Find a Qt-style isNull() method suitable for nb_bool AbstractMetaFunctionCPtr findQtIsNullMethod() const; @@ -81,8 +83,8 @@ public: bool hasCopyConstructor() const; bool hasPrivateCopyConstructor() const; - void addDefaultConstructor(); - void addDefaultCopyConstructor(); + static void addDefaultConstructor(const AbstractMetaClassPtr &klass); + static void addDefaultCopyConstructor(const AbstractMetaClassPtr &klass); bool hasNonPrivateConstructor() const; void setHasNonPrivateConstructor(bool value); @@ -113,11 +115,7 @@ public: bool isImplicitlyCopyConstructible() const; bool canAddDefaultCopyConstructor() const; - /// Return type entry of the base class that declares the parent management - TypeEntryCPtr parentManagementEntry() const; - bool hasParentManagement() const { return !parentManagementEntry().isNull(); } - - void addSynthesizedComparisonOperators(); + static void addSynthesizedComparisonOperators(const AbstractMetaClassPtr &c); bool generateExceptionHandling() const; @@ -125,7 +123,7 @@ public: const UsingMembers &usingMembers() const; void addUsingMember(const UsingMember &um); - bool isUsingMember(const AbstractMetaClass *c, const QString &memberName, + bool isUsingMember(const AbstractMetaClassCPtr &c, const QString &memberName, Access minimumAccess) const; bool hasUsingMemberFor(const QString &memberName) const; @@ -190,27 +188,27 @@ public: QString baseClassName() const; - const AbstractMetaClass *defaultSuperclass() const; // Attribute "default-superclass" - void setDefaultSuperclass(AbstractMetaClass *s); + AbstractMetaClassCPtr defaultSuperclass() const; // Attribute "default-superclass" + void setDefaultSuperclass(const AbstractMetaClassPtr &s); - const AbstractMetaClass *baseClass() const; + AbstractMetaClassCPtr baseClass() const; const AbstractMetaClassCList &baseClasses() const; // base classes including defaultSuperclass AbstractMetaClassCList typeSystemBaseClasses() const; // Recursive list of all base classes including defaultSuperclass AbstractMetaClassCList allTypeSystemAncestors() const; - void addBaseClass(const AbstractMetaClass *base_class); - void setBaseClass(const AbstractMetaClass *base_class); + void addBaseClass(const AbstractMetaClassCPtr &base_class); + void setBaseClass(const AbstractMetaClassCPtr &base_class); /** * \return the namespace from another package which this namespace extends. */ - const AbstractMetaClass *extendedNamespace() const; - void setExtendedNamespace(const AbstractMetaClass *e); + AbstractMetaClassCPtr extendedNamespace() const; + void setExtendedNamespace(const AbstractMetaClassCPtr &e); const AbstractMetaClassCList &innerClasses() const; - void addInnerClass(AbstractMetaClass *cl); + void addInnerClass(const AbstractMetaClassPtr &cl); void setInnerClasses(const AbstractMetaClassCList &innerClasses); QString package() const; @@ -219,14 +217,11 @@ public: bool isInvisibleNamespace() const; bool isInlineNamespace() const; - bool isQObject() const; bool isQtNamespace() const; QString qualifiedCppName() const; bool hasSignals() const; - bool inheritsFrom(const AbstractMetaClass *other) const; - bool inheritsFrom(const QString &name) const; /** * Says if the class that declares or inherits a virtual function. @@ -292,8 +287,8 @@ public: void sortFunctions(); - const AbstractMetaClass *templateBaseClass() const; - void setTemplateBaseClass(const AbstractMetaClass *cls); + AbstractMetaClassCPtr templateBaseClass() const; + void setTemplateBaseClass(const AbstractMetaClassCPtr &cls); bool hasTemplateBaseClassInstantiations() const; const AbstractMetaTypeList &templateBaseClassInstantiations() const; @@ -317,18 +312,18 @@ public: bool isCopyable() const; bool isValueTypeWithCopyConstructorOnly() const; void setValueTypeWithCopyConstructorOnly(bool v); - static bool determineValueTypeWithCopyConstructorOnly(const AbstractMetaClass *c, + static bool determineValueTypeWithCopyConstructorOnly(const AbstractMetaClassCPtr &c, bool avoidProtectedHack); - static AbstractMetaClass *findClass(const AbstractMetaClassList &classes, - QStringView name); - static const AbstractMetaClass *findClass(const AbstractMetaClassCList &classes, - QStringView name); - static AbstractMetaClass *findClass(const AbstractMetaClassList &classes, + static AbstractMetaClassPtr findClass(const AbstractMetaClassList &classes, + QAnyStringView name); + static AbstractMetaClassCPtr findClass(const AbstractMetaClassCList &classes, + QAnyStringView name); + static AbstractMetaClassPtr findClass(const AbstractMetaClassList &classes, const TypeEntryCPtr &typeEntry); - static const AbstractMetaClass *findClass(const AbstractMetaClassCList &classes, + static AbstractMetaClassCPtr findClass(const AbstractMetaClassCList &classes, const TypeEntryCPtr &typeEntry); - const AbstractMetaClass *findBaseClass(const QString &qualifiedName) const; + AbstractMetaClassCPtr findBaseClass(const QString &qualifiedName) const; static std::optional<AbstractMetaEnumValue> findEnumValue(const AbstractMetaClassList &classes, const QString &string); @@ -337,7 +332,7 @@ public: void setSourceLocation(const SourceLocation &sourceLocation); // For AbstractMetaBuilder - void fixFunctions(); + static void fixFunctions(const AbstractMetaClassPtr &klass); bool needsInheritanceSetup() const; void setInheritanceDone(bool b); bool inheritanceDone() const; @@ -349,17 +344,15 @@ private: #ifndef QT_NO_DEBUG_STREAM void format(QDebug &d) const; void formatMembers(QDebug &d) const; + friend QDebug operator<<(QDebug d, const AbstractMetaClassCPtr &ac); + friend QDebug operator<<(QDebug d, const AbstractMetaClassPtr &ac); friend QDebug operator<<(QDebug d, const AbstractMetaClass *ac); + friend void formatMetaClass(QDebug &, const AbstractMetaClass *); #endif QScopedPointer<AbstractMetaClassPrivate> d; }; -inline bool AbstractMetaClass::isFinalInTargetLang() const -{ - return attributes().testFlag(FinalInTargetLang); -} - inline bool AbstractMetaClass::isAbstract() const { return attributes().testFlag(Abstract); @@ -368,7 +361,7 @@ inline bool AbstractMetaClass::isAbstract() const template <class Function> void AbstractMetaClass::invisibleNamespaceRecursion(Function f) const { - for (auto ic : innerClasses()) { + for (const auto &ic : innerClasses()) { if (ic->isInvisibleNamespace()) { f(ic); ic->invisibleNamespaceRecursion(f); @@ -376,6 +369,23 @@ void AbstractMetaClass::invisibleNamespaceRecursion(Function f) const } } +bool inheritsFrom(const AbstractMetaClassCPtr &c, const AbstractMetaClassCPtr &other); +bool inheritsFrom(const AbstractMetaClassCPtr &c, QAnyStringView name); +inline bool isQObject(const AbstractMetaClassCPtr &c) +{ + return inheritsFrom(c, "QObject"); +} + +AbstractMetaClassCPtr findBaseClass(const AbstractMetaClassCPtr &c, + const QString &qualifiedName); + +/// Return type entry of the base class that declares the parent management +TypeEntryCPtr parentManagementEntry(const AbstractMetaClassCPtr &klass); +inline bool hasParentManagement(const AbstractMetaClassCPtr &c) +{ return bool(parentManagementEntry(c)); } + +AbstractMetaClassCList allBaseClasses(const AbstractMetaClassCPtr metaClass); + Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaClass::CppWrapper); Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaClass::Attributes); diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h b/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h index 2bdfdb54d..9047c6bcd 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h +++ b/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h @@ -11,18 +11,15 @@ enum class FunctionQueryOption { Constructors = 0x0000002, // Constructors except copy/move CopyConstructor = 0x0000004, // Only copy constructors //Destructors = 0x0000002, // Only destructors. Not included in class. - FinalInTargetLangFunctions = 0x0000008, // Only functions that are non-virtual in TargetLang ClassImplements = 0x0000020, // Only functions implemented by the current class StaticFunctions = 0x0000080, // Only static functions Signals = 0x0000100, // Only signals NormalFunctions = 0x0000200, // Only functions that aren't signals Visible = 0x0000400, // Only public and protected functions - WasPublic = 0x0001000, // Only functions that were originally public NonStaticFunctions = 0x0004000, // No static functions Empty = 0x0008000, // Empty overrides of abstract functions Invisible = 0x0010000, // Only private functions VirtualInCppFunctions = 0x0020000, // Only functions that are virtual in C++ - VirtualInTargetLangFunctions = 0x0080000, // Only functions which are virtual in TargetLang NotRemoved = 0x0400000, // Only functions that have not been removed OperatorOverloads = 0x2000000, // Only functions that are operator overloads GenerateExceptionHandling = 0x4000000, diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang_helpers.h b/sources/shiboken6/ApiExtractor/abstractmetalang_helpers.h index c1deea2c2..2a053ceaf 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang_helpers.h +++ b/sources/shiboken6/ApiExtractor/abstractmetalang_helpers.h @@ -4,21 +4,24 @@ #ifndef ABSTRACTMETALANG_HELPERS_H #define ABSTRACTMETALANG_HELPERS_H +#include "abstractmetalang_typedefs.h" + template <class MetaClass> -MetaClass *findByName(QList<MetaClass *> haystack, QStringView needle) +std::shared_ptr<MetaClass> findByName(const QList<std::shared_ptr<MetaClass> > &haystack, + QStringView needle) { - for (MetaClass *c : haystack) { + for (const auto &c : haystack) { if (c->name() == needle) return c; } - return nullptr; + return {}; } // Helper for recursing the base classes of an AbstractMetaClass. // Returns the class for which the predicate is true. template <class Predicate> -const AbstractMetaClass *recurseClassHierarchy(const AbstractMetaClass *klass, - Predicate pred) +AbstractMetaClassCPtr recurseClassHierarchy(const AbstractMetaClassCPtr &klass, + Predicate pred) { if (pred(klass)) return klass; @@ -26,7 +29,7 @@ const AbstractMetaClass *recurseClassHierarchy(const AbstractMetaClass *klass, if (auto r = recurseClassHierarchy(base, pred)) return r; } - return nullptr; + return {}; } #endif // ABSTRACTMETALANG_HELPERS_H diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang_typedefs.h b/sources/shiboken6/ApiExtractor/abstractmetalang_typedefs.h index 3b444197c..802f549cf 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang_typedefs.h +++ b/sources/shiboken6/ApiExtractor/abstractmetalang_typedefs.h @@ -4,9 +4,10 @@ #ifndef ABSTRACTMETALANG_TYPEDEFS_H #define ABSTRACTMETALANG_TYPEDEFS_H -#include <QtCore/QSharedPointer> #include <QtCore/QList> +#include <memory> + class AbstractMetaClass; class AbstractMetaField; class AbstractMetaArgument; @@ -16,12 +17,14 @@ class AbstractMetaFunction; class AbstractMetaType; struct UsingMember; -using AbstractMetaFunctionPtr = QSharedPointer<AbstractMetaFunction>; -using AbstractMetaFunctionCPtr = QSharedPointer<const AbstractMetaFunction>; +using AbstractMetaFunctionPtr = std::shared_ptr<AbstractMetaFunction>; +using AbstractMetaFunctionCPtr = std::shared_ptr<const AbstractMetaFunction>; +using AbstractMetaClassPtr = std::shared_ptr<AbstractMetaClass>; +using AbstractMetaClassCPtr = std::shared_ptr<const AbstractMetaClass>; using AbstractMetaArgumentList = QList<AbstractMetaArgument>; -using AbstractMetaClassList = QList<AbstractMetaClass *>; -using AbstractMetaClassCList = QList<const AbstractMetaClass *>; +using AbstractMetaClassList = QList<AbstractMetaClassPtr>; +using AbstractMetaClassCList = QList<AbstractMetaClassCPtr>; using AbstractMetaEnumList = QList<AbstractMetaEnum>; using AbstractMetaEnumValueList = QList<AbstractMetaEnumValue>; using AbstractMetaFieldList = QList<AbstractMetaField>; diff --git a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp index 19e030330..3ec07509d 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp @@ -7,6 +7,8 @@ #include "messages.h" #include "typedatabase.h" #include "containertypeentry.h" +#include "enumtypeentry.h" +#include "flagstypeentry.h" #include "qtcompat.h" #include "typeinfo.h" @@ -17,12 +19,13 @@ #include <QtCore/QHash> #include <QtCore/QSharedData> -#include <QtCore/QSharedPointer> #include <QtCore/QStack> +#include <memory> + using namespace Qt::StringLiterals; -using AbstractMetaTypeCPtr = QSharedPointer<const AbstractMetaType>; +using AbstractMetaTypeCPtr = std::shared_ptr<const AbstractMetaType>; const QSet<QString> &AbstractMetaType::cppFloatTypes() { @@ -116,6 +119,7 @@ public: QString formatPythonSignature() const; bool isEquivalent(const AbstractMetaTypeData &rhs) const; bool equals(const AbstractMetaTypeData &rhs) const; + QStringList instantiationCppSignatures() const; template <class Predicate> bool generateOpaqueContainer(Predicate p) const; @@ -151,6 +155,14 @@ AbstractMetaTypeData::AbstractMetaTypeData(const TypeEntryCPtr &t) : { } +QStringList AbstractMetaTypeData::instantiationCppSignatures() const +{ + QStringList result; + for (const auto &i : m_instantiations) + result.append(i.cppSignature()); + return result; +} + AbstractMetaType::AbstractMetaType(const TypeEntryCPtr &t) : d(new AbstractMetaTypeData(t)) { @@ -166,9 +178,9 @@ AbstractMetaType &AbstractMetaType::operator=(const AbstractMetaType &) = defaul AbstractMetaType::AbstractMetaType(const AbstractMetaType &rhs) = default; -AbstractMetaType::AbstractMetaType(AbstractMetaType &&) = default; +AbstractMetaType::AbstractMetaType(AbstractMetaType &&) noexcept = default; -AbstractMetaType &AbstractMetaType::operator=(AbstractMetaType &&) = default; +AbstractMetaType &AbstractMetaType::operator=(AbstractMetaType &&) noexcept = default; AbstractMetaType::~AbstractMetaType() = default; @@ -219,6 +231,11 @@ const AbstractMetaTypeList &AbstractMetaType::instantiations() const return d->m_instantiations; } +QStringList AbstractMetaType::instantiationCppSignatures() const +{ + return d->instantiationCppSignatures(); +} + // For applying the <array> function argument modification: change into a type // where "int *" becomes "int[]". bool AbstractMetaType::applyArrayModification(QString *errorMessage) @@ -228,7 +245,7 @@ bool AbstractMetaType::applyArrayModification(QString *errorMessage) *errorMessage = u"<array> modification already applied."_s; return false; } - if (!d->m_arrayElementType.isNull()) { + if (d->m_arrayElementType) { QTextStream(errorMessage) << "The type \"" << cppSignature() << "\" is an array of " << d->m_arrayElementType->name() << '.'; return false; @@ -276,13 +293,13 @@ QString AbstractMetaType::originalTypeDescription() const void AbstractMetaType::setOriginalTemplateType(const AbstractMetaType &type) { - if (d->m_originalTemplateType.isNull() || *d->m_originalTemplateType != type) + if (!d->m_originalTemplateType || *d->m_originalTemplateType != type) d->m_originalTemplateType.reset(new AbstractMetaType(type)); } const AbstractMetaType *AbstractMetaType::originalTemplateType() const { - return d->m_originalTemplateType.data(); + return d->m_originalTemplateType.get(); } AbstractMetaType AbstractMetaType::getSmartPointerInnerType() const @@ -311,7 +328,7 @@ AbstractMetaTypeList AbstractMetaType::nestedArrayTypes() const } break; case NativePointerAsArrayPattern: - result.append(*d->m_arrayElementType.data()); + result.append(*d->m_arrayElementType.get()); break; default: break; @@ -339,6 +356,12 @@ bool AbstractMetaType::passByValue() const return d->passByValue(); } +bool AbstractMetaType::useStdMove() const +{ + return (isUniquePointer() && d->passByValue()) + || d->m_referenceType == RValueReference; +} + ReferenceType AbstractMetaType::referenceType() const { return d->m_referenceType; @@ -417,17 +440,28 @@ int AbstractMetaType::arrayElementCount() const const AbstractMetaType *AbstractMetaType::arrayElementType() const { - return d->m_arrayElementType.data(); + return d->m_arrayElementType.get(); } void AbstractMetaType::setArrayElementType(const AbstractMetaType &t) { - if (d->m_arrayElementType.isNull() || *d->m_arrayElementType != t) { + if (!d->m_arrayElementType || *d->m_arrayElementType != t) { d->m_arrayElementType.reset(new AbstractMetaType(t)); d->m_signaturesDirty = true; } } +AbstractMetaType AbstractMetaType::plainType() const +{ + AbstractMetaType result = *this; + result.clearIndirections(); + result.setReferenceType(NoReference); + result.setConstant(false); + result.setVolatile(false); + result.decideUsagePattern(); + return result; +} + QString AbstractMetaType::cppSignature() const { const AbstractMetaTypeData *cd = d.constData(); @@ -509,6 +543,7 @@ void AbstractMetaType::decideUsagePattern() pattern = ObjectPattern; } setTypeUsagePattern(pattern); + Q_ASSERT(pattern != ContainerPattern || !d->m_instantiations.isEmpty()); } bool AbstractMetaTypeData::hasTemplateChildren() const @@ -542,6 +577,29 @@ static inline QString formatArraySize(int e) return result; } +// Return the number of template parameters; remove the default +// non template type parameter of std::span from the signature. +static qsizetype stripDefaultTemplateArgs(const TypeEntryCPtr &te, + const AbstractMetaTypeList &instantiations) +{ + static const char16_t dynamicExtent64[] = u"18446744073709551615"; // size_t(-1) + static const char16_t dynamicExtent32[] = u"4294967295"; + + qsizetype result = instantiations.size(); + if (result == 0 || !te->isContainer()) + return result; + auto cte = std::static_pointer_cast<const ContainerTypeEntry>(te); + if (cte->containerKind() != ContainerTypeEntry::SpanContainer) + return result; + const auto lastTe = instantiations.constLast().typeEntry(); + if (lastTe->type() == TypeEntry::ConstantValueType) { + const QString &name = lastTe->name(); + if (name == dynamicExtent64 || name == dynamicExtent32) + --result; + } + return result; +} + QString AbstractMetaTypeData::formatSignature(bool minimal) const { QString result; @@ -564,12 +622,13 @@ QString AbstractMetaTypeData::formatSignature(bool minimal) const result += u'<'; if (minimal) result += u' '; - for (qsizetype i = 0, size = m_instantiations.size(); i < size; ++i) { + const auto size = stripDefaultTemplateArgs(m_typeEntry, m_instantiations); + for (qsizetype i = 0; i < size; ++i) { if (i > 0) result += u','; result += m_instantiations.at(i).minimalSignature(); } - result += u" >"_s; + result += u'>'; } if (!minimal && (!m_indirections.isEmpty() || m_referenceType != NoReference)) @@ -642,10 +701,12 @@ QString AbstractMetaTypeData::formatPythonSignature() const if (m_typeEntry->isPrimitive()) for (Indirection i : m_indirections) result += TypeInfo::indirectionKeyword(i); - // If it is a flags type, we replace it with the full name: - // "PySide6.QtCore.Qt.ItemFlags" instead of "PySide6.QtCore.QFlags<Qt.ItemFlag>" - if (m_typeEntry->isFlags()) - result = m_typeEntry->qualifiedTargetLangName(); + // If it is a flags type, we replace it with the full name of the enum: + // "PySide6.QtCore.Qt.ItemFlag" instead of "PySide6.QtCore.QFlags<Qt.ItemFlag>" + if (m_typeEntry->isFlags()) { + const auto fte = std::static_pointer_cast<const FlagsTypeEntry>(m_typeEntry); + result = fte->originator()->qualifiedTargetLangName(); + } result.replace(u"::"_s, u"."_s); return result; } @@ -688,9 +749,9 @@ void AbstractMetaType::setVolatile(bool v) static bool equalsCPtr(const AbstractMetaTypeCPtr &t1, const AbstractMetaTypeCPtr &t2) { - if (t1.isNull() != t2.isNull()) + if (bool(t1) != bool(t2)) return false; - return t1.isNull() || *t1 == *t2; + return !t1 || *t1 == *t2; } bool AbstractMetaTypeData::isEquivalent(const AbstractMetaTypeData &rhs) const @@ -718,9 +779,9 @@ bool AbstractMetaTypeData::equals(const AbstractMetaTypeData &rhs) const && m_referenceType == rhs.m_referenceType && isEquivalent(rhs); } -bool AbstractMetaType::equals(const AbstractMetaType &rhs) const +bool comparesEqual(const AbstractMetaType &lhs, const AbstractMetaType &rhs) noexcept { - return d->equals(*rhs.d); + return lhs.d->equals(*rhs.d); } bool AbstractMetaType::isEquivalent(const AbstractMetaType &rhs) const @@ -730,12 +791,12 @@ bool AbstractMetaType::isEquivalent(const AbstractMetaType &rhs) const const AbstractMetaType *AbstractMetaType::viewOn() const { - return d->m_viewOn.data(); + return d->m_viewOn.get(); } void AbstractMetaType::setViewOn(const AbstractMetaType &v) { - if (d->m_viewOn.isNull() || *d->m_viewOn != v) + if (!d->m_viewOn || *d->m_viewOn != v) d->m_viewOn.reset(new AbstractMetaType(v)); } @@ -744,7 +805,7 @@ AbstractMetaType AbstractMetaType::createVoid() static QScopedPointer<AbstractMetaType> metaType; if (metaType.isNull()) { static TypeEntryCPtr voidTypeEntry = TypeDatabase::instance()->findType(u"void"_s); - Q_ASSERT(!voidTypeEntry.isNull()); + Q_ASSERT(voidTypeEntry); metaType.reset(new AbstractMetaType(voidTypeEntry)); metaType->decideUsagePattern(); } @@ -871,7 +932,7 @@ bool AbstractMetaType::isValueTypeWithCopyConstructorOnly() const { bool result = false; if (d->m_typeEntry->isComplex()) { - const auto cte = qSharedPointerCast<const ComplexTypeEntry>(d->m_typeEntry); + const auto cte = std::static_pointer_cast<const ComplexTypeEntry>(d->m_typeEntry); result = cte->isValueTypeWithCopyConstructorOnly(); } return result; @@ -888,14 +949,18 @@ using AbstractMetaTypeCache = QHash<QString, AbstractMetaType>; Q_GLOBAL_STATIC(AbstractMetaTypeCache, metaTypeFromStringCache) std::optional<AbstractMetaType> -AbstractMetaType::fromString(QString typeSignature, QString *errorMessage) +AbstractMetaType::fromString(const QString &typeSignatureIn, QString *errorMessage) { - typeSignature = typeSignature.trimmed(); + auto &cache = *metaTypeFromStringCache(); + auto it = cache.find(typeSignatureIn); + if (it != cache.end()) + return it.value(); + + QString typeSignature = typeSignatureIn.trimmed(); if (typeSignature.startsWith(u"::")) typeSignature.remove(0, 2); - auto &cache = *metaTypeFromStringCache(); - auto it = cache.find(typeSignature); + it = cache.find(typeSignature); if (it == cache.end()) { auto metaType = AbstractMetaBuilder::translateType(typeSignature, nullptr, {}, errorMessage); @@ -904,6 +969,8 @@ AbstractMetaType::fromString(QString typeSignature, QString *errorMessage) errorMessage->prepend(msgCannotBuildMetaType(typeSignature)); return {}; } + if (typeSignature != typeSignatureIn) + cache.insert(typeSignatureIn, metaType.value()); it = cache.insert(typeSignature, metaType.value()); } return it.value(); @@ -918,16 +985,12 @@ AbstractMetaType AbstractMetaType::fromTypeEntry(const TypeEntryCPtr &typeEntry) auto it = cache.find(typeName); if (it != cache.end()) return it.value(); - AbstractMetaType metaType(typeEntry); - metaType.clearIndirections(); - metaType.setReferenceType(NoReference); - metaType.setConstant(false); - metaType.decideUsagePattern(); + AbstractMetaType metaType = AbstractMetaType(typeEntry).plainType(); cache.insert(typeName, metaType); return metaType; } -AbstractMetaType AbstractMetaType::fromAbstractMetaClass(const AbstractMetaClass *metaClass) +AbstractMetaType AbstractMetaType::fromAbstractMetaClass(const AbstractMetaClassCPtr &metaClass) { return fromTypeEntry(metaClass->typeEntry()); } @@ -940,37 +1003,34 @@ bool AbstractMetaTypeData::generateOpaqueContainer(Predicate pred) const return false; if (m_indirections.size() > 1) return false; - auto containerTypeEntry = qSharedPointerCast<const ContainerTypeEntry>(m_typeEntry); + auto containerTypeEntry = std::static_pointer_cast<const ContainerTypeEntry>(m_typeEntry); auto kind = containerTypeEntry->containerKind(); - if (kind != ContainerTypeEntry::ListContainer) - return false; - const auto &instantation = m_instantiations.constFirst(); - if (instantation.referenceType() != NoReference) + if (kind != ContainerTypeEntry::ListContainer && kind != ContainerTypeEntry::SpanContainer) return false; - const QString signature = instantation.cppSignature(); - bool result = false; - auto instTypEntry = instantation.typeEntry(); - switch (instTypEntry->type()) { + const auto &firstInstantiation = m_instantiations.constFirst(); + if (firstInstantiation.referenceType() != NoReference) + return false; + switch (firstInstantiation.typeEntry()->type()) { case TypeEntry::PrimitiveType: case TypeEntry::FlagsType: case TypeEntry::EnumType: case TypeEntry::BasicValueType: case TypeEntry::ObjectType: case TypeEntry::CustomType: - result = pred(containerTypeEntry, signature); break; default: - break; + return false; } - return result; + + return pred(containerTypeEntry, instantiationCppSignatures()); } // Simple predicate for checking whether an opaque container should be generated static bool opaqueContainerPredicate(const ContainerTypeEntryCPtr &t, - const QString &signature) + const QStringList &instantiations) { - return t->generateOpaqueContainer(signature); + return t->generateOpaqueContainer(instantiations); } bool AbstractMetaType::generateOpaqueContainer() const @@ -983,8 +1043,9 @@ bool AbstractMetaType::generateOpaqueContainer() const // (cf AbstractMetaFunction::generateOpaqueContainerReturn()) bool AbstractMetaType::generateOpaqueContainerForGetter(const QString &modifiedType) const { - auto predicate = [&modifiedType](const ContainerTypeEntryCPtr &t, const QString &signature) { - return t->opaqueContainerName(signature) == modifiedType; + auto predicate = [&modifiedType](const ContainerTypeEntryCPtr &t, + const QStringList &instantiations) { + return t->opaqueContainerName(instantiations) == modifiedType; }; return d->generateOpaqueContainer(predicate); } @@ -1008,7 +1069,7 @@ void AbstractMetaType::formatDebug(QDebug &debug) const for (auto i : indirections) debug << ' ' << TypeInfo::indirectionKeyword(i); } - if (referenceType()) + if (referenceType() != NoReference) debug << ", reftype=" << referenceType(); if (isConstant()) debug << ", [const]"; diff --git a/sources/shiboken6/ApiExtractor/abstractmetatype.h b/sources/shiboken6/ApiExtractor/abstractmetatype.h index 237c33d20..8a1ecdf20 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetatype.h +++ b/sources/shiboken6/ApiExtractor/abstractmetatype.h @@ -9,7 +9,9 @@ #include "parser/codemodel_enums.h" #include "typedatabase_typedefs.h" +#include <QtCore/QtCompare> #include <QtCore/qobjectdefs.h> +#include <QtCore/QHashFunctions> #include <QtCore/QSharedDataPointer> #include <QtCore/QList> #include <QtCore/QSet> @@ -50,8 +52,8 @@ public: explicit AbstractMetaType(const TypeEntryCPtr &t); AbstractMetaType(const AbstractMetaType &); AbstractMetaType &operator=(const AbstractMetaType &); - AbstractMetaType(AbstractMetaType &&); - AbstractMetaType &operator=(AbstractMetaType &&); + AbstractMetaType(AbstractMetaType &&) noexcept; + AbstractMetaType &operator=(AbstractMetaType &&) noexcept; ~AbstractMetaType(); QString package() const; @@ -67,6 +69,7 @@ public: const AbstractMetaTypeList &instantiations() const; void addInstantiation(const AbstractMetaType &inst); void setInstantiations(const AbstractMetaTypeList &insts); + QStringList instantiationCppSignatures() const; QString minimalSignature() const { return formatSignature(true); } @@ -118,6 +121,7 @@ public: bool passByConstRef() const; bool passByValue() const; + bool useStdMove() const; ReferenceType referenceType() const; void setReferenceType(ReferenceType ref); @@ -141,6 +145,9 @@ public: AbstractMetaTypeList nestedArrayTypes() const; + /// Strip const/indirections/reference from the type + AbstractMetaType plainType() const; + QString cppSignature() const; QString pythonSignature() const; @@ -165,7 +172,6 @@ public: bool hasTemplateChildren() const; - bool equals(const AbstractMetaType &rhs) const; /// Is equivalent from the POV of argument passing (differ by const ref) bool isEquivalent(const AbstractMetaType &rhs) const; @@ -182,11 +188,11 @@ public: /// \param typeSignature The string describing the type to be built. /// \return A new AbstractMetaType object or nullopt in case of failure. static std::optional<AbstractMetaType> - fromString(QString typeSignature, QString *errorMessage = nullptr); + fromString(const QString &typeSignatureIn, QString *errorMessage = nullptr); /// Creates an AbstractMetaType object from a TypeEntry. static AbstractMetaType fromTypeEntry(const TypeEntryCPtr &typeEntry); /// Creates an AbstractMetaType object from an AbstractMetaClass. - static AbstractMetaType fromAbstractMetaClass(const AbstractMetaClass *metaClass); + static AbstractMetaType fromAbstractMetaClass(const AbstractMetaClassCPtr &metaClass); static void dereference(QString *type); // "foo" -> "(*foo)" /// Apply the result of shouldDereferenceArgument() @@ -248,6 +254,12 @@ public: #endif private: + friend size_t qHash(const AbstractMetaType &t, size_t seed = 0) noexcept + { return qHash(t.typeEntry().get(), seed); } + friend bool comparesEqual(const AbstractMetaType &lhs, + const AbstractMetaType &rhs) noexcept; + Q_DECLARE_EQUALITY_COMPARABLE(AbstractMetaType) + friend class AbstractMetaTypeData; QSharedDataPointer<AbstractMetaTypeData> d; @@ -256,14 +268,6 @@ private: QString formatPythonSignature() const; }; -inline bool operator==(const AbstractMetaType &t1, const AbstractMetaType &t2) -{ return t1.equals(t2); } -inline bool operator!=(const AbstractMetaType &t1, const AbstractMetaType &t2) -{ return !t1.equals(t2); } - -inline size_t qHash(const AbstractMetaType &t, size_t seed) -{ return qHash(t.typeEntry(), seed); } - #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const AbstractMetaType &at); QDebug operator<<(QDebug d, const AbstractMetaType *at); diff --git a/sources/shiboken6/ApiExtractor/addedfunction.cpp b/sources/shiboken6/ApiExtractor/addedfunction.cpp index 6525c1ed7..9d95b734c 100644 --- a/sources/shiboken6/ApiExtractor/addedfunction.cpp +++ b/sources/shiboken6/ApiExtractor/addedfunction.cpp @@ -9,18 +9,13 @@ using namespace Qt::StringLiterals; -static inline QString callOperator() { return QStringLiteral("operator()"); } +constexpr auto callOperator = "operator()"_L1; // Helpers to split a parameter list of <add-function>, <declare-function> // (@ denoting names), like // "void foo(QList<X,Y> &@list@ = QList<X,Y>{1,2}, int @b@=5, ...)" namespace AddedFunctionParser { -bool Argument::equals(const Argument &rhs) const -{ - return type == rhs.type && name == rhs.name && defaultValue == rhs.defaultValue; -} - QDebug operator<<(QDebug d, const Argument &a) { QDebugStateSaver saver(d); @@ -87,7 +82,7 @@ Arguments splitParameters(QStringView paramString, QString *errorMessage) for (const auto &t : tokens) { Argument argument; // Check defaultValue, "int @b@=5" - const int equalPos = t.lastIndexOf(u'='); + const auto equalPos = t.lastIndexOf(u'='); if (equalPos != -1) { const int defaultValuePos = equalPos + 1; argument.defaultValue = @@ -95,7 +90,7 @@ Arguments splitParameters(QStringView paramString, QString *errorMessage) } QString typeString = (equalPos != -1 ? t.left(equalPos) : t).trimmed().toString(); // Check @name@ - const int atPos = typeString.indexOf(u'@'); + const auto atPos = typeString.indexOf(u'@'); if (atPos != -1) { const int namePos = atPos + 1; const int nameEndPos = typeString.indexOf(u'@', namePos); @@ -143,16 +138,16 @@ AddedFunction::AddedFunctionPtr QStringView signature = QStringView{signatureIn}.trimmed(); // Skip past "operator()(...)" - const int parenSearchStartPos = signature.startsWith(callOperator()) - ? callOperator().size() : 0; - const int openParenPos = signature.indexOf(u'(', parenSearchStartPos); + const auto parenSearchStartPos = signature.startsWith(callOperator) + ? callOperator.size() : 0; + const auto openParenPos = signature.indexOf(u'(', parenSearchStartPos); if (openParenPos < 0) { return AddedFunctionPtr(new AddedFunction(signature.toString(), arguments, returnType)); } const QString name = signature.left(openParenPos).trimmed().toString(); - const int closingParenPos = signature.lastIndexOf(u')'); + const auto closingParenPos = signature.lastIndexOf(u')'); if (closingParenPos < 0) { *errorMessage = u"Missing closing parenthesis"_s; return {}; @@ -160,8 +155,8 @@ AddedFunction::AddedFunctionPtr // Check for "foo() const" bool isConst = false; - const int signatureLength = signature.length(); - const int qualifierLength = signatureLength - closingParenPos - 1; + const auto signatureLength = signature.length(); + const auto qualifierLength = signatureLength - closingParenPos - 1; if (qualifierLength >= 5 && signature.right(qualifierLength).contains(u"const")) { isConst = true; @@ -182,7 +177,7 @@ AddedFunction::AddedFunctionPtr arguments.append({type, p.name, p.defaultValue}); } - AddedFunctionPtr result(new AddedFunction(name, arguments, returnType)); + auto result = std::make_shared<AddedFunction>(name, arguments, returnType); result->setConstant(isConst); return result; } diff --git a/sources/shiboken6/ApiExtractor/addedfunction.h b/sources/shiboken6/ApiExtractor/addedfunction.h index 0f5dc89ef..b8d189b7a 100644 --- a/sources/shiboken6/ApiExtractor/addedfunction.h +++ b/sources/shiboken6/ApiExtractor/addedfunction.h @@ -8,9 +8,10 @@ #include "parser/typeinfo.h" #include <QtCore/QList> -#include <QtCore/QSharedPointer> #include <QtCore/QString> +#include <memory> + QT_FORWARD_DECLARE_CLASS(QDebug) /// \internal @@ -19,7 +20,7 @@ QT_FORWARD_DECLARE_CLASS(QDebug) /// will be inserted into the right AbstractMetaClass. struct AddedFunction { - using AddedFunctionPtr = QSharedPointer<AddedFunction>; + using AddedFunctionPtr = std::shared_ptr<AddedFunction>; /// Function access types. enum Access { @@ -78,6 +79,9 @@ struct AddedFunction bool isDeclaration() const { return m_isDeclaration; } // <declare-function> void setDeclaration(bool value) { m_isDeclaration = value; } + bool isPythonOverride() const { return m_isPythonOverride; } + void setPythonOverride(bool o) { m_isPythonOverride = o; } + const FunctionModificationList &modifications() const { return m_modifications; } FunctionModificationList &modifications() { return m_modifications; } @@ -85,17 +89,22 @@ struct AddedFunction DocModificationList &docModifications() { return m_docModifications; } void addDocModification(const DocModification &m) { m_docModifications.append(m); } + QString targetLangPackage() const { return m_targetLangPackage; } + void setTargetLangPackage(const QString &p) { m_targetLangPackage = p; } + private: QString m_name; QList<Argument> m_arguments; TypeInfo m_returnType; FunctionModificationList m_modifications; DocModificationList m_docModifications; + QString m_targetLangPackage; Access m_access = Public; bool m_isConst = false; bool m_isClassMethod = false; bool m_isStatic = false; bool m_isDeclaration = false; + bool m_isPythonOverride = false; }; QDebug operator<<(QDebug d, const AddedFunction::Argument &a); diff --git a/sources/shiboken6/ApiExtractor/addedfunction_p.h b/sources/shiboken6/ApiExtractor/addedfunction_p.h index 9915871ad..40b69a5df 100644 --- a/sources/shiboken6/ApiExtractor/addedfunction_p.h +++ b/sources/shiboken6/ApiExtractor/addedfunction_p.h @@ -4,6 +4,7 @@ #ifndef ADDEDFUNCTION_P_H #define ADDEDFUNCTION_P_H +#include <QtCore/QtCompare> #include <QtCore/QList> #include <QtCore/QString> #include <QtCore/QStringView> @@ -19,18 +20,20 @@ namespace AddedFunctionParser { struct Argument { - bool equals(const Argument &rhs) const; - QString type; QString name; QString defaultValue; + + friend bool comparesEqual(const Argument &lhs, const Argument &rhs) noexcept + { + return lhs.type == rhs.type && lhs.name == rhs.name + && lhs.defaultValue == rhs.defaultValue; + } + Q_DECLARE_EQUALITY_COMPARABLE(Argument) }; using Arguments = QList<Argument>; -inline bool operator==(const Argument &a1, const Argument &a2) { return a1.equals(a2); } -inline bool operator!=(const Argument &a1, const Argument &a2) { return !a1.equals(a2); } - #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const Argument &a); #endif diff --git a/sources/shiboken6/ApiExtractor/anystringview_helpers.cpp b/sources/shiboken6/ApiExtractor/anystringview_helpers.cpp new file mode 100644 index 000000000..35d2d535a --- /dev/null +++ b/sources/shiboken6/ApiExtractor/anystringview_helpers.cpp @@ -0,0 +1,56 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "anystringview_helpers.h" + +#include <QtCore/QString> // Must go before QAnyStringView for operator<<(QTextStream,QASV)! +#include <QtCore/QAnyStringView> +#include <QtCore/QDebug> +#include <QtCore/QTextStream> + +#include <cstring> + +QTextStream &operator<<(QTextStream &str, QAnyStringView asv) +{ + asv.visit([&str](auto s) { str << s; }); + return str; +} + +static bool asv_containsImpl(QLatin1StringView v, char c) +{ + return v.contains(uint16_t(c)); +} + +static bool asv_containsImpl(QUtf8StringView v, char c) +{ + return std::strchr(v.data(), c) != nullptr; +} + +static bool asv_containsImpl(QStringView v, char c) +{ + return v.contains(uint16_t(c)); +} + +bool asv_contains(QAnyStringView asv, char needle) +{ + return asv.visit([needle](auto s) { return asv_containsImpl(s, needle); }); +} + +static bool asv_containsImpl(QLatin1StringView v, const char *c) +{ + return v.contains(QLatin1StringView(c)); +} +static bool asv_containsImpl(QUtf8StringView v, const char *c) +{ + return std::strstr(v.data(), c) != nullptr; +} + +static bool asv_containsImpl(QStringView v, const char *c) +{ + return v.contains(QLatin1StringView(c)); +} + +bool asv_contains(QAnyStringView asv, const char *needle) +{ + return asv.visit([needle](auto s) { return asv_containsImpl(s, needle); }); +} diff --git a/sources/shiboken6/ApiExtractor/anystringview_helpers.h b/sources/shiboken6/ApiExtractor/anystringview_helpers.h new file mode 100644 index 000000000..e1e6ab7f0 --- /dev/null +++ b/sources/shiboken6/ApiExtractor/anystringview_helpers.h @@ -0,0 +1,18 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef ANYSTRINGVIEW_STREAM_H +#define ANYSTRINGVIEW_STREAM_H + +#include <QtCore/QtClassHelperMacros> + +QT_FORWARD_DECLARE_CLASS(QAnyStringView) +QT_FORWARD_DECLARE_CLASS(QTextStream) +QT_FORWARD_DECLARE_CLASS(QDebug) + +QTextStream &operator<<(QTextStream &str, QAnyStringView asv); + +bool asv_contains(QAnyStringView asv, char needle); +bool asv_contains(QAnyStringView asv, const char *needle); + +#endif // ANYSTRINGVIEW_STREAM_H diff --git a/sources/shiboken6/ApiExtractor/apiextractor.cpp b/sources/shiboken6/ApiExtractor/apiextractor.cpp index 2e22f21e3..83ee4437e 100644 --- a/sources/shiboken6/ApiExtractor/apiextractor.cpp +++ b/sources/shiboken6/ApiExtractor/apiextractor.cpp @@ -3,7 +3,6 @@ #include "apiextractor.h" #include "apiextractorresult.h" -#include "apiextractorresultdata_p.h" #include "abstractmetaargument.h" #include "abstractmetabuilder.h" #include "abstractmetaenum.h" @@ -14,6 +13,7 @@ #include "exception.h" #include "messages.h" #include "modifications.h" +#include "optionsparser.h" #include "reporthandler.h" #include "typedatabase.h" #include "customconversion.h" @@ -43,7 +43,186 @@ struct InstantiationCollectContext QStringList instantiatedContainersNames; }; -struct ApiExtractorPrivate +struct ApiExtractorOptions +{ + QString m_typeSystemFileName; + QFileInfoList m_cppFileNames; + HeaderPaths m_includePaths; + QStringList m_clangOptions; + QString m_logDirectory; + LanguageLevel m_languageLevel = LanguageLevel::Default; + bool m_skipDeprecated = false; +}; + +static inline QString languageLevelDescription() +{ + return u"C++ Language level (c++11..c++17, default="_s + + QLatin1StringView(clang::languageLevelOption(clang::emulatedCompilerLanguageLevel())) + + u')'; +} + +QList<OptionDescription> ApiExtractor::options() +{ + return { + {u"use-global-header"_s, + u"Use the global headers in generated code."_s}, + {u"clang-option"_s, + u"Option to be passed to clang"_s}, + {u"clang-options"_s, + u"A comma-separated list of options to be passed to clang"_s}, + {u"skip-deprecated"_s, + u"Skip deprecated functions"_s}, + {u"-F<path>"_s, {} }, + {u"framework-include-paths="_s + OptionsParser::pathSyntax(), + u"Framework include paths used by the C++ parser"_s}, + {u"-isystem<path>"_s, {} }, + {u"system-include-paths="_s + OptionsParser::pathSyntax(), + u"System include paths used by the C++ parser"_s}, + {u"language-level=, -std=<level>"_s, + languageLevelDescription()}, + }; +} + +class ApiExtractorOptionsParser : public OptionsParser +{ +public: + explicit ApiExtractorOptionsParser(ApiExtractorOptions *o) : m_options(o) {} + + bool handleBoolOption(const QString &key, OptionSource source) override; + bool handleOption(const QString &key, const QString &value, + OptionSource source) override; + +private: + void parseIncludePathOption(const QString &value, HeaderType headerType); + void parseIncludePathOption(const QStringList &values, HeaderType headerType); + void setLanguageLevel(const QString &value); + + ApiExtractorOptions *m_options; +}; + +void ApiExtractorOptionsParser::parseIncludePathOption(const QString &value, + HeaderType headerType) +{ + if (value.isEmpty()) + throw Exception(u"Empty value passed to include path option"_s); + const auto path = QFile::encodeName(QDir::cleanPath(value)); + m_options->m_includePaths.append(HeaderPath{path, headerType}); +} + +void ApiExtractorOptionsParser::parseIncludePathOption(const QStringList &values, + HeaderType headerType) +{ + for (const auto &value : values) + parseIncludePathOption(value, headerType); +} + +void ApiExtractorOptionsParser::setLanguageLevel(const QString &value) +{ + const QByteArray languageLevelBA = value.toLatin1(); + const LanguageLevel level = clang::languageLevelFromOption(languageLevelBA.constData()); + if (level == LanguageLevel::Default) + throw Exception(msgInvalidLanguageLevel(value)); + m_options->m_languageLevel = level; +} + +bool ApiExtractorOptionsParser::handleBoolOption(const QString &key, OptionSource source) +{ + static const auto isystemOption = "isystem"_L1; + + switch (source) { + case OptionSource::CommandLine: + case OptionSource::ProjectFile: + if (key == u"use-global-header") { + AbstractMetaBuilder::setUseGlobalHeader(true); + return true; + } + if (key == u"skip-deprecated") { + m_options->m_skipDeprecated = true; + return true; + } + break; + + case OptionSource::CommandLineSingleDash: + if (key.startsWith(u'I')) { // Shorthand path arguments -I/usr/include... + parseIncludePathOption(key.sliced(1), HeaderType::Standard); + return true; + } + if (key.startsWith(u'F')) { + parseIncludePathOption(key.sliced(1), HeaderType::Framework); + return true; + } + if (key.startsWith(isystemOption)) { + parseIncludePathOption(key.sliced(isystemOption.size()), HeaderType::System); + return true; + } + break; + } + return false; +} + +bool ApiExtractorOptionsParser::handleOption(const QString &key, const QString &value, + OptionSource source) +{ + if (source == OptionSource::CommandLineSingleDash) { + if (key == u"std") { + setLanguageLevel(value); + return true; + } + return false; + } + + if (key == u"clang-option") { + m_options->m_clangOptions.append(value); + return true; + } + if (key == u"clang-options") { + m_options->m_clangOptions.append(value.split(u',', Qt::SkipEmptyParts)); + return true; + } + if (key == u"include-paths") { + parseIncludePathOption(value.split(QDir::listSeparator(), Qt::SkipEmptyParts), + HeaderType::Standard); + return true; + } + if (key == u"framework-include-paths") { + parseIncludePathOption(value.split(QDir::listSeparator(), Qt::SkipEmptyParts), + HeaderType::Framework); + return true; + } + if (key == u"system-include-paths") { + parseIncludePathOption(value.split(QDir::listSeparator(), Qt::SkipEmptyParts), + HeaderType::System); + return true; + } + if (key == u"language-level") { + setLanguageLevel(value); + return true; + } + + if (source == OptionSource::ProjectFile) { + if (key == u"include-path") { + parseIncludePathOption(value, HeaderType::Standard); + return true; + } + if (key == u"framework-include-path") { + parseIncludePathOption(value, HeaderType::Framework); + return true; + } + if (key == u"system-include-path") { + parseIncludePathOption(value, HeaderType::System); + return true; + } + } + + return false; +} + +std::shared_ptr<OptionsParser> ApiExtractor::createOptionsParser() +{ + return std::make_shared<ApiExtractorOptionsParser>(d); +} + +struct ApiExtractorPrivate : public ApiExtractorOptions { bool runHelper(ApiExtractorFlags flags); @@ -54,7 +233,7 @@ struct ApiExtractorPrivate void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context, const AbstractMetaFunctionCPtr &func); void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context, - const AbstractMetaClass *metaClass); + const AbstractMetaClassCPtr &metaClass); void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context); void collectInstantiatedOpqaqueContainers(InstantiationCollectContext &context); void collectContainerTypesFromSnippets(InstantiationCollectContext &context); @@ -64,23 +243,12 @@ struct ApiExtractorPrivate void addInstantiatedSmartPointer(InstantiationCollectContext &context, const AbstractMetaType &type); - QString m_typeSystemFileName; - QFileInfoList m_cppFileNames; - HeaderPaths m_includePaths; - QStringList m_clangOptions; AbstractMetaBuilder *m_builder = nullptr; - QString m_logDirectory; - LanguageLevel m_languageLevel = LanguageLevel::Default; - bool m_skipDeprecated = false; }; ApiExtractor::ApiExtractor() : d(new ApiExtractorPrivate) { - // Environment TYPESYSTEMPATH - QString envTypesystemPaths = QFile::decodeName(qgetenv("TYPESYSTEMPATH")); - if (!envTypesystemPaths.isEmpty()) - TypeDatabase::instance()->addTypesystemPath(envTypesystemPaths); } ApiExtractor::~ApiExtractor() @@ -89,32 +257,6 @@ ApiExtractor::~ApiExtractor() delete d; } -void ApiExtractor::addTypesystemSearchPath (const QString& path) -{ - TypeDatabase::instance()->addTypesystemPath(path); -} - -void ApiExtractor::addTypesystemSearchPath(const QStringList& paths) -{ - for (const QString &path : paths) - addTypesystemSearchPath(path); -} - -void ApiExtractor::setTypesystemKeywords(const QStringList &keywords) -{ - TypeDatabase::instance()->setTypesystemKeywords(keywords); -} - -void ApiExtractor::addIncludePath(const HeaderPath& path) -{ - d->m_includePaths << path; -} - -void ApiExtractor::addIncludePath(const HeaderPaths& paths) -{ - d->m_includePaths << paths; -} - HeaderPaths ApiExtractor::includePaths() const { return d->m_includePaths; @@ -145,33 +287,6 @@ QString ApiExtractor::typeSystem() const return d->m_typeSystemFileName; } -void ApiExtractor::setSkipDeprecated(bool value) -{ - d->m_skipDeprecated = value; - if (d->m_builder) - d->m_builder->setSkipDeprecated(d->m_skipDeprecated); -} - -void ApiExtractor::setSuppressWarnings ( bool value ) -{ - TypeDatabase::instance()->setSuppressWarnings(value); -} - -void ApiExtractor::setSilent ( bool value ) -{ - ReportHandler::setSilent(value); -} - -bool ApiExtractor::setApiVersion(const QString& package, const QString &version) -{ - return TypeDatabase::setApiVersion(package, version); -} - -void ApiExtractor::setDropTypeEntries(const QStringList &dropEntries) -{ - TypeDatabase::instance()->setDropTypeEntries(dropEntries); -} - const AbstractMetaEnumList &ApiExtractor::globalEnums() const { Q_ASSERT(d->m_builder); @@ -225,8 +340,7 @@ bool ApiExtractorPrivate::runHelper(ApiExtractorFlags flags) } const QString pattern = QDir::tempPath() + u'/' - + m_cppFileNames.constFirst().baseName() - + QStringLiteral("_XXXXXX.hpp"); + + m_cppFileNames.constFirst().baseName() + "_XXXXXX.hpp"_L1; QTemporaryFile ppFile(pattern); bool autoRemove = !qEnvironmentVariableIsSet("KEEP_TEMP_FILES"); // make sure that a tempfile can be written @@ -266,16 +380,16 @@ bool ApiExtractorPrivate::runHelper(ApiExtractorFlags flags) for (const HeaderPath &headerPath : std::as_const(m_includePaths)) arguments.append(HeaderPath::includeOption(headerPath)); + if (flags.testFlag(ApiExtractorFlag::UsePySideExtensions)) + addPySideExtensions(&arguments); arguments.append(QFile::encodeName(preprocessedCppFileName)); + if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { qCInfo(lcShiboken).noquote().nospace() << "clang language level: " << int(m_languageLevel) << "\nclang arguments: " << arguments; } - if (flags.testFlag(ApiExtractorFlag::UsePySideExtensions)) - addPySideExtensions(&arguments); - const bool result = m_builder->build(arguments, flags, addCompilerSupportArguments, m_languageLevel); if (!result) @@ -300,18 +414,17 @@ std::optional<ApiExtractorResult> ApiExtractor::run(ApiExtractorFlags flags) InstantiationCollectContext collectContext; d->collectInstantiatedContainersAndSmartPointers(collectContext); - auto *data = new ApiExtractorResultData; - - classListToCList(d->m_builder->takeClasses(), &data->m_metaClasses); - classListToCList(d->m_builder->takeTemplates(), &data->m_templates); - classListToCList(d->m_builder->takeSmartPointers(), &data->m_smartPointers); - data->m_globalFunctions = d->m_builder->globalFunctions(); - data->m_globalEnums = d->m_builder->globalEnums(); - data->m_enums = d->m_builder->typeEntryToEnumsHash(); - data->m_flags = flags; - qSwap(data->m_instantiatedContainers, collectContext.instantiatedContainers); - qSwap(data->m_instantiatedSmartPointers, collectContext.instantiatedSmartPointers); - return ApiExtractorResult(data); + ApiExtractorResult result; + classListToCList(d->m_builder->takeClasses(), &result.m_metaClasses); + classListToCList(d->m_builder->takeSmartPointers(), &result.m_smartPointers); + result.m_globalFunctions = d->m_builder->globalFunctions(); + result.m_globalEnums = d->m_builder->globalEnums(); + result.m_enums = d->m_builder->typeEntryToEnumsHash(); + result.m_flags = flags; + result.m_typedefTargetToName = d->m_builder->typedefTargetToName(); + qSwap(result.m_instantiatedContainers, collectContext.instantiatedContainers); + qSwap(result.m_instantiatedSmartPointers, collectContext.instantiatedSmartPointers); + return result; } LanguageLevel ApiExtractor::languageLevel() const @@ -319,26 +432,11 @@ LanguageLevel ApiExtractor::languageLevel() const return d->m_languageLevel; } -void ApiExtractor::setLanguageLevel(LanguageLevel languageLevel) -{ - d->m_languageLevel = languageLevel; -} - QStringList ApiExtractor::clangOptions() const { return d->m_clangOptions; } -void ApiExtractor::setClangOptions(const QStringList &co) -{ - d->m_clangOptions = co; -} - -void ApiExtractor::setUseGlobalHeader(bool h) -{ - AbstractMetaBuilder::setUseGlobalHeader(h); -} - AbstractMetaFunctionPtr ApiExtractor::inheritTemplateFunction(const AbstractMetaFunctionCPtr &function, const AbstractMetaTypeList &templateTypes) @@ -349,15 +447,15 @@ AbstractMetaFunctionPtr AbstractMetaFunctionPtr ApiExtractor::inheritTemplateMember(const AbstractMetaFunctionCPtr &function, const AbstractMetaTypeList &templateTypes, - const AbstractMetaClass *templateClass, - AbstractMetaClass *subclass) + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaClassPtr &subclass) { return AbstractMetaBuilder::inheritTemplateMember(function, templateTypes, templateClass, subclass); } -AbstractMetaClass *ApiExtractor::inheritTemplateClass(const ComplexTypeEntryPtr &te, - const AbstractMetaClass *templateClass, +AbstractMetaClassPtr ApiExtractor::inheritTemplateClass(const ComplexTypeEntryPtr &te, + const AbstractMetaClassCPtr &templateClass, const AbstractMetaTypeList &templateTypes, InheritTemplateFlags flags) { @@ -436,12 +534,12 @@ ApiExtractorPrivate::addInstantiatedContainersAndSmartPointers(InstantiationColl return; } if (type.hasTemplateChildren()) { - QString piece = isContainer ? QStringLiteral("container") : QStringLiteral("smart pointer"); + const auto piece = isContainer ? "container"_L1 : "smart pointer"_L1; QString warning = QString::fromLatin1("Skipping instantiation of %1 '%2' because it has template" " arguments.").arg(piece, type.originalTypeDescription()); if (!contextName.isEmpty()) - warning.append(QStringLiteral(" Calling context: ") + contextName); + warning.append(" Calling context: "_L1 + contextName); qCWarning(lcShiboken).noquote().nospace() << warning; return; @@ -489,7 +587,7 @@ static void addOwnerModification(const AbstractMetaFunctionCList &functions, for (const auto &f : functions) { if (!f->arguments().isEmpty() && f->arguments().constFirst().type().indirections() > 0) { - qSharedPointerConstCast<AbstractMetaFunction>(f)->clearModificationsCache(); + std::const_pointer_cast<AbstractMetaFunction>(f)->clearModificationsCache(); typeEntry->addFunctionModification(invalidateArgMod(f)); } } @@ -505,7 +603,7 @@ void ApiExtractorPrivate::addInstantiatedSmartPointer(InstantiationCollectContex Q_ASSERT(smp.smartPointer); const auto &instantiatedType = type.instantiations().constFirst(); - const auto ste = qSharedPointerCast<const SmartPointerTypeEntry>(smp.smartPointer->typeEntry()); + const auto ste = std::static_pointer_cast<const SmartPointerTypeEntry>(smp.smartPointer->typeEntry()); QString name = ste->getTargetName(smp.type); auto parentTypeEntry = ste->parent(); InheritTemplateFlags flags; @@ -532,9 +630,9 @@ void ApiExtractorPrivate::addInstantiatedSmartPointer(InstantiationCollectContex {instantiatedType}, flags); Q_ASSERT(smp.specialized); if (withinNameSpace) { // move class to desired namespace - auto *enclClass = AbstractMetaClass::findClass(m_builder->classes(), parentTypeEntry); + const auto enclClass = AbstractMetaClass::findClass(m_builder->classes(), parentTypeEntry); Q_ASSERT(enclClass); - auto *specialized = const_cast<AbstractMetaClass *>(smp.specialized); + auto specialized = std::const_pointer_cast<AbstractMetaClass>(smp.specialized); specialized->setEnclosingClass(enclClass); enclClass->addInnerClass(specialized); } @@ -556,26 +654,31 @@ ApiExtractorPrivate::collectInstantiatedContainersAndSmartPointers(Instantiation const AbstractMetaFunctionCPtr &func) { addInstantiatedContainersAndSmartPointers(context, func->type(), func->signature()); - for (const AbstractMetaArgument &arg : func->arguments()) - addInstantiatedContainersAndSmartPointers(context, arg.type(), func->signature()); + for (const AbstractMetaArgument &arg : func->arguments()) { + const auto argType = arg.type(); + const auto type = argType.viewOn() != nullptr ? *argType.viewOn() : argType; + addInstantiatedContainersAndSmartPointers(context, type, func->signature()); + } } void ApiExtractorPrivate::collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context, - const AbstractMetaClass *metaClass) + const AbstractMetaClassCPtr &metaClass) { if (!metaClass->typeEntry()->generateCode()) return; for (const auto &func : metaClass->functions()) collectInstantiatedContainersAndSmartPointers(context, func); + for (const auto &func : metaClass->userAddedPythonOverrides()) + collectInstantiatedContainersAndSmartPointers(context, func); for (const AbstractMetaField &field : metaClass->fields()) addInstantiatedContainersAndSmartPointers(context, field.type(), field.name()); // The list of inner classes might be extended when smart pointer // instantiations are specified to be in namespaces. - auto &innerClasses = metaClass->innerClasses(); + const auto &innerClasses = metaClass->innerClasses(); for (auto i = innerClasses.size() - 1; i >= 0; --i) { - auto *innerClass = innerClasses.at(i); + const auto innerClass = innerClasses.at(i); if (!innerClass->typeEntry()->isSmartPointer()) collectInstantiatedContainersAndSmartPointers(context, innerClass); } @@ -587,7 +690,7 @@ ApiExtractorPrivate::collectInstantiatedContainersAndSmartPointers(Instantiation collectInstantiatedOpqaqueContainers(context); for (const auto &func : m_builder->globalFunctions()) collectInstantiatedContainersAndSmartPointers(context, func); - for (auto metaClass : m_builder->classes()) + for (const auto &metaClass : m_builder->classes()) collectInstantiatedContainersAndSmartPointers(context, metaClass); collectContainerTypesFromSnippets(context); } @@ -614,8 +717,7 @@ void ApiExtractorPrivate::collectInstantiatedOpqaqueContainers(InstantiationColl for (const auto &container : containers) { for (const auto &oc : container->opaqueContainers()) { QString errorMessage; - const QString typeName = container->qualifiedCppName() + u'<' - + oc.instantiation + u'>'; + const QString typeName = container->qualifiedCppName() + oc.templateParameters(); auto typeOpt = AbstractMetaType::fromString(typeName, &errorMessage); if (typeOpt.has_value() && generateOpaqueContainer(typeOpt.value(), moduleEntry)) { @@ -635,12 +737,12 @@ static void getCode(QStringList &code, const CodeSnipList &codeSnips) static void getCode(QStringList &code, const TypeEntryCPtr &type) { if (type->isComplex()) - getCode(code, qSharedPointerCast<const ComplexTypeEntry>(type)->codeSnips()); + getCode(code, std::static_pointer_cast<const ComplexTypeEntry>(type)->codeSnips()); else if (type->isTypeSystem()) - getCode(code, qSharedPointerCast<const TypeSystemTypeEntry>(type)->codeSnips()); + getCode(code, std::static_pointer_cast<const TypeSystemTypeEntry>(type)->codeSnips()); auto customConversion = CustomConversion::getCustomConversion(type); - if (customConversion.isNull()) + if (!customConversion) return; if (!customConversion->nativeToTargetConversion().isEmpty()) @@ -664,11 +766,11 @@ void ApiExtractorPrivate::collectContainerTypesFromSnippets(InstantiationCollect const ContainerTypeEntryCList &containerTypeList = td->containerTypes(); for (const auto &type : containerTypeList) getCode(snips, type); - for (auto metaClass : m_builder->classes()) + for (const auto &metaClass : m_builder->classes()) getCode(snips, metaClass->typeEntry()); const auto moduleEntry = td->defaultTypeSystemType(); - Q_ASSERT(!moduleEntry.isNull()); + Q_ASSERT(moduleEntry); getCode(snips, moduleEntry); for (const auto &func : m_builder->globalFunctions()) @@ -686,8 +788,8 @@ ApiExtractorPrivate::collectContainerTypesFromConverterMacros(InstantiationColle bool toPythonMacro) { QString convMacro = toPythonMacro ? u"%CONVERTTOPYTHON["_s : u"%CONVERTTOCPP["_s; - int offset = toPythonMacro ? sizeof("%CONVERTTOPYTHON") : sizeof("%CONVERTTOCPP"); - int start = 0; + const qsizetype offset = toPythonMacro ? sizeof("%CONVERTTOPYTHON") : sizeof("%CONVERTTOCPP"); + qsizetype start = 0; QString errorMessage; while ((start = code.indexOf(convMacro, start)) != -1) { int end = code.indexOf(u']', start); diff --git a/sources/shiboken6/ApiExtractor/apiextractor.h b/sources/shiboken6/ApiExtractor/apiextractor.h index 51df5e45a..feae9454c 100644 --- a/sources/shiboken6/ApiExtractor/apiextractor.h +++ b/sources/shiboken6/ApiExtractor/apiextractor.h @@ -20,6 +20,8 @@ class AbstractMetaClass; class AbstractMetaEnum; class AbstractMetaFunction; class ComplexTypeEntry; +struct OptionDescription; +class OptionsParser; QT_BEGIN_NAMESPACE class QDebug; @@ -36,27 +38,17 @@ public: ApiExtractor(); ~ApiExtractor(); + static QList<OptionDescription> options(); + std::shared_ptr<OptionsParser> createOptionsParser(); + void setTypeSystem(const QString& typeSystemFileName); QString typeSystem() const; void setCppFileNames(const QFileInfoList &cppFileNames); QFileInfoList cppFileNames() const; - void setSkipDeprecated(bool value); - static void setSuppressWarnings(bool value); - static void setSilent(bool value); - static void addTypesystemSearchPath(const QString &path); - static void addTypesystemSearchPath(const QStringList& paths); - static void setTypesystemKeywords(const QStringList& keywords); - void addIncludePath(const HeaderPath& path); - void addIncludePath(const HeaderPaths& paths); HeaderPaths includePaths() const; void setLogDirectory(const QString& logDir); - static bool setApiVersion(const QString &package, const QString &version); - static void setDropTypeEntries(const QStringList &dropEntries); LanguageLevel languageLevel() const; - void setLanguageLevel(LanguageLevel languageLevel); QStringList clangOptions() const; - void setClangOptions(const QStringList &co); - static void setUseGlobalHeader(bool h); const AbstractMetaEnumList &globalEnums() const; const AbstractMetaFunctionCList &globalFunctions() const; @@ -74,13 +66,13 @@ public: static AbstractMetaFunctionPtr inheritTemplateMember(const AbstractMetaFunctionCPtr &function, const AbstractMetaTypeList &templateTypes, - const AbstractMetaClass *templateClass, - AbstractMetaClass *subclass); + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaClassPtr &subclass); /// Forwards to AbstractMetaBuilder::inheritTemplateClass() - static AbstractMetaClass * + static AbstractMetaClassPtr inheritTemplateClass(const ComplexTypeEntryPtr &te, - const AbstractMetaClass *templateClass, + const AbstractMetaClassCPtr &templateClass, const AbstractMetaTypeList &templateTypes, InheritTemplateFlags flags = {}); diff --git a/sources/shiboken6/ApiExtractor/apiextractorresult.cpp b/sources/shiboken6/ApiExtractor/apiextractorresult.cpp index a0917d64e..2a48a30d1 100644 --- a/sources/shiboken6/ApiExtractor/apiextractorresult.cpp +++ b/sources/shiboken6/ApiExtractor/apiextractorresult.cpp @@ -2,90 +2,76 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "apiextractorresult.h" -#include "apiextractorresultdata_p.h" #include "abstractmetalang.h" #include "abstractmetaenum.h" #include "enumtypeentry.h" #include "flagstypeentry.h" -ApiExtractorResultData::ApiExtractorResultData() = default; - -ApiExtractorResultData::~ApiExtractorResultData() -{ - qDeleteAll(m_smartPointers); - qDeleteAll(m_metaClasses); - qDeleteAll(m_templates); - for (auto &smp : m_instantiatedSmartPointers) - delete smp.specialized; -} - -ApiExtractorResult::ApiExtractorResult() : d(new ApiExtractorResultData) -{ -} - -ApiExtractorResult::ApiExtractorResult(ApiExtractorResultData *data) : - d(data) -{ -} +ApiExtractorResult::ApiExtractorResult() = default; ApiExtractorResult::ApiExtractorResult(const ApiExtractorResult &) = default; ApiExtractorResult &ApiExtractorResult::operator=(const ApiExtractorResult &) = default; -ApiExtractorResult::ApiExtractorResult(ApiExtractorResult &&) = default; +ApiExtractorResult::ApiExtractorResult(ApiExtractorResult &&) noexcept = default; -ApiExtractorResult &ApiExtractorResult::operator=(ApiExtractorResult &&) = default; +ApiExtractorResult &ApiExtractorResult::operator=(ApiExtractorResult &&) noexcept = default; ApiExtractorResult::~ApiExtractorResult() = default; const AbstractMetaEnumList &ApiExtractorResult::globalEnums() const { - return d->m_globalEnums; + return m_globalEnums; } const AbstractMetaFunctionCList &ApiExtractorResult::globalFunctions() const { - return d->m_globalFunctions; + return m_globalFunctions; } const AbstractMetaClassCList &ApiExtractorResult::classes() const { - return d->m_metaClasses; + return m_metaClasses; } const AbstractMetaClassCList &ApiExtractorResult::smartPointers() const { - return d->m_smartPointers; + return m_smartPointers; } const AbstractMetaTypeList &ApiExtractorResult::instantiatedContainers() const { - return d->m_instantiatedContainers; + return m_instantiatedContainers; } const InstantiatedSmartPointers &ApiExtractorResult::instantiatedSmartPointers() const { - return d->m_instantiatedSmartPointers; + return m_instantiatedSmartPointers; +} + +const QMultiHash<QString, QString> &ApiExtractorResult::typedefTargetToName() const +{ + return m_typedefTargetToName; } ApiExtractorFlags ApiExtractorResult::flags() const { - return d->m_flags; + return m_flags; } void ApiExtractorResult::setFlags(ApiExtractorFlags f) { - d->m_flags = f; + m_flags = f; } std::optional<AbstractMetaEnum> ApiExtractorResult::findAbstractMetaEnum(TypeEntryCPtr typeEntry) const { - if (!typeEntry.isNull() && typeEntry->isFlags()) - typeEntry = qSharedPointerCast<const FlagsTypeEntry>(typeEntry)->originator(); - const auto it = d->m_enums.constFind(typeEntry); - if (it == d->m_enums.constEnd()) + if (typeEntry && typeEntry->isFlags()) + typeEntry = std::static_pointer_cast<const FlagsTypeEntry>(typeEntry)->originator(); + const auto it = m_enums.constFind(typeEntry); + if (it == m_enums.constEnd()) return {}; return it.value(); } @@ -93,7 +79,7 @@ std::optional<AbstractMetaEnum> AbstractMetaFunctionCList ApiExtractorResult::implicitConversions(const TypeEntryCPtr &type) const { if (type->isValue()) { - if (auto metaClass = AbstractMetaClass::findClass(d->m_metaClasses, type)) + if (auto metaClass = AbstractMetaClass::findClass(m_metaClasses, type)) return metaClass->implicitConversions(); } return {}; diff --git a/sources/shiboken6/ApiExtractor/apiextractorresult.h b/sources/shiboken6/ApiExtractor/apiextractorresult.h index f85fca9f0..88a2093f1 100644 --- a/sources/shiboken6/ApiExtractor/apiextractorresult.h +++ b/sources/shiboken6/ApiExtractor/apiextractorresult.h @@ -9,7 +9,8 @@ #include "abstractmetalang_typedefs.h" #include "typesystem_typedefs.h" -#include <QtCore/QExplicitlySharedDataPointer> +#include <QtCore/QHash> +#include <QtCore/QMultiHash> #include <optional> @@ -17,8 +18,8 @@ class ApiExtractorResultData; struct InstantiatedSmartPointer { - const AbstractMetaClass *smartPointer = nullptr; // Template class - const AbstractMetaClass *specialized = nullptr; // Specialized for type + AbstractMetaClassCPtr smartPointer; // Template class + AbstractMetaClassCPtr specialized; // Specialized for type AbstractMetaType type; }; @@ -29,11 +30,10 @@ class ApiExtractorResult { public: ApiExtractorResult(); - explicit ApiExtractorResult(ApiExtractorResultData *data); ApiExtractorResult(const ApiExtractorResult &); ApiExtractorResult &operator=(const ApiExtractorResult &); - ApiExtractorResult(ApiExtractorResult &&); - ApiExtractorResult &operator=(ApiExtractorResult &&); + ApiExtractorResult(ApiExtractorResult &&) noexcept; + ApiExtractorResult &operator=(ApiExtractorResult &&) noexcept; ~ApiExtractorResult(); const AbstractMetaEnumList &globalEnums() const; @@ -44,6 +44,8 @@ public: const AbstractMetaTypeList &instantiatedContainers() const; const InstantiatedSmartPointers &instantiatedSmartPointers() const; + const QMultiHash<QString, QString> &typedefTargetToName() const; + // Query functions for the generators std::optional<AbstractMetaEnum> findAbstractMetaEnum(TypeEntryCPtr typeEntry) const; @@ -60,7 +62,17 @@ public: void setFlags(ApiExtractorFlags f); private: - QExplicitlySharedDataPointer<ApiExtractorResultData> d; + AbstractMetaClassCList m_metaClasses; + AbstractMetaClassCList m_smartPointers; + AbstractMetaFunctionCList m_globalFunctions; + AbstractMetaEnumList m_globalEnums; + AbstractMetaTypeList m_instantiatedContainers; + InstantiatedSmartPointers m_instantiatedSmartPointers; + QHash<TypeEntryCPtr, AbstractMetaEnum> m_enums; + QMultiHash<QString, QString> m_typedefTargetToName; + ApiExtractorFlags m_flags; + + friend class ApiExtractor; }; #endif // APIEXTRACTORRESULT_H diff --git a/sources/shiboken6/ApiExtractor/apiextractorresultdata_p.h b/sources/shiboken6/ApiExtractor/apiextractorresultdata_p.h deleted file mode 100644 index 05d548d6d..000000000 --- a/sources/shiboken6/ApiExtractor/apiextractorresultdata_p.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#ifndef APIEXTRACTORRESULTDATA_P_H -#define APIEXTRACTORRESULTDATA_P_H - -#include "apiextractorresult.h" - -#include <QtCore/QHash> -#include <QtCore/QSharedData> - -class ApiExtractorResultData : public QSharedData -{ -public: - ApiExtractorResultData(); - ~ApiExtractorResultData(); - - AbstractMetaClassCList m_metaClasses; - AbstractMetaClassCList m_templates; // not exposed, just for ownership - AbstractMetaClassCList m_smartPointers; - AbstractMetaFunctionCList m_globalFunctions; - AbstractMetaEnumList m_globalEnums; - AbstractMetaTypeList m_instantiatedContainers; - InstantiatedSmartPointers m_instantiatedSmartPointers; - QHash<TypeEntryCPtr, AbstractMetaEnum> m_enums; - ApiExtractorFlags m_flags; -}; - -#endif // APIEXTRACTORRESULTDATA_P_H diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp index 512f1a879..31e7efb05 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp @@ -4,6 +4,7 @@ #include "clangbuilder.h" #include "compilersupport.h" #include "clangutils.h" +#include "clangdebugutils.h" #include <codemodel.h> #include <reporthandler.h> @@ -25,9 +26,6 @@ using namespace Qt::StringLiterals; namespace clang { -static inline QString colonColon() { return QStringLiteral("::"); } -static inline QString templateBrackets() { return QStringLiteral("<>"); } - static inline bool isClassCursor(const CXCursor &c) { return c.kind == CXCursor_ClassDecl || c.kind == CXCursor_StructDecl @@ -115,8 +113,17 @@ static bool isSigned(CXTypeKind kind) class BuilderPrivate { public: + Q_DISABLE_COPY_MOVE(BuilderPrivate) + + enum class SpecialSystemHeader { + None, + Types, + OpenGL, + WhiteListed, + WhiteListedPath + }; + using CursorClassHash = QHash<CXCursor, ClassModelItem>; - using CursorTypedefHash = QHash<CXCursor, TypeDefModelItem>; using TypeInfoHash = QHash<CXType, TypeInfo>; explicit BuilderPrivate(BaseVisitor *bv) : m_baseVisitor(bv), m_model(new CodeModel) @@ -182,10 +189,9 @@ public: std::pair<QString, ClassModelItem> getBaseClass(CXType type) const; void addBaseClass(const CXCursor &cursor); - template <class Item> - void qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer<Item> &item) const; - + SpecialSystemHeader specialSystemHeader(const QString &fileName) const; bool visitHeader(const QString &fileName) const; + static const char *specialSystemHeaderReason(SpecialSystemHeader sh); void setFileName(const CXCursor &cursor, _CodeModelItem *item); @@ -198,7 +204,6 @@ public: // classes can be correctly parented in case of forward-declared inner classes // (QMetaObject::Connection) CursorClassHash m_cursorClassHash; - CursorTypedefHash m_cursorTypedefHash; mutable TypeInfoHash m_typeInfoHash; // Cache type information mutable QHash<QString, TemplateTypeAliasModelItem> m_templateTypeAliases; @@ -209,21 +214,22 @@ public: ArgumentModelItem m_currentArgument; VariableModelItem m_currentField; TemplateTypeAliasModelItem m_currentTemplateTypeAlias; - QStringList m_systemIncludes; // files, like "memory" - QStringList m_systemIncludePaths; // paths, like "/usr/include/Qt/" + QStringList m_forceProcessSystemIncludes; // files, like "memory" + QStringList m_forceProcessSystemIncludePaths; // paths, like "/usr/include/Qt/" QString m_usingTypeRef; // Base classes in "using Base::member;" bool m_withinUsingDeclaration = false; int m_anonymousEnumCount = 0; CodeModel::FunctionType m_currentFunctionType = CodeModel::Normal; bool m_withinFriendDecl = false; + mutable QHash<QString, SpecialSystemHeader> m_systemHeaders; }; bool BuilderPrivate::addClass(const CXCursor &cursor, CodeModel::ClassType t) { QString className = getCursorSpelling(cursor); m_currentClass.reset(new _ClassModelItem(m_model, className)); - setFileName(cursor, m_currentClass.data()); + setFileName(cursor, m_currentClass.get()); m_currentClass->setClassType(t); // Some inner class? Note that it does not need to be (lexically) contained in a // class since it is possible to forward declare an inner class: @@ -266,7 +272,7 @@ static QString msgCannotDetermineException(const std::string_view &snippetV) const qsizetype length = qsizetype(truncate ? newLine : snippetV.size()); QString snippet = QString::fromUtf8(snippetV.data(), length); if (truncate) - snippet += QStringLiteral("..."); + snippet += "..."_L1; return u"Cannot determine exception specification: \""_s + snippet + u'"'; } @@ -327,9 +333,11 @@ FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor, // Apply type fixes to "operator X &" -> "operator X&" if (name.startsWith(u"operator ")) name = fixTypeName(name); - FunctionModelItem result(new _FunctionModelItem(m_model, name)); - setFileName(cursor, result.data()); - result->setType(createTypeInfo(clang_getCursorResultType(cursor))); + auto result = std::make_shared<_FunctionModelItem>(m_model, name); + setFileName(cursor, result.get()); + const auto type = clang_getCursorResultType(cursor); + result->setType(createTypeInfo(type)); + result->setScopeResolution(hasScopeResolution(type)); result->setFunctionType(t); result->setScope(m_scope); result->setStatic(clang_Cursor_getStorageClass(cursor) == CX_SC_Static); @@ -338,7 +346,7 @@ FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor, case CXAvailability_Available: break; case CXAvailability_Deprecated: - result->setDeprecated(true); + result->setAttribute(FunctionAttribute::Deprecated); break; case CXAvailability_NotAvailable: // "Foo(const Foo&) = delete;" result->setDeleted(true); @@ -381,9 +389,9 @@ FunctionModelItem BuilderPrivate::createMemberFunction(const CXCursor &cursor, auto result = createFunction(cursor, functionType, isTemplateCode); result->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor))); result->setConstant(clang_CXXMethod_isConst(cursor) != 0); - result->setStatic(clang_CXXMethod_isStatic(cursor) != 0); - result->setVirtual(clang_CXXMethod_isVirtual(cursor) != 0); - result->setAbstract(clang_CXXMethod_isPureVirtual(cursor) != 0); + result->setAttribute(FunctionAttribute::Static, clang_CXXMethod_isStatic(cursor) != 0); + result->setAttribute(FunctionAttribute::Virtual, clang_CXXMethod_isVirtual(cursor) != 0); + result->setAttribute(FunctionAttribute::Abstract, clang_CXXMethod_isPureVirtual(cursor) != 0); return result; } @@ -399,13 +407,14 @@ void BuilderPrivate::qualifyConstructor(const CXCursor &cursor) && m_currentFunction->arguments().size() == 1 && clang_CXXConstructor_isCopyConstructor(cursor) == 0 && clang_CXXConstructor_isMoveConstructor(cursor) == 0) { - m_currentFunction->setExplicit(clang_CXXConstructor_isConvertingConstructor(cursor) == 0); + m_currentFunction->setAttribute(FunctionAttribute::Explicit, + clang_CXXConstructor_isConvertingConstructor(cursor) == 0); } } TemplateParameterModelItem BuilderPrivate::createTemplateParameter(const CXCursor &cursor) const { - return TemplateParameterModelItem(new _TemplateParameterModelItem(m_model, getCursorSpelling(cursor))); + return std::make_shared<_TemplateParameterModelItem>(m_model, getCursorSpelling(cursor)); } TemplateParameterModelItem BuilderPrivate::createNonTypeTemplateParameter(const CXCursor &cursor) const @@ -418,11 +427,12 @@ TemplateParameterModelItem BuilderPrivate::createNonTypeTemplateParameter(const // CXCursor_VarDecl, CXCursor_FieldDecl cursors void BuilderPrivate::addField(const CXCursor &cursor) { - VariableModelItem field(new _VariableModelItem(m_model, getCursorSpelling(cursor))); + auto field = std::make_shared<_VariableModelItem>(m_model, getCursorSpelling(cursor)); field->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor))); field->setScope(m_scope); field->setType(createTypeInfo(cursor)); field->setMutable(clang_CXXField_isMutable(cursor) != 0); + setFileName(cursor, field.get()); m_currentField = field; m_scopeStack.back()->addVariable(field); } @@ -438,7 +448,7 @@ static QStringList qualifiedName(const QString &t) end = t.size(); int lastPos = 0; while (true) { - const int nextPos = t.indexOf(colonColon(), lastPos); + const int nextPos = t.indexOf(u"::"_s, lastPos); if (nextPos < 0 || nextPos >= end) break; result.append(t.mid(lastPos, nextPos - lastPos)); @@ -556,7 +566,7 @@ TypeInfo BuilderPrivate::createTypeInfoUncached(const CXType &type, typeInfo.setConstant(clang_isConstQualifiedType(nestedType) != 0); typeInfo.setVolatile(clang_isVolatileQualifiedType(nestedType) != 0); - QString typeName = getTypeName(nestedType); + QString typeName = getResolvedTypeName(nestedType); while (TypeInfo::stripLeadingConst(&typeName) || TypeInfo::stripLeadingVolatile(&typeName)) { } @@ -566,14 +576,14 @@ TypeInfo BuilderPrivate::createTypeInfoUncached(const CXType &type, // the typedef source is named "type-parameter-0-0". Convert it back to the // template parameter name. The CXTypes are the same for all templates and // must not be cached. - if (!m_currentClass.isNull() && typeName.startsWith(u"type-parameter-0-")) { + if (m_currentClass && typeName.startsWith(u"type-parameter-0-")) { if (cacheable != nullptr) *cacheable = false; bool ok; const int n = QStringView{typeName}.mid(17).toInt(&ok); if (ok) { auto currentTemplate = currentTemplateClass(); - if (!currentTemplate.isNull() && n < currentTemplate->templateParameters().size()) + if (currentTemplate && n < currentTemplate->templateParameters().size()) typeName = currentTemplate->templateParameters().at(n)->name(); } } @@ -604,19 +614,18 @@ TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const void BuilderPrivate::addTypeDef(const CXCursor &cursor, const CXType &cxType) { const QString target = getCursorSpelling(cursor); - TypeDefModelItem item(new _TypeDefModelItem(m_model, target)); - setFileName(cursor, item.data()); + auto item = std::make_shared<_TypeDefModelItem>(m_model, target); + setFileName(cursor, item.get()); item->setType(createTypeInfo(cxType)); item->setScope(m_scope); m_scopeStack.back()->addTypeDef(item); - m_cursorTypedefHash.insert(cursor, item); } ClassModelItem BuilderPrivate::currentTemplateClass() const { for (auto i = m_scopeStack.size() - 1; i >= 0; --i) { - auto klass = qSharedPointerDynamicCast<_ClassModelItem>(m_scopeStack.at(i)); - if (!klass.isNull() && klass->isTemplate()) + auto klass = std::dynamic_pointer_cast<_ClassModelItem>(m_scopeStack.at(i)); + if (klass && klass->isTemplate()) return klass; } return {}; @@ -626,7 +635,7 @@ void BuilderPrivate::startTemplateTypeAlias(const CXCursor &cursor) { const QString target = getCursorSpelling(cursor); m_currentTemplateTypeAlias.reset(new _TemplateTypeAliasModelItem(m_model, target)); - setFileName(cursor, m_currentTemplateTypeAlias.data()); + setFileName(cursor, m_currentTemplateTypeAlias.get()); m_currentTemplateTypeAlias->setScope(m_scope); } @@ -659,6 +668,9 @@ QString BuilderPrivate::cursorValueExpression(BaseVisitor *bv, const CXCursor &c } // Resolve a type (loop over aliases/typedefs), for example for base classes +// Note: TypeAliasTemplateDecl ("using QVector<T>=QList<T>") is automatically +// resolved by clang_getTypeDeclaration(), but it stops at +// TypeAliasDecl / TypedefDecl. struct TypeDeclaration { @@ -666,17 +678,21 @@ struct TypeDeclaration CXCursor declaration; }; -static TypeDeclaration resolveType(CXType type) +static inline bool isTypeAliasDecl(const CXCursor &cursor) +{ + const auto kind = clang_getCursorKind(cursor); + return kind == CXCursor_TypeAliasDecl || kind == CXCursor_TypedefDecl; +} + +static TypeDeclaration resolveBaseClassType(CXType type) { CXCursor decl = clang_getTypeDeclaration(type); - if (type.kind != CXType_Unexposed) { - while (true) { - auto kind = clang_getCursorKind(decl); - if (kind != CXCursor_TypeAliasDecl && kind != CXCursor_TypedefDecl) - break; - type = clang_getTypedefDeclUnderlyingType(decl); - decl = clang_getTypeDeclaration(type); - } + auto resolvedType = clang_getCursorType(decl); + if (resolvedType.kind != CXType_Invalid && resolvedType.kind != type.kind) + type = resolvedType; + while (isTypeAliasDecl(decl)) { + type = clang_getTypedefDeclUnderlyingType(decl); + decl = clang_getTypeDeclaration(type); } return {type, decl}; } @@ -685,21 +701,11 @@ static TypeDeclaration resolveType(CXType type) // where the cursor spelling has "struct baseClass". std::pair<QString, ClassModelItem> BuilderPrivate::getBaseClass(CXType type) const { - const auto decl = resolveType(type); + const auto decl = resolveBaseClassType(type); // Note: spelling has "struct baseClass", use type - QString baseClassName; - if (decl.type.kind == CXType_Unexposed) { - // The type is unexposed when the base class is a template type alias: - // "class QItemSelection : public QList<X>" where QList is aliased to QVector. - // Try to resolve via code model. - TypeInfo info = createTypeInfo(decl.type); - auto parentScope = m_scopeStack.at(m_scopeStack.size() - 2); // Current is class. - auto resolved = TypeInfo::resolveType(info, parentScope); - if (resolved != info) - baseClassName = resolved.toString(); - } - if (baseClassName.isEmpty()) - baseClassName = getTypeName(decl.type); + QString baseClassName = getTypeName(decl.type); + if (baseClassName.startsWith(u"std::")) // Simplify "std::" types + baseClassName = createTypeInfo(decl.type).toString(); auto it = m_cursorClassHash.constFind(decl.declaration); // Not found: Set unqualified name. This happens in cases like @@ -720,11 +726,11 @@ std::pair<QString, ClassModelItem> BuilderPrivate::getBaseClass(CXType type) con // "std::vector<T>"). const QStringList &baseScope = it.value()->scope(); if (!baseScope.isEmpty()) { - const int lastSep = baseClassName.lastIndexOf(colonColon()); + const int lastSep = baseClassName.lastIndexOf(u"::"_s); if (lastSep >= 0) - baseClassName.remove(0, lastSep + colonColon().size()); - baseClassName.prepend(colonColon()); - baseClassName.prepend(baseScope.join(colonColon())); + baseClassName.remove(0, lastSep + u"::"_s.size()); + baseClassName.prepend(u"::"_s); + baseClassName.prepend(baseScope.join(u"::"_s)); } return {baseClassName, it.value()}; } @@ -738,37 +744,6 @@ void BuilderPrivate::addBaseClass(const CXCursor &cursor) m_currentClass->addBaseClass({baseClass.first, baseClass.second, access}); } -static inline CXCursor definitionFromTypeRef(const CXCursor &typeRefCursor) -{ - Q_ASSERT(typeRefCursor.kind == CXCursor_TypeRef); - return clang_getTypeDeclaration(clang_getCursorType(typeRefCursor)); -} - -// Qualify function arguments or fields that are typedef'ed from another scope: -// enum ConversionFlag {}; -// typedef QFlags<ConversionFlag> ConversionFlags; -// class QTextCodec { -// enum ConversionFlag {}; -// typedef QFlags<ConversionFlag> ConversionFlags; -// struct ConverterState { -// explicit ConverterState(ConversionFlags); -// ^^ qualify to QTextCodec::ConversionFlags -// ConversionFlags m_flags; -// ^^ ditto - -template <class Item> // ArgumentModelItem, VariableModelItem -void BuilderPrivate::qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer<Item> &item) const -{ - TypeInfo type = item->type(); - if (type.qualifiedName().size() == 1) { // item's type is unqualified. - const auto it = m_cursorTypedefHash.constFind(definitionFromTypeRef(typeRefCursor)); - if (it != m_cursorTypedefHash.constEnd() && !it.value()->scope().isEmpty()) { - type.setQualifiedName(it.value()->scope() + type.qualifiedName()); - item->setType(type); - } - } -} - void BuilderPrivate::setFileName(const CXCursor &cursor, _CodeModelItem *item) { const SourceRange range = getCursorRange(cursor); @@ -802,8 +777,38 @@ static QString baseName(QString path) return path; } +const char * BuilderPrivate::specialSystemHeaderReason(BuilderPrivate::SpecialSystemHeader sh) +{ + static const QHash<SpecialSystemHeader, const char *> mapping { + {SpecialSystemHeader::OpenGL, "OpenGL"}, + {SpecialSystemHeader::Types, "types"}, + {SpecialSystemHeader::WhiteListed, "white listed"}, + {SpecialSystemHeader::WhiteListedPath, "white listed path"} + }; + return mapping.value(sh, ""); +} + bool BuilderPrivate::visitHeader(const QString &fileName) const { + auto it = m_systemHeaders.find(fileName); + if (it == m_systemHeaders.end()) { + it = m_systemHeaders.insert(fileName, specialSystemHeader(fileName)); + if (ReportHandler::isDebug(ReportHandler::MediumDebug)) { + const QString &name = QDir::toNativeSeparators(fileName); + if (it.value() == SpecialSystemHeader::None) { + qCInfo(lcShiboken, "Skipping system header %s", qPrintable(name)); + } else { + qCInfo(lcShiboken, "Parsing system header %s (%s)", + qPrintable(name), specialSystemHeaderReason(it.value())); + } + } + } + return it.value() != SpecialSystemHeader::None; +} + +BuilderPrivate::SpecialSystemHeader + BuilderPrivate::specialSystemHeader(const QString &fileName) const +{ // Resolve OpenGL typedefs although the header is considered a system header. const QString baseName = clang::baseName(fileName); if (baseName == u"gl.h" @@ -812,8 +817,8 @@ bool BuilderPrivate::visitHeader(const QString &fileName) const || baseName == u"gl31.h" || baseName == u"gl32.h" || baseName == u"stdint.h" // Windows: int32_t, uint32_t - || baseName == u"stddef.h") { // size_t - return true; + || baseName == u"stddef.h") { // size_t` + return SpecialSystemHeader::OpenGL; } switch (clang::platform()) { @@ -822,7 +827,7 @@ bool BuilderPrivate::visitHeader(const QString &fileName) const || baseName == u"types.h" || baseName == u"stdint-intn.h" // int32_t || baseName == u"stdint-uintn.h") { // uint32_t - return true; + return SpecialSystemHeader::Types; } break; case Platform::macOS: @@ -832,22 +837,28 @@ bool BuilderPrivate::visitHeader(const QString &fileName) const if (baseName == u"gltypes.h" || fileName.contains(u"/usr/include/_types") || fileName.contains(u"/usr/include/sys/_types")) { - return true; + return SpecialSystemHeader::Types; } break; default: break; } - for (const auto &systemInclude : m_systemIncludes) { - if (systemInclude == baseName) - return true; - } - for (const auto &systemIncludePath : m_systemIncludePaths) { - if (fileName.startsWith(systemIncludePath)) - return true; + // When building against system Qt (as it happens with yocto / Boot2Qt), the Qt headers are + // considered system headers by clang_Location_isInSystemHeader, and shiboken will not + // process them. We need to explicitly process them by checking against the list of + // include paths that were passed to shiboken's --force-process-system-include-paths option + // or specified via the <system-include> xml tag. + if (m_forceProcessSystemIncludes.contains(baseName)) + return SpecialSystemHeader::WhiteListed; + + if (std::any_of(m_forceProcessSystemIncludePaths.cbegin(), + m_forceProcessSystemIncludePaths.cend(), + [fileName](const QString &p) { return fileName.startsWith(p); })) { + return SpecialSystemHeader::WhiteListedPath; } - return false; + + return SpecialSystemHeader::None; } bool Builder::visitLocation(const QString &fileName, LocationType locationType) const @@ -855,13 +866,14 @@ bool Builder::visitLocation(const QString &fileName, LocationType locationType) return locationType != LocationType::System || d->visitHeader(fileName); } -void Builder::setSystemIncludes(const QStringList &systemIncludes) +void Builder::setForceProcessSystemIncludes(const QStringList &systemIncludes) { for (const auto &i : systemIncludes) { - if (i.endsWith(u'/')) - d->m_systemIncludePaths.append(i); + QFileInfo fi(i); + if (fi.exists() && fi.isDir()) + d->m_forceProcessSystemIncludePaths.append(i); else - d->m_systemIncludes.append(i); + d->m_forceProcessSystemIncludes.append(i); } } @@ -870,7 +882,7 @@ FileModelItem Builder::dom() const Q_ASSERT(!d->m_scopeStack.isEmpty()); auto rootScope = d->m_scopeStack.constFirst(); rootScope->purgeClassDeclarations(); - return qSharedPointerDynamicCast<_FileModelItem>(rootScope); + return std::dynamic_pointer_cast<_FileModelItem>(rootScope); } static QString msgOutOfOrder(const CXCursor &cursor, const char *expectedScope) @@ -904,6 +916,8 @@ static NamespaceType namespaceType(const CXCursor &cursor) static QString enumType(const CXCursor &cursor) { QString name = getCursorSpelling(cursor); // "enum Foo { v1, v2 };" + if (name.contains(u"unnamed enum")) // Clang 16.0 + return {}; if (name.isEmpty()) { // PYSIDE-1228: For "typedef enum { v1, v2 } Foo;", type will return // "Foo" as expected. Care must be taken to exclude real anonymous enums. @@ -933,7 +947,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) } break; case CXCursor_CXXBaseSpecifier: - if (d->m_currentClass.isNull()) { + if (!d->m_currentClass) { const Diagnostic d(msgOutOfOrder(cursor, "class"), cursor, CXDiagnostic_Error); qWarning() << d; appendDiagnostic(d); @@ -955,15 +969,15 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) || !d->addClass(cursor, CodeModel::Class)) { return Skip; } - d->m_currentClass->setName(d->m_currentClass->name() + templateBrackets()); - d->m_scope.back() += templateBrackets(); + d->m_currentClass->setName(d->m_currentClass->name() + "<>"_L1); + d->m_scope.back() += "<>"_L1; break; case CXCursor_EnumDecl: { QString name = enumType(cursor); EnumKind kind = CEnum; if (name.isEmpty()) { kind = AnonymousEnum; - name = QStringLiteral("enum_") + QString::number(++d->m_anonymousEnumCount); + name = "enum_"_L1 + QString::number(++d->m_anonymousEnumCount); #if !CLANG_NO_ENUMDECL_ISSCOPED } else if (clang_EnumDecl_isScoped(cursor) != 0) { #else @@ -972,19 +986,21 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) kind = EnumClass; } d->m_currentEnum.reset(new _EnumModelItem(d->m_model, name)); - d->setFileName(cursor, d->m_currentEnum.data()); + d->setFileName(cursor, d->m_currentEnum.get()); d->m_currentEnum->setScope(d->m_scope); d->m_currentEnum->setEnumKind(kind); if (clang_getCursorAvailability(cursor) == CXAvailability_Deprecated) d->m_currentEnum->setDeprecated(true); - d->m_currentEnum->setSigned(isSigned(clang_getEnumDeclIntegerType(cursor).kind)); - if (!qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back()).isNull()) + const auto enumType = fullyResolveType(clang_getEnumDeclIntegerType(cursor)); + d->m_currentEnum->setSigned(isSigned(enumType.kind)); + d->m_currentEnum->setUnderlyingType(getTypeName(enumType)); + if (std::dynamic_pointer_cast<_ClassModelItem>(d->m_scopeStack.back())) d->m_currentEnum->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor))); } break; case CXCursor_EnumConstantDecl: { const QString name = getCursorSpelling(cursor); - if (d->m_currentEnum.isNull()) { + if (!d->m_currentEnum) { const Diagnostic d(msgOutOfOrder(cursor, "enum"), cursor, CXDiagnostic_Error); qWarning() << d; appendDiagnostic(d); @@ -995,7 +1011,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) enumValue.setValue(clang_getEnumConstantDeclValue(cursor)); else enumValue.setUnsignedValue(clang_getEnumConstantDeclUnsignedValue(cursor)); - EnumeratorModelItem enumConstant(new _EnumeratorModelItem(d->m_model, name)); + auto enumConstant = std::make_shared<_EnumeratorModelItem>(d->m_model, name); enumConstant->setStringValue(d->cursorValueExpression(this, cursor)); enumConstant->setValue(enumValue); if (clang_getCursorAvailability(cursor) == CXAvailability_Deprecated) @@ -1043,6 +1059,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) } } d->m_currentFunction = d->createFunction(cursor, CodeModel::Normal, true); + d->setFileName(cursor, d->m_currentFunction.get()); d->m_scopeStack.back()->addFunction(d->m_currentFunction); break; case CXCursor_FunctionDecl: @@ -1066,8 +1083,8 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) if (type == NamespaceType::Anonymous) return Skip; const QString name = getCursorSpelling(cursor); - const NamespaceModelItem parentNamespaceItem = qSharedPointerDynamicCast<_NamespaceModelItem>(d->m_scopeStack.back()); - if (parentNamespaceItem.isNull()) { + const auto parentNamespaceItem = std::dynamic_pointer_cast<_NamespaceModelItem>(d->m_scopeStack.back()); + if (!parentNamespaceItem) { const QString message = msgOutOfOrder(cursor, "namespace") + u" (current scope: "_s + d->m_scopeStack.back()->name() + u')'; const Diagnostic d(message, cursor, CXDiagnostic_Error); @@ -1079,7 +1096,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) // in subsequent modules. NamespaceModelItem namespaceItem = parentNamespaceItem->findNamespace(name); namespaceItem.reset(new _NamespaceModelItem(d->m_model, name)); - d->setFileName(cursor, namespaceItem.data()); + d->setFileName(cursor, namespaceItem.get()); namespaceItem->setScope(d->m_scope); namespaceItem->setType(type); parentNamespaceItem->addNamespace(namespaceItem); @@ -1089,10 +1106,12 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) case CXCursor_ParmDecl: // Skip in case of nested CXCursor_ParmDecls in case one parameter is a function pointer // and function pointer typedefs. - if (d->m_currentArgument.isNull() && !d->m_currentFunction.isNull()) { + if (!d->m_currentArgument && d->m_currentFunction) { const QString name = getCursorSpelling(cursor); d->m_currentArgument.reset(new _ArgumentModelItem(d->m_model, name)); - d->m_currentArgument->setType(d->createTypeInfo(cursor)); + const auto type = clang_getCursorType(cursor); + d->m_currentArgument->setScopeResolution(hasScopeResolution(type)); + d->m_currentArgument->setType(d->createTypeInfo(type)); d->m_currentFunction->addArgument(d->m_currentArgument); QString defaultValueExpression = d->cursorValueExpression(this, cursor); if (!defaultValueExpression.isEmpty()) { @@ -1108,16 +1127,16 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) const TemplateParameterModelItem tItem = cursor.kind == CXCursor_TemplateTemplateParameter ? d->createTemplateParameter(cursor) : d->createNonTypeTemplateParameter(cursor); // Apply to function/member template? - if (!d->m_currentFunction.isNull()) { + if (d->m_currentFunction) { d->m_currentFunction->setTemplateParameters(d->m_currentFunction->templateParameters() << tItem); - } else if (!d->m_currentTemplateTypeAlias.isNull()) { + } else if (d->m_currentTemplateTypeAlias) { d->m_currentTemplateTypeAlias->addTemplateParameter(tItem); - } else if (!d->m_currentClass.isNull()) { // Apply to class + } else if (d->m_currentClass) { // Apply to class const QString &tplParmName = tItem->name(); if (Q_UNLIKELY(!insertTemplateParameterIntoClassName(tplParmName, d->m_currentClass) || !insertTemplateParameterIntoClassName(tplParmName, &d->m_scope.back()))) { - const QString message = QStringLiteral("Error inserting template parameter \"") + tplParmName - + QStringLiteral("\" into ") + d->m_currentClass->name(); + const QString message = "Error inserting template parameter \""_L1 + tplParmName + + "\" into "_L1 + d->m_currentClass->name(); const Diagnostic d(message, cursor, CXDiagnostic_Error); qWarning() << d; appendDiagnostic(d); @@ -1131,7 +1150,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) d->startTemplateTypeAlias(cursor); break; case CXCursor_TypeAliasDecl: // May contain nested CXCursor_TemplateTypeParameter - if (d->m_currentTemplateTypeAlias.isNull()) { + if (!d->m_currentTemplateTypeAlias) { const CXType type = clang_getCanonicalType(clang_getCursorType(cursor)); if (type.kind > CXType_Unexposed) d->addTypeDef(cursor, type); @@ -1159,31 +1178,23 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) d->m_usingTypeRef = getCursorSpelling(cursor); break; case CXCursor_TypeRef: - if (!d->m_currentFunction.isNull()) { - if (d->m_currentArgument.isNull()) - d->qualifyTypeDef(cursor, d->m_currentFunction); // return type - else - d->qualifyTypeDef(cursor, d->m_currentArgument); - } else if (!d->m_currentField.isNull()) { - d->qualifyTypeDef(cursor, d->m_currentField); - } else if (d->m_withinUsingDeclaration && d->m_usingTypeRef.isEmpty()) { + if (d->m_withinUsingDeclaration && d->m_usingTypeRef.isEmpty()) d->m_usingTypeRef = d->getBaseClass(clang_getCursorType(cursor)).first; - } break; case CXCursor_CXXFinalAttr: - if (!d->m_currentFunction.isNull()) - d->m_currentFunction->setFinal(true); - else if (!d->m_currentClass.isNull()) + if (d->m_currentFunction) + d->m_currentFunction->setAttribute(FunctionAttribute::Final); + else if (d->m_currentClass) d->m_currentClass->setFinal(true); break; case CXCursor_CXXOverrideAttr: - if (!d->m_currentFunction.isNull()) - d->m_currentFunction->setOverride(true); + if (d->m_currentFunction) + d->m_currentFunction->setAttribute(FunctionAttribute::Override); break; case CXCursor_StaticAssert: // Check for Q_PROPERTY() (see PySide6/global.h.in for an explanation // how it is defined, and qdoc). - if (clang_isDeclaration(cursor.kind) && !d->m_currentClass.isNull()) { + if (clang_isDeclaration(cursor.kind) && d->m_currentClass) { auto snippet = getCodeSnippet(cursor); const auto length = snippet.size(); if (length > 12 && *snippet.rbegin() == ')' @@ -1195,7 +1206,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) break; // UsingDeclaration: consists of a TypeRef (base) and OverloadedDeclRef (member name) case CXCursor_UsingDeclaration: - if (!d->m_currentClass.isNull()) + if (d->m_currentClass) d->m_withinUsingDeclaration = true; break; case CXCursor_OverloadedDeclRef: @@ -1223,51 +1234,51 @@ bool Builder::endToken(const CXCursor &cursor) case CXCursor_ClassTemplatePartialSpecialization: d->popScope(); // Continue in outer class after leaving inner class? - if (ClassModelItem lastClass = qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back())) + if (auto lastClass = std::dynamic_pointer_cast<_ClassModelItem>(d->m_scopeStack.back())) d->m_currentClass = lastClass; else - d->m_currentClass.clear(); + d->m_currentClass.reset(); d->m_currentFunctionType = CodeModel::Normal; break; case CXCursor_EnumDecl: - if (!d->m_currentEnum.isNull()) + if (d->m_currentEnum) d->m_scopeStack.back()->addEnum(d->m_currentEnum); - d->m_currentEnum.clear(); + d->m_currentEnum.reset(); break; case CXCursor_FriendDecl: d->m_withinFriendDecl = false; break; case CXCursor_VarDecl: case CXCursor_FieldDecl: - d->m_currentField.clear(); + d->m_currentField.reset(); break; case CXCursor_Constructor: d->qualifyConstructor(cursor); - if (!d->m_currentFunction.isNull()) { + if (d->m_currentFunction) { d->m_currentFunction->_determineType(); - d->m_currentFunction.clear(); + d->m_currentFunction.reset(); } break; case CXCursor_Destructor: case CXCursor_CXXMethod: case CXCursor_FunctionDecl: case CXCursor_FunctionTemplate: - if (!d->m_currentFunction.isNull()) { + if (d->m_currentFunction) { d->m_currentFunction->_determineType(); - d->m_currentFunction.clear(); + d->m_currentFunction.reset(); } break; case CXCursor_ConversionFunction: - if (!d->m_currentFunction.isNull()) { + if (d->m_currentFunction) { d->m_currentFunction->setFunctionType(CodeModel::ConversionOperator); - d->m_currentFunction.clear(); + d->m_currentFunction.reset(); } break; case CXCursor_Namespace: d->popScope(); break; case CXCursor_ParmDecl: - d->m_currentArgument.clear(); + d->m_currentArgument.reset(); break; case CXCursor_TypeAliasTemplateDecl: d->m_currentTemplateTypeAlias.reset(); diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.h b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.h index 56b6347d5..b2ec6d304 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.h +++ b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.h @@ -14,12 +14,12 @@ class BuilderPrivate; class Builder : public BaseVisitor { public: - Q_DISABLE_COPY(Builder) + Q_DISABLE_COPY_MOVE(Builder) Builder(); ~Builder(); - void setSystemIncludes(const QStringList &systemIncludes); + void setForceProcessSystemIncludes(const QStringList &systemIncludes); bool visitLocation(const QString &fileName, LocationType locationType) const override; diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.cpp index 93618cf0f..3c002da9c 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.cpp +++ b/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.cpp @@ -7,8 +7,6 @@ #include <QtCore/QDebug> #include <QtCore/QString> -#include <string.h> - #ifndef QT_NO_DEBUG_STREAM #ifdef Q_OS_WIN @@ -19,7 +17,7 @@ const char pathSep = '/'; static const char *baseName(const char *fileName) { - const char *b = strrchr(fileName, pathSep); + const char *b = std::strrchr(fileName, pathSep); return b ? b + 1 : fileName; } @@ -49,59 +47,99 @@ QDebug operator<<(QDebug s, CX_CXXAccessSpecifier ac) return s; } -QDebug operator<<(QDebug s, const CXType &t) +struct formatCXTypeName +{ + explicit formatCXTypeName(const CXType &type) : m_type(type) {} + + const CXType &m_type; +}; + +QDebug operator<<(QDebug debug, const formatCXTypeName &ft) { - CXString typeSpelling = clang_getTypeSpelling(t); - s << typeSpelling; + CXString typeSpelling = clang_getTypeSpelling(ft.m_type); + debug << typeSpelling; clang_disposeString(typeSpelling); - return s; + return debug; } -QDebug operator<<(QDebug s, const CXCursor &cursor) +QDebug operator<<(QDebug debug, const CXType &type) { - QDebugStateSaver saver(s); - s.nospace(); - s.noquote(); + QDebugStateSaver saver(debug); + debug.nospace(); + debug.noquote(); + debug << "CXType("; + if (type.kind == CXType_Invalid) { + debug << "invalid)"; + return debug; + } + + debug << type.kind; + switch (type.kind) { + case CXType_Unexposed: + debug << " [unexposed]"; + break; + case CXType_Elaborated: + debug << " [elaborated]"; + break; + default: + break; + } + debug << ", " << formatCXTypeName(type) << ')'; + return debug; +} + +QDebug operator<<(QDebug debug, const CXCursor &cursor) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + debug.noquote(); const CXCursorKind kind = clang_getCursorKind(cursor); - s << kind; - if (kind >= CXCursor_FirstInvalid && kind <= CXCursor_LastInvalid) - return s; + debug << "CXCursor("; + if (kind >= CXCursor_FirstInvalid && kind <= CXCursor_LastInvalid) { + debug << "invalid)"; + return debug; + } + + const QString cursorSpelling = clang::getCursorSpelling(cursor); + debug << '"' << cursorSpelling << '"'; + CXString cursorDisplay = clang_getCursorDisplayName(cursor); + if (const char *dpy = clang_getCString(cursorDisplay)) { + const QString display = QString::fromUtf8(dpy); + if (display != cursorSpelling) + debug << ", display=\"" << dpy << '"'; + } + clang_disposeString(cursorDisplay); + + debug << ", kind=" << kind; + const CXType type = clang_getCursorType(cursor); switch (kind) { case CXCursor_CXXAccessSpecifier: - s << ' ' << clang_getCXXAccessSpecifier(cursor); + debug << ", " << clang_getCXXAccessSpecifier(cursor); break; case CXCursor_CXXBaseSpecifier: - s << ", inherits=\"" << clang::getCursorSpelling(clang_getTypeDeclaration(type)) << '"'; + debug << ", inherits=\"" << clang::getCursorSpelling(clang_getTypeDeclaration(type)) << '"'; break; case CXCursor_CXXMethod: case CXCursor_FunctionDecl: case CXCursor_ConversionFunction: - s << ", result type=\"" << clang_getCursorResultType(cursor) << '"'; + debug << ", result type=\"" + << formatCXTypeName(clang_getCursorResultType(cursor)) << '"'; break; case CXCursor_TypedefDecl: - s << ", underlyingType=\"" << clang_getTypedefDeclUnderlyingType(cursor) << '"'; + debug << ", underlyingType=\"" + << formatCXTypeName(clang_getTypedefDeclUnderlyingType(cursor)) << '"'; break; default: break; } - if (type.kind != CXType_Invalid) - s << ", type=\"" << type << '"'; + debug << ", type=\"" << formatCXTypeName(type) << '"'; if (clang_Cursor_hasAttrs(cursor)) - s << ", [attrs]"; + debug << ", [attrs]"; - const QString cursorSpelling = clang::getCursorSpelling(cursor); - if (!cursorSpelling.isEmpty()) - s << ", spelling=\"" << cursorSpelling << '"'; - CXString cursorDisplay = clang_getCursorDisplayName(cursor); - if (const char *dpy = clang_getCString(cursorDisplay)) { - const QString display = QString::fromUtf8(dpy); - if (display != cursorSpelling) - s << ", display=\"" << dpy << '"'; - } - clang_disposeString(cursorDisplay); - return s; + debug << ')'; + return debug; } QDebug operator<<(QDebug s, const CXSourceLocation &location) diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.h b/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.h index 3a1b91e1a..7aac8a575 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.h +++ b/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.h @@ -4,7 +4,7 @@ #ifndef CLANGDEBUGUTILS_H #define CLANGDEBUGUTILS_H -#include <QtCore/QtGlobal> +#include <QtCore/qtclasshelpermacros.h> #include <clang-c/Index.h> diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp index 9762b352f..6c0cf3ae2 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp +++ b/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp @@ -13,6 +13,8 @@ #include <QtCore/QScopedArrayPointer> #include <QtCore/QString> +using namespace Qt::StringLiterals; + namespace clang { QString SourceFileCache::getFileName(CXFile file) @@ -39,7 +41,7 @@ std::string_view SourceFileCache::getCodeSnippet(const CXCursor &cursor, if (range.first.file != range.second.file) { if (errorMessage) - *errorMessage = QStringLiteral("Range spans several files"); + *errorMessage = "Range spans several files"_L1; return std::string_view(empty, 0); } @@ -48,7 +50,7 @@ std::string_view SourceFileCache::getCodeSnippet(const CXCursor &cursor, const QString fileName = getFileName(range.first.file); if (fileName.isEmpty()) { if (errorMessage) - *errorMessage = QStringLiteral("Range has no file"); + *errorMessage = "Range has no file"_L1; return std::string_view(empty, 0); } QFile file(fileName); @@ -233,6 +235,7 @@ static QByteArray msgCreateTranslationUnit(const QByteArrayList &clangArgs, unsi static CXTranslationUnit createTranslationUnit(CXIndex index, const QByteArrayList &args, bool addCompilerSupportArguments, + LanguageLevel level, unsigned flags = 0) { // courtesy qdoc @@ -253,7 +256,7 @@ static CXTranslationUnit createTranslationUnit(CXIndex index, QByteArrayList clangArgs; if (addCompilerSupportArguments) { - clangArgs += emulatedCompilerOptions(); + clangArgs += emulatedCompilerOptions(level); clangArgs += defaultArgs; } clangArgs += detectVulkan(); @@ -278,7 +281,7 @@ static CXTranslationUnit createTranslationUnit(CXIndex index, */ bool parse(const QByteArrayList &clangArgs, bool addCompilerSupportArguments, - unsigned clangFlags, BaseVisitor &bv) + LanguageLevel level, unsigned clangFlags, BaseVisitor &bv) { CXIndex index = clang_createIndex(0 /* excludeDeclarationsFromPCH */, 1 /* displayDiagnostics */); @@ -289,7 +292,7 @@ bool parse(const QByteArrayList &clangArgs, bool addCompilerSupportArguments, CXTranslationUnit translationUnit = createTranslationUnit(index, clangArgs, addCompilerSupportArguments, - clangFlags); + level, clangFlags); if (!translationUnit) return false; diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangparser.h b/sources/shiboken6/ApiExtractor/clangparser/clangparser.h index 3abbece24..22e0a50cd 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangparser.h +++ b/sources/shiboken6/ApiExtractor/clangparser/clangparser.h @@ -8,11 +8,13 @@ #include <QtCore/QByteArrayList> #include <QtCore/QHash> -#include <QtCore/QPair> #include <QtCore/QString> #include <QtCore/QList> #include <string_view> +#include <utility> + +enum class LanguageLevel; namespace clang { @@ -40,7 +42,7 @@ enum class LocationType }; class BaseVisitor { - Q_DISABLE_COPY(BaseVisitor) + Q_DISABLE_COPY_MOVE(BaseVisitor) public: using Diagnostics = QList<Diagnostic>; @@ -79,7 +81,7 @@ private: bool parse(const QByteArrayList &clangArgs, bool addCompilerSupportArguments, - unsigned clangFlags, BaseVisitor &ctx); + LanguageLevel level, unsigned clangFlags, BaseVisitor &ctx); } // namespace clang diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangutils.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangutils.cpp index 6955e4ec2..1651e09ec 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangutils.cpp +++ b/sources/shiboken6/ApiExtractor/clangparser/clangutils.cpp @@ -8,38 +8,33 @@ #include <QtCore/QHashFunctions> #include <QtCore/QProcess> -bool operator==(const CXCursor &c1, const CXCursor &c2) +#include <string_view> + +bool operator==(const CXCursor &c1, const CXCursor &c2) noexcept { return c1.kind == c2.kind && c1.xdata == c2.xdata && std::equal(c1.data, c1.data + sizeof(c1.data) / sizeof(c1.data[0]), c2.data); } -size_t qHash(const CXCursor &c, size_t seed) +size_t qHash(const CXCursor &c, size_t seed) noexcept { - return qHash(c.kind) ^ qHash(c.xdata) ^ qHash(c.data[0]) - ^ qHash(c.data[1]) ^ qHash(c.data[2]) ^ seed; + return qHashMulti(seed, c.kind, c.xdata, c.data[0], c.data[1], c.data[2]); } -bool operator==(const CXType &t1, const CXType &t2) +bool operator==(const CXType &t1, const CXType &t2) noexcept { return t1.kind == t2.kind && t1.data[0] == t2.data[0] && t1.data[1] == t2.data[1]; } -size_t qHash(const CXType &ct, size_t seed) +size_t qHash(const CXType &ct, size_t seed) noexcept { - return size_t(ct.kind) ^ size_t(0xFFFFFFFF & quintptr(ct.data[0])) - ^ size_t(0xFFFFFFFF & quintptr(ct.data[1])) ^ seed; + return qHashMulti(seed, ct.kind, ct.data[0], ct.data[1]); } namespace clang { -bool SourceLocation::equals(const SourceLocation &rhs) const -{ - return file == rhs.file && offset == rhs.offset; -} - SourceLocation getExpansionLocation(const CXSourceLocation &location) { SourceLocation result; @@ -77,8 +72,8 @@ CXString getFileNameFromLocation(const CXSourceLocation &location) SourceRange getCursorRange(const CXCursor &cursor) { const CXSourceRange extent = clang_getCursorExtent(cursor); - return qMakePair(getExpansionLocation(clang_getRangeStart(extent)), - getExpansionLocation(clang_getRangeEnd(extent))); + return std::make_pair(getExpansionLocation(clang_getRangeStart(extent)), + getExpansionLocation(clang_getRangeEnd(extent))); } QString getCursorKindName(CXCursorKind cursorKind) @@ -105,6 +100,43 @@ QString getCursorDisplayName(const CXCursor &cursor) return result; } +static inline bool isBuiltinType(CXTypeKind kind) +{ + return kind >= CXType_FirstBuiltin && kind <= CXType_LastBuiltin; +} + +// Resolve elaborated types occurring with clang 16 +static CXType resolveElaboratedType(const CXType &type) +{ + if (!isBuiltinType(type.kind)) { + CXCursor decl = clang_getTypeDeclaration(type); + auto resolvedType = clang_getCursorType(decl); + if (resolvedType.kind != CXType_Invalid && resolvedType.kind != type.kind) + return resolvedType; + } + return type; +} + +// Resolve typedefs +static CXType resolveTypedef(const CXType &type) +{ + auto result = type; + while (result.kind == CXType_Typedef) { + auto decl = clang_getTypeDeclaration(result); + auto resolved = clang_getTypedefDeclUnderlyingType(decl); + if (resolved.kind == CXType_Invalid) + break; + result = resolved; + } + return result; +} + +// Fully resolve a type from elaborated & typedefs +CXType fullyResolveType(const CXType &type) +{ + return resolveTypedef(resolveElaboratedType(type)); +} + QString getTypeName(const CXType &type) { CXString typeSpelling = clang_getTypeSpelling(type); @@ -113,6 +145,23 @@ QString getTypeName(const CXType &type) return result; } +// Quick check for "::Type" +bool hasScopeResolution(const CXType &type) +{ + CXString typeSpelling = clang_getTypeSpelling(type); + std::string_view spelling = clang_getCString(typeSpelling); + const bool result = spelling.compare(0, 2, "::") == 0 + || spelling.find(" ::") != std::string::npos; + clang_disposeString(typeSpelling); + return result; +} + +// Resolve elaborated types occurring with clang 16 +QString getResolvedTypeName(const CXType &type) +{ + return getTypeName(resolveElaboratedType(type)); +} + Diagnostic::Diagnostic(const QString &m, const CXCursor &c, CXDiagnosticSeverity s) : message(m), source(Other), severity(s) { @@ -166,14 +215,14 @@ QList<Diagnostic> getDiagnostics(CXTranslationUnit tu) return result; } -QPair<qsizetype, qsizetype> +std::pair<qsizetype, qsizetype> parseTemplateArgumentList(const QString &l, const TemplateArgumentHandler &handler, qsizetype from) { const auto ltPos = l.indexOf(u'<', from); if (ltPos == - 1) - return qMakePair(-1, -1); + return std::make_pair(-1, -1); auto startPos = ltPos + 1; int level = 1; for (qsizetype p = startPos, end = l.size(); p < end; ) { @@ -185,7 +234,7 @@ QPair<qsizetype, qsizetype> ++p; if (c == '>') { if (--level == 0) - return qMakePair(ltPos, p); + return std::make_pair(ltPos, p); // Skip over next ',': "a<b<c,d>,e>" for (; p < end && (l.at(p).isSpace() || l.at(p) == u','); ++p) {} } @@ -201,7 +250,7 @@ QPair<qsizetype, qsizetype> break; } } - return qMakePair(-1, -1); + return std::make_pair(-1, -1); } CXDiagnosticSeverity maxSeverity(const QList<Diagnostic> &ds) diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangutils.h b/sources/shiboken6/ApiExtractor/clangparser/clangutils.h index 9ad0cbc57..fbbf95f1b 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangutils.h +++ b/sources/shiboken6/ApiExtractor/clangparser/clangutils.h @@ -5,20 +5,21 @@ #define CLANGUTILS_H #include <clang-c/Index.h> -#include <QtCore/QPair> #include <QtCore/QString> #include <QtCore/QStringList> +#include <QtCore/QtCompare> #include <QtCore/QList> #include <functional> +#include <utility> QT_FORWARD_DECLARE_CLASS(QDebug) -bool operator==(const CXCursor &c1, const CXCursor &c2); -size_t qHash(const CXCursor &c, size_t seed = 0); +bool operator==(const CXCursor &c1, const CXCursor &c2) noexcept; +size_t qHash(const CXCursor &c, size_t seed = 0) noexcept; -bool operator==(const CXType &t1, const CXType &t2); -size_t qHash(const CXType &ct, size_t seed); +bool operator==(const CXType &t1, const CXType &t2) noexcept; +size_t qHash(const CXType &ct, size_t seed = 0) noexcept; namespace clang { @@ -26,6 +27,9 @@ QString getCursorKindName(CXCursorKind cursorKind); QString getCursorSpelling(const CXCursor &cursor); QString getCursorDisplayName(const CXCursor &cursor); QString getTypeName(const CXType &type); +bool hasScopeResolution(const CXType &type); +CXType fullyResolveType(const CXType &type); +QString getResolvedTypeName(const CXType &type); inline QString getCursorTypeName(const CXCursor &cursor) { return getTypeName(clang_getCursorType(cursor)); } inline QString getCursorResultTypeName(const CXCursor &cursor) @@ -46,17 +50,18 @@ struct SourceLocation unsigned line = 0; unsigned column = 0; unsigned offset = 0; -}; - -inline bool operator==(const SourceLocation &l1, const SourceLocation &l2) -{ return l1.equals(l2); } -inline bool operator!=(const SourceLocation &l1, const SourceLocation &l2) -{ return !l1.equals(l2); } + friend constexpr bool comparesEqual(const SourceLocation &lhs, + const SourceLocation &rhs) noexcept + { + return lhs.file == rhs.file && lhs.offset == rhs.offset; + } + Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(SourceLocation) +}; SourceLocation getExpansionLocation(const CXSourceLocation &location); -using SourceRange =QPair<SourceLocation, SourceLocation>; +using SourceRange = std::pair<SourceLocation, SourceLocation>; SourceLocation getCursorLocation(const CXCursor &cursor); CXString getFileNameFromLocation(const CXSourceLocation &location); @@ -89,7 +94,7 @@ CXDiagnosticSeverity maxSeverity(const QList<Diagnostic> &ds); // with each match (level and string). Return begin and end of the list. using TemplateArgumentHandler = std::function<void (int, QStringView)>; -QPair<qsizetype, qsizetype> +std::pair<qsizetype, qsizetype> parseTemplateArgumentList(const QString &l, const TemplateArgumentHandler &handler, qsizetype from = 0); diff --git a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp index 4145c8dec..20224020b 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp +++ b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp @@ -3,6 +3,7 @@ #include "compilersupport.h" #include "header_paths.h" +#include "clangutils.h" #include <reporthandler.h> @@ -19,7 +20,6 @@ #include <clang-c/Index.h> -#include <string.h> #include <algorithm> #include <iterator> @@ -94,13 +94,19 @@ bool setPlatform(const QString &name) return result; } +// 3/2024: Use a recent MSVC2022 for libclang 18.X +static QByteArray msvcCompatVersion() +{ + return libClangVersion() >= QVersionNumber(0, 64) ? "19.39"_ba : "19.26"_ba; +} + static bool runProcess(const QString &program, const QStringList &arguments, QByteArray *stdOutIn = nullptr, QByteArray *stdErrIn = nullptr) { QProcess process; process.start(program, arguments, QProcess::ReadWrite); if (!process.waitForStarted()) { - qWarning().noquote().nospace() << "Unable to start " + qCWarning(lcShiboken).noquote().nospace() << "Unable to start " << process.program() << ": " << process.errorString(); return false; } @@ -113,18 +119,18 @@ static bool runProcess(const QString &program, const QStringList &arguments, *stdOutIn = process.readAllStandardOutput(); if (!finished) { - qWarning().noquote().nospace() << process.program() << " timed out: " << stdErr; + qCWarning(lcShiboken).noquote().nospace() << process.program() << " timed out: " << stdErr; process.kill(); return false; } if (process.exitStatus() != QProcess::NormalExit) { - qWarning().noquote().nospace() << process.program() << " crashed: " << stdErr; + qCWarning(lcShiboken).noquote().nospace() << process.program() << " crashed: " << stdErr; return false; } if (process.exitCode() != 0) { - qWarning().noquote().nospace() << process.program() << " exited " + qCWarning(lcShiboken).noquote().nospace() << process.program() << " exited " << process.exitCode() << ": " << stdErr; return false; } @@ -179,6 +185,13 @@ static HeaderPaths gppInternalIncludePaths(const QString &compiler) return result; const QByteArrayList stdErrLines = stdErr.split('\n'); bool isIncludeDir = false; + + if (ReportHandler::isDebug(ReportHandler::MediumDebug)) + qCInfo(lcShiboken()).noquote().nospace() + << "gppInternalIncludePaths:\n compiler: " << compiler + << "\n stdOut: " << stdOut + << "\n stdErr: " << stdErr; + for (const QByteArray &line : stdErrLines) { if (isIncludeDir) { if (line.startsWith(QByteArrayLiteral("End of search list"))) { @@ -240,6 +253,23 @@ static bool needsClangBuiltinIncludes() return platform() != Platform::macOS; } +static QString queryLlvmConfigDir(const QString &arg) +{ + static const QString llvmConfig = QStandardPaths::findExecutable(u"llvm-config"_s); + if (llvmConfig.isEmpty()) + return {}; + QByteArray stdOut; + if (!runProcess(llvmConfig, QStringList{arg}, &stdOut)) + return {}; + const QString path = QFile::decodeName(stdOut.trimmed()); + if (!QFileInfo::exists(path)) { + qCWarning(lcShiboken, R"(%s: "%s" as returned by llvm-config "%s" does not exist.)", + __FUNCTION__, qPrintable(QDir::toNativeSeparators(path)), qPrintable(arg)); + return {}; + } + return path; +} + static QString findClangLibDir() { for (const char *envVar : {"LLVM_INSTALL_DIR", "CLANG_INSTALL_DIR"}) { @@ -247,21 +277,11 @@ static QString findClangLibDir() const QString path = QFile::decodeName(qgetenv(envVar)) + u"/lib"_s; if (QFileInfo::exists(path)) return path; - qWarning("%s: %s as pointed to by %s does not exist.", __FUNCTION__, qPrintable(path), envVar); - } - } - const QString llvmConfig = - QStandardPaths::findExecutable(u"llvm-config"_s); - if (!llvmConfig.isEmpty()) { - QByteArray stdOut; - if (runProcess(llvmConfig, QStringList{u"--libdir"_s}, &stdOut)) { - const QString path = QFile::decodeName(stdOut.trimmed()); - if (QFileInfo::exists(path)) - return path; - qWarning("%s: %s as returned by llvm-config does not exist.", __FUNCTION__, qPrintable(path)); + qCWarning(lcShiboken, "%s: %s as pointed to by %s does not exist.", + __FUNCTION__, qPrintable(path), envVar); } } - return QString(); + return queryLlvmConfigDir(u"--libdir"_s); } static QString findClangBuiltInIncludesDir() @@ -270,13 +290,23 @@ static QString findClangBuiltInIncludesDir() const QString clangPathLibDir = findClangLibDir(); if (!clangPathLibDir.isEmpty()) { QString candidate; + QString clangDirName = clangPathLibDir + u"/clang"_s; + // PYSIDE-2769: llvm-config --libdir may report /usr/lib64 on manylinux_2_28_x86_64 + // whereas the includes are under /usr/lib/clang/../include. + if (!QFileInfo::exists(clangDirName) && clangPathLibDir.endsWith("64"_L1)) { + const QString fallback = clangPathLibDir.sliced(0, clangPathLibDir.size() - 2); + clangDirName = fallback + u"/clang"_s; + qCWarning(lcShiboken, "%s: Falling back from %s to %s.", + __FUNCTION__, qPrintable(clangPathLibDir), qPrintable(fallback)); + } + QVersionNumber lastVersionNumber(1, 0, 0); - const QString clangDirName = clangPathLibDir + u"/clang"_s; QDir clangDir(clangDirName); const QFileInfoList versionDirs = clangDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); if (versionDirs.isEmpty()) - qWarning("%s: No subdirectories found in %s.", __FUNCTION__, qPrintable(clangDirName)); + qCWarning(lcShiboken, "%s: No subdirectories found in %s.", + __FUNCTION__, qPrintable(clangDirName)); for (const QFileInfo &fi : versionDirs) { const QString fileName = fi.fileName(); if (fileName.at(0).isDigit()) { @@ -288,22 +318,44 @@ static QString findClangBuiltInIncludesDir() } } if (!candidate.isEmpty()) - return candidate + QStringLiteral("/include"); + return candidate + "/include"_L1; } - return QString(); + return queryLlvmConfigDir(u"--includedir"_s); } +QString compilerFromCMake() +{ +#ifdef CMAKE_CXX_COMPILER + return QString::fromLocal8Bit(CMAKE_CXX_COMPILER); +#else + return {}; +#endif +} + +// Return a compiler suitable for determining the internal include paths static QString compilerFromCMake(const QString &defaultCompiler) { if (!compilerPath().isEmpty()) return compilerPath(); -// Added !defined(Q_OS_DARWIN) due to PYSIDE-1032 - QString result = defaultCompiler; -#ifdef CMAKE_CXX_COMPILER - if (platform() != Platform::macOS) - result = QString::fromLocal8Bit(CMAKE_CXX_COMPILER); -#endif - return result; + // Exclude macOS since cmakeCompiler returns the full path instead of the + // /usr/bin/clang shim, which results in the default SDK sysroot path + // missing (PYSIDE-1032) + if (platform() == Platform::macOS) + return defaultCompiler; + QString cmakeCompiler = compilerFromCMake(); + if (cmakeCompiler.isEmpty()) + return defaultCompiler; + QFileInfo fi(cmakeCompiler); + // Should be absolute by default, but a user may specify -DCMAKE_CXX_COMPILER=cl.exe + if (fi.isRelative()) + return cmakeCompiler; + if (fi.exists()) + return fi.absoluteFilePath(); + // The compiler may not exist in case something like icecream or + // a non-standard-path was used on the build machine. Check + // the executable. + cmakeCompiler = QStandardPaths::findExecutable(fi.fileName()); + return cmakeCompiler.isEmpty() ? defaultCompiler : cmakeCompiler; } static void appendClangBuiltinIncludes(HeaderPaths *p) @@ -315,7 +367,8 @@ static void appendClangBuiltinIncludes(HeaderPaths *p) "(neither by checking the environment variables LLVM_INSTALL_DIR, CLANG_INSTALL_DIR " " nor running llvm-config). This may lead to parse errors."); } else { - qCInfo(lcShiboken, "CLANG builtins includes directory: %s", + qCInfo(lcShiboken, "CLANG v%d.%d, builtins includes directory: %s", + CINDEX_VERSION_MAJOR, CINDEX_VERSION_MINOR, qPrintable(clangBuiltinIncludesDir)); p->append(HeaderPath{QFile::encodeName(clangBuiltinIncludesDir), HeaderType::System}); @@ -323,15 +376,17 @@ static void appendClangBuiltinIncludes(HeaderPaths *p) } // Returns clang options needed for emulating the host compiler -QByteArrayList emulatedCompilerOptions() +QByteArrayList emulatedCompilerOptions(LanguageLevel level) { QByteArrayList result; HeaderPaths headerPaths; switch (compiler()) { case Compiler::Msvc: - result.append(QByteArrayLiteral("-fms-compatibility-version=19.26.28806")); - result.append(QByteArrayLiteral("-fdelayed-template-parsing")); + result.append("-fms-compatibility-version="_ba + msvcCompatVersion()); + if (level < LanguageLevel::Cpp20) + result.append("-fdelayed-template-parsing"_ba); result.append(QByteArrayLiteral("-Wno-microsoft-enum-value")); + result.append("/Zc:__cplusplus"_ba); // Fix yvals_core.h: STL1000: Unexpected compiler version, expected Clang 7 or newer (MSVC2017 update) result.append(QByteArrayLiteral("-D_ALLOW_COMPILER_AND_STL_VERSION_MISMATCH")); if (needsClangBuiltinIncludes()) @@ -347,7 +402,7 @@ QByteArrayList emulatedCompilerOptions() // Append the c++ include paths since Clang is unable to find // <type_traits> etc (g++ 11.3). - const HeaderPaths gppPaths = gppInternalIncludePaths(compilerFromCMake(u"g++"_qs)); + const HeaderPaths gppPaths = gppInternalIncludePaths(compilerFromCMake(u"g++"_s)); for (const HeaderPath &h : gppPaths) { if (h.path.contains("c++") || h.path.contains("sysroot")) headerPaths.append(h); diff --git a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h index 18e87c495..f1d63b7c3 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h +++ b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h @@ -33,7 +33,7 @@ enum class Platform { namespace clang { QVersionNumber libClangVersion(); -QByteArrayList emulatedCompilerOptions(); +QByteArrayList emulatedCompilerOptions(LanguageLevel level); LanguageLevel emulatedCompilerLanguageLevel(); const char *languageLevelOption(LanguageLevel l); @@ -44,6 +44,8 @@ QByteArrayList detectVulkan(); Compiler compiler(); bool setCompiler(const QString &name); +QString compilerFromCMake(); + const QString &compilerPath(); void setCompilerPath(const QString &name); diff --git a/sources/shiboken6/ApiExtractor/classdocumentation.cpp b/sources/shiboken6/ApiExtractor/classdocumentation.cpp index 3d4abb87d..637e4a422 100644 --- a/sources/shiboken6/ApiExtractor/classdocumentation.cpp +++ b/sources/shiboken6/ApiExtractor/classdocumentation.cpp @@ -3,6 +3,7 @@ #include "classdocumentation.h" #include "messages.h" +#include "debughelpers_p.h" #include <QtCore/QDebug> #include <QtCore/QBuffer> @@ -82,44 +83,51 @@ qsizetype ClassDocumentation::indexOfProperty(const QString &name) const return -1; } -enum class WebXmlTag +enum class WebXmlCodeTag { - Class, Description, Enum, Function, Parameter, Property, Typedef, Other + Class, Description, Enum, Function, Header, Parameter, Property, Typedef, Other }; -static WebXmlTag tag(QStringView name) +static WebXmlCodeTag tag(QStringView name) { if (name == u"class" || name == u"namespace") - return WebXmlTag::Class; + return WebXmlCodeTag::Class; if (name == u"enum") - return WebXmlTag::Enum; + return WebXmlCodeTag::Enum; if (name == u"function") - return WebXmlTag::Function; + return WebXmlCodeTag::Function; if (name == u"description") - return WebXmlTag::Description; + return WebXmlCodeTag::Description; + if (name == u"header") + return WebXmlCodeTag::Header; if (name == u"parameter") - return WebXmlTag::Parameter; + return WebXmlCodeTag::Parameter; if (name == u"property") - return WebXmlTag::Property; + return WebXmlCodeTag::Property; if (name == u"typedef") - return WebXmlTag::Typedef; - return WebXmlTag::Other; + return WebXmlCodeTag::Typedef; + return WebXmlCodeTag::Other; } -static void parseWebXmlElement(WebXmlTag tag, const QXmlStreamAttributes &attributes, +static void parseWebXmlElement(WebXmlCodeTag tag, const QXmlStreamAttributes &attributes, ClassDocumentation *cd) { switch (tag) { - case WebXmlTag::Class: + case WebXmlCodeTag::Class: cd->name = attributes.value(u"name"_s).toString(); + cd->type = ClassDocumentation::Class; break; - case WebXmlTag::Enum: { + case WebXmlCodeTag::Header: + cd->name = attributes.value(u"name"_s).toString(); + cd->type = ClassDocumentation::Header; + break; + case WebXmlCodeTag::Enum: { EnumDocumentation ed; ed.name = attributes.value(u"name"_s).toString(); cd->enums.append(ed); } break; - case WebXmlTag::Function: { + case WebXmlCodeTag::Function: { FunctionDocumentation fd; fd.name = attributes.value(u"name"_s).toString(); fd.signature = attributes.value(u"signature"_s).toString(); @@ -128,11 +136,11 @@ static void parseWebXmlElement(WebXmlTag tag, const QXmlStreamAttributes &attrib cd->functions.append(fd); } break; - case WebXmlTag::Parameter: + case WebXmlCodeTag::Parameter: Q_ASSERT(!cd->functions.isEmpty()); cd->functions.last().parameters.append(attributes.value(u"type"_s).toString()); break; - case WebXmlTag::Property: { + case WebXmlCodeTag::Property: { PropertyDocumentation pd; pd.name = attributes.value(u"name"_s).toString(); pd.brief = attributes.value(u"brief"_s).toString(); @@ -184,17 +192,17 @@ static QString msgXmlError(const QString &fileName, const QXmlStreamReader &read return result; } -ClassDocumentation parseWebXml(const QString &fileName, QString *errorMessage) +std::optional<ClassDocumentation> parseWebXml(const QString &fileName, QString *errorMessage) { ClassDocumentation result; QFile file(fileName); if (!file.open(QIODevice::Text | QIODevice::ReadOnly)) { *errorMessage = msgCannotOpenForReading(file); - return result; + return std::nullopt; } - WebXmlTag lastTag = WebXmlTag::Other; + WebXmlCodeTag lastTag = WebXmlCodeTag::Other; QXmlStreamReader reader(&file); while (!reader.atEnd()) { switch (reader.readNext()) { @@ -202,26 +210,27 @@ ClassDocumentation parseWebXml(const QString &fileName, QString *errorMessage) const auto currentTag = tag(reader.name()); parseWebXmlElement(currentTag, reader.attributes(), &result); switch (currentTag) { // Store relevant tags in lastTag - case WebXmlTag::Class: - case WebXmlTag::Function: - case WebXmlTag::Enum: - case WebXmlTag::Property: - case WebXmlTag::Typedef: + case WebXmlCodeTag::Class: + case WebXmlCodeTag::Function: + case WebXmlCodeTag::Enum: + case WebXmlCodeTag::Header: + case WebXmlCodeTag::Property: + case WebXmlCodeTag::Typedef: lastTag = currentTag; break; - case WebXmlTag::Description: { // Append the description to the element + case WebXmlCodeTag::Description: { // Append the description to the element QString *target = nullptr; switch (lastTag) { - case WebXmlTag::Class: + case WebXmlCodeTag::Class: target = &result.description; break; - case WebXmlTag::Function: + case WebXmlCodeTag::Function: target = &result.functions.last().description; break; - case WebXmlTag::Enum: + case WebXmlCodeTag::Enum: target = &result.enums.last().description; break; - case WebXmlTag::Property: + case WebXmlCodeTag::Property: target = &result.properties.last().description; default: break; @@ -241,7 +250,7 @@ ClassDocumentation parseWebXml(const QString &fileName, QString *errorMessage) if (reader.error() != QXmlStreamReader::NoError) { *errorMessage= msgXmlError(fileName, reader); - return {}; + return std::nullopt; } sortDocumentation(&result); @@ -277,21 +286,6 @@ QString webXmlModuleDescription(const QString &fileName, QString *errorMessage) return result; } -// Debug helpers -template <class T> -static void formatList(QDebug &debug, const char *title, const QList<T> &l) -{ - if (const qsizetype size = l.size()) { - debug << title << '[' << size << "]=("; - for (qsizetype i = 0; i < size; ++i) { - if (i) - debug << ", "; - debug << l.at(i); - } - debug << ')'; - } -} - static void formatDescription(QDebug &debug, const QString &desc) { debug << "description="; @@ -351,7 +345,7 @@ QDebug operator<<(QDebug debug, const FunctionDocumentation &f) debug << ", returns " << f.returnType; if (f.constant) debug << ", const"; - formatList(debug, ", parameters", f.parameters); + formatList(debug, ", parameters", f.parameters, ", "); debug << ", signature=\"" << f.signature << "\", "; formatDescription(debug, f.description); } @@ -377,16 +371,11 @@ QDebug operator<<(QDebug debug, const ClassDocumentation &c) QDebugStateSaver saver(debug); debug.noquote(); debug.nospace(); - debug << "Class("; - if (c) { - debug << c.name << ", "; - formatDescription(debug, c.description); - formatList(debug, ", enums", c.enums); - formatList(debug, ", properties", c.properties); - formatList(debug, ", functions", c.functions); - } else { - debug << "invalid"; - } + debug << "Class(" << c.name << ", "; + formatDescription(debug, c.description); + formatList(debug, ", enums", c.enums); + formatList(debug, ", properties", c.properties); + formatList(debug, ", functions", c.functions); debug << ')'; return debug; } diff --git a/sources/shiboken6/ApiExtractor/classdocumentation.h b/sources/shiboken6/ApiExtractor/classdocumentation.h index ef66912f8..d47101389 100644 --- a/sources/shiboken6/ApiExtractor/classdocumentation.h +++ b/sources/shiboken6/ApiExtractor/classdocumentation.h @@ -6,6 +6,8 @@ #include <QtCore/QStringList> +#include <optional> + QT_FORWARD_DECLARE_CLASS(QDebug) /// An enumeration in a WebXML/doxygen document @@ -41,9 +43,14 @@ struct FunctionDocumentation : public FunctionDocumentationQuery using FunctionDocumentationList = QList<FunctionDocumentation>; -/// A class/namespace in a WebXML/doxygen document +/// A WebXML/doxygen document struct ClassDocumentation { + enum Type { + Class, // <class>, class/namespace + Header // <header>, grouped global functions/enums + }; + qsizetype indexOfEnum(const QString &name) const; FunctionDocumentationList findFunctionCandidates(const QString &name, bool constant) const; @@ -51,18 +58,17 @@ struct ClassDocumentation const FunctionDocumentationQuery &q); qsizetype indexOfProperty(const QString &name) const; + Type type = Type::Class; QString name; QString description; QList<EnumDocumentation> enums; QList<PropertyDocumentation> properties; FunctionDocumentationList functions; - - operator bool() const { return !name.isEmpty(); } }; /// Parse a WebXML class/namespace document -ClassDocumentation parseWebXml(const QString &fileName, QString *errorMessage); +std::optional<ClassDocumentation> parseWebXml(const QString &fileName, QString *errorMessage); /// Extract the module description from a WebXML module document QString webXmlModuleDescription(const QString &fileName, QString *errorMessage); diff --git a/sources/shiboken6/ApiExtractor/cmake_uninstall.cmake b/sources/shiboken6/ApiExtractor/cmake_uninstall.cmake index df95fb9d8..4031b4e1a 100644 --- a/sources/shiboken6/ApiExtractor/cmake_uninstall.cmake +++ b/sources/shiboken6/ApiExtractor/cmake_uninstall.cmake @@ -1,3 +1,6 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") diff --git a/sources/shiboken6/ApiExtractor/codesnip.cpp b/sources/shiboken6/ApiExtractor/codesnip.cpp index 81977ceb1..e2cd5eb35 100644 --- a/sources/shiboken6/ApiExtractor/codesnip.cpp +++ b/sources/shiboken6/ApiExtractor/codesnip.cpp @@ -14,7 +14,7 @@ using namespace Qt::StringLiterals; QString TemplateInstance::expandCode() const { const auto templateEntry = TypeDatabase::instance()->findTemplate(m_name); - if (templateEntry.isNull()) { + if (!templateEntry) { const QString m = u"<insert-template> referring to non-existing template '"_s + m_name + u"'."_s; throw Exception(m); @@ -63,7 +63,7 @@ void CodeSnipAbstract::purgeEmptyFragments() QRegularExpression CodeSnipAbstract::placeHolderRegex(int index) { - return QRegularExpression(u'%' + QString::number(index) + QStringLiteral("\\b")); + return QRegularExpression(u'%' + QString::number(index) + "\\b"_L1); } void purgeEmptyCodeSnips(QList<CodeSnip> *list) diff --git a/sources/shiboken6/ApiExtractor/codesnip.h b/sources/shiboken6/ApiExtractor/codesnip.h index 7a1ab0624..86834a1db 100644 --- a/sources/shiboken6/ApiExtractor/codesnip.h +++ b/sources/shiboken6/ApiExtractor/codesnip.h @@ -9,9 +9,10 @@ #include <QtCore/QList> #include <QtCore/QHash> -#include <QtCore/QSharedPointer> #include <QtCore/QString> +#include <memory> + class TemplateInstance { public: @@ -34,7 +35,7 @@ private: QHash<QString, QString> replaceRules; }; -using TemplateInstancePtr = QSharedPointer<TemplateInstance>; +using TemplateInstancePtr = std::shared_ptr<TemplateInstance>; class CodeSnipFragment { @@ -43,7 +44,7 @@ public: explicit CodeSnipFragment(const QString &code) : m_code(code) {} explicit CodeSnipFragment(const TemplateInstancePtr &instance) : m_instance(instance) {} - bool isEmpty() const { return m_code.isEmpty() && m_instance.isNull(); } + bool isEmpty() const { return m_code.isEmpty() && !m_instance; } QString code() const; @@ -51,7 +52,7 @@ public: private: QString m_code; - QSharedPointer<TemplateInstance> m_instance; + std::shared_ptr<TemplateInstance> m_instance; }; class CodeSnipAbstract : public CodeSnipHelpers diff --git a/sources/shiboken6/ApiExtractor/complextypeentry.h b/sources/shiboken6/ApiExtractor/complextypeentry.h index bdbd7fa22..5b884f2cc 100644 --- a/sources/shiboken6/ApiExtractor/complextypeentry.h +++ b/sources/shiboken6/ApiExtractor/complextypeentry.h @@ -4,7 +4,7 @@ #ifndef COMPLEXTYPEENTRY_H #define COMPLEXTYPEENTRY_H -#include "typesystem.h" +#include "configurabletypeentry.h" #include "typesystem_enums.h" #include "modifications_typedefs.h" #include "pymethoddefentry.h" @@ -33,7 +33,7 @@ struct TypeSystemProperty bool generateGetSetDef = false; }; -class ComplexTypeEntry : public TypeEntry +class ComplexTypeEntry : public ConfigurableTypeEntry { public: enum TypeFlag { @@ -42,7 +42,9 @@ public: ForceAbstract = 0x8, // Indicates that the instances are used to create hierarchies // like widgets; parent ownership heuristics are enabled for them. - ParentManagement = 0x10 + ParentManagement = 0x10, + DisableQtMetaObjectFunctions = 0x20, + Typedef = 0x40 // Result of a <typedef-type> }; Q_DECLARE_FLAGS(TypeFlags, TypeFlag) diff --git a/sources/shiboken6/ApiExtractor/conditionalstreamreader.cpp b/sources/shiboken6/ApiExtractor/conditionalstreamreader.cpp index c02a95777..b6eda651c 100644 --- a/sources/shiboken6/ApiExtractor/conditionalstreamreader.cpp +++ b/sources/shiboken6/ApiExtractor/conditionalstreamreader.cpp @@ -165,15 +165,15 @@ QStringList ConditionalStreamReader::platformConditions() { QStringList result; #if defined (Q_OS_UNIX) - result << QStringLiteral("unix"); + result << "unix"_L1; #endif #if defined (Q_OS_LINUX) - result << QStringLiteral("linux"); + result << "linux"_L1; #elif defined (Q_OS_MACOS) - result << QStringLiteral("darwin"); + result << "darwin"_L1; #elif defined (Q_OS_WINDOWS) - result << QStringLiteral("windows"); + result << "windows"_L1; #endif return result; } diff --git a/sources/shiboken6/ApiExtractor/conditionalstreamreader.h b/sources/shiboken6/ApiExtractor/conditionalstreamreader.h index a273fd0ca..730697525 100644 --- a/sources/shiboken6/ApiExtractor/conditionalstreamreader.h +++ b/sources/shiboken6/ApiExtractor/conditionalstreamreader.h @@ -26,6 +26,8 @@ class ProxyEntityResolver; class ConditionalStreamReader { public: + Q_DISABLE_COPY_MOVE(ConditionalStreamReader) + using TokenType = QXmlStreamReader::TokenType; explicit ConditionalStreamReader(QIODevice *iod); explicit ConditionalStreamReader(const QString &s); diff --git a/sources/shiboken6/ApiExtractor/configurabletypeentry.h b/sources/shiboken6/ApiExtractor/configurabletypeentry.h new file mode 100644 index 000000000..59522e16c --- /dev/null +++ b/sources/shiboken6/ApiExtractor/configurabletypeentry.h @@ -0,0 +1,28 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef CONFIGURABLETYPEENTRY_H +#define CONFIGURABLETYPEENTRY_H + +#include "typesystem.h" + +class ConfigurableTypeEntryPrivate; + +class ConfigurableTypeEntry : public TypeEntry +{ +public: + explicit ConfigurableTypeEntry(const QString &entryName, Type t, + const QVersionNumber &vr, + const TypeEntryCPtr &parent); + + TypeEntry *clone() const override; + + QString configCondition() const; + void setConfigCondition(const QString &c); + bool hasConfigCondition() const; + +protected: + explicit ConfigurableTypeEntry(ConfigurableTypeEntryPrivate *d); +}; + +#endif // CONFIGURABLETYPEENTRY_H diff --git a/sources/shiboken6/ApiExtractor/containertypeentry.h b/sources/shiboken6/ApiExtractor/containertypeentry.h index 8acf038fd..b2003816b 100644 --- a/sources/shiboken6/ApiExtractor/containertypeentry.h +++ b/sources/shiboken6/ApiExtractor/containertypeentry.h @@ -9,15 +9,19 @@ class ContainerTypeEntryPrivate; +struct OpaqueContainer // Generate an opaque container for an instantiation under name +{ + QStringList instantiations; + QString name; + + QString templateParameters() const; +}; + +using OpaqueContainers = QList<OpaqueContainer>; + class ContainerTypeEntry : public ComplexTypeEntry { public: - struct OpaqueContainer // Generate an opaque container for an instantiation under name - { - QString instantiation; - QString name; - }; - using OpaqueContainers = QList<OpaqueContainer>; enum ContainerKind { ListContainer, @@ -25,6 +29,7 @@ public: MapContainer, MultiMapContainer, PairContainer, + SpanContainer, // Fixed size }; explicit ContainerTypeEntry(const QString &entryName, ContainerKind containerKind, @@ -32,10 +37,13 @@ public: ContainerKind containerKind() const; + /// Number of template parameters (except allocators) + qsizetype templateParameterCount() const; + const OpaqueContainers &opaqueContainers() const; - void addOpaqueContainer(OpaqueContainer r); - bool generateOpaqueContainer(const QString &instantiation) const; - QString opaqueContainerName(const QString &instantiation) const; + void appendOpaqueContainers(const OpaqueContainers &l); + bool generateOpaqueContainer(const QStringList &instantiations) const; + QString opaqueContainerName(const QStringList &instantiations) const; bool hasCustomConversion() const; void setCustomConversion(const CustomConversionPtr &customConversion); @@ -50,4 +58,6 @@ protected: explicit ContainerTypeEntry(ContainerTypeEntryPrivate *d); }; +QDebug operator<<(QDebug d, const OpaqueContainer &oc); + #endif // CONTAINERTYPEENTRY_H diff --git a/sources/shiboken6/ApiExtractor/customconversion.cpp b/sources/shiboken6/ApiExtractor/customconversion.cpp index 4632e4e76..4cfd1b974 100644 --- a/sources/shiboken6/ApiExtractor/customconversion.cpp +++ b/sources/shiboken6/ApiExtractor/customconversion.cpp @@ -99,7 +99,7 @@ QString TargetToNativeConversion::sourceTypeCheck() const return m_sourceTypeCheck; if (m_sourceType != nullptr && m_sourceType->isCustom()) { - const auto cte = qSharedPointerCast<const CustomTypeEntry>(m_sourceType); + const auto cte = std::static_pointer_cast<const CustomTypeEntry>(m_sourceType); if (cte->hasCheckFunction()) { QString result = cte->checkFunction(); if (result != u"true") // For PyObject, which is always true @@ -134,11 +134,11 @@ void TargetToNativeConversion::formatDebug(QDebug &debug) const CustomConversionPtr CustomConversion::getCustomConversion(const TypeEntryCPtr &type) { if (type->isPrimitive()) - return qSharedPointerCast<const PrimitiveTypeEntry>(type)->customConversion(); + return std::static_pointer_cast<const PrimitiveTypeEntry>(type)->customConversion(); if (type->isContainer()) - return qSharedPointerCast<const ContainerTypeEntry>(type)->customConversion(); + return std::static_pointer_cast<const ContainerTypeEntry>(type)->customConversion(); if (type->isValue()) - return qSharedPointerCast<const ValueTypeEntry>(type)->customConversion(); + return std::static_pointer_cast<const ValueTypeEntry>(type)->customConversion(); return {}; } @@ -188,7 +188,7 @@ QDebug operator<<(QDebug debug, const CustomConversionPtr &cptr) debug.noquote(); debug.nospace(); debug << "CustomConversionPtr"; - if (auto *c = cptr.data()) { + if (auto *c = cptr.get()) { c->formatDebug(debug); } else { debug << "(0)"; diff --git a/sources/shiboken6/ApiExtractor/customconversion_typedefs.h b/sources/shiboken6/ApiExtractor/customconversion_typedefs.h index a928378b7..6528f7d7b 100644 --- a/sources/shiboken6/ApiExtractor/customconversion_typedefs.h +++ b/sources/shiboken6/ApiExtractor/customconversion_typedefs.h @@ -5,9 +5,10 @@ #define CUSTOMCONVERSION_TYPEDEFS_H #include <QtCore/QList> -#include <QtCore/QSharedPointer> + +#include <memory> class CustomConversion; -using CustomConversionPtr = QSharedPointer<CustomConversion>; +using CustomConversionPtr = std::shared_ptr<CustomConversion>; #endif // CUSTOMCONVERSION_TYPEDEFS_H diff --git a/sources/shiboken6/ApiExtractor/debughelpers_p.h b/sources/shiboken6/ApiExtractor/debughelpers_p.h new file mode 100644 index 000000000..81ebbb3b9 --- /dev/null +++ b/sources/shiboken6/ApiExtractor/debughelpers_p.h @@ -0,0 +1,56 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef DEBUGHELPERS_P_H +#define DEBUGHELPERS_P_H + +#include <QtCore/QDebug> +#include <memory> + +template <class T> +inline QDebug operator<<(QDebug debug, const std::shared_ptr<T> &ptr) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + debug << "std::shared_ptr(" << ptr.get() << ")"; + return debug; +} + +template <class It> +inline void formatSequence(QDebug &d, It i1, It i2, + const char *separator=", ") +{ + for (It i = i1; i != i2; ++i) { + if (i != i1) + d << separator; + d << *i; + } +} + +template <class It> +inline static void formatPtrSequence(QDebug &d, It i1, It i2, + const char *separator=", ") +{ + for (It i = i1; i != i2; ++i) { + if (i != i1) + d << separator; + d << i->get(); + } +} + +template <class Container> +static void formatList(QDebug &d, const char *name, const Container &c, + const char *separator=", ") +{ + if (const auto size = c.size()) { + d << ", " << name << '[' << size << "]=("; + for (qsizetype i = 0; i < size; ++i) { + if (i) + d << separator; + d << c.at(i); + } + d << ')'; + } +} + +#endif // DEBUGHELPERS_P_H diff --git a/sources/shiboken6/ApiExtractor/dependency.h b/sources/shiboken6/ApiExtractor/dependency.h index f0e525e26..aa280de03 100644 --- a/sources/shiboken6/ApiExtractor/dependency.h +++ b/sources/shiboken6/ApiExtractor/dependency.h @@ -13,8 +13,8 @@ class AbstractMetaClass; struct Dependency { - AbstractMetaClass *parent; - AbstractMetaClass *child; + AbstractMetaClassPtr parent; + AbstractMetaClassPtr child; }; using Dependencies = QList<Dependency>; diff --git a/sources/shiboken6/ApiExtractor/docparser.cpp b/sources/shiboken6/ApiExtractor/docparser.cpp index 908e8576b..468fe1098 100644 --- a/sources/shiboken6/ApiExtractor/docparser.cpp +++ b/sources/shiboken6/ApiExtractor/docparser.cpp @@ -31,15 +31,37 @@ using namespace Qt::StringLiterals; -DocParser::DocParser() +static inline bool isXpathDocModification(const DocModification &mod) { -#ifdef HAVE_LIBXSLT - xmlSubstituteEntitiesDefault(1); -#endif + return mod.mode() == TypeSystem::DocModificationXPathReplace; } +static inline bool isNotXpathDocModification(const DocModification &mod) +{ + return mod.mode() != TypeSystem::DocModificationXPathReplace; +} + +static void removeXpathDocModifications(DocModificationList *l) +{ + l->erase(std::remove_if(l->begin(), l->end(), isXpathDocModification), l->end()); +} + +static void removeNonXpathDocModifications(DocModificationList *l) +{ + l->erase(std::remove_if(l->begin(), l->end(), isNotXpathDocModification), l->end()); +} + +DocParser::DocParser() = default; DocParser::~DocParser() = default; +void DocParser::fillGlobalFunctionDocumentation(const AbstractMetaFunctionPtr &) +{ +} + +void DocParser::fillGlobalEnumDocumentation(AbstractMetaEnum &) +{ +} + QString DocParser::getDocumentation(const XQueryPtr &xquery, const QString& query, const DocModificationList& mods) { @@ -86,22 +108,59 @@ bool DocParser::skipForQuery(const AbstractMetaFunctionCPtr &func) usesRValueReference); } -DocModificationList DocParser::getDocModifications(const AbstractMetaClass *cppClass, - const AbstractMetaFunctionCPtr &func) +DocModificationList DocParser::getDocModifications(const AbstractMetaClassCPtr &cppClass) + +{ + auto result = cppClass->typeEntry()->docModifications(); + removeXpathDocModifications(&result); + return result; +} + +static void filterBySignature(const AbstractMetaFunctionCPtr &func, DocModificationList *l) { - auto te = cppClass->typeEntry(); - if (func.isNull()) - return te->docModifications(); + if (!l->isEmpty()) { + const QString minimalSignature = func->minimalSignature(); + const auto filter = [&minimalSignature](const DocModification &mod) { + return mod.signature() != minimalSignature; + }; + l->erase(std::remove_if(l->begin(), l->end(), filter), l->end()); + } +} - if (func->isUserAdded()) - return func->addedFunctionDocModifications(); +DocModificationList DocParser::getDocModifications(const AbstractMetaFunctionCPtr &func, + const AbstractMetaClassCPtr &cppClass) +{ + DocModificationList result; + if (func->isUserAdded()) { + result = func->addedFunctionDocModifications(); + removeXpathDocModifications(&result); + } else if (cppClass != nullptr) { + result = cppClass->typeEntry()->functionDocModifications(); + removeXpathDocModifications(&result); + filterBySignature(func, &result); + } + return result; +} - DocModificationList result = te->functionDocModifications(); - const QString minimalSignature = func->minimalSignature(); - const auto filter = [&minimalSignature](const DocModification &mod) { - return mod.signature() != minimalSignature; - }; - result.erase(std::remove_if(result.begin(), result.end(), filter), result.end()); +DocModificationList DocParser::getXpathDocModifications(const AbstractMetaClassCPtr &cppClass) +{ + auto result = cppClass->typeEntry()->docModifications(); + removeNonXpathDocModifications(&result); + return result; +} + +DocModificationList DocParser::getXpathDocModifications(const AbstractMetaFunctionCPtr &func, + const AbstractMetaClassCPtr &cppClass) +{ + DocModificationList result; + if (func->isUserAdded()) { + result = func->addedFunctionDocModifications(); + removeNonXpathDocModifications(&result); + } else if (cppClass != nullptr) { + result = cppClass->typeEntry()->functionDocModifications(); + removeNonXpathDocModifications(&result); + filterBySignature(func, &result); + } return result; } @@ -120,7 +179,7 @@ QString DocParser::enumBaseClass(const AbstractMetaEnum &e) return e.typeEntry()->flags() != nullptr ? u"Flag"_s : u"Enum"_s; } -AbstractMetaFunctionCList DocParser::documentableFunctions(const AbstractMetaClass *metaClass) +AbstractMetaFunctionCList DocParser::documentableFunctions(const AbstractMetaClassCPtr &metaClass) { auto result = metaClass->functionsInTargetLang(); for (auto i = result.size() - 1; i >= 0; --i) { @@ -131,12 +190,8 @@ AbstractMetaFunctionCList DocParser::documentableFunctions(const AbstractMetaCla return result; } -static inline bool isXpathDocModification(const DocModification &mod) -{ - return mod.mode() == TypeSystem::DocModificationXPathReplace; -} - -QString DocParser::applyDocModifications(const DocModificationList& mods, const QString& xml) +QString DocParser::applyDocModifications(const DocModificationList& xpathMods, + const QString& xml) { const char xslPrefix[] = R"(<xsl:template match="/"> @@ -150,32 +205,28 @@ R"(<xsl:template match="/"> </xsl:template> )"; - if (mods.isEmpty() || xml.isEmpty() - || !std::any_of(mods.cbegin(), mods.cend(), isXpathDocModification)) { + if (xpathMods.isEmpty() || xml.isEmpty()) return xml; - } QString xsl = QLatin1StringView(xslPrefix); - for (const DocModification &mod : mods) { - if (isXpathDocModification(mod)) { - QString xpath = mod.xpath(); - xpath.replace(u'"', u"""_s); - xsl += u"<xsl:template match=\""_s - + xpath + u"\">"_s - + mod.code() + u"</xsl:template>\n"_s; - } + for (const DocModification &mod : xpathMods) { + Q_ASSERT(isXpathDocModification(mod)); + QString xpath = mod.xpath(); + xpath.replace(u'"', u"""_s); + xsl += "<xsl:template match=\""_L1 + xpath + "\">"_L1 + + mod.code() + "</xsl:template>\n"_L1; } QString errorMessage; const QString result = xsl_transform(xml, xsl, &errorMessage); if (!errorMessage.isEmpty()) qCWarning(lcShibokenDoc, "%s", - qPrintable(msgXpathDocModificationError(mods, errorMessage))); + qPrintable(msgXpathDocModificationError(xpathMods, errorMessage))); if (result == xml) { const QString message = u"Query did not result in any modifications to \""_s + xml + u'"'; qCWarning(lcShibokenDoc, "%s", - qPrintable(msgXpathDocModificationError(mods, message))); + qPrintable(msgXpathDocModificationError(xpathMods, message))); } return result; } diff --git a/sources/shiboken6/ApiExtractor/docparser.h b/sources/shiboken6/ApiExtractor/docparser.h index 88643b7bf..6d458b25a 100644 --- a/sources/shiboken6/ApiExtractor/docparser.h +++ b/sources/shiboken6/ApiExtractor/docparser.h @@ -7,7 +7,8 @@ #include "modifications_typedefs.h" #include <QtCore/QString> -#include <QtCore/QSharedPointer> + +#include <memory> class AbstractMetaClass; class DocModification; @@ -20,13 +21,15 @@ struct FunctionDocumentation; class DocParser { public: - Q_DISABLE_COPY(DocParser) + Q_DISABLE_COPY_MOVE(DocParser) - using XQueryPtr = QSharedPointer<XQuery>; + using XQueryPtr = std::shared_ptr<XQuery>; DocParser(); virtual ~DocParser(); - virtual void fillDocumentation(AbstractMetaClass *metaClass) = 0; + virtual void fillDocumentation(const AbstractMetaClassPtr &metaClass) = 0; + virtual void fillGlobalFunctionDocumentation(const AbstractMetaFunctionPtr &f); + virtual void fillGlobalEnumDocumentation(AbstractMetaEnum &e); /** * Process and retrieves documentation concerning the entire @@ -93,8 +96,12 @@ public: /// Helper to return the documentation modifications for a class /// or a member function. - static DocModificationList getDocModifications(const AbstractMetaClass *cppClass, - const AbstractMetaFunctionCPtr &func = {}); + static DocModificationList getDocModifications(const AbstractMetaClassCPtr &cppClass); + static DocModificationList getDocModifications(const AbstractMetaFunctionCPtr &func, + const AbstractMetaClassCPtr &cppClass = {}); + static DocModificationList getXpathDocModifications(const AbstractMetaClassCPtr &cppClass); + static DocModificationList getXpathDocModifications(const AbstractMetaFunctionCPtr &func, + const AbstractMetaClassCPtr &cppClass = {}); static QString enumBaseClass(const AbstractMetaEnum &e); @@ -103,9 +110,9 @@ protected: const QString &query, const DocModificationList &mods); - static AbstractMetaFunctionCList documentableFunctions(const AbstractMetaClass *metaClass); + static AbstractMetaFunctionCList documentableFunctions(const AbstractMetaClassCPtr &metaClass); - static QString applyDocModifications(const DocModificationList &mods, const QString &xml); + static QString applyDocModifications(const DocModificationList &xpathMods, const QString &xml); private: QString m_packageName; diff --git a/sources/shiboken6/ApiExtractor/documentation.cpp b/sources/shiboken6/ApiExtractor/documentation.cpp index 6c4d7166e..33cf0e9fb 100644 --- a/sources/shiboken6/ApiExtractor/documentation.cpp +++ b/sources/shiboken6/ApiExtractor/documentation.cpp @@ -35,12 +35,6 @@ void Documentation::setFormat(Documentation::Format f) m_format = f; } -bool Documentation::equals(const Documentation &rhs) const -{ - return m_format == rhs.m_format && m_detailed == rhs.m_detailed - && m_brief == rhs.m_brief; -} - void Documentation::setDetailed(const QString &detailed) { m_detailed = detailed.trimmed(); diff --git a/sources/shiboken6/ApiExtractor/documentation.h b/sources/shiboken6/ApiExtractor/documentation.h index a18bb1a13..df9d5d614 100644 --- a/sources/shiboken6/ApiExtractor/documentation.h +++ b/sources/shiboken6/ApiExtractor/documentation.h @@ -5,6 +5,7 @@ #define DOCUMENTATION_H #include <QtCore/QString> +#include <QtCore/QtCompare> QT_FORWARD_DECLARE_CLASS(QDebug) @@ -44,16 +45,19 @@ public: void setBrief(const QString &brief); private: + friend bool comparesEqual(const Documentation &lhs, + const Documentation &rhs) noexcept + { + return lhs.m_format == rhs.m_format && lhs.m_detailed == rhs.m_detailed + && lhs.m_brief == rhs.m_brief; + } + Q_DECLARE_EQUALITY_COMPARABLE(Documentation) + QString m_detailed; QString m_brief; Format m_format = Documentation::Native; }; -inline bool operator==(const Documentation &d1, const Documentation &d2) -{ return d1.equals(d2); } -inline bool operator!=(const Documentation &d1, const Documentation &d2) -{ return !d1.equals(d2); } - #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, const Documentation &); #endif diff --git a/sources/shiboken6/ApiExtractor/dotview.cpp b/sources/shiboken6/ApiExtractor/dotview.cpp index da94f5e7f..0bd192257 100644 --- a/sources/shiboken6/ApiExtractor/dotview.cpp +++ b/sources/shiboken6/ApiExtractor/dotview.cpp @@ -13,7 +13,7 @@ using namespace Qt::StringLiterals; bool showDotGraph(const QString &name, const QString &graph) { - const QString imageType = u"jpg"_s; + constexpr auto imageType = "jpg"_L1; // Write out the graph to a temporary file QTemporaryFile dotFile(QDir::tempPath() + u'/' + name + u"_XXXXXX.dot"_s); @@ -43,9 +43,9 @@ bool showDotGraph(const QString &name, const QString &graph) // Launch image. Should use QDesktopServices::openUrl(), // but we don't link against QtGui #ifdef Q_OS_UNIX - const QString imageViewer = u"gwenview"_s; + constexpr auto imageViewer = "gwenview"_L1; #else - const QString imageViewer = u"mspaint"_s; + constexpr auto imageViewer = "mspaint"_L1; #endif if (!QProcess::startDetached(imageViewer, {imageFile})) { qWarning("Failed to launch viewer: %s", qPrintable(imageViewer)); diff --git a/sources/shiboken6/ApiExtractor/doxygenparser.cpp b/sources/shiboken6/ApiExtractor/doxygenparser.cpp index 8f608cbc8..da790015f 100644 --- a/sources/shiboken6/ApiExtractor/doxygenparser.cpp +++ b/sources/shiboken6/ApiExtractor/doxygenparser.cpp @@ -41,7 +41,7 @@ Documentation DoxygenParser::retrieveModuleDocumentation() return retrieveModuleDocumentation(packageName()); } -void DoxygenParser::fillDocumentation(AbstractMetaClass *metaClass) +void DoxygenParser::fillDocumentation(const AbstractMetaClassPtr &metaClass) { if (!metaClass) return; @@ -54,13 +54,12 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass *metaClass) doxyFileSuffix += metaClass->name(); doxyFileSuffix += u".xml"_s; - const char* prefixes[] = { "class", "struct", "namespace" }; + static constexpr QLatin1StringView prefixes[] = { "class"_L1, "struct"_L1, "namespace"_L1 }; bool isProperty = false; QString doxyFilePath; - for (const char *prefix : prefixes) { - doxyFilePath = documentationDataDirectory() + u'/' - + QLatin1StringView(prefix) + doxyFileSuffix; + for (const auto &prefix : prefixes) { + doxyFilePath = documentationDataDirectory() + u'/' + prefix + doxyFileSuffix; if (QFile::exists(doxyFilePath)) break; doxyFilePath.clear(); @@ -76,12 +75,12 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass *metaClass) QString errorMessage; XQueryPtr xquery = XQuery::create(doxyFilePath, &errorMessage); - if (xquery.isNull()) { + if (!xquery) { qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); return; } - static const QList<QPair<Documentation::Type, QString>> docTags = { + static const QList<std::pair<Documentation::Type, QString>> docTags = { { Documentation::Brief, u"briefdescription"_s }, { Documentation::Detailed, u"detaileddescription"_s } }; @@ -119,7 +118,7 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass *metaClass) + func->originalName() + u"\"]"_s; if (func->arguments().isEmpty()) { - QString args = func->isConstant() ? u"() const "_s : u"()"_s; + QString args = func->isConstant() ? u"() const"_s : u"()"_s; query += u"/../argsstring[text()=\""_s + args + u"\"]"_s; } else { int i = 1; @@ -151,16 +150,16 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass *metaClass) } QString doc = getDocumentation(xquery, funcQuery, - DocParser::getDocModifications(metaClass, func)); + DocParser::getXpathDocModifications(func, metaClass)); if (doc.isEmpty()) { qCWarning(lcShibokenDoc, "%s", - qPrintable(msgCannotFindDocumentation(doxyFilePath, func.data(), + qPrintable(msgCannotFindDocumentation(doxyFilePath, func.get(), funcQuery))); } else { funcDoc.setValue(doc, tag.first); } } - qSharedPointerConstCast<AbstractMetaFunction>(func)->setDocumentation(funcDoc); + std::const_pointer_cast<AbstractMetaFunction>(func)->setDocumentation(funcDoc); isProperty = false; } @@ -207,12 +206,12 @@ Documentation DoxygenParser::retrieveModuleDocumentation(const QString& name){ qCWarning(lcShibokenDoc).noquote().nospace() << "Can't find doxygen XML file for module " << name << ", tried: " << QDir::toNativeSeparators(sourceFile); - return Documentation(); + return {}; } QString errorMessage; XQueryPtr xquery = XQuery::create(sourceFile, &errorMessage); - if (xquery.isNull()) { + if (!xquery) { qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); return {}; } diff --git a/sources/shiboken6/ApiExtractor/doxygenparser.h b/sources/shiboken6/ApiExtractor/doxygenparser.h index ea1883d12..4f6a9e53c 100644 --- a/sources/shiboken6/ApiExtractor/doxygenparser.h +++ b/sources/shiboken6/ApiExtractor/doxygenparser.h @@ -10,7 +10,7 @@ class DoxygenParser : public DocParser { public: DoxygenParser() = default; - void fillDocumentation(AbstractMetaClass *metaClass) override; + void fillDocumentation(const AbstractMetaClassPtr &metaClass) override; Documentation retrieveModuleDocumentation() override; Documentation retrieveModuleDocumentation(const QString& name) override; }; diff --git a/sources/shiboken6/ApiExtractor/enclosingclassmixin.cpp b/sources/shiboken6/ApiExtractor/enclosingclassmixin.cpp index f2d5074b7..2421ae527 100644 --- a/sources/shiboken6/ApiExtractor/enclosingclassmixin.cpp +++ b/sources/shiboken6/ApiExtractor/enclosingclassmixin.cpp @@ -5,9 +5,9 @@ #include "abstractmetalang.h" #include "namespacetypeentry.h" -const AbstractMetaClass *EnclosingClassMixin::targetLangEnclosingClass() const +AbstractMetaClassCPtr EnclosingClassMixin::targetLangEnclosingClass() const { - auto result = m_enclosingClass; + auto result = m_enclosingClass.lock(); while (result && !NamespaceTypeEntry::isVisibleScope(result->typeEntry())) result = result->enclosingClass(); return result; diff --git a/sources/shiboken6/ApiExtractor/enclosingclassmixin.h b/sources/shiboken6/ApiExtractor/enclosingclassmixin.h index 31aeb9285..8d735d5ec 100644 --- a/sources/shiboken6/ApiExtractor/enclosingclassmixin.h +++ b/sources/shiboken6/ApiExtractor/enclosingclassmixin.h @@ -4,16 +4,21 @@ #ifndef ENCLOSINGCLASSMIXIN_H #define ENCLOSINGCLASSMIXIN_H +#include "abstractmetalang_typedefs.h" + class AbstractMetaClass; class EnclosingClassMixin { public: - const AbstractMetaClass *enclosingClass() const { return m_enclosingClass; } - void setEnclosingClass(const AbstractMetaClass *cls) { m_enclosingClass = cls; } - const AbstractMetaClass *targetLangEnclosingClass() const; + + const AbstractMetaClassCPtr enclosingClass() const + { return m_enclosingClass.lock(); } + void setEnclosingClass(const AbstractMetaClassCPtr &cls) + { m_enclosingClass = cls; } + AbstractMetaClassCPtr targetLangEnclosingClass() const; private: - const AbstractMetaClass *m_enclosingClass = nullptr; + std::weak_ptr<const AbstractMetaClass> m_enclosingClass; }; #endif // ENCLOSINGCLASSMIXIN_H diff --git a/sources/shiboken6/ApiExtractor/enumtypeentry.h b/sources/shiboken6/ApiExtractor/enumtypeentry.h index 14bab50cf..3360d7db5 100644 --- a/sources/shiboken6/ApiExtractor/enumtypeentry.h +++ b/sources/shiboken6/ApiExtractor/enumtypeentry.h @@ -4,12 +4,13 @@ #ifndef ENUMTYPEENTRY_H #define ENUMTYPEENTRY_H -#include "typesystem.h" +#include "configurabletypeentry.h" #include "typesystem_enums.h" class EnumTypeEntryPrivate; -class EnumTypeEntry : public TypeEntry +// EnumTypeEntry is configurable for global enums only +class EnumTypeEntry : public ConfigurableTypeEntry { public: explicit EnumTypeEntry(const QString &entryName, @@ -36,6 +37,9 @@ public: void addEnumValueRejection(const QString &name); QStringList enumValueRejections() const; + QString docFile() const; + void setDocFile(const QString &df); + TypeEntry *clone() const override; #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; diff --git a/sources/shiboken6/ApiExtractor/fileout.cpp b/sources/shiboken6/ApiExtractor/fileout.cpp index da81f5a1b..6f9ec4d8a 100644 --- a/sources/shiboken6/ApiExtractor/fileout.cpp +++ b/sources/shiboken6/ApiExtractor/fileout.cpp @@ -175,7 +175,7 @@ FileOut::State FileOut::done() if (!FileOut::m_dryRun) { QDir dir(info.absolutePath()); if (!dir.mkpath(dir.absolutePath())) { - const QString message = QStringLiteral("Unable to create directory '%1'") + const QString message = QString::fromLatin1("Unable to create directory '%1'") .arg(QDir::toNativeSeparators(dir.absolutePath())); throw Exception(message); } diff --git a/sources/shiboken6/ApiExtractor/fileout.h b/sources/shiboken6/ApiExtractor/fileout.h index d3f1b7b1f..b11ad1e20 100644 --- a/sources/shiboken6/ApiExtractor/fileout.h +++ b/sources/shiboken6/ApiExtractor/fileout.h @@ -14,7 +14,7 @@ class FileOut { QByteArray m_buffer; public: - Q_DISABLE_COPY(FileOut) + Q_DISABLE_COPY_MOVE(FileOut) enum State { Unchanged, Success }; diff --git a/sources/shiboken6/ApiExtractor/flagstypeentry.h b/sources/shiboken6/ApiExtractor/flagstypeentry.h index b784b64e6..6eddcd12b 100644 --- a/sources/shiboken6/ApiExtractor/flagstypeentry.h +++ b/sources/shiboken6/ApiExtractor/flagstypeentry.h @@ -9,6 +9,7 @@ class EnumTypeEntry; class FlagsTypeEntryPrivate; +// FlagsTypeEntry is configurable for global flags only class FlagsTypeEntry : public TypeEntry { public: diff --git a/sources/shiboken6/ApiExtractor/functiontypeentry.h b/sources/shiboken6/ApiExtractor/functiontypeentry.h index 0901ff017..53aa1fad6 100644 --- a/sources/shiboken6/ApiExtractor/functiontypeentry.h +++ b/sources/shiboken6/ApiExtractor/functiontypeentry.h @@ -5,7 +5,6 @@ #define FUNCTIONTYPEENTRY_H #include "typesystem.h" -#include "typesystem_enums.h" class FunctionTypeEntryPrivate; @@ -20,8 +19,8 @@ public: bool hasSignature(const QString& signature) const; void addSignature(const QString& signature); - TypeSystem::SnakeCase snakeCase() const; - void setSnakeCase(TypeSystem::SnakeCase sc); + QString docFile() const; + void setDocFile(const QString &df); TypeEntry *clone() const override; diff --git a/sources/shiboken6/ApiExtractor/icecc.cmake b/sources/shiboken6/ApiExtractor/icecc.cmake index b2bf071aa..fa8d3b7cf 100644 --- a/sources/shiboken6/ApiExtractor/icecc.cmake +++ b/sources/shiboken6/ApiExtractor/icecc.cmake @@ -1,3 +1,6 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + include (CMakeForceCompiler) option(ENABLE_ICECC "Enable icecc checking, for distributed compilation") if (ENABLE_ICECC) diff --git a/sources/shiboken6/ApiExtractor/include.cpp b/sources/shiboken6/ApiExtractor/include.cpp index d2d577817..aee6b7337 100644 --- a/sources/shiboken6/ApiExtractor/include.cpp +++ b/sources/shiboken6/ApiExtractor/include.cpp @@ -24,18 +24,15 @@ QString Include::toString() const return u"import "_s + m_name + u';'; } -int Include::compare(const Include &rhs) const +Qt::strong_ordering compareThreeWay(const Include &lhs, const Include &rhs) noexcept { - if (m_type < rhs.m_type) - return -1; - if (m_type > rhs.m_type) - return 1; - return m_name.compare(rhs.m_name); -} - -size_t qHash(const Include& inc) -{ - return qHash(inc.m_name); + if (lhs.m_type < rhs.m_type) + return Qt::strong_ordering::less; + if (lhs.m_type > rhs.m_type) + return Qt::strong_ordering::greater; + if (auto c = lhs.m_name.compare(rhs.m_name)) + return c < 0 ? Qt::strong_ordering::less : Qt::strong_ordering::greater; + return Qt::strong_ordering::equal; } QTextStream& operator<<(QTextStream& out, const Include& g) diff --git a/sources/shiboken6/ApiExtractor/include.h b/sources/shiboken6/ApiExtractor/include.h index 7fd7d3b36..875a941f9 100644 --- a/sources/shiboken6/ApiExtractor/include.h +++ b/sources/shiboken6/ApiExtractor/include.h @@ -4,6 +4,8 @@ #ifndef INCLUDE_H #define INCLUDE_H +#include <QtCore/QtCompare> +#include <QtCore/QHashFunctions> #include <QtCore/QString> #include <QtCore/QList> @@ -42,45 +44,24 @@ public: QString toString() const; - friend size_t qHash(const Include &); int compare(const Include &rhs) const; - private: - IncludeType m_type = IncludePath; - QString m_name; -}; - -size_t qHash(const Include& inc); - -inline bool operator<(const Include &lhs, const Include &rhs) -{ - return lhs.compare(rhs) < 0; -} - -inline bool operator<=(const Include &lhs, const Include &rhs) -{ - return lhs.compare(rhs) <= 0; -} - -inline bool operator==(const Include &lhs, const Include &rhs) -{ - return lhs.compare(rhs) == 0; -} - -inline bool operator!=(const Include &lhs, const Include &rhs) -{ - return lhs.compare(rhs) != 0; -} - -inline bool operator>=(const Include &lhs, const Include &rhs) -{ - return lhs.compare(rhs) >= 0; -} +private: + friend size_t qHash(Include &inc, size_t seed = 0) noexcept + { + return qHashMulti(seed, inc.m_type, inc.m_name); + } + friend bool comparesEqual(const Include &lhs, const Include &rhs) noexcept + { + return lhs.m_type == rhs.m_type && lhs.m_name == rhs.m_name; + } + friend Qt::strong_ordering compareThreeWay(const Include &lhs, + const Include &rhs) noexcept; + Q_DECLARE_STRONGLY_ORDERED(Include) -inline bool operator>(const Include &lhs, const Include &rhs) -{ - return lhs.compare(rhs) > 0; -} + IncludeType m_type = IncludePath; + QString m_name; +}; QTextStream& operator<<(QTextStream& out, const Include& include); TextStream& operator<<(TextStream& out, const Include& include); diff --git a/sources/shiboken6/ApiExtractor/messages.cpp b/sources/shiboken6/ApiExtractor/messages.cpp index 247bb7db0..b1f0b240e 100644 --- a/sources/shiboken6/ApiExtractor/messages.cpp +++ b/sources/shiboken6/ApiExtractor/messages.cpp @@ -16,7 +16,6 @@ #include "qtcompat.h" -#include <QtCore/QCoreApplication> #include <QtCore/QDebug> #include <QtCore/QDir> #include <QtCore/QFile> @@ -25,11 +24,25 @@ using namespace Qt::StringLiterals; -static inline QString colonColon() { return QStringLiteral("::"); } - // abstractmetabuilder.cpp -QString msgNoFunctionForModification(const AbstractMetaClass *klass, +static QTextStream &operator<<(QTextStream &s, Access a) +{ + switch (a) { + case Access::Public: + s << "public"; + break; + case Access::Protected: + s << "protected"; + break; + case Access::Private: + s << "private"; + break; + } + return s; +} + +QString msgNoFunctionForModification(const AbstractMetaClassCPtr &klass, const QString &signature, const QString &originalSignature, const QStringList &possibleSignatures, @@ -79,7 +92,7 @@ QString msgTypeModificationFailed(const QString &type, int n, str << "type of argument " << n; str << " of "; - if (auto *c = func->ownerClass()) + if (auto c = func->ownerClass()) str << c->name() << "::"; str << func->signature() << " to \"" << type << "\": " << why; return result; @@ -113,7 +126,7 @@ QString msgArgumentRemovalFailed(const AbstractMetaFunction *func, int n, QString result; QTextStream str(&result); str << "Unable to remove argument " << n << " of "; - if (auto *c = func->ownerClass()) + if (auto c = func->ownerClass()) str << c->name() << "::"; str << func->signature() << ": " << why; return result; @@ -126,7 +139,7 @@ static void msgFormatEnumType(Stream &str, { switch (enumItem->enumKind()) { case CEnum: - str << "Enum '" << enumItem->qualifiedName().join(colonColon()) << '\''; + str << "Enum '" << enumItem->qualifiedName().join(u"::"_s) << '\''; break; case AnonymousEnum: { const EnumeratorList &values = enumItem->enumerators(); @@ -149,7 +162,7 @@ static void msgFormatEnumType(Stream &str, } break; case EnumClass: - str << "Scoped enum '" << enumItem->qualifiedName().join(colonColon()) << '\''; + str << "Scoped enum '" << enumItem->qualifiedName().join(u"::"_s) << '\''; break; } if (!className.isEmpty()) @@ -157,7 +170,7 @@ static void msgFormatEnumType(Stream &str, } static void formatAddedFuncError(const QString &addedFuncName, - const AbstractMetaClass *context, + const AbstractMetaClassCPtr &context, QTextStream &str) { if (context) { @@ -173,12 +186,12 @@ static void formatAddedFuncError(const QString &addedFuncName, QString msgAddedFunctionInvalidArgType(const QString &addedFuncName, const QStringList &typeName, int pos, const QString &why, - const AbstractMetaClass *context) + const AbstractMetaClassCPtr &context) { QString result; QTextStream str(&result); formatAddedFuncError(addedFuncName, context, str); - str << "Unable to translate type \"" << typeName.join(colonColon()) + str << "Unable to translate type \"" << typeName.join(u"::"_s) << "\" of argument " << pos << " of added function \"" << addedFuncName << "\": " << why; return result; @@ -186,18 +199,18 @@ QString msgAddedFunctionInvalidArgType(const QString &addedFuncName, QString msgAddedFunctionInvalidReturnType(const QString &addedFuncName, const QStringList &typeName, const QString &why, - const AbstractMetaClass *context) + const AbstractMetaClassCPtr &context) { QString result; QTextStream str(&result); formatAddedFuncError(addedFuncName, context, str); - str << "Unable to translate return type \"" << typeName.join(colonColon()) + str << "Unable to translate return type \"" << typeName.join(u"::"_s) << "\" of added function \"" << addedFuncName << "\": " << why; return result; } -QString msgUnnamedArgumentDefaultExpression(const AbstractMetaClass *context, +QString msgUnnamedArgumentDefaultExpression(const AbstractMetaClassCPtr &context, int n, const QString &className, const AbstractMetaFunction *f) { @@ -227,7 +240,8 @@ QString msgNoEnumTypeEntry(const EnumModelItem &enumItem, QTextStream str(&result); str << enumItem->sourceLocation(); msgFormatEnumType(str, enumItem, className); - str << " does not have a type entry"; + str << " does not have a type entry (type systems: " + << TypeDatabase::instance()->loadedTypeSystemNames() << ')'; return result; } @@ -251,7 +265,8 @@ QString msgNamespaceNoTypeEntry(const NamespaceModelItem &item, QString result; QTextStream str(&result); str << item->sourceLocation() << "namespace '" << fullName - << "' does not have a type entry"; + << "' does not have a type entry (type systems: " + << TypeDatabase::instance()->loadedTypeSystemNames() << ')'; return result; } @@ -302,11 +317,13 @@ QString msgSkippingFunction(const FunctionModelItem &functionItem, { QString result; QTextStream str(&result); - str << functionItem->sourceLocation() << "skipping "; - if (functionItem->isAbstract()) + str << functionItem->sourceLocation() << "skipping " + << functionItem->accessPolicy() << ' '; + const bool isAbstract = functionItem->attributes().testFlag(FunctionAttribute::Abstract); + if (isAbstract) str << "abstract "; str << "function '" << signature << "', " << why; - if (functionItem->isAbstract()) { + if (isAbstract) { str << "\nThis will lead to compilation errors due to not " "being able to instantiate the wrapper."; } @@ -324,7 +341,7 @@ QString msgShadowingFunction(const AbstractMetaFunction *f1, return result; } -QString msgSignalOverloaded(const AbstractMetaClass *c, +QString msgSignalOverloaded(const AbstractMetaClassCPtr &c, const AbstractMetaFunction *f) { QString result; @@ -339,8 +356,9 @@ QString msgSkippingField(const VariableModelItem &field, const QString &classNam { QString result; QTextStream str(&result); - str << field->sourceLocation() << "skipping field '" << className - << "::" << field->name() << "' with unmatched type '" << type << '\''; + str << field->sourceLocation() << "skipping " << field->accessPolicy() + << " field '" << className << "::" << field->name() + << "' with unmatched type '" << type << '\''; return result; } @@ -351,8 +369,14 @@ QString msgTypeNotDefined(const TypeEntryCPtr &entry) { QString result; QTextStream str(&result); + const bool hasConfigCondition = entry->isComplex() + && std::static_pointer_cast<const ConfigurableTypeEntry>(entry)->hasConfigCondition(); str << entry->sourceLocation() << "type '" <<entry->qualifiedCppName() - << "' is specified in typesystem, but not defined. " << msgCompilationError; + << "' is specified in typesystem, but not defined"; + if (hasConfigCondition) + str << " (disabled by configuration?)."; + else + str << ". " << msgCompilationError; return result; } @@ -372,14 +396,15 @@ QString msgGlobalFunctionNotDefined(const FunctionTypeEntryCPtr &fte, QString msgStrippingArgument(const FunctionModelItem &f, int i, const QString &originalSignature, - const ArgumentModelItem &arg) + const ArgumentModelItem &arg, + const QString &reason) { QString result; QTextStream str(&result); str << f->sourceLocation() << "Stripping argument #" << (i + 1) << " of " << originalSignature << " due to unmatched type \"" << arg->type().toString() << "\" with default expression \"" - << arg->defaultValueExpression() << "\"."; + << arg->defaultValueExpression() << "\": " << reason; return result; } @@ -392,7 +417,7 @@ QString msgEnumNotDefined(const EnumTypeEntryCPtr &t) return result; } -QString msgUnknownBase(const AbstractMetaClass *metaClass, +QString msgUnknownBase(const AbstractMetaClassCPtr &metaClass, const QString &baseClassName) { QString result; @@ -402,7 +427,7 @@ QString msgUnknownBase(const AbstractMetaClass *metaClass, return result; } -QString msgBaseNotInTypeSystem(const AbstractMetaClass *metaClass, +QString msgBaseNotInTypeSystem(const AbstractMetaClassCPtr &metaClass, const QString &baseClassName) { QString result; @@ -456,6 +481,21 @@ QString msgCannotFindTypeEntryForSmartPointer(const QString &t, const QString &s + u"\" for instantiation of \""_s +smartPointerType + u"\"."_s; } +QString msgInheritTemplateIssue(const AbstractMetaClassPtr &subclass, + const TypeInfo &info, + const QString &what) +{ + return "While inheriting template "_L1 + subclass->name() + + " from "_L1 + info.toString() + ": "_L1 + what; +} + +QString msgIgnoringTemplateParameter(const QString &typeName, + const char *why) +{ + return "Ignoring template parameter "_L1 + typeName + + ": "_L1 + QLatin1StringView(why); +} + QString msgInvalidSmartPointerType(const TypeInfo &i) { return u"Invalid smart pointer type \""_s +i.toString() + u"\"."_s; @@ -511,7 +551,7 @@ QString msgPropertyExists(const QString &className, const QString &name) + name + u"\" (defined by Q_PROPERTY)."_s; } -QString msgFunctionVisibilityModified(const AbstractMetaClass *c, +QString msgFunctionVisibilityModified(const AbstractMetaClassCPtr &c, const AbstractMetaFunction *f) { QString result; @@ -521,7 +561,7 @@ QString msgFunctionVisibilityModified(const AbstractMetaClass *c, return result; } -QString msgUsingMemberClassNotFound(const AbstractMetaClass *c, +QString msgUsingMemberClassNotFound(const AbstractMetaClassCPtr &c, const QString &baseClassName, const QString &memberName) { @@ -587,23 +627,25 @@ QString msgFallbackForDocumentation(const QString &fileName, } QString msgCannotFindDocumentation(const QString &fileName, - const AbstractMetaClass *metaClass, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaEnum &e, const QString &query) { - return msgCannotFindDocumentation(fileName, "enum", - metaClass->name() + u"::"_s + e.name(), - query); + QString name = e.name(); + if (metaClass != nullptr) + name.prepend(metaClass->name() + "::"_L1); + return msgCannotFindDocumentation(fileName, "enum", name, query); } QString msgCannotFindDocumentation(const QString &fileName, - const AbstractMetaClass *metaClass, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaField &f, const QString &query) { - return msgCannotFindDocumentation(fileName, "field", - metaClass->name() + u"::"_s + f.name(), - query); + QString name = f.name(); + if (metaClass != nullptr) + name.prepend(metaClass->name() + "::"_L1); + return msgCannotFindDocumentation(fileName, "field", name, query); } QString msgXpathDocModificationError(const DocModificationList& mods, @@ -631,13 +673,13 @@ QString msgXpathDocModificationError(const DocModificationList& mods, QString msgCannotOpenForReading(const QFile &f) { - return QStringLiteral("Failed to open file '%1' for reading: %2") + return QString::fromLatin1("Failed to open file '%1' for reading: %2") .arg(QDir::toNativeSeparators(f.fileName()), f.errorString()); } QString msgCannotOpenForWriting(const QFile &f) { - return QStringLiteral("Failed to open file '%1' for writing: %2") + return QString::fromLatin1("Failed to open file '%1' for writing: %2") .arg(QDir::toNativeSeparators(f.fileName()), f.errorString()); } @@ -659,23 +701,6 @@ QString msgCannotUseEnumAsInt(const QString &name) "Compilation errors may occur when used as a function argument."_s; } -QString msgConversionTypesDiffer(const QString &varType, const QString &conversionType) -{ - QString result; - QTextStream str(&result); - str << "Types of receiver variable ('" << varType - << "') and %%CONVERTTOCPP type system variable ('" << conversionType - << "') differ"; - QString strippedVarType = varType; - QString strippedConversionType = conversionType; - TypeInfo::stripQualifiers(&strippedVarType); - TypeInfo::stripQualifiers(&strippedConversionType); - if (strippedVarType == strippedConversionType) - str << " in qualifiers. Please make sure the type is a distinct token"; - str << '.'; - return result; -} - QString msgCannotFindSmartPointerGetter(const SmartPointerTypeEntryCPtr &te) { return u"Getter \""_s + te->getter() + u"()\" of smart pointer \""_s @@ -688,7 +713,7 @@ QString msgCannotFindSmartPointerMethod(const SmartPointerTypeEntryCPtr &te, con + te->name() + u"\" not found."_s; } -QString msgMethodNotFound(const AbstractMetaClass *klass, const QString &name) +QString msgMethodNotFound(const AbstractMetaClassCPtr &klass, const QString &name) { return u"Method \""_s + name + u"\" not found in class "_s + klass->name() + u'.'; @@ -696,18 +721,12 @@ QString msgMethodNotFound(const AbstractMetaClass *klass, const QString &name) // main.cpp -QString msgLeftOverArguments(const QVariantMap &remainingArgs) +QString msgLeftOverArguments(const QString &remainingArgs, const QStringList &argV) { QString message; QTextStream str(&message); - str << "shiboken: Called with wrong arguments:"; - for (auto it = remainingArgs.cbegin(), end = remainingArgs.cend(); it != end; ++it) { - str << ' ' << it.key(); - const QString value = it.value().toString(); - if (!value.isEmpty()) - str << ' ' << value; - } - str << "\nCommand line: " << QCoreApplication::arguments().join(u' '); + str << "shiboken: Unprocessed arguments: " << remainingArgs + << "\nCommand line: " << argV.join(u' '); return message; } @@ -734,7 +753,7 @@ QString msgCyclicDependency(const QString &funcName, const QString &graphName, if (i) str << ", \""; str << involvedConversions.at(i)->signature() << '"'; - if (const AbstractMetaClass *c = involvedConversions.at(i)->implementingClass()) + if (const auto c = involvedConversions.at(i)->implementingClass()) str << '(' << c->name() << ')'; } } @@ -763,7 +782,7 @@ QString msgUnknownOperator(const AbstractMetaFunction *func) { QString result = u"Unknown operator: \""_s + func->originalName() + u'"'; - if (const AbstractMetaClass *c = func->implementingClass()) + if (const auto c = func->implementingClass()) result += u" in class: "_s + c->name(); return result; } @@ -774,7 +793,7 @@ QString msgWrongIndex(const char *varName, const QString &capture, QString result; QTextStream str(&result); str << "Wrong index for " << varName << " variable (" << capture << ") on "; - if (const AbstractMetaClass *c = func->implementingClass()) + if (const auto c = func->implementingClass()) str << c->name() << "::"; str << func->signature(); return result; @@ -816,17 +835,17 @@ QString msgRejectReason(const TypeRejection &r, const QString &needle) QTextStream str(&result); switch (r.matchType) { case TypeRejection::ExcludeClass: - str << " matches class exclusion \"" << r.className.pattern() << '"'; + str << "matches class exclusion \"" << r.className.pattern() << '"'; break; case TypeRejection::Function: case TypeRejection::Field: case TypeRejection::Enum: - str << " matches class \"" << r.className.pattern() << "\" and \"" + str << "matches class \"" << r.className.pattern() << "\" and \"" << r.pattern.pattern() << '"'; break; case TypeRejection::ArgumentType: case TypeRejection::ReturnType: - str << " matches class \"" << r.className.pattern() << "\" and \"" + str << "matches class \"" << r.className.pattern() << "\" and \"" << needle << "\" matches \"" << r.pattern.pattern() << '"'; break; } @@ -879,6 +898,21 @@ QString msgCannotFindSnippet(const QString &file, const QString &snippetLabel) return result; } +QString msgSnippetError(const QString &context, const char *what) +{ + return "Error processing code snippet of "_L1 + context + + ": "_L1 + QString::fromUtf8(what); +} + +QString msgUnableToResolveTypedef(const QString &sourceType, const QString &sourceName) +{ + QString result; + QTextStream(&result) << "Unable to resolve typedef \"" << sourceType + << "\": Could not find a value, container, object or smart pointer type named \"" + << sourceName << "\"."; + return result; +} + // cppgenerator.cpp QString msgPureVirtualFunctionRemoved(const AbstractMetaFunction *f) @@ -950,3 +984,14 @@ QString msgUnknownArrayPointerConversion(const QString &s) return u"Warning: Falling back to pointer conversion for unknown array type \""_s + s + u"\""_s; } + +QString msgMissingProjectFileMarker(const QString &name, const QByteArray &startMarker) +{ + return u"First line of project file \""_s + QDir::toNativeSeparators(name) + + u"\" must be the string \""_s + QString::fromLatin1(startMarker) + u"\"."_s; +} + +QString msgInvalidLanguageLevel(const QString &l) +{ + return u"Invalid argument for language level: \""_s + l + u"\"."_s; +} diff --git a/sources/shiboken6/ApiExtractor/messages.h b/sources/shiboken6/ApiExtractor/messages.h index 17255f717..e3f582b49 100644 --- a/sources/shiboken6/ApiExtractor/messages.h +++ b/sources/shiboken6/ApiExtractor/messages.h @@ -25,19 +25,19 @@ QT_FORWARD_DECLARE_CLASS(QXmlStreamReader) QString msgAddedFunctionInvalidArgType(const QString &addedFuncName, const QStringList &typeName, int pos, const QString &why, - const AbstractMetaClass *context = nullptr); + const AbstractMetaClassCPtr &context = {}); QString msgAddedFunctionInvalidReturnType(const QString &addedFuncName, const QStringList &typeName, const QString &why, - const AbstractMetaClass *context = nullptr); + const AbstractMetaClassCPtr &context = {}); -QString msgUnnamedArgumentDefaultExpression(const AbstractMetaClass *context, +QString msgUnnamedArgumentDefaultExpression(const AbstractMetaClassCPtr &context, int n, const QString &className, const AbstractMetaFunction *f); QString msgArgumentIndexOutOfRange(const AbstractMetaFunction *func, int index); -QString msgNoFunctionForModification(const AbstractMetaClass *klass, +QString msgNoFunctionForModification(const AbstractMetaClassCPtr &klass, const QString &signature, const QString &originalSignature, const QStringList &possibleSignatures, @@ -82,7 +82,7 @@ QString msgUnmatchedReturnType(const FunctionModelItem &functionItem, QString msgShadowingFunction(const AbstractMetaFunction *f1, const AbstractMetaFunction *f2); -QString msgSignalOverloaded(const AbstractMetaClass *c, +QString msgSignalOverloaded(const AbstractMetaClassCPtr &c, const AbstractMetaFunction *f); QString msgSkippingFunction(const FunctionModelItem &functionItem, @@ -99,14 +99,15 @@ QString msgGlobalFunctionNotDefined(const FunctionTypeEntryCPtr &fte, QString msgStrippingArgument(const FunctionModelItem &f, int i, const QString &originalSignature, - const ArgumentModelItem &arg); + const ArgumentModelItem &arg, + const QString &reason); QString msgEnumNotDefined(const EnumTypeEntryCPtr &t); -QString msgUnknownBase(const AbstractMetaClass *metaClass, +QString msgUnknownBase(const AbstractMetaClassCPtr &metaClass, const QString &baseClassName); -QString msgBaseNotInTypeSystem(const AbstractMetaClass *metaClass, +QString msgBaseNotInTypeSystem(const AbstractMetaClassCPtr &metaClass, const QString &baseClassName); QString msgArrayModificationFailed(const FunctionModelItem &functionItem, @@ -125,6 +126,10 @@ QString msgUnableToTranslateType(const TypeInfo &typeInfo, QString msgCannotFindTypeEntry(const QString &t); QString msgCannotFindTypeEntryForSmartPointer(const QString &t, const QString &smartPointerType); +QString msgInheritTemplateIssue(const AbstractMetaClassPtr &subclass, + const TypeInfo &info, const QString &what); +QString msgIgnoringTemplateParameter(const QString &typeName, + const char *why); QString msgInvalidSmartPointerType(const TypeInfo &i); QString msgCannotFindSmartPointerInstantion(const TypeInfo &i); @@ -140,10 +145,10 @@ QString msgPropertyTypeParsingFailed(const QString &name, const QString &typeNam const QString &why); QString msgPropertyExists(const QString &className, const QString &name); -QString msgFunctionVisibilityModified(const AbstractMetaClass *c, +QString msgFunctionVisibilityModified(const AbstractMetaClassCPtr &c, const AbstractMetaFunction *f); -QString msgUsingMemberClassNotFound(const AbstractMetaClass *c, +QString msgUsingMemberClassNotFound(const AbstractMetaClassCPtr &c, const QString &baseClassName, const QString &memberName); @@ -164,12 +169,12 @@ QString msgFallbackForDocumentation(const QString &fileName, const QString &query = {}); QString msgCannotFindDocumentation(const QString &fileName, - const AbstractMetaClass *metaClass, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaEnum &e, const QString &query = {}); QString msgCannotFindDocumentation(const QString &fileName, - const AbstractMetaClass *metaClass, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaField &f, const QString &query); @@ -184,15 +189,13 @@ QString msgWriteFailed(const QFile &f, qsizetype size); QString msgCannotUseEnumAsInt(const QString &name); -QString msgConversionTypesDiffer(const QString &varType, const QString &conversionType); - QString msgCannotFindSmartPointerGetter(const SmartPointerTypeEntryCPtr &); QString msgCannotFindSmartPointerMethod(const SmartPointerTypeEntryCPtr &te, const QString &m); -QString msgMethodNotFound(const AbstractMetaClass *klass, const QString &name); +QString msgMethodNotFound(const AbstractMetaClassCPtr &klass, const QString &name); -QString msgLeftOverArguments(const QVariantMap &remainingArgs); +QString msgLeftOverArguments(const QString &remainingArgs, const QStringList &argV); QString msgInvalidVersion(const QString &package, const QString &version); @@ -210,6 +213,8 @@ QString msgIncorrectlyNestedName(const QString &name); QString msgCannotFindView(const QString &viewedName, const QString &name); QString msgCannotFindSnippet(const QString &file, const QString &snippetLabel); +QString msgSnippetError(const QString &context, const char *what); +QString msgUnableToResolveTypedef(const QString &sourceType, const QString &sourceName); QString msgCyclicDependency(const QString &funcName, const QString &graphName, const AbstractMetaFunctionCList &cyclic, @@ -252,4 +257,8 @@ QString msgMissingCustomConversion(const TypeEntryCPtr &t); QString msgUnknownArrayPointerConversion(const QString &s); +QString msgMissingProjectFileMarker(const QString &name, const QByteArray &startMarker); + +QString msgInvalidLanguageLevel(const QString &l); + #endif // MESSAGES_H diff --git a/sources/shiboken6/ApiExtractor/modifications.cpp b/sources/shiboken6/ApiExtractor/modifications.cpp index d42cfb460..d876e8035 100644 --- a/sources/shiboken6/ApiExtractor/modifications.cpp +++ b/sources/shiboken6/ApiExtractor/modifications.cpp @@ -14,20 +14,6 @@ using namespace Qt::StringLiterals; -// ---------------------- Modification -QString FunctionModification::accessModifierString() const -{ - if (isPrivate()) - return u"private"_s; - if (isProtected()) - return u"protected"_s; - if (isPublic()) - return u"public"_s; - if (isFriendly()) - return u"friendly"_s; - return QString(); -} - // ---------------------- FieldModification class FieldModificationData : public QSharedData @@ -48,8 +34,8 @@ FieldModification::FieldModification() : d(new FieldModificationData) FieldModification::FieldModification(const FieldModification &) = default; FieldModification &FieldModification::operator=(const FieldModification &) = default; -FieldModification::FieldModification(FieldModification &&) = default; -FieldModification &FieldModification::operator=(FieldModification &&) = default; +FieldModification::FieldModification(FieldModification &&) noexcept = default; +FieldModification &FieldModification::operator=(FieldModification &&) noexcept = default; FieldModification::~FieldModification() = default; QString FieldModification::name() const @@ -188,7 +174,7 @@ QDebug operator<<(QDebug d, const CodeSnip &s) if (i) d << ", "; d << '#' << i << ' '; - if (f.instance().isNull()) { + if (!f.instance()) { d << '"'; const QString &code = f.code(); const auto lines = QStringView{code}.split(u'\n'); @@ -241,8 +227,8 @@ ArgumentModification::ArgumentModification(int idx) : d(new ArgumentModification ArgumentModification::ArgumentModification(const ArgumentModification &) = default; ArgumentModification &ArgumentModification::operator=(const ArgumentModification &) = default; -ArgumentModification::ArgumentModification(ArgumentModification &&) = default; -ArgumentModification &ArgumentModification::operator=(ArgumentModification &&) = default; +ArgumentModification::ArgumentModification(ArgumentModification &&) noexcept = default; +ArgumentModification &ArgumentModification::operator=(ArgumentModification &&) noexcept = default; ArgumentModification::~ArgumentModification() = default; const QString &ArgumentModification::modifiedType() const @@ -423,7 +409,6 @@ public: QString m_originalSignature; QRegularExpression m_signaturePattern; int m_overloadNumber = TypeSystem::OverloadNumberUnset; - bool m_thread = false; bool removed = false; TypeSystem::AllowThread m_allowThread = TypeSystem::AllowThread::Unspecified; TypeSystem::ExceptionHandling m_exceptionHandling = TypeSystem::ExceptionHandling::Unspecified; @@ -436,8 +421,8 @@ FunctionModification::FunctionModification() : d(new FunctionModificationData) FunctionModification::FunctionModification(const FunctionModification &) = default; FunctionModification &FunctionModification::operator=(const FunctionModification &) = default; -FunctionModification::FunctionModification(FunctionModification &&) = default; -FunctionModification &FunctionModification::operator=(FunctionModification &&) = default; +FunctionModification::FunctionModification(FunctionModification &&) noexcept = default; +FunctionModification &FunctionModification::operator=(FunctionModification &&) noexcept = default; FunctionModification::~FunctionModification() = default; void FunctionModification::formatDebug(QDebug &debug) const @@ -453,8 +438,6 @@ void FunctionModification::formatDebug(QDebug &debug) const debug << ", renamedToName=\"" << d->renamedToName << '"'; if (d->m_allowThread != TypeSystem::AllowThread::Unspecified) debug << ", allowThread=" << int(d->m_allowThread); - if (d->m_thread) - debug << ", thread"; if (d->m_exceptionHandling != TypeSystem::ExceptionHandling::Unspecified) debug << ", exceptionHandling=" << int(d->m_exceptionHandling); if (!d->m_snips.isEmpty()) @@ -557,17 +540,6 @@ void FunctionModification::setSnips(const CodeSnipList &snips) } // ---------------------- FunctionModification -void FunctionModification::setIsThread(bool flag) -{ - if (d->m_thread != flag) - d->m_thread = flag; -} - -bool FunctionModification::isThread() const -{ - return d->m_thread; -} - FunctionModification::AllowThread FunctionModification::allowThread() const { return d->m_allowThread; diff --git a/sources/shiboken6/ApiExtractor/modifications.h b/sources/shiboken6/ApiExtractor/modifications.h index 65ed81ff8..27a38f1aa 100644 --- a/sources/shiboken6/ApiExtractor/modifications.h +++ b/sources/shiboken6/ApiExtractor/modifications.h @@ -64,8 +64,8 @@ public: explicit ArgumentModification(int idx); ArgumentModification(const ArgumentModification &); ArgumentModification &operator=(const ArgumentModification &); - ArgumentModification(ArgumentModification &&); - ArgumentModification &operator=(ArgumentModification &&); + ArgumentModification(ArgumentModification &&) noexcept; + ArgumentModification &operator=(ArgumentModification &&) noexcept; ~ArgumentModification(); // Reference count flags for this argument @@ -134,15 +134,14 @@ public: FunctionModification(); FunctionModification(const FunctionModification &); FunctionModification &operator=(const FunctionModification &); - FunctionModification(FunctionModification &&); - FunctionModification &operator=(FunctionModification &&); + FunctionModification(FunctionModification &&) noexcept; + FunctionModification &operator=(FunctionModification &&) noexcept; ~FunctionModification(); enum ModifierFlag { Private = 0x0001, Protected = 0x0002, - Public = 0x0003, - Friendly = 0x0004, + Public = 0x0004, AccessModifierMask = 0x000f, Final = 0x0010, @@ -155,7 +154,8 @@ public: CodeInjection = 0x1000, Rename = 0x2000, Deprecated = 0x4000, - ReplaceExpression = 0x8000 + Undeprecated = 0x8000, + ReplaceExpression = 0x10000 }; Q_DECLARE_FLAGS(Modifiers, ModifierFlag); @@ -190,10 +190,6 @@ public: { return accessModifier() == Public; } - bool isFriendly() const - { - return accessModifier() == Friendly; - } bool isFinal() const { return modifiers().testFlag(Final); @@ -202,7 +198,6 @@ public: { return modifiers().testFlag(NonFinal); } - QString accessModifierString() const; bool isDeprecated() const { @@ -222,8 +217,6 @@ public: { return modifiers().testFlag(CodeInjection); } - void setIsThread(bool flag); - bool isThread() const; AllowThread allowThread() const; void setAllowThread(AllowThread allow); @@ -278,8 +271,8 @@ public: FieldModification(); FieldModification(const FieldModification &); FieldModification &operator=(const FieldModification &); - FieldModification(FieldModification &&); - FieldModification &operator=(FieldModification &&); + FieldModification(FieldModification &&) noexcept; + FieldModification &operator=(FieldModification &&) noexcept; ~FieldModification(); QString name() const; diff --git a/sources/shiboken6/ApiExtractor/modifications_typedefs.h b/sources/shiboken6/ApiExtractor/modifications_typedefs.h index c827335ab..3b86c55d3 100644 --- a/sources/shiboken6/ApiExtractor/modifications_typedefs.h +++ b/sources/shiboken6/ApiExtractor/modifications_typedefs.h @@ -5,7 +5,8 @@ #define MODIFICATIONS_TYPEDEFS_H #include <QtCore/QList> -#include <QtCore/QSharedPointer> + +#include <memory> class CodeSnip; class DocModification; @@ -14,7 +15,7 @@ struct AddedFunction; class FieldModification; class FunctionModification; -using AddedFunctionPtr = QSharedPointer<AddedFunction>; +using AddedFunctionPtr = std::shared_ptr<AddedFunction>; using AddedFunctionList = QList<AddedFunctionPtr>; using CodeSnipList = QList<CodeSnip>; using DocModificationList = QList<DocModification>; diff --git a/sources/shiboken6/ApiExtractor/optionsparser.cpp b/sources/shiboken6/ApiExtractor/optionsparser.cpp new file mode 100644 index 000000000..f2e64c7e4 --- /dev/null +++ b/sources/shiboken6/ApiExtractor/optionsparser.cpp @@ -0,0 +1,232 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "optionsparser.h" +#include "messages.h" +#include "exception.h" + +#include <QtCore/QDir> +#include <QtCore/QTextStream> + +using namespace Qt::StringLiterals; + +template <class Stream> void formatBoolOption(Stream &s, const BoolOption &bo) +{ + switch (bo.source) { + case OptionSource::CommandLine: + s << "--"; + break; + case OptionSource::CommandLineSingleDash: + s << '-'; + break; + default: + break; + } + s << bo.option; + if (bo.source == OptionSource::ProjectFile) + s << " (project)"; +} + +template <class Stream> void formatOptionValue(Stream &s, const OptionValue &ov) +{ + switch (ov.source) { + case OptionSource::CommandLine: + s << "--"; + break; + case OptionSource::CommandLineSingleDash: + s << '-'; + break; + default: + break; + } + s << ov.option << '=' << ov.value; + if (ov.source == OptionSource::ProjectFile) + s << " (project)"; +} + +QTextStream &operator<<(QTextStream &s, const BoolOption &bo) +{ + formatBoolOption(s, bo); + return s; +} + +QTextStream &operator<<(QTextStream &s, const OptionValue &ov) +{ + formatOptionValue(s, ov); + return s; +} + +QDebug operator<<(QDebug debug, const BoolOption &bo) +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + formatBoolOption(debug, bo); + return debug; +} + +QDebug operator<<(QDebug debug, const OptionValue &v) +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + formatOptionValue(debug, v); + return debug; +} + +QDebug operator<<(QDebug debug, const Options &v) +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + debug << "Options("; + if (!v.boolOptions.isEmpty()) + debug << "bools=" << v.boolOptions; + if (!v.valueOptions.isEmpty()) + debug << ", option values=" << v.valueOptions; + if (!v.positionalArguments.isEmpty()) + debug << ", pos=" << v.positionalArguments; + debug << ')'; + return debug; +} + +QTextStream &operator<<(QTextStream &s, const OptionDescription &od) +{ + if (!od.name.startsWith(u'-')) + s << "--"; + s << od.name; + if (od.description.isEmpty()) { // For formatting {{"-s", ""}, {"--short", "descr"}} + s << ", "; + } else { + s << '\n'; + const auto lines = QStringView{od.description}.split(u'\n'); + for (const auto &line : lines) + s << " " << line << '\n'; + s << '\n'; + } + return s; +} + +QTextStream &operator<<(QTextStream &s, const OptionDescriptions &options) +{ + s.setFieldAlignment(QTextStream::AlignLeft); + for (const auto &od : options) + s << od; + return s; +} + +OptionsParser::OptionsParser() noexcept = default; +OptionsParser::~OptionsParser() = default; + +const QString &OptionsParser::pathSyntax() +{ + static const QString result = + u"<path>["_s + QDir::listSeparator() + u"<path>"_s + + QDir::listSeparator() + u"...]"_s; + return result; +} + +bool OptionsParser::handleBoolOption(const QString &, OptionSource) +{ + return false; +} + +bool OptionsParser::handleOption(const QString &, const QString &, OptionSource) +{ + return false; +} + +void OptionsParser::process(Options *o) +{ + for (auto i = o->boolOptions.size() - 1; i >= 0; --i) { + const auto &opt = o->boolOptions.at(i); + if (handleBoolOption(opt.option, opt.source)) + o->boolOptions.removeAt(i); + } + for (auto i = o->valueOptions.size() - 1; i >= 0; --i) { + const auto &opt = o->valueOptions.at(i); + if (handleOption(opt.option, opt.value, opt.source)) + o->valueOptions.removeAt(i); + } +} + +bool OptionsParserList::handleBoolOption(const QString &key, OptionSource source) +{ + for (const auto &p : std::as_const(m_parsers)) { + if (p->handleBoolOption(key, source)) + return true; + } + return false; +} + +bool OptionsParserList::handleOption(const QString &key, const QString &value, OptionSource source) +{ + for (const auto &p : std::as_const(m_parsers)) { + if (p->handleOption(key, value, source)) + return true; + } + return false; +} + +static void processOption(const QString &o, OptionSource source, + BoolOptions *bools, OptionValues *values) +{ + const auto equals = o.indexOf(u'='); + if (equals == -1) { + bools->append({o.trimmed(), source}); + } else { + QString key = o.left(equals).trimmed(); + QString value = o.mid(equals + 1).trimmed(); + if (!value.isEmpty()) + values->append({key, value, source}); + } +} + +static void readProjectFile(const QString &name, Options *o) +{ + const auto startMarker = "[generator-project]"_ba; + + QFile file(name); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + throw Exception(msgCannotOpenForReading(file)); + + if (file.atEnd() || file.readLine().trimmed() != startMarker) + throw Exception(msgMissingProjectFileMarker(name, startMarker)); + + while (!file.atEnd()) { + const QByteArray lineB = file.readLine().trimmed(); + if (!lineB.isEmpty() && !lineB.startsWith('#')) { + processOption(QString::fromUtf8(lineB), OptionSource::ProjectFile, + &o->boolOptions, &o->valueOptions); + } + } +} + +void Options::setOptions(const QStringList &argv) +{ + const auto projectFileOption = "--project-file="_L1; + for (const auto &o : argv) { + if (o.startsWith(projectFileOption)) { + readProjectFile(o.sliced(projectFileOption.size()), this); + } else if (o.startsWith(u"--")) { + processOption(o.sliced(2), OptionSource::CommandLine, + &boolOptions, &valueOptions); + } else if (o.startsWith(u'-')) { + processOption(o.sliced(1), OptionSource::CommandLineSingleDash, + &boolOptions, &valueOptions); + } else { + positionalArguments.append(o); + } + } +} + +QString Options::msgUnprocessedOptions() const +{ + QString result; + QTextStream str(&result); + for (const auto &b : boolOptions) + str << b << ' '; + for (const auto &v : valueOptions) + str << v << ' '; + return result.trimmed(); +} diff --git a/sources/shiboken6/ApiExtractor/optionsparser.h b/sources/shiboken6/ApiExtractor/optionsparser.h new file mode 100644 index 000000000..d5557dc15 --- /dev/null +++ b/sources/shiboken6/ApiExtractor/optionsparser.h @@ -0,0 +1,98 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef OPTIONSPARSER_H +#define OPTIONSPARSER_H + +#include <QtCore/QString> +#include <QtCore/QStringList> + +#include <memory> + +QT_FORWARD_DECLARE_CLASS(QTextStream) + +enum class OptionSource +{ + CommandLine, // "--option" + CommandLineSingleDash, // "-o" + ProjectFile +}; + +struct BoolOption +{ + QString option; + OptionSource source = OptionSource::CommandLine; +}; + +struct OptionValue // --option=value pair +{ + QString option; + QString value; + OptionSource source = OptionSource::CommandLine; +}; + +using BoolOptions = QList<BoolOption>; +using OptionValues = QList<OptionValue>; + +struct Options // Options from command line and project file +{ + void setOptions(const QStringList &argv); + QString msgUnprocessedOptions() const; + + BoolOptions boolOptions; + OptionValues valueOptions; + QStringList positionalArguments; +}; + +struct OptionDescription // For help formatting +{ + QString name; + QString description; +}; + +using OptionDescriptions = QList<OptionDescription>; + +QTextStream &operator<<(QTextStream &s, const BoolOption &bo); +QTextStream &operator<<(QTextStream &s, const OptionValue &ov); +QTextStream &operator<<(QTextStream &s, const OptionDescription &od); +QTextStream &operator<<(QTextStream &s, const OptionDescriptions &options); + +class OptionsParser +{ +public: + Q_DISABLE_COPY_MOVE(OptionsParser) + + virtual ~OptionsParser(); + + // Return true to indicate the option was processed. + virtual bool handleBoolOption(const QString &key, OptionSource source); + virtual bool handleOption(const QString &key, const QString &value, OptionSource source); + + void process(Options *); + + static const QString &pathSyntax(); + +protected: + OptionsParser() noexcept; +}; + +class OptionsParserList : public OptionsParser +{ +public: + using OptionsParserPtr = std::shared_ptr<OptionsParser>; + + void append(const OptionsParserPtr &parser) { m_parsers.append(parser); } + void clear() { m_parsers.clear(); } + + bool handleBoolOption(const QString &key, OptionSource source) override; + bool handleOption(const QString &key, const QString &value, OptionSource source) override; + +private: + QList<OptionsParserPtr> m_parsers; +}; + +QDebug operator<<(QDebug debug, const BoolOption &bo); +QDebug operator<<(QDebug debug, const OptionValue &v); +QDebug operator<<(QDebug debug, const Options &v); + +#endif // OPTIONSPARSER_H diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp index 8c6279ee6..259a706dc 100644 --- a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp @@ -6,33 +6,24 @@ #include "codemodel.h" #include <sourcelocation.h> +#include <debughelpers_p.h> #include <QtCore/QDebug> #include <QtCore/QDir> #include <QtCore/QRegularExpression> #include <algorithm> -#include <functional> -#include <iostream> using namespace Qt::StringLiterals; -// Predicate to find an item by name in a list of QSharedPointer<Item> -template <class T> class ModelItemNamePredicate -{ -public: - explicit ModelItemNamePredicate(const QString &name) : m_name(name) {} - bool operator()(const QSharedPointer<T> &item) const { return item->name() == m_name; } - -private: - const QString m_name; -}; - template <class T> -static QSharedPointer<T> findModelItem(const QList<QSharedPointer<T> > &list, const QString &name) +static std::shared_ptr<T> findModelItem(const QList<std::shared_ptr<T> > &list, + QAnyStringView name) { - const auto it = std::find_if(list.cbegin(), list.cend(), ModelItemNamePredicate<T>(name)); - return it != list.cend() ? *it : QSharedPointer<T>(); + using ItemPtr = std::shared_ptr<T>; + auto pred = [name](const ItemPtr &item) { return item->name() == name; }; + const auto it = std::find_if(list.cbegin(), list.cend(), pred); + return it != list.cend() ? *it : ItemPtr{}; } // --------------------------------------------------------------------------- @@ -53,7 +44,7 @@ void CodeModel::addFile(const FileModelItem &item) m_files.append(item); } -FileModelItem CodeModel::findFile(const QString &name) const +FileModelItem CodeModel::findFile(QAnyStringView name) const { return findModelItem(m_files, name); } @@ -71,11 +62,11 @@ static CodeModelItem findRecursion(const ScopeModelItem &scope, return tp; if (TemplateTypeAliasModelItem tta = scope->findTemplateTypeAlias(nameSegment)) return tta; - return CodeModelItem(); + return {}; } if (auto nestedClass = scope->findClass(nameSegment)) return findRecursion(nestedClass, qualifiedName, segment + 1); - if (auto namespaceItem = qSharedPointerDynamicCast<_NamespaceModelItem>(scope)) { + if (auto namespaceItem = std::dynamic_pointer_cast<_NamespaceModelItem>(scope)) { for (const auto &nestedNamespace : namespaceItem->namespaces()) { if (nestedNamespace->name() == nameSegment) { if (auto item = findRecursion(nestedNamespace, qualifiedName, segment + 1)) @@ -83,7 +74,7 @@ static CodeModelItem findRecursion(const ScopeModelItem &scope, } } } - return CodeModelItem(); + return {}; } CodeModelItem CodeModel::findItem(const QStringList &qualifiedName, const ScopeModelItem &scope) @@ -120,7 +111,7 @@ QDebug operator<<(QDebug d, const CodeModel *m) d << "CodeModel("; if (m) { const NamespaceModelItem globalNamespaceP = m->globalNamespace(); - if (globalNamespaceP.data()) + if (globalNamespaceP) globalNamespaceP->formatDebug(d); } else { d << '0'; @@ -243,27 +234,17 @@ void _CodeModelItem::setEnclosingScope(const _ScopeModelItem *s) m_enclosingScope = s; } -#ifndef QT_NO_DEBUG_STREAM -template <class It> -void formatSequence(QDebug &d, It i1, It i2, const char *separator=", ") +_ScopeModelItem::_ScopeModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind) { - for (It i = i1; i != i2; ++i) { - if (i != i1) - d << separator; - d << *i; - } } -template <class It> -static void formatPtrSequence(QDebug &d, It i1, It i2, const char *separator=", ") +_ScopeModelItem::_ScopeModelItem(CodeModel *model, const QString &name, int kind) + : _CodeModelItem(model, name, kind) { - for (It i = i1; i != i2; ++i) { - if (i != i1) - d << separator; - d << i->data(); - } } +#ifndef QT_NO_DEBUG_STREAM void _CodeModelItem::formatKind(QDebug &d, int k) { switch (k) { @@ -373,6 +354,16 @@ bool _ClassModelItem::extendsClass(const QString &name) const return false; } +_ClassModelItem::_ClassModelItem(CodeModel *model, int kind) + : _ScopeModelItem(model, kind) +{ +} + +_ClassModelItem::_ClassModelItem(CodeModel *model, const QString &name, int kind) + : _ScopeModelItem(model, name, kind) +{ +} + const QList<_ClassModelItem::UsingMember> &_ClassModelItem::usingMembers() const { return m_usingMembers; @@ -458,7 +449,7 @@ FunctionModelItem _ScopeModelItem::declaredFunction(const FunctionModelItem &ite return fun; } - return FunctionModelItem(); + return {}; } _ScopeModelItem::~_ScopeModelItem() = default; @@ -627,52 +618,46 @@ void _ScopeModelItem::formatDebug(QDebug &d) const } #endif // !QT_NO_DEBUG_STREAM -namespace { // Predicate to match a non-template class name against the class list. // "Vector" should match "Vector" as well as "Vector<T>" (as seen for methods // from within the class "Vector"). -class ClassNamePredicate +static bool matchClassNameNonTemplatePart(const ClassModelItem &item, const QString &name) { -public: - explicit ClassNamePredicate(const QString &name) : m_name(name) {} - bool operator()(const ClassModelItem &item) const - { - const QString &itemName = item->name(); - if (!itemName.startsWith(m_name)) - return false; - return itemName.size() == m_name.size() || itemName.at(m_name.size()) == u'<'; - } - -private: - const QString m_name; -}; -} // namespace + const QString &itemName = item->name(); + if (!itemName.startsWith(name)) + return false; + return itemName.size() == name.size() || itemName.at(name.size()) == u'<'; +} ClassModelItem _ScopeModelItem::findClass(const QString &name) const { // A fully qualified template is matched by name only const ClassList::const_iterator it = name.contains(u'<') - ? std::find_if(m_classes.begin(), m_classes.end(), ModelItemNamePredicate<_ClassModelItem>(name)) - : std::find_if(m_classes.begin(), m_classes.end(), ClassNamePredicate(name)); + ? std::find_if(m_classes.begin(), m_classes.end(), + [&name](const ClassModelItem &item) { + return item->name() == name; }) + : std::find_if(m_classes.begin(), m_classes.end(), + [&name](const ClassModelItem &item) { + return matchClassNameNonTemplatePart(item, name); }); return it != m_classes.end() ? *it : ClassModelItem(); } -VariableModelItem _ScopeModelItem::findVariable(const QString &name) const +VariableModelItem _ScopeModelItem::findVariable(QAnyStringView name) const { return findModelItem(m_variables, name); } -TypeDefModelItem _ScopeModelItem::findTypeDef(const QString &name) const +TypeDefModelItem _ScopeModelItem::findTypeDef(QAnyStringView name) const { return findModelItem(m_typeDefs, name); } -TemplateTypeAliasModelItem _ScopeModelItem::findTemplateTypeAlias(const QString &name) const +TemplateTypeAliasModelItem _ScopeModelItem::findTemplateTypeAlias(QAnyStringView name) const { return findModelItem(m_templateTypeAliases, name); } -EnumModelItem _ScopeModelItem::findEnum(const QString &name) const +EnumModelItem _ScopeModelItem::findEnum(QAnyStringView name) const { return findModelItem(m_enums, name); } @@ -724,8 +709,8 @@ _ScopeModelItem::FindEnumByValueReturn if (searchSiblingNamespaces && scope->kind() == Kind_Namespace) { if (auto *enclosingNamespace = dynamic_cast<const _NamespaceModelItem *>(enclosingScope)) { for (const auto &sibling : enclosingNamespace->namespaces()) { - if (sibling.data() != scope && sibling->name() == scope->name()) { - if (const auto e = findEnumByValueRecursion(sibling.data(), + if (sibling.get() != scope && sibling->name() == scope->name()) { + if (const auto e = findEnumByValueRecursion(sibling.get(), fullValue, enumValue, false)) { return e; } @@ -741,8 +726,8 @@ _ScopeModelItem::FindEnumByValueReturn // PYSIDE-331: We need to also search the base classes. if (auto *classItem = dynamic_cast<const _ClassModelItem *>(scope)) { for (const auto &base : classItem->baseClasses()) { - if (!base.klass.isNull()) { - auto *c = base.klass.data(); + if (base.klass) { + auto *c = base.klass.get(); if (const auto e = findEnumByValueRecursion(c, fullValue, enumValue)) return e; } @@ -761,7 +746,7 @@ _ScopeModelItem::FindEnumByValueReturn return findEnumByValueRecursion(this, value, enumValue); } -FunctionList _ScopeModelItem::findFunctions(const QString &name) const +FunctionList _ScopeModelItem::findFunctions(QAnyStringView name) const { FunctionList result; for (const FunctionModelItem &func : m_functions) { @@ -772,17 +757,25 @@ FunctionList _ScopeModelItem::findFunctions(const QString &name) const } // --------------------------------------------------------------------------- -_NamespaceModelItem::~_NamespaceModelItem() +_NamespaceModelItem::_NamespaceModelItem(CodeModel *model, int kind) + : _ScopeModelItem(model, kind) { } +_NamespaceModelItem::_NamespaceModelItem(CodeModel *model, const QString &name, int kind) + : _ScopeModelItem(model, name, kind) +{ +} + +_NamespaceModelItem::~_NamespaceModelItem() = default; + void _NamespaceModelItem::addNamespace(NamespaceModelItem item) { item->setEnclosingScope(this); m_namespaces.append(item); } -NamespaceModelItem _NamespaceModelItem::findNamespace(const QString &name) const +NamespaceModelItem _NamespaceModelItem::findNamespace(QAnyStringView name) const { return findModelItem(m_namespaces, name); } @@ -814,10 +807,18 @@ void _NamespaceModelItem::formatDebug(QDebug &d) const #endif // !QT_NO_DEBUG_STREAM // --------------------------------------------------------------------------- -_ArgumentModelItem::~_ArgumentModelItem() +_ArgumentModelItem::_ArgumentModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind) { } +_ArgumentModelItem::_ArgumentModelItem(CodeModel *model, const QString &name, int kind) + : _CodeModelItem(model, name, kind) +{ +} + +_ArgumentModelItem::~_ArgumentModelItem() = default; + TypeInfo _ArgumentModelItem::type() const { return m_type; @@ -838,11 +839,23 @@ void _ArgumentModelItem::setDefaultValue(bool defaultValue) m_defaultValue = defaultValue; } +bool _ArgumentModelItem::scopeResolution() const +{ + return m_scopeResolution; +} + +void _ArgumentModelItem::setScopeResolution(bool v) +{ + m_scopeResolution = v; +} + #ifndef QT_NO_DEBUG_STREAM void _ArgumentModelItem::formatDebug(QDebug &d) const { _CodeModelItem::formatDebug(d); d << ", type=" << m_type; + if (m_scopeResolution) + d << ", [m_scope resolution]"; if (m_defaultValue) d << ", defaultValue=\"" << m_defaultValueExpression << '"'; } @@ -877,6 +890,16 @@ bool _FunctionModelItem::isSimilar(const FunctionModelItem &other) const return true; } +_FunctionModelItem::_FunctionModelItem(CodeModel *model, int kind) + : _MemberModelItem(model, kind), m_flags(0) +{ +} + +_FunctionModelItem::_FunctionModelItem(CodeModel *model, const QString &name, int kind) + : _MemberModelItem(model, name, kind), m_flags(0) +{ +} + ArgumentList _FunctionModelItem::arguments() const { return m_arguments; @@ -907,6 +930,16 @@ void _FunctionModelItem::setVariadics(bool isVariadics) m_isVariadics = isVariadics; } +bool _FunctionModelItem::scopeResolution() const +{ + return m_scopeResolution; +} + +void _FunctionModelItem::setScopeResolution(bool v) +{ + m_scopeResolution = v; +} + bool _FunctionModelItem::isDefaultConstructor() const { return m_functionType == CodeModel::Constructor @@ -969,66 +1002,16 @@ void _FunctionModelItem::setDeleted(bool d) m_isDeleted = d; } -bool _FunctionModelItem::isDeprecated() const -{ - return m_isDeprecated; -} - -void _FunctionModelItem::setDeprecated(bool d) -{ - m_isDeprecated = d; -} - -bool _FunctionModelItem::isVirtual() const -{ - return m_isVirtual; -} - -void _FunctionModelItem::setVirtual(bool isVirtual) -{ - m_isVirtual = isVirtual; -} - bool _FunctionModelItem::isInline() const { return m_isInline; } -bool _FunctionModelItem::isOverride() const -{ - return m_isOverride; -} - -void _FunctionModelItem::setOverride(bool o) -{ - m_isOverride = o; -} - -bool _FunctionModelItem::isFinal() const -{ - return m_isFinal; -} - -void _FunctionModelItem::setFinal(bool f) -{ - m_isFinal = f; -} - void _FunctionModelItem::setInline(bool isInline) { m_isInline = isInline; } -bool _FunctionModelItem::isExplicit() const -{ - return m_isExplicit; -} - -void _FunctionModelItem::setExplicit(bool isExplicit) -{ - m_isExplicit = isExplicit; -} - bool _FunctionModelItem::isHiddenFriend() const { return m_isHiddenFriend; @@ -1039,27 +1022,6 @@ void _FunctionModelItem::setHiddenFriend(bool f) m_isHiddenFriend = f; } -bool _FunctionModelItem::isAbstract() const -{ - return m_isAbstract; -} - -void _FunctionModelItem::setAbstract(bool isAbstract) -{ - m_isAbstract = isAbstract; -} - -// Qt -bool _FunctionModelItem::isInvokable() const -{ - return m_isInvokable; -} - -void _FunctionModelItem::setInvokable(bool isInvokable) -{ - m_isInvokable = isInvokable; -} - QString _FunctionModelItem::typeSystemSignature() const // For dumping out type system files { QString result; @@ -1184,20 +1146,22 @@ void _FunctionModelItem::formatDebug(QDebug &d) const d << " [deleted!]"; if (m_isInline) d << " [inline]"; - if (m_isVirtual) + if (m_attributes.testFlag(FunctionAttribute::Virtual)) d << " [virtual]"; - if (m_isOverride) + if (m_attributes.testFlag(FunctionAttribute::Override)) d << " [override]"; - if (m_isDeprecated) + if (m_attributes.testFlag(FunctionAttribute::Deprecated)) d << " [deprecated]"; - if (m_isFinal) + if (m_attributes.testFlag(FunctionAttribute::Final)) d << " [final]"; - if (m_isAbstract) + if (m_attributes.testFlag(FunctionAttribute::Abstract)) d << " [abstract]"; - if (m_isExplicit) + if (m_attributes.testFlag(FunctionAttribute::Explicit)) d << " [explicit]"; if (m_isInvokable) d << " [invokable]"; + if (m_scopeResolution) + d << " [scope resolution]"; formatModelItemList(d, ", arguments=", m_arguments); if (m_isVariadics) d << ",..."; @@ -1205,6 +1169,16 @@ void _FunctionModelItem::formatDebug(QDebug &d) const #endif // !QT_NO_DEBUG_STREAM // --------------------------------------------------------------------------- +_TypeDefModelItem::_TypeDefModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind) +{ +} + +_TypeDefModelItem::_TypeDefModelItem(CodeModel *model, const QString &name, int kind) + : _CodeModelItem(model, name, kind) +{ +} + TypeInfo _TypeDefModelItem::type() const { return m_type; @@ -1266,6 +1240,16 @@ void _TemplateTypeAliasModelItem::formatDebug(QDebug &d) const #endif // !QT_NO_DEBUG_STREAM // --------------------------------------------------------------------------- +_EnumModelItem::_EnumModelItem(CodeModel *model, const QString &name, int kind) + : _CodeModelItem(model, name, kind) +{ +} + +_EnumModelItem::_EnumModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind) +{ +} + Access _EnumModelItem::accessPolicy() const { return m_accessPolicy; @@ -1307,6 +1291,16 @@ void _EnumModelItem::setSigned(bool s) m_signed = s; } +QString _EnumModelItem::underlyingType() const +{ + return m_underlyingType; +} + +void _EnumModelItem::setUnderlyingType(const QString &underlyingType) +{ + m_underlyingType = underlyingType; +} + bool _EnumModelItem::isDeprecated() const { return m_deprecated; @@ -1342,6 +1336,16 @@ void _EnumModelItem::formatDebug(QDebug &d) const // --------------------------------------------------------------------------- _EnumeratorModelItem::~_EnumeratorModelItem() = default; +_EnumeratorModelItem::_EnumeratorModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind) +{ +} + +_EnumeratorModelItem::_EnumeratorModelItem(CodeModel *model, const QString &name, int kind) + : _CodeModelItem(model, name, kind) +{ +} + QString _EnumeratorModelItem::stringValue() const { return m_stringValue; @@ -1375,6 +1379,17 @@ void _EnumeratorModelItem::formatDebug(QDebug &d) const // --------------------------------------------------------------------------- _TemplateParameterModelItem::~_TemplateParameterModelItem() = default; +_TemplateParameterModelItem::_TemplateParameterModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind) +{ +} + +_TemplateParameterModelItem::_TemplateParameterModelItem(CodeModel *model, + const QString &name, int kind) + : _CodeModelItem(model, name, kind) +{ +} + TypeInfo _TemplateParameterModelItem::type() const { return m_type; @@ -1438,6 +1453,16 @@ void _MemberModelItem::setStatic(bool isStatic) m_isStatic = isStatic; } +_MemberModelItem::_MemberModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind), m_flags(0) +{ +} + +_MemberModelItem::_MemberModelItem(CodeModel *model, const QString &name, int kind) + : _CodeModelItem(model, name, kind), m_flags(0) +{ +} + bool _MemberModelItem::isConstant() const { return m_isConstant; diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.h b/sources/shiboken6/ApiExtractor/parser/codemodel.h index 97a851995..b31c09163 100644 --- a/sources/shiboken6/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken6/ApiExtractor/parser/codemodel.h @@ -12,7 +12,6 @@ #include "typeinfo.h" #include <QtCore/QHash> -#include <QtCore/QPair> #include <QtCore/QSet> #include <QtCore/QString> #include <QtCore/QStringList> @@ -20,6 +19,7 @@ #include <QtCore/QWeakPointer> #include <optional> +#include <utility> QT_FORWARD_DECLARE_CLASS(QDebug) @@ -32,7 +32,7 @@ class CodeModel { Q_GADGET public: - Q_DISABLE_COPY(CodeModel) + Q_DISABLE_COPY_MOVE(CodeModel) enum FunctionType { Normal, @@ -74,7 +74,7 @@ public: NamespaceModelItem globalNamespace() const; void addFile(const FileModelItem &item); - FileModelItem findFile(const QString &name) const; + FileModelItem findFile(QAnyStringView name) const; static CodeModelItem findItem(const QStringList &qualifiedName, const ScopeModelItem &scope); @@ -91,8 +91,9 @@ QDebug operator<<(QDebug d, const CodeModel *m); class _CodeModelItem { - Q_DISABLE_COPY(_CodeModelItem) public: + Q_DISABLE_COPY_MOVE(_CodeModelItem) + enum Kind { /* These are bit-flags resembling inheritance */ Kind_Scope = 0x1, @@ -175,6 +176,7 @@ QDebug operator<<(QDebug d, const _CodeModelItem *t); class _ScopeModelItem: public _CodeModelItem { public: + Q_DISABLE_COPY_MOVE(_ScopeModelItem) DECLARE_MODEL_NODE(Scope) ~_ScopeModelItem(); @@ -194,21 +196,21 @@ public: void addVariable(const VariableModelItem &item); ClassModelItem findClass(const QString &name) const; - EnumModelItem findEnum(const QString &name) const; + EnumModelItem findEnum(QAnyStringView name) const; struct FindEnumByValueReturn { - operator bool() const { return !item.isNull(); } + operator bool() const { return bool(item); } EnumModelItem item; QString qualifiedName; }; FindEnumByValueReturn findEnumByValue(QStringView value) const; - FunctionList findFunctions(const QString &name) const; - TypeDefModelItem findTypeDef(const QString &name) const; - TemplateTypeAliasModelItem findTemplateTypeAlias(const QString &name) const; - VariableModelItem findVariable(const QString &name) const; + FunctionList findFunctions(QAnyStringView name) const; + TypeDefModelItem findTypeDef(QAnyStringView name) const; + TemplateTypeAliasModelItem findTemplateTypeAlias(QAnyStringView name) const; + VariableModelItem findVariable(QAnyStringView name) const; void addEnumsDeclaration(const QString &enumsDeclaration); QStringList enumsDeclarations() const { return m_enumsDeclarations; } @@ -223,10 +225,9 @@ public: #endif protected: - explicit _ScopeModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind) {} - explicit _ScopeModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind) {} + explicit _ScopeModelItem(CodeModel *model, int kind = __node_kind); + explicit _ScopeModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); void appendScope(const _ScopeModelItem &other); @@ -258,6 +259,7 @@ private: class _ClassModelItem: public _ScopeModelItem { public: + Q_DISABLE_COPY_MOVE(_ClassModelItem) DECLARE_MODEL_NODE(Class) struct BaseClass @@ -274,10 +276,9 @@ public: Access access = Access::Public; }; - explicit _ClassModelItem(CodeModel *model, int kind = __node_kind) - : _ScopeModelItem(model, kind), m_classType(CodeModel::Class) {} - explicit _ClassModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _ScopeModelItem(model, name, kind), m_classType(CodeModel::Class) {} + explicit _ClassModelItem(CodeModel *model, int kind = __node_kind); + explicit _ClassModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); ~_ClassModelItem(); const QList<BaseClass> &baseClasses() const { return m_baseClasses; } @@ -313,7 +314,7 @@ private: QList<BaseClass> m_baseClasses; QList<UsingMember> m_usingMembers; TemplateParameterList m_templateParameters; - CodeModel::ClassType m_classType; + CodeModel::ClassType m_classType = CodeModel::Class; QStringList m_propertyDeclarations; bool m_final = false; @@ -322,12 +323,12 @@ private: class _NamespaceModelItem: public _ScopeModelItem { public: + Q_DISABLE_COPY_MOVE(_NamespaceModelItem) DECLARE_MODEL_NODE(Namespace) - explicit _NamespaceModelItem(CodeModel *model, int kind = __node_kind) - : _ScopeModelItem(model, kind) {} - explicit _NamespaceModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _ScopeModelItem(model, name, kind) {} + explicit _NamespaceModelItem(CodeModel *model, int kind = __node_kind); + explicit _NamespaceModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); ~_NamespaceModelItem(); const NamespaceList &namespaces() const { return m_namespaces; } @@ -337,7 +338,7 @@ public: void addNamespace(NamespaceModelItem item); - NamespaceModelItem findNamespace(const QString &name) const; + NamespaceModelItem findNamespace(QAnyStringView name) const; void appendNamespace(const _NamespaceModelItem &other); @@ -353,24 +354,23 @@ private: class _FileModelItem: public _NamespaceModelItem { public: + Q_DISABLE_COPY_MOVE(_FileModelItem) DECLARE_MODEL_NODE(File) - explicit _FileModelItem(CodeModel *model, int kind = __node_kind) - : _NamespaceModelItem(model, kind) {} - explicit _FileModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _NamespaceModelItem(model, name, kind) {} + using _NamespaceModelItem::_NamespaceModelItem; + ~_FileModelItem(); }; class _ArgumentModelItem: public _CodeModelItem { public: + Q_DISABLE_COPY_MOVE(_ArgumentModelItem) DECLARE_MODEL_NODE(Argument) - explicit _ArgumentModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind), m_defaultValue(false) {} - explicit _ArgumentModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind), m_defaultValue(false) {} + explicit _ArgumentModelItem(CodeModel *model, int kind = __node_kind); + explicit _ArgumentModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); ~_ArgumentModelItem(); TypeInfo type() const; @@ -382,6 +382,10 @@ public: QString defaultValueExpression() const { return m_defaultValueExpression; } void setDefaultValueExpression(const QString &expr) { m_defaultValueExpression = expr; } + // Argument type has scope resolution "::ArgumentType" + bool scopeResolution() const; + void setScopeResolution(bool v); + #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; #endif @@ -389,18 +393,19 @@ public: private: TypeInfo m_type; QString m_defaultValueExpression; - bool m_defaultValue; + bool m_defaultValue = false; + bool m_scopeResolution = false; }; class _MemberModelItem: public _CodeModelItem { public: + Q_DISABLE_COPY_MOVE(_MemberModelItem) DECLARE_MODEL_NODE(Member) - explicit _MemberModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind), m_accessPolicy(Access::Public), m_flags(0) {} - explicit _MemberModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind), m_accessPolicy(Access::Public), m_flags(0) {} + explicit _MemberModelItem(CodeModel *model, int kind = __node_kind); + explicit _MemberModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); ~_MemberModelItem(); bool isConstant() const; @@ -443,7 +448,7 @@ public: private: TemplateParameterList m_templateParameters; TypeInfo m_type; - Access m_accessPolicy; + Access m_accessPolicy = Access::Public; union { struct { uint m_isConstant: 1; @@ -463,12 +468,12 @@ private: class _FunctionModelItem: public _MemberModelItem { public: + Q_DISABLE_COPY_MOVE(_FunctionModelItem) DECLARE_MODEL_NODE(Function) - explicit _FunctionModelItem(CodeModel *model, int kind = __node_kind) - : _MemberModelItem(model, kind), m_functionType(CodeModel::Normal), m_flags(0) {} - explicit _FunctionModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _MemberModelItem(model, name, kind), m_functionType(CodeModel::Normal), m_flags(0) {} + explicit _FunctionModelItem(CodeModel *model, int kind = __node_kind); + explicit _FunctionModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); ~_FunctionModelItem(); ArgumentList arguments() const; @@ -480,39 +485,25 @@ public: static std::optional<CodeModel::FunctionType> functionTypeFromName(QStringView name); + FunctionAttributes attributes() const { return m_attributes; } + void setAttributes(FunctionAttributes a) { m_attributes = a; } + void setAttribute(FunctionAttribute a, bool on = true) { m_attributes.setFlag(a, on); } + bool isDeleted() const; void setDeleted(bool d); - bool isDeprecated() const; - void setDeprecated(bool d); - - bool isVirtual() const; - void setVirtual(bool isVirtual); - - bool isOverride() const; - void setOverride(bool o); - - bool isFinal() const; - void setFinal(bool f); - bool isInline() const; void setInline(bool isInline); - bool isExplicit() const; - void setExplicit(bool isExplicit); - bool isHiddenFriend() const; void setHiddenFriend(bool f); - bool isInvokable() const; // Qt - void setInvokable(bool isInvokable); // Qt - - bool isAbstract() const; - void setAbstract(bool isAbstract); - bool isVariadics() const; void setVariadics(bool isVariadics); + bool scopeResolution() const; // Return type has scope resolution "::ReturnType" + void setScopeResolution(bool v); + bool isDefaultConstructor() const; bool isSpaceshipOperator() const; @@ -538,20 +529,16 @@ private: CodeModel::FunctionType _determineTypeHelper() const; ArgumentList m_arguments; - CodeModel::FunctionType m_functionType; + FunctionAttributes m_attributes; + CodeModel::FunctionType m_functionType = CodeModel::Normal; union { struct { uint m_isDeleted: 1; - uint m_isVirtual: 1; - uint m_isOverride: 1; - uint m_isFinal: 1; - uint m_isDeprecated: 1; uint m_isInline: 1; - uint m_isAbstract: 1; - uint m_isExplicit: 1; uint m_isVariadics: 1; uint m_isHiddenFriend: 1; uint m_isInvokable : 1; // Qt + uint m_scopeResolution: 1; }; uint m_flags; }; @@ -563,10 +550,7 @@ class _VariableModelItem: public _MemberModelItem public: DECLARE_MODEL_NODE(Variable) - explicit _VariableModelItem(CodeModel *model, int kind = __node_kind) - : _MemberModelItem(model, kind) {} - explicit _VariableModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _MemberModelItem(model, name, kind) {} + using _MemberModelItem::_MemberModelItem; }; class _TypeDefModelItem: public _CodeModelItem @@ -574,10 +558,9 @@ class _TypeDefModelItem: public _CodeModelItem public: DECLARE_MODEL_NODE(TypeDef) - explicit _TypeDefModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind) {} - explicit _TypeDefModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind) {} + explicit _TypeDefModelItem(CodeModel *model, int kind = __node_kind); + explicit _TypeDefModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); TypeInfo type() const; void setType(const TypeInfo &type); @@ -617,12 +600,11 @@ private: class _EnumModelItem: public _CodeModelItem { public: + Q_DISABLE_COPY_MOVE(_EnumModelItem) DECLARE_MODEL_NODE(Enum) - explicit _EnumModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind) {} - explicit _EnumModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind) {} + explicit _EnumModelItem(CodeModel *model, const QString &name, int kind = __node_kind); + explicit _EnumModelItem(CodeModel *model, int kind = __node_kind); ~_EnumModelItem(); Access accessPolicy() const; @@ -647,7 +629,11 @@ public: bool isSigned() const; void setSigned(bool s); + QString underlyingType() const; + void setUnderlyingType(const QString &underlyingType); + private: + QString m_underlyingType; Access m_accessPolicy = Access::Public; EnumeratorList m_enumerators; EnumKind m_enumKind = CEnum; @@ -658,12 +644,12 @@ private: class _EnumeratorModelItem: public _CodeModelItem { public: + Q_DISABLE_COPY_MOVE(_EnumeratorModelItem) DECLARE_MODEL_NODE(Enumerator) - explicit _EnumeratorModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind) {} - explicit _EnumeratorModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind) {} + explicit _EnumeratorModelItem(CodeModel *model, int kind = __node_kind); + explicit _EnumeratorModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); ~_EnumeratorModelItem(); QString stringValue() const; @@ -688,12 +674,12 @@ private: class _TemplateParameterModelItem: public _CodeModelItem { public: + Q_DISABLE_COPY_MOVE(_TemplateParameterModelItem) DECLARE_MODEL_NODE(TemplateParameter) - explicit _TemplateParameterModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind), m_defaultValue(false) {} - explicit _TemplateParameterModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind), m_defaultValue(false) {} + explicit _TemplateParameterModelItem(CodeModel *model, int kind = __node_kind); + explicit _TemplateParameterModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); ~_TemplateParameterModelItem(); TypeInfo type() const; @@ -708,9 +694,7 @@ public: private: TypeInfo m_type; - bool m_defaultValue; + bool m_defaultValue = false; }; #endif // CODEMODEL_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h b/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h index 1a058bdfe..e5c429bd0 100644 --- a/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h +++ b/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h @@ -4,6 +4,8 @@ #ifndef CODEMODEL_ENUMS_H #define CODEMODEL_ENUMS_H +#include <QtCore/qflags.h> + enum ReferenceType { NoReference, LValueReference, @@ -43,4 +45,17 @@ enum class Access Public }; +enum class FunctionAttribute { + Abstract = 0x00000001, + Static = 0x00000002, + Virtual = 0x00000004, + Override = 0x00000008, + Final = 0x00000010, + Deprecated = 0x00000020, // Code annotation + Explicit = 0x00000040, // Constructor +}; + +Q_DECLARE_FLAGS(FunctionAttributes, FunctionAttribute) +Q_DECLARE_OPERATORS_FOR_FLAGS(FunctionAttributes) + #endif // CODEMODEL_ENUMS_H diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel_fwd.h b/sources/shiboken6/ApiExtractor/parser/codemodel_fwd.h index a3adf6678..f0a25c9db 100644 --- a/sources/shiboken6/ApiExtractor/parser/codemodel_fwd.h +++ b/sources/shiboken6/ApiExtractor/parser/codemodel_fwd.h @@ -7,7 +7,8 @@ #define CODEMODEL_FWD_H #include <QtCore/QList> -#include <QtCore/QSharedPointer> + +#include <memory> // forward declarations class CodeModel; @@ -27,20 +28,20 @@ class _VariableModelItem; class _MemberModelItem; class TypeInfo; -using ArgumentModelItem = QSharedPointer<_ArgumentModelItem>; -using ClassModelItem = QSharedPointer<_ClassModelItem>; -using CodeModelItem = QSharedPointer<_CodeModelItem>; -using EnumModelItem = QSharedPointer<_EnumModelItem>; -using EnumeratorModelItem = QSharedPointer<_EnumeratorModelItem>; -using FileModelItem = QSharedPointer<_FileModelItem>; -using FunctionModelItem = QSharedPointer<_FunctionModelItem>; -using NamespaceModelItem = QSharedPointer<_NamespaceModelItem>; -using ScopeModelItem = QSharedPointer<_ScopeModelItem>; -using TemplateParameterModelItem = QSharedPointer<_TemplateParameterModelItem>; -using TypeDefModelItem = QSharedPointer<_TypeDefModelItem>; -using TemplateTypeAliasModelItem = QSharedPointer<_TemplateTypeAliasModelItem>; -using VariableModelItem = QSharedPointer<_VariableModelItem>; -using MemberModelItem = QSharedPointer<_MemberModelItem>; +using ArgumentModelItem = std::shared_ptr<_ArgumentModelItem>; +using ClassModelItem = std::shared_ptr<_ClassModelItem>; +using CodeModelItem = std::shared_ptr<_CodeModelItem>; +using EnumModelItem = std::shared_ptr<_EnumModelItem>; +using EnumeratorModelItem = std::shared_ptr<_EnumeratorModelItem>; +using FileModelItem = std::shared_ptr<_FileModelItem>; +using FunctionModelItem = std::shared_ptr<_FunctionModelItem>; +using NamespaceModelItem = std::shared_ptr<_NamespaceModelItem>; +using ScopeModelItem = std::shared_ptr<_ScopeModelItem>; +using TemplateParameterModelItem = std::shared_ptr<_TemplateParameterModelItem>; +using TypeDefModelItem = std::shared_ptr<_TypeDefModelItem>; +using TemplateTypeAliasModelItem = std::shared_ptr<_TemplateTypeAliasModelItem>; +using VariableModelItem = std::shared_ptr<_VariableModelItem>; +using MemberModelItem = std::shared_ptr<_MemberModelItem>; using ArgumentList = QList<ArgumentModelItem>; using ClassList = QList<ClassModelItem>; diff --git a/sources/shiboken6/ApiExtractor/parser/enumvalue.cpp b/sources/shiboken6/ApiExtractor/parser/enumvalue.cpp index 165b52101..3749e16a8 100644 --- a/sources/shiboken6/ApiExtractor/parser/enumvalue.cpp +++ b/sources/shiboken6/ApiExtractor/parser/enumvalue.cpp @@ -7,12 +7,34 @@ #include <QtCore/QString> #include <QtCore/QTextStream> +using namespace Qt::StringLiterals; + QString EnumValue::toString() const { return m_type == EnumValue::Signed ? QString::number(m_value) : QString::number(m_unsignedValue); } +QString EnumValue::toHex(int fieldWidth) const +{ + QString result; + QTextStream str(&result); + // Note: Qt goofes up formatting of negative padded hex numbers, it ends up + // with "0x00-1". Write '-' before. + if (isNegative()) + str << '-'; + str << "0x" << Qt::hex; + if (fieldWidth) { + str.setFieldWidth(fieldWidth); + str.setPadChar(u'0'); + } + if (m_type == EnumValue::Signed) + str << qAbs(m_value); + else + str << m_unsignedValue; + return result; +} + void EnumValue::setValue(qint64 v) { m_value = v; @@ -25,15 +47,33 @@ void EnumValue::setUnsignedValue(quint64 v) m_type = Unsigned; } -bool EnumValue::equals(const EnumValue &rhs) const +EnumValue EnumValue::toUnsigned() const { - if (m_type != rhs.m_type) + if (m_type == Unsigned) + return *this; + EnumValue result; + result.setUnsignedValue(m_value < 0 ? quint64(-m_value) : quint64(m_value)); + return result; +} + +bool comparesEqual(const EnumValue &lhs, const EnumValue &rhs) noexcept +{ + if (lhs.m_type != rhs.m_type) return false; - return m_type == Signed ? m_value == rhs.m_value : m_unsignedValue == rhs.m_unsignedValue; + return lhs.m_type == EnumValue::Signed + ? lhs.m_value == rhs.m_value : lhs.m_unsignedValue == rhs.m_unsignedValue; +} + +void EnumValue::formatDebugHex(QDebug &d) const +{ + d << "0x" << Qt::hex; + formatDebug(d); + d << Qt::dec; } void EnumValue::formatDebug(QDebug &d) const { + if (m_type == EnumValue::Signed) d << m_value; else diff --git a/sources/shiboken6/ApiExtractor/parser/enumvalue.h b/sources/shiboken6/ApiExtractor/parser/enumvalue.h index 3aaed2b73..bbd5a712d 100644 --- a/sources/shiboken6/ApiExtractor/parser/enumvalue.h +++ b/sources/shiboken6/ApiExtractor/parser/enumvalue.h @@ -4,7 +4,9 @@ #ifndef ENUMVALUE_H #define ENUMVALUE_H -#include <QtCore/QtGlobal> +#include <QtCore/qtypes.h> +#include <QtCore/qtclasshelpermacros.h> +#include <QtCore/QtCompare> QT_FORWARD_DECLARE_CLASS(QDebug) QT_FORWARD_DECLARE_CLASS(QString) @@ -20,20 +22,29 @@ public: }; QString toString() const; + QString toHex(int fieldWidth = 0) const; Type type() { return m_type; } qint64 value() const { return m_value; } quint64 unsignedValue() const { return m_unsignedValue; } bool isNullValue() const { return m_type == Signed ? m_value == 0 : m_unsignedValue == 0u; } + bool isNegative() const { return m_type == Signed && m_value < 0; } void setValue(qint64 v); void setUnsignedValue(quint64 v); + EnumValue toUnsigned() const; + bool equals(const EnumValue &rhs) const; void formatDebug(QDebug &d) const; + void formatDebugHex(QDebug &d) const; private: + friend bool comparesEqual(const EnumValue &lhs, + const EnumValue &rhs) noexcept; + Q_DECLARE_EQUALITY_COMPARABLE(EnumValue) + #ifndef QT_NO_DEBUG_STREAM friend QDebug operator<<(QDebug, const EnumValue &); #endif @@ -47,9 +58,4 @@ private: Type m_type = Signed; }; -inline bool operator==(const EnumValue &e1, const EnumValue &e2) -{ return e1.equals(e2); } -inline bool operator!=(const EnumValue &e1, const EnumValue &e2) -{ return !e1.equals(e2); } - #endif // ENUMVALUE_H diff --git a/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp b/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp index 205f01de8..f8c5c31d8 100644 --- a/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp +++ b/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp @@ -7,6 +7,7 @@ #include "codemodel.h" #include <clangparser/clangutils.h> +#include <debughelpers_p.h> #include "qtcompat.h" @@ -46,10 +47,10 @@ public: }; }; - ReferenceType m_referenceType; + ReferenceType m_referenceType = NoReference; }; -TypeInfoData::TypeInfoData() : flags(0), m_referenceType(NoReference) +TypeInfoData::TypeInfoData() : flags(0) { } @@ -60,9 +61,8 @@ TypeInfo::TypeInfo() : d(new TypeInfoData) TypeInfo::~TypeInfo() = default; TypeInfo::TypeInfo(const TypeInfo &) = default; TypeInfo& TypeInfo::operator=(const TypeInfo &) = default; -TypeInfo::TypeInfo(TypeInfo &&) = default; -TypeInfo& TypeInfo::operator=(TypeInfo &&) = default; - +TypeInfo::TypeInfo(TypeInfo &&) noexcept = default; +TypeInfo &TypeInfo::operator=(TypeInfo &&) noexcept = default; static inline TypeInfo createType(const QString &name) { @@ -98,7 +98,7 @@ TypeInfo TypeInfo::combine(const TypeInfo &__lhs, const TypeInfo &__rhs) __result.setArrayElements(__result.arrayElements() + __rhs.arrayElements()); - const auto instantiations = __rhs.instantiations(); + const auto &instantiations = __rhs.instantiations(); for (const auto &i : instantiations) __result.addInstantiation(i); @@ -266,6 +266,12 @@ void TypeInfo::clearInstantiations() d->m_instantiations.clear(); } +bool TypeInfo::isPlain() const +{ + return d->m_constant == 0 && d->m_volatile == 0 && d->m_referenceType == NoReference + && d->m_indirections.isEmpty() && d->m_arrayElements.isEmpty(); +} + TypeInfo TypeInfo::resolveType(TypeInfo const &__type, const ScopeModelItem &__scope) { CodeModel *__model = __scope->model(); @@ -286,14 +292,14 @@ TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, con otherType.setQualifiedName(__item->qualifiedName()); } - if (TypeDefModelItem __typedef = qSharedPointerDynamicCast<_TypeDefModelItem>(__item)) { + if (TypeDefModelItem __typedef = std::dynamic_pointer_cast<_TypeDefModelItem>(__item)) { const TypeInfo combined = TypeInfo::combine(__typedef->type(), otherType); const CodeModelItem nextItem = __scope->model()->findItem(combined.qualifiedName(), __scope); if (!nextItem) return combined; // PYSIDE-362, prevent recursion on opaque structs like // typedef struct xcb_connection_t xcb_connection_t; - if (nextItem.data() ==__item.data()) { + if (nextItem.get() ==__item.get()) { std::cerr << "** WARNING Bailing out recursion of " << __FUNCTION__ << "() on " << qPrintable(__type.qualifiedName().join(u"::"_s)) << std::endl; @@ -302,7 +308,7 @@ TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, con return resolveType(nextItem, combined, __scope); } - if (TemplateTypeAliasModelItem templateTypeAlias = qSharedPointerDynamicCast<_TemplateTypeAliasModelItem>(__item)) { + if (TemplateTypeAliasModelItem templateTypeAlias = std::dynamic_pointer_cast<_TemplateTypeAliasModelItem>(__item)) { TypeInfo combined = TypeInfo::combine(templateTypeAlias->type(), otherType); // For the alias "template<typename T> using QList = QVector<T>" with @@ -313,7 +319,7 @@ TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, con for (qsizetype i = 0; i < count; ++i) aliasInstantiations[i] = concreteInstantiations.at(i); combined.setInstantiations(aliasInstantiations); - const CodeModelItem nextItem = __scope->model()->findItem(combined.qualifiedName(), __scope); + const CodeModelItem nextItem = CodeModel::findItem(combined.qualifiedName(), __scope); if (!nextItem) return combined; return resolveType(nextItem, combined, __scope); @@ -341,6 +347,10 @@ public: while (level < m_parseStack.size()) m_parseStack.pop(); TypeInfo instantiation; + if (name.startsWith(u"const ")) { + instantiation.setConstant(true); + name = name.mid(6); + } instantiation.setQualifiedName(qualifiedName(name)); top()->addInstantiation(instantiation); } @@ -361,7 +371,8 @@ private: QStack<TypeInfo *> m_parseStack; }; -QPair<qsizetype, qsizetype> TypeInfo::parseTemplateArgumentList(const QString &l, qsizetype from) +std::pair<qsizetype, qsizetype> + TypeInfo::parseTemplateArgumentList(const QString &l, qsizetype from) { return clang::parseTemplateArgumentList(l, clang::TemplateArgumentHandler(TypeInfoTemplateArgumentHandler(this)), from); } @@ -441,31 +452,28 @@ bool TypeInfoData::equals(const TypeInfoData &other) const && m_instantiations == other.m_instantiations; } -bool TypeInfo::equals(const TypeInfo &other) const + +bool comparesEqual(const TypeInfo &lhs, const TypeInfo &rhs) noexcept { - return d.data() == other.d.data() || d->equals(*other.d); + return lhs.d.data() == rhs.d.data() || lhs.d->equals(*rhs.d); } QString TypeInfo::indirectionKeyword(Indirection i) { - return i == Indirection::Pointer - ? QStringLiteral("*") : QStringLiteral("*const"); + return i == Indirection::Pointer ? "*"_L1 : "*const"_L1; } -static inline QString constQualifier() { return QStringLiteral("const"); } -static inline QString volatileQualifier() { return QStringLiteral("volatile"); } - bool TypeInfo::stripLeadingConst(QString *s) { - return stripLeadingQualifier(constQualifier(), s); + return stripLeadingQualifier("const"_L1, s); } bool TypeInfo::stripLeadingVolatile(QString *s) { - return stripLeadingQualifier(volatileQualifier(), s); + return stripLeadingQualifier("volatile"_L1, s); } -bool TypeInfo::stripLeadingQualifier(const QString &qualifier, QString *s) +bool TypeInfo::stripLeadingQualifier(QLatin1StringView qualifier, QString *s) { // "const int x" const auto qualifierSize = qualifier.size(); @@ -558,16 +566,6 @@ void TypeInfo::formatTypeSystemSignature(QTextStream &str) const } #ifndef QT_NO_DEBUG_STREAM -template <class It> -void formatSequence(QDebug &d, It i1, It i2, const char *separator=", ") -{ - for (It i = i1; i != i2; ++i) { - if (i != i1) - d << separator; - d << *i; - } -} - void TypeInfo::formatDebug(QDebug &debug) const { debug << '"'; diff --git a/sources/shiboken6/ApiExtractor/parser/typeinfo.h b/sources/shiboken6/ApiExtractor/parser/typeinfo.h index cf3576eb6..e4f363b67 100644 --- a/sources/shiboken6/ApiExtractor/parser/typeinfo.h +++ b/sources/shiboken6/ApiExtractor/parser/typeinfo.h @@ -10,8 +10,11 @@ #include <QtCore/QString> #include <QtCore/QSharedDataPointer> +#include <QtCore/QtCompare> #include <QtCore/QStringList> +#include <utility> + QT_FORWARD_DECLARE_CLASS(QDebug) QT_FORWARD_DECLARE_CLASS(QTextStream) @@ -28,8 +31,8 @@ public: ~TypeInfo(); TypeInfo(const TypeInfo &); TypeInfo& operator=(const TypeInfo &); - TypeInfo(TypeInfo &&); - TypeInfo& operator=(TypeInfo &&); + TypeInfo(TypeInfo &&) noexcept; + TypeInfo &operator=(TypeInfo &&) noexcept; static TypeInfo voidType(); static TypeInfo varArgsType(); @@ -77,11 +80,12 @@ public: void addInstantiation(const TypeInfo &i); void clearInstantiations(); - bool isStdType() const; + bool isPlain() const; // neither const,volatile, no indirections/references, array - QPair<qsizetype, qsizetype> parseTemplateArgumentList(const QString &l, qsizetype from = 0); + bool isStdType() const; - bool equals(const TypeInfo &other) const; + std::pair<qsizetype, qsizetype> + parseTemplateArgumentList(const QString &l, qsizetype from = 0); // ### arrays and templates?? @@ -100,12 +104,16 @@ public: static bool stripLeadingConst(QString *s); static bool stripLeadingVolatile(QString *s); - static bool stripLeadingQualifier(const QString &qualifier, QString *s); + static bool stripLeadingQualifier(QLatin1StringView qualifier, QString *s); static void stripQualifiers(QString *s); void simplifyStdType(); private: + friend bool comparesEqual(const TypeInfo &lhs, + const TypeInfo &rhs) noexcept; + Q_DECLARE_EQUALITY_COMPARABLE(TypeInfo) + QSharedDataPointer<TypeInfoData> d; friend class TypeInfoTemplateArgumentHandler; @@ -113,12 +121,6 @@ private: static TypeInfo resolveType(CodeModelItem item, TypeInfo const &__type, const ScopeModelItem &__scope); }; -inline bool operator==(const TypeInfo &t1, const TypeInfo &t2) -{ return t1.equals(t2); } - -inline bool operator!=(const TypeInfo &t1, const TypeInfo &t2) -{ return !t1.equals(t2); } - #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const TypeInfo &t); #endif diff --git a/sources/shiboken6/ApiExtractor/predefined_templates.cpp b/sources/shiboken6/ApiExtractor/predefined_templates.cpp index be3dd9319..992f735ac 100644 --- a/sources/shiboken6/ApiExtractor/predefined_templates.cpp +++ b/sources/shiboken6/ApiExtractor/predefined_templates.cpp @@ -39,20 +39,37 @@ while (true) { return result; } -static const char stlMapKeyAccessor[] = "->first"; -static const char stlMapValueAccessor[] = "->second"; -static const char qtMapKeyAccessor[] = ".key()"; -static const char qtMapValueAccessor[] = ".value()"; +// Convert a sequence to a limited/fixed array +static QString pySequenceToCppArray() +{ + return uR"(Shiboken::AutoDecRef it(PyObject_GetIter(%in)); +for (auto oit = std::begin(%out), oend = std::end(%out); oit != oend; ++oit) { + Shiboken::AutoDecRef pyItem(PyIter_Next(it.object())); + if (pyItem.isNull()) { + if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration)) + PyErr_Clear(); + break; + } + %OUTTYPE_0 cppItem = %CONVERTTOCPP[%OUTTYPE_0](pyItem); + *oit = cppItem; +} +)"_s; +} + +static constexpr auto stlMapKeyAccessor = "->first"_L1; +static constexpr auto stlMapValueAccessor = "->second"_L1; +static constexpr auto qtMapKeyAccessor = ".key()"_L1; +static constexpr auto qtMapValueAccessor = ".value()"_L1; static QString cppMapToPyDict(bool isQMap) { return uR"(PyObject *%out = PyDict_New(); -for (auto it = %in.cbegin(), end = %in.cend(); it != end; ++it) { +for (auto it = std::cbegin(%in), end = std::cend(%in); it != end; ++it) { const auto &key = it)"_s - + QLatin1StringView(isQMap ? qtMapKeyAccessor : stlMapKeyAccessor) + + (isQMap ? qtMapKeyAccessor : stlMapKeyAccessor) + uR"(; const auto &value = it)"_s - + QLatin1StringView(isQMap ? qtMapValueAccessor : stlMapValueAccessor) + + (isQMap ? qtMapValueAccessor : stlMapValueAccessor) + uR"(; PyObject *pyKey = %CONVERTTOPYTHON[%INTYPE_0](key); PyObject *pyValue = %CONVERTTOPYTHON[%INTYPE_1](value); @@ -84,9 +101,9 @@ while (PyDict_Next(%in, &pos, &key, &value)) { static QString cppMultiMapToPyDict(bool isQMultiMap) { return uR"(PyObject *%out = PyDict_New(); - for (auto it = %in.cbegin(), end = %in.cend(); it != end; ) { + for (auto it = std::cbegin(%in), end = std::cend(%in); it != end; ) { const auto &key = it)"_s - + QLatin1StringView(isQMultiMap ? qtMapKeyAccessor : stlMapKeyAccessor) + + (isQMultiMap ? qtMapKeyAccessor : stlMapKeyAccessor) + uR"(; PyObject *pyKey = %CONVERTTOPYTHON[%INTYPE_0](key); auto upper = %in.)"_s @@ -110,9 +127,9 @@ static QString cppMultiMapToPyDict(bool isQMultiMap) static QString cppMultiHashToPyDict(bool isQMultiHash) { return uR"(PyObject *%out = PyDict_New(); - for (auto it = %in.cbegin(), end = %in.cend(); it != end; ) { + for (auto it = std::cbegin(%in), end = std::cend(%in); it != end; ) { const auto &key = it)"_s - + QLatin1StringView(isQMultiHash ? qtMapKeyAccessor : stlMapKeyAccessor) + + (isQMultiHash ? qtMapKeyAccessor : stlMapKeyAccessor) + uR"(; PyObject *pyKey = %CONVERTTOPYTHON[%INTYPE_0](key); auto range = %in.equal_range(key); @@ -174,7 +191,7 @@ return %out; {u"shiboken_conversion_cppsequence_to_pylist"_s, uR"(PyObject *%out = PyList_New(Py_ssize_t(%in.size())); Py_ssize_t idx = 0; -for (auto it = %in.cbegin(), end = %in.cend(); it != end; ++it, ++idx) { +for (auto it = std::cbegin(%in), end = std::cend(%in); it != end; ++it, ++idx) { const auto &cppItem = *it; PyList_SET_ITEM(%out, idx, %CONVERTTOPYTHON[%INTYPE_0](cppItem)); } @@ -192,6 +209,8 @@ return %out;)"_s}, pySequenceToCppContainer(u"push_back"_s, false)}, {u"shiboken_conversion_pyiterable_to_cppsequentialcontainer_reserve"_s, pySequenceToCppContainer(u"push_back"_s, true)}, + {u"shiboken_conversion_pyiterable_to_cpparray"_s, + pySequenceToCppArray()}, {u"shiboken_conversion_pyiterable_to_cppsetcontainer"_s, pySequenceToCppContainer(u"insert"_s, false)}, @@ -233,19 +252,25 @@ QByteArray containerTypeSystemSnippet(const char *name, const char *type, const char *targetToNativeType, const char *targetToNative) { - return QByteArrayLiteral("<container-type name=\"") + QByteArray result = QByteArrayLiteral("<container-type name=\"") + name + QByteArrayLiteral("\" type=\"") + type + R"("> <include file-name=")" + include + R"(" location="global"/> <conversion-rule> <native-to-target> <insert-template name=")" + nativeToTarget + R"("/> </native-to-target> - <target-to-native> - <add-conversion type=")" + targetToNativeType + R"("> - <insert-template name=")" + targetToNative + R"("/> +)"; + if (targetToNativeType != nullptr) { + result += QByteArrayLiteral(R"( <target-to-native> + <add-conversion type=")") + targetToNativeType + + QByteArrayLiteral(R"("> + <insert-template name=")") + targetToNative + QByteArrayLiteral(R"("/> </add-conversion> </target-to-native> - </conversion-rule> +)"); + } +result += QByteArrayLiteral(R"( </conversion-rule> </container-type> -)"; +)"); + return result; } diff --git a/sources/shiboken6/ApiExtractor/predefined_templates.h b/sources/shiboken6/ApiExtractor/predefined_templates.h index 2519f65d9..0cc2c7f32 100644 --- a/sources/shiboken6/ApiExtractor/predefined_templates.h +++ b/sources/shiboken6/ApiExtractor/predefined_templates.h @@ -21,7 +21,7 @@ const PredefinedTemplates &predefinedTemplates(); QByteArray containerTypeSystemSnippet(const char *name, const char *type, const char *include, const char *nativeToTarget, - const char *targetToNativeType, - const char *targetToNative); + const char *targetToNativeType = nullptr, + const char *targetToNative = nullptr); #endif // PREDEFINED_TEMPLATES_H diff --git a/sources/shiboken6/ApiExtractor/propertyspec.cpp b/sources/shiboken6/ApiExtractor/propertyspec.cpp index 1c86cacf6..32b756fad 100644 --- a/sources/shiboken6/ApiExtractor/propertyspec.cpp +++ b/sources/shiboken6/ApiExtractor/propertyspec.cpp @@ -59,8 +59,8 @@ QPropertySpec::QPropertySpec(const TypeSystemProperty &ts, QPropertySpec::QPropertySpec(const QPropertySpec &) = default; QPropertySpec &QPropertySpec::operator=(const QPropertySpec &) = default; -QPropertySpec::QPropertySpec(QPropertySpec &&) = default; -QPropertySpec &QPropertySpec::operator=(QPropertySpec &&) = default; +QPropertySpec::QPropertySpec(QPropertySpec &&) noexcept = default; +QPropertySpec &QPropertySpec::operator=(QPropertySpec &&) noexcept = default; QPropertySpec::~QPropertySpec() = default; const AbstractMetaType &QPropertySpec::type() const @@ -189,14 +189,15 @@ void QPropertySpec::setGenerateGetSetDef(bool generateGetSetDef) TypeSystemProperty QPropertySpec::typeSystemPropertyFromQ_Property(const QString &declarationIn, QString *errorMessage) { - enum class PropertyToken { None, Read, Write, Designable, Reset, Notify }; + enum class PropertyToken { None, Read, Write, Designable, Reset, Notify, Member }; static const QHash<QString, PropertyToken> tokenLookup = { - {QStringLiteral("READ"), PropertyToken::Read}, - {QStringLiteral("WRITE"), PropertyToken::Write}, - {QStringLiteral("DESIGNABLE"), PropertyToken::Designable}, - {QStringLiteral("RESET"), PropertyToken::Reset}, - {QStringLiteral("NOTIFY"), PropertyToken::Notify} + {"READ"_L1, PropertyToken::Read}, + {"WRITE"_L1, PropertyToken::Write}, + {"DESIGNABLE"_L1, PropertyToken::Designable}, + {"RESET"_L1, PropertyToken::Reset}, + {"NOTIFY"_L1, PropertyToken::Notify}, + {"MEMBER"_L1, PropertyToken::Member} }; errorMessage->clear(); @@ -242,17 +243,21 @@ TypeSystemProperty QPropertySpec::typeSystemPropertyFromQ_Property(const QString case PropertyToken::Notify: result.notify = propertyTokens.at(pos + 1); break; + case PropertyToken::Member: + // Ignore MEMBER tokens introduced by QTBUG-16852 as Python + // properties are anyways generated for fields. + return {}; case PropertyToken::None: break; } } - const int namePos = firstToken - 1; + const auto namePos = firstToken - 1; result.name = propertyTokens.at(namePos); result.type = propertyTokens.constFirst(); - for (int pos = 1; pos < namePos; ++pos) + for (qsizetype pos = 1; pos < namePos; ++pos) result.type += u' ' + propertyTokens.at(pos); // Fix errors like "Q_PROPERTY(QXYSeries *series .." to be of type "QXYSeries*" @@ -269,7 +274,7 @@ TypeSystemProperty QPropertySpec::typeSystemPropertyFromQ_Property(const QString // the AbstractMetaType from the type string. std::optional<QPropertySpec> QPropertySpec::fromTypeSystemProperty(AbstractMetaBuilderPrivate *b, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, const TypeSystemProperty &ts, const QStringList &scopes, QString *errorMessage) @@ -302,7 +307,7 @@ std::optional<QPropertySpec> // via TypeSystemProperty. std::optional<QPropertySpec> QPropertySpec::parseQ_Property(AbstractMetaBuilderPrivate *b, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, const QString &declarationIn, const QStringList &scopes, QString *errorMessage) diff --git a/sources/shiboken6/ApiExtractor/propertyspec.h b/sources/shiboken6/ApiExtractor/propertyspec.h index 907668cb1..9e2e0f3d4 100644 --- a/sources/shiboken6/ApiExtractor/propertyspec.h +++ b/sources/shiboken6/ApiExtractor/propertyspec.h @@ -6,6 +6,7 @@ class AbstractMetaType; +#include "abstractmetalang_typedefs.h" #include "typesystem_typedefs.h" #include <QtCore/QStringList> @@ -32,8 +33,8 @@ public: const AbstractMetaType &type); QPropertySpec(const QPropertySpec &); QPropertySpec &operator=(const QPropertySpec &); - QPropertySpec(QPropertySpec &&); - QPropertySpec &operator=(QPropertySpec &&); + QPropertySpec(QPropertySpec &&) noexcept; + QPropertySpec &operator=(QPropertySpec &&) noexcept; ~QPropertySpec(); static TypeSystemProperty typeSystemPropertyFromQ_Property(const QString &declarationIn, @@ -42,14 +43,14 @@ public: static std::optional<QPropertySpec> fromTypeSystemProperty(AbstractMetaBuilderPrivate *b, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, const TypeSystemProperty &ts, const QStringList &scopes, QString *errorMessage); static std::optional<QPropertySpec> parseQ_Property(AbstractMetaBuilderPrivate *b, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, const QString &declarationIn, const QStringList &scopes, QString *errorMessage); diff --git a/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp b/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp index 75ac227b8..64d44378b 100644 --- a/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp +++ b/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp @@ -6,10 +6,15 @@ #include <QtCore/QDebug> +TextStream &operator<<(TextStream &str, const castToPyCFunction &c) +{ + str << "reinterpret_cast<PyCFunction>(" << c.m_function << ')'; + return str; +} + TextStream &operator<<(TextStream &s, const PyMethodDefEntry &e) { - s << "{\"" << e.name << "\", reinterpret_cast<PyCFunction>(" - << e.function << "), "; + s << "{\"" << e.name << "\", " << castToPyCFunction(e.function) <<", "; if (e.methFlags.isEmpty()) { s << '0'; } else { diff --git a/sources/shiboken6/ApiExtractor/pymethoddefentry.h b/sources/shiboken6/ApiExtractor/pymethoddefentry.h index 54eaa4ce1..a8694eb30 100644 --- a/sources/shiboken6/ApiExtractor/pymethoddefentry.h +++ b/sources/shiboken6/ApiExtractor/pymethoddefentry.h @@ -11,6 +11,14 @@ QT_FORWARD_DECLARE_CLASS(QDebug) class TextStream; +struct castToPyCFunction +{ + explicit castToPyCFunction(QAnyStringView function) noexcept : + m_function(function) {} + + QAnyStringView m_function; +}; + struct PyMethodDefEntry { QString name; @@ -21,6 +29,7 @@ struct PyMethodDefEntry using PyMethodDefEntries = QList<PyMethodDefEntry>; +TextStream &operator<<(TextStream &str, const castToPyCFunction &e); TextStream &operator<<(TextStream &s, const PyMethodDefEntry &e); TextStream &operator<<(TextStream &s, const PyMethodDefEntries &e); diff --git a/sources/shiboken6/ApiExtractor/qtcompat.h b/sources/shiboken6/ApiExtractor/qtcompat.h index 9627bb76c..3837dcfd2 100644 --- a/sources/shiboken6/ApiExtractor/qtcompat.h +++ b/sources/shiboken6/ApiExtractor/qtcompat.h @@ -4,7 +4,7 @@ #ifndef QTCOMPAT_H #define QTCOMPAT_H -#include <QtCore/QtGlobal> +#include <QtCore/qtconfigmacros.h> #if QT_VERSION < 0x060400 diff --git a/sources/shiboken6/ApiExtractor/qtdocparser.cpp b/sources/shiboken6/ApiExtractor/qtdocparser.cpp index 8daf1ad85..5bd99bbd8 100644 --- a/sources/shiboken6/ApiExtractor/qtdocparser.cpp +++ b/sources/shiboken6/ApiExtractor/qtdocparser.cpp @@ -15,6 +15,8 @@ #include "reporthandler.h" #include "flagstypeentry.h" #include "complextypeentry.h" +#include "functiontypeentry.h" +#include "enumtypeentry.h" #include "qtcompat.h" @@ -26,8 +28,9 @@ using namespace Qt::StringLiterals; enum { debugFunctionSearch = 0 }; -static inline QString briefStartElement() { return QStringLiteral("<brief>"); } -static inline QString briefEndElement() { return QStringLiteral("</brief>"); } +constexpr auto briefStartElement = "<brief>"_L1; +constexpr auto briefEndElement = "</brief>"_L1; +constexpr auto webxmlSuffix = ".webxml"_L1; Documentation QtDocParser::retrieveModuleDocumentation() { @@ -57,7 +60,7 @@ static void formatFunctionUnqualifiedArgTypeQuery(QTextStream &str, case AbstractMetaType::FlagsPattern: { // Modify qualified name "QFlags<Qt::AlignmentFlag>" with name "Alignment" // to "Qt::Alignment" as seen by qdoc. - const auto flagsEntry = qSharedPointerCast<const FlagsTypeEntry>(metaType.typeEntry()); + const auto flagsEntry = std::static_pointer_cast<const FlagsTypeEntry>(metaType.typeEntry()); QString name = flagsEntry->qualifiedCppName(); if (name.endsWith(u'>') && name.startsWith(u"QFlags<")) { const int lastColon = name.lastIndexOf(u':'); @@ -102,7 +105,7 @@ static QString formatFunctionArgTypeQuery(const AbstractMetaType &metaType) QString QtDocParser::functionDocumentation(const QString &sourceFileName, const ClassDocumentation &classDocumentation, - const AbstractMetaClass *metaClass, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaFunctionCPtr &func, QString *errorMessage) { @@ -112,14 +115,14 @@ QString QtDocParser::functionDocumentation(const QString &sourceFileName, queryFunctionDocumentation(sourceFileName, classDocumentation, metaClass, func, errorMessage); - const auto funcModifs = DocParser::getDocModifications(metaClass, func); + const auto funcModifs = DocParser::getXpathDocModifications(func, metaClass); return docString.isEmpty() || funcModifs.isEmpty() ? docString : applyDocModifications(funcModifs, docString); } QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName, const ClassDocumentation &classDocumentation, - const AbstractMetaClass *metaClass, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaFunctionCPtr &func, QString *errorMessage) { @@ -127,7 +130,7 @@ QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName, FunctionDocumentationList candidates = classDocumentation.findFunctionCandidates(func->name(), func->isConstant()); if (candidates.isEmpty()) { - *errorMessage = msgCannotFindDocumentation(sourceFileName, func.data()) + *errorMessage = msgCannotFindDocumentation(sourceFileName, func.get()) + u" (no matches)"_s; return {}; } @@ -172,13 +175,13 @@ QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName, candidates.erase(pend, candidates.end()); if (candidates.size() == 1) { const auto &match = candidates.constFirst(); - QTextStream(errorMessage) << msgFallbackForDocumentation(sourceFileName, func.data()) + QTextStream(errorMessage) << msgFallbackForDocumentation(sourceFileName, func.get()) << "\n Falling back to \"" << match.signature << "\" obtained by matching the argument count only."; return candidates.constFirst().description; } - QTextStream(errorMessage) << msgCannotFindDocumentation(sourceFileName, func.data()) + QTextStream(errorMessage) << msgCannotFindDocumentation(sourceFileName, func.get()) << " (" << candidates.size() << " candidates matching the argument count)"; return {}; } @@ -187,29 +190,100 @@ QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName, // from the source. static QString extractBrief(QString *value) { - const auto briefStart = value->indexOf(briefStartElement()); + const auto briefStart = value->indexOf(briefStartElement); if (briefStart < 0) return {}; - const auto briefEnd = value->indexOf(briefEndElement(), - briefStart + briefStartElement().size()); + const auto briefEnd = value->indexOf(briefEndElement, + briefStart + briefStartElement.size()); if (briefEnd < briefStart) return {}; - const auto briefLength = briefEnd + briefEndElement().size() - briefStart; + const auto briefLength = briefEnd + briefEndElement.size() - briefStart; QString briefValue = value->mid(briefStart, briefLength); - briefValue.insert(briefValue.size() - briefEndElement().size(), + briefValue.insert(briefValue.size() - briefEndElement.size(), u"<rst> More_...</rst>"_s); value->remove(briefStart, briefLength); return briefValue; } -void QtDocParser::fillDocumentation(AbstractMetaClass *metaClass) +// Find the webxml file for global functions/enums +// by the doc-file typesystem attribute or via include file. +static QString findGlobalWebXmLFile(const QString &documentationDataDirectory, + const QString &docFile, + const Include &include) +{ + QString result; + if (!docFile.isEmpty()) { + result = documentationDataDirectory + u'/' + docFile; + if (!result.endsWith(webxmlSuffix)) + result += webxmlSuffix; + return QFileInfo::exists(result) ? result : QString{}; + } + if (include.name().isEmpty()) + return {}; + // qdoc "\headerfile <QtLogging>" directive produces "qtlogging.webxml" + result = documentationDataDirectory + u'/' + + QFileInfo(include.name()).baseName() + webxmlSuffix; + if (QFileInfo::exists(result)) + return result; + // qdoc "\headerfile <qdrawutil.h>" produces "qdrawutil-h.webxml" + result.insert(result.size() - webxmlSuffix.size(), "-h"_L1); + return QFileInfo::exists(result) ? result : QString{}; +} + +void QtDocParser::fillGlobalFunctionDocumentation(const AbstractMetaFunctionPtr &f) +{ + auto te = f->typeEntry(); + if (te == nullptr) + return; + + const QString sourceFileName = + findGlobalWebXmLFile(documentationDataDirectory(), te->docFile(), te->include()); + if (sourceFileName.isEmpty()) + return; + + QString errorMessage; + auto classDocumentationO = parseWebXml(sourceFileName, &errorMessage); + if (!classDocumentationO.has_value()) { + qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); + return; + } + const QString detailed = + functionDocumentation(sourceFileName, classDocumentationO.value(), + {}, f, &errorMessage); + if (!errorMessage.isEmpty()) + qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); + const Documentation documentation(detailed, {}); + f->setDocumentation(documentation); +} + +void QtDocParser::fillGlobalEnumDocumentation(AbstractMetaEnum &e) +{ + auto te = e.typeEntry(); + const QString sourceFileName = + findGlobalWebXmLFile(documentationDataDirectory(), te->docFile(), te->include()); + if (sourceFileName.isEmpty()) + return; + + QString errorMessage; + auto classDocumentationO = parseWebXml(sourceFileName, &errorMessage); + if (!classDocumentationO.has_value()) { + qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); + return; + } + if (!extractEnumDocumentation(classDocumentationO.value(), e)) { + qCWarning(lcShibokenDoc, "%s", + qPrintable(msgCannotFindDocumentation(sourceFileName, {}, e, {}))); + } +} + +void QtDocParser::fillDocumentation(const AbstractMetaClassPtr &metaClass) { if (!metaClass) return; - auto *context = metaClass->enclosingClass(); - while(context) { - if (context->enclosingClass() == nullptr) + auto context = metaClass->enclosingClass(); + while (context) { + if (!context->enclosingClass()) break; context = context->enclosingClass(); } @@ -218,9 +292,9 @@ void QtDocParser::fillDocumentation(AbstractMetaClass *metaClass) + metaClass->qualifiedCppName().toLower(); sourceFileRoot.replace(u"::"_s, u"-"_s); - QFileInfo sourceFile(sourceFileRoot + QStringLiteral(".webxml")); + QFileInfo sourceFile(sourceFileRoot + webxmlSuffix); if (!sourceFile.exists()) - sourceFile.setFile(sourceFileRoot + QStringLiteral(".xml")); + sourceFile.setFile(sourceFileRoot + ".xml"_L1); if (!sourceFile.exists()) { qCWarning(lcShibokenDoc).noquote().nospace() << "Can't find qdoc file for class " << metaClass->name() << ", tried: " @@ -231,18 +305,19 @@ void QtDocParser::fillDocumentation(AbstractMetaClass *metaClass) const QString sourceFileName = sourceFile.absoluteFilePath(); QString errorMessage; - const ClassDocumentation classDocumentation = parseWebXml(sourceFileName, &errorMessage); - if (!classDocumentation) { + const auto classDocumentationO = parseWebXml(sourceFileName, &errorMessage); + if (!classDocumentationO.has_value()) { qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); return; } + const auto &classDocumentation = classDocumentationO.value(); for (const auto &p : classDocumentation.properties) { Documentation doc(p.description, p.brief); metaClass->setPropertyDocumentation(p.name, doc); } - QString docString = applyDocModifications(metaClass->typeEntry()->docModifications(), + QString docString = applyDocModifications(DocParser::getXpathDocModifications(metaClass), classDocumentation.description); if (docString.isEmpty()) { @@ -267,7 +342,7 @@ void QtDocParser::fillDocumentation(AbstractMetaClass *metaClass) if (!errorMessage.isEmpty()) qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); const Documentation documentation(detailed, {}); - qSharedPointerConstCast<AbstractMetaFunction>(func)->setDocumentation(documentation); + std::const_pointer_cast<AbstractMetaFunction>(func)->setDocumentation(documentation); } #if 0 // Fields @@ -283,28 +358,35 @@ void QtDocParser::fillDocumentation(AbstractMetaClass *metaClass) #endif // Enums for (AbstractMetaEnum &meta_enum : metaClass->enums()) { - Documentation enumDoc; - const auto index = classDocumentation.indexOfEnum(meta_enum.name()); - if (index != -1) { - QString doc = classDocumentation.enums.at(index).description; - const auto firstPara = doc.indexOf(u"<para>"); - if (firstPara != -1) { - const QString baseClass = QtDocParser::enumBaseClass(meta_enum); - if (baseClass != u"Enum") { - const QString note = u"(inherits <teletype>enum."_s + baseClass - + u"</teletype>) "_s; - doc.insert(firstPara + 6, note); - } - } - enumDoc.setValue(doc); - meta_enum.setDocumentation(enumDoc); - } else { + if (!extractEnumDocumentation(classDocumentation, meta_enum)) { qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotFindDocumentation(sourceFileName, metaClass, meta_enum, {}))); } } } +bool QtDocParser::extractEnumDocumentation(const ClassDocumentation &classDocumentation, + AbstractMetaEnum &meta_enum) +{ + Documentation enumDoc; + const auto index = classDocumentation.indexOfEnum(meta_enum.name()); + if (index == -1) + return false; + QString doc = classDocumentation.enums.at(index).description; + const auto firstPara = doc.indexOf(u"<para>"); + if (firstPara != -1) { + const QString baseClass = QtDocParser::enumBaseClass(meta_enum); + if (baseClass != "Enum"_L1) { + const QString note = "(inherits <teletype>enum."_L1 + baseClass + + "</teletype>) "_L1; + doc.insert(firstPara + 6, note); + } + } + enumDoc.setValue(doc); + meta_enum.setDocumentation(enumDoc); + return true; +} + static QString qmlReferenceLink(const QFileInfo &qmlModuleFi) { QString result; diff --git a/sources/shiboken6/ApiExtractor/qtdocparser.h b/sources/shiboken6/ApiExtractor/qtdocparser.h index 402664217..f6ba5e47a 100644 --- a/sources/shiboken6/ApiExtractor/qtdocparser.h +++ b/sources/shiboken6/ApiExtractor/qtdocparser.h @@ -12,22 +12,28 @@ class QtDocParser : public DocParser { public: QtDocParser() = default; - void fillDocumentation(AbstractMetaClass *metaClass) override; + void fillDocumentation(const AbstractMetaClassPtr &metaClass) override; + void fillGlobalFunctionDocumentation(const AbstractMetaFunctionPtr &f) override; + void fillGlobalEnumDocumentation(AbstractMetaEnum &e) override; + Documentation retrieveModuleDocumentation() override; Documentation retrieveModuleDocumentation(const QString& name) override; private: static QString functionDocumentation(const QString &sourceFileName, const ClassDocumentation &classDocumentation, - const AbstractMetaClass *metaClass, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaFunctionCPtr &func, QString *errorMessage); static QString queryFunctionDocumentation(const QString &sourceFileName, const ClassDocumentation &classDocumentation, - const AbstractMetaClass *metaClass, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaFunctionCPtr &func, QString *errorMessage); + static bool extractEnumDocumentation(const ClassDocumentation &classDocumentation, + AbstractMetaEnum &meta_enum); + }; #endif // QTDOCPARSER_H diff --git a/sources/shiboken6/ApiExtractor/reporthandler.cpp b/sources/shiboken6/ApiExtractor/reporthandler.cpp index 2fc7b47b7..23066ba21 100644 --- a/sources/shiboken6/ApiExtractor/reporthandler.cpp +++ b/sources/shiboken6/ApiExtractor/reporthandler.cpp @@ -33,6 +33,7 @@ static ReportHandler::DebugLevel m_debugLevel = ReportHandler::NoDebug; static QSet<QString> m_reportedWarnings; static QString m_prefix; static bool m_withinProgress = false; +static QByteArray m_progressMessage; static int m_step_warning = 0; static QElapsedTimer m_timer; @@ -147,9 +148,13 @@ void ReportHandler::startProgress(const QByteArray& str) endProgress(); m_withinProgress = true; - const auto ts = '[' + timeStamp() + ']'; - std::printf("%s %8s %-60s", qPrintable(m_prefix), ts.constData(), str.constData()); - std::fflush(stdout); + m_progressMessage = str; +} + +static void indentStdout(qsizetype n) +{ + for (qsizetype i = 0; i < n; ++i) + fputc(' ', stdout); } void ReportHandler::endProgress() @@ -158,11 +163,23 @@ void ReportHandler::endProgress() return; m_withinProgress = false; + + std::fputs(m_prefix.toUtf8().constData(), stdout); + const auto ts = timeStamp(); + if (ts.size() < 6) + indentStdout(6 - ts.size()); + std::fputs(" [", stdout); + std::fputs(ts.constData(), stdout); + std::fputs("] ", stdout); + std::fputs(m_progressMessage.constData(), stdout); + if (m_progressMessage.size() < 60) + indentStdout(60 - m_progressMessage.size()); const char *endMessage = m_step_warning == 0 ? "[" COLOR_GREEN "OK" COLOR_END "]\n" : "[" COLOR_YELLOW "WARNING" COLOR_END "]\n"; std::fputs(endMessage, stdout); std::fflush(stdout); + m_progressMessage.clear(); m_step_warning = 0; } diff --git a/sources/shiboken6/ApiExtractor/tests/CMakeLists.txt b/sources/shiboken6/ApiExtractor/tests/CMakeLists.txt index 8abc88d6f..76c014fbb 100644 --- a/sources/shiboken6/ApiExtractor/tests/CMakeLists.txt +++ b/sources/shiboken6/ApiExtractor/tests/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + set(CMAKE_AUTORCC ON) macro(declare_test testname) diff --git a/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp b/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp index 8021810b3..4b5da0c3a 100644 --- a/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp @@ -23,7 +23,7 @@ void TestAbstractMetaClass::testClassName() <value-type name="ClassName"/> </typesystem>)"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); QCOMPARE(classes[0]->name(), u"ClassName"); @@ -39,7 +39,7 @@ void TestAbstractMetaClass::testClassNameUnderNamespace() </namespace-type> </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); // 1 namespace + 1 class if (classes.constFirst()->name() != u"ClassName") @@ -71,7 +71,7 @@ void TestAbstractMetaClass::testClassNameUnderNamespace() // QVERIFY(classes[0]->hasNonPrivateConstructor()); } -static AbstractMetaFunctionCList virtualFunctions(const AbstractMetaClass *c) +static AbstractMetaFunctionCList virtualFunctions(const AbstractMetaClassCPtr &c) { AbstractMetaFunctionCList result; const auto &functions = c->functions(); @@ -110,13 +110,13 @@ public: </typesystem> )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 4); - auto *a = AbstractMetaClass::findClass(classes, u"A"); - auto *b = AbstractMetaClass::findClass(classes, u"B"); - auto *c = AbstractMetaClass::findClass(classes, u"C"); - const AbstractMetaClass *f = AbstractMetaClass::findClass(classes, u"F"); + const auto a = AbstractMetaClass::findClass(classes, "A"); + const auto b = AbstractMetaClass::findClass(classes, "B"); + const auto c = AbstractMetaClass::findClass(classes, "C"); + const auto f = AbstractMetaClass::findClass(classes, "F"); QVERIFY(f); QCOMPARE(a->baseClass(), nullptr); @@ -159,11 +159,11 @@ public: const auto funcF = virtualFunctionsF.constFirst(); QCOMPARE(funcA->ownerClass(), a); - QVERIFY(funcC->attributes().testFlag(AbstractMetaFunction::VirtualCppMethod)); + QVERIFY(funcC->isVirtual()); QCOMPARE(funcB->ownerClass(), b); QCOMPARE(funcC->ownerClass(), c); - QVERIFY(funcC->attributes().testFlag(AbstractMetaFunction::OverriddenCppMethod)); - QVERIFY(funcF->attributes().testFlag(AbstractMetaFunction::FinalCppMethod)); + QVERIFY(funcC->cppAttributes().testFlag(FunctionAttribute::Override)); + QVERIFY(funcF->cppAttributes().testFlag(FunctionAttribute::Final)); QCOMPARE(funcA->declaringClass(), a); QCOMPARE(funcB->declaringClass(), a); @@ -194,12 +194,12 @@ class Derived : public Base {}; </typesystem> )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto base = AbstractMetaClass::findClass(classes, u"Base"); + const auto base = AbstractMetaClass::findClass(classes, "Base"); QVERIFY(base); QVERIFY(base->isPolymorphic()); - auto derived = AbstractMetaClass::findClass(classes, u"Derived"); + const auto derived = AbstractMetaClass::findClass(classes, "Derived"); QVERIFY(derived); QVERIFY(derived->isPolymorphic()); } @@ -218,10 +218,10 @@ void TestAbstractMetaClass::testDefaultValues() </value-type> </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); const auto candidates = classA->queryFunctionsByName(u"method"_s); QCOMPARE(candidates.size(), 1); const auto &method = candidates.constFirst(); @@ -248,10 +248,10 @@ void TestAbstractMetaClass::testModifiedDefaultValues() </value-type> </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); const auto methodMatches = classA->queryFunctionsByName(u"method"_s); QCOMPARE(methodMatches.size(), 1); const auto method = methodMatches.constFirst(); @@ -274,13 +274,13 @@ void TestAbstractMetaClass::testInnerClassOfAPolymorphicOne() </object-type> </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QVERIFY(classA->isPolymorphic()); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"A::B"); + const auto classB = AbstractMetaClass::findClass(classes, "A::B"); QVERIFY(classB); QVERIFY(!classB->isPolymorphic()); } @@ -302,15 +302,15 @@ void TestAbstractMetaClass::testForwardDeclaredInnerClass() </value-type> </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"A::B"); + const auto classB = AbstractMetaClass::findClass(classes, "A::B"); QVERIFY(classB); - const auto fooF = classB->findFunction(u"foo"); - QVERIFY(!fooF.isNull()); + const auto fooF = classB->findFunction("foo"); + QVERIFY(fooF); } void TestAbstractMetaClass::testSpecialFunctions() @@ -333,11 +333,11 @@ void TestAbstractMetaClass::testSpecialFunctions() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); auto ctors = classA->queryFunctions(FunctionQueryOption::AnyConstructor); QCOMPARE(ctors.size(), 2); @@ -348,7 +348,7 @@ void TestAbstractMetaClass::testSpecialFunctions() QCOMPARE(assigmentOps.constFirst()->functionType(), AbstractMetaFunction::AssignmentOperatorFunction); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); ctors = classB->queryFunctions(FunctionQueryOption::AnyConstructor); QCOMPARE(ctors.size(), 2); @@ -399,11 +399,11 @@ void TestAbstractMetaClass::testClassDefaultConstructors() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 6); - auto *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->functions().size(), 2); @@ -417,28 +417,28 @@ void TestAbstractMetaClass::testClassDefaultConstructors() QCOMPARE(ctors[1]->arguments().size(), 1); QCOMPARE(ctors[1]->minimalSignature(), u"A(A)"); - auto *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); QCOMPARE(classB->functions().size(), 2); QCOMPARE(classB->functions().constFirst()->minimalSignature(), u"B()"); - auto *classC = AbstractMetaClass::findClass(classes, u"C"); + const auto classC = AbstractMetaClass::findClass(classes, "C"); QVERIFY(classC); QCOMPARE(classC->functions().size(), 1); QCOMPARE(classC->functions().constFirst()->minimalSignature(), u"C(C)"); - auto *classD = AbstractMetaClass::findClass(classes, u"D"); + const auto classD = AbstractMetaClass::findClass(classes, "D"); QVERIFY(classD); QCOMPARE(classD->functions().size(), 1); QCOMPARE(classD->functions().constFirst()->minimalSignature(), u"D(D)"); QVERIFY(classD->functions().constFirst()->isPrivate()); - auto *classE = AbstractMetaClass::findClass(classes, u"E"); + const auto classE = AbstractMetaClass::findClass(classes, "E"); QVERIFY(classE); QVERIFY(classE->hasPrivateDestructor()); QCOMPARE(classE->functions().size(), 0); - auto *classF = AbstractMetaClass::findClass(classes, u"F"); + const auto classF = AbstractMetaClass::findClass(classes, "F"); QVERIFY(classF); ctors = classF->queryFunctions(FunctionQueryOption::AnyConstructor); @@ -468,10 +468,10 @@ void TestAbstractMetaClass::testClassInheritedDefaultConstructors() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); auto ctors = classA->queryFunctions(FunctionQueryOption::AnyConstructor); @@ -485,7 +485,7 @@ void TestAbstractMetaClass::testClassInheritedDefaultConstructors() QCOMPARE(ctors[1]->minimalSignature(), u"A(A)"); QVERIFY(ctors[1]->isPrivate()); - auto *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); ctors = classB->queryFunctions(FunctionQueryOption::Constructors); @@ -506,10 +506,10 @@ void TestAbstractMetaClass::testAbstractClassDefaultConstructors() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - auto *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); const auto ctors = classA->queryFunctions(FunctionQueryOption::Constructors); @@ -527,10 +527,10 @@ void TestAbstractMetaClass::testObjectTypesMustNotHaveCopyConstructors() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - auto *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); const auto ctors = classA->queryFunctions(FunctionQueryOption::Constructors); @@ -563,13 +563,13 @@ void TestAbstractMetaClass::testIsPolymorphic() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *b = AbstractMetaClass::findClass(classes, u"A"); + const auto b = AbstractMetaClass::findClass(classes, "A"); QVERIFY(!b->isPolymorphic()); - auto *a = AbstractMetaClass::findClass(classes, u"B"); + const auto a = AbstractMetaClass::findClass(classes, "B"); QVERIFY(!a->isPolymorphic()); } @@ -593,12 +593,12 @@ class Derived : public BaseAlias2 { )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto base = AbstractMetaClass::findClass(classes, u"Base"); + const auto base = AbstractMetaClass::findClass(classes, "Base"); QVERIFY(base); - auto derived = AbstractMetaClass::findClass(classes, u"Derived"); + const auto derived = AbstractMetaClass::findClass(classes, "Derived"); QVERIFY(derived); QCOMPARE(derived->baseClasses().value(0), base); } @@ -644,7 +644,7 @@ void TestAbstractMetaClass::testFreeOperators() </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(code.constData(), xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); const auto classes = builder->classes(); QCOMPARE(classes.size(), 1); QVERIFY(classes.constFirst()->hasArithmeticOperatorOverload()); @@ -678,12 +678,12 @@ public: )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto base = AbstractMetaClass::findClass(classes, u"Base"); + const auto base = AbstractMetaClass::findClass(classes, "Base"); QVERIFY(base); - auto derived = AbstractMetaClass::findClass(classes, u"Derived"); + const auto derived = AbstractMetaClass::findClass(classes, "Derived"); QVERIFY(derived); const auto usingMembers = derived->usingMembers(); QCOMPARE(usingMembers.size(), 2); @@ -733,9 +733,9 @@ void TestAbstractMetaClass::testUsingTemplateMembers() )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(code.constData(), xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto valueList = AbstractMetaClass::findClass(classes, u"ValueList"); + const auto valueList = AbstractMetaClass::findClass(classes, "ValueList"); QVERIFY(valueList); auto list = valueList->templateBaseClass(); QVERIFY(valueList->isUsingMember(list, u"append"_s, Access::Public)); @@ -763,9 +763,9 @@ public: )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto *tc = AbstractMetaClass::findClass(classes, u"TestClass"); + const auto tc = AbstractMetaClass::findClass(classes, "TestClass"); // Verify that the constructor and 2 functions are generated. const auto &functions = tc->functions(); QCOMPARE(functions.size(), 5); diff --git a/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp b/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp index 072764155..2c320c874 100644 --- a/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp @@ -54,7 +54,7 @@ void TestAbstractMetaType::testConstCharPtrType() <function signature='justAtest()' />\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); QCOMPARE(builder->globalFunctions().size(), 1); const auto func = builder->globalFunctions().constFirst(); AbstractMetaType rtype = func->type(); @@ -87,7 +87,7 @@ void TestAbstractMetaType::testApiVersionSupported() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, u"1.0"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); @@ -105,7 +105,7 @@ void TestAbstractMetaType::testApiVersionNotSupported() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); @@ -120,7 +120,7 @@ void TestAbstractMetaType::testCharType() <function signature='justAtest()'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); @@ -157,11 +157,11 @@ void TestAbstractMetaType::testTypedef() <value-type name='C' />\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - const AbstractMetaClass *c = AbstractMetaClass::findClass(classes, u"C"); + const auto c = AbstractMetaClass::findClass(classes, "C"); QVERIFY(c); QVERIFY(c->isTypeDef()); } @@ -182,7 +182,7 @@ void TestAbstractMetaType::testTypedefWithTemplates() <function signature='func(A<B>)'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); @@ -193,7 +193,7 @@ void TestAbstractMetaType::testTypedefWithTemplates() QCOMPARE(args.size(), 1); const AbstractMetaArgument &arg = args.constFirst(); AbstractMetaType metaType = arg.type(); - QCOMPARE(metaType.cppSignature(), u"A<B >"); + QCOMPARE(metaType.cppSignature(), u"A<B>"); } @@ -207,11 +207,11 @@ void TestAbstractMetaType::testObjectTypeUsedAsValue() <object-type name='A'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); const auto overloads = classA->queryFunctionsByName(u"method"_s); QCOMPARE(overloads.size(), 1); diff --git a/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp b/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp index 72cf34693..a891e1e28 100644 --- a/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp @@ -19,28 +19,31 @@ using namespace Qt::StringLiterals; +static constexpr auto voidT = "void"_L1; + void TestAddFunction::testParsingFuncNameAndConstness() { // generic test... - const char sig1[] = "func(type1, const type2, const type3* const)"; + static constexpr auto sig1 = "func(type1, const type2, const type3* const)"_L1; QString errorMessage; - auto f1 = AddedFunction::createAddedFunction(QLatin1StringView(sig1), u"void"_s, - &errorMessage); - QVERIFY2(!f1.isNull(), qPrintable(errorMessage)); + auto f1 = AddedFunction::createAddedFunction(sig1, voidT, &errorMessage); + QVERIFY2(f1, qPrintable(errorMessage)); QCOMPARE(f1->name(), u"func"); QCOMPARE(f1->arguments().size(), 3); TypeInfo retval = f1->returnType(); - QCOMPARE(retval.qualifiedName(), QStringList{u"void"_s}); + QCOMPARE(retval.qualifiedName(), QStringList{voidT}); QCOMPARE(retval.indirections(), 0); QCOMPARE(retval.isConstant(), false); QCOMPARE(retval.referenceType(), NoReference); // test with a ugly template as argument and other ugly stuff - const char sig2[] = " _fu__nc_ ( type1, const type2, const Abc<int& , C<char*> * > * *@my_name@, const type3* const ) const "; - auto f2 = AddedFunction::createAddedFunction(QLatin1StringView(sig2), + static constexpr auto sig2 = + " _fu__nc_ ( type1, const type2, const Abc<int& , C<char*> * >" + " * *@my_name@, const type3* const ) const "_L1; + auto f2 = AddedFunction::createAddedFunction(sig2, u"const Abc<int& , C<char*> * > * *"_s, &errorMessage); - QVERIFY2(!f2.isNull(), qPrintable(errorMessage)); + QVERIFY2(f2, qPrintable(errorMessage)); QCOMPARE(f2->name(), u"_fu__nc_"); const auto &args = f2->arguments(); QCOMPARE(args.size(), 4); @@ -66,18 +69,15 @@ void TestAddFunction::testParsingFuncNameAndConstness() QVERIFY(args.at(3).name.isEmpty()); // function with no args. - const char sig3[] = "func()"; - auto f3 = AddedFunction::createAddedFunction(QLatin1StringView(sig3), u"void"_s, - &errorMessage); - QVERIFY2(!f3.isNull(), qPrintable(errorMessage)); + auto f3 = AddedFunction::createAddedFunction("func()"_L1, voidT, &errorMessage); + QVERIFY2(f3, qPrintable(errorMessage)); QCOMPARE(f3->name(), u"func"); QCOMPARE(f3->arguments().size(), 0); // const call operator - const char sig4[] = "operator()(int)const"; - auto f4 = AddedFunction::createAddedFunction(QLatin1StringView(sig4), u"int"_s, - &errorMessage); - QVERIFY2(!f4.isNull(), qPrintable(errorMessage)); + auto f4 = AddedFunction::createAddedFunction("operator()(int)const"_L1, + "int"_L1, &errorMessage); + QVERIFY2(f4, qPrintable(errorMessage)); QCOMPARE(f4->name(), u"operator()"); QCOMPARE(f4->arguments().size(), 1); QVERIFY(f4->isConstant()); @@ -102,15 +102,15 @@ struct A { </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); auto *typeDb = TypeDatabase::instance(); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); // default ctor, default copy ctor, func a() and the added functions QCOMPARE(classA->functions().size(), 5); - auto addedFunc = classA->findFunction(u"b"); + auto addedFunc = classA->findFunction("b"); QVERIFY(addedFunc); QCOMPARE(addedFunc->access(), Access::Protected); QCOMPARE(addedFunc->functionType(), AbstractMetaFunction::NormalFunction); @@ -131,7 +131,7 @@ struct A { QCOMPARE(args.at(1).defaultValueExpression(), u"4.6"); QCOMPARE(args.at(2).type().typeEntry(), typeDb->findType(u"B"_s)); - auto addedCallOperator = classA->findFunction(u"operator()"); + auto addedCallOperator = classA->findFunction("operator()"); QVERIFY(addedCallOperator); } @@ -146,9 +146,9 @@ void TestAddFunction::testAddFunctionConstructor() </value-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->functions().size(), 3); // default and added ctors const auto addedFunc = classA->functions().constLast(); @@ -169,9 +169,9 @@ void TestAddFunction::testAddFunctionTagDefaultValues() </value-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); // default ctor, default copy ctor and the added function QCOMPARE(classA->functions().size(), 3); @@ -195,9 +195,9 @@ void TestAddFunction::testAddFunctionCodeSnippets() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); const auto addedFunc = classA->functions().constLast(); QVERIFY(addedFunc->hasInjectedCode()); @@ -205,11 +205,10 @@ void TestAddFunction::testAddFunctionCodeSnippets() void TestAddFunction::testAddFunctionWithoutParenteses() { - const char sig1[] = "func"; + static constexpr auto sig1 = "func"_L1; QString errorMessage; - auto f1 = AddedFunction::createAddedFunction(QLatin1StringView(sig1), u"void"_s, - &errorMessage); - QVERIFY2(!f1.isNull(), qPrintable(errorMessage)); + auto f1 = AddedFunction::createAddedFunction(sig1, voidT, &errorMessage); + QVERIFY2(f1, qPrintable(errorMessage)); QCOMPARE(f1->name(), u"func"); QCOMPARE(f1->arguments().size(), 0); QCOMPARE(f1->isConstant(), false); @@ -225,12 +224,12 @@ void TestAddFunction::testAddFunctionWithoutParenteses() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const auto addedFunc = classA->findFunction(u"func"); - QVERIFY(!addedFunc.isNull()); + const auto addedFunc = classA->findFunction(sig1); + QVERIFY(addedFunc); QVERIFY(addedFunc->hasInjectedCode()); const auto snips = addedFunc->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); @@ -239,11 +238,10 @@ void TestAddFunction::testAddFunctionWithoutParenteses() void TestAddFunction::testAddFunctionWithDefaultArgs() { - const char sig1[] = "func"; + static constexpr auto sig1 = "func"_L1; QString errorMessage; - auto f1 = AddedFunction::createAddedFunction(QLatin1StringView(sig1), u"void"_s, - &errorMessage); - QVERIFY2(!f1.isNull(), qPrintable(errorMessage)); + auto f1 = AddedFunction::createAddedFunction(sig1, voidT, &errorMessage); + QVERIFY2(f1, qPrintable(errorMessage)); QCOMPARE(f1->name(), u"func"); QCOMPARE(f1->arguments().size(), 0); QCOMPARE(f1->isConstant(), false); @@ -262,12 +260,12 @@ void TestAddFunction::testAddFunctionWithDefaultArgs() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const auto addedFunc = classA->findFunction(u"func"); - QVERIFY(!addedFunc.isNull()); + const auto addedFunc = classA->findFunction(sig1); + QVERIFY(addedFunc); const AbstractMetaArgument &arg = addedFunc->arguments().at(1); QCOMPARE(arg.defaultValueExpression(), u"2"); } @@ -285,9 +283,9 @@ void TestAddFunction::testAddFunctionAtModuleLevel() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); auto *typeDb = TypeDatabase::instance(); @@ -306,11 +304,10 @@ void TestAddFunction::testAddFunctionAtModuleLevel() void TestAddFunction::testAddFunctionWithVarargs() { - const char sig1[] = "func(int,char,...)"; QString errorMessage; - auto f1 = AddedFunction::createAddedFunction(QLatin1StringView(sig1), u"void"_s, + auto f1 = AddedFunction::createAddedFunction("func(int,char,...)"_L1, voidT, &errorMessage); - QVERIFY2(!f1.isNull(), qPrintable(errorMessage)); + QVERIFY2(f1, qPrintable(errorMessage)); QCOMPARE(f1->name(), u"func"); QCOMPARE(f1->arguments().size(), 3); QVERIFY(!f1->isConstant()); @@ -326,12 +323,12 @@ void TestAddFunction::testAddFunctionWithVarargs() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const auto addedFunc = classA->findFunction(u"func"); - QVERIFY(!addedFunc.isNull()); + const auto addedFunc = classA->findFunction("func"); + QVERIFY(addedFunc); const AbstractMetaArgument &arg = addedFunc->arguments().constLast(); QVERIFY(arg.type().isVarargs()); QVERIFY(arg.type().typeEntry()->isVarargs()); @@ -350,12 +347,12 @@ void TestAddFunction::testAddStaticFunction() </value-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const auto addedFunc = classA->findFunction(u"func"); - QVERIFY(!addedFunc.isNull()); + const auto addedFunc = classA->findFunction("func"); + QVERIFY(addedFunc); QVERIFY(addedFunc->isStatic()); } @@ -375,13 +372,13 @@ void TestAddFunction::testAddGlobalFunction() <value-type name='B'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); const auto globalFuncs = builder->globalFunctions(); QCOMPARE(globalFuncs.size(), 2); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(builder->classes(), u"B"); + const auto classB = AbstractMetaClass::findClass(builder->classes(), "B"); QVERIFY(classB); - QVERIFY(!classB->findFunction(u"globalFunc")); - QVERIFY(!classB->findFunction(u"globalFunc2")); + QVERIFY(!classB->findFunction("globalFunc")); + QVERIFY(!classB->findFunction("globalFunc2")); QVERIFY(!globalFuncs[0]->injectedCodeSnips().isEmpty()); QVERIFY(!globalFuncs[1]->injectedCodeSnips().isEmpty()); } @@ -401,7 +398,7 @@ void TestAddFunction::testAddFunctionWithApiVersion() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); const auto globalFuncs = builder->globalFunctions(); QCOMPARE(globalFuncs.size(), 1); } @@ -424,11 +421,11 @@ void TestAddFunction::testModifyAddedFunction() </typesystem> )"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto *foo = AbstractMetaClass::findClass(classes, u"Foo"); - const auto method = foo->findFunction(u"method"); - QVERIFY(!method.isNull()); + const auto foo = AbstractMetaClass::findClass(classes, "Foo"); + const auto method = foo->findFunction("method"); + QVERIFY(method); QCOMPARE(method->arguments().size(), 2); const AbstractMetaArgument &arg = method->arguments().at(1); QCOMPARE(arg.defaultValueExpression(), u"0"); @@ -451,17 +448,17 @@ void TestAddFunction::testAddFunctionOnTypedef() </value-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto *foo = AbstractMetaClass::findClass(classes, u"FooInt"); + const auto foo = AbstractMetaClass::findClass(classes, "FooInt"); QVERIFY(foo); QVERIFY(foo->hasNonPrivateConstructor()); const auto &lst = foo->queryFunctions(FunctionQueryOption::AnyConstructor); for (const auto &f : lst) QVERIFY(f->signature().startsWith(f->name())); QCOMPARE(lst.size(), 2); - const auto method = foo->findFunction(u"method"); - QVERIFY(!method.isNull()); + const auto method = foo->findFunction("method"); + QVERIFY(method); } void TestAddFunction::testAddFunctionWithTemplateArg() @@ -475,7 +472,7 @@ void TestAddFunction::testAddFunctionWithTemplateArg() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); QCOMPARE(builder->globalFunctions().size(), 1); const auto func = builder->globalFunctions().constFirst(); const AbstractMetaArgument &arg = func->arguments().constFirst(); diff --git a/sources/shiboken6/ApiExtractor/tests/testarrayargument.cpp b/sources/shiboken6/ApiExtractor/tests/testarrayargument.cpp index e7c3a0106..6e1820bed 100644 --- a/sources/shiboken6/ApiExtractor/tests/testarrayargument.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testarrayargument.cpp @@ -34,7 +34,7 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByInteger() QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); QVERIFY(!builder.isNull()); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); const AbstractMetaArgument &arg = classA->functions().constLast()->arguments().constFirst(); @@ -43,10 +43,10 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByInteger() QCOMPARE(arg.type().arrayElementType()->name(), u"double"); } -static QString functionMinimalSignature(const AbstractMetaClass *c, const QString &name) +static QString functionMinimalSignature(const AbstractMetaClassCPtr &c, const QString &name) { const auto f = c->findFunction(name); - return f.isNull() ? QString() : f->minimalSignature(); + return f ? f->minimalSignature() : QString(); } void TestArrayArgument::testArraySignature() @@ -72,7 +72,7 @@ void TestArrayArgument::testArraySignature() QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); QVERIFY(!builder.isNull()); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "A"); QCOMPARE(functionMinimalSignature(classA, u"mi1"_s), u"mi1(int[5])"); QCOMPARE(functionMinimalSignature(classA, u"mi1c"_s), @@ -108,7 +108,7 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValue() QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); QVERIFY(!builder.isNull()); - AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + AbstractMetaClassPtr classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); auto someEnum = classA->findEnum(u"SomeEnum"_s); @@ -138,8 +138,8 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValueFromGlobalEnu </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + QVERIFY(builder); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); AbstractMetaEnum someEnum = builder->globalEnums().constFirst(); diff --git a/sources/shiboken6/ApiExtractor/tests/testcodeinjection.cpp b/sources/shiboken6/ApiExtractor/tests/testcodeinjection.cpp index bb8c6882b..4829e6c33 100644 --- a/sources/shiboken6/ApiExtractor/tests/testcodeinjection.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testcodeinjection.cpp @@ -59,14 +59,14 @@ void TestCodeInjections::testReadFile() </value-type>\n\ </typesystem>\n"_s; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode.toLocal8Bit().constData())); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QCOMPARE(classA->typeEntry()->codeSnips().size(), 1); QString code = classA->typeEntry()->codeSnips().constFirst().code(); QVERIFY(code.indexOf(expected) != -1); QVERIFY(classA->typeEntry()->isValue()); - auto vte = qSharedPointerCast<const ValueTypeEntry>(classA->typeEntry()); + auto vte = std::static_pointer_cast<const ValueTypeEntry>(classA->typeEntry()); code = vte->targetConversionRule(); QVERIFY(code.indexOf(expected) != -1); } @@ -85,9 +85,9 @@ void TestCodeInjections::testInjectWithValidApiVersion() QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, u"1.0"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QCOMPARE(classA->typeEntry()->codeSnips().size(), 1); } @@ -105,10 +105,10 @@ void TestCodeInjections::testInjectWithInvalidApiVersion() QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QCOMPARE(classA->typeEntry()->codeSnips().size(), 0); } @@ -125,7 +125,7 @@ void TestCodeInjections::testTextStream() str << "\n2nd table\n|" << AlignedField("bla", 3, QTextStream::AlignLeft) << '|' << AlignedField(QString{}, 0, QTextStream::AlignLeft) << "|\n"; -static const char expected[] = R"(void foo(int a, int b) { +constexpr auto expected = R"(void foo(int a, int b) { if (a == b) return a; #if Q_OS_WIN @@ -141,9 +141,9 @@ static const char expected[] = R"(void foo(int a, int b) { 2nd table |bla|| -)"; +)"_L1; - QCOMPARE(str.toString(), QLatin1String(expected)); + QCOMPARE(str.toString(), expected); } void TestCodeInjections::testTextStreamRst() diff --git a/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp b/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp index 4f8dcd4b7..0bb72b3c1 100644 --- a/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp @@ -28,15 +28,15 @@ void TestContainer::testContainerType() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); //search for class A - auto *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); auto baseContainer = classA->typeEntry()->baseContainerType(); QVERIFY(baseContainer); - QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer.data())->containerKind(), + QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer.get())->containerKind(), ContainerTypeEntry::ListContainer); } @@ -61,11 +61,11 @@ void TestContainer::testListOfValueType() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 3); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->templateBaseClassInstantiations().size(), 1); const AbstractMetaType templateInstanceType = diff --git a/sources/shiboken6/ApiExtractor/tests/testconversionoperator.cpp b/sources/shiboken6/ApiExtractor/tests/testconversionoperator.cpp index f7d4b0673..8f2b277af 100644 --- a/sources/shiboken6/ApiExtractor/tests/testconversionoperator.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testconversionoperator.cpp @@ -33,11 +33,11 @@ void TestConversionOperator::testConversionOperator() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); - const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, u"C"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); + const auto classC = AbstractMetaClass::findClass(classes, "C"); QVERIFY(classA); QVERIFY(classB); QVERIFY(classC); @@ -53,7 +53,7 @@ void TestConversionOperator::testConversionOperator() break; } } - QVERIFY(!convOp.isNull()); + QVERIFY(convOp); QVERIFY(classA->externalConversionOperators().contains(convOp)); } @@ -71,9 +71,9 @@ void TestConversionOperator::testConversionOperatorOfDiscardedClass() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->externalConversionOperators().size(), 0); } @@ -95,10 +95,10 @@ void TestConversionOperator::testRemovedConversionOperator() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classA); QVERIFY(classB); QCOMPARE(classA->functions().size(), 2); @@ -121,10 +121,10 @@ void TestConversionOperator::testConversionOperatorReturningReference() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classA); QVERIFY(classB); QCOMPARE(classA->functions().size(), 2); @@ -155,10 +155,10 @@ void TestConversionOperator::testConversionOperatorReturningConstReference() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classA); QVERIFY(classB); QCOMPARE(classA->functions().size(), 2); diff --git a/sources/shiboken6/ApiExtractor/tests/testconversionruletag.cpp b/sources/shiboken6/ApiExtractor/tests/testconversionruletag.cpp index 0f3edcfe5..b5efd92a6 100644 --- a/sources/shiboken6/ApiExtractor/tests/testconversionruletag.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testconversionruletag.cpp @@ -21,10 +21,10 @@ void TestConversionRuleTag::testConversionRuleTagWithFile() { // FIXME PYSIDE7 remove // temp file used later - const char conversionData[] = "Hi! I'm a conversion rule."; + constexpr auto conversionData = "Hi! I'm a conversion rule."_L1; QTemporaryFile file; - file.open(); - QCOMPARE(file.write(conversionData), qint64(sizeof(conversionData)-1)); + QVERIFY(file.open()); + QCOMPARE(file.write(conversionData.constData()), conversionData.size()); file.close(); const char cppCode[] = "struct A {};\n"; @@ -35,15 +35,15 @@ void TestConversionRuleTag::testConversionRuleTagWithFile() </value-type>\n\ </typesystem>\n"_s; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode.toLocal8Bit().data())); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); const auto typeEntry = classA->typeEntry(); QVERIFY(typeEntry->isValue()); - auto vte = qSharedPointerCast<const ValueTypeEntry>(typeEntry); + auto vte = std::static_pointer_cast<const ValueTypeEntry>(typeEntry); QVERIFY(vte->hasTargetConversionRule()); - QCOMPARE(vte->targetConversionRule(), QLatin1String(conversionData)); + QCOMPARE(vte->targetConversionRule(), conversionData); } void TestConversionRuleTag::testConversionRuleTagReplace() @@ -85,10 +85,10 @@ void TestConversionRuleTag::testConversionRuleTagReplace() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); auto *typeDb = TypeDatabase::instance(); auto typeA = typeDb->findPrimitiveType(u"A"_s); - QVERIFY(!typeA.isNull()); + QVERIFY(typeA); QVERIFY(typeA->hasCustomConversion()); auto conversion = typeA->customConversion(); @@ -115,7 +115,7 @@ void TestConversionRuleTag::testConversionRuleTagReplace() QCOMPARE(toNative.sourceTypeName(), u"B"); QVERIFY(!toNative.isCustomType()); auto typeB = typeDb->findType(u"B"_s); - QVERIFY(!typeB.isNull()); + QVERIFY(typeB); QCOMPARE(toNative.sourceType(), typeB); QCOMPARE(toNative.sourceTypeCheck(), u"CheckIfInputObjectIsB(%IN)"); QCOMPARE(toNative.conversion().trimmed(), u"%OUT = %IN.createA();"); @@ -153,12 +153,12 @@ if (!TargetDateTimeAPI) TargetDateTime_IMPORT;\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - auto *classA = AbstractMetaClass::findClass(builder->classes(), u"Date"); + QVERIFY(builder); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "Date"); QVERIFY(classA); QVERIFY(classA->typeEntry()->isValue()); - auto vte = qSharedPointerCast<const ValueTypeEntry>(classA->typeEntry()); + auto vte = std::static_pointer_cast<const ValueTypeEntry>(classA->typeEntry()); QVERIFY(vte->hasCustomConversion()); auto conversion = vte->customConversion(); @@ -216,10 +216,10 @@ void TestConversionRuleTag::testConversionRuleTagWithInsertTemplate() "// TEMPLATE - target_to_native - END"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); auto *typeDb = TypeDatabase::instance(); auto typeA = typeDb->findPrimitiveType(u"A"_s); - QVERIFY(!typeA.isNull()); + QVERIFY(typeA); QVERIFY(typeA->hasCustomConversion()); auto conversion = typeA->customConversion(); diff --git a/sources/shiboken6/ApiExtractor/tests/testctorinformation.cpp b/sources/shiboken6/ApiExtractor/tests/testctorinformation.cpp index 7579509ff..c3a3ebef0 100644 --- a/sources/shiboken6/ApiExtractor/tests/testctorinformation.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testctorinformation.cpp @@ -19,16 +19,16 @@ void TestCtorInformation::testCtorIsPrivate() <value-type name='CtorLess'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 3); - auto *klass = AbstractMetaClass::findClass(classes, u"Control"); + auto klass = AbstractMetaClass::findClass(classes, "Control"); QVERIFY(klass); QVERIFY(klass->hasNonPrivateConstructor()); - klass = AbstractMetaClass::findClass(classes, u"Subject"); + klass = AbstractMetaClass::findClass(classes, "Subject"); QVERIFY(klass); QVERIFY(!klass->hasNonPrivateConstructor()); - klass = AbstractMetaClass::findClass(classes, u"CtorLess"); + klass = AbstractMetaClass::findClass(classes, "CtorLess"); QVERIFY(klass); QVERIFY(klass->hasNonPrivateConstructor()); } @@ -45,12 +45,12 @@ void TestCtorInformation::testHasNonPrivateCtor() <object-type name='Derived'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - const AbstractMetaClass *base = AbstractMetaClass::findClass(classes, u"Base"); + const auto base = AbstractMetaClass::findClass(classes, "Base"); QCOMPARE(base->hasNonPrivateConstructor(), true); - const AbstractMetaClass *derived = AbstractMetaClass::findClass(classes, u"Derived"); + const auto derived = AbstractMetaClass::findClass(classes, "Derived"); QCOMPARE(derived->hasNonPrivateConstructor(), true); } diff --git a/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp b/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp index 2e07b8cba..16f50e69d 100644 --- a/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp @@ -56,16 +56,16 @@ void TestDropTypeEntries::testDropEntries() u"Foo.NamespaceA.InnerNamespaceA"_s}; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, QString(), droppedEntries)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - QVERIFY(AbstractMetaClass::findClass(classes, u"ValueA")); - QVERIFY(!AbstractMetaClass::findClass(classes, u"ValueB")); - QVERIFY(AbstractMetaClass::findClass(classes, u"ObjectA")); - QVERIFY(!AbstractMetaClass::findClass(classes, u"ObjectB")); - QVERIFY(AbstractMetaClass::findClass(classes, u"NamespaceA")); - QVERIFY(!AbstractMetaClass::findClass(classes, u"NamespaceA::InnerClassA")); - QVERIFY(!AbstractMetaClass::findClass(classes, u"NamespaceB")); + QVERIFY(AbstractMetaClass::findClass(classes, "ValueA")); + QVERIFY(!AbstractMetaClass::findClass(classes, "ValueB")); + QVERIFY(AbstractMetaClass::findClass(classes, "ObjectA")); + QVERIFY(!AbstractMetaClass::findClass(classes, "ObjectB")); + QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceA")); + QVERIFY(!AbstractMetaClass::findClass(classes, "NamespaceA::InnerClassA")); + QVERIFY(!AbstractMetaClass::findClass(classes, "NamespaceB")); AbstractMetaEnumList globalEnums = builder->globalEnums(); QCOMPARE(globalEnums.size(), 1); @@ -79,16 +79,16 @@ void TestDropTypeEntries::testDropEntries() void TestDropTypeEntries::testDontDropEntries() { QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - QVERIFY(AbstractMetaClass::findClass(classes, u"ValueA")); - QVERIFY(AbstractMetaClass::findClass(classes, u"ValueB")); - QVERIFY(AbstractMetaClass::findClass(classes, u"ObjectA")); - QVERIFY(AbstractMetaClass::findClass(classes, u"ObjectB")); - QVERIFY(AbstractMetaClass::findClass(classes, u"NamespaceA")); - QVERIFY(AbstractMetaClass::findClass(classes, u"NamespaceA::InnerClassA")); - QVERIFY(AbstractMetaClass::findClass(classes, u"NamespaceB")); + QVERIFY(AbstractMetaClass::findClass(classes, "ValueA")); + QVERIFY(AbstractMetaClass::findClass(classes, "ValueB")); + QVERIFY(AbstractMetaClass::findClass(classes, "ObjectA")); + QVERIFY(AbstractMetaClass::findClass(classes, "ObjectB")); + QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceA")); + QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceA::InnerClassA")); + QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceB")); QCOMPARE(builder->globalEnums().size(), 2); @@ -115,21 +115,21 @@ void TestDropTypeEntries::testDropEntryWithChildTags() QStringList droppedEntries(u"Foo.ValueA"_s); QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode2, xmlCode2, false, QString(), droppedEntries)); - QVERIFY(!builder.isNull()); - QVERIFY(!AbstractMetaClass::findClass(builder->classes(), u"ValueA")); + QVERIFY(builder); + QVERIFY(!AbstractMetaClass::findClass(builder->classes(), "ValueA")); } void TestDropTypeEntries::testDontDropEntryWithChildTags() { QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode2, xmlCode2, false)); - QVERIFY(!builder.isNull()); - QVERIFY(AbstractMetaClass::findClass(builder->classes(), u"ValueA")); + QVERIFY(builder); + QVERIFY(AbstractMetaClass::findClass(builder->classes(), "ValueA")); } void TestDropTypeEntries::testConditionalParsing_data() { - const QString xml = QStringLiteral(R"(<?xml version="1.0" encoding="UTF-8"?> + const QString xml = R"(<?xml version="1.0" encoding="UTF-8"?> <root> <tag1>text</tag1> <?if keyword1?> @@ -145,17 +145,17 @@ void TestDropTypeEntries::testConditionalParsing_data() <?if !keyword99?> <!-- Exclusion only --> <tag6>text</tag6> <?endif?> -</root>)"); - - const QString root = QStringLiteral("root"); - const QString tag1 = QStringLiteral("tag1"); - const QString tag2 = QStringLiteral("tag2"); - const QString tag3 = QStringLiteral("tag3"); - const QString tag4 = QStringLiteral("tag4"); - const QString tag5 = QStringLiteral("tag5"); - const QString tag6 = QStringLiteral("tag6"); - const QString keyword1 = QStringLiteral("keyword1"); - const QString keyword2 = QStringLiteral("keyword2"); +</root>)"_L1; + + constexpr auto root = "root"_L1; + constexpr auto tag1 = "tag1"_L1; + constexpr auto tag2 = "tag2"_L1; + constexpr auto tag3 = "tag3"_L1; + constexpr auto tag4 = "tag4"_L1; + constexpr auto tag5 = "tag5"_L1; + constexpr auto tag6 = "tag6"_L1; + constexpr auto keyword1 = "keyword1"_L1; + constexpr auto keyword2 = "keyword2"_L1; QTest::addColumn<QString>("xml"); QTest::addColumn<QStringList>("keywords"); @@ -204,11 +204,11 @@ void TestDropTypeEntries::testConditionalParsing() void TestDropTypeEntries::testEntityParsing() { - const QString xml = QStringLiteral(R"(<?xml version="1.0" encoding="UTF-8"?> + const QString xml = R"(<?xml version="1.0" encoding="UTF-8"?> <root> <?entity testentity word1 word2?> <text>bla &testentity;</text> -</root>)"); +</root>)"_L1; QString actual; ConditionalStreamReader reader(xml); diff --git a/sources/shiboken6/ApiExtractor/tests/testdtorinformation.cpp b/sources/shiboken6/ApiExtractor/tests/testdtorinformation.cpp index 95b33243e..2152d39de 100644 --- a/sources/shiboken6/ApiExtractor/tests/testdtorinformation.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testdtorinformation.cpp @@ -25,13 +25,13 @@ private: </typesystem>)"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *klass = AbstractMetaClass::findClass(classes, u"Control"); + auto klass = AbstractMetaClass::findClass(classes, "Control"); QVERIFY(klass); QVERIFY(!klass->hasPrivateDestructor()); - klass = AbstractMetaClass::findClass(classes, u"Subject"); + klass = AbstractMetaClass::findClass(classes, "Subject"); QVERIFY(klass); QVERIFY(klass->hasPrivateDestructor()); } @@ -53,13 +53,13 @@ protected: </typesystem>)"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *klass = AbstractMetaClass::findClass(classes, u"Control"); + auto klass = AbstractMetaClass::findClass(classes, "Control"); QVERIFY(klass); QVERIFY(!klass->hasProtectedDestructor()); - klass = AbstractMetaClass::findClass(classes, u"Subject"); + klass = AbstractMetaClass::findClass(classes, "Subject"); QVERIFY(klass); QVERIFY(klass->hasProtectedDestructor()); } @@ -81,13 +81,13 @@ protected: </typesystem>)"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *klass = AbstractMetaClass::findClass(classes, u"Control"); + auto klass = AbstractMetaClass::findClass(classes, "Control"); QVERIFY(klass); QVERIFY(!klass->hasVirtualDestructor()); - klass = AbstractMetaClass::findClass(classes, u"Subject"); + klass = AbstractMetaClass::findClass(classes, "Subject"); QVERIFY(klass); QVERIFY(klass->hasVirtualDestructor()); } @@ -106,21 +106,21 @@ class Subject : public SubjectBase {}; </typesystem> )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 4); - auto klass = AbstractMetaClass::findClass(classes, u"ControlBase"); + auto klass = AbstractMetaClass::findClass(classes, "ControlBase"); QVERIFY(klass); QVERIFY(!klass->hasVirtualDestructor()); - klass = AbstractMetaClass::findClass(classes, u"Control"); + klass = AbstractMetaClass::findClass(classes, "Control"); QVERIFY(klass); QVERIFY(!klass->hasVirtualDestructor()); - klass = AbstractMetaClass::findClass(classes, u"SubjectBase"); + klass = AbstractMetaClass::findClass(classes, "SubjectBase"); QVERIFY(klass); QVERIFY(klass->hasVirtualDestructor()); - klass = AbstractMetaClass::findClass(classes, u"Subject"); + klass = AbstractMetaClass::findClass(classes, "Subject"); QVERIFY(klass); QVERIFY(klass->hasVirtualDestructor()); } @@ -142,13 +142,13 @@ protected: </typesystem>)"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *klass = AbstractMetaClass::findClass(classes, u"Control"); + auto klass = AbstractMetaClass::findClass(classes, "Control"); QVERIFY(klass); QVERIFY(klass->isPolymorphic()); - klass = AbstractMetaClass::findClass(classes, u"Subject"); + klass = AbstractMetaClass::findClass(classes, "Subject"); QVERIFY(klass); QVERIFY(klass->isPolymorphic()); } diff --git a/sources/shiboken6/ApiExtractor/tests/testenum.cpp b/sources/shiboken6/ApiExtractor/tests/testenum.cpp index e45da9e70..c7c2b8b3b 100644 --- a/sources/shiboken6/ApiExtractor/tests/testenum.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testenum.cpp @@ -38,7 +38,7 @@ void TestEnum::testEnumCppSignature() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); @@ -54,7 +54,7 @@ void TestEnum::testEnumCppSignature() u"A::ClassEnum"); // enum as parameter of a method - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QCOMPARE(classA->enums().size(), 1); const auto funcs = classA->queryFunctionsByName(u"method"_s); QVERIFY(!funcs.isEmpty()); @@ -93,7 +93,7 @@ void TestEnum::testEnumWithApiVersion() QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); QCOMPARE(classes[0]->enums().size(), 1); @@ -119,7 +119,7 @@ void TestEnum::testAnonymousEnum() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaEnumList globalEnums = builder->globalEnums(); QCOMPARE(globalEnums.size(), 1); @@ -174,7 +174,7 @@ void TestEnum::testGlobalEnums() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaEnumList globalEnums = builder->globalEnums(); QCOMPARE(globalEnums.size(), 2); @@ -222,7 +222,7 @@ void TestEnum::testEnumValueFromNeighbourEnum() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); @@ -284,9 +284,9 @@ void TestEnum::testEnumValueFromExpression() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); - AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + AbstractMetaClassPtr classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); auto enumA = classA->findEnum(u"EnumA"_s); @@ -362,9 +362,9 @@ void TestEnum::testPrivateEnum() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); - AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); QCOMPARE(classA->enums().size(), 2); @@ -401,7 +401,7 @@ void TestEnum::testTypedefEnum() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaEnumList globalEnums = builder->globalEnums(); QCOMPARE(globalEnums.size(), 1); @@ -426,7 +426,7 @@ void TestEnum::testTypedefEnum() struct EnumDefaultValuesFixture { - QSharedPointer<AbstractMetaBuilder> builder; + std::shared_ptr<AbstractMetaBuilder> builder; AbstractMetaType globalEnum; AbstractMetaType testEnum; @@ -462,7 +462,7 @@ namespace Test2 )"; fixture->builder.reset(TestUtil::parse(cppCode, xmlCode, false)); - if (fixture->builder.isNull()) + if (!fixture->builder) return -1; const auto globalEnums = fixture->builder->globalEnums(); @@ -472,8 +472,8 @@ namespace Test2 fixture->globalEnum = AbstractMetaType(globalEnums.constFirst().typeEntry()); fixture->globalEnum.decideUsagePattern(); - const AbstractMetaClass *testNamespace = nullptr; - for (auto *c : fixture->builder->classes()) { + AbstractMetaClassCPtr testNamespace; + for (const auto &c : fixture->builder->classes()) { if (c->name() == u"Test2") { testNamespace = c; break; @@ -486,8 +486,8 @@ namespace Test2 if (namespaceEnums.size() != 2) return -4; QList<EnumTypeEntryCPtr > enumTypeEntries{ - qSharedPointerCast<const EnumTypeEntry>(namespaceEnums.at(0).typeEntry()), - qSharedPointerCast<const EnumTypeEntry>(namespaceEnums.at(1).typeEntry())}; + std::static_pointer_cast<const EnumTypeEntry>(namespaceEnums.at(0).typeEntry()), + std::static_pointer_cast<const EnumTypeEntry>(namespaceEnums.at(1).typeEntry())}; if (enumTypeEntries.constFirst()->flags()) std::swap(enumTypeEntries[0], enumTypeEntries[1]); fixture->testEnum = AbstractMetaType(enumTypeEntries.at(0)); diff --git a/sources/shiboken6/ApiExtractor/tests/testextrainclude.cpp b/sources/shiboken6/ApiExtractor/tests/testextrainclude.cpp index 048626d2a..fcc409a42 100644 --- a/sources/shiboken6/ApiExtractor/tests/testextrainclude.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testextrainclude.cpp @@ -21,9 +21,9 @@ void TestExtraInclude::testClassExtraInclude() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QList<Include> includes = classA->typeEntry()->extraIncludes(); @@ -44,13 +44,13 @@ void TestExtraInclude::testGlobalExtraIncludes() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - QVERIFY(AbstractMetaClass::findClass(classes, u"A")); + QVERIFY(AbstractMetaClass::findClass(classes, "A")); auto *td = TypeDatabase::instance(); TypeSystemTypeEntryCPtr module = td->defaultTypeSystemType(); - QVERIFY(!module.isNull()); + QVERIFY(module); QCOMPARE(module->name(), u"Foo"); QList<Include> includes = module->extraIncludes(); diff --git a/sources/shiboken6/ApiExtractor/tests/testfunctiontag.cpp b/sources/shiboken6/ApiExtractor/tests/testfunctiontag.cpp index 4a98047f1..18eaf5774 100644 --- a/sources/shiboken6/ApiExtractor/tests/testfunctiontag.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testfunctiontag.cpp @@ -23,7 +23,7 @@ void TestFunctionTag::testFunctionTagForSpecificSignature() <function signature='globalFunction(int)'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); TypeEntryCPtr func = TypeDatabase::instance()->findType(u"globalFunction"_s); QVERIFY(func); @@ -41,10 +41,10 @@ void TestFunctionTag::testFunctionTagForAllSignatures() <function signature='globalFunction(float)'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); TypeEntryCPtr func = TypeDatabase::instance()->findType(u"globalFunction"_s); - QVERIFY(!func.isNull()); + QVERIFY(func); QCOMPARE(builder->globalFunctions().size(), 2); } @@ -56,10 +56,10 @@ void TestFunctionTag::testRenameGlobalFunction() <function signature='global_function_with_ugly_name()' rename='smooth'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); TypeEntryCPtr func = TypeDatabase::instance()->findType(u"global_function_with_ugly_name"_s); - QVERIFY(!func.isNull()); + QVERIFY(func); QCOMPARE(builder->globalFunctions().size(), 1); const auto metaFunc = builder->globalFunctions().constFirst(); diff --git a/sources/shiboken6/ApiExtractor/tests/testimplicitconversions.cpp b/sources/shiboken6/ApiExtractor/tests/testimplicitconversions.cpp index eabd8b046..899d00ad4 100644 --- a/sources/shiboken6/ApiExtractor/tests/testimplicitconversions.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testimplicitconversions.cpp @@ -29,12 +29,12 @@ void TestImplicitConversions::testWithPrivateCtors() <value-type name='C'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 3); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); - const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, u"C"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto classC = AbstractMetaClass::findClass(classes, "C"); const auto implicitConvs = classA->implicitConversions(); QCOMPARE(implicitConvs.size(), 1); QCOMPARE(implicitConvs.constFirst()->arguments().constFirst().type().typeEntry(), @@ -59,11 +59,11 @@ void TestImplicitConversions::testWithModifiedVisibility() </typesystem> )"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); const auto implicitConvs = classA->implicitConversions(); QCOMPARE(implicitConvs.size(), 1); QCOMPARE(implicitConvs.constFirst()->arguments().constFirst().type().typeEntry(), @@ -93,16 +93,16 @@ void TestImplicitConversions::testWithAddedCtor() <value-type name='C'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 3); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); auto implicitConvs = classA->implicitConversions(); QCOMPARE(implicitConvs.size(), 2); // Added constructors with custom types should never result in implicit converters. - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); implicitConvs = classB->implicitConversions(); QCOMPARE(implicitConvs.size(), 0); } @@ -120,11 +120,11 @@ void TestImplicitConversions::testWithExternalConversionOperator() <value-type name='B'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *classA = AbstractMetaClass::findClass(classes, u"A"); - auto *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); const auto implicitConvs = classA->implicitConversions(); QCOMPARE(implicitConvs.size(), 1); const auto &externalConvOps = classA->externalConversionOperators(); @@ -135,7 +135,7 @@ void TestImplicitConversions::testWithExternalConversionOperator() if (func->isConversionOperator()) convOp = func; } - QVERIFY(!convOp.isNull()); + QVERIFY(convOp); QCOMPARE(implicitConvs.constFirst(), convOp); } diff --git a/sources/shiboken6/ApiExtractor/tests/testinserttemplate.cpp b/sources/shiboken6/ApiExtractor/tests/testinserttemplate.cpp index ffab76923..23cf0f9ea 100644 --- a/sources/shiboken6/ApiExtractor/tests/testinserttemplate.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testinserttemplate.cpp @@ -25,10 +25,10 @@ void TestInsertTemplate::testInsertTemplateOnClassInjectCode() </value-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->typeEntry()->codeSnips().size(), 1); QString code = classA->typeEntry()->codeSnips().constFirst().code(); @@ -48,12 +48,12 @@ void TestInsertTemplate::testInsertTemplateOnModuleInjectCode() </inject-code>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QVERIFY(classes.isEmpty()); TypeSystemTypeEntryCPtr module = TypeDatabase::instance()->defaultTypeSystemType(); - QVERIFY(!module.isNull()); + QVERIFY(module); QCOMPARE(module->name(), u"Foo"); QCOMPARE(module->codeSnips().size(), 1); QString code = module->codeSnips().constFirst().code().trimmed(); diff --git a/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp b/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp index 168f1a67b..9cf2e0cc7 100644 --- a/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp @@ -33,8 +33,8 @@ R"(<typesystem package="Foo"> </typesystem> )"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + QVERIFY(builder); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); DocModificationList docMods = classA->typeEntry()->docModifications(); QCOMPARE(docMods.size(), 2); @@ -47,7 +47,7 @@ R"(<typesystem package="Foo"> // cannot handle Qt resources. QTemporaryDir tempDir(QDir::tempPath() + u"/shiboken_testmodifydocXXXXXX"_s); QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString())); - const QString docFileName = u"a.xml"_s; + constexpr auto docFileName = "a.xml"_L1; QVERIFY(QFile::copy(u":/"_s + docFileName, tempDir.filePath(docFileName))); QtDocParser docParser; @@ -94,11 +94,11 @@ void TestModifyDocumentation::testInjectAddedFunctionDocumentation() </typesystem> )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + QVERIFY(builder); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); - const auto f = classA->findFunction(u"foo"); - QVERIFY(!f.isNull()); + const auto f = classA->findFunction("foo"); + QVERIFY(f); QVERIFY(f->isUserAdded()); auto docMods = f->addedFunctionDocModifications(); QCOMPARE(docMods.size(), 1); diff --git a/sources/shiboken6/ApiExtractor/tests/testmodifyfunction.cpp b/sources/shiboken6/ApiExtractor/tests/testmodifyfunction.cpp index 2b2525a8c..a7d40f70a 100644 --- a/sources/shiboken6/ApiExtractor/tests/testmodifyfunction.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testmodifyfunction.cpp @@ -46,11 +46,11 @@ void TestModifyFunction::testRenameArgument() const QByteArray xmlCode = QByteArray(xmlCode1) + pattern + QByteArray(xmlCode2); QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode.constData(), false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); - const auto func = classA->findFunction(u"method"); - QVERIFY(!func.isNull()); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto func = classA->findFunction("method"); + QVERIFY(func); QCOMPARE(func->argumentName(1), u"otherArg"); } @@ -74,11 +74,11 @@ void TestModifyFunction::testOwnershipTransfer() </object-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); - const auto func = classB->findFunction(u"method"); - QVERIFY(!func.isNull()); + const auto classB = AbstractMetaClass::findClass(classes, "B"); + const auto func = classB->findFunction("method"); + QVERIFY(func); QCOMPARE(func->argumentTargetOwnership(func->ownerClass(), 0), TypeSystem::CppOwnership); @@ -124,47 +124,47 @@ void TestModifyFunction::invalidateAfterUse() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); - auto func = classB->findFunction(u"call"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); + auto func = classB->findFunction("call"); QCOMPARE(func->modifications().size(), 1); QCOMPARE(func->modifications().at(0).argument_mods().size(), 1); QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse()); - const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, u"C"); + const auto classC = AbstractMetaClass::findClass(classes, "C"); QVERIFY(classC); - func = classC->findFunction(u"call"); + func = classC->findFunction("call"); QCOMPARE(func->modifications().size(), 1); QCOMPARE(func->modifications().at(0).argument_mods().size(), 1); QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse()); - func = classC->findFunction(u"call2"); + func = classC->findFunction("call2"); QCOMPARE(func->modifications().size(), 1); QCOMPARE(func->modifications().at(0).argument_mods().size(), 1); QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse()); - const AbstractMetaClass *classD = AbstractMetaClass::findClass(classes, u"D"); + AbstractMetaClassCPtr classD = AbstractMetaClass::findClass(classes, "D"); QVERIFY(classD); - func = classD->findFunction(u"call"); + func = classD->findFunction("call"); QCOMPARE(func->modifications().size(), 1); QCOMPARE(func->modifications().at(0).argument_mods().size(), 1); QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse()); - func = classD->findFunction(u"call2"); + func = classD->findFunction("call2"); QCOMPARE(func->modifications().size(), 1); QCOMPARE(func->modifications().at(0).argument_mods().size(), 1); QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse()); - const AbstractMetaClass *classE = AbstractMetaClass::findClass(classes, u"E"); + const auto classE = AbstractMetaClass::findClass(classes, "E"); QVERIFY(classE); - func = classE->findFunction(u"call"); + func = classE->findFunction("call"); QVERIFY(func); QCOMPARE(func->modifications().size(), 1); QCOMPARE(func->modifications().at(0).argument_mods().size(), 1); QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse()); - func = classE->findFunction(u"call2"); + func = classE->findFunction("call2"); QVERIFY(func); QCOMPARE(func->modifications().size(), 1); QCOMPARE(func->modifications().at(0).argument_mods().size(), 1); @@ -197,15 +197,15 @@ void TestModifyFunction::testWithApiVersion() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto *classB = AbstractMetaClass::findClass(classes, u"B"); - auto func = classB->findFunction(u"method"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); + auto func = classB->findFunction("method"); auto returnOwnership = func->argumentTargetOwnership(func->ownerClass(), 0); QCOMPARE(returnOwnership, TypeSystem::CppOwnership); - func = classB->findFunction(u"methodB"); + func = classB->findFunction("methodB"); returnOwnership = func->argumentTargetOwnership(func->ownerClass(), 0); QVERIFY(returnOwnership != TypeSystem::CppOwnership); } @@ -236,34 +236,34 @@ struct A { )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); // Nothing specified, true - const auto f1 = classA->findFunction(u"f1"); - QVERIFY(!f1.isNull()); + const auto f1 = classA->findFunction("f1"); + QVERIFY(f1); QVERIFY(!f1->allowThread()); // 'auto' specified, should be false for nontrivial function - const auto f2 = classA->findFunction(u"f2"); - QVERIFY(!f2.isNull()); + const auto f2 = classA->findFunction("f2"); + QVERIFY(f2); QVERIFY(f2->allowThread()); // 'no' specified, should be false - const auto f3 = classA->findFunction(u"f3"); - QVERIFY(!f3.isNull()); + const auto f3 = classA->findFunction("f3"); + QVERIFY(f3); QVERIFY(!f3->allowThread()); // Nothing specified, should be false for simple getter - const auto getter1 = classA->findFunction(u"getter1"); - QVERIFY(!getter1.isNull()); + const auto getter1 = classA->findFunction("getter1"); + QVERIFY(getter1); QVERIFY(!getter1->allowThread()); // Forced to true simple getter - const auto getter2 = classA->findFunction(u"getter2"); - QVERIFY(!getter2.isNull()); + const auto getter2 = classA->findFunction("getter2"); + QVERIFY(getter2); QVERIFY(getter2->allowThread()); // Forced to true simple getter } @@ -286,7 +286,7 @@ void TestModifyFunction::testGlobalFunctionModification() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); QCOMPARE(builder->globalFunctions().size(), 1); auto *td = TypeDatabase::instance(); @@ -434,44 +434,44 @@ void TestModifyFunction::testScopedModifications() QFETCH(bool, expectedAllowThread); QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode.constData(), xmlCode.constData(), false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); - auto f = classA->findFunction(QStringLiteral("unspecified")); - QVERIFY(!f.isNull()); + auto f = classA->findFunction("unspecified"); + QVERIFY(f); QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::Unknown); QCOMPARE(f->generateExceptionHandling(), expectedGenerateUnspecified); QCOMPARE(f->allowThread(), expectedAllowThread); - f = classA->findFunction(QStringLiteral("nonThrowing")); - QVERIFY(!f.isNull()); + f = classA->findFunction("nonThrowing"); + QVERIFY(f); QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::NoExcept); QCOMPARE(f->generateExceptionHandling(), expectedGenerateNonThrowing); - f = classA->findFunction(QStringLiteral("throwing")); - QVERIFY(!f.isNull()); + f = classA->findFunction("throwing"); + QVERIFY(f); QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::Throws); QCOMPARE(f->generateExceptionHandling(), expectedGenerateThrowing); } void TestModifyFunction::testSnakeCaseRenaming_data() { - QTest::addColumn<QString>("name"); - QTest::addColumn<QString>("expected"); + QTest::addColumn<QLatin1StringView>("name"); + QTest::addColumn<QLatin1StringView>("expected"); QTest::newRow("s1") - << QStringLiteral("snakeCaseFunc") << QStringLiteral("snake_case_func"); + << "snakeCaseFunc"_L1 << "snake_case_func"_L1; QTest::newRow("s2") - << QStringLiteral("SnakeCaseFunc") << QStringLiteral("snake_case_func"); + << "SnakeCaseFunc"_L1 << "snake_case_func"_L1; QTest::newRow("consecutive-uppercase") - << QStringLiteral("snakeCAseFunc") << QStringLiteral("snakeCAseFunc"); + << "snakeCAseFunc"_L1 << "snakeCAseFunc"_L1; } void TestModifyFunction::testSnakeCaseRenaming() { - QFETCH(QString, name); - QFETCH(QString, expected); + QFETCH(QLatin1StringView, name); + QFETCH(QLatin1StringView, expected); const QString actual = AbstractMetaBuilder::getSnakeCaseName(name); QCOMPARE(actual, expected); diff --git a/sources/shiboken6/ApiExtractor/tests/testmultipleinheritance.cpp b/sources/shiboken6/ApiExtractor/tests/testmultipleinheritance.cpp index a3f955602..1cf4c8e0f 100644 --- a/sources/shiboken6/ApiExtractor/tests/testmultipleinheritance.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testmultipleinheritance.cpp @@ -31,11 +31,11 @@ void TestMultipleInheritance::testVirtualClass() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 4); - const AbstractMetaClass *classD = AbstractMetaClass::findClass(classes, u"D"); + const auto classD = AbstractMetaClass::findClass(classes, "D"); bool functionFound = false; for (const auto &f : classD->functions()) { if (f->name() == u"theBug") { diff --git a/sources/shiboken6/ApiExtractor/tests/testnamespace.cpp b/sources/shiboken6/ApiExtractor/tests/testnamespace.cpp index 248812048..3773e614a 100644 --- a/sources/shiboken6/ApiExtractor/tests/testnamespace.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testnamespace.cpp @@ -31,14 +31,14 @@ void NamespaceTest::testNamespaceMembers() </namespace-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass *ns = AbstractMetaClass::findClass(classes, u"Namespace"); + const auto ns = AbstractMetaClass::findClass(classes, "Namespace"); QVERIFY(ns); auto metaEnum = ns->findEnum(u"Option"_s); QVERIFY(metaEnum.has_value()); - const auto func = ns->findFunction(u"foo"); - QVERIFY(!func.isNull()); + const auto func = ns->findFunction("foo"); + QVERIFY(func); } void NamespaceTest::testNamespaceInnerClassMembers() @@ -61,16 +61,16 @@ void NamespaceTest::testNamespaceInnerClassMembers() </namespace-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *ons = AbstractMetaClass::findClass(classes, u"OuterNamespace"); + const auto ons = AbstractMetaClass::findClass(classes, "OuterNamespace"); QVERIFY(ons); - const AbstractMetaClass *ins = AbstractMetaClass::findClass(classes, u"OuterNamespace::InnerNamespace"); + const auto ins = AbstractMetaClass::findClass(classes, "OuterNamespace::InnerNamespace"); QVERIFY(ins); - const AbstractMetaClass *sc = AbstractMetaClass::findClass(classes, u"OuterNamespace::InnerNamespace::SomeClass"); + const auto sc = AbstractMetaClass::findClass(classes, "OuterNamespace::InnerNamespace::SomeClass"); QVERIFY(sc); - const auto meth = sc->findFunction(u"method"); - QVERIFY(!meth.isNull()); + const auto meth = sc->findFunction("method"); + QVERIFY(meth); } QTEST_APPLESS_MAIN(NamespaceTest) diff --git a/sources/shiboken6/ApiExtractor/tests/testnestedtypes.cpp b/sources/shiboken6/ApiExtractor/tests/testnestedtypes.cpp index f6daab0b8..10ca1a0f6 100644 --- a/sources/shiboken6/ApiExtractor/tests/testnestedtypes.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testnestedtypes.cpp @@ -43,13 +43,13 @@ void TestNestedTypes::testNestedTypesModifications() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto *ons = AbstractMetaClass::findClass(classes, u"OuterNamespace"); + const auto ons = AbstractMetaClass::findClass(classes, "OuterNamespace"); QVERIFY(ons); - auto *ins = AbstractMetaClass::findClass(classes, u"OuterNamespace::InnerNamespace"); + const auto ins = AbstractMetaClass::findClass(classes, "OuterNamespace::InnerNamespace"); QVERIFY(ins); QCOMPARE(ins->functions().size(), 1); QCOMPARE(ins->typeEntry()->codeSnips().size(), 1); @@ -68,8 +68,9 @@ void TestNestedTypes::testNestedTypesModifications() snip = addedFunc->modifications().constFirst().snips().constFirst(); QCOMPARE(snip.code().trimmed(), u"custom_code2();"); - auto *sc = AbstractMetaClass::findClass(classes, u"OuterNamespace::InnerNamespace::SomeClass"); - QVERIFY(ins); + const auto sc = + AbstractMetaClass::findClass(classes, "OuterNamespace::InnerNamespace::SomeClass"); + QVERIFY(sc); QCOMPARE(sc->functions().size(), 2); // default constructor and removed method const auto removedFunc = sc->functions().constLast(); QVERIFY(removedFunc->isModifiedRemoved()); @@ -92,23 +93,23 @@ void TestNestedTypes::testDuplicationOfNestedTypes() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *nspace = AbstractMetaClass::findClass(classes, u"Namespace"); + const auto nspace = AbstractMetaClass::findClass(classes, "Namespace"); QVERIFY(nspace); - auto *cls1 = AbstractMetaClass::findClass(classes, u"SomeClass"); + const auto cls1 = AbstractMetaClass::findClass(classes, "SomeClass"); QVERIFY(cls1); - auto *cls2 = AbstractMetaClass::findClass(classes, u"Namespace::SomeClass"); + const auto cls2 = AbstractMetaClass::findClass(classes, "Namespace::SomeClass"); QVERIFY(cls2); QCOMPARE(cls1, cls2); QCOMPARE(cls1->name(), u"SomeClass"); QCOMPARE(cls1->qualifiedCppName(), u"Namespace::SomeClass"); auto t1 = TypeDatabase::instance()->findType(u"Namespace::SomeClass"_s); - QVERIFY(!t1.isNull()); + QVERIFY(t1); auto t2 = TypeDatabase::instance()->findType(u"SomeClass"_s); - QVERIFY(t2.isNull()); + QVERIFY(!t2); } QTEST_APPLESS_MAIN(TestNestedTypes) diff --git a/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp b/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp index 8dc9b641b..9eef7ec47 100644 --- a/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp @@ -24,7 +24,7 @@ void TestNumericalTypedef::testNumericalTypedef() <function signature='funcReal(real)'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); QCOMPARE(builder->globalFunctions().size(), 2); auto funcDouble = builder->globalFunctions().constFirst(); @@ -63,7 +63,7 @@ void TestNumericalTypedef::testUnsignedNumericalTypedef() <function signature='funcUShort(custom_ushort)'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); QCOMPARE(builder->globalFunctions().size(), 2); auto funcUnsignedShort = builder->globalFunctions().constFirst(); diff --git a/sources/shiboken6/ApiExtractor/tests/testprimitivetypetag.cpp b/sources/shiboken6/ApiExtractor/tests/testprimitivetypetag.cpp index ba2b25829..99cced09d 100644 --- a/sources/shiboken6/ApiExtractor/tests/testprimitivetypetag.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testprimitivetypetag.cpp @@ -23,15 +23,15 @@ void TestPrimitiveTypeTag::testPrimitiveTypeDefaultConstructor() <object-type name='B'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); auto typeEntry = TypeDatabase::instance()->findPrimitiveType(u"A"_s); - QVERIFY(!typeEntry.isNull()); + QVERIFY(typeEntry); QVERIFY(typeEntry->hasDefaultConstructor()); QCOMPARE(typeEntry->defaultConstructor(), u"A()"); } diff --git a/sources/shiboken6/ApiExtractor/tests/testrefcounttag.cpp b/sources/shiboken6/ApiExtractor/tests/testrefcounttag.cpp index ef83d99fb..f2e261624 100644 --- a/sources/shiboken6/ApiExtractor/tests/testrefcounttag.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testrefcounttag.cpp @@ -32,11 +32,11 @@ void TestRefCountTag::testReferenceCountTag() </object-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); - const auto func = classB->findFunction(u"keepObject"); - QVERIFY(!func.isNull()); + const auto classB = AbstractMetaClass::findClass(classes, "B"); + const auto func = classB->findFunction("keepObject"); + QVERIFY(func); const auto refCount = func->modifications().constFirst().argument_mods().constFirst().referenceCounts().constFirst(); QCOMPARE(refCount.action, ReferenceCount::Add); @@ -66,11 +66,11 @@ void TestRefCountTag::testWithApiVersion() QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); - const auto func = classB->findFunction(u"keepObject"); - QVERIFY(!func.isNull()); + const auto classB = AbstractMetaClass::findClass(classes, "B"); + const auto func = classB->findFunction("keepObject"); + QVERIFY(func); const auto refCount = func->modifications().constFirst().argument_mods().constFirst().referenceCounts().constFirst(); QCOMPARE(refCount.action, ReferenceCount::Add); diff --git a/sources/shiboken6/ApiExtractor/tests/testreferencetopointer.cpp b/sources/shiboken6/ApiExtractor/tests/testreferencetopointer.cpp index 74a0adcea..ae85c5a86 100644 --- a/sources/shiboken6/ApiExtractor/tests/testreferencetopointer.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testreferencetopointer.cpp @@ -23,12 +23,12 @@ void TestReferenceToPointer::testReferenceToPointerArgument() <object-type name='B'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); - const auto func = classB->findFunction(u"dummy"); - QVERIFY(!func.isNull()); + const auto func = classB->findFunction("dummy"); + QVERIFY(func); QCOMPARE(func->arguments().constFirst().type().minimalSignature(), u"A*&"); } diff --git a/sources/shiboken6/ApiExtractor/tests/testremovefield.cpp b/sources/shiboken6/ApiExtractor/tests/testremovefield.cpp index e0acb0e5b..2cc82071b 100644 --- a/sources/shiboken6/ApiExtractor/tests/testremovefield.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testremovefield.cpp @@ -4,10 +4,15 @@ #include "testremovefield.h" #include <QtTest/QTest> #include "testutil.h" +#include <abstractmetaargument.h> #include <abstractmetafield.h> +#include <abstractmetafunction.h> +#include <abstractmetatype.h> #include <abstractmetalang.h> #include <typesystem.h> +using namespace Qt::StringLiterals; + void TestRemoveField::testRemoveField() { const char cppCode[] = "\ @@ -23,15 +28,49 @@ void TestRemoveField::testRemoveField() </value-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->fields().size(), 1); const AbstractMetaField &fieldA = classA->fields().constFirst(); QCOMPARE(fieldA.name(), u"fieldA"); } +// Verify that 'static constexpr' fields are seen as static/const and +// appear fully qualified for function parameter default values. +void TestRemoveField::testConstExprField() +{ + const char cppCode[] = R"( +struct A { + static constexpr int constExprField = 44; + + void f(int iParam=constExprField); +}; +)"; + + const char xmlCode[] = R"( +<typesystem package="Foo"> + <value-type name='A'/> +</typesystem> +)"; + + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(builder); + AbstractMetaClassList classes = builder->classes(); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + QVERIFY(classA); + const auto &fields = classA->fields(); + QCOMPARE(fields.size(), 1); + QVERIFY(fields.constFirst().isStatic()); + QVERIFY(fields.constFirst().type().isConstant()); + const auto function = classA->findFunction("f"_L1); + QVERIFY(function); + const auto &arguments = function->arguments(); + QCOMPARE(arguments.size(), 1); + QCOMPARE(arguments.constFirst().defaultValueExpression(), "A::constExprField"_L1); +} + QTEST_APPLESS_MAIN(TestRemoveField) diff --git a/sources/shiboken6/ApiExtractor/tests/testremovefield.h b/sources/shiboken6/ApiExtractor/tests/testremovefield.h index febe672ce..05912d99e 100644 --- a/sources/shiboken6/ApiExtractor/tests/testremovefield.h +++ b/sources/shiboken6/ApiExtractor/tests/testremovefield.h @@ -11,6 +11,7 @@ class TestRemoveField : public QObject Q_OBJECT private slots: void testRemoveField(); + void testConstExprField(); }; #endif diff --git a/sources/shiboken6/ApiExtractor/tests/testremoveimplconv.cpp b/sources/shiboken6/ApiExtractor/tests/testremoveimplconv.cpp index 59528d517..87e318e95 100644 --- a/sources/shiboken6/ApiExtractor/tests/testremoveimplconv.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testremoveimplconv.cpp @@ -30,14 +30,14 @@ void TestRemoveImplConv::testRemoveImplConv() </value-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 3); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); - const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, u"C"); + const auto classC = AbstractMetaClass::findClass(classes, "C"); QVERIFY(classC); const auto implConv = classC->implicitConversions(); QCOMPARE(implConv.size(), 1); diff --git a/sources/shiboken6/ApiExtractor/tests/testremoveoperatormethod.cpp b/sources/shiboken6/ApiExtractor/tests/testremoveoperatormethod.cpp index a6d929c8f..17a069b5e 100644 --- a/sources/shiboken6/ApiExtractor/tests/testremoveoperatormethod.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testremoveoperatormethod.cpp @@ -15,28 +15,29 @@ using namespace Qt::StringLiterals; void TestRemoveOperatorMethod::testRemoveOperatorMethod() { - const char cppCode[] = "\ - #include <stdint.h>\n\ - \n\ - struct Char {};\n\ - struct ByteArray {};\n\ - struct String {};\n\ - \n\ - struct A {\n\ - A& operator>>(char&);\n\ - A& operator>>(char*);\n\ - A& operator>>(short&);\n\ - A& operator>>(unsigned short&);\n\ - A& operator>>(int&);\n\ - A& operator>>(unsigned int&);\n\ - A& operator>>(int64_t&);\n\ - A& operator>>(uint64_t&);\n\ - A& operator>>(float&);\n\ - A& operator>>(double&);\n\ - A& operator>>(Char&);\n\ - A& operator>>(ByteArray&);\n\ - A& operator>>(String&);\n\ - };\n"; + const char cppCode[] = R"(#include <cstdint> + +struct Char {}; +struct ByteArray {}; +struct String {}; + +struct A { + A& operator>>(char&); + A& operator>>(char*); + A& operator>>(short&); + A& operator>>(unsigned short&); + A& operator>>(int&); + A& operator>>(unsigned int&); + A& operator>>(int64_t&); + A& operator>>(uint64_t&); + A& operator>>(float&); + A& operator>>(double&); + A& operator>>(Char&); + A& operator>>(ByteArray&); + A& operator>>(String&); +}; +)"; + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='char'/>\n\ @@ -67,9 +68,9 @@ void TestRemoveOperatorMethod::testRemoveOperatorMethod() </object-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->functions().size(), 14); QStringList removedSignatures; diff --git a/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp b/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp index a798c4339..67ebcc606 100644 --- a/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp @@ -4,10 +4,12 @@ #include "testresolvetype.h" #include "testutil.h" #include <abstractmetaargument.h> +#include <abstractmetaenum.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> #include <abstractmetatype.h> #include <complextypeentry.h> +#include <enumtypeentry.h> #include <primitivetypeentry.h> #include <typedatabase.h> @@ -45,12 +47,12 @@ void TestResolveType::testResolveReturnTypeFromParentScope() </namespace-type> </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classD = AbstractMetaClass::findClass(classes, u"A::D"); + const auto classD = AbstractMetaClass::findClass(classes, "A::D"); QVERIFY(classD); - const auto meth = classD->findFunction(u"method"); - QVERIFY(!meth.isNull()); + const auto meth = classD->findFunction("method"); + QVERIFY(meth); QVERIFY(meth); } @@ -60,13 +62,14 @@ void TestResolveType::testResolveReturnTypeFromParentScope() struct DefaultValuesFixture { - QSharedPointer<AbstractMetaBuilder> builder; + std::shared_ptr<AbstractMetaBuilder> builder; AbstractMetaType intType; AbstractMetaType stringType; AbstractMetaType classType; AbstractMetaType listType; - const AbstractMetaClass *klass{}; + AbstractMetaType enumType; + AbstractMetaClassCPtr klass{}; }; Q_DECLARE_METATYPE(DefaultValuesFixture) @@ -91,6 +94,7 @@ public: static const int INT_FIELD_1 = 42; static const char *CHAR_FIELD_1; + static const Enum DefaultValue = enumValue1; }; } // Namespace )"; @@ -106,7 +110,7 @@ public: )"; fixture->builder.reset(TestUtil::parse(cppCode, xmlCode, false)); - if (fixture->builder.isNull()) + if (!fixture->builder) return -1; for (const auto &klass : fixture->builder->classes()) { @@ -121,7 +125,7 @@ public: fixture->classType = AbstractMetaType(fixture->klass->typeEntry()); fixture->classType.decideUsagePattern(); - for (const auto &f : fixture->klass->findFunctions(u"Test"_s)) { + for (const auto &f : fixture->klass->findFunctions("Test")) { if (f->functionType() == AbstractMetaFunction::ConstructorFunction && f->arguments().size() == 1) { const auto type = f->arguments().constFirst().type(); @@ -134,11 +138,14 @@ public: if (fixture->intType.isVoid() || fixture->stringType.isVoid()) return -3; - auto listFunc = fixture->klass->findFunction(u"listFunc"_s); - if (listFunc.isNull() || listFunc->arguments().size() != 1) + auto listFunc = fixture->klass->findFunction("listFunc"); + if (!listFunc || listFunc->arguments().size() != 1) return -3; fixture->listType = listFunc->arguments().constFirst().type(); + fixture->enumType = AbstractMetaType(fixture->klass->enums().constFirst().typeEntry()); + fixture->enumType.decideUsagePattern(); + return 0; } @@ -213,6 +220,11 @@ void TestResolveType::testFixDefaultArguments_data() QTest::newRow("self from enum") << fixture << setupOk << fixture.classType << "Test(enumValue1)" << expected; + + // Don't qualify fields to "Test::Enum::DefaultValue" + QTest::newRow("enum from static field") + << fixture << setupOk << fixture.enumType + << "DefaultValue" << u"Namespace::Test::DefaultValue"_s; } void TestResolveType::testFixDefaultArguments() @@ -251,16 +263,16 @@ public: )"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *testClass = AbstractMetaClass::findClass(classes, u"Test"); + const auto testClass = AbstractMetaClass::findClass(classes, "Test"); QVERIFY(testClass); auto *tdb = TypeDatabase::instance(); auto int32TEntry = tdb->findType(u"int32_t"_s); - QVERIFY2(!int32TEntry.isNull(), "int32_t not found"); + QVERIFY2(int32TEntry, "int32_t not found"); QVERIFY(int32TEntry->isPrimitive()); - auto int32T = qSharedPointerCast<const PrimitiveTypeEntry>(int32TEntry); + auto int32T = std::static_pointer_cast<const PrimitiveTypeEntry>(int32TEntry); auto basicType = basicReferencedTypeEntry(int32T); QVERIFY2(basicType != int32T, "Typedef for int32_t not found. Check the system include paths."); diff --git a/sources/shiboken6/ApiExtractor/tests/testreverseoperators.cpp b/sources/shiboken6/ApiExtractor/tests/testreverseoperators.cpp index 0e191668b..f4eecff2c 100644 --- a/sources/shiboken6/ApiExtractor/tests/testreverseoperators.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testreverseoperators.cpp @@ -25,9 +25,9 @@ void TestReverseOperators::testReverseSum() </typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->functions().size(), 4); @@ -42,10 +42,10 @@ void TestReverseOperators::testReverseSum() } } - QVERIFY(!normalOp.isNull()); + QVERIFY(normalOp); QVERIFY(!normalOp->isReverseOperator()); QCOMPARE(normalOp->arguments().size(), 1); - QVERIFY(!reverseOp.isNull()); + QVERIFY(reverseOp); QVERIFY(reverseOp->isReverseOperator()); QCOMPARE(reverseOp->arguments().size(), 1); } @@ -67,13 +67,13 @@ void TestReverseOperators::testReverseSumWithAmbiguity() </typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->functions().size(), 4); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); QCOMPARE(classB->functions().size(), 4); @@ -87,11 +87,11 @@ void TestReverseOperators::testReverseSumWithAmbiguity() normalOp = func; } } - QVERIFY(!normalOp.isNull()); + QVERIFY(normalOp); QVERIFY(!normalOp->isReverseOperator()); QCOMPARE(normalOp->arguments().size(), 1); QCOMPARE(normalOp->minimalSignature(), u"operator+(B,A)"); - QVERIFY(!reverseOp.isNull()); + QVERIFY(reverseOp); QVERIFY(reverseOp->isReverseOperator()); QCOMPARE(reverseOp->arguments().size(), 1); QCOMPARE(reverseOp->minimalSignature(), u"operator+(A,B)"); @@ -111,10 +111,10 @@ void TestReverseOperators::testSpaceshipOperator() </typesystem>)"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, {}, {}, LanguageLevel::Cpp20)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - const AbstractMetaClass *testClass = AbstractMetaClass::findClass(classes, u"Test"); + const auto testClass = AbstractMetaClass::findClass(classes, "Test"); QVERIFY(testClass); const auto &functions = testClass->functions(); // 6 operators should be synthesized diff --git a/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp b/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp index 65c95e378..ea37c6255 100644 --- a/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp @@ -55,16 +55,16 @@ namespace Internet { </typesystem>)XML").arg(file.fileName()); QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, qPrintable(xmlCode1), false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto *classB = AbstractMetaClass::findClass(classes, u"Bookmarks"); + const auto classB = AbstractMetaClass::findClass(classes, "Bookmarks"); QVERIFY(classB); - const auto func = classB->findFunction(u"list"); - QVERIFY(!func.isNull()); + const auto func = classB->findFunction("list"); + QVERIFY(func); AbstractMetaType funcType = func->type(); QVERIFY(!funcType.isVoid()); - QCOMPARE(funcType.cppSignature(), u"QList<Internet::Url >"); + QCOMPARE(funcType.cppSignature(), u"QList<Internet::Url>"); } void TestTemplates::testTemplateOnContainers() @@ -93,15 +93,15 @@ namespace Namespace { </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); QVERIFY(!classB->baseClass()); QVERIFY(classB->baseClassName().isEmpty()); - const auto func = classB->findFunction(u"foo"); - QVERIFY(!func.isNull()); + const auto func = classB->findFunction("foo"); + QVERIFY(func); AbstractMetaType argType = func->arguments().constFirst().type(); QCOMPARE(argType.instantiations().size(), 1); QCOMPARE(argType.typeEntry()->qualifiedCppName(), u"QList"); @@ -130,14 +130,14 @@ void func(List<int> arg) {} </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); const auto globalFuncs = builder->globalFunctions(); QCOMPARE(globalFuncs.size(), 1); const auto func = globalFuncs.constFirst(); QCOMPARE(func->minimalSignature(), u"func(List<int>)"); QCOMPARE(func->arguments().constFirst().type().cppSignature(), - u"List<int >"); + u"List<int>"); } void TestTemplates::testTemplatePointerAsArgument() @@ -155,14 +155,14 @@ void func(List<int>* arg) {} </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaFunctionCList globalFuncs = builder->globalFunctions(); QCOMPARE(globalFuncs.size(), 1); const auto func = globalFuncs.constFirst(); QCOMPARE(func->minimalSignature(), u"func(List<int>*)"); QCOMPARE(func->arguments().constFirst().type().cppSignature(), - u"List<int > *"); + u"List<int> *"); } void TestTemplates::testTemplateReferenceAsArgument() @@ -180,14 +180,14 @@ void func(List<int>& arg) {} </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); const auto globalFuncs = builder->globalFunctions(); QCOMPARE(globalFuncs.size(), 1); const auto func = globalFuncs.constFirst(); QCOMPARE(func->minimalSignature(), u"func(List<int>&)"); QCOMPARE(func->arguments().constFirst().type().cppSignature(), - u"List<int > &"); + u"List<int> &"); } void TestTemplates::testTemplateParameterFixup() @@ -209,21 +209,20 @@ struct List { </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); const AbstractMetaClassList templates = builder->templates(); QCOMPARE(templates.size(), 1); - const AbstractMetaClass *list = templates.constFirst(); - // Verify that the parameter of "void append(List l)" gets fixed to "List<T >" - const auto append = list->findFunction(QStringLiteral("append")); - QVERIFY(!append.isNull()); + AbstractMetaClassCPtr list = templates.constFirst(); + // Verify that the parameter of "void append(List l)" gets fixed to "List<T>" + const auto append = list->findFunction("append"); + QVERIFY(append); QCOMPARE(append->arguments().size(), 1); - QCOMPARE(append->arguments().at(0).type().cppSignature(), u"List<T >"); + QCOMPARE(append->arguments().at(0).type().cppSignature(), u"List<T>"); // Verify that the parameter of "void erase(Iterator)" is not modified - const auto erase = list->findFunction(QStringLiteral("erase")); - QVERIFY(!erase.isNull()); + const auto erase = list->findFunction("erase"); + QVERIFY(erase); QCOMPARE(erase->arguments().size(), 1); - QEXPECT_FAIL("", "Clang: Some other code changes the parameter type", Abort); QCOMPARE(erase->arguments().at(0).type().cppSignature(), u"List::Iterator"); } @@ -250,16 +249,16 @@ struct FooBars : public ListContainer<FooBar> {}; </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); AbstractMetaClassList templates = builder->templates(); QCOMPARE(classes.size(), 2); QCOMPARE(templates.size(), 1); - const auto *foobars = AbstractMetaClass::findClass(classes, u"FooBars"); + const auto foobars = AbstractMetaClass::findClass(classes, "FooBars"); QCOMPARE(foobars->functions().size(), 4); - const AbstractMetaClass *lc = templates.constFirst(); + AbstractMetaClassCPtr lc = templates.constFirst(); QCOMPARE(lc->functions().size(), 2); } @@ -287,10 +286,10 @@ template<SomeEnum type> struct Future {}; </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); QVERIFY(!classB->baseClass()); QVERIFY(classB->baseClassName().isEmpty()); @@ -326,10 +325,10 @@ template<SomeEnum type> struct Future {}; </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto *classB = AbstractMetaClass::findClass(classes, u"Namespace::B"); + const auto classB = AbstractMetaClass::findClass(classes, "Namespace::B"); QVERIFY(classB); QVERIFY(!classB->baseClass()); QVERIFY(classB->baseClassName().isEmpty()); @@ -362,13 +361,13 @@ typedef BaseTemplateClass<TypeOne> TypeOneClass; </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 3); - const auto *base = AbstractMetaClass::findClass(classes, u"BaseTemplateClass"); + const auto base = AbstractMetaClass::findClass(classes, "BaseTemplateClass"); QVERIFY(base); - const auto *one = AbstractMetaClass::findClass(classes, u"TypeOneClass"); + const auto one = AbstractMetaClass::findClass(classes, "TypeOneClass"); QVERIFY(one); QCOMPARE(one->templateBaseClass(), base); QCOMPARE(one->functions().size(), base->functions().size()); @@ -376,7 +375,7 @@ typedef BaseTemplateClass<TypeOne> TypeOneClass; auto oneType = one->typeEntry(); auto baseType = base->typeEntry(); QCOMPARE(oneType->baseContainerType(), baseType); - QCOMPARE(one->baseClassNames(), QStringList(u"BaseTemplateClass<TypeOne>"_s)); + QCOMPARE(one->baseClassNames(), QStringList(u"NSpace::BaseTemplateClass<NSpace::TypeOne>"_s)); QVERIFY(one->hasTemplateBaseClassInstantiations()); AbstractMetaTypeList instantiations = one->templateBaseClassInstantiations(); @@ -411,27 +410,27 @@ typedef Vector<int> IntVector; </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - auto *vector = AbstractMetaClass::findClass(classes, u"IntVector"); + const auto vector = AbstractMetaClass::findClass(classes, "IntVector"); QVERIFY(vector); auto baseContainer = vector->typeEntry()->baseContainerType(); - QVERIFY(!baseContainer.isNull()); - QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer.data())->containerKind(), + QVERIFY(baseContainer); + QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer.get())->containerKind(), ContainerTypeEntry::ListContainer); QCOMPARE(vector->functions().size(), 4); - const auto method = vector->findFunction(u"method"); - QVERIFY(!method.isNull()); - QCOMPARE(method->signature(), u"method(const Vector<int > & vector)"); + const auto method = vector->findFunction("method"); + QVERIFY(method); + QCOMPARE(method->signature(), u"method(const Vector<int> & vector)"); - const auto otherMethod = vector->findFunction(u"otherMethod"); - QVERIFY(!otherMethod.isNull()); + const auto otherMethod = vector->findFunction("otherMethod"); + QVERIFY(otherMethod); QCOMPARE(otherMethod->signature(), u"otherMethod()"); QVERIFY(!otherMethod->type().isVoid()); - QCOMPARE(otherMethod->type().cppSignature(), u"Vector<int >"); + QCOMPARE(otherMethod->type().cppSignature(), u"Vector<int>"); } void TestTemplates::testNonTypeTemplates() @@ -455,7 +454,7 @@ Array<int, 2> foo(); </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); auto functions = builder->globalFunctions(); QCOMPARE(functions.size(), 1); auto foo = functions.constFirst(); @@ -538,32 +537,30 @@ void TestTemplates::testTemplateTypeDefs() const QByteArray cppBa = cpp.toLocal8Bit(); const QByteArray xmlBa = xml.toLocal8Bit(); QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppBa.constData(), xmlBa.constData(), true)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *optional = AbstractMetaClass::findClass(classes, u"Optional"); + const auto optional = AbstractMetaClass::findClass(classes, "Optional"); QVERIFY(optional); // Find the typedef'ed class - const AbstractMetaClass *optionalInt = - AbstractMetaClass::findClass(classes, u"IntOptional"); + const auto optionalInt = AbstractMetaClass::findClass(classes, "IntOptional"); QVERIFY(optionalInt); QCOMPARE(optionalInt->templateBaseClass(), optional); // Find the class typedef'ed in the typesystem XML - const AbstractMetaClass *xmlOptionalInt = - AbstractMetaClass::findClass(classes, u"XmlIntOptional"); + const auto xmlOptionalInt = AbstractMetaClass::findClass(classes, "XmlIntOptional"); QVERIFY(xmlOptionalInt); QCOMPARE(xmlOptionalInt->templateBaseClass(), optional); // Check whether the value() method now has an 'int' return - const auto valueMethod = optionalInt->findFunction(u"value"); - QVERIFY(!valueMethod.isNull()); + const auto valueMethod = optionalInt->findFunction("value"); + QVERIFY(valueMethod); QCOMPARE(valueMethod->type().cppSignature(), u"int"); // ditto for typesystem XML - const auto xmlValueMethod = xmlOptionalInt->findFunction(u"value"); - QVERIFY(!xmlValueMethod.isNull()); + const auto xmlValueMethod = xmlOptionalInt->findFunction("value"); + QVERIFY(xmlValueMethod); QCOMPARE(xmlValueMethod->type().cppSignature(), u"int"); // Check whether the m_value field is of type 'int' @@ -609,10 +606,10 @@ public: </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto testClass = AbstractMetaClass::findClass(classes, u"Test"); + const auto testClass = AbstractMetaClass::findClass(classes, "Test"); QVERIFY(testClass); auto fields = testClass->fields(); @@ -621,9 +618,10 @@ public: QCOMPARE(fieldType.name(), u"Container1"); QCOMPARE(fieldType.instantiations().size(), 1); - auto derived = AbstractMetaClass::findClass(classes, u"Derived"); + const auto derived = AbstractMetaClass::findClass(classes, "Derived"); QVERIFY(derived); auto base = derived->templateBaseClass(); + QVERIFY(base); QCOMPARE(base->name(), u"Container1"); } diff --git a/sources/shiboken6/ApiExtractor/tests/testtyperevision.cpp b/sources/shiboken6/ApiExtractor/tests/testtyperevision.cpp index 1ebe71ef6..72dae8cc5 100644 --- a/sources/shiboken6/ApiExtractor/tests/testtyperevision.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testtyperevision.cpp @@ -30,15 +30,15 @@ void TestTypeRevision::testRevisionAttr() "</object-type>" "</typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *rev0 = AbstractMetaClass::findClass(classes, u"Rev_0"); + const auto rev0 = AbstractMetaClass::findClass(classes, "Rev_0"); QCOMPARE(rev0->typeEntry()->revision(), 0); - const AbstractMetaClass *rev1 = AbstractMetaClass::findClass(classes, u"Rev_1"); + const auto rev1 = AbstractMetaClass::findClass(classes, "Rev_1"); QCOMPARE(rev1->typeEntry()->revision(), 1); - AbstractMetaClass *rev2 = AbstractMetaClass::findClass(classes, u"Rev_2"); + const auto rev2 = AbstractMetaClass::findClass(classes, "Rev_2"); QCOMPARE(rev2->typeEntry()->revision(), 2); auto rev3 = rev2->findEnum(u"Rev_3"_s); @@ -82,7 +82,7 @@ class Bar20 {}; )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, version)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); QCOMPARE(builder->classes().size(), expectedClassCount); } diff --git a/sources/shiboken6/ApiExtractor/tests/testutil.h b/sources/shiboken6/ApiExtractor/tests/testutil.h index e19517e85..dc4e3b2da 100644 --- a/sources/shiboken6/ApiExtractor/tests/testutil.h +++ b/sources/shiboken6/ApiExtractor/tests/testutil.h @@ -27,19 +27,19 @@ namespace TestUtil auto *td = TypeDatabase::instance(true); if (apiVersion.isEmpty()) TypeDatabase::clearApiVersions(); - else if (!TypeDatabase::setApiVersion(QStringLiteral("*"), apiVersion)) + else if (!TypeDatabase::setApiVersion(QLatin1StringView("*"), apiVersion)) return nullptr; td->setDropTypeEntries(dropTypeEntries); QBuffer buffer; // parse typesystem buffer.setData(xmlCode); if (!buffer.open(QIODevice::ReadOnly)) - return Q_NULLPTR; + return nullptr; if (!td->parseFile(&buffer)) return nullptr; buffer.close(); // parse C++ code - QTemporaryFile tempSource(QDir::tempPath() + QStringLiteral("/st_XXXXXX_main.cpp")); + QTemporaryFile tempSource(QDir::tempPath() + QLatin1StringView("/st_XXXXXX_main.cpp")); if (!tempSource.open()) { qWarning().noquote().nospace() << "Creation of temporary file failed: " << tempSource.errorString(); diff --git a/sources/shiboken6/ApiExtractor/tests/testvaluetypedefaultctortag.cpp b/sources/shiboken6/ApiExtractor/tests/testvaluetypedefaultctortag.cpp index 06fbe9ee3..98e30eac2 100644 --- a/sources/shiboken6/ApiExtractor/tests/testvaluetypedefaultctortag.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testvaluetypedefaultctortag.cpp @@ -22,16 +22,16 @@ void TestValueTypeDefaultCtorTag::testValueTypeDefaultCtorTagArgument() <value-type name='B' />\n\ </typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QVERIFY(classA->typeEntry()->hasDefaultConstructor()); QCOMPARE(classA->typeEntry()->defaultConstructor(), u"A(0, 0)"); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); QVERIFY(!classB->typeEntry()->hasDefaultConstructor()); } diff --git a/sources/shiboken6/ApiExtractor/tests/testvoidarg.cpp b/sources/shiboken6/ApiExtractor/tests/testvoidarg.cpp index 255a33953..a600181a5 100644 --- a/sources/shiboken6/ApiExtractor/tests/testvoidarg.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testvoidarg.cpp @@ -17,12 +17,12 @@ void TestVoidArg::testVoidParsedFunction() <value-type name='A'/>\n\ </typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const auto addedFunc = classA->findFunction(u"a"); - QVERIFY(!addedFunc.isNull()); + const auto addedFunc = classA->findFunction("a"); + QVERIFY(addedFunc); QCOMPARE(addedFunc->arguments().size(), 0); } @@ -36,12 +36,12 @@ void TestVoidArg::testVoidAddedFunction() </value-type>\n\ </typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const auto addedFunc = classA->findFunction(u"a"); - QVERIFY(!addedFunc.isNull()); + const auto addedFunc = classA->findFunction("a"); + QVERIFY(addedFunc); QCOMPARE(addedFunc->arguments().size(), 0); } @@ -54,12 +54,12 @@ void TestVoidArg::testVoidPointerParsedFunction() <value-type name='A' />\n\ </typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const auto addedFunc = classA->findFunction(u"a"); - QVERIFY(!addedFunc.isNull()); + const auto addedFunc = classA->findFunction("a"); + QVERIFY(addedFunc); QCOMPARE(addedFunc->arguments().size(), 1); } diff --git a/sources/shiboken6/ApiExtractor/textstream.h b/sources/shiboken6/ApiExtractor/textstream.h index 074e23858..228f36405 100644 --- a/sources/shiboken6/ApiExtractor/textstream.h +++ b/sources/shiboken6/ApiExtractor/textstream.h @@ -31,7 +31,7 @@ public: virtual ~TextStream(); Language language() const { return m_language; } - void setLanguage(const Language &language) { m_language = language; } + void setLanguage(Language language) { m_language = language; } bool isIndentationEnabled() const { return m_indentationEnabled; } void setIndentationEnabled(bool m) @@ -77,6 +77,10 @@ public: void putRawChar(char c) { m_str << c; } TextStream &operator<<(QStringView v) { putString(v); return *this; } + TextStream &operator<<(const QString &qs) { putString(QStringView{qs}); return *this; } + TextStream &operator<<(QLatin1StringView lv) { putString(lv.constData()); return *this; } + TextStream &operator<<(QUtf8StringView uv) { putString(uv.data()); return *this; } + TextStream &operator<<(const QByteArray &ba) { putString(ba.constData()); return *this; } TextStream &operator<<(QChar c) { putChar(c); return *this; } TextStream &operator<<(const char *s) { putString(s); return *this; } TextStream &operator<<(char c) { putChar(c); return *this; } @@ -85,7 +89,7 @@ public: TextStream &operator<<(qsizetype t) { putSizeType(t); return *this; } #endif - inline TextStream &operator<<(QTextStreamManipulator m) { m_str << m; return *this; } + inline TextStream &operator<<(const QTextStreamManipulator &m) { m_str << m; return *this; } inline TextStream &operator<<(ManipulatorFunc f) { f(*this); return *this; } void putRepetitiveChars(char c, int count); @@ -140,6 +144,12 @@ void rstCodeOff(TextStream &s); void rstItalic(TextStream &s); void rstItalicOff(TextStream &s); +inline TextStream &operator<<(TextStream &str, QAnyStringView asv) +{ + asv.visit([&str](auto s) { str << s; }); + return str; +} + /// Format an aligned field template <class T> class AlignedField @@ -179,6 +189,28 @@ TextStream &operator<<(TextStream &str, const AlignedField<T> &fa) return str; } +class Pad +{ +public: + explicit Pad(char c, int count) : m_char(c), m_count(count) {} + + void write(TextStream &str) const + { + for (int i = 0; i < m_count; ++i) + str << m_char; + } + +private: + const char m_char; + const int m_count; +}; + +inline TextStream &operator<<(TextStream &str, const Pad &pad) +{ + pad.write(str); + return str; +} + class Indentation { public: diff --git a/sources/shiboken6/ApiExtractor/typedatabase.cpp b/sources/shiboken6/ApiExtractor/typedatabase.cpp index c185907b0..61fd22418 100644 --- a/sources/shiboken6/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken6/ApiExtractor/typedatabase.cpp @@ -10,11 +10,14 @@ #include "constantvaluetypeentry.h" #include "containertypeentry.h" #include "customtypenentry.h" +#include "debughelpers_p.h" +#include "exception.h" #include "flagstypeentry.h" #include "functiontypeentry.h" #include "namespacetypeentry.h" #include "objecttypeentry.h" #include "primitivetypeentry.h" +#include "optionsparser.h" #include "pythontypeentry.h" #include "smartpointertypeentry.h" #include "typedefentry.h" @@ -32,29 +35,29 @@ #include <QtCore/QFile> #include <QtCore/QDebug> #include <QtCore/QDir> -#include <QtCore/QPair> #include <QtCore/QList> #include <QtCore/QRegularExpression> #include <QtCore/QVersionNumber> #include <QtCore/QXmlStreamReader> #include "reporthandler.h" -// #include <tr1/tuple> + #include <algorithm> +#include <utility> using namespace Qt::StringLiterals; -using TypeDatabaseParserContextPtr = QSharedPointer<TypeDatabaseParserContext>; +using TypeDatabaseParserContextPtr = std::shared_ptr<TypeDatabaseParserContext>; // package -> api-version static QString wildcardToRegExp(QString w) { w.replace(u'?', u'.'); - w.replace(u'*', QStringLiteral(".*")); + w.replace(u'*', ".*"_L1); return w; } -using ApiVersion =QPair<QRegularExpression, QVersionNumber>; +using ApiVersion = std::pair<QRegularExpression, QVersionNumber>; using ApiVersions = QList<ApiVersion>; Q_GLOBAL_STATIC(ApiVersions, apiVersions) @@ -85,7 +88,8 @@ static const PythonTypes &builtinPythonTypes() {u"PyObject"_s, u"true"_s, TypeSystem::CPythonType::Other}, // shiboken-specific {u"PyPathLike"_s, u"Shiboken::String::checkPath"_s, TypeSystem::CPythonType::Other}, - {u"PySequence"_s, u"Shiboken::String::checkIterable"_s, TypeSystem::CPythonType::Other}, + {u"PySequence"_s, u"Shiboken::String::checkIterableArgument"_s, + TypeSystem::CPythonType::Other}, {u"PyUnicode"_s, u"PyUnicode_Check"_s, TypeSystem::CPythonType::String}, {u"PyTypeObject"_s, u"PyType_Check"_s, TypeSystem::CPythonType::Other}, {u"str"_s, u"Shiboken::String::check"_s, TypeSystem::CPythonType::String}, @@ -100,7 +104,127 @@ static const PythonTypes &builtinPythonTypes() return result; } -struct TypeDatabasePrivate +struct SuppressedWarning +{ + QRegularExpression pattern; + QString rawText; + bool generate; // Current type system + mutable bool matched = false; +}; + +QList<OptionDescription> TypeDatabase::options() +{ + return { + {u"api-version=<\"package mask\">,<\"version\">"_s, + u"Specify the supported api version used to generate the bindings"_s}, + {u"drop-type-entries=\"<TypeEntry0>[;TypeEntry1;...]\""_s, + u"Semicolon separated list of type system entries (classes, namespaces,\n" + "global functions and enums) to be dropped from generation."_s}, + {u"-T<path>"_s, {} }, + {u"typesystem-paths="_s + OptionsParser::pathSyntax(), + u"Paths used when searching for typesystems"_s}, + {u"force-process-system-include-paths="_s + OptionsParser::pathSyntax(), + u"Include paths that are considered as system headers by the C++ parser, but should still " + "be processed to extract types (e.g. Qt include paths in a yocto sysroot)"_s}, + {u"keywords=keyword1[,keyword2,...]"_s, + u"A comma-separated list of keywords for conditional typesystem parsing"_s}, + }; +} + +struct TypeDatabaseOptions +{ + QStringList m_dropTypeEntries; + QStringList m_forceProcessSystemIncludes; + QStringList m_typesystemKeywords; + QStringList m_typesystemPaths; + bool m_suppressWarnings = true; +}; + +class TypeDatabaseOptionsParser : public OptionsParser +{ +public: + explicit TypeDatabaseOptionsParser(TypeDatabaseOptions *o) : m_options(o) {} + + bool handleBoolOption(const QString &key, OptionSource source) override; + bool handleOption(const QString &key, const QString &value, OptionSource source) override; + +private: + TypeDatabaseOptions *m_options; +}; + +bool TypeDatabaseOptionsParser::handleBoolOption(const QString &key, OptionSource source) +{ + switch (source) { + case OptionSource::CommandLine: + case OptionSource::ProjectFile: + if (key == u"no-suppress-warnings") { + m_options->m_suppressWarnings = false; + return true; + } + break; + case OptionSource::CommandLineSingleDash: + if (key.startsWith(u'T')) { // "-T/path" ends up a bool option + m_options->m_typesystemPaths += key.sliced(1).split(QDir::listSeparator(), + Qt::SkipEmptyParts); + return true; + } + break; + } + return false; +} + +bool TypeDatabaseOptionsParser::handleOption(const QString &key, const QString &value, + OptionSource source) +{ + if (source == OptionSource::CommandLineSingleDash) + return false; + if (key == u"api-version") { + const auto fullVersions = QStringView{value}.split(u'|'); + for (const auto &fullVersion : fullVersions) { + const auto parts = fullVersion.split(u','); + const QString package = parts.size() == 1 + ? u"*"_s : parts.constFirst().toString(); + const QString version = parts.constLast().toString(); + if (!TypeDatabase::setApiVersion(package, version)) + throw Exception(msgInvalidVersion(package, version)); + } + return true; + } + + if (key == u"drop-type-entries") { + m_options->m_dropTypeEntries = value.split(u';'); + m_options->m_dropTypeEntries.sort(); + return true; + } + + if (key == u"keywords") { + m_options->m_typesystemKeywords = value.split(u','); + return true; + } + + if (key == u"typesystem-paths") { + m_options->m_typesystemPaths += value.split(QDir::listSeparator(), + Qt::SkipEmptyParts); + return true; + } + + if (key == u"force-process-system-include-paths") { + m_options->m_forceProcessSystemIncludes += value.split(QDir::listSeparator(), + Qt::SkipEmptyParts); + return true; + } + + if (source == OptionSource::ProjectFile) { + if (key == u"typesystem-path") { + m_options->m_typesystemPaths += value; + return true; + } + } + + return false; +} + +struct TypeDatabasePrivate : public TypeDatabaseOptions { TypeSystemTypeEntryCPtr defaultTypeSystemType() const; TypeEntryPtr findType(const QString &name) const; @@ -128,11 +252,12 @@ struct TypeDatabasePrivate const CustomTypeEntryPtr &targetLang); void addBuiltInPrimitiveTypes(); void addBuiltInContainerTypes(const TypeDatabaseParserContextPtr &context); + bool addOpaqueContainers(const TypeDatabaseParserContextPtr &context); TypeEntryMultiMapConstIteratorRange findTypeRange(const QString &name) const; template <class Predicate> TypeEntryCList findTypesHelper(const QString &name, Predicate pred) const; template <class Type, class Predicate> - QList<QSharedPointer<const Type> > findTypesByTypeHelper(Predicate pred) const; + QList<std::shared_ptr<const Type> > findTypesByTypeHelper(Predicate pred) const; TypeEntryPtr resolveTypeDefEntry(const TypedefEntryPtr &typedefEntry, QString *errorMessage); template <class String> bool isSuppressedWarningHelper(const String &s) const; @@ -140,12 +265,11 @@ struct TypeDatabasePrivate void formatDebug(QDebug &d) const; void formatBuiltinTypes(QDebug &d) const; - bool m_suppressWarnings = true; TypeEntryMultiMap m_entries; // Contains duplicate entries (cf addInlineNamespaceLookups). TypeEntryMap m_flagsEntries; TypedefEntryMap m_typedefEntries; TemplateEntryMap m_templates; - QList<QRegularExpression> m_suppressedWarnings; + QList<SuppressedWarning> m_suppressedWarnings; QList<TypeSystemTypeEntryCPtr > m_typeSystemEntries; // maintain order, default is first. AddedFunctionList m_globalUserFunctions; @@ -153,18 +277,22 @@ struct TypeDatabasePrivate QStringList m_requiredTargetImports; - QStringList m_typesystemPaths; - QStringList m_typesystemKeywords; QHash<QString, bool> m_parsedTypesystemFiles; QList<TypeRejection> m_rejections; - - QStringList m_dropTypeEntries; - QStringList m_systemIncludes; }; +static const char ENV_TYPESYSTEMPATH[] = "TYPESYSTEMPATH"; + TypeDatabase::TypeDatabase() : d(new TypeDatabasePrivate) { + // Environment TYPESYSTEMPATH + if (qEnvironmentVariableIsSet(ENV_TYPESYSTEMPATH)) { + d->m_typesystemPaths + += qEnvironmentVariable(ENV_TYPESYSTEMPATH).split(QDir::listSeparator(), + Qt::SkipEmptyParts); + } + d->addBuiltInType(TypeEntryPtr(new VoidTypeEntry())); d->addBuiltInType(TypeEntryPtr(new VarargsTypeEntry())); for (const auto &pt : builtinPythonTypes()) @@ -179,6 +307,11 @@ TypeDatabase::~TypeDatabase() delete d; } +std::shared_ptr<OptionsParser> TypeDatabase::createOptionsParser() +{ + return std::make_shared<TypeDatabaseOptionsParser>(d); +} + TypeDatabase *TypeDatabase::instance(bool newInstance) { static TypeDatabase *db = nullptr; @@ -205,12 +338,11 @@ static const IntTypeNormalizationEntries &intTypeNormalizationEntries() static bool firstTime = true; if (firstTime) { firstTime = false; - for (auto t : {"char", "short", "int", "long"}) { - const QString intType = QLatin1StringView(t); + for (const auto &intType : {"char"_L1, "short"_L1, "int"_L1, "long"_L1}) { if (!TypeDatabase::instance()->findType(u'u' + intType)) { IntTypeNormalizationEntry entry; - entry.replacement = QStringLiteral("unsigned ") + intType; - entry.regex.setPattern(QStringLiteral("\\bu") + intType + QStringLiteral("\\b")); + entry.replacement = "unsigned "_L1 + intType; + entry.regex.setPattern("\\bu"_L1 + intType + "\\b"_L1); Q_ASSERT(entry.regex.isValid()); result.append(entry); } @@ -296,26 +428,11 @@ void TypeDatabase::addRequiredTargetImport(const QString& moduleName) d->m_requiredTargetImports << moduleName; } -void TypeDatabase::addTypesystemPath(const QString& typesystem_paths) -{ - #if defined(Q_OS_WIN32) - const char path_splitter = ';'; - #else - const char path_splitter = ':'; - #endif - d->m_typesystemPaths += typesystem_paths.split(QLatin1Char(path_splitter)); -} - -void TypeDatabase::setTypesystemKeywords(const QStringList &keywords) -{ - d->m_typesystemKeywords = keywords; -} - QStringList TypeDatabase::typesystemKeywords() const { QStringList result = d->m_typesystemKeywords; for (const auto &d : d->m_dropTypeEntries) - result.append(QStringLiteral("no_") + d); + result.append("no_"_L1 + d); switch (clang::emulatedCompilerLanguageLevel()) { case LanguageLevel::Cpp11: @@ -339,17 +456,17 @@ QStringList TypeDatabase::typesystemKeywords() const IncludeList TypeDatabase::extraIncludes(const QString& className) const { auto typeEntry = findComplexType(className); - return typeEntry.isNull() ? IncludeList() : typeEntry->extraIncludes(); + return typeEntry ? typeEntry->extraIncludes() : IncludeList(); } -const QStringList &TypeDatabase::systemIncludes() const +const QStringList &TypeDatabase::forceProcessSystemIncludes() const { - return d->m_systemIncludes; + return d->m_forceProcessSystemIncludes; } -void TypeDatabase::addSystemInclude(const QString &name) +void TypeDatabase::addForceProcessSystemInclude(const QString &name) { - d->m_systemIncludes.append(name); + d->m_forceProcessSystemIncludes.append(name); } // Add a lookup for the short name excluding inline namespaces @@ -370,20 +487,20 @@ ContainerTypeEntryPtr TypeDatabase::findContainerType(const QString &name) const { QString template_name = name; - int pos = name.indexOf(u'<'); + const auto pos = name.indexOf(u'<'); if (pos > 0) template_name = name.left(pos); auto type_entry = findType(template_name); if (type_entry && type_entry->isContainer()) - return qSharedPointerCast<ContainerTypeEntry>(type_entry); + return std::static_pointer_cast<ContainerTypeEntry>(type_entry); return {}; } static bool inline useType(const TypeEntryCPtr &t) { return !t->isPrimitive() - || qSharedPointerCast<const PrimitiveTypeEntry>(t)->preferredTargetLangType(); + || std::static_pointer_cast<const PrimitiveTypeEntry>(t)->preferredTargetLangType(); } FunctionTypeEntryPtr TypeDatabase::findFunctionType(const QString &name) const @@ -391,7 +508,7 @@ FunctionTypeEntryPtr TypeDatabase::findFunctionType(const QString &name) const const auto entries = d->findTypeRange(name); for (const TypeEntryPtr &entry : entries) { if (entry->type() == TypeEntry::FunctionType && useType(entry)) - return qSharedPointerCast<FunctionTypeEntry>(entry); + return std::static_pointer_cast<FunctionTypeEntry>(entry); } return {}; } @@ -415,6 +532,17 @@ TypeSystemTypeEntryCPtr TypeDatabase::defaultTypeSystemType() const return d->defaultTypeSystemType(); } +QString TypeDatabase::loadedTypeSystemNames() const +{ + QString result; + for (const auto &entry : d->m_typeSystemEntries) { + if (!result.isEmpty()) + result += u", "_s; + result += entry->name(); + } + return result; +} + TypeSystemTypeEntryCPtr TypeDatabasePrivate::defaultTypeSystemType() const { return m_typeSystemEntries.value(0, nullptr); @@ -454,12 +582,12 @@ TypeEntryCList TypeDatabasePrivate::findTypesHelper(const QString &name, Predica } template<class Type, class Predicate> -QList<QSharedPointer<const Type> > TypeDatabasePrivate::findTypesByTypeHelper(Predicate pred) const +QList<std::shared_ptr<const Type> > TypeDatabasePrivate::findTypesByTypeHelper(Predicate pred) const { - QList<QSharedPointer<const Type> > result; + QList<std::shared_ptr<const Type> > result; for (const auto &entry : m_entries) { if (pred(entry)) - result.append(qSharedPointerCast<const Type>(entry)); + result.append(std::static_pointer_cast<const Type>(entry)); } return result; } @@ -559,6 +687,7 @@ bool TypeDatabase::isClassRejected(const QString& className, QString *reason) co { for (const TypeRejection& r : d->m_rejections) { if (r.matchType == TypeRejection::ExcludeClass && r.className.match(className).hasMatch()) { + r.matched = true; if (reason) *reason = msgRejectReason(r); return true; @@ -577,6 +706,7 @@ static bool findRejection(const QList<TypeRejection> &rejections, for (const TypeRejection& r : rejections) { if (r.matchType == matchType && r.pattern.match(name).hasMatch() && r.className.match(className).hasMatch()) { + r.matched = true; if (reason) *reason = msgRejectReason(r, name); return true; @@ -594,7 +724,7 @@ TypeEntryPtr TypeDatabasePrivate::resolveTypeDefEntry(const TypedefEntryPtr &typ QString *errorMessage) { QString sourceName = typedefEntry->sourceType(); - const int lessThanPos = sourceName.indexOf(u'<'); + const auto lessThanPos = sourceName.indexOf(u'<'); if (lessThanPos != -1) sourceName.truncate(lessThanPos); ComplexTypeEntryPtr source; @@ -604,8 +734,8 @@ TypeEntryPtr TypeDatabasePrivate::resolveTypeDefEntry(const TypedefEntryPtr &typ case TypeEntry::ContainerType: case TypeEntry::ObjectType: case TypeEntry::SmartPointerType: - source = qSharedPointerDynamicCast<ComplexTypeEntry>(e); - Q_ASSERT(!source.isNull()); + source = std::dynamic_pointer_cast<ComplexTypeEntry>(e); + Q_ASSERT(source); break; default: break; @@ -613,8 +743,7 @@ TypeEntryPtr TypeDatabasePrivate::resolveTypeDefEntry(const TypedefEntryPtr &typ } if (!source) { if (errorMessage) - *errorMessage = u"Unable to resolve typedef \""_s - + typedefEntry->sourceType() + u'"'; + *errorMessage = msgUnableToResolveTypedef(typedefEntry->sourceType(), sourceName); return nullptr; } @@ -641,8 +770,8 @@ bool TypeDatabase::addType(const TypeEntryPtr &e, QString *errorMessage) bool TypeDatabasePrivate::addType(TypeEntryPtr e, QString *errorMessage) { if (e->type() == TypeEntry::TypedefType) { - e = resolveTypeDefEntry(qSharedPointerCast<TypedefEntry>(e), errorMessage); - if (Q_UNLIKELY(e.isNull())) + e = resolveTypeDefEntry(std::static_pointer_cast<TypedefEntry>(e), errorMessage); + if (Q_UNLIKELY(!e)) return false; } m_entries.insert(e->qualifiedCppName(), e); @@ -654,7 +783,7 @@ ConstantValueTypeEntryPtr TypeDatabase::addConstantValueTypeEntry(const QString &value, const TypeEntryCPtr &parent) { - ConstantValueTypeEntryPtr result(new ConstantValueTypeEntry(value, parent)); + auto result = std::make_shared<ConstantValueTypeEntry>(value, parent); result->setCodeGeneration(TypeEntry::GenerateNothing); addType(result); return result; @@ -687,7 +816,7 @@ bool TypeDatabase::isReturnTypeRejected(const QString& className, const QString& FlagsTypeEntryPtr TypeDatabase::findFlagsType(const QString &name) const { TypeEntryPtr fte = findType(name); - if (fte.isNull()) { + if (!fte) { fte = d->m_flagsEntries.value(name); if (!fte) { //last hope, search for flag without scope inside of flags hash @@ -700,10 +829,10 @@ FlagsTypeEntryPtr TypeDatabase::findFlagsType(const QString &name) const } } } - return qSharedPointerCast<FlagsTypeEntry>(fte); + return std::static_pointer_cast<FlagsTypeEntry>(fte); } -void TypeDatabase::addFlagsType(FlagsTypeEntryPtr fte) +void TypeDatabase::addFlagsType(const FlagsTypeEntryPtr &fte) { d->m_flagsEntries[fte->originalName()] = fte; } @@ -720,7 +849,7 @@ void TypeDatabase::addTemplate(const TemplateEntryPtr &t) void TypeDatabase::addTemplate(const QString &name, const QString &code) { - TemplateEntryPtr te(new TemplateEntry(name)); + auto te = std::make_shared<TemplateEntry>(name); te->addCode(code); addTemplate(te); } @@ -767,12 +896,8 @@ FunctionModificationList return lst; } -void TypeDatabase::setSuppressWarnings(bool on) -{ - d->m_suppressWarnings = on; -} - -bool TypeDatabase::addSuppressedWarning(const QString &warning, QString *errorMessage) +bool TypeDatabase::addSuppressedWarning(const QString &warning, bool generate, + QString *errorMessage) { QString pattern; if (warning.startsWith(u'^') && warning.endsWith(u'$')) { @@ -793,7 +918,7 @@ bool TypeDatabase::addSuppressedWarning(const QString &warning, QString *errorMe qsizetype lastPos = 0; for (qsizetype a = 0, aSize = asteriskPositions.size(); a < aSize; ++a) { if (a) - pattern.append(QStringLiteral(".*")); + pattern.append(".*"_L1); const auto nextPos = asteriskPositions.at(a); if (nextPos > lastPos) pattern.append(QRegularExpression::escape(warning.mid(lastPos, nextPos - lastPos))); @@ -810,7 +935,7 @@ bool TypeDatabase::addSuppressedWarning(const QString &warning, QString *errorMe } expression.setPatternOptions(expression.patternOptions() | QRegularExpression::MultilineOption); - d->m_suppressedWarnings.append(expression); + d->m_suppressedWarnings.append({expression, warning, generate}); return true; } @@ -818,10 +943,14 @@ bool TypeDatabase::isSuppressedWarning(QStringView s) const { if (!d->m_suppressWarnings) return false; - return std::any_of(d->m_suppressedWarnings.cbegin(), d->m_suppressedWarnings.cend(), - [&s] (const QRegularExpression &e) { - return e.match(s).hasMatch(); - }); + auto wit = std::find_if(d->m_suppressedWarnings.cbegin(), d->m_suppressedWarnings.cend(), + [&s] (const SuppressedWarning &e) { + return e.pattern.matchView(s).hasMatch(); + }); + const bool found = wit != d->m_suppressedWarnings.cend(); + if (found) + wit->matched = true; + return found; } QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile, const QString ¤tPath) const @@ -829,6 +958,27 @@ QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile, const QS return d->modifiedTypesystemFilepath(tsFile, currentPath); } +void TypeDatabase::logUnmatched() const +{ + for (auto &sw : d->m_suppressedWarnings) { + if (sw.generate && !sw.matched) + qWarning("Unmatched suppressed warning: \"%s\"", qPrintable(sw.rawText)); + } + + for (auto &tr : d->m_rejections) { + if (tr.generate && !tr.matched) { + QDebug d = qWarning(); + d.noquote(); + d.nospace(); + d << "Unmatched rejection: " << tr.matchType; + if (!tr.className.pattern().isEmpty()) + d << " class " << tr.className.pattern(); + if (!tr.pattern.pattern().isEmpty()) + d << " \"" << tr.pattern.pattern() << '"'; + } + } +} + QString TypeDatabasePrivate::modifiedTypesystemFilepath(const QString& tsFile, const QString ¤tPath) const { @@ -854,16 +1004,25 @@ void TypeDatabasePrivate::addBuiltInContainerTypes(const TypeDatabaseParserConte { // Unless the user has added the standard containers (potentially with // some opaque types), add them by default. + const bool hasStdArray = findType(u"std::array"_s) != nullptr; const bool hasStdPair = findType(u"std::pair"_s) != nullptr; const bool hasStdList = findType(u"std::list"_s) != nullptr; const bool hasStdVector = findType(u"std::vector"_s) != nullptr; const bool hasStdMap = findType(u"std::map"_s) != nullptr; const bool hasStdUnorderedMap = findType(u"std::unordered_map"_s) != nullptr; + const bool hasStdSpan = findType(u"std::span"_s) != nullptr; if (hasStdPair && hasStdList && hasStdVector && hasStdMap && hasStdUnorderedMap) return; QByteArray ts = R"(<?xml version="1.0" encoding="UTF-8"?><typesystem>)"; + if (!hasStdArray) { + ts += containerTypeSystemSnippet( + "std::array", "list", "array", + "shiboken_conversion_cppsequence_to_pylist", + "PySequence", + "shiboken_conversion_pyiterable_to_cpparray"); + } if (!hasStdPair) { ts += containerTypeSystemSnippet( "std::pair", "pair", "utility", @@ -896,6 +1055,16 @@ void TypeDatabasePrivate::addBuiltInContainerTypes(const TypeDatabaseParserConte "shiboken_conversion_stdmap_to_pydict", "PyDict", "shiboken_conversion_pydict_to_stdmap"); } + if (!hasStdSpan + && clang::emulatedCompilerLanguageLevel() >= LanguageLevel::Cpp20) { + auto spanSnip = containerTypeSystemSnippet( + "std::span", "span", "span", + "shiboken_conversion_cppsequence_to_pylist"); + auto pos = spanSnip.indexOf('>'); + spanSnip.insert(pos, R"( view-on="std::vector")"); + ts += spanSnip; + } + ts += "</typesystem>"; QBuffer buffer(&ts); buffer.open(QIODevice::ReadOnly); @@ -903,6 +1072,22 @@ void TypeDatabasePrivate::addBuiltInContainerTypes(const TypeDatabaseParserConte Q_ASSERT(ok); } +bool TypeDatabasePrivate::addOpaqueContainers(const TypeDatabaseParserContextPtr &context) +{ + const auto &och = context->opaqueContainerHash; + for (auto it = och.cbegin(), end = och.cend(); it != end; ++it) { + const QString &name = it.key(); + auto te = findType(name); + if (!te || !te->isContainer()) { + qCWarning(lcShiboken, "No container \"%s\" found.", qPrintable(name)); + return false; + } + auto cte = std::static_pointer_cast<ContainerTypeEntry>(te); + cte->appendOpaqueContainers(it.value()); + } + return true; +} + bool TypeDatabase::parseFile(const QString &filename, bool generate) { QString filepath = modifiedTypesystemFilepath(filename, {}); @@ -966,7 +1151,7 @@ bool TypeDatabase::parseFile(QIODevice *device, bool generate) bool TypeDatabasePrivate::parseFile(QIODevice *device, TypeDatabase *db, bool generate) { - const TypeDatabaseParserContextPtr context(new TypeDatabaseParserContext); + const auto context = std::make_shared<TypeDatabaseParserContext>(); context->db = db; if (!parseFile(context, device, generate)) @@ -974,7 +1159,8 @@ bool TypeDatabasePrivate::parseFile(QIODevice *device, TypeDatabase *db, bool ge addBuiltInPrimitiveTypes(); addBuiltInContainerTypes(context); - return resolveSmartPointerInstantiations(context); + return addOpaqueContainers(context) + && resolveSmartPointerInstantiations(context); } bool TypeDatabase::parseFile(const TypeDatabaseParserContextPtr &context, @@ -1067,7 +1253,7 @@ PrimitiveTypeEntryPtr TypeDatabase::findPrimitiveType(const QString& name) const const auto entries = d->findTypeRange(name); for (const auto &entry : entries) { if (entry->isPrimitive()) { - auto pe = qSharedPointerCast<PrimitiveTypeEntry>(entry); + auto pe = std::static_pointer_cast<PrimitiveTypeEntry>(entry); if (pe->preferredTargetLangType()) return pe; } @@ -1081,7 +1267,7 @@ ComplexTypeEntryPtr TypeDatabase::findComplexType(const QString& name) const const auto entries = d->findTypeRange(name); for (const auto &entry : entries) { if (entry->isComplex() && useType(entry)) - return qSharedPointerCast<ComplexTypeEntry>(entry); + return std::static_pointer_cast<ComplexTypeEntry>(entry); } return nullptr; } @@ -1090,8 +1276,8 @@ ObjectTypeEntryPtr TypeDatabase::findObjectType(const QString& name) const { const auto entries = d->findTypeRange(name); for (const auto &entry : entries) { - if (!entry.isNull() && entry->isObject() && useType(entry)) - return qSharedPointerCast<ObjectTypeEntry>(entry); + if (entry && entry->isObject() && useType(entry)) + return std::static_pointer_cast<ObjectTypeEntry>(entry); } return nullptr; } @@ -1102,7 +1288,7 @@ NamespaceTypeEntryList TypeDatabase::findNamespaceTypes(const QString& name) con const auto entries = d->findTypeRange(name); for (const auto &entry : entries) { if (entry->isNamespace()) - result.append(qSharedPointerCast<NamespaceTypeEntry>(entry)); + result.append(std::static_pointer_cast<NamespaceTypeEntry>(entry)); } return result; } @@ -1130,7 +1316,7 @@ bool TypeDatabase::shouldDropTypeEntry(const QString& fullTypeName) const return d->m_dropTypeEntries.contains(fullTypeName); } -void TypeDatabase::setDropTypeEntries(QStringList dropTypeEntries) +void TypeDatabase::setDropTypeEntries(const QStringList &dropTypeEntries) { d->m_dropTypeEntries = dropTypeEntries; d->m_dropTypeEntries.sort(); @@ -1157,7 +1343,7 @@ static void _computeTypeIndexes() const auto &allEntries = tdb->entries(); list.reserve(allEntries.size()); for (auto tit = allEntries.cbegin(), end = allEntries.cend(); tit != end; ++tit) { - TypeEntryPtr entry = tit.value(); + const TypeEntryPtr &entry = tit.value(); if (entry->isPrimitive() || entry->isContainer() || entry->isFunction() @@ -1222,7 +1408,7 @@ bool TypeDatabase::setApiVersion(const QString& packageWildcardPattern, const QS const QRegularExpression packageRegex(packagePattern); if (!packageRegex.isValid()) return false; - versions.append(qMakePair(packageRegex, versionNumber)); + versions.append(std::make_pair(packageRegex, versionNumber)); return true; } @@ -1246,21 +1432,6 @@ bool TypeDatabase::hasDroppedTypeEntries() const } #ifndef QT_NO_DEBUG_STREAM - -template <class Container, class Separator> -static void formatList(QDebug &d, const char *name, const Container &c, Separator sep) -{ - if (const auto size = c.size()) { - d << ", " << name << '[' << size << "]=("; - for (qsizetype i = 0; i < size; ++i) { - if (i) - d << sep; - d << c.at(i); - } - d << ')'; - } -} - void TypeDatabase::formatDebug(QDebug &debug) const { d->formatDebug(debug); @@ -1303,7 +1474,7 @@ void TypeDatabasePrivate::formatDebug(QDebug &d) const d << ")\n"; } d <<"\nglobalUserFunctions=" << m_globalUserFunctions << '\n'; - formatList(d, "globalFunctionMods", m_functionMods, '\n'); + formatList(d, "globalFunctionMods", m_functionMods, "\n"); d << ')'; } @@ -1368,9 +1539,9 @@ void TypeDatabase::formatBuiltinTypes(QDebug debug) const // Determine base types and their typedef'ed types QList<PrimitiveFormatListEntry> primitiveEntries; - for (auto &e : std::as_const(d->m_entries)) { + for (const auto &e : std::as_const(d->m_entries)) { if (e->isPrimitive()) { - auto pe = qSharedPointerCast<const PrimitiveTypeEntry>(e); + auto pe = std::static_pointer_cast<const PrimitiveTypeEntry>(e); auto basic = basicReferencedTypeEntry(pe); if (basic != pe) { const auto idx = indexOf(primitiveEntries, basic); @@ -1405,7 +1576,7 @@ PrimitiveTypeEntryPtr const QString &rootPackage, const CustomTypeEntryPtr &targetLang) { - PrimitiveTypeEntryPtr result(new PrimitiveTypeEntry(name, {}, root)); + auto result = std::make_shared<PrimitiveTypeEntry>(name, QVersionNumber{}, root); result->setTargetLangApiType(targetLang); result->setTargetLangPackage(rootPackage); addBuiltInType(result); @@ -1433,15 +1604,15 @@ void TypeDatabasePrivate::addBuiltInPrimitiveTypes() // C++ primitive types auto pyLongEntry = findType(u"PyLong"_s); - Q_ASSERT(!pyLongEntry.isNull() && pyLongEntry->isCustom()); - auto pyLongCustomEntry = qSharedPointerCast<CustomTypeEntry>(pyLongEntry); + Q_ASSERT(pyLongEntry && pyLongEntry->isCustom()); + auto pyLongCustomEntry = std::static_pointer_cast<CustomTypeEntry>(pyLongEntry); auto pyBoolEntry = findType(u"PyBool"_s); - Q_ASSERT(!pyBoolEntry.isNull() && pyBoolEntry->isCustom()); + Q_ASSERT(pyBoolEntry && pyBoolEntry->isCustom()); auto sbkCharEntry = findType(u"SbkChar"_s); - Q_ASSERT(!sbkCharEntry.isNull() && sbkCharEntry->isCustom()); - auto sbkCharCustomEntry = qSharedPointerCast<CustomTypeEntry>(sbkCharEntry); + Q_ASSERT(sbkCharEntry && sbkCharEntry->isCustom()); + auto sbkCharCustomEntry = std::static_pointer_cast<CustomTypeEntry>(sbkCharEntry); - auto pyBoolCustomEntry = qSharedPointerCast<CustomTypeEntry>(pyBoolEntry); + auto pyBoolCustomEntry = std::static_pointer_cast<CustomTypeEntry>(pyBoolEntry); for (const auto &t : AbstractMetaType::cppIntegralTypes()) { if (!m_entries.contains(t)) { CustomTypeEntryPtr targetLangApi = pyLongCustomEntry; @@ -1454,24 +1625,24 @@ void TypeDatabasePrivate::addBuiltInPrimitiveTypes() } auto pyFloatEntry = findType(u"PyFloat"_s); - Q_ASSERT(!pyFloatEntry.isNull() && pyFloatEntry->isCustom()); - auto pyFloatCustomEntry = qSharedPointerCast<CustomTypeEntry>(pyFloatEntry); + Q_ASSERT(pyFloatEntry && pyFloatEntry->isCustom()); + auto pyFloatCustomEntry = std::static_pointer_cast<CustomTypeEntry>(pyFloatEntry); for (const auto &t : AbstractMetaType::cppFloatTypes()) { if (!m_entries.contains(t)) addBuiltInPrimitiveType(t, root, rootPackage, pyFloatCustomEntry); } auto pyUnicodeEntry = findType(u"PyUnicode"_s); - Q_ASSERT(!pyUnicodeEntry.isNull() && pyUnicodeEntry->isCustom()); - auto pyUnicodeCustomEntry = qSharedPointerCast<CustomTypeEntry>(pyUnicodeEntry); + Q_ASSERT(pyUnicodeEntry && pyUnicodeEntry->isCustom()); + auto pyUnicodeCustomEntry = std::static_pointer_cast<CustomTypeEntry>(pyUnicodeEntry); - const QString stdString = u"std::string"_s; + constexpr auto stdString = "std::string"_L1; if (!m_entries.contains(stdString)) { addBuiltInCppStringPrimitiveType(stdString, u"std::string_view"_s, root, rootPackage, pyUnicodeCustomEntry); } - const QString stdWString = u"std::wstring"_s; + constexpr auto stdWString = "std::wstring"_L1; if (!m_entries.contains(stdWString)) { addBuiltInCppStringPrimitiveType(stdWString, u"std::wstring_view"_s, root, rootPackage, diff --git a/sources/shiboken6/ApiExtractor/typedatabase.h b/sources/shiboken6/ApiExtractor/typedatabase.h index 11ed26002..d5adca324 100644 --- a/sources/shiboken6/ApiExtractor/typedatabase.h +++ b/sources/shiboken6/ApiExtractor/typedatabase.h @@ -11,10 +11,13 @@ #include <QtCore/QRegularExpression> #include <QtCore/QStringList> #include <QtCore/QVersionNumber> -#include <QtCore/QSharedPointer> + +#include <memory> QT_FORWARD_DECLARE_CLASS(QIODevice) +struct OptionDescription; +class OptionsParser; struct TypeDatabasePrivate; struct TypeDatabaseParserContext; @@ -48,7 +51,9 @@ struct TypeRejection QRegularExpression className; QRegularExpression pattern; - MatchType matchType; + MatchType matchType = ExcludeClass; + bool generate; // Current type system + mutable bool matched = false; }; #ifndef QT_NO_DEBUG_STREAM @@ -58,10 +63,14 @@ QDebug operator<<(QDebug d, const TypeRejection &r); class TypeDatabase { TypeDatabase(); - Q_DISABLE_COPY(TypeDatabase) public: + Q_DISABLE_COPY_MOVE(TypeDatabase) + ~TypeDatabase(); + static QList<OptionDescription> options(); + std::shared_ptr<OptionsParser> createOptionsParser(); + /** * Return the type system instance. * \param newInstance This parameter is useful just for unit testing, because singletons causes @@ -76,15 +85,12 @@ public: void addRequiredTargetImport(const QString &moduleName); - void addTypesystemPath(const QString &typesystem_paths); - - void setTypesystemKeywords(const QStringList &keywords); QStringList typesystemKeywords() const; IncludeList extraIncludes(const QString &className) const; - const QStringList &systemIncludes() const; - void addSystemInclude(const QString &name); + const QStringList &forceProcessSystemIncludes() const; + void addForceProcessSystemInclude(const QString &name); void addInlineNamespaceLookups(const NamespaceTypeEntryCPtr &n); @@ -97,6 +103,7 @@ public: FunctionTypeEntryPtr findFunctionType(const QString &name) const; TypeSystemTypeEntryCPtr findTypeSystemType(const QString &name) const; TypeSystemTypeEntryCPtr defaultTypeSystemType() const; + QString loadedTypeSystemNames() const; QString defaultPackageName() const; TypeEntryPtr findType(const QString &name) const; @@ -135,7 +142,7 @@ public: const ComplexTypeEntryCPtr &source); FlagsTypeEntryPtr findFlagsType(const QString &name) const; - void addFlagsType(FlagsTypeEntryPtr fte); + void addFlagsType(const FlagsTypeEntryPtr &fte); TemplateEntryPtr findTemplate(const QString &name) const; @@ -153,9 +160,7 @@ public: FunctionModificationList globalFunctionModifications(const QStringList &signatures) const; - void setSuppressWarnings(bool on); - - bool addSuppressedWarning(const QString &warning, QString *errorMessage); + bool addSuppressedWarning(const QString &warning, bool generate, QString *errorMessage); bool isSuppressedWarning(QStringView s) const; @@ -163,12 +168,12 @@ public: // Top level file parsing bool parseFile(const QString &filename, bool generate = true); - bool parseFile(const QSharedPointer<TypeDatabaseParserContext> &context, + bool parseFile(const std::shared_ptr<TypeDatabaseParserContext> &context, const QString &filename, const QString ¤tPath, bool generate); // Top level QIODevice parsing for tests. bool parseFile(QIODevice *device, bool generate = true); - bool parseFile(const QSharedPointer<TypeDatabaseParserContext> &context, + bool parseFile(const std::shared_ptr<TypeDatabaseParserContext> &context, QIODevice *device, bool generate = true); static bool setApiVersion(const QString &package, const QString &version); @@ -180,10 +185,12 @@ public: bool shouldDropTypeEntry(const QString &fullTypeName) const; - void setDropTypeEntries(QStringList dropTypeEntries); + void setDropTypeEntries(const QStringList &dropTypeEntries); QString modifiedTypesystemFilepath(const QString &tsFile, const QString ¤tPath = QString()) const; + void logUnmatched() const; + #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const; #endif diff --git a/sources/shiboken6/ApiExtractor/typedatabase_p.h b/sources/shiboken6/ApiExtractor/typedatabase_p.h index 04c1df145..fc56c7961 100644 --- a/sources/shiboken6/ApiExtractor/typedatabase_p.h +++ b/sources/shiboken6/ApiExtractor/typedatabase_p.h @@ -5,6 +5,7 @@ #define TYPEDATABASE_P_H #include "typesystem_typedefs.h" +#include "containertypeentry.h" #include <QtCore/QHash> #include <QtCore/QString> @@ -14,9 +15,11 @@ class TypeDatabase; struct TypeDatabaseParserContext { using SmartPointerInstantiations = QHash<SmartPointerTypeEntryPtr, QString>; + using OpaqueContainerHash = QHash<QString, OpaqueContainers>; TypeDatabase *db; SmartPointerInstantiations smartPointerInstantiations; + OpaqueContainerHash opaqueContainerHash; }; #endif // TYPEDATABASE_P_H diff --git a/sources/shiboken6/ApiExtractor/typeparser.cpp b/sources/shiboken6/ApiExtractor/typeparser.cpp index 10f102b08..11d7bf641 100644 --- a/sources/shiboken6/ApiExtractor/typeparser.cpp +++ b/sources/shiboken6/ApiExtractor/typeparser.cpp @@ -37,7 +37,7 @@ public: { } - Token nextToken(QString *errorMessage = Q_NULLPTR); + Token nextToken(QString *errorMessage = nullptr); QString identifier() const; QString msgParseError(const QString &why) const; @@ -147,8 +147,8 @@ Scanner::Token Scanner::nextToken(QString *errorMessage) QString Scanner::msgParseError(const QString &why) const { - return QStringLiteral("TypeParser: Unable to parse \"") - + QString(m_chars, m_length) + QStringLiteral("\": ") + why; + return "TypeParser: Unable to parse \""_L1 + + QString(m_chars, m_length) + "\": "_L1 + why; } TypeInfo TypeParser::parse(const QString &str, QString *errorMessage) @@ -166,7 +166,7 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage) Scanner::Token tok = scanner.nextToken(errorMessage); while (tok != Scanner::NoToken) { if (tok == Scanner::InvalidToken) - return TypeInfo(); + return {}; // switch (tok) { // case Scanner::StarToken: printf(" - *\n"); break; @@ -199,12 +199,12 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage) stack.top().setReferenceType(RValueReference); break; case RValueReference: - const QString message = scanner.msgParseError(QStringLiteral("Too many '&' qualifiers")); + const QString message = scanner.msgParseError("Too many '&' qualifiers"_L1); if (errorMessage) *errorMessage = message; else qWarning().noquote().nospace() << message; - return TypeInfo(); + return {}; } break; case Scanner::LessThanToken: @@ -246,12 +246,12 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage) case Scanner::OpenParenToken: // function pointers not supported case Scanner::CloseParenToken: { - const QString message = scanner.msgParseError(QStringLiteral("Function pointers are not supported")); + const QString message = scanner.msgParseError("Function pointers are not supported"_L1); if (errorMessage) *errorMessage = message; else qWarning().noquote().nospace() << message; - return TypeInfo(); + return {}; } case Scanner::Identifier: diff --git a/sources/shiboken6/ApiExtractor/typesystem.cpp b/sources/shiboken6/ApiExtractor/typesystem.cpp index a5f8ad36c..99d42b668 100644 --- a/sources/shiboken6/ApiExtractor/typesystem.cpp +++ b/sources/shiboken6/ApiExtractor/typesystem.cpp @@ -5,9 +5,11 @@ #include "arraytypeentry.h" #include "codesnip.h" #include "complextypeentry.h" +#include "configurabletypeentry.h" #include "constantvaluetypeentry.h" #include "containertypeentry.h" #include "customtypenentry.h" +#include "debughelpers_p.h" #include "enumtypeentry.h" #include "enumvaluetypeentry.h" #include "flagstypeentry.h" @@ -50,6 +52,11 @@ static QString buildName(const QString &entryName, const TypeEntryCPtr &parent) class TypeEntryPrivate { public: + TypeEntryPrivate(const TypeEntryPrivate &) = default; // Enable copy for cloning. + TypeEntryPrivate &operator=(const TypeEntryPrivate &) = delete; + TypeEntryPrivate(TypeEntryPrivate &&) = delete; + TypeEntryPrivate &operator=(TypeEntryPrivate &&) = delete; + explicit TypeEntryPrivate(const QString &entryName, TypeEntry::Type t, const QVersionNumber &vr, const TypeEntryCPtr &parent); virtual ~TypeEntryPrivate() = default; @@ -181,7 +188,7 @@ TypeSystemTypeEntryCPtr typeSystemTypeEntry(TypeEntryCPtr e) { for (; e; e = e->parent()) { if (e->type() == TypeEntry::TypeSystemType) - return qSharedPointerCast<const TypeSystemTypeEntry>(e); + return std::static_pointer_cast<const TypeSystemTypeEntry>(e); } return {}; } @@ -323,7 +330,7 @@ QString TypeEntryPrivate::shortName() const bool foundInlineNamespace = false; for (auto p = m_parent; p != nullptr && p->type() != TypeEntry::TypeSystemType; p = p->parent()) { if (p->type() == TypeEntry::NamespaceType - && qSharedPointerCast<const NamespaceTypeEntry>(p)->isInlineNamespace()) { + && std::static_pointer_cast<const NamespaceTypeEntry>(p)->isInlineNamespace()) { foundInlineNamespace = true; } else { parents.append(p); @@ -659,6 +666,9 @@ public: CodeSnipList m_codeSnips; TypeSystem::SnakeCase m_snakeCase = TypeSystem::SnakeCase::Disabled; + QString m_subModuleOf; + QString m_namespaceBegin; + QString m_namespaceEnd; }; TypeSystemTypeEntry::TypeSystemTypeEntry(const QString &entryName, const QVersionNumber &vr, @@ -696,6 +706,42 @@ void TypeSystemTypeEntry::addCodeSnip(const CodeSnip &codeSnip) d->m_codeSnips.append(codeSnip); } +QString TypeSystemTypeEntry::subModuleOf() const +{ + S_D(const TypeSystemTypeEntry); + return d->m_subModuleOf; +} + +void TypeSystemTypeEntry::setSubModule(const QString &s) +{ + S_D(TypeSystemTypeEntry); + d->m_subModuleOf = s; +} + +const QString &TypeSystemTypeEntry::namespaceBegin() const +{ + S_D(const TypeSystemTypeEntry); + return d->m_namespaceBegin; +} + +void TypeSystemTypeEntry::setNamespaceBegin(const QString &p) +{ + S_D(TypeSystemTypeEntry); + d->m_namespaceBegin = p; +} + +const QString &TypeSystemTypeEntry::namespaceEnd() const +{ + S_D(const TypeSystemTypeEntry); + return d->m_namespaceEnd; +} + +void TypeSystemTypeEntry::setNamespaceEnd(const QString &n) +{ + S_D(TypeSystemTypeEntry); + d->m_namespaceEnd = n; +} + TypeSystem::SnakeCase TypeSystemTypeEntry::snakeCase() const { S_D(const TypeSystemTypeEntry); @@ -892,7 +938,7 @@ PrimitiveTypeEntryCPtr basicReferencedTypeEntry(const PrimitiveTypeEntryCPtr &e) PrimitiveTypeEntryCPtr basicReferencedTypeEntry(const TypeEntryCPtr &e) { Q_ASSERT(e->isPrimitive()); - return basicReferencedTypeEntry(qSharedPointerCast<const PrimitiveTypeEntry>(e)); + return basicReferencedTypeEntry(std::static_pointer_cast<const PrimitiveTypeEntry>(e)); } PrimitiveTypeEntryCPtr basicReferencedNonBuiltinTypeEntry(const PrimitiveTypeEntryCPtr &e) @@ -926,7 +972,7 @@ void PrimitiveTypeEntry::setPreferredTargetLangType(bool b) bool PrimitiveTypeEntry::hasCustomConversion() const { S_D(const PrimitiveTypeEntry); - return !d->m_customConversion.isNull(); + return bool(d->m_customConversion); } void PrimitiveTypeEntry::setCustomConversion(const CustomConversionPtr &customConversion) @@ -952,23 +998,72 @@ PrimitiveTypeEntry::PrimitiveTypeEntry(PrimitiveTypeEntryPrivate *d) { } -// ----------------- EnumTypeEntry -class EnumTypeEntryPrivate : public TypeEntryPrivate +// ----------------- ConfigurableTypeEntry + +class ConfigurableTypeEntryPrivate : public TypeEntryPrivate { public: using TypeEntryPrivate::TypeEntryPrivate; + QString m_configCondition; +}; + +ConfigurableTypeEntry::ConfigurableTypeEntry(const QString &entryName, Type t, + const QVersionNumber &vr, + const TypeEntryCPtr &parent) : + TypeEntry(new ConfigurableTypeEntryPrivate(entryName, t, vr, parent)) +{ +} + +ConfigurableTypeEntry::ConfigurableTypeEntry(ConfigurableTypeEntryPrivate *d) : + TypeEntry(d) +{ +} + +TypeEntry *ConfigurableTypeEntry::clone() const +{ + S_D(const ConfigurableTypeEntry); + return new ConfigurableTypeEntry(new ConfigurableTypeEntryPrivate(*d)); +} + +QString ConfigurableTypeEntry::configCondition() const +{ + S_D(const ConfigurableTypeEntry); + return d->m_configCondition; +} + +void ConfigurableTypeEntry::setConfigCondition(const QString &c) +{ + S_D(ConfigurableTypeEntry); + d->m_configCondition = c; + if (!d->m_configCondition.startsWith(u'#')) + d->m_configCondition.prepend(u"#if "); +} + +bool ConfigurableTypeEntry::hasConfigCondition() const +{ + S_D(const ConfigurableTypeEntry); + return !d->m_configCondition.isEmpty(); +} + +// ----------------- EnumTypeEntry +class EnumTypeEntryPrivate : public ConfigurableTypeEntryPrivate +{ +public: + using ConfigurableTypeEntryPrivate::ConfigurableTypeEntryPrivate; + EnumValueTypeEntryCPtr m_nullValue; QStringList m_rejectedEnums; FlagsTypeEntryPtr m_flags; QString m_cppType; + QString m_docFile; TypeSystem::PythonEnumType m_pythonEnumType = TypeSystem::PythonEnumType::Unspecified; }; EnumTypeEntry::EnumTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntryCPtr &parent) : - TypeEntry(new EnumTypeEntryPrivate(entryName, EnumType, vr, parent)) + ConfigurableTypeEntry(new EnumTypeEntryPrivate(entryName, EnumType, vr, parent)) { } @@ -1055,6 +1150,18 @@ QStringList EnumTypeEntry::enumValueRejections() const return d->m_rejectedEnums; } +QString EnumTypeEntry::docFile() const +{ + S_D(const EnumTypeEntry); + return d->m_docFile; +} + +void EnumTypeEntry::setDocFile(const QString &df) +{ + S_D(EnumTypeEntry); + d->m_docFile = df; +} + TypeEntry *EnumTypeEntry::clone() const { S_D(const EnumTypeEntry); @@ -1062,7 +1169,7 @@ TypeEntry *EnumTypeEntry::clone() const } EnumTypeEntry::EnumTypeEntry(EnumTypeEntryPrivate *d) : - TypeEntry(d) + ConfigurableTypeEntry(d) { } @@ -1201,13 +1308,13 @@ ConstantValueTypeEntry::ConstantValueTypeEntry(TypeEntryPrivate *d) : } // ----------------- ComplexTypeEntry -class ComplexTypeEntryPrivate : public TypeEntryPrivate +class ComplexTypeEntryPrivate : public ConfigurableTypeEntryPrivate { public: ComplexTypeEntryPrivate(const QString &entryName, TypeEntry::Type t, const QVersionNumber &vr, const TypeEntryCPtr &parent) : - TypeEntryPrivate(entryName, t, vr, parent), + ConfigurableTypeEntryPrivate(entryName, t, vr, parent), m_qualifiedCppName(buildName(entryName, parent)), m_polymorphicBase(false), m_genericClass(false), @@ -1256,7 +1363,7 @@ public: ComplexTypeEntry::ComplexTypeEntry(const QString &entryName, TypeEntry::Type t, const QVersionNumber &vr, const TypeEntryCPtr &parent) : - TypeEntry(new ComplexTypeEntryPrivate(entryName, t, vr, parent)) + ConfigurableTypeEntry(new ComplexTypeEntryPrivate(entryName, t, vr, parent)) { } @@ -1686,10 +1793,11 @@ void ComplexTypeEntry::useAsTypedef(const ComplexTypeEntryCPtr &source) TypeEntry::useAsTypedef(source); d->m_qualifiedCppName = source->qualifiedCppName(); d->m_targetType = source->targetType(); + d->m_typeFlags.setFlag(ComplexTypeEntry::Typedef); } ComplexTypeEntry::ComplexTypeEntry(ComplexTypeEntryPrivate *d) : - TypeEntry(d) + ConfigurableTypeEntry(d) { } @@ -1777,9 +1885,6 @@ TypedefEntry::TypedefEntry(TypedefEntryPrivate *d) : class ContainerTypeEntryPrivate : public ComplexTypeEntryPrivate { public: - using OpaqueContainer = ContainerTypeEntry::OpaqueContainer; - using OpaqueContainers = ContainerTypeEntry::OpaqueContainers; - ContainerTypeEntryPrivate(const QString &entryName, ContainerTypeEntry::ContainerKind containerKind, const QVersionNumber &vr, @@ -1789,11 +1894,11 @@ public: { } - OpaqueContainers::const_iterator findOpaqueContainer(const QString &instantiation) const + OpaqueContainers::const_iterator findOpaqueContainer(const QStringList &instantiations) const { return std::find_if(m_opaqueContainers.cbegin(), m_opaqueContainers.cend(), - [&instantiation](const OpaqueContainer &r) { - return r.instantiation == instantiation; + [&instantiations](const OpaqueContainer &r) { + return r.instantiations == instantiations; }); } @@ -1802,6 +1907,19 @@ public: ContainerTypeEntry::ContainerKind m_containerKind; }; +QString OpaqueContainer::templateParameters() const +{ + QString result; + result += u'<'; + for (qsizetype i = 0, size = instantiations.size(); i < size; ++i) { + if (i) + result += u','; + result += instantiations.at(i); + } + result += u'>'; + return result; +} + ContainerTypeEntry::ContainerTypeEntry(const QString &entryName, ContainerKind containerKind, const QVersionNumber &vr, const TypeEntryCPtr &parent) : @@ -1816,40 +1934,53 @@ ContainerTypeEntry::ContainerKind ContainerTypeEntry::containerKind() const return d->m_containerKind; } -const ContainerTypeEntry::OpaqueContainers &ContainerTypeEntry::opaqueContainers() const +qsizetype ContainerTypeEntry::templateParameterCount() const +{ + S_D(const ContainerTypeEntry); + qsizetype result = 1; + switch (d->m_containerKind) { + case MapContainer: + case MultiMapContainer: + case PairContainer: + case SpanContainer: + result = 2; + break; + case ListContainer: + case SetContainer: + break; + } + return result; +} + +const OpaqueContainers &ContainerTypeEntry::opaqueContainers() const { S_D(const ContainerTypeEntry); return d->m_opaqueContainers; } -void ContainerTypeEntry::addOpaqueContainer(OpaqueContainer r) +void ContainerTypeEntry::appendOpaqueContainers(const OpaqueContainers &l) { S_D(ContainerTypeEntry); - // Fix to match AbstractMetaType::signature() which is used for matching - // "Foo*" -> "Foo *" - const auto asteriskPos = r.instantiation.indexOf(u'*'); - if (asteriskPos > 0 && !r.instantiation.at(asteriskPos - 1).isSpace()) - r.instantiation.insert(asteriskPos, u' '); - d->m_opaqueContainers.append(r); + d->m_opaqueContainers.append(l); } -bool ContainerTypeEntry::generateOpaqueContainer(const QString &instantiation) const +bool ContainerTypeEntry::generateOpaqueContainer(const QStringList &instantiations) const { S_D(const ContainerTypeEntry); - return d->findOpaqueContainer(instantiation) != d->m_opaqueContainers.cend(); + return d->findOpaqueContainer(instantiations) != d->m_opaqueContainers.cend(); } -QString ContainerTypeEntry::opaqueContainerName(const QString &instantiation) const +QString ContainerTypeEntry::opaqueContainerName(const QStringList &instantiations) const { S_D(const ContainerTypeEntry); - const auto it = d->findOpaqueContainer(instantiation); + const auto it = d->findOpaqueContainer(instantiations); return it != d->m_opaqueContainers.cend() ? it->name : QString{}; } bool ContainerTypeEntry::hasCustomConversion() const { S_D(const ContainerTypeEntry); - return !d->m_customConversion.isNull(); + return bool(d->m_customConversion); } void ContainerTypeEntry::setCustomConversion(const CustomConversionPtr &customConversion) @@ -2130,7 +2261,7 @@ void NamespaceTypeEntry::setInlineNamespace(bool i) bool NamespaceTypeEntry::isVisibleScope(const TypeEntryCPtr &e) { - return isVisibleScope(e.data()); + return isVisibleScope(e.get()); } bool NamespaceTypeEntry::isVisibleScope(const TypeEntry *e) @@ -2171,7 +2302,7 @@ ValueTypeEntry::ValueTypeEntry(const QString &entryName, const QVersionNumber &v bool ValueTypeEntry::hasCustomConversion() const { S_D(const ValueTypeEntry); - return !d->m_customConversion.isNull(); + return bool(d->m_customConversion); } void ValueTypeEntry::setCustomConversion(const CustomConversionPtr &customConversion) @@ -2239,7 +2370,7 @@ public: } QStringList m_signatures; - TypeSystem::SnakeCase m_snakeCase = TypeSystem::SnakeCase::Unspecified; + QString m_docFile; }; FunctionTypeEntry::FunctionTypeEntry(const QString &entryName, const QString &signature, @@ -2267,16 +2398,16 @@ bool FunctionTypeEntry::hasSignature(const QString &signature) const return d->m_signatures.contains(signature); } -TypeSystem::SnakeCase FunctionTypeEntry::snakeCase() const +QString FunctionTypeEntry::docFile() const { S_D(const FunctionTypeEntry); - return d->m_snakeCase; + return d->m_docFile; } -void FunctionTypeEntry::setSnakeCase(TypeSystem::SnakeCase sc) +void FunctionTypeEntry::setDocFile(const QString &df) { S_D(FunctionTypeEntry); - d->m_snakeCase = sc; + d->m_docFile = df; } TypeEntry *FunctionTypeEntry::clone() const @@ -2322,20 +2453,6 @@ ObjectTypeEntry::ObjectTypeEntry(ComplexTypeEntryPrivate *d) : if (!var.isEmpty()) \ debug << ", " << var.size() << ' ' << name; -template <class Container, class Separator> -static void formatList(QDebug &d, const char *name, const Container &c, Separator sep) -{ - if (const auto size = c.size()) { - d << ", " << name << '[' << size << "]=("; - for (qsizetype i = 0; i < size; ++i) { - if (i) - d << sep; - d << c.at(i); - } - d << ')'; - } -} - void TypeEntry::formatDebug(QDebug &debug) const { const QString cppName = qualifiedCppName(); @@ -2368,9 +2485,9 @@ void TypeEntry::formatDebug(QDebug &debug) const void PrimitiveTypeEntry::formatDebug(QDebug &debug) const { TypeEntry::formatDebug(debug); - if (auto e = referencedTypeEntry(); !e.isNull()) { + if (auto e = referencedTypeEntry()) { debug << ", references"; - for (; e != nullptr; e = e->referencedTypeEntry()) + for (; e ; e = e->referencedTypeEntry()) debug << ":\"" << e->qualifiedCppName() <<'"'; } } @@ -2418,8 +2535,7 @@ void FunctionTypeEntry::formatDebug(QDebug &debug) const S_D(const FunctionTypeEntry); TypeEntry::formatDebug(debug); - debug << "signatures=" << d->m_signatures - << ", snakeCase=" << int(d->m_snakeCase); + debug << "signatures=" << d->m_signatures; } void TypedefEntry::formatDebug(QDebug &debug) const @@ -2454,18 +2570,23 @@ void NamespaceTypeEntry::formatDebug(QDebug &debug) const debug << "[inline]"; } +QDebug operator<<(QDebug d, const OpaqueContainer &oc) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "OpaqueContainer(\"" << oc.name << "\": " << oc.templateParameters() << ')'; + return d; +} + void ContainerTypeEntry::formatDebug(QDebug &debug) const { S_D(const ContainerTypeEntry); ComplexTypeEntry::formatDebug(debug); debug << ", type=" << d->m_containerKind << '"'; - if (!d->m_opaqueContainers.isEmpty()) { - debug << ", opaque-containers=["; - for (const auto &r : d->m_opaqueContainers) - debug << r.instantiation << "->" << r.name << ','; - debug << ']'; - } + if (!d->m_opaqueContainers.isEmpty()) + debug << ", opaque-containers=[" << d->m_opaqueContainers << ']'; } void SmartPointerTypeEntry::formatDebug(QDebug &debug) const @@ -2501,7 +2622,7 @@ QDebug operator<<(QDebug d, const TypeEntry *te) QDebug operator<<(QDebug d, const TypeEntryCPtr &te) { - d << te.data(); + d << te.get(); return d; } @@ -2522,7 +2643,7 @@ QDebug operator<<(QDebug d, const TemplateEntry *te) QDebug operator<<(QDebug d, const TemplateEntryCPtr &te) { - d << te.data(); + d << te.get(); return d; } #endif // QT_NO_DEBUG_STREAM diff --git a/sources/shiboken6/ApiExtractor/typesystem_enums.h b/sources/shiboken6/ApiExtractor/typesystem_enums.h index 81304e6c2..9ecbb08a1 100644 --- a/sources/shiboken6/ApiExtractor/typesystem_enums.h +++ b/sources/shiboken6/ApiExtractor/typesystem_enums.h @@ -35,6 +35,7 @@ enum CodeSnipPosition { CodeSnipPositionBeginning, CodeSnipPositionEnd, CodeSnipPositionDeclaration, + CodeSnipPositionPyOverride, CodeSnipPositionAny }; diff --git a/sources/shiboken6/ApiExtractor/typesystem_typedefs.h b/sources/shiboken6/ApiExtractor/typesystem_typedefs.h index ca652252d..5a4e12ff2 100644 --- a/sources/shiboken6/ApiExtractor/typesystem_typedefs.h +++ b/sources/shiboken6/ApiExtractor/typesystem_typedefs.h @@ -5,10 +5,12 @@ #define TYPESYSTEM_TYPEDEFS_H #include <QtCore/QList> -#include <QtCore/QSharedPointer> + +#include <memory> class ArrayTypeEntry; class ComplexTypeEntry; +class ConfigurableTypeEntry; class ConstantValueTypeEntry; class ContainerTypeEntry; class CustomTypeEntry; @@ -26,44 +28,47 @@ class TypedefEntry; class TypeSystemTypeEntry; class ValueTypeEntry; -using ArrayTypeEntryPtr = QSharedPointer<ArrayTypeEntry>; -using ComplexTypeEntryPtr = QSharedPointer<ComplexTypeEntry>; -using ConstantValueTypeEntryPtr = QSharedPointer<ConstantValueTypeEntry>; -using ContainerTypeEntryPtr = QSharedPointer<ContainerTypeEntry>; -using CustomTypeEntryPtr = QSharedPointer<CustomTypeEntry>; -using EnumTypeEntryPtr = QSharedPointer<EnumTypeEntry>; -using EnumValueTypeEntryPtr = QSharedPointer<EnumValueTypeEntry>; -using FlagsTypeEntryPtr = QSharedPointer<FlagsTypeEntry>; -using FunctionTypeEntryPtr = QSharedPointer<FunctionTypeEntry>; -using NamespaceTypeEntryPtr = QSharedPointer<NamespaceTypeEntry>; -using ObjectTypeEntryPtr = QSharedPointer<ObjectTypeEntry>; -using PrimitiveTypeEntryPtr = QSharedPointer<PrimitiveTypeEntry>; -using SmartPointerTypeEntryPtr = QSharedPointer<SmartPointerTypeEntry>; -using TemplateEntryPtr = QSharedPointer<TemplateEntry>; -using TypeEntryPtr = QSharedPointer<TypeEntry>; -using TypedefEntryPtr = QSharedPointer<TypedefEntry>; -using TypeSystemTypeEntryPtr = QSharedPointer<TypeSystemTypeEntry>; -using ValueTypeEntryPtr = QSharedPointer<ValueTypeEntry>; +using ArrayTypeEntryPtr = std::shared_ptr<ArrayTypeEntry>; +using ComplexTypeEntryPtr = std::shared_ptr<ComplexTypeEntry>; +using ConfigurableTypeEntryPtr = std::shared_ptr<ConfigurableTypeEntry>; +using ConstantValueTypeEntryPtr = std::shared_ptr<ConstantValueTypeEntry>; +using ContainerTypeEntryPtr = std::shared_ptr<ContainerTypeEntry>; +using CustomTypeEntryPtr = std::shared_ptr<CustomTypeEntry>; +using EnumTypeEntryPtr = std::shared_ptr<EnumTypeEntry>; +using EnumValueTypeEntryPtr = std::shared_ptr<EnumValueTypeEntry>; +using FlagsTypeEntryPtr = std::shared_ptr<FlagsTypeEntry>; +using FunctionTypeEntryPtr = std::shared_ptr<FunctionTypeEntry>; +using NamespaceTypeEntryPtr = std::shared_ptr<NamespaceTypeEntry>; +using ObjectTypeEntryPtr = std::shared_ptr<ObjectTypeEntry>; +using PrimitiveTypeEntryPtr = std::shared_ptr<PrimitiveTypeEntry>; +using SmartPointerTypeEntryPtr = std::shared_ptr<SmartPointerTypeEntry>; +using TemplateEntryPtr = std::shared_ptr<TemplateEntry>; +using TypeEntryPtr = std::shared_ptr<TypeEntry>; +using TypedefEntryPtr = std::shared_ptr<TypedefEntry>; +using TypeSystemTypeEntryPtr = std::shared_ptr<TypeSystemTypeEntry>; +using ValueTypeEntryPtr = std::shared_ptr<ValueTypeEntry>; -using ArrayTypeEntryCPtr = QSharedPointer<const ArrayTypeEntry>; -using ComplexTypeEntryCPtr = QSharedPointer<const ComplexTypeEntry>; -using ConstantValueTypeEntryCPtr = QSharedPointer<const ConstantValueTypeEntry>; -using ContainerTypeEntryCPtr = QSharedPointer<const ContainerTypeEntry>; -using CustomTypeEntryCPtr = QSharedPointer<const CustomTypeEntry>; -using EnumTypeEntryCPtr = QSharedPointer<const EnumTypeEntry>; -using EnumValueTypeEntryCPtr = QSharedPointer<const EnumValueTypeEntry>; -using FlagsTypeEntryCPtr = QSharedPointer<const FlagsTypeEntry>; -using FunctionTypeEntryCPtr = QSharedPointer<const FunctionTypeEntry>; -using NamespaceTypeEntryCPtr = QSharedPointer<const NamespaceTypeEntry>; -using ObjectTypeEntryCPtr = QSharedPointer<const ObjectTypeEntry>; -using PrimitiveTypeEntryCPtr = QSharedPointer<const PrimitiveTypeEntry>; -using SmartPointerTypeEntryCPtr = QSharedPointer<const SmartPointerTypeEntry>; -using TemplateEntryCPtr = QSharedPointer<const TemplateEntry>; -using TypeEntryCPtr = QSharedPointer<const TypeEntry>; -using TypedefEntryCPtr = QSharedPointer<const TypedefEntry>; -using TypeSystemTypeEntryCPtr = QSharedPointer<const TypeSystemTypeEntry>; -using ValueTypeEntryCPtr = QSharedPointer<const ValueTypeEntry>; +using ArrayTypeEntryCPtr = std::shared_ptr<const ArrayTypeEntry>; +using ComplexTypeEntryCPtr = std::shared_ptr<const ComplexTypeEntry>; +using ConstantValueTypeEntryCPtr = std::shared_ptr<const ConstantValueTypeEntry>; +using ConfigurableTypeEntryCPtr = std::shared_ptr<const ConfigurableTypeEntry>; +using ContainerTypeEntryCPtr = std::shared_ptr<const ContainerTypeEntry>; +using CustomTypeEntryCPtr = std::shared_ptr<const CustomTypeEntry>; +using EnumTypeEntryCPtr = std::shared_ptr<const EnumTypeEntry>; +using EnumValueTypeEntryCPtr = std::shared_ptr<const EnumValueTypeEntry>; +using FlagsTypeEntryCPtr = std::shared_ptr<const FlagsTypeEntry>; +using FunctionTypeEntryCPtr = std::shared_ptr<const FunctionTypeEntry>; +using NamespaceTypeEntryCPtr = std::shared_ptr<const NamespaceTypeEntry>; +using ObjectTypeEntryCPtr = std::shared_ptr<const ObjectTypeEntry>; +using PrimitiveTypeEntryCPtr = std::shared_ptr<const PrimitiveTypeEntry>; +using SmartPointerTypeEntryCPtr = std::shared_ptr<const SmartPointerTypeEntry>; +using TemplateEntryCPtr = std::shared_ptr<const TemplateEntry>; +using TypeEntryCPtr = std::shared_ptr<const TypeEntry>; +using TypedefEntryCPtr = std::shared_ptr<const TypedefEntry>; +using TypeSystemTypeEntryCPtr = std::shared_ptr<const TypeSystemTypeEntry>; +using ValueTypeEntryCPtr = std::shared_ptr<const ValueTypeEntry>; +using ComplexTypeEntryCList = QList<ComplexTypeEntryCPtr>; using ContainerTypeEntryCList = QList<ContainerTypeEntryCPtr>; using NamespaceTypeEntryList = QList<NamespaceTypeEntryPtr>; using PrimitiveTypeEntryCList = QList<PrimitiveTypeEntryCPtr>; diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp index 42edc567a..2b686e997 100644 --- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp @@ -2,13 +2,13 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "typesystemparser_p.h" +#include "anystringview_helpers.h" #include "addedfunction.h" #include "codesnip.h" #include "enumtypeentry.h" #include "containertypeentry.h" #include "customconversion.h" #include "customtypenentry.h" -#include "enumtypeentry.h" #include "flagstypeentry.h" #include "functiontypeentry.h" #include "namespacetypeentry.h" @@ -46,78 +46,84 @@ using namespace Qt::StringLiterals; -static inline QString allowThreadAttribute() { return QStringLiteral("allow-thread"); } -static inline QString colonColon() { return QStringLiteral("::"); } -static inline QString checkFunctionAttribute() { return QStringLiteral("check-function"); } -static inline QString copyableAttribute() { return QStringLiteral("copyable"); } -static inline QString accessAttribute() { return QStringLiteral("access"); } -static inline QString actionAttribute() { return QStringLiteral("action"); } -static inline QString quoteAfterLineAttribute() { return QStringLiteral("quote-after-line"); } -static inline QString quoteBeforeLineAttribute() { return QStringLiteral("quote-before-line"); } -static inline QString textAttribute() { return QStringLiteral("text"); } -static inline QString nameAttribute() { return QStringLiteral("name"); } -static inline QString sinceAttribute() { return QStringLiteral("since"); } -static inline QString untilAttribute() { return QStringLiteral("until"); } -static inline QString defaultSuperclassAttribute() { return QStringLiteral("default-superclass"); } -static inline QString deleteInMainThreadAttribute() { return QStringLiteral("delete-in-main-thread"); } -static inline QString deprecatedAttribute() { return QStringLiteral("deprecated"); } -static inline QString disableWrapperAttribute() { return QStringLiteral("disable-wrapper"); } -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"); } -static inline QString formatAttribute() { return QStringLiteral("format"); } -static inline QString generateUsingAttribute() { return QStringLiteral("generate-using"); } -static inline QString generateFunctionsAttribute() { return QStringLiteral("generate-functions"); } -static inline QString classAttribute() { return QStringLiteral("class"); } -static inline QString generateAttribute() { return QStringLiteral("generate"); } -static inline QString generateGetSetDefAttribute() { return QStringLiteral("generate-getsetdef"); } -static inline QString genericClassAttribute() { return QStringLiteral("generic-class"); } -static inline QString indexAttribute() { return QStringLiteral("index"); } -static inline QString invalidateAfterUseAttribute() { return QStringLiteral("invalidate-after-use"); } -static inline QString isNullAttribute() { return QStringLiteral("isNull"); } -static inline QString locationAttribute() { return QStringLiteral("location"); } -static inline QString modifiedTypeAttribute() { return QStringLiteral("modified-type"); } -static inline QString operatorBoolAttribute() { return QStringLiteral("operator-bool"); } -static inline QString parentManagementAttribute() { return QStringLiteral("parent-management"); } -static inline QString pyiTypeAttribute() { return QStringLiteral("pyi-type"); } -static inline QString overloadNumberAttribute() { return QStringLiteral("overload-number"); } -static inline QString ownershipAttribute() { return QStringLiteral("owner"); } -static inline QString packageAttribute() { return QStringLiteral("package"); } -static inline QString positionAttribute() { return QStringLiteral("position"); } -static inline QString preferredConversionAttribute() { return QStringLiteral("preferred-conversion"); } -static inline QString preferredTargetLangTypeAttribute() { return QStringLiteral("preferred-target-lang-type"); } -static inline QString pythonEnumTypeAttribute() { return QStringLiteral("python-type"); } -static inline QString cppEnumTypeAttribute() { return QStringLiteral("cpp-type"); } -static inline QString qtMetaTypeAttribute() { return QStringLiteral("qt-register-metatype"); } -static inline QString removeAttribute() { return QStringLiteral("remove"); } -static inline QString renameAttribute() { return QStringLiteral("rename"); } -static inline QString readAttribute() { return QStringLiteral("read"); } -static inline QString targetLangNameAttribute() { return QStringLiteral("target-lang-name"); } -static inline QString writeAttribute() { return QStringLiteral("write"); } -static inline QString opaqueContainerFieldAttribute() { return QStringLiteral("opaque-container"); } -static inline QString replaceAttribute() { return QStringLiteral("replace"); } -static inline QString toAttribute() { return QStringLiteral("to"); } -static inline QString signatureAttribute() { return QStringLiteral("signature"); } -static inline QString snippetAttribute() { return QStringLiteral("snippet"); } -static inline QString snakeCaseAttribute() { return QStringLiteral("snake-case"); } -static inline QString staticAttribute() { return QStringLiteral("static"); } -static inline QString classmethodAttribute() { return QStringLiteral("classmethod"); } -static inline QString threadAttribute() { return QStringLiteral("thread"); } -static inline QString sourceAttribute() { return QStringLiteral("source"); } -static inline QString streamAttribute() { return QStringLiteral("stream"); } -static inline QString privateAttribute() { return QStringLiteral("private"); } -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"); } -static inline QString yesAttributeValue() { return QStringLiteral("yes"); } -static inline QString trueAttributeValue() { return QStringLiteral("true"); } -static inline QString falseAttributeValue() { return QStringLiteral("false"); } +constexpr auto allowThreadAttribute = "allow-thread"_L1; +constexpr auto checkFunctionAttribute = "check-function"_L1; +constexpr auto copyableAttribute = "copyable"_L1; +constexpr auto accessAttribute = "access"_L1; +constexpr auto actionAttribute = "action"_L1; +constexpr auto quoteAfterLineAttribute = "quote-after-line"_L1; +constexpr auto quoteBeforeLineAttribute = "quote-before-line"_L1; +constexpr auto textAttribute = "text"_L1; +constexpr auto nameAttribute = "name"_L1; +constexpr auto sinceAttribute = "since"_L1; +constexpr auto untilAttribute = "until"_L1; +constexpr auto defaultSuperclassAttribute = "default-superclass"_L1; +constexpr auto deleteInMainThreadAttribute = "delete-in-main-thread"_L1; +constexpr auto deprecatedAttribute = "deprecated"_L1; +constexpr auto disableWrapperAttribute = "disable-wrapper"_L1; +constexpr auto docFileAttribute = "doc-file"_L1; +constexpr auto exceptionHandlingAttribute = "exception-handling"_L1; +constexpr auto extensibleAttribute = "extensible"_L1; +constexpr auto fileNameAttribute = "file-name"_L1; +constexpr auto fileAttribute = "file"_L1; +constexpr auto flagsAttribute = "flags"_L1; +constexpr auto forceAbstractAttribute = "force-abstract"_L1; +constexpr auto forceIntegerAttribute = "force-integer"_L1; +constexpr auto formatAttribute = "format"_L1; +constexpr auto generateUsingAttribute = "generate-using"_L1; +constexpr auto generateFunctionsAttribute = "generate-functions"_L1; +constexpr auto classAttribute = "class"_L1; +constexpr auto generateAttribute = "generate"_L1; +constexpr auto generateGetSetDefAttribute = "generate-getsetdef"_L1; +constexpr auto genericClassAttribute = "generic-class"_L1; +constexpr auto indexAttribute = "index"_L1; +constexpr auto invalidateAfterUseAttribute = "invalidate-after-use"_L1; +constexpr auto isNullAttribute = "isNull"_L1; +constexpr auto locationAttribute = "location"_L1; +constexpr auto modifiedTypeAttribute = "modified-type"_L1; +constexpr auto opaqueContainerAttribute = "opaque-containers"_L1; +constexpr auto operatorBoolAttribute = "operator-bool"_L1; +constexpr auto parentManagementAttribute = "parent-management"_L1; +constexpr auto pyiTypeAttribute = "pyi-type"_L1; +constexpr auto overloadNumberAttribute = "overload-number"_L1; +constexpr auto ownershipAttribute = "owner"_L1; +constexpr auto packageAttribute = "package"_L1; +constexpr auto polymorphicBaseAttribute = "polymorphic-base"_L1; +constexpr auto positionAttribute = "position"_L1; +constexpr auto preferredConversionAttribute = "preferred-conversion"_L1; +constexpr auto preferredTargetLangTypeAttribute = "preferred-target-lang-type"_L1; +constexpr auto pythonEnumTypeAttribute = "python-type"_L1; +constexpr auto pythonOverrideAttribute = "python-override"_L1; +constexpr auto cppEnumTypeAttribute = "cpp-type"_L1; +constexpr auto qtMetaObjectFunctionsAttribute = "qt-metaobject"_L1; +constexpr auto qtMetaTypeAttribute = "qt-register-metatype"_L1; +constexpr auto removeAttribute = "remove"_L1; +constexpr auto renameAttribute = "rename"_L1; +constexpr auto readAttribute = "read"_L1; +constexpr auto targetLangNameAttribute = "target-lang-name"_L1; +constexpr auto writeAttribute = "write"_L1; +constexpr auto opaqueContainerFieldAttribute = "opaque-container"_L1; +constexpr auto replaceAttribute = "replace"_L1; +constexpr auto toAttribute = "to"_L1; +constexpr auto signatureAttribute = "signature"_L1; +constexpr auto snippetAttribute = "snippet"_L1; +constexpr auto snakeCaseAttribute = "snake-case"_L1; +constexpr auto staticAttribute = "static"_L1; +constexpr auto classmethodAttribute = "classmethod"_L1; +constexpr auto threadAttribute = "thread"_L1; +constexpr auto sourceAttribute = "source"_L1; +constexpr auto streamAttribute = "stream"_L1; +constexpr auto privateAttribute = "private"_L1; +constexpr auto xPathAttribute = "xpath"_L1; +constexpr auto virtualSlotAttribute = "virtual-slot"_L1; +constexpr auto visibleAttribute = "visible"_L1; +constexpr auto enumIdentifiedByValueAttribute = "identified-by-value"_L1; +constexpr auto subModuleOfAttribute = "submodule-of"_L1; + +constexpr auto noAttributeValue = "no"_L1; +constexpr auto yesAttributeValue = "yes"_L1; +constexpr auto trueAttributeValue = "true"_L1; +constexpr auto falseAttributeValue = "false"_L1; static bool isTypeEntry(StackElement el) { @@ -147,7 +153,7 @@ static bool setRejectionRegularExpression(const QString &patternIn, if (patternIn.startsWith(u'^') && patternIn.endsWith(u'$')) pattern = patternIn; else if (patternIn == u"*") - pattern = QStringLiteral("^.*$"); + pattern = "^.*$"_L1; else pattern = u'^' + QRegularExpression::escape(patternIn) + u'$'; re->setPattern(pattern); @@ -158,15 +164,20 @@ static bool setRejectionRegularExpression(const QString &patternIn, return true; } +static inline bool hasFileSnippetAttributes(const QXmlStreamAttributes *attributes) +{ + return attributes->hasAttribute(fileAttribute); +} + // Extract a snippet from a file within annotation "// @snippet label". std::optional<QString> extractSnippet(const QString &code, const QString &snippetLabel) { if (snippetLabel.isEmpty()) return code; - const QString pattern = QStringLiteral(R"(^\s*//\s*@snippet\s+)") + const QString pattern = R"(^\s*//\s*@snippet\s+)"_L1 + QRegularExpression::escape(snippetLabel) - + QStringLiteral(R"(\s*$)"); + + R"(\s*$)"_L1; const QRegularExpression snippetRe(pattern); Q_ASSERT(snippetRe.isValid()); @@ -175,7 +186,7 @@ std::optional<QString> QString result; const auto lines = QStringView{code}.split(u'\n'); for (const auto &line : lines) { - if (snippetRe.match(line).hasMatch()) { + if (snippetRe.matchView(line).hasMatch()) { foundLabel = true; useLine = !useLine; if (!useLine) @@ -188,48 +199,31 @@ std::optional<QString> return CodeSnipAbstract::fixSpaces(result); } -template <class EnumType, Qt::CaseSensitivity cs = Qt::CaseInsensitive> +template <class EnumType> struct EnumLookup { QStringView name; EnumType value; }; -template <class EnumType, Qt::CaseSensitivity cs> -bool operator==(const EnumLookup<EnumType, cs> &e1, const EnumLookup<EnumType, cs> &e2) -{ - return e1.name.compare(e2.name, cs) == 0; -} - -template <class EnumType, Qt::CaseSensitivity cs> -bool operator<(const EnumLookup<EnumType, cs> &e1, const EnumLookup<EnumType, cs> &e2) -{ - return e1.name.compare(e2.name, cs) < 0; -} - // Helper macros to define lookup functions that take a QStringView needle // and an optional default return value. #define ENUM_LOOKUP_BEGIN(EnumType, caseSensitivity, functionName) \ static std::optional<EnumType> functionName(QStringView needle) \ { \ - using HaystackEntry = EnumLookup<EnumType, caseSensitivity>; \ - static const HaystackEntry haystack[] = - -#define ENUM_LOOKUP_LINEAR_SEARCH() \ - const auto end = haystack + sizeof(haystack) / sizeof(haystack[0]); \ - const auto it = std::find(haystack, end, HaystackEntry{needle, {} }); \ + using HaystackEntry = EnumLookup<EnumType>; \ + constexpr auto cs = caseSensitivity; \ + static constexpr HaystackEntry haystack[] = + +#define ENUM_LOOKUP_LINEAR_SEARCH \ + auto pred = [cs, needle](const HaystackEntry &he) { \ + return he.name.compare(needle, cs) == 0; \ + }; \ + auto end = std::cend(haystack); \ + auto it = std::find_if(std::cbegin(haystack), end, pred); \ if (it != end) \ return it->value; \ - return {}; \ -} - -#define ENUM_LOOKUP_BINARY_SEARCH() \ - const auto end = haystack + sizeof(haystack) / sizeof(haystack[0]); \ - const HaystackEntry needleEntry{needle, {} }; \ - const auto lb = std::lower_bound(haystack, end, needleEntry); \ - if (lb != end && *lb == needleEntry) \ - return lb->value; \ - return {}; \ + return std::nullopt; \ } ENUM_LOOKUP_BEGIN(TypeSystem::AllowThread, Qt::CaseInsensitive, @@ -241,7 +235,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::AllowThread, Qt::CaseInsensitive, {u"no", TypeSystem::AllowThread::Disallow}, {u"false", TypeSystem::AllowThread::Disallow}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::BoolCast, Qt::CaseInsensitive, @@ -252,7 +246,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::BoolCast, Qt::CaseInsensitive, {u"no", TypeSystem::BoolCast::Disabled}, {u"false", TypeSystem::BoolCast::Disabled}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::PythonEnumType, Qt::CaseSensitive, pythonEnumTypeFromAttribute) @@ -262,7 +256,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::PythonEnumType, Qt::CaseSensitive, {u"Flag", TypeSystem::PythonEnumType::Flag}, {u"IntFlag", TypeSystem::PythonEnumType::IntFlag}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::QtMetaTypeRegistration, Qt::CaseSensitive, qtMetaTypeFromAttribute) @@ -273,7 +267,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::QtMetaTypeRegistration, Qt::CaseSensitive, {u"no", TypeSystem::QtMetaTypeRegistration::Disabled}, {u"false", TypeSystem::QtMetaTypeRegistration::Disabled}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::Language, Qt::CaseInsensitive, languageFromAttribute) @@ -283,7 +277,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::Language, Qt::CaseInsensitive, {u"shell", TypeSystem::ShellCode}, // coloca no header, mas antes da declaracao da classe {u"target", TypeSystem::TargetLangCode} // em algum lugar do cpp }; -ENUM_LOOKUP_BINARY_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::Ownership, Qt::CaseInsensitive, ownershipFromFromAttribute) @@ -292,7 +286,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::Ownership, Qt::CaseInsensitive, {u"c++", TypeSystem::CppOwnership}, {u"default", TypeSystem::DefaultOwnership} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(AddedFunction::Access, Qt::CaseInsensitive, addedFunctionAccessFromAttribute) @@ -300,7 +294,7 @@ ENUM_LOOKUP_BEGIN(AddedFunction::Access, Qt::CaseInsensitive, {u"public", AddedFunction::Public}, {u"protected", AddedFunction::Protected}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(FunctionModification::ModifierFlag, Qt::CaseSensitive, modifierFromAttribute) @@ -308,12 +302,11 @@ ENUM_LOOKUP_BEGIN(FunctionModification::ModifierFlag, Qt::CaseSensitive, {u"private", FunctionModification::Private}, {u"public", FunctionModification::Public}, {u"protected", FunctionModification::Protected}, - {u"friendly", FunctionModification::Friendly}, {u"rename", FunctionModification::Rename}, {u"final", FunctionModification::Final}, {u"non-final", FunctionModification::NonFinal} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(ReferenceCount::Action, Qt::CaseInsensitive, referenceCountFromAttribute) @@ -324,7 +317,7 @@ ENUM_LOOKUP_BEGIN(ReferenceCount::Action, Qt::CaseInsensitive, {u"set", ReferenceCount::Set}, {u"ignore", ReferenceCount::Ignore} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(ArgumentOwner::Action, Qt::CaseInsensitive, argumentOwnerActionFromAttribute) @@ -332,16 +325,17 @@ ENUM_LOOKUP_BEGIN(ArgumentOwner::Action, Qt::CaseInsensitive, {u"add", ArgumentOwner::Add}, {u"remove", ArgumentOwner::Remove} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::CodeSnipPosition, Qt::CaseInsensitive, codeSnipPositionFromAttribute) { {u"beginning", TypeSystem::CodeSnipPositionBeginning}, {u"end", TypeSystem::CodeSnipPositionEnd}, - {u"declaration", TypeSystem::CodeSnipPositionDeclaration} + {u"declaration", TypeSystem::CodeSnipPositionDeclaration}, + {u"override", TypeSystem::CodeSnipPositionPyOverride} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(Include::IncludeType, Qt::CaseInsensitive, locationFromAttribute) @@ -350,7 +344,7 @@ ENUM_LOOKUP_BEGIN(Include::IncludeType, Qt::CaseInsensitive, {u"local", Include::LocalPath}, {u"target", Include::TargetLangImport} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::DocModificationMode, Qt::CaseInsensitive, docModificationFromAttribute) @@ -359,7 +353,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::DocModificationMode, Qt::CaseInsensitive, {u"prepend", TypeSystem::DocModificationPrepend}, {u"replace", TypeSystem::DocModificationReplace} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(ContainerTypeEntry::ContainerKind, Qt::CaseSensitive, containerTypeFromAttribute) @@ -375,9 +369,10 @@ ENUM_LOOKUP_BEGIN(ContainerTypeEntry::ContainerKind, Qt::CaseSensitive, {u"multi-map", ContainerTypeEntry::MultiMapContainer}, {u"hash", ContainerTypeEntry::MapContainer}, {u"multi-hash", ContainerTypeEntry::MultiMapContainer}, - {u"pair", ContainerTypeEntry::PairContainer} + {u"pair", ContainerTypeEntry::PairContainer}, + {u"span", ContainerTypeEntry::SpanContainer} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeRejection::MatchType, Qt::CaseSensitive, typeRejectionFromAttribute) @@ -389,7 +384,7 @@ ENUM_LOOKUP_BEGIN(TypeRejection::MatchType, Qt::CaseSensitive, {u"argument-type", TypeRejection::ArgumentType}, {u"return-type", TypeRejection::ReturnType} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::ExceptionHandling, Qt::CaseSensitive, exceptionHandlingFromAttribute) @@ -401,7 +396,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::ExceptionHandling, Qt::CaseSensitive, {u"yes", TypeSystem::ExceptionHandling::On}, {u"true", TypeSystem::ExceptionHandling::On}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::SmartPointerType, Qt::CaseSensitive, smartPointerTypeFromAttribute) @@ -411,7 +406,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::SmartPointerType, Qt::CaseSensitive, {u"value-handle", TypeSystem::SmartPointerType::ValueHandle}, {u"shared", TypeSystem::SmartPointerType::Shared} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH template <class EnumType> static std::optional<EnumType> @@ -440,6 +435,7 @@ static const StackElementHash &stackElementHash() {u"add-function", StackElement::AddFunction}, {u"add-pymethoddef", StackElement::AddPyMethodDef}, {u"array", StackElement::Array}, + {u"configuration", StackElement::Configuration}, {u"container-type", StackElement::ContainerTypeEntry}, {u"conversion-rule", StackElement::ConversionRule}, {u"custom-constructor", StackElement::Unimplemented}, @@ -465,6 +461,7 @@ static const StackElementHash &stackElementHash() {u"native-to-target", StackElement::NativeToTarget}, {u"no-null-pointer", StackElement::NoNullPointers}, {u"object-type", StackElement::ObjectTypeEntry}, + {u"opaque-container", StackElement::OpaqueContainer}, {u"parent", StackElement::ParentOwner}, {u"primitive-type", StackElement::PrimitiveTypeEntry}, {u"property", StackElement::Property}, @@ -520,7 +517,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::SnakeCase, Qt::CaseSensitive, {u"true", TypeSystem::SnakeCase::Enabled}, {u"both", TypeSystem::SnakeCase::Both}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::Visibility, Qt::CaseSensitive, visibilityFromAttribute) @@ -531,10 +528,10 @@ ENUM_LOOKUP_BEGIN(TypeSystem::Visibility, Qt::CaseSensitive, {u"yes", TypeSystem::Visibility::Visible}, {u"true", TypeSystem::Visibility::Visible}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH static int indexOfAttribute(const QXmlStreamAttributes &atts, - QStringView name) + QAnyStringView name) { for (qsizetype i = 0, size = atts.size(); i < size; ++i) { if (atts.at(i).qualifiedName() == name) @@ -602,12 +599,12 @@ QString TypeSystemEntityResolver::readFile(const QString &entityName, QString *e path = TypeDatabase::instance()->modifiedTypesystemFilepath(fileName, m_currentPath); if (!QFileInfo::exists(path)) { *errorMessage = u"Unable to resolve: "_s + entityName; - return QString(); + return {}; } QFile file(path); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { *errorMessage = msgCannotOpenForReading(file); - return QString(); + return {}; } QString result = QString::fromUtf8(file.readAll()).trimmed(); // Remove license header comments on which QXmlStreamReader chokes @@ -647,7 +644,7 @@ enum class ParserState Template }; -TypeSystemParser::TypeSystemParser(const QSharedPointer<TypeDatabaseParserContext> &context, +TypeSystemParser::TypeSystemParser(const std::shared_ptr<TypeDatabaseParserContext> &context, bool generate) : m_context(context), m_generate(generate ? TypeEntry::GenerateCode : TypeEntry::GenerateForSubclass) @@ -690,7 +687,7 @@ static QString msgReaderError(const ConditionalStreamReader &reader, const QStri } static QString msgUnimplementedElementWarning(const ConditionalStreamReader &reader, - QStringView name) + QAnyStringView name) { QString message; QTextStream(&message) << "The element \"" << name @@ -715,7 +712,7 @@ static inline QString msgUnimplementedAttributeWarning(const ConditionalStreamRe static QString msgUnimplementedAttributeValueWarning(const ConditionalStreamReader &reader, - QStringView name, QStringView value) + QAnyStringView name, QAnyStringView value) { QString message; QTextStream(&message) << "The value \"" << value @@ -732,16 +729,17 @@ static inline attribute.value()); } -static bool addRejection(TypeDatabase *database, QXmlStreamAttributes *attributes, +static bool addRejection(TypeDatabase *database, bool generate, QXmlStreamAttributes *attributes, QString *errorMessage) { - const auto classIndex = indexOfAttribute(*attributes, classAttribute()); + const auto classIndex = indexOfAttribute(*attributes, classAttribute); if (classIndex == -1) { - *errorMessage = msgMissingAttribute(classAttribute()); + *errorMessage = msgMissingAttribute(classAttribute); return false; } TypeRejection rejection; + rejection.generate = generate; const QString className = attributes->takeAt(classIndex).value().toString(); if (!setRejectionRegularExpression(className, &rejection.className, errorMessage)) return false; @@ -880,7 +878,7 @@ bool TypeSystemParser::endElement(StackElement element) toNative.setSourceType(m_context->db->findType(toNative.sourceTypeName())); } } - purgeEmptyCodeSnips(&qSharedPointerCast<TypeSystemTypeEntry>(top->entry)->codeSnips()); + purgeEmptyCodeSnips(&std::static_pointer_cast<TypeSystemTypeEntry>(top->entry)->codeSnips()); break; case StackElement::FunctionTypeEntry: TypeDatabase::instance()->addGlobalUserFunctionModifications(top->functionMods); @@ -892,7 +890,7 @@ bool TypeSystemParser::endElement(StackElement element) case StackElement::NamespaceTypeEntry: { Q_ASSERT(top->entry); Q_ASSERT(top->entry->isComplex()); - auto centry = qSharedPointerCast<ComplexTypeEntry>(top->entry); + auto centry = std::static_pointer_cast<ComplexTypeEntry>(top->entry); purgeEmptyCodeSnips(¢ry->codeSnips()); centry->setAddedFunctions(top->addedFunctions); centry->setFunctionModifications(top->functionMods); @@ -902,13 +900,13 @@ bool TypeSystemParser::endElement(StackElement element) break; case StackElement::TypedefTypeEntry: { - auto centry = qSharedPointerCast<TypedefEntry>(top->entry)->target(); + auto centry = std::static_pointer_cast<TypedefEntry>(top->entry)->target(); centry->setAddedFunctions(centry->addedFunctions() + top->addedFunctions); centry->setFunctionModifications(centry->functionModifications() + top->functionMods); centry->setFieldModifications(centry->fieldModifications() + top->fieldMods); centry->setDocModification(centry->docModifications() + top->docModifications); if (top->entry->isComplex()) { - auto cte = qSharedPointerCast<const ComplexTypeEntry>(top->entry); + auto cte = std::static_pointer_cast<const ComplexTypeEntry>(top->entry); centry->setCodeSnips(centry->codeSnips() + cte->codeSnips()); } } @@ -931,7 +929,7 @@ bool TypeSystemParser::endElement(StackElement element) case ParserState::PrimitiveTypeNativeToTargetConversion: case ParserState::PrimitiveTypeTargetToNativeConversion: { auto customConversion = CustomConversion::getCustomConversion(top->entry); - if (customConversion.isNull()) { + if (!customConversion) { m_error = msgMissingCustomConversion(top->entry); return false; } @@ -1068,12 +1066,12 @@ CodeSnipAbstract *TypeSystemParser::injectCodeTarget(qsizetype offset) const } case ParserState::TypeEntryCodeInjection: Q_ASSERT(top->entry->isComplex()); - return &qSharedPointerCast<ComplexTypeEntry>(top->entry)->codeSnips().last(); + return &std::static_pointer_cast<ComplexTypeEntry>(top->entry)->codeSnips().last(); case ParserState::TypeSystemCodeInjection: Q_ASSERT(top->entry->isTypeSystem()); - return &qSharedPointerCast<TypeSystemTypeEntry>(top->entry)->codeSnips().last(); + return &std::static_pointer_cast<TypeSystemTypeEntry>(top->entry)->codeSnips().last(); case ParserState::Template: - return m_templateEntry.data(); + return m_templateEntry.get(); default: break; } @@ -1122,7 +1120,7 @@ bool TypeSystemParser::characters(const String &ch) bool TypeSystemParser::importFileElement(const QXmlStreamAttributes &atts) { - const QString fileName = atts.value(nameAttribute()).toString(); + const QString fileName = atts.value(nameAttribute).toString(); if (fileName.isEmpty()) { m_error = u"Required attribute 'name' missing for include-file tag."_s; return false; @@ -1137,11 +1135,11 @@ bool TypeSystemParser::importFileElement(const QXmlStreamAttributes &atts) } } - const auto quoteFrom = atts.value(quoteAfterLineAttribute()); + const auto quoteFrom = atts.value(quoteAfterLineAttribute); bool foundFromOk = quoteFrom.isEmpty(); bool from = quoteFrom.isEmpty(); - const auto quoteTo = atts.value(quoteBeforeLineAttribute()); + const auto quoteTo = atts.value(quoteBeforeLineAttribute); bool foundToOk = quoteTo.isEmpty(); bool to = true; @@ -1161,10 +1159,10 @@ bool TypeSystemParser::importFileElement(const QXmlStreamAttributes &atts) } } if (!foundFromOk || !foundToOk) { - QString fromError = QStringLiteral("Could not find quote-after-line='%1' in file '%2'.") - .arg(quoteFrom.toString(), fileName); - QString toError = QStringLiteral("Could not find quote-before-line='%1' in file '%2'.") - .arg(quoteTo.toString(), fileName); + QString fromError = QString::fromLatin1("Could not find quote-after-line='%1' in file '%2'.") + .arg(quoteFrom.toString(), fileName); + QString toError = QString::fromLatin1("Could not find quote-before-line='%1' in file '%2'.") + .arg(quoteTo.toString(), fileName); if (!foundToOk) m_error = toError; @@ -1178,29 +1176,27 @@ bool TypeSystemParser::importFileElement(const QXmlStreamAttributes &atts) return true; } -static bool convertBoolean(QStringView value, const QString &attributeName, bool defaultValue) +static bool convertBoolean(QStringView value, QAnyStringView attributeName, bool defaultValue) { - if (value.compare(trueAttributeValue(), Qt::CaseInsensitive) == 0 - || value.compare(yesAttributeValue(), Qt::CaseInsensitive) == 0) { + if (value.compare(trueAttributeValue, Qt::CaseInsensitive) == 0 + || value.compare(yesAttributeValue, Qt::CaseInsensitive) == 0) { return true; } - if (value.compare(falseAttributeValue(), Qt::CaseInsensitive) == 0 - || value.compare(noAttributeValue(), Qt::CaseInsensitive) == 0) { + if (value.compare(falseAttributeValue, Qt::CaseInsensitive) == 0 + || value.compare(noAttributeValue, Qt::CaseInsensitive) == 0) { return false; } - const QString warn = QStringLiteral("Boolean value '%1' not supported in attribute '%2'. Use 'yes' or 'no'. Defaulting to '%3'.") - .arg(value) - .arg(attributeName, - defaultValue ? yesAttributeValue() : noAttributeValue()); - - qCWarning(lcShiboken).noquote().nospace() << warn; + qCWarning(lcShiboken).noquote().nospace() << "Boolean value '" << value + << "' not supported in attribute '" << attributeName + << "'. Use 'yes' or 'no'. Defaulting to '" + << (defaultValue ? yesAttributeValue : noAttributeValue) << "'."; return defaultValue; } static bool convertRemovalAttribute(QStringView value) { return value == u"all" // Legacy - || convertBoolean(value, removeAttribute(), false); + || convertBoolean(value, removeAttribute, false); } // Check whether an entry should be dropped, allowing for dropping the module @@ -1226,7 +1222,7 @@ static bool shouldDropTypeEntry(const TypeDatabase *db, static QString checkSignatureError(const QString& signature, const QString& tag) { QString funcName = signature.left(signature.indexOf(u'(')).trimmed(); - static const QRegularExpression whiteSpace(QStringLiteral("\\s")); + static const QRegularExpression whiteSpace("\\s"_L1); Q_ASSERT(whiteSpace.isValid()); if (!funcName.startsWith(u"operator ") && funcName.contains(whiteSpace)) { return QString::fromLatin1("Error in <%1> tag signature attribute '%2'.\n" @@ -1247,7 +1243,7 @@ bool TypeSystemParser::checkRootElement() { for (auto i = m_contextStack.size() - 1; i >= 0; --i) { auto e = m_contextStack.at(i)->entry; - if (!e.isNull() && e->isTypeSystem()) + if (e && e->isTypeSystem()) return true; } m_error = msgNoRootTypeSystemEntry(); @@ -1285,7 +1281,7 @@ bool TypeSystemParser::applyCommonAttributes(const ConditionalStreamReader &read } else if (name == u"view-on") { const QString name = attributes->takeAt(i).value().toString(); TypeEntryPtr views = findViewedType(name); - if (views.isNull()) { + if (!views) { m_error = msgCannotFindView(name, type->name()); return false; } @@ -1302,10 +1298,10 @@ CustomTypeEntryPtr TypeSystemParser::parseCustomTypeEntry(const ConditionalStrea { if (!checkRootElement()) return nullptr; - CustomTypeEntryPtr result(new CustomTypeEntry(name, since, m_contextStack.top()->entry)); + auto result = std::make_shared<CustomTypeEntry>(name, since, m_contextStack.top()->entry); for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == checkFunctionAttribute()) + if (name == checkFunctionAttribute) result->setCheckFunction(attributes->takeAt(i).value().toString()); } return result; @@ -1320,30 +1316,30 @@ FlagsTypeEntryPtr { if (!checkRootElement()) return nullptr; - FlagsTypeEntryPtr ftype(new FlagsTypeEntry(u"QFlags<"_s + enumEntry->name() + u'>', - since, - typeSystemTypeEntry(currentParentTypeEntry()))); + auto ftype = std::make_shared<FlagsTypeEntry>(u"QFlags<"_s + enumEntry->name() + u'>', + since, + typeSystemTypeEntry(currentParentTypeEntry())); ftype->setOriginator(enumEntry); ftype->setTargetLangPackage(enumEntry->targetLangPackage()); // Try toenumEntry get the guess the qualified flag name - if (!flagName.contains(colonColon())) { + if (!flagName.contains(u"::"_s)) { auto eq = enumEntry->qualifier(); if (!eq.isEmpty()) - flagName.prepend(eq + colonColon()); + flagName.prepend(eq + u"::"_s); } ftype->setOriginalName(flagName); if (!applyCommonAttributes(reader, ftype, attributes)) return nullptr; - QStringList lst = flagName.split(colonColon()); + QStringList lst = flagName.split(u"::"_s); const QString name = lst.takeLast(); const QString targetLangFlagName = lst.join(u'.'); const QString &targetLangQualifier = enumEntry->targetLangQualifier(); if (targetLangFlagName != targetLangQualifier) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("enum %1 and flags %2 (%3) differ in qualifiers") - .arg(targetLangQualifier, lst.value(0), targetLangFlagName); + qCWarning(lcShiboken, "enum %s and flags %s (%s) differ in qualifiers", + qPrintable(targetLangQualifier), qPrintable(lst.value(0)), + qPrintable(targetLangFlagName)); } ftype->setFlagsName(name); @@ -1423,8 +1419,9 @@ SmartPointerTypeEntryPtr return nullptr; } - SmartPointerTypeEntryPtr type(new SmartPointerTypeEntry(name, getter, smartPointerType, - refCountMethodName, since, currentParentTypeEntry())); + auto type = std::make_shared<SmartPointerTypeEntry>(name, getter, smartPointerType, + refCountMethodName, since, + currentParentTypeEntry()); if (!applyCommonAttributes(reader, type, attributes)) return nullptr; applyComplexTypeAttributes(reader, type, attributes); @@ -1442,22 +1439,22 @@ PrimitiveTypeEntryPtr { if (!checkRootElement()) return nullptr; - PrimitiveTypeEntryPtr type (new PrimitiveTypeEntry(name, since, currentParentTypeEntry())); + auto type = std::make_shared<PrimitiveTypeEntry>(name, since, currentParentTypeEntry()); QString targetLangApiName; if (!applyCommonAttributes(reader, type, attributes)) return nullptr; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == targetLangNameAttribute()) { + if (name == targetLangNameAttribute) { type->setTargetLangName(attributes->takeAt(i).value().toString()); } else if (name == u"target-lang-api-name") { targetLangApiName = attributes->takeAt(i).value().toString(); - } else if (name == preferredConversionAttribute()) { + } else if (name == preferredConversionAttribute) { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedAttributeWarning(reader, name))); - } else if (name == preferredTargetLangTypeAttribute()) { + } else if (name == preferredTargetLangTypeAttribute) { const bool v = convertBoolean(attributes->takeAt(i).value(), - preferredTargetLangTypeAttribute(), true); + preferredTargetLangTypeAttribute, true); type->setPreferredTargetLangType(v); } else if (name == u"default-constructor") { type->setDefaultConstructor(attributes->takeAt(i).value().toString()); @@ -1466,27 +1463,40 @@ PrimitiveTypeEntryPtr if (!targetLangApiName.isEmpty()) { auto e = m_context->db->findType(targetLangApiName); - if (e.isNull() || !e->isCustom()) { + if (!e || !e->isCustom()) { m_error = msgInvalidTargetLanguageApiName(targetLangApiName); return nullptr; } - type->setTargetLangApiType(qSharedPointerCast<CustomTypeEntry>(e)); + type->setTargetLangApiType(std::static_pointer_cast<CustomTypeEntry>(e)); } type->setTargetLangPackage(m_defaultPackage); return type; } // "int:QList_int;QString:QList_QString" -static bool parseOpaqueContainers(QStringView s, ContainerTypeEntryPtr cte) +bool TypeSystemParser::parseOpaqueContainers(QStringView s, OpaqueContainers *result) { const auto entries = s.split(u';'); for (const auto &entry : entries) { const auto values = entry.split(u':'); - if (values.size() != 2) - return false; - QString instantiation = values.at(0).trimmed().toString(); - QString name = values.at(1).trimmed().toString(); - cte->addOpaqueContainer({instantiation, name}); + if (values.size() != 2) { + m_error = u"Error parsing the opaque container attribute: \""_s + + s.toString() + u"\"."_s; + return false; + } + OpaqueContainer oc; + oc.name = values.at(1).trimmed().toString(); + const auto instantiations = values.at(0).split(u',', Qt::SkipEmptyParts); + for (const auto &instantiationV : instantiations) { + QString instantiation = instantiationV.trimmed().toString(); + // Fix to match AbstractMetaType::signature() which is used for matching + // "Foo*" -> "Foo *" + const auto asteriskPos = instantiation.indexOf(u'*'); + if (asteriskPos > 0 && !instantiation.at(asteriskPos - 1).isSpace()) + instantiation.insert(asteriskPos, u' '); + oc.instantiations.append(instantiation); + } + result->append(oc); } return true; } @@ -1510,27 +1520,48 @@ ContainerTypeEntryPtr return nullptr; } attributes->removeAt(typeIndex); - ContainerTypeEntryPtr type(new ContainerTypeEntry(name, containerTypeOpt.value(), - since, currentParentTypeEntry())); + auto type = std::make_shared<ContainerTypeEntry>(name, containerTypeOpt.value(), + since, currentParentTypeEntry()); if (!applyCommonAttributes(reader, type, attributes)) return nullptr; applyComplexTypeAttributes(reader, type, attributes); for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == u"opaque-containers") { + if (name == opaqueContainerAttribute) { const auto attribute = attributes->takeAt(i); - if (!parseOpaqueContainers(attribute.value(), type)) { - m_error = u"Error parsing the opaque container attribute: \""_s - + attribute.value().toString() + u"\"."_s; + OpaqueContainers oc; + if (!parseOpaqueContainers(attribute.value(), &oc)) return nullptr; - } + type->appendOpaqueContainers(oc); } } return type; } +bool TypeSystemParser::parseOpaqueContainerElement(QXmlStreamAttributes *attributes) +{ + QString containerName; + OpaqueContainers oc; + for (auto i = attributes->size() - 1; i >= 0; --i) { + const auto name = attributes->at(i).qualifiedName(); + if (name == nameAttribute) { + containerName = attributes->takeAt(i).value().toString(); + } else if (name == opaqueContainerAttribute) { + const auto attribute = attributes->takeAt(i); + if (!parseOpaqueContainers(attribute.value(), &oc)) + return false; + } + } + if (containerName.isEmpty()) { + m_error = msgMissingAttribute(nameAttribute); + return false; + } + m_context->opaqueContainerHash[containerName].append(oc); + return true; +} + EnumTypeEntryPtr TypeSystemParser::parseEnumTypeEntry(const ConditionalStreamReader &reader, const QString &name, const QVersionNumber &since, @@ -1538,7 +1569,7 @@ EnumTypeEntryPtr { if (!checkRootElement()) return nullptr; - EnumTypeEntryPtr entry(new EnumTypeEntry(name, since, currentParentTypeEntry())); + auto entry = std::make_shared<EnumTypeEntry>(name, since, currentParentTypeEntry()); applyCommonAttributes(reader, entry, attributes); entry->setTargetLangPackage(m_defaultPackage); @@ -1551,10 +1582,12 @@ EnumTypeEntryPtr } else if (name == u"lower-bound") { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedAttributeWarning(reader, name))); - } else if (name == forceIntegerAttribute()) { + } else if (name == docFileAttribute) { + entry->setDocFile(attributes->takeAt(i).value().toString()); + } else if (name == forceIntegerAttribute) { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedAttributeWarning(reader, name))); - } else if (name == pythonEnumTypeAttribute()) { + } else if (name == pythonEnumTypeAttribute) { const auto attribute = attributes->takeAt(i); const auto typeOpt = pythonEnumTypeFromAttribute(attribute.value()); if (typeOpt.has_value()) { @@ -1563,12 +1596,12 @@ EnumTypeEntryPtr qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == cppEnumTypeAttribute()) { + } else if (name == cppEnumTypeAttribute) { entry->setCppType(attributes->takeAt(i).value().toString()); - } else if (name == extensibleAttribute()) { + } else if (name == extensibleAttribute) { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedAttributeWarning(reader, name))); - } else if (name == flagsAttribute()) { + } else if (name == flagsAttribute) { flagNames = attributes->takeAt(i).value().toString(); } } @@ -1590,7 +1623,7 @@ NamespaceTypeEntryPtr { if (!checkRootElement()) return nullptr; - NamespaceTypeEntryPtr result(new NamespaceTypeEntry(name, since, currentParentTypeEntry())); + auto result = std::make_shared<NamespaceTypeEntry>(name, since, currentParentTypeEntry()); auto visibility = TypeSystem::Visibility::Unspecified; applyCommonAttributes(reader, result, attributes); for (auto i = attributes->size() - 1; i >= 0; --i) { @@ -1616,7 +1649,7 @@ NamespaceTypeEntryPtr } result->setExtends(*extendsIt); attributes->removeAt(i); - } else if (attributeName == visibleAttribute()) { + } else if (attributeName == visibleAttribute) { const auto attribute = attributes->takeAt(i); const auto visibilityOpt = visibilityFromAttribute(attribute.value()); if (!visibilityOpt.has_value()) { @@ -1624,11 +1657,12 @@ NamespaceTypeEntryPtr return nullptr; } visibility = visibilityOpt.value(); - } else if (attributeName == generateAttribute()) { - if (!convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true)) + } else if (attributeName == generateAttribute) { + if (!convertBoolean(attributes->takeAt(i).value(), generateAttribute, true)) visibility = TypeSystem::Visibility::Invisible; - } else if (attributeName == generateUsingAttribute()) { - result->setGenerateUsing(convertBoolean(attributes->takeAt(i).value(), generateUsingAttribute(), true)); + } else if (attributeName == generateUsingAttribute) { + result->setGenerateUsing(convertBoolean(attributes->takeAt(i).value(), + generateUsingAttribute, true)); } } @@ -1652,7 +1686,7 @@ ValueTypeEntryPtr { if (!checkRootElement()) return nullptr; - ValueTypeEntryPtr typeEntry(new ValueTypeEntry(name, since, currentParentTypeEntry())); + auto typeEntry = std::make_shared<ValueTypeEntry>(name, since, currentParentTypeEntry()); if (!applyCommonAttributes(reader, typeEntry, attributes)) return nullptr; applyComplexTypeAttributes(reader, typeEntry, attributes); @@ -1671,45 +1705,51 @@ FunctionTypeEntryPtr if (!checkRootElement()) return nullptr; - QString signature; - TypeSystem::SnakeCase snakeCase = TypeSystem::SnakeCase::Disabled; + FunctionModification mod; + const auto oldAttributesSize = attributes->size(); + if (!parseModifyFunctionAttributes(attributes, &mod)) + return nullptr; + const bool hasModification = attributes->size() < oldAttributesSize; + QString originalSignature; + QString docFile; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == signatureAttribute()) { - signature = TypeDatabase::normalizedSignature(attributes->takeAt(i).value().toString()); - } else if (name == snakeCaseAttribute()) { - const auto attribute = attributes->takeAt(i); - const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value()); - if (!snakeCaseOpt.has_value()) { - m_error = msgInvalidAttributeValue(attribute); - return nullptr; - } - snakeCase = snakeCaseOpt.value(); - } + if (name == signatureAttribute) + originalSignature = attributes->takeAt(i).value().toString().simplified(); + else if (name == docFileAttribute) + docFile = attributes->takeAt(i).value().toString(); } + const QString signature = TypeDatabase::normalizedSignature(originalSignature); if (signature.isEmpty()) { - m_error = msgMissingAttribute(signatureAttribute()); + m_error = msgMissingAttribute(signatureAttribute); return nullptr; } + if (hasModification) { + mod.setOriginalSignature(originalSignature); + mod.setSignature(signature); + m_contextStack.top()->functionMods << mod; + } + TypeEntryPtr existingType = m_context->db->findType(name); - if (existingType.isNull()) { - FunctionTypeEntryPtr result(new FunctionTypeEntry(name, signature, since, currentParentTypeEntry())); - result->setSnakeCase(snakeCase); + if (!existingType) { + auto result = std::make_shared<FunctionTypeEntry>(name, signature, since, + currentParentTypeEntry()); + result->setTargetLangPackage(m_defaultPackage); + result->setDocFile(docFile); applyCommonAttributes(reader, result, attributes); return result; } if (existingType->type() != TypeEntry::FunctionType) { - m_error = QStringLiteral("%1 expected to be a function, but isn't! Maybe it was already declared as a class or something else.") - .arg(name); + m_error = name + " expected to be a function, but isn't! Maybe it was already declared as a class or something else."_L1; return nullptr; } - auto result = qSharedPointerCast<FunctionTypeEntry>(existingType); + auto result = std::static_pointer_cast<FunctionTypeEntry>(existingType); result->addSignature(signature); return result; } @@ -1727,13 +1767,14 @@ TypedefEntryPtr m_error = u"typedef entries must be nested in namespaces or type system."_s; return nullptr; } - const auto sourceIndex = indexOfAttribute(*attributes, sourceAttribute()); + const auto sourceIndex = indexOfAttribute(*attributes, sourceAttribute); if (sourceIndex == -1) { - m_error = msgMissingAttribute(sourceAttribute()); + m_error = msgMissingAttribute(sourceAttribute); return nullptr; } const QString sourceType = attributes->takeAt(sourceIndex).value().toString(); - TypedefEntryPtr result(new TypedefEntry(name, sourceType, since, currentParentTypeEntry())); + auto result = std::make_shared<TypedefEntry>(name, sourceType, since, + currentParentTypeEntry()); if (!applyCommonAttributes(reader, result, attributes)) return nullptr; applyComplexTypeAttributes(reader, result, attributes); @@ -1752,34 +1793,38 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader QString package = m_defaultPackage; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == streamAttribute()) { - ctype->setStream(convertBoolean(attributes->takeAt(i).value(), streamAttribute(), false)); - } else if (name == privateAttribute()) { + if (name == streamAttribute) { + ctype->setStream(convertBoolean(attributes->takeAt(i).value(), streamAttribute, false)); + } else if (name == privateAttribute) { ctype->setPrivate(convertBoolean(attributes->takeAt(i).value(), - privateAttribute(), false)); - } else if (name == generateAttribute()) { - generate = convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true); - } else if (name ==packageAttribute()) { + privateAttribute, false)); + } else if (name == generateAttribute) { + generate = convertBoolean(attributes->takeAt(i).value(), generateAttribute, true); + } else if (name ==packageAttribute) { package = attributes->takeAt(i).value().toString(); - } else if (name == defaultSuperclassAttribute()) { + } else if (name == defaultSuperclassAttribute) { ctype->setDefaultSuperclass(attributes->takeAt(i).value().toString()); - } else if (name == genericClassAttribute()) { + } else if (name == genericClassAttribute) { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedAttributeWarning(reader, name))); - const bool v = convertBoolean(attributes->takeAt(i).value(), genericClassAttribute(), false); + const bool v = convertBoolean(attributes->takeAt(i).value(), + genericClassAttribute, false); ctype->setGenericClass(v); - } else if (name == targetLangNameAttribute()) { + } else if (name == targetLangNameAttribute) { ctype->setTargetLangName(attributes->takeAt(i).value().toString()); - } else if (name == u"polymorphic-base") { - ctype->setPolymorphicIdValue(attributes->takeAt(i).value().toString()); + } else if (name == polymorphicBaseAttribute) { + const bool v = convertBoolean(attributes->takeAt(i).value(), + polymorphicBaseAttribute, false); + ctype->setIsPolymorphicBase(v); } else if (name == u"polymorphic-name-function") { ctype->setPolymorphicNameFunction(attributes->takeAt(i).value().toString()); } else if (name == u"polymorphic-id-expression") { ctype->setPolymorphicIdValue(attributes->takeAt(i).value().toString()); - } else if (name == copyableAttribute()) { - const bool v = convertBoolean(attributes->takeAt(i).value(), copyableAttribute(), false); + } else if (name == copyableAttribute) { + const bool v = convertBoolean(attributes->takeAt(i).value(), + copyableAttribute, false); ctype->setCopyable(v ? ComplexTypeEntry::CopyableSet : ComplexTypeEntry::NonCopyableSet); - } else if (name == exceptionHandlingAttribute()) { + } else if (name == exceptionHandlingAttribute) { const auto attribute = attributes->takeAt(i); const auto exceptionOpt = exceptionHandlingFromAttribute(attribute.value()); if (exceptionOpt.has_value()) { @@ -1788,7 +1833,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == allowThreadAttribute()) { + } else if (name == allowThreadAttribute) { const auto attribute = attributes->takeAt(i); const auto allowThreadOpt = allowThreadFromAttribute(attribute.value()); if (allowThreadOpt.has_value()) { @@ -1802,19 +1847,25 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader qPrintable(msgUnimplementedAttributeWarning(reader, name))); } else if (name == u"hash-function") { ctype->setHashFunction(attributes->takeAt(i).value().toString()); - } else if (name == forceAbstractAttribute()) { - if (convertBoolean(attributes->takeAt(i).value(), forceAbstractAttribute(), false)) + } else if (name == forceAbstractAttribute) { + if (convertBoolean(attributes->takeAt(i).value(), forceAbstractAttribute, false)) ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::ForceAbstract); - } else if (name == deprecatedAttribute()) { - if (convertBoolean(attributes->takeAt(i).value(), deprecatedAttribute(), false)) + } else if (name == deprecatedAttribute) { + if (convertBoolean(attributes->takeAt(i).value(), deprecatedAttribute, false)) ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::Deprecated); - } else if (name == disableWrapperAttribute()) { - if (convertBoolean(attributes->takeAt(i).value(), disableWrapperAttribute(), false)) + } else if (name == disableWrapperAttribute) { + if (convertBoolean(attributes->takeAt(i).value(), disableWrapperAttribute, false)) ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::DisableWrapper); - } else if (name == deleteInMainThreadAttribute()) { - if (convertBoolean(attributes->takeAt(i).value(), deleteInMainThreadAttribute(), false)) + } else if (name == deleteInMainThreadAttribute) { + if (convertBoolean(attributes->takeAt(i).value(), deleteInMainThreadAttribute, false)) ctype->setDeleteInMainThread(true); - } else if (name == generateFunctionsAttribute()) { + } else if (name == qtMetaObjectFunctionsAttribute) { + if (!convertBoolean(attributes->takeAt(i).value(), + qtMetaObjectFunctionsAttribute, true)) { + ctype->setTypeFlags(ctype->typeFlags() + | ComplexTypeEntry::DisableQtMetaObjectFunctions); + } + } else if (name == generateFunctionsAttribute) { const auto names = attributes->takeAt(i).value(); const auto nameList = names.split(u';', Qt::SkipEmptyParts); QSet<QString> nameSet; @@ -1823,7 +1874,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader ctype->setGenerateFunctions(nameSet); } else if (name == u"target-type") { ctype->setTargetType(attributes->takeAt(i).value().toString()); - } else if (name == snakeCaseAttribute()) { + } else if (name == snakeCaseAttribute) { const auto attribute = attributes->takeAt(i); const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value()); if (snakeCaseOpt.has_value()) { @@ -1832,7 +1883,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == isNullAttribute()) { + } else if (name == isNullAttribute) { const auto attribute = attributes->takeAt(i); const auto boolCastOpt = boolCastFromAttribute(attribute.value()); if (boolCastOpt.has_value()) { @@ -1841,7 +1892,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == operatorBoolAttribute()) { + } else if (name == operatorBoolAttribute) { const auto attribute = attributes->takeAt(i); const auto boolCastOpt = boolCastFromAttribute(attribute.value()); if (boolCastOpt.has_value()) { @@ -1850,7 +1901,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == qtMetaTypeAttribute()) { + } else if (name == qtMetaTypeAttribute) { const auto attribute = attributes->takeAt(i); const auto qtMetaTypeOpt = qtMetaTypeFromAttribute(attribute.value()); if (qtMetaTypeOpt.has_value()) { @@ -1859,9 +1910,9 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == parentManagementAttribute()) { + } else if (name == parentManagementAttribute) { const auto attribute = attributes->takeAt(i); - if (convertBoolean(attribute.value(), parentManagementAttribute(), false)) + if (convertBoolean(attribute.value(), parentManagementAttribute, false)) ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::ParentManagement); ComplexTypeEntry::setParentManagementEnabled(true); } @@ -1882,6 +1933,32 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader ctype->setCodeGeneration(TypeEntry::GenerationDisabled); } +bool TypeSystemParser::parseConfiguration(StackElement topElement, + QXmlStreamAttributes *attributes) +{ + if (!isComplexTypeEntry(topElement) + && topElement != StackElement::EnumTypeEntry) { + m_error = u"<configuration> must be nested into a complex or enum type entry."_s; + return false; + } + QString condition; + for (auto i = attributes->size() - 1; i >= 0; --i) { + const auto name = attributes->at(i).qualifiedName(); + if (name == u"condition") { + condition = attributes->takeAt(i).value().toString(); + } + } + if (condition.isEmpty()) { + m_error = u"<configuration> requires a \"condition\" attribute."_s; + return false; + } + const auto topEntry = m_contextStack.top()->entry; + const auto configurableEntry = std::dynamic_pointer_cast<ConfigurableTypeEntry>(topEntry); + Q_ASSERT(configurableEntry); + configurableEntry->setConfigCondition(condition); + return true; +} + bool TypeSystemParser::parseRenameFunction(const ConditionalStreamReader &, QString *name, QXmlStreamAttributes *attributes) { @@ -1889,16 +1966,16 @@ bool TypeSystemParser::parseRenameFunction(const ConditionalStreamReader &, QString rename; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == signatureAttribute()) { + if (name == signatureAttribute) { // Do not remove as it is needed for the type entry later on - signature = attributes->at(i).value().toString(); - } else if (name == renameAttribute()) { + signature = attributes->at(i).value().toString().simplified(); + } else if (name == renameAttribute) { rename = attributes->takeAt(i).value().toString(); } } if (signature.isEmpty()) { - m_error = msgMissingAttribute(signatureAttribute()); + m_error = msgMissingAttribute(signatureAttribute); return false; } @@ -1954,7 +2031,7 @@ bool TypeSystemParser::parseInjectDocumentation(const ConditionalStreamReader &, return false; } mode = modeOpt.value(); - } else if (name == formatAttribute()) { + } else if (name == formatAttribute) { const auto attribute = attributes->takeAt(i); const auto langOpt = languageFromAttribute(attribute.value()); if (!langOpt.has_value()) { @@ -1968,6 +2045,12 @@ bool TypeSystemParser::parseInjectDocumentation(const ConditionalStreamReader &, QString signature = isTypeEntry(topElement) ? QString() : m_currentSignature; DocModification mod(mode, signature); mod.setFormat(lang); + if (hasFileSnippetAttributes(attributes)) { + const auto snippetOptional = readFileSnippet(attributes); + if (!snippetOptional.has_value()) + return false; + mod.setCode(snippetOptional.value().content); + } auto &top = m_contextStack.top(); if (isAddFunction) top->addedFunctions.last()->addDocModification(mod); @@ -1989,9 +2072,9 @@ bool TypeSystemParser::parseModifyDocumentation(const ConditionalStreamReader &, return false; } - const auto xpathIndex = indexOfAttribute(*attributes, xPathAttribute()); + const auto xpathIndex = indexOfAttribute(*attributes, xPathAttribute); if (xpathIndex == -1) { - m_error = msgMissingAttribute(xPathAttribute()); + m_error = msgMissingAttribute(xPathAttribute); return false; } @@ -2008,14 +2091,17 @@ TypeSystemTypeEntryPtr TypeSystemParser::parseRootElement(const ConditionalStrea QXmlStreamAttributes *attributes) { TypeSystem::SnakeCase snakeCase = TypeSystem::SnakeCase::Unspecified; + QString subModuleOf; + QString namespaceBegin; + QString namespaceEnd; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == packageAttribute()) { + if (name == packageAttribute) { m_defaultPackage = attributes->takeAt(i).value().toString(); - } else if (name == defaultSuperclassAttribute()) { + } else if (name == defaultSuperclassAttribute) { m_defaultSuperclass = attributes->takeAt(i).value().toString(); - } else if (name == exceptionHandlingAttribute()) { + } else if (name == exceptionHandlingAttribute) { const auto attribute = attributes->takeAt(i); const auto exceptionOpt = exceptionHandlingFromAttribute(attribute.value()); if (exceptionOpt.has_value()) { @@ -2024,7 +2110,7 @@ TypeSystemTypeEntryPtr TypeSystemParser::parseRootElement(const ConditionalStrea qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == allowThreadAttribute()) { + } else if (name == allowThreadAttribute) { const auto attribute = attributes->takeAt(i); const auto allowThreadOpt = allowThreadFromAttribute(attribute.value()); if (allowThreadOpt.has_value()) { @@ -2033,7 +2119,7 @@ TypeSystemTypeEntryPtr TypeSystemParser::parseRootElement(const ConditionalStrea qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == snakeCaseAttribute()) { + } else if (name == snakeCaseAttribute) { const auto attribute = attributes->takeAt(i); const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value()); if (snakeCaseOpt.has_value()) { @@ -2042,25 +2128,36 @@ TypeSystemTypeEntryPtr TypeSystemParser::parseRootElement(const ConditionalStrea qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } + } else if (name == subModuleOfAttribute) { + subModuleOf = attributes->takeAt(i).value().toString(); + } else if (name == "namespace-begin"_L1) { + namespaceBegin = attributes->takeAt(i).value().toString(); + } else if (name == "namespace-end"_L1) { + namespaceEnd = attributes->takeAt(i).value().toString(); } } if (m_defaultPackage.isEmpty()) { // Extending default, see addBuiltInContainerTypes() - auto moduleEntry = qSharedPointerConstCast<TypeSystemTypeEntry>(m_context->db->defaultTypeSystemType()); - Q_ASSERT(!moduleEntry.isNull()); + auto moduleEntry = std::const_pointer_cast<TypeSystemTypeEntry>(m_context->db->defaultTypeSystemType()); + Q_ASSERT(moduleEntry); m_defaultPackage = moduleEntry->name(); return moduleEntry; } auto moduleEntry = - qSharedPointerConstCast<TypeSystemTypeEntry>(m_context->db->findTypeSystemType(m_defaultPackage)); - const bool add = moduleEntry.isNull(); + std::const_pointer_cast<TypeSystemTypeEntry>(m_context->db->findTypeSystemType(m_defaultPackage)); + const bool add = !moduleEntry; if (add) { moduleEntry.reset(new TypeSystemTypeEntry(m_defaultPackage, since, currentParentTypeEntry())); + moduleEntry->setSubModule(subModuleOf); } moduleEntry->setCodeGeneration(m_generate); moduleEntry->setSnakeCase(snakeCase); + if (!namespaceBegin.isEmpty()) + moduleEntry->setNamespaceBegin(namespaceBegin); + if (!namespaceEnd.isEmpty()) + moduleEntry->setNamespaceEnd(namespaceEnd); if ((m_generate == TypeEntry::GenerateForSubclass || m_generate == TypeEntry::GenerateNothing) && !m_defaultPackage.isEmpty()) @@ -2078,10 +2175,10 @@ bool TypeSystemParser::loadTypesystem(const ConditionalStreamReader &, bool generateChild = true; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == nameAttribute()) + if (name == nameAttribute) typeSystemName = attributes->takeAt(i).value().toString(); - else if (name == generateAttribute()) - generateChild = convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true); + else if (name == generateAttribute) + generateChild = convertBoolean(attributes->takeAt(i).value(), generateAttribute, true); } if (typeSystemName.isEmpty()) { m_error = u"No typesystem name specified"_s; @@ -2098,13 +2195,13 @@ bool TypeSystemParser::loadTypesystem(const ConditionalStreamReader &, bool TypeSystemParser::parseRejectEnumValue(const ConditionalStreamReader &, QXmlStreamAttributes *attributes) { - if (m_currentEnum.isNull()) { + if (!m_currentEnum) { m_error = u"<reject-enum-value> node must be used inside a <enum-type> node"_s; return false; } - const auto nameIndex = indexOfAttribute(*attributes, nameAttribute()); + const auto nameIndex = indexOfAttribute(*attributes, nameAttribute); if (nameIndex == -1) { - m_error = msgMissingAttribute(nameAttribute()); + m_error = msgMissingAttribute(nameAttribute); return false; } m_currentEnum->addEnumValueRejection(attributes->takeAt(nameIndex).value().toString()); @@ -2119,7 +2216,7 @@ bool TypeSystemParser::parseReplaceArgumentType(const ConditionalStreamReader &, m_error = u"Type replacement can only be specified for argument modifications"_s; return false; } - const auto modifiedTypeIndex = indexOfAttribute(*attributes, modifiedTypeAttribute()); + const auto modifiedTypeIndex = indexOfAttribute(*attributes, modifiedTypeAttribute); if (modifiedTypeIndex == -1) { m_error = u"Type replacement requires 'modified-type' attribute"_s; return false; @@ -2147,7 +2244,7 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &, TypeSystem::Language lang = TypeSystem::NativeCode; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == classAttribute()) { + if (name == classAttribute) { const auto languageAttribute = attributes->takeAt(i); const auto langOpt = languageFromAttribute(languageAttribute.value()); if (!langOpt.has_value()) { @@ -2157,7 +2254,7 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &, lang = langOpt.value(); } else if (name == u"file") { sourceFile = attributes->takeAt(i).value().toString(); - } else if (name == snippetAttribute()) { + } else if (name == snippetAttribute) { snippetLabel = attributes->takeAt(i).value().toString(); } } @@ -2172,7 +2269,7 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &, ValueTypeEntryPtr valueTypeEntry; if (top->entry->isValue()) { - valueTypeEntry = qSharedPointerCast<ValueTypeEntry>(top->entry); + valueTypeEntry = std::static_pointer_cast<ValueTypeEntry>(top->entry); if (valueTypeEntry->hasTargetConversionRule() || valueTypeEntry->hasCustomConversion()) { m_error = u"Types can have only one conversion rule"_s; return false; @@ -2204,13 +2301,13 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &, return true; } - CustomConversionPtr customConversion(new CustomConversion(top->entry)); + auto customConversion = std::make_shared<CustomConversion>(top->entry); if (top->entry->isPrimitive()) - qSharedPointerCast<PrimitiveTypeEntry>(top->entry)->setCustomConversion(customConversion); + std::static_pointer_cast<PrimitiveTypeEntry>(top->entry)->setCustomConversion(customConversion); else if (top->entry->isContainer()) - qSharedPointerCast<ContainerTypeEntry>(top->entry)->setCustomConversion(customConversion); + std::static_pointer_cast<ContainerTypeEntry>(top->entry)->setCustomConversion(customConversion); else if (top->entry->isValue()) - qSharedPointerCast<ValueTypeEntry>(top->entry)->setCustomConversion(customConversion); + std::static_pointer_cast<ValueTypeEntry>(top->entry)->setCustomConversion(customConversion); customConversionsForReview.append(customConversion); return true; } @@ -2224,7 +2321,7 @@ bool TypeSystemParser::parseNativeToTarget(const ConditionalStreamReader &, return false; } CodeSnip snip; - if (!readFileSnippet(attributes, &snip)) + if (!readCodeSnippet(attributes, &snip)) return false; m_contextStack.top()->conversionCodeSnips.append(snip); return true; @@ -2241,7 +2338,7 @@ bool TypeSystemParser::parseAddConversion(const ConditionalStreamReader &, QString sourceTypeName; QString typeCheck; CodeSnip snip; - if (!readFileSnippet(attributes, &snip)) + if (!readCodeSnippet(attributes, &snip)) return false; const auto &top = m_contextStack.top(); @@ -2263,7 +2360,7 @@ bool TypeSystemParser::parseAddConversion(const ConditionalStreamReader &, return false; } auto customConversion = CustomConversion::getCustomConversion(top->entry); - if (customConversion.isNull()) { + if (!customConversion) { m_error = msgMissingCustomConversion(top->entry); return false; } @@ -2276,7 +2373,7 @@ static bool parseIndex(const QString &index, int *result, QString *errorMessage) bool ok = false; *result = index.toInt(&ok); if (!ok) - *errorMessage = QStringLiteral("Cannot convert '%1' to integer").arg(index); + *errorMessage = QString::fromLatin1("Cannot convert '%1' to integer").arg(index); return ok; } @@ -2311,20 +2408,20 @@ bool TypeSystemParser::parseModifyArgument(const ConditionalStreamReader &, bool resetAfterUse = false; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == indexAttribute()) { + if (name == indexAttribute) { index = attributes->takeAt(i).value().toString(); - } else if (name == invalidateAfterUseAttribute()) { + } else if (name == invalidateAfterUseAttribute) { resetAfterUse = convertBoolean(attributes->takeAt(i).value(), - invalidateAfterUseAttribute(), false); - } else if (name == renameAttribute()) { + invalidateAfterUseAttribute, false); + } else if (name == renameAttribute) { renameTo = attributes->takeAt(i).value().toString(); - } else if (name == pyiTypeAttribute()) { + } else if (name == pyiTypeAttribute) { pyiType = attributes->takeAt(i).value().toString(); } } if (index.isEmpty()) { - m_error = msgMissingAttribute(indexAttribute()); + m_error = msgMissingAttribute(indexAttribute); return false; } @@ -2374,7 +2471,7 @@ bool TypeSystemParser::parseDefineOwnership(const ConditionalStreamReader &, std::optional<TypeSystem::Ownership> ownershipOpt; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == classAttribute()) { + if (name == classAttribute) { const auto classAttribute = attributes->takeAt(i); const auto langOpt = languageFromAttribute(classAttribute.value()); if (!langOpt.has_value() || langOpt.value() == TypeSystem::ShellCode) { @@ -2382,7 +2479,7 @@ bool TypeSystemParser::parseDefineOwnership(const ConditionalStreamReader &, return false; } lang = langOpt.value(); - } else if (name == ownershipAttribute()) { + } else if (name == ownershipAttribute) { const auto attribute = attributes->takeAt(i); ownershipOpt = ownershipFromFromAttribute(attribute.value()); if (!ownershipOpt.has_value()) { @@ -2393,7 +2490,7 @@ bool TypeSystemParser::parseDefineOwnership(const ConditionalStreamReader &, } if (!ownershipOpt.has_value()) { - m_error = QStringLiteral("unspecified ownership"); + m_error = "unspecified ownership"_L1; return false; } auto &lastArgMod = m_contextStack.top()->functionMods.last().argument_mods().last(); @@ -2420,9 +2517,9 @@ bool TypeSystemParser::parseRename(const ConditionalStreamReader &, return false; } - const auto toIndex = indexOfAttribute(*attributes, toAttribute()); + const auto toIndex = indexOfAttribute(*attributes, toAttribute); if (toIndex == -1) { - m_error = msgMissingAttribute(toAttribute()); + m_error = msgMissingAttribute(toAttribute); return false; } const QString renamed_to = attributes->takeAt(toIndex).value().toString(); @@ -2436,20 +2533,20 @@ bool TypeSystemParser::parseModifyField(const ConditionalStreamReader &, FieldModification fm; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == nameAttribute()) { + if (name == nameAttribute) { fm.setName(attributes->takeAt(i).value().toString()); - } else if (name == removeAttribute()) { + } else if (name == removeAttribute) { fm.setRemoved(convertRemovalAttribute(attributes->takeAt(i).value())); - } else if (name == opaqueContainerFieldAttribute()) { + } else if (name == opaqueContainerFieldAttribute) { fm.setOpaqueContainer(convertBoolean(attributes->takeAt(i).value(), - opaqueContainerFieldAttribute(), false)); - } else if (name == readAttribute()) { - fm.setReadable(convertBoolean(attributes->takeAt(i).value(), readAttribute(), true)); - } else if (name == writeAttribute()) { - fm.setWritable(convertBoolean(attributes->takeAt(i).value(), writeAttribute(), true)); - } else if (name == renameAttribute()) { + opaqueContainerFieldAttribute, false)); + } else if (name == readAttribute) { + fm.setReadable(convertBoolean(attributes->takeAt(i).value(), readAttribute, true)); + } else if (name == writeAttribute) { + fm.setWritable(convertBoolean(attributes->takeAt(i).value(), writeAttribute, true)); + } else if (name == renameAttribute) { fm.setRenamedToName(attributes->takeAt(i).value().toString()); - } else if (name == snakeCaseAttribute()) { + } else if (name == snakeCaseAttribute) { const auto attribute = attributes->takeAt(i); const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value()); if (snakeCaseOpt.has_value()) { @@ -2461,7 +2558,7 @@ bool TypeSystemParser::parseModifyField(const ConditionalStreamReader &, } } if (fm.name().isEmpty()) { - m_error = msgMissingAttribute(nameAttribute()); + m_error = msgMissingAttribute(nameAttribute); return false; } m_contextStack.top()->fieldMods << fm; @@ -2493,29 +2590,37 @@ bool TypeSystemParser::parseAddFunction(const ConditionalStreamReader &, ", was=%1").arg(tagFromElement(topElement)); return false; } + + FunctionModification mod; + if (!(t == StackElement::AddFunction + ? parseBasicModifyFunctionAttributes(attributes, &mod) + : parseModifyFunctionAttributes(attributes, &mod))) { + return false; + } + QString originalSignature; QString returnType; bool staticFunction = false; bool classMethod = false; + bool pythonOverride = false; QString access; - int overloadNumber = TypeSystem::OverloadNumberUnset; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == u"signature") { - originalSignature = attributes->takeAt(i).value().toString(); + if (name == signatureAttribute) { + originalSignature = attributes->takeAt(i).value().toString().simplified(); } else if (name == u"return-type") { returnType = attributes->takeAt(i).value().toString(); - } else if (name == staticAttribute()) { + } else if (name == staticAttribute) { staticFunction = convertBoolean(attributes->takeAt(i).value(), - staticAttribute(), false); - } else if (name == classmethodAttribute()) { + staticAttribute, false); + } else if (name == classmethodAttribute) { classMethod = convertBoolean(attributes->takeAt(i).value(), - classmethodAttribute(), false); - } else if (name == accessAttribute()) { + classmethodAttribute, false); + } else if (name == accessAttribute) { access = attributes->takeAt(i).value().toString(); - } else if (name == overloadNumberAttribute()) { - if (!parseOverloadNumber(attributes->takeAt(i), &overloadNumber, &m_error)) - return false; + } else if (name == pythonOverrideAttribute) { + pythonOverride = convertBoolean(attributes->takeAt(i).value(), + pythonOverrideAttribute, false); } } @@ -2532,13 +2637,15 @@ bool TypeSystemParser::parseAddFunction(const ConditionalStreamReader &, } AddedFunctionPtr func = AddedFunction::createAddedFunction(signature, returnType, &errorString); - if (func.isNull()) { + if (!func) { m_error = errorString; return false; } func->setStatic(staticFunction); func->setClassMethod(classMethod); + func->setPythonOverride(pythonOverride); + func->setTargetLangPackage(m_defaultPackage); // Create signature for matching modifications signature = TypeDatabase::normalizedSignature(originalSignature); @@ -2560,8 +2667,6 @@ bool TypeSystemParser::parseAddFunction(const ConditionalStreamReader &, m_contextStack.top()->addedFunctionModificationIndex = m_contextStack.top()->functionMods.size(); - FunctionModification mod; - mod.setOverloadNumber(overloadNumber); if (!mod.setSignature(m_currentSignature, &m_error)) return false; mod.setOriginalSignature(originalSignature); @@ -2582,7 +2687,7 @@ bool TypeSystemParser::parseAddPyMethodDef(const ConditionalStreamReader &, TypeSystemPyMethodDefEntry def; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == nameAttribute()) { + if (name == nameAttribute) { def.name = attributes->takeAt(i).value().toString(); } else if (name == u"doc") { def.doc = attributes->takeAt(i).value().toString(); @@ -2605,7 +2710,7 @@ bool TypeSystemParser::parseAddPyMethodDef(const ConditionalStreamReader &, m_error = u"add-pymethoddef requires at least a name and a function attribute"_s; return false; } - qSharedPointerCast<ComplexTypeEntry>(m_contextStack.top()->entry)->addPyMethodDef(def); + std::static_pointer_cast<ComplexTypeEntry>(m_contextStack.top()->entry)->addPyMethodDef(def); return true; } @@ -2621,7 +2726,7 @@ bool TypeSystemParser::parseProperty(const ConditionalStreamReader &, StackEleme TypeSystemProperty property; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == nameAttribute()) { + if (name == nameAttribute) { property.name = attributes->takeAt(i).value().toString(); } else if (name == u"get") { property.read = attributes->takeAt(i).value().toString(); @@ -2629,17 +2734,78 @@ bool TypeSystemParser::parseProperty(const ConditionalStreamReader &, StackEleme property.type = attributes->takeAt(i).value().toString(); } else if (name == u"set") { property.write = attributes->takeAt(i).value().toString(); - } else if (name == generateGetSetDefAttribute()) { + } else if (name == generateGetSetDefAttribute) { property.generateGetSetDef = convertBoolean(attributes->takeAt(i).value(), - generateGetSetDefAttribute(), false); + generateGetSetDefAttribute, false); } } if (!property.isValid()) { m_error = u"<property> element is missing required attibutes (name/type/get)."_s; return false; } - qSharedPointerCast<ComplexTypeEntry>(m_contextStack.top()->entry)->addProperty(property); + std::static_pointer_cast<ComplexTypeEntry>(m_contextStack.top()->entry)->addProperty(property); + return true; +} + +// Parse basic attributes applicable to <add-function>/<declare-function>/<function> +// and <modify-function> (all that is not done by injected code). +bool TypeSystemParser::parseBasicModifyFunctionAttributes(QXmlStreamAttributes *attributes, + FunctionModification *mod) +{ + for (auto i = attributes->size() - 1; i >= 0; --i) { + const auto name = attributes->at(i).qualifiedName(); + if (name == overloadNumberAttribute) { + int overloadNumber = TypeSystem::OverloadNumberUnset; + if (!parseOverloadNumber(attributes->takeAt(i), &overloadNumber, &m_error)) + return false; + mod->setOverloadNumber(overloadNumber); + } + } + return true; +} + +// Parse attributes applicable to <declare-function>/<function> +// and <modify-function>. +bool TypeSystemParser::parseModifyFunctionAttributes(QXmlStreamAttributes *attributes, + FunctionModification *mod) +{ + if (!parseBasicModifyFunctionAttributes(attributes, mod)) + return false; + + for (auto i = attributes->size() - 1; i >= 0; --i) { + const auto name = attributes->at(i).qualifiedName(); + if (name == allowThreadAttribute) { + const QXmlStreamAttribute attribute = attributes->takeAt(i); + const auto allowThreadOpt = allowThreadFromAttribute(attribute.value()); + if (!allowThreadOpt.has_value()) { + m_error = msgInvalidAttributeValue(attribute); + return false; + } + mod->setAllowThread(allowThreadOpt.value()); + } else if (name == exceptionHandlingAttribute) { + const auto attribute = attributes->takeAt(i); + const auto exceptionOpt = exceptionHandlingFromAttribute(attribute.value()); + if (!exceptionOpt.has_value()) { + m_error = msgInvalidAttributeValue(attribute); + return false; + } + mod->setExceptionHandling(exceptionOpt.value()); + } else if (name == snakeCaseAttribute) { + const auto attribute = attributes->takeAt(i); + const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value()); + if (!snakeCaseOpt.has_value()) { + m_error = msgInvalidAttributeValue(attribute); + return false; + } + mod->setSnakeCase(snakeCaseOpt.value()); + } else if (name == deprecatedAttribute) { + const bool deprecated = convertBoolean(attributes->takeAt(i).value(), + deprecatedAttribute, false); + mod->setModifierFlag(deprecated ? FunctionModification::Deprecated + : FunctionModification::Undeprecated); + } + } return true; } @@ -2657,61 +2823,24 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader } QString originalSignature; + FunctionModification mod; + if (!parseModifyFunctionAttributes(attributes, &mod)) + return false; + QString access; bool removed = false; QString rename; - bool deprecated = false; - bool isThread = false; - int overloadNumber = TypeSystem::OverloadNumberUnset; - TypeSystem::ExceptionHandling exceptionHandling = TypeSystem::ExceptionHandling::Unspecified; - TypeSystem::AllowThread allowThread = TypeSystem::AllowThread::Unspecified; - TypeSystem::SnakeCase snakeCase = TypeSystem::SnakeCase::Unspecified; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == u"signature") { - originalSignature = attributes->takeAt(i).value().toString(); - } else if (name == accessAttribute()) { + if (name == signatureAttribute) { + originalSignature = attributes->takeAt(i).value().toString().simplified(); + } else if (name == accessAttribute) { access = attributes->takeAt(i).value().toString(); - } else if (name == renameAttribute()) { + } else if (name == renameAttribute) { rename = attributes->takeAt(i).value().toString(); - } else if (name == removeAttribute()) { + } else if (name == removeAttribute) { removed = convertRemovalAttribute(attributes->takeAt(i).value()); - } else if (name == deprecatedAttribute()) { - deprecated = convertBoolean(attributes->takeAt(i).value(), - deprecatedAttribute(), false); - } else if (name == threadAttribute()) { - isThread = convertBoolean(attributes->takeAt(i).value(), - threadAttribute(), false); - } else if (name == allowThreadAttribute()) { - const QXmlStreamAttribute attribute = attributes->takeAt(i); - const auto allowThreadOpt = allowThreadFromAttribute(attribute.value()); - if (!allowThreadOpt.has_value()) { - m_error = msgInvalidAttributeValue(attribute); - return false; - } - allowThread = allowThreadOpt.value(); - } else if (name == exceptionHandlingAttribute()) { - const auto attribute = attributes->takeAt(i); - const auto exceptionOpt = exceptionHandlingFromAttribute(attribute.value()); - if (exceptionOpt.has_value()) { - exceptionHandling = exceptionOpt.value(); - } else { - qCWarning(lcShiboken, "%s", - qPrintable(msgInvalidAttributeValue(attribute))); - } - } else if (name == overloadNumberAttribute()) { - if (!parseOverloadNumber(attributes->takeAt(i), &overloadNumber, &m_error)) - return false; - } else if (name == snakeCaseAttribute()) { - const auto attribute = attributes->takeAt(i); - const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value()); - if (snakeCaseOpt.has_value()) { - snakeCase = snakeCaseOpt.value(); - } else { - qCWarning(lcShiboken, "%s", - qPrintable(msgInvalidAttributeValue(attribute))); - } - } else if (name == virtualSlotAttribute()) { + } else if (name == virtualSlotAttribute || name == threadAttribute) { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedAttributeWarning(reader, name))); } @@ -2720,7 +2849,7 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader // Child of global <function> const auto &top = m_contextStack.top(); if (originalSignature.isEmpty() && top->entry->isFunction()) { - auto f = qSharedPointerCast<const FunctionTypeEntry>(top->entry); + auto f = std::static_pointer_cast<const FunctionTypeEntry>(top->entry); originalSignature = f->signatures().value(0); } @@ -2736,13 +2865,9 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader return false; } - FunctionModification mod; if (!mod.setSignature(signature, &m_error)) return false; mod.setOriginalSignature(originalSignature); - mod.setExceptionHandling(exceptionHandling); - mod.setOverloadNumber(overloadNumber); - mod.setSnakeCase(snakeCase); m_currentSignature = signature; if (!access.isEmpty()) { @@ -2755,14 +2880,11 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader if (m == FunctionModification::NonFinal) { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedAttributeValueWarning(reader, - accessAttribute(), access))); + accessAttribute, access))); } mod.setModifierFlag(m); } - if (deprecated) - mod.setModifierFlag(FunctionModification::Deprecated); - mod.setRemoved(removed); if (!rename.isEmpty()) { @@ -2770,10 +2892,6 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader mod.setModifierFlag(FunctionModification::Rename); } - mod.setIsThread(isThread); - if (allowThread != TypeSystem::AllowThread::Unspecified) - mod.setAllowThread(allowThread); - top->functionMods << mod; return true; } @@ -2809,7 +2927,7 @@ bool TypeSystemParser::parseReferenceCount(const ConditionalStreamReader &reader ReferenceCount rc; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == actionAttribute()) { + if (name == actionAttribute) { const QXmlStreamAttribute attribute = attributes->takeAt(i); const auto actionOpt = referenceCountFromAttribute(attribute.value()); if (!actionOpt.has_value()) { @@ -2846,11 +2964,11 @@ bool TypeSystemParser::parseParentOwner(const ConditionalStreamReader &, ArgumentOwner ao; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == indexAttribute()) { + if (name == indexAttribute) { const QString index = attributes->takeAt(i).value().toString(); if (!parseArgumentIndex(index, &ao.index, &m_error)) return false; - } else if (name == actionAttribute()) { + } else if (name == actionAttribute) { const auto action = attributes->takeAt(i); const auto actionOpt = argumentOwnerActionFromAttribute(action.value()); if (!actionOpt.has_value()) { @@ -2864,46 +2982,62 @@ bool TypeSystemParser::parseParentOwner(const ConditionalStreamReader &, return true; } -bool TypeSystemParser::readFileSnippet(QXmlStreamAttributes *attributes, CodeSnip *snip) +std::optional<TypeSystemParser::Snippet> + TypeSystemParser::readFileSnippet(QXmlStreamAttributes *attributes) { - QString fileName; - QString snippetLabel; + Snippet result; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == u"file") { - fileName = attributes->takeAt(i).value().toString(); - } else if (name == snippetAttribute()) { - snippetLabel = attributes->takeAt(i).value().toString(); + if (name == fileAttribute) { + result.fileName = attributes->takeAt(i).value().toString(); + } else if (name == snippetAttribute) { + result.snippetLabel = attributes->takeAt(i).value().toString(); } } - if (fileName.isEmpty()) - return true; - const QString resolved = m_context->db->modifiedTypesystemFilepath(fileName, m_currentPath); + if (result.fileName.isEmpty()) { + m_error = "Snippet missing file name"_L1; + return std::nullopt; + } + const QString resolved = m_context->db->modifiedTypesystemFilepath(result.fileName, + m_currentPath); if (!QFile::exists(resolved)) { m_error = u"File for inject code not exist: "_s - + QDir::toNativeSeparators(fileName); - return false; + + QDir::toNativeSeparators(result.fileName); + return std::nullopt; } QFile codeFile(resolved); if (!codeFile.open(QIODevice::Text | QIODevice::ReadOnly)) { m_error = msgCannotOpenForReading(codeFile); - return false; + return std::nullopt; } - const auto codeOptional = extractSnippet(QString::fromUtf8(codeFile.readAll()), snippetLabel); + const auto contentOptional = extractSnippet(QString::fromUtf8(codeFile.readAll()), + result.snippetLabel); codeFile.close(); - if (!codeOptional.has_value()) { - m_error = msgCannotFindSnippet(resolved, snippetLabel); - return false; + if (!contentOptional.has_value()) { + m_error = msgCannotFindSnippet(resolved, result.snippetLabel); + return std::nullopt; } + result.content = contentOptional.value(); + return result; +} + +bool TypeSystemParser::readCodeSnippet(QXmlStreamAttributes *attributes, CodeSnip *snip) +{ + if (!hasFileSnippetAttributes(attributes)) + return true; // Expecting inline content. + const auto snippetOptional = readFileSnippet(attributes); + if (!snippetOptional.has_value()) + return false; + const auto snippet = snippetOptional.value(); - QString source = fileName; - if (!snippetLabel.isEmpty()) - source += u" ("_s + snippetLabel + u')'; + QString source = snippet.fileName; + if (!snippet.snippetLabel.isEmpty()) + source += " ("_L1 + snippet.snippetLabel + u')'; QString content; QTextStream str(&content); str << "// ========================================================================\n" "// START of custom code block [file: " - << source << "]\n" << codeOptional.value() + << source << "]\n" << snippet.content << "// END of custom code block [file: " << source << "]\n// ========================================================================\n"; snip->addCode(content); @@ -2925,11 +3059,11 @@ bool TypeSystemParser::parseInjectCode(const ConditionalStreamReader &, TypeSystem::CodeSnipPosition position = TypeSystem::CodeSnipPositionBeginning; TypeSystem::Language lang = TypeSystem::TargetLangCode; CodeSnip snip; - if (!readFileSnippet(attributes, &snip)) + if (!readCodeSnippet(attributes, &snip)) return false; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == classAttribute()) { + if (name == classAttribute) { const auto attribute = attributes->takeAt(i); const auto langOpt = languageFromAttribute(attribute.value()); if (!langOpt.has_value()) { @@ -2937,7 +3071,7 @@ bool TypeSystemParser::parseInjectCode(const ConditionalStreamReader &, return false; } lang = langOpt.value(); - } else if (name == positionAttribute()) { + } else if (name == positionAttribute) { const auto attribute = attributes->takeAt(i); const auto positionOpt = codeSnipPositionFromAttribute(attribute.value()); if (!positionOpt.has_value()) { @@ -2961,10 +3095,10 @@ bool TypeSystemParser::parseInjectCode(const ConditionalStreamReader &, } break; case StackElement::Root: - qSharedPointerCast<TypeSystemTypeEntry>(m_contextStack.top()->entry)->addCodeSnip(snip); + std::static_pointer_cast<TypeSystemTypeEntry>(m_contextStack.top()->entry)->addCodeSnip(snip); break; default: - qSharedPointerCast<ComplexTypeEntry>(m_contextStack.top()->entry)->addCodeSnip(snip); + std::static_pointer_cast<ComplexTypeEntry>(m_contextStack.top()->entry)->addCodeSnip(snip); break; } return true; @@ -2978,9 +3112,9 @@ bool TypeSystemParser::parseInclude(const ConditionalStreamReader &, Include::IncludeType location = Include::IncludePath; for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == fileNameAttribute()) { + if (name == fileNameAttribute) { fileName = attributes->takeAt(i).value().toString(); - } else if (name == locationAttribute()) { + } else if (name == locationAttribute) { const auto attribute = attributes->takeAt(i); const auto locationOpt = locationFromAttribute(attribute.value()); if (!locationOpt.has_value()) { @@ -3010,12 +3144,12 @@ bool TypeSystemParser::parseInclude(const ConditionalStreamReader &, bool TypeSystemParser::parseSystemInclude(const ConditionalStreamReader &, QXmlStreamAttributes *attributes) { - const auto index = indexOfAttribute(*attributes, fileNameAttribute()); + const auto index = indexOfAttribute(*attributes, fileNameAttribute); if (index == -1) { - m_error = msgMissingAttribute(fileNameAttribute()); + m_error = msgMissingAttribute(fileNameAttribute); return false; } - TypeDatabase::instance()->addSystemInclude(attributes->takeAt(index).value().toString()); + TypeDatabase::instance()->addForceProcessSystemInclude(attributes->takeAt(index).value().toString()); return true; } @@ -3033,9 +3167,9 @@ TemplateInstance * "conversion-rule, native-to-target or add-conversion tags."_s; return nullptr; } - const auto nameIndex = indexOfAttribute(*attributes, nameAttribute()); + const auto nameIndex = indexOfAttribute(*attributes, nameAttribute); if (nameIndex == -1) { - m_error = msgMissingAttribute(nameAttribute()); + m_error = msgMissingAttribute(nameAttribute); return nullptr; } return new TemplateInstance(attributes->takeAt(nameIndex).value().toString()); @@ -3054,7 +3188,7 @@ bool TypeSystemParser::parseReplace(const ConditionalStreamReader &, const auto name = attributes->at(i).qualifiedName(); if (name == u"from") from = attributes->takeAt(i).value().toString(); - else if (name == toAttribute()) + else if (name == toAttribute) to = attributes->takeAt(i).value().toString(); } m_templateInstance->addReplaceRule(from, to); @@ -3072,7 +3206,7 @@ bool TypeSystemParser::checkDuplicatedTypeEntry(const ConditionalStreamReader &r if (t == StackElement::PrimitiveTypeEntry || t == StackElement::FunctionTypeEntry) return true; const auto duplicated = m_context->db->findType(name); - if (duplicated.isNull() || duplicated->isNamespace()) + if (!duplicated || duplicated->isNamespace()) return true; if (duplicated->isBuiltIn()) { qCWarning(lcShiboken, "%s", @@ -3110,12 +3244,12 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack VersionRange versionRange; for (auto i = attributes.size() - 1; i >= 0; --i) { const auto name = attributes.at(i).qualifiedName(); - if (name == sinceAttribute()) { + if (name == sinceAttribute) { if (!parseVersion(attributes.takeAt(i).value().toString(), m_defaultPackage, &versionRange.since, &m_error)) { return false; } - } else if (name == untilAttribute()) { + } else if (name == untilAttribute) { if (!parseVersion(attributes.takeAt(i).value().toString(), m_defaultPackage, &versionRange.until, &m_error)) { return false; @@ -3149,7 +3283,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack } if (isTypeEntry(element) || element == StackElement::Root) - m_contextStack.push(StackElementContextPtr(new StackElementContext())); + m_contextStack.push(std::make_shared<StackElementContext>()); if (m_contextStack.isEmpty()) { m_error = msgNoRootTypeSystemEntry(); @@ -3162,11 +3296,11 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack if (isTypeEntry(element)) { QString name; if (element != StackElement::FunctionTypeEntry) { - const auto nameIndex = indexOfAttribute(attributes, nameAttribute()); + const auto nameIndex = indexOfAttribute(attributes, nameAttribute); if (nameIndex != -1) { name = attributes.takeAt(nameIndex).value().toString(); } else if (element != StackElement::EnumTypeEntry) { // anonymous enum? - m_error = msgMissingAttribute(nameAttribute()); + m_error = msgMissingAttribute(nameAttribute); return false; } } @@ -3179,7 +3313,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack if (m_context->db->hasDroppedTypeEntries()) { const QString identifier = element == StackElement::FunctionTypeEntry - ? attributes.value(signatureAttribute()).toString() : name; + ? attributes.value(signatureAttribute).toString().simplified() : name; if (shouldDropTypeEntry(m_context->db, m_contextStack, identifier)) { m_currentDroppedEntryDepth = 1; if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { @@ -3204,14 +3338,14 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack if (element != StackElement::PrimitiveTypeEntry && element != StackElement::FunctionTypeEntry) { TypeEntryPtr tmp = m_context->db->findType(name); - if (!tmp.isNull() && !tmp->isNamespace()) + if (tmp && !tmp->isNamespace()) qCWarning(lcShiboken).noquote().nospace() << "Duplicate type entry: '" << name << '\''; } if (element == StackElement::EnumTypeEntry) { const auto enumIdentifiedByIndex = - indexOfAttribute(attributes, enumIdentifiedByValueAttribute()); + indexOfAttribute(attributes, enumIdentifiedByValueAttribute); const QString identifiedByValue = enumIdentifiedByIndex != -1 ? attributes.takeAt(enumIdentifiedByIndex).value().toString() : QString(); if (name.isEmpty()) { @@ -3270,7 +3404,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack case StackElement::InterfaceTypeEntry: { if (!checkRootElement()) return false; - ComplexTypeEntryPtr ce(new ObjectTypeEntry(name, versionRange.since, currentParentTypeEntry())); + auto ce = std::make_shared<ObjectTypeEntry>(name, versionRange.since, currentParentTypeEntry()); top->entry = ce; applyCommonAttributes(reader, top->entry, &attributes); applyComplexTypeAttributes(reader, ce, &attributes); @@ -3318,7 +3452,8 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack || element == StackElement::ConversionRule || element == StackElement::AddFunction || element == StackElement::DeclareFunction - || element == StackElement::Template; + || element == StackElement::Template + || element == StackElement::OpaqueContainer; if (!topLevel && m_stack.at(m_stack.size() - 2) == StackElement::Root) { m_error = u"Tag requires parent: '"_s + tagName.toString() + u'\''; @@ -3357,12 +3492,12 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack const auto topParent = m_stack.value(m_stack.size() - 3, StackElement::None); if (isTypeEntry(topParent)) { - const auto replaceIndex = indexOfAttribute(attributes, replaceAttribute()); + const auto replaceIndex = indexOfAttribute(attributes, replaceAttribute); const bool replace = replaceIndex == -1 || convertBoolean(attributes.takeAt(replaceIndex).value(), - replaceAttribute(), true); + replaceAttribute, true); auto customConversion = CustomConversion::getCustomConversion(top->entry); - if (customConversion.isNull()) { + if (!customConversion) { m_error = msgMissingCustomConversion(top->entry); return false; } @@ -3387,14 +3522,17 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack return false; break; case StackElement::SuppressedWarning: { - const auto textIndex = indexOfAttribute(attributes, textAttribute()); + const auto textIndex = indexOfAttribute(attributes, textAttribute); if (textIndex == -1) { qCWarning(lcShiboken) << "Suppressed warning with no text specified"; } else { const QString suppressedWarning = attributes.takeAt(textIndex).value().toString(); - if (!m_context->db->addSuppressedWarning(suppressedWarning, &m_error)) + if (!m_context->db->addSuppressedWarning(suppressedWarning, + m_generate == TypeEntry::GenerateCode, + &m_error)) { return false; + } } } break; @@ -3463,17 +3601,19 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack return false; break; case StackElement::Rejection: - if (!addRejection(m_context->db, &attributes, &m_error)) + if (!addRejection(m_context->db, m_generate == TypeEntry::GenerateCode, + &attributes, &m_error)) { return false; + } break; case StackElement::SystemInclude: if (!parseSystemInclude(reader, &attributes)) return false; break; case StackElement::Template: { - const auto nameIndex = indexOfAttribute(attributes, nameAttribute()); + const auto nameIndex = indexOfAttribute(attributes, nameAttribute); if (nameIndex == -1) { - m_error = msgMissingAttribute(nameAttribute()); + m_error = msgMissingAttribute(nameAttribute); return false; } m_templateEntry.reset(new TemplateEntry(attributes.takeAt(nameIndex).value().toString())); @@ -3481,13 +3621,19 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack break; case StackElement::InsertTemplate: m_templateInstance.reset(parseInsertTemplate(reader, topElement, &attributes)); - if (m_templateInstance.isNull()) + if (!m_templateInstance) return false; break; case StackElement::Replace: if (!parseReplace(reader, topElement, &attributes)) return false; break; + case StackElement::OpaqueContainer: + if (!parseOpaqueContainerElement(&attributes)) + case StackElement::Configuration: + if (!parseConfiguration(topElement, &attributes)) + return false; + break; default: break; // nada } diff --git a/sources/shiboken6/ApiExtractor/typesystemparser_p.h b/sources/shiboken6/ApiExtractor/typesystemparser_p.h index 7d47c31e4..4d9d4fd92 100644 --- a/sources/shiboken6/ApiExtractor/typesystemparser_p.h +++ b/sources/shiboken6/ApiExtractor/typesystemparser_p.h @@ -4,6 +4,7 @@ #define TYPESYSTEMPARSER_H #include "typesystem.h" +#include "containertypeentry.h" #include "typedatabase.h" #include "typedatabase_p.h" #include "typesystem_typedefs.h" @@ -12,7 +13,9 @@ #include <QtCore/QStack> #include <QtCore/QHash> #include <QtCore/QScopedPointer> -#include <QtCore/QSharedPointer> + +#include <memory> +#include <optional> QT_FORWARD_DECLARE_CLASS(QVersionNumber) QT_FORWARD_DECLARE_CLASS(QXmlStreamAttributes) @@ -101,6 +104,8 @@ enum class StackElement { ArgumentModifiers, ImportFile, + OpaqueContainer, + Configuration, Unimplemented }; @@ -128,12 +133,12 @@ struct StackElementContext class TypeSystemParser { public: - Q_DISABLE_COPY(TypeSystemParser) + Q_DISABLE_COPY_MOVE(TypeSystemParser) - using StackElementContextPtr = QSharedPointer<StackElementContext>; + using StackElementContextPtr = std::shared_ptr<StackElementContext>; using ContextStack = QStack<StackElementContextPtr>; - explicit TypeSystemParser(const QSharedPointer<TypeDatabaseParserContext> &context, + explicit TypeSystemParser(const std::shared_ptr<TypeDatabaseParserContext> &context, bool generate); ~TypeSystemParser(); @@ -142,6 +147,13 @@ public: QString errorString() const { return m_error; } private: + struct Snippet + { + QString content; + QString fileName; + QString snippetLabel; + }; + bool parseXml(ConditionalStreamReader &reader); bool setupSmartPointerInstantiations(); bool startElement(const ConditionalStreamReader &reader, StackElement element); @@ -166,9 +178,11 @@ private: CustomTypeEntryPtr parseCustomTypeEntry(const ConditionalStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *); + bool parseOpaqueContainers(QStringView s, OpaqueContainers *result); ContainerTypeEntryPtr parseContainerTypeEntry(const ConditionalStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *); + bool parseOpaqueContainerElement(QXmlStreamAttributes *attributes); EnumTypeEntryPtr parseEnumTypeEntry(const ConditionalStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *); @@ -194,6 +208,8 @@ private: const QVersionNumber &since, QXmlStreamAttributes *); void applyComplexTypeAttributes(const ConditionalStreamReader &, const ComplexTypeEntryPtr &ctype, QXmlStreamAttributes *) const; + bool parseConfiguration(StackElement topElement, + QXmlStreamAttributes *attributes); bool parseRenameFunction(const ConditionalStreamReader &, QString *name, QXmlStreamAttributes *); bool parseInjectDocumentation(const ConditionalStreamReader &, StackElement topElement, @@ -228,6 +244,10 @@ private: StackElement topElement, QXmlStreamAttributes *attributes); bool parseProperty(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); + bool parseBasicModifyFunctionAttributes(QXmlStreamAttributes *, + FunctionModification *mod); + bool parseModifyFunctionAttributes(QXmlStreamAttributes *, + FunctionModification *mod); bool parseModifyFunction(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); bool parseReplaceDefaultExpression(const ConditionalStreamReader &, @@ -236,7 +256,8 @@ private: QXmlStreamAttributes *); bool parseParentOwner(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); - bool readFileSnippet(QXmlStreamAttributes *attributes, CodeSnip *snip); + std::optional<Snippet> readFileSnippet(QXmlStreamAttributes *attributes); + bool readCodeSnippet(QXmlStreamAttributes *attributes, CodeSnip *snip); bool parseInjectCode(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); bool parseInclude(const ConditionalStreamReader &, StackElement topElement, const TypeEntryPtr &entry, QXmlStreamAttributes *); @@ -251,7 +272,7 @@ private: ParserState parserState(qsizetype offset = 0) const; CodeSnipAbstract *injectCodeTarget(qsizetype offset = 0) const; - QSharedPointer<TypeDatabaseParserContext> m_context; + std::shared_ptr<TypeDatabaseParserContext> m_context; QStack<StackElement> m_stack; int m_currentDroppedEntryDepth = 0; int m_ignoreDepth = 0; diff --git a/sources/shiboken6/ApiExtractor/typesystemtypeentry.h b/sources/shiboken6/ApiExtractor/typesystemtypeentry.h index bd69058d2..9b9670696 100644 --- a/sources/shiboken6/ApiExtractor/typesystemtypeentry.h +++ b/sources/shiboken6/ApiExtractor/typesystemtypeentry.h @@ -5,6 +5,7 @@ #define TYPESYSTEMTYPEENTRY_H #include "typesystem.h" +#include "modifications_typedefs.h" #include "typesystem_enums.h" #include "typesystem_typedefs.h" @@ -23,6 +24,15 @@ public: CodeSnipList &codeSnips(); void addCodeSnip(const CodeSnip &codeSnip); + QString subModuleOf() const; + void setSubModule(const QString &); + + const QString &namespaceBegin() const; + void setNamespaceBegin(const QString &n); + + const QString &namespaceEnd() const; + void setNamespaceEnd(const QString &n); + protected: explicit TypeSystemTypeEntry(TypeEntryPrivate *d); }; diff --git a/sources/shiboken6/ApiExtractor/usingmember.h b/sources/shiboken6/ApiExtractor/usingmember.h index ed362688d..346eab13c 100644 --- a/sources/shiboken6/ApiExtractor/usingmember.h +++ b/sources/shiboken6/ApiExtractor/usingmember.h @@ -12,7 +12,7 @@ QT_FORWARD_DECLARE_CLASS(QDebug) struct UsingMember // Introducing a base class member via 'using' directive { QString memberName; - const AbstractMetaClass *baseClass; + AbstractMetaClassCPtr baseClass; Access access; }; diff --git a/sources/shiboken6/ApiExtractor/xmlutils.cpp b/sources/shiboken6/ApiExtractor/xmlutils.cpp index b0c9c2084..ccacd4ce7 100644 --- a/sources/shiboken6/ApiExtractor/xmlutils.cpp +++ b/sources/shiboken6/ApiExtractor/xmlutils.cpp @@ -21,13 +21,13 @@ QString XQuery::evaluate(QString xPathExpression, QString *errorMessage) return doEvaluate(xPathExpression, errorMessage); } -QSharedPointer<XQuery> XQuery::create(const QString &focus, QString *errorMessage) +std::shared_ptr<XQuery> XQuery::create(const QString &focus, QString *errorMessage) { #if defined(HAVE_LIBXSLT) return libXml_createXQuery(focus, errorMessage); #else *errorMessage = QLatin1StringView(__FUNCTION__) + u" is not implemented."_s; - return QSharedPointer<XQuery>(); + return std::shared_ptr<XQuery>(); #endif } diff --git a/sources/shiboken6/ApiExtractor/xmlutils.h b/sources/shiboken6/ApiExtractor/xmlutils.h index 2d6adbe9e..ac23c9c9c 100644 --- a/sources/shiboken6/ApiExtractor/xmlutils.h +++ b/sources/shiboken6/ApiExtractor/xmlutils.h @@ -3,19 +3,20 @@ #ifndef XMLUTILS_H #define XMLUTILS_H -#include <QtCore/QSharedPointer> #include <QtCore/QString> +#include <memory> + class XQuery { public: - Q_DISABLE_COPY(XQuery); + Q_DISABLE_COPY_MOVE(XQuery) virtual ~XQuery(); QString evaluate(QString xPathExpression, QString *errorMessage); - static QSharedPointer<XQuery> create(const QString &focus, QString *errorMessage); + static std::shared_ptr<XQuery> create(const QString &focus, QString *errorMessage); protected: XQuery(); diff --git a/sources/shiboken6/ApiExtractor/xmlutils_libxslt.cpp b/sources/shiboken6/ApiExtractor/xmlutils_libxslt.cpp index fad8889fa..5a9a26913 100644 --- a/sources/shiboken6/ApiExtractor/xmlutils_libxslt.cpp +++ b/sources/shiboken6/ApiExtractor/xmlutils_libxslt.cpp @@ -40,8 +40,6 @@ static void ensureInitialized() } } -namespace { - // RAI Helpers for cleaning up libxml2/libxslt data struct XmlDocDeleter // for std::unique_ptr<xmlDoc> @@ -64,8 +62,6 @@ struct XmlXPathContextDeleter void operator()(xmlXPathContextPtr xPathContext) { xmlXPathFreeContext(xPathContext); } }; -} // namespace - using XmlDocUniquePtr = std::unique_ptr<xmlDoc, XmlDocDeleter>; using XmlPathObjectUniquePtr = std::unique_ptr<xmlXPathObject, XmlXPathObjectDeleter>; using XmlStyleSheetUniquePtr = std::unique_ptr<xsltStylesheet, XmlStyleSheetDeleter>; @@ -141,9 +137,10 @@ QString LibXmlXQuery::doEvaluate(const QString &xPathExpression, QString *errorM return result; } -QSharedPointer<XQuery> libXml_createXQuery(const QString &focus, QString *errorMessage) +std::shared_ptr<XQuery> libXml_createXQuery(const QString &focus, QString *errorMessage) { - XmlDocUniquePtr doc(xmlParseFile(QFile::encodeName(focus).constData())); + XmlDocUniquePtr doc(xmlReadFile(QFile::encodeName(focus).constData(), + "utf-8", XML_PARSE_NOENT)); if (!doc) { *errorMessage = u"libxml2: Cannot set focus to "_s + QDir::toNativeSeparators(focus); return {}; @@ -153,25 +150,27 @@ QSharedPointer<XQuery> libXml_createXQuery(const QString &focus, QString *errorM *errorMessage = u"libxml2: xmlXPathNewContext() failed"_s; return {}; } - return QSharedPointer<XQuery>(new LibXmlXQuery(doc, xpathContext)); + return std::shared_ptr<XQuery>(new LibXmlXQuery(doc, xpathContext)); } // XSLT transformation -static const char xsltPrefix[] = R"(<?xml version="1.0" encoding="UTF-8" ?> +static constexpr auto xsltPrefix = R"(<?xml version="1.0" encoding="UTF-8" ?> <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> -)"; +)"_L1; QString libXslt_transform(const QString &xml, QString xsl, QString *errorMessage) { ensureInitialized(); // Read XML data if (!xsl.startsWith(u"<?xml")) { - xsl.prepend(QLatin1StringView(xsltPrefix)); + xsl.prepend(xsltPrefix); xsl.append(u"</xsl:transform>"_s); } const QByteArray xmlData = xml.toUtf8(); - XmlDocUniquePtr xmlDoc(xmlParseMemory(xmlData.constData(), xmlData.size())); + + XmlDocUniquePtr xmlDoc(xmlReadMemory(xmlData.constData(), int(xmlData.size()), + "", "utf-8", XML_PARSE_NOENT)); if (!xmlDoc) { *errorMessage = u"xmlParseMemory() failed for XML."_s; return xml; diff --git a/sources/shiboken6/ApiExtractor/xmlutils_libxslt.h b/sources/shiboken6/ApiExtractor/xmlutils_libxslt.h index 3430dce71..0dd8eafcb 100644 --- a/sources/shiboken6/ApiExtractor/xmlutils_libxslt.h +++ b/sources/shiboken6/ApiExtractor/xmlutils_libxslt.h @@ -4,11 +4,12 @@ #define XMLUTILS_LIBXSLT_H #include <QtCore/QString> -#include <QtCore/QSharedPointer> + +#include <memory> class XQuery; -QSharedPointer<XQuery> libXml_createXQuery(const QString &focus, QString *errorMessage); +std::shared_ptr<XQuery> libXml_createXQuery(const QString &focus, QString *errorMessage); QString libXslt_transform(const QString &xml, QString xsl, QString *errorMessage); diff --git a/sources/shiboken6/ApiExtractor/xmlutils_qt.h b/sources/shiboken6/ApiExtractor/xmlutils_qt.h index f0c51915f..274827044 100644 --- a/sources/shiboken6/ApiExtractor/xmlutils_qt.h +++ b/sources/shiboken6/ApiExtractor/xmlutils_qt.h @@ -4,11 +4,12 @@ #define XMLUTILS_QT_H #include <QtCore/QString> -#include <QtCore/QSharedPointer> + +#include <memory> class XQuery; -QSharedPointer<XQuery> qt_createXQuery(const QString &focus, QString *errorMessage); +std::shared_ptr<XQuery> qt_createXQuery(const QString &focus, QString *errorMessage); QString qt_xsl_transform(const QString &xml, QString xsl, QString *errorMessage); |