diff options
Diffstat (limited to 'sources/shiboken2/ApiExtractor/abstractmetalang.cpp')
-rw-r--r-- | sources/shiboken2/ApiExtractor/abstractmetalang.cpp | 693 |
1 files changed, 323 insertions, 370 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index a040f3caa..f1f01e02c 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt for Python. @@ -28,6 +28,7 @@ #include "abstractmetalang.h" #include "messages.h" +#include "propertyspec.h" #include "reporthandler.h" #include "typedatabase.h" #include "typesystem.h" @@ -80,19 +81,57 @@ const AbstractMetaClass *recurseClassHierarchy(const AbstractMetaClass *klass, { if (pred(klass)) return klass; - if (auto base = klass->baseClass()) { + for (auto base : klass->baseClasses()) { if (auto r = recurseClassHierarchy(base, pred)) return r; } - const auto interfaces = klass->interfaces(); - for (auto i : interfaces) { - if (auto r = recurseClassHierarchy(i, pred)) - return r; - } return nullptr; } /******************************************************************************* + * Documentation + */ + +Documentation::Documentation(const QString &value, Documentation::Type t, Documentation::Format fmt) +{ + setValue(value, t, fmt); +} + +bool Documentation::isEmpty() const +{ + for (int i = 0; i < Type::Last; i++) { + if (!m_data.value(static_cast<Type>(i)).isEmpty()) + return false; + } + return true; +} + +QString Documentation::value(Documentation::Type t) const +{ + return m_data.value(t); +} + +void Documentation::setValue(const QString &value, Documentation::Type t, Documentation::Format fmt) +{ + const QString v = value.trimmed(); + if (v.isEmpty()) + m_data.remove(t); + else + m_data[t] = value.trimmed(); + m_format = fmt; +} + +Documentation::Format Documentation::format() const +{ + return m_format; +} + +void Documentation::setFormat(Documentation::Format f) +{ + m_format = f; +} + +/******************************************************************************* * AbstractMetaVariable */ @@ -147,7 +186,8 @@ void AbstractMetaAttributes::assignMetaAttributes(const AbstractMetaAttributes & * AbstractMetaType */ -AbstractMetaType::AbstractMetaType() : +AbstractMetaType::AbstractMetaType(const TypeEntry *t) : + m_typeEntry(t), m_constant(false), m_volatile(false), m_cppInstantiation(true), @@ -166,19 +206,9 @@ QString AbstractMetaType::package() const return m_typeEntry->targetLangPackage(); } -static QString lastNameSegment(QString name) -{ - const int index = name.lastIndexOf(QStringLiteral("::")); - if (index >= 0) - name.remove(0, index + 2); - return name; -} - QString AbstractMetaType::name() const { - if (m_name.isEmpty()) - m_name = lastNameSegment(m_typeEntry->targetLangName()); - return m_name; + return m_typeEntry->targetLangEntryName(); } QString AbstractMetaType::fullName() const @@ -188,7 +218,7 @@ QString AbstractMetaType::fullName() const AbstractMetaType *AbstractMetaType::copy() const { - auto *cpy = new AbstractMetaType; + auto *cpy = new AbstractMetaType(typeEntry()); cpy->setTypeUsagePattern(typeUsagePattern()); cpy->setConstant(isConstant()); @@ -202,8 +232,6 @@ AbstractMetaType *AbstractMetaType::copy() const cpy->setArrayElementType(arrayElementType() ? arrayElementType()->copy() : nullptr); - cpy->setTypeEntry(typeEntry()); - return cpy; } @@ -256,11 +284,16 @@ AbstractMetaTypeCList AbstractMetaType::nestedArrayTypes() const return result; } -bool AbstractMetaType::isConstRef() const +bool AbstractMetaType::passByConstRef() const { return isConstant() && m_referenceType == LValueReference && indirections() == 0; } +bool AbstractMetaType::passByValue() const +{ + return m_referenceType == NoReference && indirections() == 0; +} + QString AbstractMetaType::cppSignature() const { if (m_cachedCppSignature.isEmpty()) @@ -273,25 +306,31 @@ QString AbstractMetaType::pythonSignature() const // PYSIDE-921: Handle container returntypes correctly. // This is now a clean reimplementation. if (m_cachedPythonSignature.isEmpty()) - m_cachedPythonSignature = formatPythonSignature(false); + m_cachedPythonSignature = formatPythonSignature(); return m_cachedPythonSignature; } AbstractMetaType::TypeUsagePattern AbstractMetaType::determineUsagePattern() const { - if (m_typeEntry->isTemplateArgument() || m_referenceType == RValueReference) - return InvalidPattern; + if (m_typeEntry->isTemplateArgument()) + return TemplateArgument; + + if (m_typeEntry->type() == TypeEntry::ConstantValueType) + return NonTypeTemplateArgument; - if (m_typeEntry->isPrimitive() && (actualIndirections() == 0 || isConstRef())) + if (m_typeEntry->isPrimitive() && (actualIndirections() == 0 || passByConstRef())) return PrimitivePattern; - if (m_typeEntry->isVoid()) - return NativePointerPattern; + if (m_typeEntry->isVoid()) { + return m_arrayElementCount < 0 && m_referenceType == NoReference + && m_indirections.isEmpty() && m_constant == 0 && m_volatile == 0 + ? VoidPattern : NativePointerPattern; + } if (m_typeEntry->isVarargs()) return VarargsPattern; - if (m_typeEntry->isEnum() && (actualIndirections() == 0 || isConstRef())) + if (m_typeEntry->isEnum() && (actualIndirections() == 0 || passByConstRef())) return EnumPattern; if (m_typeEntry->isObject()) { @@ -306,7 +345,7 @@ AbstractMetaType::TypeUsagePattern AbstractMetaType::determineUsagePattern() con if (m_typeEntry->isSmartPointer() && indirections() == 0) return SmartPointerPattern; - if (m_typeEntry->isFlags() && (actualIndirections() == 0 || isConstRef())) + if (m_typeEntry->isFlags() && (actualIndirections() == 0 || passByConstRef())) return FlagsPattern; if (m_typeEntry->isArray()) @@ -315,10 +354,6 @@ AbstractMetaType::TypeUsagePattern AbstractMetaType::determineUsagePattern() con if (m_typeEntry->isValue()) return indirections() == 1 ? ValuePointerPattern : ValuePattern; - if (ReportHandler::isDebug(ReportHandler::FullDebug)) { - qCDebug(lcShiboken) - << QStringLiteral("native pointer pattern for '%1'").arg(cppSignature()); - } return NativePointerPattern; } @@ -352,26 +387,43 @@ bool AbstractMetaType::hasTemplateChildren() const return false; } -bool AbstractMetaType::equals(const AbstractMetaType &rhs) const +bool AbstractMetaType::compare(const AbstractMetaType &rhs, ComparisonFlags flags) const { - if (m_typeEntry != rhs.m_typeEntry || m_constant != rhs.m_constant - || m_referenceType != rhs.m_referenceType + if (m_typeEntry != rhs.m_typeEntry || m_indirections != rhs.m_indirections || m_instantiations.size() != rhs.m_instantiations.size() || m_arrayElementCount != rhs.m_arrayElementCount) { return false; } + + if (m_constant != rhs.m_constant || m_referenceType != rhs.m_referenceType) { + if (!flags.testFlag(ConstRefMatchesValue) + || !(passByValue() || passByConstRef()) + || !(rhs.passByValue() || rhs.passByConstRef())) { + return false; + } + } + if ((m_arrayElementType != nullptr) != (rhs.m_arrayElementType != nullptr) - || (m_arrayElementType != nullptr && !m_arrayElementType->equals(*rhs.m_arrayElementType))) { + || (m_arrayElementType != nullptr && !m_arrayElementType->compare(*rhs.m_arrayElementType, flags))) { return false; } for (int i = 0, size = m_instantiations.size(); i < size; ++i) { - if (!m_instantiations.at(i)->equals(*rhs.m_instantiations.at(i))) + if (!m_instantiations.at(i)->compare(*rhs.m_instantiations.at(i), flags)) return false; } return true; } +AbstractMetaType *AbstractMetaType::createVoid() +{ + static const TypeEntry *voidTypeEntry = TypeDatabase::instance()->findType(QLatin1String("void")); + Q_ASSERT(voidTypeEntry); + auto *metaType = new AbstractMetaType(voidTypeEntry); + metaType->decideUsagePattern(); + return metaType; +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const AbstractMetaType *at) { @@ -528,7 +580,7 @@ bool AbstractMetaFunction::operator<(const AbstractMetaFunction &other) const */ AbstractMetaFunction::CompareResult AbstractMetaFunction::compareTo(const AbstractMetaFunction *other) const { - CompareResult result = nullptr; + CompareResult result; // Enclosing class... if (ownerClass() == other->ownerClass()) @@ -604,8 +656,7 @@ AbstractMetaFunction *AbstractMetaFunction::copy() const cpy->setImplementingClass(implementingClass()); cpy->setFunctionType(functionType()); cpy->setDeclaringClass(declaringClass()); - if (type()) - cpy->setType(type()->copy()); + cpy->setType(type()->copy()); cpy->setConstant(isConstant()); cpy->setExceptionSpecification(m_exceptionSpecification); cpy->setAllowThreadModification(m_allowThreadModification); @@ -615,8 +666,7 @@ AbstractMetaFunction *AbstractMetaFunction::copy() const for (AbstractMetaArgument *arg : m_arguments) cpy->addArgument(arg->copy()); - Q_ASSERT((!type() && !cpy->type()) - || (type()->instantiations() == cpy->type()->instantiations())); + Q_ASSERT(type()->instantiations() == cpy->type()->instantiations()); return cpy; } @@ -625,7 +675,7 @@ bool AbstractMetaFunction::usesRValueReferences() const { if (m_functionType == MoveConstructorFunction || m_functionType == MoveAssignmentOperatorFunction) return true; - if (m_type && m_type->referenceType() == RValueReference) + if (m_type->referenceType() == RValueReference) return true; for (const AbstractMetaArgument *a : m_arguments) { if (a->type()->referenceType() == RValueReference) @@ -765,6 +815,12 @@ bool AbstractMetaFunction::argumentRemoved(int key) const return false; } +const AbstractMetaClass *AbstractMetaFunction::targetLangOwner() const +{ + return m_class && m_class->isInvisibleNamespace() + ? m_class->targetLangEnclosingClass() : m_class; +} + bool AbstractMetaFunction::isDeprecated() const { const FunctionModificationList &modifications = this->modifications(declaringClass()); @@ -784,11 +840,20 @@ bool AbstractMetaFunction::isDeprecated() const bool AbstractMetaFunction::autoDetectAllowThread() const { // Disallow for simple getter functions. - const bool maybeGetter = m_constant != 0 && m_type != nullptr - && m_arguments.isEmpty(); + const bool maybeGetter = m_constant != 0 && !isVoid() && m_arguments.isEmpty(); return !maybeGetter; } +SourceLocation AbstractMetaFunction::sourceLocation() const +{ + return m_sourceLocation; +} + +void AbstractMetaFunction::setSourceLocation(const SourceLocation &sourceLocation) +{ + m_sourceLocation = sourceLocation; +} + static inline TypeSystem::AllowThread allowThreadMod(const AbstractMetaClass *klass) { return klass->typeEntry()->allowThread(); @@ -816,12 +881,14 @@ bool AbstractMetaFunction::allowThread() const case TypeSystem::AllowThread::Allow: break; case TypeSystem::AllowThread::Auto: - case TypeSystem::AllowThread::Unspecified: result = autoDetectAllowThread(); break; + case TypeSystem::AllowThread::Unspecified: + result = false; + break; } - if (!result) - qCDebug(lcShiboken).noquote() << msgDisallowThread(this); + if (!result && ReportHandler::isDebug(ReportHandler::MediumDebug)) + qCInfo(lcShiboken).noquote() << msgDisallowThread(this); return result; } @@ -945,9 +1012,6 @@ FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaC (implementor == implementingClass() && !mods.isEmpty())) { break; } - const AbstractMetaClassList &interfaces = implementor->interfaces(); - for (const AbstractMetaClass *interface : interfaces) - mods += this->modifications(interface); implementor = implementor->baseClass(); } return mods; @@ -1237,6 +1301,21 @@ AbstractMetaFunction::find(const AbstractMetaFunctionList &haystack, return findByName(haystack, needle); } +int AbstractMetaFunction::overloadNumber() const +{ + if (m_cachedOverloadNumber == TypeSystem::OverloadNumberUnset) { + m_cachedOverloadNumber = TypeSystem::OverloadNumberDefault; + const FunctionModificationList &mods = modifications(implementingClass()); + for (const FunctionModification &mod : mods) { + if (mod.overloadNumber() != TypeSystem::OverloadNumberUnset) { + m_cachedOverloadNumber = mod.overloadNumber(); + break; + } + } + } + return m_cachedOverloadNumber; +} + #ifndef QT_NO_DEBUG_STREAM static inline void formatMetaFunctionBrief(QDebug &d, const AbstractMetaFunction *af) { @@ -1339,8 +1418,8 @@ AbstractMetaClass::~AbstractMetaClass() qDeleteAll(m_functions); qDeleteAll(m_fields); qDeleteAll(m_enums); - if (hasTemplateBaseClassInstantiations()) - qDeleteAll(templateBaseClassInstantiations()); + qDeleteAll(m_propertySpecs); + qDeleteAll(m_baseTemplateInstantiations); } /******************************************************************************* @@ -1362,44 +1441,6 @@ bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const } /******************************************************************************* - * Constructs an interface based on the functions and enums in this - * class and returns it... - */ -AbstractMetaClass *AbstractMetaClass::extractInterface() -{ - Q_ASSERT(typeEntry()->designatedInterface()); - - if (!m_extractedInterface) { - auto *iface = new AbstractMetaClass; - iface->setAttributes(attributes()); - iface->setBaseClass(nullptr); - - iface->setTypeEntry(typeEntry()->designatedInterface()); - - for (AbstractMetaFunction *function : qAsConst(m_functions)) { - if (!function->isConstructor()) - iface->addFunction(function->copy()); - } - -// iface->setEnums(enums()); -// setEnums(AbstractMetaEnumList()); - - for (const AbstractMetaField *field : qAsConst(m_fields)) { - if (field->isPublic()) { - AbstractMetaField *new_field = field->copy(); - new_field->setEnclosingClass(iface); - iface->addField(new_field); - } - } - - m_extractedInterface = iface; - addInterface(iface); - } - - return m_extractedInterface; -} - -/******************************************************************************* * Returns a list of all the functions with a given name */ AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString &name) const @@ -1421,10 +1462,6 @@ AbstractMetaFunctionList AbstractMetaClass::functionsInTargetLang() const { FunctionQueryOptions default_flags = NormalFunctions | Visible | NotRemovedFromTargetLang; - // Interfaces don't implement functions - if (isInterface()) - default_flags |= ClassImplements; - // Only public functions in final classes // default_flags |= isFinal() ? WasPublic : 0; FunctionQueryOptions public_flags; @@ -1547,16 +1584,6 @@ void AbstractMetaClass::setFunctions(const AbstractMetaFunctionList &functions) } } -bool AbstractMetaClass::hasFieldAccessors() const -{ - for (const AbstractMetaField *field : m_fields) { - if (field->getter() || field->setter()) - return true; - } - - return false; -} - bool AbstractMetaClass::hasDefaultToStringFunction() const { const AbstractMetaFunctionList &funcs = queryFunctionsByName(QLatin1String("toString")); @@ -1577,7 +1604,7 @@ void AbstractMetaClass::addFunction(AbstractMetaFunction *function) else Q_ASSERT(false); //memory leak - m_hasVirtuals |= function->isVirtual() || hasVirtualDestructor(); + m_hasVirtuals |= function->isVirtual(); m_isPolymorphic |= m_hasVirtuals; m_hasNonpublic |= !function->isPublic(); } @@ -1598,14 +1625,22 @@ bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const QString AbstractMetaClass::name() const { - return lastNameSegment(m_typeEntry->targetLangName()); + return m_typeEntry->targetLangEntryName(); +} + +void AbstractMetaClass::addBaseClass(AbstractMetaClass *baseClass) +{ + Q_ASSERT(baseClass); + m_baseClasses.append(baseClass); + m_isPolymorphic |= baseClass->isPolymorphic(); } void AbstractMetaClass::setBaseClass(AbstractMetaClass *baseClass) { - m_baseClass = baseClass; - if (baseClass) + if (baseClass) { + m_baseClasses.prepend(baseClass); m_isPolymorphic |= baseClass->isPolymorphic(); + } } QString AbstractMetaClass::package() const @@ -1613,14 +1648,17 @@ QString AbstractMetaClass::package() const return m_typeEntry->targetLangPackage(); } -bool AbstractMetaClass::isInterface() const +bool AbstractMetaClass::isNamespace() const { - return m_typeEntry->isInterface(); + return m_typeEntry->isNamespace(); } -bool AbstractMetaClass::isNamespace() const +// Is an invisible namespaces whose functions/enums +// should be mapped to the global space. +bool AbstractMetaClass::isInvisibleNamespace() const { - return m_typeEntry->isNamespace(); + return m_typeEntry->isNamespace() && m_typeEntry->generateCode() + && !NamespaceTypeEntry::isVisibleScope(m_typeEntry); } static bool qObjectPredicate(const AbstractMetaClass *c) @@ -1671,6 +1709,15 @@ bool AbstractMetaClass::hasProtectedMembers() const return hasProtectedFields() || hasProtectedFunctions(); } +QPropertySpec *AbstractMetaClass::propertySpecByName(const QString &name) const +{ + for (auto propertySpec : m_propertySpecs) { + if (name == propertySpec->name()) + return propertySpec; + } + return nullptr; +} + QPropertySpec *AbstractMetaClass::propertySpecForRead(const QString &name) const { for (const auto &propertySpec : m_propertySpecs) { @@ -1698,35 +1745,27 @@ QPropertySpec *AbstractMetaClass::propertySpecForReset(const QString &name) cons return nullptr; } -using AbstractMetaClassBaseTemplateInstantiationsMap = QHash<const AbstractMetaClass *, AbstractMetaTypeList>; -Q_GLOBAL_STATIC(AbstractMetaClassBaseTemplateInstantiationsMap, metaClassBaseTemplateInstantiations); - bool AbstractMetaClass::hasTemplateBaseClassInstantiations() const { - if (!templateBaseClass()) - return false; - return metaClassBaseTemplateInstantiations()->contains(this); + return m_templateBaseClass != nullptr && !m_baseTemplateInstantiations.isEmpty(); } -AbstractMetaTypeList AbstractMetaClass::templateBaseClassInstantiations() const +const AbstractMetaTypeList &AbstractMetaClass::templateBaseClassInstantiations() const { - if (!templateBaseClass()) - return AbstractMetaTypeList(); - return metaClassBaseTemplateInstantiations()->value(this); + return m_baseTemplateInstantiations; } -void AbstractMetaClass::setTemplateBaseClassInstantiations(AbstractMetaTypeList &instantiations) +void AbstractMetaClass::setTemplateBaseClassInstantiations(const AbstractMetaTypeList &instantiations) { - if (!templateBaseClass()) - return; - metaClassBaseTemplateInstantiations()->insert(this, instantiations); + Q_ASSERT(m_templateBaseClass != nullptr); + m_baseTemplateInstantiations = instantiations; } // Does any of the base classes require deletion in the main thread? bool AbstractMetaClass::deleteInMainThread() const { return typeEntry()->deleteInMainThread() - || (m_baseClass && m_baseClass->deleteInMainThread()); + || (!m_baseClasses.isEmpty() && m_baseClasses.constFirst()->deleteInMainThread()); } static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func) @@ -1740,12 +1779,6 @@ static bool functions_contains(const AbstractMetaFunctionList &l, const Abstract AbstractMetaField::AbstractMetaField() = default; -AbstractMetaField::~AbstractMetaField() -{ - delete m_setter; - delete m_getter; -} - AbstractMetaField *AbstractMetaField::copy() const { auto *returned = new AbstractMetaField; @@ -1777,55 +1810,6 @@ bool AbstractMetaField::isModifiedRemoved(int types) const return false; } -static QString upCaseFirst(const QString &str) -{ - Q_ASSERT(!str.isEmpty()); - QString s = str; - s[0] = s.at(0).toUpper(); - return s; -} - -static AbstractMetaFunction *createXetter(const AbstractMetaField *g, const QString &name, - AbstractMetaAttributes::Attributes type) -{ - auto *f = new AbstractMetaFunction; - - f->setName(name); - f->setOriginalName(name); - f->setOwnerClass(g->enclosingClass()); - f->setImplementingClass(g->enclosingClass()); - f->setDeclaringClass(g->enclosingClass()); - - AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::FinalInTargetLang | type; - if (g->isStatic()) - attr |= AbstractMetaAttributes::Static; - if (g->isPublic()) - attr |= AbstractMetaAttributes::Public; - else if (g->isProtected()) - attr |= AbstractMetaAttributes::Protected; - else - attr |= AbstractMetaAttributes::Private; - f->setAttributes(attr); - f->setOriginalAttributes(attr); - - const FieldModificationList &mods = g->modifications(); - for (const FieldModification &mod : mods) { - if (mod.isRenameModifier()) - f->setName(mod.renamedTo()); - if (mod.isAccessModifier()) { - if (mod.isPrivate()) - f->setVisibility(AbstractMetaAttributes::Private); - else if (mod.isProtected()) - f->setVisibility(AbstractMetaAttributes::Protected); - else if (mod.isPublic()) - f->setVisibility(AbstractMetaAttributes::Public); - else if (mod.isFriendly()) - f->setVisibility(AbstractMetaAttributes::Friendly); - } - } - return f; -} - FieldModificationList AbstractMetaField::modifications() const { const FieldModificationList &mods = enclosingClass()->typeEntry()->fieldModifications(); @@ -1839,32 +1823,12 @@ FieldModificationList AbstractMetaField::modifications() const return returned; } -const AbstractMetaFunction *AbstractMetaField::setter() const +const AbstractMetaClass *EnclosingClassMixin::targetLangEnclosingClass() const { - if (!m_setter) { - m_setter = createXetter(this, - QLatin1String("set") + upCaseFirst(name()), - AbstractMetaAttributes::SetterFunction); - AbstractMetaArgumentList arguments; - auto *argument = new AbstractMetaArgument; - argument->setType(type()->copy()); - argument->setName(name()); - arguments.append(argument); - m_setter->setArguments(arguments); - } - return m_setter; -} - -const AbstractMetaFunction *AbstractMetaField::getter() const -{ - if (!m_getter) { - m_getter = createXetter(this, - name(), - AbstractMetaAttributes::GetterFunction); - m_getter->setType(type()); - } - - return m_getter; + auto result = m_enclosingClass; + while (result && !NamespaceTypeEntry::isVisibleScope(result->typeEntry())) + result = result->enclosingClass(); + return result; } #ifndef QT_NO_DEBUG_STREAM @@ -1967,6 +1931,7 @@ bool AbstractMetaClass::hasPrivateCopyConstructor() const void AbstractMetaClass::addDefaultConstructor() { auto *f = new AbstractMetaFunction; + f->setType(AbstractMetaType::createVoid()); f->setOriginalName(name()); f->setName(name()); f->setOwnerClass(this); @@ -1985,14 +1950,14 @@ void AbstractMetaClass::addDefaultConstructor() void AbstractMetaClass::addDefaultCopyConstructor(bool isPrivate) { auto f = new AbstractMetaFunction; + f->setType(AbstractMetaType::createVoid()); f->setOriginalName(name()); f->setName(name()); f->setOwnerClass(this); f->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); f->setDeclaringClass(this); - auto argType = new AbstractMetaType; - argType->setTypeEntry(typeEntry()); + auto argType = new AbstractMetaType(typeEntry()); argType->setReferenceType(LValueReference); argType->setConstant(true); argType->setTypeUsagePattern(AbstractMetaType::ValuePattern); @@ -2014,6 +1979,13 @@ void AbstractMetaClass::addDefaultCopyConstructor(bool isPrivate) addFunction(f); } +void AbstractMetaClass::setHasVirtualDestructor(bool value) +{ + m_hasVirtualDestructor = value; + if (value) + m_hasVirtuals = m_isPolymorphic = 1; +} + bool AbstractMetaClass::hasFunction(const AbstractMetaFunction *f) const { return functions_contains(m_functions, f); @@ -2096,6 +2068,16 @@ bool AbstractMetaClass::queryFunction(const AbstractMetaFunction *f, FunctionQue if ((query & GenerateExceptionHandling) && !f->generateExceptionHandling()) return false; + if (query.testFlag(GetAttroFunction) + && f->functionType() != AbstractMetaFunction::GetAttroFunction) { + return false; + } + + if (query.testFlag(SetAttroFunction) + && f->functionType() != AbstractMetaFunction::SetAttroFunction) { + return false; + } + return true; } @@ -2136,57 +2118,6 @@ AbstractMetaFunctionList AbstractMetaClass::cppSignalFunctions() const return queryFunctions(Signals | Visible | NotRemovedFromTargetLang); } -/** - * Adds the specified interface to this class by adding all the - * functions in the interface to this class. - */ -void AbstractMetaClass::addInterface(AbstractMetaClass *interface) -{ - Q_ASSERT(!m_interfaces.contains(interface)); - m_interfaces << interface; - - m_isPolymorphic |= interface->isPolymorphic(); - - if (m_extractedInterface && m_extractedInterface != interface) - m_extractedInterface->addInterface(interface); - - -#if 0 - const AbstractMetaFunctionList &funcs = interface->functions(); - for (AbstractMetaFunction *function : funcs) - if (!hasFunction(function) && !function->isConstructor()) { - AbstractMetaFunction *cpy = function->copy(); - cpy->setImplementingClass(this); - - // Setup that this function is an interface class. - cpy->setInterfaceClass(interface); - *cpy += AbstractMetaAttributes::InterfaceFunction; - - // Copy the modifications in interface into the implementing classes. - const FunctionModificationList &mods = function->modifications(interface); - for (const FunctionModification &mod : mods) - m_typeEntry->addFunctionModification(mod); - - // It should be mostly safe to assume that when we implement an interface - // we don't "pass on" pure virtual functions to our sublcasses... -// *cpy -= AbstractMetaAttributes::Abstract; - - addFunction(cpy); - } -#endif - -} - - -void AbstractMetaClass::setInterfaces(const AbstractMetaClassList &interfaces) -{ - m_interfaces = interfaces; - for (const AbstractMetaClass *interface : interfaces) { - if (interface) - m_isPolymorphic |= interface->isPolymorphic(); - } -} - AbstractMetaField *AbstractMetaClass::findField(const QString &name) const { return AbstractMetaField::find(m_fields, name); @@ -2196,10 +2127,6 @@ AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName) { if (AbstractMetaEnum *e = findByName(m_enums, enumName)) return e; - - if (typeEntry()->designatedInterface()) - return extractInterface()->findEnum(enumName); - return nullptr; } @@ -2212,16 +2139,37 @@ AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValue if (AbstractMetaEnumValue *v = e->findEnumValue(enumValueName)) return v; } - - if (typeEntry()->designatedInterface()) - return extractInterface()->findEnumValue(enumValueName); - if (baseClass()) return baseClass()->findEnumValue(enumValueName); return nullptr; } +void AbstractMetaClass::getEnumsToBeGenerated(AbstractMetaEnumList *enumList) const +{ + for (AbstractMetaEnum *metaEnum : m_enums) { + if (!metaEnum->isPrivate() && metaEnum->typeEntry()->generateCode()) + enumList->append(metaEnum); + } +} + +void AbstractMetaClass::getEnumsFromInvisibleNamespacesToBeGenerated(AbstractMetaEnumList *enumList) const +{ + if (isNamespace()) { + invisibleNamespaceRecursion([enumList](AbstractMetaClass *c) { + c->getEnumsToBeGenerated(enumList); + }); + } +} + +void AbstractMetaClass::getFunctionsFromInvisibleNamespacesToBeGenerated(AbstractMetaFunctionList *funcList) const +{ + if (isNamespace()) { + invisibleNamespaceRecursion([funcList](AbstractMetaClass *c) { + funcList->append(c->functions()); + }); + } +} static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractMetaType *type) { @@ -2238,8 +2186,7 @@ static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractM } if (type->hasInstantiations()) { - const AbstractMetaTypeList &instantiations = type->instantiations(); - for (const AbstractMetaType *instantiation : instantiations) + for (const AbstractMetaType *instantiation : type->instantiations()) addExtraIncludeForType(metaClass, instantiation); } } @@ -2262,32 +2209,23 @@ void AbstractMetaClass::fixFunctions() m_functionsFixed = true; - AbstractMetaClass *superClass = baseClass(); AbstractMetaFunctionList funcs = functions(); - if (superClass) + for (auto superClass : m_baseClasses) { superClass->fixFunctions(); - int iface_idx = 0; - while (superClass || iface_idx < interfaces().size()) { // 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. AbstractMetaFunctionList superFuncs; - if (superClass) { - // 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 -= AbstractMetaAttributes::FinalInTargetLang; - } - superFuncs = superClass->queryFunctions(AbstractMetaClass::ClassImplements); - AbstractMetaFunctionList virtuals = superClass->queryFunctions(AbstractMetaClass::VirtualInCppFunctions); - superFuncs += virtuals; - } else { - superFuncs = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::NormalFunctions); - AbstractMetaFunctionList virtuals = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::VirtualInCppFunctions); - superFuncs += virtuals; + // 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 -= AbstractMetaAttributes::FinalInTargetLang; } + superFuncs = superClass->queryFunctions(AbstractMetaClass::ClassImplements); + AbstractMetaFunctionList virtuals = superClass->queryFunctions(AbstractMetaClass::VirtualInCppFunctions); + superFuncs += virtuals; QSet<AbstractMetaFunction *> funcsToAdd; for (auto sf : qAsConst(superFuncs)) { @@ -2416,11 +2354,6 @@ void AbstractMetaClass::fixFunctions() (*copy) += AddedMethod; funcs.append(copy); } - - if (superClass) - superClass = superClass->baseClass(); - else - iface_idx++; } bool hasPrivateConstructors = false; @@ -2519,7 +2452,7 @@ QString AbstractMetaType::formatSignature(bool minimal) const return result; } -QString AbstractMetaType::formatPythonSignature(bool minimal) const +QString AbstractMetaType::formatPythonSignature() const { /* * This is a version of the above, more suitable for Python. @@ -2530,6 +2463,7 @@ QString AbstractMetaType::formatPythonSignature(bool minimal) const * When we have a primitive with an indirection, we use that '*' * character for later postprocessing, since those indirections * need to be modified into a result tuple. + * Smart pointer instantiations: Drop the package */ QString result; if (m_pattern == AbstractMetaType::NativePointerAsArrayPattern) @@ -2538,25 +2472,25 @@ QString AbstractMetaType::formatPythonSignature(bool minimal) const // NativePointerAsArrayPattern indicates when we have <array> in XML. // if (m_typeEntry->isPrimitive() && isConstant()) // result += QLatin1String("const "); - if (!m_typeEntry->isPrimitive() && !package().isEmpty()) + if (!m_typeEntry->isPrimitive() && !m_typeEntry->isSmartPointer() && !package().isEmpty()) result += package() + QLatin1Char('.'); if (isArray()) { // Build nested array dimensions a[2][3] in correct order - result += m_arrayElementType->formatPythonSignature(true); + result += m_arrayElementType->formatPythonSignature(); const int arrayPos = result.indexOf(QLatin1Char('[')); if (arrayPos != -1) result.insert(arrayPos, formatArraySize(m_arrayElementCount)); else result.append(formatArraySize(m_arrayElementCount)); } else { - result += typeEntry()->qualifiedCppName(); + result += typeEntry()->targetLangName(); } if (!m_instantiations.isEmpty()) { result += QLatin1Char('['); for (int i = 0, size = m_instantiations.size(); i < size; ++i) { if (i > 0) result += QLatin1String(", "); - result += m_instantiations.at(i)->formatPythonSignature(true); + result += m_instantiations.at(i)->formatPythonSignature(); } result += QLatin1Char(']'); } @@ -2586,28 +2520,18 @@ AbstractMetaEnum *AbstractMetaClass::findEnum(const AbstractMetaClassList &class { Q_ASSERT(entry->isEnum()); - QString qualifiedName = entry->qualifiedCppName(); - int pos = qualifiedName.lastIndexOf(QLatin1String("::")); - - QString enumName; - QString className; - - if (pos > 0) { - enumName = qualifiedName.mid(pos + 2); - className = qualifiedName.mid(0, pos); - } else { - enumName = qualifiedName; - className = TypeDatabase::globalNamespaceClassName(entry); - } - - AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes, className); + auto scopeEntry = entry->parent(); + AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes, scopeEntry); if (!metaClass) { qCWarning(lcShiboken).noquote().nospace() << QStringLiteral("AbstractMeta::findEnum(), unknown class '%1' in '%2'") - .arg(className, entry->qualifiedCppName()); + .arg(scopeEntry->qualifiedCppName(), entry->qualifiedCppName()); return nullptr; } + QString qualifiedName = entry->qualifiedCppName(); + const int pos = qualifiedName.lastIndexOf(QLatin1String("::")); + const QString enumName = pos > 0 ? qualifiedName.mid(pos + 2) : qualifiedName; return metaClass->findEnum(enumName); } @@ -2673,6 +2597,82 @@ AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &cla } #ifndef QT_NO_DEBUG_STREAM + +void AbstractMetaClass::format(QDebug &d) const +{ + if (d.verbosity() > 2) + d << static_cast<const void *>(this) << ", "; + d << '"' << qualifiedCppName(); + if (const int count = m_templateArgs.size()) { + for (int i = 0; i < count; ++i) + d << (i ? ',' : '<') << m_templateArgs.at(i)->qualifiedCppName(); + d << '>'; + } + d << '"'; + if (isNamespace()) + d << " [namespace]"; + if (attributes() & AbstractMetaAttributes::FinalCppClass) + d << " [final]"; + if (attributes().testFlag(AbstractMetaAttributes::Deprecated)) + d << " [deprecated]"; + if (!m_baseClasses.isEmpty()) { + d << ", inherits "; + for (auto b : m_baseClasses) + d << " \"" << b->name() << '"'; + } + if (auto templateBase = templateBaseClass()) { + const auto &instantiatedTypes = templateBaseClassInstantiations(); + d << ", instantiates \"" << templateBase->name(); + for (int i = 0, count = instantiatedTypes.size(); i < count; ++i) + d << (i ? ',' : '<') << instantiatedTypes.at(i)->name(); + d << ">\""; + } + if (const int count = m_propertySpecs.size()) { + d << ", properties (" << count << "): ["; + for (int i = 0; i < count; ++i) { + if (i) + d << ", "; + m_propertySpecs.at(i)->formatDebug(d); + } + d << ']'; + } +} + +void AbstractMetaClass::formatMembers(QDebug &d) const +{ + if (!m_enums.isEmpty()) + d << ", enums[" << m_enums.size() << "]=" << m_enums; + if (!m_functions.isEmpty()) { + const int count = m_functions.size(); + d << ", functions=[" << count << "]("; + for (int i = 0; i < count; ++i) { + if (i) + d << ", "; + formatMetaFunctionBrief(d, m_functions.at(i)); + } + d << ')'; + } + if (const int count = m_fields.size()) { + d << ", fields=[" << count << "]("; + for (int i = 0; i < count; ++i) { + if (i) + d << ", "; + formatMetaField(d, m_fields.at(i)); + } + d << ')'; + } +} + +SourceLocation AbstractMetaClass::sourceLocation() const +{ + return m_sourceLocation; +} + +void AbstractMetaClass::setSourceLocation(const SourceLocation &sourceLocation) +{ + m_sourceLocation = sourceLocation; +} + QDebug operator<<(QDebug d, const AbstractMetaClass *ac) { QDebugStateSaver saver(d); @@ -2680,57 +2680,9 @@ QDebug operator<<(QDebug d, const AbstractMetaClass *ac) d.nospace(); d << "AbstractMetaClass("; if (ac) { - d << '"' << ac->fullName() << '"'; - if (ac->attributes() & AbstractMetaAttributes::FinalCppClass) - d << " [final]"; - if (ac->attributes().testFlag(AbstractMetaAttributes::Deprecated)) - d << " [deprecated]"; - if (ac->m_baseClass) - d << ", inherits \"" << ac->m_baseClass->name() << '"'; - if (ac->m_templateBaseClass) - d << ", inherits template \"" << ac->m_templateBaseClass->name() << '"'; - const AbstractMetaEnumList &enums = ac->enums(); - if (!enums.isEmpty()) - d << ", enums[" << enums.size() << "]=" << enums; - const AbstractMetaFunctionList &functions = ac->functions(); - if (!functions.isEmpty()) { - const int count = functions.size(); - d << ", functions=[" << count << "]("; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; -#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) - if (d.verbosity() > 2) - d << functions.at(i); - else -#endif - formatMetaFunctionBrief(d, functions.at(i)); - } - d << ')'; - } - const AbstractMetaFieldList &fields = ac->fields(); - if (!fields.isEmpty()) { - const int count = fields.size(); - d << ", fields=[" << count << "]("; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; - formatMetaField(d, fields.at(i)); - } - d << ')'; - } - const auto &templateArguments = ac->templateArguments(); - if (const int count = templateArguments.size()) { - d << ", templateArguments=[" << count << "]("; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; - d << templateArguments.at(i); - } - d << ')'; - } - - + ac->format(d); + if (d.verbosity() > 2) + ac->formatMembers(d); } else { d << '0'; } @@ -2778,7 +2730,7 @@ AbstractMetaEnumValue *AbstractMetaEnum::findEnumValue(const QString &value) con QString AbstractMetaEnum::name() const { - return m_typeEntry->targetLangName(); + return m_typeEntry->targetLangEntryName(); } QString AbstractMetaEnum::qualifier() const @@ -2790,3 +2742,4 @@ QString AbstractMetaEnum::package() const { return m_typeEntry->targetLangPackage(); } + |