diff options
Diffstat (limited to 'sources/shiboken6/ApiExtractor')
170 files changed, 8228 insertions, 5257 deletions
diff --git a/sources/shiboken6/ApiExtractor/CMakeLists.txt b/sources/shiboken6/ApiExtractor/CMakeLists.txt index 2a779dad6..7aa2fbd11 100644 --- a/sources/shiboken6/ApiExtractor/CMakeLists.txt +++ b/sources/shiboken6/ApiExtractor/CMakeLists.txt @@ -1,56 +1,88 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + project(apiextractor) -cmake_minimum_required(VERSION 3.16) -cmake_policy(VERSION 3.16) +cmake_minimum_required(VERSION 3.18) +cmake_policy(VERSION 3.18) set(CMAKE_AUTOMOC ON) set(apiextractor_SRC -apiextractor.cpp -apiextractorresult.cpp -abstractmetaargument.cpp -abstractmetabuilder.cpp +abstractmetaargument.cpp abstractmetaargument.h +abstractmetabuilder.cpp abstractmetabuilder.h abstractmetabuilder_p.h abstractmetabuilder_helpers.cpp -abstractmetaenum.cpp -abstractmetafield.cpp -abstractmetafunction.cpp -abstractmetatype.cpp -abstractmetalang.cpp -classdocumentation.cpp -codesnip.cpp -codesniphelpers.cpp -conditionalstreamreader.cpp -documentation.cpp -dotview.cpp -enclosingclassmixin.cpp -fileout.cpp -messages.cpp -modifications.cpp -predefined_templates.cpp -propertyspec.cpp -pymethoddefentry.cpp -reporthandler.cpp -sourcelocation.cpp -typeparser.cpp -typesystem.cpp -typesystemparser.cpp -include.cpp -typedatabase.cpp -textstream.cpp +abstractmetaenum.cpp abstractmetaenum.h +abstractmetafield.cpp abstractmetafield.h +abstractmetafunction.cpp abstractmetafunction.h +abstractmetalang.cpp abstractmetalang.h abstractmetalang_helpers.h abstractmetalang_typedefs.h +abstractmetatype.cpp abstractmetatype.h +addedfunction.cpp addedfunction.h addedfunction_p.h +anystringview_helpers.cpp anystringview_helpers.h +apiextractor.cpp apiextractor.h apiextractorflags.h +apiextractorresult.cpp apiextractorresult.h +arraytypeentry.h +classdocumentation.cpp classdocumentation.h +codesnip.cpp codesnip.h +codesniphelpers.cpp codesniphelpers.h +complextypeentry.h +conditionalstreamreader.cpp conditionalstreamreader.h +configurabletypeentry.h +constantvaluetypeentry.h +containertypeentry.h +customconversion.cpp customconversion.h customconversion_typedefs.h +customtypenentry.h +debughelpers_p.h +dependency.h +documentation.cpp documentation.h +dotview.cpp dotview.h +enclosingclassmixin.cpp enclosingclassmixin.h +enumtypeentry.h +enumvaluetypeentry.h +exception.h +fileout.cpp fileout.h +flagstypeentry.h +functiontypeentry.h +graph.h +header_paths.h +include.cpp include.h +messages.cpp messages.h +modifications.cpp modifications.h modifications_typedefs.h +namespacetypeentry.h +objecttypeentry.h +optionsparser.cpp optionsparser.h +predefined_templates.cpp predefined_templates.h +primitivetypeentry.h +propertyspec.cpp propertyspec.h +pymethoddefentry.cpp pymethoddefentry.h +pythontypeentry.h +reporthandler.cpp reporthandler.h +smartpointertypeentry.h +sourcelocation.cpp sourcelocation.h +templateargumententry.h +textstream.cpp textstream.h +typedatabase.cpp typedatabase.h typedatabase_p.h typedatabase_typedefs.h +typedefentry.h +typeparser.cpp typeparser.h +typesystem.cpp typesystem.h typesystem_enums.h typesystem_typedefs.h +typesystemparser.cpp typesystemparser_p.h +usingmember.h +valuetypeentry.h +varargstypeentry.h +voidtypeentry.h +xmlutils.cpp xmlutils.h xmlutils_libxslt.h xmlutils_qt.h # Clang -clangparser/compilersupport.cpp -clangparser/clangparser.cpp -clangparser/clangbuilder.cpp -clangparser/clangdebugutils.cpp -clangparser/clangutils.cpp +clangparser/clangbuilder.cpp clangparser/clangbuilder.h +clangparser/clangdebugutils.cpp clangparser/clangdebugutils.h +clangparser/clangparser.cpp clangparser/clangparser.h +clangparser/clangutils.cpp clangparser/clangutils.h +clangparser/compilersupport.cpp clangparser/compilersupport.h # Old parser -parser/typeinfo.cpp -parser/codemodel.cpp -parser/enumvalue.cpp -xmlutils.cpp +parser/codemodel.cpp parser/codemodel.h parser/codemodel_fwd.h parser/codemodel_enums.h +parser/enumvalue.cpp parser/enumvalue.h +parser/typeinfo.cpp parser/typeinfo.h ) -find_package(Qt${QT_MAJOR_VERSION}Xml 6.0) find_package(LibXml2 2.6.32) find_package(LibXslt 1.1.19) @@ -73,7 +105,7 @@ target_include_directories(apiextractor PRIVATE ${CLANG_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/parser) -target_link_libraries(apiextractor PUBLIC Qt${QT_MAJOR_VERSION}::Core) +target_link_libraries(apiextractor PUBLIC Qt::Core) target_link_libraries(apiextractor PRIVATE libclang) if (HAS_LIBXSLT) @@ -86,9 +118,10 @@ if (HAS_LIBXSLT) endif() if (NOT DISABLE_DOCSTRINGS) - target_sources(apiextractor PRIVATE docparser.cpp - doxygenparser.cpp - qtdocparser.cpp) + target_sources(apiextractor PRIVATE + docparser.cpp docparser.h + doxygenparser.cpp doxygenparser.h + qtdocparser.cpp qtdocparser.h) endif() target_compile_definitions(apiextractor @@ -98,7 +131,7 @@ target_compile_definitions(apiextractor set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE) if (BUILD_TESTS) - find_package(Qt${QT_MAJOR_VERSION}Test 6.0 REQUIRED) + find_package(Qt6 REQUIRED COMPONENTS Test) set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests) enable_testing() add_subdirectory(tests) diff --git a/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp b/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp index a34cfde9f..05cebe10a 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "abstractmetaargument.h" +#include "abstractmetatype.h" #include "documentation.h" #include "qtcompat.h" @@ -37,9 +38,9 @@ AbstractMetaArgument::AbstractMetaArgument(const AbstractMetaArgument &) = defau AbstractMetaArgument &AbstractMetaArgument::operator=(const AbstractMetaArgument &) = default; -AbstractMetaArgument::AbstractMetaArgument(AbstractMetaArgument &&) = default; +AbstractMetaArgument::AbstractMetaArgument(AbstractMetaArgument &&) noexcept = default; -AbstractMetaArgument &AbstractMetaArgument::operator=(AbstractMetaArgument &&) = default; +AbstractMetaArgument &AbstractMetaArgument::operator=(AbstractMetaArgument &&) noexcept = default; const AbstractMetaType &AbstractMetaArgument::type() const { @@ -57,6 +58,11 @@ const AbstractMetaType &AbstractMetaArgument::modifiedType() const return d->m_modifiedType; } +bool AbstractMetaArgument::isTypeModified() const +{ + return modifiedType() != type(); +} + bool AbstractMetaArgument::isModifiedRemoved() const { return d->m_modifiedRemoved; @@ -185,7 +191,7 @@ QDebug operator<<(QDebug d, const AbstractMetaArgument *aa) d.noquote(); d.nospace(); d << "AbstractMetaArgument("; - if (aa) + if (aa != nullptr) d << aa->toString(); else d << '0'; diff --git a/sources/shiboken6/ApiExtractor/abstractmetaargument.h b/sources/shiboken6/ApiExtractor/abstractmetaargument.h index ef68b8687..38402e369 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetaargument.h +++ b/sources/shiboken6/ApiExtractor/abstractmetaargument.h @@ -4,15 +4,11 @@ #ifndef ABSTRACTMETAARGUMENT_H #define ABSTRACTMETAARGUMENT_H -#include "abstractmetalang_typedefs.h" -#include "abstractmetatype.h" -#include "typesystem_enums.h" -#include "typesystem_typedefs.h" - #include <QtCore/QSharedDataPointer> QT_FORWARD_DECLARE_CLASS(QDebug) +class AbstractMetaType; class AbstractMetaArgumentData; class Documentation; @@ -23,15 +19,14 @@ public: ~AbstractMetaArgument(); AbstractMetaArgument(const AbstractMetaArgument &); AbstractMetaArgument &operator=(const AbstractMetaArgument &); - AbstractMetaArgument(AbstractMetaArgument &&); - AbstractMetaArgument &operator=(AbstractMetaArgument &&); - + AbstractMetaArgument(AbstractMetaArgument &&) noexcept; + AbstractMetaArgument &operator=(AbstractMetaArgument &&) noexcept; const AbstractMetaType &type() const; void setType(const AbstractMetaType &type); void setModifiedType(const AbstractMetaType &type); const AbstractMetaType &modifiedType() const; - bool isTypeModified() const { return modifiedType() != type(); } + bool isTypeModified() const; bool isModifiedRemoved() const; void setModifiedRemoved(bool v); diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp index 1391a7b0a..fa0767a62 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(); @@ -428,15 +461,15 @@ FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments, + clang::languageLevelOption(level)); } FileModelItem result = clang::parse(arguments, addCompilerSupportArguments, - clangFlags, builder) + level, clangFlags, builder) ? builder.dom() : FileModelItem(); const clang::BaseVisitor::Diagnostics &diagnostics = builder.diagnostics(); - if (const 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,11 +1569,13 @@ 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); + if (!inheritTemplate(metaClass, templ, info)) + return false; metaClass->typeEntry()->setBaseContainerType(templ->typeEntry()); return true; } @@ -1524,15 +1592,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 +1629,7 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) } else { QString message; QTextStream(&message) << "Class \"" << defaultSuperclassName - << "\" specified as \"default-superclass\" of \"" << metaClass->name() + << R"(" specified as "default-superclass" of ")" << metaClass->name() << "\" could not be found in the code model."; qCWarning(lcShiboken, "%s", qPrintable(message)); } @@ -1571,7 +1639,7 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) } void AbstractMetaBuilderPrivate::traverseEnums(const ScopeModelItem &scopeItem, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, const QStringList &enumsDeclarations) { const EnumList &enums = scopeItem->enums(); @@ -1619,7 +1687,7 @@ bool AbstractMetaBuilderPrivate::traverseAddedGlobalFunction(const AddedFunction AbstractMetaFunction * AbstractMetaBuilderPrivate::traverseAddedFunctionHelper(const AddedFunctionPtr &addedFunc, - AbstractMetaClass *metaClass /* = nullptr */, + const AbstractMetaClassPtr &metaClass /* = {} */, QString *errorMessage) { auto returnType = translateType(addedFunc->returnType(), metaClass, {}, errorMessage); @@ -1631,7 +1699,7 @@ AbstractMetaFunction * return nullptr; } - auto metaFunction = new AbstractMetaFunction(addedFunc); + auto *metaFunction = new AbstractMetaFunction(addedFunc); metaFunction->setType(returnType.value()); metaFunction->setFunctionType(functionTypeFromName(addedFunc->name())); @@ -1688,7 +1756,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 +1772,7 @@ AbstractMetaFunction * } bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunctionPtr &addedFunc, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, QString *errorMessage) { AbstractMetaFunction *metaFunction = @@ -1713,11 +1782,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 +1796,7 @@ bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunction metaFunction->setDeclaringClass(metaClass); metaFunction->setImplementingClass(metaClass); - metaClass->addFunction(AbstractMetaFunctionCPtr(metaFunction)); + AbstractMetaClass::addFunction(metaClass, AbstractMetaFunctionCPtr(metaFunction)); metaClass->setHasNonPrivateConstructor(true); return true; } @@ -1743,7 +1812,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 +1832,7 @@ static inline QString qualifiedFunctionSignatureWithType(const FunctionModelItem { QString result = functionItem->type().toString() + u' '; if (!className.isEmpty()) - result += className + colonColon(); + result += className + u"::"_s; result += functionSignature(functionItem); return result; } @@ -1875,9 +1944,48 @@ static bool applyArrayArgumentModifications(const FunctionModificationList &func return true; } +// Create the meta type for a view (std::string_view -> std::string) +static AbstractMetaType createViewOnType(const AbstractMetaType &metaType, + const TypeEntryCPtr &viewOnTypeEntry) +{ + auto result = metaType; + result.setTypeEntry(viewOnTypeEntry); + if (!metaType.isContainer() || !viewOnTypeEntry->isContainer()) + return result; + // For containers, when sth with several template parameters + // (std::span<T, int N>) is mapped onto a std::vector<T>, + // remove the superfluous template parameters and strip 'const'. + const auto vcte = std::static_pointer_cast<const ContainerTypeEntry>(viewOnTypeEntry); + const auto &instantiations = metaType.instantiations(); + AbstractMetaTypeList viewInstantiations; + const auto size = std::min(vcte->templateParameterCount(), instantiations.size()); + for (qsizetype i = 0; i < size; ++i) { + auto ins = instantiations.at(i); + ins.setConstant(false); + viewInstantiations.append(ins); + } + result.setInstantiations(viewInstantiations); + return result; +} + +void AbstractMetaBuilderPrivate::rejectFunction(const FunctionModelItem &functionItem, + const AbstractMetaClassPtr ¤tClass, + AbstractMetaBuilder::RejectReason reason, + const QString &rejectReason) +{ + QString sortKey; + if (currentClass) + sortKey += currentClass->typeEntry()->qualifiedCppName() + u"::"_s; + sortKey += functionSignature(functionItem); // Sort without return type + const QString signatureWithType = functionItem->type().toString() + u' ' + sortKey; + m_rejectedFunctions.insert({reason, signatureWithType, sortKey, rejectReason}); +} + AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const FunctionModelItem &functionItem, - AbstractMetaClass *currentClass) + const AbstractMetaClassPtr ¤tClass) { + const auto *tdb = TypeDatabase::instance(); + if (!functionItem->templateParameters().isEmpty()) return nullptr; @@ -1918,20 +2026,17 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio } } // PySide extensions - // Store original signature with unresolved typedefs for message/log purposes - const QString originalQualifiedSignatureWithReturn = - qualifiedFunctionSignatureWithType(functionItem, className); - QString rejectReason; - if (TypeDatabase::instance()->isFunctionRejected(className, functionName, &rejectReason)) { - m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); + if (tdb->isFunctionRejected(className, functionName, &rejectReason)) { + rejectFunction(functionItem, currentClass, + AbstractMetaBuilder::GenerationDisabled, rejectReason); return nullptr; } - const QString &signature = functionSignature(functionItem); - const bool rejected = - TypeDatabase::instance()->isFunctionRejected(className, signature, &rejectReason); - if (rejected) { + const QString &signature = functionSignature(functionItem); + if (tdb->isFunctionRejected(className, signature, &rejectReason)) { + rejectFunction(functionItem, currentClass, + AbstractMetaBuilder::GenerationDisabled, rejectReason); if (ReportHandler::isDebug(ReportHandler::MediumDebug)) { qCInfo(lcShiboken, "%s::%s was rejected by the type database (%s).", qPrintable(className), qPrintable(signature), qPrintable(rejectReason)); @@ -1942,46 +2047,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 +2080,30 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio metaFunction->setType(AbstractMetaType::createVoid()); break; case AbstractMetaFunction::ConstructorFunction: - metaFunction->setExplicit(functionItem->isExplicit()); metaFunction->setName(currentClass->name()); metaFunction->setType(AbstractMetaType::createVoid()); break; default: { TypeInfo returnType = functionItem->type(); - if (TypeDatabase::instance()->isReturnTypeRejected(className, returnType.toString(), &rejectReason)) { - m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); + if (tdb->isReturnTypeRejected(className, returnType.toString(), &rejectReason)) { + rejectFunction(functionItem, currentClass, + AbstractMetaBuilder::GenerationDisabled, rejectReason); delete metaFunction; return nullptr; } - auto type = translateType(returnType, currentClass, {}, &errorMessage); + TranslateTypeFlags flags; + if (functionItem->scopeResolution()) + flags.setFlag(AbstractMetaBuilder::NoClassScopeLookup); + auto type = translateType(returnType, currentClass, flags, &errorMessage); if (!type.has_value()) { const QString reason = msgUnmatchedReturnType(functionItem, errorMessage); + const QString signature = qualifiedFunctionSignatureWithType(functionItem, className); qCWarning(lcShiboken, "%s", - qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason))); - m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn, AbstractMetaBuilder::UnmatchedReturnType); + qPrintable(msgSkippingFunction(functionItem, signature, reason))); + rejectFunction(functionItem, currentClass, + AbstractMetaBuilder::UnmatchedReturnType, reason); delete metaFunction; return nullptr; } @@ -2020,6 +2114,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 +2130,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 +2174,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio auto viewOnTypeEntry = metaType.typeEntry()->viewOn(); if (viewOnTypeEntry != nullptr && metaType.indirections() == 0 && metaType.arrayElementType() == nullptr - && !metaType.hasInstantiations()) { - auto viewOn = metaType; - viewOn.setTypeEntry(viewOnTypeEntry); - metaType.setViewOn(viewOn); + && (!metaType.hasInstantiations() || metaType.isContainer())) { + metaType.setViewOn(createViewOnType(metaType, viewOnTypeEntry)); } AbstractMetaArgument metaArgument; @@ -2084,15 +2191,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 +2248,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 +2304,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 +2314,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 +2332,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 +2344,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 +2367,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 +2391,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 +2414,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 +2425,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 +2436,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 +2450,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 +2481,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 +2504,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 +2549,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 +2565,7 @@ void AbstractMetaBuilderPrivate::fixSmartPointers() std::optional<AbstractMetaType> AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei, - const AbstractMetaClass *currentClass, + const AbstractMetaClassCPtr ¤tClass, TranslateTypeFlags flags, QString *errorMessage) { @@ -2464,9 +2578,16 @@ static bool isNumber(const QString &s) [](QChar c) { return c.isDigit(); }); } +// A type entry relevant only for non type template "X<5>" +static bool isNonTypeTemplateArgument(const TypeEntryCPtr &te) +{ + const auto type = te->type(); + return type == TypeEntry::EnumValue || type == TypeEntry::ConstantValueType; +} + std::optional<AbstractMetaType> AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo &_typei, - const AbstractMetaClass *currentClass, + const AbstractMetaClassCPtr ¤tClass, AbstractMetaBuilderPrivate *d, TranslateTypeFlags flags, QString *errorMessageIn) @@ -2493,10 +2614,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 +2641,7 @@ std::optional<AbstractMetaType> bool isConstCharStarCase = oneDimensionalArrayOfUnspecifiedSize && typeInfo.qualifiedName().size() == 1 - && typeInfo.qualifiedName().at(0) == QStringLiteral("char") + && typeInfo.qualifiedName().at(0) == "char"_L1 && typeInfo.indirections() == 0 && typeInfo.isConstant() && typeInfo.referenceType() == NoReference @@ -2550,7 +2671,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 +2684,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 +2705,7 @@ std::optional<AbstractMetaType> return {}; } - QString qualifiedName = qualifierList.join(colonColon()); + QString qualifiedName = qualifierList.join(u"::"_s); QString name = qualifierList.takeLast(); // 4. Special case QFlags (include instantiation in name) @@ -2592,14 +2714,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 +2741,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 +2778,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 +2813,7 @@ std::optional<AbstractMetaType> std::optional<AbstractMetaType> AbstractMetaBuilder::translateType(const TypeInfo &_typei, - AbstractMetaClass *currentClass, + const AbstractMetaClassPtr ¤tClass, TranslateTypeFlags flags, QString *errorMessage) { @@ -2690,7 +2824,7 @@ std::optional<AbstractMetaType> std::optional<AbstractMetaType> AbstractMetaBuilder::translateType(const QString &t, - AbstractMetaClass *currentClass, + const AbstractMetaClassPtr ¤tClass, TranslateTypeFlags flags, QString *errorMessageIn) { @@ -2720,7 +2854,7 @@ qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringV // This is a very lame way to handle expression evaluation, // but it is not critical and will do for the time being. - static const QRegularExpression variableNameRegExp(QStringLiteral("^[a-zA-Z_][a-zA-Z0-9_]*$")); + static const QRegularExpression variableNameRegExp("^[a-zA-Z_][a-zA-Z0-9_]*$"_L1); Q_ASSERT(variableNameRegExp.isValid()); if (!variableNameRegExp.match(stringValue).hasMatch()) { ok = true; @@ -2733,7 +2867,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 +2891,10 @@ static bool isUnderQualifiedSpec(QStringView qualifiedType, QStringView candidat } QString AbstractMetaBuilder::fixEnumDefault(const AbstractMetaType &type, - const QString &expr) const + const QString &expr, + const AbstractMetaClassCPtr &klass) const { - return d->fixEnumDefault(type, expr); + return d->fixEnumDefault(type, expr, klass); } void AbstractMetaBuilder::setCodeModelTestMode(bool b) @@ -2770,7 +2905,7 @@ void AbstractMetaBuilder::setCodeModelTestMode(bool b) // Helper to fix a simple default value (field or enum reference) in a // class context. QString AbstractMetaBuilderPrivate::fixSimpleDefaultValue(QStringView expr, - const AbstractMetaClass *klass) const + const AbstractMetaClassCPtr &klass) const { const QString field = qualifyStaticField(klass, expr); @@ -2789,7 +2924,7 @@ QString AbstractMetaBuilderPrivate::fixSimpleDefaultValue(QStringView expr, // see TestResolveType::testFixDefaultArguments() QString AbstractMetaBuilderPrivate::fixDefaultValue(QString expr, const AbstractMetaType &type, - const AbstractMetaClass *implementingClass) const + const AbstractMetaClassCPtr &implementingClass) const { expr.replace(u'\n', u' '); // breaks signature parser @@ -2797,13 +2932,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 +2992,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 +3007,7 @@ QString AbstractMetaBuilderPrivate::fixDefaultValue(QString expr, const Abstract } QString AbstractMetaBuilder::fixDefaultValue(const QString &expr, const AbstractMetaType &type, - const AbstractMetaClass *c) const + const AbstractMetaClassCPtr &c) const { return d->fixDefaultValue(expr, type, c); } @@ -2883,23 +3018,24 @@ bool AbstractMetaBuilderPrivate::isEnum(const FileModelItem &dom, const QStringL return item && item->kind() == _EnumModelItem::__node_kind; } -AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString &name, - const AbstractMetaClass *context, - TypeInfo *info, - 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 +3044,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 +3066,7 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString & } AbstractMetaClassCList - AbstractMetaBuilderPrivate::getBaseClasses(const AbstractMetaClass *metaClass) const + AbstractMetaBuilderPrivate::getBaseClasses(const AbstractMetaClassCPtr &metaClass) const { // Shortcut if inheritance has already been set up if (metaClass->inheritanceDone() || !metaClass->needsInheritanceSetup()) @@ -2938,11 +3074,9 @@ AbstractMetaClassCList AbstractMetaClassCList baseClasses; const QStringList &baseClassNames = metaClass->baseClassNames(); for (const QString& parent : baseClassNames) { - AbstractMetaClass *cls = nullptr; - if (parent.contains(u'<')) - cls = findTemplateClass(parent, metaClass); - else - cls = AbstractMetaClass::findClass(m_metaClasses, parent); + const auto cls = parent.contains(u'<') + ? findTemplateClass(parent, metaClass) + : AbstractMetaClass::findClass(m_metaClasses, parent); if (cls) baseClasses << cls; @@ -2962,7 +3096,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,83 +3126,106 @@ std::optional<AbstractMetaType> return returned; } -AbstractMetaClass * - AbstractMetaBuilder::inheritTemplateClass(ComplexTypeEntry *te, - const AbstractMetaClass *templateClass, - const AbstractMetaTypeList &templateTypes, - InheritTemplateFlags flags) +AbstractMetaClassPtr + AbstractMetaBuilder::inheritTemplateClass(const ComplexTypeEntryPtr &te, + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaTypeList &templateTypes) { - auto result = std::make_unique<AbstractMetaClass>(); + auto result = std::make_shared<AbstractMetaClass>(); result->setTypeDef(true); result->setTypeEntry(te); - if (!AbstractMetaBuilderPrivate::inheritTemplate(result.get(), templateClass, - templateTypes, flags)) { - return nullptr; + if (!AbstractMetaBuilderPrivate::inheritTemplate(result, templateClass, + templateTypes)) { + return {}; } - AbstractMetaBuilderPrivate::inheritTemplateFunctions(result.get()); - return result.release(); + AbstractMetaBuilderPrivate::inheritTemplateFunctions(result); + return result; } -bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, - const AbstractMetaClass *templateClass, + +static std::optional<AbstractMetaType> + inheritTemplateParameter(const AbstractMetaClassPtr &subclass, + const AbstractMetaClassCPtr &templateClass, + const TypeInfo &info, QString *errorMessage) +{ + QString typeName = info.qualifiedName().join("::"_L1); + TypeDatabase *typeDb = TypeDatabase::instance(); + TypeEntryPtr t; + // Check for a non-type template integer parameter, that is, for a base + // "template <int R, int C> Matrix<R, C>" and subclass + // "typedef Matrix<2,3> Matrix2x3;". If so, create dummy entries of + // EnumValueTypeEntry for the integer values encountered on the fly. + if (isNumber(typeName)) { + t = typeDb->findType(typeName); + if (!t) { + auto parent = typeSystemTypeEntry(subclass->typeEntry()); + t = TypeDatabase::instance()->addConstantValueTypeEntry(typeName, parent); + } + } else { + QStringList possibleNames; + possibleNames << subclass->qualifiedCppName() + "::"_L1 + typeName; + possibleNames << templateClass->qualifiedCppName() + "::"_L1 + typeName; + if (subclass->enclosingClass()) + possibleNames << subclass->enclosingClass()->qualifiedCppName() + "::"_L1 + typeName; + possibleNames << typeName; + + for (const QString &possibleName : std::as_const(possibleNames)) { + t = typeDb->findType(possibleName); + if (t) + break; + } + } + + if (!t) { + *errorMessage = msgIgnoringTemplateParameter(typeName, + "The corresponding type was not found in the typesystem."); + return std::nullopt; + } + + if (t->isContainer()) { + *errorMessage = msgIgnoringTemplateParameter(typeName, + "Template inheritance from nested containers is not supported"); + return std::nullopt; + } + AbstractMetaType result(t); + result.setConstant(info.isConstant()); + result.setReferenceType(info.referenceType()); + result.setIndirectionsV(info.indirectionsV()); + result.decideUsagePattern(); + return result; +} + +bool AbstractMetaBuilderPrivate::inheritTemplate(const AbstractMetaClassPtr &subclass, + const AbstractMetaClassCPtr &templateClass, const TypeInfo &info) { AbstractMetaTypeList templateTypes; + QString errorMessage; for (const TypeInfo &i : info.instantiations()) { - QString typeName = i.qualifiedName().join(colonColon()); - TypeDatabase *typeDb = TypeDatabase::instance(); - TypeEntry *t = nullptr; - // Check for a non-type template integer parameter, that is, for a base - // "template <int R, int C> Matrix<R, C>" and subclass - // "typedef Matrix<2,3> Matrix2x3;". If so, create dummy entries of - // EnumValueTypeEntry for the integer values encountered on the fly. - if (isNumber(typeName)) { - t = typeDb->findType(typeName); - if (!t) { - auto parent = subclass->typeEntry()->typeSystemTypeEntry(); - t = TypeDatabase::instance()->addConstantValueTypeEntry(typeName, parent); - } + const auto typeO = inheritTemplateParameter(subclass, templateClass, i, &errorMessage); + if (typeO.has_value()) { + templateTypes.append(typeO.value()); } else { - QStringList possibleNames; - possibleNames << subclass->qualifiedCppName() + colonColon() + typeName; - possibleNames << templateClass->qualifiedCppName() + colonColon() + typeName; - if (subclass->enclosingClass()) - possibleNames << subclass->enclosingClass()->qualifiedCppName() + colonColon() + typeName; - possibleNames << typeName; - - for (const QString &possibleName : qAsConst(possibleNames)) { - t = typeDb->findType(possibleName); - if (t) - break; - } - } - - if (t) { - AbstractMetaType temporaryType(t); - temporaryType.setConstant(i.isConstant()); - temporaryType.setReferenceType(i.referenceType()); - temporaryType.setIndirectionsV(i.indirectionsV()); - temporaryType.decideUsagePattern(); - templateTypes << temporaryType; - } else { - qCWarning(lcShiboken).noquote().nospace() - << "Ignoring template parameter " << typeName << " from " - << info.toString() << ". The corresponding type was not found in the typesystem."; + errorMessage = msgInheritTemplateIssue(subclass, info, errorMessage); + qCWarning(lcShiboken, "%s", qPrintable(errorMessage)); } } + if (templateTypes.isEmpty()) { + errorMessage = msgInheritTemplateIssue(subclass, info, + "No template parameters could be inherited"_L1); + qCWarning(lcShiboken, "%s", qPrintable(errorMessage)); + return false; + } return inheritTemplate(subclass, templateClass, templateTypes); } -bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, - const AbstractMetaClass *templateClass, - const AbstractMetaTypeList &templateTypes, - InheritTemplateFlags flags) +bool AbstractMetaBuilderPrivate::inheritTemplate(const AbstractMetaClassPtr &subclass, + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaTypeList &templateTypes) { subclass->setTemplateBaseClass(templateClass); - if (flags.testFlag(InheritTemplateFlag::SetEnclosingClass)) - subclass->setEnclosingClass(templateClass->enclosingClass()); subclass->setTemplateBaseClassInstantiations(templateTypes); subclass->setBaseClass(templateClass->baseClass()); return true; @@ -3112,11 +3269,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 +3290,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 +3327,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 +3336,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 +3350,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 +3371,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 +3382,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 +3397,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 +3408,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 +3437,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 +3474,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 +3501,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 +3515,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 +3529,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 +3564,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 +3613,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 +3668,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 +3722,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()); diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder.h index 563db8f6e..20261ed3c 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.h +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.h @@ -8,6 +8,7 @@ #include "apiextractorflags.h" #include "header_paths.h" #include "typesystem_enums.h" +#include "typesystem_typedefs.h" #include "clangparser/compilersupport.h" @@ -28,13 +29,15 @@ class TypeEntry; class AbstractMetaBuilder { public: + Q_DISABLE_COPY_MOVE(AbstractMetaBuilder) + enum RejectReason { NotInTypeSystem, GenerationDisabled, RedefinedToNotClass, UnmatchedArgumentType, UnmatchedReturnType, - ApiIncompatible, + UnmatchedOperator, Deprecated, NoReason }; @@ -50,7 +53,8 @@ public: AbstractMetaClassList takeSmartPointers(); const AbstractMetaFunctionCList &globalFunctions() const; const AbstractMetaEnumList &globalEnums() const; - const QHash<const TypeEntry *, AbstractMetaEnum> &typeEntryToEnumsHash() const; + const QHash<TypeEntryCPtr, AbstractMetaEnum> &typeEntryToEnumsHash() const; + const QMultiHash<QString, QString> &typedefTargetToName() const; bool build(const QByteArrayList &arguments, ApiExtractorFlags apiExtractorFlags = {}, @@ -74,15 +78,17 @@ public: void setApiExtractorFlags(ApiExtractorFlags flags); enum TranslateTypeFlag { - DontResolveType = 0x1 + DontResolveType = 0x1, + TemplateArgument = 0x2, + NoClassScopeLookup = 0x4 }; Q_DECLARE_FLAGS(TranslateTypeFlags, TranslateTypeFlag); static std::optional<AbstractMetaType> - translateType(const TypeInfo &_typei, AbstractMetaClass *currentClass = nullptr, + translateType(const TypeInfo &_typei, const AbstractMetaClassPtr ¤tClass = {}, TranslateTypeFlags flags = {}, QString *errorMessage = nullptr); static std::optional<AbstractMetaType> - translateType(const QString &t, AbstractMetaClass *currentClass = nullptr, + translateType(const QString &t, const AbstractMetaClassPtr ¤tClass = {}, TranslateTypeFlags flags = {}, QString *errorMessage = nullptr); /// Performs a template specialization of the function. @@ -93,11 +99,10 @@ public: inheritTemplateFunction(const AbstractMetaFunctionCPtr &function, const AbstractMetaTypeList &templateTypes); - static AbstractMetaClass * - inheritTemplateClass(ComplexTypeEntry *te, - const AbstractMetaClass *templateClass, - const AbstractMetaTypeList &templateTypes, - InheritTemplateFlags flags = {}); + static AbstractMetaClassPtr + inheritTemplateClass(const ComplexTypeEntryPtr &te, + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaTypeList &templateTypes); /// Performs a template specialization of the member function. /// \param function Member function @@ -108,23 +113,24 @@ public: static AbstractMetaFunctionPtr inheritTemplateMember(const AbstractMetaFunctionCPtr &function, const AbstractMetaTypeList &templateTypes, - const AbstractMetaClass *templateClass, - AbstractMetaClass *subclass); + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaClassPtr &subclass); static QString getSnakeCaseName(const QString &name); // Names under which an item will be registered to Python depending on snakeCase static QStringList definitionNames(const QString &name, TypeSystem::SnakeCase snakeCase); - static QString resolveScopePrefix(const AbstractMetaClass *scope, + static QString resolveScopePrefix(const AbstractMetaClassCPtr &scope, QStringView value); static bool dontFixDefaultValue(QStringView expr); // For testing purposes QString fixDefaultValue(const QString &expr, const AbstractMetaType &type, - const AbstractMetaClass *) const; - QString fixEnumDefault(const AbstractMetaType &type, const QString &expr) const; + const AbstractMetaClassCPtr &) const; + QString fixEnumDefault(const AbstractMetaType &type, const QString &expr, + const AbstractMetaClassCPtr & = {}) const; static void setCodeModelTestMode(bool b); diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp index f41104a77..68eef737a 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp @@ -9,6 +9,8 @@ #include "enumtypeentry.h" #include "flagstypeentry.h" +using namespace Qt::StringLiterals; + using QStringViewList = QList<QStringView>; // Return a prefix to fully qualify value, eg: @@ -19,7 +21,7 @@ static QString resolveScopePrefixHelper(const QStringViewList &scopeList, { QString name; for (qsizetype i = scopeList.size() - 1 ; i >= 0; --i) { - const QString prefix = scopeList.at(i).toString() + u"::"_qs; + const QString prefix = scopeList.at(i).toString() + u"::"_s; if (value.startsWith(prefix)) name.clear(); else @@ -28,14 +30,14 @@ static QString resolveScopePrefixHelper(const QStringViewList &scopeList, return name; } -QString AbstractMetaBuilder::resolveScopePrefix(const AbstractMetaClass *scope, +QString AbstractMetaBuilder::resolveScopePrefix(const AbstractMetaClassCPtr &scope, QStringView value) { if (!scope) return {}; const QString &qualifiedCppName = scope->qualifiedCppName(); const QStringViewList scopeList = - QStringView{qualifiedCppName}.split(u"::"_qs, Qt::SkipEmptyParts); + QStringView{qualifiedCppName}.split(u"::"_s, Qt::SkipEmptyParts); return resolveScopePrefixHelper(scopeList, value); } @@ -43,13 +45,13 @@ QString AbstractMetaBuilder::resolveScopePrefix(const AbstractMetaClass *scope, static QString resolveEnumValueScopePrefix(const AbstractMetaEnum &metaEnum, QStringView value) { - const AbstractMetaClass *scope = metaEnum.enclosingClass(); + AbstractMetaClassCPtr scope = metaEnum.enclosingClass(); if (!scope) return {}; // global enum, value should work as is const QString &qualifiedCppName = scope->qualifiedCppName(); const QString &enumName = metaEnum.name(); QStringViewList parts = - QStringView{qualifiedCppName}.split(u"::"_qs, Qt::SkipEmptyParts); + QStringView{qualifiedCppName}.split(u"::"_s, Qt::SkipEmptyParts); // Append the type (as required for enum classes) unless it is an anonymous enum. if (!metaEnum.isAnonymous()) parts.append(QStringView{enumName}); @@ -83,21 +85,26 @@ static bool isFloatConstant(const QStringView expr) // to the default value, making it usable from Python wrapper code outside the // owner class hierarchy. See TestEnum::testEnumDefaultValues(). QString AbstractMetaBuilderPrivate::fixEnumDefault(const AbstractMetaType &type, - const QString &expr) const + const QString &expr, + const AbstractMetaClassCPtr &klass) const { // QFlags construct from integers, do not fix that if (isIntegerConstant(expr)) return expr; - const auto *typeEntry = type.typeEntry(); - const EnumTypeEntry *enumTypeEntry = nullptr; - const FlagsTypeEntry *flagsTypeEntry = nullptr; + const QString field = qualifyStaticField(klass, expr); + if (!field.isEmpty()) + return field; + + const auto typeEntry = type.typeEntry(); + EnumTypeEntryCPtr enumTypeEntry; + FlagsTypeEntryCPtr flagsTypeEntry; if (typeEntry->isFlags()) { - flagsTypeEntry = static_cast<const FlagsTypeEntry *>(typeEntry); + flagsTypeEntry = std::static_pointer_cast<const FlagsTypeEntry>(typeEntry); enumTypeEntry = flagsTypeEntry->originator(); } else { Q_ASSERT(typeEntry->isEnum()); - enumTypeEntry = static_cast<const EnumTypeEntry *>(typeEntry); + enumTypeEntry = std::static_pointer_cast<const EnumTypeEntry>(typeEntry); } // Use the enum's qualified name (would otherwise be "QFlags<Enum>") if (!enumTypeEntry->qualifiedCppName().contains(u"::")) @@ -157,7 +164,7 @@ QString AbstractMetaBuilderPrivate::fixEnumDefault(const AbstractMetaType &type, qualified.prepend(resolveEnumValueScopePrefix(metaEnum, token)); qualifiedTokens.append(qualified); } - const QString qualifiedExpression = qualifiedTokens.join(u" | "_qs); + const QString qualifiedExpression = qualifiedTokens.join(u" | "_s); if (!typeCast) return qualifiedExpression; @@ -175,7 +182,7 @@ bool AbstractMetaBuilder::dontFixDefaultValue(QStringView expr) || isIntegerConstant(expr) || isFloatConstant(expr); } -QString AbstractMetaBuilderPrivate::qualifyStaticField(const AbstractMetaClass *c, +QString AbstractMetaBuilderPrivate::qualifyStaticField(const AbstractMetaClassCPtr &c, QStringView field) { if (!c || c->fields().isEmpty()) diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h index a64ae68b3..e65a4f176 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h @@ -10,25 +10,38 @@ #include "abstractmetalang.h" #include "abstractmetatype.h" #include "include.h" -#include "modifications.h" #include "typeparser.h" +#include "modifications_typedefs.h" +#include "typesystem_typedefs.h" #include <QtCore/QFileInfo> #include <QtCore/QList> #include <QtCore/QMap> +#include <QtCore/QMultiHash> #include <QtCore/QSet> #include <optional> +#include <set> class TypeDatabase; +struct RejectEntry +{ + AbstractMetaBuilder::RejectReason reason; + QString signature; + QString sortkey; + QString message; +}; + +bool operator<(const RejectEntry &re1, const RejectEntry &re2); + class AbstractMetaBuilderPrivate { public: struct TypeClassEntry { AbstractMetaType type; - const AbstractMetaClass *klass; + AbstractMetaClassCPtr klass; }; using TranslateTypeFlags = AbstractMetaBuilder::TranslateTypeFlags; @@ -36,7 +49,6 @@ public: Q_DISABLE_COPY(AbstractMetaBuilderPrivate) AbstractMetaBuilderPrivate(); - ~AbstractMetaBuilderPrivate(); static FileModelItem buildDom(QByteArrayList arguments, bool addCompilerSupportArguments, @@ -59,57 +71,66 @@ public: NamespaceModelItem currentScope() const { return m_scopes.constLast(); } - AbstractMetaClass *argumentToClass(const ArgumentModelItem &, - const AbstractMetaClass *currentClass); + AbstractMetaClassPtr argumentToClass(const ArgumentModelItem &, + const AbstractMetaClassCPtr ¤tClass); - void addAbstractMetaClass(AbstractMetaClass *cls, const _CodeModelItem *item); - AbstractMetaClass *traverseTypeDef(const FileModelItem &dom, + void addAbstractMetaClass(const AbstractMetaClassPtr &cls, const _CodeModelItem *item); + AbstractMetaClassPtr traverseTypeDef(const FileModelItem &dom, const TypeDefModelItem &typeDef, - AbstractMetaClass *currentClass); + const AbstractMetaClassPtr ¤tClass); + AbstractMetaClassPtr traverseTypeDefHelper(const FileModelItem &dom, + const TypeDefModelItem &typeDef, + const AbstractMetaClassPtr ¤tClass); void traverseTypesystemTypedefs(); - AbstractMetaClass *traverseClass(const FileModelItem &dom, + AbstractMetaClassPtr traverseClass(const FileModelItem &dom, const ClassModelItem &item, - AbstractMetaClass *currentClass); - void traverseScopeMembers(const ScopeModelItem &item, AbstractMetaClass *metaClass); + const AbstractMetaClassPtr ¤tClass); + void traverseScopeMembers(const ScopeModelItem &item, + const AbstractMetaClassPtr &metaClass); void traverseClassMembers(const ClassModelItem &scopeItem); - void traverseUsingMembers(AbstractMetaClass *metaClass); + void traverseUsingMembers(const AbstractMetaClassPtr &metaClass) const; void traverseNamespaceMembers(const NamespaceModelItem &scopeItem); - bool setupInheritance(AbstractMetaClass *metaClass); - AbstractMetaClass *traverseNamespace(const FileModelItem &dom, + bool setupInheritance(const AbstractMetaClassPtr &metaClass); + AbstractMetaClassPtr traverseNamespace(const FileModelItem &dom, const NamespaceModelItem &item); std::optional<AbstractMetaEnum> traverseEnum(const EnumModelItem &item, - AbstractMetaClass *enclosing, + const AbstractMetaClassPtr &enclosing, const QSet<QString> &enumsDeclarations); - void traverseEnums(const ScopeModelItem &item, AbstractMetaClass *parent, + void traverseEnums(const ScopeModelItem &item, const AbstractMetaClassPtr &parent, const QStringList &enumsDeclarations); AbstractMetaFunctionRawPtrList classFunctionList(const ScopeModelItem &scopeItem, AbstractMetaClass::Attributes *constructorAttributes, - AbstractMetaClass *currentClass); - void traverseFunctions(ScopeModelItem item, AbstractMetaClass *parent); + const AbstractMetaClassPtr ¤tClass); + void traverseFunctions(const ScopeModelItem& item, + const AbstractMetaClassPtr &parent); static void applyFunctionModifications(AbstractMetaFunction *func); - void traverseFields(const ScopeModelItem &item, AbstractMetaClass *parent); + void traverseFields(const ScopeModelItem &item, const AbstractMetaClassPtr &parent); bool traverseStreamOperator(const FunctionModelItem &functionItem, - AbstractMetaClass *currentClass); + const AbstractMetaClassPtr ¤tClass); void traverseOperatorFunction(const FunctionModelItem &item, - AbstractMetaClass *currentClass); + const AbstractMetaClassPtr ¤tClass); AbstractMetaFunction *traverseAddedFunctionHelper(const AddedFunctionPtr &addedFunc, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, QString *errorMessage); bool traverseAddedGlobalFunction(const AddedFunctionPtr &addedFunc, QString *errorMessage); bool traverseAddedMemberFunction(const AddedFunctionPtr &addedFunc, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, QString *errorMessage); - AbstractMetaFunction *traverseFunction(const FunctionModelItem &function, - AbstractMetaClass *currentClass); + void rejectFunction(const FunctionModelItem &functionItem, + const AbstractMetaClassPtr ¤tClass, + AbstractMetaBuilder::RejectReason reason, + const QString &rejectReason); + AbstractMetaFunction *traverseFunction(const FunctionModelItem &function, + const AbstractMetaClassPtr ¤tClass); std::optional<AbstractMetaField> traverseField(const VariableModelItem &field, - const AbstractMetaClass *cls); - void checkFunctionModifications(); + const AbstractMetaClassCPtr &cls); + void checkFunctionModifications() const; void registerHashFunction(const FunctionModelItem &functionItem, - AbstractMetaClass *currentClass); + const AbstractMetaClassPtr ¤tClass); void registerToStringCapabilityIn(const NamespaceModelItem &namespaceItem); void registerToStringCapability(const FunctionModelItem &functionItem, - AbstractMetaClass *currentClass); + const AbstractMetaClassPtr ¤tClass); /** * A conversion operator function should not have its owner class as @@ -123,50 +144,53 @@ public: */ static void fixReturnTypeOfConversionOperator(AbstractMetaFunction *metaFunction); - void parseQ_Properties(AbstractMetaClass *metaClass, const QStringList &declarations); - void setupEquals(AbstractMetaClass *metaClass); - void setupComparable(AbstractMetaClass *metaClass); - void setupExternalConversion(const AbstractMetaClass *cls); + void parseQ_Properties(const AbstractMetaClassPtr &metaClass, + const QStringList &declarations); + void setupEquals(const AbstractMetaClassPtr &metaClass); + void setupComparable(const AbstractMetaClassPtr &metaClass); + void setupExternalConversion(const AbstractMetaClassCPtr &cls); static bool isQualifiedCppIdentifier(QStringView e); QString fixDefaultValue(QString expr, const AbstractMetaType &type, - const AbstractMetaClass *) const; + const AbstractMetaClassCPtr &) const; QString fixSimpleDefaultValue(QStringView expr, - const AbstractMetaClass *klass) const; + const AbstractMetaClassCPtr &klass) const; - QString fixEnumDefault(const AbstractMetaType &type, const QString &expr) const; + QString fixEnumDefault(const AbstractMetaType &type, const QString &expr, + const AbstractMetaClassCPtr &) const; /// Qualify a static field name for default value expressions - static QString qualifyStaticField(const AbstractMetaClass *c, QStringView field); + static QString qualifyStaticField(const AbstractMetaClassCPtr &c, QStringView field); std::optional<AbstractMetaType> - translateType(const TypeInfo &type, const AbstractMetaClass *currentClass, + translateType(const TypeInfo &type, const AbstractMetaClassCPtr ¤tClass, TranslateTypeFlags flags = {}, QString *errorMessage = nullptr); static std::optional<AbstractMetaType> - translateTypeStatic(const TypeInfo &type, const AbstractMetaClass *current, + translateTypeStatic(const TypeInfo &type, const AbstractMetaClassCPtr ¤t, AbstractMetaBuilderPrivate *d = nullptr, TranslateTypeFlags flags = {}, QString *errorMessageIn = nullptr); - static TypeEntries findTypeEntriesHelper(const QString &qualifiedName, const QString &name, - const AbstractMetaClass *currentClass = nullptr, - AbstractMetaBuilderPrivate *d = nullptr); - static TypeEntries findTypeEntries(const QString &qualifiedName, const QString &name, - const AbstractMetaClass *currentClass = nullptr, - AbstractMetaBuilderPrivate *d = nullptr, - QString *errorMessage = nullptr); + static TypeEntryCList findTypeEntriesHelper(const QString &qualifiedName, const QString &name, + TranslateTypeFlags flags = {}, + const AbstractMetaClassCPtr ¤tClass = {}, + AbstractMetaBuilderPrivate *d = nullptr); + static TypeEntryCList findTypeEntries(const QString &qualifiedName, const QString &name, + TranslateTypeFlags flags = {}, + const AbstractMetaClassCPtr ¤tClass = {}, + AbstractMetaBuilderPrivate *d = nullptr, + QString *errorMessage = nullptr); qint64 findOutValueFromString(const QString &stringValue, bool &ok); - AbstractMetaClass *findTemplateClass(const QString& name, const AbstractMetaClass *context, - TypeInfo *info = Q_NULLPTR, - ComplexTypeEntry **baseContainerType = Q_NULLPTR) const; - AbstractMetaClassCList getBaseClasses(const AbstractMetaClass *metaClass) const; + AbstractMetaClassPtr findTemplateClass(const QString& name, const AbstractMetaClassCPtr &context, + TypeInfo *info = nullptr, + ComplexTypeEntryPtr *baseContainerType = nullptr) const; + AbstractMetaClassCList getBaseClasses(const AbstractMetaClassCPtr &metaClass) const; - static bool inheritTemplate(AbstractMetaClass *subclass, - const AbstractMetaClass *templateClass, + static bool inheritTemplate(const AbstractMetaClassPtr &subclass, + const AbstractMetaClassCPtr &templateClass, const TypeInfo &info); - static bool inheritTemplate(AbstractMetaClass *subclass, - const AbstractMetaClass *templateClass, - const AbstractMetaTypeList &templateTypes, - InheritTemplateFlags flags = {}); + static bool inheritTemplate(const AbstractMetaClassPtr &subclass, + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaTypeList &templateTypes); static AbstractMetaFunctionPtr inheritTemplateFunction(const AbstractMetaFunctionCPtr &function, @@ -175,10 +199,10 @@ public: static AbstractMetaFunctionPtr inheritTemplateMember(const AbstractMetaFunctionCPtr &function, const AbstractMetaTypeList &templateTypes, - const AbstractMetaClass *templateClass, - AbstractMetaClass *subclass); + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaClassPtr &subclass); - static void inheritTemplateFunctions(AbstractMetaClass *subclass); + static void inheritTemplateFunctions(const AbstractMetaClassPtr &subclass); static std::optional<AbstractMetaType> inheritTemplateType(const AbstractMetaTypeList &templateTypes, const AbstractMetaType &metaType); @@ -187,31 +211,31 @@ public: static bool isEnum(const FileModelItem &dom, const QStringList &qualifiedName); void sortLists(); - void setInclude(TypeEntry *te, const QString &path) const; + void setInclude(const TypeEntryPtr &te, const QString &path) const; static void fixArgumentNames(AbstractMetaFunction *func, const FunctionModificationList &mods); - void fillAddedFunctions(AbstractMetaClass *metaClass); - const AbstractMetaClass *resolveTypeSystemTypeDef(const AbstractMetaType &t) const; + void fillAddedFunctions(const AbstractMetaClassPtr &metaClass); + AbstractMetaClassCPtr resolveTypeSystemTypeDef(const AbstractMetaType &t) const; void fixSmartPointers(); - AbstractMetaBuilder *q; + AbstractMetaBuilder *q = nullptr; AbstractMetaClassList m_metaClasses; AbstractMetaClassList m_templates; AbstractMetaClassList m_smartPointers; - QHash<const _CodeModelItem *, AbstractMetaClass *> m_itemToClass; - QHash<const AbstractMetaClass *, const _CodeModelItem *> m_classToItem; + QHash<const _CodeModelItem *, AbstractMetaClassPtr > m_itemToClass; + QHash<AbstractMetaClassCPtr, const _CodeModelItem *> m_classToItem; AbstractMetaFunctionCList m_globalFunctions; AbstractMetaEnumList m_globalEnums; - using RejectMap = QMap<QString, AbstractMetaBuilder::RejectReason>; + using RejectSet = std::set<RejectEntry>; - RejectMap m_rejectedClasses; - RejectMap m_rejectedEnums; - RejectMap m_rejectedFunctions; - RejectMap m_rejectedFields; + RejectSet m_rejectedClasses; + RejectSet m_rejectedEnums; + RejectSet m_rejectedFunctions; + RejectSet m_rejectedFields; - QHash<const TypeEntry *, AbstractMetaEnum> m_enums; + QHash<TypeEntryCPtr, AbstractMetaEnum> m_enums; QList<NamespaceModelItem> m_scopes; @@ -219,6 +243,7 @@ public: QFileInfoList m_globalHeaders; QStringList m_headerPaths; mutable QHash<QString, Include> m_resolveIncludeHash; + QMultiHash<QString, QString> m_typedefTargetToName; QList<TypeClassEntry> m_typeSystemTypeDefs; // look up metatype->class for type system typedefs ApiExtractorFlags m_apiExtractorFlags; bool m_skipDeprecated = false; diff --git a/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp index b912273bb..780170c22 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp @@ -11,6 +11,8 @@ #include <QtCore/QDebug> +#include <algorithm> + using namespace Qt::StringLiterals; class AbstractMetaEnumValueData : public QSharedData @@ -20,6 +22,7 @@ public: QString m_stringValue; EnumValue m_value; Documentation m_doc; + bool m_deprecated = false; }; AbstractMetaEnumValue::AbstractMetaEnumValue() : @@ -29,8 +32,8 @@ AbstractMetaEnumValue::AbstractMetaEnumValue() : AbstractMetaEnumValue::AbstractMetaEnumValue(const AbstractMetaEnumValue &) = default; AbstractMetaEnumValue &AbstractMetaEnumValue::operator=(const AbstractMetaEnumValue &) = default; -AbstractMetaEnumValue::AbstractMetaEnumValue(AbstractMetaEnumValue &&) = default; -AbstractMetaEnumValue &AbstractMetaEnumValue::operator=(AbstractMetaEnumValue &&) = default; +AbstractMetaEnumValue::AbstractMetaEnumValue(AbstractMetaEnumValue &&) noexcept = default; +AbstractMetaEnumValue &AbstractMetaEnumValue::operator=(AbstractMetaEnumValue &&) noexcept = default; AbstractMetaEnumValue::~AbstractMetaEnumValue() = default; EnumValue AbstractMetaEnumValue::value() const @@ -66,6 +69,17 @@ void AbstractMetaEnumValue::setName(const QString &name) d->m_name = name; } +bool AbstractMetaEnumValue::isDeprecated() const +{ + return d->m_deprecated; +} + +void AbstractMetaEnumValue::setDeprecated(bool deprecated) +{ + if (d->m_deprecated != deprecated) + d->m_deprecated = deprecated; +} + Documentation AbstractMetaEnumValue::documentation() const { return d->m_doc; @@ -82,29 +96,67 @@ void AbstractMetaEnumValue::setDocumentation(const Documentation &doc) class AbstractMetaEnumData : public QSharedData { public: - AbstractMetaEnumData() : m_hasQenumsDeclaration(false), m_signed(true) + AbstractMetaEnumData() : m_deprecated(false), + m_hasQenumsDeclaration(false), m_signed(true) { } + int unsignedUsedBits() const; + int signedUsedBits() const; + AbstractMetaEnumValueList m_enumValues; - EnumTypeEntry *m_typeEntry = nullptr; + EnumTypeEntryCPtr m_typeEntry; Documentation m_doc; + QString m_underlyingType; EnumKind m_enumKind = CEnum; Access m_access = Access::Public; + uint m_deprecated : 1; uint m_hasQenumsDeclaration : 1; uint m_signed : 1; }; +static int _usedBits(uint64_t v) +{ + return (v >> 32) ? 64 : (v >> 16) ? 32 : (v >> 8) ? 16 : 8; +} + +static int _usedBits(int64_t v) +{ + return (v >> 31) ? 64 : (v >> 15) ? 32 : (v >> 7) ? 16 : 8; +} + +int AbstractMetaEnumData::unsignedUsedBits() const +{ + uint64_t maxValue = 0; + for (const auto &v : m_enumValues) { + if (const auto uv = v.value().unsignedValue(); uv > maxValue) + maxValue = uv; + } + return _usedBits(maxValue); +} + +int AbstractMetaEnumData::signedUsedBits() const +{ + int64_t maxValue = 0; + for (const auto &v : m_enumValues) { + const auto sv = v.value().value(); + const auto absV = sv < 0 ? ~sv : sv; + if (absV > maxValue) + maxValue = absV; + } + return _usedBits(maxValue); +} + AbstractMetaEnum::AbstractMetaEnum() : d(new AbstractMetaEnumData) { } AbstractMetaEnum::AbstractMetaEnum(const AbstractMetaEnum &) = default; AbstractMetaEnum &AbstractMetaEnum::operator=(const AbstractMetaEnum&) = default; -AbstractMetaEnum::AbstractMetaEnum(AbstractMetaEnum &&) = default; -AbstractMetaEnum &AbstractMetaEnum::operator=(AbstractMetaEnum &&) = default; +AbstractMetaEnum::AbstractMetaEnum(AbstractMetaEnum &&) noexcept = default; +AbstractMetaEnum &AbstractMetaEnum::operator=(AbstractMetaEnum &&) noexcept = default; AbstractMetaEnum::~AbstractMetaEnum() = default; const AbstractMetaEnumValueList &AbstractMetaEnum::values() const @@ -112,6 +164,16 @@ const AbstractMetaEnumValueList &AbstractMetaEnum::values() const return d->m_enumValues; } +AbstractMetaEnumValueList AbstractMetaEnum::nonRejectedValues() const +{ + auto te = d->m_typeEntry; + AbstractMetaEnumValueList result = d->m_enumValues; + auto pred = [te](const AbstractMetaEnumValue &v) { + return te->isEnumValueRejected(v.name()); }; + result.erase(std::remove_if(result.begin(), result.end(), pred), result.end()); + return result; +} + void AbstractMetaEnum::addEnumValue(const AbstractMetaEnumValue &enumValue) { d->m_enumValues << enumValue; @@ -164,6 +226,36 @@ void AbstractMetaEnum::setAccess(Access a) d->m_access = a; } +bool AbstractMetaEnum::isDeprecated() const +{ + return d->m_deprecated; +} + +void AbstractMetaEnum::setDeprecated(bool deprecated) +{ + if (d->m_deprecated != deprecated) + d->m_deprecated = deprecated; +} + +static bool isDeprecatedValue(const AbstractMetaEnumValue &v) +{ + return v.isDeprecated(); +}; + +bool AbstractMetaEnum::hasDeprecatedValues() const +{ + return std::any_of(d->m_enumValues.cbegin(), d->m_enumValues.cend(), + isDeprecatedValue); +} + +AbstractMetaEnumValueList AbstractMetaEnum::deprecatedValues() const +{ + AbstractMetaEnumValueList result; + std::copy_if(d->m_enumValues.cbegin(), d->m_enumValues.cend(), + std::back_inserter(result), isDeprecatedValue); + return result; +} + const Documentation &AbstractMetaEnum::documentation() const { return d->m_doc; @@ -217,12 +309,12 @@ void AbstractMetaEnum::setHasQEnumsDeclaration(bool on) d->m_hasQenumsDeclaration = on; } -EnumTypeEntry *AbstractMetaEnum::typeEntry() const +EnumTypeEntryCPtr AbstractMetaEnum::typeEntry() const { return d->m_typeEntry; } -void AbstractMetaEnum::setTypeEntry(EnumTypeEntry *entry) +void AbstractMetaEnum::setTypeEntry(const EnumTypeEntryCPtr &entry) { if (d->m_typeEntry != entry) d->m_typeEntry = entry; @@ -239,11 +331,39 @@ void AbstractMetaEnum::setSigned(bool s) d->m_signed = s; } +QString AbstractMetaEnum::underlyingType() const +{ + return d->m_underlyingType; +} + +void AbstractMetaEnum::setUnderlyingType(const QString &underlyingType) +{ + if (d->m_underlyingType != underlyingType) + d->m_underlyingType = underlyingType; +} + +int AbstractMetaEnum::usedBits() const +{ + return isSigned() ? d->signedUsedBits() : d->unsignedUsedBits(); +} + +QString AbstractMetaEnum::intTypeForSize(int usedBits, bool isSigned) +{ + QString result = u"int"_s + QString::number(usedBits) + u"_t"_s; + return isSigned ? result : u'u' + result; +} + #ifndef QT_NO_DEBUG_STREAM -static void formatMetaEnumValue(QDebug &d, const AbstractMetaEnumValue &v) +static void formatMetaEnumValue(QDebug &d, const AbstractMetaEnumValue &v, bool forceHex = false) { - d << v.name() << '=' << v.value(); + d << v.name() << '='; + if (forceHex) + v.value().formatDebugHex(d); + else + v.value().formatDebug(d); + if (v.isDeprecated()) + d << " (deprecated)"; } QDebug operator<<(QDebug d, const AbstractMetaEnumValue &v) @@ -259,15 +379,19 @@ QDebug operator<<(QDebug d, const AbstractMetaEnumValue &v) static void formatMetaEnum(QDebug &d, const AbstractMetaEnum &e) { - d << e.fullName(); + d << '"' << e.fullName() << '"'; + if (e.isDeprecated()) + d << " (deprecated)"; + d << " \"" << e.underlyingType() << '"'; if (!e.isSigned()) - d << " (unsigned) "; - d << '['; + d << " (unsigned)"; + d << " ["; const AbstractMetaEnumValueList &values = e.values(); - for (int i = 0, count = values.size(); i < count; ++i) { + const bool hasFlags = e.typeEntry()->flags() != nullptr; + for (qsizetype i = 0, count = values.size(); i < count; ++i) { if (i) - d << ' '; - formatMetaEnumValue(d, values.at(i)); + d << ", "; + formatMetaEnumValue(d, values.at(i), hasFlags); } d << ']'; } diff --git a/sources/shiboken6/ApiExtractor/abstractmetaenum.h b/sources/shiboken6/ApiExtractor/abstractmetaenum.h index 1151b7164..03d7a3082 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetaenum.h +++ b/sources/shiboken6/ApiExtractor/abstractmetaenum.h @@ -7,6 +7,7 @@ #include "abstractmetalang_typedefs.h" #include "enclosingclassmixin.h" #include "parser/codemodel_enums.h" +#include "typesystem_typedefs.h" #include <QtCore/QSharedDataPointer> #include <QtCore/QString> @@ -27,8 +28,8 @@ public: AbstractMetaEnumValue(); AbstractMetaEnumValue(const AbstractMetaEnumValue &); AbstractMetaEnumValue &operator=(const AbstractMetaEnumValue &); - AbstractMetaEnumValue(AbstractMetaEnumValue &&); - AbstractMetaEnumValue &operator=(AbstractMetaEnumValue &&); + AbstractMetaEnumValue(AbstractMetaEnumValue &&) noexcept; + AbstractMetaEnumValue &operator=(AbstractMetaEnumValue &&) noexcept; ~AbstractMetaEnumValue(); EnumValue value() const; @@ -40,9 +41,14 @@ public: QString name() const; void setName(const QString &name); + bool isDeprecated() const; + void setDeprecated(bool deprecated); + Documentation documentation() const; void setDocumentation(const Documentation& doc); + int usedBits() const; + private: QSharedDataPointer<AbstractMetaEnumValueData> d; }; @@ -53,11 +59,12 @@ public: AbstractMetaEnum(); AbstractMetaEnum(const AbstractMetaEnum &); AbstractMetaEnum &operator=(const AbstractMetaEnum &); - AbstractMetaEnum(AbstractMetaEnum &&); - AbstractMetaEnum &operator=(AbstractMetaEnum &&); + AbstractMetaEnum(AbstractMetaEnum &&) noexcept; + AbstractMetaEnum &operator=(AbstractMetaEnum &&) noexcept; ~AbstractMetaEnum(); const AbstractMetaEnumValueList &values() const; + AbstractMetaEnumValueList nonRejectedValues() const; void addEnumValue(const AbstractMetaEnumValue &enumValue); std::optional<AbstractMetaEnumValue> findEnumValue(QStringView value) const; @@ -70,6 +77,11 @@ public: bool isPrivate() const { return access() == Access::Private; } bool isProtected() const { return access() == Access::Protected; } + bool isDeprecated() const; + void setDeprecated(bool deprecated); + bool hasDeprecatedValues() const; + AbstractMetaEnumValueList deprecatedValues() const; + const Documentation &documentation() const; void setDocumentation(const Documentation& doc); @@ -88,12 +100,18 @@ public: bool hasQEnumsDeclaration() const; void setHasQEnumsDeclaration(bool on); - EnumTypeEntry *typeEntry() const; - void setTypeEntry(EnumTypeEntry *entry); + EnumTypeEntryCPtr typeEntry() const; + void setTypeEntry(const EnumTypeEntryCPtr &entry); bool isSigned() const; void setSigned(bool s); + QString underlyingType() const; + void setUnderlyingType(const QString &underlyingType); + + static QString intTypeForSize(int usedBits, bool isSigned); + int usedBits() const; + private: QSharedDataPointer<AbstractMetaEnumData> d; }; diff --git a/sources/shiboken6/ApiExtractor/abstractmetafield.cpp b/sources/shiboken6/ApiExtractor/abstractmetafield.cpp index 8be9ed87d..27a76d04d 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetafield.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetafield.cpp @@ -36,8 +36,8 @@ AbstractMetaField::AbstractMetaField() : d(new AbstractMetaFieldData) AbstractMetaField::AbstractMetaField(const AbstractMetaField &) = default; AbstractMetaField &AbstractMetaField::operator=(const AbstractMetaField &) = default; -AbstractMetaField::AbstractMetaField(AbstractMetaField &&) = default; -AbstractMetaField &AbstractMetaField::operator=(AbstractMetaField &&) = default; +AbstractMetaField::AbstractMetaField(AbstractMetaField &&) noexcept = default; +AbstractMetaField &AbstractMetaField::operator=(AbstractMetaField &&) noexcept = default; AbstractMetaField::~AbstractMetaField() = default; // returned->setEnclosingClass(nullptr); @@ -56,7 +56,7 @@ std::optional<AbstractMetaField> /******************************************************************************* * Indicates that this field has a modification that removes it */ -bool AbstractMetaField::isModifiedRemoved(int types) const +bool AbstractMetaField::isModifiedRemoved() const { const FieldModificationList &mods = modifications(); for (const FieldModification &mod : mods) { @@ -202,7 +202,7 @@ TypeSystem::SnakeCase AbstractMetaField::snakeCase() const auto typeEntry = enclosingClass()->typeEntry(); const auto snakeCase = typeEntry->snakeCase(); return snakeCase != TypeSystem::SnakeCase::Unspecified - ? snakeCase : typeEntry->typeSystemTypeEntry()->snakeCase(); + ? snakeCase : typeSystemTypeEntry(typeEntry)->snakeCase(); } FieldModificationList AbstractMetaField::modifications() const diff --git a/sources/shiboken6/ApiExtractor/abstractmetafield.h b/sources/shiboken6/ApiExtractor/abstractmetafield.h index 051fca66c..0fa858791 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetafield.h +++ b/sources/shiboken6/ApiExtractor/abstractmetafield.h @@ -7,6 +7,7 @@ #include "abstractmetalang_typedefs.h" #include "parser/codemodel_enums.h" #include "typesystem_enums.h" +#include "modifications_typedefs.h" #include "typesystem_typedefs.h" #include "enclosingclassmixin.h" @@ -25,13 +26,13 @@ public: AbstractMetaField(); AbstractMetaField(const AbstractMetaField &); AbstractMetaField &operator=(const AbstractMetaField &); - AbstractMetaField(AbstractMetaField &&); - AbstractMetaField &operator=(AbstractMetaField &&); + AbstractMetaField(AbstractMetaField &&) noexcept; + AbstractMetaField &operator=(AbstractMetaField &&) noexcept; ~AbstractMetaField(); FieldModificationList modifications() const; - bool isModifiedRemoved(int types = TypeSystem::All) const; + bool isModifiedRemoved() const; bool generateOpaqueContainer() const; const AbstractMetaType &type() const; diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp index 0ce2d0260..11a02f154 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp @@ -2,21 +2,23 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "abstractmetafunction.h" +#include "abstractmetaargument.h" #include "abstractmetabuilder.h" #include "abstractmetalang.h" #include "abstractmetalang_helpers.h" #include "abstractmetatype.h" +#include "addedfunction.h" #include <codemodel.h> #include "documentation.h" #include "exception.h" #include "messages.h" #include "codesnip.h" #include "modifications.h" -#include "propertyspec.h" #include "reporthandler.h" #include "sourcelocation.h" #include "typedatabase.h" #include "complextypeentry.h" +#include "containertypeentry.h" #include "functiontypeentry.h" #include "primitivetypeentry.h" #include "typesystemtypeentry.h" @@ -26,13 +28,15 @@ #include <QtCore/QDebug> #include <QtCore/QRegularExpression> +#include <algorithm> + using namespace Qt::StringLiterals; // Cache FunctionModificationList in a flat list per class (0 for global // functions, or typically owner/implementing/declaring class. struct ModificationCacheEntry { - const AbstractMetaClass *klass; + AbstractMetaClassCPtr klass; FunctionModificationList modifications; }; @@ -44,7 +48,6 @@ public: AbstractMetaFunctionPrivate() : m_constant(false), m_reverse(false), - m_explicit(false), m_pointerOperator(false), m_isCallOperator(false) { @@ -57,7 +60,7 @@ public: int overloadNumber(const AbstractMetaFunction *q) const; const FunctionModificationList &modifications(const AbstractMetaFunction *q, - const AbstractMetaClass *implementor) const; + const AbstractMetaClassCPtr &implementor) const; bool applyTypeModification(const AbstractMetaFunction *q, const QString &type, int number, QString *errorMessage); @@ -68,24 +71,25 @@ public: mutable QString m_cachedMinimalSignature; mutable QString m_cachedSignature; mutable QString m_cachedModifiedName; + QString m_unresolvedSignature; - FunctionTypeEntry* m_typeEntry = nullptr; + FunctionTypeEntryPtr m_typeEntry; AbstractMetaFunction::FunctionType m_functionType = AbstractMetaFunction::NormalFunction; AbstractMetaType m_type; QString m_modifiedTypeName; - const AbstractMetaClass *m_class = nullptr; - const AbstractMetaClass *m_implementingClass = nullptr; - const AbstractMetaClass *m_declaringClass = nullptr; + AbstractMetaClassCPtr m_class; + AbstractMetaClassCPtr m_implementingClass; + AbstractMetaClassCPtr m_declaringClass; mutable ModificationCache m_modificationCache; int m_propertySpecIndex = -1; AbstractMetaArgumentList m_arguments; AddedFunctionPtr m_addedFunction; SourceLocation m_sourceLocation; AbstractMetaFunction::Attributes m_attributes; + FunctionAttributes m_cppAttributes; AbstractMetaFunction::Flags m_flags; uint m_constant : 1; uint m_reverse : 1; - uint m_explicit : 1; uint m_pointerOperator : 1; uint m_isCallOperator : 1; mutable int m_cachedOverloadNumber = TypeSystem::OverloadNumberUnset; @@ -115,9 +119,9 @@ AbstractMetaFunction::AbstractMetaFunction(const AddedFunctionPtr &addedFunc) : setAccess(Access::Public); break; } - AbstractMetaFunction::Attributes atts = AbstractMetaFunction::FinalInTargetLang; + AbstractMetaFunction::Attributes atts; if (addedFunc->isStatic()) - atts |= AbstractMetaFunction::Static; + setCppAttribute(FunctionAttribute::Static); if (addedFunc->isClassMethod()) atts |= AbstractMetaFunction::ClassMethod; setAttributes(atts); @@ -210,20 +214,19 @@ void AbstractMetaFunction::setPointerOperator(bool value) bool AbstractMetaFunction::isExplicit() const { - return d->m_explicit; + return d->m_cppAttributes.testFlag(FunctionAttribute::Explicit); } void AbstractMetaFunction::setExplicit(bool isExplicit) { - d->m_explicit = isExplicit; + d->m_cppAttributes.setFlag(FunctionAttribute::Explicit, isExplicit); } bool AbstractMetaFunction::returnsBool() const { if (d->m_type.typeUsagePattern() != AbstractMetaType::PrimitivePattern) return false; - const auto *pte = d->m_type.typeEntry()->asPrimitive(); - return pte->basicReferencedTypeEntry()->name() == u"bool"; + return basicReferencedTypeEntry(d->m_type.typeEntry())->name() == u"bool"; } bool AbstractMetaFunction::isOperatorBool() const @@ -258,6 +261,21 @@ void AbstractMetaFunction::operator-=(AbstractMetaFunction::Attribute attribute) d->m_attributes.setFlag(attribute, false); } +FunctionAttributes AbstractMetaFunction::cppAttributes() const +{ + return d->m_cppAttributes; +} + +void AbstractMetaFunction::setCppAttributes(FunctionAttributes a) +{ + d->m_cppAttributes = a; +} + +void AbstractMetaFunction::setCppAttribute(FunctionAttribute a, bool on) +{ + d->m_cppAttributes.setFlag(a, on); +} + AbstractMetaFunction::Flags AbstractMetaFunction::flags() const { return d->m_flags; @@ -271,9 +289,9 @@ void AbstractMetaFunction::setFlags(Flags f) /******************************************************************************* * Indicates that this function has a modification that removes it */ -bool AbstractMetaFunction::isModifiedRemoved(const AbstractMetaClass *cls) const +bool AbstractMetaFunction::isModifiedRemoved(AbstractMetaClassCPtr cls) const { - if (!isInGlobalScope() && cls == nullptr) + if (!isInGlobalScope() && !cls) cls = d->m_implementingClass; for (const auto &mod : modifications(cls)) { if (mod.isRemoved()) @@ -283,6 +301,17 @@ bool AbstractMetaFunction::isModifiedRemoved(const AbstractMetaClass *cls) const return false; } +bool AbstractMetaFunction::isModifiedFinal(AbstractMetaClassCPtr cls) const +{ + if (!isInGlobalScope() && cls == nullptr) + cls = d->m_implementingClass; + for (const auto &mod : modifications(cls)) { + if (mod.modifiers().testFlag(FunctionModification::Final)) + return true; + } + return false; +} + bool AbstractMetaFunction::isVoid() const { return d->m_type.isVoid(); @@ -298,12 +327,12 @@ void AbstractMetaFunction::setType(const AbstractMetaType &type) d->m_type = type; } -const AbstractMetaClass *AbstractMetaFunction::ownerClass() const +AbstractMetaClassCPtr AbstractMetaFunction::ownerClass() const { return d->m_class; } -void AbstractMetaFunction::setOwnerClass(const AbstractMetaClass *cls) +void AbstractMetaFunction::setOwnerClass(const AbstractMetaClassCPtr &cls) { d->m_class = cls; } @@ -327,7 +356,7 @@ AbstractMetaFunction::CompareResult AbstractMetaFunction::compareTo(const Abstra result |= EqualImplementor; // Attributes - if (attributes() == other->attributes()) + if (attributes() == other->attributes() && cppAttributes() == other->cppAttributes()) result |= EqualAttributes; // Compare types @@ -358,10 +387,10 @@ AbstractMetaFunction::CompareResult AbstractMetaFunction::compareTo(const Abstra maxArguments = arguments(); } - int minCount = minArguments.size(); - int maxCount = maxArguments.size(); + const auto minCount = minArguments.size(); + const auto maxCount = maxArguments.size(); bool same = true; - for (int i = 0; i < maxCount; ++i) { + for (qsizetype i = 0; i < maxCount; ++i) { if (i < minCount) { const AbstractMetaArgument &min_arg = minArguments.at(i); const AbstractMetaArgument &max_arg = maxArguments.at(i); @@ -412,6 +441,10 @@ AbstractMetaFunction *AbstractMetaFunction::copy() const { auto *cpy = new AbstractMetaFunction; cpy->setAttributes(attributes()); + auto ca = cppAttributes(); + // Historical bug: explicit was not copied! (causing nontypetemplate_test.py fail) + ca.setFlag(FunctionAttribute::Explicit, false); + cpy->setCppAttributes(ca); cpy->setFlags(flags()); cpy->setAccess(access()); cpy->setName(name()); @@ -449,6 +482,9 @@ bool AbstractMetaFunction::generateBinding() const { switch (d->m_functionType) { case ConversionOperator: + if (d->m_name != u"operator int" && d->m_name != u"operator double") + return false; + break; case AssignmentOperatorFunction: case MoveAssignmentOperatorFunction: case AbstractMetaFunction::MoveConstructorFunction: @@ -458,9 +494,19 @@ bool AbstractMetaFunction::generateBinding() const return false; break; } + // Can we access the wrapper in case of a protected method? If not, + // disable for consistency regardless of avoidProtectedHack. + if (isProtected()) { + const auto typeFlags = ownerClass()->typeEntry()->typeFlags(); + if (typeFlags.testFlag(ComplexTypeEntry::DisableWrapper)) + return false; + } if (isPrivate() && d->m_functionType != EmptyFunction) return false; - return d->m_name != u"qt_metacall" && !usesRValueReferences() + // RValue references only for user-specified + // functions (<add-function>/<declare-function>/<function>) + return d->m_name != u"qt_metacall" && + (!usesRValueReferences() || d->m_addedFunction || d->m_typeEntry) && !isModifiedRemoved(); } @@ -470,7 +516,7 @@ bool AbstractMetaFunction::isWhiteListed() const case NormalFunction: case SignalFunction: case SlotFunction: - if (auto *dc = declaringClass()) { + if (auto dc = declaringClass()) { const QSet<QString> &whiteList = dc->typeEntry()->generateFunctions(); return whiteList.isEmpty() || whiteList.contains(d->m_name) || whiteList.contains(minimalSignature()); @@ -521,6 +567,16 @@ QString AbstractMetaFunction::classQualifiedSignature() const return result; } +QString AbstractMetaFunction::unresolvedSignature() const +{ + return d->m_unresolvedSignature; +} + +void AbstractMetaFunction::setUnresolvedSignature(const QString &s) +{ + d->m_unresolvedSignature = s; +} + bool AbstractMetaFunction::isConstant() const { return d->m_constant; @@ -533,18 +589,23 @@ void AbstractMetaFunction::setConstant(bool constant) bool AbstractMetaFunction::isUserAdded() const { - return !d->m_addedFunction.isNull() && !d->m_addedFunction->isDeclaration(); + return d->m_addedFunction && !d->m_addedFunction->isDeclaration(); +} + +bool AbstractMetaFunction::isUserAddedPythonOverride() const +{ + return d->m_addedFunction && d->m_addedFunction->isPythonOverride(); } bool AbstractMetaFunction::isUserDeclared() const { - return !d->m_addedFunction.isNull() && d->m_addedFunction->isDeclaration(); + return d->m_addedFunction && d->m_addedFunction->isDeclaration(); } int AbstractMetaFunction::actualMinimumArgumentCount() const { int count = 0; - for (int i = 0, size = d->m_arguments.size(); i < size; ++i && ++count) { + for (qsizetype i = 0, size = d->m_arguments.size(); i < size; ++i && ++count) { const auto &arg = d->m_arguments.at(i); if (arg.isModifiedRemoved()) --count; @@ -568,7 +629,7 @@ int AbstractMetaFunction::actualArgumentIndex(int index) const } // Returns reference counts for argument at idx, or all arguments if idx == -2 -QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const +QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClassCPtr &cls, int idx) const { QList<ReferenceCount> returned; @@ -583,7 +644,7 @@ QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaCl return returned; } -ArgumentOwner AbstractMetaFunction::argumentOwner(const AbstractMetaClass *cls, int idx) const +ArgumentOwner AbstractMetaFunction::argumentOwner(const AbstractMetaClassCPtr &cls, int idx) const { for (const auto &mod : modifications(cls)) { for (const ArgumentModification &argumentMod : mod.argument_mods()) { @@ -632,28 +693,28 @@ bool AbstractMetaFunction::argumentRemoved(int key) const return false; } -const AbstractMetaClass *AbstractMetaFunction::targetLangOwner() const +AbstractMetaClassCPtr AbstractMetaFunction::targetLangOwner() const { return d->m_class && d->m_class->isInvisibleNamespace() ? d->m_class->targetLangEnclosingClass() : d->m_class; } -const AbstractMetaClass *AbstractMetaFunction::declaringClass() const +AbstractMetaClassCPtr AbstractMetaFunction::declaringClass() const { return d->m_declaringClass; } -void AbstractMetaFunction::setDeclaringClass(const AbstractMetaClass *cls) +void AbstractMetaFunction::setDeclaringClass(const AbstractMetaClassCPtr &cls) { d->m_declaringClass = cls; } -const AbstractMetaClass *AbstractMetaFunction::implementingClass() const +AbstractMetaClassCPtr AbstractMetaFunction::implementingClass() const { return d->m_implementingClass; } -void AbstractMetaFunction::setImplementingClass(const AbstractMetaClass *cls) +void AbstractMetaFunction::setImplementingClass(const AbstractMetaClassCPtr &cls) { d->m_implementingClass = cls; } @@ -678,15 +739,23 @@ void AbstractMetaFunction::addArgument(const AbstractMetaArgument &argument) d->m_arguments << argument; } +static bool modifiedDeprecated(const FunctionModification &mod) +{ + return mod.modifiers().testFlag(FunctionModification::Deprecated); +} + +static bool modifiedUndeprecated(const FunctionModification &mod) +{ + return mod.modifiers().testFlag(FunctionModification::Undeprecated); +} + bool AbstractMetaFunction::isDeprecated() const { - if (d->m_attributes.testFlag(Attribute::Deprecated)) - return true; - for (const auto &modification : modifications(declaringClass())) { - if (modification.isDeprecated()) - return true; - } - return false; + const auto &mods = modifications(declaringClass()); + + return d->m_cppAttributes.testFlag(FunctionAttribute::Deprecated) + ? std::none_of(mods.cbegin(), mods.cend(), modifiedUndeprecated) + : std::any_of(mods.cbegin(), mods.cend(), modifiedDeprecated); } bool AbstractMetaFunction::isConstructor() const @@ -777,12 +846,12 @@ void AbstractMetaFunction::setSourceLocation(const SourceLocation &sourceLocatio d->m_sourceLocation = sourceLocation; } -static inline TypeSystem::AllowThread allowThreadMod(const AbstractMetaClass *klass) +static inline TypeSystem::AllowThread allowThreadMod(const AbstractMetaClassCPtr &klass) { return klass->typeEntry()->allowThread(); } -static inline bool hasAllowThreadMod(const AbstractMetaClass *klass) +static inline bool hasAllowThreadMod(const AbstractMetaClassCPtr &klass) { return allowThreadMod(klass) != TypeSystem::AllowThread::Unspecified; } @@ -815,7 +884,7 @@ bool AbstractMetaFunction::allowThread() const return result; } -TypeSystem::Ownership AbstractMetaFunction::argumentTargetOwnership(const AbstractMetaClass *cls, int idx) const +TypeSystem::Ownership AbstractMetaFunction::argumentTargetOwnership(const AbstractMetaClassCPtr &cls, int idx) const { for (const auto &modification : modifications(cls)) { for (const ArgumentModification &argumentModification : modification.argument_mods()) { @@ -834,10 +903,15 @@ const QString &AbstractMetaFunction::modifiedTypeName() const bool AbstractMetaFunction::generateOpaqueContainerReturn() const { - return isTypeModified() - && d->m_type.typeUsagePattern() == AbstractMetaType::ContainerPattern - && d->m_type.referenceType() == LValueReference - && d->m_type.generateOpaqueContainerForGetter(d->m_modifiedTypeName); + if (!isTypeModified() || d->m_type.typeUsagePattern() != AbstractMetaType::ContainerPattern) + return false; + // Needs to be a reference to a container, allow by value only for spans + if (d->m_type.referenceType() != LValueReference) { + auto cte = std::static_pointer_cast<const ContainerTypeEntry>(d->m_type.typeEntry()); + if (cte->containerKind() != ContainerTypeEntry::SpanContainer) + return false; + } + return d->m_type.generateOpaqueContainerForGetter(d->m_modifiedTypeName); } bool AbstractMetaFunction::isModifiedToArray(int argumentIndex) const @@ -925,12 +999,14 @@ QString AbstractMetaFunctionPrivate::formatMinimalSignature(const AbstractMetaFu { QString result = m_originalName + u'('; for (qsizetype i = 0; i < m_arguments.size(); ++i) { + const auto &argument = m_arguments.at(i); if (i > 0) result += u','; - result += comment - ? m_arguments.at(i).modifiedType().minimalSignature() - : m_arguments.at(i).type().minimalSignature(); + const auto &type = comment ? argument.modifiedType() : argument.type(); + result += type.minimalSignature(); + if (comment && argument.hasDefaultValueExpression()) + result += u'='; } result += u')'; if (m_constant) @@ -952,6 +1028,14 @@ QString AbstractMetaFunction::minimalSignature() const return d->m_cachedMinimalSignature; } +QStringList AbstractMetaFunction::modificationSignatures() const +{ + QStringList result{minimalSignature()}; + if (d->m_unresolvedSignature != result.constFirst()) + result.append(d->m_unresolvedSignature); + return result; +} + QString AbstractMetaFunction::signatureComment() const { return d->formatMinimalSignature(this, true); @@ -960,9 +1044,10 @@ QString AbstractMetaFunction::signatureComment() const QString AbstractMetaFunction::debugSignature() const { QString result; - const bool isOverride = attributes() & AbstractMetaFunction::OverriddenCppMethod; - const bool isFinal = attributes() & AbstractMetaFunction::FinalCppMethod; - if (!isOverride && !isFinal && (attributes() & AbstractMetaFunction::VirtualCppMethod)) + const auto attributes = cppAttributes(); + const bool isOverride = attributes.testFlag(FunctionAttribute::Override); + const bool isFinal = attributes.testFlag(FunctionAttribute::Final); + if (!isOverride && !isFinal && (attributes.testFlag(FunctionAttribute::Virtual))) result += u"virtual "_s; if (d->m_implementingClass) result += d->m_implementingClass->qualifiedCppName() + u"::"_s; @@ -975,12 +1060,12 @@ QString AbstractMetaFunction::debugSignature() const } FunctionModificationList AbstractMetaFunction::findClassModifications(const AbstractMetaFunction *f, - const AbstractMetaClass *implementor) + AbstractMetaClassCPtr implementor) { - const QString signature = f->minimalSignature(); + const auto signatures = f->modificationSignatures(); FunctionModificationList mods; while (implementor) { - mods += implementor->typeEntry()->functionModifications(signature); + mods += implementor->typeEntry()->functionModifications(signatures); if ((implementor == implementor->baseClass()) || (implementor == f->implementingClass() && !mods.isEmpty())) { break; @@ -992,15 +1077,16 @@ FunctionModificationList AbstractMetaFunction::findClassModifications(const Abst FunctionModificationList AbstractMetaFunction::findGlobalModifications(const AbstractMetaFunction *f) { - return TypeDatabase::instance()->functionModifications(f->minimalSignature()); + auto *td = TypeDatabase::instance(); + return td->globalFunctionModifications(f->modificationSignatures()); } const FunctionModificationList & AbstractMetaFunctionPrivate::modifications(const AbstractMetaFunction *q, - const AbstractMetaClass *implementor) const + const AbstractMetaClassCPtr &implementor) const { - if (!m_addedFunction.isNull()) - return m_addedFunction->modifications; + if (m_addedFunction) + return m_addedFunction->modifications(); for (const auto &ce : m_modificationCache) { if (ce.klass == implementor) return ce.modifications; @@ -1014,9 +1100,9 @@ const FunctionModificationList & } const FunctionModificationList & - AbstractMetaFunction::modifications(const AbstractMetaClass *implementor) const + AbstractMetaFunction::modifications(AbstractMetaClassCPtr implementor) const { - if (implementor == nullptr) + if (!implementor) implementor = d->m_class; return d->modifications(this, implementor); } @@ -1026,9 +1112,15 @@ void AbstractMetaFunction::clearModificationsCache() d->m_modificationCache.clear(); } +const DocModificationList AbstractMetaFunction::addedFunctionDocModifications() const +{ + return d->m_addedFunction + ? d->m_addedFunction->docModifications() : DocModificationList{}; +} + QString AbstractMetaFunction::argumentName(int index, bool /* create */, - const AbstractMetaClass * /* implementor */) const + AbstractMetaClassCPtr /* implementor */) const { return d->m_arguments[--index].name(); } @@ -1043,16 +1135,27 @@ void AbstractMetaFunction::setPropertySpecIndex(int i) d->m_propertySpecIndex = i; } -FunctionTypeEntry *AbstractMetaFunction::typeEntry() const +FunctionTypeEntryPtr AbstractMetaFunction::typeEntry() const { return d->m_typeEntry; } -void AbstractMetaFunction::setTypeEntry(FunctionTypeEntry *typeEntry) +void AbstractMetaFunction::setTypeEntry(const FunctionTypeEntryPtr &typeEntry) { d->m_typeEntry = typeEntry; } +QString AbstractMetaFunction::targetLangPackage() const +{ + if (d->m_addedFunction != nullptr) + return d->m_addedFunction->targetLangPackage(); + if (d->m_class != nullptr) + return d->m_class->typeEntry()->targetLangPackage(); + if (d->m_typeEntry != nullptr) + return d->m_typeEntry->targetLangPackage(); + return {}; +} + bool AbstractMetaFunction::isCallOperator() const { return d->m_name == u"operator()"; @@ -1149,12 +1252,12 @@ void AbstractMetaFunction::setExceptionSpecification(ExceptionSpecification e) d->m_exceptionSpecification = e; } -static inline TypeSystem::ExceptionHandling exceptionMod(const AbstractMetaClass *klass) +static inline TypeSystem::ExceptionHandling exceptionMod(const AbstractMetaClassCPtr &klass) { return klass->typeEntry()->exceptionHandling(); } -static inline bool hasExceptionMod(const AbstractMetaClass *klass) +static inline bool hasExceptionMod(const AbstractMetaClassCPtr &klass) { return exceptionMod(klass) != TypeSystem::ExceptionHandling::Unspecified; } @@ -1308,7 +1411,7 @@ bool AbstractMetaFunction::isInplaceOperator() const bool AbstractMetaFunction::isVirtual() const { - return d->m_attributes.testFlag(AbstractMetaFunction::VirtualCppMethod); + return d->m_cppAttributes.testFlag(FunctionAttribute::Virtual); } QString AbstractMetaFunctionPrivate::modifiedName(const AbstractMetaFunction *q) const @@ -1333,7 +1436,7 @@ QString AbstractMetaFunction::modifiedName() const AbstractMetaFunctionCPtr AbstractMetaFunction::find(const AbstractMetaFunctionCList &haystack, - QStringView needle) + QAnyStringView needle) { for (const auto &f : haystack) { if (f->name() == needle) @@ -1431,17 +1534,14 @@ TypeSystem::SnakeCase AbstractMetaFunction::snakeCase() const return mod.snakeCase(); } - if (d->m_typeEntry) { // Global function - const auto snakeCase = d->m_typeEntry->snakeCase(); - return snakeCase != TypeSystem::SnakeCase::Unspecified - ? snakeCase : d->m_typeEntry->typeSystemTypeEntry()->snakeCase(); - } + if (d->m_typeEntry) // Global function + return typeSystemTypeEntry(d->m_typeEntry)->snakeCase(); if (d->m_class) { auto typeEntry = d->m_class->typeEntry(); const auto snakeCase = typeEntry->snakeCase(); return snakeCase != TypeSystem::SnakeCase::Unspecified - ? snakeCase : typeEntry->typeSystemTypeEntry()->snakeCase(); + ? snakeCase : typeSystemTypeEntry(typeEntry)->snakeCase(); } return TypeSystem::SnakeCase::Disabled; } @@ -1455,7 +1555,7 @@ bool AbstractMetaFunction::injectedCodeUsesPySelf() const bool AbstractMetaFunction::injectedCodeCallsPythonOverride() const { static const QRegularExpression - overrideCallRegexCheck(QStringLiteral(R"(PyObject_Call\s*\(\s*%PYTHON_METHOD_OVERRIDE\s*,)")); + overrideCallRegexCheck(R"(PyObject_Call\s*\(\s*%PYTHON_METHOD_OVERRIDE\s*,)"_L1); Q_ASSERT(overrideCallRegexCheck.isValid()); return injectedCodeContains(overrideCallRegexCheck, TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode); @@ -1465,13 +1565,13 @@ bool AbstractMetaFunction::injectedCodeHasReturnValueAttribution(TypeSystem::Lan { if (language == TypeSystem::TargetLangCode) { static const QRegularExpression - retValAttributionRegexCheck_target(QStringLiteral(R"(%PYARG_0\s*=[^=]\s*.+)")); + retValAttributionRegexCheck_target(R"(%PYARG_0\s*=[^=]\s*.+)"_L1); Q_ASSERT(retValAttributionRegexCheck_target.isValid()); return injectedCodeContains(retValAttributionRegexCheck_target, TypeSystem::CodeSnipPositionAny, language); } static const QRegularExpression - retValAttributionRegexCheck_native(QStringLiteral(R"(%0\s*=[^=]\s*.+)")); + retValAttributionRegexCheck_native(R"(%0\s*=[^=]\s*.+)"_L1); Q_ASSERT(retValAttributionRegexCheck_native.isValid()); return injectedCodeContains(retValAttributionRegexCheck_native, TypeSystem::CodeSnipPositionAny, language); } @@ -1552,12 +1652,15 @@ void AbstractMetaFunction::formatDebugVerbose(QDebug &debug) const if (d->m_exceptionHandlingModification != TypeSystem::ExceptionHandling::Unspecified) debug << " exeption-mod " << int(d->m_exceptionHandlingModification); debug << '('; - for (int i = 0, count = d->m_arguments.size(); i < count; ++i) { + for (qsizetype i = 0, count = d->m_arguments.size(); i < count; ++i) { if (i) debug << ", "; debug << d->m_arguments.at(i); } - debug << "), signature=\"" << minimalSignature() << '"'; + const QString signature = minimalSignature(); + debug << "), signature=\"" << signature << '"'; + if (signature != d->m_unresolvedSignature) + debug << ", unresolvedSignature=\"" << d->m_unresolvedSignature << '"'; if (d->m_constant) debug << " [const]"; if (d->m_reverse) @@ -1566,9 +1669,9 @@ void AbstractMetaFunction::formatDebugVerbose(QDebug &debug) const debug << " [userAdded]"; if (isUserDeclared()) debug << " [userDeclared]"; - if (d->m_explicit) + if (d->m_cppAttributes.testFlag(FunctionAttribute::Explicit)) debug << " [explicit]"; - if (attributes().testFlag(AbstractMetaFunction::Deprecated)) + if (d->m_cppAttributes.testFlag(FunctionAttribute::Deprecated)) debug << " [deprecated]"; if (d->m_pointerOperator) debug << " [operator->]"; diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.h b/sources/shiboken6/ApiExtractor/abstractmetafunction.h index 4c0815540..e252e439d 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetafunction.h +++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.h @@ -6,10 +6,12 @@ #include "abstractmetalang_enums.h" #include "abstractmetalang_typedefs.h" -#include "abstractmetaargument.h" #include "typesystem_enums.h" +#include "modifications_typedefs.h" #include "typesystem_typedefs.h" +#include "parser/codemodel_enums.h" +#include <QtCore/QMetaObject> #include <QtCore/QScopedPointer> #include <optional> @@ -30,6 +32,8 @@ class AbstractMetaFunction { Q_GADGET public: + Q_DISABLE_COPY_MOVE(AbstractMetaFunction) + enum FunctionType { ConstructorFunction, CopyConstructorFunction, @@ -88,29 +92,18 @@ public: enum Attribute { None = 0x00000000, - Friendly = 0x00000001, - - Abstract = 0x00000002, - Static = 0x00000004, ClassMethod = 0x00000008, - FinalInTargetLang = 0x00000010, - GetterFunction = 0x00000020, SetterFunction = 0x00000040, PropertyReader = 0x00000100, PropertyWriter = 0x00000200, PropertyResetter = 0x00000400, + PropertyNotify = 0x00000800, - Invokable = 0x00001000, - - VirtualCppMethod = 0x00010000, - OverriddenCppMethod = 0x00020000, - FinalCppMethod = 0x00040000, // Add by meta builder (implicit constructors, inherited methods, etc) AddedMethod = 0x001000000, - Deprecated = 0x002000000 // Code annotation }; Q_DECLARE_FLAGS(Attributes, Attribute) Q_FLAG(Attribute) @@ -121,24 +114,27 @@ public: void operator+=(Attribute attribute); void operator-=(Attribute attribute); + FunctionAttributes cppAttributes() const; + void setCppAttributes(FunctionAttributes a); + void setCppAttribute(FunctionAttribute a, bool on = true); + enum class Flag { // Internal flags not relevant for comparing functions // Binary operator whose leading/trailing argument was removed by metabuilder OperatorLeadingClassArgumentRemoved = 0x1, OperatorTrailingClassArgumentRemoved = 0x2, OperatorClassArgumentByValue = 0x4, // The removed class argument was passed by value InheritedFromTemplate = 0x8, // Inherited from a template in metabuilder - HiddenFriend = 0x10 + HiddenFriend = 0x10, + PrivateSignal = 0x20 // Private Qt signal (cannot emit from client code) }; Q_DECLARE_FLAGS(Flags, Flag) Flags flags() const; void setFlags(Flags f); - bool isFinalInTargetLang() const; bool isAbstract() const; bool isClassMethod() const; bool isStatic() const; - bool isInvokable() const; bool isPropertyReader() const; bool isPropertyWriter() const; bool isPropertyResetter() const; @@ -231,12 +227,15 @@ public: QString modifiedName() const; QString minimalSignature() const; + /// List of signatures matched for modifications + QStringList modificationSignatures() const; // Signature with replaced argument types and return type for overload // decisor comment. QString signatureComment() const; QString debugSignature() const; // including virtual/override/final, etc., for debugging only. - bool isModifiedRemoved(const AbstractMetaClass *cls = nullptr) const; + bool isModifiedRemoved(AbstractMetaClassCPtr cls = {}) const; + bool isModifiedFinal(AbstractMetaClassCPtr cls = {}) const; bool isVoid() const; @@ -244,19 +243,19 @@ public: void setType(const AbstractMetaType &type); // The class that has this function as a member. - const AbstractMetaClass *ownerClass() const; - void setOwnerClass(const AbstractMetaClass *cls); + AbstractMetaClassCPtr ownerClass() const; + void setOwnerClass(const AbstractMetaClassCPtr &cls); // Owner excluding invisible namespaces - const AbstractMetaClass *targetLangOwner() const; + AbstractMetaClassCPtr targetLangOwner() const; // The first class in a hierarchy that declares the function - const AbstractMetaClass *declaringClass() const; - void setDeclaringClass(const AbstractMetaClass *cls); + AbstractMetaClassCPtr declaringClass() const; + void setDeclaringClass(const AbstractMetaClassCPtr &cls); // The class that actually implements this function - const AbstractMetaClass *implementingClass() const; - void setImplementingClass(const AbstractMetaClass *cls); + AbstractMetaClassCPtr implementingClass() const; + void setImplementingClass(const AbstractMetaClassCPtr &cls); const AbstractMetaArgumentList &arguments() const; AbstractMetaArgumentList &arguments(); @@ -292,11 +291,16 @@ public: /// Return a signature qualified by class name, for error reporting. QString classQualifiedSignature() const; + /// Signature with unresolved typedefs as seen by the code parser + QString unresolvedSignature() const; + void setUnresolvedSignature(const QString &); + bool isConstant() const; void setConstant(bool constant); /// Returns true if the AbstractMetaFunction was added by the user via the type system description. bool isUserAdded() const; + bool isUserAddedPythonOverride() const; /// Returns true if the AbstractMetaFunction was declared by the user via /// the type system description. bool isUserDeclared() const; @@ -310,11 +314,13 @@ public: QString conversionRule(TypeSystem::Language language, int idx) const; bool hasConversionRule(TypeSystem::Language language, int idx) const; - QList<ReferenceCount> referenceCounts(const AbstractMetaClass *cls, int idx = -2) const; - ArgumentOwner argumentOwner(const AbstractMetaClass *cls, int idx) const; + QList<ReferenceCount> + referenceCounts(const AbstractMetaClassCPtr &cls, int idx = -2) const; + ArgumentOwner argumentOwner(const AbstractMetaClassCPtr &cls, int idx) const; // Returns the ownership rules for the given argument (target lang). - TypeSystem::Ownership argumentTargetOwnership(const AbstractMetaClass *cls, int idx) const; + TypeSystem::Ownership + argumentTargetOwnership(const AbstractMetaClassCPtr &cls, int idx) const; const QString &modifiedTypeName() const; bool isTypeModified() const { return !modifiedTypeName().isEmpty(); } @@ -354,29 +360,32 @@ public: */ bool hasSignatureModifications() const; - const FunctionModificationList &modifications(const AbstractMetaClass *implementor = nullptr) const; + const FunctionModificationList &modifications(AbstractMetaClassCPtr implementor = {}) const; void clearModificationsCache(); + const DocModificationList addedFunctionDocModifications() const; + static FunctionModificationList findClassModifications(const AbstractMetaFunction *f, - const AbstractMetaClass *implementor); + AbstractMetaClassCPtr implementor); static FunctionModificationList findGlobalModifications(const AbstractMetaFunction *f); /** * Return the argument name if there is a modification the renamed value will be returned */ - QString argumentName(int index, bool create = true, const AbstractMetaClass *cl = nullptr) const; + QString argumentName(int index, bool create = true, AbstractMetaClassCPtr cl = {}) const; int propertySpecIndex() const; void setPropertySpecIndex(int i); - FunctionTypeEntry* typeEntry() const; + FunctionTypeEntryPtr typeEntry() const; + void setTypeEntry(const FunctionTypeEntryPtr &typeEntry); - void setTypeEntry(FunctionTypeEntry* typeEntry); + QString targetLangPackage() const; bool isCallOperator() const; static AbstractMetaFunctionCPtr - find(const AbstractMetaFunctionCList &haystack, QStringView needle); + find(const AbstractMetaFunctionCList &haystack, QAnyStringView needle); bool matches(OperatorQueryOptions) const; @@ -435,19 +444,14 @@ private: QScopedPointer<AbstractMetaFunctionPrivate> d; }; -inline bool AbstractMetaFunction::isFinalInTargetLang() const -{ - return attributes().testFlag(FinalInTargetLang); -} - inline bool AbstractMetaFunction::isAbstract() const { - return attributes().testFlag(Abstract); + return cppAttributes().testFlag(FunctionAttribute::Abstract); } inline bool AbstractMetaFunction::isStatic() const { - return attributes().testFlag(Static); + return cppAttributes().testFlag(FunctionAttribute::Static); } inline bool AbstractMetaFunction::isClassMethod() const @@ -455,11 +459,6 @@ inline bool AbstractMetaFunction::isClassMethod() const return attributes().testFlag(ClassMethod); } -inline bool AbstractMetaFunction::isInvokable() const -{ - return attributes().testFlag(Invokable); -} - inline bool AbstractMetaFunction::isPropertyReader() const { return attributes().testFlag(PropertyReader); diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp index 33ed659c0..fb49cc9d0 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp @@ -2,10 +2,14 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "abstractmetalang.h" +#include "anystringview_helpers.h" #include "abstractmetalang_helpers.h" +#include "abstractmetaargument.h" #include "abstractmetaenum.h" #include "abstractmetafunction.h" +#include "abstractmetatype.h" #include "abstractmetafield.h" +#include "parser/codemodel.h" #include "documentation.h" #include "messages.h" #include "modifications.h" @@ -53,24 +57,23 @@ public: { } - ~AbstractMetaClassPrivate() - { - qDeleteAll(m_templateArgs); - } - void addFunction(const AbstractMetaFunctionCPtr &function); static AbstractMetaFunction * createFunction(const QString &name, AbstractMetaFunction::FunctionType t, Access access, const AbstractMetaArgumentList &arguments, - const AbstractMetaType &returnType, AbstractMetaClass *q); + const AbstractMetaType &returnType, const AbstractMetaClassPtr &q); void addConstructor(AbstractMetaFunction::FunctionType t, Access access, const AbstractMetaArgumentList &arguments, - AbstractMetaClass *q); - void addUsingConstructors(AbstractMetaClass *q); - bool isUsingMember(const AbstractMetaClass *c, const QString &memberName, + const AbstractMetaClassPtr &q); + void addUsingConstructors(const AbstractMetaClassPtr &q); + void sortFunctions(); + void setFunctions(const AbstractMetaFunctionCList &functions, + const AbstractMetaClassCPtr &q); + bool isUsingMember(const AbstractMetaClassCPtr &c, const QString &memberName, Access minimumAccess) const; bool hasConstructors() const; + qsizetype indexOfProperty(const QString &name) const; uint m_hasVirtuals : 1; uint m_isPolymorphic : 1; @@ -91,14 +94,15 @@ public: Documentation m_doc; - const AbstractMetaClass *m_enclosingClass = nullptr; - const AbstractMetaClass *m_defaultSuperclass = nullptr; + AbstractMetaClassCPtr m_enclosingClass; + AbstractMetaClassCPtr m_defaultSuperclass; AbstractMetaClassCList m_baseClasses; // Real base classes after setting up inheritance AbstractMetaTypeList m_baseTemplateInstantiations; - const AbstractMetaClass *m_extendedNamespace = nullptr; + AbstractMetaClassCPtr m_extendedNamespace; - const AbstractMetaClass *m_templateBaseClass = nullptr; + AbstractMetaClassCPtr m_templateBaseClass; AbstractMetaFunctionCList m_functions; + AbstractMetaFunctionCList m_userAddedPythonOverrides; AbstractMetaFieldList m_fields; AbstractMetaEnumList m_enums; QList<QPropertySpec> m_propertySpecs; @@ -108,8 +112,8 @@ public: AbstractMetaFunctionCList m_externalConversionOperators; QStringList m_baseClassNames; // Base class names from C++, including rejected - TypeEntries m_templateArgs; - ComplexTypeEntry *m_typeEntry = nullptr; + TypeEntryCList m_templateArgs; + ComplexTypeEntryPtr m_typeEntry; SourceLocation m_sourceLocation; UsingMembers m_usingMembers; @@ -174,29 +178,16 @@ AbstractMetaFunctionCList AbstractMetaClass::functionsInTargetLang() const FunctionQueryOptions default_flags = FunctionQueryOption::NormalFunctions | FunctionQueryOption::Visible | FunctionQueryOption::NotRemoved; - // Only public functions in final classes - // default_flags |= isFinal() ? WasPublic : 0; - FunctionQueryOptions public_flags; - if (isFinalInTargetLang()) - public_flags |= FunctionQueryOption::WasPublic; - // Constructors AbstractMetaFunctionCList returned = queryFunctions(FunctionQueryOption::AnyConstructor - | default_flags | public_flags); - - // Final functions - returned += queryFunctions(FunctionQueryOption::FinalInTargetLangFunctions - | FunctionQueryOption::NonStaticFunctions - | default_flags | public_flags); + | default_flags); - // Virtual functions - returned += queryFunctions(FunctionQueryOption::VirtualInTargetLangFunctions - | FunctionQueryOption::NonStaticFunctions - | default_flags | public_flags); + returned += queryFunctions(FunctionQueryOption::NonStaticFunctions + | default_flags); // Static functions returned += queryFunctions(FunctionQueryOption::StaticFunctions - | default_flags | public_flags); + | default_flags); // Empty, private functions, since they aren't caught by the other ones returned += queryFunctions(FunctionQueryOption::Empty | FunctionQueryOption::Invisible); @@ -315,15 +306,15 @@ bool AbstractMetaClass::hasStaticFields() const void AbstractMetaClass::sortFunctions() { - std::sort(d->m_functions.begin(), d->m_functions.end(), function_sorter); + d->sortFunctions(); } -const AbstractMetaClass *AbstractMetaClass::templateBaseClass() const +AbstractMetaClassCPtr AbstractMetaClass::templateBaseClass() const { return d->m_templateBaseClass; } -void AbstractMetaClass::setTemplateBaseClass(const AbstractMetaClass *cls) +void AbstractMetaClass::setTemplateBaseClass(const AbstractMetaClassCPtr &cls) { d->m_templateBaseClass = cls; } @@ -333,17 +324,28 @@ const AbstractMetaFunctionCList &AbstractMetaClass::functions() const return d->m_functions; } -void AbstractMetaClass::setFunctions(const AbstractMetaFunctionCList &functions) +const AbstractMetaFunctionCList &AbstractMetaClass::userAddedPythonOverrides() const +{ + return d->m_userAddedPythonOverrides; +} + +void AbstractMetaClassPrivate::sortFunctions() +{ + std::sort(m_functions.begin(), m_functions.end(), function_sorter); +} + +void AbstractMetaClassPrivate::setFunctions(const AbstractMetaFunctionCList &functions, + const AbstractMetaClassCPtr &q) { - d->m_functions = functions; + m_functions = functions; // Functions must be sorted by name before next loop sortFunctions(); - for (const auto &f : qAsConst(d->m_functions)) { - qSharedPointerConstCast<AbstractMetaFunction>(f)->setOwnerClass(this); + for (const auto &f : std::as_const(m_functions)) { + std::const_pointer_cast<AbstractMetaFunction>(f)->setOwnerClass(q); if (!f->isPublic()) - d->m_hasNonpublic = true; + m_hasNonpublic = true; } } @@ -357,6 +359,13 @@ void AbstractMetaClass::addPropertySpec(const QPropertySpec &spec) d->m_propertySpecs << spec; } +void AbstractMetaClass::setPropertyDocumentation(const QString &name, const Documentation &doc) +{ + const auto index = d->indexOfProperty(name); + if (index >= 0) + d->m_propertySpecs[index].setDocumentation(doc); +} + void AbstractMetaClassPrivate::addFunction(const AbstractMetaFunctionCPtr &function) { Q_ASSERT(!function->signature().startsWith(u'(')); @@ -373,20 +382,27 @@ void AbstractMetaClassPrivate::addFunction(const AbstractMetaFunctionCPtr &funct && function->functionType() == AbstractMetaFunction::ConstructorFunction; } -void AbstractMetaClass::addFunction(const AbstractMetaFunctionCPtr &function) +void AbstractMetaClass::addFunction(const AbstractMetaClassPtr &klass, + const AbstractMetaFunctionCPtr &function) { - auto nonConstF = qSharedPointerConstCast<AbstractMetaFunction>(function); - nonConstF->setOwnerClass(this); + auto nonConstF = std::const_pointer_cast<AbstractMetaFunction>(function); + nonConstF->setOwnerClass(klass); // Set the default value of the declaring class. This may be changed // in fixFunctions later on - nonConstF->setDeclaringClass(this); + nonConstF->setDeclaringClass(klass); // Some of the queries below depend on the implementing class being set // to function properly. Such as function modifications - nonConstF->setImplementingClass(this); + nonConstF->setImplementingClass(klass); - d->addFunction(function); + if (function->isUserAddedPythonOverride()) { + nonConstF->setConstant(false); + nonConstF->setCppAttribute(FunctionAttribute::Static); + klass->d->m_userAddedPythonOverrides.append(function); + } else { + klass->d->addFunction(function); + } } bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const @@ -424,17 +440,17 @@ QString AbstractMetaClass::baseClassName() const } // Attribute "default-superclass" -const AbstractMetaClass *AbstractMetaClass::defaultSuperclass() const +AbstractMetaClassCPtr AbstractMetaClass::defaultSuperclass() const { return d->m_defaultSuperclass; } -void AbstractMetaClass::setDefaultSuperclass(AbstractMetaClass *s) +void AbstractMetaClass::setDefaultSuperclass(const AbstractMetaClassPtr &s) { d->m_defaultSuperclass = s; } -const AbstractMetaClass *AbstractMetaClass::baseClass() const +AbstractMetaClassCPtr AbstractMetaClass::baseClass() const { return d->m_baseClasses.value(0, nullptr); } @@ -449,7 +465,7 @@ const AbstractMetaClassCList &AbstractMetaClass::baseClasses() const AbstractMetaClassCList AbstractMetaClass::typeSystemBaseClasses() const { AbstractMetaClassCList result = d->m_baseClasses; - if (d->m_defaultSuperclass != nullptr) { + if (d->m_defaultSuperclass) { result.removeAll(d->m_defaultSuperclass); result.prepend(d->m_defaultSuperclass); } @@ -461,21 +477,21 @@ AbstractMetaClassCList AbstractMetaClass::allTypeSystemAncestors() const { AbstractMetaClassCList result; const auto baseClasses = typeSystemBaseClasses(); - for (auto *base : baseClasses) { + for (const auto &base : baseClasses) { result.append(base); result.append(base->allTypeSystemAncestors()); } return result; } -void AbstractMetaClass::addBaseClass(const AbstractMetaClass *baseClass) +void AbstractMetaClass::addBaseClass(const AbstractMetaClassCPtr &baseClass) { Q_ASSERT(baseClass); d->m_baseClasses.append(baseClass); d->m_isPolymorphic |= baseClass->isPolymorphic(); } -void AbstractMetaClass::setBaseClass(const AbstractMetaClass *baseClass) +void AbstractMetaClass::setBaseClass(const AbstractMetaClassCPtr &baseClass) { if (baseClass) { d->m_baseClasses.prepend(baseClass); @@ -483,12 +499,12 @@ void AbstractMetaClass::setBaseClass(const AbstractMetaClass *baseClass) } } -const AbstractMetaClass *AbstractMetaClass::extendedNamespace() const +AbstractMetaClassCPtr AbstractMetaClass::extendedNamespace() const { return d->m_extendedNamespace; } -void AbstractMetaClass::setExtendedNamespace(const AbstractMetaClass *e) +void AbstractMetaClass::setExtendedNamespace(const AbstractMetaClassCPtr &e) { d->m_extendedNamespace = e; } @@ -498,7 +514,7 @@ const AbstractMetaClassCList &AbstractMetaClass::innerClasses() const return d->m_innerClasses; } -void AbstractMetaClass::addInnerClass(AbstractMetaClass *cl) +void AbstractMetaClass::addInnerClass(const AbstractMetaClassPtr &cl) { d->m_innerClasses << cl; } @@ -526,6 +542,16 @@ bool AbstractMetaClass::isInvisibleNamespace() const && !NamespaceTypeEntry::isVisibleScope(d->m_typeEntry); } +bool AbstractMetaClass::isInlineNamespace() const +{ + bool result = false; + if (d->m_typeEntry->isNamespace()) { + const auto nte = std::static_pointer_cast<const NamespaceTypeEntry>(d->m_typeEntry); + result = nte->isInlineNamespace(); + } + return result; +} + bool AbstractMetaClass::isQtNamespace() const { return isNamespace() && name() == u"Qt"; @@ -538,15 +564,15 @@ QString AbstractMetaClass::qualifiedCppName() const bool AbstractMetaClass::hasFunction(const QString &str) const { - return !findFunction(str).isNull(); + return bool(findFunction(str)); } -AbstractMetaFunctionCPtr AbstractMetaClass::findFunction(QStringView functionName) const +AbstractMetaFunctionCPtr AbstractMetaClass::findFunction(QAnyStringView functionName) const { return AbstractMetaFunction::find(d->m_functions, functionName); } -AbstractMetaFunctionCList AbstractMetaClass::findFunctions(QStringView functionName) const +AbstractMetaFunctionCList AbstractMetaClass::findFunctions(QAnyStringView functionName) const { AbstractMetaFunctionCList result; std::copy_if(d->m_functions.cbegin(), d->m_functions.cend(), @@ -588,12 +614,12 @@ bool AbstractMetaClass::hasProtectedFields() const return false; } -const TypeEntries &AbstractMetaClass::templateArguments() const +const TypeEntryCList &AbstractMetaClass::templateArguments() const { return d->m_templateArgs; } -void AbstractMetaClass::setTemplateArguments(const TypeEntries &args) +void AbstractMetaClass::setTemplateArguments(const TypeEntryCList &args) { d->m_templateArgs = args; } @@ -608,17 +634,17 @@ void AbstractMetaClass::setBaseClassNames(const QStringList &names) d->m_baseClassNames = names; } -const ComplexTypeEntry *AbstractMetaClass::typeEntry() const +ComplexTypeEntryCPtr AbstractMetaClass::typeEntry() const { return d->m_typeEntry; } -ComplexTypeEntry *AbstractMetaClass::typeEntry() +ComplexTypeEntryPtr AbstractMetaClass::typeEntry() { return d->m_typeEntry; } -void AbstractMetaClass::setTypeEntry(ComplexTypeEntry *type) +void AbstractMetaClass::setTypeEntry(const ComplexTypeEntryPtr &type) { d->m_typeEntry = type; } @@ -642,7 +668,7 @@ bool AbstractMetaClass::hasHashFunction() const AbstractMetaClass::PropertyFunctionSearchResult AbstractMetaClass::searchPropertyFunction(const QString &name) const { - for (int i = 0, size = d->m_propertySpecs.size(); i < size; ++i) { + for (qsizetype i = 0, size = d->m_propertySpecs.size(); i < size; ++i) { const auto &propertySpec = d->m_propertySpecs.at(i); if (name == propertySpec.read()) return PropertyFunctionSearchResult{i, PropertyFunction::Read}; @@ -650,6 +676,8 @@ AbstractMetaClass::PropertyFunctionSearchResult return PropertyFunctionSearchResult{i, PropertyFunction::Write}; if (name == propertySpec.reset()) return PropertyFunctionSearchResult{i, PropertyFunction::Reset}; + if (name == propertySpec.notify()) + return PropertyFunctionSearchResult{i, PropertyFunction::Notify}; } return PropertyFunctionSearchResult{-1, PropertyFunction::Read}; } @@ -657,10 +685,9 @@ AbstractMetaClass::PropertyFunctionSearchResult std::optional<QPropertySpec> AbstractMetaClass::propertySpecByName(const QString &name) const { - for (const auto &propertySpec : d->m_propertySpecs) { - if (name == propertySpec.name()) - return propertySpec; - } + const auto index = d->indexOfProperty(name); + if (index >= 0) + return d->m_propertySpecs.at(index); return {}; } @@ -745,6 +772,15 @@ bool AbstractMetaClassPrivate::hasConstructors() const FunctionQueryOption::AnyConstructor) != nullptr; } +qsizetype AbstractMetaClassPrivate::indexOfProperty(const QString &name) const +{ + for (qsizetype i = 0; i < m_propertySpecs.size(); ++i) { + if (m_propertySpecs.at(i).name() == name) + return i; + } + return -1; +} + bool AbstractMetaClass::hasConstructors() const { return d->hasConstructors(); @@ -767,41 +803,40 @@ bool AbstractMetaClass::hasCopyConstructor() const bool AbstractMetaClass::hasPrivateCopyConstructor() const { const auto copyCt = copyConstructor(); - return !copyCt.isNull() && copyCt->isPrivate(); + return copyCt && copyCt->isPrivate(); } void AbstractMetaClassPrivate::addConstructor(AbstractMetaFunction::FunctionType t, Access access, const AbstractMetaArgumentList &arguments, - AbstractMetaClass *q) + const AbstractMetaClassPtr &q) { auto *f = createFunction(q->name(), t, access, arguments, AbstractMetaType::createVoid(), q); if (access != Access::Private) m_hasNonPrivateConstructor = true; - f->setAttributes(AbstractMetaFunction::FinalInTargetLang - | AbstractMetaFunction::AddedMethod); + f->setAttributes(AbstractMetaFunction::AddedMethod); addFunction(AbstractMetaFunctionCPtr(f)); } -void AbstractMetaClass::addDefaultConstructor() +void AbstractMetaClass::addDefaultConstructor(const AbstractMetaClassPtr &klass) { - d->addConstructor(AbstractMetaFunction::ConstructorFunction, - Access::Public, {}, this); + klass->d->addConstructor(AbstractMetaFunction::ConstructorFunction, + Access::Public, {}, klass); } -void AbstractMetaClass::addDefaultCopyConstructor() +void AbstractMetaClass::addDefaultCopyConstructor(const AbstractMetaClassPtr &klass) { - AbstractMetaType argType(typeEntry()); + AbstractMetaType argType(klass->typeEntry()); argType.setReferenceType(LValueReference); argType.setConstant(true); argType.setTypeUsagePattern(AbstractMetaType::ValuePattern); AbstractMetaArgument arg; arg.setType(argType); - arg.setName(name()); + arg.setName(klass->name()); - d->addConstructor(AbstractMetaFunction::CopyConstructorFunction, - Access::Public, {arg}, this); + klass->d->addConstructor(AbstractMetaFunction::CopyConstructorFunction, + Access::Public, {arg}, klass); } AbstractMetaFunction * @@ -810,7 +845,7 @@ AbstractMetaFunction * Access access, const AbstractMetaArgumentList &arguments, const AbstractMetaType &returnType, - AbstractMetaClass *q) + const AbstractMetaClassPtr &q) { auto *f = new AbstractMetaFunction(name); f->setType(returnType); @@ -825,7 +860,7 @@ AbstractMetaFunction * static AbstractMetaType boolType() { - auto *boolType = TypeDatabase::instance()->findType(u"bool"_s); + auto boolType = TypeDatabase::instance()->findType(u"bool"_s); Q_ASSERT(boolType); AbstractMetaType result(boolType); result.decideUsagePattern(); @@ -835,17 +870,17 @@ static AbstractMetaType boolType() // Helper to synthesize comparison operators from a spaceship operator. Since // shiboken also generates code for comparing to different types, this fits // better than of handling it in the generator code. -void AbstractMetaClass::addSynthesizedComparisonOperators() +void AbstractMetaClass::addSynthesizedComparisonOperators(const AbstractMetaClassPtr &c) { static const auto returnType = boolType(); - AbstractMetaType selfType(typeEntry()); + AbstractMetaType selfType(c->typeEntry()); selfType.setConstant(true); selfType.setReferenceType(LValueReference); selfType.decideUsagePattern(); AbstractMetaArgument selfArgument; selfArgument.setType(selfType); - selfArgument.setName(u"rhs"_qs); + selfArgument.setName(u"rhs"_s); AbstractMetaArgumentList arguments(1, selfArgument); static const char *operators[] @@ -854,8 +889,8 @@ void AbstractMetaClass::addSynthesizedComparisonOperators() auto *f = AbstractMetaClassPrivate::createFunction(QLatin1StringView(op), AbstractMetaFunction::ComparisonOperator, Access::Public, arguments, - returnType, this); - d->addFunction(AbstractMetaFunctionCPtr(f)); + returnType, c); + c->d->addFunction(AbstractMetaFunctionCPtr(f)); } } @@ -961,7 +996,7 @@ bool AbstractMetaClass::isImplicitlyDefaultConstructible() const return std::all_of(d->m_fields.cbegin(), d->m_fields.cend(), defaultConstructibleField) && std::all_of(d->m_baseClasses.cbegin(), d->m_baseClasses.cend(), - [] (const AbstractMetaClass *c) { + [] (const AbstractMetaClassCPtr &c) { return c->isDefaultConstructible(); }); } @@ -969,6 +1004,7 @@ bool AbstractMetaClass::isImplicitlyDefaultConstructible() const static bool canAddDefaultConstructorHelper(const AbstractMetaClass *cls) { return !cls->isNamespace() + && !cls->hasDeletedDefaultConstructor() && !cls->attributes().testFlag(AbstractMetaClass::HasRejectedConstructor) && !cls->hasPrivateDestructor(); } @@ -995,7 +1031,7 @@ bool AbstractMetaClass::isImplicitlyCopyConstructible() const { // Fields are currently not considered return std::all_of(d->m_baseClasses.cbegin(), d->m_baseClasses.cend(), - [] (const AbstractMetaClass *c) { + [] (const AbstractMetaClassCPtr &c) { return c->isCopyConstructible(); }); } @@ -1010,16 +1046,16 @@ bool AbstractMetaClass::canAddDefaultCopyConstructor() const return isImplicitlyCopyConstructible(); } -static bool classHasParentManagement(const AbstractMetaClass *c) +static bool classHasParentManagement(const AbstractMetaClassCPtr &c) { const auto flags = c->typeEntry()->typeFlags(); return flags.testFlag(ComplexTypeEntry::ParentManagement); } -const TypeEntry *AbstractMetaClass::parentManagementEntry() const +TypeEntryCPtr parentManagementEntry(const AbstractMetaClassCPtr &klass) { - if (isObjectType()) { - if (auto *c = recurseClassHierarchy(this, classHasParentManagement)) + if (klass->typeEntry()->isObject()) { + if (auto c = recurseClassHierarchy(klass, classHasParentManagement)) return c->typeEntry(); } return nullptr; @@ -1089,7 +1125,7 @@ void AbstractMetaClass::addUsingMember(const UsingMember &um) d->m_usingMembers.append(um); } -bool AbstractMetaClassPrivate::isUsingMember(const AbstractMetaClass *c, +bool AbstractMetaClassPrivate::isUsingMember(const AbstractMetaClassCPtr &c, const QString &memberName, Access minimumAccess) const { @@ -1100,7 +1136,7 @@ bool AbstractMetaClassPrivate::isUsingMember(const AbstractMetaClass *c, return it != m_usingMembers.cend() && it->access >= minimumAccess; } -bool AbstractMetaClass::isUsingMember(const AbstractMetaClass *c, +bool AbstractMetaClass::isUsingMember(const AbstractMetaClassCPtr &c, const QString &memberName, Access minimumAccess) const { @@ -1131,24 +1167,15 @@ bool AbstractMetaClass::queryFunction(const AbstractMetaFunction *f, FunctionQue if (query.testFlag(FunctionQueryOption::Visible) && f->isPrivate()) return false; - if (query.testFlag(FunctionQueryOption::VirtualInTargetLangFunctions) && f->isFinalInTargetLang()) - return false; - if (query.testFlag(FunctionQueryOption::Invisible) && !f->isPrivate()) return false; if (query.testFlag(FunctionQueryOption::Empty) && !f->isEmptyFunction()) return false; - if (query.testFlag(FunctionQueryOption::WasPublic) && !f->wasPublic()) - return false; - if (query.testFlag(FunctionQueryOption::ClassImplements) && f->ownerClass() != f->implementingClass()) return false; - if (query.testFlag(FunctionQueryOption::FinalInTargetLangFunctions) && !f->isFinalInTargetLang()) - return false; - if (query.testFlag(FunctionQueryOption::VirtualInCppFunctions) && !f->isVirtual()) return false; @@ -1212,7 +1239,7 @@ AbstractMetaFunctionCList AbstractMetaClass::queryFunctionList(const AbstractMet { AbstractMetaFunctionCList result; for (const auto &f : list) { - if (queryFunction(f.data(), query)) + if (queryFunction(f.get(), query)) result.append(f); } return result; @@ -1222,7 +1249,7 @@ AbstractMetaFunctionCPtr AbstractMetaClass::queryFirstFunction(const AbstractMet FunctionQueryOptions query) { for (const auto &f : list) { - if (queryFunction(f.data(), query)) + if (queryFunction(f.get(), query)) return f; } return {}; @@ -1290,7 +1317,7 @@ std::optional<AbstractMetaEnum> std::optional<AbstractMetaEnumValue> AbstractMetaClass::findEnumValue(const QString &enumValueName) const { - for (const AbstractMetaEnum &e : qAsConst(d->m_enums)) { + for (const AbstractMetaEnum &e : std::as_const(d->m_enums)) { auto v = e.findEnumValue(enumValueName); if (v.has_value()) return v; @@ -1312,7 +1339,7 @@ void AbstractMetaClass::getEnumsToBeGenerated(AbstractMetaEnumList *enumList) co void AbstractMetaClass::getEnumsFromInvisibleNamespacesToBeGenerated(AbstractMetaEnumList *enumList) const { if (isNamespace()) { - invisibleNamespaceRecursion([enumList](const AbstractMetaClass *c) { + invisibleNamespaceRecursion([enumList](const AbstractMetaClassCPtr &c) { c->getEnumsToBeGenerated(enumList); }); } @@ -1321,7 +1348,7 @@ void AbstractMetaClass::getEnumsFromInvisibleNamespacesToBeGenerated(AbstractMet void AbstractMetaClass::getFunctionsFromInvisibleNamespacesToBeGenerated(AbstractMetaFunctionCList *funcList) const { if (isNamespace()) { - invisibleNamespaceRecursion([funcList](const AbstractMetaClass *c) { + invisibleNamespaceRecursion([funcList](const AbstractMetaClassCPtr &c) { funcList->append(c->functions()); }); } @@ -1332,16 +1359,16 @@ QString AbstractMetaClass::fullName() const return package() + u'.' + d->m_typeEntry->targetLangName(); } -static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractMetaType &type) +static void addExtraIncludeForType(const AbstractMetaClassPtr &metaClass, + const AbstractMetaType &type) { Q_ASSERT(metaClass); - const TypeEntry *entry = type.typeEntry(); - if (entry && entry->isComplex()) { - const auto *centry = static_cast<const ComplexTypeEntry *>(entry); - ComplexTypeEntry *class_entry = metaClass->typeEntry(); - if (class_entry && centry->include().isValid()) - class_entry->addArgumentInclude(centry->include()); + const auto entry = type.typeEntry(); + + if (entry && entry->include().isValid()) { + const auto class_entry = metaClass->typeEntry(); + class_entry->addArgumentInclude(entry->include()); } if (type.hasInstantiations()) { @@ -1350,7 +1377,7 @@ static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractM } } -static void addExtraIncludesForFunction(AbstractMetaClass *metaClass, +static void addExtraIncludesForFunction(const AbstractMetaClassPtr &metaClass, const AbstractMetaFunctionCPtr &meta_function) { Q_ASSERT(metaClass); @@ -1358,8 +1385,12 @@ static void addExtraIncludesForFunction(AbstractMetaClass *metaClass, addExtraIncludeForType(metaClass, meta_function->type()); const AbstractMetaArgumentList &arguments = meta_function->arguments(); - for (const AbstractMetaArgument &argument : arguments) - addExtraIncludeForType(metaClass, argument.type()); + for (const AbstractMetaArgument &argument : arguments) { + const auto &type = argument.type(); + addExtraIncludeForType(metaClass, type); + if (argument.modifiedType() != type) + addExtraIncludeForType(metaClass, argument.modifiedType()); + } } static bool addSuperFunction(const AbstractMetaFunctionCPtr &f) @@ -1381,7 +1412,7 @@ static bool addSuperFunction(const AbstractMetaFunctionCPtr &f) // Add constructors imported via "using" from the base classes. This is not // needed for normal hidden inherited member functions since we generate a // cast to the base class to call them into binding code. -void AbstractMetaClassPrivate::addUsingConstructors(AbstractMetaClass *q) +void AbstractMetaClassPrivate::addUsingConstructors(const AbstractMetaClassPtr &q) { // Restricted to the non-constructor case currently to avoid // having to compare the parameter lists of existing constructors. @@ -1390,7 +1421,7 @@ void AbstractMetaClassPrivate::addUsingConstructors(AbstractMetaClass *q) return; } - for (auto superClass : m_baseClasses) { + for (const auto &superClass : m_baseClasses) { // Find any "using base-constructor" directives if (isUsingMember(superClass, superClass->name(), Access::Protected)) { // Add to derived class with parameter lists. @@ -1405,51 +1436,61 @@ void AbstractMetaClassPrivate::addUsingConstructors(AbstractMetaClass *q) } } -void AbstractMetaClass::fixFunctions() +static inline bool isSignal(const AbstractMetaFunctionCPtr &f) +{ + return f->isSignal(); +} + +void AbstractMetaClass::fixFunctions(const AbstractMetaClassPtr &klass) { + auto *d = klass->d.data(); if (d->m_functionsFixed) return; d->m_functionsFixed = true; - AbstractMetaFunctionCList funcs = functions(); + AbstractMetaFunctionCList funcs = klass->functions(); AbstractMetaFunctionCList nonRemovedFuncs; nonRemovedFuncs.reserve(funcs.size()); - d->addUsingConstructors(this); + d->addUsingConstructors(klass); - for (const auto &f : qAsConst(funcs)) { + for (const auto &f : std::as_const(funcs)) { // Fishy: Setting up of implementing/declaring/base classes changes // the applicable modifications; clear cached ones. - qSharedPointerConstCast<AbstractMetaFunction>(f)->clearModificationsCache(); + std::const_pointer_cast<AbstractMetaFunction>(f)->clearModificationsCache(); if (!f->isModifiedRemoved()) nonRemovedFuncs.append(f); } - for (auto *superClassC : d->m_baseClasses) { - auto *superClass = const_cast<AbstractMetaClass *>(superClassC); - superClass->fixFunctions(); + for (const auto &superClassC : d->m_baseClasses) { + for (const auto &pof : superClassC->userAddedPythonOverrides()) { + auto *clonedPof = pof->copy(); + clonedPof->setOwnerClass(klass); + d->m_userAddedPythonOverrides.append(AbstractMetaFunctionCPtr{clonedPof}); + } + + auto superClass = std::const_pointer_cast<AbstractMetaClass>(superClassC); + AbstractMetaClass::fixFunctions(superClass); // Since we always traverse the complete hierarchy we are only // interrested in what each super class implements, not what // we may have propagated from their base classes again. AbstractMetaFunctionCList superFuncs; - // Super classes can never be final - if (superClass->isFinalInTargetLang()) { - qCWarning(lcShiboken).noquote().nospace() - << "Final class '" << superClass->name() << "' set to non-final, as it is extended by other classes"; - *superClass -= AbstractMetaClass::FinalInTargetLang; - } superFuncs = superClass->queryFunctions(FunctionQueryOption::ClassImplements); + // We are not interested in signals as no bindings are generated for them; + // they cause documentation warnings. + superFuncs.erase(std::remove_if(superFuncs.begin(), superFuncs.end(), isSignal), + superFuncs.end()); const auto virtuals = superClass->queryFunctions(FunctionQueryOption::VirtualInCppFunctions); superFuncs += virtuals; QSet<AbstractMetaFunctionCPtr> funcsToAdd; - for (const auto &sf : qAsConst(superFuncs)) { + for (const auto &sf : std::as_const(superFuncs)) { if (sf->isModifiedRemoved()) continue; // skip functions added in base classes - if (sf->isUserAdded() && sf->declaringClass() != this) + if (sf->isUserAdded() && sf->declaringClass() != klass) continue; // Skip base class comparison operators declared as members (free @@ -1460,43 +1501,25 @@ void AbstractMetaClass::fixFunctions() // we generally don't care about private functions, but we have to get the ones that are // virtual in case they override abstract functions. bool add = addSuperFunction(sf); - for (const auto &cf : qAsConst(nonRemovedFuncs)) { - AbstractMetaFunctionPtr f(qSharedPointerConstCast<AbstractMetaFunction>(cf)); - const AbstractMetaFunction::CompareResult cmp = cf->compareTo(sf.data()); + for (const auto &cf : std::as_const(nonRemovedFuncs)) { + AbstractMetaFunctionPtr f(std::const_pointer_cast<AbstractMetaFunction>(cf)); + const AbstractMetaFunction::CompareResult cmp = cf->compareTo(sf.get()); if (cmp & AbstractMetaFunction::EqualModifiedName) { add = false; if (cmp & AbstractMetaFunction::EqualArguments) { // Set "override" in case it was not spelled out (since it // is then not detected by clang parsing). - const auto attributes = cf->attributes(); - if (cf->isVirtual() - && !attributes.testFlag(AbstractMetaFunction::OverriddenCppMethod) - && !attributes.testFlag(AbstractMetaFunction::FinalCppMethod)) { - *f += AbstractMetaFunction::OverriddenCppMethod; - } - // Same function, propegate virtual... - if (!(cmp & AbstractMetaFunction::EqualAttributes)) { - if (!f->isEmptyFunction()) { - if (!sf->isFinalInTargetLang() && f->isFinalInTargetLang()) { - *f -= AbstractMetaFunction::FinalInTargetLang; - } -#if 0 - if (!f->isFinalInTargetLang() && f->isPrivate()) { - f->setFunctionType(AbstractMetaFunction::EmptyFunction); - f->setVisibility(AbstractMetaAttributes::Protected); - *f += AbstractMetaAttributes::FinalInTargetLang; - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("private virtual function '%1' in '%2'") - .arg(f->signature(), f->implementingClass()->name()); - } -#endif - } + const auto attributes = cf->cppAttributes(); + if (attributes.testFlag(FunctionAttribute::Virtual) + && !attributes.testFlag(FunctionAttribute::Override) + && !attributes.testFlag(FunctionAttribute::Final)) { + f->setCppAttribute(FunctionAttribute::Override); } if (f->access() != sf->access()) { qCWarning(lcShiboken, "%s", - qPrintable(msgFunctionVisibilityModified(this, f.data()))); + qPrintable(msgFunctionVisibilityModified(klass, f.get()))); #if 0 // If new visibility is private, we can't // do anything. If it isn't, then we @@ -1508,43 +1531,12 @@ void AbstractMetaClass::fixFunctions() // Private overrides of abstract functions have to go into the class or // the subclasses will not compile as non-abstract classes. // But they don't need to be implemented, since they can never be called. - if (f->isPrivate()) { + if (f->isPrivate()) f->setFunctionType(AbstractMetaFunction::EmptyFunction); - *f += AbstractMetaFunction::FinalInTargetLang; - } } // Set the class which first declares this function, afawk f->setDeclaringClass(sf->declaringClass()); - - if (sf->isFinalInTargetLang() && !sf->isPrivate() && !f->isPrivate() && !sf->isStatic() && !f->isStatic()) { - // Shadowed funcion, need to make base class - // function non-virtual - if (f->implementingClass() != sf->implementingClass() && f->implementingClass()->inheritsFrom(sf->implementingClass())) { - - // Check whether the superclass method has been redefined to non-final - - bool hasNonFinalModifier = false; - bool isBaseImplPrivate = false; - const FunctionModificationList &mods = sf->modifications(sf->implementingClass()); - for (const FunctionModification &mod : mods) { - if (mod.isNonFinal()) { - hasNonFinalModifier = true; - break; - } - if (mod.isPrivate()) { - isBaseImplPrivate = true; - break; - } - } - - if (!hasNonFinalModifier && !isBaseImplPrivate) { - qCWarning(lcShiboken, "%s", - qPrintable(msgShadowingFunction(sf.data(), f.data()))); - } - } - } - } if (cmp & AbstractMetaFunction::EqualDefaultValueOverload) { @@ -1572,7 +1564,7 @@ void AbstractMetaClass::fixFunctions() funcsToAdd << sf; } - for (const auto &f : qAsConst(funcsToAdd)) { + for (const auto &f : std::as_const(funcsToAdd)) { AbstractMetaFunction *copy = f->copy(); (*copy) += AbstractMetaFunction::AddedMethod; funcs.append(AbstractMetaFunctionCPtr(copy)); @@ -1582,9 +1574,9 @@ void AbstractMetaClass::fixFunctions() bool hasPrivateConstructors = false; bool hasPublicConstructors = false; // Apply modifications after the declaring class has been set - for (const auto &func : qAsConst(funcs)) { - auto ncFunc = qSharedPointerConstCast<AbstractMetaFunction>(func); - for (const auto &mod : func->modifications(this)) { + for (const auto &func : std::as_const(funcs)) { + auto ncFunc = std::const_pointer_cast<AbstractMetaFunction>(func); + for (const auto &mod : func->modifications(klass)) { if (mod.isRenameModifier()) ncFunc->setName(mod.renamedToName()); } @@ -1592,8 +1584,8 @@ void AbstractMetaClass::fixFunctions() // Make sure class is abstract if one of the functions is if (func->isAbstract()) { - (*this) += AbstractMetaClass::Abstract; - (*this) -= AbstractMetaClass::FinalInTargetLang; + (*klass) += AbstractMetaClass::Abstract; + (*klass) -= AbstractMetaClass::FinalInTargetLang; } if (func->isConstructor()) { @@ -1606,15 +1598,15 @@ void AbstractMetaClass::fixFunctions() // Make sure that we include files for all classes that are in use - addExtraIncludesForFunction(this, func); + addExtraIncludesForFunction(klass, func); } if (hasPrivateConstructors && !hasPublicConstructors) { - (*this) += AbstractMetaClass::Abstract; - (*this) -= AbstractMetaClass::FinalInTargetLang; + (*klass) += AbstractMetaClass::Abstract; + (*klass) -= AbstractMetaClass::FinalInTargetLang; } - setFunctions(funcs); + d->setFunctions(funcs, klass); } bool AbstractMetaClass::needsInheritanceSetup() const @@ -1623,6 +1615,7 @@ bool AbstractMetaClass::needsInheritanceSetup() const switch (d->m_typeEntry->type()) { case TypeEntry::NamespaceType: case TypeEntry::SmartPointerType: + case TypeEntry::ContainerType: return false; default: break; @@ -1654,11 +1647,11 @@ std::optional<AbstractMetaEnumValue> if (lst.size() > 1) { const auto &prefixName = lst.at(0); const auto &enumName = lst.at(1); - if (auto *cl = findClass(classes, prefixName)) + if (auto cl = findClass(classes, prefixName)) return cl->findEnumValue(enumName.toString()); } - for (AbstractMetaClass *metaClass : classes) { + for (const auto &metaClass : classes) { auto enumValue = metaClass->findEnumValue(name); if (enumValue.has_value()) return enumValue; @@ -1672,12 +1665,12 @@ std::optional<AbstractMetaEnumValue> /// Target language base name or complete Target language package.class name. template <class It> -static It findClassHelper(It begin, It end, QStringView name) +static It findClassHelper(It begin, It end, QAnyStringView name) { if (name.isEmpty() || begin == end) return end; - if (name.contains(u'.')) { // Search target lang name + if (asv_contains(name,'.')) { // Search target lang name for (auto it = begin; it != end; ++it) { if ((*it)->fullName() == name) return it; @@ -1690,7 +1683,7 @@ static It findClassHelper(It begin, It end, QStringView name) return it; } - if (name.contains(u"::")) // Qualified, cannot possibly match name + if (asv_contains(name, "::")) // Qualified, cannot possibly match name return end; for (auto it = begin; it != end; ++it) { @@ -1701,32 +1694,32 @@ static It findClassHelper(It begin, It end, QStringView name) return end; } -AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes, - QStringView name) +AbstractMetaClassPtr AbstractMetaClass::findClass(const AbstractMetaClassList &classes, + QAnyStringView name) { auto it =findClassHelper(classes.cbegin(), classes.cend(), name); return it != classes.cend() ? *it : nullptr; } -const AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassCList &classes, - QStringView name) +AbstractMetaClassCPtr AbstractMetaClass::findClass(const AbstractMetaClassCList &classes, + QAnyStringView name) { auto it = findClassHelper(classes.cbegin(), classes.cend(), name); return it != classes.cend() ? *it : nullptr; } -AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes, - const TypeEntry *typeEntry) +AbstractMetaClassPtr AbstractMetaClass::findClass(const AbstractMetaClassList &classes, + const TypeEntryCPtr &typeEntry) { - for (AbstractMetaClass *c : classes) { + for (AbstractMetaClassPtr c : classes) { if (c->typeEntry() == typeEntry) return c; } return nullptr; } -const AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassCList &classes, - const TypeEntry *typeEntry) +AbstractMetaClassCPtr AbstractMetaClass::findClass(const AbstractMetaClassCList &classes, + const TypeEntryCPtr &typeEntry) { for (auto c : classes) { if (c->typeEntry() == typeEntry) @@ -1736,40 +1729,41 @@ const AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassCLi } /// Returns true if this class is a subclass of the given class -bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const +bool inheritsFrom(const AbstractMetaClassCPtr &c, const AbstractMetaClassCPtr &cls) { Q_ASSERT(cls != nullptr); - if (this == cls || d->m_templateBaseClass == cls) + if (c == cls || c->templateBaseClass() == cls) return true; - return recurseClassHierarchy(this, [cls](const AbstractMetaClass *c) { - return cls == c; - }) != nullptr; + return bool(recurseClassHierarchy(c, [cls](const AbstractMetaClassCPtr &c) { + return cls.get() == c.get(); + })); } -bool AbstractMetaClass::inheritsFrom(const QString &name) const +bool inheritsFrom(const AbstractMetaClassCPtr &c, QAnyStringView name) { - if (this->qualifiedCppName() == name) + if (c->qualifiedCppName() == name) return true; - if (d->m_templateBaseClass != nullptr - && d->m_templateBaseClass->qualifiedCppName() == name) { + if (c->templateBaseClass() != nullptr + && c->templateBaseClass()->qualifiedCppName() == name) { return true; } - return recurseClassHierarchy(this, [&name](const AbstractMetaClass *c) { + return bool(recurseClassHierarchy(c, [&name](const AbstractMetaClassCPtr &c) { return c->qualifiedCppName() == name; - }) != nullptr; + })); } -const AbstractMetaClass *AbstractMetaClass::findBaseClass(const QString &qualifiedName) const +AbstractMetaClassCPtr findBaseClass(const AbstractMetaClassCPtr &c, + const QString &qualifiedName) { - if (d->m_templateBaseClass != nullptr - && d->m_templateBaseClass->qualifiedCppName() == qualifiedName) { - return d->m_templateBaseClass; - } - return recurseClassHierarchy(this, [&qualifiedName](const AbstractMetaClass *c) { + auto tp = c->templateBaseClass(); + if (tp && tp->qualifiedCppName() == qualifiedName) + return tp; + + return recurseClassHierarchy(c, [&qualifiedName](const AbstractMetaClassCPtr &c) { return c->qualifiedCppName() == qualifiedName; }); } @@ -1799,7 +1793,7 @@ void AbstractMetaClass::setValueTypeWithCopyConstructorOnly(bool v) d->m_valueTypeWithCopyConstructorOnly = v; } -bool AbstractMetaClass::determineValueTypeWithCopyConstructorOnly(const AbstractMetaClass *c, +bool AbstractMetaClass::determineValueTypeWithCopyConstructorOnly(const AbstractMetaClassCPtr &c, bool avoidProtectedHack) { @@ -1835,8 +1829,8 @@ void AbstractMetaClass::format(QDebug &debug) const if (debug.verbosity() > 2) debug << static_cast<const void *>(this) << ", "; debug << '"' << qualifiedCppName(); - if (const int count = d->m_templateArgs.size()) { - for (int i = 0; i < count; ++i) + if (const auto count = d->m_templateArgs.size()) { + for (qsizetype i = 0; i < count; ++i) debug << (i ? ',' : '<') << d->m_templateArgs.at(i)->qualifiedCppName(); debug << '>'; } @@ -1865,7 +1859,7 @@ void AbstractMetaClass::format(QDebug &debug) const if (!d->m_baseClasses.isEmpty()) { debug << ", inherits "; - for (auto b : d->m_baseClasses) + for (const auto &b : d->m_baseClasses) debug << " \"" << b->name() << '"'; } @@ -1880,13 +1874,13 @@ void AbstractMetaClass::format(QDebug &debug) const if (auto templateBase = templateBaseClass()) { const auto &instantiatedTypes = templateBaseClassInstantiations(); debug << ", instantiates \"" << templateBase->name(); - for (int i = 0, count = instantiatedTypes.size(); i < count; ++i) + for (qsizetype i = 0, count = instantiatedTypes.size(); i < count; ++i) debug << (i ? ',' : '<') << instantiatedTypes.at(i).name(); debug << ">\""; } - if (const int count = d->m_propertySpecs.size()) { + if (const auto count = d->m_propertySpecs.size()) { debug << ", properties (" << count << "): ["; - for (int i = 0; i < count; ++i) { + for (qsizetype i = 0; i < count; ++i) { if (i) debug << ", "; d->m_propertySpecs.at(i).formatDebug(debug); @@ -1900,18 +1894,18 @@ void AbstractMetaClass::formatMembers(QDebug &debug) const if (!d->m_enums.isEmpty()) debug << ", enums[" << d->m_enums.size() << "]=" << d->m_enums; if (!d->m_functions.isEmpty()) { - const int count = d->m_functions.size(); + const auto count = d->m_functions.size(); debug << ", functions=[" << count << "]("; - for (int i = 0; i < count; ++i) { + for (qsizetype i = 0; i < count; ++i) { if (i) debug << ", "; d->m_functions.at(i)->formatDebugBrief(debug); } debug << ')'; } - if (const int count = d->m_fields.size()) { + if (const auto count = d->m_fields.size()) { debug << ", fields=[" << count << "]("; - for (int i = 0; i < count; ++i) { + for (qsizetype i = 0; i < count; ++i) { if (i) debug << ", "; d->m_fields.at(i).formatDebug(debug); @@ -1930,6 +1924,18 @@ void AbstractMetaClass::setSourceLocation(const SourceLocation &sourceLocation) d->m_sourceLocation = sourceLocation; } +AbstractMetaClassCList allBaseClasses(const AbstractMetaClassCPtr metaClass) +{ + AbstractMetaClassCList result; + recurseClassHierarchy(metaClass, [&result] (const AbstractMetaClassCPtr &c) { + if (!result.contains(c)) + result.append(c); + return false; + }); + result.removeFirst(); // remove self + return result; +} + QDebug operator<<(QDebug debug, const UsingMember &d) { QDebugStateSaver saver(debug); @@ -1940,20 +1946,38 @@ QDebug operator<<(QDebug debug, const UsingMember &d) return debug; } -QDebug operator<<(QDebug d, const AbstractMetaClass *ac) +void formatMetaClass(QDebug &ddebug, const AbstractMetaClass *ac) { - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaClass("; - if (ac) { - ac->format(d); - if (d.verbosity() > 2) - ac->formatMembers(d); + QDebugStateSaver saver(ddebug); + ddebug.noquote(); + ddebug.nospace(); + ddebug << "AbstractMetaClass("; + if (ac != nullptr) { + ac->format(ddebug); + if (ddebug.verbosity() > 2) + ac->formatMembers(ddebug); } else { - d << '0'; + ddebug << '0'; } - d << ')'; + ddebug << ')'; +} + +QDebug operator<<(QDebug d, const AbstractMetaClassCPtr &ac) +{ + formatMetaClass(d, ac.get()); + return d; +} + +QDebug operator<<(QDebug d, const AbstractMetaClassPtr &ac) +{ + formatMetaClass(d, ac.get()); return d; } + +QDebug operator<<(QDebug d, const AbstractMetaClass *ac) +{ + formatMetaClass(d, ac); + return d; +} + #endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.h b/sources/shiboken6/ApiExtractor/abstractmetalang.h index 10543381a..3dc876690 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken6/ApiExtractor/abstractmetalang.h @@ -7,7 +7,6 @@ #include "abstractmetalang_enums.h" #include "abstractmetalang_typedefs.h" #include "enclosingclassmixin.h" -#include "typesystem_enums.h" #include "typesystem_typedefs.h" #include <QtCore/qobjectdefs.h> @@ -48,7 +47,8 @@ public: HasRejectedDefaultConstructor = 0x00000020, FinalCppClass = 0x00000100, - Deprecated = 0x00000200 + Deprecated = 0x00000200, + Struct = 0x00000400 }; Q_DECLARE_FLAGS(Attributes, Attribute) Q_FLAG(Attribute) @@ -66,11 +66,13 @@ public: ~AbstractMetaClass(); const AbstractMetaFunctionCList &functions() const; + const AbstractMetaFunctionCList &userAddedPythonOverrides() const; void setFunctions(const AbstractMetaFunctionCList &functions); - void addFunction(const AbstractMetaFunctionCPtr &function); + static void addFunction(const AbstractMetaClassPtr &klass, + const AbstractMetaFunctionCPtr &function); bool hasFunction(const QString &str) const; - AbstractMetaFunctionCPtr findFunction(QStringView functionName) const; - AbstractMetaFunctionCList findFunctions(QStringView functionName) const; + AbstractMetaFunctionCPtr findFunction(QAnyStringView functionName) const; + AbstractMetaFunctionCList findFunctions(QAnyStringView functionName) const; AbstractMetaFunctionCPtr findOperatorBool() const; // Find a Qt-style isNull() method suitable for nb_bool AbstractMetaFunctionCPtr findQtIsNullMethod() const; @@ -81,8 +83,8 @@ public: bool hasCopyConstructor() const; bool hasPrivateCopyConstructor() const; - void addDefaultConstructor(); - void addDefaultCopyConstructor(); + static void addDefaultConstructor(const AbstractMetaClassPtr &klass); + static void addDefaultCopyConstructor(const AbstractMetaClassPtr &klass); bool hasNonPrivateConstructor() const; void setHasNonPrivateConstructor(bool value); @@ -113,11 +115,7 @@ public: bool isImplicitlyCopyConstructible() const; bool canAddDefaultCopyConstructor() const; - /// Return type entry of the base class that declares the parent management - const TypeEntry *parentManagementEntry() const; - bool hasParentManagement() const { return parentManagementEntry() != nullptr; } - - void addSynthesizedComparisonOperators(); + static void addSynthesizedComparisonOperators(const AbstractMetaClassPtr &c); bool generateExceptionHandling() const; @@ -125,7 +123,7 @@ public: const UsingMembers &usingMembers() const; void addUsingMember(const UsingMember &um); - bool isUsingMember(const AbstractMetaClass *c, const QString &memberName, + bool isUsingMember(const AbstractMetaClassCPtr &c, const QString &memberName, Access minimumAccess) const; bool hasUsingMemberFor(const QString &memberName) const; @@ -190,42 +188,40 @@ public: QString baseClassName() const; - const AbstractMetaClass *defaultSuperclass() const; // Attribute "default-superclass" - void setDefaultSuperclass(AbstractMetaClass *s); + AbstractMetaClassCPtr defaultSuperclass() const; // Attribute "default-superclass" + void setDefaultSuperclass(const AbstractMetaClassPtr &s); - const AbstractMetaClass *baseClass() const; + AbstractMetaClassCPtr baseClass() const; const AbstractMetaClassCList &baseClasses() const; // base classes including defaultSuperclass AbstractMetaClassCList typeSystemBaseClasses() const; // Recursive list of all base classes including defaultSuperclass AbstractMetaClassCList allTypeSystemAncestors() const; - void addBaseClass(const AbstractMetaClass *base_class); - void setBaseClass(const AbstractMetaClass *base_class); + void addBaseClass(const AbstractMetaClassCPtr &base_class); + void setBaseClass(const AbstractMetaClassCPtr &base_class); /** * \return the namespace from another package which this namespace extends. */ - const AbstractMetaClass *extendedNamespace() const; - void setExtendedNamespace(const AbstractMetaClass *e); + AbstractMetaClassCPtr extendedNamespace() const; + void setExtendedNamespace(const AbstractMetaClassCPtr &e); const AbstractMetaClassCList &innerClasses() const; - void addInnerClass(AbstractMetaClass* cl); + void addInnerClass(const AbstractMetaClassPtr &cl); void setInnerClasses(const AbstractMetaClassCList &innerClasses); QString package() const; bool isNamespace() const; bool isInvisibleNamespace() const; + bool isInlineNamespace() const; - bool isQObject() const { return inheritsFrom(u"QObject"_qs); } bool isQtNamespace() const; QString qualifiedCppName() const; bool hasSignals() const; - bool inheritsFrom(const AbstractMetaClass *other) const; - bool inheritsFrom(const QString &name) const; /** * Says if the class that declares or inherits a virtual function. @@ -240,16 +236,16 @@ public: bool hasProtectedFields() const; - const TypeEntries &templateArguments() const; - void setTemplateArguments(const TypeEntries &); + const TypeEntryCList &templateArguments() const; + void setTemplateArguments(const TypeEntryCList &); // only valid during metabuilder's run const QStringList &baseClassNames() const; void setBaseClassNames(const QStringList &names); - const ComplexTypeEntry *typeEntry() const; - ComplexTypeEntry *typeEntry(); - void setTypeEntry(ComplexTypeEntry *type); + ComplexTypeEntryCPtr typeEntry() const; + ComplexTypeEntryPtr typeEntry(); + void setTypeEntry(const ComplexTypeEntryPtr &type); /// Returns the global hash function as found by the code parser QString hashFunction() const; @@ -261,17 +257,19 @@ public: const QList<QPropertySpec> &propertySpecs() const; void addPropertySpec(const QPropertySpec &spec); + void setPropertyDocumentation(const QString &name, const Documentation &doc); // Helpers to search whether a functions is a property setter/getter/reset enum class PropertyFunction { Read, Write, - Reset + Reset, + Notify }; struct PropertyFunctionSearchResult { - int index; + qsizetype index; PropertyFunction function; }; @@ -289,8 +287,8 @@ public: void sortFunctions(); - const AbstractMetaClass *templateBaseClass() const; - void setTemplateBaseClass(const AbstractMetaClass *cls); + AbstractMetaClassCPtr templateBaseClass() const; + void setTemplateBaseClass(const AbstractMetaClassCPtr &cls); bool hasTemplateBaseClassInstantiations() const; const AbstractMetaTypeList &templateBaseClassInstantiations() const; @@ -314,18 +312,18 @@ public: bool isCopyable() const; bool isValueTypeWithCopyConstructorOnly() const; void setValueTypeWithCopyConstructorOnly(bool v); - static bool determineValueTypeWithCopyConstructorOnly(const AbstractMetaClass *c, + static bool determineValueTypeWithCopyConstructorOnly(const AbstractMetaClassCPtr &c, bool avoidProtectedHack); - static AbstractMetaClass *findClass(const AbstractMetaClassList &classes, - QStringView name); - static const AbstractMetaClass *findClass(const AbstractMetaClassCList &classes, - QStringView name); - static AbstractMetaClass *findClass(const AbstractMetaClassList &classes, - const TypeEntry* typeEntry); - static const AbstractMetaClass *findClass(const AbstractMetaClassCList &classes, - const TypeEntry* typeEntry); - const AbstractMetaClass *findBaseClass(const QString &qualifiedName) const; + static AbstractMetaClassPtr findClass(const AbstractMetaClassList &classes, + QAnyStringView name); + static AbstractMetaClassCPtr findClass(const AbstractMetaClassCList &classes, + QAnyStringView name); + static AbstractMetaClassPtr findClass(const AbstractMetaClassList &classes, + const TypeEntryCPtr &typeEntry); + static AbstractMetaClassCPtr findClass(const AbstractMetaClassCList &classes, + const TypeEntryCPtr &typeEntry); + AbstractMetaClassCPtr findBaseClass(const QString &qualifiedName) const; static std::optional<AbstractMetaEnumValue> findEnumValue(const AbstractMetaClassList &classes, const QString &string); @@ -334,7 +332,7 @@ public: void setSourceLocation(const SourceLocation &sourceLocation); // For AbstractMetaBuilder - void fixFunctions(); + static void fixFunctions(const AbstractMetaClassPtr &klass); bool needsInheritanceSetup() const; void setInheritanceDone(bool b); bool inheritanceDone() const; @@ -346,17 +344,15 @@ private: #ifndef QT_NO_DEBUG_STREAM void format(QDebug &d) const; void formatMembers(QDebug &d) const; + friend QDebug operator<<(QDebug d, const AbstractMetaClassCPtr &ac); + friend QDebug operator<<(QDebug d, const AbstractMetaClassPtr &ac); friend QDebug operator<<(QDebug d, const AbstractMetaClass *ac); + friend void formatMetaClass(QDebug &, const AbstractMetaClass *); #endif QScopedPointer<AbstractMetaClassPrivate> d; }; -inline bool AbstractMetaClass::isFinalInTargetLang() const -{ - return attributes().testFlag(FinalInTargetLang); -} - inline bool AbstractMetaClass::isAbstract() const { return attributes().testFlag(Abstract); @@ -365,7 +361,7 @@ inline bool AbstractMetaClass::isAbstract() const template <class Function> void AbstractMetaClass::invisibleNamespaceRecursion(Function f) const { - for (auto ic : innerClasses()) { + for (const auto &ic : innerClasses()) { if (ic->isInvisibleNamespace()) { f(ic); ic->invisibleNamespaceRecursion(f); @@ -373,6 +369,23 @@ void AbstractMetaClass::invisibleNamespaceRecursion(Function f) const } } +bool inheritsFrom(const AbstractMetaClassCPtr &c, const AbstractMetaClassCPtr &other); +bool inheritsFrom(const AbstractMetaClassCPtr &c, QAnyStringView name); +inline bool isQObject(const AbstractMetaClassCPtr &c) +{ + return inheritsFrom(c, "QObject"); +} + +AbstractMetaClassCPtr findBaseClass(const AbstractMetaClassCPtr &c, + const QString &qualifiedName); + +/// Return type entry of the base class that declares the parent management +TypeEntryCPtr parentManagementEntry(const AbstractMetaClassCPtr &klass); +inline bool hasParentManagement(const AbstractMetaClassCPtr &c) +{ return bool(parentManagementEntry(c)); } + +AbstractMetaClassCList allBaseClasses(const AbstractMetaClassCPtr metaClass); + Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaClass::CppWrapper); Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaClass::Attributes); diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h b/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h index 2bdfdb54d..9047c6bcd 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h +++ b/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h @@ -11,18 +11,15 @@ enum class FunctionQueryOption { Constructors = 0x0000002, // Constructors except copy/move CopyConstructor = 0x0000004, // Only copy constructors //Destructors = 0x0000002, // Only destructors. Not included in class. - FinalInTargetLangFunctions = 0x0000008, // Only functions that are non-virtual in TargetLang ClassImplements = 0x0000020, // Only functions implemented by the current class StaticFunctions = 0x0000080, // Only static functions Signals = 0x0000100, // Only signals NormalFunctions = 0x0000200, // Only functions that aren't signals Visible = 0x0000400, // Only public and protected functions - WasPublic = 0x0001000, // Only functions that were originally public NonStaticFunctions = 0x0004000, // No static functions Empty = 0x0008000, // Empty overrides of abstract functions Invisible = 0x0010000, // Only private functions VirtualInCppFunctions = 0x0020000, // Only functions that are virtual in C++ - VirtualInTargetLangFunctions = 0x0080000, // Only functions which are virtual in TargetLang NotRemoved = 0x0400000, // Only functions that have not been removed OperatorOverloads = 0x2000000, // Only functions that are operator overloads GenerateExceptionHandling = 0x4000000, diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang_helpers.h b/sources/shiboken6/ApiExtractor/abstractmetalang_helpers.h index c1deea2c2..2a053ceaf 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang_helpers.h +++ b/sources/shiboken6/ApiExtractor/abstractmetalang_helpers.h @@ -4,21 +4,24 @@ #ifndef ABSTRACTMETALANG_HELPERS_H #define ABSTRACTMETALANG_HELPERS_H +#include "abstractmetalang_typedefs.h" + template <class MetaClass> -MetaClass *findByName(QList<MetaClass *> haystack, QStringView needle) +std::shared_ptr<MetaClass> findByName(const QList<std::shared_ptr<MetaClass> > &haystack, + QStringView needle) { - for (MetaClass *c : haystack) { + for (const auto &c : haystack) { if (c->name() == needle) return c; } - return nullptr; + return {}; } // Helper for recursing the base classes of an AbstractMetaClass. // Returns the class for which the predicate is true. template <class Predicate> -const AbstractMetaClass *recurseClassHierarchy(const AbstractMetaClass *klass, - Predicate pred) +AbstractMetaClassCPtr recurseClassHierarchy(const AbstractMetaClassCPtr &klass, + Predicate pred) { if (pred(klass)) return klass; @@ -26,7 +29,7 @@ const AbstractMetaClass *recurseClassHierarchy(const AbstractMetaClass *klass, if (auto r = recurseClassHierarchy(base, pred)) return r; } - return nullptr; + return {}; } #endif // ABSTRACTMETALANG_HELPERS_H diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang_typedefs.h b/sources/shiboken6/ApiExtractor/abstractmetalang_typedefs.h index 3b444197c..802f549cf 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang_typedefs.h +++ b/sources/shiboken6/ApiExtractor/abstractmetalang_typedefs.h @@ -4,9 +4,10 @@ #ifndef ABSTRACTMETALANG_TYPEDEFS_H #define ABSTRACTMETALANG_TYPEDEFS_H -#include <QtCore/QSharedPointer> #include <QtCore/QList> +#include <memory> + class AbstractMetaClass; class AbstractMetaField; class AbstractMetaArgument; @@ -16,12 +17,14 @@ class AbstractMetaFunction; class AbstractMetaType; struct UsingMember; -using AbstractMetaFunctionPtr = QSharedPointer<AbstractMetaFunction>; -using AbstractMetaFunctionCPtr = QSharedPointer<const AbstractMetaFunction>; +using AbstractMetaFunctionPtr = std::shared_ptr<AbstractMetaFunction>; +using AbstractMetaFunctionCPtr = std::shared_ptr<const AbstractMetaFunction>; +using AbstractMetaClassPtr = std::shared_ptr<AbstractMetaClass>; +using AbstractMetaClassCPtr = std::shared_ptr<const AbstractMetaClass>; using AbstractMetaArgumentList = QList<AbstractMetaArgument>; -using AbstractMetaClassList = QList<AbstractMetaClass *>; -using AbstractMetaClassCList = QList<const AbstractMetaClass *>; +using AbstractMetaClassList = QList<AbstractMetaClassPtr>; +using AbstractMetaClassCList = QList<AbstractMetaClassCPtr>; using AbstractMetaEnumList = QList<AbstractMetaEnum>; using AbstractMetaEnumValueList = QList<AbstractMetaEnumValue>; using AbstractMetaFieldList = QList<AbstractMetaField>; diff --git a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp index a56557e76..3ec07509d 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp @@ -9,9 +9,9 @@ #include "containertypeentry.h" #include "enumtypeentry.h" #include "flagstypeentry.h" -#include "parser/codemodel.h" #include "qtcompat.h" +#include "typeinfo.h" #ifndef QT_NO_DEBUG_STREAM # include <QtCore/QDebug> @@ -19,12 +19,13 @@ #include <QtCore/QHash> #include <QtCore/QSharedData> -#include <QtCore/QSharedPointer> #include <QtCore/QStack> +#include <memory> + using namespace Qt::StringLiterals; -using AbstractMetaTypeCPtr = QSharedPointer<const AbstractMetaType>; +using AbstractMetaTypeCPtr = std::shared_ptr<const AbstractMetaType>; const QSet<QString> &AbstractMetaType::cppFloatTypes() { @@ -107,7 +108,7 @@ const QSet<QString> &AbstractMetaType::cppPrimitiveTypes() class AbstractMetaTypeData : public QSharedData { public: - AbstractMetaTypeData(const TypeEntry *t); + AbstractMetaTypeData(const TypeEntryCPtr &t); int actualIndirections() const; bool passByConstRef() const; @@ -118,11 +119,12 @@ public: QString formatPythonSignature() const; bool isEquivalent(const AbstractMetaTypeData &rhs) const; bool equals(const AbstractMetaTypeData &rhs) const; + QStringList instantiationCppSignatures() const; template <class Predicate> bool generateOpaqueContainer(Predicate p) const; - const TypeEntry *m_typeEntry; + TypeEntryCPtr m_typeEntry; AbstractMetaTypeList m_instantiations; mutable QString m_cachedCppSignature; mutable QString m_cachedPythonSignature; @@ -144,7 +146,7 @@ public: AbstractMetaTypeList m_children; }; -AbstractMetaTypeData::AbstractMetaTypeData(const TypeEntry *t) : +AbstractMetaTypeData::AbstractMetaTypeData(const TypeEntryCPtr &t) : m_typeEntry(t), m_constant(false), m_volatile(false), @@ -153,7 +155,16 @@ AbstractMetaTypeData::AbstractMetaTypeData(const TypeEntry *t) : { } -AbstractMetaType::AbstractMetaType(const TypeEntry *t) : d(new AbstractMetaTypeData(t)) +QStringList AbstractMetaTypeData::instantiationCppSignatures() const +{ + QStringList result; + for (const auto &i : m_instantiations) + result.append(i.cppSignature()); + return result; +} + +AbstractMetaType::AbstractMetaType(const TypeEntryCPtr &t) : + d(new AbstractMetaTypeData(t)) { Q_ASSERT(t); } @@ -167,9 +178,9 @@ AbstractMetaType &AbstractMetaType::operator=(const AbstractMetaType &) = defaul AbstractMetaType::AbstractMetaType(const AbstractMetaType &rhs) = default; -AbstractMetaType::AbstractMetaType(AbstractMetaType &&) = default; +AbstractMetaType::AbstractMetaType(AbstractMetaType &&) noexcept = default; -AbstractMetaType &AbstractMetaType::operator=(AbstractMetaType &&) = default; +AbstractMetaType &AbstractMetaType::operator=(AbstractMetaType &&) noexcept = default; AbstractMetaType::~AbstractMetaType() = default; @@ -220,6 +231,11 @@ const AbstractMetaTypeList &AbstractMetaType::instantiations() const return d->m_instantiations; } +QStringList AbstractMetaType::instantiationCppSignatures() const +{ + return d->instantiationCppSignatures(); +} + // For applying the <array> function argument modification: change into a type // where "int *" becomes "int[]". bool AbstractMetaType::applyArrayModification(QString *errorMessage) @@ -229,7 +245,7 @@ bool AbstractMetaType::applyArrayModification(QString *errorMessage) *errorMessage = u"<array> modification already applied."_s; return false; } - if (!d->m_arrayElementType.isNull()) { + if (d->m_arrayElementType) { QTextStream(errorMessage) << "The type \"" << cppSignature() << "\" is an array of " << d->m_arrayElementType->name() << '.'; return false; @@ -253,12 +269,12 @@ bool AbstractMetaType::applyArrayModification(QString *errorMessage) return true; } -const TypeEntry *AbstractMetaType::typeEntry() const +TypeEntryCPtr AbstractMetaType::typeEntry() const { return d->m_typeEntry; } -void AbstractMetaType::setTypeEntry(const TypeEntry *type) +void AbstractMetaType::setTypeEntry(const TypeEntryCPtr &type) { if (d->m_typeEntry != type) d->m_typeEntry = type; @@ -277,13 +293,13 @@ QString AbstractMetaType::originalTypeDescription() const void AbstractMetaType::setOriginalTemplateType(const AbstractMetaType &type) { - if (d->m_originalTemplateType.isNull() || *d->m_originalTemplateType != type) + if (!d->m_originalTemplateType || *d->m_originalTemplateType != type) d->m_originalTemplateType.reset(new AbstractMetaType(type)); } const AbstractMetaType *AbstractMetaType::originalTemplateType() const { - return d->m_originalTemplateType.data(); + return d->m_originalTemplateType.get(); } AbstractMetaType AbstractMetaType::getSmartPointerInnerType() const @@ -312,7 +328,7 @@ AbstractMetaTypeList AbstractMetaType::nestedArrayTypes() const } break; case NativePointerAsArrayPattern: - result.append(*d->m_arrayElementType.data()); + result.append(*d->m_arrayElementType.get()); break; default: break; @@ -340,6 +356,12 @@ bool AbstractMetaType::passByValue() const return d->passByValue(); } +bool AbstractMetaType::useStdMove() const +{ + return (isUniquePointer() && d->passByValue()) + || d->m_referenceType == RValueReference; +} + ReferenceType AbstractMetaType::referenceType() const { return d->m_referenceType; @@ -418,17 +440,28 @@ int AbstractMetaType::arrayElementCount() const const AbstractMetaType *AbstractMetaType::arrayElementType() const { - return d->m_arrayElementType.data(); + return d->m_arrayElementType.get(); } void AbstractMetaType::setArrayElementType(const AbstractMetaType &t) { - if (d->m_arrayElementType.isNull() || *d->m_arrayElementType != t) { + if (!d->m_arrayElementType || *d->m_arrayElementType != t) { d->m_arrayElementType.reset(new AbstractMetaType(t)); d->m_signaturesDirty = true; } } +AbstractMetaType AbstractMetaType::plainType() const +{ + AbstractMetaType result = *this; + result.clearIndirections(); + result.setReferenceType(NoReference); + result.setConstant(false); + result.setVolatile(false); + result.decideUsagePattern(); + return result; +} + QString AbstractMetaType::cppSignature() const { const AbstractMetaTypeData *cd = d.constData(); @@ -510,6 +543,7 @@ void AbstractMetaType::decideUsagePattern() pattern = ObjectPattern; } setTypeUsagePattern(pattern); + Q_ASSERT(pattern != ContainerPattern || !d->m_instantiations.isEmpty()); } bool AbstractMetaTypeData::hasTemplateChildren() const @@ -543,6 +577,29 @@ static inline QString formatArraySize(int e) return result; } +// Return the number of template parameters; remove the default +// non template type parameter of std::span from the signature. +static qsizetype stripDefaultTemplateArgs(const TypeEntryCPtr &te, + const AbstractMetaTypeList &instantiations) +{ + static const char16_t dynamicExtent64[] = u"18446744073709551615"; // size_t(-1) + static const char16_t dynamicExtent32[] = u"4294967295"; + + qsizetype result = instantiations.size(); + if (result == 0 || !te->isContainer()) + return result; + auto cte = std::static_pointer_cast<const ContainerTypeEntry>(te); + if (cte->containerKind() != ContainerTypeEntry::SpanContainer) + return result; + const auto lastTe = instantiations.constLast().typeEntry(); + if (lastTe->type() == TypeEntry::ConstantValueType) { + const QString &name = lastTe->name(); + if (name == dynamicExtent64 || name == dynamicExtent32) + --result; + } + return result; +} + QString AbstractMetaTypeData::formatSignature(bool minimal) const { QString result; @@ -565,12 +622,13 @@ QString AbstractMetaTypeData::formatSignature(bool minimal) const result += u'<'; if (minimal) result += u' '; - for (int i = 0, size = m_instantiations.size(); i < size; ++i) { + const auto size = stripDefaultTemplateArgs(m_typeEntry, m_instantiations); + for (qsizetype i = 0; i < size; ++i) { if (i > 0) result += u','; result += m_instantiations.at(i).minimalSignature(); } - result += u" >"_s; + result += u'>'; } if (!minimal && (!m_indirections.isEmpty() || m_referenceType != NoReference)) @@ -633,7 +691,7 @@ QString AbstractMetaTypeData::formatPythonSignature() const } if (!m_instantiations.isEmpty()) { result += u'['; - for (int i = 0, size = m_instantiations.size(); i < size; ++i) { + for (qsizetype i = 0, size = m_instantiations.size(); i < size; ++i) { if (i > 0) result += u", "_s; result += m_instantiations.at(i).formatPythonSignature(); @@ -643,18 +701,12 @@ QString AbstractMetaTypeData::formatPythonSignature() const if (m_typeEntry->isPrimitive()) for (Indirection i : m_indirections) result += TypeInfo::indirectionKeyword(i); - // If it is a flags type, we replace it with the full name: - // "PySide6.QtCore.Qt.ItemFlags" instead of "PySide6.QtCore.QFlags<Qt.ItemFlag>" + // If it is a flags type, we replace it with the full name of the enum: + // "PySide6.QtCore.Qt.ItemFlag" instead of "PySide6.QtCore.QFlags<Qt.ItemFlag>" if (m_typeEntry->isFlags()) { - // PYSIDE-1735: We need to provide both the flags type and the original enum type - // as a choice at runtime. - auto flagsTypeEntry = static_cast<const FlagsTypeEntry *>(m_typeEntry); - auto enumTypeEntry = flagsTypeEntry->originator(); - result = m_typeEntry->targetLangPackage() + u".^^"_s - + flagsTypeEntry->targetLangName() + u"^^"_s - + enumTypeEntry->targetLangName() + u"^^"_s; + const auto fte = std::static_pointer_cast<const FlagsTypeEntry>(m_typeEntry); + result = fte->originator()->qualifiedTargetLangName(); } - result.replace(u"::"_s, u"."_s); return result; } @@ -666,7 +718,7 @@ QString AbstractMetaType::formatPythonSignature() const bool AbstractMetaType::isCppPrimitive() const { - return d->m_pattern == PrimitivePattern && d->m_typeEntry->isCppPrimitive(); + return d->m_pattern == PrimitivePattern && ::isCppPrimitive(d->m_typeEntry); } bool AbstractMetaType::isConstant() const @@ -697,9 +749,9 @@ void AbstractMetaType::setVolatile(bool v) static bool equalsCPtr(const AbstractMetaTypeCPtr &t1, const AbstractMetaTypeCPtr &t2) { - if (t1.isNull() != t2.isNull()) + if (bool(t1) != bool(t2)) return false; - return t1.isNull() || *t1 == *t2; + return !t1 || *t1 == *t2; } bool AbstractMetaTypeData::isEquivalent(const AbstractMetaTypeData &rhs) const @@ -727,9 +779,9 @@ bool AbstractMetaTypeData::equals(const AbstractMetaTypeData &rhs) const && m_referenceType == rhs.m_referenceType && isEquivalent(rhs); } -bool AbstractMetaType::equals(const AbstractMetaType &rhs) const +bool comparesEqual(const AbstractMetaType &lhs, const AbstractMetaType &rhs) noexcept { - return d->equals(*rhs.d); + return lhs.d->equals(*rhs.d); } bool AbstractMetaType::isEquivalent(const AbstractMetaType &rhs) const @@ -739,12 +791,12 @@ bool AbstractMetaType::isEquivalent(const AbstractMetaType &rhs) const const AbstractMetaType *AbstractMetaType::viewOn() const { - return d->m_viewOn.data(); + return d->m_viewOn.get(); } void AbstractMetaType::setViewOn(const AbstractMetaType &v) { - if (d->m_viewOn.isNull() || *d->m_viewOn != v) + if (!d->m_viewOn || *d->m_viewOn != v) d->m_viewOn.reset(new AbstractMetaType(v)); } @@ -752,7 +804,7 @@ AbstractMetaType AbstractMetaType::createVoid() { static QScopedPointer<AbstractMetaType> metaType; if (metaType.isNull()) { - static const TypeEntry *voidTypeEntry = TypeDatabase::instance()->findType(u"void"_s); + static TypeEntryCPtr voidTypeEntry = TypeDatabase::instance()->findType(u"void"_s); Q_ASSERT(voidTypeEntry); metaType.reset(new AbstractMetaType(voidTypeEntry)); metaType->decideUsagePattern(); @@ -766,13 +818,18 @@ void AbstractMetaType::dereference(QString *type) type->append(u')'); } +QString AbstractMetaType::dereferencePrefix(qsizetype n) +{ + const QChar c = n > 0 ? u'*' : u'&'; + return QString(qAbs(n), c); +} + void AbstractMetaType::applyDereference(QString *type, qsizetype n) { if (n == 0) return; - const char c = n > 0 ? '*' : '&'; - type->prepend(QString(qAbs(n), QLatin1Char(c))); + type->prepend(dereferencePrefix(n)); type->prepend(u'('); type->append(u')'); } @@ -832,7 +889,7 @@ bool AbstractMetaType::isVoidPointer() const bool AbstractMetaType::isUserPrimitive() const { - return d->m_indirections.isEmpty() && d->m_typeEntry->isUserPrimitive(); + return d->m_indirections.isEmpty() && ::isUserPrimitive(d->m_typeEntry); } bool AbstractMetaType::isObjectTypeUsedAsValueType() const @@ -857,28 +914,9 @@ bool AbstractMetaType::isWrapperPassedByReference() const && !isPointer(); } -qsizetype AbstractMetaType::shouldDereferenceArgument() const -{ - if (isWrapperPassedByReference() || valueTypeWithCopyConstructorOnlyPassed() - || isObjectTypeUsedAsValueType()) { - return 1; - } - - if (!d->m_typeEntry->isContainer()) - return 0; - - qsizetype result = -d->m_indirections.size(); - - // For opaque containers, the cppArg in the generated code is a pointer - if (generateOpaqueContainer()) - ++result; - - return result; -} - bool AbstractMetaType::isCppIntegralPrimitive() const { - return d->m_typeEntry->isCppIntegralPrimitive(); + return ::isCppIntegralPrimitive(d->m_typeEntry); } bool AbstractMetaType::isExtendedCppPrimitive() const @@ -887,14 +925,14 @@ bool AbstractMetaType::isExtendedCppPrimitive() const return true; if (!d->m_indirections.isEmpty()) return false; - return d->m_typeEntry->isExtendedCppPrimitive(); + return ::isExtendedCppPrimitive(d->m_typeEntry); } bool AbstractMetaType::isValueTypeWithCopyConstructorOnly() const { bool result = false; if (d->m_typeEntry->isComplex()) { - const auto *cte = static_cast<const ComplexTypeEntry *>(d->m_typeEntry); + const auto cte = std::static_pointer_cast<const ComplexTypeEntry>(d->m_typeEntry); result = cte->isValueTypeWithCopyConstructorOnly(); } return result; @@ -911,14 +949,18 @@ using AbstractMetaTypeCache = QHash<QString, AbstractMetaType>; Q_GLOBAL_STATIC(AbstractMetaTypeCache, metaTypeFromStringCache) std::optional<AbstractMetaType> -AbstractMetaType::fromString(QString typeSignature, QString *errorMessage) +AbstractMetaType::fromString(const QString &typeSignatureIn, QString *errorMessage) { - typeSignature = typeSignature.trimmed(); + auto &cache = *metaTypeFromStringCache(); + auto it = cache.find(typeSignatureIn); + if (it != cache.end()) + return it.value(); + + QString typeSignature = typeSignatureIn.trimmed(); if (typeSignature.startsWith(u"::")) typeSignature.remove(0, 2); - auto &cache = *metaTypeFromStringCache(); - auto it = cache.find(typeSignature); + it = cache.find(typeSignature); if (it == cache.end()) { auto metaType = AbstractMetaBuilder::translateType(typeSignature, nullptr, {}, errorMessage); @@ -927,12 +969,14 @@ AbstractMetaType::fromString(QString typeSignature, QString *errorMessage) errorMessage->prepend(msgCannotBuildMetaType(typeSignature)); return {}; } + if (typeSignature != typeSignatureIn) + cache.insert(typeSignatureIn, metaType.value()); it = cache.insert(typeSignature, metaType.value()); } return it.value(); } -AbstractMetaType AbstractMetaType::fromTypeEntry(const TypeEntry *typeEntry) +AbstractMetaType AbstractMetaType::fromTypeEntry(const TypeEntryCPtr &typeEntry) { QString typeName = typeEntry->qualifiedCppName(); if (typeName.startsWith(u"::")) @@ -941,16 +985,12 @@ AbstractMetaType AbstractMetaType::fromTypeEntry(const TypeEntry *typeEntry) auto it = cache.find(typeName); if (it != cache.end()) return it.value(); - AbstractMetaType metaType(typeEntry); - metaType.clearIndirections(); - metaType.setReferenceType(NoReference); - metaType.setConstant(false); - metaType.decideUsagePattern(); + AbstractMetaType metaType = AbstractMetaType(typeEntry).plainType(); cache.insert(typeName, metaType); return metaType; } -AbstractMetaType AbstractMetaType::fromAbstractMetaClass(const AbstractMetaClass *metaClass) +AbstractMetaType AbstractMetaType::fromAbstractMetaClass(const AbstractMetaClassCPtr &metaClass) { return fromTypeEntry(metaClass->typeEntry()); } @@ -963,37 +1003,34 @@ bool AbstractMetaTypeData::generateOpaqueContainer(Predicate pred) const return false; if (m_indirections.size() > 1) return false; - auto *containerTypeEntry = static_cast<const ContainerTypeEntry *>(m_typeEntry); + auto containerTypeEntry = std::static_pointer_cast<const ContainerTypeEntry>(m_typeEntry); auto kind = containerTypeEntry->containerKind(); - if (kind != ContainerTypeEntry::ListContainer) - return false; - const auto &instantation = m_instantiations.constFirst(); - if (instantation.referenceType() != NoReference) + if (kind != ContainerTypeEntry::ListContainer && kind != ContainerTypeEntry::SpanContainer) return false; - const QString signature = instantation.cppSignature(); - bool result = false; - auto *instTypEntry = instantation.typeEntry(); - switch (instTypEntry->type()) { + const auto &firstInstantiation = m_instantiations.constFirst(); + if (firstInstantiation.referenceType() != NoReference) + return false; + switch (firstInstantiation.typeEntry()->type()) { case TypeEntry::PrimitiveType: case TypeEntry::FlagsType: case TypeEntry::EnumType: case TypeEntry::BasicValueType: case TypeEntry::ObjectType: case TypeEntry::CustomType: - result = pred(containerTypeEntry, signature); break; default: - break; + return false; } - return result; + + return pred(containerTypeEntry, instantiationCppSignatures()); } // Simple predicate for checking whether an opaque container should be generated -static bool opaqueContainerPredicate(const ContainerTypeEntry *t, - const QString &signature) +static bool opaqueContainerPredicate(const ContainerTypeEntryCPtr &t, + const QStringList &instantiations) { - return t->generateOpaqueContainer(signature); + return t->generateOpaqueContainer(instantiations); } bool AbstractMetaType::generateOpaqueContainer() const @@ -1006,8 +1043,9 @@ bool AbstractMetaType::generateOpaqueContainer() const // (cf AbstractMetaFunction::generateOpaqueContainerReturn()) bool AbstractMetaType::generateOpaqueContainerForGetter(const QString &modifiedType) const { - auto predicate = [&modifiedType](const ContainerTypeEntry *t, const QString &signature) { - return t->opaqueContainerName(signature) == modifiedType; + auto predicate = [&modifiedType](const ContainerTypeEntryCPtr &t, + const QStringList &instantiations) { + return t->opaqueContainerName(instantiations) == modifiedType; }; return d->generateOpaqueContainer(predicate); } @@ -1031,7 +1069,7 @@ void AbstractMetaType::formatDebug(QDebug &debug) const for (auto i : indirections) debug << ' ' << TypeInfo::indirectionKeyword(i); } - if (referenceType()) + if (referenceType() != NoReference) debug << ", reftype=" << referenceType(); if (isConstant()) debug << ", [const]"; @@ -1042,9 +1080,9 @@ void AbstractMetaType::formatDebug(QDebug &debug) const << "\", arrayElementCount=" << arrayElementCount(); } const auto &instantiations = this->instantiations(); - if (const int instantiationsSize = instantiations.size()) { + if (const auto instantiationsSize = instantiations.size()) { debug << ", instantiations[" << instantiationsSize << "]=<"; - for (int i = 0; i < instantiationsSize; ++i) { + for (qsizetype i = 0; i < instantiationsSize; ++i) { if (i) debug << ", "; instantiations.at(i).formatDebug(debug); diff --git a/sources/shiboken6/ApiExtractor/abstractmetatype.h b/sources/shiboken6/ApiExtractor/abstractmetatype.h index 561cac317..8a1ecdf20 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetatype.h +++ b/sources/shiboken6/ApiExtractor/abstractmetatype.h @@ -7,8 +7,11 @@ #include "abstractmetalang_enums.h" #include "abstractmetalang_typedefs.h" #include "parser/codemodel_enums.h" +#include "typedatabase_typedefs.h" +#include <QtCore/QtCompare> #include <QtCore/qobjectdefs.h> +#include <QtCore/QHashFunctions> #include <QtCore/QSharedDataPointer> #include <QtCore/QList> #include <QtCore/QSet> @@ -46,11 +49,11 @@ public: Q_ENUM(TypeUsagePattern) AbstractMetaType(); - explicit AbstractMetaType(const TypeEntry *t); + explicit AbstractMetaType(const TypeEntryCPtr &t); AbstractMetaType(const AbstractMetaType &); AbstractMetaType &operator=(const AbstractMetaType &); - AbstractMetaType(AbstractMetaType &&); - AbstractMetaType &operator=(AbstractMetaType &&); + AbstractMetaType(AbstractMetaType &&) noexcept; + AbstractMetaType &operator=(AbstractMetaType &&) noexcept; ~AbstractMetaType(); QString package() const; @@ -66,6 +69,7 @@ public: const AbstractMetaTypeList &instantiations() const; void addInstantiation(const AbstractMetaType &inst); void setInstantiations(const AbstractMetaTypeList &insts); + QStringList instantiationCppSignatures() const; QString minimalSignature() const { return formatSignature(true); } @@ -117,6 +121,7 @@ public: bool passByConstRef() const; bool passByValue() const; + bool useStdMove() const; ReferenceType referenceType() const; void setReferenceType(ReferenceType ref); @@ -140,14 +145,17 @@ public: AbstractMetaTypeList nestedArrayTypes() const; + /// Strip const/indirections/reference from the type + AbstractMetaType plainType() const; + QString cppSignature() const; QString pythonSignature() const; bool applyArrayModification(QString *errorMessage); - const TypeEntry *typeEntry() const; - void setTypeEntry(const TypeEntry *type); + TypeEntryCPtr typeEntry() const; + void setTypeEntry(const TypeEntryCPtr &type); void setOriginalTypeDescription(const QString &otd); QString originalTypeDescription() const; @@ -164,7 +172,6 @@ public: bool hasTemplateChildren() const; - bool equals(const AbstractMetaType &rhs) const; /// Is equivalent from the POV of argument passing (differ by const ref) bool isEquivalent(const AbstractMetaType &rhs) const; @@ -181,14 +188,15 @@ public: /// \param typeSignature The string describing the type to be built. /// \return A new AbstractMetaType object or nullopt in case of failure. static std::optional<AbstractMetaType> - fromString(QString typeSignature, QString *errorMessage = nullptr); + fromString(const QString &typeSignatureIn, QString *errorMessage = nullptr); /// Creates an AbstractMetaType object from a TypeEntry. - static AbstractMetaType fromTypeEntry(const TypeEntry *typeEntry); + static AbstractMetaType fromTypeEntry(const TypeEntryCPtr &typeEntry); /// Creates an AbstractMetaType object from an AbstractMetaClass. - static AbstractMetaType fromAbstractMetaClass(const AbstractMetaClass *metaClass); + static AbstractMetaType fromAbstractMetaClass(const AbstractMetaClassCPtr &metaClass); static void dereference(QString *type); // "foo" -> "(*foo)" /// Apply the result of shouldDereferenceArgument() + static QString dereferencePrefix(qsizetype n); // Return the prefix **/& as as required static void applyDereference(QString *type, qsizetype n); static bool stripDereference(QString *type); // "(*foo)" -> "foo" @@ -214,10 +222,6 @@ public: bool isPointerToWrapperType() const; /// Wrapper type passed by reference bool isWrapperPassedByReference() const; - /// Checks if the meta type of an argument should be dereferenced by the Python - /// method wrapper passing it to C++. - /// \return positive numbers for dereferencing, negative for referencing - qsizetype shouldDereferenceArgument() const; /// Returns true if the type is a C++ integral primitive, /// i.e. bool, char, int, long, and their unsigned counterparts. bool isCppIntegralPrimitive() const; @@ -250,6 +254,12 @@ public: #endif private: + friend size_t qHash(const AbstractMetaType &t, size_t seed = 0) noexcept + { return qHash(t.typeEntry().get(), seed); } + friend bool comparesEqual(const AbstractMetaType &lhs, + const AbstractMetaType &rhs) noexcept; + Q_DECLARE_EQUALITY_COMPARABLE(AbstractMetaType) + friend class AbstractMetaTypeData; QSharedDataPointer<AbstractMetaTypeData> d; @@ -258,14 +268,6 @@ private: QString formatPythonSignature() const; }; -inline bool operator==(const AbstractMetaType &t1, const AbstractMetaType &t2) -{ return t1.equals(t2); } -inline bool operator!=(const AbstractMetaType &t1, const AbstractMetaType &t2) -{ return !t1.equals(t2); } - -inline size_t qHash(const AbstractMetaType &t, size_t seed) -{ return qHash(t.typeEntry(), seed); } - #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const AbstractMetaType &at); QDebug operator<<(QDebug d, const AbstractMetaType *at); diff --git a/sources/shiboken6/ApiExtractor/addedfunction.cpp b/sources/shiboken6/ApiExtractor/addedfunction.cpp new file mode 100644 index 000000000..9d95b734c --- /dev/null +++ b/sources/shiboken6/ApiExtractor/addedfunction.cpp @@ -0,0 +1,216 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "addedfunction.h" +#include "addedfunction_p.h" +#include "typeparser.h" + +#include <QtCore/QDebug> + +using namespace Qt::StringLiterals; + +constexpr auto callOperator = "operator()"_L1; + +// Helpers to split a parameter list of <add-function>, <declare-function> +// (@ denoting names), like +// "void foo(QList<X,Y> &@list@ = QList<X,Y>{1,2}, int @b@=5, ...)" +namespace AddedFunctionParser { + +QDebug operator<<(QDebug d, const Argument &a) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "Argument(type=\"" << a.type << '"'; + if (!a.name.isEmpty()) + d << ", name=\"" << a.name << '"'; + if (!a.defaultValue.isEmpty()) + d << ", defaultValue=\"" << a.defaultValue << '"'; + d << ')'; + return d; +} + +// Helper for finding the end of a function parameter, observing +// nested template parameters or lists. +static qsizetype parameterTokenEnd(qsizetype startPos, QStringView paramString) +{ + const auto end = paramString.size(); + int nestingLevel = 0; + for (qsizetype p = startPos; p < end; ++p) { + switch (paramString.at(p).toLatin1()) { + case ',': + if (nestingLevel == 0) + return p; + break; + case '<': // templates + case '{': // initializer lists of default values + case '(': // initialization, function pointers + case '[': // array dimensions + ++nestingLevel; + break; + case '>': + case '}': + case ')': + case ']': + --nestingLevel; + break; + } + } + return end; +} + +// Split a function parameter list into string tokens containing one +// parameters (including default value, etc). +static QList<QStringView> splitParameterTokens(QStringView paramString) +{ + QList<QStringView> result; + qsizetype startPos = 0; + for ( ; startPos < paramString.size(); ) { + const auto end = parameterTokenEnd(startPos, paramString); + result.append(paramString.mid(startPos, end - startPos).trimmed()); + startPos = end + 1; + } + return result; +} + +// Split a function parameter list +Arguments splitParameters(QStringView paramString, QString *errorMessage) +{ + Arguments result; + const QList<QStringView> tokens = splitParameterTokens(paramString); + + for (const auto &t : tokens) { + Argument argument; + // Check defaultValue, "int @b@=5" + const auto equalPos = t.lastIndexOf(u'='); + if (equalPos != -1) { + const int defaultValuePos = equalPos + 1; + argument.defaultValue = + t.mid(defaultValuePos, t.size() - defaultValuePos).trimmed().toString(); + } + QString typeString = (equalPos != -1 ? t.left(equalPos) : t).trimmed().toString(); + // Check @name@ + const auto atPos = typeString.indexOf(u'@'); + if (atPos != -1) { + const int namePos = atPos + 1; + const int nameEndPos = typeString.indexOf(u'@', namePos); + if (nameEndPos == -1) { + if (errorMessage != nullptr) { + *errorMessage = u"Mismatched @ in \""_s + + paramString.toString() + u'"'; + } + return {}; + } + argument.name = typeString.mid(namePos, nameEndPos - namePos).trimmed(); + typeString.remove(atPos, nameEndPos - atPos + 1); + } + argument.type = typeString.trimmed(); + result.append(argument); + } + + return result; +} + +} // namespace AddedFunctionParser + +AddedFunction::AddedFunction(const QString &name, const QList<Argument> &arguments, + const TypeInfo &returnType) : + m_name(name), + m_arguments(arguments), + m_returnType(returnType) +{ +} + +AddedFunction::AddedFunctionPtr + AddedFunction::createAddedFunction(const QString &signatureIn, const QString &returnTypeIn, + QString *errorMessage) + +{ + errorMessage->clear(); + + QList<Argument> arguments; + const TypeInfo returnType = returnTypeIn.isEmpty() + ? TypeInfo::voidType() + : TypeParser::parse(returnTypeIn, errorMessage); + if (!errorMessage->isEmpty()) + return {}; + + QStringView signature = QStringView{signatureIn}.trimmed(); + + // Skip past "operator()(...)" + const auto parenSearchStartPos = signature.startsWith(callOperator) + ? callOperator.size() : 0; + const auto openParenPos = signature.indexOf(u'(', parenSearchStartPos); + if (openParenPos < 0) { + return AddedFunctionPtr(new AddedFunction(signature.toString(), + arguments, returnType)); + } + + const QString name = signature.left(openParenPos).trimmed().toString(); + const auto closingParenPos = signature.lastIndexOf(u')'); + if (closingParenPos < 0) { + *errorMessage = u"Missing closing parenthesis"_s; + return {}; + } + + // Check for "foo() const" + bool isConst = false; + const auto signatureLength = signature.length(); + const auto qualifierLength = signatureLength - closingParenPos - 1; + if (qualifierLength >= 5 + && signature.right(qualifierLength).contains(u"const")) { + isConst = true; + } + + const auto paramString = signature.mid(openParenPos + 1, closingParenPos - openParenPos - 1); + const auto params = AddedFunctionParser::splitParameters(paramString, errorMessage); + if (params.isEmpty() && !errorMessage->isEmpty()) + return {}; + for (const auto &p : params) { + TypeInfo type = p.type == u"..." + ? TypeInfo::varArgsType() : TypeParser::parse(p.type, errorMessage); + if (!errorMessage->isEmpty()) { + errorMessage->prepend(u"Unable to parse added function "_s + signatureIn + + u": "_s); + return {}; + } + arguments.append({type, p.name, p.defaultValue}); + } + + auto result = std::make_shared<AddedFunction>(name, arguments, returnType); + result->setConstant(isConst); + return result; +} + +QDebug operator<<(QDebug d, const AddedFunction::Argument &a) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "Argument("; + d << a.typeInfo; + if (!a.name.isEmpty()) + d << ' ' << a.name; + if (!a.defaultValue.isEmpty()) + d << " = " << a.defaultValue; + d << ')'; + return d; +} + +QDebug operator<<(QDebug d, const AddedFunction &af) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "AddedFunction("; + if (af.access() == AddedFunction::Protected) + d << "protected"; + if (af.isStatic()) + d << " static"; + d << af.returnType() << ' ' << af.name() << '(' << af.arguments() << ')'; + if (af.isConstant()) + d << " const"; + if (af.isDeclaration()) + d << " [declaration]"; + return d; +} diff --git a/sources/shiboken6/ApiExtractor/addedfunction.h b/sources/shiboken6/ApiExtractor/addedfunction.h new file mode 100644 index 000000000..b8d189b7a --- /dev/null +++ b/sources/shiboken6/ApiExtractor/addedfunction.h @@ -0,0 +1,113 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef ADDEDFUNCTION_H +#define ADDEDFUNCTION_H + +#include "modifications.h" +#include "parser/typeinfo.h" + +#include <QtCore/QList> +#include <QtCore/QString> + +#include <memory> + +QT_FORWARD_DECLARE_CLASS(QDebug) + +/// \internal +/// Struct used to store information about functions added by the typesystem. +/// This info will be used later to create a fake AbstractMetaFunction which +/// will be inserted into the right AbstractMetaClass. +struct AddedFunction +{ + using AddedFunctionPtr = std::shared_ptr<AddedFunction>; + + /// Function access types. + enum Access { + Protected = 0x1, + Public = 0x2 + }; + + struct Argument + { + TypeInfo typeInfo; + QString name; + QString defaultValue; + }; + + /// Creates a new AddedFunction with a signature and a return type. + explicit AddedFunction(const QString &name, const QList<Argument> &arguments, + const TypeInfo &returnType); + + static AddedFunctionPtr createAddedFunction(const QString &signatureIn, + const QString &returnTypeIn, + QString *errorMessage); + + AddedFunction() = default; + + /// Returns the function name. + QString name() const { return m_name; } + + /// Set the function access type. + void setAccess(Access access) { m_access = access; } + + /// Returns the function access type. + Access access() const { return m_access; } + + /// Returns the function return type. + const TypeInfo &returnType() const { return m_returnType; } + + /// Returns a list of argument type infos. + const QList<Argument> &arguments() const { return m_arguments; } + + /// Returns true if this is a constant method. + bool isConstant() const { return m_isConst; } + void setConstant(bool c) { m_isConst = c; }; + + /// Set this method static. + void setStatic(bool value) { m_isStatic = value; } + + /// Set this method as a classmethod. + void setClassMethod(bool value) { m_isClassMethod = value; } + + /// Returns true if this is a static method. + bool isStatic() const { return m_isStatic; } + + /// Returns true if this is a class method. + bool isClassMethod() const { return m_isClassMethod; } + + bool isDeclaration() const { return m_isDeclaration; } // <declare-function> + void setDeclaration(bool value) { m_isDeclaration = value; } + + bool isPythonOverride() const { return m_isPythonOverride; } + void setPythonOverride(bool o) { m_isPythonOverride = o; } + + const FunctionModificationList &modifications() const { return m_modifications; } + FunctionModificationList &modifications() { return m_modifications; } + + const DocModificationList &docModifications() const { return m_docModifications; } + DocModificationList &docModifications() { return m_docModifications; } + void addDocModification(const DocModification &m) { m_docModifications.append(m); } + + QString targetLangPackage() const { return m_targetLangPackage; } + void setTargetLangPackage(const QString &p) { m_targetLangPackage = p; } + +private: + QString m_name; + QList<Argument> m_arguments; + TypeInfo m_returnType; + FunctionModificationList m_modifications; + DocModificationList m_docModifications; + QString m_targetLangPackage; + Access m_access = Public; + bool m_isConst = false; + bool m_isClassMethod = false; + bool m_isStatic = false; + bool m_isDeclaration = false; + bool m_isPythonOverride = false; +}; + +QDebug operator<<(QDebug d, const AddedFunction::Argument &a); +QDebug operator<<(QDebug d, const AddedFunction &af); + +#endif // ADDEDFUNCTION_H diff --git a/sources/shiboken6/ApiExtractor/modifications_p.h b/sources/shiboken6/ApiExtractor/addedfunction_p.h index e21df9061..40b69a5df 100644 --- a/sources/shiboken6/ApiExtractor/modifications_p.h +++ b/sources/shiboken6/ApiExtractor/addedfunction_p.h @@ -1,9 +1,10 @@ -// Copyright (C) 2020 The Qt Company Ltd. +// Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -#ifndef MODIFICATIONS_P_H -#define MODIFICATIONS_P_H +#ifndef ADDEDFUNCTION_P_H +#define ADDEDFUNCTION_P_H +#include <QtCore/QtCompare> #include <QtCore/QList> #include <QtCore/QString> #include <QtCore/QStringView> @@ -19,18 +20,20 @@ namespace AddedFunctionParser { struct Argument { - bool equals(const Argument &rhs) const; - QString type; QString name; QString defaultValue; + + friend bool comparesEqual(const Argument &lhs, const Argument &rhs) noexcept + { + return lhs.type == rhs.type && lhs.name == rhs.name + && lhs.defaultValue == rhs.defaultValue; + } + Q_DECLARE_EQUALITY_COMPARABLE(Argument) }; using Arguments = QList<Argument>; -inline bool operator==(const Argument &a1, const Argument &a2) { return a1.equals(a2); } -inline bool operator!=(const Argument &a1, const Argument &a2) { return !a1.equals(a2); } - #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const Argument &a); #endif diff --git a/sources/shiboken6/ApiExtractor/anystringview_helpers.cpp b/sources/shiboken6/ApiExtractor/anystringview_helpers.cpp new file mode 100644 index 000000000..35d2d535a --- /dev/null +++ b/sources/shiboken6/ApiExtractor/anystringview_helpers.cpp @@ -0,0 +1,56 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "anystringview_helpers.h" + +#include <QtCore/QString> // Must go before QAnyStringView for operator<<(QTextStream,QASV)! +#include <QtCore/QAnyStringView> +#include <QtCore/QDebug> +#include <QtCore/QTextStream> + +#include <cstring> + +QTextStream &operator<<(QTextStream &str, QAnyStringView asv) +{ + asv.visit([&str](auto s) { str << s; }); + return str; +} + +static bool asv_containsImpl(QLatin1StringView v, char c) +{ + return v.contains(uint16_t(c)); +} + +static bool asv_containsImpl(QUtf8StringView v, char c) +{ + return std::strchr(v.data(), c) != nullptr; +} + +static bool asv_containsImpl(QStringView v, char c) +{ + return v.contains(uint16_t(c)); +} + +bool asv_contains(QAnyStringView asv, char needle) +{ + return asv.visit([needle](auto s) { return asv_containsImpl(s, needle); }); +} + +static bool asv_containsImpl(QLatin1StringView v, const char *c) +{ + return v.contains(QLatin1StringView(c)); +} +static bool asv_containsImpl(QUtf8StringView v, const char *c) +{ + return std::strstr(v.data(), c) != nullptr; +} + +static bool asv_containsImpl(QStringView v, const char *c) +{ + return v.contains(QLatin1StringView(c)); +} + +bool asv_contains(QAnyStringView asv, const char *needle) +{ + return asv.visit([needle](auto s) { return asv_containsImpl(s, needle); }); +} diff --git a/sources/shiboken6/ApiExtractor/anystringview_helpers.h b/sources/shiboken6/ApiExtractor/anystringview_helpers.h new file mode 100644 index 000000000..e1e6ab7f0 --- /dev/null +++ b/sources/shiboken6/ApiExtractor/anystringview_helpers.h @@ -0,0 +1,18 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef ANYSTRINGVIEW_STREAM_H +#define ANYSTRINGVIEW_STREAM_H + +#include <QtCore/QtClassHelperMacros> + +QT_FORWARD_DECLARE_CLASS(QAnyStringView) +QT_FORWARD_DECLARE_CLASS(QTextStream) +QT_FORWARD_DECLARE_CLASS(QDebug) + +QTextStream &operator<<(QTextStream &str, QAnyStringView asv); + +bool asv_contains(QAnyStringView asv, char needle); +bool asv_contains(QAnyStringView asv, const char *needle); + +#endif // ANYSTRINGVIEW_STREAM_H diff --git a/sources/shiboken6/ApiExtractor/apiextractor.cpp b/sources/shiboken6/ApiExtractor/apiextractor.cpp index d18758fe8..786cd0783 100644 --- a/sources/shiboken6/ApiExtractor/apiextractor.cpp +++ b/sources/shiboken6/ApiExtractor/apiextractor.cpp @@ -3,7 +3,6 @@ #include "apiextractor.h" #include "apiextractorresult.h" -#include "apiextractorresultdata_p.h" #include "abstractmetaargument.h" #include "abstractmetabuilder.h" #include "abstractmetaenum.h" @@ -12,8 +11,9 @@ #include "abstractmetalang.h" #include "codesnip.h" #include "exception.h" -#include "fileout.h" +#include "messages.h" #include "modifications.h" +#include "optionsparser.h" #include "reporthandler.h" #include "typedatabase.h" #include "customconversion.h" @@ -21,6 +21,7 @@ #include "primitivetypeentry.h" #include "smartpointertypeentry.h" #include "typedefentry.h" +#include "namespacetypeentry.h" #include "typesystemtypeentry.h" #include "qtcompat.h" @@ -40,136 +41,250 @@ struct InstantiationCollectContext AbstractMetaTypeList instantiatedContainers; InstantiatedSmartPointers instantiatedSmartPointers; QStringList instantiatedContainersNames; - QList<const TypeEntry *> m_synthesizedTypeEntries; }; -struct ApiExtractorPrivate +struct ApiExtractorOptions { - bool runHelper(ApiExtractorFlags flags); - - static QString getSimplifiedContainerTypeName(const AbstractMetaType &type); - void addInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context, - const AbstractMetaType &type, - const QString &contextName); - void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context, - const AbstractMetaFunctionCPtr &func); - void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context, - const AbstractMetaClass *metaClass); - void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context); - void collectInstantiatedOpqaqueContainers(InstantiationCollectContext &context); - void collectContainerTypesFromSnippets(InstantiationCollectContext &context); - void collectContainerTypesFromConverterMacros(InstantiationCollectContext &context, - const QString &code, - bool toPythonMacro); - void addInstantiatedSmartPointer(InstantiationCollectContext &context, - const AbstractMetaType &type); - QString m_typeSystemFileName; QFileInfoList m_cppFileNames; HeaderPaths m_includePaths; QStringList m_clangOptions; - AbstractMetaBuilder* m_builder = nullptr; QString m_logDirectory; LanguageLevel m_languageLevel = LanguageLevel::Default; bool m_skipDeprecated = false; }; -ApiExtractor::ApiExtractor() : - d(new ApiExtractorPrivate) +static inline QString languageLevelDescription() { - // Environment TYPESYSTEMPATH - QString envTypesystemPaths = QFile::decodeName(qgetenv("TYPESYSTEMPATH")); - if (!envTypesystemPaths.isEmpty()) - TypeDatabase::instance()->addTypesystemPath(envTypesystemPaths); + return u"C++ Language level (c++11..c++17, default="_s + + QLatin1StringView(clang::languageLevelOption(clang::emulatedCompilerLanguageLevel())) + + u')'; } -ApiExtractor::~ApiExtractor() +QList<OptionDescription> ApiExtractor::options() { - delete d->m_builder; - delete d; + return { + {u"use-global-header"_s, + u"Use the global headers in generated code."_s}, + {u"clang-option"_s, + u"Option to be passed to clang"_s}, + {u"clang-options"_s, + u"A comma-separated list of options to be passed to clang"_s}, + {u"skip-deprecated"_s, + u"Skip deprecated functions"_s}, + {u"-F<path>"_s, {} }, + {u"framework-include-paths="_s + OptionsParser::pathSyntax(), + u"Framework include paths used by the C++ parser"_s}, + {u"-isystem<path>"_s, {} }, + {u"system-include-paths="_s + OptionsParser::pathSyntax(), + u"System include paths used by the C++ parser"_s}, + {u"language-level=, -std=<level>"_s, + languageLevelDescription()}, + }; } -void ApiExtractor::addTypesystemSearchPath (const QString& path) +class ApiExtractorOptionsParser : public OptionsParser { - TypeDatabase::instance()->addTypesystemPath(path); -} +public: + explicit ApiExtractorOptionsParser(ApiExtractorOptions *o) : m_options(o) {} + + bool handleBoolOption(const QString &key, OptionSource source) override; + bool handleOption(const QString &key, const QString &value, + OptionSource source) override; -void ApiExtractor::addTypesystemSearchPath(const QStringList& paths) +private: + void parseIncludePathOption(const QString &value, HeaderType headerType); + void parseIncludePathOption(const QStringList &values, HeaderType headerType); + void setLanguageLevel(const QString &value); + + ApiExtractorOptions *m_options; +}; + +void ApiExtractorOptionsParser::parseIncludePathOption(const QString &value, + HeaderType headerType) { - for (const QString &path : paths) - addTypesystemSearchPath(path); + if (value.isEmpty()) + throw Exception(u"Empty value passed to include path option"_s); + const auto path = QFile::encodeName(QDir::cleanPath(value)); + m_options->m_includePaths.append(HeaderPath{path, headerType}); } -void ApiExtractor::setTypesystemKeywords(const QStringList &keywords) +void ApiExtractorOptionsParser::parseIncludePathOption(const QStringList &values, + HeaderType headerType) { - TypeDatabase::instance()->setTypesystemKeywords(keywords); + for (const auto &value : values) + parseIncludePathOption(value, headerType); } -void ApiExtractor::addIncludePath(const HeaderPath& path) +void ApiExtractorOptionsParser::setLanguageLevel(const QString &value) { - d->m_includePaths << path; + const QByteArray languageLevelBA = value.toLatin1(); + const LanguageLevel level = clang::languageLevelFromOption(languageLevelBA.constData()); + if (level == LanguageLevel::Default) + throw Exception(msgInvalidLanguageLevel(value)); + m_options->m_languageLevel = level; } -void ApiExtractor::addIncludePath(const HeaderPaths& paths) +bool ApiExtractorOptionsParser::handleBoolOption(const QString &key, OptionSource source) { - d->m_includePaths << paths; + static const auto isystemOption = "isystem"_L1; + + switch (source) { + case OptionSource::CommandLine: + case OptionSource::ProjectFile: + if (key == u"use-global-header") { + AbstractMetaBuilder::setUseGlobalHeader(true); + return true; + } + if (key == u"skip-deprecated") { + m_options->m_skipDeprecated = true; + return true; + } + break; + + case OptionSource::CommandLineSingleDash: + if (key.startsWith(u'I')) { // Shorthand path arguments -I/usr/include... + parseIncludePathOption(key.sliced(1), HeaderType::Standard); + return true; + } + if (key.startsWith(u'F')) { + parseIncludePathOption(key.sliced(1), HeaderType::Framework); + return true; + } + if (key.startsWith(isystemOption)) { + parseIncludePathOption(key.sliced(isystemOption.size()), HeaderType::System); + return true; + } + break; + } + return false; } -HeaderPaths ApiExtractor::includePaths() const +bool ApiExtractorOptionsParser::handleOption(const QString &key, const QString &value, + OptionSource source) { - return d->m_includePaths; + if (source == OptionSource::CommandLineSingleDash) { + if (key == u"std") { + setLanguageLevel(value); + return true; + } + return false; + } + + if (key == u"clang-option") { + m_options->m_clangOptions.append(value); + return true; + } + if (key == u"clang-options") { + m_options->m_clangOptions.append(value.split(u',', Qt::SkipEmptyParts)); + return true; + } + if (key == u"include-paths") { + parseIncludePathOption(value.split(QDir::listSeparator(), Qt::SkipEmptyParts), + HeaderType::Standard); + return true; + } + if (key == u"framework-include-paths") { + parseIncludePathOption(value.split(QDir::listSeparator(), Qt::SkipEmptyParts), + HeaderType::Framework); + return true; + } + if (key == u"system-include-paths") { + parseIncludePathOption(value.split(QDir::listSeparator(), Qt::SkipEmptyParts), + HeaderType::System); + return true; + } + if (key == u"language-level") { + setLanguageLevel(value); + return true; + } + + if (source == OptionSource::ProjectFile) { + if (key == u"include-path") { + parseIncludePathOption(value, HeaderType::Standard); + return true; + } + if (key == u"framework-include-path") { + parseIncludePathOption(value, HeaderType::Framework); + return true; + } + if (key == u"system-include-path") { + parseIncludePathOption(value, HeaderType::System); + return true; + } + } + + return false; } -void ApiExtractor::setLogDirectory(const QString& logDir) +std::shared_ptr<OptionsParser> ApiExtractor::createOptionsParser() { - d->m_logDirectory = logDir; + return std::make_shared<ApiExtractorOptionsParser>(d); } -void ApiExtractor::setCppFileNames(const QFileInfoList &cppFileName) +struct ApiExtractorPrivate : public ApiExtractorOptions { - d->m_cppFileNames = cppFileName; -} + bool runHelper(ApiExtractorFlags flags); -QFileInfoList ApiExtractor::cppFileNames() const + static QString getSimplifiedContainerTypeName(const AbstractMetaType &type); + void addInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context, + const AbstractMetaType &type, + const QString &contextName); + void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context, + const AbstractMetaFunctionCPtr &func); + void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context, + const AbstractMetaClassCPtr &metaClass); + void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context); + void collectInstantiatedOpqaqueContainers(InstantiationCollectContext &context); + void collectContainerTypesFromSnippets(InstantiationCollectContext &context); + void collectContainerTypesFromConverterMacros(InstantiationCollectContext &context, + const QString &code, + bool toPythonMacro); + void addInstantiatedSmartPointer(InstantiationCollectContext &context, + const AbstractMetaType &type); + + AbstractMetaBuilder *m_builder = nullptr; +}; + +ApiExtractor::ApiExtractor() : + d(new ApiExtractorPrivate) { - return d->m_cppFileNames; } -void ApiExtractor::setTypeSystem(const QString& typeSystemFileName) +ApiExtractor::~ApiExtractor() { - d->m_typeSystemFileName = typeSystemFileName; + delete d->m_builder; + delete d; } -QString ApiExtractor::typeSystem() const +HeaderPaths ApiExtractor::includePaths() const { - return d->m_typeSystemFileName; + return d->m_includePaths; } -void ApiExtractor::setSkipDeprecated(bool value) +void ApiExtractor::setLogDirectory(const QString& logDir) { - d->m_skipDeprecated = value; - if (d->m_builder) - d->m_builder->setSkipDeprecated(d->m_skipDeprecated); + d->m_logDirectory = logDir; } -void ApiExtractor::setSuppressWarnings ( bool value ) +void ApiExtractor::setCppFileNames(const QFileInfoList &cppFileName) { - TypeDatabase::instance()->setSuppressWarnings(value); + d->m_cppFileNames = cppFileName; } -void ApiExtractor::setSilent ( bool value ) +QFileInfoList ApiExtractor::cppFileNames() const { - ReportHandler::setSilent(value); + return d->m_cppFileNames; } -bool ApiExtractor::setApiVersion(const QString& package, const QString &version) +void ApiExtractor::setTypeSystem(const QString& typeSystemFileName) { - return TypeDatabase::setApiVersion(package, version); + d->m_typeSystemFileName = typeSystemFileName; } -void ApiExtractor::setDropTypeEntries(const QStringList &dropEntries) +QString ApiExtractor::typeSystem() const { - TypeDatabase::instance()->setDropTypeEntries(dropEntries); + return d->m_typeSystemFileName; } const AbstractMetaEnumList &ApiExtractor::globalEnums() const @@ -225,8 +340,7 @@ bool ApiExtractorPrivate::runHelper(ApiExtractorFlags flags) } const QString pattern = QDir::tempPath() + u'/' - + m_cppFileNames.constFirst().baseName() - + QStringLiteral("_XXXXXX.hpp"); + + m_cppFileNames.constFirst().baseName() + "_XXXXXX.hpp"_L1; QTemporaryFile ppFile(pattern); bool autoRemove = !qEnvironmentVariableIsSet("KEEP_TEMP_FILES"); // make sure that a tempfile can be written @@ -235,7 +349,7 @@ bool ApiExtractorPrivate::runHelper(ApiExtractorFlags flags) << ": " << qPrintable(ppFile.errorString()) << '\n'; return false; } - for (const auto &cppFileName : qAsConst(m_cppFileNames)) { + for (const auto &cppFileName : std::as_const(m_cppFileNames)) { ppFile.write("#include \""); ppFile.write(cppFileName.absoluteFilePath().toLocal8Bit()); ppFile.write("\"\n"); @@ -264,18 +378,18 @@ bool ApiExtractorPrivate::runHelper(ApiExtractorFlags flags) arguments.append(m_clangOptions.at(i).toUtf8()); } - for (const HeaderPath &headerPath : qAsConst(m_includePaths)) + for (const HeaderPath &headerPath : std::as_const(m_includePaths)) arguments.append(HeaderPath::includeOption(headerPath)); + if (flags.testFlag(ApiExtractorFlag::UsePySideExtensions)) + addPySideExtensions(&arguments); arguments.append(QFile::encodeName(preprocessedCppFileName)); + if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { qCInfo(lcShiboken).noquote().nospace() << "clang language level: " << int(m_languageLevel) << "\nclang arguments: " << arguments; } - if (flags.testFlag(ApiExtractorFlag::UsePySideExtensions)) - addPySideExtensions(&arguments); - const bool result = m_builder->build(arguments, flags, addCompilerSupportArguments, m_languageLevel); if (!result) @@ -300,19 +414,17 @@ std::optional<ApiExtractorResult> ApiExtractor::run(ApiExtractorFlags flags) InstantiationCollectContext collectContext; d->collectInstantiatedContainersAndSmartPointers(collectContext); - auto *data = new ApiExtractorResultData; - - classListToCList(d->m_builder->takeClasses(), &data->m_metaClasses); - classListToCList(d->m_builder->takeTemplates(), &data->m_templates); - classListToCList(d->m_builder->takeSmartPointers(), &data->m_smartPointers); - data->m_globalFunctions = d->m_builder->globalFunctions(); - data->m_globalEnums = d->m_builder->globalEnums(); - data->m_enums = d->m_builder->typeEntryToEnumsHash(); - data->m_flags = flags; - qSwap(data->m_instantiatedContainers, collectContext.instantiatedContainers); - qSwap(data->m_instantiatedSmartPointers, collectContext.instantiatedSmartPointers); - qSwap(data->m_synthesizedTypeEntries, collectContext.m_synthesizedTypeEntries); - return ApiExtractorResult(data); + ApiExtractorResult result; + classListToCList(d->m_builder->takeClasses(), &result.m_metaClasses); + classListToCList(d->m_builder->takeSmartPointers(), &result.m_smartPointers); + result.m_globalFunctions = d->m_builder->globalFunctions(); + result.m_globalEnums = d->m_builder->globalEnums(); + result.m_enums = d->m_builder->typeEntryToEnumsHash(); + result.m_flags = flags; + result.m_typedefTargetToName = d->m_builder->typedefTargetToName(); + qSwap(result.m_instantiatedContainers, collectContext.instantiatedContainers); + qSwap(result.m_instantiatedSmartPointers, collectContext.instantiatedSmartPointers); + return result; } LanguageLevel ApiExtractor::languageLevel() const @@ -320,26 +432,11 @@ LanguageLevel ApiExtractor::languageLevel() const return d->m_languageLevel; } -void ApiExtractor::setLanguageLevel(LanguageLevel languageLevel) -{ - d->m_languageLevel = languageLevel; -} - QStringList ApiExtractor::clangOptions() const { return d->m_clangOptions; } -void ApiExtractor::setClangOptions(const QStringList &co) -{ - d->m_clangOptions = co; -} - -void ApiExtractor::setUseGlobalHeader(bool h) -{ - AbstractMetaBuilder::setUseGlobalHeader(h); -} - AbstractMetaFunctionPtr ApiExtractor::inheritTemplateFunction(const AbstractMetaFunctionCPtr &function, const AbstractMetaTypeList &templateTypes) @@ -350,20 +447,19 @@ AbstractMetaFunctionPtr AbstractMetaFunctionPtr ApiExtractor::inheritTemplateMember(const AbstractMetaFunctionCPtr &function, const AbstractMetaTypeList &templateTypes, - const AbstractMetaClass *templateClass, - AbstractMetaClass *subclass) + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaClassPtr &subclass) { return AbstractMetaBuilder::inheritTemplateMember(function, templateTypes, templateClass, subclass); } -AbstractMetaClass *ApiExtractor::inheritTemplateClass(ComplexTypeEntry *te, - const AbstractMetaClass *templateClass, - const AbstractMetaTypeList &templateTypes, - InheritTemplateFlags flags) +AbstractMetaClassPtr ApiExtractor::inheritTemplateClass(const ComplexTypeEntryPtr &te, + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaTypeList &templateTypes) { return AbstractMetaBuilder::inheritTemplateClass(te, templateClass, - templateTypes, flags); + templateTypes); } QString ApiExtractorPrivate::getSimplifiedContainerTypeName(const AbstractMetaType &type) @@ -409,7 +505,7 @@ AbstractMetaType canonicalSmartPtrInstantiation(const AbstractMetaType &type) return fixedType; } -static inline const TypeEntry *pointeeTypeEntry(const AbstractMetaType &smartPtrType) +static inline TypeEntryCPtr pointeeTypeEntry(const AbstractMetaType &smartPtrType) { return smartPtrType.instantiations().constFirst().typeEntry(); } @@ -437,12 +533,12 @@ ApiExtractorPrivate::addInstantiatedContainersAndSmartPointers(InstantiationColl return; } if (type.hasTemplateChildren()) { - QString piece = isContainer ? QStringLiteral("container") : QStringLiteral("smart pointer"); + const auto piece = isContainer ? "container"_L1 : "smart pointer"_L1; QString warning = QString::fromLatin1("Skipping instantiation of %1 '%2' because it has template" " arguments.").arg(piece, type.originalTypeDescription()); if (!contextName.isEmpty()) - warning.append(QStringLiteral(" Calling context: ") + contextName); + warning.append(" Calling context: "_L1 + contextName); qCWarning(lcShiboken).noquote().nospace() << warning; return; @@ -485,12 +581,12 @@ static FunctionModification invalidateArgMod(const AbstractMetaFunctionCPtr &f, } static void addOwnerModification(const AbstractMetaFunctionCList &functions, - ComplexTypeEntry *typeEntry) + const ComplexTypeEntryPtr &typeEntry) { for (const auto &f : functions) { if (!f->arguments().isEmpty() && f->arguments().constFirst().type().indirections() > 0) { - qSharedPointerConstCast<AbstractMetaFunction>(f)->clearModificationsCache(); + std::const_pointer_cast<AbstractMetaFunction>(f)->clearModificationsCache(); typeEntry->addFunctionModification(invalidateArgMod(f)); } } @@ -500,22 +596,52 @@ void ApiExtractorPrivate::addInstantiatedSmartPointer(InstantiationCollectContex const AbstractMetaType &type) { InstantiatedSmartPointer smp; - smp.type = simplifiedType(type); + smp.type = canonicalSmartPtrInstantiation(type); smp.smartPointer = AbstractMetaClass::findClass(m_builder->smartPointers(), type.typeEntry()); Q_ASSERT(smp.smartPointer); const auto &instantiatedType = type.instantiations().constFirst(); - auto *ste = static_cast<const SmartPointerTypeEntry *>(smp.smartPointer->typeEntry()); - auto *typedefEntry = new TypedefEntry(SmartPointerTypeEntry::getTargetName(smp.type), - ste->name(), ste->version(), ste->parent()); + const auto ste = std::static_pointer_cast<const SmartPointerTypeEntry>(smp.smartPointer->typeEntry()); + QString name = ste->getTargetName(smp.type); + auto parentTypeEntry = ste->parent(); + + // FIXME PYSIDE 7: Make global scope the default behavior? + // Note: Also requires changing SmartPointerTypeEntry::getTargetName() + // to not strip namespaces from unnamed instances. + const bool globalScope = name.startsWith("::"_L1); + if (globalScope) { + name.remove(0, 2); + parentTypeEntry = typeSystemTypeEntry(ste); + } + + auto colonPos = name.lastIndexOf(u"::"); + const bool withinNameSpace = colonPos != -1; + if (withinNameSpace) { // user defined + const QString nameSpace = name.left(colonPos); + name.remove(0, colonPos + 2); + const auto nameSpaces = TypeDatabase::instance()->findNamespaceTypes(nameSpace); + if (nameSpaces.isEmpty()) + throw Exception(msgNamespaceNotFound(name)); + parentTypeEntry = nameSpaces.constFirst(); + } + + TypedefEntryPtr typedefEntry(new TypedefEntry(name, ste->name(), ste->version(), + parentTypeEntry)); typedefEntry->setTargetLangPackage(ste->targetLangPackage()); - auto *instantiationEntry = TypeDatabase::initializeTypeDefEntry(typedefEntry, ste); + auto instantiationEntry = TypeDatabase::initializeTypeDefEntry(typedefEntry, ste); + instantiationEntry->setParent(parentTypeEntry); smp.specialized = ApiExtractor::inheritTemplateClass(instantiationEntry, smp.smartPointer, - {instantiatedType}, - InheritTemplateFlag::SetEnclosingClass); + {instantiatedType}); Q_ASSERT(smp.specialized); + if (parentTypeEntry->type() != TypeEntry::TypeSystemType) { // move class to desired namespace + const auto enclClass = AbstractMetaClass::findClass(m_builder->classes(), parentTypeEntry); + Q_ASSERT(enclClass); + auto specialized = std::const_pointer_cast<AbstractMetaClass>(smp.specialized); + specialized->setEnclosingClass(enclClass); + enclClass->addInnerClass(specialized); + } if (instantiationEntry->isComplex()) { addOwnerModification(smp.specialized->queryFunctions(FunctionQueryOption::Constructors), @@ -527,8 +653,6 @@ void ApiExtractorPrivate::addInstantiatedSmartPointer(InstantiationCollectContex } context.instantiatedSmartPointers.append(smp); - context.m_synthesizedTypeEntries.append(typedefEntry); - context.m_synthesizedTypeEntries.append(instantiationEntry); } void @@ -536,22 +660,34 @@ ApiExtractorPrivate::collectInstantiatedContainersAndSmartPointers(Instantiation const AbstractMetaFunctionCPtr &func) { addInstantiatedContainersAndSmartPointers(context, func->type(), func->signature()); - for (const AbstractMetaArgument &arg : func->arguments()) - addInstantiatedContainersAndSmartPointers(context, arg.type(), func->signature()); + for (const AbstractMetaArgument &arg : func->arguments()) { + const auto argType = arg.type(); + const auto type = argType.viewOn() != nullptr ? *argType.viewOn() : argType; + addInstantiatedContainersAndSmartPointers(context, type, func->signature()); + } } void ApiExtractorPrivate::collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context, - const AbstractMetaClass *metaClass) + const AbstractMetaClassCPtr &metaClass) { if (!metaClass->typeEntry()->generateCode()) return; for (const auto &func : metaClass->functions()) collectInstantiatedContainersAndSmartPointers(context, func); + for (const auto &func : metaClass->userAddedPythonOverrides()) + collectInstantiatedContainersAndSmartPointers(context, func); for (const AbstractMetaField &field : metaClass->fields()) addInstantiatedContainersAndSmartPointers(context, field.type(), field.name()); - for (auto *innerClass : metaClass->innerClasses()) - collectInstantiatedContainersAndSmartPointers(context, innerClass); + + // The list of inner classes might be extended when smart pointer + // instantiations are specified to be in namespaces. + const auto &innerClasses = metaClass->innerClasses(); + for (auto i = innerClasses.size() - 1; i >= 0; --i) { + const auto innerClass = innerClasses.at(i); + if (!innerClass->typeEntry()->isSmartPointer()) + collectInstantiatedContainersAndSmartPointers(context, innerClass); + } } void @@ -560,7 +696,7 @@ ApiExtractorPrivate::collectInstantiatedContainersAndSmartPointers(Instantiation collectInstantiatedOpqaqueContainers(context); for (const auto &func : m_builder->globalFunctions()) collectInstantiatedContainersAndSmartPointers(context, func); - for (auto metaClass : m_builder->classes()) + for (const auto &metaClass : m_builder->classes()) collectInstantiatedContainersAndSmartPointers(context, metaClass); collectContainerTypesFromSnippets(context); } @@ -569,12 +705,12 @@ ApiExtractorPrivate::collectInstantiatedContainersAndSmartPointers(Instantiation // the current package or, for primitive types, if the container is in the // current package. static bool generateOpaqueContainer(const AbstractMetaType &type, - const TypeSystemTypeEntry *moduleEntry) + const TypeSystemTypeEntryCPtr &moduleEntry) { - auto *te = type.instantiations().constFirst().typeEntry(); - auto *typeModuleEntry = te->typeSystemTypeEntry(); + auto te = type.instantiations().constFirst().typeEntry(); + auto typeModuleEntry = typeSystemTypeEntry(te); return typeModuleEntry == moduleEntry - || (te->isPrimitive() && type.typeEntry()->typeSystemTypeEntry() == moduleEntry); + || (te->isPrimitive() && typeSystemTypeEntry(type.typeEntry()) == moduleEntry); } void ApiExtractorPrivate::collectInstantiatedOpqaqueContainers(InstantiationCollectContext &context) @@ -582,13 +718,12 @@ void ApiExtractorPrivate::collectInstantiatedOpqaqueContainers(InstantiationColl // Add all instantiations of opaque containers for types from the current // module. auto *td = TypeDatabase::instance(); - const auto *moduleEntry = TypeDatabase::instance()->defaultTypeSystemType(); + const auto moduleEntry = TypeDatabase::instance()->defaultTypeSystemType(); const auto &containers = td->containerTypes(); - for (const auto *container : containers) { + for (const auto &container : containers) { for (const auto &oc : container->opaqueContainers()) { QString errorMessage; - const QString typeName = container->qualifiedCppName() + u'<' - + oc.instantiation + u'>'; + const QString typeName = container->qualifiedCppName() + oc.templateParameters(); auto typeOpt = AbstractMetaType::fromString(typeName, &errorMessage); if (typeOpt.has_value() && generateOpaqueContainer(typeOpt.value(), moduleEntry)) { @@ -601,15 +736,18 @@ void ApiExtractorPrivate::collectInstantiatedOpqaqueContainers(InstantiationColl static void getCode(QStringList &code, const CodeSnipList &codeSnips) { - for (const CodeSnip &snip : qAsConst(codeSnips)) + for (const CodeSnip &snip : std::as_const(codeSnips)) code.append(snip.code()); } -static void getCode(QStringList &code, const TypeEntry *type) +static void getCode(QStringList &code, const TypeEntryCPtr &type) { - getCode(code, type->codeSnips()); + if (type->isComplex()) + getCode(code, std::static_pointer_cast<const ComplexTypeEntry>(type)->codeSnips()); + else if (type->isTypeSystem()) + getCode(code, std::static_pointer_cast<const TypeSystemTypeEntry>(type)->codeSnips()); - CustomConversion *customConversion = type->customConversion(); + auto customConversion = CustomConversion::getCustomConversion(type); if (!customConversion) return; @@ -620,31 +758,31 @@ static void getCode(QStringList &code, const TypeEntry *type) if (toCppConversions.isEmpty()) return; - for (CustomConversion::TargetToNativeConversion *toNative : qAsConst(toCppConversions)) - code.append(toNative->conversion()); + for (const auto &toNative : std::as_const(toCppConversions)) + code.append(toNative.conversion()); } void ApiExtractorPrivate::collectContainerTypesFromSnippets(InstantiationCollectContext &context) { QStringList snips; auto *td = TypeDatabase::instance(); - const PrimitiveTypeEntryList &primitiveTypeList = td->primitiveTypes(); - for (const PrimitiveTypeEntry *type : primitiveTypeList) + const PrimitiveTypeEntryCList &primitiveTypeList = td->primitiveTypes(); + for (const auto &type : primitiveTypeList) getCode(snips, type); - const ContainerTypeEntryList &containerTypeList = td->containerTypes(); - for (const ContainerTypeEntry *type : containerTypeList) + const ContainerTypeEntryCList &containerTypeList = td->containerTypes(); + for (const auto &type : containerTypeList) getCode(snips, type); - for (auto metaClass : m_builder->classes()) + for (const auto &metaClass : m_builder->classes()) getCode(snips, metaClass->typeEntry()); - const TypeSystemTypeEntry *moduleEntry = td->defaultTypeSystemType(); + const auto moduleEntry = td->defaultTypeSystemType(); Q_ASSERT(moduleEntry); getCode(snips, moduleEntry); for (const auto &func : m_builder->globalFunctions()) getCode(snips, func->injectedCodeSnips()); - for (const QString &code : qAsConst(snips)) { + for (const QString &code : std::as_const(snips)) { collectContainerTypesFromConverterMacros(context, code, true); collectContainerTypesFromConverterMacros(context, code, false); } @@ -656,8 +794,8 @@ ApiExtractorPrivate::collectContainerTypesFromConverterMacros(InstantiationColle bool toPythonMacro) { QString convMacro = toPythonMacro ? u"%CONVERTTOPYTHON["_s : u"%CONVERTTOCPP["_s; - int offset = toPythonMacro ? sizeof("%CONVERTTOPYTHON") : sizeof("%CONVERTTOCPP"); - int start = 0; + const qsizetype offset = toPythonMacro ? sizeof("%CONVERTTOPYTHON") : sizeof("%CONVERTTOCPP"); + qsizetype start = 0; QString errorMessage; while ((start = code.indexOf(convMacro, start)) != -1) { int end = code.indexOf(u']', start); diff --git a/sources/shiboken6/ApiExtractor/apiextractor.h b/sources/shiboken6/ApiExtractor/apiextractor.h index fd84f6870..7bff5c252 100644 --- a/sources/shiboken6/ApiExtractor/apiextractor.h +++ b/sources/shiboken6/ApiExtractor/apiextractor.h @@ -5,10 +5,10 @@ #define APIEXTRACTOR_H #include "abstractmetalang_typedefs.h" -#include "abstractmetatype.h" #include "apiextractorflags.h" #include "header_paths.h" #include "clangparser/compilersupport.h" +#include "typesystem_typedefs.h" #include <QtCore/QFileInfoList> #include <QtCore/QStringList> @@ -20,6 +20,8 @@ class AbstractMetaClass; class AbstractMetaEnum; class AbstractMetaFunction; class ComplexTypeEntry; +struct OptionDescription; +class OptionsParser; QT_BEGIN_NAMESPACE class QDebug; @@ -36,27 +38,17 @@ public: ApiExtractor(); ~ApiExtractor(); + static QList<OptionDescription> options(); + std::shared_ptr<OptionsParser> createOptionsParser(); + void setTypeSystem(const QString& typeSystemFileName); QString typeSystem() const; void setCppFileNames(const QFileInfoList &cppFileNames); QFileInfoList cppFileNames() const; - void setSkipDeprecated(bool value); - static void setSuppressWarnings(bool value); - static void setSilent(bool value); - static void addTypesystemSearchPath(const QString &path); - static void addTypesystemSearchPath(const QStringList& paths); - static void setTypesystemKeywords(const QStringList& keywords); - void addIncludePath(const HeaderPath& path); - void addIncludePath(const HeaderPaths& paths); HeaderPaths includePaths() const; void setLogDirectory(const QString& logDir); - static bool setApiVersion(const QString &package, const QString &version); - static void setDropTypeEntries(const QStringList &dropEntries); LanguageLevel languageLevel() const; - void setLanguageLevel(LanguageLevel languageLevel); QStringList clangOptions() const; - void setClangOptions(const QStringList &co); - static void setUseGlobalHeader(bool h); const AbstractMetaEnumList &globalEnums() const; const AbstractMetaFunctionCList &globalFunctions() const; @@ -74,15 +66,14 @@ public: static AbstractMetaFunctionPtr inheritTemplateMember(const AbstractMetaFunctionCPtr &function, const AbstractMetaTypeList &templateTypes, - const AbstractMetaClass *templateClass, - AbstractMetaClass *subclass); + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaClassPtr &subclass); /// Forwards to AbstractMetaBuilder::inheritTemplateClass() - static AbstractMetaClass * - inheritTemplateClass(ComplexTypeEntry *te, - const AbstractMetaClass *templateClass, - const AbstractMetaTypeList &templateTypes, - InheritTemplateFlags flags = {}); + static AbstractMetaClassPtr + inheritTemplateClass(const ComplexTypeEntryPtr &te, + const AbstractMetaClassCPtr &templateClass, + const AbstractMetaTypeList &templateTypes); private: ApiExtractorPrivate *d; diff --git a/sources/shiboken6/ApiExtractor/apiextractorflags.h b/sources/shiboken6/ApiExtractor/apiextractorflags.h index 4fe6ecc1a..6f69b8b77 100644 --- a/sources/shiboken6/ApiExtractor/apiextractorflags.h +++ b/sources/shiboken6/ApiExtractor/apiextractorflags.h @@ -15,12 +15,4 @@ enum class ApiExtractorFlag Q_DECLARE_FLAGS(ApiExtractorFlags, ApiExtractorFlag) Q_DECLARE_OPERATORS_FOR_FLAGS(ApiExtractorFlags) -enum class InheritTemplateFlag -{ - SetEnclosingClass = 0x1 -}; - -Q_DECLARE_FLAGS(InheritTemplateFlags, InheritTemplateFlag) -Q_DECLARE_OPERATORS_FOR_FLAGS(InheritTemplateFlags) - #endif // APIEXTRACTORFLAGS_H diff --git a/sources/shiboken6/ApiExtractor/apiextractorresult.cpp b/sources/shiboken6/ApiExtractor/apiextractorresult.cpp index 8067290d1..5a433bbeb 100644 --- a/sources/shiboken6/ApiExtractor/apiextractorresult.cpp +++ b/sources/shiboken6/ApiExtractor/apiextractorresult.cpp @@ -2,98 +2,97 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "apiextractorresult.h" -#include "apiextractorresultdata_p.h" #include "abstractmetalang.h" #include "abstractmetaenum.h" #include "enumtypeentry.h" #include "flagstypeentry.h" +#include "smartpointertypeentry.h" -ApiExtractorResultData::ApiExtractorResultData() = default; - -ApiExtractorResultData::~ApiExtractorResultData() -{ - qDeleteAll(m_smartPointers); - qDeleteAll(m_metaClasses); - qDeleteAll(m_templates); - for (auto &smp : m_instantiatedSmartPointers) - delete smp.specialized; - qDeleteAll(m_synthesizedTypeEntries); -} - -ApiExtractorResult::ApiExtractorResult() : d(new ApiExtractorResultData) -{ -} - -ApiExtractorResult::ApiExtractorResult(ApiExtractorResultData *data) : - d(data) -{ -} +ApiExtractorResult::ApiExtractorResult() = default; ApiExtractorResult::ApiExtractorResult(const ApiExtractorResult &) = default; ApiExtractorResult &ApiExtractorResult::operator=(const ApiExtractorResult &) = default; -ApiExtractorResult::ApiExtractorResult(ApiExtractorResult &&) = default; +ApiExtractorResult::ApiExtractorResult(ApiExtractorResult &&) noexcept = default; -ApiExtractorResult &ApiExtractorResult::operator=(ApiExtractorResult &&) = default; +ApiExtractorResult &ApiExtractorResult::operator=(ApiExtractorResult &&) noexcept = default; ApiExtractorResult::~ApiExtractorResult() = default; const AbstractMetaEnumList &ApiExtractorResult::globalEnums() const { - return d->m_globalEnums; + return m_globalEnums; } const AbstractMetaFunctionCList &ApiExtractorResult::globalFunctions() const { - return d->m_globalFunctions; + return m_globalFunctions; } const AbstractMetaClassCList &ApiExtractorResult::classes() const { - return d->m_metaClasses; + return m_metaClasses; } const AbstractMetaClassCList &ApiExtractorResult::smartPointers() const { - return d->m_smartPointers; + return m_smartPointers; } const AbstractMetaTypeList &ApiExtractorResult::instantiatedContainers() const { - return d->m_instantiatedContainers; + return m_instantiatedContainers; } const InstantiatedSmartPointers &ApiExtractorResult::instantiatedSmartPointers() const { - return d->m_instantiatedSmartPointers; + return m_instantiatedSmartPointers; +} + +std::optional<InstantiatedSmartPointer> + ApiExtractorResult::findSmartPointerInstantiation(const SmartPointerTypeEntryCPtr &pointer, + const TypeEntryCPtr &pointee) const +{ + for (const auto &smp : m_instantiatedSmartPointers) { + const auto &i = smp.type; + if (i.typeEntry() == pointer && i.instantiations().at(0).typeEntry() == pointee) + return smp; + } + return std::nullopt; +} + +const QMultiHash<QString, QString> &ApiExtractorResult::typedefTargetToName() const +{ + return m_typedefTargetToName; } ApiExtractorFlags ApiExtractorResult::flags() const { - return d->m_flags; + return m_flags; } void ApiExtractorResult::setFlags(ApiExtractorFlags f) { - d->m_flags = f; + m_flags = f; } -std::optional<AbstractMetaEnum> ApiExtractorResult::findAbstractMetaEnum(const TypeEntry *typeEntry) const +std::optional<AbstractMetaEnum> + ApiExtractorResult::findAbstractMetaEnum(TypeEntryCPtr typeEntry) const { if (typeEntry && typeEntry->isFlags()) - typeEntry = static_cast<const FlagsTypeEntry *>(typeEntry)->originator(); - const auto it = d->m_enums.constFind(typeEntry); - if (it == d->m_enums.constEnd()) + typeEntry = std::static_pointer_cast<const FlagsTypeEntry>(typeEntry)->originator(); + const auto it = m_enums.constFind(typeEntry); + if (it == m_enums.constEnd()) return {}; return it.value(); } -AbstractMetaFunctionCList ApiExtractorResult::implicitConversions(const TypeEntry *type) const +AbstractMetaFunctionCList ApiExtractorResult::implicitConversions(const TypeEntryCPtr &type) const { if (type->isValue()) { - if (auto metaClass = AbstractMetaClass::findClass(d->m_metaClasses, type)) + if (auto metaClass = AbstractMetaClass::findClass(m_metaClasses, type)) return metaClass->implicitConversions(); } return {}; diff --git a/sources/shiboken6/ApiExtractor/apiextractorresult.h b/sources/shiboken6/ApiExtractor/apiextractorresult.h index 8dd3383bf..b2aae88ed 100644 --- a/sources/shiboken6/ApiExtractor/apiextractorresult.h +++ b/sources/shiboken6/ApiExtractor/apiextractorresult.h @@ -4,14 +4,13 @@ #ifndef APIEXTRACTORRESULT_H #define APIEXTRACTORRESULT_H -#include "abstractmetalang.h" #include "apiextractorflags.h" -#include "abstractmetaenum.h" #include "abstractmetatype.h" +#include "abstractmetalang_typedefs.h" #include "typesystem_typedefs.h" #include <QtCore/QHash> -#include <QtCore/QExplicitlySharedDataPointer> +#include <QtCore/QMultiHash> #include <optional> @@ -19,8 +18,8 @@ class ApiExtractorResultData; struct InstantiatedSmartPointer { - const AbstractMetaClass *smartPointer = nullptr; // Template class - const AbstractMetaClass *specialized = nullptr; // Specialized for type + AbstractMetaClassCPtr smartPointer; // Template class + AbstractMetaClassCPtr specialized; // Specialized for type AbstractMetaType type; }; @@ -31,11 +30,10 @@ class ApiExtractorResult { public: ApiExtractorResult(); - explicit ApiExtractorResult(ApiExtractorResultData *data); ApiExtractorResult(const ApiExtractorResult &); ApiExtractorResult &operator=(const ApiExtractorResult &); - ApiExtractorResult(ApiExtractorResult &&); - ApiExtractorResult &operator=(ApiExtractorResult &&); + ApiExtractorResult(ApiExtractorResult &&) noexcept; + ApiExtractorResult &operator=(ApiExtractorResult &&) noexcept; ~ApiExtractorResult(); const AbstractMetaEnumList &globalEnums() const; @@ -45,23 +43,39 @@ public: const AbstractMetaTypeList &instantiatedContainers() const; const InstantiatedSmartPointers &instantiatedSmartPointers() const; + std::optional<InstantiatedSmartPointer> + findSmartPointerInstantiation(const SmartPointerTypeEntryCPtr &pointer, + const TypeEntryCPtr &pointee) const; + + const QMultiHash<QString, QString> &typedefTargetToName() const; // Query functions for the generators - std::optional<AbstractMetaEnum> findAbstractMetaEnum(const TypeEntry* typeEntry) const; + std::optional<AbstractMetaEnum> + findAbstractMetaEnum(TypeEntryCPtr typeEntry) const; /// Retrieves a list of constructors used in implicit conversions /// available on the given type. The TypeEntry must be a value-type /// or else it will return an empty list. /// \param type a TypeEntry that is expected to be a value-type /// \return a list of constructors that could be used as implicit converters - AbstractMetaFunctionCList implicitConversions(const TypeEntry *type) const; + AbstractMetaFunctionCList implicitConversions(const TypeEntryCPtr &type) const; AbstractMetaFunctionCList implicitConversions(const AbstractMetaType &metaType) const; ApiExtractorFlags flags() const; void setFlags(ApiExtractorFlags f); private: - QExplicitlySharedDataPointer<ApiExtractorResultData> d; + AbstractMetaClassCList m_metaClasses; + AbstractMetaClassCList m_smartPointers; + AbstractMetaFunctionCList m_globalFunctions; + AbstractMetaEnumList m_globalEnums; + AbstractMetaTypeList m_instantiatedContainers; + InstantiatedSmartPointers m_instantiatedSmartPointers; + QHash<TypeEntryCPtr, AbstractMetaEnum> m_enums; + QMultiHash<QString, QString> m_typedefTargetToName; + ApiExtractorFlags m_flags; + + friend class ApiExtractor; }; #endif // APIEXTRACTORRESULT_H diff --git a/sources/shiboken6/ApiExtractor/apiextractorresultdata_p.h b/sources/shiboken6/ApiExtractor/apiextractorresultdata_p.h deleted file mode 100644 index 2750b0c37..000000000 --- a/sources/shiboken6/ApiExtractor/apiextractorresultdata_p.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#ifndef APIEXTRACTORRESULTDATA_P_H -#define APIEXTRACTORRESULTDATA_P_H - -#include "apiextractorresult.h" - -#include <QtCore/QHash> -#include <QtCore/QSharedData> - -class ApiExtractorResultData : public QSharedData -{ -public: - ApiExtractorResultData(); - ~ApiExtractorResultData(); - - AbstractMetaClassCList m_metaClasses; - AbstractMetaClassCList m_templates; // not exposed, just for ownership - AbstractMetaClassCList m_smartPointers; - AbstractMetaFunctionCList m_globalFunctions; - AbstractMetaEnumList m_globalEnums; - AbstractMetaTypeList m_instantiatedContainers; - InstantiatedSmartPointers m_instantiatedSmartPointers; - QHash<const TypeEntry *, AbstractMetaEnum> m_enums; - QList<const TypeEntry *> m_synthesizedTypeEntries; // not exposed, just for ownership - ApiExtractorFlags m_flags; -}; - -#endif // APIEXTRACTORRESULTDATA_P_H diff --git a/sources/shiboken6/ApiExtractor/arraytypeentry.h b/sources/shiboken6/ApiExtractor/arraytypeentry.h index d520fa0b3..5b9bb191e 100644 --- a/sources/shiboken6/ApiExtractor/arraytypeentry.h +++ b/sources/shiboken6/ApiExtractor/arraytypeentry.h @@ -11,11 +11,11 @@ class ArrayTypeEntryPrivate; class ArrayTypeEntry : public TypeEntry { public: - explicit ArrayTypeEntry(const TypeEntry *nested_type, const QVersionNumber &vr, - const TypeEntry *parent); + explicit ArrayTypeEntry(const TypeEntryCPtr &nested_type, const QVersionNumber &vr, + const TypeEntryCPtr &parent); - void setNestedTypeEntry(TypeEntry *nested); - const TypeEntry *nestedTypeEntry() const; + void setNestedTypeEntry(const TypeEntryPtr &nested); + TypeEntryCPtr nestedTypeEntry() const; TypeEntry *clone() const override; diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp index bc27240df..31e7efb05 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp @@ -4,6 +4,7 @@ #include "clangbuilder.h" #include "compilersupport.h" #include "clangutils.h" +#include "clangdebugutils.h" #include <codemodel.h> #include <reporthandler.h> @@ -25,9 +26,6 @@ using namespace Qt::StringLiterals; namespace clang { -static inline QString colonColon() { return QStringLiteral("::"); } -static inline QString templateBrackets() { return QStringLiteral("<>"); } - static inline bool isClassCursor(const CXCursor &c) { return c.kind == CXCursor_ClassDecl || c.kind == CXCursor_StructDecl @@ -48,7 +46,7 @@ static inline bool withinClassDeclaration(const CXCursor &cursor) static QString fixTypeName(QString t) { // Fix "Foo &" -> "Foo&", similarly "Bar **" -> "Bar**" - int pos = t.size() - 1; + auto pos = t.size() - 1; for (; pos >= 0 && (t.at(pos) == u'&' || t.at(pos) == u'*'); --pos) {} if (pos > 0 && t.at(pos) == u' ') t.remove(pos, 1); @@ -63,7 +61,7 @@ static bool insertTemplateParameterIntoClassName(const QString &parmName, QStrin if (Q_UNLIKELY(!name->endsWith(u'>'))) return false; const bool needsComma = name->at(name->size() - 2) != u'<'; - const int insertionPos = name->size() - 1; + const auto insertionPos = name->size() - 1; name->insert(insertionPos, parmName); if (needsComma) name->insert(insertionPos, u','); @@ -115,8 +113,17 @@ static bool isSigned(CXTypeKind kind) class BuilderPrivate { public: + Q_DISABLE_COPY_MOVE(BuilderPrivate) + + enum class SpecialSystemHeader { + None, + Types, + OpenGL, + WhiteListed, + WhiteListedPath + }; + using CursorClassHash = QHash<CXCursor, ClassModelItem>; - using CursorTypedefHash = QHash<CXCursor, TypeDefModelItem>; using TypeInfoHash = QHash<CXType, TypeInfo>; explicit BuilderPrivate(BaseVisitor *bv) : m_baseVisitor(bv), m_model(new CodeModel) @@ -182,10 +189,9 @@ public: std::pair<QString, ClassModelItem> getBaseClass(CXType type) const; void addBaseClass(const CXCursor &cursor); - template <class Item> - void qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer<Item> &item) const; - + SpecialSystemHeader specialSystemHeader(const QString &fileName) const; bool visitHeader(const QString &fileName) const; + static const char *specialSystemHeaderReason(SpecialSystemHeader sh); void setFileName(const CXCursor &cursor, _CodeModelItem *item); @@ -198,7 +204,6 @@ public: // classes can be correctly parented in case of forward-declared inner classes // (QMetaObject::Connection) CursorClassHash m_cursorClassHash; - CursorTypedefHash m_cursorTypedefHash; mutable TypeInfoHash m_typeInfoHash; // Cache type information mutable QHash<QString, TemplateTypeAliasModelItem> m_templateTypeAliases; @@ -209,21 +214,22 @@ public: ArgumentModelItem m_currentArgument; VariableModelItem m_currentField; TemplateTypeAliasModelItem m_currentTemplateTypeAlias; - QStringList m_systemIncludes; // files, like "memory" - QStringList m_systemIncludePaths; // paths, like "/usr/include/Qt/" + QStringList m_forceProcessSystemIncludes; // files, like "memory" + QStringList m_forceProcessSystemIncludePaths; // paths, like "/usr/include/Qt/" QString m_usingTypeRef; // Base classes in "using Base::member;" bool m_withinUsingDeclaration = false; int m_anonymousEnumCount = 0; CodeModel::FunctionType m_currentFunctionType = CodeModel::Normal; bool m_withinFriendDecl = false; + mutable QHash<QString, SpecialSystemHeader> m_systemHeaders; }; bool BuilderPrivate::addClass(const CXCursor &cursor, CodeModel::ClassType t) { QString className = getCursorSpelling(cursor); m_currentClass.reset(new _ClassModelItem(m_model, className)); - setFileName(cursor, m_currentClass.data()); + setFileName(cursor, m_currentClass.get()); m_currentClass->setClassType(t); // Some inner class? Note that it does not need to be (lexically) contained in a // class since it is possible to forward declare an inner class: @@ -266,7 +272,7 @@ static QString msgCannotDetermineException(const std::string_view &snippetV) const qsizetype length = qsizetype(truncate ? newLine : snippetV.size()); QString snippet = QString::fromUtf8(snippetV.data(), length); if (truncate) - snippet += QStringLiteral("..."); + snippet += "..."_L1; return u"Cannot determine exception specification: \""_s + snippet + u'"'; } @@ -327,9 +333,11 @@ FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor, // Apply type fixes to "operator X &" -> "operator X&" if (name.startsWith(u"operator ")) name = fixTypeName(name); - FunctionModelItem result(new _FunctionModelItem(m_model, name)); - setFileName(cursor, result.data()); - result->setType(createTypeInfo(clang_getCursorResultType(cursor))); + auto result = std::make_shared<_FunctionModelItem>(m_model, name); + setFileName(cursor, result.get()); + const auto type = clang_getCursorResultType(cursor); + result->setType(createTypeInfo(type)); + result->setScopeResolution(hasScopeResolution(type)); result->setFunctionType(t); result->setScope(m_scope); result->setStatic(clang_Cursor_getStorageClass(cursor) == CX_SC_Static); @@ -338,7 +346,7 @@ FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor, case CXAvailability_Available: break; case CXAvailability_Deprecated: - result->setDeprecated(true); + result->setAttribute(FunctionAttribute::Deprecated); break; case CXAvailability_NotAvailable: // "Foo(const Foo&) = delete;" result->setDeleted(true); @@ -381,9 +389,9 @@ FunctionModelItem BuilderPrivate::createMemberFunction(const CXCursor &cursor, auto result = createFunction(cursor, functionType, isTemplateCode); result->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor))); result->setConstant(clang_CXXMethod_isConst(cursor) != 0); - result->setStatic(clang_CXXMethod_isStatic(cursor) != 0); - result->setVirtual(clang_CXXMethod_isVirtual(cursor) != 0); - result->setAbstract(clang_CXXMethod_isPureVirtual(cursor) != 0); + result->setAttribute(FunctionAttribute::Static, clang_CXXMethod_isStatic(cursor) != 0); + result->setAttribute(FunctionAttribute::Virtual, clang_CXXMethod_isVirtual(cursor) != 0); + result->setAttribute(FunctionAttribute::Abstract, clang_CXXMethod_isPureVirtual(cursor) != 0); return result; } @@ -399,13 +407,14 @@ void BuilderPrivate::qualifyConstructor(const CXCursor &cursor) && m_currentFunction->arguments().size() == 1 && clang_CXXConstructor_isCopyConstructor(cursor) == 0 && clang_CXXConstructor_isMoveConstructor(cursor) == 0) { - m_currentFunction->setExplicit(clang_CXXConstructor_isConvertingConstructor(cursor) == 0); + m_currentFunction->setAttribute(FunctionAttribute::Explicit, + clang_CXXConstructor_isConvertingConstructor(cursor) == 0); } } TemplateParameterModelItem BuilderPrivate::createTemplateParameter(const CXCursor &cursor) const { - return TemplateParameterModelItem(new _TemplateParameterModelItem(m_model, getCursorSpelling(cursor))); + return std::make_shared<_TemplateParameterModelItem>(m_model, getCursorSpelling(cursor)); } TemplateParameterModelItem BuilderPrivate::createNonTypeTemplateParameter(const CXCursor &cursor) const @@ -418,11 +427,12 @@ TemplateParameterModelItem BuilderPrivate::createNonTypeTemplateParameter(const // CXCursor_VarDecl, CXCursor_FieldDecl cursors void BuilderPrivate::addField(const CXCursor &cursor) { - VariableModelItem field(new _VariableModelItem(m_model, getCursorSpelling(cursor))); + auto field = std::make_shared<_VariableModelItem>(m_model, getCursorSpelling(cursor)); field->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor))); field->setScope(m_scope); field->setType(createTypeInfo(cursor)); field->setMutable(clang_CXXField_isMutable(cursor) != 0); + setFileName(cursor, field.get()); m_currentField = field; m_scopeStack.back()->addVariable(field); } @@ -438,7 +448,7 @@ static QStringList qualifiedName(const QString &t) end = t.size(); int lastPos = 0; while (true) { - const int nextPos = t.indexOf(colonColon(), lastPos); + const int nextPos = t.indexOf(u"::"_s, lastPos); if (nextPos < 0 || nextPos >= end) break; result.append(t.mid(lastPos, nextPos - lastPos)); @@ -502,7 +512,7 @@ void BuilderPrivate::addTemplateInstantiations(const CXType &type, && !t->instantiations().isEmpty(); if (!parsed) t->setInstantiations({}); - const QPair<int, int> pos = parsed + const auto pos = parsed ? parseTemplateArgumentList(*typeName, dummyTemplateArgumentHandler) : t->parseTemplateArgumentList(*typeName); if (pos.first != -1 && pos.second != -1 && pos.second > pos.first) @@ -556,7 +566,7 @@ TypeInfo BuilderPrivate::createTypeInfoUncached(const CXType &type, typeInfo.setConstant(clang_isConstQualifiedType(nestedType) != 0); typeInfo.setVolatile(clang_isVolatileQualifiedType(nestedType) != 0); - QString typeName = getTypeName(nestedType); + QString typeName = getResolvedTypeName(nestedType); while (TypeInfo::stripLeadingConst(&typeName) || TypeInfo::stripLeadingVolatile(&typeName)) { } @@ -566,14 +576,14 @@ TypeInfo BuilderPrivate::createTypeInfoUncached(const CXType &type, // the typedef source is named "type-parameter-0-0". Convert it back to the // template parameter name. The CXTypes are the same for all templates and // must not be cached. - if (!m_currentClass.isNull() && typeName.startsWith(u"type-parameter-0-")) { + if (m_currentClass && typeName.startsWith(u"type-parameter-0-")) { if (cacheable != nullptr) *cacheable = false; bool ok; const int n = QStringView{typeName}.mid(17).toInt(&ok); if (ok) { auto currentTemplate = currentTemplateClass(); - if (!currentTemplate.isNull() && n < currentTemplate->templateParameters().size()) + if (currentTemplate && n < currentTemplate->templateParameters().size()) typeName = currentTemplate->templateParameters().at(n)->name(); } } @@ -604,19 +614,18 @@ TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const void BuilderPrivate::addTypeDef(const CXCursor &cursor, const CXType &cxType) { const QString target = getCursorSpelling(cursor); - TypeDefModelItem item(new _TypeDefModelItem(m_model, target)); - setFileName(cursor, item.data()); + auto item = std::make_shared<_TypeDefModelItem>(m_model, target); + setFileName(cursor, item.get()); item->setType(createTypeInfo(cxType)); item->setScope(m_scope); m_scopeStack.back()->addTypeDef(item); - m_cursorTypedefHash.insert(cursor, item); } ClassModelItem BuilderPrivate::currentTemplateClass() const { - for (int i = m_scopeStack.size() - 1; i >= 0; --i) { - auto klass = qSharedPointerDynamicCast<_ClassModelItem>(m_scopeStack.at(i)); - if (!klass.isNull() && klass->isTemplate()) + for (auto i = m_scopeStack.size() - 1; i >= 0; --i) { + auto klass = std::dynamic_pointer_cast<_ClassModelItem>(m_scopeStack.at(i)); + if (klass && klass->isTemplate()) return klass; } return {}; @@ -626,7 +635,7 @@ void BuilderPrivate::startTemplateTypeAlias(const CXCursor &cursor) { const QString target = getCursorSpelling(cursor); m_currentTemplateTypeAlias.reset(new _TemplateTypeAliasModelItem(m_model, target)); - setFileName(cursor, m_currentTemplateTypeAlias.data()); + setFileName(cursor, m_currentTemplateTypeAlias.get()); m_currentTemplateTypeAlias->setScope(m_scope); } @@ -651,11 +660,17 @@ QString BuilderPrivate::cursorValueExpression(BaseVisitor *bv, const CXCursor &c if (equalSign == std::string::npos) return QString(); ++equalSign; - return QString::fromLocal8Bit(snippet.data() + equalSign, - qsizetype(snippet.size() - equalSign)).trimmed(); + QString result = QString::fromLocal8Bit(snippet.data() + equalSign, + qsizetype(snippet.size() - equalSign)); + // Fix a default expression as read from code. Simplify white space + result.remove(u'\r'); + return result.contains(u'"') ? result.trimmed() : result.simplified(); } // Resolve a type (loop over aliases/typedefs), for example for base classes +// Note: TypeAliasTemplateDecl ("using QVector<T>=QList<T>") is automatically +// resolved by clang_getTypeDeclaration(), but it stops at +// TypeAliasDecl / TypedefDecl. struct TypeDeclaration { @@ -663,17 +678,21 @@ struct TypeDeclaration CXCursor declaration; }; -static TypeDeclaration resolveType(CXType type) +static inline bool isTypeAliasDecl(const CXCursor &cursor) +{ + const auto kind = clang_getCursorKind(cursor); + return kind == CXCursor_TypeAliasDecl || kind == CXCursor_TypedefDecl; +} + +static TypeDeclaration resolveBaseClassType(CXType type) { CXCursor decl = clang_getTypeDeclaration(type); - if (type.kind != CXType_Unexposed) { - while (true) { - auto kind = clang_getCursorKind(decl); - if (kind != CXCursor_TypeAliasDecl && kind != CXCursor_TypedefDecl) - break; - type = clang_getTypedefDeclUnderlyingType(decl); - decl = clang_getTypeDeclaration(type); - } + auto resolvedType = clang_getCursorType(decl); + if (resolvedType.kind != CXType_Invalid && resolvedType.kind != type.kind) + type = resolvedType; + while (isTypeAliasDecl(decl)) { + type = clang_getTypedefDeclUnderlyingType(decl); + decl = clang_getTypeDeclaration(type); } return {type, decl}; } @@ -682,21 +701,11 @@ static TypeDeclaration resolveType(CXType type) // where the cursor spelling has "struct baseClass". std::pair<QString, ClassModelItem> BuilderPrivate::getBaseClass(CXType type) const { - const auto decl = resolveType(type); + const auto decl = resolveBaseClassType(type); // Note: spelling has "struct baseClass", use type - QString baseClassName; - if (decl.type.kind == CXType_Unexposed) { - // The type is unexposed when the base class is a template type alias: - // "class QItemSelection : public QList<X>" where QList is aliased to QVector. - // Try to resolve via code model. - TypeInfo info = createTypeInfo(decl.type); - auto parentScope = m_scopeStack.at(m_scopeStack.size() - 2); // Current is class. - auto resolved = TypeInfo::resolveType(info, parentScope); - if (resolved != info) - baseClassName = resolved.toString(); - } - if (baseClassName.isEmpty()) - baseClassName = getTypeName(decl.type); + QString baseClassName = getTypeName(decl.type); + if (baseClassName.startsWith(u"std::")) // Simplify "std::" types + baseClassName = createTypeInfo(decl.type).toString(); auto it = m_cursorClassHash.constFind(decl.declaration); // Not found: Set unqualified name. This happens in cases like @@ -717,11 +726,11 @@ std::pair<QString, ClassModelItem> BuilderPrivate::getBaseClass(CXType type) con // "std::vector<T>"). const QStringList &baseScope = it.value()->scope(); if (!baseScope.isEmpty()) { - const int lastSep = baseClassName.lastIndexOf(colonColon()); + const int lastSep = baseClassName.lastIndexOf(u"::"_s); if (lastSep >= 0) - baseClassName.remove(0, lastSep + colonColon().size()); - baseClassName.prepend(colonColon()); - baseClassName.prepend(baseScope.join(colonColon())); + baseClassName.remove(0, lastSep + u"::"_s.size()); + baseClassName.prepend(u"::"_s); + baseClassName.prepend(baseScope.join(u"::"_s)); } return {baseClassName, it.value()}; } @@ -735,37 +744,6 @@ void BuilderPrivate::addBaseClass(const CXCursor &cursor) m_currentClass->addBaseClass({baseClass.first, baseClass.second, access}); } -static inline CXCursor definitionFromTypeRef(const CXCursor &typeRefCursor) -{ - Q_ASSERT(typeRefCursor.kind == CXCursor_TypeRef); - return clang_getTypeDeclaration(clang_getCursorType(typeRefCursor)); -} - -// Qualify function arguments or fields that are typedef'ed from another scope: -// enum ConversionFlag {}; -// typedef QFlags<ConversionFlag> ConversionFlags; -// class QTextCodec { -// enum ConversionFlag {}; -// typedef QFlags<ConversionFlag> ConversionFlags; -// struct ConverterState { -// explicit ConverterState(ConversionFlags); -// ^^ qualify to QTextCodec::ConversionFlags -// ConversionFlags m_flags; -// ^^ ditto - -template <class Item> // ArgumentModelItem, VariableModelItem -void BuilderPrivate::qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer<Item> &item) const -{ - TypeInfo type = item->type(); - if (type.qualifiedName().size() == 1) { // item's type is unqualified. - const auto it = m_cursorTypedefHash.constFind(definitionFromTypeRef(typeRefCursor)); - if (it != m_cursorTypedefHash.constEnd() && !it.value()->scope().isEmpty()) { - type.setQualifiedName(it.value()->scope() + type.qualifiedName()); - item->setType(type); - } - } -} - void BuilderPrivate::setFileName(const CXCursor &cursor, _CodeModelItem *item) { const SourceRange range = getCursorRange(cursor); @@ -799,14 +777,48 @@ static QString baseName(QString path) return path; } +const char * BuilderPrivate::specialSystemHeaderReason(BuilderPrivate::SpecialSystemHeader sh) +{ + static const QHash<SpecialSystemHeader, const char *> mapping { + {SpecialSystemHeader::OpenGL, "OpenGL"}, + {SpecialSystemHeader::Types, "types"}, + {SpecialSystemHeader::WhiteListed, "white listed"}, + {SpecialSystemHeader::WhiteListedPath, "white listed path"} + }; + return mapping.value(sh, ""); +} + bool BuilderPrivate::visitHeader(const QString &fileName) const { + auto it = m_systemHeaders.find(fileName); + if (it == m_systemHeaders.end()) { + it = m_systemHeaders.insert(fileName, specialSystemHeader(fileName)); + if (ReportHandler::isDebug(ReportHandler::MediumDebug)) { + const QString &name = QDir::toNativeSeparators(fileName); + if (it.value() == SpecialSystemHeader::None) { + qCInfo(lcShiboken, "Skipping system header %s", qPrintable(name)); + } else { + qCInfo(lcShiboken, "Parsing system header %s (%s)", + qPrintable(name), specialSystemHeaderReason(it.value())); + } + } + } + return it.value() != SpecialSystemHeader::None; +} + +BuilderPrivate::SpecialSystemHeader + BuilderPrivate::specialSystemHeader(const QString &fileName) const +{ // Resolve OpenGL typedefs although the header is considered a system header. const QString baseName = clang::baseName(fileName); if (baseName == u"gl.h" + || baseName == u"gl2.h" + || baseName == u"gl3.h" + || baseName == u"gl31.h" + || baseName == u"gl32.h" || baseName == u"stdint.h" // Windows: int32_t, uint32_t - || baseName == u"stddef.h") { // size_t - return true; + || baseName == u"stddef.h") { // size_t` + return SpecialSystemHeader::OpenGL; } switch (clang::platform()) { @@ -815,32 +827,38 @@ bool BuilderPrivate::visitHeader(const QString &fileName) const || baseName == u"types.h" || baseName == u"stdint-intn.h" // int32_t || baseName == u"stdint-uintn.h") { // uint32_t - return true; + return SpecialSystemHeader::Types; } break; case Platform::macOS: // Parse the following system headers to get the correct typdefs for types like // int32_t, which are used in the macOS implementation of OpenGL framework. + // They are installed under /Applications/Xcode.app/Contents/Developer/Platforms... if (baseName == u"gltypes.h" - || fileName.startsWith(u"/usr/include/_types") - || fileName.startsWith(u"/usr/include/_types") - || fileName.startsWith(u"/usr/include/sys/_types")) { - return true; + || fileName.contains(u"/usr/include/_types") + || fileName.contains(u"/usr/include/sys/_types")) { + return SpecialSystemHeader::Types; } break; default: break; } - for (const auto &systemInclude : m_systemIncludes) { - if (systemInclude == baseName) - return true; - } - for (const auto &systemIncludePath : m_systemIncludePaths) { - if (fileName.startsWith(systemIncludePath)) - return true; + // When building against system Qt (as it happens with yocto / Boot2Qt), the Qt headers are + // considered system headers by clang_Location_isInSystemHeader, and shiboken will not + // process them. We need to explicitly process them by checking against the list of + // include paths that were passed to shiboken's --force-process-system-include-paths option + // or specified via the <system-include> xml tag. + if (m_forceProcessSystemIncludes.contains(baseName)) + return SpecialSystemHeader::WhiteListed; + + if (std::any_of(m_forceProcessSystemIncludePaths.cbegin(), + m_forceProcessSystemIncludePaths.cend(), + [fileName](const QString &p) { return fileName.startsWith(p); })) { + return SpecialSystemHeader::WhiteListedPath; } - return false; + + return SpecialSystemHeader::None; } bool Builder::visitLocation(const QString &fileName, LocationType locationType) const @@ -848,13 +866,14 @@ bool Builder::visitLocation(const QString &fileName, LocationType locationType) return locationType != LocationType::System || d->visitHeader(fileName); } -void Builder::setSystemIncludes(const QStringList &systemIncludes) +void Builder::setForceProcessSystemIncludes(const QStringList &systemIncludes) { for (const auto &i : systemIncludes) { - if (i.endsWith(u'/')) - d->m_systemIncludePaths.append(i); + QFileInfo fi(i); + if (fi.exists() && fi.isDir()) + d->m_forceProcessSystemIncludePaths.append(i); else - d->m_systemIncludes.append(i); + d->m_forceProcessSystemIncludes.append(i); } } @@ -863,7 +882,7 @@ FileModelItem Builder::dom() const Q_ASSERT(!d->m_scopeStack.isEmpty()); auto rootScope = d->m_scopeStack.constFirst(); rootScope->purgeClassDeclarations(); - return qSharedPointerDynamicCast<_FileModelItem>(rootScope); + return std::dynamic_pointer_cast<_FileModelItem>(rootScope); } static QString msgOutOfOrder(const CXCursor &cursor, const char *expectedScope) @@ -897,6 +916,8 @@ static NamespaceType namespaceType(const CXCursor &cursor) static QString enumType(const CXCursor &cursor) { QString name = getCursorSpelling(cursor); // "enum Foo { v1, v2 };" + if (name.contains(u"unnamed enum")) // Clang 16.0 + return {}; if (name.isEmpty()) { // PYSIDE-1228: For "typedef enum { v1, v2 } Foo;", type will return // "Foo" as expected. Care must be taken to exclude real anonymous enums. @@ -926,7 +947,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) } break; case CXCursor_CXXBaseSpecifier: - if (d->m_currentClass.isNull()) { + if (!d->m_currentClass) { const Diagnostic d(msgOutOfOrder(cursor, "class"), cursor, CXDiagnostic_Error); qWarning() << d; appendDiagnostic(d); @@ -948,15 +969,15 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) || !d->addClass(cursor, CodeModel::Class)) { return Skip; } - d->m_currentClass->setName(d->m_currentClass->name() + templateBrackets()); - d->m_scope.back() += templateBrackets(); + d->m_currentClass->setName(d->m_currentClass->name() + "<>"_L1); + d->m_scope.back() += "<>"_L1; break; case CXCursor_EnumDecl: { QString name = enumType(cursor); EnumKind kind = CEnum; if (name.isEmpty()) { kind = AnonymousEnum; - name = QStringLiteral("enum_") + QString::number(++d->m_anonymousEnumCount); + name = "enum_"_L1 + QString::number(++d->m_anonymousEnumCount); #if !CLANG_NO_ENUMDECL_ISSCOPED } else if (clang_EnumDecl_isScoped(cursor) != 0) { #else @@ -965,17 +986,21 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) kind = EnumClass; } d->m_currentEnum.reset(new _EnumModelItem(d->m_model, name)); - d->setFileName(cursor, d->m_currentEnum.data()); + d->setFileName(cursor, d->m_currentEnum.get()); d->m_currentEnum->setScope(d->m_scope); d->m_currentEnum->setEnumKind(kind); - d->m_currentEnum->setSigned(isSigned(clang_getEnumDeclIntegerType(cursor).kind)); - if (!qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back()).isNull()) + if (clang_getCursorAvailability(cursor) == CXAvailability_Deprecated) + d->m_currentEnum->setDeprecated(true); + const auto enumType = fullyResolveType(clang_getEnumDeclIntegerType(cursor)); + d->m_currentEnum->setSigned(isSigned(enumType.kind)); + d->m_currentEnum->setUnderlyingType(getTypeName(enumType)); + if (std::dynamic_pointer_cast<_ClassModelItem>(d->m_scopeStack.back())) d->m_currentEnum->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor))); } break; case CXCursor_EnumConstantDecl: { const QString name = getCursorSpelling(cursor); - if (d->m_currentEnum.isNull()) { + if (!d->m_currentEnum) { const Diagnostic d(msgOutOfOrder(cursor, "enum"), cursor, CXDiagnostic_Error); qWarning() << d; appendDiagnostic(d); @@ -986,9 +1011,11 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) enumValue.setValue(clang_getEnumConstantDeclValue(cursor)); else enumValue.setUnsignedValue(clang_getEnumConstantDeclUnsignedValue(cursor)); - EnumeratorModelItem enumConstant(new _EnumeratorModelItem(d->m_model, name)); + auto enumConstant = std::make_shared<_EnumeratorModelItem>(d->m_model, name); enumConstant->setStringValue(d->cursorValueExpression(this, cursor)); enumConstant->setValue(enumValue); + if (clang_getCursorAvailability(cursor) == CXAvailability_Deprecated) + enumConstant->setDeprecated(true); d->m_currentEnum->addEnumerator(enumConstant); } break; @@ -1032,6 +1059,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) } } d->m_currentFunction = d->createFunction(cursor, CodeModel::Normal, true); + d->setFileName(cursor, d->m_currentFunction.get()); d->m_scopeStack.back()->addFunction(d->m_currentFunction); break; case CXCursor_FunctionDecl: @@ -1039,7 +1067,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) // operators). Note: CXTranslationUnit_SkipFunctionBodies must be off for // clang_isCursorDefinition() to work here. if (!d->m_withinFriendDecl || clang_isCursorDefinition(cursor) != 0) { - int scope = d->m_scopeStack.size() - 1; // enclosing class + auto scope = d->m_scopeStack.size() - 1; // enclosing class if (d->m_withinFriendDecl) { // Friend declaration: go back to namespace or file scope. for (--scope; d->m_scopeStack.at(scope)->kind() == _CodeModelItem::Kind_Class; --scope) { @@ -1055,8 +1083,8 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) if (type == NamespaceType::Anonymous) return Skip; const QString name = getCursorSpelling(cursor); - const NamespaceModelItem parentNamespaceItem = qSharedPointerDynamicCast<_NamespaceModelItem>(d->m_scopeStack.back()); - if (parentNamespaceItem.isNull()) { + const auto parentNamespaceItem = std::dynamic_pointer_cast<_NamespaceModelItem>(d->m_scopeStack.back()); + if (!parentNamespaceItem) { const QString message = msgOutOfOrder(cursor, "namespace") + u" (current scope: "_s + d->m_scopeStack.back()->name() + u')'; const Diagnostic d(message, cursor, CXDiagnostic_Error); @@ -1068,7 +1096,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) // in subsequent modules. NamespaceModelItem namespaceItem = parentNamespaceItem->findNamespace(name); namespaceItem.reset(new _NamespaceModelItem(d->m_model, name)); - d->setFileName(cursor, namespaceItem.data()); + d->setFileName(cursor, namespaceItem.get()); namespaceItem->setScope(d->m_scope); namespaceItem->setType(type); parentNamespaceItem->addNamespace(namespaceItem); @@ -1078,10 +1106,12 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) case CXCursor_ParmDecl: // Skip in case of nested CXCursor_ParmDecls in case one parameter is a function pointer // and function pointer typedefs. - if (d->m_currentArgument.isNull() && !d->m_currentFunction.isNull()) { + if (!d->m_currentArgument && d->m_currentFunction) { const QString name = getCursorSpelling(cursor); d->m_currentArgument.reset(new _ArgumentModelItem(d->m_model, name)); - d->m_currentArgument->setType(d->createTypeInfo(cursor)); + const auto type = clang_getCursorType(cursor); + d->m_currentArgument->setScopeResolution(hasScopeResolution(type)); + d->m_currentArgument->setType(d->createTypeInfo(type)); d->m_currentFunction->addArgument(d->m_currentArgument); QString defaultValueExpression = d->cursorValueExpression(this, cursor); if (!defaultValueExpression.isEmpty()) { @@ -1097,16 +1127,16 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) const TemplateParameterModelItem tItem = cursor.kind == CXCursor_TemplateTemplateParameter ? d->createTemplateParameter(cursor) : d->createNonTypeTemplateParameter(cursor); // Apply to function/member template? - if (!d->m_currentFunction.isNull()) { + if (d->m_currentFunction) { d->m_currentFunction->setTemplateParameters(d->m_currentFunction->templateParameters() << tItem); - } else if (!d->m_currentTemplateTypeAlias.isNull()) { + } else if (d->m_currentTemplateTypeAlias) { d->m_currentTemplateTypeAlias->addTemplateParameter(tItem); - } else if (!d->m_currentClass.isNull()) { // Apply to class + } else if (d->m_currentClass) { // Apply to class const QString &tplParmName = tItem->name(); if (Q_UNLIKELY(!insertTemplateParameterIntoClassName(tplParmName, d->m_currentClass) || !insertTemplateParameterIntoClassName(tplParmName, &d->m_scope.back()))) { - const QString message = QStringLiteral("Error inserting template parameter \"") + tplParmName - + QStringLiteral("\" into ") + d->m_currentClass->name(); + const QString message = "Error inserting template parameter \""_L1 + tplParmName + + "\" into "_L1 + d->m_currentClass->name(); const Diagnostic d(message, cursor, CXDiagnostic_Error); qWarning() << d; appendDiagnostic(d); @@ -1120,7 +1150,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) d->startTemplateTypeAlias(cursor); break; case CXCursor_TypeAliasDecl: // May contain nested CXCursor_TemplateTypeParameter - if (d->m_currentTemplateTypeAlias.isNull()) { + if (!d->m_currentTemplateTypeAlias) { const CXType type = clang_getCanonicalType(clang_getCursorType(cursor)); if (type.kind > CXType_Unexposed) d->addTypeDef(cursor, type); @@ -1148,31 +1178,23 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) d->m_usingTypeRef = getCursorSpelling(cursor); break; case CXCursor_TypeRef: - if (!d->m_currentFunction.isNull()) { - if (d->m_currentArgument.isNull()) - d->qualifyTypeDef(cursor, d->m_currentFunction); // return type - else - d->qualifyTypeDef(cursor, d->m_currentArgument); - } else if (!d->m_currentField.isNull()) { - d->qualifyTypeDef(cursor, d->m_currentField); - } else if (d->m_withinUsingDeclaration && d->m_usingTypeRef.isEmpty()) { + if (d->m_withinUsingDeclaration && d->m_usingTypeRef.isEmpty()) d->m_usingTypeRef = d->getBaseClass(clang_getCursorType(cursor)).first; - } break; case CXCursor_CXXFinalAttr: - if (!d->m_currentFunction.isNull()) - d->m_currentFunction->setFinal(true); - else if (!d->m_currentClass.isNull()) + if (d->m_currentFunction) + d->m_currentFunction->setAttribute(FunctionAttribute::Final); + else if (d->m_currentClass) d->m_currentClass->setFinal(true); break; case CXCursor_CXXOverrideAttr: - if (!d->m_currentFunction.isNull()) - d->m_currentFunction->setOverride(true); + if (d->m_currentFunction) + d->m_currentFunction->setAttribute(FunctionAttribute::Override); break; case CXCursor_StaticAssert: // Check for Q_PROPERTY() (see PySide6/global.h.in for an explanation // how it is defined, and qdoc). - if (clang_isDeclaration(cursor.kind) && !d->m_currentClass.isNull()) { + if (clang_isDeclaration(cursor.kind) && d->m_currentClass) { auto snippet = getCodeSnippet(cursor); const auto length = snippet.size(); if (length > 12 && *snippet.rbegin() == ')' @@ -1184,7 +1206,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) break; // UsingDeclaration: consists of a TypeRef (base) and OverloadedDeclRef (member name) case CXCursor_UsingDeclaration: - if (!d->m_currentClass.isNull()) + if (d->m_currentClass) d->m_withinUsingDeclaration = true; break; case CXCursor_OverloadedDeclRef: @@ -1212,51 +1234,51 @@ bool Builder::endToken(const CXCursor &cursor) case CXCursor_ClassTemplatePartialSpecialization: d->popScope(); // Continue in outer class after leaving inner class? - if (ClassModelItem lastClass = qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back())) + if (auto lastClass = std::dynamic_pointer_cast<_ClassModelItem>(d->m_scopeStack.back())) d->m_currentClass = lastClass; else - d->m_currentClass.clear(); + d->m_currentClass.reset(); d->m_currentFunctionType = CodeModel::Normal; break; case CXCursor_EnumDecl: - if (!d->m_currentEnum.isNull()) + if (d->m_currentEnum) d->m_scopeStack.back()->addEnum(d->m_currentEnum); - d->m_currentEnum.clear(); + d->m_currentEnum.reset(); break; case CXCursor_FriendDecl: d->m_withinFriendDecl = false; break; case CXCursor_VarDecl: case CXCursor_FieldDecl: - d->m_currentField.clear(); + d->m_currentField.reset(); break; case CXCursor_Constructor: d->qualifyConstructor(cursor); - if (!d->m_currentFunction.isNull()) { + if (d->m_currentFunction) { d->m_currentFunction->_determineType(); - d->m_currentFunction.clear(); + d->m_currentFunction.reset(); } break; case CXCursor_Destructor: case CXCursor_CXXMethod: case CXCursor_FunctionDecl: case CXCursor_FunctionTemplate: - if (!d->m_currentFunction.isNull()) { + if (d->m_currentFunction) { d->m_currentFunction->_determineType(); - d->m_currentFunction.clear(); + d->m_currentFunction.reset(); } break; case CXCursor_ConversionFunction: - if (!d->m_currentFunction.isNull()) { + if (d->m_currentFunction) { d->m_currentFunction->setFunctionType(CodeModel::ConversionOperator); - d->m_currentFunction.clear(); + d->m_currentFunction.reset(); } break; case CXCursor_Namespace: d->popScope(); break; case CXCursor_ParmDecl: - d->m_currentArgument.clear(); + d->m_currentArgument.reset(); break; case CXCursor_TypeAliasTemplateDecl: d->m_currentTemplateTypeAlias.reset(); diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.h b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.h index 56b6347d5..b2ec6d304 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.h +++ b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.h @@ -14,12 +14,12 @@ class BuilderPrivate; class Builder : public BaseVisitor { public: - Q_DISABLE_COPY(Builder) + Q_DISABLE_COPY_MOVE(Builder) Builder(); ~Builder(); - void setSystemIncludes(const QStringList &systemIncludes); + void setForceProcessSystemIncludes(const QStringList &systemIncludes); bool visitLocation(const QString &fileName, LocationType locationType) const override; diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.cpp index 93618cf0f..3c002da9c 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.cpp +++ b/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.cpp @@ -7,8 +7,6 @@ #include <QtCore/QDebug> #include <QtCore/QString> -#include <string.h> - #ifndef QT_NO_DEBUG_STREAM #ifdef Q_OS_WIN @@ -19,7 +17,7 @@ const char pathSep = '/'; static const char *baseName(const char *fileName) { - const char *b = strrchr(fileName, pathSep); + const char *b = std::strrchr(fileName, pathSep); return b ? b + 1 : fileName; } @@ -49,59 +47,99 @@ QDebug operator<<(QDebug s, CX_CXXAccessSpecifier ac) return s; } -QDebug operator<<(QDebug s, const CXType &t) +struct formatCXTypeName +{ + explicit formatCXTypeName(const CXType &type) : m_type(type) {} + + const CXType &m_type; +}; + +QDebug operator<<(QDebug debug, const formatCXTypeName &ft) { - CXString typeSpelling = clang_getTypeSpelling(t); - s << typeSpelling; + CXString typeSpelling = clang_getTypeSpelling(ft.m_type); + debug << typeSpelling; clang_disposeString(typeSpelling); - return s; + return debug; } -QDebug operator<<(QDebug s, const CXCursor &cursor) +QDebug operator<<(QDebug debug, const CXType &type) { - QDebugStateSaver saver(s); - s.nospace(); - s.noquote(); + QDebugStateSaver saver(debug); + debug.nospace(); + debug.noquote(); + debug << "CXType("; + if (type.kind == CXType_Invalid) { + debug << "invalid)"; + return debug; + } + + debug << type.kind; + switch (type.kind) { + case CXType_Unexposed: + debug << " [unexposed]"; + break; + case CXType_Elaborated: + debug << " [elaborated]"; + break; + default: + break; + } + debug << ", " << formatCXTypeName(type) << ')'; + return debug; +} + +QDebug operator<<(QDebug debug, const CXCursor &cursor) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + debug.noquote(); const CXCursorKind kind = clang_getCursorKind(cursor); - s << kind; - if (kind >= CXCursor_FirstInvalid && kind <= CXCursor_LastInvalid) - return s; + debug << "CXCursor("; + if (kind >= CXCursor_FirstInvalid && kind <= CXCursor_LastInvalid) { + debug << "invalid)"; + return debug; + } + + const QString cursorSpelling = clang::getCursorSpelling(cursor); + debug << '"' << cursorSpelling << '"'; + CXString cursorDisplay = clang_getCursorDisplayName(cursor); + if (const char *dpy = clang_getCString(cursorDisplay)) { + const QString display = QString::fromUtf8(dpy); + if (display != cursorSpelling) + debug << ", display=\"" << dpy << '"'; + } + clang_disposeString(cursorDisplay); + + debug << ", kind=" << kind; + const CXType type = clang_getCursorType(cursor); switch (kind) { case CXCursor_CXXAccessSpecifier: - s << ' ' << clang_getCXXAccessSpecifier(cursor); + debug << ", " << clang_getCXXAccessSpecifier(cursor); break; case CXCursor_CXXBaseSpecifier: - s << ", inherits=\"" << clang::getCursorSpelling(clang_getTypeDeclaration(type)) << '"'; + debug << ", inherits=\"" << clang::getCursorSpelling(clang_getTypeDeclaration(type)) << '"'; break; case CXCursor_CXXMethod: case CXCursor_FunctionDecl: case CXCursor_ConversionFunction: - s << ", result type=\"" << clang_getCursorResultType(cursor) << '"'; + debug << ", result type=\"" + << formatCXTypeName(clang_getCursorResultType(cursor)) << '"'; break; case CXCursor_TypedefDecl: - s << ", underlyingType=\"" << clang_getTypedefDeclUnderlyingType(cursor) << '"'; + debug << ", underlyingType=\"" + << formatCXTypeName(clang_getTypedefDeclUnderlyingType(cursor)) << '"'; break; default: break; } - if (type.kind != CXType_Invalid) - s << ", type=\"" << type << '"'; + debug << ", type=\"" << formatCXTypeName(type) << '"'; if (clang_Cursor_hasAttrs(cursor)) - s << ", [attrs]"; + debug << ", [attrs]"; - const QString cursorSpelling = clang::getCursorSpelling(cursor); - if (!cursorSpelling.isEmpty()) - s << ", spelling=\"" << cursorSpelling << '"'; - CXString cursorDisplay = clang_getCursorDisplayName(cursor); - if (const char *dpy = clang_getCString(cursorDisplay)) { - const QString display = QString::fromUtf8(dpy); - if (display != cursorSpelling) - s << ", display=\"" << dpy << '"'; - } - clang_disposeString(cursorDisplay); - return s; + debug << ')'; + return debug; } QDebug operator<<(QDebug s, const CXSourceLocation &location) diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.h b/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.h index 3a1b91e1a..7aac8a575 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.h +++ b/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.h @@ -4,7 +4,7 @@ #ifndef CLANGDEBUGUTILS_H #define CLANGDEBUGUTILS_H -#include <QtCore/QtGlobal> +#include <QtCore/qtclasshelpermacros.h> #include <clang-c/Index.h> diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp index 4549d62a0..6c0cf3ae2 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp +++ b/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp @@ -13,6 +13,8 @@ #include <QtCore/QScopedArrayPointer> #include <QtCore/QString> +using namespace Qt::StringLiterals; + namespace clang { QString SourceFileCache::getFileName(CXFile file) @@ -39,7 +41,7 @@ std::string_view SourceFileCache::getCodeSnippet(const CXCursor &cursor, if (range.first.file != range.second.file) { if (errorMessage) - *errorMessage = QStringLiteral("Range spans several files"); + *errorMessage = "Range spans several files"_L1; return std::string_view(empty, 0); } @@ -48,7 +50,7 @@ std::string_view SourceFileCache::getCodeSnippet(const CXCursor &cursor, const QString fileName = getFileName(range.first.file); if (fileName.isEmpty()) { if (errorMessage) - *errorMessage = QStringLiteral("Range has no file"); + *errorMessage = "Range has no file"_L1; return std::string_view(empty, 0); } QFile file(fileName); @@ -213,9 +215,9 @@ static QByteArray msgCreateTranslationUnit(const QByteArrayList &clangArgs, unsi { QByteArray result = "clang_parseTranslationUnit2(0x"; result += QByteArray::number(flags, 16); - const int count = clangArgs.size(); + const auto count = clangArgs.size(); result += ", cmd[" + QByteArray::number(count) + "]="; - for (int i = 0; i < count; ++i) { + for (qsizetype i = 0; i < count; ++i) { const QByteArray &arg = clangArgs.at(i); if (i) result += ' '; @@ -233,6 +235,7 @@ static QByteArray msgCreateTranslationUnit(const QByteArrayList &clangArgs, unsi static CXTranslationUnit createTranslationUnit(CXIndex index, const QByteArrayList &args, bool addCompilerSupportArguments, + LanguageLevel level, unsigned flags = 0) { // courtesy qdoc @@ -253,7 +256,7 @@ static CXTranslationUnit createTranslationUnit(CXIndex index, QByteArrayList clangArgs; if (addCompilerSupportArguments) { - clangArgs += emulatedCompilerOptions(); + clangArgs += emulatedCompilerOptions(level); clangArgs += defaultArgs; } clangArgs += detectVulkan(); @@ -278,7 +281,7 @@ static CXTranslationUnit createTranslationUnit(CXIndex index, */ bool parse(const QByteArrayList &clangArgs, bool addCompilerSupportArguments, - unsigned clangFlags, BaseVisitor &bv) + LanguageLevel level, unsigned clangFlags, BaseVisitor &bv) { CXIndex index = clang_createIndex(0 /* excludeDeclarationsFromPCH */, 1 /* displayDiagnostics */); @@ -289,7 +292,7 @@ bool parse(const QByteArrayList &clangArgs, bool addCompilerSupportArguments, CXTranslationUnit translationUnit = createTranslationUnit(index, clangArgs, addCompilerSupportArguments, - clangFlags); + level, clangFlags); if (!translationUnit) return false; @@ -308,7 +311,7 @@ bool parse(const QByteArrayList &clangArgs, bool addCompilerSupportArguments, debug.nospace(); debug << "Errors in " << QDir::toNativeSeparators(QFile::decodeName(clangArgs.constLast())) << ":\n"; - for (const Diagnostic &diagnostic : qAsConst(diagnostics)) + for (const Diagnostic &diagnostic : std::as_const(diagnostics)) debug << diagnostic << '\n'; } diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangparser.h b/sources/shiboken6/ApiExtractor/clangparser/clangparser.h index 3abbece24..22e0a50cd 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangparser.h +++ b/sources/shiboken6/ApiExtractor/clangparser/clangparser.h @@ -8,11 +8,13 @@ #include <QtCore/QByteArrayList> #include <QtCore/QHash> -#include <QtCore/QPair> #include <QtCore/QString> #include <QtCore/QList> #include <string_view> +#include <utility> + +enum class LanguageLevel; namespace clang { @@ -40,7 +42,7 @@ enum class LocationType }; class BaseVisitor { - Q_DISABLE_COPY(BaseVisitor) + Q_DISABLE_COPY_MOVE(BaseVisitor) public: using Diagnostics = QList<Diagnostic>; @@ -79,7 +81,7 @@ private: bool parse(const QByteArrayList &clangArgs, bool addCompilerSupportArguments, - unsigned clangFlags, BaseVisitor &ctx); + LanguageLevel level, unsigned clangFlags, BaseVisitor &ctx); } // namespace clang diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangutils.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangutils.cpp index 3d5b04fd2..1651e09ec 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangutils.cpp +++ b/sources/shiboken6/ApiExtractor/clangparser/clangutils.cpp @@ -8,38 +8,33 @@ #include <QtCore/QHashFunctions> #include <QtCore/QProcess> -bool operator==(const CXCursor &c1, const CXCursor &c2) +#include <string_view> + +bool operator==(const CXCursor &c1, const CXCursor &c2) noexcept { return c1.kind == c2.kind && c1.xdata == c2.xdata && std::equal(c1.data, c1.data + sizeof(c1.data) / sizeof(c1.data[0]), c2.data); } -size_t qHash(const CXCursor &c, size_t seed) +size_t qHash(const CXCursor &c, size_t seed) noexcept { - return qHash(c.kind) ^ qHash(c.xdata) ^ qHash(c.data[0]) - ^ qHash(c.data[1]) ^ qHash(c.data[2]) ^ seed; + return qHashMulti(seed, c.kind, c.xdata, c.data[0], c.data[1], c.data[2]); } -bool operator==(const CXType &t1, const CXType &t2) +bool operator==(const CXType &t1, const CXType &t2) noexcept { return t1.kind == t2.kind && t1.data[0] == t2.data[0] && t1.data[1] == t2.data[1]; } -size_t qHash(const CXType &ct, size_t seed) +size_t qHash(const CXType &ct, size_t seed) noexcept { - return size_t(ct.kind) ^ size_t(0xFFFFFFFF & quintptr(ct.data[0])) - ^ size_t(0xFFFFFFFF & quintptr(ct.data[1])) ^ seed; + return qHashMulti(seed, ct.kind, ct.data[0], ct.data[1]); } namespace clang { -bool SourceLocation::equals(const SourceLocation &rhs) const -{ - return file == rhs.file && offset == rhs.offset; -} - SourceLocation getExpansionLocation(const CXSourceLocation &location) { SourceLocation result; @@ -77,8 +72,8 @@ CXString getFileNameFromLocation(const CXSourceLocation &location) SourceRange getCursorRange(const CXCursor &cursor) { const CXSourceRange extent = clang_getCursorExtent(cursor); - return qMakePair(getExpansionLocation(clang_getRangeStart(extent)), - getExpansionLocation(clang_getRangeEnd(extent))); + return std::make_pair(getExpansionLocation(clang_getRangeStart(extent)), + getExpansionLocation(clang_getRangeEnd(extent))); } QString getCursorKindName(CXCursorKind cursorKind) @@ -105,6 +100,43 @@ QString getCursorDisplayName(const CXCursor &cursor) return result; } +static inline bool isBuiltinType(CXTypeKind kind) +{ + return kind >= CXType_FirstBuiltin && kind <= CXType_LastBuiltin; +} + +// Resolve elaborated types occurring with clang 16 +static CXType resolveElaboratedType(const CXType &type) +{ + if (!isBuiltinType(type.kind)) { + CXCursor decl = clang_getTypeDeclaration(type); + auto resolvedType = clang_getCursorType(decl); + if (resolvedType.kind != CXType_Invalid && resolvedType.kind != type.kind) + return resolvedType; + } + return type; +} + +// Resolve typedefs +static CXType resolveTypedef(const CXType &type) +{ + auto result = type; + while (result.kind == CXType_Typedef) { + auto decl = clang_getTypeDeclaration(result); + auto resolved = clang_getTypedefDeclUnderlyingType(decl); + if (resolved.kind == CXType_Invalid) + break; + result = resolved; + } + return result; +} + +// Fully resolve a type from elaborated & typedefs +CXType fullyResolveType(const CXType &type) +{ + return resolveTypedef(resolveElaboratedType(type)); +} + QString getTypeName(const CXType &type) { CXString typeSpelling = clang_getTypeSpelling(type); @@ -113,6 +145,23 @@ QString getTypeName(const CXType &type) return result; } +// Quick check for "::Type" +bool hasScopeResolution(const CXType &type) +{ + CXString typeSpelling = clang_getTypeSpelling(type); + std::string_view spelling = clang_getCString(typeSpelling); + const bool result = spelling.compare(0, 2, "::") == 0 + || spelling.find(" ::") != std::string::npos; + clang_disposeString(typeSpelling); + return result; +} + +// Resolve elaborated types occurring with clang 16 +QString getResolvedTypeName(const CXType &type) +{ + return getTypeName(resolveElaboratedType(type)); +} + Diagnostic::Diagnostic(const QString &m, const CXCursor &c, CXDiagnosticSeverity s) : message(m), source(Other), severity(s) { @@ -166,16 +215,17 @@ QList<Diagnostic> getDiagnostics(CXTranslationUnit tu) return result; } -QPair<int, int> parseTemplateArgumentList(const QString &l, - const TemplateArgumentHandler &handler, - int from) +std::pair<qsizetype, qsizetype> + parseTemplateArgumentList(const QString &l, + const TemplateArgumentHandler &handler, + qsizetype from) { - const int ltPos = l.indexOf(u'<', from); + const auto ltPos = l.indexOf(u'<', from); if (ltPos == - 1) - return qMakePair(-1, -1); - int startPos = ltPos + 1; + return std::make_pair(-1, -1); + auto startPos = ltPos + 1; int level = 1; - for (int p = startPos, end = l.size(); p < end; ) { + for (qsizetype p = startPos, end = l.size(); p < end; ) { const char c = l.at(p).toLatin1(); switch (c) { case ',': @@ -184,7 +234,7 @@ QPair<int, int> parseTemplateArgumentList(const QString &l, ++p; if (c == '>') { if (--level == 0) - return qMakePair(ltPos, p); + return std::make_pair(ltPos, p); // Skip over next ',': "a<b<c,d>,e>" for (; p < end && (l.at(p).isSpace() || l.at(p) == u','); ++p) {} } @@ -200,7 +250,7 @@ QPair<int, int> parseTemplateArgumentList(const QString &l, break; } } - return qMakePair(-1, -1); + return std::make_pair(-1, -1); } CXDiagnosticSeverity maxSeverity(const QList<Diagnostic> &ds) @@ -256,9 +306,9 @@ QDebug operator<<(QDebug s, const Diagnostic &d) if (d.source != Diagnostic::Clang) s << " [other]"; - if (const int childMessagesCount = d.childMessages.size()) { + if (const auto childMessagesCount = d.childMessages.size()) { s << '\n'; - for (int i = 0; i < childMessagesCount; ++i) + for (qsizetype i = 0; i < childMessagesCount; ++i) s << " " << d.childMessages.at(i) << '\n'; } diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangutils.h b/sources/shiboken6/ApiExtractor/clangparser/clangutils.h index c1d6be446..fbbf95f1b 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangutils.h +++ b/sources/shiboken6/ApiExtractor/clangparser/clangutils.h @@ -5,20 +5,21 @@ #define CLANGUTILS_H #include <clang-c/Index.h> -#include <QtCore/QPair> #include <QtCore/QString> #include <QtCore/QStringList> +#include <QtCore/QtCompare> #include <QtCore/QList> #include <functional> +#include <utility> QT_FORWARD_DECLARE_CLASS(QDebug) -bool operator==(const CXCursor &c1, const CXCursor &c2); -size_t qHash(const CXCursor &c, size_t seed = 0); +bool operator==(const CXCursor &c1, const CXCursor &c2) noexcept; +size_t qHash(const CXCursor &c, size_t seed = 0) noexcept; -bool operator==(const CXType &t1, const CXType &t2); -size_t qHash(const CXType &ct, size_t seed); +bool operator==(const CXType &t1, const CXType &t2) noexcept; +size_t qHash(const CXType &ct, size_t seed = 0) noexcept; namespace clang { @@ -26,6 +27,9 @@ QString getCursorKindName(CXCursorKind cursorKind); QString getCursorSpelling(const CXCursor &cursor); QString getCursorDisplayName(const CXCursor &cursor); QString getTypeName(const CXType &type); +bool hasScopeResolution(const CXType &type); +CXType fullyResolveType(const CXType &type); +QString getResolvedTypeName(const CXType &type); inline QString getCursorTypeName(const CXCursor &cursor) { return getTypeName(clang_getCursorType(cursor)); } inline QString getCursorResultTypeName(const CXCursor &cursor) @@ -46,17 +50,18 @@ struct SourceLocation unsigned line = 0; unsigned column = 0; unsigned offset = 0; -}; - -inline bool operator==(const SourceLocation &l1, const SourceLocation &l2) -{ return l1.equals(l2); } -inline bool operator!=(const SourceLocation &l1, const SourceLocation &l2) -{ return !l1.equals(l2); } + friend constexpr bool comparesEqual(const SourceLocation &lhs, + const SourceLocation &rhs) noexcept + { + return lhs.file == rhs.file && lhs.offset == rhs.offset; + } + Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(SourceLocation) +}; SourceLocation getExpansionLocation(const CXSourceLocation &location); -using SourceRange =QPair<SourceLocation, SourceLocation>; +using SourceRange = std::pair<SourceLocation, SourceLocation>; SourceLocation getCursorLocation(const CXCursor &cursor); CXString getFileNameFromLocation(const CXSourceLocation &location); @@ -89,9 +94,10 @@ CXDiagnosticSeverity maxSeverity(const QList<Diagnostic> &ds); // with each match (level and string). Return begin and end of the list. using TemplateArgumentHandler = std::function<void (int, QStringView)>; -QPair<int, int> parseTemplateArgumentList(const QString &l, - const TemplateArgumentHandler &handler, - int from = 0); +std::pair<qsizetype, qsizetype> + parseTemplateArgumentList(const QString &l, + const TemplateArgumentHandler &handler, + qsizetype from = 0); #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug, const SourceLocation &); diff --git a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp index 9b9e036f4..20224020b 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp +++ b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp @@ -3,6 +3,7 @@ #include "compilersupport.h" #include "header_paths.h" +#include "clangutils.h" #include <reporthandler.h> @@ -19,7 +20,6 @@ #include <clang-c/Index.h> -#include <string.h> #include <algorithm> #include <iterator> @@ -43,6 +43,32 @@ static Compiler _compiler = Compiler compiler() { return _compiler; } +bool setCompiler(const QString &name) +{ + bool result = true; + if (name == u"msvc") + _compiler = Compiler::Msvc; + else if (name == u"g++") + _compiler = Compiler::Gpp; + else if (name == u"clang") + _compiler = Compiler::Clang; + else + result = false; + return result; +} + +QString _compilerPath; // Pre-defined compiler path (from command line) + +const QString &compilerPath() +{ + return _compilerPath; +} + +void setCompilerPath(const QString &name) +{ + _compilerPath = name; +} + static Platform _platform = #if defined (Q_OS_DARWIN) Platform::macOS; @@ -54,13 +80,33 @@ static Platform _platform = Platform platform() { return _platform; } +bool setPlatform(const QString &name) +{ + bool result = true; + if (name == u"windows") + _platform = Platform::Windows; + else if (name == u"darwin") + _platform = Platform::macOS; + else if (name == u"unix") + _platform = Platform::Unix; + else + result = false; + return result; +} + +// 3/2024: Use a recent MSVC2022 for libclang 18.X +static QByteArray msvcCompatVersion() +{ + return libClangVersion() >= QVersionNumber(0, 64) ? "19.39"_ba : "19.26"_ba; +} + static bool runProcess(const QString &program, const QStringList &arguments, QByteArray *stdOutIn = nullptr, QByteArray *stdErrIn = nullptr) { QProcess process; process.start(program, arguments, QProcess::ReadWrite); if (!process.waitForStarted()) { - qWarning().noquote().nospace() << "Unable to start " + qCWarning(lcShiboken).noquote().nospace() << "Unable to start " << process.program() << ": " << process.errorString(); return false; } @@ -73,18 +119,18 @@ static bool runProcess(const QString &program, const QStringList &arguments, *stdOutIn = process.readAllStandardOutput(); if (!finished) { - qWarning().noquote().nospace() << process.program() << " timed out: " << stdErr; + qCWarning(lcShiboken).noquote().nospace() << process.program() << " timed out: " << stdErr; process.kill(); return false; } if (process.exitStatus() != QProcess::NormalExit) { - qWarning().noquote().nospace() << process.program() << " crashed: " << stdErr; + qCWarning(lcShiboken).noquote().nospace() << process.program() << " crashed: " << stdErr; return false; } if (process.exitCode() != 0) { - qWarning().noquote().nospace() << process.program() << " exited " + qCWarning(lcShiboken).noquote().nospace() << process.program() << " exited " << process.exitCode() << ": " << stdErr; return false; } @@ -132,15 +178,20 @@ static void filterHomebrewHeaderPaths(HeaderPaths &headerPaths) static HeaderPaths gppInternalIncludePaths(const QString &compiler) { HeaderPaths result; - QStringList arguments; - arguments << QStringLiteral("-E") << QStringLiteral("-x") << QStringLiteral("c++") - << QStringLiteral("-") << QStringLiteral("-v"); + QStringList arguments{u"-E"_s, u"-x"_s, u"c++"_s, u"-"_s, u"-v"_s}; QByteArray stdOut; QByteArray stdErr; if (!runProcess(compiler, arguments, &stdOut, &stdErr)) return result; const QByteArrayList stdErrLines = stdErr.split('\n'); bool isIncludeDir = false; + + if (ReportHandler::isDebug(ReportHandler::MediumDebug)) + qCInfo(lcShiboken()).noquote().nospace() + << "gppInternalIncludePaths:\n compiler: " << compiler + << "\n stdOut: " << stdOut + << "\n stdErr: " << stdErr; + for (const QByteArray &line : stdErrLines) { if (isIncludeDir) { if (line.startsWith(QByteArrayLiteral("End of search list"))) { @@ -202,6 +253,23 @@ static bool needsClangBuiltinIncludes() return platform() != Platform::macOS; } +static QString queryLlvmConfigDir(const QString &arg) +{ + static const QString llvmConfig = QStandardPaths::findExecutable(u"llvm-config"_s); + if (llvmConfig.isEmpty()) + return {}; + QByteArray stdOut; + if (!runProcess(llvmConfig, QStringList{arg}, &stdOut)) + return {}; + const QString path = QFile::decodeName(stdOut.trimmed()); + if (!QFileInfo::exists(path)) { + qCWarning(lcShiboken, R"(%s: "%s" as returned by llvm-config "%s" does not exist.)", + __FUNCTION__, qPrintable(QDir::toNativeSeparators(path)), qPrintable(arg)); + return {}; + } + return path; +} + static QString findClangLibDir() { for (const char *envVar : {"LLVM_INSTALL_DIR", "CLANG_INSTALL_DIR"}) { @@ -209,21 +277,11 @@ static QString findClangLibDir() const QString path = QFile::decodeName(qgetenv(envVar)) + u"/lib"_s; if (QFileInfo::exists(path)) return path; - qWarning("%s: %s as pointed to by %s does not exist.", __FUNCTION__, qPrintable(path), envVar); + qCWarning(lcShiboken, "%s: %s as pointed to by %s does not exist.", + __FUNCTION__, qPrintable(path), envVar); } } - const QString llvmConfig = - QStandardPaths::findExecutable(u"llvm-config"_s); - if (!llvmConfig.isEmpty()) { - QByteArray stdOut; - if (runProcess(llvmConfig, QStringList{u"--libdir"_s}, &stdOut)) { - const QString path = QFile::decodeName(stdOut.trimmed()); - if (QFileInfo::exists(path)) - return path; - qWarning("%s: %s as returned by llvm-config does not exist.", __FUNCTION__, qPrintable(path)); - } - } - return QString(); + return queryLlvmConfigDir(u"--libdir"_s); } static QString findClangBuiltInIncludesDir() @@ -232,13 +290,23 @@ static QString findClangBuiltInIncludesDir() const QString clangPathLibDir = findClangLibDir(); if (!clangPathLibDir.isEmpty()) { QString candidate; + QString clangDirName = clangPathLibDir + u"/clang"_s; + // PYSIDE-2769: llvm-config --libdir may report /usr/lib64 on manylinux_2_28_x86_64 + // whereas the includes are under /usr/lib/clang/../include. + if (!QFileInfo::exists(clangDirName) && clangPathLibDir.endsWith("64"_L1)) { + const QString fallback = clangPathLibDir.sliced(0, clangPathLibDir.size() - 2); + clangDirName = fallback + u"/clang"_s; + qCWarning(lcShiboken, "%s: Falling back from %s to %s.", + __FUNCTION__, qPrintable(clangPathLibDir), qPrintable(fallback)); + } + QVersionNumber lastVersionNumber(1, 0, 0); - const QString clangDirName = clangPathLibDir + u"/clang"_s; QDir clangDir(clangDirName); const QFileInfoList versionDirs = clangDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); if (versionDirs.isEmpty()) - qWarning("%s: No subdirectories found in %s.", __FUNCTION__, qPrintable(clangDirName)); + qCWarning(lcShiboken, "%s: No subdirectories found in %s.", + __FUNCTION__, qPrintable(clangDirName)); for (const QFileInfo &fi : versionDirs) { const QString fileName = fi.fileName(); if (fileName.at(0).isDigit()) { @@ -250,20 +318,44 @@ static QString findClangBuiltInIncludesDir() } } if (!candidate.isEmpty()) - return candidate + QStringLiteral("/include"); + return candidate + "/include"_L1; } - return QString(); + return queryLlvmConfigDir(u"--includedir"_s); } -static QString compilerFromCMake(const QString &defaultCompiler) +QString compilerFromCMake() { -// Added !defined(Q_OS_DARWIN) due to PYSIDE-1032 - QString result = defaultCompiler; - if (platform() != Platform::macOS) #ifdef CMAKE_CXX_COMPILER - result = QString::fromLocal8Bit(CMAKE_CXX_COMPILER); + return QString::fromLocal8Bit(CMAKE_CXX_COMPILER); +#else + return {}; #endif - return result; +} + +// Return a compiler suitable for determining the internal include paths +static QString compilerFromCMake(const QString &defaultCompiler) +{ + if (!compilerPath().isEmpty()) + return compilerPath(); + // Exclude macOS since cmakeCompiler returns the full path instead of the + // /usr/bin/clang shim, which results in the default SDK sysroot path + // missing (PYSIDE-1032) + if (platform() == Platform::macOS) + return defaultCompiler; + QString cmakeCompiler = compilerFromCMake(); + if (cmakeCompiler.isEmpty()) + return defaultCompiler; + QFileInfo fi(cmakeCompiler); + // Should be absolute by default, but a user may specify -DCMAKE_CXX_COMPILER=cl.exe + if (fi.isRelative()) + return cmakeCompiler; + if (fi.exists()) + return fi.absoluteFilePath(); + // The compiler may not exist in case something like icecream or + // a non-standard-path was used on the build machine. Check + // the executable. + cmakeCompiler = QStandardPaths::findExecutable(fi.fileName()); + return cmakeCompiler.isEmpty() ? defaultCompiler : cmakeCompiler; } static void appendClangBuiltinIncludes(HeaderPaths *p) @@ -275,7 +367,8 @@ static void appendClangBuiltinIncludes(HeaderPaths *p) "(neither by checking the environment variables LLVM_INSTALL_DIR, CLANG_INSTALL_DIR " " nor running llvm-config). This may lead to parse errors."); } else { - qCInfo(lcShiboken, "CLANG builtins includes directory: %s", + qCInfo(lcShiboken, "CLANG v%d.%d, builtins includes directory: %s", + CINDEX_VERSION_MAJOR, CINDEX_VERSION_MINOR, qPrintable(clangBuiltinIncludesDir)); p->append(HeaderPath{QFile::encodeName(clangBuiltinIncludesDir), HeaderType::System}); @@ -283,15 +376,17 @@ static void appendClangBuiltinIncludes(HeaderPaths *p) } // Returns clang options needed for emulating the host compiler -QByteArrayList emulatedCompilerOptions() +QByteArrayList emulatedCompilerOptions(LanguageLevel level) { QByteArrayList result; HeaderPaths headerPaths; switch (compiler()) { case Compiler::Msvc: - result.append(QByteArrayLiteral("-fms-compatibility-version=19.26.28806")); - result.append(QByteArrayLiteral("-fdelayed-template-parsing")); + result.append("-fms-compatibility-version="_ba + msvcCompatVersion()); + if (level < LanguageLevel::Cpp20) + result.append("-fdelayed-template-parsing"_ba); result.append(QByteArrayLiteral("-Wno-microsoft-enum-value")); + result.append("/Zc:__cplusplus"_ba); // Fix yvals_core.h: STL1000: Unexpected compiler version, expected Clang 7 or newer (MSVC2017 update) result.append(QByteArrayLiteral("-D_ALLOW_COMPILER_AND_STL_VERSION_MISMATCH")); if (needsClangBuiltinIncludes()) @@ -304,6 +399,14 @@ QByteArrayList emulatedCompilerOptions() case Compiler::Gpp: if (needsClangBuiltinIncludes()) appendClangBuiltinIncludes(&headerPaths); + + // Append the c++ include paths since Clang is unable to find + // <type_traits> etc (g++ 11.3). + const HeaderPaths gppPaths = gppInternalIncludePaths(compilerFromCMake(u"g++"_s)); + for (const HeaderPath &h : gppPaths) { + if (h.path.contains("c++") || h.path.contains("sysroot")) + headerPaths.append(h); + } break; } diff --git a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h index 24d109cac..f1d63b7c3 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h +++ b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h @@ -7,6 +7,7 @@ #include <QtCore/QByteArrayList> QT_FORWARD_DECLARE_CLASS(QVersionNumber) +QT_FORWARD_DECLARE_CLASS(QString) enum class LanguageLevel { Default, @@ -32,7 +33,7 @@ enum class Platform { namespace clang { QVersionNumber libClangVersion(); -QByteArrayList emulatedCompilerOptions(); +QByteArrayList emulatedCompilerOptions(LanguageLevel level); LanguageLevel emulatedCompilerLanguageLevel(); const char *languageLevelOption(LanguageLevel l); @@ -41,7 +42,15 @@ LanguageLevel languageLevelFromOption(const char *); QByteArrayList detectVulkan(); Compiler compiler(); +bool setCompiler(const QString &name); + +QString compilerFromCMake(); + +const QString &compilerPath(); +void setCompilerPath(const QString &name); + Platform platform(); +bool setPlatform(const QString &name); } // namespace clang #endif // COMPILERSUPPORT_H diff --git a/sources/shiboken6/ApiExtractor/classdocumentation.cpp b/sources/shiboken6/ApiExtractor/classdocumentation.cpp index 4636072ea..637e4a422 100644 --- a/sources/shiboken6/ApiExtractor/classdocumentation.cpp +++ b/sources/shiboken6/ApiExtractor/classdocumentation.cpp @@ -3,6 +3,7 @@ #include "classdocumentation.h" #include "messages.h" +#include "debughelpers_p.h" #include <QtCore/QDebug> #include <QtCore/QBuffer> @@ -13,6 +14,8 @@ #include <algorithm> +using namespace Qt::StringLiterals; + // Sort functions by name and argument count static bool functionDocumentationLessThan(const FunctionDocumentation &f1, const FunctionDocumentation &f2) @@ -80,59 +83,67 @@ qsizetype ClassDocumentation::indexOfProperty(const QString &name) const return -1; } -enum class WebXmlTag +enum class WebXmlCodeTag { - Class, Description, Enum, Function, Parameter, Property, Typedef, Other + Class, Description, Enum, Function, Header, Parameter, Property, Typedef, Other }; -static WebXmlTag tag(QStringView name) +static WebXmlCodeTag tag(QStringView name) { if (name == u"class" || name == u"namespace") - return WebXmlTag::Class; + return WebXmlCodeTag::Class; if (name == u"enum") - return WebXmlTag::Enum; + return WebXmlCodeTag::Enum; if (name == u"function") - return WebXmlTag::Function; + return WebXmlCodeTag::Function; if (name == u"description") - return WebXmlTag::Description; + return WebXmlCodeTag::Description; + if (name == u"header") + return WebXmlCodeTag::Header; if (name == u"parameter") - return WebXmlTag::Parameter; + return WebXmlCodeTag::Parameter; if (name == u"property") - return WebXmlTag::Property; + return WebXmlCodeTag::Property; if (name == u"typedef") - return WebXmlTag::Typedef; - return WebXmlTag::Other; + return WebXmlCodeTag::Typedef; + return WebXmlCodeTag::Other; } -static void parseWebXmlElement(WebXmlTag tag, const QXmlStreamAttributes &attributes, +static void parseWebXmlElement(WebXmlCodeTag tag, const QXmlStreamAttributes &attributes, ClassDocumentation *cd) { switch (tag) { - case WebXmlTag::Class: - cd->name = attributes.value(u"name"_qs).toString(); + case WebXmlCodeTag::Class: + cd->name = attributes.value(u"name"_s).toString(); + cd->type = ClassDocumentation::Class; + break; + case WebXmlCodeTag::Header: + cd->name = attributes.value(u"name"_s).toString(); + cd->type = ClassDocumentation::Header; break; - case WebXmlTag::Enum: { + case WebXmlCodeTag::Enum: { EnumDocumentation ed; - ed.name = attributes.value(u"name"_qs).toString(); + ed.name = attributes.value(u"name"_s).toString(); cd->enums.append(ed); } break; - case WebXmlTag::Function: { + case WebXmlCodeTag::Function: { FunctionDocumentation fd; - fd.name = attributes.value(u"name"_qs).toString(); - fd.signature = attributes.value(u"signature"_qs).toString(); - fd.returnType = attributes.value(u"type"_qs).toString(); - fd.constant = attributes.value(u"const"_qs) == u"true"; + fd.name = attributes.value(u"name"_s).toString(); + fd.signature = attributes.value(u"signature"_s).toString(); + fd.returnType = attributes.value(u"type"_s).toString(); + fd.constant = attributes.value(u"const"_s) == u"true"; cd->functions.append(fd); } break; - case WebXmlTag::Parameter: + case WebXmlCodeTag::Parameter: Q_ASSERT(!cd->functions.isEmpty()); - cd->functions.last().parameters.append(attributes.value(u"type"_qs).toString()); + cd->functions.last().parameters.append(attributes.value(u"type"_s).toString()); break; - case WebXmlTag::Property: { + case WebXmlCodeTag::Property: { PropertyDocumentation pd; - pd.name = attributes.value(u"name"_qs).toString(); + pd.name = attributes.value(u"name"_s).toString(); + pd.brief = attributes.value(u"brief"_s).toString(); cd->properties.append(pd); } break; @@ -181,17 +192,17 @@ static QString msgXmlError(const QString &fileName, const QXmlStreamReader &read return result; } -ClassDocumentation parseWebXml(const QString &fileName, QString *errorMessage) +std::optional<ClassDocumentation> parseWebXml(const QString &fileName, QString *errorMessage) { ClassDocumentation result; QFile file(fileName); if (!file.open(QIODevice::Text | QIODevice::ReadOnly)) { *errorMessage = msgCannotOpenForReading(file); - return result; + return std::nullopt; } - WebXmlTag lastTag = WebXmlTag::Other; + WebXmlCodeTag lastTag = WebXmlCodeTag::Other; QXmlStreamReader reader(&file); while (!reader.atEnd()) { switch (reader.readNext()) { @@ -199,26 +210,27 @@ ClassDocumentation parseWebXml(const QString &fileName, QString *errorMessage) const auto currentTag = tag(reader.name()); parseWebXmlElement(currentTag, reader.attributes(), &result); switch (currentTag) { // Store relevant tags in lastTag - case WebXmlTag::Class: - case WebXmlTag::Function: - case WebXmlTag::Enum: - case WebXmlTag::Property: - case WebXmlTag::Typedef: + case WebXmlCodeTag::Class: + case WebXmlCodeTag::Function: + case WebXmlCodeTag::Enum: + case WebXmlCodeTag::Header: + case WebXmlCodeTag::Property: + case WebXmlCodeTag::Typedef: lastTag = currentTag; break; - case WebXmlTag::Description: { // Append the description to the element + case WebXmlCodeTag::Description: { // Append the description to the element QString *target = nullptr; switch (lastTag) { - case WebXmlTag::Class: + case WebXmlCodeTag::Class: target = &result.description; break; - case WebXmlTag::Function: + case WebXmlCodeTag::Function: target = &result.functions.last().description; break; - case WebXmlTag::Enum: + case WebXmlCodeTag::Enum: target = &result.enums.last().description; break; - case WebXmlTag::Property: + case WebXmlCodeTag::Property: target = &result.properties.last().description; default: break; @@ -238,7 +250,7 @@ ClassDocumentation parseWebXml(const QString &fileName, QString *errorMessage) if (reader.error() != QXmlStreamReader::NoError) { *errorMessage= msgXmlError(fileName, reader); - return {}; + return std::nullopt; } sortDocumentation(&result); @@ -274,21 +286,6 @@ QString webXmlModuleDescription(const QString &fileName, QString *errorMessage) return result; } -// Debug helpers -template <class T> -static void formatList(QDebug &debug, const char *title, const QList<T> &l) -{ - if (const qsizetype size = l.size()) { - debug << title << '[' << size << "]=("; - for (qsizetype i = 0; i < size; ++i) { - if (i) - debug << ", "; - debug << l.at(i); - } - debug << ')'; - } -} - static void formatDescription(QDebug &debug, const QString &desc) { debug << "description="; @@ -348,7 +345,7 @@ QDebug operator<<(QDebug debug, const FunctionDocumentation &f) debug << ", returns " << f.returnType; if (f.constant) debug << ", const"; - formatList(debug, ", parameters", f.parameters); + formatList(debug, ", parameters", f.parameters, ", "); debug << ", signature=\"" << f.signature << "\", "; formatDescription(debug, f.description); } @@ -374,16 +371,11 @@ QDebug operator<<(QDebug debug, const ClassDocumentation &c) QDebugStateSaver saver(debug); debug.noquote(); debug.nospace(); - debug << "Class("; - if (c) { - debug << c.name << ", "; - formatDescription(debug, c.description); - formatList(debug, ", enums", c.enums); - formatList(debug, ", properties", c.properties); - formatList(debug, ", functions", c.functions); - } else { - debug << "invalid"; - } + debug << "Class(" << c.name << ", "; + formatDescription(debug, c.description); + formatList(debug, ", enums", c.enums); + formatList(debug, ", properties", c.properties); + formatList(debug, ", functions", c.functions); debug << ')'; return debug; } diff --git a/sources/shiboken6/ApiExtractor/classdocumentation.h b/sources/shiboken6/ApiExtractor/classdocumentation.h index 9c1acbbae..d47101389 100644 --- a/sources/shiboken6/ApiExtractor/classdocumentation.h +++ b/sources/shiboken6/ApiExtractor/classdocumentation.h @@ -6,6 +6,8 @@ #include <QtCore/QStringList> +#include <optional> + QT_FORWARD_DECLARE_CLASS(QDebug) /// An enumeration in a WebXML/doxygen document @@ -19,6 +21,7 @@ struct EnumDocumentation struct PropertyDocumentation { QString name; + QString brief; QString description; }; @@ -40,9 +43,14 @@ struct FunctionDocumentation : public FunctionDocumentationQuery using FunctionDocumentationList = QList<FunctionDocumentation>; -/// A class/namespace in a WebXML/doxygen document +/// A WebXML/doxygen document struct ClassDocumentation { + enum Type { + Class, // <class>, class/namespace + Header // <header>, grouped global functions/enums + }; + qsizetype indexOfEnum(const QString &name) const; FunctionDocumentationList findFunctionCandidates(const QString &name, bool constant) const; @@ -50,18 +58,17 @@ struct ClassDocumentation const FunctionDocumentationQuery &q); qsizetype indexOfProperty(const QString &name) const; + Type type = Type::Class; QString name; QString description; QList<EnumDocumentation> enums; QList<PropertyDocumentation> properties; FunctionDocumentationList functions; - - operator bool() const { return !name.isEmpty(); } }; /// Parse a WebXML class/namespace document -ClassDocumentation parseWebXml(const QString &fileName, QString *errorMessage); +std::optional<ClassDocumentation> parseWebXml(const QString &fileName, QString *errorMessage); /// Extract the module description from a WebXML module document QString webXmlModuleDescription(const QString &fileName, QString *errorMessage); diff --git a/sources/shiboken6/ApiExtractor/cmake_uninstall.cmake b/sources/shiboken6/ApiExtractor/cmake_uninstall.cmake index df95fb9d8..4031b4e1a 100644 --- a/sources/shiboken6/ApiExtractor/cmake_uninstall.cmake +++ b/sources/shiboken6/ApiExtractor/cmake_uninstall.cmake @@ -1,3 +1,6 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") diff --git a/sources/shiboken6/ApiExtractor/codesnip.cpp b/sources/shiboken6/ApiExtractor/codesnip.cpp index 12e71fb70..e2cd5eb35 100644 --- a/sources/shiboken6/ApiExtractor/codesnip.cpp +++ b/sources/shiboken6/ApiExtractor/codesnip.cpp @@ -11,11 +11,9 @@ using namespace Qt::StringLiterals; -static inline QString callOperator() { return QStringLiteral("operator()"); } - QString TemplateInstance::expandCode() const { - TemplateEntry *templateEntry = TypeDatabase::instance()->findTemplate(m_name); + const auto templateEntry = TypeDatabase::instance()->findTemplate(m_name); if (!templateEntry) { const QString m = u"<insert-template> referring to non-existing template '"_s + m_name + u"'."_s; @@ -65,7 +63,7 @@ void CodeSnipAbstract::purgeEmptyFragments() QRegularExpression CodeSnipAbstract::placeHolderRegex(int index) { - return QRegularExpression(u'%' + QString::number(index) + QStringLiteral("\\b")); + return QRegularExpression(u'%' + QString::number(index) + "\\b"_L1); } void purgeEmptyCodeSnips(QList<CodeSnip> *list) diff --git a/sources/shiboken6/ApiExtractor/codesnip.h b/sources/shiboken6/ApiExtractor/codesnip.h index 7a1ab0624..86834a1db 100644 --- a/sources/shiboken6/ApiExtractor/codesnip.h +++ b/sources/shiboken6/ApiExtractor/codesnip.h @@ -9,9 +9,10 @@ #include <QtCore/QList> #include <QtCore/QHash> -#include <QtCore/QSharedPointer> #include <QtCore/QString> +#include <memory> + class TemplateInstance { public: @@ -34,7 +35,7 @@ private: QHash<QString, QString> replaceRules; }; -using TemplateInstancePtr = QSharedPointer<TemplateInstance>; +using TemplateInstancePtr = std::shared_ptr<TemplateInstance>; class CodeSnipFragment { @@ -43,7 +44,7 @@ public: explicit CodeSnipFragment(const QString &code) : m_code(code) {} explicit CodeSnipFragment(const TemplateInstancePtr &instance) : m_instance(instance) {} - bool isEmpty() const { return m_code.isEmpty() && m_instance.isNull(); } + bool isEmpty() const { return m_code.isEmpty() && !m_instance; } QString code() const; @@ -51,7 +52,7 @@ public: private: QString m_code; - QSharedPointer<TemplateInstance> m_instance; + std::shared_ptr<TemplateInstance> m_instance; }; class CodeSnipAbstract : public CodeSnipHelpers diff --git a/sources/shiboken6/ApiExtractor/complextypeentry.h b/sources/shiboken6/ApiExtractor/complextypeentry.h index fd17fe572..5b884f2cc 100644 --- a/sources/shiboken6/ApiExtractor/complextypeentry.h +++ b/sources/shiboken6/ApiExtractor/complextypeentry.h @@ -4,7 +4,9 @@ #ifndef COMPLEXTYPEENTRY_H #define COMPLEXTYPEENTRY_H -#include "typesystem.h" +#include "configurabletypeentry.h" +#include "typesystem_enums.h" +#include "modifications_typedefs.h" #include "pymethoddefentry.h" #include <QtCore/QSet> @@ -26,11 +28,12 @@ struct TypeSystemProperty QString write; QString reset; QString designable; + QString notify; // Q_PROPERTY/C++ only // Indicates whether actual code is generated instead of relying on libpyside. bool generateGetSetDef = false; }; -class ComplexTypeEntry : public TypeEntry +class ComplexTypeEntry : public ConfigurableTypeEntry { public: enum TypeFlag { @@ -39,7 +42,9 @@ public: ForceAbstract = 0x8, // Indicates that the instances are used to create hierarchies // like widgets; parent ownership heuristics are enabled for them. - ParentManagement = 0x10 + ParentManagement = 0x10, + DisableQtMetaObjectFunctions = 0x20, + Typedef = 0x40 // Result of a <typedef-type> }; Q_DECLARE_FLAGS(TypeFlags, TypeFlag) @@ -50,7 +55,7 @@ public: }; explicit ComplexTypeEntry(const QString &entryName, Type t, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); bool isComplex() const override; @@ -67,7 +72,22 @@ public: FunctionModificationList functionModifications() const; void setFunctionModifications(const FunctionModificationList &functionModifications); void addFunctionModification(const FunctionModification &functionModification); - FunctionModificationList functionModifications(const QString &signature) const; + FunctionModificationList functionModifications(const QStringList &signatures) const; + + const CodeSnipList &codeSnips() const; + CodeSnipList &codeSnips(); + void setCodeSnips(const CodeSnipList &codeSnips); + void addCodeSnip(const CodeSnip &codeSnip); + + void setDocModification(const DocModificationList& docMods); + /// Class documentation modifications + DocModificationList docModifications() const; + /// Function documentation modifications (matching signature) + DocModificationList functionDocModifications() const; + + /// Extra includes for function arguments determined by the meta builder. + const IncludeList &argumentIncludes() const; + void addArgumentInclude(const Include &newInclude); AddedFunctionList addedFunctions() const; void setAddedFunctions(const AddedFunctionList &addedFunctions); @@ -118,9 +138,9 @@ public: QString hashFunction() const; void setHashFunction(const QString &hashFunction); - void setBaseContainerType(const ComplexTypeEntry *baseContainer); + void setBaseContainerType(const ComplexTypeEntryCPtr &baseContainer); - const ComplexTypeEntry *baseContainerType() const; + ComplexTypeEntryCPtr baseContainerType() const; TypeSystem::ExceptionHandling exceptionHandling() const; void setExceptionHandling(TypeSystem::ExceptionHandling e); @@ -134,7 +154,7 @@ public: TypeEntry *clone() const override; - void useAsTypedef(const ComplexTypeEntry *source); + void useAsTypedef(const ComplexTypeEntryCPtr &source); TypeSystem::SnakeCase snakeCase() const; void setSnakeCase(TypeSystem::SnakeCase sc); diff --git a/sources/shiboken6/ApiExtractor/conditionalstreamreader.cpp b/sources/shiboken6/ApiExtractor/conditionalstreamreader.cpp index c8ec9b563..b6eda651c 100644 --- a/sources/shiboken6/ApiExtractor/conditionalstreamreader.cpp +++ b/sources/shiboken6/ApiExtractor/conditionalstreamreader.cpp @@ -6,6 +6,8 @@ #include <QtCore/QDebug> #include <QtCore/QHash> +using namespace Qt::StringLiterals; + // ProxyEntityResolver proxies a QXmlStreamEntityResolver set by the user // on ConditionalStreamReader and stores entity definitions from the // <?entity name value?> processing instruction in a cache @@ -126,7 +128,7 @@ bool ConditionalStreamReader::readEntityDefinitonPi() const auto data = m_reader.processingInstructionData(); const auto separator = data.indexOf(u' '); if (separator <= 0 || separator == data.size() - 1) { - m_reader.raiseError(u"Malformed entity definition: "_qs + data.toString()); + m_reader.raiseError(u"Malformed entity definition: "_s + data.toString()); return false; } defineEntity(data.left(separator).toString(), @@ -163,15 +165,15 @@ QStringList ConditionalStreamReader::platformConditions() { QStringList result; #if defined (Q_OS_UNIX) - result << QStringLiteral("unix"); + result << "unix"_L1; #endif #if defined (Q_OS_LINUX) - result << QStringLiteral("linux"); + result << "linux"_L1; #elif defined (Q_OS_MACOS) - result << QStringLiteral("darwin"); + result << "darwin"_L1; #elif defined (Q_OS_WINDOWS) - result << QStringLiteral("windows"); + result << "windows"_L1; #endif return result; } diff --git a/sources/shiboken6/ApiExtractor/conditionalstreamreader.h b/sources/shiboken6/ApiExtractor/conditionalstreamreader.h index a273fd0ca..730697525 100644 --- a/sources/shiboken6/ApiExtractor/conditionalstreamreader.h +++ b/sources/shiboken6/ApiExtractor/conditionalstreamreader.h @@ -26,6 +26,8 @@ class ProxyEntityResolver; class ConditionalStreamReader { public: + Q_DISABLE_COPY_MOVE(ConditionalStreamReader) + using TokenType = QXmlStreamReader::TokenType; explicit ConditionalStreamReader(QIODevice *iod); explicit ConditionalStreamReader(const QString &s); diff --git a/sources/shiboken6/ApiExtractor/configurabletypeentry.h b/sources/shiboken6/ApiExtractor/configurabletypeentry.h new file mode 100644 index 000000000..59522e16c --- /dev/null +++ b/sources/shiboken6/ApiExtractor/configurabletypeentry.h @@ -0,0 +1,28 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef CONFIGURABLETYPEENTRY_H +#define CONFIGURABLETYPEENTRY_H + +#include "typesystem.h" + +class ConfigurableTypeEntryPrivate; + +class ConfigurableTypeEntry : public TypeEntry +{ +public: + explicit ConfigurableTypeEntry(const QString &entryName, Type t, + const QVersionNumber &vr, + const TypeEntryCPtr &parent); + + TypeEntry *clone() const override; + + QString configCondition() const; + void setConfigCondition(const QString &c); + bool hasConfigCondition() const; + +protected: + explicit ConfigurableTypeEntry(ConfigurableTypeEntryPrivate *d); +}; + +#endif // CONFIGURABLETYPEENTRY_H diff --git a/sources/shiboken6/ApiExtractor/constantvaluetypeentry.h b/sources/shiboken6/ApiExtractor/constantvaluetypeentry.h index d88c2b07f..a16a7ad12 100644 --- a/sources/shiboken6/ApiExtractor/constantvaluetypeentry.h +++ b/sources/shiboken6/ApiExtractor/constantvaluetypeentry.h @@ -12,7 +12,7 @@ class ConstantValueTypeEntry : public TypeEntry { public: explicit ConstantValueTypeEntry(const QString& name, - const TypeEntry *parent); + const TypeEntryCPtr &parent); TypeEntry *clone() const override; diff --git a/sources/shiboken6/ApiExtractor/containertypeentry.h b/sources/shiboken6/ApiExtractor/containertypeentry.h index 34ee08808..b2003816b 100644 --- a/sources/shiboken6/ApiExtractor/containertypeentry.h +++ b/sources/shiboken6/ApiExtractor/containertypeentry.h @@ -5,18 +5,23 @@ #define CONTAINERTYPEENTRY_H #include "complextypeentry.h" +#include "customconversion_typedefs.h" class ContainerTypeEntryPrivate; +struct OpaqueContainer // Generate an opaque container for an instantiation under name +{ + QStringList instantiations; + QString name; + + QString templateParameters() const; +}; + +using OpaqueContainers = QList<OpaqueContainer>; + class ContainerTypeEntry : public ComplexTypeEntry { public: - struct OpaqueContainer // Generate an opaque container for an instantiation under name - { - QString instantiation; - QString name; - }; - using OpaqueContainers = QList<OpaqueContainer>; enum ContainerKind { ListContainer, @@ -24,17 +29,25 @@ public: MapContainer, MultiMapContainer, PairContainer, + SpanContainer, // Fixed size }; explicit ContainerTypeEntry(const QString &entryName, ContainerKind containerKind, - const QVersionNumber &vr, const TypeEntry *parent); + const QVersionNumber &vr, const TypeEntryCPtr &parent); ContainerKind containerKind() const; + /// Number of template parameters (except allocators) + qsizetype templateParameterCount() const; + const OpaqueContainers &opaqueContainers() const; - void addOpaqueContainer(OpaqueContainer r); - bool generateOpaqueContainer(const QString &instantiation) const; - QString opaqueContainerName(const QString &instantiation) const; + void appendOpaqueContainers(const OpaqueContainers &l); + bool generateOpaqueContainer(const QStringList &instantiations) const; + QString opaqueContainerName(const QStringList &instantiations) const; + + bool hasCustomConversion() const; + void setCustomConversion(const CustomConversionPtr &customConversion); + CustomConversionPtr customConversion() const; TypeEntry *clone() const override; @@ -45,4 +58,6 @@ protected: explicit ContainerTypeEntry(ContainerTypeEntryPrivate *d); }; +QDebug operator<<(QDebug d, const OpaqueContainer &oc); + #endif // CONTAINERTYPEENTRY_H diff --git a/sources/shiboken6/ApiExtractor/customconversion.cpp b/sources/shiboken6/ApiExtractor/customconversion.cpp new file mode 100644 index 000000000..4cfd1b974 --- /dev/null +++ b/sources/shiboken6/ApiExtractor/customconversion.cpp @@ -0,0 +1,197 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "customconversion.h" +#include "containertypeentry.h" +#include "customtypenentry.h" +#include "primitivetypeentry.h" +#include "valuetypeentry.h" + +#include <QtCore/qdebug.h> + +using namespace Qt::StringLiterals; + +CustomConversion::CustomConversion(const TypeEntryCPtr &ownerType) : + m_ownerType(ownerType) +{ +} + +TypeEntryCPtr CustomConversion::ownerType() const +{ + return m_ownerType; +} + +QString CustomConversion::nativeToTargetConversion() const +{ + return m_nativeToTargetConversion; +} + +void CustomConversion::setNativeToTargetConversion(const QString &nativeToTargetConversion) +{ + m_nativeToTargetConversion = nativeToTargetConversion; +} + +bool CustomConversion::replaceOriginalTargetToNativeConversions() const +{ + return m_replaceOriginalTargetToNativeConversions; +} + +void CustomConversion::setReplaceOriginalTargetToNativeConversions(bool r) +{ + m_replaceOriginalTargetToNativeConversions = r; +} + +bool CustomConversion::hasTargetToNativeConversions() const +{ + return !(m_targetToNativeConversions.isEmpty()); +} + +TargetToNativeConversions &CustomConversion::targetToNativeConversions() +{ + return m_targetToNativeConversions; +} + +const TargetToNativeConversions &CustomConversion::targetToNativeConversions() const +{ + return m_targetToNativeConversions; +} + +void CustomConversion::addTargetToNativeConversion(const QString &sourceTypeName, + const QString &sourceTypeCheck, + const QString &conversion) +{ + m_targetToNativeConversions.append(TargetToNativeConversion(sourceTypeName, + sourceTypeCheck, + conversion)); +} + +TargetToNativeConversion::TargetToNativeConversion(const QString &sourceTypeName, + const QString &sourceTypeCheck, + const QString &conversion) : + m_sourceTypeName(sourceTypeName), m_sourceTypeCheck(sourceTypeCheck), + m_conversion(conversion) +{ +} + +TypeEntryCPtr TargetToNativeConversion::sourceType() const +{ + return m_sourceType; +} + +void TargetToNativeConversion::setSourceType(const TypeEntryCPtr &sourceType) +{ + m_sourceType = sourceType; +} + +bool TargetToNativeConversion::isCustomType() const +{ + return m_sourceType == nullptr; +} + +QString TargetToNativeConversion::sourceTypeName() const +{ + return m_sourceTypeName; +} + +QString TargetToNativeConversion::sourceTypeCheck() const +{ + if (!m_sourceTypeCheck.isEmpty()) + return m_sourceTypeCheck; + + if (m_sourceType != nullptr && m_sourceType->isCustom()) { + const auto cte = std::static_pointer_cast<const CustomTypeEntry>(m_sourceType); + if (cte->hasCheckFunction()) { + QString result = cte->checkFunction(); + if (result != u"true") // For PyObject, which is always true + result += u"(%in)"_s; + return result; + } + } + + return {}; +} + +QString TargetToNativeConversion::conversion() const +{ + return m_conversion; +} + +void TargetToNativeConversion::setConversion(const QString &conversion) +{ + m_conversion = conversion; +} + +void TargetToNativeConversion::formatDebug(QDebug &debug) const +{ + debug << "(source=\"" << m_sourceTypeName << '"'; + if (debug.verbosity() > 2) + debug << ", conversion=\"" << m_conversion << '"'; + if (isCustomType()) + debug << ", [custom]"; + debug << ')'; +} + +CustomConversionPtr CustomConversion::getCustomConversion(const TypeEntryCPtr &type) +{ + if (type->isPrimitive()) + return std::static_pointer_cast<const PrimitiveTypeEntry>(type)->customConversion(); + if (type->isContainer()) + return std::static_pointer_cast<const ContainerTypeEntry>(type)->customConversion(); + if (type->isValue()) + return std::static_pointer_cast<const ValueTypeEntry>(type)->customConversion(); + return {}; +} + +void CustomConversion::formatDebug(QDebug &debug) const +{ + debug << "(owner=\"" << m_ownerType->qualifiedCppName() << '"'; + if (!m_nativeToTargetConversion.isEmpty()) + debug << ", nativeToTargetConversion=\"" << m_nativeToTargetConversion << '"'; + if (!m_targetToNativeConversions.isEmpty()) { + debug << ", targetToNativeConversions=["; + for (qsizetype i = 0, size = m_targetToNativeConversions.size(); i < size; ++i) { + if (i) + debug << ", "; + debug << m_targetToNativeConversions.at(i); + + } + debug << ']'; + } + if (m_replaceOriginalTargetToNativeConversions) + debug << ", [replaceOriginalTargetToNativeConversions]"; + debug << ')'; +} + +QDebug operator<<(QDebug debug, const TargetToNativeConversion &t) +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + debug << "TargetToNativeConversion"; + t.formatDebug(debug); + return debug; +} + +QDebug operator<<(QDebug debug, const CustomConversion &c) +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + debug << "CustomConversion"; + c.formatDebug(debug); + return debug; +} + +QDebug operator<<(QDebug debug, const CustomConversionPtr &cptr) +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + debug << "CustomConversionPtr"; + if (auto *c = cptr.get()) { + c->formatDebug(debug); + } else { + debug << "(0)"; + } + return debug; +} diff --git a/sources/shiboken6/ApiExtractor/customconversion.h b/sources/shiboken6/ApiExtractor/customconversion.h index 172600d48..fd0a67759 100644 --- a/sources/shiboken6/ApiExtractor/customconversion.h +++ b/sources/shiboken6/ApiExtractor/customconversion.h @@ -4,61 +4,78 @@ #ifndef CUSTOMCONVERSION_H #define CUSTOMCONVERSION_H -#include "typesystem_enums.h" +#include "customconversion_typedefs.h" +#include "typesystem_typedefs.h" #include <QtCore/QList> #include <QtCore/QString> +QT_FORWARD_DECLARE_CLASS(QDebug) + class TypeEntry; +class TargetToNativeConversion +{ +public: + explicit TargetToNativeConversion(const QString &sourceTypeName, + const QString &sourceTypeCheck, + const QString &conversion = {}); + + TypeEntryCPtr sourceType() const; + void setSourceType(const TypeEntryCPtr &sourceType); + bool isCustomType() const; + QString sourceTypeName() const; + QString sourceTypeCheck() const; + QString conversion() const; + void setConversion(const QString &conversion); + + void formatDebug(QDebug &d) const; + +private: + TypeEntryCPtr m_sourceType; + QString m_sourceTypeName; + QString m_sourceTypeCheck; + QString m_conversion; +}; + +using TargetToNativeConversions = QList<TargetToNativeConversion>; + class CustomConversion { public: - CustomConversion(TypeEntry* ownerType); - ~CustomConversion(); + explicit CustomConversion(const TypeEntryCPtr &ownerType); - const TypeEntry* ownerType() const; + TypeEntryCPtr ownerType() const; QString nativeToTargetConversion() const; - void setNativeToTargetConversion(const QString& nativeToTargetConversion); - - class TargetToNativeConversion - { - public: - TargetToNativeConversion(const QString& sourceTypeName, - const QString& sourceTypeCheck, - const QString& conversion = QString()); - ~TargetToNativeConversion(); - - const TypeEntry* sourceType() const; - void setSourceType(const TypeEntry* sourceType); - bool isCustomType() const; - QString sourceTypeName() const; - QString sourceTypeCheck() const; - QString conversion() const; - void setConversion(const QString& conversion); - private: - struct TargetToNativeConversionPrivate; - TargetToNativeConversionPrivate* m_d; - }; - - /** - * Returns true if the target to C++ custom conversions should - * replace the original existing ones, and false if the custom - * conversions should be added to the original. - */ + void setNativeToTargetConversion(const QString &nativeToTargetConversion); + + /// Returns true if the target to C++ custom conversions should + /// replace the original existing ones, and false if the custom + /// conversions should be added to the original. bool replaceOriginalTargetToNativeConversions() const; - void setReplaceOriginalTargetToNativeConversions(bool replaceOriginalTargetToNativeConversions); + void setReplaceOriginalTargetToNativeConversions(bool r); - using TargetToNativeConversions = QList<TargetToNativeConversion *>; bool hasTargetToNativeConversions() const; - TargetToNativeConversions& targetToNativeConversions(); - const TargetToNativeConversions& targetToNativeConversions() const; - void addTargetToNativeConversion(const QString& sourceTypeName, - const QString& sourceTypeCheck, - const QString& conversion = QString()); + TargetToNativeConversions &targetToNativeConversions(); + const TargetToNativeConversions &targetToNativeConversions() const; + void addTargetToNativeConversion(const QString &sourceTypeName, + const QString &sourceTypeCheck, + const QString &conversion = QString()); + + /// Return the custom conversion of a type; helper for type system parser + static CustomConversionPtr getCustomConversion(const TypeEntryCPtr &type); + + void formatDebug(QDebug &debug) const; + private: - struct CustomConversionPrivate; - CustomConversionPrivate* m_d; + TypeEntryCPtr m_ownerType; + QString m_nativeToTargetConversion; + TargetToNativeConversions m_targetToNativeConversions; + bool m_replaceOriginalTargetToNativeConversions = false; }; +QDebug operator<<(QDebug debug, const TargetToNativeConversion &t); +QDebug operator<<(QDebug debug, const CustomConversion &c); +QDebug operator<<(QDebug debug, const CustomConversionPtr &cptr); + #endif // CUSTOMCONVERSION_H diff --git a/sources/shiboken6/ApiExtractor/customconversion_typedefs.h b/sources/shiboken6/ApiExtractor/customconversion_typedefs.h new file mode 100644 index 000000000..6528f7d7b --- /dev/null +++ b/sources/shiboken6/ApiExtractor/customconversion_typedefs.h @@ -0,0 +1,14 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef CUSTOMCONVERSION_TYPEDEFS_H +#define CUSTOMCONVERSION_TYPEDEFS_H + +#include <QtCore/QList> + +#include <memory> + +class CustomConversion; +using CustomConversionPtr = std::shared_ptr<CustomConversion>; + +#endif // CUSTOMCONVERSION_TYPEDEFS_H diff --git a/sources/shiboken6/ApiExtractor/customtypenentry.h b/sources/shiboken6/ApiExtractor/customtypenentry.h index e0dda4387..a57bb858f 100644 --- a/sources/shiboken6/ApiExtractor/customtypenentry.h +++ b/sources/shiboken6/ApiExtractor/customtypenentry.h @@ -10,7 +10,7 @@ class CustomTypeEntry : public TypeEntry { public: explicit CustomTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); TypeEntry *clone() const override; diff --git a/sources/shiboken6/ApiExtractor/debughelpers_p.h b/sources/shiboken6/ApiExtractor/debughelpers_p.h new file mode 100644 index 000000000..81ebbb3b9 --- /dev/null +++ b/sources/shiboken6/ApiExtractor/debughelpers_p.h @@ -0,0 +1,56 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef DEBUGHELPERS_P_H +#define DEBUGHELPERS_P_H + +#include <QtCore/QDebug> +#include <memory> + +template <class T> +inline QDebug operator<<(QDebug debug, const std::shared_ptr<T> &ptr) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + debug << "std::shared_ptr(" << ptr.get() << ")"; + return debug; +} + +template <class It> +inline void formatSequence(QDebug &d, It i1, It i2, + const char *separator=", ") +{ + for (It i = i1; i != i2; ++i) { + if (i != i1) + d << separator; + d << *i; + } +} + +template <class It> +inline static void formatPtrSequence(QDebug &d, It i1, It i2, + const char *separator=", ") +{ + for (It i = i1; i != i2; ++i) { + if (i != i1) + d << separator; + d << i->get(); + } +} + +template <class Container> +static void formatList(QDebug &d, const char *name, const Container &c, + const char *separator=", ") +{ + if (const auto size = c.size()) { + d << ", " << name << '[' << size << "]=("; + for (qsizetype i = 0; i < size; ++i) { + if (i) + d << separator; + d << c.at(i); + } + d << ')'; + } +} + +#endif // DEBUGHELPERS_P_H diff --git a/sources/shiboken6/ApiExtractor/dependency.h b/sources/shiboken6/ApiExtractor/dependency.h index f0e525e26..aa280de03 100644 --- a/sources/shiboken6/ApiExtractor/dependency.h +++ b/sources/shiboken6/ApiExtractor/dependency.h @@ -13,8 +13,8 @@ class AbstractMetaClass; struct Dependency { - AbstractMetaClass *parent; - AbstractMetaClass *child; + AbstractMetaClassPtr parent; + AbstractMetaClassPtr child; }; using Dependencies = QList<Dependency>; diff --git a/sources/shiboken6/ApiExtractor/docparser.cpp b/sources/shiboken6/ApiExtractor/docparser.cpp index ea3828a43..468fe1098 100644 --- a/sources/shiboken6/ApiExtractor/docparser.cpp +++ b/sources/shiboken6/ApiExtractor/docparser.cpp @@ -1,15 +1,17 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + #include "docparser.h" -#include "classdocumentation.h" +#include "abstractmetaargument.h" #include "abstractmetaenum.h" -#include "abstractmetafield.h" #include "abstractmetafunction.h" #include "abstractmetalang.h" +#include "abstractmetatype.h" #include "messages.h" #include "modifications.h" #include "reporthandler.h" -#include "typesystem.h" +#include "enumtypeentry.h" +#include "complextypeentry.h" #include "xmlutils.h" #include <QtCore/QBuffer> @@ -29,15 +31,37 @@ using namespace Qt::StringLiterals; -DocParser::DocParser() +static inline bool isXpathDocModification(const DocModification &mod) { -#ifdef HAVE_LIBXSLT - xmlSubstituteEntitiesDefault(1); -#endif + return mod.mode() == TypeSystem::DocModificationXPathReplace; +} + +static inline bool isNotXpathDocModification(const DocModification &mod) +{ + return mod.mode() != TypeSystem::DocModificationXPathReplace; +} + +static void removeXpathDocModifications(DocModificationList *l) +{ + l->erase(std::remove_if(l->begin(), l->end(), isXpathDocModification), l->end()); +} + +static void removeNonXpathDocModifications(DocModificationList *l) +{ + l->erase(std::remove_if(l->begin(), l->end(), isNotXpathDocModification), l->end()); } +DocParser::DocParser() = default; DocParser::~DocParser() = default; +void DocParser::fillGlobalFunctionDocumentation(const AbstractMetaFunctionPtr &) +{ +} + +void DocParser::fillGlobalEnumDocumentation(AbstractMetaEnum &) +{ +} + QString DocParser::getDocumentation(const XQueryPtr &xquery, const QString& query, const DocModificationList& mods) { @@ -84,22 +108,90 @@ bool DocParser::skipForQuery(const AbstractMetaFunctionCPtr &func) usesRValueReference); } -AbstractMetaFunctionCList DocParser::documentableFunctions(const AbstractMetaClass *metaClass) +DocModificationList DocParser::getDocModifications(const AbstractMetaClassCPtr &cppClass) + +{ + auto result = cppClass->typeEntry()->docModifications(); + removeXpathDocModifications(&result); + return result; +} + +static void filterBySignature(const AbstractMetaFunctionCPtr &func, DocModificationList *l) { - auto result = metaClass->functionsInTargetLang(); - for (int i = result.size() - 1; i >= 0; --i) { - if (DocParser::skipForQuery(result.at(i)) || result.at(i)->isUserAdded()) - result.removeAt(i); + if (!l->isEmpty()) { + const QString minimalSignature = func->minimalSignature(); + const auto filter = [&minimalSignature](const DocModification &mod) { + return mod.signature() != minimalSignature; + }; + l->erase(std::remove_if(l->begin(), l->end(), filter), l->end()); + } +} + +DocModificationList DocParser::getDocModifications(const AbstractMetaFunctionCPtr &func, + const AbstractMetaClassCPtr &cppClass) +{ + DocModificationList result; + if (func->isUserAdded()) { + result = func->addedFunctionDocModifications(); + removeXpathDocModifications(&result); + } else if (cppClass != nullptr) { + result = cppClass->typeEntry()->functionDocModifications(); + removeXpathDocModifications(&result); + filterBySignature(func, &result); } return result; } -static inline bool isXpathDocModification(const DocModification &mod) +DocModificationList DocParser::getXpathDocModifications(const AbstractMetaClassCPtr &cppClass) { - return mod.mode() == TypeSystem::DocModificationXPathReplace; + auto result = cppClass->typeEntry()->docModifications(); + removeNonXpathDocModifications(&result); + return result; } -QString DocParser::applyDocModifications(const DocModificationList& mods, const QString& xml) +DocModificationList DocParser::getXpathDocModifications(const AbstractMetaFunctionCPtr &func, + const AbstractMetaClassCPtr &cppClass) +{ + DocModificationList result; + if (func->isUserAdded()) { + result = func->addedFunctionDocModifications(); + removeNonXpathDocModifications(&result); + } else if (cppClass != nullptr) { + result = cppClass->typeEntry()->functionDocModifications(); + removeNonXpathDocModifications(&result); + filterBySignature(func, &result); + } + return result; +} + +QString DocParser::enumBaseClass(const AbstractMetaEnum &e) +{ + switch (e.typeEntry()->pythonEnumType()) { + case TypeSystem::PythonEnumType::IntEnum: + return u"IntEnum"_s; + case TypeSystem::PythonEnumType::Flag: + return u"Flag"_s; + case TypeSystem::PythonEnumType::IntFlag: + return u"IntFlag"_s; + default: + break; + } + return e.typeEntry()->flags() != nullptr ? u"Flag"_s : u"Enum"_s; +} + +AbstractMetaFunctionCList DocParser::documentableFunctions(const AbstractMetaClassCPtr &metaClass) +{ + auto result = metaClass->functionsInTargetLang(); + for (auto i = result.size() - 1; i >= 0; --i) { + if (DocParser::skipForQuery(result.at(i)) || result.at(i)->isUserAdded()) + result.removeAt(i); + } + result.append(metaClass->cppSignalFunctions()); + return result; +} + +QString DocParser::applyDocModifications(const DocModificationList& xpathMods, + const QString& xml) { const char xslPrefix[] = R"(<xsl:template match="/"> @@ -113,32 +205,28 @@ R"(<xsl:template match="/"> </xsl:template> )"; - if (mods.isEmpty() || xml.isEmpty() - || !std::any_of(mods.cbegin(), mods.cend(), isXpathDocModification)) { + if (xpathMods.isEmpty() || xml.isEmpty()) return xml; - } QString xsl = QLatin1StringView(xslPrefix); - for (const DocModification &mod : mods) { - if (isXpathDocModification(mod)) { - QString xpath = mod.xpath(); - xpath.replace(u'"', u"""_s); - xsl += u"<xsl:template match=\""_s - + xpath + u"\">"_s - + mod.code() + u"</xsl:template>\n"_s; - } + for (const DocModification &mod : xpathMods) { + Q_ASSERT(isXpathDocModification(mod)); + QString xpath = mod.xpath(); + xpath.replace(u'"', u"""_s); + xsl += "<xsl:template match=\""_L1 + xpath + "\">"_L1 + + mod.code() + "</xsl:template>\n"_L1; } QString errorMessage; const QString result = xsl_transform(xml, xsl, &errorMessage); if (!errorMessage.isEmpty()) qCWarning(lcShibokenDoc, "%s", - qPrintable(msgXpathDocModificationError(mods, errorMessage))); + qPrintable(msgXpathDocModificationError(xpathMods, errorMessage))); if (result == xml) { const QString message = u"Query did not result in any modifications to \""_s + xml + u'"'; qCWarning(lcShibokenDoc, "%s", - qPrintable(msgXpathDocModificationError(mods, message))); + qPrintable(msgXpathDocModificationError(xpathMods, message))); } return result; } diff --git a/sources/shiboken6/ApiExtractor/docparser.h b/sources/shiboken6/ApiExtractor/docparser.h index bf305272a..6d458b25a 100644 --- a/sources/shiboken6/ApiExtractor/docparser.h +++ b/sources/shiboken6/ApiExtractor/docparser.h @@ -3,11 +3,12 @@ #ifndef DOCPARSER_H #define DOCPARSER_H -#include "typesystem_typedefs.h" #include "abstractmetalang_typedefs.h" +#include "modifications_typedefs.h" #include <QtCore/QString> -#include <QtCore/QSharedPointer> + +#include <memory> class AbstractMetaClass; class DocModification; @@ -20,13 +21,15 @@ struct FunctionDocumentation; class DocParser { public: - Q_DISABLE_COPY(DocParser) + Q_DISABLE_COPY_MOVE(DocParser) - using XQueryPtr = QSharedPointer<XQuery>; + using XQueryPtr = std::shared_ptr<XQuery>; DocParser(); virtual ~DocParser(); - virtual void fillDocumentation(AbstractMetaClass* metaClass) = 0; + virtual void fillDocumentation(const AbstractMetaClassPtr &metaClass) = 0; + virtual void fillGlobalFunctionDocumentation(const AbstractMetaFunctionPtr &f); + virtual void fillGlobalEnumDocumentation(AbstractMetaEnum &e); /** * Process and retrieves documentation concerning the entire @@ -91,14 +94,25 @@ public: static bool skipForQuery(const AbstractMetaFunctionCPtr &func); + /// Helper to return the documentation modifications for a class + /// or a member function. + static DocModificationList getDocModifications(const AbstractMetaClassCPtr &cppClass); + static DocModificationList getDocModifications(const AbstractMetaFunctionCPtr &func, + const AbstractMetaClassCPtr &cppClass = {}); + static DocModificationList getXpathDocModifications(const AbstractMetaClassCPtr &cppClass); + static DocModificationList getXpathDocModifications(const AbstractMetaFunctionCPtr &func, + const AbstractMetaClassCPtr &cppClass = {}); + + static QString enumBaseClass(const AbstractMetaEnum &e); + protected: static QString getDocumentation(const XQueryPtr &xquery, const QString &query, const DocModificationList &mods); - static AbstractMetaFunctionCList documentableFunctions(const AbstractMetaClass *metaClass); + static AbstractMetaFunctionCList documentableFunctions(const AbstractMetaClassCPtr &metaClass); - static QString applyDocModifications(const DocModificationList &mods, const QString &xml); + static QString applyDocModifications(const DocModificationList &xpathMods, const QString &xml); private: QString m_packageName; diff --git a/sources/shiboken6/ApiExtractor/documentation.cpp b/sources/shiboken6/ApiExtractor/documentation.cpp index 6c4d7166e..33cf0e9fb 100644 --- a/sources/shiboken6/ApiExtractor/documentation.cpp +++ b/sources/shiboken6/ApiExtractor/documentation.cpp @@ -35,12 +35,6 @@ void Documentation::setFormat(Documentation::Format f) m_format = f; } -bool Documentation::equals(const Documentation &rhs) const -{ - return m_format == rhs.m_format && m_detailed == rhs.m_detailed - && m_brief == rhs.m_brief; -} - void Documentation::setDetailed(const QString &detailed) { m_detailed = detailed.trimmed(); diff --git a/sources/shiboken6/ApiExtractor/documentation.h b/sources/shiboken6/ApiExtractor/documentation.h index a18bb1a13..df9d5d614 100644 --- a/sources/shiboken6/ApiExtractor/documentation.h +++ b/sources/shiboken6/ApiExtractor/documentation.h @@ -5,6 +5,7 @@ #define DOCUMENTATION_H #include <QtCore/QString> +#include <QtCore/QtCompare> QT_FORWARD_DECLARE_CLASS(QDebug) @@ -44,16 +45,19 @@ public: void setBrief(const QString &brief); private: + friend bool comparesEqual(const Documentation &lhs, + const Documentation &rhs) noexcept + { + return lhs.m_format == rhs.m_format && lhs.m_detailed == rhs.m_detailed + && lhs.m_brief == rhs.m_brief; + } + Q_DECLARE_EQUALITY_COMPARABLE(Documentation) + QString m_detailed; QString m_brief; Format m_format = Documentation::Native; }; -inline bool operator==(const Documentation &d1, const Documentation &d2) -{ return d1.equals(d2); } -inline bool operator!=(const Documentation &d1, const Documentation &d2) -{ return !d1.equals(d2); } - #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, const Documentation &); #endif diff --git a/sources/shiboken6/ApiExtractor/dotview.cpp b/sources/shiboken6/ApiExtractor/dotview.cpp index 4fd795a84..0bd192257 100644 --- a/sources/shiboken6/ApiExtractor/dotview.cpp +++ b/sources/shiboken6/ApiExtractor/dotview.cpp @@ -9,12 +9,14 @@ #include <QtCore/QProcess> #include <QtCore/QTemporaryFile> +using namespace Qt::StringLiterals; + bool showDotGraph(const QString &name, const QString &graph) { - const QString imageType = u"jpg"_qs; + constexpr auto imageType = "jpg"_L1; // Write out the graph to a temporary file - QTemporaryFile dotFile(QDir::tempPath() + u'/' + name + u"_XXXXXX.dot"_qs); + QTemporaryFile dotFile(QDir::tempPath() + u'/' + name + u"_XXXXXX.dot"_s); if (!dotFile.open()) { qWarning("Cannot open temporary file: %s", qPrintable(dotFile.errorString())); return false; @@ -26,7 +28,7 @@ bool showDotGraph(const QString &name, const QString &graph) // Convert to image using "dot" const QString imageFile = tempDotFile.left(tempDotFile.size() - 3) + imageType; QProcess process; - process.start(u"dot"_qs, {u"-T"_qs + imageType, u"-o"_qs + imageFile, tempDotFile}); + process.start(u"dot"_s, {u"-T"_s + imageType, u"-o"_s + imageFile, tempDotFile}); if (!process.waitForStarted() || !process.waitForFinished()) { qWarning("Image conversion failed: %s", qPrintable(process.errorString())); return false; @@ -41,9 +43,9 @@ bool showDotGraph(const QString &name, const QString &graph) // Launch image. Should use QDesktopServices::openUrl(), // but we don't link against QtGui #ifdef Q_OS_UNIX - const QString imageViewer = u"gwenview"_qs; + constexpr auto imageViewer = "gwenview"_L1; #else - const QString imageViewer = u"mspaint"_qs; + constexpr auto imageViewer = "mspaint"_L1; #endif if (!QProcess::startDetached(imageViewer, {imageFile})) { qWarning("Failed to launch viewer: %s", qPrintable(imageViewer)); diff --git a/sources/shiboken6/ApiExtractor/doxygenparser.cpp b/sources/shiboken6/ApiExtractor/doxygenparser.cpp index b8d97a748..da790015f 100644 --- a/sources/shiboken6/ApiExtractor/doxygenparser.cpp +++ b/sources/shiboken6/ApiExtractor/doxygenparser.cpp @@ -2,10 +2,12 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "doxygenparser.h" +#include "abstractmetaargument.h" #include "abstractmetalang.h" #include "abstractmetafield.h" #include "abstractmetafunction.h" #include "abstractmetaenum.h" +#include "abstractmetatype.h" #include "documentation.h" #include "messages.h" #include "modifications.h" @@ -39,7 +41,7 @@ Documentation DoxygenParser::retrieveModuleDocumentation() return retrieveModuleDocumentation(packageName()); } -void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) +void DoxygenParser::fillDocumentation(const AbstractMetaClassPtr &metaClass) { if (!metaClass) return; @@ -52,13 +54,12 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) doxyFileSuffix += metaClass->name(); doxyFileSuffix += u".xml"_s; - const char* prefixes[] = { "class", "struct", "namespace" }; + static constexpr QLatin1StringView prefixes[] = { "class"_L1, "struct"_L1, "namespace"_L1 }; bool isProperty = false; QString doxyFilePath; - for (const char *prefix : prefixes) { - doxyFilePath = documentationDataDirectory() + u'/' - + QLatin1StringView(prefix) + doxyFileSuffix; + for (const auto &prefix : prefixes) { + doxyFilePath = documentationDataDirectory() + u'/' + prefix + doxyFileSuffix; if (QFile::exists(doxyFilePath)) break; doxyFilePath.clear(); @@ -74,12 +75,12 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) QString errorMessage; XQueryPtr xquery = XQuery::create(doxyFilePath, &errorMessage); - if (xquery.isNull()) { + if (!xquery) { qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); return; } - static const QList<QPair<Documentation::Type, QString>> docTags = { + static const QList<std::pair<Documentation::Type, QString>> docTags = { { Documentation::Brief, u"briefdescription"_s }, { Documentation::Detailed, u"detaileddescription"_s } }; @@ -117,7 +118,7 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) + func->originalName() + u"\"]"_s; if (func->arguments().isEmpty()) { - QString args = func->isConstant() ? u"() const "_s : u"()"_s; + QString args = func->isConstant() ? u"() const"_s : u"()"_s; query += u"/../argsstring[text()=\""_s + args + u"\"]"_s; } else { int i = 1; @@ -148,16 +149,17 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) funcQuery += u"/../"_s + tag.second + u")[1]"_s; } - QString doc = getDocumentation(xquery, funcQuery, DocModificationList()); + QString doc = getDocumentation(xquery, funcQuery, + DocParser::getXpathDocModifications(func, metaClass)); if (doc.isEmpty()) { qCWarning(lcShibokenDoc, "%s", - qPrintable(msgCannotFindDocumentation(doxyFilePath, func.data(), + qPrintable(msgCannotFindDocumentation(doxyFilePath, func.get(), funcQuery))); } else { funcDoc.setValue(doc, tag.first); } } - qSharedPointerConstCast<AbstractMetaFunction>(func)->setDocumentation(funcDoc); + std::const_pointer_cast<AbstractMetaFunction>(func)->setDocumentation(funcDoc); isProperty = false; } @@ -204,12 +206,12 @@ Documentation DoxygenParser::retrieveModuleDocumentation(const QString& name){ qCWarning(lcShibokenDoc).noquote().nospace() << "Can't find doxygen XML file for module " << name << ", tried: " << QDir::toNativeSeparators(sourceFile); - return Documentation(); + return {}; } QString errorMessage; XQueryPtr xquery = XQuery::create(sourceFile, &errorMessage); - if (xquery.isNull()) { + if (!xquery) { qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); return {}; } diff --git a/sources/shiboken6/ApiExtractor/doxygenparser.h b/sources/shiboken6/ApiExtractor/doxygenparser.h index ea1883d12..4f6a9e53c 100644 --- a/sources/shiboken6/ApiExtractor/doxygenparser.h +++ b/sources/shiboken6/ApiExtractor/doxygenparser.h @@ -10,7 +10,7 @@ class DoxygenParser : public DocParser { public: DoxygenParser() = default; - void fillDocumentation(AbstractMetaClass *metaClass) override; + void fillDocumentation(const AbstractMetaClassPtr &metaClass) override; Documentation retrieveModuleDocumentation() override; Documentation retrieveModuleDocumentation(const QString& name) override; }; diff --git a/sources/shiboken6/ApiExtractor/enclosingclassmixin.cpp b/sources/shiboken6/ApiExtractor/enclosingclassmixin.cpp index f2d5074b7..2421ae527 100644 --- a/sources/shiboken6/ApiExtractor/enclosingclassmixin.cpp +++ b/sources/shiboken6/ApiExtractor/enclosingclassmixin.cpp @@ -5,9 +5,9 @@ #include "abstractmetalang.h" #include "namespacetypeentry.h" -const AbstractMetaClass *EnclosingClassMixin::targetLangEnclosingClass() const +AbstractMetaClassCPtr EnclosingClassMixin::targetLangEnclosingClass() const { - auto result = m_enclosingClass; + auto result = m_enclosingClass.lock(); while (result && !NamespaceTypeEntry::isVisibleScope(result->typeEntry())) result = result->enclosingClass(); return result; diff --git a/sources/shiboken6/ApiExtractor/enclosingclassmixin.h b/sources/shiboken6/ApiExtractor/enclosingclassmixin.h index 31aeb9285..8d735d5ec 100644 --- a/sources/shiboken6/ApiExtractor/enclosingclassmixin.h +++ b/sources/shiboken6/ApiExtractor/enclosingclassmixin.h @@ -4,16 +4,21 @@ #ifndef ENCLOSINGCLASSMIXIN_H #define ENCLOSINGCLASSMIXIN_H +#include "abstractmetalang_typedefs.h" + class AbstractMetaClass; class EnclosingClassMixin { public: - const AbstractMetaClass *enclosingClass() const { return m_enclosingClass; } - void setEnclosingClass(const AbstractMetaClass *cls) { m_enclosingClass = cls; } - const AbstractMetaClass *targetLangEnclosingClass() const; + + const AbstractMetaClassCPtr enclosingClass() const + { return m_enclosingClass.lock(); } + void setEnclosingClass(const AbstractMetaClassCPtr &cls) + { m_enclosingClass = cls; } + AbstractMetaClassCPtr targetLangEnclosingClass() const; private: - const AbstractMetaClass *m_enclosingClass = nullptr; + std::weak_ptr<const AbstractMetaClass> m_enclosingClass; }; #endif // ENCLOSINGCLASSMIXIN_H diff --git a/sources/shiboken6/ApiExtractor/enumtypeentry.h b/sources/shiboken6/ApiExtractor/enumtypeentry.h index f575de956..3360d7db5 100644 --- a/sources/shiboken6/ApiExtractor/enumtypeentry.h +++ b/sources/shiboken6/ApiExtractor/enumtypeentry.h @@ -4,18 +4,18 @@ #ifndef ENUMTYPEENTRY_H #define ENUMTYPEENTRY_H -#include "typesystem.h" +#include "configurabletypeentry.h" +#include "typesystem_enums.h" class EnumTypeEntryPrivate; -class EnumValueTypeEntry; -class FlagsTypeEntry; -class EnumTypeEntry : public TypeEntry +// EnumTypeEntry is configurable for global enums only +class EnumTypeEntry : public ConfigurableTypeEntry { public: explicit EnumTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); TypeSystem::PythonEnumType pythonEnumType() const; void setPythonEnumType(TypeSystem::PythonEnumType t); @@ -24,16 +24,22 @@ public: QString qualifier() const; - const EnumValueTypeEntry *nullValue() const; - void setNullValue(const EnumValueTypeEntry *n); + EnumValueTypeEntryCPtr nullValue() const; + void setNullValue(const EnumValueTypeEntryCPtr &n); - void setFlags(FlagsTypeEntry *flags); - FlagsTypeEntry *flags() const; + void setFlags(const FlagsTypeEntryPtr &flags); + FlagsTypeEntryPtr flags() const; + + QString cppType() const; + void setCppType(const QString &t); bool isEnumValueRejected(const QString &name) const; void addEnumValueRejection(const QString &name); QStringList enumValueRejections() const; + QString docFile() const; + void setDocFile(const QString &df); + TypeEntry *clone() const override; #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; diff --git a/sources/shiboken6/ApiExtractor/enumvaluetypeentry.h b/sources/shiboken6/ApiExtractor/enumvaluetypeentry.h index 730631b0a..006b84e0a 100644 --- a/sources/shiboken6/ApiExtractor/enumvaluetypeentry.h +++ b/sources/shiboken6/ApiExtractor/enumvaluetypeentry.h @@ -16,11 +16,11 @@ class EnumValueTypeEntry : public TypeEntry { public: explicit EnumValueTypeEntry(const QString& name, const QString& value, - const EnumTypeEntry* enclosingEnum, + const EnumTypeEntryCPtr &enclosingEnum, bool isScopedEnum, const QVersionNumber &vr); QString value() const; - const EnumTypeEntry* enclosingEnum() const; + EnumTypeEntryCPtr enclosingEnum() const; TypeEntry *clone() const override; diff --git a/sources/shiboken6/ApiExtractor/fileout.cpp b/sources/shiboken6/ApiExtractor/fileout.cpp index e6770aabc..6f9ec4d8a 100644 --- a/sources/shiboken6/ApiExtractor/fileout.cpp +++ b/sources/shiboken6/ApiExtractor/fileout.cpp @@ -42,20 +42,20 @@ FileOut::~FileOut() } } -static QList<int> lcsLength(const QByteArrayList &a, const QByteArrayList &b) +static QList<qsizetype> lcsLength(const QByteArrayList &a, const QByteArrayList &b) { - const int height = a.size() + 1; - const int width = b.size() + 1; + const auto height = a.size() + 1; + const auto width = b.size() + 1; - QList<int> res(width * height, 0); + QList<qsizetype> res(width * height, 0); - for (int row = 1; row < height; row++) { - for (int col = 1; col < width; col++) { - if (a[row-1] == b[col-1]) - res[width * row + col] = res[width * (row-1) + col-1] + 1; + for (qsizetype row = 1; row < height; row++) { + for (qsizetype col = 1; col < width; col++) { + if (a.at(row - 1) == b.at(col - 1)) + res[width * row + col] = res[width * (row - 1) + col - 1] + 1; else - res[width * row + col] = qMax(res[width * row + col-1], - res[width * (row-1) + col]); + res[width * row + col] = qMax(res[width * row + col - 1], + res[width * (row - 1) + col]); } } return res; @@ -70,8 +70,8 @@ enum Type { struct Unit { Type type; - int start; - int end; + qsizetype start; + qsizetype end; void print(const QByteArrayList &a, const QByteArrayList &b) const; }; @@ -81,33 +81,33 @@ void Unit::print(const QByteArrayList &a, const QByteArrayList &b) const switch (type) { case Unchanged: if ((end - start) > 9) { - for (int i = start; i <= start + 2; i++) + for (auto i = start; i <= start + 2; ++i) std::printf(" %s\n", a.at(i).constData()); std::printf("%s=\n= %d more lines\n=%s\n", - colorInfo, end - start - 6, colorReset); - for (int i = end - 2; i <= end; i++) + colorInfo, int(end - start - 6), colorReset); + for (auto i = end - 2; i <= end; ++i) std::printf(" %s\n", a.at(i).constData()); } else { - for (int i = start; i <= end; i++) + for (auto i = start; i <= end; ++i) std::printf(" %s\n", a.at(i).constData()); } break; case Add: std::fputs(colorAdd, stdout); - for (int i = start; i <= end; i++) + for (auto i = start; i <= end; ++i) std::printf("+ %s\n", b.at(i).constData()); std::fputs(colorReset, stdout); break; case Delete: std::fputs(colorDelete, stdout); - for (int i = start; i <= end; i++) + for (auto i = start; i <= end; ++i) std::printf("- %s\n", a.at(i).constData()); std::fputs(colorReset, stdout); break; } } -static void unitAppend(Type type, int pos, QList<Unit> *units) +static void unitAppend(Type type, qsizetype pos, QList<Unit> *units) { if (!units->isEmpty() && units->last().type == type) units->last().end = pos; @@ -115,9 +115,9 @@ static void unitAppend(Type type, int pos, QList<Unit> *units) units->append(Unit{type, pos, pos}); } -static QList<Unit> diffHelper(const QList<int> &lcs, - const QByteArrayList &a, const QByteArrayList &b, - int row, int col) +static QList<Unit> diffHelper(const QList<qsizetype> &lcs, + const QByteArrayList &a, const QByteArrayList &b, + qsizetype row, qsizetype col) { if (row > 0 && col > 0 && a.at(row - 1) == b.at(col - 1)) { QList<Unit> result = diffHelper(lcs, a, b, row - 1, col - 1); @@ -125,7 +125,7 @@ static QList<Unit> diffHelper(const QList<int> &lcs, return result; } - const int width = b.size() + 1; + const auto width = b.size() + 1; if (col > 0 && (row == 0 || lcs.at(width * row + col -1 ) >= lcs.at(width * (row - 1) + col))) { QList<Unit> result = diffHelper(lcs, a, b, row, col - 1); @@ -175,7 +175,7 @@ FileOut::State FileOut::done() if (!FileOut::m_dryRun) { QDir dir(info.absolutePath()); if (!dir.mkpath(dir.absolutePath())) { - const QString message = QStringLiteral("Unable to create directory '%1'") + const QString message = QString::fromLatin1("Unable to create directory '%1'") .arg(QDir::toNativeSeparators(dir.absolutePath())); throw Exception(message); } diff --git a/sources/shiboken6/ApiExtractor/fileout.h b/sources/shiboken6/ApiExtractor/fileout.h index d3f1b7b1f..b11ad1e20 100644 --- a/sources/shiboken6/ApiExtractor/fileout.h +++ b/sources/shiboken6/ApiExtractor/fileout.h @@ -14,7 +14,7 @@ class FileOut { QByteArray m_buffer; public: - Q_DISABLE_COPY(FileOut) + Q_DISABLE_COPY_MOVE(FileOut) enum State { Unchanged, Success }; diff --git a/sources/shiboken6/ApiExtractor/flagstypeentry.h b/sources/shiboken6/ApiExtractor/flagstypeentry.h index 172407d1b..6eddcd12b 100644 --- a/sources/shiboken6/ApiExtractor/flagstypeentry.h +++ b/sources/shiboken6/ApiExtractor/flagstypeentry.h @@ -9,11 +9,12 @@ class EnumTypeEntry; class FlagsTypeEntryPrivate; +// FlagsTypeEntry is configurable for global flags only class FlagsTypeEntry : public TypeEntry { public: explicit FlagsTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); QString originalName() const; void setOriginalName(const QString &s); @@ -21,8 +22,8 @@ public: QString flagsName() const; void setFlagsName(const QString &name); - EnumTypeEntry *originator() const; - void setOriginator(EnumTypeEntry *e); + EnumTypeEntryPtr originator() const; + void setOriginator(const EnumTypeEntryPtr &e); TypeEntry *clone() const override; diff --git a/sources/shiboken6/ApiExtractor/functiontypeentry.h b/sources/shiboken6/ApiExtractor/functiontypeentry.h index 3d7399931..53aa1fad6 100644 --- a/sources/shiboken6/ApiExtractor/functiontypeentry.h +++ b/sources/shiboken6/ApiExtractor/functiontypeentry.h @@ -13,14 +13,14 @@ class FunctionTypeEntry : public TypeEntry public: explicit FunctionTypeEntry(const QString& name, const QString& signature, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); const QStringList &signatures() const; bool hasSignature(const QString& signature) const; void addSignature(const QString& signature); - TypeSystem::SnakeCase snakeCase() const; - void setSnakeCase(TypeSystem::SnakeCase sc); + QString docFile() const; + void setDocFile(const QString &df); TypeEntry *clone() const override; diff --git a/sources/shiboken6/ApiExtractor/header_paths.h b/sources/shiboken6/ApiExtractor/header_paths.h index ca00a5360..af4a768e8 100644 --- a/sources/shiboken6/ApiExtractor/header_paths.h +++ b/sources/shiboken6/ApiExtractor/header_paths.h @@ -6,7 +6,6 @@ #include <QtCore/QByteArray> #include <QtCore/QList> -#include <QtCore/QString> enum class HeaderType { diff --git a/sources/shiboken6/ApiExtractor/icecc.cmake b/sources/shiboken6/ApiExtractor/icecc.cmake index b2bf071aa..fa8d3b7cf 100644 --- a/sources/shiboken6/ApiExtractor/icecc.cmake +++ b/sources/shiboken6/ApiExtractor/icecc.cmake @@ -1,3 +1,6 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + include (CMakeForceCompiler) option(ENABLE_ICECC "Enable icecc checking, for distributed compilation") if (ENABLE_ICECC) diff --git a/sources/shiboken6/ApiExtractor/include.cpp b/sources/shiboken6/ApiExtractor/include.cpp index 634945ed8..aee6b7337 100644 --- a/sources/shiboken6/ApiExtractor/include.cpp +++ b/sources/shiboken6/ApiExtractor/include.cpp @@ -24,9 +24,15 @@ QString Include::toString() const return u"import "_s + m_name + u';'; } -size_t qHash(const Include& inc) +Qt::strong_ordering compareThreeWay(const Include &lhs, const Include &rhs) noexcept { - return qHash(inc.m_name); + if (lhs.m_type < rhs.m_type) + return Qt::strong_ordering::less; + if (lhs.m_type > rhs.m_type) + return Qt::strong_ordering::greater; + if (auto c = lhs.m_name.compare(rhs.m_name)) + return c < 0 ? Qt::strong_ordering::less : Qt::strong_ordering::greater; + return Qt::strong_ordering::equal; } QTextStream& operator<<(QTextStream& out, const Include& g) @@ -50,7 +56,7 @@ TextStream& operator<<(TextStream &out, const IncludeGroup& g) out << "\n// " << g.title << "\n"; auto includes = g.includes; std::sort(includes.begin(), includes.end()); - for (const Include &inc : qAsConst(includes)) + for (const Include &inc : std::as_const(includes)) out << inc.toString() << '\n'; } return out; diff --git a/sources/shiboken6/ApiExtractor/include.h b/sources/shiboken6/ApiExtractor/include.h index 6b463a230..875a941f9 100644 --- a/sources/shiboken6/ApiExtractor/include.h +++ b/sources/shiboken6/ApiExtractor/include.h @@ -4,6 +4,8 @@ #ifndef INCLUDE_H #define INCLUDE_H +#include <QtCore/QtCompare> +#include <QtCore/QHashFunctions> #include <QtCore/QString> #include <QtCore/QList> @@ -42,23 +44,25 @@ public: QString toString() const; - bool operator<(const Include& other) const + int compare(const Include &rhs) const; + +private: + friend size_t qHash(Include &inc, size_t seed = 0) noexcept { - return m_name < other.m_name; + return qHashMulti(seed, inc.m_type, inc.m_name); } - - bool operator==(const Include& other) const + friend bool comparesEqual(const Include &lhs, const Include &rhs) noexcept { - return m_type == other.m_type && m_name == other.m_name; + return lhs.m_type == rhs.m_type && lhs.m_name == rhs.m_name; } + friend Qt::strong_ordering compareThreeWay(const Include &lhs, + const Include &rhs) noexcept; + Q_DECLARE_STRONGLY_ORDERED(Include) - friend size_t qHash(const Include&); - private: - IncludeType m_type = IncludePath; - QString m_name; + IncludeType m_type = IncludePath; + QString m_name; }; -size_t qHash(const Include& inc); QTextStream& operator<<(QTextStream& out, const Include& include); TextStream& operator<<(TextStream& out, const Include& include); #ifndef QT_NO_DEBUG_STREAM @@ -71,6 +75,17 @@ struct IncludeGroup { QString title; IncludeList includes; + + void append(const Include &include) + { + IncludeGroup::appendInclude(include, &includes); + } + + static void appendInclude(const Include &include, IncludeList *list) + { + if (include.isValid() && !list->contains(include)) + list->append(include); + } }; TextStream& operator<<(TextStream &out, const IncludeGroup& include); diff --git a/sources/shiboken6/ApiExtractor/messages.cpp b/sources/shiboken6/ApiExtractor/messages.cpp index e91aef5cc..170595660 100644 --- a/sources/shiboken6/ApiExtractor/messages.cpp +++ b/sources/shiboken6/ApiExtractor/messages.cpp @@ -16,7 +16,6 @@ #include "qtcompat.h" -#include <QtCore/QCoreApplication> #include <QtCore/QDebug> #include <QtCore/QDir> #include <QtCore/QFile> @@ -25,11 +24,25 @@ using namespace Qt::StringLiterals; -static inline QString colonColon() { return QStringLiteral("::"); } - // abstractmetabuilder.cpp -QString msgNoFunctionForModification(const AbstractMetaClass *klass, +static QTextStream &operator<<(QTextStream &s, Access a) +{ + switch (a) { + case Access::Public: + s << "public"; + break; + case Access::Protected: + s << "protected"; + break; + case Access::Private: + s << "private"; + break; + } + return s; +} + +QString msgNoFunctionForModification(const AbstractMetaClassCPtr &klass, const QString &signature, const QString &originalSignature, const QStringList &possibleSignatures, @@ -49,8 +62,8 @@ QString msgNoFunctionForModification(const AbstractMetaClass *klass, str << " " << s << '\n'; } else if (!allFunctions.isEmpty()) { str << "\n No candidates were found. Member functions:\n"; - const int maxCount = qMin(10, allFunctions.size()); - for (int f = 0; f < maxCount; ++f) + const auto maxCount = qMin(qsizetype(10), allFunctions.size()); + for (qsizetype f = 0; f < maxCount; ++f) str << " " << allFunctions.at(f)->minimalSignature() << '\n'; if (maxCount < allFunctions.size()) str << " ...\n"; @@ -79,7 +92,7 @@ QString msgTypeModificationFailed(const QString &type, int n, str << "type of argument " << n; str << " of "; - if (auto *c = func->ownerClass()) + if (auto c = func->ownerClass()) str << c->name() << "::"; str << func->signature() << " to \"" << type << "\": " << why; return result; @@ -113,7 +126,7 @@ QString msgArgumentRemovalFailed(const AbstractMetaFunction *func, int n, QString result; QTextStream str(&result); str << "Unable to remove argument " << n << " of "; - if (auto *c = func->ownerClass()) + if (auto c = func->ownerClass()) str << c->name() << "::"; str << func->signature() << ": " << why; return result; @@ -126,7 +139,7 @@ static void msgFormatEnumType(Stream &str, { switch (enumItem->enumKind()) { case CEnum: - str << "Enum '" << enumItem->qualifiedName().join(colonColon()) << '\''; + str << "Enum '" << enumItem->qualifiedName().join(u"::"_s) << '\''; break; case AnonymousEnum: { const EnumeratorList &values = enumItem->enumerators(); @@ -149,7 +162,7 @@ static void msgFormatEnumType(Stream &str, } break; case EnumClass: - str << "Scoped enum '" << enumItem->qualifiedName().join(colonColon()) << '\''; + str << "Scoped enum '" << enumItem->qualifiedName().join(u"::"_s) << '\''; break; } if (!className.isEmpty()) @@ -157,7 +170,7 @@ static void msgFormatEnumType(Stream &str, } static void formatAddedFuncError(const QString &addedFuncName, - const AbstractMetaClass *context, + const AbstractMetaClassCPtr &context, QTextStream &str) { if (context) { @@ -173,12 +186,12 @@ static void formatAddedFuncError(const QString &addedFuncName, QString msgAddedFunctionInvalidArgType(const QString &addedFuncName, const QStringList &typeName, int pos, const QString &why, - const AbstractMetaClass *context) + const AbstractMetaClassCPtr &context) { QString result; QTextStream str(&result); formatAddedFuncError(addedFuncName, context, str); - str << "Unable to translate type \"" << typeName.join(colonColon()) + str << "Unable to translate type \"" << typeName.join(u"::"_s) << "\" of argument " << pos << " of added function \"" << addedFuncName << "\": " << why; return result; @@ -186,18 +199,18 @@ QString msgAddedFunctionInvalidArgType(const QString &addedFuncName, QString msgAddedFunctionInvalidReturnType(const QString &addedFuncName, const QStringList &typeName, const QString &why, - const AbstractMetaClass *context) + const AbstractMetaClassCPtr &context) { QString result; QTextStream str(&result); formatAddedFuncError(addedFuncName, context, str); - str << "Unable to translate return type \"" << typeName.join(colonColon()) + str << "Unable to translate return type \"" << typeName.join(u"::"_s) << "\" of added function \"" << addedFuncName << "\": " << why; return result; } -QString msgUnnamedArgumentDefaultExpression(const AbstractMetaClass *context, +QString msgUnnamedArgumentDefaultExpression(const AbstractMetaClassCPtr &context, int n, const QString &className, const AbstractMetaFunction *f) { @@ -210,7 +223,7 @@ QString msgUnnamedArgumentDefaultExpression(const AbstractMetaClass *context, return result; } -QString msgClassOfEnumNotFound(const EnumTypeEntry *entry) +QString msgClassOfEnumNotFound(const EnumTypeEntryCPtr &entry) { QString result; QTextStream str(&result); @@ -227,13 +240,14 @@ QString msgNoEnumTypeEntry(const EnumModelItem &enumItem, QTextStream str(&result); str << enumItem->sourceLocation(); msgFormatEnumType(str, enumItem, className); - str << " does not have a type entry"; + str << " does not have a type entry (type systems: " + << TypeDatabase::instance()->loadedTypeSystemNames() << ')'; return result; } QString msgNoEnumTypeConflict(const EnumModelItem &enumItem, const QString &className, - const TypeEntry *t) + const TypeEntryCPtr &t) { QString result; QDebug debug(&result); // Use the debug operator for TypeEntry::Type @@ -251,11 +265,17 @@ QString msgNamespaceNoTypeEntry(const NamespaceModelItem &item, QString result; QTextStream str(&result); str << item->sourceLocation() << "namespace '" << fullName - << "' does not have a type entry"; + << "' does not have a type entry (type systems: " + << TypeDatabase::instance()->loadedTypeSystemNames() << ')'; return result; } -QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te) +QString msgNamespaceNotFound(const QString &name) +{ + return u"namespace '"_s + name + u"' not found."_s; +} + +QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntryCList &te) { QString result = u"Ambiguous types of varying types found for \""_s + qualifiedName + u"\": "_s; @@ -263,7 +283,7 @@ QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEn return result; } -QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te) +QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntryCList &te) { QString result = u"Ambiguous types found for \""_s + qualifiedName + u"\": "_s; @@ -297,11 +317,13 @@ QString msgSkippingFunction(const FunctionModelItem &functionItem, { QString result; QTextStream str(&result); - str << functionItem->sourceLocation() << "skipping "; - if (functionItem->isAbstract()) + str << functionItem->sourceLocation() << "skipping " + << functionItem->accessPolicy() << ' '; + const bool isAbstract = functionItem->attributes().testFlag(FunctionAttribute::Abstract); + if (isAbstract) str << "abstract "; str << "function '" << signature << "', " << why; - if (functionItem->isAbstract()) { + if (isAbstract) { str << "\nThis will lead to compilation errors due to not " "being able to instantiate the wrapper."; } @@ -319,7 +341,7 @@ QString msgShadowingFunction(const AbstractMetaFunction *f1, return result; } -QString msgSignalOverloaded(const AbstractMetaClass *c, +QString msgSignalOverloaded(const AbstractMetaClassCPtr &c, const AbstractMetaFunction *f) { QString result; @@ -334,24 +356,31 @@ QString msgSkippingField(const VariableModelItem &field, const QString &classNam { QString result; QTextStream str(&result); - str << field->sourceLocation() << "skipping field '" << className - << "::" << field->name() << "' with unmatched type '" << type << '\''; + str << field->sourceLocation() << "skipping " << field->accessPolicy() + << " field '" << className << "::" << field->name() + << "' with unmatched type '" << type << '\''; return result; } static const char msgCompilationError[] = "This could potentially lead to compilation errors."; -QString msgTypeNotDefined(const TypeEntry *entry) +QString msgTypeNotDefined(const TypeEntryCPtr &entry) { QString result; QTextStream str(&result); + const bool hasConfigCondition = entry->isComplex() + && std::static_pointer_cast<const ConfigurableTypeEntry>(entry)->hasConfigCondition(); str << entry->sourceLocation() << "type '" <<entry->qualifiedCppName() - << "' is specified in typesystem, but not defined. " << msgCompilationError; + << "' is specified in typesystem, but not defined"; + if (hasConfigCondition) + str << " (disabled by configuration?)."; + else + str << ". " << msgCompilationError; return result; } -QString msgGlobalFunctionNotDefined(const FunctionTypeEntry *fte, +QString msgGlobalFunctionNotDefined(const FunctionTypeEntryCPtr &fte, const QString &signature, const QStringList &candidates) { @@ -367,18 +396,19 @@ QString msgGlobalFunctionNotDefined(const FunctionTypeEntry *fte, QString msgStrippingArgument(const FunctionModelItem &f, int i, const QString &originalSignature, - const ArgumentModelItem &arg) + const ArgumentModelItem &arg, + const QString &reason) { QString result; QTextStream str(&result); str << f->sourceLocation() << "Stripping argument #" << (i + 1) << " of " << originalSignature << " due to unmatched type \"" << arg->type().toString() << "\" with default expression \"" - << arg->defaultValueExpression() << "\"."; + << arg->defaultValueExpression() << "\": " << reason; return result; } -QString msgEnumNotDefined(const EnumTypeEntry *t) +QString msgEnumNotDefined(const EnumTypeEntryCPtr &t) { QString result; QTextStream str(&result); @@ -387,7 +417,7 @@ QString msgEnumNotDefined(const EnumTypeEntry *t) return result; } -QString msgUnknownBase(const AbstractMetaClass *metaClass, +QString msgUnknownBase(const AbstractMetaClassCPtr &metaClass, const QString &baseClassName) { QString result; @@ -397,7 +427,7 @@ QString msgUnknownBase(const AbstractMetaClass *metaClass, return result; } -QString msgBaseNotInTypeSystem(const AbstractMetaClass *metaClass, +QString msgBaseNotInTypeSystem(const AbstractMetaClassCPtr &metaClass, const QString &baseClassName) { QString result; @@ -451,6 +481,21 @@ QString msgCannotFindTypeEntryForSmartPointer(const QString &t, const QString &s + u"\" for instantiation of \""_s +smartPointerType + u"\"."_s; } +QString msgInheritTemplateIssue(const AbstractMetaClassPtr &subclass, + const TypeInfo &info, + const QString &what) +{ + return "While inheriting template "_L1 + subclass->name() + + " from "_L1 + info.toString() + ": "_L1 + what; +} + +QString msgIgnoringTemplateParameter(const QString &typeName, + const char *why) +{ + return "Ignoring template parameter "_L1 + typeName + + ": "_L1 + QLatin1StringView(why); +} + QString msgInvalidSmartPointerType(const TypeInfo &i) { return u"Invalid smart pointer type \""_s +i.toString() + u"\"."_s; @@ -506,7 +551,7 @@ QString msgPropertyExists(const QString &className, const QString &name) + name + u"\" (defined by Q_PROPERTY)."_s; } -QString msgFunctionVisibilityModified(const AbstractMetaClass *c, +QString msgFunctionVisibilityModified(const AbstractMetaClassCPtr &c, const AbstractMetaFunction *f) { QString result; @@ -516,7 +561,7 @@ QString msgFunctionVisibilityModified(const AbstractMetaClass *c, return result; } -QString msgUsingMemberClassNotFound(const AbstractMetaClass *c, +QString msgUsingMemberClassNotFound(const AbstractMetaClassCPtr &c, const QString &baseClassName, const QString &memberName) { @@ -582,23 +627,25 @@ QString msgFallbackForDocumentation(const QString &fileName, } QString msgCannotFindDocumentation(const QString &fileName, - const AbstractMetaClass *metaClass, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaEnum &e, const QString &query) { - return msgCannotFindDocumentation(fileName, "enum", - metaClass->name() + u"::"_s + e.name(), - query); + QString name = e.name(); + if (metaClass != nullptr) + name.prepend(metaClass->name() + "::"_L1); + return msgCannotFindDocumentation(fileName, "enum", name, query); } QString msgCannotFindDocumentation(const QString &fileName, - const AbstractMetaClass *metaClass, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaField &f, const QString &query) { - return msgCannotFindDocumentation(fileName, "field", - metaClass->name() + u"::"_s + f.name(), - query); + QString name = f.name(); + if (metaClass != nullptr) + name.prepend(metaClass->name() + "::"_L1); + return msgCannotFindDocumentation(fileName, "field", name, query); } QString msgXpathDocModificationError(const DocModificationList& mods, @@ -626,13 +673,13 @@ QString msgXpathDocModificationError(const DocModificationList& mods, QString msgCannotOpenForReading(const QFile &f) { - return QStringLiteral("Failed to open file '%1' for reading: %2") + return QString::fromLatin1("Failed to open file '%1' for reading: %2") .arg(QDir::toNativeSeparators(f.fileName()), f.errorString()); } QString msgCannotOpenForWriting(const QFile &f) { - return QStringLiteral("Failed to open file '%1' for writing: %2") + return QString::fromLatin1("Failed to open file '%1' for writing: %2") .arg(QDir::toNativeSeparators(f.fileName()), f.errorString()); } @@ -654,36 +701,19 @@ QString msgCannotUseEnumAsInt(const QString &name) "Compilation errors may occur when used as a function argument."_s; } -QString msgConversionTypesDiffer(const QString &varType, const QString &conversionType) -{ - QString result; - QTextStream str(&result); - str << "Types of receiver variable ('" << varType - << "') and %%CONVERTTOCPP type system variable ('" << conversionType - << "') differ"; - QString strippedVarType = varType; - QString strippedConversionType = conversionType; - TypeInfo::stripQualifiers(&strippedVarType); - TypeInfo::stripQualifiers(&strippedConversionType); - if (strippedVarType == strippedConversionType) - str << " in qualifiers. Please make sure the type is a distinct token"; - str << '.'; - return result; -} - -QString msgCannotFindSmartPointerGetter(const SmartPointerTypeEntry *te) +QString msgCannotFindSmartPointerGetter(const SmartPointerTypeEntryCPtr &te) { return u"Getter \""_s + te->getter() + u"()\" of smart pointer \""_s + te->name() + u"\" not found."_s; } -QString msgCannotFindSmartPointerMethod(const SmartPointerTypeEntry *te, const QString &m) +QString msgCannotFindSmartPointerMethod(const SmartPointerTypeEntryCPtr &te, const QString &m) { return u"Method \""_s + m + u"()\" of smart pointer \""_s + te->name() + u"\" not found."_s; } -QString msgMethodNotFound(const AbstractMetaClass *klass, const QString &name) +QString msgMethodNotFound(const AbstractMetaClassCPtr &klass, const QString &name) { return u"Method \""_s + name + u"\" not found in class "_s + klass->name() + u'.'; @@ -691,18 +721,12 @@ QString msgMethodNotFound(const AbstractMetaClass *klass, const QString &name) // main.cpp -QString msgLeftOverArguments(const QVariantMap &remainingArgs) +QString msgLeftOverArguments(const QString &remainingArgs, const QStringList &argV) { QString message; QTextStream str(&message); - str << "shiboken: Called with wrong arguments:"; - for (auto it = remainingArgs.cbegin(), end = remainingArgs.cend(); it != end; ++it) { - str << ' ' << it.key(); - const QString value = it.value().toString(); - if (!value.isEmpty()) - str << ' ' << value; - } - str << "\nCommand line: " << QCoreApplication::arguments().join(u' '); + str << "shiboken: Unprocessed arguments: " << remainingArgs + << "\nCommand line: " << argV.join(u' '); return message; } @@ -723,13 +747,13 @@ QString msgCyclicDependency(const QString &funcName, const QString &graphName, << "\". Cyclic functions:"; for (const auto &c : cyclic) str << ' ' << c->signature(); - if (const int count = involvedConversions.size()) { + if (const auto count = involvedConversions.size()) { str << " Implicit conversions (" << count << "): "; - for (int i = 0; i < count; ++i) { + for (qsizetype i = 0; i < count; ++i) { if (i) str << ", \""; str << involvedConversions.at(i)->signature() << '"'; - if (const AbstractMetaClass *c = involvedConversions.at(i)->implementingClass()) + if (const auto c = involvedConversions.at(i)->implementingClass()) str << '(' << c->name() << ')'; } } @@ -738,14 +762,14 @@ QString msgCyclicDependency(const QString &funcName, const QString &graphName, // shibokengenerator.cpp -QString msgClassNotFound(const TypeEntry *t) +QString msgClassNotFound(const TypeEntryCPtr &t) { return u"Could not find class \""_s + t->qualifiedCppName() + u"\" in the code model. Maybe it is forward declared?"_s; } -QString msgEnclosingClassNotFound(const TypeEntry *t) +QString msgEnclosingClassNotFound(const TypeEntryCPtr &t) { QString result; QTextStream str(&result); @@ -754,11 +778,11 @@ QString msgEnclosingClassNotFound(const TypeEntry *t) return result; } -QString msgUnknownOperator(const AbstractMetaFunction* func) +QString msgUnknownOperator(const AbstractMetaFunction *func) { QString result = u"Unknown operator: \""_s + func->originalName() + u'"'; - if (const AbstractMetaClass *c = func->implementingClass()) + if (const auto c = func->implementingClass()) result += u" in class: "_s + c->name(); return result; } @@ -769,7 +793,7 @@ QString msgWrongIndex(const char *varName, const QString &capture, QString result; QTextStream str(&result); str << "Wrong index for " << varName << " variable (" << capture << ") on "; - if (const AbstractMetaClass *c = func->implementingClass()) + if (const auto c = func->implementingClass()) str << c->name() << "::"; str << func->signature(); return result; @@ -811,17 +835,17 @@ QString msgRejectReason(const TypeRejection &r, const QString &needle) QTextStream str(&result); switch (r.matchType) { case TypeRejection::ExcludeClass: - str << " matches class exclusion \"" << r.className.pattern() << '"'; + str << "matches class exclusion \"" << r.className.pattern() << '"'; break; case TypeRejection::Function: case TypeRejection::Field: case TypeRejection::Enum: - str << " matches class \"" << r.className.pattern() << "\" and \"" + str << "matches class \"" << r.className.pattern() << "\" and \"" << r.pattern.pattern() << '"'; break; case TypeRejection::ArgumentType: case TypeRejection::ReturnType: - str << " matches class \"" << r.className.pattern() << "\" and \"" + str << "matches class \"" << r.className.pattern() << "\" and \"" << needle << "\" matches \"" << r.pattern.pattern() << '"'; break; } @@ -874,6 +898,21 @@ QString msgCannotFindSnippet(const QString &file, const QString &snippetLabel) return result; } +QString msgSnippetError(const QString &context, const char *what) +{ + return "Error processing code snippet of "_L1 + context + + ": "_L1 + QString::fromUtf8(what); +} + +QString msgUnableToResolveTypedef(const QString &sourceType, const QString &sourceName) +{ + QString result; + QTextStream(&result) << "Unable to resolve typedef \"" << sourceType + << "\": Could not find a value, container, object or smart pointer type named \"" + << sourceName << "\"."; + return result; +} + // cppgenerator.cpp QString msgPureVirtualFunctionRemoved(const AbstractMetaFunction *f) @@ -917,17 +956,49 @@ QString msgInvalidTargetLanguageApiName(const QString &name) + name + u"\"."_s; } -QString msgUnknownCheckFunction(const TypeEntry *t) +QString msgUnknownCheckFunction(const TypeEntryCPtr &t) { return u"Unknown check function for type: '"_s + t->qualifiedCppName() + u"'."_s; } QString msgArgumentClassNotFound(const AbstractMetaFunctionCPtr &func, - const TypeEntry *t) + const TypeEntryCPtr &t) { QString result; QTextStream(&result) << "Internal Error: Class \"" << t->qualifiedCppName() << "\" for \"" << func->classQualifiedSignature() << "\" not found!"; return result; } + +QString msgMissingCustomConversion(const TypeEntryCPtr &t) +{ + QString result; + QTextStream(&result) << "Entry \"" << t->qualifiedCppName() + << "\" is missing a custom conversion."; + return result; +} + +QString msgUnknownArrayPointerConversion(const QString &s) +{ + return u"Warning: Falling back to pointer conversion for unknown array type \""_s + + s + u"\""_s; +} + +QString msgMissingProjectFileMarker(const QString &name, const QByteArray &startMarker) +{ + return u"First line of project file \""_s + QDir::toNativeSeparators(name) + + u"\" must be the string \""_s + QString::fromLatin1(startMarker) + u"\"."_s; +} + +QString msgInvalidLanguageLevel(const QString &l) +{ + return u"Invalid argument for language level: \""_s + l + u"\"."_s; +} + +QString msgCannotFindImage(const QString &href, const QString &context, + const QString &candidate) +{ + return "Cannot resolve image "_L1 + href + " for "_L1 + context + + " (tried "_L1 + QDir::toNativeSeparators(candidate) + ")."_L1; +} diff --git a/sources/shiboken6/ApiExtractor/messages.h b/sources/shiboken6/ApiExtractor/messages.h index 4a23c6487..5216b26a7 100644 --- a/sources/shiboken6/ApiExtractor/messages.h +++ b/sources/shiboken6/ApiExtractor/messages.h @@ -6,11 +6,10 @@ #include "abstractmetalang_typedefs.h" #include "parser/codemodel_fwd.h" +#include "modifications_typedefs.h" #include "typesystem_typedefs.h" -#include <QtCore/QMap> #include <QtCore/QString> -#include <QtCore/QList> class EnumTypeEntry; class FunctionTypeEntry; @@ -26,19 +25,19 @@ QT_FORWARD_DECLARE_CLASS(QXmlStreamReader) QString msgAddedFunctionInvalidArgType(const QString &addedFuncName, const QStringList &typeName, int pos, const QString &why, - const AbstractMetaClass *context = nullptr); + const AbstractMetaClassCPtr &context = {}); QString msgAddedFunctionInvalidReturnType(const QString &addedFuncName, const QStringList &typeName, const QString &why, - const AbstractMetaClass *context = nullptr); + const AbstractMetaClassCPtr &context = {}); -QString msgUnnamedArgumentDefaultExpression(const AbstractMetaClass *context, +QString msgUnnamedArgumentDefaultExpression(const AbstractMetaClassCPtr &context, int n, const QString &className, const AbstractMetaFunction *f); QString msgArgumentIndexOutOfRange(const AbstractMetaFunction *func, int index); -QString msgNoFunctionForModification(const AbstractMetaClass *klass, +QString msgNoFunctionForModification(const AbstractMetaClassCPtr &klass, const QString &signature, const QString &originalSignature, const QStringList &possibleSignatures, @@ -56,7 +55,7 @@ QString msgArgumentOutOfRange(int number, int minValue, int maxValue); QString msgArgumentRemovalFailed(const AbstractMetaFunction *func, int n, const QString &why); -QString msgClassOfEnumNotFound(const EnumTypeEntry *entry); +QString msgClassOfEnumNotFound(const EnumTypeEntryCPtr &entry); QString msgNoEnumTypeEntry(const EnumModelItem &enumItem, const QString &className); @@ -64,13 +63,15 @@ QString msgNoEnumTypeEntry(const EnumModelItem &enumItem, QString msgNoEnumTypeConflict(const EnumModelItem &enumItem, const QString &className, - const TypeEntry *t); + const TypeEntryCPtr &t); QString msgNamespaceNoTypeEntry(const NamespaceModelItem &item, const QString &fullName); -QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te); -QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te); +QString msgNamespaceNotFound(const QString &name); + +QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntryCList &te); +QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntryCList &te); QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n, const QString &why); @@ -81,7 +82,7 @@ QString msgUnmatchedReturnType(const FunctionModelItem &functionItem, QString msgShadowingFunction(const AbstractMetaFunction *f1, const AbstractMetaFunction *f2); -QString msgSignalOverloaded(const AbstractMetaClass *c, +QString msgSignalOverloaded(const AbstractMetaClassCPtr &c, const AbstractMetaFunction *f); QString msgSkippingFunction(const FunctionModelItem &functionItem, @@ -90,22 +91,23 @@ QString msgSkippingFunction(const FunctionModelItem &functionItem, QString msgSkippingField(const VariableModelItem &field, const QString &className, const QString &type); -QString msgTypeNotDefined(const TypeEntry *entry); +QString msgTypeNotDefined(const TypeEntryCPtr &entry); -QString msgGlobalFunctionNotDefined(const FunctionTypeEntry *fte, +QString msgGlobalFunctionNotDefined(const FunctionTypeEntryCPtr &fte, const QString &signature, const QStringList &candidates); QString msgStrippingArgument(const FunctionModelItem &f, int i, const QString &originalSignature, - const ArgumentModelItem &arg); + const ArgumentModelItem &arg, + const QString &reason); -QString msgEnumNotDefined(const EnumTypeEntry *t); +QString msgEnumNotDefined(const EnumTypeEntryCPtr &t); -QString msgUnknownBase(const AbstractMetaClass *metaClass, +QString msgUnknownBase(const AbstractMetaClassCPtr &metaClass, const QString &baseClassName); -QString msgBaseNotInTypeSystem(const AbstractMetaClass *metaClass, +QString msgBaseNotInTypeSystem(const AbstractMetaClassCPtr &metaClass, const QString &baseClassName); QString msgArrayModificationFailed(const FunctionModelItem &functionItem, @@ -124,6 +126,10 @@ QString msgUnableToTranslateType(const TypeInfo &typeInfo, QString msgCannotFindTypeEntry(const QString &t); QString msgCannotFindTypeEntryForSmartPointer(const QString &t, const QString &smartPointerType); +QString msgInheritTemplateIssue(const AbstractMetaClassPtr &subclass, + const TypeInfo &info, const QString &what); +QString msgIgnoringTemplateParameter(const QString &typeName, + const char *why); QString msgInvalidSmartPointerType(const TypeInfo &i); QString msgCannotFindSmartPointerInstantion(const TypeInfo &i); @@ -139,10 +145,10 @@ QString msgPropertyTypeParsingFailed(const QString &name, const QString &typeNam const QString &why); QString msgPropertyExists(const QString &className, const QString &name); -QString msgFunctionVisibilityModified(const AbstractMetaClass *c, +QString msgFunctionVisibilityModified(const AbstractMetaClassCPtr &c, const AbstractMetaFunction *f); -QString msgUsingMemberClassNotFound(const AbstractMetaClass *c, +QString msgUsingMemberClassNotFound(const AbstractMetaClassCPtr &c, const QString &baseClassName, const QString &memberName); @@ -163,12 +169,12 @@ QString msgFallbackForDocumentation(const QString &fileName, const QString &query = {}); QString msgCannotFindDocumentation(const QString &fileName, - const AbstractMetaClass *metaClass, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaEnum &e, const QString &query = {}); QString msgCannotFindDocumentation(const QString &fileName, - const AbstractMetaClass *metaClass, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaField &f, const QString &query); @@ -183,15 +189,13 @@ QString msgWriteFailed(const QFile &f, qsizetype size); QString msgCannotUseEnumAsInt(const QString &name); -QString msgConversionTypesDiffer(const QString &varType, const QString &conversionType); - -QString msgCannotFindSmartPointerGetter(const SmartPointerTypeEntry *); +QString msgCannotFindSmartPointerGetter(const SmartPointerTypeEntryCPtr &); -QString msgCannotFindSmartPointerMethod(const SmartPointerTypeEntry *te, const QString &m); +QString msgCannotFindSmartPointerMethod(const SmartPointerTypeEntryCPtr &te, const QString &m); -QString msgMethodNotFound(const AbstractMetaClass *klass, const QString &name); +QString msgMethodNotFound(const AbstractMetaClassCPtr &klass, const QString &name); -QString msgLeftOverArguments(const QVariantMap &remainingArgs); +QString msgLeftOverArguments(const QString &remainingArgs, const QStringList &argV); QString msgInvalidVersion(const QString &package, const QString &version); @@ -209,16 +213,18 @@ QString msgIncorrectlyNestedName(const QString &name); QString msgCannotFindView(const QString &viewedName, const QString &name); QString msgCannotFindSnippet(const QString &file, const QString &snippetLabel); +QString msgSnippetError(const QString &context, const char *what); +QString msgUnableToResolveTypedef(const QString &sourceType, const QString &sourceName); QString msgCyclicDependency(const QString &funcName, const QString &graphName, const AbstractMetaFunctionCList &cyclic, const AbstractMetaFunctionCList &involvedConversions); -QString msgClassNotFound(const TypeEntry *t); +QString msgClassNotFound(const TypeEntryCPtr &t); -QString msgEnclosingClassNotFound(const TypeEntry *t); +QString msgEnclosingClassNotFound(const TypeEntryCPtr &t); -QString msgUnknownOperator(const AbstractMetaFunction* func); +QString msgUnknownOperator(const AbstractMetaFunction *func); QString msgWrongIndex(const char *varName, const QString &capture, const AbstractMetaFunction *func); @@ -242,9 +248,20 @@ QString msgDuplicateBuiltInTypeEntry(const QString &name); QString msgDuplicateTypeEntry(const QString &name); QString msgInvalidTargetLanguageApiName(const QString &name); -QString msgUnknownCheckFunction(const TypeEntry *t); +QString msgUnknownCheckFunction(const TypeEntryCPtr &t); QString msgArgumentClassNotFound(const AbstractMetaFunctionCPtr &func, - const TypeEntry *t); + const TypeEntryCPtr &t); + +QString msgMissingCustomConversion(const TypeEntryCPtr &t); + +QString msgUnknownArrayPointerConversion(const QString &s); + +QString msgMissingProjectFileMarker(const QString &name, const QByteArray &startMarker); + +QString msgInvalidLanguageLevel(const QString &l); + +QString msgCannotFindImage(const QString &href, const QString &context, + const QString &candidate); #endif // MESSAGES_H diff --git a/sources/shiboken6/ApiExtractor/modifications.cpp b/sources/shiboken6/ApiExtractor/modifications.cpp index 803709162..d876e8035 100644 --- a/sources/shiboken6/ApiExtractor/modifications.cpp +++ b/sources/shiboken6/ApiExtractor/modifications.cpp @@ -2,38 +2,18 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "modifications.h" -#include "modifications_p.h" #include "codesnip.h" -#include "exception.h" -#include "typedatabase.h" -#include "typeparser.h" -#include "typesystem.h" #include "qtcompat.h" #include <QtCore/QDebug> +#include <QtCore/QRegularExpression> #include <algorithm> #include <limits> using namespace Qt::StringLiterals; -static inline QString callOperator() { return QStringLiteral("operator()"); } - -// ---------------------- Modification -QString FunctionModification::accessModifierString() const -{ - if (isPrivate()) - return u"private"_s; - if (isProtected()) - return u"protected"_s; - if (isPublic()) - return u"public"_s; - if (isFriendly()) - return u"friendly"_s; - return QString(); -} - // ---------------------- FieldModification class FieldModificationData : public QSharedData @@ -54,8 +34,8 @@ FieldModification::FieldModification() : d(new FieldModificationData) FieldModification::FieldModification(const FieldModification &) = default; FieldModification &FieldModification::operator=(const FieldModification &) = default; -FieldModification::FieldModification(FieldModification &&) = default; -FieldModification &FieldModification::operator=(FieldModification &&) = default; +FieldModification::FieldModification(FieldModification &&) noexcept = default; +FieldModification &FieldModification::operator=(FieldModification &&) noexcept = default; FieldModification::~FieldModification() = default; QString FieldModification::name() const @@ -140,184 +120,6 @@ void FieldModification::setSnakeCase(TypeSystem::SnakeCase s) d->snakeCase = s; } -// Helpers to split a parameter list of <add-function>, <declare-function> -// (@ denoting names), like -// "void foo(QList<X,Y> &@list@ = QList<X,Y>{1,2}, int @b@=5, ...)" -namespace AddedFunctionParser { - -bool Argument::equals(const Argument &rhs) const -{ - return type == rhs.type && name == rhs.name && defaultValue == rhs.defaultValue; -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const Argument &a) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "Argument(type=\"" << a.type << '"'; - if (!a.name.isEmpty()) - d << ", name=\"" << a.name << '"'; - if (!a.defaultValue.isEmpty()) - d << ", defaultValue=\"" << a.defaultValue << '"'; - d << ')'; - return d; -} -#endif // QT_NO_DEBUG_STREAM - -// Helper for finding the end of a function parameter, observing -// nested template parameters or lists. -static int parameterTokenEnd(int startPos, QStringView paramString) -{ - const int end = paramString.size(); - int nestingLevel = 0; - for (int p = startPos; p < end; ++p) { - switch (paramString.at(p).toLatin1()) { - case ',': - if (nestingLevel == 0) - return p; - break; - case '<': // templates - case '{': // initializer lists of default values - case '(': // initialization, function pointers - case '[': // array dimensions - ++nestingLevel; - break; - case '>': - case '}': - case ')': - case ']': - --nestingLevel; - break; - } - } - return end; -} - -// Split a function parameter list into string tokens containing one -// parameters (including default value, etc). -static QList<QStringView> splitParameterTokens(QStringView paramString) -{ - QList<QStringView> result; - int startPos = 0; - for ( ; startPos < paramString.size(); ) { - int end = parameterTokenEnd(startPos, paramString); - result.append(paramString.mid(startPos, end - startPos).trimmed()); - startPos = end + 1; - } - return result; -} - -// Split a function parameter list -Arguments splitParameters(QStringView paramString, QString *errorMessage) -{ - Arguments result; - const QList<QStringView> tokens = splitParameterTokens(paramString); - - for (const auto &t : tokens) { - Argument argument; - // Check defaultValue, "int @b@=5" - const int equalPos = t.lastIndexOf(u'='); - if (equalPos != -1) { - const int defaultValuePos = equalPos + 1; - argument.defaultValue = - t.mid(defaultValuePos, t.size() - defaultValuePos).trimmed().toString(); - } - QString typeString = (equalPos != -1 ? t.left(equalPos) : t).trimmed().toString(); - // Check @name@ - const int atPos = typeString.indexOf(u'@'); - if (atPos != -1) { - const int namePos = atPos + 1; - const int nameEndPos = typeString.indexOf(u'@', namePos); - if (nameEndPos == -1) { - if (errorMessage != nullptr) { - *errorMessage = u"Mismatched @ in \""_s - + paramString.toString() + u'"'; - } - return {}; - } - argument.name = typeString.mid(namePos, nameEndPos - namePos).trimmed(); - typeString.remove(atPos, nameEndPos - atPos + 1); - } - argument.type = typeString.trimmed(); - result.append(argument); - } - - return result; -} - -} // namespace AddedFunctionParser - -AddedFunction::AddedFunction(const QString &name, const QList<Argument> &arguments, - const TypeInfo &returnType) : - m_name(name), - m_arguments(arguments), - m_returnType(returnType) -{ -} - -AddedFunction::AddedFunctionPtr - AddedFunction::createAddedFunction(const QString &signatureIn, const QString &returnTypeIn, - QString *errorMessage) - -{ - errorMessage->clear(); - - QList<Argument> arguments; - const TypeInfo returnType = returnTypeIn.isEmpty() - ? TypeInfo::voidType() - : TypeParser::parse(returnTypeIn, errorMessage); - if (!errorMessage->isEmpty()) - return {}; - - QStringView signature = QStringView{signatureIn}.trimmed(); - - // Skip past "operator()(...)" - const int parenSearchStartPos = signature.startsWith(callOperator()) - ? callOperator().size() : 0; - const int openParenPos = signature.indexOf(u'(', parenSearchStartPos); - if (openParenPos < 0) { - return AddedFunctionPtr(new AddedFunction(signature.toString(), - arguments, returnType)); - } - - const QString name = signature.left(openParenPos).trimmed().toString(); - const int closingParenPos = signature.lastIndexOf(u')'); - if (closingParenPos < 0) { - *errorMessage = u"Missing closing parenthesis"_s; - return {}; - } - - // Check for "foo() const" - bool isConst = false; - const int signatureLength = signature.length(); - const int qualifierLength = signatureLength - closingParenPos - 1; - if (qualifierLength >= 5 - && signature.right(qualifierLength).contains(u"const")) { - isConst = true; - } - - const auto paramString = signature.mid(openParenPos + 1, closingParenPos - openParenPos - 1); - const auto params = AddedFunctionParser::splitParameters(paramString, errorMessage); - if (params.isEmpty() && !errorMessage->isEmpty()) - return {}; - for (const auto &p : params) { - TypeInfo type = p.type == u"..." - ? TypeInfo::varArgsType() : TypeParser::parse(p.type, errorMessage); - if (!errorMessage->isEmpty()) { - errorMessage->prepend(u"Unable to parse added function "_s + signatureIn - + u": "_s); - return {}; - } - arguments.append({type, p.name, p.defaultValue}); - } - - AddedFunctionPtr result(new AddedFunction(name, arguments, returnType)); - result->setConstant(isConst); - return result; -} - // Remove the parameter names enclosed in '@' from an added function signature // so that it matches the C++ type signature. static QString removeParameterNames(QString signature) @@ -372,11 +174,11 @@ QDebug operator<<(QDebug d, const CodeSnip &s) if (i) d << ", "; d << '#' << i << ' '; - if (f.instance().isNull()) { + if (!f.instance()) { d << '"'; const QString &code = f.code(); const auto lines = QStringView{code}.split(u'\n'); - for (int i = 0, size = lines.size(); i < size; ++i) { + for (qsizetype i = 0, size = lines.size(); i < size; ++i) { if (i) d << "\\n"; d << lines.at(i).trimmed(); @@ -425,8 +227,8 @@ ArgumentModification::ArgumentModification(int idx) : d(new ArgumentModification ArgumentModification::ArgumentModification(const ArgumentModification &) = default; ArgumentModification &ArgumentModification::operator=(const ArgumentModification &) = default; -ArgumentModification::ArgumentModification(ArgumentModification &&) = default; -ArgumentModification &ArgumentModification::operator=(ArgumentModification &&) = default; +ArgumentModification::ArgumentModification(ArgumentModification &&) noexcept = default; +ArgumentModification &ArgumentModification::operator=(ArgumentModification &&) noexcept = default; ArgumentModification::~ArgumentModification() = default; const QString &ArgumentModification::modifiedType() const @@ -607,7 +409,6 @@ public: QString m_originalSignature; QRegularExpression m_signaturePattern; int m_overloadNumber = TypeSystem::OverloadNumberUnset; - bool m_thread = false; bool removed = false; TypeSystem::AllowThread m_allowThread = TypeSystem::AllowThread::Unspecified; TypeSystem::ExceptionHandling m_exceptionHandling = TypeSystem::ExceptionHandling::Unspecified; @@ -620,8 +421,8 @@ FunctionModification::FunctionModification() : d(new FunctionModificationData) FunctionModification::FunctionModification(const FunctionModification &) = default; FunctionModification &FunctionModification::operator=(const FunctionModification &) = default; -FunctionModification::FunctionModification(FunctionModification &&) = default; -FunctionModification &FunctionModification::operator=(FunctionModification &&) = default; +FunctionModification::FunctionModification(FunctionModification &&) noexcept = default; +FunctionModification &FunctionModification::operator=(FunctionModification &&) noexcept = default; FunctionModification::~FunctionModification() = default; void FunctionModification::formatDebug(QDebug &debug) const @@ -637,8 +438,6 @@ void FunctionModification::formatDebug(QDebug &debug) const debug << ", renamedToName=\"" << d->renamedToName << '"'; if (d->m_allowThread != TypeSystem::AllowThread::Unspecified) debug << ", allowThread=" << int(d->m_allowThread); - if (d->m_thread) - debug << ", thread"; if (d->m_exceptionHandling != TypeSystem::ExceptionHandling::Unspecified) debug << ", exceptionHandling=" << int(d->m_exceptionHandling); if (!d->m_snips.isEmpty()) @@ -741,17 +540,6 @@ void FunctionModification::setSnips(const CodeSnipList &snips) } // ---------------------- FunctionModification -void FunctionModification::setIsThread(bool flag) -{ - if (d->m_thread != flag) - d->m_thread = flag; -} - -bool FunctionModification::isThread() const -{ - return d->m_thread; -} - FunctionModification::AllowThread FunctionModification::allowThread() const { return d->m_allowThread; @@ -763,11 +551,16 @@ void FunctionModification::setAllowThread(FunctionModification::AllowThread allo d->m_allowThread = allow; } -bool FunctionModification::matches(const QString &functionSignature) const +bool FunctionModification::matches(const QStringList &functionSignatures) const { - return d->m_signature.isEmpty() - ? d->m_signaturePattern.match(functionSignature).hasMatch() - : d->m_signature == functionSignature; + if (!d->m_signature.isEmpty()) + return functionSignatures.contains(d->m_signature); + + for (const auto &s : functionSignatures) { + if (d->m_signaturePattern.match(s).hasMatch()) + return true; + } + return false; } bool FunctionModification::setSignature(const QString &s, QString *errorMessage) @@ -876,37 +669,4 @@ QDebug operator<<(QDebug d, const FunctionModification &fm) d << ')'; return d; } - -QDebug operator<<(QDebug d, const AddedFunction::Argument &a) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "Argument("; - d << a.typeInfo; - if (!a.name.isEmpty()) - d << ' ' << a.name; - if (!a.defaultValue.isEmpty()) - d << " = " << a.defaultValue; - d << ')'; - return d; -} - -QDebug operator<<(QDebug d, const AddedFunction &af) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AddedFunction("; - if (af.access() == AddedFunction::Protected) - d << "protected"; - if (af.isStatic()) - d << " static"; - d << af.returnType() << ' ' << af.name() << '(' << af.arguments() << ')'; - if (af.isConstant()) - d << " const"; - if (af.isDeclaration()) - d << " [declaration]"; - return d; -} #endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken6/ApiExtractor/modifications.h b/sources/shiboken6/ApiExtractor/modifications.h index 57dc3e2b0..27a38f1aa 100644 --- a/sources/shiboken6/ApiExtractor/modifications.h +++ b/sources/shiboken6/ApiExtractor/modifications.h @@ -5,8 +5,7 @@ #define MODIFICATIONS_H #include "typesystem_enums.h" -#include "typesystem_typedefs.h" -#include "parser/typeinfo.h" +#include "modifications_typedefs.h" #include <QtCore/QList> #include <QtCore/QSharedDataPointer> @@ -65,8 +64,8 @@ public: explicit ArgumentModification(int idx); ArgumentModification(const ArgumentModification &); ArgumentModification &operator=(const ArgumentModification &); - ArgumentModification(ArgumentModification &&); - ArgumentModification &operator=(ArgumentModification &&); + ArgumentModification(ArgumentModification &&) noexcept; + ArgumentModification &operator=(ArgumentModification &&) noexcept; ~ArgumentModification(); // Reference count flags for this argument @@ -135,15 +134,14 @@ public: FunctionModification(); FunctionModification(const FunctionModification &); FunctionModification &operator=(const FunctionModification &); - FunctionModification(FunctionModification &&); - FunctionModification &operator=(FunctionModification &&); + FunctionModification(FunctionModification &&) noexcept; + FunctionModification &operator=(FunctionModification &&) noexcept; ~FunctionModification(); enum ModifierFlag { Private = 0x0001, Protected = 0x0002, - Public = 0x0003, - Friendly = 0x0004, + Public = 0x0004, AccessModifierMask = 0x000f, Final = 0x0010, @@ -156,7 +154,8 @@ public: CodeInjection = 0x1000, Rename = 0x2000, Deprecated = 0x4000, - ReplaceExpression = 0x8000 + Undeprecated = 0x8000, + ReplaceExpression = 0x10000 }; Q_DECLARE_FLAGS(Modifiers, ModifierFlag); @@ -191,10 +190,6 @@ public: { return accessModifier() == Public; } - bool isFriendly() const - { - return accessModifier() == Friendly; - } bool isFinal() const { return modifiers().testFlag(Final); @@ -203,7 +198,6 @@ public: { return modifiers().testFlag(NonFinal); } - QString accessModifierString() const; bool isDeprecated() const { @@ -223,13 +217,11 @@ public: { return modifiers().testFlag(CodeInjection); } - void setIsThread(bool flag); - bool isThread() const; AllowThread allowThread() const; void setAllowThread(AllowThread allow); - bool matches(const QString &functionSignature) const; + bool matches(const QStringList &functionSignatures) const; bool setSignature(const QString &s, QString *errorMessage = nullptr); QString signature() const; @@ -279,8 +271,8 @@ public: FieldModification(); FieldModification(const FieldModification &); FieldModification &operator=(const FieldModification &); - FieldModification(FieldModification &&); - FieldModification &operator=(FieldModification &&); + FieldModification(FieldModification &&) noexcept; + FieldModification &operator=(FieldModification &&) noexcept; ~FieldModification(); QString name() const; @@ -309,121 +301,6 @@ private: QSharedDataPointer<FieldModificationData> d; }; -/** -* \internal -* Struct used to store information about functions added by the typesystem. -* This info will be used later to create a fake AbstractMetaFunction which -* will be inserted into the right AbstractMetaClass. -*/ -struct AddedFunction -{ - using AddedFunctionPtr = QSharedPointer<AddedFunction>; - - /// Function access types. - enum Access { - Protected = 0x1, - Public = 0x2 - }; - - struct Argument - { - TypeInfo typeInfo; - QString name; - QString defaultValue; - }; - - /// Creates a new AddedFunction with a signature and a return type. - explicit AddedFunction(const QString &name, const QList<Argument> &arguments, - const TypeInfo &returnType); - - static AddedFunctionPtr createAddedFunction(const QString &signatureIn, - const QString &returnTypeIn, - QString *errorMessage); - - AddedFunction() = default; - - /// Returns the function name. - QString name() const - { - return m_name; - } - - /// Set the function access type. - void setAccess(Access access) - { - m_access = access; - } - - /// Returns the function access type. - Access access() const - { - return m_access; - } - - /// Returns the function return type. - TypeInfo returnType() const - { - return m_returnType; - } - - /// Returns a list of argument type infos. - const QList<Argument> &arguments() const - { - return m_arguments; - } - - /// Returns true if this is a constant method. - bool isConstant() const - { - return m_isConst; - } - void setConstant(bool c) { m_isConst = c; }; - - /// Set this method static. - void setStatic(bool value) - { - m_isStatic = value; - } - - /// Set this method as a classmethod. - void setClassMethod(bool value) - { - m_isClassMethod = value; - } - - /// Returns true if this is a static method. - bool isStatic() const - { - return m_isStatic; - } - - /// Returns true if this is a class method. - bool isClassMethod() const - { - return m_isClassMethod; - } - - bool isDeclaration() const { return m_isDeclaration; } // <declare-function> - void setDeclaration(bool value) { m_isDeclaration = value; } - - FunctionModificationList modifications; - -private: - QString m_name; - QList<Argument> m_arguments; - TypeInfo m_returnType; - Access m_access = Public; - bool m_isConst = false; - bool m_isClassMethod = false; - bool m_isStatic = false; - bool m_isDeclaration = false; -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AddedFunction::Argument &a); -QDebug operator<<(QDebug d, const AddedFunction &af); -#endif - class DocModification { public: diff --git a/sources/shiboken6/ApiExtractor/modifications_typedefs.h b/sources/shiboken6/ApiExtractor/modifications_typedefs.h new file mode 100644 index 000000000..3b86c55d3 --- /dev/null +++ b/sources/shiboken6/ApiExtractor/modifications_typedefs.h @@ -0,0 +1,25 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef MODIFICATIONS_TYPEDEFS_H +#define MODIFICATIONS_TYPEDEFS_H + +#include <QtCore/QList> + +#include <memory> + +class CodeSnip; +class DocModification; + +struct AddedFunction; +class FieldModification; +class FunctionModification; + +using AddedFunctionPtr = std::shared_ptr<AddedFunction>; +using AddedFunctionList = QList<AddedFunctionPtr>; +using CodeSnipList = QList<CodeSnip>; +using DocModificationList = QList<DocModification>; +using FieldModificationList = QList<FieldModification>; +using FunctionModificationList = QList<FunctionModification>; + +#endif // MODIFICATIONS_TYPEDEFS_H diff --git a/sources/shiboken6/ApiExtractor/namespacetypeentry.h b/sources/shiboken6/ApiExtractor/namespacetypeentry.h index dd0656009..6ffd38430 100644 --- a/sources/shiboken6/ApiExtractor/namespacetypeentry.h +++ b/sources/shiboken6/ApiExtractor/namespacetypeentry.h @@ -12,12 +12,12 @@ class NamespaceTypeEntry : public ComplexTypeEntry { public: explicit NamespaceTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); TypeEntry *clone() const override; - const NamespaceTypeEntry *extends() const; - void setExtends(const NamespaceTypeEntry *e); + NamespaceTypeEntryCPtr extends() const; + void setExtends(const NamespaceTypeEntryCPtr &e); const QRegularExpression &filePattern() const; // restrict files void setFilePattern(const QRegularExpression &r); @@ -33,6 +33,7 @@ public: bool isInlineNamespace() const; void setInlineNamespace(bool i); + static bool isVisibleScope(const TypeEntryCPtr &e); static bool isVisibleScope(const TypeEntry *e); #ifndef QT_NO_DEBUG_STREAM diff --git a/sources/shiboken6/ApiExtractor/objecttypeentry.h b/sources/shiboken6/ApiExtractor/objecttypeentry.h index a9df6b4fb..da91e8ff4 100644 --- a/sources/shiboken6/ApiExtractor/objecttypeentry.h +++ b/sources/shiboken6/ApiExtractor/objecttypeentry.h @@ -10,7 +10,7 @@ class ObjectTypeEntry : public ComplexTypeEntry { public: explicit ObjectTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); TypeEntry *clone() const override; diff --git a/sources/shiboken6/ApiExtractor/optionsparser.cpp b/sources/shiboken6/ApiExtractor/optionsparser.cpp new file mode 100644 index 000000000..f2e64c7e4 --- /dev/null +++ b/sources/shiboken6/ApiExtractor/optionsparser.cpp @@ -0,0 +1,232 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "optionsparser.h" +#include "messages.h" +#include "exception.h" + +#include <QtCore/QDir> +#include <QtCore/QTextStream> + +using namespace Qt::StringLiterals; + +template <class Stream> void formatBoolOption(Stream &s, const BoolOption &bo) +{ + switch (bo.source) { + case OptionSource::CommandLine: + s << "--"; + break; + case OptionSource::CommandLineSingleDash: + s << '-'; + break; + default: + break; + } + s << bo.option; + if (bo.source == OptionSource::ProjectFile) + s << " (project)"; +} + +template <class Stream> void formatOptionValue(Stream &s, const OptionValue &ov) +{ + switch (ov.source) { + case OptionSource::CommandLine: + s << "--"; + break; + case OptionSource::CommandLineSingleDash: + s << '-'; + break; + default: + break; + } + s << ov.option << '=' << ov.value; + if (ov.source == OptionSource::ProjectFile) + s << " (project)"; +} + +QTextStream &operator<<(QTextStream &s, const BoolOption &bo) +{ + formatBoolOption(s, bo); + return s; +} + +QTextStream &operator<<(QTextStream &s, const OptionValue &ov) +{ + formatOptionValue(s, ov); + return s; +} + +QDebug operator<<(QDebug debug, const BoolOption &bo) +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + formatBoolOption(debug, bo); + return debug; +} + +QDebug operator<<(QDebug debug, const OptionValue &v) +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + formatOptionValue(debug, v); + return debug; +} + +QDebug operator<<(QDebug debug, const Options &v) +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + debug << "Options("; + if (!v.boolOptions.isEmpty()) + debug << "bools=" << v.boolOptions; + if (!v.valueOptions.isEmpty()) + debug << ", option values=" << v.valueOptions; + if (!v.positionalArguments.isEmpty()) + debug << ", pos=" << v.positionalArguments; + debug << ')'; + return debug; +} + +QTextStream &operator<<(QTextStream &s, const OptionDescription &od) +{ + if (!od.name.startsWith(u'-')) + s << "--"; + s << od.name; + if (od.description.isEmpty()) { // For formatting {{"-s", ""}, {"--short", "descr"}} + s << ", "; + } else { + s << '\n'; + const auto lines = QStringView{od.description}.split(u'\n'); + for (const auto &line : lines) + s << " " << line << '\n'; + s << '\n'; + } + return s; +} + +QTextStream &operator<<(QTextStream &s, const OptionDescriptions &options) +{ + s.setFieldAlignment(QTextStream::AlignLeft); + for (const auto &od : options) + s << od; + return s; +} + +OptionsParser::OptionsParser() noexcept = default; +OptionsParser::~OptionsParser() = default; + +const QString &OptionsParser::pathSyntax() +{ + static const QString result = + u"<path>["_s + QDir::listSeparator() + u"<path>"_s + + QDir::listSeparator() + u"...]"_s; + return result; +} + +bool OptionsParser::handleBoolOption(const QString &, OptionSource) +{ + return false; +} + +bool OptionsParser::handleOption(const QString &, const QString &, OptionSource) +{ + return false; +} + +void OptionsParser::process(Options *o) +{ + for (auto i = o->boolOptions.size() - 1; i >= 0; --i) { + const auto &opt = o->boolOptions.at(i); + if (handleBoolOption(opt.option, opt.source)) + o->boolOptions.removeAt(i); + } + for (auto i = o->valueOptions.size() - 1; i >= 0; --i) { + const auto &opt = o->valueOptions.at(i); + if (handleOption(opt.option, opt.value, opt.source)) + o->valueOptions.removeAt(i); + } +} + +bool OptionsParserList::handleBoolOption(const QString &key, OptionSource source) +{ + for (const auto &p : std::as_const(m_parsers)) { + if (p->handleBoolOption(key, source)) + return true; + } + return false; +} + +bool OptionsParserList::handleOption(const QString &key, const QString &value, OptionSource source) +{ + for (const auto &p : std::as_const(m_parsers)) { + if (p->handleOption(key, value, source)) + return true; + } + return false; +} + +static void processOption(const QString &o, OptionSource source, + BoolOptions *bools, OptionValues *values) +{ + const auto equals = o.indexOf(u'='); + if (equals == -1) { + bools->append({o.trimmed(), source}); + } else { + QString key = o.left(equals).trimmed(); + QString value = o.mid(equals + 1).trimmed(); + if (!value.isEmpty()) + values->append({key, value, source}); + } +} + +static void readProjectFile(const QString &name, Options *o) +{ + const auto startMarker = "[generator-project]"_ba; + + QFile file(name); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + throw Exception(msgCannotOpenForReading(file)); + + if (file.atEnd() || file.readLine().trimmed() != startMarker) + throw Exception(msgMissingProjectFileMarker(name, startMarker)); + + while (!file.atEnd()) { + const QByteArray lineB = file.readLine().trimmed(); + if (!lineB.isEmpty() && !lineB.startsWith('#')) { + processOption(QString::fromUtf8(lineB), OptionSource::ProjectFile, + &o->boolOptions, &o->valueOptions); + } + } +} + +void Options::setOptions(const QStringList &argv) +{ + const auto projectFileOption = "--project-file="_L1; + for (const auto &o : argv) { + if (o.startsWith(projectFileOption)) { + readProjectFile(o.sliced(projectFileOption.size()), this); + } else if (o.startsWith(u"--")) { + processOption(o.sliced(2), OptionSource::CommandLine, + &boolOptions, &valueOptions); + } else if (o.startsWith(u'-')) { + processOption(o.sliced(1), OptionSource::CommandLineSingleDash, + &boolOptions, &valueOptions); + } else { + positionalArguments.append(o); + } + } +} + +QString Options::msgUnprocessedOptions() const +{ + QString result; + QTextStream str(&result); + for (const auto &b : boolOptions) + str << b << ' '; + for (const auto &v : valueOptions) + str << v << ' '; + return result.trimmed(); +} diff --git a/sources/shiboken6/ApiExtractor/optionsparser.h b/sources/shiboken6/ApiExtractor/optionsparser.h new file mode 100644 index 000000000..d5557dc15 --- /dev/null +++ b/sources/shiboken6/ApiExtractor/optionsparser.h @@ -0,0 +1,98 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef OPTIONSPARSER_H +#define OPTIONSPARSER_H + +#include <QtCore/QString> +#include <QtCore/QStringList> + +#include <memory> + +QT_FORWARD_DECLARE_CLASS(QTextStream) + +enum class OptionSource +{ + CommandLine, // "--option" + CommandLineSingleDash, // "-o" + ProjectFile +}; + +struct BoolOption +{ + QString option; + OptionSource source = OptionSource::CommandLine; +}; + +struct OptionValue // --option=value pair +{ + QString option; + QString value; + OptionSource source = OptionSource::CommandLine; +}; + +using BoolOptions = QList<BoolOption>; +using OptionValues = QList<OptionValue>; + +struct Options // Options from command line and project file +{ + void setOptions(const QStringList &argv); + QString msgUnprocessedOptions() const; + + BoolOptions boolOptions; + OptionValues valueOptions; + QStringList positionalArguments; +}; + +struct OptionDescription // For help formatting +{ + QString name; + QString description; +}; + +using OptionDescriptions = QList<OptionDescription>; + +QTextStream &operator<<(QTextStream &s, const BoolOption &bo); +QTextStream &operator<<(QTextStream &s, const OptionValue &ov); +QTextStream &operator<<(QTextStream &s, const OptionDescription &od); +QTextStream &operator<<(QTextStream &s, const OptionDescriptions &options); + +class OptionsParser +{ +public: + Q_DISABLE_COPY_MOVE(OptionsParser) + + virtual ~OptionsParser(); + + // Return true to indicate the option was processed. + virtual bool handleBoolOption(const QString &key, OptionSource source); + virtual bool handleOption(const QString &key, const QString &value, OptionSource source); + + void process(Options *); + + static const QString &pathSyntax(); + +protected: + OptionsParser() noexcept; +}; + +class OptionsParserList : public OptionsParser +{ +public: + using OptionsParserPtr = std::shared_ptr<OptionsParser>; + + void append(const OptionsParserPtr &parser) { m_parsers.append(parser); } + void clear() { m_parsers.clear(); } + + bool handleBoolOption(const QString &key, OptionSource source) override; + bool handleOption(const QString &key, const QString &value, OptionSource source) override; + +private: + QList<OptionsParserPtr> m_parsers; +}; + +QDebug operator<<(QDebug debug, const BoolOption &bo); +QDebug operator<<(QDebug debug, const OptionValue &v); +QDebug operator<<(QDebug debug, const Options &v); + +#endif // OPTIONSPARSER_H diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp index 4099caa2c..259a706dc 100644 --- a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp @@ -6,31 +6,24 @@ #include "codemodel.h" #include <sourcelocation.h> +#include <debughelpers_p.h> #include <QtCore/QDebug> #include <QtCore/QDir> #include <QtCore/QRegularExpression> #include <algorithm> -#include <functional> -#include <iostream> -// Predicate to find an item by name in a list of QSharedPointer<Item> -template <class T> class ModelItemNamePredicate -{ -public: - explicit ModelItemNamePredicate(const QString &name) : m_name(name) {} - bool operator()(const QSharedPointer<T> &item) const { return item->name() == m_name; } - -private: - const QString m_name; -}; +using namespace Qt::StringLiterals; template <class T> -static QSharedPointer<T> findModelItem(const QList<QSharedPointer<T> > &list, const QString &name) +static std::shared_ptr<T> findModelItem(const QList<std::shared_ptr<T> > &list, + QAnyStringView name) { - const auto it = std::find_if(list.cbegin(), list.cend(), ModelItemNamePredicate<T>(name)); - return it != list.cend() ? *it : QSharedPointer<T>(); + using ItemPtr = std::shared_ptr<T>; + auto pred = [name](const ItemPtr &item) { return item->name() == name; }; + const auto it = std::find_if(list.cbegin(), list.cend(), pred); + return it != list.cend() ? *it : ItemPtr{}; } // --------------------------------------------------------------------------- @@ -51,7 +44,7 @@ void CodeModel::addFile(const FileModelItem &item) m_files.append(item); } -FileModelItem CodeModel::findFile(const QString &name) const +FileModelItem CodeModel::findFile(QAnyStringView name) const { return findModelItem(m_files, name); } @@ -69,11 +62,11 @@ static CodeModelItem findRecursion(const ScopeModelItem &scope, return tp; if (TemplateTypeAliasModelItem tta = scope->findTemplateTypeAlias(nameSegment)) return tta; - return CodeModelItem(); + return {}; } if (auto nestedClass = scope->findClass(nameSegment)) return findRecursion(nestedClass, qualifiedName, segment + 1); - if (auto namespaceItem = qSharedPointerDynamicCast<_NamespaceModelItem>(scope)) { + if (auto namespaceItem = std::dynamic_pointer_cast<_NamespaceModelItem>(scope)) { for (const auto &nestedNamespace : namespaceItem->namespaces()) { if (nestedNamespace->name() == nameSegment) { if (auto item = findRecursion(nestedNamespace, qualifiedName, segment + 1)) @@ -81,7 +74,7 @@ static CodeModelItem findRecursion(const ScopeModelItem &scope, } } } - return CodeModelItem(); + return {}; } CodeModelItem CodeModel::findItem(const QStringList &qualifiedName, const ScopeModelItem &scope) @@ -118,7 +111,7 @@ QDebug operator<<(QDebug d, const CodeModel *m) d << "CodeModel("; if (m) { const NamespaceModelItem globalNamespaceP = m->globalNamespace(); - if (globalNamespaceP.data()) + if (globalNamespaceP) globalNamespaceP->formatDebug(d); } else { d << '0'; @@ -241,27 +234,17 @@ void _CodeModelItem::setEnclosingScope(const _ScopeModelItem *s) m_enclosingScope = s; } -#ifndef QT_NO_DEBUG_STREAM -template <class It> -void formatSequence(QDebug &d, It i1, It i2, const char *separator=", ") +_ScopeModelItem::_ScopeModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind) { - for (It i = i1; i != i2; ++i) { - if (i != i1) - d << separator; - d << *i; - } } -template <class It> -static void formatPtrSequence(QDebug &d, It i1, It i2, const char *separator=", ") +_ScopeModelItem::_ScopeModelItem(CodeModel *model, const QString &name, int kind) + : _CodeModelItem(model, name, kind) { - for (It i = i1; i != i2; ++i) { - if (i != i1) - d << separator; - d << i->data(); - } } +#ifndef QT_NO_DEBUG_STREAM void _CodeModelItem::formatKind(QDebug &d, int k) { switch (k) { @@ -371,6 +354,16 @@ bool _ClassModelItem::extendsClass(const QString &name) const return false; } +_ClassModelItem::_ClassModelItem(CodeModel *model, int kind) + : _ScopeModelItem(model, kind) +{ +} + +_ClassModelItem::_ClassModelItem(CodeModel *model, const QString &name, int kind) + : _ScopeModelItem(model, name, kind) +{ +} + const QList<_ClassModelItem::UsingMember> &_ClassModelItem::usingMembers() const { return m_usingMembers; @@ -413,9 +406,9 @@ template <class List> static void formatModelItemList(QDebug &d, const char *prefix, const List &l, const char *separator = ", ") { - if (const int size = l.size()) { + if (const auto size = l.size()) { d << prefix << '[' << size << "]("; - for (int i = 0; i < size; ++i) { + for (qsizetype i = 0; i < size; ++i) { if (i) d << separator; l.at(i)->formatDebug(d); @@ -432,7 +425,7 @@ void _ClassModelItem::formatDebug(QDebug &d) const d << " [final]"; d << ", inherits="; d << ", inherits="; - for (int i = 0, size = m_baseClasses.size(); i < size; ++i) { + for (qsizetype i = 0, size = m_baseClasses.size(); i < size; ++i) { if (i) d << ", "; d << m_baseClasses.at(i).name << " (" << m_baseClasses.at(i).accessPolicy << ')'; @@ -451,12 +444,12 @@ void _ClassModelItem::formatDebug(QDebug &d) const // --------------------------------------------------------------------------- FunctionModelItem _ScopeModelItem::declaredFunction(const FunctionModelItem &item) { - for (const FunctionModelItem &fun : qAsConst(m_functions)) { + for (const FunctionModelItem &fun : std::as_const(m_functions)) { if (fun->name() == item->name() && fun->isSimilar(item)) return fun; } - return FunctionModelItem(); + return {}; } _ScopeModelItem::~_ScopeModelItem() = default; @@ -556,7 +549,7 @@ template class LIBSAMPLE_EXPORT Tpl<54>; */ void _ScopeModelItem::purgeClassDeclarations() { - for (int i = m_classes.size() - 1; i >= 0; --i) { + for (auto i = m_classes.size() - 1; i >= 0; --i) { auto klass = m_classes.at(i); // For an empty class, check if there is a matching template // definition, and remove it if this is the case. @@ -625,52 +618,46 @@ void _ScopeModelItem::formatDebug(QDebug &d) const } #endif // !QT_NO_DEBUG_STREAM -namespace { // Predicate to match a non-template class name against the class list. // "Vector" should match "Vector" as well as "Vector<T>" (as seen for methods // from within the class "Vector"). -class ClassNamePredicate +static bool matchClassNameNonTemplatePart(const ClassModelItem &item, const QString &name) { -public: - explicit ClassNamePredicate(const QString &name) : m_name(name) {} - bool operator()(const ClassModelItem &item) const - { - const QString &itemName = item->name(); - if (!itemName.startsWith(m_name)) - return false; - return itemName.size() == m_name.size() || itemName.at(m_name.size()) == u'<'; - } - -private: - const QString m_name; -}; -} // namespace + const QString &itemName = item->name(); + if (!itemName.startsWith(name)) + return false; + return itemName.size() == name.size() || itemName.at(name.size()) == u'<'; +} ClassModelItem _ScopeModelItem::findClass(const QString &name) const { // A fully qualified template is matched by name only const ClassList::const_iterator it = name.contains(u'<') - ? std::find_if(m_classes.begin(), m_classes.end(), ModelItemNamePredicate<_ClassModelItem>(name)) - : std::find_if(m_classes.begin(), m_classes.end(), ClassNamePredicate(name)); + ? std::find_if(m_classes.begin(), m_classes.end(), + [&name](const ClassModelItem &item) { + return item->name() == name; }) + : std::find_if(m_classes.begin(), m_classes.end(), + [&name](const ClassModelItem &item) { + return matchClassNameNonTemplatePart(item, name); }); return it != m_classes.end() ? *it : ClassModelItem(); } -VariableModelItem _ScopeModelItem::findVariable(const QString &name) const +VariableModelItem _ScopeModelItem::findVariable(QAnyStringView name) const { return findModelItem(m_variables, name); } -TypeDefModelItem _ScopeModelItem::findTypeDef(const QString &name) const +TypeDefModelItem _ScopeModelItem::findTypeDef(QAnyStringView name) const { return findModelItem(m_typeDefs, name); } -TemplateTypeAliasModelItem _ScopeModelItem::findTemplateTypeAlias(const QString &name) const +TemplateTypeAliasModelItem _ScopeModelItem::findTemplateTypeAlias(QAnyStringView name) const { return findModelItem(m_templateTypeAliases, name); } -EnumModelItem _ScopeModelItem::findEnum(const QString &name) const +EnumModelItem _ScopeModelItem::findEnum(QAnyStringView name) const { return findModelItem(m_enums, name); } @@ -682,15 +669,15 @@ _ScopeModelItem::FindEnumByValueReturn const bool unqualified = fullValue.size() == enumValue.size(); QString scopePrefix = scope().join(u"::"); if (!scopePrefix.isEmpty()) - scopePrefix += u"::"_qs; - scopePrefix += name() + u"::"_qs; + scopePrefix += u"::"_s; + scopePrefix += name() + u"::"_s; for (const auto &e : m_enums) { const auto index = e->indexOfValue(enumValue); if (index != -1) { QString fullyQualifiedName = scopePrefix; if (e->enumKind() != AnonymousEnum) - fullyQualifiedName += e->name() + u"::"_qs; + fullyQualifiedName += e->name() + u"::"_s; fullyQualifiedName += e->enumerators().at(index)->name(); if (unqualified || fullyQualifiedName.endsWith(fullValue)) return {e, fullyQualifiedName}; @@ -722,8 +709,8 @@ _ScopeModelItem::FindEnumByValueReturn if (searchSiblingNamespaces && scope->kind() == Kind_Namespace) { if (auto *enclosingNamespace = dynamic_cast<const _NamespaceModelItem *>(enclosingScope)) { for (const auto &sibling : enclosingNamespace->namespaces()) { - if (sibling.data() != scope && sibling->name() == scope->name()) { - if (const auto e = findEnumByValueRecursion(sibling.data(), + if (sibling.get() != scope && sibling->name() == scope->name()) { + if (const auto e = findEnumByValueRecursion(sibling.get(), fullValue, enumValue, false)) { return e; } @@ -739,8 +726,8 @@ _ScopeModelItem::FindEnumByValueReturn // PYSIDE-331: We need to also search the base classes. if (auto *classItem = dynamic_cast<const _ClassModelItem *>(scope)) { for (const auto &base : classItem->baseClasses()) { - if (!base.klass.isNull()) { - auto *c = base.klass.data(); + if (base.klass) { + auto *c = base.klass.get(); if (const auto e = findEnumByValueRecursion(c, fullValue, enumValue)) return e; } @@ -759,7 +746,7 @@ _ScopeModelItem::FindEnumByValueReturn return findEnumByValueRecursion(this, value, enumValue); } -FunctionList _ScopeModelItem::findFunctions(const QString &name) const +FunctionList _ScopeModelItem::findFunctions(QAnyStringView name) const { FunctionList result; for (const FunctionModelItem &func : m_functions) { @@ -770,17 +757,25 @@ FunctionList _ScopeModelItem::findFunctions(const QString &name) const } // --------------------------------------------------------------------------- -_NamespaceModelItem::~_NamespaceModelItem() +_NamespaceModelItem::_NamespaceModelItem(CodeModel *model, int kind) + : _ScopeModelItem(model, kind) { } +_NamespaceModelItem::_NamespaceModelItem(CodeModel *model, const QString &name, int kind) + : _ScopeModelItem(model, name, kind) +{ +} + +_NamespaceModelItem::~_NamespaceModelItem() = default; + void _NamespaceModelItem::addNamespace(NamespaceModelItem item) { item->setEnclosingScope(this); m_namespaces.append(item); } -NamespaceModelItem _NamespaceModelItem::findNamespace(const QString &name) const +NamespaceModelItem _NamespaceModelItem::findNamespace(QAnyStringView name) const { return findModelItem(m_namespaces, name); } @@ -812,10 +807,18 @@ void _NamespaceModelItem::formatDebug(QDebug &d) const #endif // !QT_NO_DEBUG_STREAM // --------------------------------------------------------------------------- -_ArgumentModelItem::~_ArgumentModelItem() +_ArgumentModelItem::_ArgumentModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind) { } +_ArgumentModelItem::_ArgumentModelItem(CodeModel *model, const QString &name, int kind) + : _CodeModelItem(model, name, kind) +{ +} + +_ArgumentModelItem::~_ArgumentModelItem() = default; + TypeInfo _ArgumentModelItem::type() const { return m_type; @@ -836,11 +839,23 @@ void _ArgumentModelItem::setDefaultValue(bool defaultValue) m_defaultValue = defaultValue; } +bool _ArgumentModelItem::scopeResolution() const +{ + return m_scopeResolution; +} + +void _ArgumentModelItem::setScopeResolution(bool v) +{ + m_scopeResolution = v; +} + #ifndef QT_NO_DEBUG_STREAM void _ArgumentModelItem::formatDebug(QDebug &d) const { _CodeModelItem::formatDebug(d); d << ", type=" << m_type; + if (m_scopeResolution) + d << ", [m_scope resolution]"; if (m_defaultValue) d << ", defaultValue=\"" << m_defaultValueExpression << '"'; } @@ -875,6 +890,16 @@ bool _FunctionModelItem::isSimilar(const FunctionModelItem &other) const return true; } +_FunctionModelItem::_FunctionModelItem(CodeModel *model, int kind) + : _MemberModelItem(model, kind), m_flags(0) +{ +} + +_FunctionModelItem::_FunctionModelItem(CodeModel *model, const QString &name, int kind) + : _MemberModelItem(model, name, kind), m_flags(0) +{ +} + ArgumentList _FunctionModelItem::arguments() const { return m_arguments; @@ -905,6 +930,16 @@ void _FunctionModelItem::setVariadics(bool isVariadics) m_isVariadics = isVariadics; } +bool _FunctionModelItem::scopeResolution() const +{ + return m_scopeResolution; +} + +void _FunctionModelItem::setScopeResolution(bool v) +{ + m_scopeResolution = v; +} + bool _FunctionModelItem::isDefaultConstructor() const { return m_functionType == CodeModel::Constructor @@ -967,66 +1002,16 @@ void _FunctionModelItem::setDeleted(bool d) m_isDeleted = d; } -bool _FunctionModelItem::isDeprecated() const -{ - return m_isDeprecated; -} - -void _FunctionModelItem::setDeprecated(bool d) -{ - m_isDeprecated = d; -} - -bool _FunctionModelItem::isVirtual() const -{ - return m_isVirtual; -} - -void _FunctionModelItem::setVirtual(bool isVirtual) -{ - m_isVirtual = isVirtual; -} - bool _FunctionModelItem::isInline() const { return m_isInline; } -bool _FunctionModelItem::isOverride() const -{ - return m_isOverride; -} - -void _FunctionModelItem::setOverride(bool o) -{ - m_isOverride = o; -} - -bool _FunctionModelItem::isFinal() const -{ - return m_isFinal; -} - -void _FunctionModelItem::setFinal(bool f) -{ - m_isFinal = f; -} - void _FunctionModelItem::setInline(bool isInline) { m_isInline = isInline; } -bool _FunctionModelItem::isExplicit() const -{ - return m_isExplicit; -} - -void _FunctionModelItem::setExplicit(bool isExplicit) -{ - m_isExplicit = isExplicit; -} - bool _FunctionModelItem::isHiddenFriend() const { return m_isHiddenFriend; @@ -1037,33 +1022,12 @@ void _FunctionModelItem::setHiddenFriend(bool f) m_isHiddenFriend = f; } -bool _FunctionModelItem::isAbstract() const -{ - return m_isAbstract; -} - -void _FunctionModelItem::setAbstract(bool isAbstract) -{ - m_isAbstract = isAbstract; -} - -// Qt -bool _FunctionModelItem::isInvokable() const -{ - return m_isInvokable; -} - -void _FunctionModelItem::setInvokable(bool isInvokable) -{ - m_isInvokable = isInvokable; -} - QString _FunctionModelItem::typeSystemSignature() const // For dumping out type system files { QString result; QTextStream str(&result); str << name() << '('; - for (int a = 0, size = m_arguments.size(); a < size; ++a) { + for (qsizetype a = 0, size = m_arguments.size(); a < size; ++a) { if (a) str << ','; m_arguments.at(a)->type().formatTypeSystemSignature(str); @@ -1182,20 +1146,22 @@ void _FunctionModelItem::formatDebug(QDebug &d) const d << " [deleted!]"; if (m_isInline) d << " [inline]"; - if (m_isVirtual) + if (m_attributes.testFlag(FunctionAttribute::Virtual)) d << " [virtual]"; - if (m_isOverride) + if (m_attributes.testFlag(FunctionAttribute::Override)) d << " [override]"; - if (m_isDeprecated) + if (m_attributes.testFlag(FunctionAttribute::Deprecated)) d << " [deprecated]"; - if (m_isFinal) + if (m_attributes.testFlag(FunctionAttribute::Final)) d << " [final]"; - if (m_isAbstract) + if (m_attributes.testFlag(FunctionAttribute::Abstract)) d << " [abstract]"; - if (m_isExplicit) + if (m_attributes.testFlag(FunctionAttribute::Explicit)) d << " [explicit]"; if (m_isInvokable) d << " [invokable]"; + if (m_scopeResolution) + d << " [scope resolution]"; formatModelItemList(d, ", arguments=", m_arguments); if (m_isVariadics) d << ",..."; @@ -1203,6 +1169,16 @@ void _FunctionModelItem::formatDebug(QDebug &d) const #endif // !QT_NO_DEBUG_STREAM // --------------------------------------------------------------------------- +_TypeDefModelItem::_TypeDefModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind) +{ +} + +_TypeDefModelItem::_TypeDefModelItem(CodeModel *model, const QString &name, int kind) + : _CodeModelItem(model, name, kind) +{ +} + TypeInfo _TypeDefModelItem::type() const { return m_type; @@ -1254,7 +1230,7 @@ void _TemplateTypeAliasModelItem::formatDebug(QDebug &d) const { _CodeModelItem::formatDebug(d); d << ", <"; - for (int i = 0, count = m_templateParameters.size(); i < count; ++i) { + for (qsizetype i = 0, count = m_templateParameters.size(); i < count; ++i) { if (i) d << ", "; d << m_templateParameters.at(i)->name(); @@ -1264,6 +1240,16 @@ void _TemplateTypeAliasModelItem::formatDebug(QDebug &d) const #endif // !QT_NO_DEBUG_STREAM // --------------------------------------------------------------------------- +_EnumModelItem::_EnumModelItem(CodeModel *model, const QString &name, int kind) + : _CodeModelItem(model, name, kind) +{ +} + +_EnumModelItem::_EnumModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind) +{ +} + Access _EnumModelItem::accessPolicy() const { return m_accessPolicy; @@ -1305,6 +1291,26 @@ void _EnumModelItem::setSigned(bool s) m_signed = s; } +QString _EnumModelItem::underlyingType() const +{ + return m_underlyingType; +} + +void _EnumModelItem::setUnderlyingType(const QString &underlyingType) +{ + m_underlyingType = underlyingType; +} + +bool _EnumModelItem::isDeprecated() const +{ + return m_deprecated; +} + +void _EnumModelItem::setDeprecated(bool d) +{ + m_deprecated = d; +} + #ifndef QT_NO_DEBUG_STREAM void _EnumModelItem::formatDebug(QDebug &d) const { @@ -1319,6 +1325,8 @@ void _EnumModelItem::formatDebug(QDebug &d) const d << " (class)"; break; } + if (m_deprecated) + d << " (deprecated)"; if (!m_signed) d << " (unsigned)"; formatModelItemList(d, ", enumerators=", m_enumerators); @@ -1328,6 +1336,16 @@ void _EnumModelItem::formatDebug(QDebug &d) const // --------------------------------------------------------------------------- _EnumeratorModelItem::~_EnumeratorModelItem() = default; +_EnumeratorModelItem::_EnumeratorModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind) +{ +} + +_EnumeratorModelItem::_EnumeratorModelItem(CodeModel *model, const QString &name, int kind) + : _CodeModelItem(model, name, kind) +{ +} + QString _EnumeratorModelItem::stringValue() const { return m_stringValue; @@ -1338,17 +1356,40 @@ void _EnumeratorModelItem::setStringValue(const QString &value) m_stringValue = value; } +bool _EnumeratorModelItem::isDeprecated() const +{ + return m_deprecated; +} + +void _EnumeratorModelItem::setDeprecated(bool d) +{ + m_deprecated = d; +} + #ifndef QT_NO_DEBUG_STREAM void _EnumeratorModelItem::formatDebug(QDebug &d) const { _CodeModelItem::formatDebug(d); d << ", value=" << m_value << ", stringValue=\"" << m_stringValue << '"'; + if (m_deprecated) + d << " (deprecated)"; } #endif // !QT_NO_DEBUG_STREAM // --------------------------------------------------------------------------- _TemplateParameterModelItem::~_TemplateParameterModelItem() = default; +_TemplateParameterModelItem::_TemplateParameterModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind) +{ +} + +_TemplateParameterModelItem::_TemplateParameterModelItem(CodeModel *model, + const QString &name, int kind) + : _CodeModelItem(model, name, kind) +{ +} + TypeInfo _TemplateParameterModelItem::type() const { return m_type; @@ -1412,6 +1453,16 @@ void _MemberModelItem::setStatic(bool isStatic) m_isStatic = isStatic; } +_MemberModelItem::_MemberModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind), m_flags(0) +{ +} + +_MemberModelItem::_MemberModelItem(CodeModel *model, const QString &name, int kind) + : _CodeModelItem(model, name, kind), m_flags(0) +{ +} + bool _MemberModelItem::isConstant() const { return m_isConstant; diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.h b/sources/shiboken6/ApiExtractor/parser/codemodel.h index 58c7a9d2c..b31c09163 100644 --- a/sources/shiboken6/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken6/ApiExtractor/parser/codemodel.h @@ -12,7 +12,6 @@ #include "typeinfo.h" #include <QtCore/QHash> -#include <QtCore/QPair> #include <QtCore/QSet> #include <QtCore/QString> #include <QtCore/QStringList> @@ -20,6 +19,7 @@ #include <QtCore/QWeakPointer> #include <optional> +#include <utility> QT_FORWARD_DECLARE_CLASS(QDebug) @@ -32,7 +32,7 @@ class CodeModel { Q_GADGET public: - Q_DISABLE_COPY(CodeModel) + Q_DISABLE_COPY_MOVE(CodeModel) enum FunctionType { Normal, @@ -74,7 +74,7 @@ public: NamespaceModelItem globalNamespace() const; void addFile(const FileModelItem &item); - FileModelItem findFile(const QString &name) const; + FileModelItem findFile(QAnyStringView name) const; static CodeModelItem findItem(const QStringList &qualifiedName, const ScopeModelItem &scope); @@ -91,8 +91,9 @@ QDebug operator<<(QDebug d, const CodeModel *m); class _CodeModelItem { - Q_DISABLE_COPY(_CodeModelItem) public: + Q_DISABLE_COPY_MOVE(_CodeModelItem) + enum Kind { /* These are bit-flags resembling inheritance */ Kind_Scope = 0x1, @@ -175,6 +176,7 @@ QDebug operator<<(QDebug d, const _CodeModelItem *t); class _ScopeModelItem: public _CodeModelItem { public: + Q_DISABLE_COPY_MOVE(_ScopeModelItem) DECLARE_MODEL_NODE(Scope) ~_ScopeModelItem(); @@ -194,21 +196,21 @@ public: void addVariable(const VariableModelItem &item); ClassModelItem findClass(const QString &name) const; - EnumModelItem findEnum(const QString &name) const; + EnumModelItem findEnum(QAnyStringView name) const; struct FindEnumByValueReturn { - operator bool() const { return !item.isNull(); } + operator bool() const { return bool(item); } EnumModelItem item; QString qualifiedName; }; FindEnumByValueReturn findEnumByValue(QStringView value) const; - FunctionList findFunctions(const QString &name) const; - TypeDefModelItem findTypeDef(const QString &name) const; - TemplateTypeAliasModelItem findTemplateTypeAlias(const QString &name) const; - VariableModelItem findVariable(const QString &name) const; + FunctionList findFunctions(QAnyStringView name) const; + TypeDefModelItem findTypeDef(QAnyStringView name) const; + TemplateTypeAliasModelItem findTemplateTypeAlias(QAnyStringView name) const; + VariableModelItem findVariable(QAnyStringView name) const; void addEnumsDeclaration(const QString &enumsDeclaration); QStringList enumsDeclarations() const { return m_enumsDeclarations; } @@ -223,10 +225,9 @@ public: #endif protected: - explicit _ScopeModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind) {} - explicit _ScopeModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind) {} + explicit _ScopeModelItem(CodeModel *model, int kind = __node_kind); + explicit _ScopeModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); void appendScope(const _ScopeModelItem &other); @@ -258,6 +259,7 @@ private: class _ClassModelItem: public _ScopeModelItem { public: + Q_DISABLE_COPY_MOVE(_ClassModelItem) DECLARE_MODEL_NODE(Class) struct BaseClass @@ -274,10 +276,9 @@ public: Access access = Access::Public; }; - explicit _ClassModelItem(CodeModel *model, int kind = __node_kind) - : _ScopeModelItem(model, kind), m_classType(CodeModel::Class) {} - explicit _ClassModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _ScopeModelItem(model, name, kind), m_classType(CodeModel::Class) {} + explicit _ClassModelItem(CodeModel *model, int kind = __node_kind); + explicit _ClassModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); ~_ClassModelItem(); const QList<BaseClass> &baseClasses() const { return m_baseClasses; } @@ -313,7 +314,7 @@ private: QList<BaseClass> m_baseClasses; QList<UsingMember> m_usingMembers; TemplateParameterList m_templateParameters; - CodeModel::ClassType m_classType; + CodeModel::ClassType m_classType = CodeModel::Class; QStringList m_propertyDeclarations; bool m_final = false; @@ -322,12 +323,12 @@ private: class _NamespaceModelItem: public _ScopeModelItem { public: + Q_DISABLE_COPY_MOVE(_NamespaceModelItem) DECLARE_MODEL_NODE(Namespace) - explicit _NamespaceModelItem(CodeModel *model, int kind = __node_kind) - : _ScopeModelItem(model, kind) {} - explicit _NamespaceModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _ScopeModelItem(model, name, kind) {} + explicit _NamespaceModelItem(CodeModel *model, int kind = __node_kind); + explicit _NamespaceModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); ~_NamespaceModelItem(); const NamespaceList &namespaces() const { return m_namespaces; } @@ -337,7 +338,7 @@ public: void addNamespace(NamespaceModelItem item); - NamespaceModelItem findNamespace(const QString &name) const; + NamespaceModelItem findNamespace(QAnyStringView name) const; void appendNamespace(const _NamespaceModelItem &other); @@ -353,24 +354,23 @@ private: class _FileModelItem: public _NamespaceModelItem { public: + Q_DISABLE_COPY_MOVE(_FileModelItem) DECLARE_MODEL_NODE(File) - explicit _FileModelItem(CodeModel *model, int kind = __node_kind) - : _NamespaceModelItem(model, kind) {} - explicit _FileModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _NamespaceModelItem(model, name, kind) {} + using _NamespaceModelItem::_NamespaceModelItem; + ~_FileModelItem(); }; class _ArgumentModelItem: public _CodeModelItem { public: + Q_DISABLE_COPY_MOVE(_ArgumentModelItem) DECLARE_MODEL_NODE(Argument) - explicit _ArgumentModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind), m_defaultValue(false) {} - explicit _ArgumentModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind), m_defaultValue(false) {} + explicit _ArgumentModelItem(CodeModel *model, int kind = __node_kind); + explicit _ArgumentModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); ~_ArgumentModelItem(); TypeInfo type() const; @@ -382,6 +382,10 @@ public: QString defaultValueExpression() const { return m_defaultValueExpression; } void setDefaultValueExpression(const QString &expr) { m_defaultValueExpression = expr; } + // Argument type has scope resolution "::ArgumentType" + bool scopeResolution() const; + void setScopeResolution(bool v); + #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; #endif @@ -389,18 +393,19 @@ public: private: TypeInfo m_type; QString m_defaultValueExpression; - bool m_defaultValue; + bool m_defaultValue = false; + bool m_scopeResolution = false; }; class _MemberModelItem: public _CodeModelItem { public: + Q_DISABLE_COPY_MOVE(_MemberModelItem) DECLARE_MODEL_NODE(Member) - explicit _MemberModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind), m_accessPolicy(Access::Public), m_flags(0) {} - explicit _MemberModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind), m_accessPolicy(Access::Public), m_flags(0) {} + explicit _MemberModelItem(CodeModel *model, int kind = __node_kind); + explicit _MemberModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); ~_MemberModelItem(); bool isConstant() const; @@ -443,7 +448,7 @@ public: private: TemplateParameterList m_templateParameters; TypeInfo m_type; - Access m_accessPolicy; + Access m_accessPolicy = Access::Public; union { struct { uint m_isConstant: 1; @@ -463,12 +468,12 @@ private: class _FunctionModelItem: public _MemberModelItem { public: + Q_DISABLE_COPY_MOVE(_FunctionModelItem) DECLARE_MODEL_NODE(Function) - explicit _FunctionModelItem(CodeModel *model, int kind = __node_kind) - : _MemberModelItem(model, kind), m_functionType(CodeModel::Normal), m_flags(0) {} - explicit _FunctionModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _MemberModelItem(model, name, kind), m_functionType(CodeModel::Normal), m_flags(0) {} + explicit _FunctionModelItem(CodeModel *model, int kind = __node_kind); + explicit _FunctionModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); ~_FunctionModelItem(); ArgumentList arguments() const; @@ -480,39 +485,25 @@ public: static std::optional<CodeModel::FunctionType> functionTypeFromName(QStringView name); + FunctionAttributes attributes() const { return m_attributes; } + void setAttributes(FunctionAttributes a) { m_attributes = a; } + void setAttribute(FunctionAttribute a, bool on = true) { m_attributes.setFlag(a, on); } + bool isDeleted() const; void setDeleted(bool d); - bool isDeprecated() const; - void setDeprecated(bool d); - - bool isVirtual() const; - void setVirtual(bool isVirtual); - - bool isOverride() const; - void setOverride(bool o); - - bool isFinal() const; - void setFinal(bool f); - bool isInline() const; void setInline(bool isInline); - bool isExplicit() const; - void setExplicit(bool isExplicit); - bool isHiddenFriend() const; void setHiddenFriend(bool f); - bool isInvokable() const; // Qt - void setInvokable(bool isInvokable); // Qt - - bool isAbstract() const; - void setAbstract(bool isAbstract); - bool isVariadics() const; void setVariadics(bool isVariadics); + bool scopeResolution() const; // Return type has scope resolution "::ReturnType" + void setScopeResolution(bool v); + bool isDefaultConstructor() const; bool isSpaceshipOperator() const; @@ -538,20 +529,16 @@ private: CodeModel::FunctionType _determineTypeHelper() const; ArgumentList m_arguments; - CodeModel::FunctionType m_functionType; + FunctionAttributes m_attributes; + CodeModel::FunctionType m_functionType = CodeModel::Normal; union { struct { uint m_isDeleted: 1; - uint m_isVirtual: 1; - uint m_isOverride: 1; - uint m_isFinal: 1; - uint m_isDeprecated: 1; uint m_isInline: 1; - uint m_isAbstract: 1; - uint m_isExplicit: 1; uint m_isVariadics: 1; uint m_isHiddenFriend: 1; uint m_isInvokable : 1; // Qt + uint m_scopeResolution: 1; }; uint m_flags; }; @@ -563,10 +550,7 @@ class _VariableModelItem: public _MemberModelItem public: DECLARE_MODEL_NODE(Variable) - explicit _VariableModelItem(CodeModel *model, int kind = __node_kind) - : _MemberModelItem(model, kind) {} - explicit _VariableModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _MemberModelItem(model, name, kind) {} + using _MemberModelItem::_MemberModelItem; }; class _TypeDefModelItem: public _CodeModelItem @@ -574,10 +558,9 @@ class _TypeDefModelItem: public _CodeModelItem public: DECLARE_MODEL_NODE(TypeDef) - explicit _TypeDefModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind) {} - explicit _TypeDefModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind) {} + explicit _TypeDefModelItem(CodeModel *model, int kind = __node_kind); + explicit _TypeDefModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); TypeInfo type() const; void setType(const TypeInfo &type); @@ -617,12 +600,11 @@ private: class _EnumModelItem: public _CodeModelItem { public: + Q_DISABLE_COPY_MOVE(_EnumModelItem) DECLARE_MODEL_NODE(Enum) - explicit _EnumModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind) {} - explicit _EnumModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind) {} + explicit _EnumModelItem(CodeModel *model, const QString &name, int kind = __node_kind); + explicit _EnumModelItem(CodeModel *model, int kind = __node_kind); ~_EnumModelItem(); Access accessPolicy() const; @@ -641,25 +623,33 @@ public: void formatDebug(QDebug &d) const override; #endif + bool isDeprecated() const; + void setDeprecated(bool d); + bool isSigned() const; void setSigned(bool s); + QString underlyingType() const; + void setUnderlyingType(const QString &underlyingType); + private: + QString m_underlyingType; Access m_accessPolicy = Access::Public; EnumeratorList m_enumerators; EnumKind m_enumKind = CEnum; + bool m_deprecated = false; bool m_signed = true; }; class _EnumeratorModelItem: public _CodeModelItem { public: + Q_DISABLE_COPY_MOVE(_EnumeratorModelItem) DECLARE_MODEL_NODE(Enumerator) - explicit _EnumeratorModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind) {} - explicit _EnumeratorModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind) {} + explicit _EnumeratorModelItem(CodeModel *model, int kind = __node_kind); + explicit _EnumeratorModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); ~_EnumeratorModelItem(); QString stringValue() const; @@ -668,6 +658,9 @@ public: EnumValue value() const { return m_value; } void setValue(EnumValue v) { m_value = v; } + bool isDeprecated() const; + void setDeprecated(bool d); + #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; #endif @@ -675,17 +668,18 @@ public: private: QString m_stringValue; EnumValue m_value; + bool m_deprecated = false; }; class _TemplateParameterModelItem: public _CodeModelItem { public: + Q_DISABLE_COPY_MOVE(_TemplateParameterModelItem) DECLARE_MODEL_NODE(TemplateParameter) - explicit _TemplateParameterModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind), m_defaultValue(false) {} - explicit _TemplateParameterModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind), m_defaultValue(false) {} + explicit _TemplateParameterModelItem(CodeModel *model, int kind = __node_kind); + explicit _TemplateParameterModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); ~_TemplateParameterModelItem(); TypeInfo type() const; @@ -700,9 +694,7 @@ public: private: TypeInfo m_type; - bool m_defaultValue; + bool m_defaultValue = false; }; #endif // CODEMODEL_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h b/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h index 1a058bdfe..e5c429bd0 100644 --- a/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h +++ b/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h @@ -4,6 +4,8 @@ #ifndef CODEMODEL_ENUMS_H #define CODEMODEL_ENUMS_H +#include <QtCore/qflags.h> + enum ReferenceType { NoReference, LValueReference, @@ -43,4 +45,17 @@ enum class Access Public }; +enum class FunctionAttribute { + Abstract = 0x00000001, + Static = 0x00000002, + Virtual = 0x00000004, + Override = 0x00000008, + Final = 0x00000010, + Deprecated = 0x00000020, // Code annotation + Explicit = 0x00000040, // Constructor +}; + +Q_DECLARE_FLAGS(FunctionAttributes, FunctionAttribute) +Q_DECLARE_OPERATORS_FOR_FLAGS(FunctionAttributes) + #endif // CODEMODEL_ENUMS_H diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel_fwd.h b/sources/shiboken6/ApiExtractor/parser/codemodel_fwd.h index a3adf6678..f0a25c9db 100644 --- a/sources/shiboken6/ApiExtractor/parser/codemodel_fwd.h +++ b/sources/shiboken6/ApiExtractor/parser/codemodel_fwd.h @@ -7,7 +7,8 @@ #define CODEMODEL_FWD_H #include <QtCore/QList> -#include <QtCore/QSharedPointer> + +#include <memory> // forward declarations class CodeModel; @@ -27,20 +28,20 @@ class _VariableModelItem; class _MemberModelItem; class TypeInfo; -using ArgumentModelItem = QSharedPointer<_ArgumentModelItem>; -using ClassModelItem = QSharedPointer<_ClassModelItem>; -using CodeModelItem = QSharedPointer<_CodeModelItem>; -using EnumModelItem = QSharedPointer<_EnumModelItem>; -using EnumeratorModelItem = QSharedPointer<_EnumeratorModelItem>; -using FileModelItem = QSharedPointer<_FileModelItem>; -using FunctionModelItem = QSharedPointer<_FunctionModelItem>; -using NamespaceModelItem = QSharedPointer<_NamespaceModelItem>; -using ScopeModelItem = QSharedPointer<_ScopeModelItem>; -using TemplateParameterModelItem = QSharedPointer<_TemplateParameterModelItem>; -using TypeDefModelItem = QSharedPointer<_TypeDefModelItem>; -using TemplateTypeAliasModelItem = QSharedPointer<_TemplateTypeAliasModelItem>; -using VariableModelItem = QSharedPointer<_VariableModelItem>; -using MemberModelItem = QSharedPointer<_MemberModelItem>; +using ArgumentModelItem = std::shared_ptr<_ArgumentModelItem>; +using ClassModelItem = std::shared_ptr<_ClassModelItem>; +using CodeModelItem = std::shared_ptr<_CodeModelItem>; +using EnumModelItem = std::shared_ptr<_EnumModelItem>; +using EnumeratorModelItem = std::shared_ptr<_EnumeratorModelItem>; +using FileModelItem = std::shared_ptr<_FileModelItem>; +using FunctionModelItem = std::shared_ptr<_FunctionModelItem>; +using NamespaceModelItem = std::shared_ptr<_NamespaceModelItem>; +using ScopeModelItem = std::shared_ptr<_ScopeModelItem>; +using TemplateParameterModelItem = std::shared_ptr<_TemplateParameterModelItem>; +using TypeDefModelItem = std::shared_ptr<_TypeDefModelItem>; +using TemplateTypeAliasModelItem = std::shared_ptr<_TemplateTypeAliasModelItem>; +using VariableModelItem = std::shared_ptr<_VariableModelItem>; +using MemberModelItem = std::shared_ptr<_MemberModelItem>; using ArgumentList = QList<ArgumentModelItem>; using ClassList = QList<ClassModelItem>; diff --git a/sources/shiboken6/ApiExtractor/parser/enumvalue.cpp b/sources/shiboken6/ApiExtractor/parser/enumvalue.cpp index 3fa641e0c..3749e16a8 100644 --- a/sources/shiboken6/ApiExtractor/parser/enumvalue.cpp +++ b/sources/shiboken6/ApiExtractor/parser/enumvalue.cpp @@ -7,12 +7,34 @@ #include <QtCore/QString> #include <QtCore/QTextStream> +using namespace Qt::StringLiterals; + QString EnumValue::toString() const { return m_type == EnumValue::Signed ? QString::number(m_value) : QString::number(m_unsignedValue); } +QString EnumValue::toHex(int fieldWidth) const +{ + QString result; + QTextStream str(&result); + // Note: Qt goofes up formatting of negative padded hex numbers, it ends up + // with "0x00-1". Write '-' before. + if (isNegative()) + str << '-'; + str << "0x" << Qt::hex; + if (fieldWidth) { + str.setFieldWidth(fieldWidth); + str.setPadChar(u'0'); + } + if (m_type == EnumValue::Signed) + str << qAbs(m_value); + else + str << m_unsignedValue; + return result; +} + void EnumValue::setValue(qint64 v) { m_value = v; @@ -25,11 +47,37 @@ void EnumValue::setUnsignedValue(quint64 v) m_type = Unsigned; } -bool EnumValue::equals(const EnumValue &rhs) const +EnumValue EnumValue::toUnsigned() const { - if (m_type != rhs.m_type) + if (m_type == Unsigned) + return *this; + EnumValue result; + result.setUnsignedValue(m_value < 0 ? quint64(-m_value) : quint64(m_value)); + return result; +} + +bool comparesEqual(const EnumValue &lhs, const EnumValue &rhs) noexcept +{ + if (lhs.m_type != rhs.m_type) return false; - return m_type == Signed ? m_value == rhs.m_value : m_unsignedValue == rhs.m_unsignedValue; + return lhs.m_type == EnumValue::Signed + ? lhs.m_value == rhs.m_value : lhs.m_unsignedValue == rhs.m_unsignedValue; +} + +void EnumValue::formatDebugHex(QDebug &d) const +{ + d << "0x" << Qt::hex; + formatDebug(d); + d << Qt::dec; +} + +void EnumValue::formatDebug(QDebug &d) const +{ + + if (m_type == EnumValue::Signed) + d << m_value; + else + d << m_unsignedValue << 'u'; } #ifndef QT_NO_DEBUG_STREAM @@ -39,10 +87,7 @@ QDebug operator<<(QDebug d,const EnumValue &v) d.nospace(); d.noquote(); d << "EnumValue("; - if (v.m_type == EnumValue::Signed) - d << v.m_value; - else - d << v.m_unsignedValue << 'u'; + v.formatDebug(d); d << ')'; return d; } diff --git a/sources/shiboken6/ApiExtractor/parser/enumvalue.h b/sources/shiboken6/ApiExtractor/parser/enumvalue.h index bae2b30bf..bbd5a712d 100644 --- a/sources/shiboken6/ApiExtractor/parser/enumvalue.h +++ b/sources/shiboken6/ApiExtractor/parser/enumvalue.h @@ -4,7 +4,9 @@ #ifndef ENUMVALUE_H #define ENUMVALUE_H -#include <QtCore/QtGlobal> +#include <QtCore/qtypes.h> +#include <QtCore/qtclasshelpermacros.h> +#include <QtCore/QtCompare> QT_FORWARD_DECLARE_CLASS(QDebug) QT_FORWARD_DECLARE_CLASS(QString) @@ -20,18 +22,29 @@ public: }; QString toString() const; + QString toHex(int fieldWidth = 0) const; Type type() { return m_type; } qint64 value() const { return m_value; } quint64 unsignedValue() const { return m_unsignedValue; } bool isNullValue() const { return m_type == Signed ? m_value == 0 : m_unsignedValue == 0u; } + bool isNegative() const { return m_type == Signed && m_value < 0; } void setValue(qint64 v); void setUnsignedValue(quint64 v); + EnumValue toUnsigned() const; + bool equals(const EnumValue &rhs) const; + void formatDebug(QDebug &d) const; + void formatDebugHex(QDebug &d) const; + private: + friend bool comparesEqual(const EnumValue &lhs, + const EnumValue &rhs) noexcept; + Q_DECLARE_EQUALITY_COMPARABLE(EnumValue) + #ifndef QT_NO_DEBUG_STREAM friend QDebug operator<<(QDebug, const EnumValue &); #endif @@ -45,9 +58,4 @@ private: Type m_type = Signed; }; -inline bool operator==(const EnumValue &e1, const EnumValue &e2) -{ return e1.equals(e2); } -inline bool operator!=(const EnumValue &e1, const EnumValue &e2) -{ return !e1.equals(e2); } - #endif // ENUMVALUE_H diff --git a/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp b/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp index 2dff569cb..f8c5c31d8 100644 --- a/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp +++ b/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp @@ -7,6 +7,7 @@ #include "codemodel.h" #include <clangparser/clangutils.h> +#include <debughelpers_p.h> #include "qtcompat.h" @@ -46,10 +47,10 @@ public: }; }; - ReferenceType m_referenceType; + ReferenceType m_referenceType = NoReference; }; -TypeInfoData::TypeInfoData() : flags(0), m_referenceType(NoReference) +TypeInfoData::TypeInfoData() : flags(0) { } @@ -60,9 +61,8 @@ TypeInfo::TypeInfo() : d(new TypeInfoData) TypeInfo::~TypeInfo() = default; TypeInfo::TypeInfo(const TypeInfo &) = default; TypeInfo& TypeInfo::operator=(const TypeInfo &) = default; -TypeInfo::TypeInfo(TypeInfo &&) = default; -TypeInfo& TypeInfo::operator=(TypeInfo &&) = default; - +TypeInfo::TypeInfo(TypeInfo &&) noexcept = default; +TypeInfo &TypeInfo::operator=(TypeInfo &&) noexcept = default; static inline TypeInfo createType(const QString &name) { @@ -98,7 +98,7 @@ TypeInfo TypeInfo::combine(const TypeInfo &__lhs, const TypeInfo &__rhs) __result.setArrayElements(__result.arrayElements() + __rhs.arrayElements()); - const auto instantiations = __rhs.instantiations(); + const auto &instantiations = __rhs.instantiations(); for (const auto &i : instantiations) __result.addInstantiation(i); @@ -266,6 +266,12 @@ void TypeInfo::clearInstantiations() d->m_instantiations.clear(); } +bool TypeInfo::isPlain() const +{ + return d->m_constant == 0 && d->m_volatile == 0 && d->m_referenceType == NoReference + && d->m_indirections.isEmpty() && d->m_arrayElements.isEmpty(); +} + TypeInfo TypeInfo::resolveType(TypeInfo const &__type, const ScopeModelItem &__scope) { CodeModel *__model = __scope->model(); @@ -286,14 +292,14 @@ TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, con otherType.setQualifiedName(__item->qualifiedName()); } - if (TypeDefModelItem __typedef = qSharedPointerDynamicCast<_TypeDefModelItem>(__item)) { + if (TypeDefModelItem __typedef = std::dynamic_pointer_cast<_TypeDefModelItem>(__item)) { const TypeInfo combined = TypeInfo::combine(__typedef->type(), otherType); const CodeModelItem nextItem = __scope->model()->findItem(combined.qualifiedName(), __scope); if (!nextItem) return combined; // PYSIDE-362, prevent recursion on opaque structs like // typedef struct xcb_connection_t xcb_connection_t; - if (nextItem.data() ==__item.data()) { + if (nextItem.get() ==__item.get()) { std::cerr << "** WARNING Bailing out recursion of " << __FUNCTION__ << "() on " << qPrintable(__type.qualifiedName().join(u"::"_s)) << std::endl; @@ -302,18 +308,18 @@ TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, con return resolveType(nextItem, combined, __scope); } - if (TemplateTypeAliasModelItem templateTypeAlias = qSharedPointerDynamicCast<_TemplateTypeAliasModelItem>(__item)) { + if (TemplateTypeAliasModelItem templateTypeAlias = std::dynamic_pointer_cast<_TemplateTypeAliasModelItem>(__item)) { TypeInfo combined = TypeInfo::combine(templateTypeAlias->type(), otherType); // For the alias "template<typename T> using QList = QVector<T>" with // other="QList<int>", replace the instantiations to obtain "QVector<int>". auto aliasInstantiations = templateTypeAlias->type().instantiations(); const auto &concreteInstantiations = otherType.instantiations(); - const int count = qMin(aliasInstantiations.size(), concreteInstantiations.size()); - for (int i = 0; i < count; ++i) - aliasInstantiations[i] = concreteInstantiations[i]; + const auto count = qMin(aliasInstantiations.size(), concreteInstantiations.size()); + for (qsizetype i = 0; i < count; ++i) + aliasInstantiations[i] = concreteInstantiations.at(i); combined.setInstantiations(aliasInstantiations); - const CodeModelItem nextItem = __scope->model()->findItem(combined.qualifiedName(), __scope); + const CodeModelItem nextItem = CodeModel::findItem(combined.qualifiedName(), __scope); if (!nextItem) return combined; return resolveType(nextItem, combined, __scope); @@ -341,6 +347,10 @@ public: while (level < m_parseStack.size()) m_parseStack.pop(); TypeInfo instantiation; + if (name.startsWith(u"const ")) { + instantiation.setConstant(true); + name = name.mid(6); + } instantiation.setQualifiedName(qualifiedName(name)); top()->addInstantiation(instantiation); } @@ -361,7 +371,8 @@ private: QStack<TypeInfo *> m_parseStack; }; -QPair<int, int> TypeInfo::parseTemplateArgumentList(const QString &l, int from) +std::pair<qsizetype, qsizetype> + TypeInfo::parseTemplateArgumentList(const QString &l, qsizetype from) { return clang::parseTemplateArgumentList(l, clang::TemplateArgumentHandler(TypeInfoTemplateArgumentHandler(this)), from); } @@ -377,9 +388,9 @@ QString TypeInfo::toString() const tmp += d->m_qualifiedName.join(u"::"_s); - if (const int instantiationCount = d->m_instantiations.size()) { + if (const auto instantiationCount = d->m_instantiations.size()) { tmp += u'<'; - for (int i = 0; i < instantiationCount; ++i) { + for (qsizetype i = 0; i < instantiationCount; ++i) { if (i) tmp += u", "_s; tmp += d->m_instantiations.at(i).toString(); @@ -441,34 +452,31 @@ bool TypeInfoData::equals(const TypeInfoData &other) const && m_instantiations == other.m_instantiations; } -bool TypeInfo::equals(const TypeInfo &other) const + +bool comparesEqual(const TypeInfo &lhs, const TypeInfo &rhs) noexcept { - return d.data() == other.d.data() || d->equals(*other.d); + return lhs.d.data() == rhs.d.data() || lhs.d->equals(*rhs.d); } QString TypeInfo::indirectionKeyword(Indirection i) { - return i == Indirection::Pointer - ? QStringLiteral("*") : QStringLiteral("*const"); + return i == Indirection::Pointer ? "*"_L1 : "*const"_L1; } -static inline QString constQualifier() { return QStringLiteral("const"); } -static inline QString volatileQualifier() { return QStringLiteral("volatile"); } - bool TypeInfo::stripLeadingConst(QString *s) { - return stripLeadingQualifier(constQualifier(), s); + return stripLeadingQualifier("const"_L1, s); } bool TypeInfo::stripLeadingVolatile(QString *s) { - return stripLeadingQualifier(volatileQualifier(), s); + return stripLeadingQualifier("volatile"_L1, s); } -bool TypeInfo::stripLeadingQualifier(const QString &qualifier, QString *s) +bool TypeInfo::stripLeadingQualifier(QLatin1StringView qualifier, QString *s) { // "const int x" - const int qualifierSize = qualifier.size(); + const auto qualifierSize = qualifier.size(); if (s->size() < qualifierSize + 1 || !s->startsWith(qualifier) || !s->at(qualifierSize).isSpace()) { return false; @@ -514,7 +522,7 @@ void TypeInfoData::simplifyStdType() Q_ASSERT(isStdType()); if (m_qualifiedName.at(1).startsWith(u"__")) m_qualifiedName.removeAt(1); - for (int t = m_instantiations.size() - 1; t >= 0; --t) { + for (auto t = m_instantiations.size() - 1; t >= 0; --t) { if (m_instantiations.at(t).isStdType()) { if (discardStdType(m_instantiations.at(t).qualifiedName().constLast())) m_instantiations.removeAt(t); @@ -558,16 +566,6 @@ void TypeInfo::formatTypeSystemSignature(QTextStream &str) const } #ifndef QT_NO_DEBUG_STREAM -template <class It> -void formatSequence(QDebug &d, It i1, It i2, const char *separator=", ") -{ - for (It i = i1; i != i2; ++i) { - if (i != i1) - d << separator; - d << *i; - } -} - void TypeInfo::formatDebug(QDebug &debug) const { debug << '"'; diff --git a/sources/shiboken6/ApiExtractor/parser/typeinfo.h b/sources/shiboken6/ApiExtractor/parser/typeinfo.h index e015647fa..e4f363b67 100644 --- a/sources/shiboken6/ApiExtractor/parser/typeinfo.h +++ b/sources/shiboken6/ApiExtractor/parser/typeinfo.h @@ -10,8 +10,11 @@ #include <QtCore/QString> #include <QtCore/QSharedDataPointer> +#include <QtCore/QtCompare> #include <QtCore/QStringList> +#include <utility> + QT_FORWARD_DECLARE_CLASS(QDebug) QT_FORWARD_DECLARE_CLASS(QTextStream) @@ -28,8 +31,8 @@ public: ~TypeInfo(); TypeInfo(const TypeInfo &); TypeInfo& operator=(const TypeInfo &); - TypeInfo(TypeInfo &&); - TypeInfo& operator=(TypeInfo &&); + TypeInfo(TypeInfo &&) noexcept; + TypeInfo &operator=(TypeInfo &&) noexcept; static TypeInfo voidType(); static TypeInfo varArgsType(); @@ -77,11 +80,12 @@ public: void addInstantiation(const TypeInfo &i); void clearInstantiations(); - bool isStdType() const; + bool isPlain() const; // neither const,volatile, no indirections/references, array - QPair<int, int> parseTemplateArgumentList(const QString &l, int from = 0); + bool isStdType() const; - bool equals(const TypeInfo &other) const; + std::pair<qsizetype, qsizetype> + parseTemplateArgumentList(const QString &l, qsizetype from = 0); // ### arrays and templates?? @@ -100,12 +104,16 @@ public: static bool stripLeadingConst(QString *s); static bool stripLeadingVolatile(QString *s); - static bool stripLeadingQualifier(const QString &qualifier, QString *s); + static bool stripLeadingQualifier(QLatin1StringView qualifier, QString *s); static void stripQualifiers(QString *s); void simplifyStdType(); private: + friend bool comparesEqual(const TypeInfo &lhs, + const TypeInfo &rhs) noexcept; + Q_DECLARE_EQUALITY_COMPARABLE(TypeInfo) + QSharedDataPointer<TypeInfoData> d; friend class TypeInfoTemplateArgumentHandler; @@ -113,12 +121,6 @@ private: static TypeInfo resolveType(CodeModelItem item, TypeInfo const &__type, const ScopeModelItem &__scope); }; -inline bool operator==(const TypeInfo &t1, const TypeInfo &t2) -{ return t1.equals(t2); } - -inline bool operator!=(const TypeInfo &t1, const TypeInfo &t2) -{ return !t1.equals(t2); } - #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const TypeInfo &t); #endif diff --git a/sources/shiboken6/ApiExtractor/predefined_templates.cpp b/sources/shiboken6/ApiExtractor/predefined_templates.cpp index f1b23c240..992f735ac 100644 --- a/sources/shiboken6/ApiExtractor/predefined_templates.cpp +++ b/sources/shiboken6/ApiExtractor/predefined_templates.cpp @@ -10,7 +10,7 @@ using namespace Qt::StringLiterals; static QString pySequenceToCppContainer(const QString &insertFunc, bool reserve) { - QString result; + QString result = u"(%out).clear();\n"_s; if (reserve) { result += uR"(if (PyList_Check(%in)) { const Py_ssize_t size = PySequence_Size(%in); @@ -39,20 +39,37 @@ while (true) { return result; } -static const char stlMapKeyAccessor[] = "->first"; -static const char stlMapValueAccessor[] = "->second"; -static const char qtMapKeyAccessor[] = ".key()"; -static const char qtMapValueAccessor[] = ".value()"; +// Convert a sequence to a limited/fixed array +static QString pySequenceToCppArray() +{ + return uR"(Shiboken::AutoDecRef it(PyObject_GetIter(%in)); +for (auto oit = std::begin(%out), oend = std::end(%out); oit != oend; ++oit) { + Shiboken::AutoDecRef pyItem(PyIter_Next(it.object())); + if (pyItem.isNull()) { + if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration)) + PyErr_Clear(); + break; + } + %OUTTYPE_0 cppItem = %CONVERTTOCPP[%OUTTYPE_0](pyItem); + *oit = cppItem; +} +)"_s; +} + +static constexpr auto stlMapKeyAccessor = "->first"_L1; +static constexpr auto stlMapValueAccessor = "->second"_L1; +static constexpr auto qtMapKeyAccessor = ".key()"_L1; +static constexpr auto qtMapValueAccessor = ".value()"_L1; static QString cppMapToPyDict(bool isQMap) { return uR"(PyObject *%out = PyDict_New(); -for (auto it = %in.cbegin(), end = %in.cend(); it != end; ++it) { +for (auto it = std::cbegin(%in), end = std::cend(%in); it != end; ++it) { const auto &key = it)"_s - + QLatin1StringView(isQMap ? qtMapKeyAccessor : stlMapKeyAccessor) + + (isQMap ? qtMapKeyAccessor : stlMapKeyAccessor) + uR"(; const auto &value = it)"_s - + QLatin1StringView(isQMap ? qtMapValueAccessor : stlMapValueAccessor) + + (isQMap ? qtMapValueAccessor : stlMapValueAccessor) + uR"(; PyObject *pyKey = %CONVERTTOPYTHON[%INTYPE_0](key); PyObject *pyValue = %CONVERTTOPYTHON[%INTYPE_1](value); @@ -68,6 +85,7 @@ static QString pyDictToCppMap(bool isQMap) { return uR"(PyObject *key; PyObject *value; +%out.clear(); Py_ssize_t pos = 0; while (PyDict_Next(%in, &pos, &key, &value)) { %OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key); @@ -83,9 +101,9 @@ while (PyDict_Next(%in, &pos, &key, &value)) { static QString cppMultiMapToPyDict(bool isQMultiMap) { return uR"(PyObject *%out = PyDict_New(); - for (auto it = %in.cbegin(), end = %in.cend(); it != end; ) { + for (auto it = std::cbegin(%in), end = std::cend(%in); it != end; ) { const auto &key = it)"_s - + QLatin1StringView(isQMultiMap ? qtMapKeyAccessor : stlMapKeyAccessor) + + (isQMultiMap ? qtMapKeyAccessor : stlMapKeyAccessor) + uR"(; PyObject *pyKey = %CONVERTTOPYTHON[%INTYPE_0](key); auto upper = %in.)"_s @@ -109,9 +127,9 @@ static QString cppMultiMapToPyDict(bool isQMultiMap) static QString cppMultiHashToPyDict(bool isQMultiHash) { return uR"(PyObject *%out = PyDict_New(); - for (auto it = %in.cbegin(), end = %in.cend(); it != end; ) { + for (auto it = std::cbegin(%in), end = std::cend(%in); it != end; ) { const auto &key = it)"_s - + QLatin1StringView(isQMultiHash ? qtMapKeyAccessor : stlMapKeyAccessor) + + (isQMultiHash ? qtMapKeyAccessor : stlMapKeyAccessor) + uR"(; PyObject *pyKey = %CONVERTTOPYTHON[%INTYPE_0](key); auto range = %in.equal_range(key); @@ -134,6 +152,7 @@ static QString pyDictToCppMultiHash(bool isQMultiHash) { return uR"(PyObject *key; PyObject *values; + %out.clear(); Py_ssize_t pos = 0; while (PyDict_Next(%in, &pos, &key, &values)) { %OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key); @@ -172,7 +191,7 @@ return %out; {u"shiboken_conversion_cppsequence_to_pylist"_s, uR"(PyObject *%out = PyList_New(Py_ssize_t(%in.size())); Py_ssize_t idx = 0; -for (auto it = %in.cbegin(), end = %in.cend(); it != end; ++it, ++idx) { +for (auto it = std::cbegin(%in), end = std::cend(%in); it != end; ++it, ++idx) { const auto &cppItem = *it; PyList_SET_ITEM(%out, idx, %CONVERTTOPYTHON[%INTYPE_0](cppItem)); } @@ -190,6 +209,8 @@ return %out;)"_s}, pySequenceToCppContainer(u"push_back"_s, false)}, {u"shiboken_conversion_pyiterable_to_cppsequentialcontainer_reserve"_s, pySequenceToCppContainer(u"push_back"_s, true)}, + {u"shiboken_conversion_pyiterable_to_cpparray"_s, + pySequenceToCppArray()}, {u"shiboken_conversion_pyiterable_to_cppsetcontainer"_s, pySequenceToCppContainer(u"insert"_s, false)}, @@ -231,19 +252,25 @@ QByteArray containerTypeSystemSnippet(const char *name, const char *type, const char *targetToNativeType, const char *targetToNative) { - return QByteArrayLiteral("<container-type name=\"") + QByteArray result = QByteArrayLiteral("<container-type name=\"") + name + QByteArrayLiteral("\" type=\"") + type + R"("> <include file-name=")" + include + R"(" location="global"/> <conversion-rule> <native-to-target> <insert-template name=")" + nativeToTarget + R"("/> </native-to-target> - <target-to-native> - <add-conversion type=")" + targetToNativeType + R"("> - <insert-template name=")" + targetToNative + R"("/> +)"; + if (targetToNativeType != nullptr) { + result += QByteArrayLiteral(R"( <target-to-native> + <add-conversion type=")") + targetToNativeType + + QByteArrayLiteral(R"("> + <insert-template name=")") + targetToNative + QByteArrayLiteral(R"("/> </add-conversion> </target-to-native> - </conversion-rule> +)"); + } +result += QByteArrayLiteral(R"( </conversion-rule> </container-type> -)"; +)"); + return result; } diff --git a/sources/shiboken6/ApiExtractor/predefined_templates.h b/sources/shiboken6/ApiExtractor/predefined_templates.h index 2519f65d9..0cc2c7f32 100644 --- a/sources/shiboken6/ApiExtractor/predefined_templates.h +++ b/sources/shiboken6/ApiExtractor/predefined_templates.h @@ -21,7 +21,7 @@ const PredefinedTemplates &predefinedTemplates(); QByteArray containerTypeSystemSnippet(const char *name, const char *type, const char *include, const char *nativeToTarget, - const char *targetToNativeType, - const char *targetToNative); + const char *targetToNativeType = nullptr, + const char *targetToNative = nullptr); #endif // PREDEFINED_TEMPLATES_H diff --git a/sources/shiboken6/ApiExtractor/primitivetypeentry.h b/sources/shiboken6/ApiExtractor/primitivetypeentry.h index d0b50aa9c..6faaf7a61 100644 --- a/sources/shiboken6/ApiExtractor/primitivetypeentry.h +++ b/sources/shiboken6/ApiExtractor/primitivetypeentry.h @@ -5,6 +5,7 @@ #define PRIMITIVETYPEENTRY_H #include "typesystem.h" +#include "customconversion_typedefs.h" class PrimitiveTypeEntryPrivate; @@ -15,7 +16,7 @@ class PrimitiveTypeEntry : public TypeEntry { public: explicit PrimitiveTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); QString defaultConstructor() const; void setDefaultConstructor(const QString& defaultConstructor); @@ -27,25 +28,13 @@ public: * \return the type referenced by the typedef, or a null pointer * if the current object is not an typedef */ - PrimitiveTypeEntry *referencedTypeEntry() const; + PrimitiveTypeEntryPtr referencedTypeEntry() const; /** * Defines type referenced by this entry. * \param referencedTypeEntry type referenced by this entry */ - void setReferencedTypeEntry(PrimitiveTypeEntry* referencedTypeEntry); - - /// Finds the most basic primitive type that the typedef represents, - /// i.e. a type that is not an typedef'ed. - /// \return the most basic non-typedef'ed primitive type represented - /// by this typedef or self in case it is not a reference. - const PrimitiveTypeEntry* basicReferencedTypeEntry() const; - - /// Finds the basic primitive type that the typedef represents - /// and was explicitly specified in the type system. - /// \return the basic primitive type that was explicitly specified in - /// the type system. - const PrimitiveTypeEntry* basicReferencedNonBuiltinTypeEntry() const; + void setReferencedTypeEntry(PrimitiveTypeEntryPtr referencedTypeEntry); /// Returns whether this entry references another entry. bool referencesType() const; @@ -53,6 +42,10 @@ public: bool preferredTargetLangType() const; void setPreferredTargetLangType(bool b); + bool hasCustomConversion() const; + void setCustomConversion(const CustomConversionPtr &customConversion); + CustomConversionPtr customConversion() const; + TypeEntry *clone() const override; #ifndef QT_NO_DEBUG_STREAM @@ -63,4 +56,17 @@ protected: explicit PrimitiveTypeEntry(PrimitiveTypeEntryPrivate *d); }; +/// Finds the most basic primitive type that the typedef represents, +/// i.e. a type that is not an typedef'ed. +/// \return the most basic non-typedef'ed primitive type represented +/// by this typedef or self in case it is not a reference. +PrimitiveTypeEntryCPtr basicReferencedTypeEntry(const PrimitiveTypeEntryCPtr &e); +PrimitiveTypeEntryCPtr basicReferencedTypeEntry(const TypeEntryCPtr &e); + +/// Finds the basic primitive type that the typedef represents +/// and was explicitly specified in the type system. +/// \return the basic primitive type that was explicitly specified in +/// the type system. +PrimitiveTypeEntryCPtr basicReferencedNonBuiltinTypeEntry(const PrimitiveTypeEntryCPtr &e); + #endif // PRIMITIVETYPEENTRY_H diff --git a/sources/shiboken6/ApiExtractor/propertyspec.cpp b/sources/shiboken6/ApiExtractor/propertyspec.cpp index 54ac6fdab..32b756fad 100644 --- a/sources/shiboken6/ApiExtractor/propertyspec.cpp +++ b/sources/shiboken6/ApiExtractor/propertyspec.cpp @@ -5,9 +5,10 @@ #include "abstractmetalang.h" #include "abstractmetabuilder_p.h" #include "abstractmetatype.h" -#include "codemodel.h" +#include "documentation.h" #include "messages.h" #include "complextypeentry.h" +#include "typeinfo.h" #include "qtcompat.h" @@ -31,6 +32,7 @@ public: m_write(ts.write), m_designable(ts.designable), m_reset(ts.reset), + m_notify(ts.notify), m_type(type), m_generateGetSetDef(ts.generateGetSetDef) { @@ -41,6 +43,8 @@ public: QString m_write; QString m_designable; QString m_reset; + QString m_notify; + Documentation m_documentation; AbstractMetaType m_type; int m_index = -1; // Indicates whether actual code is generated instead of relying on libpyside. @@ -55,8 +59,8 @@ QPropertySpec::QPropertySpec(const TypeSystemProperty &ts, QPropertySpec::QPropertySpec(const QPropertySpec &) = default; QPropertySpec &QPropertySpec::operator=(const QPropertySpec &) = default; -QPropertySpec::QPropertySpec(QPropertySpec &&) = default; -QPropertySpec &QPropertySpec::operator=(QPropertySpec &&) = default; +QPropertySpec::QPropertySpec(QPropertySpec &&) noexcept = default; +QPropertySpec &QPropertySpec::operator=(QPropertySpec &&) noexcept = default; QPropertySpec::~QPropertySpec() = default; const AbstractMetaType &QPropertySpec::type() const @@ -70,7 +74,7 @@ void QPropertySpec::setType(const AbstractMetaType &t) d->m_type = t; } -const TypeEntry *QPropertySpec::typeEntry() const +TypeEntryCPtr QPropertySpec::typeEntry() const { return d->m_type.typeEntry(); } @@ -86,6 +90,17 @@ void QPropertySpec::setName(const QString &name) d->m_name = name; } +Documentation QPropertySpec::documentation() const +{ + return d->m_documentation; +} + +void QPropertySpec::setDocumentation(const Documentation &doc) +{ + if (d->m_documentation != doc) + d->m_documentation = doc; +} + QString QPropertySpec::read() const { return d->m_read; @@ -135,6 +150,17 @@ void QPropertySpec::setReset(const QString &reset) d->m_reset = reset; } +QString QPropertySpec::notify() const +{ + return d->m_notify; +} + +void QPropertySpec::setNotify(const QString ¬ify) +{ + if (d->m_notify != notify) + d->m_notify = notify; +} + int QPropertySpec::index() const { return d->m_index; @@ -163,13 +189,15 @@ void QPropertySpec::setGenerateGetSetDef(bool generateGetSetDef) TypeSystemProperty QPropertySpec::typeSystemPropertyFromQ_Property(const QString &declarationIn, QString *errorMessage) { - enum class PropertyToken { None, Read, Write, Designable, Reset }; + enum class PropertyToken { None, Read, Write, Designable, Reset, Notify, Member }; static const QHash<QString, PropertyToken> tokenLookup = { - {QStringLiteral("READ"), PropertyToken::Read}, - {QStringLiteral("WRITE"), PropertyToken::Write}, - {QStringLiteral("DESIGNABLE"), PropertyToken::Designable}, - {QStringLiteral("RESET"), PropertyToken::Reset} + {"READ"_L1, PropertyToken::Read}, + {"WRITE"_L1, PropertyToken::Write}, + {"DESIGNABLE"_L1, PropertyToken::Designable}, + {"RESET"_L1, PropertyToken::Reset}, + {"NOTIFY"_L1, PropertyToken::Notify}, + {"MEMBER"_L1, PropertyToken::Member} }; errorMessage->clear(); @@ -192,13 +220,13 @@ TypeSystemProperty QPropertySpec::typeSystemPropertyFromQ_Property(const QString return result; } - const int firstToken = int(it - propertyTokens.cbegin()); + const auto firstToken = qsizetype(it - propertyTokens.cbegin()); if (firstToken < 2) { *errorMessage = u"Insufficient number of tokens in property specification"_s; return result; } - for (int pos = firstToken; pos + 1 < propertyTokens.size(); pos += 2) { + for (qsizetype pos = firstToken; pos + 1 < propertyTokens.size(); pos += 2) { switch (tokenLookup.value(propertyTokens.at(pos))) { case PropertyToken::Read: result.read = propertyTokens.at(pos + 1); @@ -212,16 +240,24 @@ TypeSystemProperty QPropertySpec::typeSystemPropertyFromQ_Property(const QString case PropertyToken::Designable: result.designable = propertyTokens.at(pos + 1); break; + case PropertyToken::Notify: + result.notify = propertyTokens.at(pos + 1); + break; + case PropertyToken::Member: + // Ignore MEMBER tokens introduced by QTBUG-16852 as Python + // properties are anyways generated for fields. + return {}; + case PropertyToken::None: break; } } - const int namePos = firstToken - 1; + const auto namePos = firstToken - 1; result.name = propertyTokens.at(namePos); result.type = propertyTokens.constFirst(); - for (int pos = 1; pos < namePos; ++pos) + for (qsizetype pos = 1; pos < namePos; ++pos) result.type += u' ' + propertyTokens.at(pos); // Fix errors like "Q_PROPERTY(QXYSeries *series .." to be of type "QXYSeries*" @@ -238,7 +274,7 @@ TypeSystemProperty QPropertySpec::typeSystemPropertyFromQ_Property(const QString // the AbstractMetaType from the type string. std::optional<QPropertySpec> QPropertySpec::fromTypeSystemProperty(AbstractMetaBuilderPrivate *b, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, const TypeSystemProperty &ts, const QStringList &scopes, QString *errorMessage) @@ -254,7 +290,7 @@ std::optional<QPropertySpec> auto type = b->translateType(info, metaClass, {}, &typeError); if (!type.has_value()) { const QStringList qualifiedName = info.qualifiedName(); - for (int j = scopes.size(); j >= 0 && !type; --j) { + for (auto j = scopes.size(); j >= 0 && !type; --j) { info.setQualifiedName(scopes.mid(0, j) + qualifiedName); type = b->translateType(info, metaClass, {}, &typeError); } @@ -271,7 +307,7 @@ std::optional<QPropertySpec> // via TypeSystemProperty. std::optional<QPropertySpec> QPropertySpec::parseQ_Property(AbstractMetaBuilderPrivate *b, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, const QString &declarationIn, const QStringList &scopes, QString *errorMessage) @@ -294,6 +330,8 @@ void QPropertySpec::formatDebug(QDebug &debug) const debug << ", reset=" << d->m_reset; if (!d->m_designable.isEmpty()) debug << ", designable=" << d->m_designable; + if (!d->m_documentation.isEmpty()) + debug << ", doc=\"" << d->m_documentation << '"'; } QDebug operator<<(QDebug d, const QPropertySpec &p) diff --git a/sources/shiboken6/ApiExtractor/propertyspec.h b/sources/shiboken6/ApiExtractor/propertyspec.h index b32d6c08a..9e2e0f3d4 100644 --- a/sources/shiboken6/ApiExtractor/propertyspec.h +++ b/sources/shiboken6/ApiExtractor/propertyspec.h @@ -6,6 +6,9 @@ class AbstractMetaType; +#include "abstractmetalang_typedefs.h" +#include "typesystem_typedefs.h" + #include <QtCore/QStringList> #include <QtCore/QSharedDataPointer> @@ -14,6 +17,7 @@ class AbstractMetaType; class AbstractMetaClass; class AbstractMetaBuilderPrivate; class AbstractMetaType; +class Documentation; class TypeEntry; struct TypeSystemProperty; @@ -29,8 +33,8 @@ public: const AbstractMetaType &type); QPropertySpec(const QPropertySpec &); QPropertySpec &operator=(const QPropertySpec &); - QPropertySpec(QPropertySpec &&); - QPropertySpec &operator=(QPropertySpec &&); + QPropertySpec(QPropertySpec &&) noexcept; + QPropertySpec &operator=(QPropertySpec &&) noexcept; ~QPropertySpec(); static TypeSystemProperty typeSystemPropertyFromQ_Property(const QString &declarationIn, @@ -39,14 +43,14 @@ public: static std::optional<QPropertySpec> fromTypeSystemProperty(AbstractMetaBuilderPrivate *b, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, const TypeSystemProperty &ts, const QStringList &scopes, QString *errorMessage); static std::optional<QPropertySpec> parseQ_Property(AbstractMetaBuilderPrivate *b, - AbstractMetaClass *metaClass, + const AbstractMetaClassPtr &metaClass, const QString &declarationIn, const QStringList &scopes, QString *errorMessage); @@ -54,11 +58,14 @@ public: const AbstractMetaType &type() const; void setType(const AbstractMetaType &t); - const TypeEntry *typeEntry() const; + TypeEntryCPtr typeEntry() const; QString name() const; void setName(const QString &name); + Documentation documentation() const; + void setDocumentation(const Documentation &doc); + QString read() const; void setRead(const QString &read); @@ -72,6 +79,9 @@ public: QString reset() const; void setReset(const QString &reset); + QString notify() const; // Q_PROPERTY/C++ only + void setNotify(const QString ¬ify); + int index() const; void setIndex(int index); diff --git a/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp b/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp index 3e7cc2a33..64d44378b 100644 --- a/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp +++ b/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp @@ -6,10 +6,15 @@ #include <QtCore/QDebug> +TextStream &operator<<(TextStream &str, const castToPyCFunction &c) +{ + str << "reinterpret_cast<PyCFunction>(" << c.m_function << ')'; + return str; +} + TextStream &operator<<(TextStream &s, const PyMethodDefEntry &e) { - s << "{\"" << e.name << "\", reinterpret_cast<PyCFunction>(" - << e.function << "), "; + s << "{\"" << e.name << "\", " << castToPyCFunction(e.function) <<", "; if (e.methFlags.isEmpty()) { s << '0'; } else { @@ -19,7 +24,9 @@ TextStream &operator<<(TextStream &s, const PyMethodDefEntry &e) s << e.methFlags.at(i); } } - if (!e.doc.isEmpty()) + if (e.doc.isEmpty()) + s << ", nullptr"; + else s << ", R\"(" << e.doc << ")\""; s << '}'; return s; diff --git a/sources/shiboken6/ApiExtractor/pymethoddefentry.h b/sources/shiboken6/ApiExtractor/pymethoddefentry.h index 54eaa4ce1..a8694eb30 100644 --- a/sources/shiboken6/ApiExtractor/pymethoddefentry.h +++ b/sources/shiboken6/ApiExtractor/pymethoddefentry.h @@ -11,6 +11,14 @@ QT_FORWARD_DECLARE_CLASS(QDebug) class TextStream; +struct castToPyCFunction +{ + explicit castToPyCFunction(QAnyStringView function) noexcept : + m_function(function) {} + + QAnyStringView m_function; +}; + struct PyMethodDefEntry { QString name; @@ -21,6 +29,7 @@ struct PyMethodDefEntry using PyMethodDefEntries = QList<PyMethodDefEntry>; +TextStream &operator<<(TextStream &str, const castToPyCFunction &e); TextStream &operator<<(TextStream &s, const PyMethodDefEntry &e); TextStream &operator<<(TextStream &s, const PyMethodDefEntries &e); diff --git a/sources/shiboken6/ApiExtractor/pythontypeentry.h b/sources/shiboken6/ApiExtractor/pythontypeentry.h index f1d12e6fd..2e0fbda97 100644 --- a/sources/shiboken6/ApiExtractor/pythontypeentry.h +++ b/sources/shiboken6/ApiExtractor/pythontypeentry.h @@ -5,6 +5,7 @@ #define PYTHONTYPEENTRY_H #include "customtypenentry.h" +#include "typesystem_enums.h" class PythonTypeEntry : public CustomTypeEntry { diff --git a/sources/shiboken6/ApiExtractor/qtcompat.h b/sources/shiboken6/ApiExtractor/qtcompat.h index 9627bb76c..3837dcfd2 100644 --- a/sources/shiboken6/ApiExtractor/qtcompat.h +++ b/sources/shiboken6/ApiExtractor/qtcompat.h @@ -4,7 +4,7 @@ #ifndef QTCOMPAT_H #define QTCOMPAT_H -#include <QtCore/QtGlobal> +#include <QtCore/qtconfigmacros.h> #if QT_VERSION < 0x060400 diff --git a/sources/shiboken6/ApiExtractor/qtdocparser.cpp b/sources/shiboken6/ApiExtractor/qtdocparser.cpp index b20a53632..5bd99bbd8 100644 --- a/sources/shiboken6/ApiExtractor/qtdocparser.cpp +++ b/sources/shiboken6/ApiExtractor/qtdocparser.cpp @@ -3,10 +3,11 @@ #include "qtdocparser.h" #include "classdocumentation.h" +#include "abstractmetaargument.h" #include "abstractmetaenum.h" -#include "abstractmetafield.h" #include "abstractmetafunction.h" #include "abstractmetalang.h" +#include "abstractmetatype.h" #include "documentation.h" #include "modifications.h" #include "messages.h" @@ -14,6 +15,8 @@ #include "reporthandler.h" #include "flagstypeentry.h" #include "complextypeentry.h" +#include "functiontypeentry.h" +#include "enumtypeentry.h" #include "qtcompat.h" @@ -25,8 +28,9 @@ using namespace Qt::StringLiterals; enum { debugFunctionSearch = 0 }; -static inline QString briefStartElement() { return QStringLiteral("<brief>"); } -static inline QString briefEndElement() { return QStringLiteral("</brief>"); } +constexpr auto briefStartElement = "<brief>"_L1; +constexpr auto briefEndElement = "</brief>"_L1; +constexpr auto webxmlSuffix = ".webxml"_L1; Documentation QtDocParser::retrieveModuleDocumentation() { @@ -56,7 +60,7 @@ static void formatFunctionUnqualifiedArgTypeQuery(QTextStream &str, case AbstractMetaType::FlagsPattern: { // Modify qualified name "QFlags<Qt::AlignmentFlag>" with name "Alignment" // to "Qt::Alignment" as seen by qdoc. - const auto *flagsEntry = static_cast<const FlagsTypeEntry *>(metaType.typeEntry()); + const auto flagsEntry = std::static_pointer_cast<const FlagsTypeEntry>(metaType.typeEntry()); QString name = flagsEntry->qualifiedCppName(); if (name.endsWith(u'>') && name.startsWith(u"QFlags<")) { const int lastColon = name.lastIndexOf(u':'); @@ -73,7 +77,7 @@ static void formatFunctionUnqualifiedArgTypeQuery(QTextStream &str, case AbstractMetaType::ContainerPattern: { // QVector<int> str << metaType.typeEntry()->qualifiedCppName() << '<'; const auto instantiations = metaType.instantiations(); - for (int i = 0, size = instantiations.size(); i < size; ++i) { + for (qsizetype i = 0, size = instantiations.size(); i < size; ++i) { if (i) str << ", "; const auto &instantiation = instantiations.at(i); @@ -99,51 +103,34 @@ static QString formatFunctionArgTypeQuery(const AbstractMetaType &metaType) return result; } -QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName, - const ClassDocumentation &classDocumentation, - const AbstractMetaClass* metaClass, - const AbstractMetaFunctionCPtr &func, - const DocModificationList &signedModifs, - QString *errorMessage) +QString QtDocParser::functionDocumentation(const QString &sourceFileName, + const ClassDocumentation &classDocumentation, + const AbstractMetaClassCPtr &metaClass, + const AbstractMetaFunctionCPtr &func, + QString *errorMessage) { errorMessage->clear(); - DocModificationList funcModifs; - for (const DocModification &funcModif : signedModifs) { - if (funcModif.signature() == func->minimalSignature()) - funcModifs.append(funcModif); - } - const QString docString = queryFunctionDocumentation(sourceFileName, classDocumentation, metaClass, func, errorMessage); + const auto funcModifs = DocParser::getXpathDocModifications(func, metaClass); return docString.isEmpty() || funcModifs.isEmpty() ? docString : applyDocModifications(funcModifs, docString); } QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName, const ClassDocumentation &classDocumentation, - const AbstractMetaClass* metaClass, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaFunctionCPtr &func, QString *errorMessage) { - // Properties - if (func->isPropertyReader() || func->isPropertyWriter() || func->isPropertyResetter()) { - const QPropertySpec &prop = metaClass->propertySpecs().at(func->propertySpecIndex()); - const auto index = classDocumentation.indexOfProperty(prop.name()); - if (index == -1) { - *errorMessage = msgCannotFindDocumentation(sourceFileName, func.data()); - return {}; - } - return classDocumentation.properties.at(index).description; - } - // Search candidates by name and const-ness FunctionDocumentationList candidates = classDocumentation.findFunctionCandidates(func->name(), func->isConstant()); if (candidates.isEmpty()) { - *errorMessage = msgCannotFindDocumentation(sourceFileName, func.data()) + *errorMessage = msgCannotFindDocumentation(sourceFileName, func.get()) + u" (no matches)"_s; return {}; } @@ -188,13 +175,13 @@ QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName, candidates.erase(pend, candidates.end()); if (candidates.size() == 1) { const auto &match = candidates.constFirst(); - QTextStream(errorMessage) << msgFallbackForDocumentation(sourceFileName, func.data()) + QTextStream(errorMessage) << msgFallbackForDocumentation(sourceFileName, func.get()) << "\n Falling back to \"" << match.signature << "\" obtained by matching the argument count only."; return candidates.constFirst().description; } - QTextStream(errorMessage) << msgCannotFindDocumentation(sourceFileName, func.data()) + QTextStream(errorMessage) << msgCannotFindDocumentation(sourceFileName, func.get()) << " (" << candidates.size() << " candidates matching the argument count)"; return {}; } @@ -203,29 +190,100 @@ QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName, // from the source. static QString extractBrief(QString *value) { - const auto briefStart = value->indexOf(briefStartElement()); + const auto briefStart = value->indexOf(briefStartElement); if (briefStart < 0) return {}; - const auto briefEnd = value->indexOf(briefEndElement(), - briefStart + briefStartElement().size()); + const auto briefEnd = value->indexOf(briefEndElement, + briefStart + briefStartElement.size()); if (briefEnd < briefStart) return {}; - const auto briefLength = briefEnd + briefEndElement().size() - briefStart; + const auto briefLength = briefEnd + briefEndElement.size() - briefStart; QString briefValue = value->mid(briefStart, briefLength); - briefValue.insert(briefValue.size() - briefEndElement().size(), + briefValue.insert(briefValue.size() - briefEndElement.size(), u"<rst> More_...</rst>"_s); value->remove(briefStart, briefLength); return briefValue; } -void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) +// Find the webxml file for global functions/enums +// by the doc-file typesystem attribute or via include file. +static QString findGlobalWebXmLFile(const QString &documentationDataDirectory, + const QString &docFile, + const Include &include) +{ + QString result; + if (!docFile.isEmpty()) { + result = documentationDataDirectory + u'/' + docFile; + if (!result.endsWith(webxmlSuffix)) + result += webxmlSuffix; + return QFileInfo::exists(result) ? result : QString{}; + } + if (include.name().isEmpty()) + return {}; + // qdoc "\headerfile <QtLogging>" directive produces "qtlogging.webxml" + result = documentationDataDirectory + u'/' + + QFileInfo(include.name()).baseName() + webxmlSuffix; + if (QFileInfo::exists(result)) + return result; + // qdoc "\headerfile <qdrawutil.h>" produces "qdrawutil-h.webxml" + result.insert(result.size() - webxmlSuffix.size(), "-h"_L1); + return QFileInfo::exists(result) ? result : QString{}; +} + +void QtDocParser::fillGlobalFunctionDocumentation(const AbstractMetaFunctionPtr &f) +{ + auto te = f->typeEntry(); + if (te == nullptr) + return; + + const QString sourceFileName = + findGlobalWebXmLFile(documentationDataDirectory(), te->docFile(), te->include()); + if (sourceFileName.isEmpty()) + return; + + QString errorMessage; + auto classDocumentationO = parseWebXml(sourceFileName, &errorMessage); + if (!classDocumentationO.has_value()) { + qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); + return; + } + const QString detailed = + functionDocumentation(sourceFileName, classDocumentationO.value(), + {}, f, &errorMessage); + if (!errorMessage.isEmpty()) + qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); + const Documentation documentation(detailed, {}); + f->setDocumentation(documentation); +} + +void QtDocParser::fillGlobalEnumDocumentation(AbstractMetaEnum &e) +{ + auto te = e.typeEntry(); + const QString sourceFileName = + findGlobalWebXmLFile(documentationDataDirectory(), te->docFile(), te->include()); + if (sourceFileName.isEmpty()) + return; + + QString errorMessage; + auto classDocumentationO = parseWebXml(sourceFileName, &errorMessage); + if (!classDocumentationO.has_value()) { + qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); + return; + } + if (!extractEnumDocumentation(classDocumentationO.value(), e)) { + qCWarning(lcShibokenDoc, "%s", + qPrintable(msgCannotFindDocumentation(sourceFileName, {}, e, {}))); + } +} + +void QtDocParser::fillDocumentation(const AbstractMetaClassPtr &metaClass) { if (!metaClass) return; - const AbstractMetaClass* context = metaClass->enclosingClass(); - while(context) { - if (context->enclosingClass() == nullptr) + auto context = metaClass->enclosingClass(); + while (context) { + if (!context->enclosingClass()) break; context = context->enclosingClass(); } @@ -234,9 +292,9 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) + metaClass->qualifiedCppName().toLower(); sourceFileRoot.replace(u"::"_s, u"-"_s); - QFileInfo sourceFile(sourceFileRoot + QStringLiteral(".webxml")); + QFileInfo sourceFile(sourceFileRoot + webxmlSuffix); if (!sourceFile.exists()) - sourceFile.setFile(sourceFileRoot + QStringLiteral(".xml")); + sourceFile.setFile(sourceFileRoot + ".xml"_L1); if (!sourceFile.exists()) { qCWarning(lcShibokenDoc).noquote().nospace() << "Can't find qdoc file for class " << metaClass->name() << ", tried: " @@ -247,22 +305,20 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) const QString sourceFileName = sourceFile.absoluteFilePath(); QString errorMessage; - ClassDocumentation classDocumentation = parseWebXml(sourceFileName, &errorMessage); - if (!classDocumentation) { + const auto classDocumentationO = parseWebXml(sourceFileName, &errorMessage); + if (!classDocumentationO.has_value()) { qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); return; } - DocModificationList signedModifs, classModifs; - const DocModificationList &mods = metaClass->typeEntry()->docModifications(); - for (const DocModification &docModif : mods) { - if (docModif.signature().isEmpty()) - classModifs.append(docModif); - else - signedModifs.append(docModif); + const auto &classDocumentation = classDocumentationO.value(); + for (const auto &p : classDocumentation.properties) { + Documentation doc(p.description, p.brief); + metaClass->setPropertyDocumentation(p.name, doc); } - QString docString = applyDocModifications(mods, classDocumentation.description); + QString docString = applyDocModifications(DocParser::getXpathDocModifications(metaClass), + classDocumentation.description); if (docString.isEmpty()) { QString className = metaClass->name(); @@ -281,12 +337,12 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) const auto &funcs = DocParser::documentableFunctions(metaClass); for (const auto &func : funcs) { const QString detailed = - queryFunctionDocumentation(sourceFileName, classDocumentation, - metaClass, func, signedModifs, &errorMessage); + functionDocumentation(sourceFileName, classDocumentation, + metaClass, func, &errorMessage); if (!errorMessage.isEmpty()) qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); const Documentation documentation(detailed, {}); - qSharedPointerConstCast<AbstractMetaFunction>(func)->setDocumentation(documentation); + std::const_pointer_cast<AbstractMetaFunction>(func)->setDocumentation(documentation); } #if 0 // Fields @@ -302,18 +358,35 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) #endif // Enums for (AbstractMetaEnum &meta_enum : metaClass->enums()) { - Documentation enumDoc; - const auto index = classDocumentation.indexOfEnum(meta_enum.name()); - if (index != -1) { - enumDoc.setValue(classDocumentation.enums.at(index).description); - meta_enum.setDocumentation(enumDoc); - } else { + if (!extractEnumDocumentation(classDocumentation, meta_enum)) { qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotFindDocumentation(sourceFileName, metaClass, meta_enum, {}))); } } } +bool QtDocParser::extractEnumDocumentation(const ClassDocumentation &classDocumentation, + AbstractMetaEnum &meta_enum) +{ + Documentation enumDoc; + const auto index = classDocumentation.indexOfEnum(meta_enum.name()); + if (index == -1) + return false; + QString doc = classDocumentation.enums.at(index).description; + const auto firstPara = doc.indexOf(u"<para>"); + if (firstPara != -1) { + const QString baseClass = QtDocParser::enumBaseClass(meta_enum); + if (baseClass != "Enum"_L1) { + const QString note = "(inherits <teletype>enum."_L1 + baseClass + + "</teletype>) "_L1; + doc.insert(firstPara + 6, note); + } + } + enumDoc.setValue(doc); + meta_enum.setDocumentation(enumDoc); + return true; +} + static QString qmlReferenceLink(const QFileInfo &qmlModuleFi) { QString result; diff --git a/sources/shiboken6/ApiExtractor/qtdocparser.h b/sources/shiboken6/ApiExtractor/qtdocparser.h index 2b82c1265..f6ba5e47a 100644 --- a/sources/shiboken6/ApiExtractor/qtdocparser.h +++ b/sources/shiboken6/ApiExtractor/qtdocparser.h @@ -12,23 +12,28 @@ class QtDocParser : public DocParser { public: QtDocParser() = default; - void fillDocumentation(AbstractMetaClass* metaClass) override; + void fillDocumentation(const AbstractMetaClassPtr &metaClass) override; + void fillGlobalFunctionDocumentation(const AbstractMetaFunctionPtr &f) override; + void fillGlobalEnumDocumentation(AbstractMetaEnum &e) override; + Documentation retrieveModuleDocumentation() override; Documentation retrieveModuleDocumentation(const QString& name) override; private: - static QString queryFunctionDocumentation(const QString &sourceFileName, - const ClassDocumentation &classDocumentation, - const AbstractMetaClass* metaClass, - const AbstractMetaFunctionCPtr &func, - const DocModificationList &signedModifs, - QString *errorMessage); + static QString functionDocumentation(const QString &sourceFileName, + const ClassDocumentation &classDocumentation, + const AbstractMetaClassCPtr &metaClass, + const AbstractMetaFunctionCPtr &func, + QString *errorMessage); static QString queryFunctionDocumentation(const QString &sourceFileName, const ClassDocumentation &classDocumentation, - const AbstractMetaClass* metaClass, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaFunctionCPtr &func, QString *errorMessage); + static bool extractEnumDocumentation(const ClassDocumentation &classDocumentation, + AbstractMetaEnum &meta_enum); + }; #endif // QTDOCPARSER_H diff --git a/sources/shiboken6/ApiExtractor/reporthandler.cpp b/sources/shiboken6/ApiExtractor/reporthandler.cpp index 1fbd36bf4..23066ba21 100644 --- a/sources/shiboken6/ApiExtractor/reporthandler.cpp +++ b/sources/shiboken6/ApiExtractor/reporthandler.cpp @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "reporthandler.h" -#include "typesystem.h" #include "typedatabase.h" #include "qtcompat.h" @@ -34,6 +33,7 @@ static ReportHandler::DebugLevel m_debugLevel = ReportHandler::NoDebug; static QSet<QString> m_reportedWarnings; static QString m_prefix; static bool m_withinProgress = false; +static QByteArray m_progressMessage; static int m_step_warning = 0; static QElapsedTimer m_timer; @@ -123,7 +123,7 @@ void ReportHandler::messageOutput(QtMsgType type, const QMessageLogContext &cont QString message = m_prefix; if (!message.isEmpty()) message.append(u' '); - const int prefixLength = message.size(); + const auto prefixLength = message.size(); message.append(text); // Replace file location tab by space if (fileLocationPos >= 0) @@ -148,9 +148,13 @@ void ReportHandler::startProgress(const QByteArray& str) endProgress(); m_withinProgress = true; - const auto ts = '[' + timeStamp() + ']'; - std::printf("%s %8s %-60s", qPrintable(m_prefix), ts.constData(), str.constData()); - std::fflush(stdout); + m_progressMessage = str; +} + +static void indentStdout(qsizetype n) +{ + for (qsizetype i = 0; i < n; ++i) + fputc(' ', stdout); } void ReportHandler::endProgress() @@ -159,11 +163,23 @@ void ReportHandler::endProgress() return; m_withinProgress = false; + + std::fputs(m_prefix.toUtf8().constData(), stdout); + const auto ts = timeStamp(); + if (ts.size() < 6) + indentStdout(6 - ts.size()); + std::fputs(" [", stdout); + std::fputs(ts.constData(), stdout); + std::fputs("] ", stdout); + std::fputs(m_progressMessage.constData(), stdout); + if (m_progressMessage.size() < 60) + indentStdout(60 - m_progressMessage.size()); const char *endMessage = m_step_warning == 0 ? "[" COLOR_GREEN "OK" COLOR_END "]\n" : "[" COLOR_YELLOW "WARNING" COLOR_END "]\n"; std::fputs(endMessage, stdout); std::fflush(stdout); + m_progressMessage.clear(); m_step_warning = 0; } diff --git a/sources/shiboken6/ApiExtractor/smartpointertypeentry.h b/sources/shiboken6/ApiExtractor/smartpointertypeentry.h index d99c7ef8f..7b712fe35 100644 --- a/sources/shiboken6/ApiExtractor/smartpointertypeentry.h +++ b/sources/shiboken6/ApiExtractor/smartpointertypeentry.h @@ -8,17 +8,23 @@ class SmartPointerTypeEntryPrivate; +struct SmartPointerInstantiation +{ + QString name; // user defined name + TypeEntryCPtr typeEntry; +}; + class SmartPointerTypeEntry : public ComplexTypeEntry { public: - using Instantiations = QList<const TypeEntry *>; + using Instantiations = QList<SmartPointerInstantiation>; explicit SmartPointerTypeEntry(const QString &entryName, const QString &getterName, TypeSystem::SmartPointerType type, const QString &refCountMethodName, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); TypeSystem::SmartPointerType smartPointerType() const; @@ -35,13 +41,11 @@ public: TypeEntry *clone() const override; - Instantiations instantiations() const; + const Instantiations &instantiations() const; void setInstantiations(const Instantiations &i); - bool matchesInstantiation(const TypeEntry *e) const; + bool matchesInstantiation(const TypeEntryCPtr &e) const; - static QString getTargetFullName(const AbstractMetaType &metaType, - bool includePackageName = true); - static QString getTargetName(const AbstractMetaType &metaType); + QString getTargetName(const AbstractMetaType &metaType) const; #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; diff --git a/sources/shiboken6/ApiExtractor/templateargumententry.h b/sources/shiboken6/ApiExtractor/templateargumententry.h index 6f191b595..9f2338022 100644 --- a/sources/shiboken6/ApiExtractor/templateargumententry.h +++ b/sources/shiboken6/ApiExtractor/templateargumententry.h @@ -12,7 +12,7 @@ class TemplateArgumentEntry : public TypeEntry { public: explicit TemplateArgumentEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); int ordinal() const; void setOrdinal(int o); diff --git a/sources/shiboken6/ApiExtractor/tests/CMakeLists.txt b/sources/shiboken6/ApiExtractor/tests/CMakeLists.txt index 97ae0f850..76c014fbb 100644 --- a/sources/shiboken6/ApiExtractor/tests/CMakeLists.txt +++ b/sources/shiboken6/ApiExtractor/tests/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + set(CMAKE_AUTORCC ON) macro(declare_test testname) @@ -15,7 +18,7 @@ macro(declare_test testname) ${CMAKE_CURRENT_BINARY_DIR} ${apiextractor_SOURCE_DIR} ) - target_link_libraries(${testname} PRIVATE apiextractor Qt${QT_MAJOR_VERSION}::Test) + target_link_libraries(${testname} PRIVATE apiextractor Qt::Test) add_test(${testname} ${testname}) if (INSTALL_TESTS) install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${testname} diff --git a/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp b/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp index 17a6c5e2e..4b5da0c3a 100644 --- a/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp @@ -4,6 +4,7 @@ #include "testabstractmetaclass.h" #include "abstractmetabuilder.h" #include "testutil.h" +#include <abstractmetaargument.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> #include <usingmember.h> @@ -17,10 +18,12 @@ using namespace Qt::StringLiterals; void TestAbstractMetaClass::testClassName() { - const char* cppCode ="class ClassName {};"; - const char* xmlCode = "<typesystem package=\"Foo\"><value-type name=\"ClassName\"/></typesystem>"; + const char cppCode[] = "class ClassName {};"; + const char xmlCode[] = R"(<typesystem package="Foo"> + <value-type name="ClassName"/> +</typesystem>)"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); QCOMPARE(classes[0]->name(), u"ClassName"); @@ -28,15 +31,15 @@ void TestAbstractMetaClass::testClassName() void TestAbstractMetaClass::testClassNameUnderNamespace() { - const char* cppCode ="namespace Namespace { class ClassName {}; }\n"; - const char* xmlCode = R"XML( + const char cppCode[] = "namespace Namespace { class ClassName {}; }\n"; + const char xmlCode[] = R"XML( <typesystem package="Foo"> <namespace-type name="Namespace"> <value-type name="ClassName"/> </namespace-type> </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); // 1 namespace + 1 class if (classes.constFirst()->name() != u"ClassName") @@ -68,7 +71,7 @@ void TestAbstractMetaClass::testClassNameUnderNamespace() // QVERIFY(classes[0]->hasNonPrivateConstructor()); } -static AbstractMetaFunctionCList virtualFunctions(const AbstractMetaClass *c) +static AbstractMetaFunctionCList virtualFunctions(const AbstractMetaClassCPtr &c) { AbstractMetaFunctionCList result; const auto &functions = c->functions(); @@ -107,18 +110,16 @@ public: </typesystem> )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 4); - AbstractMetaClass* a = AbstractMetaClass::findClass(classes, u"A"); - AbstractMetaClass* b = AbstractMetaClass::findClass(classes, u"B"); - AbstractMetaClass* c = AbstractMetaClass::findClass(classes, u"C"); - const AbstractMetaClass *f = AbstractMetaClass::findClass(classes, u"F"); + const auto a = AbstractMetaClass::findClass(classes, "A"); + const auto b = AbstractMetaClass::findClass(classes, "B"); + const auto c = AbstractMetaClass::findClass(classes, "C"); + const auto f = AbstractMetaClass::findClass(classes, "F"); QVERIFY(f); - AbstractMetaClass* no_class = nullptr; - - QCOMPARE(a->baseClass(), no_class); + QCOMPARE(a->baseClass(), nullptr); QCOMPARE(b->baseClass(), a); QCOMPARE(c->baseClass(), b); QCOMPARE(f->baseClass(), c); @@ -158,11 +159,11 @@ public: const auto funcF = virtualFunctionsF.constFirst(); QCOMPARE(funcA->ownerClass(), a); - QVERIFY(funcC->attributes().testFlag(AbstractMetaFunction::VirtualCppMethod)); + QVERIFY(funcC->isVirtual()); QCOMPARE(funcB->ownerClass(), b); QCOMPARE(funcC->ownerClass(), c); - QVERIFY(funcC->attributes().testFlag(AbstractMetaFunction::OverriddenCppMethod)); - QVERIFY(funcF->attributes().testFlag(AbstractMetaFunction::FinalCppMethod)); + QVERIFY(funcC->cppAttributes().testFlag(FunctionAttribute::Override)); + QVERIFY(funcF->cppAttributes().testFlag(FunctionAttribute::Final)); QCOMPARE(funcA->declaringClass(), a); QCOMPARE(funcB->declaringClass(), a); @@ -193,34 +194,34 @@ class Derived : public Base {}; </typesystem> )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto base = AbstractMetaClass::findClass(classes, u"Base"); + const auto base = AbstractMetaClass::findClass(classes, "Base"); QVERIFY(base); QVERIFY(base->isPolymorphic()); - auto derived = AbstractMetaClass::findClass(classes, u"Derived"); + const auto derived = AbstractMetaClass::findClass(classes, "Derived"); QVERIFY(derived); QVERIFY(derived->isPolymorphic()); } void TestAbstractMetaClass::testDefaultValues() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {\n\ class B {};\n\ void method(B b = B());\n\ };\n"; - const char* xmlCode = R"XML( + const char xmlCode[] = R"XML( <typesystem package="Foo"> <value-type name='A'> <value-type name='B'/> </value-type> </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); const auto candidates = classA->queryFunctionsByName(u"method"_s); QCOMPARE(candidates.size(), 1); const auto &method = candidates.constFirst(); @@ -230,12 +231,12 @@ void TestAbstractMetaClass::testDefaultValues() void TestAbstractMetaClass::testModifiedDefaultValues() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {\n\ class B {};\n\ void method(B b = B());\n\ };\n"; - const char* xmlCode = R"XML( + const char xmlCode[] = R"XML( <typesystem package="Foo"> <value-type name='A'> <modify-function signature='method(A::B)'> @@ -247,10 +248,10 @@ void TestAbstractMetaClass::testModifiedDefaultValues() </value-type> </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); const auto methodMatches = classA->queryFunctionsByName(u"method"_s); QCOMPARE(methodMatches.size(), 1); const auto method = methodMatches.constFirst(); @@ -261,25 +262,25 @@ void TestAbstractMetaClass::testModifiedDefaultValues() void TestAbstractMetaClass::testInnerClassOfAPolymorphicOne() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {\n\ class B {};\n\ virtual void method();\n\ };\n"; - const char* xmlCode = R"XML( + const char xmlCode[] = R"XML( <typesystem package="Foo"> <object-type name='A'> <value-type name='B'/> </object-type> </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QVERIFY(classA->isPolymorphic()); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"A::B"); + const auto classB = AbstractMetaClass::findClass(classes, "A::B"); QVERIFY(classB); QVERIFY(!classB->isPolymorphic()); } @@ -301,15 +302,15 @@ void TestAbstractMetaClass::testForwardDeclaredInnerClass() </value-type> </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"A::B"); + const auto classB = AbstractMetaClass::findClass(classes, "A::B"); QVERIFY(classB); - const auto fooF = classB->findFunction(u"foo"); - QVERIFY(!fooF.isNull()); + const auto fooF = classB->findFunction("foo"); + QVERIFY(fooF); } void TestAbstractMetaClass::testSpecialFunctions() @@ -332,11 +333,11 @@ void TestAbstractMetaClass::testSpecialFunctions() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); auto ctors = classA->queryFunctions(FunctionQueryOption::AnyConstructor); QCOMPARE(ctors.size(), 2); @@ -347,7 +348,7 @@ void TestAbstractMetaClass::testSpecialFunctions() QCOMPARE(assigmentOps.constFirst()->functionType(), AbstractMetaFunction::AssignmentOperatorFunction); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); ctors = classB->queryFunctions(FunctionQueryOption::AnyConstructor); QCOMPARE(ctors.size(), 2); @@ -360,7 +361,7 @@ void TestAbstractMetaClass::testSpecialFunctions() void TestAbstractMetaClass::testClassDefaultConstructors() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {};\n\ \n\ struct B {\n\ @@ -386,7 +387,7 @@ void TestAbstractMetaClass::testClassDefaultConstructors() struct F {\n\ F(int, int);\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='int'/>\n\ <value-type name='A'/>\n\ @@ -398,11 +399,11 @@ void TestAbstractMetaClass::testClassDefaultConstructors() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 6); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->functions().size(), 2); @@ -416,28 +417,28 @@ void TestAbstractMetaClass::testClassDefaultConstructors() QCOMPARE(ctors[1]->arguments().size(), 1); QCOMPARE(ctors[1]->minimalSignature(), u"A(A)"); - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); QCOMPARE(classB->functions().size(), 2); QCOMPARE(classB->functions().constFirst()->minimalSignature(), u"B()"); - AbstractMetaClass* classC = AbstractMetaClass::findClass(classes, u"C"); + const auto classC = AbstractMetaClass::findClass(classes, "C"); QVERIFY(classC); QCOMPARE(classC->functions().size(), 1); QCOMPARE(classC->functions().constFirst()->minimalSignature(), u"C(C)"); - AbstractMetaClass* classD = AbstractMetaClass::findClass(classes, u"D"); + const auto classD = AbstractMetaClass::findClass(classes, "D"); QVERIFY(classD); QCOMPARE(classD->functions().size(), 1); QCOMPARE(classD->functions().constFirst()->minimalSignature(), u"D(D)"); QVERIFY(classD->functions().constFirst()->isPrivate()); - AbstractMetaClass* classE = AbstractMetaClass::findClass(classes, u"E"); + const auto classE = AbstractMetaClass::findClass(classes, "E"); QVERIFY(classE); QVERIFY(classE->hasPrivateDestructor()); QCOMPARE(classE->functions().size(), 0); - AbstractMetaClass* classF = AbstractMetaClass::findClass(classes, u"F"); + const auto classF = AbstractMetaClass::findClass(classes, "F"); QVERIFY(classF); ctors = classF->queryFunctions(FunctionQueryOption::AnyConstructor); @@ -453,24 +454,24 @@ void TestAbstractMetaClass::testClassDefaultConstructors() void TestAbstractMetaClass::testClassInheritedDefaultConstructors() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {\n\ A();\n\ private: \n\ A(const A&);\n\ };\n\ struct B : public A {};\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <object-type name='A'/>\n\ <object-type name='B'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); auto ctors = classA->queryFunctions(FunctionQueryOption::AnyConstructor); @@ -484,7 +485,7 @@ void TestAbstractMetaClass::testClassInheritedDefaultConstructors() QCOMPARE(ctors[1]->minimalSignature(), u"A(A)"); QVERIFY(ctors[1]->isPrivate()); - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); ctors = classB->queryFunctions(FunctionQueryOption::Constructors); @@ -495,20 +496,20 @@ void TestAbstractMetaClass::testClassInheritedDefaultConstructors() void TestAbstractMetaClass::testAbstractClassDefaultConstructors() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {\n\ virtual void method() = 0;\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <object-type name='A'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); const auto ctors = classA->queryFunctions(FunctionQueryOption::Constructors); @@ -519,17 +520,17 @@ void TestAbstractMetaClass::testAbstractClassDefaultConstructors() void TestAbstractMetaClass::testObjectTypesMustNotHaveCopyConstructors() { - const char* cppCode ="struct A {};\n"; - const char* xmlCode = "\ + const char cppCode[] = "struct A {};\n"; + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <object-type name='A'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); const auto ctors = classA->queryFunctions(FunctionQueryOption::Constructors); @@ -540,7 +541,7 @@ void TestAbstractMetaClass::testObjectTypesMustNotHaveCopyConstructors() void TestAbstractMetaClass::testIsPolymorphic() { - const char* cppCode = "\ + const char cppCode[] = "\ class A\n\ {\n\ public:\n\ @@ -554,7 +555,7 @@ void TestAbstractMetaClass::testIsPolymorphic() B();\n\ inline bool abc() const { return false; }\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='bool'/>\n\ <value-type name='A'/>\n\ @@ -562,13 +563,13 @@ void TestAbstractMetaClass::testIsPolymorphic() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - AbstractMetaClass* b = AbstractMetaClass::findClass(classes, u"A"); + const auto b = AbstractMetaClass::findClass(classes, "A"); QVERIFY(!b->isPolymorphic()); - AbstractMetaClass* a = AbstractMetaClass::findClass(classes, u"B"); + const auto a = AbstractMetaClass::findClass(classes, "B"); QVERIFY(!a->isPolymorphic()); } @@ -592,12 +593,12 @@ class Derived : public BaseAlias2 { )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto base = AbstractMetaClass::findClass(classes, u"Base"); + const auto base = AbstractMetaClass::findClass(classes, "Base"); QVERIFY(base); - auto derived = AbstractMetaClass::findClass(classes, u"Derived"); + const auto derived = AbstractMetaClass::findClass(classes, "Derived"); QVERIFY(derived); QCOMPARE(derived->baseClasses().value(0), base); } @@ -643,7 +644,7 @@ void TestAbstractMetaClass::testFreeOperators() </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(code.constData(), xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); const auto classes = builder->classes(); QCOMPARE(classes.size(), 1); QVERIFY(classes.constFirst()->hasArithmeticOperatorOverload()); @@ -677,12 +678,12 @@ public: )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto base = AbstractMetaClass::findClass(classes, u"Base"); + const auto base = AbstractMetaClass::findClass(classes, "Base"); QVERIFY(base); - auto derived = AbstractMetaClass::findClass(classes, u"Derived"); + const auto derived = AbstractMetaClass::findClass(classes, "Derived"); QVERIFY(derived); const auto usingMembers = derived->usingMembers(); QCOMPARE(usingMembers.size(), 2); @@ -732,9 +733,9 @@ void TestAbstractMetaClass::testUsingTemplateMembers() )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(code.constData(), xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto valueList = AbstractMetaClass::findClass(classes, u"ValueList"); + const auto valueList = AbstractMetaClass::findClass(classes, "ValueList"); QVERIFY(valueList); auto list = valueList->templateBaseClass(); QVERIFY(valueList->isUsingMember(list, u"append"_s, Access::Public)); @@ -762,9 +763,9 @@ public: )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto *tc = AbstractMetaClass::findClass(classes, u"TestClass"); + const auto tc = AbstractMetaClass::findClass(classes, "TestClass"); // Verify that the constructor and 2 functions are generated. const auto &functions = tc->functions(); QCOMPARE(functions.size(), 5); diff --git a/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp b/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp index 0b210583f..2c320c874 100644 --- a/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp @@ -3,8 +3,10 @@ #include "testabstractmetatype.h" #include "testutil.h" +#include <abstractmetaargument.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> +#include <abstractmetatype.h> #include <typesystem.h> #include <parser/codemodel.h> #include <typeparser.h> @@ -46,13 +48,13 @@ void TestAbstractMetaType::parsing() void TestAbstractMetaType::testConstCharPtrType() { - const char* cppCode ="const char* justAtest();\n"; - const char* xmlCode = "<typesystem package=\"Foo\">\n\ + const char cppCode[] = "const char* justAtest();\n"; + const char xmlCode[] = "<typesystem package=\"Foo\">\n\ <primitive-type name='char'/>\n\ <function signature='justAtest()' />\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); QCOMPARE(builder->globalFunctions().size(), 1); const auto func = builder->globalFunctions().constFirst(); AbstractMetaType rtype = func->type(); @@ -73,9 +75,9 @@ void TestAbstractMetaType::testConstCharPtrType() void TestAbstractMetaType::testApiVersionSupported() { - const char* cppCode ="class foo {}; class foo2 {};\n\ + const char cppCode[] = "class foo {}; class foo2 {};\n\ void justAtest(); void justAtest3();\n"; - const char* xmlCode = "<typesystem package='Foo'>\n\ + const char xmlCode[] = "<typesystem package='Foo'>\n\ <value-type name='foo' since='0.1'/>\n\ <value-type name='foo2' since='1.0'/>\n\ <value-type name='foo3' since='1.1'/>\n\ @@ -85,7 +87,7 @@ void TestAbstractMetaType::testApiVersionSupported() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, u"1.0"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); @@ -97,13 +99,13 @@ void TestAbstractMetaType::testApiVersionSupported() void TestAbstractMetaType::testApiVersionNotSupported() { - const char* cppCode ="class object {};\n"; - const char* xmlCode = "<typesystem package='Foo'>\n\ + const char cppCode[] = "class object {};\n"; + const char xmlCode[] = "<typesystem package='Foo'>\n\ <value-type name='object' since='0.1'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); @@ -111,14 +113,14 @@ void TestAbstractMetaType::testApiVersionNotSupported() void TestAbstractMetaType::testCharType() { - const char* cppCode ="char justAtest(); class A {};\n"; - const char* xmlCode = "<typesystem package=\"Foo\">\n\ + const char cppCode[] = "char justAtest(); class A {};\n"; + const char xmlCode[] = "<typesystem package=\"Foo\">\n\ <primitive-type name='char'/>\n\ <value-type name='A'/>\n\ <function signature='justAtest()'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); @@ -145,28 +147,28 @@ void TestAbstractMetaType::testCharType() void TestAbstractMetaType::testTypedef() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {\n\ void someMethod();\n\ };\n\ typedef A B;\n\ typedef B C;\n"; - const char* xmlCode = "<typesystem package=\"Foo\">\n\ + const char xmlCode[] = "<typesystem package=\"Foo\">\n\ <value-type name='C' />\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - const AbstractMetaClass *c = AbstractMetaClass::findClass(classes, u"C"); + const auto c = AbstractMetaClass::findClass(classes, "C"); QVERIFY(c); QVERIFY(c->isTypeDef()); } void TestAbstractMetaType::testTypedefWithTemplates() { - const char* cppCode ="\ + const char cppCode[] = "\ template<typename T>\n\ class A {};\n\ \n\ @@ -174,13 +176,13 @@ void TestAbstractMetaType::testTypedefWithTemplates() typedef A<B> C;\n\ \n\ void func(C c);\n"; - const char* xmlCode = "<typesystem package=\"Foo\">\n\ + const char xmlCode[] = "<typesystem package=\"Foo\">\n\ <container-type name='A' type='list'/>\n\ <value-type name='B' />\n\ <function signature='func(A<B>)'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); @@ -191,25 +193,25 @@ void TestAbstractMetaType::testTypedefWithTemplates() QCOMPARE(args.size(), 1); const AbstractMetaArgument &arg = args.constFirst(); AbstractMetaType metaType = arg.type(); - QCOMPARE(metaType.cppSignature(), u"A<B >"); + QCOMPARE(metaType.cppSignature(), u"A<B>"); } void TestAbstractMetaType::testObjectTypeUsedAsValue() { - const char* cppCode ="\ + const char cppCode[] = "\ class A {\n\ void method(A);\n\ };\n"; - const char* xmlCode = "<typesystem package='Foo'>\n\ + const char xmlCode[] = "<typesystem package='Foo'>\n\ <object-type name='A'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); const auto overloads = classA->queryFunctionsByName(u"method"_s); QCOMPARE(overloads.size(), 1); diff --git a/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp b/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp index d1aa1a7c4..a891e1e28 100644 --- a/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp @@ -3,11 +3,13 @@ #include "testaddfunction.h" #include "testutil.h" +#include <abstractmetaargument.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> +#include <abstractmetatype.h> #include <codesnip.h> -#include <modifications.h> -#include <modifications_p.h> +#include <addedfunction.h> +#include <addedfunction_p.h> #include <complextypeentry.h> #include <primitivetypeentry.h> @@ -17,28 +19,31 @@ using namespace Qt::StringLiterals; +static constexpr auto voidT = "void"_L1; + void TestAddFunction::testParsingFuncNameAndConstness() { // generic test... - const char sig1[] = "func(type1, const type2, const type3* const)"; + static constexpr auto sig1 = "func(type1, const type2, const type3* const)"_L1; QString errorMessage; - auto f1 = AddedFunction::createAddedFunction(QLatin1StringView(sig1), u"void"_s, - &errorMessage); - QVERIFY2(!f1.isNull(), qPrintable(errorMessage)); + auto f1 = AddedFunction::createAddedFunction(sig1, voidT, &errorMessage); + QVERIFY2(f1, qPrintable(errorMessage)); QCOMPARE(f1->name(), u"func"); QCOMPARE(f1->arguments().size(), 3); TypeInfo retval = f1->returnType(); - QCOMPARE(retval.qualifiedName(), QStringList{u"void"_s}); + QCOMPARE(retval.qualifiedName(), QStringList{voidT}); QCOMPARE(retval.indirections(), 0); QCOMPARE(retval.isConstant(), false); QCOMPARE(retval.referenceType(), NoReference); // test with a ugly template as argument and other ugly stuff - const char sig2[] = " _fu__nc_ ( type1, const type2, const Abc<int& , C<char*> * > * *@my_name@, const type3* const ) const "; - auto f2 = AddedFunction::createAddedFunction(QLatin1StringView(sig2), + static constexpr auto sig2 = + " _fu__nc_ ( type1, const type2, const Abc<int& , C<char*> * >" + " * *@my_name@, const type3* const ) const "_L1; + auto f2 = AddedFunction::createAddedFunction(sig2, u"const Abc<int& , C<char*> * > * *"_s, &errorMessage); - QVERIFY2(!f2.isNull(), qPrintable(errorMessage)); + QVERIFY2(f2, qPrintable(errorMessage)); QCOMPARE(f2->name(), u"_fu__nc_"); const auto &args = f2->arguments(); QCOMPARE(args.size(), 4); @@ -64,18 +69,15 @@ void TestAddFunction::testParsingFuncNameAndConstness() QVERIFY(args.at(3).name.isEmpty()); // function with no args. - const char sig3[] = "func()"; - auto f3 = AddedFunction::createAddedFunction(QLatin1StringView(sig3), u"void"_s, - &errorMessage); - QVERIFY2(!f3.isNull(), qPrintable(errorMessage)); + auto f3 = AddedFunction::createAddedFunction("func()"_L1, voidT, &errorMessage); + QVERIFY2(f3, qPrintable(errorMessage)); QCOMPARE(f3->name(), u"func"); QCOMPARE(f3->arguments().size(), 0); // const call operator - const char sig4[] = "operator()(int)const"; - auto f4 = AddedFunction::createAddedFunction(QLatin1StringView(sig4), u"int"_s, - &errorMessage); - QVERIFY2(!f4.isNull(), qPrintable(errorMessage)); + auto f4 = AddedFunction::createAddedFunction("operator()(int)const"_L1, + "int"_L1, &errorMessage); + QVERIFY2(f4, qPrintable(errorMessage)); QCOMPARE(f4->name(), u"operator()"); QCOMPARE(f4->arguments().size(), 1); QVERIFY(f4->isConstant()); @@ -100,15 +102,15 @@ struct A { </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - TypeDatabase* typeDb = TypeDatabase::instance(); + QVERIFY(builder); + auto *typeDb = TypeDatabase::instance(); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); // default ctor, default copy ctor, func a() and the added functions QCOMPARE(classA->functions().size(), 5); - auto addedFunc = classA->findFunction(u"b"); + auto addedFunc = classA->findFunction("b"); QVERIFY(addedFunc); QCOMPARE(addedFunc->access(), Access::Protected); QCOMPARE(addedFunc->functionType(), AbstractMetaFunction::NormalFunction); @@ -129,7 +131,7 @@ struct A { QCOMPARE(args.at(1).defaultValueExpression(), u"4.6"); QCOMPARE(args.at(2).type().typeEntry(), typeDb->findType(u"B"_s)); - auto addedCallOperator = classA->findFunction(u"operator()"); + auto addedCallOperator = classA->findFunction("operator()"); QVERIFY(addedCallOperator); } @@ -144,9 +146,9 @@ void TestAddFunction::testAddFunctionConstructor() </value-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->functions().size(), 3); // default and added ctors const auto addedFunc = classA->functions().constLast(); @@ -167,9 +169,9 @@ void TestAddFunction::testAddFunctionTagDefaultValues() </value-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); // default ctor, default copy ctor and the added function QCOMPARE(classA->functions().size(), 3); @@ -193,9 +195,9 @@ void TestAddFunction::testAddFunctionCodeSnippets() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); const auto addedFunc = classA->functions().constLast(); QVERIFY(addedFunc->hasInjectedCode()); @@ -203,11 +205,10 @@ void TestAddFunction::testAddFunctionCodeSnippets() void TestAddFunction::testAddFunctionWithoutParenteses() { - const char sig1[] = "func"; + static constexpr auto sig1 = "func"_L1; QString errorMessage; - auto f1 = AddedFunction::createAddedFunction(QLatin1StringView(sig1), u"void"_s, - &errorMessage); - QVERIFY2(!f1.isNull(), qPrintable(errorMessage)); + auto f1 = AddedFunction::createAddedFunction(sig1, voidT, &errorMessage); + QVERIFY2(f1, qPrintable(errorMessage)); QCOMPARE(f1->name(), u"func"); QCOMPARE(f1->arguments().size(), 0); QCOMPARE(f1->isConstant(), false); @@ -223,12 +224,12 @@ void TestAddFunction::testAddFunctionWithoutParenteses() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const auto addedFunc = classA->findFunction(u"func"); - QVERIFY(!addedFunc.isNull()); + const auto addedFunc = classA->findFunction(sig1); + QVERIFY(addedFunc); QVERIFY(addedFunc->hasInjectedCode()); const auto snips = addedFunc->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); @@ -237,11 +238,10 @@ void TestAddFunction::testAddFunctionWithoutParenteses() void TestAddFunction::testAddFunctionWithDefaultArgs() { - const char sig1[] = "func"; + static constexpr auto sig1 = "func"_L1; QString errorMessage; - auto f1 = AddedFunction::createAddedFunction(QLatin1StringView(sig1), u"void"_s, - &errorMessage); - QVERIFY2(!f1.isNull(), qPrintable(errorMessage)); + auto f1 = AddedFunction::createAddedFunction(sig1, voidT, &errorMessage); + QVERIFY2(f1, qPrintable(errorMessage)); QCOMPARE(f1->name(), u"func"); QCOMPARE(f1->arguments().size(), 0); QCOMPARE(f1->isConstant(), false); @@ -260,12 +260,12 @@ void TestAddFunction::testAddFunctionWithDefaultArgs() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const auto addedFunc = classA->findFunction(u"func"); - QVERIFY(!addedFunc.isNull()); + const auto addedFunc = classA->findFunction(sig1); + QVERIFY(addedFunc); const AbstractMetaArgument &arg = addedFunc->arguments().at(1); QCOMPARE(arg.defaultValueExpression(), u"2"); } @@ -283,18 +283,18 @@ void TestAddFunction::testAddFunctionAtModuleLevel() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - TypeDatabase* typeDb = TypeDatabase::instance(); + auto *typeDb = TypeDatabase::instance(); AddedFunctionList addedFuncs = typeDb->findGlobalUserFunctions(u"func"_s); QCOMPARE(addedFuncs.size(), 1); - const FunctionModificationList mods = addedFuncs.constFirst()->modifications; + auto &mods = addedFuncs.constFirst()->modifications(); QCOMPARE(mods.size(), 1); QVERIFY(mods.constFirst().isCodeInjection()); @@ -304,11 +304,10 @@ void TestAddFunction::testAddFunctionAtModuleLevel() void TestAddFunction::testAddFunctionWithVarargs() { - const char sig1[] = "func(int,char,...)"; QString errorMessage; - auto f1 = AddedFunction::createAddedFunction(QLatin1StringView(sig1), u"void"_s, + auto f1 = AddedFunction::createAddedFunction("func(int,char,...)"_L1, voidT, &errorMessage); - QVERIFY2(!f1.isNull(), qPrintable(errorMessage)); + QVERIFY2(f1, qPrintable(errorMessage)); QCOMPARE(f1->name(), u"func"); QCOMPARE(f1->arguments().size(), 3); QVERIFY(!f1->isConstant()); @@ -324,12 +323,12 @@ void TestAddFunction::testAddFunctionWithVarargs() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const auto addedFunc = classA->findFunction(u"func"); - QVERIFY(!addedFunc.isNull()); + const auto addedFunc = classA->findFunction("func"); + QVERIFY(addedFunc); const AbstractMetaArgument &arg = addedFunc->arguments().constLast(); QVERIFY(arg.type().isVarargs()); QVERIFY(arg.type().typeEntry()->isVarargs()); @@ -348,12 +347,12 @@ void TestAddFunction::testAddStaticFunction() </value-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const auto addedFunc = classA->findFunction(u"func"); - QVERIFY(!addedFunc.isNull()); + const auto addedFunc = classA->findFunction("func"); + QVERIFY(addedFunc); QVERIFY(addedFunc->isStatic()); } @@ -373,13 +372,13 @@ void TestAddFunction::testAddGlobalFunction() <value-type name='B'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); const auto globalFuncs = builder->globalFunctions(); QCOMPARE(globalFuncs.size(), 2); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(builder->classes(), u"B"); + const auto classB = AbstractMetaClass::findClass(builder->classes(), "B"); QVERIFY(classB); - QVERIFY(!classB->findFunction(u"globalFunc")); - QVERIFY(!classB->findFunction(u"globalFunc2")); + QVERIFY(!classB->findFunction("globalFunc")); + QVERIFY(!classB->findFunction("globalFunc2")); QVERIFY(!globalFuncs[0]->injectedCodeSnips().isEmpty()); QVERIFY(!globalFuncs[1]->injectedCodeSnips().isEmpty()); } @@ -399,7 +398,7 @@ void TestAddFunction::testAddFunctionWithApiVersion() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); const auto globalFuncs = builder->globalFunctions(); QCOMPARE(globalFuncs.size(), 1); } @@ -422,11 +421,11 @@ void TestAddFunction::testModifyAddedFunction() </typesystem> )"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass* foo = AbstractMetaClass::findClass(classes, u"Foo"); - const auto method = foo->findFunction(u"method"); - QVERIFY(!method.isNull()); + const auto foo = AbstractMetaClass::findClass(classes, "Foo"); + const auto method = foo->findFunction("method"); + QVERIFY(method); QCOMPARE(method->arguments().size(), 2); const AbstractMetaArgument &arg = method->arguments().at(1); QCOMPARE(arg.defaultValueExpression(), u"0"); @@ -449,17 +448,17 @@ void TestAddFunction::testAddFunctionOnTypedef() </value-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass* foo = AbstractMetaClass::findClass(classes, u"FooInt"); + const auto foo = AbstractMetaClass::findClass(classes, "FooInt"); QVERIFY(foo); QVERIFY(foo->hasNonPrivateConstructor()); const auto &lst = foo->queryFunctions(FunctionQueryOption::AnyConstructor); for (const auto &f : lst) QVERIFY(f->signature().startsWith(f->name())); QCOMPARE(lst.size(), 2); - const auto method = foo->findFunction(u"method"); - QVERIFY(!method.isNull()); + const auto method = foo->findFunction("method"); + QVERIFY(method); } void TestAddFunction::testAddFunctionWithTemplateArg() @@ -473,7 +472,7 @@ void TestAddFunction::testAddFunctionWithTemplateArg() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); QCOMPARE(builder->globalFunctions().size(), 1); const auto func = builder->globalFunctions().constFirst(); const AbstractMetaArgument &arg = func->arguments().constFirst(); diff --git a/sources/shiboken6/ApiExtractor/tests/testarrayargument.cpp b/sources/shiboken6/ApiExtractor/tests/testarrayargument.cpp index 0afbcb38f..6e1820bed 100644 --- a/sources/shiboken6/ApiExtractor/tests/testarrayargument.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testarrayargument.cpp @@ -3,9 +3,11 @@ #include "testarrayargument.h" #include "testutil.h" +#include <abstractmetaargument.h> #include <abstractmetaenum.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> +#include <abstractmetatype.h> #include <primitivetypeentry.h> #include <parser/enumvalue.h> @@ -17,12 +19,12 @@ using namespace Qt::StringLiterals; void TestArrayArgument::testArrayArgumentWithSizeDefinedByInteger() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {\n\ enum SomeEnum { Value0, Value1, NValues };\n\ void method(double[3]);\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='double'/>\n\ <object-type name='A'>\n\ @@ -32,7 +34,7 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByInteger() QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); QVERIFY(!builder.isNull()); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); const AbstractMetaArgument &arg = classA->functions().constLast()->arguments().constFirst(); @@ -41,10 +43,10 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByInteger() QCOMPARE(arg.type().arrayElementType()->name(), u"double"); } -static QString functionMinimalSignature(const AbstractMetaClass *c, const QString &name) +static QString functionMinimalSignature(const AbstractMetaClassCPtr &c, const QString &name) { const auto f = c->findFunction(name); - return f.isNull() ? QString() : f->minimalSignature(); + return f ? f->minimalSignature() : QString(); } void TestArrayArgument::testArraySignature() @@ -70,7 +72,7 @@ void TestArrayArgument::testArraySignature() QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); QVERIFY(!builder.isNull()); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "A"); QCOMPARE(functionMinimalSignature(classA, u"mi1"_s), u"mi1(int[5])"); QCOMPARE(functionMinimalSignature(classA, u"mi1c"_s), @@ -91,12 +93,12 @@ void TestArrayArgument::testArraySignature() void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValue() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {\n\ enum SomeEnum { Value0, Value1, NValues };\n\ void method(double[NValues]);\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='double'/>\n\ <object-type name='A'>\n\ @@ -106,7 +108,7 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValue() QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); QVERIFY(!builder.isNull()); - AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + AbstractMetaClassPtr classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); auto someEnum = classA->findEnum(u"SomeEnum"_s); @@ -122,12 +124,12 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValue() void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValueFromGlobalEnum() { - const char* cppCode ="\ + const char cppCode[] = "\ enum SomeEnum { Value0, Value1, NValues };\n\ struct A {\n\ void method(double[NValues]);\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='double'/>\n\ <enum-type name='SomeEnum'/>\n\ @@ -136,8 +138,8 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValueFromGlobalEnu </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + QVERIFY(builder); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); AbstractMetaEnum someEnum = builder->globalEnums().constFirst(); diff --git a/sources/shiboken6/ApiExtractor/tests/testcodeinjection.cpp b/sources/shiboken6/ApiExtractor/tests/testcodeinjection.cpp index c6c209bb4..4829e6c33 100644 --- a/sources/shiboken6/ApiExtractor/tests/testcodeinjection.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testcodeinjection.cpp @@ -8,6 +8,7 @@ #include <modifications.h> #include <textstream.h> #include <complextypeentry.h> +#include <valuetypeentry.h> #include <qtcompat.h> @@ -40,7 +41,7 @@ void TestCodeInjections::testReadFile() QFETCH(QString, snippet); QFETCH(QString, expected); - const char* cppCode ="struct A {};\n"; + const char cppCode[] = "struct A {};\n"; int argc = 0; char *argv[] = {nullptr}; QCoreApplication app(argc, argv); @@ -58,20 +59,22 @@ void TestCodeInjections::testReadFile() </value-type>\n\ </typesystem>\n"_s; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode.toLocal8Bit().constData())); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QCOMPARE(classA->typeEntry()->codeSnips().size(), 1); QString code = classA->typeEntry()->codeSnips().constFirst().code(); QVERIFY(code.indexOf(expected) != -1); - code = classA->typeEntry()->targetConversionRule(); + QVERIFY(classA->typeEntry()->isValue()); + auto vte = std::static_pointer_cast<const ValueTypeEntry>(classA->typeEntry()); + code = vte->targetConversionRule(); QVERIFY(code.indexOf(expected) != -1); } void TestCodeInjections::testInjectWithValidApiVersion() { - const char* cppCode ="struct A {};\n"; - const char* xmlCode = "\ + const char cppCode[] = "struct A {};\n"; + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <value-type name='A'>\n\ <inject-code class='target' since='1.0'>\n\ @@ -82,16 +85,16 @@ void TestCodeInjections::testInjectWithValidApiVersion() QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, u"1.0"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QCOMPARE(classA->typeEntry()->codeSnips().size(), 1); } void TestCodeInjections::testInjectWithInvalidApiVersion() { - const char* cppCode ="struct A {};\n"; - const char* xmlCode = "\ + const char cppCode[] = "struct A {};\n"; + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <value-type name='A'>\n\ <inject-code class='target' since='1.0'>\n\ @@ -102,30 +105,27 @@ void TestCodeInjections::testInjectWithInvalidApiVersion() QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QCOMPARE(classA->typeEntry()->codeSnips().size(), 0); } void TestCodeInjections::testTextStream() { StringStream str(TextStream::Language::Cpp); - str << "void foo(int a, int b) {\n"; - { - Indentation i(str); - str << "if (a == b)\n" << indent << "return a;\n" << outdent - << "#if Q_OS_WIN\nprint()\n#endif\nreturn a + b;\n"; - } - str << "}\n\n// A table\n|" + str << "void foo(int a, int b) {\n" << indent + << "if (a == b)\n" << indent << "return a;\n" << outdent + << "#if Q_OS_WIN\nprint()\n#endif\nreturn a + b;\n" << outdent + << "}\n\n// A table\n|" << AlignedField("bla", 40, QTextStream::AlignRight) << "|\n|" << AlignedField("bla", 40, QTextStream::AlignLeft) << "|\n|" << AlignedField(QString(), 40, QTextStream::AlignLeft) << "|\n"; str << "\n2nd table\n|" << AlignedField("bla", 3, QTextStream::AlignLeft) << '|' << AlignedField(QString{}, 0, QTextStream::AlignLeft) << "|\n"; -static const char expected[] = R"(void foo(int a, int b) { +constexpr auto expected = R"(void foo(int a, int b) { if (a == b) return a; #if Q_OS_WIN @@ -141,9 +141,9 @@ static const char expected[] = R"(void foo(int a, int b) { 2nd table |bla|| -)"; +)"_L1; - QCOMPARE(str.toString(), QLatin1String(expected)); + QCOMPARE(str.toString(), expected); } void TestCodeInjections::testTextStreamRst() diff --git a/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp b/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp index 164409578..0bb72b3c1 100644 --- a/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp @@ -11,7 +11,7 @@ void TestContainer::testContainerType() { - const char* cppCode ="\ + const char cppCode[] = "\ namespace std {\n\ template<class T>\n\ class list {\n\ @@ -20,7 +20,7 @@ void TestContainer::testContainerType() }\n\ class A : public std::list<int> {\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <namespace-type name='std' generate='no' />\n\ <container-type name='std::list' type='list' />\n\ @@ -28,21 +28,21 @@ void TestContainer::testContainerType() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); //search for class A - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); auto baseContainer = classA->typeEntry()->baseContainerType(); QVERIFY(baseContainer); - QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer)->containerKind(), + QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer.get())->containerKind(), ContainerTypeEntry::ListContainer); } void TestContainer::testListOfValueType() { - const char* cppCode ="\ + const char cppCode[] = "\ namespace std {\n\ template<class T>\n\ class list {\n\ @@ -52,7 +52,7 @@ void TestContainer::testListOfValueType() class ValueType {};\n\ class A : public std::list<ValueType> {\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <namespace-type name='std' generate='no'/>\n\ <container-type name='std::list' type='list'/>\n\ @@ -61,11 +61,11 @@ void TestContainer::testListOfValueType() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 3); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->templateBaseClassInstantiations().size(), 1); const AbstractMetaType templateInstanceType = diff --git a/sources/shiboken6/ApiExtractor/tests/testconversionoperator.cpp b/sources/shiboken6/ApiExtractor/tests/testconversionoperator.cpp index a03220b0a..8f2b277af 100644 --- a/sources/shiboken6/ApiExtractor/tests/testconversionoperator.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testconversionoperator.cpp @@ -5,6 +5,7 @@ #include "testutil.h" #include <abstractmetafunction.h> #include <abstractmetalang.h> +#include <abstractmetatype.h> #include <typesystem.h> #include <qtcompat.h> @@ -32,11 +33,11 @@ void TestConversionOperator::testConversionOperator() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); - const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, u"C"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); + const auto classC = AbstractMetaClass::findClass(classes, "C"); QVERIFY(classA); QVERIFY(classB); QVERIFY(classC); @@ -52,7 +53,7 @@ void TestConversionOperator::testConversionOperator() break; } } - QVERIFY(!convOp.isNull()); + QVERIFY(convOp); QVERIFY(classA->externalConversionOperators().contains(convOp)); } @@ -70,9 +71,9 @@ void TestConversionOperator::testConversionOperatorOfDiscardedClass() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->externalConversionOperators().size(), 0); } @@ -94,10 +95,10 @@ void TestConversionOperator::testRemovedConversionOperator() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classA); QVERIFY(classB); QCOMPARE(classA->functions().size(), 2); @@ -120,10 +121,10 @@ void TestConversionOperator::testConversionOperatorReturningReference() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classA); QVERIFY(classB); QCOMPARE(classA->functions().size(), 2); @@ -154,10 +155,10 @@ void TestConversionOperator::testConversionOperatorReturningConstReference() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classA); QVERIFY(classB); QCOMPARE(classA->functions().size(), 2); diff --git a/sources/shiboken6/ApiExtractor/tests/testconversionruletag.cpp b/sources/shiboken6/ApiExtractor/tests/testconversionruletag.cpp index 5f126c5f5..b5efd92a6 100644 --- a/sources/shiboken6/ApiExtractor/tests/testconversionruletag.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testconversionruletag.cpp @@ -7,6 +7,7 @@ #include <complextypeentry.h> #include <customconversion.h> #include <primitivetypeentry.h> +#include <valuetypeentry.h> #include <qtcompat.h> @@ -20,10 +21,10 @@ void TestConversionRuleTag::testConversionRuleTagWithFile() { // FIXME PYSIDE7 remove // temp file used later - const char conversionData[] = "Hi! I'm a conversion rule."; + constexpr auto conversionData = "Hi! I'm a conversion rule."_L1; QTemporaryFile file; - file.open(); - QCOMPARE(file.write(conversionData), qint64(sizeof(conversionData)-1)); + QVERIFY(file.open()); + QCOMPARE(file.write(conversionData.constData()), conversionData.size()); file.close(); const char cppCode[] = "struct A {};\n"; @@ -34,13 +35,15 @@ void TestConversionRuleTag::testConversionRuleTagWithFile() </value-type>\n\ </typesystem>\n"_s; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode.toLocal8Bit().data())); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const ComplexTypeEntry* typeEntry = classA->typeEntry(); - QVERIFY(typeEntry->hasTargetConversionRule()); - QCOMPARE(typeEntry->targetConversionRule(), QLatin1String(conversionData)); + const auto typeEntry = classA->typeEntry(); + QVERIFY(typeEntry->isValue()); + auto vte = std::static_pointer_cast<const ValueTypeEntry>(typeEntry); + QVERIFY(vte->hasTargetConversionRule()); + QCOMPARE(vte->targetConversionRule(), conversionData); } void TestConversionRuleTag::testConversionRuleTagReplace() @@ -53,7 +56,7 @@ void TestConversionRuleTag::testConversionRuleTagReplace() struct B {\n\ A createA();\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='int'/>\n\ <primitive-type name='char'/>\n\ @@ -82,13 +85,13 @@ void TestConversionRuleTag::testConversionRuleTagReplace() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - TypeDatabase* typeDb = TypeDatabase::instance(); - PrimitiveTypeEntry* typeA = typeDb->findPrimitiveType(u"A"_s); + QVERIFY(builder); + auto *typeDb = TypeDatabase::instance(); + auto typeA = typeDb->findPrimitiveType(u"A"_s); QVERIFY(typeA); - CustomConversion* conversion = typeA->customConversion(); - QVERIFY(conversion); + QVERIFY(typeA->hasCustomConversion()); + auto conversion = typeA->customConversion(); QCOMPARE(typeA, conversion->ownerType()); QCOMPARE(conversion->nativeToTargetConversion().simplified(), @@ -98,32 +101,33 @@ void TestConversionRuleTag::testConversionRuleTagReplace() QVERIFY(conversion->hasTargetToNativeConversions()); QCOMPARE(conversion->targetToNativeConversions().size(), 3); - CustomConversion::TargetToNativeConversion* toNative = conversion->targetToNativeConversions().at(0); - QVERIFY(toNative); - QCOMPARE(toNative->sourceTypeName(), u"TargetNone"); - QVERIFY(toNative->isCustomType()); - QCOMPARE(toNative->sourceType(), nullptr); - QCOMPARE(toNative->sourceTypeCheck(), u"%IN == Target_None"); - QCOMPARE(toNative->conversion().simplified(), + QVERIFY(!conversion->targetToNativeConversions().isEmpty()); + auto toNative = conversion->targetToNativeConversions().at(0); + QCOMPARE(toNative.sourceTypeName(), u"TargetNone"); + QVERIFY(toNative.isCustomType()); + QCOMPARE(toNative.sourceType(), nullptr); + QCOMPARE(toNative.sourceTypeCheck(), u"%IN == Target_None"); + QCOMPARE(toNative.conversion().simplified(), u"DoThat(); DoSomething(); %OUT = A();"); + QVERIFY(conversion->targetToNativeConversions().size() > 1); toNative = conversion->targetToNativeConversions().at(1); - QVERIFY(toNative); - QCOMPARE(toNative->sourceTypeName(), u"B"); - QVERIFY(!toNative->isCustomType()); - TypeEntry* typeB = typeDb->findType(u"B"_s); + QCOMPARE(toNative.sourceTypeName(), u"B"); + QVERIFY(!toNative.isCustomType()); + auto typeB = typeDb->findType(u"B"_s); QVERIFY(typeB); - QCOMPARE(toNative->sourceType(), typeB); - QCOMPARE(toNative->sourceTypeCheck(), u"CheckIfInputObjectIsB(%IN)"); - QCOMPARE(toNative->conversion().trimmed(), u"%OUT = %IN.createA();"); + QCOMPARE(toNative.sourceType(), typeB); + QCOMPARE(toNative.sourceTypeCheck(), u"CheckIfInputObjectIsB(%IN)"); + QCOMPARE(toNative.conversion().trimmed(), u"%OUT = %IN.createA();"); + QVERIFY(conversion->targetToNativeConversions().size() > 2); toNative = conversion->targetToNativeConversions().at(2); - QVERIFY(toNative); - QCOMPARE(toNative->sourceTypeName(), u"String"); - QVERIFY(toNative->isCustomType()); - QCOMPARE(toNative->sourceType(), nullptr); - QCOMPARE(toNative->sourceTypeCheck(), u"String_Check(%IN)"); - QCOMPARE(toNative->conversion().trimmed(), u"%OUT = new A(String_AsString(%IN), String_GetSize(%IN));"); + QCOMPARE(toNative.sourceTypeName(), u"String"); + QVERIFY(toNative.isCustomType()); + QCOMPARE(toNative.sourceType(), nullptr); + QCOMPARE(toNative.sourceTypeCheck(), u"String_Check(%IN)"); + QCOMPARE(toNative.conversion().trimmed(), + u"%OUT = new A(String_AsString(%IN), String_GetSize(%IN));"); } void TestConversionRuleTag::testConversionRuleTagAdd() @@ -133,7 +137,7 @@ void TestConversionRuleTag::testConversionRuleTagAdd() Date();\n\ Date(int, int, int);\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='int'/>\n\ <value-type name='Date'>\n\ @@ -149,12 +153,14 @@ if (!TargetDateTimeAPI) TargetDateTime_IMPORT;\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - auto *classA = AbstractMetaClass::findClass(builder->classes(), u"Date"); + QVERIFY(builder); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "Date"); QVERIFY(classA); - CustomConversion* conversion = classA->typeEntry()->customConversion(); - QVERIFY(conversion); + QVERIFY(classA->typeEntry()->isValue()); + auto vte = std::static_pointer_cast<const ValueTypeEntry>(classA->typeEntry()); + QVERIFY(vte->hasCustomConversion()); + auto conversion = vte->customConversion(); QCOMPARE(conversion->nativeToTargetConversion(), QString()); @@ -162,14 +168,13 @@ if (!TargetDateTimeAPI) TargetDateTime_IMPORT;\n\ QVERIFY(conversion->hasTargetToNativeConversions()); QCOMPARE(conversion->targetToNativeConversions().size(), 1); - CustomConversion::TargetToNativeConversion *toNative = - conversion->targetToNativeConversions().constFirst(); - QVERIFY(toNative); - QCOMPARE(toNative->sourceTypeName(), u"TargetDate"); - QVERIFY(toNative->isCustomType()); - QCOMPARE(toNative->sourceType(), nullptr); - QCOMPARE(toNative->sourceTypeCheck(), u"TargetDate_Check(%IN)"); - QCOMPARE(toNative->conversion().trimmed(), + QVERIFY(!conversion->targetToNativeConversions().isEmpty()); + const auto &toNative = conversion->targetToNativeConversions().constFirst(); + QCOMPARE(toNative.sourceTypeName(), u"TargetDate"); + QVERIFY(toNative.isCustomType()); + QCOMPARE(toNative.sourceType(), nullptr); + QCOMPARE(toNative.sourceTypeCheck(), u"TargetDate_Check(%IN)"); + QCOMPARE(toNative.conversion().trimmed(), uR"(if (!TargetDateTimeAPI) TargetDateTime_IMPORT; %OUT = new Date(TargetDate_Day(%IN), TargetDate_Month(%IN), TargetDate_Year(%IN));)"); } @@ -177,7 +182,7 @@ if (!TargetDateTimeAPI) TargetDateTime_IMPORT;\n\ void TestConversionRuleTag::testConversionRuleTagWithInsertTemplate() { const char cppCode[] = "struct A {};"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='int'/>\n\ <!-- single line -->\n\ @@ -211,13 +216,13 @@ void TestConversionRuleTag::testConversionRuleTagWithInsertTemplate() "// TEMPLATE - target_to_native - END"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - TypeDatabase* typeDb = TypeDatabase::instance(); - PrimitiveTypeEntry* typeA = typeDb->findPrimitiveType(u"A"_s); + QVERIFY(builder); + auto *typeDb = TypeDatabase::instance(); + auto typeA = typeDb->findPrimitiveType(u"A"_s); QVERIFY(typeA); - CustomConversion* conversion = typeA->customConversion(); - QVERIFY(conversion); + QVERIFY(typeA->hasCustomConversion()); + auto conversion = typeA->customConversion(); QCOMPARE(typeA, conversion->ownerType()); QCOMPARE(conversion->nativeToTargetConversion().trimmed(), @@ -226,9 +231,9 @@ void TestConversionRuleTag::testConversionRuleTagWithInsertTemplate() QVERIFY(conversion->hasTargetToNativeConversions()); QCOMPARE(conversion->targetToNativeConversions().size(), 1); - CustomConversion::TargetToNativeConversion* toNative = conversion->targetToNativeConversions().constFirst(); - QVERIFY(toNative); - QCOMPARE(toNative->conversion().trimmed(), + QVERIFY(!conversion->targetToNativeConversions().isEmpty()); + const auto &toNative = conversion->targetToNativeConversions().constFirst(); + QCOMPARE(toNative.conversion().trimmed(), QLatin1StringView(targetToNativeExpected)); } diff --git a/sources/shiboken6/ApiExtractor/tests/testctorinformation.cpp b/sources/shiboken6/ApiExtractor/tests/testctorinformation.cpp index 6e6a86d17..c3a3ebef0 100644 --- a/sources/shiboken6/ApiExtractor/tests/testctorinformation.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testctorinformation.cpp @@ -10,47 +10,47 @@ void TestCtorInformation::testCtorIsPrivate() { - const char* cppCode = "class Control { public: Control() {} };\n\ + const char cppCode[] = "class Control { public: Control() {} };\n\ class Subject { private: Subject() {} };\n\ class CtorLess { };\n"; - const char* xmlCode = "<typesystem package='Foo'>\n\ + const char xmlCode[] = "<typesystem package='Foo'>\n\ <value-type name='Control'/>\n\ <object-type name='Subject'/>\n\ <value-type name='CtorLess'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 3); - auto *klass = AbstractMetaClass::findClass(classes, u"Control"); + auto klass = AbstractMetaClass::findClass(classes, "Control"); QVERIFY(klass); QVERIFY(klass->hasNonPrivateConstructor()); - klass = AbstractMetaClass::findClass(classes, u"Subject"); + klass = AbstractMetaClass::findClass(classes, "Subject"); QVERIFY(klass); QVERIFY(!klass->hasNonPrivateConstructor()); - klass = AbstractMetaClass::findClass(classes, u"CtorLess"); + klass = AbstractMetaClass::findClass(classes, "CtorLess"); QVERIFY(klass); QVERIFY(klass->hasNonPrivateConstructor()); } void TestCtorInformation::testHasNonPrivateCtor() { - const char* cppCode = "template<typename T>\n\ + const char cppCode[] = "template<typename T>\n\ struct Base { Base(double) {} };\n\ typedef Base<int> Derived;\n"; - const char* xmlCode = "<typesystem package='Foo'>\n\ + const char xmlCode[] = "<typesystem package='Foo'>\n\ <primitive-type name='int'/>\n\ <primitive-type name='double'/>\n\ <object-type name='Base' generate='no'/>\n\ <object-type name='Derived'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - const AbstractMetaClass *base = AbstractMetaClass::findClass(classes, u"Base"); + const auto base = AbstractMetaClass::findClass(classes, "Base"); QCOMPARE(base->hasNonPrivateConstructor(), true); - const AbstractMetaClass *derived = AbstractMetaClass::findClass(classes, u"Derived"); + const auto derived = AbstractMetaClass::findClass(classes, "Derived"); QCOMPARE(derived->hasNonPrivateConstructor(), true); } diff --git a/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp b/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp index b6f06458d..16f50e69d 100644 --- a/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp @@ -14,7 +14,7 @@ using namespace Qt::StringLiterals; -static const char* cppCode ="\ +static const char cppCode[] = "\ struct ValueA {};\n\ struct ValueB {};\n\ struct ObjectA {};\n\ @@ -29,7 +29,7 @@ static const char* cppCode ="\ void funcA();\n\ void funcB();\n"; -static const char* xmlCode = "\ +static const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <value-type name='ValueA'/>\n\ <value-type name='ValueB'/>\n\ @@ -56,22 +56,22 @@ void TestDropTypeEntries::testDropEntries() u"Foo.NamespaceA.InnerNamespaceA"_s}; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, QString(), droppedEntries)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - QVERIFY(AbstractMetaClass::findClass(classes, u"ValueA")); - QVERIFY(!AbstractMetaClass::findClass(classes, u"ValueB")); - QVERIFY(AbstractMetaClass::findClass(classes, u"ObjectA")); - QVERIFY(!AbstractMetaClass::findClass(classes, u"ObjectB")); - QVERIFY(AbstractMetaClass::findClass(classes, u"NamespaceA")); - QVERIFY(!AbstractMetaClass::findClass(classes, u"NamespaceA::InnerClassA")); - QVERIFY(!AbstractMetaClass::findClass(classes, u"NamespaceB")); + QVERIFY(AbstractMetaClass::findClass(classes, "ValueA")); + QVERIFY(!AbstractMetaClass::findClass(classes, "ValueB")); + QVERIFY(AbstractMetaClass::findClass(classes, "ObjectA")); + QVERIFY(!AbstractMetaClass::findClass(classes, "ObjectB")); + QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceA")); + QVERIFY(!AbstractMetaClass::findClass(classes, "NamespaceA::InnerClassA")); + QVERIFY(!AbstractMetaClass::findClass(classes, "NamespaceB")); AbstractMetaEnumList globalEnums = builder->globalEnums(); QCOMPARE(globalEnums.size(), 1); QCOMPARE(globalEnums.constFirst().name(), u"EnumA"); - TypeDatabase* td = TypeDatabase::instance(); + auto *td = TypeDatabase::instance(); QVERIFY(td->findType(u"funcA"_s)); QVERIFY(!td->findType(u"funcB"_s)); } @@ -79,30 +79,30 @@ void TestDropTypeEntries::testDropEntries() void TestDropTypeEntries::testDontDropEntries() { QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - QVERIFY(AbstractMetaClass::findClass(classes, u"ValueA")); - QVERIFY(AbstractMetaClass::findClass(classes, u"ValueB")); - QVERIFY(AbstractMetaClass::findClass(classes, u"ObjectA")); - QVERIFY(AbstractMetaClass::findClass(classes, u"ObjectB")); - QVERIFY(AbstractMetaClass::findClass(classes, u"NamespaceA")); - QVERIFY(AbstractMetaClass::findClass(classes, u"NamespaceA::InnerClassA")); - QVERIFY(AbstractMetaClass::findClass(classes, u"NamespaceB")); + QVERIFY(AbstractMetaClass::findClass(classes, "ValueA")); + QVERIFY(AbstractMetaClass::findClass(classes, "ValueB")); + QVERIFY(AbstractMetaClass::findClass(classes, "ObjectA")); + QVERIFY(AbstractMetaClass::findClass(classes, "ObjectB")); + QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceA")); + QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceA::InnerClassA")); + QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceB")); QCOMPARE(builder->globalEnums().size(), 2); - TypeDatabase* td = TypeDatabase::instance(); + auto *td = TypeDatabase::instance(); QVERIFY(td->findType(u"funcA"_s)); QVERIFY(td->findType(u"funcB"_s)); } -static const char* cppCode2 ="\ +static const char cppCode2[] = "\ struct ValueA {\n\ void func();\n\ };\n"; -static const char* xmlCode2 = R"( +static const char xmlCode2[] = R"( <typesystem package='Foo'> <value-type name='ValueA'> <modify-function signature='func()' remove='all'/> @@ -115,21 +115,21 @@ void TestDropTypeEntries::testDropEntryWithChildTags() QStringList droppedEntries(u"Foo.ValueA"_s); QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode2, xmlCode2, false, QString(), droppedEntries)); - QVERIFY(!builder.isNull()); - QVERIFY(!AbstractMetaClass::findClass(builder->classes(), u"ValueA")); + QVERIFY(builder); + QVERIFY(!AbstractMetaClass::findClass(builder->classes(), "ValueA")); } void TestDropTypeEntries::testDontDropEntryWithChildTags() { QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode2, xmlCode2, false)); - QVERIFY(!builder.isNull()); - QVERIFY(AbstractMetaClass::findClass(builder->classes(), u"ValueA")); + QVERIFY(builder); + QVERIFY(AbstractMetaClass::findClass(builder->classes(), "ValueA")); } void TestDropTypeEntries::testConditionalParsing_data() { - const QString xml = QStringLiteral(R"(<?xml version="1.0" encoding="UTF-8"?> + const QString xml = R"(<?xml version="1.0" encoding="UTF-8"?> <root> <tag1>text</tag1> <?if keyword1?> @@ -145,17 +145,17 @@ void TestDropTypeEntries::testConditionalParsing_data() <?if !keyword99?> <!-- Exclusion only --> <tag6>text</tag6> <?endif?> -</root>)"); - - const QString root = QStringLiteral("root"); - const QString tag1 = QStringLiteral("tag1"); - const QString tag2 = QStringLiteral("tag2"); - const QString tag3 = QStringLiteral("tag3"); - const QString tag4 = QStringLiteral("tag4"); - const QString tag5 = QStringLiteral("tag5"); - const QString tag6 = QStringLiteral("tag6"); - const QString keyword1 = QStringLiteral("keyword1"); - const QString keyword2 = QStringLiteral("keyword2"); +</root>)"_L1; + + constexpr auto root = "root"_L1; + constexpr auto tag1 = "tag1"_L1; + constexpr auto tag2 = "tag2"_L1; + constexpr auto tag3 = "tag3"_L1; + constexpr auto tag4 = "tag4"_L1; + constexpr auto tag5 = "tag5"_L1; + constexpr auto tag6 = "tag6"_L1; + constexpr auto keyword1 = "keyword1"_L1; + constexpr auto keyword2 = "keyword2"_L1; QTest::addColumn<QString>("xml"); QTest::addColumn<QStringList>("keywords"); @@ -204,11 +204,11 @@ void TestDropTypeEntries::testConditionalParsing() void TestDropTypeEntries::testEntityParsing() { - const QString xml = QStringLiteral(R"(<?xml version="1.0" encoding="UTF-8"?> + const QString xml = R"(<?xml version="1.0" encoding="UTF-8"?> <root> <?entity testentity word1 word2?> <text>bla &testentity;</text> -</root>)"); +</root>)"_L1; QString actual; ConditionalStreamReader reader(xml); diff --git a/sources/shiboken6/ApiExtractor/tests/testdtorinformation.cpp b/sources/shiboken6/ApiExtractor/tests/testdtorinformation.cpp index add5a42da..2152d39de 100644 --- a/sources/shiboken6/ApiExtractor/tests/testdtorinformation.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testdtorinformation.cpp @@ -25,13 +25,13 @@ private: </typesystem>)"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *klass = AbstractMetaClass::findClass(classes, u"Control"); + auto klass = AbstractMetaClass::findClass(classes, "Control"); QVERIFY(klass); QVERIFY(!klass->hasPrivateDestructor()); - klass = AbstractMetaClass::findClass(classes, u"Subject"); + klass = AbstractMetaClass::findClass(classes, "Subject"); QVERIFY(klass); QVERIFY(klass->hasPrivateDestructor()); } @@ -53,13 +53,13 @@ protected: </typesystem>)"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *klass = AbstractMetaClass::findClass(classes, u"Control"); + auto klass = AbstractMetaClass::findClass(classes, "Control"); QVERIFY(klass); QVERIFY(!klass->hasProtectedDestructor()); - klass = AbstractMetaClass::findClass(classes, u"Subject"); + klass = AbstractMetaClass::findClass(classes, "Subject"); QVERIFY(klass); QVERIFY(klass->hasProtectedDestructor()); } @@ -81,46 +81,46 @@ protected: </typesystem>)"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *klass = AbstractMetaClass::findClass(classes, u"Control"); + auto klass = AbstractMetaClass::findClass(classes, "Control"); QVERIFY(klass); QVERIFY(!klass->hasVirtualDestructor()); - klass = AbstractMetaClass::findClass(classes, u"Subject"); + klass = AbstractMetaClass::findClass(classes, "Subject"); QVERIFY(klass); QVERIFY(klass->hasVirtualDestructor()); } void TestDtorInformation::testDtorFromBaseIsVirtual() { - const char* cppCode = R"CPP(class ControlBase { public: ~ControlBase() {} }; + const char cppCode[] = R"CPP(class ControlBase { public: ~ControlBase() {} }; class Control : public ControlBase {}; class SubjectBase { public: virtual ~SubjectBase() {} }; class Subject : public SubjectBase {}; )CPP"; - const char* xmlCode = R"XML(<typesystem package="Foo"><value-type name="ControlBase"/> + const char xmlCode[] = R"XML(<typesystem package="Foo"><value-type name="ControlBase"/> <value-type name="Control"/>" <value-type name="SubjectBase"/>" <value-type name="Subject"/> </typesystem> )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 4); - auto klass = AbstractMetaClass::findClass(classes, u"ControlBase"); + auto klass = AbstractMetaClass::findClass(classes, "ControlBase"); QVERIFY(klass); QVERIFY(!klass->hasVirtualDestructor()); - klass = AbstractMetaClass::findClass(classes, u"Control"); + klass = AbstractMetaClass::findClass(classes, "Control"); QVERIFY(klass); QVERIFY(!klass->hasVirtualDestructor()); - klass = AbstractMetaClass::findClass(classes, u"SubjectBase"); + klass = AbstractMetaClass::findClass(classes, "SubjectBase"); QVERIFY(klass); QVERIFY(klass->hasVirtualDestructor()); - klass = AbstractMetaClass::findClass(classes, u"Subject"); + klass = AbstractMetaClass::findClass(classes, "Subject"); QVERIFY(klass); QVERIFY(klass->hasVirtualDestructor()); } @@ -142,13 +142,13 @@ protected: </typesystem>)"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *klass = AbstractMetaClass::findClass(classes, u"Control"); + auto klass = AbstractMetaClass::findClass(classes, "Control"); QVERIFY(klass); QVERIFY(klass->isPolymorphic()); - klass = AbstractMetaClass::findClass(classes, u"Subject"); + klass = AbstractMetaClass::findClass(classes, "Subject"); QVERIFY(klass); QVERIFY(klass->isPolymorphic()); } diff --git a/sources/shiboken6/ApiExtractor/tests/testenum.cpp b/sources/shiboken6/ApiExtractor/tests/testenum.cpp index 9fd413ddc..c7c2b8b3b 100644 --- a/sources/shiboken6/ApiExtractor/tests/testenum.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testenum.cpp @@ -3,6 +3,7 @@ #include "testenum.h" #include "testutil.h" +#include <abstractmetaargument.h> #include <abstractmetaenum.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> @@ -19,7 +20,7 @@ using namespace Qt::StringLiterals; void TestEnum::testEnumCppSignature() { - const char* cppCode ="\ + const char cppCode[] = "\ enum GlobalEnum { A, B };\n\ \n\ struct A {\n\ @@ -27,7 +28,7 @@ void TestEnum::testEnumCppSignature() void method(ClassEnum);\n\ };\n\ void func(A::ClassEnum);\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <enum-type name='GlobalEnum'/>\n\ <value-type name='A'>\n\ @@ -37,7 +38,7 @@ void TestEnum::testEnumCppSignature() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); @@ -53,7 +54,7 @@ void TestEnum::testEnumCppSignature() u"A::ClassEnum"); // enum as parameter of a method - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QCOMPARE(classA->enums().size(), 1); const auto funcs = classA->queryFunctionsByName(u"method"_s); QVERIFY(!funcs.isEmpty()); @@ -77,12 +78,12 @@ void TestEnum::testEnumCppSignature() void TestEnum::testEnumWithApiVersion() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {\n\ enum ClassEnum { EnumA, EnumB };\n\ enum ClassEnum2 { EnumC, EnumD };\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <value-type name='A'>\n\ <enum-type name='ClassEnum' since='0.1'/>\n\ @@ -92,7 +93,7 @@ void TestEnum::testEnumWithApiVersion() QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); QCOMPARE(classes[0]->enums().size(), 1); @@ -100,13 +101,13 @@ void TestEnum::testEnumWithApiVersion() void TestEnum::testAnonymousEnum() { - const char* cppCode ="\ + const char cppCode[] = "\ enum { Global0, Global1 };\n\ struct A {\n\ enum { A0, A1 };\n\ enum { isThis = true, isThat = false };\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <!-- Uses the first value of the enum to identify it. -->\n\ <enum-type identified-by-value='Global0'/>\n\ @@ -118,7 +119,7 @@ void TestEnum::testAnonymousEnum() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaEnumList globalEnums = builder->globalEnums(); QCOMPARE(globalEnums.size(), 1); @@ -163,17 +164,17 @@ void TestEnum::testAnonymousEnum() void TestEnum::testGlobalEnums() { - const char* cppCode ="\ + const char cppCode[] = "\ enum EnumA { A0, A1 };\n\ enum EnumB { B0 = 2, B1 = 0x4 };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <enum-type name='EnumA'/>\n\ <enum-type name='EnumB'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaEnumList globalEnums = builder->globalEnums(); QCOMPARE(globalEnums.size(), 2); @@ -207,12 +208,12 @@ void TestEnum::testGlobalEnums() void TestEnum::testEnumValueFromNeighbourEnum() { - const char* cppCode ="\ + const char cppCode[] = "\ namespace A {\n\ enum EnumA { ValueA0, ValueA1 };\n\ enum EnumB { ValueB0 = A::ValueA1, ValueB1 = ValueA0 };\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <namespace-type name='A'>\n\ <enum-type name='EnumA'/>\n\ @@ -221,7 +222,7 @@ void TestEnum::testEnumValueFromNeighbourEnum() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); @@ -258,7 +259,7 @@ void TestEnum::testEnumValueFromNeighbourEnum() void TestEnum::testEnumValueFromExpression() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {\n\ enum EnumA : unsigned {\n\ ValueA0 = 3u,\n\ @@ -274,7 +275,7 @@ void TestEnum::testEnumValueFromExpression() ValueB0 = ~3,\n\ };\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <value-type name='A'>\n\ <enum-type name='EnumA'/>\n\ @@ -283,9 +284,9 @@ void TestEnum::testEnumValueFromExpression() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); - AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + AbstractMetaClassPtr classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); auto enumA = classA->findEnum(u"EnumA"_s); @@ -346,14 +347,14 @@ void TestEnum::testEnumValueFromExpression() void TestEnum::testPrivateEnum() { - const char* cppCode ="\ + const char cppCode[] = "\ class A {\n\ private:\n\ enum PrivateEnum { Priv0 = 0x0f, Priv1 = 0xf0 };\n\ public:\n\ enum PublicEnum { Pub0 = Priv0, Pub1 = A::Priv1 };\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <value-type name='A'>\n\ <enum-type name='PublicEnum'/>\n\ @@ -361,9 +362,9 @@ void TestEnum::testPrivateEnum() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); - AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); QCOMPARE(classA->enums().size(), 2); @@ -389,18 +390,18 @@ void TestEnum::testPrivateEnum() void TestEnum::testTypedefEnum() { - const char* cppCode ="\ + const char cppCode[] = "\ typedef enum EnumA {\n\ A0,\n\ A1,\n\ } EnumA;\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <enum-type name='EnumA'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaEnumList globalEnums = builder->globalEnums(); QCOMPARE(globalEnums.size(), 1); @@ -425,7 +426,7 @@ void TestEnum::testTypedefEnum() struct EnumDefaultValuesFixture { - QSharedPointer<AbstractMetaBuilder> builder; + std::shared_ptr<AbstractMetaBuilder> builder; AbstractMetaType globalEnum; AbstractMetaType testEnum; @@ -461,7 +462,7 @@ namespace Test2 )"; fixture->builder.reset(TestUtil::parse(cppCode, xmlCode, false)); - if (fixture->builder.isNull()) + if (!fixture->builder) return -1; const auto globalEnums = fixture->builder->globalEnums(); @@ -471,8 +472,8 @@ namespace Test2 fixture->globalEnum = AbstractMetaType(globalEnums.constFirst().typeEntry()); fixture->globalEnum.decideUsagePattern(); - const AbstractMetaClass *testNamespace = nullptr; - for (auto *c : fixture->builder->classes()) { + AbstractMetaClassCPtr testNamespace; + for (const auto &c : fixture->builder->classes()) { if (c->name() == u"Test2") { testNamespace = c; break; @@ -484,9 +485,9 @@ namespace Test2 const auto namespaceEnums = testNamespace->enums(); if (namespaceEnums.size() != 2) return -4; - QList<const EnumTypeEntry *> enumTypeEntries{ - static_cast<const EnumTypeEntry *>(namespaceEnums.at(0).typeEntry()), - static_cast<const EnumTypeEntry *>(namespaceEnums.at(1).typeEntry())}; + QList<EnumTypeEntryCPtr > enumTypeEntries{ + std::static_pointer_cast<const EnumTypeEntry>(namespaceEnums.at(0).typeEntry()), + std::static_pointer_cast<const EnumTypeEntry>(namespaceEnums.at(1).typeEntry())}; if (enumTypeEntries.constFirst()->flags()) std::swap(enumTypeEntries[0], enumTypeEntries[1]); fixture->testEnum = AbstractMetaType(enumTypeEntries.at(0)); diff --git a/sources/shiboken6/ApiExtractor/tests/testextrainclude.cpp b/sources/shiboken6/ApiExtractor/tests/testextrainclude.cpp index f540074e9..fcc409a42 100644 --- a/sources/shiboken6/ApiExtractor/tests/testextrainclude.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testextrainclude.cpp @@ -10,8 +10,8 @@ void TestExtraInclude::testClassExtraInclude() { - const char* cppCode ="struct A {};\n"; - const char* xmlCode = "\ + const char cppCode[] = "struct A {};\n"; + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <value-type name='A'>\n\ <extra-includes>\n\ @@ -21,9 +21,9 @@ void TestExtraInclude::testClassExtraInclude() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QList<Include> includes = classA->typeEntry()->extraIncludes(); @@ -33,8 +33,8 @@ void TestExtraInclude::testClassExtraInclude() void TestExtraInclude::testGlobalExtraIncludes() { - const char* cppCode ="struct A {};\n"; - const char* xmlCode = "\ + const char cppCode[] = "struct A {};\n"; + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <extra-includes>\n\ <include file-name='header1.h' location='global'/>\n\ @@ -44,12 +44,12 @@ void TestExtraInclude::testGlobalExtraIncludes() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - QVERIFY(AbstractMetaClass::findClass(classes, u"A")); + QVERIFY(AbstractMetaClass::findClass(classes, "A")); - TypeDatabase* td = TypeDatabase::instance(); - const TypeSystemTypeEntry *module = td->defaultTypeSystemType(); + auto *td = TypeDatabase::instance(); + TypeSystemTypeEntryCPtr module = td->defaultTypeSystemType(); QVERIFY(module); QCOMPARE(module->name(), u"Foo"); diff --git a/sources/shiboken6/ApiExtractor/tests/testfunctiontag.cpp b/sources/shiboken6/ApiExtractor/tests/testfunctiontag.cpp index 66c2e08c9..18eaf5774 100644 --- a/sources/shiboken6/ApiExtractor/tests/testfunctiontag.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testfunctiontag.cpp @@ -23,9 +23,9 @@ void TestFunctionTag::testFunctionTagForSpecificSignature() <function signature='globalFunction(int)'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); - const TypeEntry *func = TypeDatabase::instance()->findType(u"globalFunction"_s); + TypeEntryCPtr func = TypeDatabase::instance()->findType(u"globalFunction"_s); QVERIFY(func); QCOMPARE(builder->globalFunctions().size(), 1); } @@ -41,24 +41,24 @@ void TestFunctionTag::testFunctionTagForAllSignatures() <function signature='globalFunction(float)'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); - const TypeEntry *func = TypeDatabase::instance()->findType(u"globalFunction"_s); + TypeEntryCPtr func = TypeDatabase::instance()->findType(u"globalFunction"_s); QVERIFY(func); QCOMPARE(builder->globalFunctions().size(), 2); } void TestFunctionTag::testRenameGlobalFunction() { - const char* cppCode ="void global_function_with_ugly_name();\n"; - const char* xmlCode = "\ + const char cppCode[] = "void global_function_with_ugly_name();\n"; + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <function signature='global_function_with_ugly_name()' rename='smooth'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); - const TypeEntry *func = TypeDatabase::instance()->findType(u"global_function_with_ugly_name"_s); + TypeEntryCPtr func = TypeDatabase::instance()->findType(u"global_function_with_ugly_name"_s); QVERIFY(func); QCOMPARE(builder->globalFunctions().size(), 1); diff --git a/sources/shiboken6/ApiExtractor/tests/testimplicitconversions.cpp b/sources/shiboken6/ApiExtractor/tests/testimplicitconversions.cpp index f600c3ea9..899d00ad4 100644 --- a/sources/shiboken6/ApiExtractor/tests/testimplicitconversions.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testimplicitconversions.cpp @@ -3,14 +3,16 @@ #include "testimplicitconversions.h" #include "testutil.h" +#include <abstractmetaargument.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> +#include <abstractmetatype.h> #include <complextypeentry.h> #include <QtTest/QTest> void TestImplicitConversions::testWithPrivateCtors() { - const char* cppCode ="\ + const char cppCode[] = "\ class B;\n\ class C;\n\ class A {\n\ @@ -20,19 +22,19 @@ void TestImplicitConversions::testWithPrivateCtors() };\n\ class B {};\n\ class C {};\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <value-type name='A'/>\n\ <value-type name='B'/>\n\ <value-type name='C'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 3); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); - const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, u"C"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto classC = AbstractMetaClass::findClass(classes, "C"); const auto implicitConvs = classA->implicitConversions(); QCOMPARE(implicitConvs.size(), 1); QCOMPARE(implicitConvs.constFirst()->arguments().constFirst().type().typeEntry(), @@ -41,14 +43,14 @@ void TestImplicitConversions::testWithPrivateCtors() void TestImplicitConversions::testWithModifiedVisibility() { - const char* cppCode ="\ + const char cppCode[] = "\ class B;\n\ class A {\n\ public:\n\ A(const B&);\n\ };\n\ class B {};\n"; - const char* xmlCode = R"( + const char xmlCode[] = R"( <typesystem package='Foo'> <value-type name='A'> <modify-function signature='A(const B&)' access='private'/> @@ -57,11 +59,11 @@ void TestImplicitConversions::testWithModifiedVisibility() </typesystem> )"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); const auto implicitConvs = classA->implicitConversions(); QCOMPARE(implicitConvs.size(), 1); QCOMPARE(implicitConvs.constFirst()->arguments().constFirst().type().typeEntry(), @@ -71,7 +73,7 @@ void TestImplicitConversions::testWithModifiedVisibility() void TestImplicitConversions::testWithAddedCtor() { - const char* cppCode ="\ + const char cppCode[] = "\ class B;\n\ class A {\n\ public:\n\ @@ -79,7 +81,7 @@ void TestImplicitConversions::testWithAddedCtor() };\n\ class B {};\n\ class C {};\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <custom-type name='TARGETLANGTYPE'/>\n\ <value-type name='A'>\n\ @@ -91,38 +93,38 @@ void TestImplicitConversions::testWithAddedCtor() <value-type name='C'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 3); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); auto implicitConvs = classA->implicitConversions(); QCOMPARE(implicitConvs.size(), 2); // Added constructors with custom types should never result in implicit converters. - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); implicitConvs = classB->implicitConversions(); QCOMPARE(implicitConvs.size(), 0); } void TestImplicitConversions::testWithExternalConversionOperator() { - const char* cppCode ="\ + const char cppCode[] = "\ class A {};\n\ struct B {\n\ operator A() const;\n\ };\n"; - const char* xmlCode = "\n\ + const char xmlCode[] = "\n\ <typesystem package='Foo'>\n\ <value-type name='A'/>\n\ <value-type name='B'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A"); - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); const auto implicitConvs = classA->implicitConversions(); QCOMPARE(implicitConvs.size(), 1); const auto &externalConvOps = classA->externalConversionOperators(); @@ -133,7 +135,7 @@ void TestImplicitConversions::testWithExternalConversionOperator() if (func->isConversionOperator()) convOp = func; } - QVERIFY(!convOp.isNull()); + QVERIFY(convOp); QCOMPARE(implicitConvs.constFirst(), convOp); } diff --git a/sources/shiboken6/ApiExtractor/tests/testinserttemplate.cpp b/sources/shiboken6/ApiExtractor/tests/testinserttemplate.cpp index 416f9c792..23cf0f9ea 100644 --- a/sources/shiboken6/ApiExtractor/tests/testinserttemplate.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testinserttemplate.cpp @@ -12,8 +12,8 @@ void TestInsertTemplate::testInsertTemplateOnClassInjectCode() { - const char* cppCode ="struct A{};\n"; - const char* xmlCode = "\ + const char cppCode[] = "struct A{};\n"; + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <template name='code_template'>\n\ code template content\n\ @@ -25,10 +25,10 @@ void TestInsertTemplate::testInsertTemplateOnClassInjectCode() </value-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->typeEntry()->codeSnips().size(), 1); QString code = classA->typeEntry()->codeSnips().constFirst().code(); @@ -37,8 +37,8 @@ void TestInsertTemplate::testInsertTemplateOnClassInjectCode() void TestInsertTemplate::testInsertTemplateOnModuleInjectCode() { - const char* cppCode =""; - const char* xmlCode = "\ + const char cppCode[] = ""; + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <template name='code_template'>\n\ code template content\n\ @@ -48,14 +48,13 @@ void TestInsertTemplate::testInsertTemplateOnModuleInjectCode() </inject-code>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QVERIFY(classes.isEmpty()); - const TypeSystemTypeEntry *module = TypeDatabase::instance()->defaultTypeSystemType(); + TypeSystemTypeEntryCPtr module = TypeDatabase::instance()->defaultTypeSystemType(); QVERIFY(module); QCOMPARE(module->name(), u"Foo"); - QVERIFY(module); QCOMPARE(module->codeSnips().size(), 1); QString code = module->codeSnips().constFirst().code().trimmed(); QVERIFY(code.contains(u"code template content")); diff --git a/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp b/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp index 05fd3bf6b..9cf2e0cc7 100644 --- a/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp @@ -4,6 +4,7 @@ #include "testmodifydocumentation.h" #include "testutil.h" #include <abstractmetalang.h> +#include <abstractmetafunction.h> #include <documentation.h> #include <modifications.h> #include <complextypeentry.h> @@ -19,7 +20,7 @@ using namespace Qt::StringLiterals; void TestModifyDocumentation::testModifyDocumentation() { - const char* cppCode ="struct B { void b(); }; class A {};\n"; + const char cppCode[] = "struct B { void b(); }; class A {};\n"; const char xmlCode[] = R"(<typesystem package="Foo"> <value-type name='B'> @@ -32,8 +33,8 @@ R"(<typesystem package="Foo"> </typesystem> )"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + QVERIFY(builder); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); DocModificationList docMods = classA->typeEntry()->docModifications(); QCOMPARE(docMods.size(), 2); @@ -46,7 +47,7 @@ R"(<typesystem package="Foo"> // cannot handle Qt resources. QTemporaryDir tempDir(QDir::tempPath() + u"/shiboken_testmodifydocXXXXXX"_s); QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString())); - const QString docFileName = u"a.xml"_s; + constexpr auto docFileName = "a.xml"_L1; QVERIFY(QFile::copy(u":/"_s + docFileName, tempDir.filePath(docFileName))); QtDocParser docParser; @@ -78,6 +79,33 @@ R"(<?xml version="1.0"?> QCOMPARE(actualDocSimplified, expectedDocSimplified); } +void TestModifyDocumentation::testInjectAddedFunctionDocumentation() +{ + const char cppCode[] ="class A {};\n"; + const char xmlCode[] = R"XML( +<typesystem package="Foo"> + <value-type name='A'> + <add-function signature="foo(int@parameter_name@)"> + <inject-documentation format="target" mode="append"> + Injected documentation of added function foo. + </inject-documentation> + </add-function> + </value-type> +</typesystem> +)XML"; + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(builder); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "A"); + QVERIFY(classA); + const auto f = classA->findFunction("foo"); + QVERIFY(f); + QVERIFY(f->isUserAdded()); + auto docMods = f->addedFunctionDocModifications(); + QCOMPARE(docMods.size(), 1); + const QString code = docMods.constFirst().code(); + QVERIFY(code.contains(u"Injected documentation of added function foo.")); +} + // We expand QTEST_MAIN macro but using QCoreApplication instead of QApplication // because this test needs an event loop but can't use QApplication to avoid a crash // on our ARMEL/FRAMANTLE buildbot diff --git a/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.h b/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.h index c7479f23e..c1cc8f480 100644 --- a/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.h +++ b/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.h @@ -11,6 +11,7 @@ class TestModifyDocumentation : public QObject Q_OBJECT private slots: void testModifyDocumentation(); + void testInjectAddedFunctionDocumentation(); }; #endif diff --git a/sources/shiboken6/ApiExtractor/tests/testmodifyfunction.cpp b/sources/shiboken6/ApiExtractor/tests/testmodifyfunction.cpp index 837564051..a7d40f70a 100644 --- a/sources/shiboken6/ApiExtractor/tests/testmodifyfunction.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testmodifyfunction.cpp @@ -3,9 +3,11 @@ #include "testmodifyfunction.h" #include "testutil.h" +#include <abstractmetaargument.h> #include <abstractmetabuilder_p.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> +#include <abstractmetatype.h> #include <modifications.h> #include <typesystem.h> @@ -26,7 +28,7 @@ void TestModifyFunction::testRenameArgument() { QFETCH(QByteArray, pattern); - const char* cppCode ="\ + const char cppCode[] = "\ struct A {\n\ void method(int=0);\n\ };\n"; @@ -44,23 +46,23 @@ void TestModifyFunction::testRenameArgument() const QByteArray xmlCode = QByteArray(xmlCode1) + pattern + QByteArray(xmlCode2); QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode.constData(), false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); - const auto func = classA->findFunction(u"method"); - QVERIFY(!func.isNull()); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + const auto func = classA->findFunction("method"); + QVERIFY(func); QCOMPARE(func->argumentName(1), u"otherArg"); } void TestModifyFunction::testOwnershipTransfer() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {};\n\ struct B {\n\ virtual A* method();\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <object-type name='A' />\n\ <object-type name='B'>\n\ @@ -72,11 +74,11 @@ void TestModifyFunction::testOwnershipTransfer() </object-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); - const auto func = classB->findFunction(u"method"); - QVERIFY(!func.isNull()); + const auto classB = AbstractMetaClass::findClass(classes, "B"); + const auto func = classB->findFunction("method"); + QVERIFY(func); QCOMPARE(func->argumentTargetOwnership(func->ownerClass(), 0), TypeSystem::CppOwnership); @@ -85,7 +87,7 @@ void TestModifyFunction::testOwnershipTransfer() void TestModifyFunction::invalidateAfterUse() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {\n\ virtual void call(int *a);\n\ };\n\ @@ -99,7 +101,7 @@ void TestModifyFunction::invalidateAfterUse() };\n\ struct E : D {\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='int'/>\n\ <object-type name='A'>\n\ @@ -122,47 +124,47 @@ void TestModifyFunction::invalidateAfterUse() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); - auto func = classB->findFunction(u"call"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); + auto func = classB->findFunction("call"); QCOMPARE(func->modifications().size(), 1); QCOMPARE(func->modifications().at(0).argument_mods().size(), 1); QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse()); - const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, u"C"); + const auto classC = AbstractMetaClass::findClass(classes, "C"); QVERIFY(classC); - func = classC->findFunction(u"call"); + func = classC->findFunction("call"); QCOMPARE(func->modifications().size(), 1); QCOMPARE(func->modifications().at(0).argument_mods().size(), 1); QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse()); - func = classC->findFunction(u"call2"); + func = classC->findFunction("call2"); QCOMPARE(func->modifications().size(), 1); QCOMPARE(func->modifications().at(0).argument_mods().size(), 1); QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse()); - const AbstractMetaClass *classD = AbstractMetaClass::findClass(classes, u"D"); + AbstractMetaClassCPtr classD = AbstractMetaClass::findClass(classes, "D"); QVERIFY(classD); - func = classD->findFunction(u"call"); + func = classD->findFunction("call"); QCOMPARE(func->modifications().size(), 1); QCOMPARE(func->modifications().at(0).argument_mods().size(), 1); QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse()); - func = classD->findFunction(u"call2"); + func = classD->findFunction("call2"); QCOMPARE(func->modifications().size(), 1); QCOMPARE(func->modifications().at(0).argument_mods().size(), 1); QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse()); - const AbstractMetaClass *classE = AbstractMetaClass::findClass(classes, u"E"); + const auto classE = AbstractMetaClass::findClass(classes, "E"); QVERIFY(classE); - func = classE->findFunction(u"call"); + func = classE->findFunction("call"); QVERIFY(func); QCOMPARE(func->modifications().size(), 1); QCOMPARE(func->modifications().at(0).argument_mods().size(), 1); QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse()); - func = classE->findFunction(u"call2"); + func = classE->findFunction("call2"); QVERIFY(func); QCOMPARE(func->modifications().size(), 1); QCOMPARE(func->modifications().at(0).argument_mods().size(), 1); @@ -171,13 +173,13 @@ void TestModifyFunction::invalidateAfterUse() void TestModifyFunction::testWithApiVersion() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {};\n\ struct B {\n\ virtual A* method();\n\ virtual B* methodB();\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <object-type name='A' />\n\ <object-type name='B'>\n\ @@ -195,15 +197,15 @@ void TestModifyFunction::testWithApiVersion() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"B"); - auto func = classB->findFunction(u"method"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); + auto func = classB->findFunction("method"); auto returnOwnership = func->argumentTargetOwnership(func->ownerClass(), 0); QCOMPARE(returnOwnership, TypeSystem::CppOwnership); - func = classB->findFunction(u"methodB"); + func = classB->findFunction("methodB"); returnOwnership = func->argumentTargetOwnership(func->ownerClass(), 0); QVERIFY(returnOwnership != TypeSystem::CppOwnership); } @@ -234,43 +236,43 @@ struct A { )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); // Nothing specified, true - const auto f1 = classA->findFunction(u"f1"); - QVERIFY(!f1.isNull()); + const auto f1 = classA->findFunction("f1"); + QVERIFY(f1); QVERIFY(!f1->allowThread()); // 'auto' specified, should be false for nontrivial function - const auto f2 = classA->findFunction(u"f2"); - QVERIFY(!f2.isNull()); + const auto f2 = classA->findFunction("f2"); + QVERIFY(f2); QVERIFY(f2->allowThread()); // 'no' specified, should be false - const auto f3 = classA->findFunction(u"f3"); - QVERIFY(!f3.isNull()); + const auto f3 = classA->findFunction("f3"); + QVERIFY(f3); QVERIFY(!f3->allowThread()); // Nothing specified, should be false for simple getter - const auto getter1 = classA->findFunction(u"getter1"); - QVERIFY(!getter1.isNull()); + const auto getter1 = classA->findFunction("getter1"); + QVERIFY(getter1); QVERIFY(!getter1->allowThread()); // Forced to true simple getter - const auto getter2 = classA->findFunction(u"getter2"); - QVERIFY(!getter2.isNull()); + const auto getter2 = classA->findFunction("getter2"); + QVERIFY(getter2); QVERIFY(getter2->allowThread()); // Forced to true simple getter } void TestModifyFunction::testGlobalFunctionModification() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {};\n\ void function(A* a = 0);\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='A'/>\n\ <function signature='function(A*)'>\n\ @@ -284,10 +286,11 @@ void TestModifyFunction::testGlobalFunctionModification() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); QCOMPARE(builder->globalFunctions().size(), 1); - FunctionModificationList mods = TypeDatabase::instance()->functionModifications(u"function(A*)"_s); + auto *td = TypeDatabase::instance(); + FunctionModificationList mods = td->globalFunctionModifications({u"function(A*)"_s}); QCOMPARE(mods.size(), 1); const QList<ArgumentModification> &argMods = mods.constFirst().argument_mods(); QCOMPARE(argMods.size(), 1); @@ -431,44 +434,44 @@ void TestModifyFunction::testScopedModifications() QFETCH(bool, expectedAllowThread); QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode.constData(), xmlCode.constData(), false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A"); + const auto classA = AbstractMetaClass::findClass(builder->classes(), "A"); QVERIFY(classA); - auto f = classA->findFunction(QStringLiteral("unspecified")); - QVERIFY(!f.isNull()); + auto f = classA->findFunction("unspecified"); + QVERIFY(f); QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::Unknown); QCOMPARE(f->generateExceptionHandling(), expectedGenerateUnspecified); QCOMPARE(f->allowThread(), expectedAllowThread); - f = classA->findFunction(QStringLiteral("nonThrowing")); - QVERIFY(!f.isNull()); + f = classA->findFunction("nonThrowing"); + QVERIFY(f); QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::NoExcept); QCOMPARE(f->generateExceptionHandling(), expectedGenerateNonThrowing); - f = classA->findFunction(QStringLiteral("throwing")); - QVERIFY(!f.isNull()); + f = classA->findFunction("throwing"); + QVERIFY(f); QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::Throws); QCOMPARE(f->generateExceptionHandling(), expectedGenerateThrowing); } void TestModifyFunction::testSnakeCaseRenaming_data() { - QTest::addColumn<QString>("name"); - QTest::addColumn<QString>("expected"); + QTest::addColumn<QLatin1StringView>("name"); + QTest::addColumn<QLatin1StringView>("expected"); QTest::newRow("s1") - << QStringLiteral("snakeCaseFunc") << QStringLiteral("snake_case_func"); + << "snakeCaseFunc"_L1 << "snake_case_func"_L1; QTest::newRow("s2") - << QStringLiteral("SnakeCaseFunc") << QStringLiteral("snake_case_func"); + << "SnakeCaseFunc"_L1 << "snake_case_func"_L1; QTest::newRow("consecutive-uppercase") - << QStringLiteral("snakeCAseFunc") << QStringLiteral("snakeCAseFunc"); + << "snakeCAseFunc"_L1 << "snakeCAseFunc"_L1; } void TestModifyFunction::testSnakeCaseRenaming() { - QFETCH(QString, name); - QFETCH(QString, expected); + QFETCH(QLatin1StringView, name); + QFETCH(QLatin1StringView, expected); const QString actual = AbstractMetaBuilder::getSnakeCaseName(name); QCOMPARE(actual, expected); diff --git a/sources/shiboken6/ApiExtractor/tests/testmultipleinheritance.cpp b/sources/shiboken6/ApiExtractor/tests/testmultipleinheritance.cpp index af84ef864..1cf4c8e0f 100644 --- a/sources/shiboken6/ApiExtractor/tests/testmultipleinheritance.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testmultipleinheritance.cpp @@ -10,7 +10,7 @@ void TestMultipleInheritance::testVirtualClass() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {\n\ virtual ~A();\n\ virtual void theBug();\n\ @@ -22,7 +22,7 @@ void TestMultipleInheritance::testVirtualClass() };\n\ struct D : C {\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <object-type name='A' />\n\ <object-type name='B' />\n\ @@ -31,11 +31,11 @@ void TestMultipleInheritance::testVirtualClass() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 4); - const AbstractMetaClass *classD = AbstractMetaClass::findClass(classes, u"D"); + const auto classD = AbstractMetaClass::findClass(classes, "D"); bool functionFound = false; for (const auto &f : classD->functions()) { if (f->name() == u"theBug") { diff --git a/sources/shiboken6/ApiExtractor/tests/testnamespace.cpp b/sources/shiboken6/ApiExtractor/tests/testnamespace.cpp index 00af4d48d..3773e614a 100644 --- a/sources/shiboken6/ApiExtractor/tests/testnamespace.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testnamespace.cpp @@ -15,7 +15,7 @@ using namespace Qt::StringLiterals; void NamespaceTest::testNamespaceMembers() { - const char* cppCode = "\ + const char cppCode[] = "\ namespace Namespace\n\ {\n\ enum Option {\n\ @@ -24,26 +24,26 @@ void NamespaceTest::testNamespaceMembers() };\n\ void foo(Option opt);\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <namespace-type name='Namespace'>\n\ <enum-type name='Option' />\n\ </namespace-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass *ns = AbstractMetaClass::findClass(classes, u"Namespace"); + const auto ns = AbstractMetaClass::findClass(classes, "Namespace"); QVERIFY(ns); auto metaEnum = ns->findEnum(u"Option"_s); QVERIFY(metaEnum.has_value()); - const auto func = ns->findFunction(u"foo"); - QVERIFY(!func.isNull()); + const auto func = ns->findFunction("foo"); + QVERIFY(func); } void NamespaceTest::testNamespaceInnerClassMembers() { - const char* cppCode = "\ + const char cppCode[] = "\ namespace OuterNamespace\n\ {\n\ namespace InnerNamespace {\n\ @@ -52,7 +52,7 @@ void NamespaceTest::testNamespaceInnerClassMembers() };\n\ };\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <namespace-type name='OuterNamespace'>\n\ <namespace-type name='InnerNamespace'>\n\ @@ -61,16 +61,16 @@ void NamespaceTest::testNamespaceInnerClassMembers() </namespace-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *ons = AbstractMetaClass::findClass(classes, u"OuterNamespace"); + const auto ons = AbstractMetaClass::findClass(classes, "OuterNamespace"); QVERIFY(ons); - const AbstractMetaClass *ins = AbstractMetaClass::findClass(classes, u"OuterNamespace::InnerNamespace"); + const auto ins = AbstractMetaClass::findClass(classes, "OuterNamespace::InnerNamespace"); QVERIFY(ins); - const AbstractMetaClass *sc = AbstractMetaClass::findClass(classes, u"OuterNamespace::InnerNamespace::SomeClass"); + const auto sc = AbstractMetaClass::findClass(classes, "OuterNamespace::InnerNamespace::SomeClass"); QVERIFY(sc); - const auto meth = sc->findFunction(u"method"); - QVERIFY(!meth.isNull()); + const auto meth = sc->findFunction("method"); + QVERIFY(meth); } QTEST_APPLESS_MAIN(NamespaceTest) diff --git a/sources/shiboken6/ApiExtractor/tests/testnestedtypes.cpp b/sources/shiboken6/ApiExtractor/tests/testnestedtypes.cpp index 7f827d5aa..10ca1a0f6 100644 --- a/sources/shiboken6/ApiExtractor/tests/testnestedtypes.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testnestedtypes.cpp @@ -5,6 +5,7 @@ #include "testutil.h" #include <abstractmetafunction.h> #include <abstractmetalang.h> +#include <abstractmetatype.h> #include <codesnip.h> #include <modifications.h> #include <complextypeentry.h> @@ -18,7 +19,7 @@ using namespace Qt::StringLiterals; void TestNestedTypes::testNestedTypesModifications() { - const char* cppCode ="\ + const char cppCode[] = "\ namespace OuterNamespace {\n\ namespace InnerNamespace {\n\ struct SomeClass {\n\ @@ -26,7 +27,7 @@ void TestNestedTypes::testNestedTypesModifications() };\n\ };\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <namespace-type name='OuterNamespace'>\n\ <namespace-type name='InnerNamespace'>\n\ @@ -42,13 +43,13 @@ void TestNestedTypes::testNestedTypesModifications() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto *ons = AbstractMetaClass::findClass(classes, u"OuterNamespace"); + const auto ons = AbstractMetaClass::findClass(classes, "OuterNamespace"); QVERIFY(ons); - auto *ins = AbstractMetaClass::findClass(classes, u"OuterNamespace::InnerNamespace"); + const auto ins = AbstractMetaClass::findClass(classes, "OuterNamespace::InnerNamespace"); QVERIFY(ins); QCOMPARE(ins->functions().size(), 1); QCOMPARE(ins->typeEntry()->codeSnips().size(), 1); @@ -67,8 +68,9 @@ void TestNestedTypes::testNestedTypesModifications() snip = addedFunc->modifications().constFirst().snips().constFirst(); QCOMPARE(snip.code().trimmed(), u"custom_code2();"); - auto *sc = AbstractMetaClass::findClass(classes, u"OuterNamespace::InnerNamespace::SomeClass"); - QVERIFY(ins); + const auto sc = + AbstractMetaClass::findClass(classes, "OuterNamespace::InnerNamespace::SomeClass"); + QVERIFY(sc); QCOMPARE(sc->functions().size(), 2); // default constructor and removed method const auto removedFunc = sc->functions().constLast(); QVERIFY(removedFunc->isModifiedRemoved()); @@ -77,11 +79,11 @@ void TestNestedTypes::testNestedTypesModifications() void TestNestedTypes::testDuplicationOfNestedTypes() { - const char* cppCode ="\ + const char cppCode[] = "\ namespace Namespace {\n\ class SomeClass {};\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <namespace-type name='Namespace'>\n\ <value-type name='SomeClass'>\n\ @@ -91,22 +93,22 @@ void TestNestedTypes::testDuplicationOfNestedTypes() </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 2); - auto *nspace = AbstractMetaClass::findClass(classes, u"Namespace"); + const auto nspace = AbstractMetaClass::findClass(classes, "Namespace"); QVERIFY(nspace); - auto *cls1 = AbstractMetaClass::findClass(classes, u"SomeClass"); + const auto cls1 = AbstractMetaClass::findClass(classes, "SomeClass"); QVERIFY(cls1); - auto *cls2 = AbstractMetaClass::findClass(classes, u"Namespace::SomeClass"); + const auto cls2 = AbstractMetaClass::findClass(classes, "Namespace::SomeClass"); QVERIFY(cls2); QCOMPARE(cls1, cls2); QCOMPARE(cls1->name(), u"SomeClass"); QCOMPARE(cls1->qualifiedCppName(), u"Namespace::SomeClass"); - TypeEntry* t1 = TypeDatabase::instance()->findType(u"Namespace::SomeClass"_s); + auto t1 = TypeDatabase::instance()->findType(u"Namespace::SomeClass"_s); QVERIFY(t1); - TypeEntry* t2 = TypeDatabase::instance()->findType(u"SomeClass"_s); + auto t2 = TypeDatabase::instance()->findType(u"SomeClass"_s); QVERIFY(!t2); } diff --git a/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp b/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp index 7d72aa7c7..9eef7ec47 100644 --- a/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp @@ -4,17 +4,19 @@ #include "testnumericaltypedef.h" #include <QtTest/QTest> #include "testutil.h" +#include <abstractmetaargument.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> +#include <abstractmetatype.h> #include <typesystem.h> void TestNumericalTypedef::testNumericalTypedef() { - const char* cppCode ="\ + const char cppCode[] = "\ typedef double real;\n\ void funcDouble(double);\n\ void funcReal(real);\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='double'/>\n\ <primitive-type name='real'/>\n\ @@ -22,7 +24,7 @@ void TestNumericalTypedef::testNumericalTypedef() <function signature='funcReal(real)'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); QCOMPARE(builder->globalFunctions().size(), 2); auto funcDouble = builder->globalFunctions().constFirst(); @@ -38,21 +40,21 @@ void TestNumericalTypedef::testNumericalTypedef() const AbstractMetaType doubleType = funcDouble->arguments().constFirst().type(); QCOMPARE(doubleType.cppSignature(), u"double"); QVERIFY(doubleType.isPrimitive()); - QVERIFY(doubleType.typeEntry()->isCppPrimitive()); + QVERIFY(isCppPrimitive(doubleType.typeEntry())); const AbstractMetaType realType = funcReal->arguments().constFirst().type(); QCOMPARE(realType.cppSignature(), u"real"); QVERIFY(realType.isPrimitive()); - QVERIFY(realType.typeEntry()->isCppPrimitive()); + QVERIFY(isCppPrimitive(realType.typeEntry())); } void TestNumericalTypedef::testUnsignedNumericalTypedef() { - const char* cppCode ="\ + const char cppCode[] = "\ typedef unsigned short custom_ushort;\n\ void funcUnsignedShort(unsigned short);\n\ void funcUShort(custom_ushort);\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='short'/>\n\ <primitive-type name='unsigned short'/>\n\ @@ -61,7 +63,7 @@ void TestNumericalTypedef::testUnsignedNumericalTypedef() <function signature='funcUShort(custom_ushort)'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); QCOMPARE(builder->globalFunctions().size(), 2); auto funcUnsignedShort = builder->globalFunctions().constFirst(); @@ -76,12 +78,12 @@ void TestNumericalTypedef::testUnsignedNumericalTypedef() const AbstractMetaType unsignedShortType = funcUnsignedShort->arguments().constFirst().type(); QCOMPARE(unsignedShortType.cppSignature(), u"unsigned short"); QVERIFY(unsignedShortType.isPrimitive()); - QVERIFY(unsignedShortType.typeEntry()->isCppPrimitive()); + QVERIFY(isCppPrimitive(unsignedShortType.typeEntry())); const AbstractMetaType ushortType = funcUShort->arguments().constFirst().type(); QCOMPARE(ushortType.cppSignature(), u"custom_ushort"); QVERIFY(ushortType.isPrimitive()); - QVERIFY(ushortType.typeEntry()->isCppPrimitive()); + QVERIFY(isCppPrimitive(ushortType.typeEntry())); } QTEST_APPLESS_MAIN(TestNumericalTypedef) diff --git a/sources/shiboken6/ApiExtractor/tests/testprimitivetypetag.cpp b/sources/shiboken6/ApiExtractor/tests/testprimitivetypetag.cpp index 30552ff0b..99cced09d 100644 --- a/sources/shiboken6/ApiExtractor/tests/testprimitivetypetag.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testprimitivetypetag.cpp @@ -14,23 +14,23 @@ using namespace Qt::StringLiterals; void TestPrimitiveTypeTag::testPrimitiveTypeDefaultConstructor() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {};\n\ struct B {};\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <primitive-type name='A' default-constructor='A()'/>\n\ <object-type name='B'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); - PrimitiveTypeEntry* typeEntry = TypeDatabase::instance()->findPrimitiveType(u"A"_s); + auto typeEntry = TypeDatabase::instance()->findPrimitiveType(u"A"_s); QVERIFY(typeEntry); QVERIFY(typeEntry->hasDefaultConstructor()); QCOMPARE(typeEntry->defaultConstructor(), u"A()"); diff --git a/sources/shiboken6/ApiExtractor/tests/testrefcounttag.cpp b/sources/shiboken6/ApiExtractor/tests/testrefcounttag.cpp index 3ceac5fca..f2e261624 100644 --- a/sources/shiboken6/ApiExtractor/tests/testrefcounttag.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testrefcounttag.cpp @@ -15,12 +15,12 @@ using namespace Qt::StringLiterals; void TestRefCountTag::testReferenceCountTag() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {};\n\ struct B {\n\ void keepObject(B* b);\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <object-type name='A'/>\n\ <object-type name='B'>\n\ @@ -32,11 +32,11 @@ void TestRefCountTag::testReferenceCountTag() </object-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); - const auto func = classB->findFunction(u"keepObject"); - QVERIFY(!func.isNull()); + const auto classB = AbstractMetaClass::findClass(classes, "B"); + const auto func = classB->findFunction("keepObject"); + QVERIFY(func); const auto refCount = func->modifications().constFirst().argument_mods().constFirst().referenceCounts().constFirst(); QCOMPARE(refCount.action, ReferenceCount::Add); @@ -44,12 +44,12 @@ void TestRefCountTag::testReferenceCountTag() void TestRefCountTag::testWithApiVersion() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {};\n\ struct B {\n\ void keepObject(B*, B*);\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <object-type name='A'/>\n\ <object-type name='B'>\n\ @@ -66,11 +66,11 @@ void TestRefCountTag::testWithApiVersion() QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, u"0.1"_s)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); - const auto func = classB->findFunction(u"keepObject"); - QVERIFY(!func.isNull()); + const auto classB = AbstractMetaClass::findClass(classes, "B"); + const auto func = classB->findFunction("keepObject"); + QVERIFY(func); const auto refCount = func->modifications().constFirst().argument_mods().constFirst().referenceCounts().constFirst(); QCOMPARE(refCount.action, ReferenceCount::Add); diff --git a/sources/shiboken6/ApiExtractor/tests/testreferencetopointer.cpp b/sources/shiboken6/ApiExtractor/tests/testreferencetopointer.cpp index e82c398c4..ae85c5a86 100644 --- a/sources/shiboken6/ApiExtractor/tests/testreferencetopointer.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testreferencetopointer.cpp @@ -4,29 +4,31 @@ #include "testreferencetopointer.h" #include <QtTest/QTest> #include "testutil.h" +#include <abstractmetaargument.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> +#include <abstractmetatype.h> #include <typesystem.h> void TestReferenceToPointer::testReferenceToPointerArgument() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {};\n\ struct B {\n\ void dummy(A*&);\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <object-type name='A'/>\n\ <object-type name='B'/>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); - const auto func = classB->findFunction(u"dummy"); - QVERIFY(!func.isNull()); + const auto func = classB->findFunction("dummy"); + QVERIFY(func); QCOMPARE(func->arguments().constFirst().type().minimalSignature(), u"A*&"); } diff --git a/sources/shiboken6/ApiExtractor/tests/testremovefield.cpp b/sources/shiboken6/ApiExtractor/tests/testremovefield.cpp index 3ec348c2a..2cc82071b 100644 --- a/sources/shiboken6/ApiExtractor/tests/testremovefield.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testremovefield.cpp @@ -4,18 +4,23 @@ #include "testremovefield.h" #include <QtTest/QTest> #include "testutil.h" +#include <abstractmetaargument.h> #include <abstractmetafield.h> +#include <abstractmetafunction.h> +#include <abstractmetatype.h> #include <abstractmetalang.h> #include <typesystem.h> +using namespace Qt::StringLiterals; + void TestRemoveField::testRemoveField() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {\n\ int fieldA;\n\ int fieldB;\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <primitive-type name='int'/>\n\ <value-type name='A'>\n\ @@ -23,15 +28,49 @@ void TestRemoveField::testRemoveField() </value-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->fields().size(), 1); const AbstractMetaField &fieldA = classA->fields().constFirst(); QCOMPARE(fieldA.name(), u"fieldA"); } +// Verify that 'static constexpr' fields are seen as static/const and +// appear fully qualified for function parameter default values. +void TestRemoveField::testConstExprField() +{ + const char cppCode[] = R"( +struct A { + static constexpr int constExprField = 44; + + void f(int iParam=constExprField); +}; +)"; + + const char xmlCode[] = R"( +<typesystem package="Foo"> + <value-type name='A'/> +</typesystem> +)"; + + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(builder); + AbstractMetaClassList classes = builder->classes(); + const auto classA = AbstractMetaClass::findClass(classes, "A"); + QVERIFY(classA); + const auto &fields = classA->fields(); + QCOMPARE(fields.size(), 1); + QVERIFY(fields.constFirst().isStatic()); + QVERIFY(fields.constFirst().type().isConstant()); + const auto function = classA->findFunction("f"_L1); + QVERIFY(function); + const auto &arguments = function->arguments(); + QCOMPARE(arguments.size(), 1); + QCOMPARE(arguments.constFirst().defaultValueExpression(), "A::constExprField"_L1); +} + QTEST_APPLESS_MAIN(TestRemoveField) diff --git a/sources/shiboken6/ApiExtractor/tests/testremovefield.h b/sources/shiboken6/ApiExtractor/tests/testremovefield.h index febe672ce..05912d99e 100644 --- a/sources/shiboken6/ApiExtractor/tests/testremovefield.h +++ b/sources/shiboken6/ApiExtractor/tests/testremovefield.h @@ -11,6 +11,7 @@ class TestRemoveField : public QObject Q_OBJECT private slots: void testRemoveField(); + void testConstExprField(); }; #endif diff --git a/sources/shiboken6/ApiExtractor/tests/testremoveimplconv.cpp b/sources/shiboken6/ApiExtractor/tests/testremoveimplconv.cpp index e7c183586..87e318e95 100644 --- a/sources/shiboken6/ApiExtractor/tests/testremoveimplconv.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testremoveimplconv.cpp @@ -4,22 +4,24 @@ #include "testremoveimplconv.h" #include "testutil.h" #include <QtTest/QTest> +#include <abstractmetaargument.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> +#include <abstractmetatype.h> #include <complextypeentry.h> // When a constructor able to trigger implicity conversions is removed // it should not appear in the implicity conversion list. void TestRemoveImplConv::testRemoveImplConv() { - const char* cppCode ="\ + const char cppCode[] = "\ struct A {};\n\ struct B {};\n\ struct C {\n\ C(const A&);\n\ C(const B&);\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode[] = "\ <typesystem package=\"Foo\">\n\ <value-type name='A'/>\n\ <value-type name='B'/>\n\ @@ -28,14 +30,14 @@ void TestRemoveImplConv::testRemoveImplConv() </value-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 3); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); - const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, u"C"); + const auto classC = AbstractMetaClass::findClass(classes, "C"); QVERIFY(classC); const auto implConv = classC->implicitConversions(); QCOMPARE(implConv.size(), 1); diff --git a/sources/shiboken6/ApiExtractor/tests/testremoveoperatormethod.cpp b/sources/shiboken6/ApiExtractor/tests/testremoveoperatormethod.cpp index 3f687186e..17a069b5e 100644 --- a/sources/shiboken6/ApiExtractor/tests/testremoveoperatormethod.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testremoveoperatormethod.cpp @@ -15,29 +15,30 @@ using namespace Qt::StringLiterals; void TestRemoveOperatorMethod::testRemoveOperatorMethod() { - const char* cppCode ="\ - #include <stdint.h>\n\ - \n\ - struct Char {};\n\ - struct ByteArray {};\n\ - struct String {};\n\ - \n\ - struct A {\n\ - A& operator>>(char&);\n\ - A& operator>>(char*);\n\ - A& operator>>(short&);\n\ - A& operator>>(unsigned short&);\n\ - A& operator>>(int&);\n\ - A& operator>>(unsigned int&);\n\ - A& operator>>(int64_t&);\n\ - A& operator>>(uint64_t&);\n\ - A& operator>>(float&);\n\ - A& operator>>(double&);\n\ - A& operator>>(Char&);\n\ - A& operator>>(ByteArray&);\n\ - A& operator>>(String&);\n\ - };\n"; - const char* xmlCode = "\ + const char cppCode[] = R"(#include <cstdint> + +struct Char {}; +struct ByteArray {}; +struct String {}; + +struct A { + A& operator>>(char&); + A& operator>>(char*); + A& operator>>(short&); + A& operator>>(unsigned short&); + A& operator>>(int&); + A& operator>>(unsigned int&); + A& operator>>(int64_t&); + A& operator>>(uint64_t&); + A& operator>>(float&); + A& operator>>(double&); + A& operator>>(Char&); + A& operator>>(ByteArray&); + A& operator>>(String&); +}; +)"; + + const char xmlCode[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='char'/>\n\ <primitive-type name='short'/>\n\ @@ -67,9 +68,9 @@ void TestRemoveOperatorMethod::testRemoveOperatorMethod() </object-type>\n\ </typesystem>\n"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->functions().size(), 14); QStringList removedSignatures; @@ -85,7 +86,7 @@ void TestRemoveOperatorMethod::testRemoveOperatorMethod() removedSignatures.append(u"operator>>(double&)"_s); removedSignatures.append(u"operator>>(Char&)"_s); removedSignatures.append(u"operator>>(String&)"_s); - int notRemoved = classA->functions().size(); + auto notRemoved = classA->functions().size(); for (const auto &f : classA->functions()) { QCOMPARE(f->isModifiedRemoved(), bool(removedSignatures.contains(f->minimalSignature()))); notRemoved -= int(f->isModifiedRemoved()); diff --git a/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp b/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp index 8b8f02a8f..67ebcc606 100644 --- a/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp @@ -3,10 +3,15 @@ #include "testresolvetype.h" #include "testutil.h" +#include <abstractmetaargument.h> +#include <abstractmetaenum.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> #include <abstractmetatype.h> #include <complextypeentry.h> +#include <enumtypeentry.h> +#include <primitivetypeentry.h> +#include <typedatabase.h> #include <qtcompat.h> @@ -22,7 +27,7 @@ void TestResolveType::initTestCase() void TestResolveType::testResolveReturnTypeFromParentScope() { - const char* cppCode = "\n\ + const char cppCode[] = "\n\ namespace A {\n\ struct B {\n\ struct C {};\n\ @@ -32,7 +37,7 @@ void TestResolveType::testResolveReturnTypeFromParentScope() C* method();\n\ };\n\ };"; - const char* xmlCode = R"XML( + const char xmlCode[] = R"XML( <typesystem package='Foo'> <namespace-type name='A'> <value-type name='B'> @@ -42,12 +47,12 @@ void TestResolveType::testResolveReturnTypeFromParentScope() </namespace-type> </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classD = AbstractMetaClass::findClass(classes, u"A::D"); + const auto classD = AbstractMetaClass::findClass(classes, "A::D"); QVERIFY(classD); - const auto meth = classD->findFunction(u"method"); - QVERIFY(!meth.isNull()); + const auto meth = classD->findFunction("method"); + QVERIFY(meth); QVERIFY(meth); } @@ -57,13 +62,14 @@ void TestResolveType::testResolveReturnTypeFromParentScope() struct DefaultValuesFixture { - QSharedPointer<AbstractMetaBuilder> builder; + std::shared_ptr<AbstractMetaBuilder> builder; AbstractMetaType intType; AbstractMetaType stringType; AbstractMetaType classType; AbstractMetaType listType; - const AbstractMetaClass *klass{}; + AbstractMetaType enumType; + AbstractMetaClassCPtr klass{}; }; Q_DECLARE_METATYPE(DefaultValuesFixture) @@ -88,6 +94,7 @@ public: static const int INT_FIELD_1 = 42; static const char *CHAR_FIELD_1; + static const Enum DefaultValue = enumValue1; }; } // Namespace )"; @@ -103,7 +110,7 @@ public: )"; fixture->builder.reset(TestUtil::parse(cppCode, xmlCode, false)); - if (fixture->builder.isNull()) + if (!fixture->builder) return -1; for (const auto &klass : fixture->builder->classes()) { @@ -118,7 +125,7 @@ public: fixture->classType = AbstractMetaType(fixture->klass->typeEntry()); fixture->classType.decideUsagePattern(); - for (const auto &f : fixture->klass->findFunctions(u"Test"_s)) { + for (const auto &f : fixture->klass->findFunctions("Test")) { if (f->functionType() == AbstractMetaFunction::ConstructorFunction && f->arguments().size() == 1) { const auto type = f->arguments().constFirst().type(); @@ -131,11 +138,14 @@ public: if (fixture->intType.isVoid() || fixture->stringType.isVoid()) return -3; - auto listFunc = fixture->klass->findFunction(u"listFunc"_s); - if (listFunc.isNull() || listFunc->arguments().size() != 1) + auto listFunc = fixture->klass->findFunction("listFunc"); + if (!listFunc || listFunc->arguments().size() != 1) return -3; fixture->listType = listFunc->arguments().constFirst().type(); + fixture->enumType = AbstractMetaType(fixture->klass->enums().constFirst().typeEntry()); + fixture->enumType.decideUsagePattern(); + return 0; } @@ -210,6 +220,11 @@ void TestResolveType::testFixDefaultArguments_data() QTest::newRow("self from enum") << fixture << setupOk << fixture.classType << "Test(enumValue1)" << expected; + + // Don't qualify fields to "Test::Enum::DefaultValue" + QTest::newRow("enum from static field") + << fixture << setupOk << fixture.enumType + << "DefaultValue" << u"Namespace::Test::DefaultValue"_s; } void TestResolveType::testFixDefaultArguments() @@ -224,5 +239,43 @@ void TestResolveType::testFixDefaultArguments() QCOMPARE(actual, expected); } -QTEST_APPLESS_MAIN(TestResolveType) +// Verify that the typedefs of the C++ 11 integer types (int32_t, ...) +// are seen by the C++ parser, otherwise they are handled as unknown +// primitive types, causing invalid code to be generated. +// (see BuilderPrivate::visitHeader(), +// sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp). +void TestResolveType::testCppTypes() +{ + static const char cppCode[] =R"( +#include <cstdint> +class Test +{ +public: + explicit Test(int32_t v); +}; +)"; + static const char xmlCode[] = R"( +<typesystem package="Foo"> + <value-type name='Test'/> + <primitive-type name='int32_t'/> +</typesystem> +)"; + + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(builder); + AbstractMetaClassList classes = builder->classes(); + const auto testClass = AbstractMetaClass::findClass(classes, "Test"); + QVERIFY(testClass); + + auto *tdb = TypeDatabase::instance(); + auto int32TEntry = tdb->findType(u"int32_t"_s); + QVERIFY2(int32TEntry, "int32_t not found"); + QVERIFY(int32TEntry->isPrimitive()); + auto int32T = std::static_pointer_cast<const PrimitiveTypeEntry>(int32TEntry); + auto basicType = basicReferencedTypeEntry(int32T); + QVERIFY2(basicType != int32T, + "Typedef for int32_t not found. Check the system include paths."); +} + +QTEST_APPLESS_MAIN(TestResolveType) diff --git a/sources/shiboken6/ApiExtractor/tests/testresolvetype.h b/sources/shiboken6/ApiExtractor/tests/testresolvetype.h index 2c059416d..a07855eab 100644 --- a/sources/shiboken6/ApiExtractor/tests/testresolvetype.h +++ b/sources/shiboken6/ApiExtractor/tests/testresolvetype.h @@ -15,6 +15,7 @@ class TestResolveType : public QObject void testResolveReturnTypeFromParentScope(); void testFixDefaultArguments_data(); void testFixDefaultArguments(); + void testCppTypes(); }; #endif diff --git a/sources/shiboken6/ApiExtractor/tests/testreverseoperators.cpp b/sources/shiboken6/ApiExtractor/tests/testreverseoperators.cpp index 90c613f96..f4eecff2c 100644 --- a/sources/shiboken6/ApiExtractor/tests/testreverseoperators.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testreverseoperators.cpp @@ -4,6 +4,7 @@ #include "testreverseoperators.h" #include <QtTest/QTest> #include "testutil.h" +#include <abstractmetaargument.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> #include <typesystem.h> @@ -24,9 +25,9 @@ void TestReverseOperators::testReverseSum() </typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->functions().size(), 4); @@ -41,10 +42,10 @@ void TestReverseOperators::testReverseSum() } } - QVERIFY(!normalOp.isNull()); + QVERIFY(normalOp); QVERIFY(!normalOp->isReverseOperator()); QCOMPARE(normalOp->arguments().size(), 1); - QVERIFY(!reverseOp.isNull()); + QVERIFY(reverseOp); QVERIFY(reverseOp->isReverseOperator()); QCOMPARE(reverseOp->arguments().size(), 1); } @@ -66,13 +67,13 @@ void TestReverseOperators::testReverseSumWithAmbiguity() </typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QCOMPARE(classA->functions().size(), 4); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); QCOMPARE(classB->functions().size(), 4); @@ -86,11 +87,11 @@ void TestReverseOperators::testReverseSumWithAmbiguity() normalOp = func; } } - QVERIFY(!normalOp.isNull()); + QVERIFY(normalOp); QVERIFY(!normalOp->isReverseOperator()); QCOMPARE(normalOp->arguments().size(), 1); QCOMPARE(normalOp->minimalSignature(), u"operator+(B,A)"); - QVERIFY(!reverseOp.isNull()); + QVERIFY(reverseOp); QVERIFY(reverseOp->isReverseOperator()); QCOMPARE(reverseOp->arguments().size(), 1); QCOMPARE(reverseOp->minimalSignature(), u"operator+(A,B)"); @@ -110,10 +111,10 @@ void TestReverseOperators::testSpaceshipOperator() </typesystem>)"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, {}, {}, LanguageLevel::Cpp20)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - const AbstractMetaClass *testClass = AbstractMetaClass::findClass(classes, u"Test"); + const auto testClass = AbstractMetaClass::findClass(classes, "Test"); QVERIFY(testClass); const auto &functions = testClass->functions(); // 6 operators should be synthesized diff --git a/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp b/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp index ddd134306..ea37c6255 100644 --- a/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp @@ -3,9 +3,11 @@ #include "testtemplates.h" #include "testutil.h" +#include <abstractmetaargument.h> #include <abstractmetafield.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> +#include <abstractmetatype.h> #include <complextypeentry.h> #include <containertypeentry.h> @@ -53,16 +55,16 @@ namespace Internet { </typesystem>)XML").arg(file.fileName()); QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, qPrintable(xmlCode1), false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"Bookmarks"); + const auto classB = AbstractMetaClass::findClass(classes, "Bookmarks"); QVERIFY(classB); - const auto func = classB->findFunction(u"list"); - QVERIFY(!func.isNull()); + const auto func = classB->findFunction("list"); + QVERIFY(func); AbstractMetaType funcType = func->type(); QVERIFY(!funcType.isVoid()); - QCOMPARE(funcType.cppSignature(), u"QList<Internet::Url >"); + QCOMPARE(funcType.cppSignature(), u"QList<Internet::Url>"); } void TestTemplates::testTemplateOnContainers() @@ -91,15 +93,15 @@ namespace Namespace { </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); QVERIFY(!classB->baseClass()); QVERIFY(classB->baseClassName().isEmpty()); - const auto func = classB->findFunction(u"foo"); - QVERIFY(!func.isNull()); + const auto func = classB->findFunction("foo"); + QVERIFY(func); AbstractMetaType argType = func->arguments().constFirst().type(); QCOMPARE(argType.instantiations().size(), 1); QCOMPARE(argType.typeEntry()->qualifiedCppName(), u"QList"); @@ -128,14 +130,14 @@ void func(List<int> arg) {} </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); const auto globalFuncs = builder->globalFunctions(); QCOMPARE(globalFuncs.size(), 1); const auto func = globalFuncs.constFirst(); QCOMPARE(func->minimalSignature(), u"func(List<int>)"); QCOMPARE(func->arguments().constFirst().type().cppSignature(), - u"List<int >"); + u"List<int>"); } void TestTemplates::testTemplatePointerAsArgument() @@ -153,14 +155,14 @@ void func(List<int>* arg) {} </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaFunctionCList globalFuncs = builder->globalFunctions(); QCOMPARE(globalFuncs.size(), 1); const auto func = globalFuncs.constFirst(); QCOMPARE(func->minimalSignature(), u"func(List<int>*)"); QCOMPARE(func->arguments().constFirst().type().cppSignature(), - u"List<int > *"); + u"List<int> *"); } void TestTemplates::testTemplateReferenceAsArgument() @@ -178,14 +180,14 @@ void func(List<int>& arg) {} </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); const auto globalFuncs = builder->globalFunctions(); QCOMPARE(globalFuncs.size(), 1); const auto func = globalFuncs.constFirst(); QCOMPARE(func->minimalSignature(), u"func(List<int>&)"); QCOMPARE(func->arguments().constFirst().type().cppSignature(), - u"List<int > &"); + u"List<int> &"); } void TestTemplates::testTemplateParameterFixup() @@ -207,21 +209,20 @@ struct List { </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); const AbstractMetaClassList templates = builder->templates(); QCOMPARE(templates.size(), 1); - const AbstractMetaClass *list = templates.constFirst(); - // Verify that the parameter of "void append(List l)" gets fixed to "List<T >" - const auto append = list->findFunction(QStringLiteral("append")); - QVERIFY(!append.isNull()); + AbstractMetaClassCPtr list = templates.constFirst(); + // Verify that the parameter of "void append(List l)" gets fixed to "List<T>" + const auto append = list->findFunction("append"); + QVERIFY(append); QCOMPARE(append->arguments().size(), 1); - QCOMPARE(append->arguments().at(0).type().cppSignature(), u"List<T >"); + QCOMPARE(append->arguments().at(0).type().cppSignature(), u"List<T>"); // Verify that the parameter of "void erase(Iterator)" is not modified - const auto erase = list->findFunction(QStringLiteral("erase")); - QVERIFY(!erase.isNull()); + const auto erase = list->findFunction("erase"); + QVERIFY(erase); QCOMPARE(erase->arguments().size(), 1); - QEXPECT_FAIL("", "Clang: Some other code changes the parameter type", Abort); QCOMPARE(erase->arguments().at(0).type().cppSignature(), u"List::Iterator"); } @@ -248,16 +249,16 @@ struct FooBars : public ListContainer<FooBar> {}; </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); AbstractMetaClassList templates = builder->templates(); QCOMPARE(classes.size(), 2); QCOMPARE(templates.size(), 1); - const AbstractMetaClass* foobars = AbstractMetaClass::findClass(classes, u"FooBars"); + const auto foobars = AbstractMetaClass::findClass(classes, "FooBars"); QCOMPARE(foobars->functions().size(), 4); - const AbstractMetaClass *lc = templates.constFirst(); + AbstractMetaClassCPtr lc = templates.constFirst(); QCOMPARE(lc->functions().size(), 2); } @@ -285,10 +286,10 @@ template<SomeEnum type> struct Future {}; </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); QVERIFY(!classB->baseClass()); QVERIFY(classB->baseClassName().isEmpty()); @@ -324,10 +325,10 @@ template<SomeEnum type> struct Future {}; </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"Namespace::B"); + const auto classB = AbstractMetaClass::findClass(classes, "Namespace::B"); QVERIFY(classB); QVERIFY(!classB->baseClass()); QVERIFY(classB->baseClassName().isEmpty()); @@ -360,21 +361,21 @@ typedef BaseTemplateClass<TypeOne> TypeOneClass; </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 3); - const AbstractMetaClass* base = AbstractMetaClass::findClass(classes, u"BaseTemplateClass"); + const auto base = AbstractMetaClass::findClass(classes, "BaseTemplateClass"); QVERIFY(base); - const AbstractMetaClass* one = AbstractMetaClass::findClass(classes, u"TypeOneClass"); + const auto one = AbstractMetaClass::findClass(classes, "TypeOneClass"); QVERIFY(one); QCOMPARE(one->templateBaseClass(), base); QCOMPARE(one->functions().size(), base->functions().size()); QVERIFY(one->isTypeDef()); - const ComplexTypeEntry* oneType = one->typeEntry(); - const ComplexTypeEntry* baseType = base->typeEntry(); + auto oneType = one->typeEntry(); + auto baseType = base->typeEntry(); QCOMPARE(oneType->baseContainerType(), baseType); - QCOMPARE(one->baseClassNames(), QStringList(u"BaseTemplateClass<TypeOne>"_s)); + QCOMPARE(one->baseClassNames(), QStringList(u"NSpace::BaseTemplateClass<NSpace::TypeOne>"_s)); QVERIFY(one->hasTemplateBaseClassInstantiations()); AbstractMetaTypeList instantiations = one->templateBaseClassInstantiations(); @@ -409,27 +410,27 @@ typedef Vector<int> IntVector; </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.size(), 1); - AbstractMetaClass* vector = AbstractMetaClass::findClass(classes, u"IntVector"); + const auto vector = AbstractMetaClass::findClass(classes, "IntVector"); QVERIFY(vector); auto baseContainer = vector->typeEntry()->baseContainerType(); QVERIFY(baseContainer); - QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer)->containerKind(), + QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer.get())->containerKind(), ContainerTypeEntry::ListContainer); QCOMPARE(vector->functions().size(), 4); - const auto method = vector->findFunction(u"method"); - QVERIFY(!method.isNull()); - QCOMPARE(method->signature(), u"method(const Vector<int > & vector)"); + const auto method = vector->findFunction("method"); + QVERIFY(method); + QCOMPARE(method->signature(), u"method(const Vector<int> & vector)"); - const auto otherMethod = vector->findFunction(u"otherMethod"); - QVERIFY(!otherMethod.isNull()); + const auto otherMethod = vector->findFunction("otherMethod"); + QVERIFY(otherMethod); QCOMPARE(otherMethod->signature(), u"otherMethod()"); QVERIFY(!otherMethod->type().isVoid()); - QCOMPARE(otherMethod->type().cppSignature(), u"Vector<int >"); + QCOMPARE(otherMethod->type().cppSignature(), u"Vector<int>"); } void TestTemplates::testNonTypeTemplates() @@ -453,7 +454,7 @@ Array<int, 2> foo(); </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); auto functions = builder->globalFunctions(); QCOMPARE(functions.size(), 1); auto foo = functions.constFirst(); @@ -536,32 +537,30 @@ void TestTemplates::testTemplateTypeDefs() const QByteArray cppBa = cpp.toLocal8Bit(); const QByteArray xmlBa = xml.toLocal8Bit(); QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppBa.constData(), xmlBa.constData(), true)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *optional = AbstractMetaClass::findClass(classes, u"Optional"); + const auto optional = AbstractMetaClass::findClass(classes, "Optional"); QVERIFY(optional); // Find the typedef'ed class - const AbstractMetaClass *optionalInt = - AbstractMetaClass::findClass(classes, u"IntOptional"); + const auto optionalInt = AbstractMetaClass::findClass(classes, "IntOptional"); QVERIFY(optionalInt); QCOMPARE(optionalInt->templateBaseClass(), optional); // Find the class typedef'ed in the typesystem XML - const AbstractMetaClass *xmlOptionalInt = - AbstractMetaClass::findClass(classes, u"XmlIntOptional"); + const auto xmlOptionalInt = AbstractMetaClass::findClass(classes, "XmlIntOptional"); QVERIFY(xmlOptionalInt); QCOMPARE(xmlOptionalInt->templateBaseClass(), optional); // Check whether the value() method now has an 'int' return - const auto valueMethod = optionalInt->findFunction(u"value"); - QVERIFY(!valueMethod.isNull()); + const auto valueMethod = optionalInt->findFunction("value"); + QVERIFY(valueMethod); QCOMPARE(valueMethod->type().cppSignature(), u"int"); // ditto for typesystem XML - const auto xmlValueMethod = xmlOptionalInt->findFunction(u"value"); - QVERIFY(!xmlValueMethod.isNull()); + const auto xmlValueMethod = xmlOptionalInt->findFunction("value"); + QVERIFY(xmlValueMethod); QCOMPARE(xmlValueMethod->type().cppSignature(), u"int"); // Check whether the m_value field is of type 'int' @@ -607,10 +606,10 @@ public: </typesystem>)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - auto testClass = AbstractMetaClass::findClass(classes, u"Test"); + const auto testClass = AbstractMetaClass::findClass(classes, "Test"); QVERIFY(testClass); auto fields = testClass->fields(); @@ -619,9 +618,10 @@ public: QCOMPARE(fieldType.name(), u"Container1"); QCOMPARE(fieldType.instantiations().size(), 1); - auto derived = AbstractMetaClass::findClass(classes, u"Derived"); + const auto derived = AbstractMetaClass::findClass(classes, "Derived"); QVERIFY(derived); auto base = derived->templateBaseClass(); + QVERIFY(base); QCOMPARE(base->name(), u"Container1"); } diff --git a/sources/shiboken6/ApiExtractor/tests/testtyperevision.cpp b/sources/shiboken6/ApiExtractor/tests/testtyperevision.cpp index 299993bbf..72dae8cc5 100644 --- a/sources/shiboken6/ApiExtractor/tests/testtyperevision.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testtyperevision.cpp @@ -18,10 +18,10 @@ using namespace Qt::StringLiterals; void TestTypeRevision::testRevisionAttr() { - const char* cppCode = "class Rev_0 {};" + const char cppCode[] = "class Rev_0 {};" "class Rev_1 {};" "class Rev_2 { public: enum Rev_3 { X }; enum Rev_5 { Y }; };"; - const char* xmlCode = "<typesystem package=\"Foo\">" + const char xmlCode[] = "<typesystem package=\"Foo\">" "<value-type name=\"Rev_0\"/>" "<value-type name=\"Rev_1\" revision=\"1\"/>" "<object-type name=\"Rev_2\" revision=\"2\">" @@ -30,25 +30,25 @@ void TestTypeRevision::testRevisionAttr() "</object-type>" "</typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *rev0 = AbstractMetaClass::findClass(classes, u"Rev_0"); + const auto rev0 = AbstractMetaClass::findClass(classes, "Rev_0"); QCOMPARE(rev0->typeEntry()->revision(), 0); - const AbstractMetaClass *rev1 = AbstractMetaClass::findClass(classes, u"Rev_1"); + const auto rev1 = AbstractMetaClass::findClass(classes, "Rev_1"); QCOMPARE(rev1->typeEntry()->revision(), 1); - AbstractMetaClass *rev2 = AbstractMetaClass::findClass(classes, u"Rev_2"); + const auto rev2 = AbstractMetaClass::findClass(classes, "Rev_2"); QCOMPARE(rev2->typeEntry()->revision(), 2); auto rev3 = rev2->findEnum(u"Rev_3"_s); QVERIFY(rev3.has_value()); QCOMPARE(rev3->typeEntry()->revision(), 3); - FlagsTypeEntry* rev4 = rev3->typeEntry()->flags(); + auto rev4 = rev3->typeEntry()->flags(); QCOMPARE(rev4->revision(), 4); auto rev5 = rev2->findEnum(u"Rev_5"_s); QVERIFY(rev5.has_value()); - const EnumTypeEntry *revEnumTypeEntry = rev5->typeEntry(); + EnumTypeEntryCPtr revEnumTypeEntry = rev5->typeEntry(); QCOMPARE(revEnumTypeEntry->revision(), 5); QCOMPARE(revEnumTypeEntry->flags()->revision(), 5); } @@ -82,7 +82,7 @@ class Bar20 {}; )XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, version)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); QCOMPARE(builder->classes().size(), expectedClassCount); } diff --git a/sources/shiboken6/ApiExtractor/tests/testutil.h b/sources/shiboken6/ApiExtractor/tests/testutil.h index 7fbc7e906..dc4e3b2da 100644 --- a/sources/shiboken6/ApiExtractor/tests/testutil.h +++ b/sources/shiboken6/ApiExtractor/tests/testutil.h @@ -24,22 +24,22 @@ namespace TestUtil { ReportHandler::setSilent(silent); ReportHandler::startTimer(); - TypeDatabase* td = TypeDatabase::instance(true); + auto *td = TypeDatabase::instance(true); if (apiVersion.isEmpty()) TypeDatabase::clearApiVersions(); - else if (!TypeDatabase::setApiVersion(QStringLiteral("*"), apiVersion)) + else if (!TypeDatabase::setApiVersion(QLatin1StringView("*"), apiVersion)) return nullptr; td->setDropTypeEntries(dropTypeEntries); QBuffer buffer; // parse typesystem buffer.setData(xmlCode); if (!buffer.open(QIODevice::ReadOnly)) - return Q_NULLPTR; + return nullptr; if (!td->parseFile(&buffer)) return nullptr; buffer.close(); // parse C++ code - QTemporaryFile tempSource(QDir::tempPath() + QStringLiteral("/st_XXXXXX_main.cpp")); + QTemporaryFile tempSource(QDir::tempPath() + QLatin1StringView("/st_XXXXXX_main.cpp")); if (!tempSource.open()) { qWarning().noquote().nospace() << "Creation of temporary file failed: " << tempSource.errorString(); diff --git a/sources/shiboken6/ApiExtractor/tests/testvaluetypedefaultctortag.cpp b/sources/shiboken6/ApiExtractor/tests/testvaluetypedefaultctortag.cpp index 73f2d44ca..98e30eac2 100644 --- a/sources/shiboken6/ApiExtractor/tests/testvaluetypedefaultctortag.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testvaluetypedefaultctortag.cpp @@ -9,29 +9,29 @@ void TestValueTypeDefaultCtorTag::testValueTypeDefaultCtorTagArgument() { - const char* cppCode ="\n\ + const char cppCode[] = "\n\ struct A {\n\ A(int,int);\n\ };\n\ struct B {};\n\ "; - const char* xmlCode = "\n\ + const char xmlCode[] = "\n\ <typesystem package='Foo'>\n\ <primitive-type name='int' />\n\ <value-type name='A' default-constructor='A(0, 0)' />\n\ <value-type name='B' />\n\ </typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); QVERIFY(classA->typeEntry()->hasDefaultConstructor()); QCOMPARE(classA->typeEntry()->defaultConstructor(), u"A(0, 0)"); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B"); + const auto classB = AbstractMetaClass::findClass(classes, "B"); QVERIFY(classB); QVERIFY(!classB->typeEntry()->hasDefaultConstructor()); } diff --git a/sources/shiboken6/ApiExtractor/tests/testvoidarg.cpp b/sources/shiboken6/ApiExtractor/tests/testvoidarg.cpp index 56d70336a..a600181a5 100644 --- a/sources/shiboken6/ApiExtractor/tests/testvoidarg.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testvoidarg.cpp @@ -4,6 +4,7 @@ #include "testvoidarg.h" #include <QtTest/QTest> #include "testutil.h" +#include <abstractmetaargument.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> #include <typesystem.h> @@ -16,12 +17,12 @@ void TestVoidArg::testVoidParsedFunction() <value-type name='A'/>\n\ </typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const auto addedFunc = classA->findFunction(u"a"); - QVERIFY(!addedFunc.isNull()); + const auto addedFunc = classA->findFunction("a"); + QVERIFY(addedFunc); QCOMPARE(addedFunc->arguments().size(), 0); } @@ -35,12 +36,12 @@ void TestVoidArg::testVoidAddedFunction() </value-type>\n\ </typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const auto addedFunc = classA->findFunction(u"a"); - QVERIFY(!addedFunc.isNull()); + const auto addedFunc = classA->findFunction("a"); + QVERIFY(addedFunc); QCOMPARE(addedFunc->arguments().size(), 0); } @@ -53,12 +54,12 @@ void TestVoidArg::testVoidPointerParsedFunction() <value-type name='A' />\n\ </typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); + QVERIFY(builder); AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); + const auto classA = AbstractMetaClass::findClass(classes, "A"); QVERIFY(classA); - const auto addedFunc = classA->findFunction(u"a"); - QVERIFY(!addedFunc.isNull()); + const auto addedFunc = classA->findFunction("a"); + QVERIFY(addedFunc); QCOMPARE(addedFunc->arguments().size(), 1); } diff --git a/sources/shiboken6/ApiExtractor/textstream.h b/sources/shiboken6/ApiExtractor/textstream.h index 074e23858..228f36405 100644 --- a/sources/shiboken6/ApiExtractor/textstream.h +++ b/sources/shiboken6/ApiExtractor/textstream.h @@ -31,7 +31,7 @@ public: virtual ~TextStream(); Language language() const { return m_language; } - void setLanguage(const Language &language) { m_language = language; } + void setLanguage(Language language) { m_language = language; } bool isIndentationEnabled() const { return m_indentationEnabled; } void setIndentationEnabled(bool m) @@ -77,6 +77,10 @@ public: void putRawChar(char c) { m_str << c; } TextStream &operator<<(QStringView v) { putString(v); return *this; } + TextStream &operator<<(const QString &qs) { putString(QStringView{qs}); return *this; } + TextStream &operator<<(QLatin1StringView lv) { putString(lv.constData()); return *this; } + TextStream &operator<<(QUtf8StringView uv) { putString(uv.data()); return *this; } + TextStream &operator<<(const QByteArray &ba) { putString(ba.constData()); return *this; } TextStream &operator<<(QChar c) { putChar(c); return *this; } TextStream &operator<<(const char *s) { putString(s); return *this; } TextStream &operator<<(char c) { putChar(c); return *this; } @@ -85,7 +89,7 @@ public: TextStream &operator<<(qsizetype t) { putSizeType(t); return *this; } #endif - inline TextStream &operator<<(QTextStreamManipulator m) { m_str << m; return *this; } + inline TextStream &operator<<(const QTextStreamManipulator &m) { m_str << m; return *this; } inline TextStream &operator<<(ManipulatorFunc f) { f(*this); return *this; } void putRepetitiveChars(char c, int count); @@ -140,6 +144,12 @@ void rstCodeOff(TextStream &s); void rstItalic(TextStream &s); void rstItalicOff(TextStream &s); +inline TextStream &operator<<(TextStream &str, QAnyStringView asv) +{ + asv.visit([&str](auto s) { str << s; }); + return str; +} + /// Format an aligned field template <class T> class AlignedField @@ -179,6 +189,28 @@ TextStream &operator<<(TextStream &str, const AlignedField<T> &fa) return str; } +class Pad +{ +public: + explicit Pad(char c, int count) : m_char(c), m_count(count) {} + + void write(TextStream &str) const + { + for (int i = 0; i < m_count; ++i) + str << m_char; + } + +private: + const char m_char; + const int m_count; +}; + +inline TextStream &operator<<(TextStream &str, const Pad &pad) +{ + pad.write(str); + return str; +} + class Indentation { public: diff --git a/sources/shiboken6/ApiExtractor/typedatabase.cpp b/sources/shiboken6/ApiExtractor/typedatabase.cpp index 22d558cc2..61fd22418 100644 --- a/sources/shiboken6/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken6/ApiExtractor/typedatabase.cpp @@ -3,28 +3,25 @@ #include "typedatabase.h" #include "abstractmetatype.h" -#include "exception.h" +#include "addedfunction.h" #include "messages.h" #include "typesystemparser_p.h" -#include "arraytypeentry.h" #include "complextypeentry.h" #include "constantvaluetypeentry.h" #include "containertypeentry.h" -#include "customconversion.h" #include "customtypenentry.h" -#include "enumtypeentry.h" -#include "enumvaluetypeentry.h" +#include "debughelpers_p.h" +#include "exception.h" #include "flagstypeentry.h" #include "functiontypeentry.h" #include "namespacetypeentry.h" #include "objecttypeentry.h" #include "primitivetypeentry.h" +#include "optionsparser.h" #include "pythontypeentry.h" #include "smartpointertypeentry.h" -#include "templateargumententry.h" #include "typedefentry.h" #include "typesystemtypeentry.h" -#include "valuetypeentry.h" #include "varargstypeentry.h" #include "voidtypeentry.h" #include "conditionalstreamreader.h" @@ -38,29 +35,29 @@ #include <QtCore/QFile> #include <QtCore/QDebug> #include <QtCore/QDir> -#include <QtCore/QPair> #include <QtCore/QList> #include <QtCore/QRegularExpression> #include <QtCore/QVersionNumber> #include <QtCore/QXmlStreamReader> #include "reporthandler.h" -// #include <tr1/tuple> + #include <algorithm> +#include <utility> using namespace Qt::StringLiterals; -using TypeDatabaseParserContextPtr = QSharedPointer<TypeDatabaseParserContext>; +using TypeDatabaseParserContextPtr = std::shared_ptr<TypeDatabaseParserContext>; // package -> api-version static QString wildcardToRegExp(QString w) { w.replace(u'?', u'.'); - w.replace(u'*', QStringLiteral(".*")); + w.replace(u'*', ".*"_L1); return w; } -using ApiVersion =QPair<QRegularExpression, QVersionNumber>; +using ApiVersion = std::pair<QRegularExpression, QVersionNumber>; using ApiVersions = QList<ApiVersion>; Q_GLOBAL_STATIC(ApiVersions, apiVersions) @@ -91,7 +88,8 @@ static const PythonTypes &builtinPythonTypes() {u"PyObject"_s, u"true"_s, TypeSystem::CPythonType::Other}, // shiboken-specific {u"PyPathLike"_s, u"Shiboken::String::checkPath"_s, TypeSystem::CPythonType::Other}, - {u"PySequence"_s, u"Shiboken::String::checkIterable"_s, TypeSystem::CPythonType::Other}, + {u"PySequence"_s, u"Shiboken::String::checkIterableArgument"_s, + TypeSystem::CPythonType::Other}, {u"PyUnicode"_s, u"PyUnicode_Check"_s, TypeSystem::CPythonType::String}, {u"PyTypeObject"_s, u"PyType_Check"_s, TypeSystem::CPythonType::Other}, {u"str"_s, u"Shiboken::String::check"_s, TypeSystem::CPythonType::String}, @@ -106,12 +104,132 @@ static const PythonTypes &builtinPythonTypes() return result; } -struct TypeDatabasePrivate +struct SuppressedWarning +{ + QRegularExpression pattern; + QString rawText; + bool generate; // Current type system + mutable bool matched = false; +}; + +QList<OptionDescription> TypeDatabase::options() +{ + return { + {u"api-version=<\"package mask\">,<\"version\">"_s, + u"Specify the supported api version used to generate the bindings"_s}, + {u"drop-type-entries=\"<TypeEntry0>[;TypeEntry1;...]\""_s, + u"Semicolon separated list of type system entries (classes, namespaces,\n" + "global functions and enums) to be dropped from generation."_s}, + {u"-T<path>"_s, {} }, + {u"typesystem-paths="_s + OptionsParser::pathSyntax(), + u"Paths used when searching for typesystems"_s}, + {u"force-process-system-include-paths="_s + OptionsParser::pathSyntax(), + u"Include paths that are considered as system headers by the C++ parser, but should still " + "be processed to extract types (e.g. Qt include paths in a yocto sysroot)"_s}, + {u"keywords=keyword1[,keyword2,...]"_s, + u"A comma-separated list of keywords for conditional typesystem parsing"_s}, + }; +} + +struct TypeDatabaseOptions { - const TypeSystemTypeEntry *defaultTypeSystemType() const; - TypeEntry *findType(const QString &name) const; - TypeEntries findCppTypes(const QString &name) const; - bool addType(TypeEntry *e, QString *errorMessage = nullptr); + QStringList m_dropTypeEntries; + QStringList m_forceProcessSystemIncludes; + QStringList m_typesystemKeywords; + QStringList m_typesystemPaths; + bool m_suppressWarnings = true; +}; + +class TypeDatabaseOptionsParser : public OptionsParser +{ +public: + explicit TypeDatabaseOptionsParser(TypeDatabaseOptions *o) : m_options(o) {} + + bool handleBoolOption(const QString &key, OptionSource source) override; + bool handleOption(const QString &key, const QString &value, OptionSource source) override; + +private: + TypeDatabaseOptions *m_options; +}; + +bool TypeDatabaseOptionsParser::handleBoolOption(const QString &key, OptionSource source) +{ + switch (source) { + case OptionSource::CommandLine: + case OptionSource::ProjectFile: + if (key == u"no-suppress-warnings") { + m_options->m_suppressWarnings = false; + return true; + } + break; + case OptionSource::CommandLineSingleDash: + if (key.startsWith(u'T')) { // "-T/path" ends up a bool option + m_options->m_typesystemPaths += key.sliced(1).split(QDir::listSeparator(), + Qt::SkipEmptyParts); + return true; + } + break; + } + return false; +} + +bool TypeDatabaseOptionsParser::handleOption(const QString &key, const QString &value, + OptionSource source) +{ + if (source == OptionSource::CommandLineSingleDash) + return false; + if (key == u"api-version") { + const auto fullVersions = QStringView{value}.split(u'|'); + for (const auto &fullVersion : fullVersions) { + const auto parts = fullVersion.split(u','); + const QString package = parts.size() == 1 + ? u"*"_s : parts.constFirst().toString(); + const QString version = parts.constLast().toString(); + if (!TypeDatabase::setApiVersion(package, version)) + throw Exception(msgInvalidVersion(package, version)); + } + return true; + } + + if (key == u"drop-type-entries") { + m_options->m_dropTypeEntries = value.split(u';'); + m_options->m_dropTypeEntries.sort(); + return true; + } + + if (key == u"keywords") { + m_options->m_typesystemKeywords = value.split(u','); + return true; + } + + if (key == u"typesystem-paths") { + m_options->m_typesystemPaths += value.split(QDir::listSeparator(), + Qt::SkipEmptyParts); + return true; + } + + if (key == u"force-process-system-include-paths") { + m_options->m_forceProcessSystemIncludes += value.split(QDir::listSeparator(), + Qt::SkipEmptyParts); + return true; + } + + if (source == OptionSource::ProjectFile) { + if (key == u"typesystem-path") { + m_options->m_typesystemPaths += value; + return true; + } + } + + return false; +} + +struct TypeDatabasePrivate : public TypeDatabaseOptions +{ + TypeSystemTypeEntryCPtr defaultTypeSystemType() const; + TypeEntryPtr findType(const QString &name) const; + TypeEntryCList findCppTypes(const QString &name) const; + bool addType(TypeEntryPtr e, QString *errorMessage = nullptr); bool parseFile(QIODevice *device, TypeDatabase *db, bool generate = true); static bool parseFile(const TypeDatabaseParserContextPtr &context, QIODevice *device, bool generate = true); @@ -122,58 +240,63 @@ struct TypeDatabasePrivate QString modifiedTypesystemFilepath(const QString& tsFile, const QString ¤tPath) const; - void addBuiltInType(TypeEntry *e); - PrimitiveTypeEntry *addBuiltInPrimitiveType(const QString &name, - const TypeSystemTypeEntry *root, + void addBuiltInType(const TypeEntryPtr &e); + PrimitiveTypeEntryPtr addBuiltInPrimitiveType(const QString &name, + const TypeSystemTypeEntryCPtr &root, const QString &rootPackage, - CustomTypeEntry *targetLang); + const CustomTypeEntryPtr &targetLang); void addBuiltInCppStringPrimitiveType(const QString &name, const QString &viewName, - const TypeSystemTypeEntry *root, + const TypeSystemTypeEntryCPtr &root, const QString &rootPackage, - CustomTypeEntry *targetLang); + const CustomTypeEntryPtr &targetLang); void addBuiltInPrimitiveTypes(); void addBuiltInContainerTypes(const TypeDatabaseParserContextPtr &context); + bool addOpaqueContainers(const TypeDatabaseParserContextPtr &context); TypeEntryMultiMapConstIteratorRange findTypeRange(const QString &name) const; template <class Predicate> - TypeEntries findTypesHelper(const QString &name, Predicate pred) const; + TypeEntryCList findTypesHelper(const QString &name, Predicate pred) const; template <class Type, class Predicate> - QList<const Type *> findTypesByTypeHelper(Predicate pred) const; - TypeEntry *resolveTypeDefEntry(TypedefEntry *typedefEntry, QString *errorMessage); + QList<std::shared_ptr<const Type> > findTypesByTypeHelper(Predicate pred) const; + TypeEntryPtr resolveTypeDefEntry(const TypedefEntryPtr &typedefEntry, QString *errorMessage); template <class String> bool isSuppressedWarningHelper(const String &s) const; bool resolveSmartPointerInstantiations(const TypeDatabaseParserContextPtr &context); void formatDebug(QDebug &d) const; + void formatBuiltinTypes(QDebug &d) const; - bool m_suppressWarnings = true; TypeEntryMultiMap m_entries; // Contains duplicate entries (cf addInlineNamespaceLookups). TypeEntryMap m_flagsEntries; TypedefEntryMap m_typedefEntries; TemplateEntryMap m_templates; - QList<QRegularExpression> m_suppressedWarnings; - QList<const TypeSystemTypeEntry *> m_typeSystemEntries; // maintain order, default is first. + QList<SuppressedWarning> m_suppressedWarnings; + QList<TypeSystemTypeEntryCPtr > m_typeSystemEntries; // maintain order, default is first. AddedFunctionList m_globalUserFunctions; FunctionModificationList m_functionMods; QStringList m_requiredTargetImports; - QStringList m_typesystemPaths; - QStringList m_typesystemKeywords; QHash<QString, bool> m_parsedTypesystemFiles; QList<TypeRejection> m_rejections; - - QStringList m_dropTypeEntries; - QStringList m_systemIncludes; }; +static const char ENV_TYPESYSTEMPATH[] = "TYPESYSTEMPATH"; + TypeDatabase::TypeDatabase() : d(new TypeDatabasePrivate) { - d->addBuiltInType(new VoidTypeEntry()); - d->addBuiltInType(new VarargsTypeEntry()); + // Environment TYPESYSTEMPATH + if (qEnvironmentVariableIsSet(ENV_TYPESYSTEMPATH)) { + d->m_typesystemPaths + += qEnvironmentVariable(ENV_TYPESYSTEMPATH).split(QDir::listSeparator(), + Qt::SkipEmptyParts); + } + + d->addBuiltInType(TypeEntryPtr(new VoidTypeEntry())); + d->addBuiltInType(TypeEntryPtr(new VarargsTypeEntry())); for (const auto &pt : builtinPythonTypes()) - d->addBuiltInType(new PythonTypeEntry(pt.name, pt.checkFunction, pt.type)); + d->addBuiltInType(TypeEntryPtr(new PythonTypeEntry(pt.name, pt.checkFunction, pt.type))); for (const auto &p : predefinedTemplates()) addTemplate(p.name, p.content); @@ -184,7 +307,12 @@ TypeDatabase::~TypeDatabase() delete d; } -TypeDatabase* TypeDatabase::instance(bool newInstance) +std::shared_ptr<OptionsParser> TypeDatabase::createOptionsParser() +{ + return std::make_shared<TypeDatabaseOptionsParser>(d); +} + +TypeDatabase *TypeDatabase::instance(bool newInstance) { static TypeDatabase *db = nullptr; if (!db || newInstance) { @@ -210,12 +338,11 @@ static const IntTypeNormalizationEntries &intTypeNormalizationEntries() static bool firstTime = true; if (firstTime) { firstTime = false; - for (auto t : {"char", "short", "int", "long"}) { - const QString intType = QLatin1StringView(t); + for (const auto &intType : {"char"_L1, "short"_L1, "int"_L1, "long"_L1}) { if (!TypeDatabase::instance()->findType(u'u' + intType)) { IntTypeNormalizationEntry entry; - entry.replacement = QStringLiteral("unsigned ") + intType; - entry.regex.setPattern(QStringLiteral("\\bu") + intType + QStringLiteral("\\b")); + entry.replacement = "unsigned "_L1 + intType; + entry.regex.setPattern("\\bu"_L1 + intType + "\\b"_L1); Q_ASSERT(entry.regex.isValid()); result.append(entry); } @@ -301,26 +428,11 @@ void TypeDatabase::addRequiredTargetImport(const QString& moduleName) d->m_requiredTargetImports << moduleName; } -void TypeDatabase::addTypesystemPath(const QString& typesystem_paths) -{ - #if defined(Q_OS_WIN32) - const char path_splitter = ';'; - #else - const char path_splitter = ':'; - #endif - d->m_typesystemPaths += typesystem_paths.split(QLatin1Char(path_splitter)); -} - -void TypeDatabase::setTypesystemKeywords(const QStringList &keywords) -{ - d->m_typesystemKeywords = keywords; -} - QStringList TypeDatabase::typesystemKeywords() const { QStringList result = d->m_typesystemKeywords; for (const auto &d : d->m_dropTypeEntries) - result.append(QStringLiteral("no_") + d); + result.append("no_"_L1 + d); switch (clang::emulatedCompilerLanguageLevel()) { case LanguageLevel::Cpp11: @@ -343,84 +455,95 @@ QStringList TypeDatabase::typesystemKeywords() const IncludeList TypeDatabase::extraIncludes(const QString& className) const { - ComplexTypeEntry* typeEntry = findComplexType(className); - return typeEntry ? typeEntry->extraIncludes() : IncludeList(); + auto typeEntry = findComplexType(className); + return typeEntry ? typeEntry->extraIncludes() : IncludeList(); } -const QStringList &TypeDatabase::systemIncludes() const +const QStringList &TypeDatabase::forceProcessSystemIncludes() const { - return d->m_systemIncludes; + return d->m_forceProcessSystemIncludes; } -void TypeDatabase::addSystemInclude(const QString &name) +void TypeDatabase::addForceProcessSystemInclude(const QString &name) { - d->m_systemIncludes.append(name); + d->m_forceProcessSystemIncludes.append(name); } // Add a lookup for the short name excluding inline namespaces // so that "std::shared_ptr" finds "std::__1::shared_ptr" as well. -// Note: This inserts duplicate TypeEntry * into m_entries. -void TypeDatabase::addInlineNamespaceLookups(const NamespaceTypeEntry *n) +// Note: This inserts duplicate TypeEntryPtr into m_entries. +void TypeDatabase::addInlineNamespaceLookups(const NamespaceTypeEntryCPtr &n) { TypeEntryList additionalEntries; // Store before modifying the hash - for (TypeEntry *entry : qAsConst(d->m_entries)) { + for (const auto &entry : std::as_const(d->m_entries)) { if (entry->isChildOf(n)) additionalEntries.append(entry); } - for (const auto &ae : qAsConst(additionalEntries)) + for (const auto &ae : std::as_const(additionalEntries)) d->m_entries.insert(ae->shortName(), ae); } -ContainerTypeEntry* TypeDatabase::findContainerType(const QString &name) const +ContainerTypeEntryPtr TypeDatabase::findContainerType(const QString &name) const { QString template_name = name; - int pos = name.indexOf(u'<'); + const auto pos = name.indexOf(u'<'); if (pos > 0) template_name = name.left(pos); - TypeEntry* type_entry = findType(template_name); + auto type_entry = findType(template_name); if (type_entry && type_entry->isContainer()) - return static_cast<ContainerTypeEntry*>(type_entry); - return nullptr; + return std::static_pointer_cast<ContainerTypeEntry>(type_entry); + return {}; } -static bool inline useType(const TypeEntry *t) +static bool inline useType(const TypeEntryCPtr &t) { return !t->isPrimitive() - || static_cast<const PrimitiveTypeEntry *>(t)->preferredTargetLangType(); + || std::static_pointer_cast<const PrimitiveTypeEntry>(t)->preferredTargetLangType(); } -FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const +FunctionTypeEntryPtr TypeDatabase::findFunctionType(const QString &name) const { const auto entries = d->findTypeRange(name); - for (TypeEntry *entry : entries) { + for (const TypeEntryPtr &entry : entries) { if (entry->type() == TypeEntry::FunctionType && useType(entry)) - return static_cast<FunctionTypeEntry*>(entry); + return std::static_pointer_cast<FunctionTypeEntry>(entry); } - return nullptr; + return {}; } -void TypeDatabase::addTypeSystemType(const TypeSystemTypeEntry *e) +void TypeDatabase::addTypeSystemType(const TypeSystemTypeEntryCPtr &e) { d->m_typeSystemEntries.append(e); } -const TypeSystemTypeEntry *TypeDatabase::findTypeSystemType(const QString &name) const +TypeSystemTypeEntryCPtr TypeDatabase::findTypeSystemType(const QString &name) const { for (auto entry : d->m_typeSystemEntries) { if (entry->name() == name) return entry; } - return nullptr; + return {}; } -const TypeSystemTypeEntry *TypeDatabase::defaultTypeSystemType() const +TypeSystemTypeEntryCPtr TypeDatabase::defaultTypeSystemType() const { return d->defaultTypeSystemType(); } -const TypeSystemTypeEntry *TypeDatabasePrivate::defaultTypeSystemType() const +QString TypeDatabase::loadedTypeSystemNames() const +{ + QString result; + for (const auto &entry : d->m_typeSystemEntries) { + if (!result.isEmpty()) + result += u", "_s; + result += entry->name(); + } + return result; +} + +TypeSystemTypeEntryCPtr TypeDatabasePrivate::defaultTypeSystemType() const { return m_typeSystemEntries.value(0, nullptr); } @@ -431,27 +554,27 @@ QString TypeDatabase::defaultPackageName() const return d->m_typeSystemEntries.constFirst()->name(); } -TypeEntry* TypeDatabase::findType(const QString& name) const +TypeEntryPtr TypeDatabase::findType(const QString& name) const { return d->findType(name); } -TypeEntry* TypeDatabasePrivate::findType(const QString& name) const +TypeEntryPtr TypeDatabasePrivate::findType(const QString& name) const { const auto entries = findTypeRange(name); - for (TypeEntry *entry : entries) { + for (const auto &entry : entries) { if (useType(entry)) return entry; } - return nullptr; + return {}; } template <class Predicate> -TypeEntries TypeDatabasePrivate::findTypesHelper(const QString &name, Predicate pred) const +TypeEntryCList TypeDatabasePrivate::findTypesHelper(const QString &name, Predicate pred) const { - TypeEntries result; + TypeEntryCList result; const auto entries = findTypeRange(name); - for (TypeEntry *entry : entries) { + for (const auto &entry : entries) { if (pred(entry)) result.append(entry); } @@ -459,22 +582,22 @@ TypeEntries TypeDatabasePrivate::findTypesHelper(const QString &name, Predicate } template<class Type, class Predicate> -QList<const Type *> TypeDatabasePrivate::findTypesByTypeHelper(Predicate pred) const +QList<std::shared_ptr<const Type> > TypeDatabasePrivate::findTypesByTypeHelper(Predicate pred) const { - QList<const Type *> result; - for (auto *entry : m_entries) { + QList<std::shared_ptr<const Type> > result; + for (const auto &entry : m_entries) { if (pred(entry)) - result.append(static_cast<const Type *>(entry)); + result.append(std::static_pointer_cast<const Type>(entry)); } return result; } -TypeEntries TypeDatabase::findTypes(const QString &name) const +TypeEntryCList TypeDatabase::findTypes(const QString &name) const { return d->findTypesHelper(name, useType); } -static bool useCppType(const TypeEntry *t) +static bool useCppType(const TypeEntryCPtr &t) { bool result = false; switch (t->type()) { @@ -498,12 +621,12 @@ static bool useCppType(const TypeEntry *t) return result; } -TypeEntries TypeDatabase::findCppTypes(const QString &name) const +TypeEntryCList TypeDatabase::findCppTypes(const QString &name) const { return d->findCppTypes(name); } -TypeEntries TypeDatabasePrivate::findCppTypes(const QString &name) const +TypeEntryCList TypeDatabasePrivate::findCppTypes(const QString &name) const { return findTypesHelper(name, useCppType); } @@ -524,21 +647,21 @@ TypeEntryMultiMapConstIteratorRange TypeDatabasePrivate::findTypeRange(const QSt return {range.first, range.second}; } -PrimitiveTypeEntryList TypeDatabase::primitiveTypes() const +PrimitiveTypeEntryCList TypeDatabase::primitiveTypes() const { - auto pred = [](const TypeEntry *t) { return t->isPrimitive(); }; + auto pred = [](const TypeEntryCPtr &t) { return t->isPrimitive(); }; return d->findTypesByTypeHelper<PrimitiveTypeEntry>(pred); } -ContainerTypeEntryList TypeDatabase::containerTypes() const +ContainerTypeEntryCList TypeDatabase::containerTypes() const { - auto pred = [](const TypeEntry *t) { return t->isContainer(); }; + auto pred = [](const TypeEntryCPtr &t) { return t->isContainer(); }; return d->findTypesByTypeHelper<ContainerTypeEntry>(pred); } SmartPointerTypeEntryList TypeDatabase::smartPointerTypes() const { - auto pred = [](const TypeEntry *t) { return t->isSmartPointer(); }; + auto pred = [](const TypeEntryCPtr &t) { return t->isSmartPointer(); }; return d->findTypesByTypeHelper<SmartPointerTypeEntry>(pred); } @@ -564,6 +687,7 @@ bool TypeDatabase::isClassRejected(const QString& className, QString *reason) co { for (const TypeRejection& r : d->m_rejections) { if (r.matchType == TypeRejection::ExcludeClass && r.className.match(className).hasMatch()) { + r.matched = true; if (reason) *reason = msgRejectReason(r); return true; @@ -582,6 +706,7 @@ static bool findRejection(const QList<TypeRejection> &rejections, for (const TypeRejection& r : rejections) { if (r.matchType == matchType && r.pattern.match(name).hasMatch() && r.className.match(className).hasMatch()) { + r.matched = true; if (reason) *reason = msgRejectReason(r, name); return true; @@ -595,21 +720,21 @@ bool TypeDatabase::isEnumRejected(const QString& className, const QString& enumN return findRejection(d->m_rejections, TypeRejection::Enum, className, enumName, reason); } -TypeEntry *TypeDatabasePrivate::resolveTypeDefEntry(TypedefEntry *typedefEntry, +TypeEntryPtr TypeDatabasePrivate::resolveTypeDefEntry(const TypedefEntryPtr &typedefEntry, QString *errorMessage) { QString sourceName = typedefEntry->sourceType(); - const int lessThanPos = sourceName.indexOf(u'<'); + const auto lessThanPos = sourceName.indexOf(u'<'); if (lessThanPos != -1) sourceName.truncate(lessThanPos); - ComplexTypeEntry *source = nullptr; - for (TypeEntry *e : findTypeRange(sourceName)) { + ComplexTypeEntryPtr source; + for (const auto &e : findTypeRange(sourceName)) { switch (e->type()) { case TypeEntry::BasicValueType: case TypeEntry::ContainerType: case TypeEntry::ObjectType: case TypeEntry::SmartPointerType: - source = dynamic_cast<ComplexTypeEntry *>(e); + source = std::dynamic_pointer_cast<ComplexTypeEntry>(e); Q_ASSERT(source); break; default: @@ -618,8 +743,7 @@ TypeEntry *TypeDatabasePrivate::resolveTypeDefEntry(TypedefEntry *typedefEntry, } if (!source) { if (errorMessage) - *errorMessage = u"Unable to resolve typedef \""_s - + typedefEntry->sourceType() + u'"'; + *errorMessage = msgUnableToResolveTypedef(typedefEntry->sourceType(), sourceName); return nullptr; } @@ -627,26 +751,26 @@ TypeEntry *TypeDatabasePrivate::resolveTypeDefEntry(TypedefEntry *typedefEntry, return TypeDatabase::initializeTypeDefEntry(typedefEntry, source); } -ComplexTypeEntry * - TypeDatabase::initializeTypeDefEntry(TypedefEntry *typedefEntry, - const ComplexTypeEntry *source) +ComplexTypeEntryPtr + TypeDatabase::initializeTypeDefEntry(const TypedefEntryPtr &typedefEntry, + const ComplexTypeEntryCPtr &source) { - auto *result = static_cast<ComplexTypeEntry *>(source->clone()); + ComplexTypeEntryPtr result(static_cast<ComplexTypeEntry *>(source->clone())); result->useAsTypedef(typedefEntry); typedefEntry->setSource(source); typedefEntry->setTarget(result); return result; } -bool TypeDatabase::addType(TypeEntry *e, QString *errorMessage) +bool TypeDatabase::addType(const TypeEntryPtr &e, QString *errorMessage) { return d->addType(e, errorMessage); } -bool TypeDatabasePrivate::addType(TypeEntry *e, QString *errorMessage) +bool TypeDatabasePrivate::addType(TypeEntryPtr e, QString *errorMessage) { if (e->type() == TypeEntry::TypedefType) { - e = resolveTypeDefEntry(static_cast<TypedefEntry *>(e), errorMessage); + e = resolveTypeDefEntry(std::static_pointer_cast<TypedefEntry>(e), errorMessage); if (Q_UNLIKELY(!e)) return false; } @@ -655,11 +779,11 @@ bool TypeDatabasePrivate::addType(TypeEntry *e, QString *errorMessage) } // Add a dummy value entry for non-type template parameters -ConstantValueTypeEntry * +ConstantValueTypeEntryPtr TypeDatabase::addConstantValueTypeEntry(const QString &value, - const TypeEntry *parent) + const TypeEntryCPtr &parent) { - auto result = new ConstantValueTypeEntry(value, parent); + auto result = std::make_shared<ConstantValueTypeEntry>(value, parent); result->setCodeGeneration(TypeEntry::GenerateNothing); addType(result); return result; @@ -689,9 +813,9 @@ bool TypeDatabase::isReturnTypeRejected(const QString& className, const QString& return findRejection(d->m_rejections, TypeRejection::ReturnType, className, typeName, reason); } -FlagsTypeEntry* TypeDatabase::findFlagsType(const QString &name) const +FlagsTypeEntryPtr TypeDatabase::findFlagsType(const QString &name) const { - TypeEntry *fte = findType(name); + TypeEntryPtr fte = findType(name); if (!fte) { fte = d->m_flagsEntries.value(name); if (!fte) { @@ -705,27 +829,27 @@ FlagsTypeEntry* TypeDatabase::findFlagsType(const QString &name) const } } } - return static_cast<FlagsTypeEntry *>(fte); + return std::static_pointer_cast<FlagsTypeEntry>(fte); } -void TypeDatabase::addFlagsType(FlagsTypeEntry *fte) +void TypeDatabase::addFlagsType(const FlagsTypeEntryPtr &fte) { d->m_flagsEntries[fte->originalName()] = fte; } -TemplateEntry *TypeDatabase::findTemplate(const QString &name) const +TemplateEntryPtr TypeDatabase::findTemplate(const QString &name) const { return d->m_templates[name]; } -void TypeDatabase::addTemplate(TemplateEntry *t) +void TypeDatabase::addTemplate(const TemplateEntryPtr &t) { d->m_templates[t->name()] = t; } void TypeDatabase::addTemplate(const QString &name, const QString &code) { - auto *te = new TemplateEntry(name); + auto te = std::make_shared<TemplateEntry>(name); te->addCode(code); addTemplate(te); } @@ -755,37 +879,34 @@ void TypeDatabase::addGlobalUserFunctionModifications(const FunctionModification d->m_functionMods << functionModifications; } -QString TypeDatabase::globalNamespaceClassName(const TypeEntry * /*entry*/) +QString TypeDatabase::globalNamespaceClassName(const TypeEntryCPtr & /*entry*/) { return u"Global"_s; } -FunctionModificationList TypeDatabase::functionModifications(const QString& signature) const +FunctionModificationList + TypeDatabase::globalFunctionModifications(const QStringList &signatures) const { FunctionModificationList lst; for (const auto &mod : d->m_functionMods) { - if (mod.matches(signature)) + if (mod.matches(signatures)) lst << mod; } return lst; } -void TypeDatabase::setSuppressWarnings(bool on) -{ - d->m_suppressWarnings = on; -} - -bool TypeDatabase::addSuppressedWarning(const QString &warning, QString *errorMessage) +bool TypeDatabase::addSuppressedWarning(const QString &warning, bool generate, + QString *errorMessage) { QString pattern; if (warning.startsWith(u'^') && warning.endsWith(u'$')) { pattern = warning; } else { // Legacy syntax: Use wildcards '*' (unless escaped by '\') - QList<int> asteriskPositions; - const int warningSize = warning.size(); - for (int i = 0; i < warningSize; ++i) { + QList<qsizetype> asteriskPositions; + const auto warningSize = warning.size(); + for (qsizetype i = 0, warningSize = warning.size(); i < warningSize; ++i) { if (warning.at(i) == u'\\') ++i; else if (warning.at(i) == u'*') @@ -794,11 +915,11 @@ bool TypeDatabase::addSuppressedWarning(const QString &warning, QString *errorMe asteriskPositions.append(warningSize); pattern.append(u'^'); - int lastPos = 0; - for (int a = 0, aSize = asteriskPositions.size(); a < aSize; ++a) { + qsizetype lastPos = 0; + for (qsizetype a = 0, aSize = asteriskPositions.size(); a < aSize; ++a) { if (a) - pattern.append(QStringLiteral(".*")); - const int nextPos = asteriskPositions.at(a); + pattern.append(".*"_L1); + const auto nextPos = asteriskPositions.at(a); if (nextPos > lastPos) pattern.append(QRegularExpression::escape(warning.mid(lastPos, nextPos - lastPos))); lastPos = nextPos + 1; @@ -814,7 +935,7 @@ bool TypeDatabase::addSuppressedWarning(const QString &warning, QString *errorMe } expression.setPatternOptions(expression.patternOptions() | QRegularExpression::MultilineOption); - d->m_suppressedWarnings.append(expression); + d->m_suppressedWarnings.append({expression, warning, generate}); return true; } @@ -822,10 +943,14 @@ bool TypeDatabase::isSuppressedWarning(QStringView s) const { if (!d->m_suppressWarnings) return false; - return std::any_of(d->m_suppressedWarnings.cbegin(), d->m_suppressedWarnings.cend(), - [&s] (const QRegularExpression &e) { - return e.match(s).hasMatch(); - }); + auto wit = std::find_if(d->m_suppressedWarnings.cbegin(), d->m_suppressedWarnings.cend(), + [&s] (const SuppressedWarning &e) { + return e.pattern.matchView(s).hasMatch(); + }); + const bool found = wit != d->m_suppressedWarnings.cend(); + if (found) + wit->matched = true; + return found; } QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile, const QString ¤tPath) const @@ -833,6 +958,27 @@ QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile, const QS return d->modifiedTypesystemFilepath(tsFile, currentPath); } +void TypeDatabase::logUnmatched() const +{ + for (auto &sw : d->m_suppressedWarnings) { + if (sw.generate && !sw.matched) + qWarning("Unmatched suppressed warning: \"%s\"", qPrintable(sw.rawText)); + } + + for (auto &tr : d->m_rejections) { + if (tr.generate && !tr.matched) { + QDebug d = qWarning(); + d.noquote(); + d.nospace(); + d << "Unmatched rejection: " << tr.matchType; + if (!tr.className.pattern().isEmpty()) + d << " class " << tr.className.pattern(); + if (!tr.pattern.pattern().isEmpty()) + d << " \"" << tr.pattern.pattern() << '"'; + } + } +} + QString TypeDatabasePrivate::modifiedTypesystemFilepath(const QString& tsFile, const QString ¤tPath) const { @@ -858,16 +1004,25 @@ void TypeDatabasePrivate::addBuiltInContainerTypes(const TypeDatabaseParserConte { // Unless the user has added the standard containers (potentially with // some opaque types), add them by default. + const bool hasStdArray = findType(u"std::array"_s) != nullptr; const bool hasStdPair = findType(u"std::pair"_s) != nullptr; const bool hasStdList = findType(u"std::list"_s) != nullptr; const bool hasStdVector = findType(u"std::vector"_s) != nullptr; const bool hasStdMap = findType(u"std::map"_s) != nullptr; const bool hasStdUnorderedMap = findType(u"std::unordered_map"_s) != nullptr; + const bool hasStdSpan = findType(u"std::span"_s) != nullptr; if (hasStdPair && hasStdList && hasStdVector && hasStdMap && hasStdUnorderedMap) return; QByteArray ts = R"(<?xml version="1.0" encoding="UTF-8"?><typesystem>)"; + if (!hasStdArray) { + ts += containerTypeSystemSnippet( + "std::array", "list", "array", + "shiboken_conversion_cppsequence_to_pylist", + "PySequence", + "shiboken_conversion_pyiterable_to_cpparray"); + } if (!hasStdPair) { ts += containerTypeSystemSnippet( "std::pair", "pair", "utility", @@ -900,6 +1055,16 @@ void TypeDatabasePrivate::addBuiltInContainerTypes(const TypeDatabaseParserConte "shiboken_conversion_stdmap_to_pydict", "PyDict", "shiboken_conversion_pydict_to_stdmap"); } + if (!hasStdSpan + && clang::emulatedCompilerLanguageLevel() >= LanguageLevel::Cpp20) { + auto spanSnip = containerTypeSystemSnippet( + "std::span", "span", "span", + "shiboken_conversion_cppsequence_to_pylist"); + auto pos = spanSnip.indexOf('>'); + spanSnip.insert(pos, R"( view-on="std::vector")"); + ts += spanSnip; + } + ts += "</typesystem>"; QBuffer buffer(&ts); buffer.open(QIODevice::ReadOnly); @@ -907,6 +1072,22 @@ void TypeDatabasePrivate::addBuiltInContainerTypes(const TypeDatabaseParserConte Q_ASSERT(ok); } +bool TypeDatabasePrivate::addOpaqueContainers(const TypeDatabaseParserContextPtr &context) +{ + const auto &och = context->opaqueContainerHash; + for (auto it = och.cbegin(), end = och.cend(); it != end; ++it) { + const QString &name = it.key(); + auto te = findType(name); + if (!te || !te->isContainer()) { + qCWarning(lcShiboken, "No container \"%s\" found.", qPrintable(name)); + return false; + } + auto cte = std::static_pointer_cast<ContainerTypeEntry>(te); + cte->appendOpaqueContainers(it.value()); + } + return true; +} + bool TypeDatabase::parseFile(const QString &filename, bool generate) { QString filepath = modifiedTypesystemFilepath(filename, {}); @@ -963,14 +1144,14 @@ bool TypeDatabasePrivate::parseFile(const TypeDatabaseParserContextPtr &context, return ok; } -bool TypeDatabase::parseFile(QIODevice* device, bool generate) +bool TypeDatabase::parseFile(QIODevice *device, bool generate) { return d->parseFile(device, this, generate); } -bool TypeDatabasePrivate::parseFile(QIODevice* device, TypeDatabase *db, bool generate) +bool TypeDatabasePrivate::parseFile(QIODevice *device, TypeDatabase *db, bool generate) { - const TypeDatabaseParserContextPtr context(new TypeDatabaseParserContext); + const auto context = std::make_shared<TypeDatabaseParserContext>(); context->db = db; if (!parseFile(context, device, generate)) @@ -978,7 +1159,8 @@ bool TypeDatabasePrivate::parseFile(QIODevice* device, TypeDatabase *db, bool ge addBuiltInPrimitiveTypes(); addBuiltInContainerTypes(context); - return resolveSmartPointerInstantiations(context); + return addOpaqueContainers(context) + && resolveSmartPointerInstantiations(context); } bool TypeDatabase::parseFile(const TypeDatabaseParserContextPtr &context, @@ -1007,9 +1189,9 @@ static QStringList splitTypeList(const QString &s) { QStringList result; int templateDepth = 0; - int lastPos = 0; - const int size = s.size(); - for (int i = 0; i < size; ++i) { + qsizetype lastPos = 0; + const auto size = s.size(); + for (qsizetype i = 0; i < size; ++i) { switch (s.at(i).toLatin1()) { case '<': ++templateDepth; @@ -1038,32 +1220,40 @@ bool TypeDatabasePrivate::resolveSmartPointerInstantiations(const TypeDatabasePa const auto instantiationNames = splitTypeList(it.value()); SmartPointerTypeEntry::Instantiations instantiations; instantiations.reserve(instantiationNames.size()); - for (const auto &instantiationName : instantiationNames) { - const auto types = findCppTypes(instantiationName); - if (types.isEmpty()) { - const QString m = msgCannotFindTypeEntryForSmartPointer(instantiationName, + for (const auto &instantiation : instantiationNames) { + QString name; + QString type = instantiation; + const auto equalsPos = instantiation.indexOf(u'='); + if (equalsPos != -1) { + type.truncate(equalsPos); + name = instantiation.mid(equalsPos + 1); + } + + const auto typeEntries = findCppTypes(type); + if (typeEntries.isEmpty()) { + const QString m = msgCannotFindTypeEntryForSmartPointer(type, smartPointerEntry->name()); qCWarning(lcShiboken, "%s", qPrintable(m)); return false; } - if (types.size() > 1) { - const QString m = msgAmbiguousTypesFound(instantiationName, types); + if (typeEntries.size() > 1) { + const QString m = msgAmbiguousTypesFound(type, typeEntries); qCWarning(lcShiboken, "%s", qPrintable(m)); return false; } - instantiations.append(types.constFirst()); + instantiations.append({name, typeEntries.constFirst()}); } smartPointerEntry->setInstantiations(instantiations); } return true; } -PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const +PrimitiveTypeEntryPtr TypeDatabase::findPrimitiveType(const QString& name) const { const auto entries = d->findTypeRange(name); - for (TypeEntry *entry : entries) { + for (const auto &entry : entries) { if (entry->isPrimitive()) { - auto *pe = static_cast<PrimitiveTypeEntry *>(entry); + auto pe = std::static_pointer_cast<PrimitiveTypeEntry>(entry); if (pe->preferredTargetLangType()) return pe; } @@ -1072,22 +1262,22 @@ PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const return nullptr; } -ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const +ComplexTypeEntryPtr TypeDatabase::findComplexType(const QString& name) const { const auto entries = d->findTypeRange(name); - for (TypeEntry *entry : entries) { + for (const auto &entry : entries) { if (entry->isComplex() && useType(entry)) - return static_cast<ComplexTypeEntry*>(entry); + return std::static_pointer_cast<ComplexTypeEntry>(entry); } return nullptr; } -ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const +ObjectTypeEntryPtr TypeDatabase::findObjectType(const QString& name) const { const auto entries = d->findTypeRange(name); - for (TypeEntry *entry : entries) { + for (const auto &entry : entries) { if (entry && entry->isObject() && useType(entry)) - return static_cast<ObjectTypeEntry*>(entry); + return std::static_pointer_cast<ObjectTypeEntry>(entry); } return nullptr; } @@ -1096,25 +1286,25 @@ NamespaceTypeEntryList TypeDatabase::findNamespaceTypes(const QString& name) con { NamespaceTypeEntryList result; const auto entries = d->findTypeRange(name); - for (TypeEntry *entry : entries) { + for (const auto &entry : entries) { if (entry->isNamespace()) - result.append(static_cast<NamespaceTypeEntry*>(entry)); + result.append(std::static_pointer_cast<NamespaceTypeEntry>(entry)); } return result; } -NamespaceTypeEntry *TypeDatabase::findNamespaceType(const QString& name, +NamespaceTypeEntryPtr TypeDatabase::findNamespaceType(const QString& name, const QString &fileName) const { const auto entries = findNamespaceTypes(name); // Preferably check on matching file name first, if a pattern was given. if (!fileName.isEmpty()) { - for (NamespaceTypeEntry *entry : entries) { + for (const auto &entry : entries) { if (entry->hasPattern() && entry->matchesFile(fileName)) return entry; } } - for (NamespaceTypeEntry *entry : entries) { + for (const auto &entry : entries) { if (!entry->hasPattern()) return entry; } @@ -1126,7 +1316,7 @@ bool TypeDatabase::shouldDropTypeEntry(const QString& fullTypeName) const return d->m_dropTypeEntries.contains(fullTypeName); } -void TypeDatabase::setDropTypeEntries(QStringList dropTypeEntries) +void TypeDatabase::setDropTypeEntries(const QStringList &dropTypeEntries) { d->m_dropTypeEntries = dropTypeEntries; d->m_dropTypeEntries.sort(); @@ -1135,7 +1325,7 @@ void TypeDatabase::setDropTypeEntries(QStringList dropTypeEntries) static bool computeTypeIndexes = true; static int maxTypeIndex; -static bool typeEntryLessThan(const TypeEntry* t1, const TypeEntry* t2) +static bool typeEntryLessThan(const TypeEntryCPtr &t1, const TypeEntryCPtr &t2) { if (t1->revision() < t2->revision()) return true; @@ -1145,7 +1335,7 @@ static bool typeEntryLessThan(const TypeEntry* t1, const TypeEntry* t2) static void _computeTypeIndexes() { - TypeDatabase* tdb = TypeDatabase::instance(); + auto *tdb = TypeDatabase::instance(); TypeEntryList list; @@ -1153,7 +1343,7 @@ static void _computeTypeIndexes() const auto &allEntries = tdb->entries(); list.reserve(allEntries.size()); for (auto tit = allEntries.cbegin(), end = allEntries.cend(); tit != end; ++tit) { - TypeEntry *entry = tit.value(); + const TypeEntryPtr &entry = tit.value(); if (entry->isPrimitive() || entry->isContainer() || entry->isFunction() @@ -1172,7 +1362,7 @@ static void _computeTypeIndexes() std::sort(list.begin(), list.end(), typeEntryLessThan); maxTypeIndex = 0; - for (TypeEntry *e : qAsConst(list)) + for (const TypeEntryPtr &e : std::as_const(list)) e->setSbkIndex(maxTypeIndex++); computeTypeIndexes = false; } @@ -1209,7 +1399,7 @@ bool TypeDatabase::setApiVersion(const QString& packageWildcardPattern, const QS if (versionNumber.isNull()) return false; ApiVersions &versions = *apiVersions(); - for (int i = 0, size = versions.size(); i < size; ++i) { + for (qsizetype i = 0, size = versions.size(); i < size; ++i) { if (versions.at(i).first.pattern() == packagePattern) { versions[i].second = versionNumber; return true; @@ -1218,7 +1408,7 @@ bool TypeDatabase::setApiVersion(const QString& packageWildcardPattern, const QS const QRegularExpression packageRegex(packagePattern); if (!packageRegex.isValid()) return false; - versions.append(qMakePair(packageRegex, versionNumber)); + versions.append(std::make_pair(packageRegex, versionNumber)); return true; } @@ -1228,7 +1418,7 @@ bool TypeDatabase::checkApiVersion(const QString &package, const ApiVersions &versions = *apiVersions(); if (versions.isEmpty()) // Nothing specified: use latest. return true; - for (int i = 0, size = versions.size(); i < size; ++i) { + for (qsizetype i = 0, size = versions.size(); i < size; ++i) { if (versions.at(i).first.match(package).hasMatch()) return versions.at(i).second >= vr.since && versions.at(i).second <= vr.until; @@ -1242,21 +1432,6 @@ bool TypeDatabase::hasDroppedTypeEntries() const } #ifndef QT_NO_DEBUG_STREAM - -template <class Container, class Separator> -static void formatList(QDebug &d, const char *name, const Container &c, Separator sep) -{ - if (const int size = c.size()) { - d << ", " << name << '[' << size << "]=("; - for (int i = 0; i < size; ++i) { - if (i) - d << sep; - d << c.at(i); - } - d << ')'; - } -} - void TypeDatabase::formatDebug(QDebug &debug) const { d->formatDebug(debug); @@ -1299,23 +1474,109 @@ void TypeDatabasePrivate::formatDebug(QDebug &d) const d << ")\n"; } d <<"\nglobalUserFunctions=" << m_globalUserFunctions << '\n'; - formatList(d, "globalFunctionMods", m_functionMods, '\n'); + formatList(d, "globalFunctionMods", m_functionMods, "\n"); d << ')'; } -void TypeDatabasePrivate::addBuiltInType(TypeEntry *e) +// Helpers for dumping out primitive type info + +struct formatPrimitiveEntry +{ + explicit formatPrimitiveEntry(const PrimitiveTypeEntryCPtr &e) : m_pe(e) {} + + PrimitiveTypeEntryCPtr m_pe; +}; + +QDebug operator<<(QDebug debug, const formatPrimitiveEntry &fe) +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + const QString &name = fe.m_pe->name(); + const QString &targetLangName = fe.m_pe->targetLangApiName(); + debug << '"' << name << '"'; + if (name != targetLangName) + debug << " (\"" << targetLangName << "\")"; + if (fe.m_pe->isBuiltIn()) + debug << " [builtin]"; + if (isExtendedCppPrimitive(fe.m_pe)) { + debug << " ["; + if (!isCppPrimitive(fe.m_pe)) + debug << "extended "; + debug << "C++]"; + } + return debug; +} + +// Sort primitive types for displaying; base type and typedef'ed types +struct PrimitiveFormatListEntry +{ + PrimitiveTypeEntryCPtr baseType; + PrimitiveTypeEntryCList typedefs; +}; + +static bool operator<(const PrimitiveFormatListEntry &e1, const PrimitiveFormatListEntry &e2) +{ + return e1.baseType->name() < e2.baseType->name(); +} + +using PrimitiveFormatListEntries = QList<PrimitiveFormatListEntry>; + +static qsizetype indexOf(const PrimitiveFormatListEntries &e, const PrimitiveTypeEntryCPtr &needle) +{ + for (qsizetype i = 0, size = e.size(); i < size; ++i) { + if (e.at(i).baseType == needle) + return i; + } + return -1; +} + +void TypeDatabase::formatBuiltinTypes(QDebug debug) const +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + + // Determine base types and their typedef'ed types + QList<PrimitiveFormatListEntry> primitiveEntries; + for (const auto &e : std::as_const(d->m_entries)) { + if (e->isPrimitive()) { + auto pe = std::static_pointer_cast<const PrimitiveTypeEntry>(e); + auto basic = basicReferencedTypeEntry(pe); + if (basic != pe) { + const auto idx = indexOf(primitiveEntries, basic); + if (idx != -1) + primitiveEntries[idx].typedefs.append(pe); + else + primitiveEntries.append(PrimitiveFormatListEntry{basic, {pe}}); + } else { + primitiveEntries.append(PrimitiveFormatListEntry{pe, {}}); + } + } + } + + std::sort(primitiveEntries.begin(), primitiveEntries.end()); + + for (const auto &e : std::as_const(primitiveEntries)) { + debug << "Primitive: " << formatPrimitiveEntry(e.baseType) << '\n'; + for (const auto &pe : e.typedefs) + debug << " " << formatPrimitiveEntry(pe) << '\n'; + } +} + +void TypeDatabasePrivate::addBuiltInType(const TypeEntryPtr &e) { e->setBuiltIn(true); addType(e); } -PrimitiveTypeEntry * +PrimitiveTypeEntryPtr TypeDatabasePrivate::addBuiltInPrimitiveType(const QString &name, - const TypeSystemTypeEntry *root, + const TypeSystemTypeEntryCPtr &root, const QString &rootPackage, - CustomTypeEntry *targetLang) + const CustomTypeEntryPtr &targetLang) { - auto *result = new PrimitiveTypeEntry(name, {}, root); + auto result = std::make_shared<PrimitiveTypeEntry>(name, QVersionNumber{}, root); result->setTargetLangApiType(targetLang); result->setTargetLangPackage(rootPackage); addBuiltInType(result); @@ -1324,37 +1585,37 @@ PrimitiveTypeEntry * void TypeDatabasePrivate::addBuiltInCppStringPrimitiveType(const QString &name, const QString &viewName, - const TypeSystemTypeEntry *root, + const TypeSystemTypeEntryCPtr &root, const QString &rootPackage, - CustomTypeEntry *targetLang) + const CustomTypeEntryPtr &targetLang) { - auto *stringType = addBuiltInPrimitiveType(name, root, rootPackage, - targetLang); - auto *viewType = addBuiltInPrimitiveType(viewName, root, rootPackage, - nullptr); + auto stringType = addBuiltInPrimitiveType(name, root, rootPackage, + targetLang); + auto viewType = addBuiltInPrimitiveType(viewName, root, rootPackage, + nullptr); viewType->setViewOn(stringType); } void TypeDatabasePrivate::addBuiltInPrimitiveTypes() { - auto *root = defaultTypeSystemType(); + auto root = defaultTypeSystemType(); const QString &rootPackage = root->name(); // C++ primitive types - auto *pyLongEntry = findType(u"PyLong"_s); + auto pyLongEntry = findType(u"PyLong"_s); Q_ASSERT(pyLongEntry && pyLongEntry->isCustom()); - auto *pyLongCustomEntry = static_cast<CustomTypeEntry *>(pyLongEntry); - auto *pyBoolEntry = findType(u"PyBool"_s); + auto pyLongCustomEntry = std::static_pointer_cast<CustomTypeEntry>(pyLongEntry); + auto pyBoolEntry = findType(u"PyBool"_s); Q_ASSERT(pyBoolEntry && pyBoolEntry->isCustom()); - auto *sbkCharEntry = findType(u"SbkChar"_s); + auto sbkCharEntry = findType(u"SbkChar"_s); Q_ASSERT(sbkCharEntry && sbkCharEntry->isCustom()); - auto *sbkCharCustomEntry = static_cast<CustomTypeEntry *>(sbkCharEntry); + auto sbkCharCustomEntry = std::static_pointer_cast<CustomTypeEntry>(sbkCharEntry); - auto *pyBoolCustomEntry = static_cast<CustomTypeEntry *>(pyBoolEntry); + auto pyBoolCustomEntry = std::static_pointer_cast<CustomTypeEntry>(pyBoolEntry); for (const auto &t : AbstractMetaType::cppIntegralTypes()) { if (!m_entries.contains(t)) { - CustomTypeEntry *targetLangApi = pyLongCustomEntry; + CustomTypeEntryPtr targetLangApi = pyLongCustomEntry; if (t == u"bool") targetLangApi = pyBoolCustomEntry; else if (AbstractMetaType::cppCharTypes().contains(t)) @@ -1363,25 +1624,25 @@ void TypeDatabasePrivate::addBuiltInPrimitiveTypes() } } - auto *pyFloatEntry = findType(u"PyFloat"_s); + auto pyFloatEntry = findType(u"PyFloat"_s); Q_ASSERT(pyFloatEntry && pyFloatEntry->isCustom()); - auto *pyFloatCustomEntry = static_cast<CustomTypeEntry *>(pyFloatEntry); + auto pyFloatCustomEntry = std::static_pointer_cast<CustomTypeEntry>(pyFloatEntry); for (const auto &t : AbstractMetaType::cppFloatTypes()) { if (!m_entries.contains(t)) addBuiltInPrimitiveType(t, root, rootPackage, pyFloatCustomEntry); } - auto *pyUnicodeEntry = findType(u"PyUnicode"_s); + auto pyUnicodeEntry = findType(u"PyUnicode"_s); Q_ASSERT(pyUnicodeEntry && pyUnicodeEntry->isCustom()); - auto *pyUnicodeCustomEntry = static_cast<CustomTypeEntry *>(pyUnicodeEntry); + auto pyUnicodeCustomEntry = std::static_pointer_cast<CustomTypeEntry>(pyUnicodeEntry); - const QString stdString = u"std::string"_s; + constexpr auto stdString = "std::string"_L1; if (!m_entries.contains(stdString)) { addBuiltInCppStringPrimitiveType(stdString, u"std::string_view"_s, root, rootPackage, pyUnicodeCustomEntry); } - const QString stdWString = u"std::wstring"_s; + constexpr auto stdWString = "std::wstring"_L1; if (!m_entries.contains(stdWString)) { addBuiltInCppStringPrimitiveType(stdWString, u"std::wstring_view"_s, root, rootPackage, diff --git a/sources/shiboken6/ApiExtractor/typedatabase.h b/sources/shiboken6/ApiExtractor/typedatabase.h index 0ea7097be..d5adca324 100644 --- a/sources/shiboken6/ApiExtractor/typedatabase.h +++ b/sources/shiboken6/ApiExtractor/typedatabase.h @@ -5,26 +5,19 @@ #define TYPEDATABASE_H #include "include.h" +#include "modifications_typedefs.h" #include "typedatabase_typedefs.h" -#include "typesystem_enums.h" -#include "typesystem_typedefs.h" #include <QtCore/QRegularExpression> #include <QtCore/QStringList> #include <QtCore/QVersionNumber> -#include <QtCore/QSharedPointer> -QT_FORWARD_DECLARE_CLASS(QIODevice) +#include <memory> -class ComplexTypeEntry; -class ContainerTypeEntry; -class FlagsTypeEntry; -class FunctionTypeEntry; -class NamespaceTypeEntry; -class ObjectTypeEntry; -class TemplateEntry; -class TypeEntry; +QT_FORWARD_DECLARE_CLASS(QIODevice) +struct OptionDescription; +class OptionsParser; struct TypeDatabasePrivate; struct TypeDatabaseParserContext; @@ -32,10 +25,6 @@ QT_FORWARD_DECLARE_CLASS(QDebug) int getMaxTypeIndex(); -class ContainerTypeEntry; -class PrimitiveTypeEntry; -class TypeSystemTypeEntry; - struct VersionRange { bool isNull() const @@ -62,7 +51,9 @@ struct TypeRejection QRegularExpression className; QRegularExpression pattern; - MatchType matchType; + MatchType matchType = ExcludeClass; + bool generate; // Current type system + mutable bool matched = false; }; #ifndef QT_NO_DEBUG_STREAM @@ -72,10 +63,14 @@ QDebug operator<<(QDebug d, const TypeRejection &r); class TypeDatabase { TypeDatabase(); - Q_DISABLE_COPY(TypeDatabase) public: + Q_DISABLE_COPY_MOVE(TypeDatabase) + ~TypeDatabase(); + static QList<OptionDescription> options(); + std::shared_ptr<OptionsParser> createOptionsParser(); + /** * Return the type system instance. * \param newInstance This parameter is useful just for unit testing, because singletons causes @@ -90,39 +85,37 @@ public: void addRequiredTargetImport(const QString &moduleName); - void addTypesystemPath(const QString &typesystem_paths); - - void setTypesystemKeywords(const QStringList &keywords); QStringList typesystemKeywords() const; IncludeList extraIncludes(const QString &className) const; - const QStringList &systemIncludes() const; - void addSystemInclude(const QString &name); + const QStringList &forceProcessSystemIncludes() const; + void addForceProcessSystemInclude(const QString &name); - void addInlineNamespaceLookups(const NamespaceTypeEntry *n); + void addInlineNamespaceLookups(const NamespaceTypeEntryCPtr &n); - PrimitiveTypeEntry *findPrimitiveType(const QString &name) const; - ComplexTypeEntry *findComplexType(const QString &name) const; - ObjectTypeEntry *findObjectType(const QString &name) const; + PrimitiveTypeEntryPtr findPrimitiveType(const QString &name) const; + ComplexTypeEntryPtr findComplexType(const QString &name) const; + ObjectTypeEntryPtr findObjectType(const QString &name) const; NamespaceTypeEntryList findNamespaceTypes(const QString &name) const; - NamespaceTypeEntry *findNamespaceType(const QString &name, const QString &fileName = QString()) const; - ContainerTypeEntry *findContainerType(const QString &name) const; - FunctionTypeEntry *findFunctionType(const QString &name) const; - const TypeSystemTypeEntry *findTypeSystemType(const QString &name) const; - const TypeSystemTypeEntry *defaultTypeSystemType() const; + NamespaceTypeEntryPtr findNamespaceType(const QString &name, const QString &fileName = QString()) const; + ContainerTypeEntryPtr findContainerType(const QString &name) const; + FunctionTypeEntryPtr findFunctionType(const QString &name) const; + TypeSystemTypeEntryCPtr findTypeSystemType(const QString &name) const; + TypeSystemTypeEntryCPtr defaultTypeSystemType() const; + QString loadedTypeSystemNames() const; QString defaultPackageName() const; - TypeEntry *findType(const QString &name) const; - TypeEntries findTypes(const QString &name) const; - TypeEntries findCppTypes(const QString &name) const; + TypeEntryPtr findType(const QString &name) const; + TypeEntryCList findTypes(const QString &name) const; + TypeEntryCList findCppTypes(const QString &name) const; const TypeEntryMultiMap &entries() const; const TypedefEntryMap &typedefEntries() const; - PrimitiveTypeEntryList primitiveTypes() const; + PrimitiveTypeEntryCList primitiveTypes() const; - ContainerTypeEntryList containerTypes() const; + ContainerTypeEntryCList containerTypes() const; SmartPointerTypeEntryList smartPointerTypes() const; @@ -139,21 +132,21 @@ public: bool isReturnTypeRejected(const QString &className, const QString &typeName, QString *reason = nullptr) const; - bool addType(TypeEntry *e, QString *errorMessage = nullptr); - ConstantValueTypeEntry *addConstantValueTypeEntry(const QString &value, - const TypeEntry *parent); - void addTypeSystemType(const TypeSystemTypeEntry *e); + bool addType(const TypeEntryPtr &e, QString *errorMessage = nullptr); + ConstantValueTypeEntryPtr addConstantValueTypeEntry(const QString &value, + const TypeEntryCPtr &parent); + void addTypeSystemType(const TypeSystemTypeEntryCPtr &e); - static ComplexTypeEntry * - initializeTypeDefEntry(TypedefEntry *typedefEntry, - const ComplexTypeEntry *source); + static ComplexTypeEntryPtr + initializeTypeDefEntry(const TypedefEntryPtr &typedefEntry, + const ComplexTypeEntryCPtr &source); - FlagsTypeEntry *findFlagsType(const QString &name) const; - void addFlagsType(FlagsTypeEntry *fte); + FlagsTypeEntryPtr findFlagsType(const QString &name) const; + void addFlagsType(const FlagsTypeEntryPtr &fte); - TemplateEntry *findTemplate(const QString &name) const; + TemplateEntryPtr findTemplate(const QString &name) const; - void addTemplate(TemplateEntry *t); + void addTemplate(const TemplateEntryPtr &t); void addTemplate(const QString &name, const QString &code); AddedFunctionList globalUserFunctions() const; @@ -164,24 +157,23 @@ public: void addGlobalUserFunctionModifications(const FunctionModificationList &functionModifications); - FunctionModificationList functionModifications(const QString &signature) const; + FunctionModificationList + globalFunctionModifications(const QStringList &signatures) const; - void setSuppressWarnings(bool on); - - bool addSuppressedWarning(const QString &warning, QString *errorMessage); + bool addSuppressedWarning(const QString &warning, bool generate, QString *errorMessage); bool isSuppressedWarning(QStringView s) const; - static QString globalNamespaceClassName(const TypeEntry *te); + static QString globalNamespaceClassName(const TypeEntryCPtr &te); // Top level file parsing bool parseFile(const QString &filename, bool generate = true); - bool parseFile(const QSharedPointer<TypeDatabaseParserContext> &context, + bool parseFile(const std::shared_ptr<TypeDatabaseParserContext> &context, const QString &filename, const QString ¤tPath, bool generate); // Top level QIODevice parsing for tests. bool parseFile(QIODevice *device, bool generate = true); - bool parseFile(const QSharedPointer<TypeDatabaseParserContext> &context, + bool parseFile(const std::shared_ptr<TypeDatabaseParserContext> &context, QIODevice *device, bool generate = true); static bool setApiVersion(const QString &package, const QString &version); @@ -193,19 +185,23 @@ public: bool shouldDropTypeEntry(const QString &fullTypeName) const; - void setDropTypeEntries(QStringList dropTypeEntries); + void setDropTypeEntries(const QStringList &dropTypeEntries); QString modifiedTypesystemFilepath(const QString &tsFile, const QString ¤tPath = QString()) const; + void logUnmatched() const; + #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const; #endif + void formatBuiltinTypes(QDebug debug) const; private: TypeDatabasePrivate *d; }; #ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const TypeEntryCPtr &te); QDebug operator<<(QDebug d, const TypeEntry *te); QDebug operator<<(QDebug d, const TypeDatabase &db); #endif diff --git a/sources/shiboken6/ApiExtractor/typedatabase_p.h b/sources/shiboken6/ApiExtractor/typedatabase_p.h index 4d16040cf..fc56c7961 100644 --- a/sources/shiboken6/ApiExtractor/typedatabase_p.h +++ b/sources/shiboken6/ApiExtractor/typedatabase_p.h @@ -4,18 +4,22 @@ #ifndef TYPEDATABASE_P_H #define TYPEDATABASE_P_H +#include "typesystem_typedefs.h" +#include "containertypeentry.h" + #include <QtCore/QHash> #include <QtCore/QString> class TypeDatabase; -class SmartPointerTypeEntry; struct TypeDatabaseParserContext { - using SmartPointerInstantiations = QHash<SmartPointerTypeEntry *, QString>; + using SmartPointerInstantiations = QHash<SmartPointerTypeEntryPtr, QString>; + using OpaqueContainerHash = QHash<QString, OpaqueContainers>; TypeDatabase *db; SmartPointerInstantiations smartPointerInstantiations; + OpaqueContainerHash opaqueContainerHash; }; #endif // TYPEDATABASE_P_H diff --git a/sources/shiboken6/ApiExtractor/typedatabase_typedefs.h b/sources/shiboken6/ApiExtractor/typedatabase_typedefs.h index bc964eee2..f00c61570 100644 --- a/sources/shiboken6/ApiExtractor/typedatabase_typedefs.h +++ b/sources/shiboken6/ApiExtractor/typedatabase_typedefs.h @@ -4,21 +4,13 @@ #ifndef TYPEDATABASE_TYPEDEFS_H #define TYPEDATABASE_TYPEDEFS_H +#include "typesystem_typedefs.h" + #include <QtCore/QMultiMap> #include <QtCore/QString> #include <QtCore/QList> -class ConstantValueTypeEntry; -class ContainerTypeEntry; -class NamespaceTypeEntry; -class PrimitiveTypeEntry; -class SmartPointerTypeEntry; -class TemplateEntry; -class TypeEntry; -class TypedefEntry; - -using TypeEntryList = QList<TypeEntry *>; -using TemplateEntryMap =QMap<QString, TemplateEntry *>; +using TemplateEntryMap =QMap<QString, TemplateEntryPtr>; template <class Key, class Value> struct QMultiMapConstIteratorRange // A range of iterator for a range-based for loop @@ -32,15 +24,10 @@ struct QMultiMapConstIteratorRange // A range of iterator for a range-based for ConstIterator m_end; }; -using TypeEntryMultiMap = QMultiMap<QString, TypeEntry *>; -using TypeEntryMultiMapConstIteratorRange = QMultiMapConstIteratorRange<QString, TypeEntry *>; - -using TypeEntryMap = QMap<QString, TypeEntry *>; -using TypedefEntryMap = QMap<QString, TypedefEntry *>; +using TypeEntryMultiMap = QMultiMap<QString, TypeEntryPtr>; +using TypeEntryMultiMapConstIteratorRange = QMultiMapConstIteratorRange<QString, TypeEntryPtr>; -using ContainerTypeEntryList = QList<const ContainerTypeEntry *>; -using NamespaceTypeEntryList = QList<NamespaceTypeEntry *>; -using PrimitiveTypeEntryList = QList<const PrimitiveTypeEntry *>; -using SmartPointerTypeEntryList = QList<const SmartPointerTypeEntry *>; +using TypeEntryMap = QMap<QString, TypeEntryPtr>; +using TypedefEntryMap = QMap<QString, TypedefEntryPtr>; #endif // TYPEDATABASE_TYPEDEFS_H diff --git a/sources/shiboken6/ApiExtractor/typedefentry.h b/sources/shiboken6/ApiExtractor/typedefentry.h index e0eaf5efc..44646972c 100644 --- a/sources/shiboken6/ApiExtractor/typedefentry.h +++ b/sources/shiboken6/ApiExtractor/typedefentry.h @@ -14,18 +14,18 @@ public: explicit TypedefEntry(const QString &entryName, const QString &sourceType, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); QString sourceType() const; void setSourceType(const QString &s); TypeEntry *clone() const override; - const ComplexTypeEntry *source() const; - void setSource(const ComplexTypeEntry *source); + ComplexTypeEntryCPtr source() const; + void setSource(const ComplexTypeEntryCPtr &source); - ComplexTypeEntry *target() const; - void setTarget(ComplexTypeEntry *target); + ComplexTypeEntryPtr target() const; + void setTarget(ComplexTypeEntryPtr target); #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; diff --git a/sources/shiboken6/ApiExtractor/typeparser.cpp b/sources/shiboken6/ApiExtractor/typeparser.cpp index cff10eb67..11d7bf641 100644 --- a/sources/shiboken6/ApiExtractor/typeparser.cpp +++ b/sources/shiboken6/ApiExtractor/typeparser.cpp @@ -8,6 +8,8 @@ #include <QtCore/QStack> #include <QtCore/QTextStream> +using namespace Qt::StringLiterals; + class Scanner { public: @@ -35,7 +37,7 @@ public: { } - Token nextToken(QString *errorMessage = Q_NULLPTR); + Token nextToken(QString *errorMessage = nullptr); QString identifier() const; QString msgParseError(const QString &why) const; @@ -145,8 +147,8 @@ Scanner::Token Scanner::nextToken(QString *errorMessage) QString Scanner::msgParseError(const QString &why) const { - return QStringLiteral("TypeParser: Unable to parse \"") - + QString(m_chars, m_length) + QStringLiteral("\": ") + why; + return "TypeParser: Unable to parse \""_L1 + + QString(m_chars, m_length) + "\": "_L1 + why; } TypeInfo TypeParser::parse(const QString &str, QString *errorMessage) @@ -164,7 +166,7 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage) Scanner::Token tok = scanner.nextToken(errorMessage); while (tok != Scanner::NoToken) { if (tok == Scanner::InvalidToken) - return TypeInfo(); + return {}; // switch (tok) { // case Scanner::StarToken: printf(" - *\n"); break; @@ -197,12 +199,12 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage) stack.top().setReferenceType(RValueReference); break; case RValueReference: - const QString message = scanner.msgParseError(QStringLiteral("Too many '&' qualifiers")); + const QString message = scanner.msgParseError("Too many '&' qualifiers"_L1); if (errorMessage) *errorMessage = message; else qWarning().noquote().nospace() << message; - return TypeInfo(); + return {}; } break; case Scanner::LessThanToken: @@ -244,12 +246,12 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage) case Scanner::OpenParenToken: // function pointers not supported case Scanner::CloseParenToken: { - const QString message = scanner.msgParseError(QStringLiteral("Function pointers are not supported")); + const QString message = scanner.msgParseError("Function pointers are not supported"_L1); if (errorMessage) *errorMessage = message; else qWarning().noquote().nospace() << message; - return TypeInfo(); + return {}; } case Scanner::Identifier: @@ -279,11 +281,11 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage) break; } - tok = scanner.nextToken(); + tok = scanner.nextToken(errorMessage); } if (stack.isEmpty() || stack.constFirst().qualifiedName().isEmpty()) { - *errorMessage = u"Unable to parse type \""_qs + str + u"\"."_qs; + *errorMessage = u"Unable to parse type \""_s + str + u"\"."_s; return {}; } return stack.constFirst(); diff --git a/sources/shiboken6/ApiExtractor/typeparser.h b/sources/shiboken6/ApiExtractor/typeparser.h index 8e81435b2..97634b5db 100644 --- a/sources/shiboken6/ApiExtractor/typeparser.h +++ b/sources/shiboken6/ApiExtractor/typeparser.h @@ -4,8 +4,6 @@ #ifndef TYPEPARSER_H #define TYPEPARSER_H -#include "parser/codemodel_enums.h" - #include <QtCore/QString> class TypeInfo; diff --git a/sources/shiboken6/ApiExtractor/typesystem.cpp b/sources/shiboken6/ApiExtractor/typesystem.cpp index 9888de31a..99d42b668 100644 --- a/sources/shiboken6/ApiExtractor/typesystem.cpp +++ b/sources/shiboken6/ApiExtractor/typesystem.cpp @@ -5,14 +5,16 @@ #include "arraytypeentry.h" #include "codesnip.h" #include "complextypeentry.h" +#include "configurabletypeentry.h" #include "constantvaluetypeentry.h" #include "containertypeentry.h" -#include "customconversion.h" #include "customtypenentry.h" +#include "debughelpers_p.h" #include "enumtypeentry.h" #include "enumvaluetypeentry.h" #include "flagstypeentry.h" #include "functiontypeentry.h" +#include "include.h" #include "namespacetypeentry.h" #include "objecttypeentry.h" #include "primitivetypeentry.h" @@ -27,7 +29,6 @@ #include "abstractmetatype.h" #include "typedatabase.h" #include "modifications.h" -#include "messages.h" #include "sourcelocation.h" #include "qtcompat.h" @@ -39,7 +40,7 @@ using namespace Qt::StringLiterals; -static QString buildName(const QString &entryName, const TypeEntry *parent) +static QString buildName(const QString &entryName, const TypeEntryCPtr &parent) { return parent == nullptr || parent->type() == TypeEntry::TypeSystemType ? entryName : parent->name() + u"::"_s + entryName; @@ -51,31 +52,31 @@ static QString buildName(const QString &entryName, const TypeEntry *parent) class TypeEntryPrivate { public: + TypeEntryPrivate(const TypeEntryPrivate &) = default; // Enable copy for cloning. + TypeEntryPrivate &operator=(const TypeEntryPrivate &) = delete; + TypeEntryPrivate(TypeEntryPrivate &&) = delete; + TypeEntryPrivate &operator=(TypeEntryPrivate &&) = delete; + explicit TypeEntryPrivate(const QString &entryName, TypeEntry::Type t, const QVersionNumber &vr, - const TypeEntry *parent); - virtual ~TypeEntryPrivate(); + const TypeEntryCPtr &parent); + virtual ~TypeEntryPrivate() = default; QString shortName() const; - const TypeEntry *m_parent; + TypeEntryCPtr m_parent; QString m_name; // C++ fully qualified mutable QString m_cachedShortName; // C++ excluding inline namespaces QString m_entryName; QString m_targetLangPackage; mutable QString m_cachedTargetLangName; // "Foo.Bar" mutable QString m_cachedTargetLangEntryName; // "Bar" - CodeSnipList m_codeSnips; - DocModificationList m_docModifications; IncludeList m_extraIncludes; - IncludeList m_argumentIncludes; Include m_include; - QString m_targetConversionRule; QVersionNumber m_version; - CustomConversion *m_customConversion = nullptr; SourceLocation m_sourceLocation; // XML file TypeEntry::CodeGeneration m_codeGeneration = TypeEntry::GenerateCode; - TypeEntry *m_viewOn = nullptr; - CustomTypeEntry *m_targetLangApiType = nullptr; + TypeEntryPtr m_viewOn; + CustomTypeEntryPtr m_targetLangApiType; int m_revision = 0; int m_sbkIndex = 0; TypeEntry::Type m_type; @@ -85,7 +86,7 @@ public: }; TypeEntryPrivate::TypeEntryPrivate(const QString &entryName, TypeEntry::Type t, const QVersionNumber &vr, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : m_parent(parent), m_name(buildName(entryName, parent)), m_entryName(entryName), @@ -94,13 +95,8 @@ TypeEntryPrivate::TypeEntryPrivate(const QString &entryName, TypeEntry::Type t, { } -TypeEntryPrivate::~TypeEntryPrivate() -{ - delete m_customConversion; -} - TypeEntry::TypeEntry(const QString &entryName, TypeEntry::Type t, const QVersionNumber &vr, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : TypeEntry(new TypeEntryPrivate(entryName, t, vr, parent)) { } @@ -111,36 +107,6 @@ TypeEntry::TypeEntry(TypeEntryPrivate *d) : m_d(d) TypeEntry::~TypeEntry() = default; -const CodeSnipList &TypeEntry::codeSnips() const -{ - return m_d->m_codeSnips; -} - -CodeSnipList &TypeEntry::codeSnips() -{ - return m_d->m_codeSnips; -} - -void TypeEntry::setCodeSnips(const CodeSnipList &codeSnips) -{ - m_d->m_codeSnips = codeSnips; -} - -void TypeEntry::addCodeSnip(const CodeSnip &codeSnip) -{ - m_d->m_codeSnips << codeSnip; -} - -void TypeEntry::setDocModification(const DocModificationList &docMods) -{ - m_d->m_docModifications << docMods; -} - -DocModificationList TypeEntry::docModifications() const -{ - return m_d->m_docModifications; -} - const IncludeList &TypeEntry::extraIncludes() const { return m_d->m_extraIncludes; @@ -157,17 +123,6 @@ void TypeEntry::addExtraInclude(const Include &newInclude) m_d->m_extraIncludes.append(newInclude); } -const IncludeList &TypeEntry::argumentIncludes() const -{ - return m_d->m_argumentIncludes; -} - -void TypeEntry::addArgumentInclude(const Include &newInclude) -{ - if (!m_d->m_argumentIncludes.contains(newInclude)) - m_d->m_argumentIncludes.append(newInclude); -} - Include TypeEntry::include() const { return m_d->m_include; @@ -187,36 +142,20 @@ void TypeEntry::setInclude(const Include &inc) } } -void TypeEntry::setTargetConversionRule(const QString &conversionRule) -{ - m_d->m_targetConversionRule = conversionRule; -} - -QString TypeEntry::targetConversionRule() const -{ - return m_d->m_targetConversionRule; -} - QVersionNumber TypeEntry::version() const { return m_d->m_version; } -bool TypeEntry::hasTargetConversionRule() const -{ - return !m_d->m_targetConversionRule.isEmpty(); -} - -bool TypeEntry::isCppPrimitive() const +bool isCppPrimitive(const TypeEntryCPtr &e) { - if (!isPrimitive()) + if (!e->isPrimitive()) return false; - if (m_d->m_type == VoidType) + if (e->type() == TypeEntry::VoidType) return true; - const PrimitiveTypeEntry *referencedType = - static_cast<const PrimitiveTypeEntry *>(this)->basicReferencedTypeEntry(); + PrimitiveTypeEntryCPtr referencedType = basicReferencedTypeEntry(e); const QString &typeName = referencedType->name(); return AbstractMetaType::cppPrimitiveTypes().contains(typeName); } @@ -226,17 +165,17 @@ TypeEntry::Type TypeEntry::type() const return m_d->m_type; } -const TypeEntry *TypeEntry::parent() const +TypeEntryCPtr TypeEntry::parent() const { return m_d->m_parent; } -void TypeEntry::setParent(const TypeEntry *p) +void TypeEntry::setParent(const TypeEntryCPtr &p) { m_d->m_parent = p; } -bool TypeEntry::isChildOf(const TypeEntry *p) const +bool TypeEntry::isChildOf(const TypeEntryCPtr &p) const { for (auto e = m_d->m_parent; e; e = e->parent()) { if (e == p) @@ -245,18 +184,18 @@ bool TypeEntry::isChildOf(const TypeEntry *p) const return false; } -const TypeSystemTypeEntry *TypeEntry::typeSystemTypeEntry() const +TypeSystemTypeEntryCPtr typeSystemTypeEntry(TypeEntryCPtr e) { - for (auto e = this; e; e = e->parent()) { + for (; e; e = e->parent()) { if (e->type() == TypeEntry::TypeSystemType) - return static_cast<const TypeSystemTypeEntry *>(e); + return std::static_pointer_cast<const TypeSystemTypeEntry>(e); } - return nullptr; + return {}; } -const TypeEntry *TypeEntry::targetLangEnclosingEntry() const +TypeEntryCPtr targetLangEnclosingEntry(const TypeEntryCPtr &e) { - auto result = m_d->m_parent; + auto result = e->parent(); while (result && result->type() != TypeEntry::TypeSystemType && !NamespaceTypeEntry::isVisibleScope(result)) { result = result->parent(); @@ -387,11 +326,11 @@ QString TypeEntry::name() const QString TypeEntryPrivate::shortName() const { if (m_cachedShortName.isEmpty()) { - QVarLengthArray<const TypeEntry *> parents; + QVarLengthArray<TypeEntryCPtr > parents; bool foundInlineNamespace = false; for (auto p = m_parent; p != nullptr && p->type() != TypeEntry::TypeSystemType; p = p->parent()) { if (p->type() == TypeEntry::NamespaceType - && static_cast<const NamespaceTypeEntry *>(p)->isInlineNamespace()) { + && std::static_pointer_cast<const NamespaceTypeEntry>(p)->isInlineNamespace()) { foundInlineNamespace = true; } else { parents.append(p); @@ -399,7 +338,7 @@ QString TypeEntryPrivate::shortName() const } if (foundInlineNamespace) { m_cachedShortName.reserve(m_name.size()); - for (int i = parents.size() - 1; i >= 0; --i) { + for (auto i = parents.size() - 1; i >= 0; --i) { m_cachedShortName.append(parents.at(i)->entryName()); m_cachedShortName.append(u"::"_s); } @@ -456,7 +395,7 @@ QString TypeEntry::qualifiedCppName() const return m_d->m_name; } -const CustomTypeEntry *TypeEntry::targetLangApiType() const +CustomTypeEntryCPtr TypeEntry::targetLangApiType() const { return m_d->m_targetLangApiType; } @@ -466,7 +405,7 @@ bool TypeEntry::hasTargetLangApiType() const return m_d->m_targetLangApiType != nullptr; } -void TypeEntry::setTargetLangApiType(CustomTypeEntry *cte) +void TypeEntry::setTargetLangApiType(const CustomTypeEntryPtr &cte) { m_d->m_targetLangApiType = cte; } @@ -526,18 +465,12 @@ void TypeEntry::setSourceLocation(const SourceLocation &sourceLocation) m_d->m_sourceLocation = sourceLocation; } -const PrimitiveTypeEntry *TypeEntry::asPrimitive() const -{ - Q_ASSERT(m_d->m_type == PrimitiveType); - return static_cast<const PrimitiveTypeEntry *>(this); -} - -bool TypeEntry::isUserPrimitive() const +bool isUserPrimitive(const TypeEntryCPtr &e) { - if (!isPrimitive()) + if (!e->isPrimitive()) return false; - const auto *type = asPrimitive()->basicReferencedTypeEntry(); - return !type->isCppPrimitive() + const auto type = basicReferencedTypeEntry(e); + return !isCppPrimitive(type) && type->qualifiedCppName() != u"std::string"; } @@ -546,21 +479,21 @@ bool TypeEntry::isWrapperType() const return isObject() || isValue() || isSmartPointer(); } -bool TypeEntry::isCppIntegralPrimitive() const +bool isCppIntegralPrimitive(const TypeEntryCPtr &e) { - if (!isCppPrimitive()) + if (!isCppPrimitive(e)) return false; - const auto *type = asPrimitive()->basicReferencedTypeEntry(); + const auto type = basicReferencedTypeEntry(e); return AbstractMetaType::cppIntegralTypes().contains(type->qualifiedCppName()); } -bool TypeEntry::isExtendedCppPrimitive() const +bool isExtendedCppPrimitive(const TypeEntryCPtr &e) { - if (isCppPrimitive()) + if (isCppPrimitive(e)) return true; - if (!isPrimitive()) + if (!e->isPrimitive()) return false; - const auto *type = asPrimitive()->basicReferencedTypeEntry(); + const auto type = basicReferencedTypeEntry(e); const QString &name = type->qualifiedCppName(); return name == u"std::string" || name == u"std::wstring"; } @@ -611,27 +544,12 @@ bool TypeEntry::isComplex() const return false; } -bool TypeEntry::hasCustomConversion() const -{ - return m_d->m_customConversion != nullptr; -} - -void TypeEntry::setCustomConversion(CustomConversion* customConversion) -{ - m_d->m_customConversion = customConversion; -} - -CustomConversion* TypeEntry::customConversion() const -{ - return m_d->m_customConversion; -} - -TypeEntry *TypeEntry::viewOn() const +TypeEntryPtr TypeEntry::viewOn() const { return m_d->m_viewOn; } -void TypeEntry::setViewOn(TypeEntry *v) +void TypeEntry::setViewOn(const TypeEntryPtr &v) { m_d->m_viewOn = v; } @@ -642,10 +560,10 @@ TypeEntry *TypeEntry::clone() const } // Take over parameters relevant for typedefs -void TypeEntry::useAsTypedef(const TypeEntry *source) +void TypeEntry::useAsTypedef(const TypeEntryCPtr &source) { // XML Typedefs are in the global namespace for now. - m_d->m_parent = source->typeSystemTypeEntry(); + m_d->m_parent = typeSystemTypeEntry(source); m_d->m_entryName = source->m_d->m_entryName; m_d->m_name = source->m_d->m_name; m_d->m_targetLangPackage = source->m_d->m_targetLangPackage; @@ -665,7 +583,7 @@ public: }; CustomTypeEntry::CustomTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : TypeEntry(new CustomTypeEntryPrivate(entryName, CustomType, vr, parent)) { } @@ -746,11 +664,15 @@ class TypeSystemTypeEntryPrivate : public TypeEntryPrivate public: using TypeEntryPrivate::TypeEntryPrivate; + CodeSnipList m_codeSnips; TypeSystem::SnakeCase m_snakeCase = TypeSystem::SnakeCase::Disabled; + QString m_subModuleOf; + QString m_namespaceBegin; + QString m_namespaceEnd; }; TypeSystemTypeEntry::TypeSystemTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : TypeEntry(new TypeSystemTypeEntryPrivate(entryName, TypeSystemType, vr, parent)) { } @@ -766,6 +688,60 @@ TypeEntry *TypeSystemTypeEntry::clone() const return new TypeSystemTypeEntry(new TypeSystemTypeEntryPrivate(*d)); } +const CodeSnipList &TypeSystemTypeEntry::codeSnips() const +{ + S_D(const TypeSystemTypeEntry); + return d->m_codeSnips; +} + +CodeSnipList &TypeSystemTypeEntry::codeSnips() +{ + S_D(TypeSystemTypeEntry); + return d->m_codeSnips; +} + +void TypeSystemTypeEntry::addCodeSnip(const CodeSnip &codeSnip) +{ + S_D(TypeSystemTypeEntry); + d->m_codeSnips.append(codeSnip); +} + +QString TypeSystemTypeEntry::subModuleOf() const +{ + S_D(const TypeSystemTypeEntry); + return d->m_subModuleOf; +} + +void TypeSystemTypeEntry::setSubModule(const QString &s) +{ + S_D(TypeSystemTypeEntry); + d->m_subModuleOf = s; +} + +const QString &TypeSystemTypeEntry::namespaceBegin() const +{ + S_D(const TypeSystemTypeEntry); + return d->m_namespaceBegin; +} + +void TypeSystemTypeEntry::setNamespaceBegin(const QString &p) +{ + S_D(TypeSystemTypeEntry); + d->m_namespaceBegin = p; +} + +const QString &TypeSystemTypeEntry::namespaceEnd() const +{ + S_D(const TypeSystemTypeEntry); + return d->m_namespaceEnd; +} + +void TypeSystemTypeEntry::setNamespaceEnd(const QString &n) +{ + S_D(TypeSystemTypeEntry); + d->m_namespaceEnd = n; +} + TypeSystem::SnakeCase TypeSystemTypeEntry::snakeCase() const { S_D(const TypeSystemTypeEntry); @@ -820,7 +796,7 @@ public: }; TemplateArgumentEntry::TemplateArgumentEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : TypeEntry(new TemplateArgumentEntryPrivate(entryName, TemplateArgumentType, vr, parent)) { } @@ -852,30 +828,30 @@ TemplateArgumentEntry::TemplateArgumentEntry(TemplateArgumentEntryPrivate *d) : class ArrayTypeEntryPrivate : public TypeEntryPrivate { public: - explicit ArrayTypeEntryPrivate(const TypeEntry *nested_type, const QVersionNumber &vr, - const TypeEntry *parent) : + explicit ArrayTypeEntryPrivate(const TypeEntryCPtr &nested_type, const QVersionNumber &vr, + const TypeEntryCPtr &parent) : TypeEntryPrivate(u"Array"_s, TypeEntry::ArrayType, vr, parent), m_nestedType(nested_type) { } - const TypeEntry *m_nestedType; + TypeEntryCPtr m_nestedType; }; -ArrayTypeEntry::ArrayTypeEntry(const TypeEntry *nested_type, const QVersionNumber &vr, - const TypeEntry *parent) : +ArrayTypeEntry::ArrayTypeEntry(const TypeEntryCPtr &nested_type, const QVersionNumber &vr, + const TypeEntryCPtr &parent) : TypeEntry(new ArrayTypeEntryPrivate(nested_type, vr, parent)) { Q_ASSERT(nested_type); } -void ArrayTypeEntry::setNestedTypeEntry(TypeEntry *nested) +void ArrayTypeEntry::setNestedTypeEntry(const TypeEntryPtr &nested) { S_D(ArrayTypeEntry); d->m_nestedType = nested; } -const TypeEntry *ArrayTypeEntry::nestedTypeEntry() const +TypeEntryCPtr ArrayTypeEntry::nestedTypeEntry() const { S_D(const ArrayTypeEntry); return d->m_nestedType; @@ -903,19 +879,20 @@ class PrimitiveTypeEntryPrivate : public TypeEntryPrivate { public: PrimitiveTypeEntryPrivate(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : TypeEntryPrivate(entryName, TypeEntry::PrimitiveType, vr, parent), m_preferredTargetLangType(true) { } QString m_defaultConstructor; + CustomConversionPtr m_customConversion; + PrimitiveTypeEntryPtr m_referencedTypeEntry; uint m_preferredTargetLangType : 1; - PrimitiveTypeEntry* m_referencedTypeEntry = nullptr; }; PrimitiveTypeEntry::PrimitiveTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : TypeEntry(new PrimitiveTypeEntryPrivate(entryName, vr, parent)) { } @@ -938,29 +915,35 @@ bool PrimitiveTypeEntry::hasDefaultConstructor() const return !d->m_defaultConstructor.isEmpty(); } -PrimitiveTypeEntry *PrimitiveTypeEntry::referencedTypeEntry() const +PrimitiveTypeEntryPtr PrimitiveTypeEntry::referencedTypeEntry() const { S_D(const PrimitiveTypeEntry); return d->m_referencedTypeEntry; } -void PrimitiveTypeEntry::setReferencedTypeEntry(PrimitiveTypeEntry *referencedTypeEntry) +void PrimitiveTypeEntry::setReferencedTypeEntry(PrimitiveTypeEntryPtr referencedTypeEntry) { S_D(PrimitiveTypeEntry); d->m_referencedTypeEntry = referencedTypeEntry; } -const PrimitiveTypeEntry *PrimitiveTypeEntry::basicReferencedTypeEntry() const +PrimitiveTypeEntryCPtr basicReferencedTypeEntry(const PrimitiveTypeEntryCPtr &e) { - auto *result = this; - while (auto *referenced = result->referencedTypeEntry()) + auto result = e; + while (auto referenced = result->referencedTypeEntry()) result = referenced; return result; } -const PrimitiveTypeEntry *PrimitiveTypeEntry::basicReferencedNonBuiltinTypeEntry() const +PrimitiveTypeEntryCPtr basicReferencedTypeEntry(const TypeEntryCPtr &e) { - auto *result = this; + Q_ASSERT(e->isPrimitive()); + return basicReferencedTypeEntry(std::static_pointer_cast<const PrimitiveTypeEntry>(e)); +} + +PrimitiveTypeEntryCPtr basicReferencedNonBuiltinTypeEntry(const PrimitiveTypeEntryCPtr &e) +{ + auto result = e; for (; result->referencedTypeEntry() ; result = result->referencedTypeEntry()) { if (!result->isBuiltIn()) break; @@ -986,6 +969,24 @@ void PrimitiveTypeEntry::setPreferredTargetLangType(bool b) d->m_preferredTargetLangType = b; } +bool PrimitiveTypeEntry::hasCustomConversion() const +{ + S_D(const PrimitiveTypeEntry); + return bool(d->m_customConversion); +} + +void PrimitiveTypeEntry::setCustomConversion(const CustomConversionPtr &customConversion) +{ + S_D(PrimitiveTypeEntry); + d->m_customConversion = customConversion; +} + +CustomConversionPtr PrimitiveTypeEntry::customConversion() const +{ + S_D(const PrimitiveTypeEntry); + return d->m_customConversion; +} + TypeEntry *PrimitiveTypeEntry::clone() const { S_D(const PrimitiveTypeEntry); @@ -997,22 +998,72 @@ PrimitiveTypeEntry::PrimitiveTypeEntry(PrimitiveTypeEntryPrivate *d) { } -// ----------------- EnumTypeEntry -class EnumTypeEntryPrivate : public TypeEntryPrivate +// ----------------- ConfigurableTypeEntry + +class ConfigurableTypeEntryPrivate : public TypeEntryPrivate { public: using TypeEntryPrivate::TypeEntryPrivate; - const EnumValueTypeEntry *m_nullValue = nullptr; + QString m_configCondition; +}; + +ConfigurableTypeEntry::ConfigurableTypeEntry(const QString &entryName, Type t, + const QVersionNumber &vr, + const TypeEntryCPtr &parent) : + TypeEntry(new ConfigurableTypeEntryPrivate(entryName, t, vr, parent)) +{ +} + +ConfigurableTypeEntry::ConfigurableTypeEntry(ConfigurableTypeEntryPrivate *d) : + TypeEntry(d) +{ +} + +TypeEntry *ConfigurableTypeEntry::clone() const +{ + S_D(const ConfigurableTypeEntry); + return new ConfigurableTypeEntry(new ConfigurableTypeEntryPrivate(*d)); +} + +QString ConfigurableTypeEntry::configCondition() const +{ + S_D(const ConfigurableTypeEntry); + return d->m_configCondition; +} + +void ConfigurableTypeEntry::setConfigCondition(const QString &c) +{ + S_D(ConfigurableTypeEntry); + d->m_configCondition = c; + if (!d->m_configCondition.startsWith(u'#')) + d->m_configCondition.prepend(u"#if "); +} + +bool ConfigurableTypeEntry::hasConfigCondition() const +{ + S_D(const ConfigurableTypeEntry); + return !d->m_configCondition.isEmpty(); +} + +// ----------------- EnumTypeEntry +class EnumTypeEntryPrivate : public ConfigurableTypeEntryPrivate +{ +public: + using ConfigurableTypeEntryPrivate::ConfigurableTypeEntryPrivate; + + EnumValueTypeEntryCPtr m_nullValue; QStringList m_rejectedEnums; - FlagsTypeEntry *m_flags = nullptr; + FlagsTypeEntryPtr m_flags; + QString m_cppType; + QString m_docFile; TypeSystem::PythonEnumType m_pythonEnumType = TypeSystem::PythonEnumType::Unspecified; }; EnumTypeEntry::EnumTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent) : - TypeEntry(new EnumTypeEntryPrivate(entryName, EnumType, vr, parent)) + const TypeEntryCPtr &parent) : + ConfigurableTypeEntry(new EnumTypeEntryPrivate(entryName, EnumType, vr, parent)) { } @@ -1045,30 +1096,42 @@ QString EnumTypeEntry::qualifier() const parentEntry->name() : QString(); } -const EnumValueTypeEntry *EnumTypeEntry::nullValue() const +EnumValueTypeEntryCPtr EnumTypeEntry::nullValue() const { S_D(const EnumTypeEntry); return d->m_nullValue; } -void EnumTypeEntry::setNullValue(const EnumValueTypeEntry *n) +void EnumTypeEntry::setNullValue(const EnumValueTypeEntryCPtr &n) { S_D(EnumTypeEntry); d->m_nullValue = n; } -void EnumTypeEntry::setFlags(FlagsTypeEntry *flags) +void EnumTypeEntry::setFlags(const FlagsTypeEntryPtr &flags) { S_D(EnumTypeEntry); d->m_flags = flags; } -FlagsTypeEntry *EnumTypeEntry::flags() const +FlagsTypeEntryPtr EnumTypeEntry::flags() const { S_D(const EnumTypeEntry); return d->m_flags; } +QString EnumTypeEntry::cppType() const +{ + S_D(const EnumTypeEntry); + return d->m_cppType; +} + +void EnumTypeEntry::setCppType(const QString &t) +{ + S_D(EnumTypeEntry); + d->m_cppType = t; +} + bool EnumTypeEntry::isEnumValueRejected(const QString &name) const { S_D(const EnumTypeEntry); @@ -1087,6 +1150,18 @@ QStringList EnumTypeEntry::enumValueRejections() const return d->m_rejectedEnums; } +QString EnumTypeEntry::docFile() const +{ + S_D(const EnumTypeEntry); + return d->m_docFile; +} + +void EnumTypeEntry::setDocFile(const QString &df) +{ + S_D(EnumTypeEntry); + d->m_docFile = df; +} + TypeEntry *EnumTypeEntry::clone() const { S_D(const EnumTypeEntry); @@ -1094,7 +1169,7 @@ TypeEntry *EnumTypeEntry::clone() const } EnumTypeEntry::EnumTypeEntry(EnumTypeEntryPrivate *d) : - TypeEntry(d) + ConfigurableTypeEntry(d) { } @@ -1103,7 +1178,7 @@ class EnumValueTypeEntryPrivate : public TypeEntryPrivate { public: EnumValueTypeEntryPrivate(const QString &name, const QString &value, - const EnumTypeEntry *enclosingEnum, + const EnumTypeEntryCPtr &enclosingEnum, bool isScopedEnum, const QVersionNumber &vr) : TypeEntryPrivate(name, TypeEntry::EnumValue, vr, @@ -1114,11 +1189,11 @@ public: } QString m_value; - const EnumTypeEntry *m_enclosingEnum; + EnumTypeEntryCPtr m_enclosingEnum; }; EnumValueTypeEntry::EnumValueTypeEntry(const QString &name, const QString &value, - const EnumTypeEntry *enclosingEnum, + const EnumTypeEntryCPtr &enclosingEnum, bool isScopedEnum, const QVersionNumber &vr) : TypeEntry(new EnumValueTypeEntryPrivate(name, value, enclosingEnum, isScopedEnum, vr)) @@ -1131,7 +1206,7 @@ QString EnumValueTypeEntry::value() const return d->m_value; } -const EnumTypeEntry *EnumValueTypeEntry::enclosingEnum() const +EnumTypeEntryCPtr EnumValueTypeEntry::enclosingEnum() const { S_D(const EnumValueTypeEntry); return d->m_enclosingEnum; @@ -1156,11 +1231,11 @@ public: QString m_originalName; QString m_flagsName; - EnumTypeEntry *m_enum = nullptr; + EnumTypeEntryPtr m_enum; }; FlagsTypeEntry::FlagsTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : TypeEntry(new FlagsTypeEntryPrivate(entryName, FlagsType, vr, parent)) { } @@ -1202,13 +1277,13 @@ void FlagsTypeEntry::setFlagsName(const QString &name) d->m_flagsName = name; } -EnumTypeEntry *FlagsTypeEntry::originator() const +EnumTypeEntryPtr FlagsTypeEntry::originator() const { S_D(const FlagsTypeEntry); return d->m_enum; } -void FlagsTypeEntry::setOriginator(EnumTypeEntry *e) +void FlagsTypeEntry::setOriginator(const EnumTypeEntryPtr &e) { S_D(FlagsTypeEntry); d->m_enum = e; @@ -1222,7 +1297,7 @@ TypeEntry *FlagsTypeEntry::clone() const // ----------------- ConstantValueTypeEntry ConstantValueTypeEntry::ConstantValueTypeEntry(const QString& name, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : TypeEntry(name, ConstantValueType, QVersionNumber(0, 0), parent) { } @@ -1233,13 +1308,13 @@ ConstantValueTypeEntry::ConstantValueTypeEntry(TypeEntryPrivate *d) : } // ----------------- ComplexTypeEntry -class ComplexTypeEntryPrivate : public TypeEntryPrivate +class ComplexTypeEntryPrivate : public ConfigurableTypeEntryPrivate { public: ComplexTypeEntryPrivate(const QString &entryName, TypeEntry::Type t, const QVersionNumber &vr, - const TypeEntry *parent) : - TypeEntryPrivate(entryName, t, vr, parent), + const TypeEntryCPtr &parent) : + ConfigurableTypeEntryPrivate(entryName, t, vr, parent), m_qualifiedCppName(buildName(entryName, parent)), m_polymorphicBase(false), m_genericClass(false), @@ -1249,6 +1324,10 @@ public: AddedFunctionList m_addedFunctions; FunctionModificationList m_functionMods; + CodeSnipList m_codeSnips; + DocModificationList m_docModifications; + DocModificationList m_functionDocModifications; + IncludeList m_argumentIncludes; QSet<QString> m_generateFunctions; FieldModificationList m_fieldMods; QList<TypeSystemProperty> m_properties; @@ -1268,7 +1347,7 @@ public: ComplexTypeEntry::CopyableFlag m_copyableFlag = ComplexTypeEntry::Unknown; QString m_hashFunction; - const ComplexTypeEntry* m_baseContainerType = nullptr; + ComplexTypeEntryCPtr m_baseContainerType; // For class functions TypeSystem::ExceptionHandling m_exceptionHandling = TypeSystem::ExceptionHandling::Unspecified; TypeSystem::AllowThread m_allowThread = TypeSystem::AllowThread::Unspecified; @@ -1283,8 +1362,8 @@ public: ComplexTypeEntry::ComplexTypeEntry(const QString &entryName, TypeEntry::Type t, const QVersionNumber &vr, - const TypeEntry *parent) : - TypeEntry(new ComplexTypeEntryPrivate(entryName, t, vr, parent)) + const TypeEntryCPtr &parent) : + ConfigurableTypeEntry(new ComplexTypeEntryPrivate(entryName, t, vr, parent)) { } @@ -1347,17 +1426,77 @@ void ComplexTypeEntry::addFunctionModification(const FunctionModification &funct d->m_functionMods << functionModification; } -FunctionModificationList ComplexTypeEntry::functionModifications(const QString &signature) const +FunctionModificationList + ComplexTypeEntry::functionModifications(const QStringList &signatures) const { S_D(const ComplexTypeEntry); FunctionModificationList lst; for (const auto &mod : std::as_const(d->m_functionMods)) { - if (mod.matches(signature)) + if (mod.matches(signatures)) lst << mod; } return lst; } +const CodeSnipList &ComplexTypeEntry::codeSnips() const +{ + S_D(const ComplexTypeEntry); + return d->m_codeSnips; +} + +CodeSnipList &ComplexTypeEntry::codeSnips() +{ + S_D(ComplexTypeEntry); + return d->m_codeSnips; +} + +void ComplexTypeEntry::setCodeSnips(const CodeSnipList &codeSnips) +{ + S_D(ComplexTypeEntry); + d->m_codeSnips = codeSnips; +} + +void ComplexTypeEntry::addCodeSnip(const CodeSnip &codeSnip) +{ + S_D(ComplexTypeEntry); + d->m_codeSnips << codeSnip; +} + +void ComplexTypeEntry::setDocModification(const DocModificationList &docMods) +{ + S_D(ComplexTypeEntry); + for (const auto &m : docMods) { + if (m.signature().isEmpty()) + d->m_docModifications << m; + else + d->m_functionDocModifications << m; + } +} + +DocModificationList ComplexTypeEntry::docModifications() const +{ + S_D(const ComplexTypeEntry); + return d->m_docModifications; +} + +DocModificationList ComplexTypeEntry::functionDocModifications() const +{ + S_D(const ComplexTypeEntry); + return d->m_functionDocModifications; +} + +const IncludeList &ComplexTypeEntry::argumentIncludes() const +{ + S_D(const ComplexTypeEntry); + return d->m_argumentIncludes; +} + +void ComplexTypeEntry::addArgumentInclude(const Include &newInclude) +{ + S_D(ComplexTypeEntry); + IncludeGroup::appendInclude(newInclude, &d->m_argumentIncludes); +} + AddedFunctionList ComplexTypeEntry::addedFunctions() const { S_D(const ComplexTypeEntry); @@ -1550,13 +1689,13 @@ void ComplexTypeEntry::setHashFunction(const QString &hashFunction) d->m_hashFunction = hashFunction; } -void ComplexTypeEntry::setBaseContainerType(const ComplexTypeEntry *baseContainer) +void ComplexTypeEntry::setBaseContainerType(const ComplexTypeEntryCPtr &baseContainer) { S_D(ComplexTypeEntry); d->m_baseContainerType = baseContainer; } -const ComplexTypeEntry *ComplexTypeEntry::baseContainerType() const +ComplexTypeEntryCPtr ComplexTypeEntry::baseContainerType() const { S_D(const ComplexTypeEntry); return d->m_baseContainerType; @@ -1648,16 +1787,17 @@ TypeEntry *ComplexTypeEntry::clone() const } // Take over parameters relevant for typedefs -void ComplexTypeEntry::useAsTypedef(const ComplexTypeEntry *source) +void ComplexTypeEntry::useAsTypedef(const ComplexTypeEntryCPtr &source) { S_D(ComplexTypeEntry); TypeEntry::useAsTypedef(source); d->m_qualifiedCppName = source->qualifiedCppName(); d->m_targetType = source->targetType(); + d->m_typeFlags.setFlag(ComplexTypeEntry::Typedef); } ComplexTypeEntry::ComplexTypeEntry(ComplexTypeEntryPrivate *d) : - TypeEntry(d) + ConfigurableTypeEntry(d) { } @@ -1676,7 +1816,7 @@ public: TypedefEntryPrivate(const QString &entryName, const QString &sourceType, const QVersionNumber &vr, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : ComplexTypeEntryPrivate(entryName, TypeEntry::TypedefType, vr, parent), m_sourceType(sourceType) @@ -1684,12 +1824,12 @@ public: } QString m_sourceType; - const ComplexTypeEntry *m_source = nullptr; - ComplexTypeEntry *m_target = nullptr; + ComplexTypeEntryCPtr m_source; + ComplexTypeEntryPtr m_target; }; TypedefEntry::TypedefEntry(const QString &entryName, const QString &sourceType, - const QVersionNumber &vr, const TypeEntry *parent) : + const QVersionNumber &vr, const TypeEntryCPtr &parent) : ComplexTypeEntry(new TypedefEntryPrivate(entryName, sourceType, vr, parent)) { } @@ -1712,25 +1852,25 @@ TypeEntry *TypedefEntry::clone() const return new TypedefEntry(new TypedefEntryPrivate(*d)); } -const ComplexTypeEntry *TypedefEntry::source() const +ComplexTypeEntryCPtr TypedefEntry::source() const { S_D(const TypedefEntry); return d->m_source; } -void TypedefEntry::setSource(const ComplexTypeEntry *source) +void TypedefEntry::setSource(const ComplexTypeEntryCPtr &source) { S_D(TypedefEntry); d->m_source = source; } -ComplexTypeEntry *TypedefEntry::target() const +ComplexTypeEntryPtr TypedefEntry::target() const { S_D(const TypedefEntry); return d->m_target; } -void TypedefEntry::setTarget(ComplexTypeEntry *target) +void TypedefEntry::setTarget(ComplexTypeEntryPtr target) { S_D(TypedefEntry); d->m_target = target; @@ -1745,33 +1885,44 @@ TypedefEntry::TypedefEntry(TypedefEntryPrivate *d) : class ContainerTypeEntryPrivate : public ComplexTypeEntryPrivate { public: - using OpaqueContainer = ContainerTypeEntry::OpaqueContainer; - using OpaqueContainers = ContainerTypeEntry::OpaqueContainers; - ContainerTypeEntryPrivate(const QString &entryName, ContainerTypeEntry::ContainerKind containerKind, const QVersionNumber &vr, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : ComplexTypeEntryPrivate(entryName, TypeEntry::ContainerType, vr, parent), m_containerKind(containerKind) { } - OpaqueContainers::const_iterator findOpaqueContainer(const QString &instantiation) const + OpaqueContainers::const_iterator findOpaqueContainer(const QStringList &instantiations) const { return std::find_if(m_opaqueContainers.cbegin(), m_opaqueContainers.cend(), - [&instantiation](const OpaqueContainer &r) { - return r.instantiation == instantiation; + [&instantiations](const OpaqueContainer &r) { + return r.instantiations == instantiations; }); } OpaqueContainers m_opaqueContainers; + CustomConversionPtr m_customConversion; ContainerTypeEntry::ContainerKind m_containerKind; }; +QString OpaqueContainer::templateParameters() const +{ + QString result; + result += u'<'; + for (qsizetype i = 0, size = instantiations.size(); i < size; ++i) { + if (i) + result += u','; + result += instantiations.at(i); + } + result += u'>'; + return result; +} + ContainerTypeEntry::ContainerTypeEntry(const QString &entryName, ContainerKind containerKind, const QVersionNumber &vr, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : ComplexTypeEntry(new ContainerTypeEntryPrivate(entryName, containerKind, vr, parent)) { setCodeGeneration(GenerateForSubclass); @@ -1783,36 +1934,67 @@ ContainerTypeEntry::ContainerKind ContainerTypeEntry::containerKind() const return d->m_containerKind; } -const ContainerTypeEntry::OpaqueContainers &ContainerTypeEntry::opaqueContainers() const +qsizetype ContainerTypeEntry::templateParameterCount() const +{ + S_D(const ContainerTypeEntry); + qsizetype result = 1; + switch (d->m_containerKind) { + case MapContainer: + case MultiMapContainer: + case PairContainer: + case SpanContainer: + result = 2; + break; + case ListContainer: + case SetContainer: + break; + } + return result; +} + +const OpaqueContainers &ContainerTypeEntry::opaqueContainers() const { S_D(const ContainerTypeEntry); return d->m_opaqueContainers; } -void ContainerTypeEntry::addOpaqueContainer(OpaqueContainer r) +void ContainerTypeEntry::appendOpaqueContainers(const OpaqueContainers &l) { S_D(ContainerTypeEntry); - // Fix to match AbstractMetaType::signature() which is used for matching - // "Foo*" -> "Foo *" - const auto asteriskPos = r.instantiation.indexOf(u'*'); - if (asteriskPos > 0 && !r.instantiation.at(asteriskPos - 1).isSpace()) - r.instantiation.insert(asteriskPos, u' '); - d->m_opaqueContainers.append(r); + d->m_opaqueContainers.append(l); } -bool ContainerTypeEntry::generateOpaqueContainer(const QString &instantiation) const +bool ContainerTypeEntry::generateOpaqueContainer(const QStringList &instantiations) const { S_D(const ContainerTypeEntry); - return d->findOpaqueContainer(instantiation) != d->m_opaqueContainers.cend(); + return d->findOpaqueContainer(instantiations) != d->m_opaqueContainers.cend(); } -QString ContainerTypeEntry::opaqueContainerName(const QString &instantiation) const +QString ContainerTypeEntry::opaqueContainerName(const QStringList &instantiations) const { S_D(const ContainerTypeEntry); - const auto it = d->findOpaqueContainer(instantiation); + const auto it = d->findOpaqueContainer(instantiations); return it != d->m_opaqueContainers.cend() ? it->name : QString{}; } +bool ContainerTypeEntry::hasCustomConversion() const +{ + S_D(const ContainerTypeEntry); + return bool(d->m_customConversion); +} + +void ContainerTypeEntry::setCustomConversion(const CustomConversionPtr &customConversion) +{ + S_D(ContainerTypeEntry); + d->m_customConversion = customConversion; +} + +CustomConversionPtr ContainerTypeEntry::customConversion() const +{ + S_D(const ContainerTypeEntry); + return d->m_customConversion; +} + TypeEntry *ContainerTypeEntry::clone() const { S_D(const ContainerTypeEntry); @@ -1832,7 +2014,7 @@ public: const QString &getterName, TypeSystem::SmartPointerType type, const QString &refCountMethodName, - const QVersionNumber &vr, const TypeEntry *parent) : + const QVersionNumber &vr, const TypeEntryCPtr &parent) : ComplexTypeEntryPrivate(entryName, TypeEntry::SmartPointerType, vr, parent), m_getterName(getterName), m_refCountMethodName(refCountMethodName), @@ -1840,6 +2022,8 @@ public: { } + qsizetype instantiationIndex(const TypeEntryCPtr &t) const; + QString m_getterName; QString m_refCountMethodName; QString m_valueCheckMethod; @@ -1849,11 +2033,21 @@ public: TypeSystem::SmartPointerType m_smartPointerType; }; +qsizetype SmartPointerTypeEntryPrivate::instantiationIndex(const TypeEntryCPtr &t) const +{ + for (qsizetype i = 0, size = m_instantiations.size(); i < size; ++i) { + if (m_instantiations.at(i).typeEntry == t) + return i; + } + return -1; +} + SmartPointerTypeEntry::SmartPointerTypeEntry(const QString &entryName, const QString &getterName, TypeSystem::SmartPointerType smartPointerType, const QString &refCountMethodName, - const QVersionNumber &vr, const TypeEntry *parent) : + const QVersionNumber &vr, + const TypeEntryCPtr &parent) : ComplexTypeEntry(new SmartPointerTypeEntryPrivate(entryName, getterName, smartPointerType, refCountMethodName, vr, parent)) { @@ -1919,7 +2113,7 @@ TypeEntry *SmartPointerTypeEntry::clone() const return new SmartPointerTypeEntry(new SmartPointerTypeEntryPrivate(*d)); } -SmartPointerTypeEntry::Instantiations SmartPointerTypeEntry::instantiations() const +const SmartPointerTypeEntry::Instantiations &SmartPointerTypeEntry::instantiations() const { S_D(const SmartPointerTypeEntry); return d->m_instantiations; @@ -1936,10 +2130,11 @@ SmartPointerTypeEntry::SmartPointerTypeEntry(SmartPointerTypeEntryPrivate *d) : { } -bool SmartPointerTypeEntry::matchesInstantiation(const TypeEntry *e) const +bool SmartPointerTypeEntry::matchesInstantiation(const TypeEntryCPtr &e) const { S_D(const SmartPointerTypeEntry); - return d->m_instantiations.isEmpty() || d->m_instantiations.contains(e); + // No instantiations specified, or match + return d->m_instantiations.isEmpty() || d->instantiationIndex(e) != -1; } static QString fixSmartPointerName(QString name) @@ -1951,18 +2146,14 @@ static QString fixSmartPointerName(QString name) return name; } -QString SmartPointerTypeEntry::getTargetFullName(const AbstractMetaType &metaType, - bool includePackageName) +QString SmartPointerTypeEntry::getTargetName(const AbstractMetaType &metaType) const { - QString result; - if (includePackageName) - result += metaType.package() + u'.'; - result += fixSmartPointerName(metaType.cppSignature()); - return result; -} + S_D(const SmartPointerTypeEntry); + auto instantiatedTe = metaType.instantiations().constFirst().typeEntry(); + const auto index = d->instantiationIndex(instantiatedTe); + if (index != -1 && !d->m_instantiations.at(index).name.isEmpty()) + return d->m_instantiations.at(index).name; -QString SmartPointerTypeEntry::getTargetName(const AbstractMetaType &metaType) -{ QString name = metaType.cppSignature(); const auto templatePos = name.indexOf(u'<'); if (templatePos != -1) { // "std::shared_ptr<A::B>" -> "shared_ptr<A::B>" @@ -1980,7 +2171,7 @@ public: using ComplexTypeEntryPrivate::ComplexTypeEntryPrivate; QRegularExpression m_filePattern; - const NamespaceTypeEntry *m_extends = nullptr; + NamespaceTypeEntryCPtr m_extends; TypeSystem::Visibility m_visibility = TypeSystem::Visibility::Auto; bool m_hasPattern = false; bool m_inlineNamespace = false; @@ -1988,7 +2179,7 @@ public: }; NamespaceTypeEntry::NamespaceTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : ComplexTypeEntry(new NamespaceTypeEntryPrivate(entryName, NamespaceType, vr, parent)) { } @@ -1999,13 +2190,13 @@ TypeEntry *NamespaceTypeEntry::clone() const return new NamespaceTypeEntry(new NamespaceTypeEntryPrivate(*d)); } -const NamespaceTypeEntry *NamespaceTypeEntry::extends() const +NamespaceTypeEntryCPtr NamespaceTypeEntry::extends() const { S_D(const NamespaceTypeEntry); return d->m_extends; } -void NamespaceTypeEntry::setExtends(const NamespaceTypeEntry *e) +void NamespaceTypeEntry::setExtends(const NamespaceTypeEntryCPtr &e) { S_D(NamespaceTypeEntry); d->m_extends = e; @@ -2068,6 +2259,11 @@ void NamespaceTypeEntry::setInlineNamespace(bool i) d->m_inlineNamespace = i; } +bool NamespaceTypeEntry::isVisibleScope(const TypeEntryCPtr &e) +{ + return isVisibleScope(e.get()); +} + bool NamespaceTypeEntry::isVisibleScope(const TypeEntry *e) { return e->type() != TypeEntry::NamespaceType @@ -2087,180 +2283,78 @@ void NamespaceTypeEntry::setGenerateUsing(bool generateUsing) } // ----------------- ValueTypeEntry -ValueTypeEntry::ValueTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent) : - ComplexTypeEntry(entryName, BasicValueType, vr, parent) -{ -} - -bool ValueTypeEntry::isValue() const -{ - return true; -} - -TypeEntry *ValueTypeEntry::clone() const -{ - S_D(const ComplexTypeEntry); - return new ValueTypeEntry(new ComplexTypeEntryPrivate(*d)); -} -ValueTypeEntry::ValueTypeEntry(ComplexTypeEntryPrivate *d) : - ComplexTypeEntry(d) +class ValueTypeEntryPrivate : public ComplexTypeEntryPrivate { -} - -ValueTypeEntry::ValueTypeEntry(const QString &entryName, Type t, const QVersionNumber &vr, - const TypeEntry *parent) : - ComplexTypeEntry(entryName, t, vr, parent) -{ -} - -// ----------------- CustomConversion -struct CustomConversion::CustomConversionPrivate -{ - CustomConversionPrivate(const TypeEntry* ownerType) - : ownerType(ownerType), replaceOriginalTargetToNativeConversions(false) - { - } - const TypeEntry* ownerType; - QString nativeToTargetConversion; - bool replaceOriginalTargetToNativeConversions; - TargetToNativeConversions targetToNativeConversions; -}; +public: + using ComplexTypeEntryPrivate::ComplexTypeEntryPrivate; -struct CustomConversion::TargetToNativeConversion::TargetToNativeConversionPrivate -{ - TargetToNativeConversionPrivate() - : sourceType(nullptr) - { - } - const TypeEntry* sourceType; - QString sourceTypeName; - QString sourceTypeCheck; - QString conversion; + QString m_targetConversionRule; + CustomConversionPtr m_customConversion; }; -CustomConversion::CustomConversion(TypeEntry* ownerType) -{ - m_d = new CustomConversionPrivate(ownerType); - if (ownerType) - ownerType->setCustomConversion(this); -} - -CustomConversion::~CustomConversion() -{ - qDeleteAll(m_d->targetToNativeConversions); - delete m_d; -} - -const TypeEntry* CustomConversion::ownerType() const -{ - return m_d->ownerType; -} - -QString CustomConversion::nativeToTargetConversion() const -{ - return m_d->nativeToTargetConversion; -} - -void CustomConversion::setNativeToTargetConversion(const QString& nativeToTargetConversion) -{ - m_d->nativeToTargetConversion = nativeToTargetConversion; -} - -bool CustomConversion::replaceOriginalTargetToNativeConversions() const -{ - return m_d->replaceOriginalTargetToNativeConversions; -} - -void CustomConversion::setReplaceOriginalTargetToNativeConversions(bool replaceOriginalTargetToNativeConversions) -{ - m_d->replaceOriginalTargetToNativeConversions = replaceOriginalTargetToNativeConversions; -} - -bool CustomConversion::hasTargetToNativeConversions() const -{ - return !(m_d->targetToNativeConversions.isEmpty()); -} - -CustomConversion::TargetToNativeConversions& CustomConversion::targetToNativeConversions() -{ - return m_d->targetToNativeConversions; -} - -const CustomConversion::TargetToNativeConversions& CustomConversion::targetToNativeConversions() const +ValueTypeEntry::ValueTypeEntry(const QString &entryName, const QVersionNumber &vr, + const TypeEntryCPtr &parent) : + ComplexTypeEntry(new ValueTypeEntryPrivate(entryName, BasicValueType, vr, parent)) { - return m_d->targetToNativeConversions; } -void CustomConversion::addTargetToNativeConversion(const QString& sourceTypeName, - const QString& sourceTypeCheck, - const QString& conversion) +bool ValueTypeEntry::hasCustomConversion() const { - m_d->targetToNativeConversions.append(new TargetToNativeConversion(sourceTypeName, sourceTypeCheck, conversion)); + S_D(const ValueTypeEntry); + return bool(d->m_customConversion); } -CustomConversion::TargetToNativeConversion::TargetToNativeConversion(const QString& sourceTypeName, - const QString& sourceTypeCheck, - const QString& conversion) +void ValueTypeEntry::setCustomConversion(const CustomConversionPtr &customConversion) { - m_d = new TargetToNativeConversionPrivate; - m_d->sourceTypeName = sourceTypeName; - m_d->sourceTypeCheck = sourceTypeCheck; - m_d->conversion = conversion; + S_D(ValueTypeEntry); + d->m_customConversion = customConversion; } -CustomConversion::TargetToNativeConversion::~TargetToNativeConversion() +CustomConversionPtr ValueTypeEntry::customConversion() const { - delete m_d; + S_D(const ValueTypeEntry); + return d->m_customConversion; } -const TypeEntry* CustomConversion::TargetToNativeConversion::sourceType() const +void ValueTypeEntry::setTargetConversionRule(const QString &conversionRule) { - return m_d->sourceType; + S_D(ValueTypeEntry); + d->m_targetConversionRule = conversionRule; } -void CustomConversion::TargetToNativeConversion::setSourceType(const TypeEntry* sourceType) +QString ValueTypeEntry::targetConversionRule() const { - m_d->sourceType = sourceType; + S_D(const ValueTypeEntry); + return d->m_targetConversionRule; } -bool CustomConversion::TargetToNativeConversion::isCustomType() const +bool ValueTypeEntry::hasTargetConversionRule() const { - return !(m_d->sourceType); + S_D(const ValueTypeEntry); + return !d->m_targetConversionRule.isEmpty(); } -QString CustomConversion::TargetToNativeConversion::sourceTypeName() const +bool ValueTypeEntry::isValue() const { - return m_d->sourceTypeName; + return true; } -QString CustomConversion::TargetToNativeConversion::sourceTypeCheck() const +TypeEntry *ValueTypeEntry::clone() const { - if (!m_d->sourceTypeCheck.isEmpty()) - return m_d->sourceTypeCheck; - - if (m_d->sourceType != nullptr && m_d->sourceType->isCustom()) { - const auto *cte = static_cast<const CustomTypeEntry *>(m_d->sourceType); - if (cte->hasCheckFunction()) { - QString result = cte->checkFunction(); - if (result != u"true") // For PyObject, which is always true - result += u"(%in)"_s; - return result; - } - } - - return {}; + S_D(const ValueTypeEntry); + return new ValueTypeEntry(new ValueTypeEntryPrivate(*d)); } -QString CustomConversion::TargetToNativeConversion::conversion() const +ValueTypeEntry::ValueTypeEntry(ComplexTypeEntryPrivate *d) : + ComplexTypeEntry(d) { - return m_d->conversion; } -void CustomConversion::TargetToNativeConversion::setConversion(const QString& conversion) +ValueTypeEntry::ValueTypeEntry(const QString &entryName, Type t, const QVersionNumber &vr, + const TypeEntryCPtr &parent) : + ComplexTypeEntry(entryName, t, vr, parent) { - m_d->conversion = conversion; } // ----------------- FunctionTypeEntry @@ -2269,19 +2363,19 @@ class FunctionTypeEntryPrivate : public TypeEntryPrivate public: FunctionTypeEntryPrivate(const QString &entryName, const QString &signature, const QVersionNumber &vr, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : TypeEntryPrivate(entryName, TypeEntry::FunctionType, vr, parent), m_signatures(signature) { } QStringList m_signatures; - TypeSystem::SnakeCase m_snakeCase = TypeSystem::SnakeCase::Unspecified; + QString m_docFile; }; FunctionTypeEntry::FunctionTypeEntry(const QString &entryName, const QString &signature, const QVersionNumber &vr, - const TypeEntry *parent) : + const TypeEntryCPtr &parent) : TypeEntry(new FunctionTypeEntryPrivate(entryName, signature, vr, parent)) { } @@ -2304,16 +2398,16 @@ bool FunctionTypeEntry::hasSignature(const QString &signature) const return d->m_signatures.contains(signature); } -TypeSystem::SnakeCase FunctionTypeEntry::snakeCase() const +QString FunctionTypeEntry::docFile() const { S_D(const FunctionTypeEntry); - return d->m_snakeCase; + return d->m_docFile; } -void FunctionTypeEntry::setSnakeCase(TypeSystem::SnakeCase sc) +void FunctionTypeEntry::setDocFile(const QString &df) { S_D(FunctionTypeEntry); - d->m_snakeCase = sc; + d->m_docFile = df; } TypeEntry *FunctionTypeEntry::clone() const @@ -2329,7 +2423,7 @@ FunctionTypeEntry::FunctionTypeEntry(FunctionTypeEntryPrivate *d) : // ----------------- ObjectTypeEntry ObjectTypeEntry::ObjectTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent) + const TypeEntryCPtr &parent) : ComplexTypeEntry(entryName, ObjectType, vr, parent) { } @@ -2359,20 +2453,6 @@ ObjectTypeEntry::ObjectTypeEntry(ComplexTypeEntryPrivate *d) : if (!var.isEmpty()) \ debug << ", " << var.size() << ' ' << name; -template <class Container, class Separator> -static void formatList(QDebug &d, const char *name, const Container &c, Separator sep) -{ - if (const int size = c.size()) { - d << ", " << name << '[' << size << "]=("; - for (int i = 0; i < size; ++i) { - if (i) - d << sep; - d << c.at(i); - } - d << ')'; - } -} - void TypeEntry::formatDebug(QDebug &debug) const { const QString cppName = qualifiedCppName(); @@ -2387,8 +2467,6 @@ void TypeEntry::formatDebug(QDebug &debug) const FORMAT_NONEMPTY_STRING("package", m_d->m_targetLangPackage) FORMAT_BOOL("stream", m_d->m_stream) FORMAT_BOOL("built-in", m_d->m_builtin) - FORMAT_LIST_SIZE("codeSnips", m_d->m_codeSnips) - FORMAT_NONEMPTY_STRING("targetConversionRule", m_d->m_targetConversionRule) if (m_d->m_viewOn) debug << ", views=" << m_d->m_viewOn->name(); if (!m_d->m_version.isNull() && m_d->m_version > QVersionNumber(0, 0)) @@ -2407,9 +2485,9 @@ void TypeEntry::formatDebug(QDebug &debug) const void PrimitiveTypeEntry::formatDebug(QDebug &debug) const { TypeEntry::formatDebug(debug); - if (auto *e = referencedTypeEntry()) { + if (auto e = referencedTypeEntry()) { debug << ", references"; - for (; e != nullptr; e = e->referencedTypeEntry()) + for (; e ; e = e->referencedTypeEntry()) debug << ":\"" << e->qualifiedCppName() <<'"'; } } @@ -2433,6 +2511,7 @@ void ComplexTypeEntry::formatDebug(QDebug &debug) const FORMAT_NONEMPTY_STRING("hash", d->m_hashFunction) FORMAT_LIST_SIZE("addedFunctions", d->m_addedFunctions) formatList(debug, "functionMods", d->m_functionMods, ", "); + FORMAT_LIST_SIZE("codeSnips", d->m_codeSnips) FORMAT_LIST_SIZE("fieldMods", d->m_fieldMods) } @@ -2456,8 +2535,7 @@ void FunctionTypeEntry::formatDebug(QDebug &debug) const S_D(const FunctionTypeEntry); TypeEntry::formatDebug(debug); - debug << "signatures=" << d->m_signatures - << ", snakeCase=" << int(d->m_snakeCase); + debug << "signatures=" << d->m_signatures; } void TypedefEntry::formatDebug(QDebug &debug) const @@ -2492,18 +2570,23 @@ void NamespaceTypeEntry::formatDebug(QDebug &debug) const debug << "[inline]"; } +QDebug operator<<(QDebug d, const OpaqueContainer &oc) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "OpaqueContainer(\"" << oc.name << "\": " << oc.templateParameters() << ')'; + return d; +} + void ContainerTypeEntry::formatDebug(QDebug &debug) const { S_D(const ContainerTypeEntry); ComplexTypeEntry::formatDebug(debug); debug << ", type=" << d->m_containerKind << '"'; - if (!d->m_opaqueContainers.isEmpty()) { - debug << ", opaque-containers=["; - for (const auto &r : d->m_opaqueContainers) - debug << r.instantiation << "->" << r.name << ','; - debug << ']'; - } + if (!d->m_opaqueContainers.isEmpty()) + debug << ", opaque-containers=[" << d->m_opaqueContainers << ']'; } void SmartPointerTypeEntry::formatDebug(QDebug &debug) const @@ -2514,8 +2597,11 @@ void SmartPointerTypeEntry::formatDebug(QDebug &debug) const if (!d->m_instantiations.isEmpty()) { debug << "type=" << d->m_type << ", instantiations[" << d->m_instantiations.size() << "]=("; - for (auto i : d->m_instantiations) - debug << i->name() << ','; + for (const auto &i : d->m_instantiations) { + debug << i.typeEntry->name() << ','; + if (!i.name.isEmpty()) + debug << "=\"" << i.name << '"'; + } debug << ')'; } } @@ -2534,6 +2620,12 @@ QDebug operator<<(QDebug d, const TypeEntry *te) return d; } +QDebug operator<<(QDebug d, const TypeEntryCPtr &te) +{ + d << te.get(); + return d; +} + QDebug operator<<(QDebug d, const TemplateEntry *te) { QDebugStateSaver saver(d); @@ -2548,4 +2640,10 @@ QDebug operator<<(QDebug d, const TemplateEntry *te) d << ')'; return d; } + +QDebug operator<<(QDebug d, const TemplateEntryCPtr &te) +{ + d << te.get(); + return d; +} #endif // QT_NO_DEBUG_STREAM diff --git a/sources/shiboken6/ApiExtractor/typesystem.h b/sources/shiboken6/ApiExtractor/typesystem.h index 186d82675..a2e4debc8 100644 --- a/sources/shiboken6/ApiExtractor/typesystem.h +++ b/sources/shiboken6/ApiExtractor/typesystem.h @@ -4,15 +4,14 @@ #ifndef TYPESYSTEM_H #define TYPESYSTEM_H -#include "typesystem_enums.h" -#include "typesystem_typedefs.h" #include "include.h" +#include "typesystem_typedefs.h" +#include <QtCore/qobjectdefs.h> #include <QtCore/QString> #include <QtCore/QScopedPointer> class AbstractMetaType; -class CustomConversion; class CustomTypeEntry; class PrimitiveTypeEntry; class SourceLocation; @@ -63,17 +62,14 @@ public: Q_ENUM(CodeGeneration) explicit TypeEntry(const QString &entryName, Type t, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); virtual ~TypeEntry(); Type type() const; - const TypeEntry *parent() const; - void setParent(const TypeEntry *p); - bool isChildOf(const TypeEntry *p) const; - const TypeSystemTypeEntry *typeSystemTypeEntry() const; - // cf AbstractMetaClass::targetLangEnclosingClass() - const TypeEntry *targetLangEnclosingEntry() const; + TypeEntryCPtr parent() const; + void setParent(const TypeEntryCPtr &); + bool isChildOf(const TypeEntryCPtr &p) const; bool isPrimitive() const; bool isEnum() const; @@ -134,9 +130,9 @@ public: /// be a JNI name, for Python it should represent the CPython type name. /// \return string representing the target language API name /// Currently used only for PrimitiveTypeEntry (attribute "target"). - const CustomTypeEntry *targetLangApiType() const; + CustomTypeEntryCPtr targetLangApiType() const; bool hasTargetLangApiType() const; - void setTargetLangApiType(CustomTypeEntry *cte); + void setTargetLangApiType(const CustomTypeEntryPtr &cte); QString targetLangApiName() const; // The type's name in TargetLang @@ -153,70 +149,32 @@ public: virtual bool isValue() const; virtual bool isComplex() const; - const CodeSnipList &codeSnips() const; - CodeSnipList &codeSnips(); - void setCodeSnips(const CodeSnipList &codeSnips); - void addCodeSnip(const CodeSnip &codeSnip); - - void setDocModification(const DocModificationList& docMods); - DocModificationList docModifications() const; - const IncludeList &extraIncludes() const; void setExtraIncludes(const IncludeList &includes); void addExtraInclude(const Include &newInclude); - /// Extra includes for function arguments determined by the meta builder. - const IncludeList &argumentIncludes() const; - void addArgumentInclude(const Include &newInclude); - Include include() const; void setInclude(const Include &inc); - // FIXME PYSIDE7: Remove - /// Set the target type conversion rule - void setTargetConversionRule(const QString& conversionRule); - - /// Returns the target type conversion rule - QString targetConversionRule() const; - QVersionNumber version() const; - /// TODO-CONVERTER: mark as deprecated - bool hasTargetConversionRule() const; - - bool isCppPrimitive() const; - - bool hasCustomConversion() const; - void setCustomConversion(CustomConversion* customConversion); - CustomConversion* customConversion() const; - // View on: Type to use for function argument conversion, fex // std::string_view -> std::string for foo(std::string_view). // cf AbstractMetaType::viewOn() - TypeEntry *viewOn() const; - void setViewOn(TypeEntry *v); + TypeEntryPtr viewOn() const; + void setViewOn(const TypeEntryPtr &v); virtual TypeEntry *clone() const; - void useAsTypedef(const TypeEntry *source); + void useAsTypedef(const TypeEntryCPtr &source); SourceLocation sourceLocation() const; void setSourceLocation(const SourceLocation &sourceLocation); - const PrimitiveTypeEntry *asPrimitive() const; - // Query functions for generators - /// Returns true if the type is a primitive but not a C++ primitive. - bool isUserPrimitive() const; /// Returns true if the type passed has a Python wrapper for it. /// Although namespace has a Python wrapper, it's not considered a type. bool isWrapperType() const; - /// Returns true if the type is a C++ integral primitive, - /// i.e. bool, char, int, long, and their unsigned counterparts. - bool isCppIntegralPrimitive() const; - /// Returns true if the type is an extended C++ primitive, a void*, - /// a const char*, or a std::string (cf isCppPrimitive()). - bool isExtendedCppPrimitive() const; #ifndef QT_NO_DEBUG_STREAM virtual void formatDebug(QDebug &d) const; @@ -236,4 +194,22 @@ private: QScopedPointer<TypeEntryPrivate> m_d; }; +TypeSystemTypeEntryCPtr typeSystemTypeEntry(TypeEntryCPtr e); + +// cf AbstractMetaClass::targetLangEnclosingClass() +TypeEntryCPtr targetLangEnclosingEntry(const TypeEntryCPtr &e); + +bool isCppPrimitive(const TypeEntryCPtr &e); + +/// Returns true if the type is a primitive but not a C++ primitive. +bool isUserPrimitive(const TypeEntryCPtr &e); + +/// Returns true if the type is a C++ integral primitive, +/// i.e. bool, char, int, long, and their unsigned counterparts. +bool isCppIntegralPrimitive(const TypeEntryCPtr &e); + +/// Returns true if the type is an extended C++ primitive, a void*, +/// a const char*, or a std::string (cf isCppPrimitive()). +bool isExtendedCppPrimitive(const TypeEntryCPtr &e); + #endif // TYPESYSTEM_H diff --git a/sources/shiboken6/ApiExtractor/typesystem_enums.h b/sources/shiboken6/ApiExtractor/typesystem_enums.h index eb73ff0f2..9ecbb08a1 100644 --- a/sources/shiboken6/ApiExtractor/typesystem_enums.h +++ b/sources/shiboken6/ApiExtractor/typesystem_enums.h @@ -35,6 +35,7 @@ enum CodeSnipPosition { CodeSnipPositionBeginning, CodeSnipPositionEnd, CodeSnipPositionDeclaration, + CodeSnipPositionPyOverride, CodeSnipPositionAny }; @@ -99,7 +100,9 @@ enum class SmartPointerType { enum class PythonEnumType { Unspecified, + Enum, IntEnum, + Flag, IntFlag }; diff --git a/sources/shiboken6/ApiExtractor/typesystem_typedefs.h b/sources/shiboken6/ApiExtractor/typesystem_typedefs.h index 3c1ad53f8..5a4e12ff2 100644 --- a/sources/shiboken6/ApiExtractor/typesystem_typedefs.h +++ b/sources/shiboken6/ApiExtractor/typesystem_typedefs.h @@ -4,24 +4,76 @@ #ifndef TYPESYSTEM_TYPEDEFS_H #define TYPESYSTEM_TYPEDEFS_H -#include <QtCore/QHash> -#include <QtCore/QList> -#include <QtCore/QSharedPointer> #include <QtCore/QList> -class CodeSnip; -class DocModification; +#include <memory> -struct AddedFunction; -class FieldModification; -class FunctionModification; +class ArrayTypeEntry; +class ComplexTypeEntry; +class ConfigurableTypeEntry; +class ConstantValueTypeEntry; +class ContainerTypeEntry; +class CustomTypeEntry; +class EnumTypeEntry; +class EnumValueTypeEntry; +class FlagsTypeEntry; +class FunctionTypeEntry; +class NamespaceTypeEntry; +class ObjectTypeEntry; +class PrimitiveTypeEntry; +class SmartPointerTypeEntry; +class TemplateEntry; class TypeEntry; +class TypedefEntry; +class TypeSystemTypeEntry; +class ValueTypeEntry; + +using ArrayTypeEntryPtr = std::shared_ptr<ArrayTypeEntry>; +using ComplexTypeEntryPtr = std::shared_ptr<ComplexTypeEntry>; +using ConfigurableTypeEntryPtr = std::shared_ptr<ConfigurableTypeEntry>; +using ConstantValueTypeEntryPtr = std::shared_ptr<ConstantValueTypeEntry>; +using ContainerTypeEntryPtr = std::shared_ptr<ContainerTypeEntry>; +using CustomTypeEntryPtr = std::shared_ptr<CustomTypeEntry>; +using EnumTypeEntryPtr = std::shared_ptr<EnumTypeEntry>; +using EnumValueTypeEntryPtr = std::shared_ptr<EnumValueTypeEntry>; +using FlagsTypeEntryPtr = std::shared_ptr<FlagsTypeEntry>; +using FunctionTypeEntryPtr = std::shared_ptr<FunctionTypeEntry>; +using NamespaceTypeEntryPtr = std::shared_ptr<NamespaceTypeEntry>; +using ObjectTypeEntryPtr = std::shared_ptr<ObjectTypeEntry>; +using PrimitiveTypeEntryPtr = std::shared_ptr<PrimitiveTypeEntry>; +using SmartPointerTypeEntryPtr = std::shared_ptr<SmartPointerTypeEntry>; +using TemplateEntryPtr = std::shared_ptr<TemplateEntry>; +using TypeEntryPtr = std::shared_ptr<TypeEntry>; +using TypedefEntryPtr = std::shared_ptr<TypedefEntry>; +using TypeSystemTypeEntryPtr = std::shared_ptr<TypeSystemTypeEntry>; +using ValueTypeEntryPtr = std::shared_ptr<ValueTypeEntry>; + +using ArrayTypeEntryCPtr = std::shared_ptr<const ArrayTypeEntry>; +using ComplexTypeEntryCPtr = std::shared_ptr<const ComplexTypeEntry>; +using ConstantValueTypeEntryCPtr = std::shared_ptr<const ConstantValueTypeEntry>; +using ConfigurableTypeEntryCPtr = std::shared_ptr<const ConfigurableTypeEntry>; +using ContainerTypeEntryCPtr = std::shared_ptr<const ContainerTypeEntry>; +using CustomTypeEntryCPtr = std::shared_ptr<const CustomTypeEntry>; +using EnumTypeEntryCPtr = std::shared_ptr<const EnumTypeEntry>; +using EnumValueTypeEntryCPtr = std::shared_ptr<const EnumValueTypeEntry>; +using FlagsTypeEntryCPtr = std::shared_ptr<const FlagsTypeEntry>; +using FunctionTypeEntryCPtr = std::shared_ptr<const FunctionTypeEntry>; +using NamespaceTypeEntryCPtr = std::shared_ptr<const NamespaceTypeEntry>; +using ObjectTypeEntryCPtr = std::shared_ptr<const ObjectTypeEntry>; +using PrimitiveTypeEntryCPtr = std::shared_ptr<const PrimitiveTypeEntry>; +using SmartPointerTypeEntryCPtr = std::shared_ptr<const SmartPointerTypeEntry>; +using TemplateEntryCPtr = std::shared_ptr<const TemplateEntry>; +using TypeEntryCPtr = std::shared_ptr<const TypeEntry>; +using TypedefEntryCPtr = std::shared_ptr<const TypedefEntry>; +using TypeSystemTypeEntryCPtr = std::shared_ptr<const TypeSystemTypeEntry>; +using ValueTypeEntryCPtr = std::shared_ptr<const ValueTypeEntry>; + +using ComplexTypeEntryCList = QList<ComplexTypeEntryCPtr>; +using ContainerTypeEntryCList = QList<ContainerTypeEntryCPtr>; +using NamespaceTypeEntryList = QList<NamespaceTypeEntryPtr>; +using PrimitiveTypeEntryCList = QList<PrimitiveTypeEntryCPtr>; +using SmartPointerTypeEntryList = QList<SmartPointerTypeEntryCPtr>; +using TypeEntryList = QList<TypeEntryPtr>; +using TypeEntryCList = QList<TypeEntryCPtr>; -using AddedFunctionPtr = QSharedPointer<AddedFunction>; -using AddedFunctionList = QList<AddedFunctionPtr>; -using CodeSnipList = QList<CodeSnip>; -using DocModificationList = QList<DocModification>; -using FieldModificationList = QList<FieldModification>; -using FunctionModificationList = QList<FunctionModification>; -using TypeEntries = QList<const TypeEntry *>; #endif // TYPESYSTEM_TYPEDEFS_H diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp index 4a0ea347c..2b686e997 100644 --- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp @@ -2,22 +2,19 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "typesystemparser_p.h" +#include "anystringview_helpers.h" +#include "addedfunction.h" #include "codesnip.h" #include "enumtypeentry.h" -#include "enumvaluetypeentry.h" -#include "arraytypeentry.h" -#include "constantvaluetypeentry.h" #include "containertypeentry.h" #include "customconversion.h" #include "customtypenentry.h" -#include "enumtypeentry.h" #include "flagstypeentry.h" #include "functiontypeentry.h" #include "namespacetypeentry.h" #include "objecttypeentry.h" #include "primitivetypeentry.h" #include "smartpointertypeentry.h" -#include "templateargumententry.h" #include "typedefentry.h" #include "typesystemtypeentry.h" #include "valuetypeentry.h" @@ -49,77 +46,84 @@ using namespace Qt::StringLiterals; -static inline QString allowThreadAttribute() { return QStringLiteral("allow-thread"); } -static inline QString colonColon() { return QStringLiteral("::"); } -static inline QString checkFunctionAttribute() { return QStringLiteral("check-function"); } -static inline QString copyableAttribute() { return QStringLiteral("copyable"); } -static inline QString accessAttribute() { return QStringLiteral("access"); } -static inline QString actionAttribute() { return QStringLiteral("action"); } -static inline QString quoteAfterLineAttribute() { return QStringLiteral("quote-after-line"); } -static inline QString quoteBeforeLineAttribute() { return QStringLiteral("quote-before-line"); } -static inline QString textAttribute() { return QStringLiteral("text"); } -static inline QString nameAttribute() { return QStringLiteral("name"); } -static inline QString sinceAttribute() { return QStringLiteral("since"); } -static inline QString untilAttribute() { return QStringLiteral("until"); } -static inline QString defaultSuperclassAttribute() { return QStringLiteral("default-superclass"); } -static inline QString deleteInMainThreadAttribute() { return QStringLiteral("delete-in-main-thread"); } -static inline QString deprecatedAttribute() { return QStringLiteral("deprecated"); } -static inline QString disableWrapperAttribute() { return QStringLiteral("disable-wrapper"); } -static inline QString exceptionHandlingAttribute() { return QStringLiteral("exception-handling"); } -static inline QString extensibleAttribute() { return QStringLiteral("extensible"); } -static inline QString fileNameAttribute() { return QStringLiteral("file-name"); } -static inline QString flagsAttribute() { return QStringLiteral("flags"); } -static inline QString forceAbstractAttribute() { return QStringLiteral("force-abstract"); } -static inline QString forceIntegerAttribute() { return QStringLiteral("force-integer"); } -static inline QString formatAttribute() { return QStringLiteral("format"); } -static inline QString generateUsingAttribute() { return QStringLiteral("generate-using"); } -static inline QString generateFunctionsAttribute() { return QStringLiteral("generate-functions"); } -static inline QString classAttribute() { return QStringLiteral("class"); } -static inline QString generateAttribute() { return QStringLiteral("generate"); } -static inline QString generateGetSetDefAttribute() { return QStringLiteral("generate-getsetdef"); } -static inline QString genericClassAttribute() { return QStringLiteral("generic-class"); } -static inline QString indexAttribute() { return QStringLiteral("index"); } -static inline QString invalidateAfterUseAttribute() { return QStringLiteral("invalidate-after-use"); } -static inline QString isNullAttribute() { return QStringLiteral("isNull"); } -static inline QString locationAttribute() { return QStringLiteral("location"); } -static inline QString modifiedTypeAttribute() { return QStringLiteral("modified-type"); } -static inline QString operatorBoolAttribute() { return QStringLiteral("operator-bool"); } -static inline QString parentManagementAttribute() { return QStringLiteral("parent-management"); } -static inline QString pyiTypeAttribute() { return QStringLiteral("pyi-type"); } -static inline QString overloadNumberAttribute() { return QStringLiteral("overload-number"); } -static inline QString ownershipAttribute() { return QStringLiteral("owner"); } -static inline QString packageAttribute() { return QStringLiteral("package"); } -static inline QString positionAttribute() { return QStringLiteral("position"); } -static inline QString preferredConversionAttribute() { return QStringLiteral("preferred-conversion"); } -static inline QString preferredTargetLangTypeAttribute() { return QStringLiteral("preferred-target-lang-type"); } -static inline QString pythonEnumTypeAttribute() { return QStringLiteral("python-type"); } -static inline QString qtMetaTypeAttribute() { return QStringLiteral("qt-register-metatype"); } -static inline QString removeAttribute() { return QStringLiteral("remove"); } -static inline QString renameAttribute() { return QStringLiteral("rename"); } -static inline QString readAttribute() { return QStringLiteral("read"); } -static inline QString targetLangNameAttribute() { return QStringLiteral("target-lang-name"); } -static inline QString writeAttribute() { return QStringLiteral("write"); } -static inline QString opaqueContainerFieldAttribute() { return QStringLiteral("opaque-container"); } -static inline QString replaceAttribute() { return QStringLiteral("replace"); } -static inline QString toAttribute() { return QStringLiteral("to"); } -static inline QString signatureAttribute() { return QStringLiteral("signature"); } -static inline QString snippetAttribute() { return QStringLiteral("snippet"); } -static inline QString snakeCaseAttribute() { return QStringLiteral("snake-case"); } -static inline QString staticAttribute() { return QStringLiteral("static"); } -static inline QString classmethodAttribute() { return QStringLiteral("classmethod"); } -static inline QString threadAttribute() { return QStringLiteral("thread"); } -static inline QString sourceAttribute() { return QStringLiteral("source"); } -static inline QString streamAttribute() { return QStringLiteral("stream"); } -static inline QString privateAttribute() { return QStringLiteral("private"); } -static inline QString xPathAttribute() { return QStringLiteral("xpath"); } -static inline QString virtualSlotAttribute() { return QStringLiteral("virtual-slot"); } -static inline QString visibleAttribute() { return QStringLiteral("visible"); } -static inline QString enumIdentifiedByValueAttribute() { return QStringLiteral("identified-by-value"); } - -static inline QString noAttributeValue() { return QStringLiteral("no"); } -static inline QString yesAttributeValue() { return QStringLiteral("yes"); } -static inline QString trueAttributeValue() { return QStringLiteral("true"); } -static inline QString falseAttributeValue() { return QStringLiteral("false"); } +constexpr auto allowThreadAttribute = "allow-thread"_L1; +constexpr auto checkFunctionAttribute = "check-function"_L1; +constexpr auto copyableAttribute = "copyable"_L1; +constexpr auto accessAttribute = "access"_L1; +constexpr auto actionAttribute = "action"_L1; +constexpr auto quoteAfterLineAttribute = "quote-after-line"_L1; +constexpr auto quoteBeforeLineAttribute = "quote-before-line"_L1; +constexpr auto textAttribute = "text"_L1; +constexpr auto nameAttribute = "name"_L1; +constexpr auto sinceAttribute = "since"_L1; +constexpr auto untilAttribute = "until"_L1; +constexpr auto defaultSuperclassAttribute = "default-superclass"_L1; +constexpr auto deleteInMainThreadAttribute = "delete-in-main-thread"_L1; +constexpr auto deprecatedAttribute = "deprecated"_L1; +constexpr auto disableWrapperAttribute = "disable-wrapper"_L1; +constexpr auto docFileAttribute = "doc-file"_L1; +constexpr auto exceptionHandlingAttribute = "exception-handling"_L1; +constexpr auto extensibleAttribute = "extensible"_L1; +constexpr auto fileNameAttribute = "file-name"_L1; +constexpr auto fileAttribute = "file"_L1; +constexpr auto flagsAttribute = "flags"_L1; +constexpr auto forceAbstractAttribute = "force-abstract"_L1; +constexpr auto forceIntegerAttribute = "force-integer"_L1; +constexpr auto formatAttribute = "format"_L1; +constexpr auto generateUsingAttribute = "generate-using"_L1; +constexpr auto generateFunctionsAttribute = "generate-functions"_L1; +constexpr auto classAttribute = "class"_L1; +constexpr auto generateAttribute = "generate"_L1; +constexpr auto generateGetSetDefAttribute = "generate-getsetdef"_L1; +constexpr auto genericClassAttribute = "generic-class"_L1; +constexpr auto indexAttribute = "index"_L1; +constexpr auto invalidateAfterUseAttribute = "invalidate-after-use"_L1; +constexpr auto isNullAttribute = "isNull"_L1; +constexpr auto locationAttribute = "location"_L1; +constexpr auto modifiedTypeAttribute = "modified-type"_L1; +constexpr auto opaqueContainerAttribute = "opaque-containers"_L1; +constexpr auto operatorBoolAttribute = "operator-bool"_L1; +constexpr auto parentManagementAttribute = "parent-management"_L1; +constexpr auto pyiTypeAttribute = "pyi-type"_L1; +constexpr auto overloadNumberAttribute = "overload-number"_L1; +constexpr auto ownershipAttribute = "owner"_L1; +constexpr auto packageAttribute = "package"_L1; +constexpr auto polymorphicBaseAttribute = "polymorphic-base"_L1; +constexpr auto positionAttribute = "position"_L1; +constexpr auto preferredConversionAttribute = "preferred-conversion"_L1; +constexpr auto preferredTargetLangTypeAttribute = "preferred-target-lang-type"_L1; +constexpr auto pythonEnumTypeAttribute = "python-type"_L1; +constexpr auto pythonOverrideAttribute = "python-override"_L1; +constexpr auto cppEnumTypeAttribute = "cpp-type"_L1; +constexpr auto qtMetaObjectFunctionsAttribute = "qt-metaobject"_L1; +constexpr auto qtMetaTypeAttribute = "qt-register-metatype"_L1; +constexpr auto removeAttribute = "remove"_L1; +constexpr auto renameAttribute = "rename"_L1; +constexpr auto readAttribute = "read"_L1; +constexpr auto targetLangNameAttribute = "target-lang-name"_L1; +constexpr auto writeAttribute = "write"_L1; +constexpr auto opaqueContainerFieldAttribute = "opaque-container"_L1; +constexpr auto replaceAttribute = "replace"_L1; +constexpr auto toAttribute = "to"_L1; +constexpr auto signatureAttribute = "signature"_L1; +constexpr auto snippetAttribute = "snippet"_L1; +constexpr auto snakeCaseAttribute = "snake-case"_L1; +constexpr auto staticAttribute = "static"_L1; +constexpr auto classmethodAttribute = "classmethod"_L1; +constexpr auto threadAttribute = "thread"_L1; +constexpr auto sourceAttribute = "source"_L1; +constexpr auto streamAttribute = "stream"_L1; +constexpr auto privateAttribute = "private"_L1; +constexpr auto xPathAttribute = "xpath"_L1; +constexpr auto virtualSlotAttribute = "virtual-slot"_L1; +constexpr auto visibleAttribute = "visible"_L1; +constexpr auto enumIdentifiedByValueAttribute = "identified-by-value"_L1; +constexpr auto subModuleOfAttribute = "submodule-of"_L1; + +constexpr auto noAttributeValue = "no"_L1; +constexpr auto yesAttributeValue = "yes"_L1; +constexpr auto trueAttributeValue = "true"_L1; +constexpr auto falseAttributeValue = "false"_L1; static bool isTypeEntry(StackElement el) { @@ -136,7 +140,7 @@ static bool isDocumentation(StackElement el) return el >= StackElement::FirstDocumentation && el <= StackElement::LastDocumentation; } -static QList<CustomConversion *> customConversionsForReview; +static QList<CustomConversionPtr> customConversionsForReview; // Set a regular expression for rejection from text. By legacy, those are fixed // strings, except for '*' meaning 'match all'. Enclosing in "^..$" @@ -149,7 +153,7 @@ static bool setRejectionRegularExpression(const QString &patternIn, if (patternIn.startsWith(u'^') && patternIn.endsWith(u'$')) pattern = patternIn; else if (patternIn == u"*") - pattern = QStringLiteral("^.*$"); + pattern = "^.*$"_L1; else pattern = u'^' + QRegularExpression::escape(patternIn) + u'$'; re->setPattern(pattern); @@ -160,15 +164,20 @@ static bool setRejectionRegularExpression(const QString &patternIn, return true; } +static inline bool hasFileSnippetAttributes(const QXmlStreamAttributes *attributes) +{ + return attributes->hasAttribute(fileAttribute); +} + // Extract a snippet from a file within annotation "// @snippet label". std::optional<QString> extractSnippet(const QString &code, const QString &snippetLabel) { if (snippetLabel.isEmpty()) return code; - const QString pattern = QStringLiteral(R"(^\s*//\s*@snippet\s+)") + const QString pattern = R"(^\s*//\s*@snippet\s+)"_L1 + QRegularExpression::escape(snippetLabel) - + QStringLiteral(R"(\s*$)"); + + R"(\s*$)"_L1; const QRegularExpression snippetRe(pattern); Q_ASSERT(snippetRe.isValid()); @@ -177,7 +186,7 @@ std::optional<QString> QString result; const auto lines = QStringView{code}.split(u'\n'); for (const auto &line : lines) { - if (snippetRe.match(line).hasMatch()) { + if (snippetRe.matchView(line).hasMatch()) { foundLabel = true; useLine = !useLine; if (!useLine) @@ -190,48 +199,31 @@ std::optional<QString> return CodeSnipAbstract::fixSpaces(result); } -template <class EnumType, Qt::CaseSensitivity cs = Qt::CaseInsensitive> +template <class EnumType> struct EnumLookup { QStringView name; EnumType value; }; -template <class EnumType, Qt::CaseSensitivity cs> -bool operator==(const EnumLookup<EnumType, cs> &e1, const EnumLookup<EnumType, cs> &e2) -{ - return e1.name.compare(e2.name, cs) == 0; -} - -template <class EnumType, Qt::CaseSensitivity cs> -bool operator<(const EnumLookup<EnumType, cs> &e1, const EnumLookup<EnumType, cs> &e2) -{ - return e1.name.compare(e2.name, cs) < 0; -} - // Helper macros to define lookup functions that take a QStringView needle // and an optional default return value. #define ENUM_LOOKUP_BEGIN(EnumType, caseSensitivity, functionName) \ static std::optional<EnumType> functionName(QStringView needle) \ { \ - using HaystackEntry = EnumLookup<EnumType, caseSensitivity>; \ - static const HaystackEntry haystack[] = - -#define ENUM_LOOKUP_LINEAR_SEARCH() \ - const auto end = haystack + sizeof(haystack) / sizeof(haystack[0]); \ - const auto it = std::find(haystack, end, HaystackEntry{needle, {} }); \ + using HaystackEntry = EnumLookup<EnumType>; \ + constexpr auto cs = caseSensitivity; \ + static constexpr HaystackEntry haystack[] = + +#define ENUM_LOOKUP_LINEAR_SEARCH \ + auto pred = [cs, needle](const HaystackEntry &he) { \ + return he.name.compare(needle, cs) == 0; \ + }; \ + auto end = std::cend(haystack); \ + auto it = std::find_if(std::cbegin(haystack), end, pred); \ if (it != end) \ return it->value; \ - return {}; \ -} - -#define ENUM_LOOKUP_BINARY_SEARCH() \ - const auto end = haystack + sizeof(haystack) / sizeof(haystack[0]); \ - const HaystackEntry needleEntry{needle, {} }; \ - const auto lb = std::lower_bound(haystack, end, needleEntry); \ - if (lb != end && *lb == needleEntry) \ - return lb->value; \ - return {}; \ + return std::nullopt; \ } ENUM_LOOKUP_BEGIN(TypeSystem::AllowThread, Qt::CaseInsensitive, @@ -243,7 +235,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::AllowThread, Qt::CaseInsensitive, {u"no", TypeSystem::AllowThread::Disallow}, {u"false", TypeSystem::AllowThread::Disallow}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::BoolCast, Qt::CaseInsensitive, @@ -254,15 +246,17 @@ ENUM_LOOKUP_BEGIN(TypeSystem::BoolCast, Qt::CaseInsensitive, {u"no", TypeSystem::BoolCast::Disabled}, {u"false", TypeSystem::BoolCast::Disabled}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::PythonEnumType, Qt::CaseSensitive, pythonEnumTypeFromAttribute) { + {u"Enum", TypeSystem::PythonEnumType::Enum}, {u"IntEnum", TypeSystem::PythonEnumType::IntEnum}, - {u"IntFlag", TypeSystem::PythonEnumType::IntFlag} + {u"Flag", TypeSystem::PythonEnumType::Flag}, + {u"IntFlag", TypeSystem::PythonEnumType::IntFlag}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::QtMetaTypeRegistration, Qt::CaseSensitive, qtMetaTypeFromAttribute) @@ -273,7 +267,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::QtMetaTypeRegistration, Qt::CaseSensitive, {u"no", TypeSystem::QtMetaTypeRegistration::Disabled}, {u"false", TypeSystem::QtMetaTypeRegistration::Disabled}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::Language, Qt::CaseInsensitive, languageFromAttribute) @@ -283,7 +277,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::Language, Qt::CaseInsensitive, {u"shell", TypeSystem::ShellCode}, // coloca no header, mas antes da declaracao da classe {u"target", TypeSystem::TargetLangCode} // em algum lugar do cpp }; -ENUM_LOOKUP_BINARY_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::Ownership, Qt::CaseInsensitive, ownershipFromFromAttribute) @@ -292,7 +286,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::Ownership, Qt::CaseInsensitive, {u"c++", TypeSystem::CppOwnership}, {u"default", TypeSystem::DefaultOwnership} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(AddedFunction::Access, Qt::CaseInsensitive, addedFunctionAccessFromAttribute) @@ -300,7 +294,7 @@ ENUM_LOOKUP_BEGIN(AddedFunction::Access, Qt::CaseInsensitive, {u"public", AddedFunction::Public}, {u"protected", AddedFunction::Protected}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(FunctionModification::ModifierFlag, Qt::CaseSensitive, modifierFromAttribute) @@ -308,12 +302,11 @@ ENUM_LOOKUP_BEGIN(FunctionModification::ModifierFlag, Qt::CaseSensitive, {u"private", FunctionModification::Private}, {u"public", FunctionModification::Public}, {u"protected", FunctionModification::Protected}, - {u"friendly", FunctionModification::Friendly}, {u"rename", FunctionModification::Rename}, {u"final", FunctionModification::Final}, {u"non-final", FunctionModification::NonFinal} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(ReferenceCount::Action, Qt::CaseInsensitive, referenceCountFromAttribute) @@ -324,7 +317,7 @@ ENUM_LOOKUP_BEGIN(ReferenceCount::Action, Qt::CaseInsensitive, {u"set", ReferenceCount::Set}, {u"ignore", ReferenceCount::Ignore} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(ArgumentOwner::Action, Qt::CaseInsensitive, argumentOwnerActionFromAttribute) @@ -332,16 +325,17 @@ ENUM_LOOKUP_BEGIN(ArgumentOwner::Action, Qt::CaseInsensitive, {u"add", ArgumentOwner::Add}, {u"remove", ArgumentOwner::Remove} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::CodeSnipPosition, Qt::CaseInsensitive, codeSnipPositionFromAttribute) { {u"beginning", TypeSystem::CodeSnipPositionBeginning}, {u"end", TypeSystem::CodeSnipPositionEnd}, - {u"declaration", TypeSystem::CodeSnipPositionDeclaration} + {u"declaration", TypeSystem::CodeSnipPositionDeclaration}, + {u"override", TypeSystem::CodeSnipPositionPyOverride} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(Include::IncludeType, Qt::CaseInsensitive, locationFromAttribute) @@ -350,7 +344,7 @@ ENUM_LOOKUP_BEGIN(Include::IncludeType, Qt::CaseInsensitive, {u"local", Include::LocalPath}, {u"target", Include::TargetLangImport} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::DocModificationMode, Qt::CaseInsensitive, docModificationFromAttribute) @@ -359,7 +353,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::DocModificationMode, Qt::CaseInsensitive, {u"prepend", TypeSystem::DocModificationPrepend}, {u"replace", TypeSystem::DocModificationReplace} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(ContainerTypeEntry::ContainerKind, Qt::CaseSensitive, containerTypeFromAttribute) @@ -375,9 +369,10 @@ ENUM_LOOKUP_BEGIN(ContainerTypeEntry::ContainerKind, Qt::CaseSensitive, {u"multi-map", ContainerTypeEntry::MultiMapContainer}, {u"hash", ContainerTypeEntry::MapContainer}, {u"multi-hash", ContainerTypeEntry::MultiMapContainer}, - {u"pair", ContainerTypeEntry::PairContainer} + {u"pair", ContainerTypeEntry::PairContainer}, + {u"span", ContainerTypeEntry::SpanContainer} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeRejection::MatchType, Qt::CaseSensitive, typeRejectionFromAttribute) @@ -389,7 +384,7 @@ ENUM_LOOKUP_BEGIN(TypeRejection::MatchType, Qt::CaseSensitive, {u"argument-type", TypeRejection::ArgumentType}, {u"return-type", TypeRejection::ReturnType} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::ExceptionHandling, Qt::CaseSensitive, exceptionHandlingFromAttribute) @@ -401,7 +396,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::ExceptionHandling, Qt::CaseSensitive, {u"yes", TypeSystem::ExceptionHandling::On}, {u"true", TypeSystem::ExceptionHandling::On}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::SmartPointerType, Qt::CaseSensitive, smartPointerTypeFromAttribute) @@ -411,7 +406,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::SmartPointerType, Qt::CaseSensitive, {u"value-handle", TypeSystem::SmartPointerType::ValueHandle}, {u"shared", TypeSystem::SmartPointerType::Shared} }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH template <class EnumType> static std::optional<EnumType> @@ -440,6 +435,7 @@ static const StackElementHash &stackElementHash() {u"add-function", StackElement::AddFunction}, {u"add-pymethoddef", StackElement::AddPyMethodDef}, {u"array", StackElement::Array}, + {u"configuration", StackElement::Configuration}, {u"container-type", StackElement::ContainerTypeEntry}, {u"conversion-rule", StackElement::ConversionRule}, {u"custom-constructor", StackElement::Unimplemented}, @@ -465,6 +461,7 @@ static const StackElementHash &stackElementHash() {u"native-to-target", StackElement::NativeToTarget}, {u"no-null-pointer", StackElement::NoNullPointers}, {u"object-type", StackElement::ObjectTypeEntry}, + {u"opaque-container", StackElement::OpaqueContainer}, {u"parent", StackElement::ParentOwner}, {u"primitive-type", StackElement::PrimitiveTypeEntry}, {u"property", StackElement::Property}, @@ -520,7 +517,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::SnakeCase, Qt::CaseSensitive, {u"true", TypeSystem::SnakeCase::Enabled}, {u"both", TypeSystem::SnakeCase::Both}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH ENUM_LOOKUP_BEGIN(TypeSystem::Visibility, Qt::CaseSensitive, visibilityFromAttribute) @@ -531,12 +528,12 @@ ENUM_LOOKUP_BEGIN(TypeSystem::Visibility, Qt::CaseSensitive, {u"yes", TypeSystem::Visibility::Visible}, {u"true", TypeSystem::Visibility::Visible}, }; -ENUM_LOOKUP_LINEAR_SEARCH() +ENUM_LOOKUP_LINEAR_SEARCH static int indexOfAttribute(const QXmlStreamAttributes &atts, - QStringView name) + QAnyStringView name) { - for (int i = 0, size = atts.size(); i < size; ++i) { + for (qsizetype i = 0, size = atts.size(); i < size; ++i) { if (atts.at(i).qualifiedName() == name) return i; } @@ -567,7 +564,7 @@ static QString msgUnusedAttributes(QStringView tag, const QXmlStreamAttributes & QString result; QTextStream str(&result); str << attributes.size() << " attributes(s) unused on <" << tag << ">: "; - for (int i = 0, size = attributes.size(); i < size; ++i) { + for (qsizetype i = 0, size = attributes.size(); i < size; ++i) { if (i) str << ", "; str << attributes.at(i); @@ -602,17 +599,17 @@ QString TypeSystemEntityResolver::readFile(const QString &entityName, QString *e path = TypeDatabase::instance()->modifiedTypesystemFilepath(fileName, m_currentPath); if (!QFileInfo::exists(path)) { *errorMessage = u"Unable to resolve: "_s + entityName; - return QString(); + return {}; } QFile file(path); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { *errorMessage = msgCannotOpenForReading(file); - return QString(); + return {}; } QString result = QString::fromUtf8(file.readAll()).trimmed(); // Remove license header comments on which QXmlStreamReader chokes if (result.startsWith(u"<!--")) { - const int commentEnd = result.indexOf(u"-->"); + const auto commentEnd = result.indexOf(u"-->"); if (commentEnd != -1) { result.remove(0, commentEnd + 3); result = result.trimmed(); @@ -647,7 +644,7 @@ enum class ParserState Template }; -TypeSystemParser::TypeSystemParser(const QSharedPointer<TypeDatabaseParserContext> &context, +TypeSystemParser::TypeSystemParser(const std::shared_ptr<TypeDatabaseParserContext> &context, bool generate) : m_context(context), m_generate(generate ? TypeEntry::GenerateCode : TypeEntry::GenerateForSubclass) @@ -690,7 +687,7 @@ static QString msgReaderError(const ConditionalStreamReader &reader, const QStri } static QString msgUnimplementedElementWarning(const ConditionalStreamReader &reader, - QStringView name) + QAnyStringView name) { QString message; QTextStream(&message) << "The element \"" << name @@ -715,7 +712,7 @@ static inline QString msgUnimplementedAttributeWarning(const ConditionalStreamRe static QString msgUnimplementedAttributeValueWarning(const ConditionalStreamReader &reader, - QStringView name, QStringView value) + QAnyStringView name, QAnyStringView value) { QString message; QTextStream(&message) << "The value \"" << value @@ -732,21 +729,22 @@ static inline attribute.value()); } -static bool addRejection(TypeDatabase *database, QXmlStreamAttributes *attributes, +static bool addRejection(TypeDatabase *database, bool generate, QXmlStreamAttributes *attributes, QString *errorMessage) { - const int classIndex = indexOfAttribute(*attributes, classAttribute()); + const auto classIndex = indexOfAttribute(*attributes, classAttribute); if (classIndex == -1) { - *errorMessage = msgMissingAttribute(classAttribute()); + *errorMessage = msgMissingAttribute(classAttribute); return false; } TypeRejection rejection; + rejection.generate = generate; const QString className = attributes->takeAt(classIndex).value().toString(); if (!setRejectionRegularExpression(className, &rejection.className, errorMessage)) return false; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto &attribute = attributes->at(i); const auto name = attribute.qualifiedName(); const auto typeOpt = typeRejectionFromAttribute(name); @@ -873,13 +871,14 @@ bool TypeSystemParser::endElement(StackElement element) if (m_generate == TypeEntry::GenerateCode) { TypeDatabase::instance()->addGlobalUserFunctions(top->addedFunctions); TypeDatabase::instance()->addGlobalUserFunctionModifications(top->functionMods); - for (CustomConversion *customConversion : qAsConst(customConversionsForReview)) { - const CustomConversion::TargetToNativeConversions &toNatives = customConversion->targetToNativeConversions(); - for (CustomConversion::TargetToNativeConversion *toNative : toNatives) - toNative->setSourceType(m_context->db->findType(toNative->sourceTypeName())); + for (const auto &customConversion : std::as_const(customConversionsForReview)) { + TargetToNativeConversions &toNatives = + customConversion->targetToNativeConversions(); + for (auto &toNative : toNatives) + toNative.setSourceType(m_context->db->findType(toNative.sourceTypeName())); } } - purgeEmptyCodeSnips(&top->entry->codeSnips()); + purgeEmptyCodeSnips(&std::static_pointer_cast<TypeSystemTypeEntry>(top->entry)->codeSnips()); break; case StackElement::FunctionTypeEntry: TypeDatabase::instance()->addGlobalUserFunctionModifications(top->functionMods); @@ -891,7 +890,7 @@ bool TypeSystemParser::endElement(StackElement element) case StackElement::NamespaceTypeEntry: { Q_ASSERT(top->entry); Q_ASSERT(top->entry->isComplex()); - auto *centry = static_cast<ComplexTypeEntry *>(top->entry); + auto centry = std::static_pointer_cast<ComplexTypeEntry>(top->entry); purgeEmptyCodeSnips(¢ry->codeSnips()); centry->setAddedFunctions(top->addedFunctions); centry->setFunctionModifications(top->functionMods); @@ -901,12 +900,15 @@ bool TypeSystemParser::endElement(StackElement element) break; case StackElement::TypedefTypeEntry: { - auto *centry = static_cast<TypedefEntry *>(top->entry)->target(); + auto centry = std::static_pointer_cast<TypedefEntry>(top->entry)->target(); centry->setAddedFunctions(centry->addedFunctions() + top->addedFunctions); centry->setFunctionModifications(centry->functionModifications() + top->functionMods); centry->setFieldModifications(centry->fieldModifications() + top->fieldMods); - centry->setCodeSnips(centry->codeSnips() + top->entry->codeSnips()); centry->setDocModification(centry->docModifications() + top->docModifications); + if (top->entry->isComplex()) { + auto cte = std::static_pointer_cast<const ComplexTypeEntry>(top->entry); + centry->setCodeSnips(centry->codeSnips() + cte->codeSnips()); + } } break; @@ -918,29 +920,30 @@ bool TypeSystemParser::endElement(StackElement element) Q_ASSERT(modIndex >= 0); Q_ASSERT(!top->addedFunctions.isEmpty()); while (modIndex < top->functionMods.size()) - top->addedFunctions.last()->modifications.append(top->functionMods.takeAt(modIndex)); + top->addedFunctions.last()->modifications().append(top->functionMods.takeAt(modIndex)); } break; case StackElement::NativeToTarget: case StackElement::AddConversion: switch (parserState()) { case ParserState::PrimitiveTypeNativeToTargetConversion: - case ParserState::PrimitiveTypeTargetToNativeConversion: - if (auto *customConversion = top->entry->customConversion()) { - QString code = top->conversionCodeSnips.constLast().code(); - if (element == StackElement::AddConversion) { - if (customConversion->targetToNativeConversions().isEmpty()) { - m_error = u"CustomConversion's target to native conversions missing."_s; - return false; - } - customConversion->targetToNativeConversions().last()->setConversion(code); - } else { - customConversion->setNativeToTargetConversion(code); + case ParserState::PrimitiveTypeTargetToNativeConversion: { + auto customConversion = CustomConversion::getCustomConversion(top->entry); + if (!customConversion) { + m_error = msgMissingCustomConversion(top->entry); + return false; + } + QString code = top->conversionCodeSnips.constLast().code(); + if (element == StackElement::AddConversion) { + if (customConversion->targetToNativeConversions().isEmpty()) { + m_error = u"CustomConversion's target to native conversions missing."_s; + return false; } + customConversion->targetToNativeConversions().last().setConversion(code); } else { - m_error = u"CustomConversion object is missing."_s; - return false; + customConversion->setNativeToTargetConversion(code); } + } break; case ParserState::ArgumentNativeToTargetConversion: { @@ -962,8 +965,6 @@ bool TypeSystemParser::endElement(StackElement element) break; case StackElement::EnumTypeEntry: - top->entry->setDocModification(top->docModifications); - top->docModifications = DocModificationList(); m_currentEnum = nullptr; break; case StackElement::Template: @@ -1064,10 +1065,13 @@ CodeSnipAbstract *TypeSystemParser::injectCodeTarget(qsizetype offset) const return &funcMod.snips().last(); } case ParserState::TypeEntryCodeInjection: + Q_ASSERT(top->entry->isComplex()); + return &std::static_pointer_cast<ComplexTypeEntry>(top->entry)->codeSnips().last(); case ParserState::TypeSystemCodeInjection: - return &top->entry->codeSnips().last(); + Q_ASSERT(top->entry->isTypeSystem()); + return &std::static_pointer_cast<TypeSystemTypeEntry>(top->entry)->codeSnips().last(); case ParserState::Template: - return m_templateEntry; + return m_templateEntry.get(); default: break; } @@ -1101,15 +1105,22 @@ bool TypeSystemParser::characters(const String &ch) return true; } - if (isDocumentation(type)) - m_contextStack.top()->docModifications.last().setCode(ch); + if (isDocumentation(type)) { + const bool isAddedFunction = m_stack.value(m_stack.size() - 2, StackElement::None) + == StackElement::AddFunction; + const auto &top = m_contextStack.top(); + auto &docModifications = isAddedFunction + ? top->addedFunctions.last()->docModifications() + : top->docModifications; + docModifications.last().setCode(ch); + } return true; } bool TypeSystemParser::importFileElement(const QXmlStreamAttributes &atts) { - const QString fileName = atts.value(nameAttribute()).toString(); + const QString fileName = atts.value(nameAttribute).toString(); if (fileName.isEmpty()) { m_error = u"Required attribute 'name' missing for include-file tag."_s; return false; @@ -1124,11 +1135,11 @@ bool TypeSystemParser::importFileElement(const QXmlStreamAttributes &atts) } } - const auto quoteFrom = atts.value(quoteAfterLineAttribute()); + const auto quoteFrom = atts.value(quoteAfterLineAttribute); bool foundFromOk = quoteFrom.isEmpty(); bool from = quoteFrom.isEmpty(); - const auto quoteTo = atts.value(quoteBeforeLineAttribute()); + const auto quoteTo = atts.value(quoteBeforeLineAttribute); bool foundToOk = quoteTo.isEmpty(); bool to = true; @@ -1148,10 +1159,10 @@ bool TypeSystemParser::importFileElement(const QXmlStreamAttributes &atts) } } if (!foundFromOk || !foundToOk) { - QString fromError = QStringLiteral("Could not find quote-after-line='%1' in file '%2'.") - .arg(quoteFrom.toString(), fileName); - QString toError = QStringLiteral("Could not find quote-before-line='%1' in file '%2'.") - .arg(quoteTo.toString(), fileName); + QString fromError = QString::fromLatin1("Could not find quote-after-line='%1' in file '%2'.") + .arg(quoteFrom.toString(), fileName); + QString toError = QString::fromLatin1("Could not find quote-before-line='%1' in file '%2'.") + .arg(quoteTo.toString(), fileName); if (!foundToOk) m_error = toError; @@ -1165,29 +1176,27 @@ bool TypeSystemParser::importFileElement(const QXmlStreamAttributes &atts) return true; } -static bool convertBoolean(QStringView value, const QString &attributeName, bool defaultValue) +static bool convertBoolean(QStringView value, QAnyStringView attributeName, bool defaultValue) { - if (value.compare(trueAttributeValue(), Qt::CaseInsensitive) == 0 - || value.compare(yesAttributeValue(), Qt::CaseInsensitive) == 0) { + if (value.compare(trueAttributeValue, Qt::CaseInsensitive) == 0 + || value.compare(yesAttributeValue, Qt::CaseInsensitive) == 0) { return true; } - if (value.compare(falseAttributeValue(), Qt::CaseInsensitive) == 0 - || value.compare(noAttributeValue(), Qt::CaseInsensitive) == 0) { + if (value.compare(falseAttributeValue, Qt::CaseInsensitive) == 0 + || value.compare(noAttributeValue, Qt::CaseInsensitive) == 0) { return false; } - const QString warn = QStringLiteral("Boolean value '%1' not supported in attribute '%2'. Use 'yes' or 'no'. Defaulting to '%3'.") - .arg(value) - .arg(attributeName, - defaultValue ? yesAttributeValue() : noAttributeValue()); - - qCWarning(lcShiboken).noquote().nospace() << warn; + qCWarning(lcShiboken).noquote().nospace() << "Boolean value '" << value + << "' not supported in attribute '" << attributeName + << "'. Use 'yes' or 'no'. Defaulting to '" + << (defaultValue ? yesAttributeValue : noAttributeValue) << "'."; return defaultValue; } static bool convertRemovalAttribute(QStringView value) { return value == u"all" // Legacy - || convertBoolean(value, removeAttribute(), false); + || convertBoolean(value, removeAttribute, false); } // Check whether an entry should be dropped, allowing for dropping the module @@ -1197,7 +1206,7 @@ static bool shouldDropTypeEntry(const TypeDatabase *db, QString name) { for (auto i = stack.size() - 1; i >= 0; --i) { - if (auto *entry = stack.at(i)->entry) { + if (auto entry = stack.at(i)->entry) { if (entry->type() == TypeEntry::TypeSystemType) { if (db->shouldDropTypeEntry(name)) // Unqualified return true; @@ -1213,7 +1222,7 @@ static bool shouldDropTypeEntry(const TypeDatabase *db, static QString checkSignatureError(const QString& signature, const QString& tag) { QString funcName = signature.left(signature.indexOf(u'(')).trimmed(); - static const QRegularExpression whiteSpace(QStringLiteral("\\s")); + static const QRegularExpression whiteSpace("\\s"_L1); Q_ASSERT(whiteSpace.isValid()); if (!funcName.startsWith(u"operator ") && funcName.contains(whiteSpace)) { return QString::fromLatin1("Error in <%1> tag signature attribute '%2'.\n" @@ -1224,7 +1233,7 @@ static QString checkSignatureError(const QString& signature, const QString& tag) return QString(); } -inline const TypeEntry *TypeSystemParser::currentParentTypeEntry() const +inline TypeEntryCPtr TypeSystemParser::currentParentTypeEntry() const { const auto size = m_contextStack.size(); return size > 1 ? m_contextStack.at(size - 2)->entry : nullptr; @@ -1233,7 +1242,7 @@ inline const TypeEntry *TypeSystemParser::currentParentTypeEntry() const bool TypeSystemParser::checkRootElement() { for (auto i = m_contextStack.size() - 1; i >= 0; --i) { - auto *e = m_contextStack.at(i)->entry; + auto e = m_contextStack.at(i)->entry; if (e && e->isTypeSystem()) return true; } @@ -1241,7 +1250,7 @@ bool TypeSystemParser::checkRootElement() return false; } -static TypeEntry *findViewedType(const QString &name) +static TypeEntryPtr findViewedType(const QString &name) { const auto range = TypeDatabase::instance()->entries().equal_range(name); for (auto i = range.first; i != range.second; ++i) { @@ -1258,20 +1267,21 @@ static TypeEntry *findViewedType(const QString &name) return nullptr; } -bool TypeSystemParser::applyCommonAttributes(const ConditionalStreamReader &reader, TypeEntry *type, +bool TypeSystemParser::applyCommonAttributes(const ConditionalStreamReader &reader, + const TypeEntryPtr &type, QXmlStreamAttributes *attributes) { type->setSourceLocation(SourceLocation(m_currentFile, reader.lineNumber())); type->setCodeGeneration(m_generate); - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); if (name == u"revision") { type->setRevision(attributes->takeAt(i).value().toInt()); } else if (name == u"view-on") { const QString name = attributes->takeAt(i).value().toString(); - TypeEntry *views = findViewedType(name); - if (views == nullptr) { + TypeEntryPtr views = findViewedType(name); + if (!views) { m_error = msgCannotFindView(name, type->name()); return false; } @@ -1281,55 +1291,55 @@ bool TypeSystemParser::applyCommonAttributes(const ConditionalStreamReader &read return true; } -CustomTypeEntry *TypeSystemParser::parseCustomTypeEntry(const ConditionalStreamReader &, +CustomTypeEntryPtr TypeSystemParser::parseCustomTypeEntry(const ConditionalStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { if (!checkRootElement()) return nullptr; - auto *result = new CustomTypeEntry(name, since, m_contextStack.top()->entry); - for (int i = attributes->size() - 1; i >= 0; --i) { + auto result = std::make_shared<CustomTypeEntry>(name, since, m_contextStack.top()->entry); + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == checkFunctionAttribute()) + if (name == checkFunctionAttribute) result->setCheckFunction(attributes->takeAt(i).value().toString()); } return result; } -FlagsTypeEntry * +FlagsTypeEntryPtr TypeSystemParser::parseFlagsEntry(const ConditionalStreamReader &reader, - EnumTypeEntry *enumEntry, QString flagName, + const EnumTypeEntryPtr &enumEntry, QString flagName, const QVersionNumber &since, QXmlStreamAttributes *attributes) { if (!checkRootElement()) return nullptr; - auto ftype = new FlagsTypeEntry(u"QFlags<"_s + enumEntry->name() + u'>', - since, - currentParentTypeEntry()->typeSystemTypeEntry()); + auto ftype = std::make_shared<FlagsTypeEntry>(u"QFlags<"_s + enumEntry->name() + u'>', + since, + typeSystemTypeEntry(currentParentTypeEntry())); ftype->setOriginator(enumEntry); ftype->setTargetLangPackage(enumEntry->targetLangPackage()); // Try toenumEntry get the guess the qualified flag name - if (!flagName.contains(colonColon())) { + if (!flagName.contains(u"::"_s)) { auto eq = enumEntry->qualifier(); if (!eq.isEmpty()) - flagName.prepend(eq + colonColon()); + flagName.prepend(eq + u"::"_s); } ftype->setOriginalName(flagName); if (!applyCommonAttributes(reader, ftype, attributes)) return nullptr; - QStringList lst = flagName.split(colonColon()); + QStringList lst = flagName.split(u"::"_s); const QString name = lst.takeLast(); const QString targetLangFlagName = lst.join(u'.'); const QString &targetLangQualifier = enumEntry->targetLangQualifier(); if (targetLangFlagName != targetLangQualifier) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("enum %1 and flags %2 (%3) differ in qualifiers") - .arg(targetLangQualifier, lst.value(0), targetLangFlagName); + qCWarning(lcShiboken, "enum %s and flags %s (%s) differ in qualifiers", + qPrintable(targetLangQualifier), qPrintable(lst.value(0)), + qPrintable(targetLangFlagName)); } ftype->setFlagsName(name); @@ -1346,7 +1356,7 @@ FlagsTypeEntry * return ftype; } -SmartPointerTypeEntry * +SmartPointerTypeEntryPtr TypeSystemParser::parseSmartPointerEntry(const ConditionalStreamReader &reader, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) @@ -1360,7 +1370,7 @@ SmartPointerTypeEntry * QString nullCheckMethod; QString resetMethod; QString instantiations; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); if (name == u"type") { const auto attribute = attributes->takeAt(i); @@ -1409,8 +1419,9 @@ SmartPointerTypeEntry * return nullptr; } - auto *type = new SmartPointerTypeEntry(name, getter, smartPointerType, - refCountMethodName, since, currentParentTypeEntry()); + auto type = std::make_shared<SmartPointerTypeEntry>(name, getter, smartPointerType, + refCountMethodName, since, + currentParentTypeEntry()); if (!applyCommonAttributes(reader, type, attributes)) return nullptr; applyComplexTypeAttributes(reader, type, attributes); @@ -1421,29 +1432,29 @@ SmartPointerTypeEntry * return type; } -PrimitiveTypeEntry * +PrimitiveTypeEntryPtr TypeSystemParser::parsePrimitiveTypeEntry(const ConditionalStreamReader &reader, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { if (!checkRootElement()) return nullptr; - auto *type = new PrimitiveTypeEntry(name, since, currentParentTypeEntry()); + auto type = std::make_shared<PrimitiveTypeEntry>(name, since, currentParentTypeEntry()); QString targetLangApiName; if (!applyCommonAttributes(reader, type, attributes)) return nullptr; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == targetLangNameAttribute()) { + if (name == targetLangNameAttribute) { type->setTargetLangName(attributes->takeAt(i).value().toString()); } else if (name == u"target-lang-api-name") { targetLangApiName = attributes->takeAt(i).value().toString(); - } else if (name == preferredConversionAttribute()) { + } else if (name == preferredConversionAttribute) { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedAttributeWarning(reader, name))); - } else if (name == preferredTargetLangTypeAttribute()) { + } else if (name == preferredTargetLangTypeAttribute) { const bool v = convertBoolean(attributes->takeAt(i).value(), - preferredTargetLangTypeAttribute(), true); + preferredTargetLangTypeAttribute, true); type->setPreferredTargetLangType(v); } else if (name == u"default-constructor") { type->setDefaultConstructor(attributes->takeAt(i).value().toString()); @@ -1451,40 +1462,53 @@ PrimitiveTypeEntry * } if (!targetLangApiName.isEmpty()) { - auto *e = m_context->db->findType(targetLangApiName); - if (e == nullptr || !e->isCustom()) { + auto e = m_context->db->findType(targetLangApiName); + if (!e || !e->isCustom()) { m_error = msgInvalidTargetLanguageApiName(targetLangApiName); return nullptr; } - type->setTargetLangApiType(static_cast<CustomTypeEntry *>(e)); + type->setTargetLangApiType(std::static_pointer_cast<CustomTypeEntry>(e)); } type->setTargetLangPackage(m_defaultPackage); return type; } // "int:QList_int;QString:QList_QString" -static bool parseOpaqueContainers(QStringView s, ContainerTypeEntry *cte) +bool TypeSystemParser::parseOpaqueContainers(QStringView s, OpaqueContainers *result) { const auto entries = s.split(u';'); for (const auto &entry : entries) { const auto values = entry.split(u':'); - if (values.size() != 2) - return false; - QString instantiation = values.at(0).trimmed().toString(); - QString name = values.at(1).trimmed().toString(); - cte->addOpaqueContainer({instantiation, name}); + if (values.size() != 2) { + m_error = u"Error parsing the opaque container attribute: \""_s + + s.toString() + u"\"."_s; + return false; + } + OpaqueContainer oc; + oc.name = values.at(1).trimmed().toString(); + const auto instantiations = values.at(0).split(u',', Qt::SkipEmptyParts); + for (const auto &instantiationV : instantiations) { + QString instantiation = instantiationV.trimmed().toString(); + // Fix to match AbstractMetaType::signature() which is used for matching + // "Foo*" -> "Foo *" + const auto asteriskPos = instantiation.indexOf(u'*'); + if (asteriskPos > 0 && !instantiation.at(asteriskPos - 1).isSpace()) + instantiation.insert(asteriskPos, u' '); + oc.instantiations.append(instantiation); + } + result->append(oc); } return true; } -ContainerTypeEntry * +ContainerTypeEntryPtr TypeSystemParser::parseContainerTypeEntry(const ConditionalStreamReader &reader, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { if (!checkRootElement()) return nullptr; - const int typeIndex = indexOfAttribute(*attributes, u"type"); + const auto typeIndex = indexOfAttribute(*attributes, u"type"); if (typeIndex == -1) { m_error = u"no 'type' attribute specified"_s; return nullptr; @@ -1496,40 +1520,61 @@ ContainerTypeEntry * return nullptr; } attributes->removeAt(typeIndex); - auto *type = new ContainerTypeEntry(name, containerTypeOpt.value(), - since, currentParentTypeEntry()); + auto type = std::make_shared<ContainerTypeEntry>(name, containerTypeOpt.value(), + since, currentParentTypeEntry()); if (!applyCommonAttributes(reader, type, attributes)) return nullptr; applyComplexTypeAttributes(reader, type, attributes); - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == u"opaque-containers") { + if (name == opaqueContainerAttribute) { const auto attribute = attributes->takeAt(i); - if (!parseOpaqueContainers(attribute.value(), type)) { - m_error = u"Error parsing the opaque container attribute: \""_s - + attribute.value().toString() + u"\"."_s; + OpaqueContainers oc; + if (!parseOpaqueContainers(attribute.value(), &oc)) return nullptr; - } + type->appendOpaqueContainers(oc); } } return type; } -EnumTypeEntry * +bool TypeSystemParser::parseOpaqueContainerElement(QXmlStreamAttributes *attributes) +{ + QString containerName; + OpaqueContainers oc; + for (auto i = attributes->size() - 1; i >= 0; --i) { + const auto name = attributes->at(i).qualifiedName(); + if (name == nameAttribute) { + containerName = attributes->takeAt(i).value().toString(); + } else if (name == opaqueContainerAttribute) { + const auto attribute = attributes->takeAt(i); + if (!parseOpaqueContainers(attribute.value(), &oc)) + return false; + } + } + if (containerName.isEmpty()) { + m_error = msgMissingAttribute(nameAttribute); + return false; + } + m_context->opaqueContainerHash[containerName].append(oc); + return true; +} + +EnumTypeEntryPtr TypeSystemParser::parseEnumTypeEntry(const ConditionalStreamReader &reader, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { if (!checkRootElement()) return nullptr; - auto *entry = new EnumTypeEntry(name, since, currentParentTypeEntry()); + auto entry = std::make_shared<EnumTypeEntry>(name, since, currentParentTypeEntry()); applyCommonAttributes(reader, entry, attributes); entry->setTargetLangPackage(m_defaultPackage); QString flagNames; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); if (name == u"upper-bound") { qCWarning(lcShiboken, "%s", @@ -1537,10 +1582,12 @@ EnumTypeEntry * } else if (name == u"lower-bound") { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedAttributeWarning(reader, name))); - } else if (name == forceIntegerAttribute()) { + } else if (name == docFileAttribute) { + entry->setDocFile(attributes->takeAt(i).value().toString()); + } else if (name == forceIntegerAttribute) { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedAttributeWarning(reader, name))); - } else if (name == pythonEnumTypeAttribute()) { + } else if (name == pythonEnumTypeAttribute) { const auto attribute = attributes->takeAt(i); const auto typeOpt = pythonEnumTypeFromAttribute(attribute.value()); if (typeOpt.has_value()) { @@ -1549,10 +1596,12 @@ EnumTypeEntry * qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == extensibleAttribute()) { + } else if (name == cppEnumTypeAttribute) { + entry->setCppType(attributes->takeAt(i).value().toString()); + } else if (name == extensibleAttribute) { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedAttributeWarning(reader, name))); - } else if (name == flagsAttribute()) { + } else if (name == flagsAttribute) { flagNames = attributes->takeAt(i).value().toString(); } } @@ -1567,17 +1616,17 @@ EnumTypeEntry * } -NamespaceTypeEntry * +NamespaceTypeEntryPtr TypeSystemParser::parseNamespaceTypeEntry(const ConditionalStreamReader &reader, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { if (!checkRootElement()) return nullptr; - std::unique_ptr<NamespaceTypeEntry> result(new NamespaceTypeEntry(name, since, currentParentTypeEntry())); + auto result = std::make_shared<NamespaceTypeEntry>(name, since, currentParentTypeEntry()); auto visibility = TypeSystem::Visibility::Unspecified; - applyCommonAttributes(reader, result.get(), attributes); - for (int i = attributes->size() - 1; i >= 0; --i) { + applyCommonAttributes(reader, result, attributes); + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto attributeName = attributes->at(i).qualifiedName(); if (attributeName == u"files") { const QString pattern = attributes->takeAt(i).value().toString(); @@ -1591,7 +1640,7 @@ NamespaceTypeEntry * const auto extendsPackageName = attributes->at(i).value(); auto allEntries = TypeDatabase::instance()->findNamespaceTypes(name); auto extendsIt = std::find_if(allEntries.cbegin(), allEntries.cend(), - [extendsPackageName] (const NamespaceTypeEntry *e) { + [extendsPackageName] (const NamespaceTypeEntryCPtr &e) { return e->targetLangPackage() == extendsPackageName; }); if (extendsIt == allEntries.cend()) { @@ -1600,7 +1649,7 @@ NamespaceTypeEntry * } result->setExtends(*extendsIt); attributes->removeAt(i); - } else if (attributeName == visibleAttribute()) { + } else if (attributeName == visibleAttribute) { const auto attribute = attributes->takeAt(i); const auto visibilityOpt = visibilityFromAttribute(attribute.value()); if (!visibilityOpt.has_value()) { @@ -1608,35 +1657,36 @@ NamespaceTypeEntry * return nullptr; } visibility = visibilityOpt.value(); - } else if (attributeName == generateAttribute()) { - if (!convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true)) + } else if (attributeName == generateAttribute) { + if (!convertBoolean(attributes->takeAt(i).value(), generateAttribute, true)) visibility = TypeSystem::Visibility::Invisible; - } else if (attributeName == generateUsingAttribute()) { - result->setGenerateUsing(convertBoolean(attributes->takeAt(i).value(), generateUsingAttribute(), true)); + } else if (attributeName == generateUsingAttribute) { + result->setGenerateUsing(convertBoolean(attributes->takeAt(i).value(), + generateUsingAttribute, true)); } } if (visibility != TypeSystem::Visibility::Unspecified) result->setVisibility(visibility); // Handle legacy "generate" before the common handling - applyComplexTypeAttributes(reader, result.get(), attributes); + applyComplexTypeAttributes(reader, result, attributes); if (result->extends() && !result->hasPattern()) { m_error = msgExtendingNamespaceRequiresPattern(name); - return nullptr; + return {}; } - return result.release(); + return result; } -ValueTypeEntry * +ValueTypeEntryPtr TypeSystemParser::parseValueTypeEntry(const ConditionalStreamReader &reader, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { if (!checkRootElement()) return nullptr; - auto *typeEntry = new ValueTypeEntry(name, since, currentParentTypeEntry()); + auto typeEntry = std::make_shared<ValueTypeEntry>(name, since, currentParentTypeEntry()); if (!applyCommonAttributes(reader, typeEntry, attributes)) return nullptr; applyComplexTypeAttributes(reader, typeEntry, attributes); @@ -1647,7 +1697,7 @@ ValueTypeEntry * return typeEntry; } -FunctionTypeEntry * +FunctionTypeEntryPtr TypeSystemParser::parseFunctionTypeEntry(const ConditionalStreamReader &reader, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) @@ -1655,50 +1705,56 @@ FunctionTypeEntry * if (!checkRootElement()) return nullptr; - QString signature; - TypeSystem::SnakeCase snakeCase = TypeSystem::SnakeCase::Disabled; + FunctionModification mod; + const auto oldAttributesSize = attributes->size(); + if (!parseModifyFunctionAttributes(attributes, &mod)) + return nullptr; + const bool hasModification = attributes->size() < oldAttributesSize; - for (int i = attributes->size() - 1; i >= 0; --i) { + QString originalSignature; + QString docFile; + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == signatureAttribute()) { - signature = TypeDatabase::normalizedSignature(attributes->takeAt(i).value().toString()); - } else if (name == snakeCaseAttribute()) { - const auto attribute = attributes->takeAt(i); - const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value()); - if (!snakeCaseOpt.has_value()) { - m_error = msgInvalidAttributeValue(attribute); - return nullptr; - } - snakeCase = snakeCaseOpt.value(); - } + if (name == signatureAttribute) + originalSignature = attributes->takeAt(i).value().toString().simplified(); + else if (name == docFileAttribute) + docFile = attributes->takeAt(i).value().toString(); } + const QString signature = TypeDatabase::normalizedSignature(originalSignature); if (signature.isEmpty()) { - m_error = msgMissingAttribute(signatureAttribute()); + m_error = msgMissingAttribute(signatureAttribute); return nullptr; } - TypeEntry *existingType = m_context->db->findType(name); + if (hasModification) { + mod.setOriginalSignature(originalSignature); + mod.setSignature(signature); + m_contextStack.top()->functionMods << mod; + } + + TypeEntryPtr existingType = m_context->db->findType(name); if (!existingType) { - auto *result = new FunctionTypeEntry(name, signature, since, currentParentTypeEntry()); - result->setSnakeCase(snakeCase); + auto result = std::make_shared<FunctionTypeEntry>(name, signature, since, + currentParentTypeEntry()); + result->setTargetLangPackage(m_defaultPackage); + result->setDocFile(docFile); applyCommonAttributes(reader, result, attributes); return result; } if (existingType->type() != TypeEntry::FunctionType) { - m_error = QStringLiteral("%1 expected to be a function, but isn't! Maybe it was already declared as a class or something else.") - .arg(name); + m_error = name + " expected to be a function, but isn't! Maybe it was already declared as a class or something else."_L1; return nullptr; } - auto *result = reinterpret_cast<FunctionTypeEntry *>(existingType); + auto result = std::static_pointer_cast<FunctionTypeEntry>(existingType); result->addSignature(signature); return result; } -TypedefEntry * +TypedefEntryPtr TypeSystemParser::parseTypedefEntry(const ConditionalStreamReader &reader, const QString &name, StackElement topElement, const QVersionNumber &since, @@ -1711,13 +1767,14 @@ TypedefEntry * m_error = u"typedef entries must be nested in namespaces or type system."_s; return nullptr; } - const int sourceIndex = indexOfAttribute(*attributes, sourceAttribute()); + const auto sourceIndex = indexOfAttribute(*attributes, sourceAttribute); if (sourceIndex == -1) { - m_error = msgMissingAttribute(sourceAttribute()); + m_error = msgMissingAttribute(sourceAttribute); return nullptr; } const QString sourceType = attributes->takeAt(sourceIndex).value().toString(); - auto result = new TypedefEntry(name, sourceType, since, currentParentTypeEntry()); + auto result = std::make_shared<TypedefEntry>(name, sourceType, since, + currentParentTypeEntry()); if (!applyCommonAttributes(reader, result, attributes)) return nullptr; applyComplexTypeAttributes(reader, result, attributes); @@ -1725,7 +1782,7 @@ TypedefEntry * } void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader &reader, - ComplexTypeEntry *ctype, + const ComplexTypeEntryPtr &ctype, QXmlStreamAttributes *attributes) const { bool generate = true; @@ -1734,36 +1791,40 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader auto allowThread = m_allowThread; QString package = m_defaultPackage; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == streamAttribute()) { - ctype->setStream(convertBoolean(attributes->takeAt(i).value(), streamAttribute(), false)); - } else if (name == privateAttribute()) { + if (name == streamAttribute) { + ctype->setStream(convertBoolean(attributes->takeAt(i).value(), streamAttribute, false)); + } else if (name == privateAttribute) { ctype->setPrivate(convertBoolean(attributes->takeAt(i).value(), - privateAttribute(), false)); - } else if (name == generateAttribute()) { - generate = convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true); - } else if (name ==packageAttribute()) { + privateAttribute, false)); + } else if (name == generateAttribute) { + generate = convertBoolean(attributes->takeAt(i).value(), generateAttribute, true); + } else if (name ==packageAttribute) { package = attributes->takeAt(i).value().toString(); - } else if (name == defaultSuperclassAttribute()) { + } else if (name == defaultSuperclassAttribute) { ctype->setDefaultSuperclass(attributes->takeAt(i).value().toString()); - } else if (name == genericClassAttribute()) { + } else if (name == genericClassAttribute) { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedAttributeWarning(reader, name))); - const bool v = convertBoolean(attributes->takeAt(i).value(), genericClassAttribute(), false); + const bool v = convertBoolean(attributes->takeAt(i).value(), + genericClassAttribute, false); ctype->setGenericClass(v); - } else if (name == targetLangNameAttribute()) { + } else if (name == targetLangNameAttribute) { ctype->setTargetLangName(attributes->takeAt(i).value().toString()); - } else if (name == u"polymorphic-base") { - ctype->setPolymorphicIdValue(attributes->takeAt(i).value().toString()); + } else if (name == polymorphicBaseAttribute) { + const bool v = convertBoolean(attributes->takeAt(i).value(), + polymorphicBaseAttribute, false); + ctype->setIsPolymorphicBase(v); } else if (name == u"polymorphic-name-function") { ctype->setPolymorphicNameFunction(attributes->takeAt(i).value().toString()); } else if (name == u"polymorphic-id-expression") { ctype->setPolymorphicIdValue(attributes->takeAt(i).value().toString()); - } else if (name == copyableAttribute()) { - const bool v = convertBoolean(attributes->takeAt(i).value(), copyableAttribute(), false); + } else if (name == copyableAttribute) { + const bool v = convertBoolean(attributes->takeAt(i).value(), + copyableAttribute, false); ctype->setCopyable(v ? ComplexTypeEntry::CopyableSet : ComplexTypeEntry::NonCopyableSet); - } else if (name == exceptionHandlingAttribute()) { + } else if (name == exceptionHandlingAttribute) { const auto attribute = attributes->takeAt(i); const auto exceptionOpt = exceptionHandlingFromAttribute(attribute.value()); if (exceptionOpt.has_value()) { @@ -1772,7 +1833,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == allowThreadAttribute()) { + } else if (name == allowThreadAttribute) { const auto attribute = attributes->takeAt(i); const auto allowThreadOpt = allowThreadFromAttribute(attribute.value()); if (allowThreadOpt.has_value()) { @@ -1786,19 +1847,25 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader qPrintable(msgUnimplementedAttributeWarning(reader, name))); } else if (name == u"hash-function") { ctype->setHashFunction(attributes->takeAt(i).value().toString()); - } else if (name == forceAbstractAttribute()) { - if (convertBoolean(attributes->takeAt(i).value(), forceAbstractAttribute(), false)) + } else if (name == forceAbstractAttribute) { + if (convertBoolean(attributes->takeAt(i).value(), forceAbstractAttribute, false)) ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::ForceAbstract); - } else if (name == deprecatedAttribute()) { - if (convertBoolean(attributes->takeAt(i).value(), deprecatedAttribute(), false)) + } else if (name == deprecatedAttribute) { + if (convertBoolean(attributes->takeAt(i).value(), deprecatedAttribute, false)) ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::Deprecated); - } else if (name == disableWrapperAttribute()) { - if (convertBoolean(attributes->takeAt(i).value(), disableWrapperAttribute(), false)) + } else if (name == disableWrapperAttribute) { + if (convertBoolean(attributes->takeAt(i).value(), disableWrapperAttribute, false)) ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::DisableWrapper); - } else if (name == deleteInMainThreadAttribute()) { - if (convertBoolean(attributes->takeAt(i).value(), deleteInMainThreadAttribute(), false)) + } else if (name == deleteInMainThreadAttribute) { + if (convertBoolean(attributes->takeAt(i).value(), deleteInMainThreadAttribute, false)) ctype->setDeleteInMainThread(true); - } else if (name == generateFunctionsAttribute()) { + } else if (name == qtMetaObjectFunctionsAttribute) { + if (!convertBoolean(attributes->takeAt(i).value(), + qtMetaObjectFunctionsAttribute, true)) { + ctype->setTypeFlags(ctype->typeFlags() + | ComplexTypeEntry::DisableQtMetaObjectFunctions); + } + } else if (name == generateFunctionsAttribute) { const auto names = attributes->takeAt(i).value(); const auto nameList = names.split(u';', Qt::SkipEmptyParts); QSet<QString> nameSet; @@ -1807,7 +1874,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader ctype->setGenerateFunctions(nameSet); } else if (name == u"target-type") { ctype->setTargetType(attributes->takeAt(i).value().toString()); - } else if (name == snakeCaseAttribute()) { + } else if (name == snakeCaseAttribute) { const auto attribute = attributes->takeAt(i); const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value()); if (snakeCaseOpt.has_value()) { @@ -1816,7 +1883,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == isNullAttribute()) { + } else if (name == isNullAttribute) { const auto attribute = attributes->takeAt(i); const auto boolCastOpt = boolCastFromAttribute(attribute.value()); if (boolCastOpt.has_value()) { @@ -1825,7 +1892,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == operatorBoolAttribute()) { + } else if (name == operatorBoolAttribute) { const auto attribute = attributes->takeAt(i); const auto boolCastOpt = boolCastFromAttribute(attribute.value()); if (boolCastOpt.has_value()) { @@ -1834,7 +1901,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == qtMetaTypeAttribute()) { + } else if (name == qtMetaTypeAttribute) { const auto attribute = attributes->takeAt(i); const auto qtMetaTypeOpt = qtMetaTypeFromAttribute(attribute.value()); if (qtMetaTypeOpt.has_value()) { @@ -1843,9 +1910,9 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == parentManagementAttribute()) { + } else if (name == parentManagementAttribute) { const auto attribute = attributes->takeAt(i); - if (convertBoolean(attribute.value(), parentManagementAttribute(), false)) + if (convertBoolean(attribute.value(), parentManagementAttribute, false)) ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::ParentManagement); ComplexTypeEntry::setParentManagementEnabled(true); } @@ -1866,23 +1933,49 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader ctype->setCodeGeneration(TypeEntry::GenerationDisabled); } +bool TypeSystemParser::parseConfiguration(StackElement topElement, + QXmlStreamAttributes *attributes) +{ + if (!isComplexTypeEntry(topElement) + && topElement != StackElement::EnumTypeEntry) { + m_error = u"<configuration> must be nested into a complex or enum type entry."_s; + return false; + } + QString condition; + for (auto i = attributes->size() - 1; i >= 0; --i) { + const auto name = attributes->at(i).qualifiedName(); + if (name == u"condition") { + condition = attributes->takeAt(i).value().toString(); + } + } + if (condition.isEmpty()) { + m_error = u"<configuration> requires a \"condition\" attribute."_s; + return false; + } + const auto topEntry = m_contextStack.top()->entry; + const auto configurableEntry = std::dynamic_pointer_cast<ConfigurableTypeEntry>(topEntry); + Q_ASSERT(configurableEntry); + configurableEntry->setConfigCondition(condition); + return true; +} + bool TypeSystemParser::parseRenameFunction(const ConditionalStreamReader &, QString *name, QXmlStreamAttributes *attributes) { QString signature; QString rename; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == signatureAttribute()) { + if (name == signatureAttribute) { // Do not remove as it is needed for the type entry later on - signature = attributes->at(i).value().toString(); - } else if (name == renameAttribute()) { + signature = attributes->at(i).value().toString().simplified(); + } else if (name == renameAttribute) { rename = attributes->takeAt(i).value().toString(); } } if (signature.isEmpty()) { - m_error = msgMissingAttribute(signatureAttribute()); + m_error = msgMissingAttribute(signatureAttribute); return false; } @@ -1915,10 +2008,11 @@ bool TypeSystemParser::parseRenameFunction(const ConditionalStreamReader &, bool TypeSystemParser::parseInjectDocumentation(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *attributes) { + const bool isAddFunction = topElement == StackElement::AddFunction; const bool validParent = isTypeEntry(topElement) || topElement == StackElement::ModifyFunction || topElement == StackElement::ModifyField - || topElement == StackElement::AddFunction; + || isAddFunction; if (!validParent) { m_error = u"inject-documentation must be inside modify-function, add-function" "modify-field or other tags that creates a type"_s; @@ -1927,7 +2021,7 @@ bool TypeSystemParser::parseInjectDocumentation(const ConditionalStreamReader &, TypeSystem::DocModificationMode mode = TypeSystem::DocModificationReplace; TypeSystem::Language lang = TypeSystem::NativeCode; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); if (name == u"mode") { const auto attribute = attributes->takeAt(i); @@ -1937,7 +2031,7 @@ bool TypeSystemParser::parseInjectDocumentation(const ConditionalStreamReader &, return false; } mode = modeOpt.value(); - } else if (name == formatAttribute()) { + } else if (name == formatAttribute) { const auto attribute = attributes->takeAt(i); const auto langOpt = languageFromAttribute(attribute.value()); if (!langOpt.has_value()) { @@ -1951,7 +2045,17 @@ bool TypeSystemParser::parseInjectDocumentation(const ConditionalStreamReader &, QString signature = isTypeEntry(topElement) ? QString() : m_currentSignature; DocModification mod(mode, signature); mod.setFormat(lang); - m_contextStack.top()->docModifications << mod; + if (hasFileSnippetAttributes(attributes)) { + const auto snippetOptional = readFileSnippet(attributes); + if (!snippetOptional.has_value()) + return false; + mod.setCode(snippetOptional.value().content); + } + auto &top = m_contextStack.top(); + if (isAddFunction) + top->addedFunctions.last()->addDocModification(mod); + else + top->docModifications << mod; return true; } @@ -1964,13 +2068,13 @@ bool TypeSystemParser::parseModifyDocumentation(const ConditionalStreamReader &, || topElement == StackElement::ModifyField; if (!validParent) { m_error = u"modify-documentation must be inside modify-function, " - "modify-field or other tags that creates a type"_qs; + "modify-field or other tags that creates a type"_s; return false; } - const int xpathIndex = indexOfAttribute(*attributes, xPathAttribute()); + const auto xpathIndex = indexOfAttribute(*attributes, xPathAttribute); if (xpathIndex == -1) { - m_error = msgMissingAttribute(xPathAttribute()); + m_error = msgMissingAttribute(xPathAttribute); return false; } @@ -1982,19 +2086,22 @@ bool TypeSystemParser::parseModifyDocumentation(const ConditionalStreamReader &, } // m_exceptionHandling -TypeSystemTypeEntry *TypeSystemParser::parseRootElement(const ConditionalStreamReader &, +TypeSystemTypeEntryPtr TypeSystemParser::parseRootElement(const ConditionalStreamReader &, const QVersionNumber &since, QXmlStreamAttributes *attributes) { TypeSystem::SnakeCase snakeCase = TypeSystem::SnakeCase::Unspecified; + QString subModuleOf; + QString namespaceBegin; + QString namespaceEnd; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == packageAttribute()) { + if (name == packageAttribute) { m_defaultPackage = attributes->takeAt(i).value().toString(); - } else if (name == defaultSuperclassAttribute()) { + } else if (name == defaultSuperclassAttribute) { m_defaultSuperclass = attributes->takeAt(i).value().toString(); - } else if (name == exceptionHandlingAttribute()) { + } else if (name == exceptionHandlingAttribute) { const auto attribute = attributes->takeAt(i); const auto exceptionOpt = exceptionHandlingFromAttribute(attribute.value()); if (exceptionOpt.has_value()) { @@ -2003,7 +2110,7 @@ TypeSystemTypeEntry *TypeSystemParser::parseRootElement(const ConditionalStreamR qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == allowThreadAttribute()) { + } else if (name == allowThreadAttribute) { const auto attribute = attributes->takeAt(i); const auto allowThreadOpt = allowThreadFromAttribute(attribute.value()); if (allowThreadOpt.has_value()) { @@ -2012,7 +2119,7 @@ TypeSystemTypeEntry *TypeSystemParser::parseRootElement(const ConditionalStreamR qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } - } else if (name == snakeCaseAttribute()) { + } else if (name == snakeCaseAttribute) { const auto attribute = attributes->takeAt(i); const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value()); if (snakeCaseOpt.has_value()) { @@ -2021,25 +2128,36 @@ TypeSystemTypeEntry *TypeSystemParser::parseRootElement(const ConditionalStreamR qCWarning(lcShiboken, "%s", qPrintable(msgInvalidAttributeValue(attribute))); } + } else if (name == subModuleOfAttribute) { + subModuleOf = attributes->takeAt(i).value().toString(); + } else if (name == "namespace-begin"_L1) { + namespaceBegin = attributes->takeAt(i).value().toString(); + } else if (name == "namespace-end"_L1) { + namespaceEnd = attributes->takeAt(i).value().toString(); } } if (m_defaultPackage.isEmpty()) { // Extending default, see addBuiltInContainerTypes() - auto *moduleEntry = const_cast<TypeSystemTypeEntry *>(m_context->db->defaultTypeSystemType()); + auto moduleEntry = std::const_pointer_cast<TypeSystemTypeEntry>(m_context->db->defaultTypeSystemType()); Q_ASSERT(moduleEntry); m_defaultPackage = moduleEntry->name(); return moduleEntry; } - auto *moduleEntry = - const_cast<TypeSystemTypeEntry *>(m_context->db->findTypeSystemType(m_defaultPackage)); - const bool add = moduleEntry == nullptr; + auto moduleEntry = + std::const_pointer_cast<TypeSystemTypeEntry>(m_context->db->findTypeSystemType(m_defaultPackage)); + const bool add = !moduleEntry; if (add) { - moduleEntry = new TypeSystemTypeEntry(m_defaultPackage, since, - currentParentTypeEntry()); + moduleEntry.reset(new TypeSystemTypeEntry(m_defaultPackage, since, + currentParentTypeEntry())); + moduleEntry->setSubModule(subModuleOf); } moduleEntry->setCodeGeneration(m_generate); moduleEntry->setSnakeCase(snakeCase); + if (!namespaceBegin.isEmpty()) + moduleEntry->setNamespaceBegin(namespaceBegin); + if (!namespaceEnd.isEmpty()) + moduleEntry->setNamespaceEnd(namespaceEnd); if ((m_generate == TypeEntry::GenerateForSubclass || m_generate == TypeEntry::GenerateNothing) && !m_defaultPackage.isEmpty()) @@ -2055,12 +2173,12 @@ bool TypeSystemParser::loadTypesystem(const ConditionalStreamReader &, { QString typeSystemName; bool generateChild = true; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == nameAttribute()) + if (name == nameAttribute) typeSystemName = attributes->takeAt(i).value().toString(); - else if (name == generateAttribute()) - generateChild = convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true); + else if (name == generateAttribute) + generateChild = convertBoolean(attributes->takeAt(i).value(), generateAttribute, true); } if (typeSystemName.isEmpty()) { m_error = u"No typesystem name specified"_s; @@ -2081,9 +2199,9 @@ bool TypeSystemParser::parseRejectEnumValue(const ConditionalStreamReader &, m_error = u"<reject-enum-value> node must be used inside a <enum-type> node"_s; return false; } - const int nameIndex = indexOfAttribute(*attributes, nameAttribute()); + const auto nameIndex = indexOfAttribute(*attributes, nameAttribute); if (nameIndex == -1) { - m_error = msgMissingAttribute(nameAttribute()); + m_error = msgMissingAttribute(nameAttribute); return false; } m_currentEnum->addEnumValueRejection(attributes->takeAt(nameIndex).value().toString()); @@ -2098,7 +2216,7 @@ bool TypeSystemParser::parseReplaceArgumentType(const ConditionalStreamReader &, m_error = u"Type replacement can only be specified for argument modifications"_s; return false; } - const int modifiedTypeIndex = indexOfAttribute(*attributes, modifiedTypeAttribute()); + const auto modifiedTypeIndex = indexOfAttribute(*attributes, modifiedTypeAttribute); if (modifiedTypeIndex == -1) { m_error = u"Type replacement requires 'modified-type' attribute"_s; return false; @@ -2124,9 +2242,9 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &, QString sourceFile; QString snippetLabel; TypeSystem::Language lang = TypeSystem::NativeCode; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == classAttribute()) { + if (name == classAttribute) { const auto languageAttribute = attributes->takeAt(i); const auto langOpt = languageFromAttribute(languageAttribute.value()); if (!langOpt.has_value()) { @@ -2136,7 +2254,7 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &, lang = langOpt.value(); } else if (name == u"file") { sourceFile = attributes->takeAt(i).value().toString(); - } else if (name == snippetAttribute()) { + } else if (name == snippetAttribute) { snippetLabel = attributes->takeAt(i).value().toString(); } } @@ -2149,14 +2267,18 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &, return true; } - if (top->entry->hasTargetConversionRule() || top->entry->hasCustomConversion()) { - m_error = u"Types can have only one conversion rule"_s; - return false; + ValueTypeEntryPtr valueTypeEntry; + if (top->entry->isValue()) { + valueTypeEntry = std::static_pointer_cast<ValueTypeEntry>(top->entry); + if (valueTypeEntry->hasTargetConversionRule() || valueTypeEntry->hasCustomConversion()) { + m_error = u"Types can have only one conversion rule"_s; + return false; + } } // The old conversion rule tag that uses a file containing the conversion // will be kept temporarily for compatibility reasons. FIXME PYSIDE7: Remove - if (!sourceFile.isEmpty()) { + if (valueTypeEntry != nullptr && !sourceFile.isEmpty()) { if (m_generate != TypeEntry::GenerateForSubclass && m_generate != TypeEntry::GenerateNothing) { qWarning(lcShiboken, "Specifying conversion rules by \"file\" is deprecated."); @@ -2174,12 +2296,18 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &, m_error = msgCannotFindSnippet(sourceFile, snippetLabel); return false; } - top->entry->setTargetConversionRule(conversionRuleOptional.value()); + valueTypeEntry->setTargetConversionRule(conversionRuleOptional.value()); } return true; } - auto *customConversion = new CustomConversion(top->entry); + auto customConversion = std::make_shared<CustomConversion>(top->entry); + if (top->entry->isPrimitive()) + std::static_pointer_cast<PrimitiveTypeEntry>(top->entry)->setCustomConversion(customConversion); + else if (top->entry->isContainer()) + std::static_pointer_cast<ContainerTypeEntry>(top->entry)->setCustomConversion(customConversion); + else if (top->entry->isValue()) + std::static_pointer_cast<ValueTypeEntry>(top->entry)->setCustomConversion(customConversion); customConversionsForReview.append(customConversion); return true; } @@ -2193,7 +2321,7 @@ bool TypeSystemParser::parseNativeToTarget(const ConditionalStreamReader &, return false; } CodeSnip snip; - if (!readFileSnippet(attributes, &snip)) + if (!readCodeSnippet(attributes, &snip)) return false; m_contextStack.top()->conversionCodeSnips.append(snip); return true; @@ -2210,7 +2338,7 @@ bool TypeSystemParser::parseAddConversion(const ConditionalStreamReader &, QString sourceTypeName; QString typeCheck; CodeSnip snip; - if (!readFileSnippet(attributes, &snip)) + if (!readCodeSnippet(attributes, &snip)) return false; const auto &top = m_contextStack.top(); @@ -2219,7 +2347,7 @@ bool TypeSystemParser::parseAddConversion(const ConditionalStreamReader &, if (parserState() == ParserState::ArgumentTargetToNativeConversion) return true; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); if (name == u"type") sourceTypeName = attributes->takeAt(i).value().toString(); @@ -2231,7 +2359,12 @@ bool TypeSystemParser::parseAddConversion(const ConditionalStreamReader &, m_error = u"Target to Native conversions must specify the input type with the 'type' attribute."_s; return false; } - top->entry->customConversion()->addTargetToNativeConversion(sourceTypeName, typeCheck); + auto customConversion = CustomConversion::getCustomConversion(top->entry); + if (!customConversion) { + m_error = msgMissingCustomConversion(top->entry); + return false; + } + customConversion->addTargetToNativeConversion(sourceTypeName, typeCheck); return true; } @@ -2240,7 +2373,7 @@ static bool parseIndex(const QString &index, int *result, QString *errorMessage) bool ok = false; *result = index.toInt(&ok); if (!ok) - *errorMessage = QStringLiteral("Cannot convert '%1' to integer").arg(index); + *errorMessage = QString::fromLatin1("Cannot convert '%1' to integer").arg(index); return ok; } @@ -2273,22 +2406,22 @@ bool TypeSystemParser::parseModifyArgument(const ConditionalStreamReader &, QString renameTo; QString pyiType; bool resetAfterUse = false; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == indexAttribute()) { + if (name == indexAttribute) { index = attributes->takeAt(i).value().toString(); - } else if (name == invalidateAfterUseAttribute()) { + } else if (name == invalidateAfterUseAttribute) { resetAfterUse = convertBoolean(attributes->takeAt(i).value(), - invalidateAfterUseAttribute(), false); - } else if (name == renameAttribute()) { + invalidateAfterUseAttribute, false); + } else if (name == renameAttribute) { renameTo = attributes->takeAt(i).value().toString(); - } else if (name == pyiTypeAttribute()) { + } else if (name == pyiTypeAttribute) { pyiType = attributes->takeAt(i).value().toString(); } } if (index.isEmpty()) { - m_error = msgMissingAttribute(indexAttribute()); + m_error = msgMissingAttribute(indexAttribute); return false; } @@ -2336,9 +2469,9 @@ bool TypeSystemParser::parseDefineOwnership(const ConditionalStreamReader &, TypeSystem::Language lang = TypeSystem::TargetLangCode; std::optional<TypeSystem::Ownership> ownershipOpt; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == classAttribute()) { + if (name == classAttribute) { const auto classAttribute = attributes->takeAt(i); const auto langOpt = languageFromAttribute(classAttribute.value()); if (!langOpt.has_value() || langOpt.value() == TypeSystem::ShellCode) { @@ -2346,7 +2479,7 @@ bool TypeSystemParser::parseDefineOwnership(const ConditionalStreamReader &, return false; } lang = langOpt.value(); - } else if (name == ownershipAttribute()) { + } else if (name == ownershipAttribute) { const auto attribute = attributes->takeAt(i); ownershipOpt = ownershipFromFromAttribute(attribute.value()); if (!ownershipOpt.has_value()) { @@ -2357,7 +2490,7 @@ bool TypeSystemParser::parseDefineOwnership(const ConditionalStreamReader &, } if (!ownershipOpt.has_value()) { - m_error = QStringLiteral("unspecified ownership"); + m_error = "unspecified ownership"_L1; return false; } auto &lastArgMod = m_contextStack.top()->functionMods.last().argument_mods().last(); @@ -2384,9 +2517,9 @@ bool TypeSystemParser::parseRename(const ConditionalStreamReader &, return false; } - const int toIndex = indexOfAttribute(*attributes, toAttribute()); + const auto toIndex = indexOfAttribute(*attributes, toAttribute); if (toIndex == -1) { - m_error = msgMissingAttribute(toAttribute()); + m_error = msgMissingAttribute(toAttribute); return false; } const QString renamed_to = attributes->takeAt(toIndex).value().toString(); @@ -2398,22 +2531,22 @@ bool TypeSystemParser::parseModifyField(const ConditionalStreamReader &, QXmlStreamAttributes *attributes) { FieldModification fm; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == nameAttribute()) { + if (name == nameAttribute) { fm.setName(attributes->takeAt(i).value().toString()); - } else if (name == removeAttribute()) { + } else if (name == removeAttribute) { fm.setRemoved(convertRemovalAttribute(attributes->takeAt(i).value())); - } else if (name == opaqueContainerFieldAttribute()) { + } else if (name == opaqueContainerFieldAttribute) { fm.setOpaqueContainer(convertBoolean(attributes->takeAt(i).value(), - opaqueContainerFieldAttribute(), false)); - } else if (name == readAttribute()) { - fm.setReadable(convertBoolean(attributes->takeAt(i).value(), readAttribute(), true)); - } else if (name == writeAttribute()) { - fm.setWritable(convertBoolean(attributes->takeAt(i).value(), writeAttribute(), true)); - } else if (name == renameAttribute()) { + opaqueContainerFieldAttribute, false)); + } else if (name == readAttribute) { + fm.setReadable(convertBoolean(attributes->takeAt(i).value(), readAttribute, true)); + } else if (name == writeAttribute) { + fm.setWritable(convertBoolean(attributes->takeAt(i).value(), writeAttribute, true)); + } else if (name == renameAttribute) { fm.setRenamedToName(attributes->takeAt(i).value().toString()); - } else if (name == snakeCaseAttribute()) { + } else if (name == snakeCaseAttribute) { const auto attribute = attributes->takeAt(i); const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value()); if (snakeCaseOpt.has_value()) { @@ -2425,7 +2558,7 @@ bool TypeSystemParser::parseModifyField(const ConditionalStreamReader &, } } if (fm.name().isEmpty()) { - m_error = msgMissingAttribute(nameAttribute()); + m_error = msgMissingAttribute(nameAttribute); return false; } m_contextStack.top()->fieldMods << fm; @@ -2457,29 +2590,37 @@ bool TypeSystemParser::parseAddFunction(const ConditionalStreamReader &, ", was=%1").arg(tagFromElement(topElement)); return false; } + + FunctionModification mod; + if (!(t == StackElement::AddFunction + ? parseBasicModifyFunctionAttributes(attributes, &mod) + : parseModifyFunctionAttributes(attributes, &mod))) { + return false; + } + QString originalSignature; QString returnType; bool staticFunction = false; bool classMethod = false; + bool pythonOverride = false; QString access; - int overloadNumber = TypeSystem::OverloadNumberUnset; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == u"signature") { - originalSignature = attributes->takeAt(i).value().toString(); + if (name == signatureAttribute) { + originalSignature = attributes->takeAt(i).value().toString().simplified(); } else if (name == u"return-type") { returnType = attributes->takeAt(i).value().toString(); - } else if (name == staticAttribute()) { + } else if (name == staticAttribute) { staticFunction = convertBoolean(attributes->takeAt(i).value(), - staticAttribute(), false); - } else if (name == classmethodAttribute()) { + staticAttribute, false); + } else if (name == classmethodAttribute) { classMethod = convertBoolean(attributes->takeAt(i).value(), - classmethodAttribute(), false); - } else if (name == accessAttribute()) { + classmethodAttribute, false); + } else if (name == accessAttribute) { access = attributes->takeAt(i).value().toString(); - } else if (name == overloadNumberAttribute()) { - if (!parseOverloadNumber(attributes->takeAt(i), &overloadNumber, &m_error)) - return false; + } else if (name == pythonOverrideAttribute) { + pythonOverride = convertBoolean(attributes->takeAt(i).value(), + pythonOverrideAttribute, false); } } @@ -2496,13 +2637,15 @@ bool TypeSystemParser::parseAddFunction(const ConditionalStreamReader &, } AddedFunctionPtr func = AddedFunction::createAddedFunction(signature, returnType, &errorString); - if (func.isNull()) { + if (!func) { m_error = errorString; return false; } func->setStatic(staticFunction); func->setClassMethod(classMethod); + func->setPythonOverride(pythonOverride); + func->setTargetLangPackage(m_defaultPackage); // Create signature for matching modifications signature = TypeDatabase::normalizedSignature(originalSignature); @@ -2524,8 +2667,6 @@ bool TypeSystemParser::parseAddFunction(const ConditionalStreamReader &, m_contextStack.top()->addedFunctionModificationIndex = m_contextStack.top()->functionMods.size(); - FunctionModification mod; - mod.setOverloadNumber(overloadNumber); if (!mod.setSignature(m_currentSignature, &m_error)) return false; mod.setOriginalSignature(originalSignature); @@ -2544,9 +2685,9 @@ bool TypeSystemParser::parseAddPyMethodDef(const ConditionalStreamReader &, } TypeSystemPyMethodDefEntry def; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == nameAttribute()) { + if (name == nameAttribute) { def.name = attributes->takeAt(i).value().toString(); } else if (name == u"doc") { def.doc = attributes->takeAt(i).value().toString(); @@ -2569,7 +2710,7 @@ bool TypeSystemParser::parseAddPyMethodDef(const ConditionalStreamReader &, m_error = u"add-pymethoddef requires at least a name and a function attribute"_s; return false; } - static_cast<ComplexTypeEntry *>(m_contextStack.top()->entry)->addPyMethodDef(def); + std::static_pointer_cast<ComplexTypeEntry>(m_contextStack.top()->entry)->addPyMethodDef(def); return true; } @@ -2583,9 +2724,9 @@ bool TypeSystemParser::parseProperty(const ConditionalStreamReader &, StackEleme } TypeSystemProperty property; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == nameAttribute()) { + if (name == nameAttribute) { property.name = attributes->takeAt(i).value().toString(); } else if (name == u"get") { property.read = attributes->takeAt(i).value().toString(); @@ -2593,17 +2734,78 @@ bool TypeSystemParser::parseProperty(const ConditionalStreamReader &, StackEleme property.type = attributes->takeAt(i).value().toString(); } else if (name == u"set") { property.write = attributes->takeAt(i).value().toString(); - } else if (name == generateGetSetDefAttribute()) { + } else if (name == generateGetSetDefAttribute) { property.generateGetSetDef = convertBoolean(attributes->takeAt(i).value(), - generateGetSetDefAttribute(), false); + generateGetSetDefAttribute, false); } } if (!property.isValid()) { m_error = u"<property> element is missing required attibutes (name/type/get)."_s; return false; } - static_cast<ComplexTypeEntry *>(m_contextStack.top()->entry)->addProperty(property); + std::static_pointer_cast<ComplexTypeEntry>(m_contextStack.top()->entry)->addProperty(property); + return true; +} + +// Parse basic attributes applicable to <add-function>/<declare-function>/<function> +// and <modify-function> (all that is not done by injected code). +bool TypeSystemParser::parseBasicModifyFunctionAttributes(QXmlStreamAttributes *attributes, + FunctionModification *mod) +{ + for (auto i = attributes->size() - 1; i >= 0; --i) { + const auto name = attributes->at(i).qualifiedName(); + if (name == overloadNumberAttribute) { + int overloadNumber = TypeSystem::OverloadNumberUnset; + if (!parseOverloadNumber(attributes->takeAt(i), &overloadNumber, &m_error)) + return false; + mod->setOverloadNumber(overloadNumber); + } + } + return true; +} + +// Parse attributes applicable to <declare-function>/<function> +// and <modify-function>. +bool TypeSystemParser::parseModifyFunctionAttributes(QXmlStreamAttributes *attributes, + FunctionModification *mod) +{ + if (!parseBasicModifyFunctionAttributes(attributes, mod)) + return false; + + for (auto i = attributes->size() - 1; i >= 0; --i) { + const auto name = attributes->at(i).qualifiedName(); + if (name == allowThreadAttribute) { + const QXmlStreamAttribute attribute = attributes->takeAt(i); + const auto allowThreadOpt = allowThreadFromAttribute(attribute.value()); + if (!allowThreadOpt.has_value()) { + m_error = msgInvalidAttributeValue(attribute); + return false; + } + mod->setAllowThread(allowThreadOpt.value()); + } else if (name == exceptionHandlingAttribute) { + const auto attribute = attributes->takeAt(i); + const auto exceptionOpt = exceptionHandlingFromAttribute(attribute.value()); + if (!exceptionOpt.has_value()) { + m_error = msgInvalidAttributeValue(attribute); + return false; + } + mod->setExceptionHandling(exceptionOpt.value()); + } else if (name == snakeCaseAttribute) { + const auto attribute = attributes->takeAt(i); + const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value()); + if (!snakeCaseOpt.has_value()) { + m_error = msgInvalidAttributeValue(attribute); + return false; + } + mod->setSnakeCase(snakeCaseOpt.value()); + } else if (name == deprecatedAttribute) { + const bool deprecated = convertBoolean(attributes->takeAt(i).value(), + deprecatedAttribute, false); + mod->setModifierFlag(deprecated ? FunctionModification::Deprecated + : FunctionModification::Undeprecated); + } + } return true; } @@ -2621,61 +2823,24 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader } QString originalSignature; + FunctionModification mod; + if (!parseModifyFunctionAttributes(attributes, &mod)) + return false; + QString access; bool removed = false; QString rename; - bool deprecated = false; - bool isThread = false; - int overloadNumber = TypeSystem::OverloadNumberUnset; - TypeSystem::ExceptionHandling exceptionHandling = TypeSystem::ExceptionHandling::Unspecified; - TypeSystem::AllowThread allowThread = TypeSystem::AllowThread::Unspecified; - TypeSystem::SnakeCase snakeCase = TypeSystem::SnakeCase::Unspecified; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == u"signature") { - originalSignature = attributes->takeAt(i).value().toString(); - } else if (name == accessAttribute()) { + if (name == signatureAttribute) { + originalSignature = attributes->takeAt(i).value().toString().simplified(); + } else if (name == accessAttribute) { access = attributes->takeAt(i).value().toString(); - } else if (name == renameAttribute()) { + } else if (name == renameAttribute) { rename = attributes->takeAt(i).value().toString(); - } else if (name == removeAttribute()) { + } else if (name == removeAttribute) { removed = convertRemovalAttribute(attributes->takeAt(i).value()); - } else if (name == deprecatedAttribute()) { - deprecated = convertBoolean(attributes->takeAt(i).value(), - deprecatedAttribute(), false); - } else if (name == threadAttribute()) { - isThread = convertBoolean(attributes->takeAt(i).value(), - threadAttribute(), false); - } else if (name == allowThreadAttribute()) { - const QXmlStreamAttribute attribute = attributes->takeAt(i); - const auto allowThreadOpt = allowThreadFromAttribute(attribute.value()); - if (!allowThreadOpt.has_value()) { - m_error = msgInvalidAttributeValue(attribute); - return false; - } - allowThread = allowThreadOpt.value(); - } else if (name == exceptionHandlingAttribute()) { - const auto attribute = attributes->takeAt(i); - const auto exceptionOpt = exceptionHandlingFromAttribute(attribute.value()); - if (exceptionOpt.has_value()) { - exceptionHandling = exceptionOpt.value(); - } else { - qCWarning(lcShiboken, "%s", - qPrintable(msgInvalidAttributeValue(attribute))); - } - } else if (name == overloadNumberAttribute()) { - if (!parseOverloadNumber(attributes->takeAt(i), &overloadNumber, &m_error)) - return false; - } else if (name == snakeCaseAttribute()) { - const auto attribute = attributes->takeAt(i); - const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value()); - if (snakeCaseOpt.has_value()) { - snakeCase = snakeCaseOpt.value(); - } else { - qCWarning(lcShiboken, "%s", - qPrintable(msgInvalidAttributeValue(attribute))); - } - } else if (name == virtualSlotAttribute()) { + } else if (name == virtualSlotAttribute || name == threadAttribute) { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedAttributeWarning(reader, name))); } @@ -2684,7 +2849,7 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader // Child of global <function> const auto &top = m_contextStack.top(); if (originalSignature.isEmpty() && top->entry->isFunction()) { - auto f = static_cast<const FunctionTypeEntry *>(top->entry); + auto f = std::static_pointer_cast<const FunctionTypeEntry>(top->entry); originalSignature = f->signatures().value(0); } @@ -2700,13 +2865,9 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader return false; } - FunctionModification mod; if (!mod.setSignature(signature, &m_error)) return false; mod.setOriginalSignature(originalSignature); - mod.setExceptionHandling(exceptionHandling); - mod.setOverloadNumber(overloadNumber); - mod.setSnakeCase(snakeCase); m_currentSignature = signature; if (!access.isEmpty()) { @@ -2716,17 +2877,14 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader return false; } const FunctionModification::ModifierFlag m = modifierFlagOpt.value(); - if (m == FunctionModification::Final || m == FunctionModification::NonFinal) { + if (m == FunctionModification::NonFinal) { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedAttributeValueWarning(reader, - accessAttribute(), access))); + accessAttribute, access))); } mod.setModifierFlag(m); } - if (deprecated) - mod.setModifierFlag(FunctionModification::Deprecated); - mod.setRemoved(removed); if (!rename.isEmpty()) { @@ -2734,10 +2892,6 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader mod.setModifierFlag(FunctionModification::Rename); } - mod.setIsThread(isThread); - if (allowThread != TypeSystem::AllowThread::Unspecified) - mod.setAllowThread(allowThread); - top->functionMods << mod; return true; } @@ -2750,7 +2904,7 @@ bool TypeSystemParser::parseReplaceDefaultExpression(const ConditionalStreamRead m_error = u"Replace default expression only allowed as child of argument modification"_s; return false; } - const int withIndex = indexOfAttribute(*attributes, u"with"); + const auto withIndex = indexOfAttribute(*attributes, u"with"); if (withIndex == -1 || attributes->at(withIndex).value().isEmpty()) { m_error = u"Default expression replaced with empty string. Use remove-default-expression instead."_s; return false; @@ -2771,9 +2925,9 @@ bool TypeSystemParser::parseReferenceCount(const ConditionalStreamReader &reader } ReferenceCount rc; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == actionAttribute()) { + if (name == actionAttribute) { const QXmlStreamAttribute attribute = attributes->takeAt(i); const auto actionOpt = referenceCountFromAttribute(attribute.value()); if (!actionOpt.has_value()) { @@ -2808,13 +2962,13 @@ bool TypeSystemParser::parseParentOwner(const ConditionalStreamReader &, return false; } ArgumentOwner ao; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == indexAttribute()) { + if (name == indexAttribute) { const QString index = attributes->takeAt(i).value().toString(); if (!parseArgumentIndex(index, &ao.index, &m_error)) return false; - } else if (name == actionAttribute()) { + } else if (name == actionAttribute) { const auto action = attributes->takeAt(i); const auto actionOpt = argumentOwnerActionFromAttribute(action.value()); if (!actionOpt.has_value()) { @@ -2828,46 +2982,62 @@ bool TypeSystemParser::parseParentOwner(const ConditionalStreamReader &, return true; } -bool TypeSystemParser::readFileSnippet(QXmlStreamAttributes *attributes, CodeSnip *snip) +std::optional<TypeSystemParser::Snippet> + TypeSystemParser::readFileSnippet(QXmlStreamAttributes *attributes) { - QString fileName; - QString snippetLabel; - for (int i = attributes->size() - 1; i >= 0; --i) { + Snippet result; + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == u"file") { - fileName = attributes->takeAt(i).value().toString(); - } else if (name == snippetAttribute()) { - snippetLabel = attributes->takeAt(i).value().toString(); + if (name == fileAttribute) { + result.fileName = attributes->takeAt(i).value().toString(); + } else if (name == snippetAttribute) { + result.snippetLabel = attributes->takeAt(i).value().toString(); } } - if (fileName.isEmpty()) - return true; - const QString resolved = m_context->db->modifiedTypesystemFilepath(fileName, m_currentPath); + if (result.fileName.isEmpty()) { + m_error = "Snippet missing file name"_L1; + return std::nullopt; + } + const QString resolved = m_context->db->modifiedTypesystemFilepath(result.fileName, + m_currentPath); if (!QFile::exists(resolved)) { m_error = u"File for inject code not exist: "_s - + QDir::toNativeSeparators(fileName); - return false; + + QDir::toNativeSeparators(result.fileName); + return std::nullopt; } QFile codeFile(resolved); if (!codeFile.open(QIODevice::Text | QIODevice::ReadOnly)) { m_error = msgCannotOpenForReading(codeFile); - return false; + return std::nullopt; } - const auto codeOptional = extractSnippet(QString::fromUtf8(codeFile.readAll()), snippetLabel); + const auto contentOptional = extractSnippet(QString::fromUtf8(codeFile.readAll()), + result.snippetLabel); codeFile.close(); - if (!codeOptional.has_value()) { - m_error = msgCannotFindSnippet(resolved, snippetLabel); - return false; + if (!contentOptional.has_value()) { + m_error = msgCannotFindSnippet(resolved, result.snippetLabel); + return std::nullopt; } + result.content = contentOptional.value(); + return result; +} + +bool TypeSystemParser::readCodeSnippet(QXmlStreamAttributes *attributes, CodeSnip *snip) +{ + if (!hasFileSnippetAttributes(attributes)) + return true; // Expecting inline content. + const auto snippetOptional = readFileSnippet(attributes); + if (!snippetOptional.has_value()) + return false; + const auto snippet = snippetOptional.value(); - QString source = fileName; - if (!snippetLabel.isEmpty()) - source += u" ("_s + snippetLabel + u')'; + QString source = snippet.fileName; + if (!snippet.snippetLabel.isEmpty()) + source += " ("_L1 + snippet.snippetLabel + u')'; QString content; QTextStream str(&content); str << "// ========================================================================\n" "// START of custom code block [file: " - << source << "]\n" << codeOptional.value() + << source << "]\n" << snippet.content << "// END of custom code block [file: " << source << "]\n// ========================================================================\n"; snip->addCode(content); @@ -2889,11 +3059,11 @@ bool TypeSystemParser::parseInjectCode(const ConditionalStreamReader &, TypeSystem::CodeSnipPosition position = TypeSystem::CodeSnipPositionBeginning; TypeSystem::Language lang = TypeSystem::TargetLangCode; CodeSnip snip; - if (!readFileSnippet(attributes, &snip)) + if (!readCodeSnippet(attributes, &snip)) return false; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == classAttribute()) { + if (name == classAttribute) { const auto attribute = attributes->takeAt(i); const auto langOpt = languageFromAttribute(attribute.value()); if (!langOpt.has_value()) { @@ -2901,7 +3071,7 @@ bool TypeSystemParser::parseInjectCode(const ConditionalStreamReader &, return false; } lang = langOpt.value(); - } else if (name == positionAttribute()) { + } else if (name == positionAttribute) { const auto attribute = attributes->takeAt(i); const auto positionOpt = codeSnipPositionFromAttribute(attribute.value()); if (!positionOpt.has_value()) { @@ -2915,29 +3085,36 @@ bool TypeSystemParser::parseInjectCode(const ConditionalStreamReader &, snip.position = position; snip.language = lang; - if (topElement == StackElement::ModifyFunction - || topElement == StackElement::AddFunction) { + switch (topElement) { + case StackElement::ModifyFunction: + case StackElement::AddFunction: { FunctionModification &mod = m_contextStack.top()->functionMods.last(); mod.appendSnip(snip); if (!snip.code().isEmpty()) mod.setModifierFlag(FunctionModification::CodeInjection); - } else { - m_contextStack.top()->entry->addCodeSnip(snip); + } + break; + case StackElement::Root: + std::static_pointer_cast<TypeSystemTypeEntry>(m_contextStack.top()->entry)->addCodeSnip(snip); + break; + default: + std::static_pointer_cast<ComplexTypeEntry>(m_contextStack.top()->entry)->addCodeSnip(snip); + break; } return true; } bool TypeSystemParser::parseInclude(const ConditionalStreamReader &, StackElement topElement, - TypeEntry *entry, QXmlStreamAttributes *attributes) + const TypeEntryPtr &entry, QXmlStreamAttributes *attributes) { QString fileName; Include::IncludeType location = Include::IncludePath; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); - if (name == fileNameAttribute()) { + if (name == fileNameAttribute) { fileName = attributes->takeAt(i).value().toString(); - } else if (name == locationAttribute()) { + } else if (name == locationAttribute) { const auto attribute = attributes->takeAt(i); const auto locationOpt = locationFromAttribute(attribute.value()); if (!locationOpt.has_value()) { @@ -2967,12 +3144,12 @@ bool TypeSystemParser::parseInclude(const ConditionalStreamReader &, bool TypeSystemParser::parseSystemInclude(const ConditionalStreamReader &, QXmlStreamAttributes *attributes) { - const int index = indexOfAttribute(*attributes, fileNameAttribute()); + const auto index = indexOfAttribute(*attributes, fileNameAttribute); if (index == -1) { - m_error = msgMissingAttribute(fileNameAttribute()); + m_error = msgMissingAttribute(fileNameAttribute); return false; } - TypeDatabase::instance()->addSystemInclude(attributes->takeAt(index).value().toString()); + TypeDatabase::instance()->addForceProcessSystemInclude(attributes->takeAt(index).value().toString()); return true; } @@ -2990,9 +3167,9 @@ TemplateInstance * "conversion-rule, native-to-target or add-conversion tags."_s; return nullptr; } - const int nameIndex = indexOfAttribute(*attributes, nameAttribute()); + const auto nameIndex = indexOfAttribute(*attributes, nameAttribute); if (nameIndex == -1) { - m_error = msgMissingAttribute(nameAttribute()); + m_error = msgMissingAttribute(nameAttribute); return nullptr; } return new TemplateInstance(attributes->takeAt(nameIndex).value().toString()); @@ -3007,11 +3184,11 @@ bool TypeSystemParser::parseReplace(const ConditionalStreamReader &, } QString from; QString to; - for (int i = attributes->size() - 1; i >= 0; --i) { + for (auto i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); if (name == u"from") from = attributes->takeAt(i).value().toString(); - else if (name == toAttribute()) + else if (name == toAttribute) to = attributes->takeAt(i).value().toString(); } m_templateInstance->addReplaceRule(from, to); @@ -3028,7 +3205,7 @@ bool TypeSystemParser::checkDuplicatedTypeEntry(const ConditionalStreamReader &r { if (t == StackElement::PrimitiveTypeEntry || t == StackElement::FunctionTypeEntry) return true; - const auto *duplicated = m_context->db->findType(name); + const auto duplicated = m_context->db->findType(name); if (!duplicated || duplicated->isNamespace()) return true; if (duplicated->isBuiltIn()) { @@ -3065,14 +3242,14 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack QXmlStreamAttributes attributes = reader.attributes(); VersionRange versionRange; - for (int i = attributes.size() - 1; i >= 0; --i) { + for (auto i = attributes.size() - 1; i >= 0; --i) { const auto name = attributes.at(i).qualifiedName(); - if (name == sinceAttribute()) { + if (name == sinceAttribute) { if (!parseVersion(attributes.takeAt(i).value().toString(), m_defaultPackage, &versionRange.since, &m_error)) { return false; } - } else if (name == untilAttribute()) { + } else if (name == untilAttribute) { if (!parseVersion(attributes.takeAt(i).value().toString(), m_defaultPackage, &versionRange.until, &m_error)) { return false; @@ -3081,7 +3258,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack } if (!m_defaultPackage.isEmpty() && !versionRange.isNull()) { - TypeDatabase* td = TypeDatabase::instance(); + auto *td = TypeDatabase::instance(); if (!td->checkApiVersion(m_defaultPackage, versionRange)) { ++m_ignoreDepth; return true; @@ -3106,7 +3283,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack } if (isTypeEntry(element) || element == StackElement::Root) - m_contextStack.push(StackElementContextPtr(new StackElementContext())); + m_contextStack.push(std::make_shared<StackElementContext>()); if (m_contextStack.isEmpty()) { m_error = msgNoRootTypeSystemEntry(); @@ -3119,11 +3296,11 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack if (isTypeEntry(element)) { QString name; if (element != StackElement::FunctionTypeEntry) { - const int nameIndex = indexOfAttribute(attributes, nameAttribute()); + const auto nameIndex = indexOfAttribute(attributes, nameAttribute); if (nameIndex != -1) { name = attributes.takeAt(nameIndex).value().toString(); } else if (element != StackElement::EnumTypeEntry) { // anonymous enum? - m_error = msgMissingAttribute(nameAttribute()); + m_error = msgMissingAttribute(nameAttribute); return false; } } @@ -3136,7 +3313,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack if (m_context->db->hasDroppedTypeEntries()) { const QString identifier = element == StackElement::FunctionTypeEntry - ? attributes.value(signatureAttribute()).toString() : name; + ? attributes.value(signatureAttribute).toString().simplified() : name; if (shouldDropTypeEntry(m_context->db, m_contextStack, identifier)) { m_currentDroppedEntryDepth = 1; if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { @@ -3160,14 +3337,15 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack // types (which we need to do in order to support fake meta objects) if (element != StackElement::PrimitiveTypeEntry && element != StackElement::FunctionTypeEntry) { - TypeEntry *tmp = m_context->db->findType(name); + TypeEntryPtr tmp = m_context->db->findType(name); if (tmp && !tmp->isNamespace()) qCWarning(lcShiboken).noquote().nospace() << "Duplicate type entry: '" << name << '\''; } if (element == StackElement::EnumTypeEntry) { - const int enumIdentifiedByIndex = indexOfAttribute(attributes, enumIdentifiedByValueAttribute()); + const auto enumIdentifiedByIndex = + indexOfAttribute(attributes, enumIdentifiedByValueAttribute); const QString identifiedByValue = enumIdentifiedByIndex != -1 ? attributes.takeAt(enumIdentifiedByIndex).value().toString() : QString(); if (name.isEmpty()) { @@ -3226,7 +3404,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack case StackElement::InterfaceTypeEntry: { if (!checkRootElement()) return false; - auto *ce = new ObjectTypeEntry(name, versionRange.since, currentParentTypeEntry()); + auto ce = std::make_shared<ObjectTypeEntry>(name, versionRange.since, currentParentTypeEntry()); top->entry = ce; applyCommonAttributes(reader, top->entry, &attributes); applyComplexTypeAttributes(reader, ce, &attributes); @@ -3274,7 +3452,8 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack || element == StackElement::ConversionRule || element == StackElement::AddFunction || element == StackElement::DeclareFunction - || element == StackElement::Template; + || element == StackElement::Template + || element == StackElement::OpaqueContainer; if (!topLevel && m_stack.at(m_stack.size() - 2) == StackElement::Root) { m_error = u"Tag requires parent: '"_s + tagName.toString() + u'\''; @@ -3313,11 +3492,16 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack const auto topParent = m_stack.value(m_stack.size() - 3, StackElement::None); if (isTypeEntry(topParent)) { - const int replaceIndex = indexOfAttribute(attributes, replaceAttribute()); + const auto replaceIndex = indexOfAttribute(attributes, replaceAttribute); const bool replace = replaceIndex == -1 || convertBoolean(attributes.takeAt(replaceIndex).value(), - replaceAttribute(), true); - top->entry->customConversion()->setReplaceOriginalTargetToNativeConversions(replace); + replaceAttribute, true); + auto customConversion = CustomConversion::getCustomConversion(top->entry); + if (!customConversion) { + m_error = msgMissingCustomConversion(top->entry); + return false; + } + customConversion->setReplaceOriginalTargetToNativeConversions(replace); } } break; @@ -3338,14 +3522,17 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack return false; break; case StackElement::SuppressedWarning: { - const int textIndex = indexOfAttribute(attributes, textAttribute()); + const auto textIndex = indexOfAttribute(attributes, textAttribute); if (textIndex == -1) { qCWarning(lcShiboken) << "Suppressed warning with no text specified"; } else { const QString suppressedWarning = attributes.takeAt(textIndex).value().toString(); - if (!m_context->db->addSuppressedWarning(suppressedWarning, &m_error)) + if (!m_context->db->addSuppressedWarning(suppressedWarning, + m_generate == TypeEntry::GenerateCode, + &m_error)) { return false; + } } } break; @@ -3414,32 +3601,39 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack return false; break; case StackElement::Rejection: - if (!addRejection(m_context->db, &attributes, &m_error)) + if (!addRejection(m_context->db, m_generate == TypeEntry::GenerateCode, + &attributes, &m_error)) { return false; + } break; case StackElement::SystemInclude: if (!parseSystemInclude(reader, &attributes)) return false; break; case StackElement::Template: { - const int nameIndex = indexOfAttribute(attributes, nameAttribute()); + const auto nameIndex = indexOfAttribute(attributes, nameAttribute); if (nameIndex == -1) { - m_error = msgMissingAttribute(nameAttribute()); + m_error = msgMissingAttribute(nameAttribute); return false; } - m_templateEntry = - new TemplateEntry(attributes.takeAt(nameIndex).value().toString()); + m_templateEntry.reset(new TemplateEntry(attributes.takeAt(nameIndex).value().toString())); } break; case StackElement::InsertTemplate: m_templateInstance.reset(parseInsertTemplate(reader, topElement, &attributes)); - if (m_templateInstance.isNull()) + if (!m_templateInstance) return false; break; case StackElement::Replace: if (!parseReplace(reader, topElement, &attributes)) return false; break; + case StackElement::OpaqueContainer: + if (!parseOpaqueContainerElement(&attributes)) + case StackElement::Configuration: + if (!parseConfiguration(topElement, &attributes)) + return false; + break; default: break; // nada } diff --git a/sources/shiboken6/ApiExtractor/typesystemparser_p.h b/sources/shiboken6/ApiExtractor/typesystemparser_p.h index c14a46c04..4d9d4fd92 100644 --- a/sources/shiboken6/ApiExtractor/typesystemparser_p.h +++ b/sources/shiboken6/ApiExtractor/typesystemparser_p.h @@ -4,14 +4,18 @@ #define TYPESYSTEMPARSER_H #include "typesystem.h" +#include "containertypeentry.h" #include "typedatabase.h" #include "typedatabase_p.h" +#include "typesystem_typedefs.h" #include "codesnip.h" #include <QtCore/QStack> #include <QtCore/QHash> #include <QtCore/QScopedPointer> -#include <QtCore/QSharedPointer> + +#include <memory> +#include <optional> QT_FORWARD_DECLARE_CLASS(QVersionNumber) QT_FORWARD_DECLARE_CLASS(QXmlStreamAttributes) @@ -100,6 +104,8 @@ enum class StackElement { ArgumentModifiers, ImportFile, + OpaqueContainer, + Configuration, Unimplemented }; @@ -120,19 +126,19 @@ struct StackElementContext FunctionModificationList functionMods; FieldModificationList fieldMods; DocModificationList docModifications; - TypeEntry* entry = nullptr; + TypeEntryPtr entry; int addedFunctionModificationIndex = -1; }; class TypeSystemParser { public: - Q_DISABLE_COPY(TypeSystemParser) + Q_DISABLE_COPY_MOVE(TypeSystemParser) - using StackElementContextPtr = QSharedPointer<StackElementContext>; + using StackElementContextPtr = std::shared_ptr<StackElementContext>; using ContextStack = QStack<StackElementContextPtr>; - explicit TypeSystemParser(const QSharedPointer<TypeDatabaseParserContext> &context, + explicit TypeSystemParser(const std::shared_ptr<TypeDatabaseParserContext> &context, bool generate); ~TypeSystemParser(); @@ -141,10 +147,17 @@ public: QString errorString() const { return m_error; } private: + struct Snippet + { + QString content; + QString fileName; + QString snippetLabel; + }; + bool parseXml(ConditionalStreamReader &reader); bool setupSmartPointerInstantiations(); bool startElement(const ConditionalStreamReader &reader, StackElement element); - SmartPointerTypeEntry *parseSmartPointerEntry(const ConditionalStreamReader &, + SmartPointerTypeEntryPtr parseSmartPointerEntry(const ConditionalStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes); @@ -154,51 +167,56 @@ private: bool importFileElement(const QXmlStreamAttributes &atts); - const TypeEntry *currentParentTypeEntry() const; + TypeEntryCPtr currentParentTypeEntry() const; bool checkRootElement(); - bool applyCommonAttributes(const ConditionalStreamReader &reader, TypeEntry *type, + bool applyCommonAttributes(const ConditionalStreamReader &reader, + const TypeEntryPtr &type, QXmlStreamAttributes *attributes); - PrimitiveTypeEntry * + PrimitiveTypeEntryPtr parsePrimitiveTypeEntry(const ConditionalStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *); - CustomTypeEntry * + CustomTypeEntryPtr parseCustomTypeEntry(const ConditionalStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *); - ContainerTypeEntry * + bool parseOpaqueContainers(QStringView s, OpaqueContainers *result); + ContainerTypeEntryPtr parseContainerTypeEntry(const ConditionalStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *); - EnumTypeEntry * + bool parseOpaqueContainerElement(QXmlStreamAttributes *attributes); + EnumTypeEntryPtr parseEnumTypeEntry(const ConditionalStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *); - FlagsTypeEntry * - parseFlagsEntry(const ConditionalStreamReader &, EnumTypeEntry *enumEntry, + FlagsTypeEntryPtr + parseFlagsEntry(const ConditionalStreamReader &, const EnumTypeEntryPtr &enumEntry, QString flagName, const QVersionNumber &since, QXmlStreamAttributes *); - NamespaceTypeEntry * + NamespaceTypeEntryPtr parseNamespaceTypeEntry(const ConditionalStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes); - ValueTypeEntry * + ValueTypeEntryPtr parseValueTypeEntry(const ConditionalStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *); - FunctionTypeEntry * + FunctionTypeEntryPtr parseFunctionTypeEntry(const ConditionalStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *); - TypedefEntry * + TypedefEntryPtr parseTypedefEntry(const ConditionalStreamReader &, const QString &name, StackElement topElement, const QVersionNumber &since, QXmlStreamAttributes *); - void applyComplexTypeAttributes(const ConditionalStreamReader &, ComplexTypeEntry *ctype, + void applyComplexTypeAttributes(const ConditionalStreamReader &, const ComplexTypeEntryPtr &ctype, QXmlStreamAttributes *) const; + bool parseConfiguration(StackElement topElement, + QXmlStreamAttributes *attributes); bool parseRenameFunction(const ConditionalStreamReader &, QString *name, QXmlStreamAttributes *); bool parseInjectDocumentation(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); bool parseModifyDocumentation(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); - TypeSystemTypeEntry * + TypeSystemTypeEntryPtr parseRootElement(const ConditionalStreamReader &, const QVersionNumber &since, QXmlStreamAttributes *); bool loadTypesystem(const ConditionalStreamReader &, QXmlStreamAttributes *); @@ -226,6 +244,10 @@ private: StackElement topElement, QXmlStreamAttributes *attributes); bool parseProperty(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); + bool parseBasicModifyFunctionAttributes(QXmlStreamAttributes *, + FunctionModification *mod); + bool parseModifyFunctionAttributes(QXmlStreamAttributes *, + FunctionModification *mod); bool parseModifyFunction(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); bool parseReplaceDefaultExpression(const ConditionalStreamReader &, @@ -234,10 +256,11 @@ private: QXmlStreamAttributes *); bool parseParentOwner(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); - bool readFileSnippet(QXmlStreamAttributes *attributes, CodeSnip *snip); + std::optional<Snippet> readFileSnippet(QXmlStreamAttributes *attributes); + bool readCodeSnippet(QXmlStreamAttributes *attributes, CodeSnip *snip); bool parseInjectCode(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); bool parseInclude(const ConditionalStreamReader &, StackElement topElement, - TypeEntry *entry, QXmlStreamAttributes *); + const TypeEntryPtr &entry, QXmlStreamAttributes *); bool parseSystemInclude(const ConditionalStreamReader &, QXmlStreamAttributes *); TemplateInstance *parseInsertTemplate(const ConditionalStreamReader &, StackElement topElement, @@ -249,7 +272,7 @@ private: ParserState parserState(qsizetype offset = 0) const; CodeSnipAbstract *injectCodeTarget(qsizetype offset = 0) const; - QSharedPointer<TypeDatabaseParserContext> m_context; + std::shared_ptr<TypeDatabaseParserContext> m_context; QStack<StackElement> m_stack; int m_currentDroppedEntryDepth = 0; int m_ignoreDepth = 0; @@ -260,9 +283,9 @@ private: QString m_error; const TypeEntry::CodeGeneration m_generate; - EnumTypeEntry* m_currentEnum = nullptr; + EnumTypeEntryPtr m_currentEnum; TemplateInstancePtr m_templateInstance; - TemplateEntry *m_templateEntry = nullptr; + TemplateEntryPtr m_templateEntry; ContextStack m_contextStack; QString m_currentSignature; diff --git a/sources/shiboken6/ApiExtractor/typesystemtypeentry.h b/sources/shiboken6/ApiExtractor/typesystemtypeentry.h index 87d1101d3..9b9670696 100644 --- a/sources/shiboken6/ApiExtractor/typesystemtypeentry.h +++ b/sources/shiboken6/ApiExtractor/typesystemtypeentry.h @@ -5,18 +5,34 @@ #define TYPESYSTEMTYPEENTRY_H #include "typesystem.h" +#include "modifications_typedefs.h" +#include "typesystem_enums.h" +#include "typesystem_typedefs.h" class TypeSystemTypeEntry : public TypeEntry { public: explicit TypeSystemTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); TypeEntry *clone() const override; TypeSystem::SnakeCase snakeCase() const; void setSnakeCase(TypeSystem::SnakeCase sc); + const CodeSnipList &codeSnips() const; + CodeSnipList &codeSnips(); + void addCodeSnip(const CodeSnip &codeSnip); + + QString subModuleOf() const; + void setSubModule(const QString &); + + const QString &namespaceBegin() const; + void setNamespaceBegin(const QString &n); + + const QString &namespaceEnd() const; + void setNamespaceEnd(const QString &n); + protected: explicit TypeSystemTypeEntry(TypeEntryPrivate *d); }; diff --git a/sources/shiboken6/ApiExtractor/usingmember.h b/sources/shiboken6/ApiExtractor/usingmember.h index d908da0cd..346eab13c 100644 --- a/sources/shiboken6/ApiExtractor/usingmember.h +++ b/sources/shiboken6/ApiExtractor/usingmember.h @@ -5,14 +5,14 @@ #define USINGMEMBER_H #include "abstractmetalang_typedefs.h" -#include "parser/codemodel.h" +#include "parser/codemodel_enums.h" QT_FORWARD_DECLARE_CLASS(QDebug) struct UsingMember // Introducing a base class member via 'using' directive { QString memberName; - const AbstractMetaClass *baseClass; + AbstractMetaClassCPtr baseClass; Access access; }; diff --git a/sources/shiboken6/ApiExtractor/valuetypeentry.h b/sources/shiboken6/ApiExtractor/valuetypeentry.h index 15cac1a79..97bc26803 100644 --- a/sources/shiboken6/ApiExtractor/valuetypeentry.h +++ b/sources/shiboken6/ApiExtractor/valuetypeentry.h @@ -5,12 +5,27 @@ #define VALUETYPEENTRY_H #include "complextypeentry.h" +#include "customconversion_typedefs.h" class ValueTypeEntry : public ComplexTypeEntry { public: explicit ValueTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); + + bool hasCustomConversion() const; + void setCustomConversion(const CustomConversionPtr &customConversion); + CustomConversionPtr customConversion() const; + + // FIXME PYSIDE7: Remove + /// Set the target type conversion rule + void setTargetConversionRule(const QString &conversionRule); + + /// Returns the target type conversion rule + QString targetConversionRule() const; + + /// TODO-CONVERTER: mark as deprecated + bool hasTargetConversionRule() const; bool isValue() const override; @@ -18,7 +33,7 @@ public: protected: explicit ValueTypeEntry(const QString &entryName, Type t, const QVersionNumber &vr, - const TypeEntry *parent); + const TypeEntryCPtr &parent); explicit ValueTypeEntry(ComplexTypeEntryPrivate *d); }; diff --git a/sources/shiboken6/ApiExtractor/xmlutils.cpp b/sources/shiboken6/ApiExtractor/xmlutils.cpp index b0c9c2084..ccacd4ce7 100644 --- a/sources/shiboken6/ApiExtractor/xmlutils.cpp +++ b/sources/shiboken6/ApiExtractor/xmlutils.cpp @@ -21,13 +21,13 @@ QString XQuery::evaluate(QString xPathExpression, QString *errorMessage) return doEvaluate(xPathExpression, errorMessage); } -QSharedPointer<XQuery> XQuery::create(const QString &focus, QString *errorMessage) +std::shared_ptr<XQuery> XQuery::create(const QString &focus, QString *errorMessage) { #if defined(HAVE_LIBXSLT) return libXml_createXQuery(focus, errorMessage); #else *errorMessage = QLatin1StringView(__FUNCTION__) + u" is not implemented."_s; - return QSharedPointer<XQuery>(); + return std::shared_ptr<XQuery>(); #endif } diff --git a/sources/shiboken6/ApiExtractor/xmlutils.h b/sources/shiboken6/ApiExtractor/xmlutils.h index 2d6adbe9e..ac23c9c9c 100644 --- a/sources/shiboken6/ApiExtractor/xmlutils.h +++ b/sources/shiboken6/ApiExtractor/xmlutils.h @@ -3,19 +3,20 @@ #ifndef XMLUTILS_H #define XMLUTILS_H -#include <QtCore/QSharedPointer> #include <QtCore/QString> +#include <memory> + class XQuery { public: - Q_DISABLE_COPY(XQuery); + Q_DISABLE_COPY_MOVE(XQuery) virtual ~XQuery(); QString evaluate(QString xPathExpression, QString *errorMessage); - static QSharedPointer<XQuery> create(const QString &focus, QString *errorMessage); + static std::shared_ptr<XQuery> create(const QString &focus, QString *errorMessage); protected: XQuery(); diff --git a/sources/shiboken6/ApiExtractor/xmlutils_libxslt.cpp b/sources/shiboken6/ApiExtractor/xmlutils_libxslt.cpp index fad8889fa..5a9a26913 100644 --- a/sources/shiboken6/ApiExtractor/xmlutils_libxslt.cpp +++ b/sources/shiboken6/ApiExtractor/xmlutils_libxslt.cpp @@ -40,8 +40,6 @@ static void ensureInitialized() } } -namespace { - // RAI Helpers for cleaning up libxml2/libxslt data struct XmlDocDeleter // for std::unique_ptr<xmlDoc> @@ -64,8 +62,6 @@ struct XmlXPathContextDeleter void operator()(xmlXPathContextPtr xPathContext) { xmlXPathFreeContext(xPathContext); } }; -} // namespace - using XmlDocUniquePtr = std::unique_ptr<xmlDoc, XmlDocDeleter>; using XmlPathObjectUniquePtr = std::unique_ptr<xmlXPathObject, XmlXPathObjectDeleter>; using XmlStyleSheetUniquePtr = std::unique_ptr<xsltStylesheet, XmlStyleSheetDeleter>; @@ -141,9 +137,10 @@ QString LibXmlXQuery::doEvaluate(const QString &xPathExpression, QString *errorM return result; } -QSharedPointer<XQuery> libXml_createXQuery(const QString &focus, QString *errorMessage) +std::shared_ptr<XQuery> libXml_createXQuery(const QString &focus, QString *errorMessage) { - XmlDocUniquePtr doc(xmlParseFile(QFile::encodeName(focus).constData())); + XmlDocUniquePtr doc(xmlReadFile(QFile::encodeName(focus).constData(), + "utf-8", XML_PARSE_NOENT)); if (!doc) { *errorMessage = u"libxml2: Cannot set focus to "_s + QDir::toNativeSeparators(focus); return {}; @@ -153,25 +150,27 @@ QSharedPointer<XQuery> libXml_createXQuery(const QString &focus, QString *errorM *errorMessage = u"libxml2: xmlXPathNewContext() failed"_s; return {}; } - return QSharedPointer<XQuery>(new LibXmlXQuery(doc, xpathContext)); + return std::shared_ptr<XQuery>(new LibXmlXQuery(doc, xpathContext)); } // XSLT transformation -static const char xsltPrefix[] = R"(<?xml version="1.0" encoding="UTF-8" ?> +static constexpr auto xsltPrefix = R"(<?xml version="1.0" encoding="UTF-8" ?> <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> -)"; +)"_L1; QString libXslt_transform(const QString &xml, QString xsl, QString *errorMessage) { ensureInitialized(); // Read XML data if (!xsl.startsWith(u"<?xml")) { - xsl.prepend(QLatin1StringView(xsltPrefix)); + xsl.prepend(xsltPrefix); xsl.append(u"</xsl:transform>"_s); } const QByteArray xmlData = xml.toUtf8(); - XmlDocUniquePtr xmlDoc(xmlParseMemory(xmlData.constData(), xmlData.size())); + + XmlDocUniquePtr xmlDoc(xmlReadMemory(xmlData.constData(), int(xmlData.size()), + "", "utf-8", XML_PARSE_NOENT)); if (!xmlDoc) { *errorMessage = u"xmlParseMemory() failed for XML."_s; return xml; diff --git a/sources/shiboken6/ApiExtractor/xmlutils_libxslt.h b/sources/shiboken6/ApiExtractor/xmlutils_libxslt.h index 3430dce71..0dd8eafcb 100644 --- a/sources/shiboken6/ApiExtractor/xmlutils_libxslt.h +++ b/sources/shiboken6/ApiExtractor/xmlutils_libxslt.h @@ -4,11 +4,12 @@ #define XMLUTILS_LIBXSLT_H #include <QtCore/QString> -#include <QtCore/QSharedPointer> + +#include <memory> class XQuery; -QSharedPointer<XQuery> libXml_createXQuery(const QString &focus, QString *errorMessage); +std::shared_ptr<XQuery> libXml_createXQuery(const QString &focus, QString *errorMessage); QString libXslt_transform(const QString &xml, QString xsl, QString *errorMessage); diff --git a/sources/shiboken6/ApiExtractor/xmlutils_qt.h b/sources/shiboken6/ApiExtractor/xmlutils_qt.h index f0c51915f..274827044 100644 --- a/sources/shiboken6/ApiExtractor/xmlutils_qt.h +++ b/sources/shiboken6/ApiExtractor/xmlutils_qt.h @@ -4,11 +4,12 @@ #define XMLUTILS_QT_H #include <QtCore/QString> -#include <QtCore/QSharedPointer> + +#include <memory> class XQuery; -QSharedPointer<XQuery> qt_createXQuery(const QString &focus, QString *errorMessage); +std::shared_ptr<XQuery> qt_createXQuery(const QString &focus, QString *errorMessage); QString qt_xsl_transform(const QString &xml, QString xsl, QString *errorMessage); |