diff options
Diffstat (limited to 'sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp')
-rw-r--r-- | sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp | 1140 |
1 files changed, 628 insertions, 512 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp index 1391a7b0a..89d636964 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp @@ -2,10 +2,14 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "abstractmetabuilder_p.h" +#include "abstractmetaargument.h" #include "abstractmetaenum.h" #include "abstractmetafield.h" #include "abstractmetafunction.h" +#include "abstractmetatype.h" +#include "addedfunction.h" #include "graph.h" +#include "debughelpers_p.h" #include "exception.h" #include "messages.h" #include "propertyspec.h" @@ -39,6 +43,7 @@ #include <QtCore/QDir> #include <QtCore/QFile> #include <QtCore/QFileInfo> +#include <QtCore/QMetaObject> #include <QtCore/QQueue> #include <QtCore/QRegularExpression> #include <QtCore/QTemporaryFile> @@ -50,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); } @@ -64,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; @@ -72,13 +100,6 @@ AbstractMetaBuilderPrivate::AbstractMetaBuilderPrivate() : { } -AbstractMetaBuilderPrivate::~AbstractMetaBuilderPrivate() -{ - qDeleteAll(m_templates); - qDeleteAll(m_smartPointers); - qDeleteAll(m_metaClasses); -} - AbstractMetaBuilder::AbstractMetaBuilder() : d(new AbstractMetaBuilderPrivate) { d->q = this; @@ -135,36 +156,41 @@ const AbstractMetaEnumList &AbstractMetaBuilder::globalEnums() const return d->m_globalEnums; } -const QHash<const TypeEntry *, AbstractMetaEnum> &AbstractMetaBuilder::typeEntryToEnumsHash() const +const QHash<TypeEntryCPtr, AbstractMetaEnum> &AbstractMetaBuilder::typeEntryToEnumsHash() const { 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) { - const TypeEntry *entry = it.value(); + TypeEntryCPtr entry = it.value(); if (!entry) continue; if (!entry->isComplex() || !entry->generateCode()) continue; - auto centry = static_cast<const ComplexTypeEntry *>(entry); + auto centry = std::static_pointer_cast<const ComplexTypeEntry>(entry); if (!centry->generateCode()) continue; FunctionModificationList modifications = centry->functionModifications(); - for (const FunctionModification &modification : qAsConst(modifications)) { + for (const FunctionModification &modification : std::as_const(modifications)) { QString signature = modification.signature(); 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; @@ -172,13 +198,14 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications() QStringList possibleSignatures; for (const auto &function : clazz->functions()) { if (function->implementingClass() == clazz - && modification.matches(function->minimalSignature())) { + && modification.matches(function->modificationSignatures())) { found = true; break; } if (function->originalName() == name) { - possibleSignatures.append(function->minimalSignature() + u" in "_s + const QString signatures = function->modificationSignatures().join(u'/'); + possibleSignatures.append(signatures + u" in "_s + function->implementingClass()->name()); } } @@ -193,14 +220,14 @@ 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; - const TypeEntry *entry = type->typeEntry(); + TypeEntryCPtr entry = type->typeEntry(); if (entry && entry->isComplex()) returned = AbstractMetaClass::findClass(m_metaClasses, entry); return returned; @@ -210,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()) @@ -235,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())); } @@ -250,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; @@ -269,8 +296,8 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte firstArgumentIsSelf = false; } else { auto type = translateType(item->type(), currentClass); - const TypeEntry *retType = type.has_value() ? type->typeEntry() : nullptr; - AbstractMetaClass *otherArgClass = argumentToClass(itemArguments.at(1), currentClass); + const auto retType = type.has_value() ? type->typeEntry() : TypeEntryCPtr{}; + const auto otherArgClass = argumentToClass(itemArguments.at(1), currentClass); if (otherArgClass && retType && (retType->isValue() || retType->isObject()) && retType != baseoperandClass->typeEntry() @@ -279,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; } @@ -320,12 +350,16 @@ 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); + } Q_ASSERT(!metaFunction->wasPrivate()); } bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem &item, - AbstractMetaClass *currentClass) + const AbstractMetaClassPtr ¤tClass) { ArgumentList itemArguments = item->arguments(); if (itemArguments.size() != 2 || item->accessPolicy() != Access::Public) @@ -352,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(); @@ -368,8 +401,8 @@ bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem funcClass = streamClass; } - funcClass->addFunction(AbstractMetaFunctionCPtr(streamFunction)); - auto *funcTe = funcClass->typeEntry(); + AbstractMetaClass::addFunction(funcClass, AbstractMetaFunctionCPtr(streamFunction)); + auto funcTe = funcClass->typeEntry(); if (funcClass == streamClass) funcTe->addArgumentInclude(streamedClass->typeEntry()->include()); else @@ -380,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) @@ -393,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; @@ -403,7 +436,7 @@ void AbstractMetaBuilderPrivate::sortLists() } m_metaClasses = classesTopologicalSorted(m_metaClasses, additionalDependencies); - for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) + for (const auto &cls : std::as_const(m_metaClasses)) cls->sortFunctions(); // Ensure that indexes are in alphabetical order, roughly, except @@ -420,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(); @@ -431,12 +464,12 @@ FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments, clangFlags, builder) ? builder.dom() : FileModelItem(); const clang::BaseVisitor::Diagnostics &diagnostics = builder.diagnostics(); - if (const int diagnosticsCount = diagnostics.size()) { + if (const auto diagnosticsCount = diagnostics.size()) { QDebug d = qWarning(); d.nospace(); d.noquote(); d << "Clang: " << diagnosticsCount << " diagnostic messages:\n"; - for (int i = 0; i < diagnosticsCount; ++i) + for (qsizetype i = 0; i < diagnosticsCount; ++i) d << " " << diagnostics.at(i) << '\n'; } return result; @@ -447,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; @@ -468,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()) { @@ -489,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(); @@ -518,7 +551,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, if (func->accessPolicy() != Access::Public || func->name().startsWith(u"operator")) continue; - FunctionTypeEntry *funcEntry = types->findFunctionType(func->name()); + FunctionTypeEntryPtr funcEntry = types->findFunctionType(func->name()); if (!funcEntry || !funcEntry->generateCode()) continue; @@ -539,8 +572,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, m_globalFunctions << metaFuncPtr; } - ReportHandler::startProgress("Fixing class inheritance..."); - for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) { + ReportHandler::startProgress("Fixed class inheritance."); + for (const auto &cls : std::as_const(m_metaClasses)) { if (cls->needsInheritanceSetup()) { setupInheritance(cls); traverseUsingMembers(cls); @@ -552,14 +585,14 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, } } - ReportHandler::startProgress("Detecting inconsistencies in class model..."); - for (AbstractMetaClass *cls : qAsConst(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 = @@ -570,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) { - TypeEntry *entry = it.value(); + const TypeEntryPtr &entry = it.value(); if (!entry->isPrimitive()) { if ((entry->isValue() || entry->isObject()) && !types->shouldDropTypeEntry(entry->qualifiedCppName()) @@ -583,11 +616,11 @@ 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 = static_cast<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; - for (const auto &func : qAsConst(m_globalFunctions)) { + for (const auto &func : std::as_const(m_globalFunctions)) { if (signature == func->minimalSignature()) { ok = true; break; @@ -601,9 +634,9 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, } } } else if (entry->isEnum() && entry->generateCode()) { - auto enumEntry = static_cast<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() @@ -620,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); } @@ -643,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 : qAsConst(m_metaClasses)) { + for (const auto &cls : std::as_const(m_metaClasses)) { // setupEquals(cls); // setupComparable(cls); setupExternalConversion(cls); @@ -693,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; @@ -709,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); @@ -723,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; } @@ -749,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()); @@ -773,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()); } } @@ -785,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); } } @@ -814,16 +851,16 @@ 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); - TypeEntry *typeEntry = nullptr; - const TypeEntry *enclosingTypeEntry = enclosing ? enclosing->typeEntry() : nullptr; + TypeEntryPtr typeEntry; + const auto enclosingTypeEntry = enclosing ? enclosing->typeEntry() : TypeEntryCPtr{}; if (enumItem->accessPolicy() == Access::Private) { - typeEntry = new EnumTypeEntry(enumItem->qualifiedName().constLast(), - QVersionNumber(0, 0), enclosingTypeEntry); + typeEntry.reset(new EnumTypeEntry(enumItem->qualifiedName().constLast(), + QVersionNumber(0, 0), enclosingTypeEntry)); TypeDatabase::instance()->addType(typeEntry); } else if (enumItem->enumKind() != AnonymousEnum) { typeEntry = TypeDatabase::instance()->findType(qualifiedName); @@ -833,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; @@ -850,65 +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 = static_cast<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.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) { - auto 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); @@ -920,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()); @@ -931,16 +1000,16 @@ 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 // we store the aliased type on the alias // TypeEntry - PrimitiveTypeEntry *ptype = types->findPrimitiveType(className); + const auto ptype = types->findPrimitiveType(className); const auto &targetNames = typeDef->type().qualifiedName(); - PrimitiveTypeEntry *pTarget = targetNames.size() == 1 - ? types->findPrimitiveType(targetNames.constFirst()) : nullptr; + const auto pTarget = targetNames.size() == 1 + ? types->findPrimitiveType(targetNames.constFirst()) : PrimitiveTypeEntryPtr{}; if (ptype) { ptype->setReferencedTypeEntry(pTarget); return nullptr; @@ -948,9 +1017,10 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt // It is a (nested?) global typedef to a primitive type // (like size_t = unsigned)? Add it to the type DB. - if (pTarget && pTarget->basicReferencedNonBuiltinTypeEntry()->isCppPrimitive() + if (pTarget && isCppPrimitive(basicReferencedNonBuiltinTypeEntry(pTarget)) && currentClass == nullptr) { - auto *pte = new PrimitiveTypeEntry(className, {}, nullptr); + auto pte = std::make_shared<PrimitiveTypeEntry>(className, QVersionNumber{}, + TypeEntryCPtr{}); pte->setReferencedTypeEntry(pTarget); pte->setBuiltIn(true); types->addType(pte); @@ -958,11 +1028,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt } // If we haven't specified anything for the typedef, then we don't care - ComplexTypeEntry *type = types->findComplexType(fullClassName); + auto type = types->findComplexType(fullClassName); 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())); @@ -981,8 +1051,8 @@ void AbstractMetaBuilderPrivate::traverseTypesystemTypedefs() { const auto &entries = TypeDatabase::instance()->typedefEntries(); for (auto it = entries.begin(), end = entries.end(); it != end; ++it) { - TypedefEntry *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())); @@ -1008,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; @@ -1018,20 +1088,24 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem // we have inner an class if (currentClass) { fullClassName = stripTemplateArgs(currentClass->typeEntry()->qualifiedCppName()) - + colonColon() + fullClassName; + + u"::"_s + fullClassName; } - ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(fullClassName); + const auto type = TypeDatabase::instance()->findComplexType(fullClassName); AbstractMetaBuilder::RejectReason reason = AbstractMetaBuilder::NoReason; if (TypeDatabase::instance()->isClassRejected(fullClassName)) { reason = AbstractMetaBuilder::GenerationDisabled; } else if (!type) { - TypeEntry *te = TypeDatabase::instance()->findType(fullClassName); - if (te && !te->isComplex()) + TypeEntryPtr te = TypeDatabase::instance()->findType(fullClassName); + if (te && !te->isComplex()) { reason = AbstractMetaBuilder::RedefinedToNotClass; - else + // Set the default include file name + if (!te->include().isValid()) + setInclude(te, classItem->fileName()); + } else { reason = AbstractMetaBuilder::NotInTypeSystem; + } } else if (type->codeGeneration() == TypeEntry::GenerateNothing) { reason = AbstractMetaBuilder::GenerationDisabled; } @@ -1040,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) @@ -1053,6 +1127,9 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem if (classItem->isFinal()) *metaClass += AbstractMetaClass::FinalCppClass; + if (classItem->classType() == CodeModel::Struct) + *metaClass += AbstractMetaClass::Struct; + QStringList baseClassNames; const QList<_ClassModelItem::BaseClass> &baseClasses = classItem->baseClasses(); for (const _ClassModelItem::BaseClass &baseClass : baseClasses) { @@ -1072,15 +1149,16 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem } TemplateParameterList template_parameters = classItem->templateParameters(); - TypeEntries template_args; + TypeEntryCList template_args; template_args.clear(); - auto argumentParent = metaClass->typeEntry()->typeSystemTypeEntry(); - for (int i = 0; i < template_parameters.size(); ++i) { + 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(param_type); + template_args.append(TypeEntryCPtr(param_type)); } metaClass->setTemplateArguments(template_args); @@ -1092,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()); } } @@ -1106,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()); } } @@ -1121,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); @@ -1135,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}); @@ -1170,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; @@ -1185,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(); @@ -1210,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 {}; } @@ -1224,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))); @@ -1259,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) { @@ -1278,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(); @@ -1287,7 +1363,7 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF if (castTo.startsWith(u"const ")) castTo.remove(0, 6); - TypeEntry *retType = types->findType(castTo); + TypeEntryPtr retType = types->findType(castTo); if (!retType) return; @@ -1299,7 +1375,7 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF AbstractMetaFunctionRawPtrList AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem, AbstractMetaClass::Attributes *constructorAttributes, - AbstractMetaClass *currentClass) + const AbstractMetaClassPtr ¤tClass) { *constructorAttributes = {}; AbstractMetaFunctionRawPtrList result; @@ -1311,10 +1387,10 @@ 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->functionType() == CodeModel::Constructor) { + } else if (!function->isDeleted() && function->functionType() == CodeModel::Constructor) { auto arguments = function->arguments(); *constructorAttributes |= AbstractMetaClass::HasRejectedConstructor; if (arguments.isEmpty() || arguments.constFirst()->defaultValue()) @@ -1324,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 = @@ -1334,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) { @@ -1367,21 +1443,20 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, metaFunction->setPropertySpecIndex(propertyFunction.index); } break; + case AbstractMetaClass::PropertyFunction::Notify: + if (metaFunction->isSignal()) { + *metaFunction += AbstractMetaFunction::PropertyNotify; + metaFunction->setPropertySpecIndex(propertyFunction.index); + } } } - 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)) { @@ -1392,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()); @@ -1408,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; @@ -1421,12 +1496,12 @@ void AbstractMetaBuilderPrivate::fillAddedFunctions(AbstractMetaClass *metaClass QString AbstractMetaBuilder::getSnakeCaseName(const QString &name) { - const int size = name.size(); + const auto size = name.size(); if (size < 3) return name; QString result; result.reserve(size + 4); - for (int i = 0; i < size; ++i) { + for (qsizetype i = 0; i < size; ++i) { const QChar c = name.at(i); if (c.isUpper()) { if (i > 0) { @@ -1472,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; @@ -1503,8 +1569,9 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) // we only support our own containers and ONLY if there is only one baseclass if (baseClasses.size() == 1 && baseClasses.constFirst().contains(u'<')) { TypeInfo info; - ComplexTypeEntry* baseContainerType; - AbstractMetaClass* templ = findTemplateClass(baseClasses.constFirst(), metaClass, &info, &baseContainerType); + ComplexTypeEntryPtr baseContainerType; + const auto templ = findTemplateClass(baseClasses.constFirst(), metaClass, + &info, &baseContainerType); if (templ) { setupInheritance(templ); inheritTemplate(metaClass, templ, info); @@ -1524,15 +1591,15 @@ 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; } - TypeDatabase* types = TypeDatabase::instance(); + auto *types = TypeDatabase::instance(); - for (const auto &baseClassName : baseClasses) { + for (const auto &baseClassName : baseClasses) { if (!types->isClassRejected(baseClassName)) { auto typeEntry = types->findType(baseClassName); if (typeEntry == nullptr || !typeEntry->isComplex()) { @@ -1561,7 +1628,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)); } @@ -1571,7 +1638,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(); @@ -1619,7 +1686,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); @@ -1631,7 +1698,7 @@ AbstractMetaFunction * return nullptr; } - auto metaFunction = new AbstractMetaFunction(addedFunc); + auto *metaFunction = new AbstractMetaFunction(addedFunc); metaFunction->setType(returnType.value()); metaFunction->setFunctionType(functionTypeFromName(addedFunc->name())); @@ -1688,7 +1755,8 @@ AbstractMetaFunction * // Find the correct default values const FunctionModificationList functionMods = metaFunction->modifications(metaClass); - for (int i = 0; i < metaArguments.size(); ++i) { + applyCachedFunctionModifications(metaFunction, functionMods); + for (qsizetype i = 0; i < metaArguments.size(); ++i) { AbstractMetaArgument &metaArg = metaArguments[i]; // use replace-default-expression for set default value @@ -1703,7 +1771,7 @@ AbstractMetaFunction * } bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunctionPtr &addedFunc, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, QString *errorMessage) { AbstractMetaFunction *metaFunction = @@ -1713,11 +1781,11 @@ 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) { - const TypeEntry *te = fargs.constFirst().type().typeEntry(); + const auto te = fargs.constFirst().type().typeEntry(); if (te->isCustom()) metaFunction->setExplicit(true); if (te->name() == metaFunction->name()) @@ -1727,7 +1795,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; } @@ -1743,7 +1811,7 @@ void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func, co } } - for (int i = 0, size = arguments.size(); i < size; ++i) { + for (qsizetype i = 0, size = arguments.size(); i < size; ++i) { if (arguments.at(i).name().isEmpty()) arguments[i].setName(u"arg__"_s + QString::number(i + 1), false); } @@ -1763,7 +1831,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; } @@ -1875,9 +1943,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; @@ -1918,20 +2025,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)); @@ -1942,46 +2046,30 @@ 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())); + metaFunction->setUnresolvedSignature(unresolvedSignature); if (functionItem->isHiddenFriend()) - metaFunction->setFlags(AbstractMetaFunction::Flag::HiddenFriend); + 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()); @@ -1991,25 +2079,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; } @@ -2020,6 +2113,14 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio } ArgumentList arguments = functionItem->arguments(); + // Add private signals for documentation purposes + if (!arguments.isEmpty() + && m_apiExtractorFlags.testFlag(ApiExtractorFlag::UsePySideExtensions) + && functionItem->functionType() == CodeModel::Signal + && arguments.constLast()->type().qualifiedName().constLast() == u"QPrivateSignal") { + flags.setFlag(AbstractMetaFunction::Flag::PrivateSignal); + arguments.removeLast(); + } if (arguments.size() == 1) { ArgumentModelItem arg = arguments.at(0); @@ -2028,33 +2129,40 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio arguments.pop_front(); } - for (int i = 0; i < arguments.size(); ++i) { + 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; } @@ -2065,10 +2173,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; @@ -2084,15 +2190,10 @@ 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 (int i = 0, size = metaArguments.size(); i < size; ++i) { + for (qsizetype i = 0, size = metaArguments.size(); i < size; ++i) { const ArgumentModelItem &arg = arguments.at(i); AbstractMetaArgument &metaArg = metaArguments[i]; @@ -2146,35 +2247,39 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio } } } + metaFunction->setFlags(flags); return metaFunction; } -static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaClass, const QString& qualifiedName) +static TypeEntryCPtr findTypeEntryUsingContext(const AbstractMetaClassCPtr &metaClass, + const QString& qualifiedName) { - const TypeEntry* type = nullptr; - QStringList context = metaClass->qualifiedCppName().split(colonColon()); + TypeEntryCPtr type; + 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; } // Helper for findTypeEntries/translateTypeStatic() -TypeEntries AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qualifiedName, - const QString &name, - const AbstractMetaClass *currentClass, - AbstractMetaBuilderPrivate *d) +TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qualifiedName, + const QString &name, + 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}; } @@ -2198,7 +2303,7 @@ TypeEntries AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qua // of the parameters. if (currentClass) { const auto &template_args = currentClass->templateArguments(); - for (const TypeEntry *te : template_args) { + for (const auto &te : template_args) { if (te->name() == qualifiedName) return {te}; } @@ -2208,13 +2313,15 @@ TypeEntries AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qua // Helper for translateTypeStatic() that calls findTypeEntriesHelper() // and does some error checking. -TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualifiedName, - const QString &name, - const AbstractMetaClass *currentClass, - AbstractMetaBuilderPrivate *d, - QString *errorMessage) -{ - TypeEntries types = findTypeEntriesHelper(qualifiedName, name, currentClass, d); +TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualifiedName, + const QString &name, + TranslateTypeFlags flags, + const AbstractMetaClassCPtr ¤tClass, + AbstractMetaBuilderPrivate *d, + QString *errorMessage) +{ + TypeEntryCList types = findTypeEntriesHelper(qualifiedName, name, flags, + currentClass, d); if (types.isEmpty()) { if (errorMessage != nullptr) *errorMessage = msgCannotFindTypeEntry(qualifiedName); @@ -2224,9 +2331,11 @@ TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualified // Resolve entries added by metabuilder (for example, "GLenum") to match // the signatures for modifications. for (qsizetype i = 0, size = types.size(); i < size; ++i) { - const auto *e = types.at(i); - if (e->isPrimitive()) - types[i] = e->asPrimitive()->basicReferencedNonBuiltinTypeEntry(); + const auto &e = types.at(i); + if (e->isPrimitive()) { + const auto pte = std::static_pointer_cast<const PrimitiveTypeEntry>(e); + types[i] = basicReferencedNonBuiltinTypeEntry(pte); + } } if (types.size() == 1) @@ -2234,7 +2343,7 @@ TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualified const auto typeEntryType = types.constFirst()->type(); const bool sameType = std::all_of(types.cbegin() + 1, types.cend(), - [typeEntryType](const TypeEntry *e) { + [typeEntryType](const TypeEntryCPtr &e) { return e->type() == typeEntryType; }); @@ -2257,10 +2366,10 @@ TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualified // 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; @@ -2281,22 +2390,22 @@ 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); + auto typeEntry = TypeDatabase::instance()->findPrimitiveType(returnTypeName); Q_ASSERT(typeEntry); AbstractMetaType returnType(typeEntry); returnType.decideUsagePattern(); @@ -2304,8 +2413,8 @@ static AbstractMetaFunctionPtr } // Create the instantiation type of a smart pointer -static AbstractMetaType instantiationType(const AbstractMetaClass *s, - const SmartPointerTypeEntry *ste) +static AbstractMetaType instantiationType(const AbstractMetaClassCPtr &s, + const SmartPointerTypeEntryCPtr &ste) { AbstractMetaType type(s->templateArguments().constFirst()); if (ste->smartPointerType() != TypeSystem::SmartPointerType::ValueHandle) @@ -2315,8 +2424,8 @@ static AbstractMetaType instantiationType(const AbstractMetaClass *s, } // Create the pointee argument of a smart pointer constructor or reset() -static AbstractMetaArgument pointeeArgument(const AbstractMetaClass *s, - const SmartPointerTypeEntry *ste) +static AbstractMetaArgument pointeeArgument(const AbstractMetaClassCPtr &s, + const SmartPointerTypeEntryCPtr &ste) { AbstractMetaArgument pointee; pointee.setType(instantiationType(s, ste)); @@ -2326,7 +2435,8 @@ 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, const SmartPointerTypeEntry *ste) +static void fixSmartPointerConstructors(const AbstractMetaClassPtr &s, + const SmartPointerTypeEntryCPtr &ste) { const auto ctors = s->queryFunctions(FunctionQueryOption::Constructors); bool seenDefaultConstructor = false; @@ -2339,23 +2449,24 @@ static void fixSmartPointerConstructors(AbstractMetaClass *s, const SmartPointer } 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, const SmartPointerTypeEntry *ste) +static void fixSmartPointerReset(const AbstractMetaClassPtr &s, + const SmartPointerTypeEntryCPtr &ste) { const QString resetMethodName = ste->resetMethod(); const auto functions = s->findFunctions(resetMethodName); @@ -2369,21 +2480,22 @@ static void fixSmartPointerReset(AbstractMetaClass *s, const SmartPointerTypeEnt } 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, const SmartPointerTypeEntry *ste) +static void fixSmartPointerClass(const AbstractMetaClassPtr &s, + const SmartPointerTypeEntryCPtr &ste) { fixSmartPointerConstructors(s, ste); @@ -2391,43 +2503,43 @@ static void fixSmartPointerClass(AbstractMetaClass *s, const SmartPointerTypeEnt 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 SmartPointerTypeEntry *ste, - const AbstractMetaClassList &allClasses) +static AbstractMetaClassPtr createSmartPointerClass(const SmartPointerTypeEntryCPtr &ste, + const AbstractMetaClassList &allClasses) { - auto *result = new AbstractMetaClass(); - result->setTypeEntry(const_cast<SmartPointerTypeEntry *>(ste)); - auto *templateArg = new TemplateArgumentEntry(u"T"_s, ste->version(), - ste->typeSystemTypeEntry()); + 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(); + 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; @@ -2436,11 +2548,12 @@ static AbstractMetaClass *createSmartPointerClass(const SmartPointerTypeEntry *s void AbstractMetaBuilderPrivate::fixSmartPointers() { const auto smartPointerTypes = TypeDatabase::instance()->smartPointerTypes(); - for (auto *ste : smartPointerTypes) { - const AbstractMetaClass *smartPointerClass = + for (const auto &ste : smartPointerTypes) { + 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())); @@ -2451,7 +2564,7 @@ void AbstractMetaBuilderPrivate::fixSmartPointers() std::optional<AbstractMetaType> AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei, - const AbstractMetaClass *currentClass, + const AbstractMetaClassCPtr ¤tClass, TranslateTypeFlags flags, QString *errorMessage) { @@ -2464,9 +2577,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) @@ -2493,10 +2613,10 @@ std::optional<AbstractMetaType> // the global scope when they are referenced from inside a namespace. // This is a work around to fix this bug since fixing it in resolveType // seemed non-trivial - int i = d ? d->m_scopes.size() - 1 : -1; + 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; } @@ -2520,7 +2640,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 @@ -2550,7 +2670,7 @@ std::optional<AbstractMetaType> return {}; } - for (int i = typeInfo.arrayElements().size() - 1; i >= 0; --i) { + for (auto i = typeInfo.arrayElements().size() - 1; i >= 0; --i) { AbstractMetaType arrayType; arrayType.setArrayElementType(elementType.value()); const QString &arrayElement = typeInfo.arrayElements().at(i); @@ -2563,8 +2683,9 @@ std::optional<AbstractMetaType> arrayType.setArrayElementCount(int(elems)); } auto elementTypeEntry = elementType->typeEntry(); - arrayType.setTypeEntry(new ArrayTypeEntry(elementTypeEntry, elementTypeEntry->version(), - elementTypeEntry->parent())); + auto at = std::make_shared<ArrayTypeEntry>(elementTypeEntry, elementTypeEntry->version(), + elementTypeEntry->parent()); + arrayType.setTypeEntry(at); arrayType.decideUsagePattern(); elementType = arrayType; @@ -2583,7 +2704,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) @@ -2592,14 +2713,23 @@ std::optional<AbstractMetaType> typeInfo.clearInstantiations(); } - const TypeEntries 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); return {}; } - const TypeEntry *type = types.constFirst(); + TypeEntryCPtr type = types.constFirst(); const TypeEntry::Type typeEntryType = type->type(); AbstractMetaType metaType; @@ -2610,15 +2740,18 @@ std::optional<AbstractMetaType> metaType.setOriginalTypeDescription(_typei.toString()); const auto &templateArguments = typeInfo.instantiations(); - for (int t = 0, size = templateArguments.size(); t < size; ++t) { + 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)) { - TypeDatabase::instance()->addConstantValueTypeEntry(value, type->typeSystemTypeEntry()); + auto module = typeSystemTypeEntry(type); + TypeDatabase::instance()->addConstantValueTypeEntry(value, module); targType = translateTypeStatic(ti, currentClass, d, flags, &errorMessage); } } @@ -2644,8 +2777,8 @@ std::optional<AbstractMetaType> type = instantiationType; } else { auto it = std::find_if(types.cbegin(), types.cend(), - [instantiationType](const TypeEntry *e) { - auto smartPtr = static_cast<const SmartPointerTypeEntry *>(e); + [instantiationType](const TypeEntryCPtr &e) { + auto smartPtr = std::static_pointer_cast<const SmartPointerTypeEntry>(e); return smartPtr->matchesInstantiation(instantiationType); }); if (it == types.cend()) { @@ -2679,7 +2812,7 @@ std::optional<AbstractMetaType> std::optional<AbstractMetaType> AbstractMetaBuilder::translateType(const TypeInfo &_typei, - AbstractMetaClass *currentClass, + const AbstractMetaClassPtr ¤tClass, TranslateTypeFlags flags, QString *errorMessage) { @@ -2690,7 +2823,7 @@ std::optional<AbstractMetaType> std::optional<AbstractMetaType> AbstractMetaBuilder::translateType(const QString &t, - AbstractMetaClass *currentClass, + const AbstractMetaClassPtr ¤tClass, TranslateTypeFlags flags, QString *errorMessageIn) { @@ -2720,7 +2853,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; @@ -2733,7 +2866,7 @@ qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringV return enumValue->value().value(); } - for (const AbstractMetaEnum &metaEnum : qAsConst(m_globalEnums)) { + for (const AbstractMetaEnum &metaEnum : std::as_const(m_globalEnums)) { auto ev = metaEnum.findEnumValue(stringValue); if (ev.has_value()) { ok = true; @@ -2757,9 +2890,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) @@ -2770,7 +2904,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); @@ -2789,7 +2923,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 @@ -2797,13 +2931,13 @@ 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>()" if (type.instantiations().size() != 1) return expr; // Only simple types are handled, not QMap<int, int>. - auto *innerTypeEntry = type.instantiations().constFirst().typeEntry(); + auto innerTypeEntry = type.instantiations().constFirst().typeEntry(); if (!innerTypeEntry->isComplex()) return expr; const QString &qualifiedInnerTypeName = innerTypeEntry->qualifiedCppName(); @@ -2857,7 +2991,7 @@ QString AbstractMetaBuilderPrivate::fixDefaultValue(QString expr, const Abstract } } // Is this a class constructor "Class(Field)"? Expand it. - auto *te = type.typeEntry(); + const auto te = type.typeEntry(); if (!te->isComplex()) return expr; const QString &qualifiedTypeName = te->qualifiedCppName(); @@ -2872,7 +3006,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); } @@ -2883,23 +3017,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, - ComplexTypeEntry **baseContainerType) const +AbstractMetaClassPtr + AbstractMetaBuilderPrivate::findTemplateClass(const QString &name, + const AbstractMetaClassCPtr &context, + TypeInfo *info, + ComplexTypeEntryPtr *baseContainerType) const { if (baseContainerType) - *baseContainerType = nullptr; - TypeDatabase* types = TypeDatabase::instance(); + 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 (int i = scope.size(); i >= 0; --i) { - QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join(colonColon()) + colonColon() : QString(); + for (auto i = scope.size(); i >= 0; --i) { + 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; @@ -2908,8 +3043,8 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString & if (info) *info = parsed; - AbstractMetaClass *templ = nullptr; - for (AbstractMetaClass *c : qAsConst(m_templates)) { + AbstractMetaClassPtr templ; + for (const auto &c : std::as_const(m_templates)) { if (c->typeEntry()->name() == qualifiedName) { templ = c; break; @@ -2930,7 +3065,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()) @@ -2938,11 +3073,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; @@ -2962,7 +3095,7 @@ std::optional<AbstractMetaType> returned.setOriginalTemplateType(metaType); if (returned.typeEntry()->isTemplateArgument()) { - const auto *tae = static_cast<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. @@ -2992,34 +3125,34 @@ std::optional<AbstractMetaType> return returned; } -AbstractMetaClass * - AbstractMetaBuilder::inheritTemplateClass(ComplexTypeEntry *te, - const AbstractMetaClass *templateClass, +AbstractMetaClassPtr + AbstractMetaBuilder::inheritTemplateClass(const ComplexTypeEntryPtr &te, + 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.get()); - return result.release(); + AbstractMetaBuilderPrivate::inheritTemplateFunctions(result); + return result; } -bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, - const AbstractMetaClass *templateClass, +bool AbstractMetaBuilderPrivate::inheritTemplate(const AbstractMetaClassPtr &subclass, + const AbstractMetaClassCPtr &templateClass, const TypeInfo &info) { AbstractMetaTypeList templateTypes; for (const TypeInfo &i : info.instantiations()) { - QString typeName = i.qualifiedName().join(colonColon()); + QString typeName = i.qualifiedName().join(u"::"_s); TypeDatabase *typeDb = TypeDatabase::instance(); - TypeEntry *t = nullptr; + 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 @@ -3027,18 +3160,18 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, if (isNumber(typeName)) { t = typeDb->findType(typeName); if (!t) { - auto parent = subclass->typeEntry()->typeSystemTypeEntry(); + auto parent = typeSystemTypeEntry(subclass->typeEntry()); t = TypeDatabase::instance()->addConstantValueTypeEntry(typeName, parent); } } else { QStringList possibleNames; - possibleNames << subclass->qualifiedCppName() + colonColon() + typeName; - possibleNames << templateClass->qualifiedCppName() + colonColon() + typeName; + possibleNames << subclass->qualifiedCppName() + u"::"_s + typeName; + possibleNames << templateClass->qualifiedCppName() + u"::"_s + typeName; if (subclass->enclosingClass()) - possibleNames << subclass->enclosingClass()->qualifiedCppName() + colonColon() + typeName; + possibleNames << subclass->enclosingClass()->qualifiedCppName() + u"::"_s + typeName; possibleNames << typeName; - for (const QString &possibleName : qAsConst(possibleNames)) { + for (const QString &possibleName : std::as_const(possibleNames)) { t = typeDb->findType(possibleName); if (t) break; @@ -3061,8 +3194,8 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, 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) { @@ -3112,11 +3245,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 @@ -3133,10 +3266,10 @@ AbstractMetaFunctionPtr f->setOriginalName(subclass->name()); } - ComplexTypeEntry *te = subclass->typeEntry(); - FunctionModificationList mods = function->modifications(templateClass); - for (int i = 0; i < mods.size(); ++i) { - FunctionModification mod = mods.at(i); + ComplexTypeEntryPtr te = subclass->typeEntry(); + const FunctionModificationList mods = function->modifications(templateClass); + + for (auto mod : mods) { mod.setSignature(f->minimalSignature()); // If we ever need it... Below is the code to do @@ -3170,8 +3303,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); @@ -3179,8 +3312,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 @@ -3193,7 +3326,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(); @@ -3214,8 +3347,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); } } @@ -3225,8 +3358,7 @@ void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *sub for (const AbstractMetaField &field : templateClassFields) { // If the field is modified or the instantiation has a field named // the same as an existing field we have shadowing, so we need to skip it. - if (field.isModifiedRemoved(TypeSystem::All) - || field.isStatic() + if (field.isModifiedRemoved() || field.isStatic() || AbstractMetaField::find(existingSubclassFields, field.name()).has_value()) { continue; } @@ -3241,7 +3373,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(); @@ -3252,7 +3384,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; @@ -3281,24 +3413,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))); @@ -3307,53 +3450,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 @@ -3368,10 +3477,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, - const TypeEntry *typeEntry, - MetaClass *clazz, - Graph<MetaClass *> *graph) +static bool addClassDependency(const QList<std::shared_ptr<MetaClass> > &classList, + const TypeEntryCPtr &typeEntry, + std::shared_ptr<MetaClass> clazz, + Graph<std::shared_ptr<MetaClass> > *graph) { if (!typeEntry->isComplex() || typeEntry == clazz->typeEntry()) return false; @@ -3382,10 +3491,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)) { @@ -3395,14 +3505,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(); @@ -3430,16 +3540,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)); } @@ -3473,8 +3589,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); @@ -3528,13 +3644,13 @@ static bool matchHeader(const QString &headerPath, const QString &fileName) #else static const Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive; #endif - const int pathSize = headerPath.size(); + const auto pathSize = headerPath.size(); return fileName.size() > pathSize && isFileSystemSlash(fileName.at(pathSize)) && fileName.startsWith(headerPath, caseSensitivity); } -void AbstractMetaBuilderPrivate::setInclude(TypeEntry *te, const QString &path) const +void AbstractMetaBuilderPrivate::setInclude(const TypeEntryPtr &te, const QString &path) const { auto it = m_resolveIncludeHash.find(path); if (it == m_resolveIncludeHash.end()) { @@ -3582,9 +3698,9 @@ void AbstractMetaBuilder::formatDebug(QDebug &debug) const debug << "m_globalHeader=" << d->m_globalHeaders; debugFormatSequence(debug, "globalEnums", d->m_globalEnums, "\n"); debugFormatSequence(debug, "globalFunctions", d->m_globalFunctions, "\n"); - if (const int scopeCount = d->m_scopes.size()) { + if (const auto scopeCount = d->m_scopes.size()) { debug << "\n scopes[" << scopeCount << "]=("; - for (int i = 0; i < scopeCount; ++i) { + for (qsizetype i = 0; i < scopeCount; ++i) { if (i) debug << ", "; _CodeModelItem::formatKind(debug, d->m_scopes.at(i)->kind()); |