diff options
Diffstat (limited to 'sources/shiboken6/ApiExtractor/abstractmetalang.cpp')
-rw-r--r-- | sources/shiboken6/ApiExtractor/abstractmetalang.cpp | 841 |
1 files changed, 460 insertions, 381 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp index 080257346..fb49cc9d0 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp @@ -1,36 +1,15 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// 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" @@ -38,13 +17,18 @@ #include "reporthandler.h" #include "sourcelocation.h" #include "typedatabase.h" -#include "typesystem.h" +#include "enumtypeentry.h" +#include "namespacetypeentry.h" #include "usingmember.h" +#include "qtcompat.h" + #include <QtCore/QDebug> #include <algorithm> +using namespace Qt::StringLiterals; + bool function_sorter(const AbstractMetaFunctionCPtr &a, const AbstractMetaFunctionCPtr &b) { return a->signature() < b->signature(); @@ -66,24 +50,30 @@ public: m_hasPrivateDestructor(false), m_hasProtectedDestructor(false), m_hasVirtualDestructor(false), - m_hasHashFunction(false), - m_hasEqualsOperator(false), - m_hasCloneOperator(false), m_isTypeDef(false), m_hasToStringCapability(false), + m_valueTypeWithCopyConstructorOnly(false), m_hasCachedWrapper(false) { } void addFunction(const AbstractMetaFunctionCPtr &function); + static AbstractMetaFunction * + createFunction(const QString &name, AbstractMetaFunction::FunctionType t, + Access access, const AbstractMetaArgumentList &arguments, + 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; @@ -97,33 +87,33 @@ public: uint m_hasPrivateDestructor : 1; uint m_hasProtectedDestructor : 1; uint m_hasVirtualDestructor : 1; - uint m_hasHashFunction : 1; - uint m_hasEqualsOperator : 1; - uint m_hasCloneOperator : 1; uint m_isTypeDef : 1; uint m_hasToStringCapability : 1; + uint m_valueTypeWithCopyConstructorOnly : 1; mutable uint m_hasCachedWrapper : 1; Documentation m_doc; - const AbstractMetaClass *m_enclosingClass = nullptr; - AbstractMetaClass *m_defaultSuperclass = nullptr; - AbstractMetaClassList m_baseClasses; // Real base classes after setting up inheritance + 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; - AbstractMetaClassList m_innerClasses; + AbstractMetaClassCList m_innerClasses; + QString m_hashFunction; 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; @@ -160,24 +150,6 @@ void AbstractMetaClass::operator-=(AbstractMetaClass::Attribute attribute) d->m_attributes.setFlag(attribute, false); } -/******************************************************************************* - * Returns true if this class is a subclass of the given class - */ -bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const -{ - Q_ASSERT(cls); - - const AbstractMetaClass *clazz = this; - while (clazz) { - if (clazz == cls) - return true; - - clazz = clazz->baseClass(); - } - - return false; -} - bool AbstractMetaClass::isPolymorphic() const { return d->m_isPolymorphic; @@ -206,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::Constructors - | default_flags | public_flags); - - // Final functions - returned += queryFunctions(FunctionQueryOption::FinalInTargetLangFunctions - | FunctionQueryOption::NonStaticFunctions - | default_flags | public_flags); + AbstractMetaFunctionCList returned = queryFunctions(FunctionQueryOption::AnyConstructor + | 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); @@ -238,7 +197,7 @@ AbstractMetaFunctionCList AbstractMetaClass::functionsInTargetLang() const AbstractMetaFunctionCList AbstractMetaClass::implicitConversions() const { - if (!hasCloneOperator() && !hasExternalConversionOperators()) + if (!isCopyConstructible() && !hasExternalConversionOperators()) return {}; AbstractMetaFunctionCList returned; @@ -250,7 +209,6 @@ AbstractMetaFunctionCList AbstractMetaClass::implicitConversions() const for (const auto &f : list) { if ((f->actualMinimumArgumentCount() == 1 || f->arguments().size() == 1 || f->isConversionOperator()) && !f->isExplicit() - && f->functionType() != AbstractMetaFunction::CopyConstructorFunction && !f->usesRValueReferences() && !f->isModifiedRemoved() && f->wasPublic()) { @@ -348,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; } @@ -366,48 +324,29 @@ const AbstractMetaFunctionCList &AbstractMetaClass::functions() const return d->m_functions; } -void AbstractMetaClass::setFunctions(const AbstractMetaFunctionCList &functions) -{ - d->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); - if (!f->isPublic()) - d->m_hasNonpublic = true; - } -} - -bool AbstractMetaClass::hasDefaultToStringFunction() const +const AbstractMetaFunctionCList &AbstractMetaClass::userAddedPythonOverrides() const { - const auto &funcs = queryFunctionsByName(QLatin1String("toString")); - for (const auto &f : funcs) { - if (!f->actualMinimumArgumentCount()) - return true; - } - return false; + return d->m_userAddedPythonOverrides; } -bool AbstractMetaClass::hasEqualsOperator() const +void AbstractMetaClassPrivate::sortFunctions() { - return d->m_hasEqualsOperator; + std::sort(m_functions.begin(), m_functions.end(), function_sorter); } -void AbstractMetaClass::setHasEqualsOperator(bool on) +void AbstractMetaClassPrivate::setFunctions(const AbstractMetaFunctionCList &functions, + const AbstractMetaClassCPtr &q) { - d->m_hasEqualsOperator = on; -} + m_functions = functions; -bool AbstractMetaClass::hasCloneOperator() const -{ - return d->m_hasCloneOperator; -} + // Functions must be sorted by name before next loop + sortFunctions(); -void AbstractMetaClass::setHasCloneOperator(bool on) -{ - d->m_hasCloneOperator = on; + for (const auto &f : std::as_const(m_functions)) { + std::const_pointer_cast<AbstractMetaFunction>(f)->setOwnerClass(q); + if (!f->isPublic()) + m_hasNonpublic = true; + } } const QList<QPropertySpec> &AbstractMetaClass::propertySpecs() const @@ -420,9 +359,16 @@ 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(QLatin1Char('('))); + Q_ASSERT(!function->signature().startsWith(u'(')); if (!function->isDestructor()) m_functions << function; @@ -432,12 +378,31 @@ void AbstractMetaClassPrivate::addFunction(const AbstractMetaFunctionCPtr &funct m_hasVirtuals |= function->isVirtual(); m_isPolymorphic |= m_hasVirtuals; m_hasNonpublic |= !function->isPublic(); + m_hasNonPrivateConstructor |= !function->isPrivate() + && function->functionType() == AbstractMetaFunction::ConstructorFunction; } -void AbstractMetaClass::addFunction(const AbstractMetaFunctionCPtr &function) +void AbstractMetaClass::addFunction(const AbstractMetaClassPtr &klass, + const AbstractMetaFunctionCPtr &function) { - qSharedPointerConstCast<AbstractMetaFunction>(function)->setOwnerClass(this); - d->addFunction(function); + 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(klass); + + // Some of the queries below depend on the implementing class being set + // to function properly. Such as function modifications + nonConstF->setImplementingClass(klass); + + 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 @@ -475,32 +440,32 @@ QString AbstractMetaClass::baseClassName() const } // Attribute "default-superclass" -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; } -AbstractMetaClass *AbstractMetaClass::baseClass() const +AbstractMetaClassCPtr AbstractMetaClass::baseClass() const { return d->m_baseClasses.value(0, nullptr); } -const AbstractMetaClassList &AbstractMetaClass::baseClasses() const +const AbstractMetaClassCList &AbstractMetaClass::baseClasses() const { Q_ASSERT(inheritanceDone() || !needsInheritanceSetup()); return d->m_baseClasses; } // base classes including "defaultSuperclass". -AbstractMetaClassList AbstractMetaClass::typeSystemBaseClasses() const +AbstractMetaClassCList AbstractMetaClass::typeSystemBaseClasses() const { - AbstractMetaClassList result = d->m_baseClasses; - if (d->m_defaultSuperclass != nullptr) { + AbstractMetaClassCList result = d->m_baseClasses; + if (d->m_defaultSuperclass) { result.removeAll(d->m_defaultSuperclass); result.prepend(d->m_defaultSuperclass); } @@ -508,25 +473,25 @@ AbstractMetaClassList AbstractMetaClass::typeSystemBaseClasses() const } // Recursive list of all base classes including defaultSuperclass -AbstractMetaClassList AbstractMetaClass::allTypeSystemAncestors() const +AbstractMetaClassCList AbstractMetaClass::allTypeSystemAncestors() const { - AbstractMetaClassList result; - const AbstractMetaClassList baseClasses = typeSystemBaseClasses(); - for (AbstractMetaClass *base : baseClasses) { + AbstractMetaClassCList result; + const auto baseClasses = typeSystemBaseClasses(); + for (const auto &base : baseClasses) { result.append(base); result.append(base->allTypeSystemAncestors()); } return result; } -void AbstractMetaClass::addBaseClass(AbstractMetaClass *baseClass) +void AbstractMetaClass::addBaseClass(const AbstractMetaClassCPtr &baseClass) { Q_ASSERT(baseClass); d->m_baseClasses.append(baseClass); d->m_isPolymorphic |= baseClass->isPolymorphic(); } -void AbstractMetaClass::setBaseClass(AbstractMetaClass *baseClass) +void AbstractMetaClass::setBaseClass(const AbstractMetaClassCPtr &baseClass) { if (baseClass) { d->m_baseClasses.prepend(baseClass); @@ -534,27 +499,27 @@ void AbstractMetaClass::setBaseClass(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; } -const AbstractMetaClassList &AbstractMetaClass::innerClasses() const +const AbstractMetaClassCList &AbstractMetaClass::innerClasses() const { return d->m_innerClasses; } -void AbstractMetaClass::addInnerClass(AbstractMetaClass *cl) +void AbstractMetaClass::addInnerClass(const AbstractMetaClassPtr &cl) { d->m_innerClasses << cl; } -void AbstractMetaClass::setInnerClasses(const AbstractMetaClassList &innerClasses) +void AbstractMetaClass::setInnerClasses(const AbstractMetaClassCList &innerClasses) { d->m_innerClasses = innerClasses; } @@ -577,19 +542,19 @@ bool AbstractMetaClass::isInvisibleNamespace() const && !NamespaceTypeEntry::isVisibleScope(d->m_typeEntry); } -static bool qObjectPredicate(const AbstractMetaClass *c) -{ - return c->qualifiedCppName() == QLatin1String("QObject"); -} - -bool AbstractMetaClass::isQObject() const +bool AbstractMetaClass::isInlineNamespace() const { - return qObjectPredicate(this) || recurseClassHierarchy(this, qObjectPredicate) != nullptr; + 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() == QLatin1String("Qt"); + return isNamespace() && name() == u"Qt"; } QString AbstractMetaClass::qualifiedCppName() const @@ -599,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(const QString &functionName) const +AbstractMetaFunctionCPtr AbstractMetaClass::findFunction(QAnyStringView functionName) const { return AbstractMetaFunction::find(d->m_functions, functionName); } -AbstractMetaFunctionCList AbstractMetaClass::findFunctions(const QString &functionName) const +AbstractMetaFunctionCList AbstractMetaClass::findFunctions(QAnyStringView functionName) const { AbstractMetaFunctionCList result; std::copy_if(d->m_functions.cbegin(), d->m_functions.cend(), @@ -640,15 +605,6 @@ AbstractMetaFunctionCPtr AbstractMetaClass::findQtIsNullMethod() const return *it; } -bool AbstractMetaClass::hasProtectedFunctions() const -{ - for (const auto &func : d->m_functions) { - if (func->isProtected()) - return true; - } - return false; -} - bool AbstractMetaClass::hasProtectedFields() const { for (const AbstractMetaField &field : d->m_fields) { @@ -658,17 +614,12 @@ bool AbstractMetaClass::hasProtectedFields() const return false; } -bool AbstractMetaClass::hasProtectedMembers() const -{ - return hasProtectedFields() || hasProtectedFunctions(); -} - -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; } @@ -683,36 +634,41 @@ 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; } -void AbstractMetaClass::setHasHashFunction(bool on) +QString AbstractMetaClass::hashFunction() const { - d->m_hasHashFunction = on; + return d->m_hashFunction; +} + +void AbstractMetaClass::setHashFunction(const QString &f) +{ + d->m_hashFunction = f; } bool AbstractMetaClass::hasHashFunction() const { - return d->m_hasHashFunction; + return !d->m_hashFunction.isEmpty(); } // Search whether a functions is a property setter/getter/reset 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}; @@ -720,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}; } @@ -727,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 {}; } @@ -812,7 +769,16 @@ bool AbstractMetaClass::deleteInMainThread() const bool AbstractMetaClassPrivate::hasConstructors() const { return AbstractMetaClass::queryFirstFunction(m_functions, - FunctionQueryOption::Constructors) != nullptr; + 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 @@ -837,51 +803,95 @@ 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 = new AbstractMetaFunction; - f->setType(AbstractMetaType::createVoid()); - f->setOriginalName(q->name()); - f->setName(q->name()); - f->setOwnerClass(q); - f->setFunctionType(t); - f->setArguments(arguments); - f->setDeclaringClass(q); - f->setAccess(access); + 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->setImplementingClass(q); - + 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()); + + klass->d->addConstructor(AbstractMetaFunction::CopyConstructorFunction, + Access::Public, {arg}, klass); +} + +AbstractMetaFunction * + AbstractMetaClassPrivate::createFunction(const QString &name, + AbstractMetaFunction::FunctionType t, + Access access, + const AbstractMetaArgumentList &arguments, + const AbstractMetaType &returnType, + const AbstractMetaClassPtr &q) +{ + auto *f = new AbstractMetaFunction(name); + f->setType(returnType); + f->setOwnerClass(q); + f->setFunctionType(t); + f->setArguments(arguments); + f->setDeclaringClass(q); + f->setAccess(access); + f->setImplementingClass(q); + return f; +} - d->addConstructor(AbstractMetaFunction::CopyConstructorFunction, - Access::Public, {arg}, this); +static AbstractMetaType boolType() +{ + auto boolType = TypeDatabase::instance()->findType(u"bool"_s); + Q_ASSERT(boolType); + AbstractMetaType result(boolType); + result.decideUsagePattern(); + return result; +} + +// 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(const AbstractMetaClassPtr &c) +{ + static const auto returnType = boolType(); + + AbstractMetaType selfType(c->typeEntry()); + selfType.setConstant(true); + selfType.setReferenceType(LValueReference); + selfType.decideUsagePattern(); + AbstractMetaArgument selfArgument; + selfArgument.setType(selfType); + selfArgument.setName(u"rhs"_s); + AbstractMetaArgumentList arguments(1, selfArgument); + + static const char *operators[] + = {"operator==", "operator!=", "operator<", "operator<=", "operator>", "operator>="}; + for (auto *op : operators) { + auto *f = AbstractMetaClassPrivate::createFunction(QLatin1StringView(op), + AbstractMetaFunction::ComparisonOperator, + Access::Public, arguments, + returnType, c); + c->d->addFunction(AbstractMetaFunctionCPtr(f)); + } } bool AbstractMetaClass::hasNonPrivateConstructor() const @@ -974,6 +984,8 @@ bool AbstractMetaClass::isDefaultConstructible() const // (non-ref or not const value). static bool defaultConstructibleField(const AbstractMetaField &f) { + if (f.isStatic()) + return true; const auto &type = f.type(); return type.referenceType() == NoReference && !(type.indirections() == 0 && type.isConstant()); // no const values @@ -984,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(); }); } @@ -992,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(); } @@ -1018,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(); }); } @@ -1033,6 +1046,21 @@ bool AbstractMetaClass::canAddDefaultCopyConstructor() const return isImplicitlyCopyConstructible(); } +static bool classHasParentManagement(const AbstractMetaClassCPtr &c) +{ + const auto flags = c->typeEntry()->typeFlags(); + return flags.testFlag(ComplexTypeEntry::ParentManagement); +} + +TypeEntryCPtr parentManagementEntry(const AbstractMetaClassCPtr &klass) +{ + if (klass->typeEntry()->isObject()) { + if (auto c = recurseClassHierarchy(klass, classHasParentManagement)) + return c->typeEntry(); + } + return nullptr; +} + bool AbstractMetaClass::generateExceptionHandling() const { return queryFirstFunction(d->m_functions, FunctionQueryOption::Visible @@ -1097,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 { @@ -1108,13 +1136,21 @@ 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 { return d->isUsingMember(c, memberName, minimumAccess); } +bool AbstractMetaClass::hasUsingMemberFor(const QString &memberName) const +{ + return std::any_of(d->m_usingMembers.cbegin(), d->m_usingMembers.cend(), + [&memberName](const UsingMember &um) { + return um.memberName == memberName; + }); +} + /* Goes through the list of functions and returns a list of all functions matching all of the criteria in \a query. */ @@ -1131,35 +1167,32 @@ 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; if (query.testFlag(FunctionQueryOption::Signals) && (!f->isSignal())) return false; - if (query.testFlag(FunctionQueryOption::Constructors) + if (query.testFlag(FunctionQueryOption::AnyConstructor) && (!f->isConstructor() || f->ownerClass() != f->implementingClass())) { return false; } + if (query.testFlag(FunctionQueryOption::Constructors) + && (f->functionType() != AbstractMetaFunction::ConstructorFunction + || f->ownerClass() != f->implementingClass())) { + return false; + } + if (query.testFlag(FunctionQueryOption::CopyConstructor) && (!f->isCopyConstructor() || f->ownerClass() != f->implementingClass())) { return false; @@ -1206,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; @@ -1216,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 {}; @@ -1243,7 +1276,7 @@ AbstractMetaFunctionCList AbstractMetaClass::cppSignalFunctions() const } std::optional<AbstractMetaField> - AbstractMetaClass::findField(const QString &name) const + AbstractMetaClass::findField(QStringView name) const { return AbstractMetaField::find(d->m_fields, name); } @@ -1284,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; @@ -1306,7 +1339,7 @@ void AbstractMetaClass::getEnumsToBeGenerated(AbstractMetaEnumList *enumList) co void AbstractMetaClass::getEnumsFromInvisibleNamespacesToBeGenerated(AbstractMetaEnumList *enumList) const { if (isNamespace()) { - invisibleNamespaceRecursion([enumList](AbstractMetaClass *c) { + invisibleNamespaceRecursion([enumList](const AbstractMetaClassCPtr &c) { c->getEnumsToBeGenerated(enumList); }); } @@ -1315,7 +1348,7 @@ void AbstractMetaClass::getEnumsFromInvisibleNamespacesToBeGenerated(AbstractMet void AbstractMetaClass::getFunctionsFromInvisibleNamespacesToBeGenerated(AbstractMetaFunctionCList *funcList) const { if (isNamespace()) { - invisibleNamespaceRecursion([funcList](AbstractMetaClass *c) { + invisibleNamespaceRecursion([funcList](const AbstractMetaClassCPtr &c) { funcList->append(c->functions()); }); } @@ -1323,19 +1356,19 @@ void AbstractMetaClass::getFunctionsFromInvisibleNamespacesToBeGenerated(Abstrac QString AbstractMetaClass::fullName() const { - return package() + QLatin1Char('.') + d->m_typeEntry->targetLangName(); + 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->addExtraInclude(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()) { @@ -1344,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); @@ -1352,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) @@ -1375,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. @@ -1384,14 +1421,13 @@ 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. const auto ctors = superClass->queryFunctions(FunctionQueryOption::Constructors); for (const auto &ctor : ctors) { - if (ctor->functionType() == AbstractMetaFunction::ConstructorFunction - && !ctor->isPrivate()) { + if (!ctor->isPrivate()) { addConstructor(AbstractMetaFunction::ConstructorFunction, ctor->access(), ctor->arguments(), q); } @@ -1400,50 +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 superClass : d->m_baseClasses) { - 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 @@ -1454,35 +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) { - // 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 - } + // Set "override" in case it was not spelled out (since it + // is then not detected by clang parsing). + 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 @@ -1494,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) { @@ -1558,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)); @@ -1567,16 +1573,19 @@ void AbstractMetaClass::fixFunctions() bool hasPrivateConstructors = false; bool hasPublicConstructors = false; - for (const auto &func : qAsConst(funcs)) { - for (const auto &mod : func->modifications(this)) { + // Apply modifications after the declaring class has been set + 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()) - qSharedPointerConstCast<AbstractMetaFunction>(func)->setName(mod.renamedToName()); + ncFunc->setName(mod.renamedToName()); } + ncFunc->applyTypeModifications(); // 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()) { @@ -1589,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 @@ -1606,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; @@ -1628,26 +1638,6 @@ bool AbstractMetaClass::inheritanceDone() const * Other stuff... */ - -std::optional<AbstractMetaEnum> - AbstractMetaClass::findEnum(const AbstractMetaClassList &classes, - const EnumTypeEntry *entry) -{ - Q_ASSERT(entry->isEnum()); - - auto scopeEntry = entry->parent(); - AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes, scopeEntry); - if (!metaClass) { - qCWarning(lcShiboken, "%s", qPrintable(msgClassOfEnumNotFound(entry))); - return {}; - } - - QString qualifiedName = entry->qualifiedCppName(); - const int pos = qualifiedName.lastIndexOf(QLatin1String("::")); - const QString enumName = pos > 0 ? qualifiedName.mid(pos + 2) : qualifiedName; - return metaClass->findEnum(enumName); -} - std::optional<AbstractMetaEnumValue> AbstractMetaClass::findEnumValue(const AbstractMetaClassList &classes, const QString &name) @@ -1657,11 +1647,11 @@ std::optional<AbstractMetaEnumValue> if (lst.size() > 1) { const auto &prefixName = lst.at(0); const auto &enumName = lst.at(1); - if (AbstractMetaClass *cl = findClass(classes, prefixName.toString())) + 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; @@ -1675,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, const QString &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; @@ -1693,7 +1683,7 @@ static It findClassHelper(It begin, It end, const QString &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) { @@ -1704,32 +1694,32 @@ static It findClassHelper(It begin, It end, const QString &name) return end; } -AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes, - const QString &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, - const QString &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) @@ -1738,13 +1728,42 @@ const AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassCLi return nullptr; } -const AbstractMetaClass *AbstractMetaClass::findBaseClass(const QString &qualifiedName) const +/// Returns true if this class is a subclass of the given class +bool inheritsFrom(const AbstractMetaClassCPtr &c, const AbstractMetaClassCPtr &cls) { - if (d->m_templateBaseClass != nullptr - && d->m_templateBaseClass->qualifiedCppName() == qualifiedName) { - return d->m_templateBaseClass; + Q_ASSERT(cls != nullptr); + + if (c == cls || c->templateBaseClass() == cls) + return true; + + return bool(recurseClassHierarchy(c, [cls](const AbstractMetaClassCPtr &c) { + return cls.get() == c.get(); + })); +} + +bool inheritsFrom(const AbstractMetaClassCPtr &c, QAnyStringView name) +{ + if (c->qualifiedCppName() == name) + return true; + + if (c->templateBaseClass() != nullptr + && c->templateBaseClass()->qualifiedCppName() == name) { + return true; } - return recurseClassHierarchy(this, [&qualifiedName](const AbstractMetaClass *c) { + + return bool(recurseClassHierarchy(c, [&name](const AbstractMetaClassCPtr &c) { + return c->qualifiedCppName() == name; + })); +} + +AbstractMetaClassCPtr findBaseClass(const AbstractMetaClassCPtr &c, + const QString &qualifiedName) +{ + auto tp = c->templateBaseClass(); + if (tp && tp->qualifiedCppName() == qualifiedName) + return tp; + + return recurseClassHierarchy(c, [&qualifiedName](const AbstractMetaClassCPtr &c) { return c->qualifiedCppName() == qualifiedName; }); } @@ -1761,21 +1780,35 @@ bool AbstractMetaClass::isCopyable() const return false; auto copyable = d->m_typeEntry->copyable(); return copyable == ComplexTypeEntry::CopyableSet - || (copyable == ComplexTypeEntry::Unknown && hasCloneOperator()); + || (copyable == ComplexTypeEntry::Unknown && isCopyConstructible()); } bool AbstractMetaClass::isValueTypeWithCopyConstructorOnly() const { - if (!typeEntry()->isValue()) + return d->m_valueTypeWithCopyConstructorOnly; +} + +void AbstractMetaClass::setValueTypeWithCopyConstructorOnly(bool v) +{ + d->m_valueTypeWithCopyConstructorOnly = v; +} + +bool AbstractMetaClass::determineValueTypeWithCopyConstructorOnly(const AbstractMetaClassCPtr &c, + bool avoidProtectedHack) +{ + + if (!c->typeEntry()->isValue()) return false; - if (attributes().testFlag(AbstractMetaClass::HasRejectedDefaultConstructor)) + if (c->attributes().testFlag(AbstractMetaClass::HasRejectedDefaultConstructor)) return false; - const auto ctors = queryFunctions(FunctionQueryOption::Constructors); + const auto ctors = c->queryFunctions(FunctionQueryOption::AnyConstructor); bool copyConstructorFound = false; for (const auto &ctor : ctors) { switch (ctor->functionType()) { case AbstractMetaFunction::ConstructorFunction: - return false; + if (!ctor->isPrivate() && (ctor->isPublic() || !avoidProtectedHack)) + return false; + break; case AbstractMetaFunction::CopyConstructorFunction: copyConstructorFound = true; break; @@ -1796,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 << '>'; } @@ -1808,9 +1841,25 @@ void AbstractMetaClass::format(QDebug &debug) const debug << " [final]"; if (attributes().testFlag(AbstractMetaClass::Deprecated)) debug << " [deprecated]"; + + if (d->m_hasPrivateConstructor) + debug << " [private constructor]"; + if (d->m_hasDeletedDefaultConstructor) + debug << " [deleted default constructor]"; + if (d->m_hasDeletedCopyConstructor) + debug << " [deleted copy constructor]"; + if (d->m_hasPrivateDestructor) + debug << " [private destructor]"; + if (d->m_hasProtectedDestructor) + debug << " [protected destructor]"; + if (d->m_hasVirtualDestructor) + debug << " [virtual destructor]"; + if (d->m_valueTypeWithCopyConstructorOnly) + debug << " [value type with copy constructor only]"; + if (!d->m_baseClasses.isEmpty()) { debug << ", inherits "; - for (auto b : d->m_baseClasses) + for (const auto &b : d->m_baseClasses) debug << " \"" << b->name() << '"'; } @@ -1825,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); @@ -1845,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); @@ -1875,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); @@ -1885,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 |