diff options
Diffstat (limited to 'sources/shiboken6/ApiExtractor/abstractmetalang.cpp')
-rw-r--r-- | sources/shiboken6/ApiExtractor/abstractmetalang.cpp | 544 |
1 files changed, 284 insertions, 260 deletions
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 |