diff options
Diffstat (limited to 'sources/shiboken2/ApiExtractor')
23 files changed, 681 insertions, 638 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 4566ed3bc..f0e5da8da 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -270,7 +270,7 @@ void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelI const ArgumentModelItem &arg = arguments.at(1); if (AbstractMetaClass *cls = argumentToClass(arg, currentClass)) { if (arg->type().indirections() < 2) - cls->setToStringCapability(true, arg->type().indirections()); + cls->setToStringCapability(true, int(arg->type().indirections())); } } } @@ -410,6 +410,7 @@ FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments, unsigned clangFlags) { clang::Builder builder; + builder.setSystemIncludes(TypeDatabase::instance()->systemIncludes()); if (level == LanguageLevel::Default) level = clang::emulatedCompilerLanguageLevel(); arguments.prepend(QByteArrayLiteral("-std=") @@ -512,7 +513,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) ReportHandler::startProgress("Fixing class inheritance..."); for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) { - if (!cls->isInterface() && !cls->isNamespace()) { + if (!cls->isNamespace()) { setupInheritance(cls); if (!cls->hasVirtualDestructor() && cls->baseClass() && cls->baseClass()->hasVirtualDestructor()) @@ -530,7 +531,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) .arg(cls->name()); } else { const bool couldAddDefaultCtors = cls->isConstructible() - && !cls->isInterface() && !cls->isNamespace() + && !cls->isNamespace() && (cls->attributes() & AbstractMetaAttributes::HasRejectedConstructor) == 0; if (couldAddDefaultCtors) { if (!cls->hasConstructors()) @@ -549,11 +550,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) if (!entry->isPrimitive()) { if ((entry->isValue() || entry->isObject()) && !types->shouldDropTypeEntry(entry->qualifiedCppName()) - && !entry->isString() - && !entry->isChar() && !entry->isContainer() && !entry->isCustom() - && !entry->isVariant() && (entry->generateCode() & TypeEntry::GenerateTargetLang) && !AbstractMetaClass::findClass(m_metaClasses, entry)) { qCWarning(lcShiboken).noquote().nospace() @@ -729,12 +727,6 @@ void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls, m_smartPointers << cls; } else { m_metaClasses << cls; - if (cls->typeEntry()->designatedInterface()) { - AbstractMetaClass *interface = cls->extractInterface(); - m_metaClasses << interface; - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) - qCDebug(lcShiboken) << QStringLiteral(" -> interface '%1'").arg(interface->name()); - } } } @@ -758,6 +750,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel return nullptr; } + if (namespaceItem->type() == NamespaceType::Inline) { + type->setInlineNamespace(true); + TypeDatabase::instance()->addInlineNamespaceLookups(type); + } + // Continue populating namespace? AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, type); if (!metaClass) { @@ -1215,7 +1212,7 @@ AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(const VariableModel metaField->setType(metaType); - AbstractMetaAttributes::Attributes attr = nullptr; + AbstractMetaAttributes::Attributes attr; if (field->isStatic()) attr |= AbstractMetaAttributes::Static; @@ -1284,46 +1281,11 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF metaFunction->replaceType(metaType); } -static bool _compareAbstractMetaTypes(const AbstractMetaType *type, - const AbstractMetaType *other, - AbstractMetaType::ComparisonFlags flags = {}) -{ - return (type != nullptr) == (other != nullptr) - && (type == nullptr || type->compare(*other, flags)); -} - -static bool _compareAbstractMetaFunctions(const AbstractMetaFunction *func, - const AbstractMetaFunction *other, - AbstractMetaType::ComparisonFlags argumentFlags = {}) -{ - if (!func && !other) - return true; - if (!func || !other) - return false; - if (func->name() != other->name()) - return false; - const int argumentsCount = func->arguments().count(); - if (argumentsCount != other->arguments().count() - || func->isConstant() != other->isConstant() - || func->isStatic() != other->isStatic() - || !_compareAbstractMetaTypes(func->type(), other->type())) { - return false; - } - for (int i = 0; i < argumentsCount; ++i) { - if (!_compareAbstractMetaTypes(func->arguments().at(i)->type(), - other->arguments().at(i)->type(), - argumentFlags)) { - return false; - } - } - return true; -} - AbstractMetaFunctionList AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem, AbstractMetaClass::Attributes *constructorAttributes, AbstractMetaClass *currentClass) { - *constructorAttributes = nullptr; + *constructorAttributes = {}; AbstractMetaFunctionList result; const FunctionList &scopeFunctionList = scopeItem->functions(); result.reserve(scopeFunctionList.size()); @@ -1464,8 +1426,6 @@ void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) { - Q_ASSERT(!metaClass->isInterface()); - if (m_setupInheritanceDone.contains(metaClass)) return true; @@ -1505,61 +1465,23 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) TypeDatabase* types = TypeDatabase::instance(); - int primary = -1; - int primaries = 0; - for (int i = 0; i < baseClasses.size(); ++i) { - - if (types->isClassRejected(baseClasses.at(i))) - continue; - - TypeEntry* baseClassEntry = types->findType(baseClasses.at(i)); - if (!baseClassEntry) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("class '%1' inherits from unknown base class '%2'") - .arg(metaClass->name(), baseClasses.at(i)); - } else if (!baseClassEntry->designatedInterface()) { // true for primary base class - primaries++; - primary = i; - } - } - - if (primary >= 0) { - AbstractMetaClass *baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClasses.at(primary)); - if (!baseClass) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("unknown baseclass for '%1': '%2'") - .arg(metaClass->name(), baseClasses.at(primary)); - return false; - } - metaClass->setBaseClass(baseClass); - } - - for (int i = 0; i < baseClasses.size(); ++i) { - if (types->isClassRejected(baseClasses.at(i))) - continue; - - if (i != primary) { - AbstractMetaClass *baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClasses.at(i)); - if (!baseClass) { + for (const auto &baseClassName : baseClasses) { + if (!types->isClassRejected(baseClassName)) { + if (!types->findType(baseClassName)) { qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("class not found for setup inheritance '%1'").arg(baseClasses.at(i)); + << QStringLiteral("class '%1' inherits from unknown base class '%2'") + .arg(metaClass->name(), baseClassName); return false; } - - setupInheritance(baseClass); - - QString interfaceName = baseClass->isInterface() ? InterfaceTypeEntry::interfaceName(baseClass->name()) : baseClass->name(); - AbstractMetaClass *iface = AbstractMetaClass::findClass(m_metaClasses, interfaceName); - if (!iface) { + auto baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClassName); + if (!baseClass) { qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("unknown interface for '%1': '%2'").arg(metaClass->name(), interfaceName); + << QStringLiteral("class not found for setup inheritance '%1'").arg(baseClassName); return false; } - metaClass->addInterface(iface); + metaClass->addBaseClass(baseClass); - const AbstractMetaClassList &interfaces = iface->interfaces(); - for (AbstractMetaClass* iface : interfaces) - metaClass->addInterface(iface); + setupInheritance(baseClass); } } @@ -2092,6 +2014,7 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const AddedFunction: qFatal("%s", qPrintable(msg)); } + // These are only implicit and should not appear in code... auto *metaType = new AbstractMetaType; metaType->setTypeEntry(type); metaType->setIndirections(typeInfo.indirections); @@ -2120,6 +2043,52 @@ static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaC return type; } +// Helper for translateTypeStatic() +TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualifiedName, + const QString &name, + AbstractMetaClass *currentClass, + AbstractMetaBuilderPrivate *d) +{ + // 5.1 - Try first using the current scope + if (currentClass) { + if (auto type = findTypeEntryUsingContext(currentClass, qualifiedName)) + return {type}; + + // 5.1.1 - Try using the class parents' scopes + if (d && !currentClass->baseClassNames().isEmpty()) { + const AbstractMetaClassList &baseClasses = d->getBaseClasses(currentClass); + for (const AbstractMetaClass *cls : baseClasses) { + if (auto type = findTypeEntryUsingContext(cls, qualifiedName)) + return {type}; + } + } + } + + // 5.2 - Try without scope + auto types = TypeDatabase::instance()->findCppTypes(qualifiedName); + if (!types.isEmpty()) + return types; + + // 6. No? Try looking it up as a flags type + if (auto type = TypeDatabase::instance()->findFlagsType(qualifiedName)) + return {type}; + + // 7. No? Try looking it up as a container type + if (auto type = TypeDatabase::instance()->findContainerType(name)) + return {type}; + + // 8. No? Check if the current class is a template and this type is one + // of the parameters. + if (currentClass) { + const QVector<TypeEntry *> &template_args = currentClass->templateArguments(); + for (TypeEntry *te : template_args) { + if (te->name() == qualifiedName) + return {te}; + } + } + return {}; +} + AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei, AbstractMetaClass *currentClass, TranslateTypeFlags flags, @@ -2252,47 +2221,8 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo typeInfo.clearInstantiations(); } - const TypeEntry *type = nullptr; - // 5. Try to find the type - - // 5.1 - Try first using the current scope - if (currentClass) { - type = findTypeEntryUsingContext(currentClass, qualifiedName); - - // 5.1.1 - Try using the class parents' scopes - if (!type && d && !currentClass->baseClassNames().isEmpty()) { - const AbstractMetaClassList &baseClasses = d->getBaseClasses(currentClass); - for (const AbstractMetaClass *cls : baseClasses) { - type = findTypeEntryUsingContext(cls, qualifiedName); - if (type) - break; - } - } - } - - // 5.2 - Try without scope - if (!type) - type = TypeDatabase::instance()->findType(qualifiedName); - - // 6. No? Try looking it up as a flags type - if (!type) - type = TypeDatabase::instance()->findFlagsType(qualifiedName); - - // 7. No? Try looking it up as a container type - if (!type) - type = TypeDatabase::instance()->findContainerType(name); - - // 8. No? Check if the current class is a template and this type is one - // of the parameters. - if (!type && currentClass) { - const QVector<TypeEntry *> &template_args = currentClass->templateArguments(); - for (TypeEntry *te : template_args) { - if (te->name() == qualifiedName) - type = te; - } - } - - if (!type) { + const TypeEntries types = findTypeEntries(qualifiedName, name, currentClass, d); + if (types.isEmpty()) { if (errorMessageIn) { *errorMessageIn = msgUnableToTranslateType(_typei, msgCannotFindTypeEntry(qualifiedName)); @@ -2300,11 +2230,10 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo return nullptr; } - // These are only implicit and should not appear in code... - Q_ASSERT(!type->isInterface()); + const TypeEntry *type = types.constFirst(); + const TypeEntry::Type typeEntryType = type->type(); - auto *metaType = new AbstractMetaType; - metaType->setTypeEntry(type); + QScopedPointer<AbstractMetaType> metaType(new AbstractMetaType); metaType->setIndirectionsV(typeInfo.indirectionsV()); metaType->setReferenceType(typeInfo.referenceType()); metaType->setConstant(typeInfo.isConstant()); @@ -2318,20 +2247,66 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo if (!targType) { if (errorMessageIn) *errorMessageIn = msgCannotTranslateTemplateArgument(t, ti, errorMessage); - delete metaType; return nullptr; } metaType->addInstantiation(targType, true); } + if (types.size() > 1) { + const bool sameType = std::all_of(types.cbegin() + 1, types.cend(), + [typeEntryType](const TypeEntry *e) { + return e->type() == typeEntryType; }); + if (!sameType) { + if (errorMessageIn) + *errorMessageIn = msgAmbiguousVaryingTypesFound(qualifiedName, types); + return nullptr; + } + // Ambiguous primitive/smart pointer types are possible (when + // including type systems). + if (typeEntryType != TypeEntry::PrimitiveType + && typeEntryType != TypeEntry::SmartPointerType) { + if (errorMessageIn) + *errorMessageIn = msgAmbiguousTypesFound(qualifiedName, types); + return nullptr; + } + } + + if (typeEntryType == TypeEntry::SmartPointerType) { + // Find a matching instantiation + if (metaType->instantiations().size() != 1) { + if (errorMessageIn) + *errorMessageIn = msgInvalidSmartPointerType(_typei); + return nullptr; + } + auto instantiationType = metaType->instantiations().constFirst()->typeEntry(); + if (instantiationType->type() == TypeEntry::TemplateArgumentType) { + // Member functions of the template itself, SharedPtr(const SharedPtr &) + type = instantiationType; + } else { + auto it = std::find_if(types.cbegin(), types.cend(), + [instantiationType](const TypeEntry *e) { + auto smartPtr = static_cast<const SmartPointerTypeEntry *>(e); + return smartPtr->matchesInstantiation(instantiationType); + }); + if (it == types.cend()) { + if (errorMessageIn) + *errorMessageIn = msgCannotFindSmartPointerInstantion(_typei); + return nullptr; + } + type =*it; + } + } + + metaType->setTypeEntry(type); + // The usage pattern *must* be decided *after* the possible template // instantiations have been determined, or else the absence of // such instantiations will break the caching scheme of // AbstractMetaType::cppSignature(). metaType->decideUsagePattern(); - return metaType; + return metaType.take(); } AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei, @@ -2786,7 +2761,6 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, subclass->setTemplateBaseClass(templateClass); subclass->setTemplateBaseClassInstantiations(templateTypes); - subclass->setInterfaces(templateClass->interfaces()); subclass->setBaseClass(templateClass->baseClass()); return true; @@ -2864,11 +2838,9 @@ void AbstractMetaBuilderPrivate::setupClonable(AbstractMetaClass *cls) QQueue<AbstractMetaClass*> baseClasses; if (cls->baseClass()) baseClasses.enqueue(cls->baseClass()); - baseClasses << cls->interfaces().toList(); while (!baseClasses.isEmpty()) { AbstractMetaClass* currentClass = baseClasses.dequeue(); - baseClasses << currentClass->interfaces().toList(); if (currentClass->baseClass()) baseClasses.enqueue(currentClass->baseClass()); @@ -2913,7 +2885,7 @@ static void writeRejectLogFile(const QString &name, for (int reason = 0; reason < AbstractMetaBuilder::NoReason; ++reason) { - s << QString(72, QLatin1Char('*')) << endl; + s << QString(72, QLatin1Char('*')) << Qt::endl; switch (reason) { case AbstractMetaBuilder::NotInTypeSystem: s << "Not in type system"; @@ -2946,16 +2918,16 @@ static void writeRejectLogFile(const QString &name, break; } - s << endl; + s << Qt::endl; for (QMap<QString, AbstractMetaBuilder::RejectReason>::const_iterator it = rejects.constBegin(); it != rejects.constEnd(); ++it) { if (it.value() != reason) continue; - s << " - " << it.key() << endl; + s << " - " << it.key() << Qt::endl; } - s << QString(72, QLatin1Char('*')) << endl << endl; + s << QString(72, QLatin1Char('*')) << Qt::endl << Qt::endl; } } @@ -3064,8 +3036,7 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const } else { for (int i : qAsConst(unmappedResult)) { Q_ASSERT(reverseMap.contains(i)); - if (!reverseMap[i]->isInterface()) - result << reverseMap[i]; + result << reverseMap[i]; } } diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index b381a62cd..e3c9e1a72 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -146,6 +146,9 @@ public: AbstractMetaBuilderPrivate *d = nullptr, TranslateTypeFlags flags = {}, QString *errorMessageIn = nullptr); + static TypeEntries findTypeEntries(const QString &qualifiedName, const QString &name, + AbstractMetaClass *currentClass = nullptr, + AbstractMetaBuilderPrivate *d = nullptr); qint64 findOutValueFromString(const QString &stringValue, bool &ok); diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index 5ae671d87..e6590e2dc 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -80,15 +80,10 @@ 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; } @@ -268,7 +263,7 @@ 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; } @@ -531,7 +526,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()) @@ -948,9 +943,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; @@ -1365,44 +1357,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 @@ -1424,10 +1378,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; @@ -1604,11 +1554,19 @@ QString AbstractMetaClass::name() const 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 @@ -1616,11 +1574,6 @@ QString AbstractMetaClass::package() const return m_typeEntry->targetLangPackage(); } -bool AbstractMetaClass::isInterface() const -{ - return m_typeEntry->isInterface(); -} - bool AbstractMetaClass::isNamespace() const { return m_typeEntry->isNamespace(); @@ -1729,7 +1682,7 @@ void AbstractMetaClass::setTemplateBaseClassInstantiations(AbstractMetaTypeList 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) @@ -1858,6 +1811,14 @@ const AbstractMetaFunction *AbstractMetaField::setter() const return m_setter; } +const AbstractMetaClass *EnclosingClassMixin::targetLangEnclosingClass() const +{ + auto result = m_enclosingClass; + while (result && !NamespaceTypeEntry::isVisibleScope(result->typeEntry())) + result = result->enclosingClass(); + return result; +} + const AbstractMetaFunction *AbstractMetaField::getter() const { if (!m_getter) { @@ -2139,57 +2100,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); @@ -2199,10 +2109,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; } @@ -2215,10 +2121,6 @@ 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); @@ -2265,32 +2167,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)) { @@ -2419,11 +2312,6 @@ void AbstractMetaClass::fixFunctions() (*copy) += AddedMethod; funcs.append(copy); } - - if (superClass) - superClass = superClass->baseClass(); - else - iface_idx++; } bool hasPrivateConstructors = false; @@ -2522,7 +2410,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. @@ -2545,7 +2433,7 @@ QString AbstractMetaType::formatPythonSignature(bool minimal) const 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)); @@ -2559,7 +2447,7 @@ QString AbstractMetaType::formatPythonSignature(bool minimal) const 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(']'); } @@ -2676,6 +2564,63 @@ 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 << ">\""; + } +} + +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 << ')'; + } +} + QDebug operator<<(QDebug d, const AbstractMetaClass *ac) { QDebugStateSaver saver(d); @@ -2683,57 +2628,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'; } diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 2ae1b6d21..3e17a713b 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -538,7 +538,7 @@ public: private: TypeUsagePattern determineUsagePattern() const; QString formatSignature(bool minimal) const; - QString formatPythonSignature(bool minimal) const; + QString formatPythonSignature() const; const TypeEntry *m_typeEntry = nullptr; AbstractMetaTypeList m_instantiations; @@ -704,25 +704,26 @@ private: friend class AbstractMetaClass; }; +class EnclosingClassMixin { +public: + const AbstractMetaClass *enclosingClass() const { return m_enclosingClass; } + void setEnclosingClass(const AbstractMetaClass *cls) { m_enclosingClass = cls; } + const AbstractMetaClass *targetLangEnclosingClass() const; + +private: + const AbstractMetaClass *m_enclosingClass = nullptr; +}; + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const AbstractMetaArgument *aa); #endif -class AbstractMetaField : public AbstractMetaVariable, public AbstractMetaAttributes +class AbstractMetaField : public AbstractMetaVariable, public AbstractMetaAttributes, public EnclosingClassMixin { public: AbstractMetaField(); ~AbstractMetaField(); - const AbstractMetaClass *enclosingClass() const - { - return m_class; - } - void setEnclosingClass(const AbstractMetaClass *cls) - { - m_class = cls; - } - const AbstractMetaFunction *getter() const; const AbstractMetaFunction *setter() const; @@ -741,7 +742,6 @@ public: private: mutable AbstractMetaFunction *m_getter = nullptr; mutable AbstractMetaFunction *m_setter = nullptr; - const AbstractMetaClass *m_class = nullptr; }; #ifndef QT_NO_DEBUG_STREAM @@ -1179,7 +1179,7 @@ private: Documentation m_doc; }; -class AbstractMetaEnum : public AbstractMetaAttributes +class AbstractMetaEnum : public AbstractMetaAttributes, public EnclosingClassMixin { public: AbstractMetaEnum(); @@ -1234,23 +1234,12 @@ public: m_typeEntry = entry; } - AbstractMetaClass *enclosingClass() const - { - return m_class; - } - - void setEnclosingClass(AbstractMetaClass *c) - { - m_class = c; - } - bool isSigned() const { return m_signed; } void setSigned(bool s) { m_signed = s; } private: AbstractMetaEnumValueList m_enumValues; EnumTypeEntry *m_typeEntry = nullptr; - AbstractMetaClass *m_class = nullptr; EnumKind m_enumKind = CEnum; uint m_hasQenumsDeclaration : 1; @@ -1261,7 +1250,7 @@ private: QDebug operator<<(QDebug d, const AbstractMetaEnum *ae); #endif -class AbstractMetaClass : public AbstractMetaAttributes +class AbstractMetaClass : public AbstractMetaAttributes, public EnclosingClassMixin { Q_GADGET public: @@ -1306,7 +1295,6 @@ public: AbstractMetaClass(); ~AbstractMetaClass(); - AbstractMetaClass *extractInterface(); void fixFunctions(); AbstractMetaFunctionList functions() const @@ -1447,13 +1435,6 @@ public: AbstractMetaEnum *findEnum(const QString &enumName); AbstractMetaEnumValue *findEnumValue(const QString &enumName); - AbstractMetaClassList interfaces() const - { - return m_interfaces; - } - void addInterface(AbstractMetaClass *interface); - void setInterfaces(const AbstractMetaClassList &interface); - QString fullName() const { return package() + QLatin1Char('.') + name(); @@ -1467,32 +1448,24 @@ public: QString baseClassName() const { - return m_baseClass ? m_baseClass->name() : QString(); + return m_baseClasses.isEmpty() ? QString() : m_baseClasses.constFirst()->name(); } AbstractMetaClass *baseClass() const { - return m_baseClass; + return m_baseClasses.value(0, nullptr); } + const AbstractMetaClassList &baseClasses() const { return m_baseClasses; } + void addBaseClass(AbstractMetaClass *base_class); void setBaseClass(AbstractMetaClass *base_class); - const AbstractMetaClass *enclosingClass() const - { - return m_enclosingClass; - } - /** * \return the namespace from another package which this namespace extends. */ AbstractMetaClass *extendedNamespace() const { return m_extendedNamespace; } void setExtendedNamespace(AbstractMetaClass *e) { m_extendedNamespace = e; } - void setEnclosingClass(AbstractMetaClass *cl) - { - m_enclosingClass = cl; - } - const AbstractMetaClassList& innerClasses() const { return m_innerClasses; @@ -1510,8 +1483,6 @@ public: QString package() const; - bool isInterface() const; - bool isNamespace() const; bool isQObject() const; @@ -1712,6 +1683,8 @@ public: private: #ifndef QT_NO_DEBUG_STREAM + void format(QDebug &d) const; + void formatMembers(QDebug &d) const; friend QDebug operator<<(QDebug d, const AbstractMetaClass *ac); #endif uint m_hasVirtuals : 1; @@ -1730,21 +1703,19 @@ private: uint m_hasToStringCapability : 1; const AbstractMetaClass *m_enclosingClass = nullptr; - AbstractMetaClass *m_baseClass = nullptr; + AbstractMetaClassList m_baseClasses; // Real base classes after setting up inheritance AbstractMetaClass *m_extendedNamespace = nullptr; const AbstractMetaClass *m_templateBaseClass = nullptr; AbstractMetaFunctionList m_functions; AbstractMetaFieldList m_fields; AbstractMetaEnumList m_enums; - AbstractMetaClassList m_interfaces; - AbstractMetaClass *m_extractedInterface = nullptr; QVector<QPropertySpec *> m_propertySpecs; AbstractMetaClassList m_innerClasses; AbstractMetaFunctionList m_externalConversionOperators; - QStringList m_baseClassNames; + QStringList m_baseClassNames; // Base class names from C++, including rejected QVector<TypeEntry *> m_templateArgs; ComplexTypeEntry *m_typeEntry = nullptr; // FunctionModelItem m_qDebugStreamFunction; diff --git a/sources/shiboken2/ApiExtractor/apiextractor.cpp b/sources/shiboken2/ApiExtractor/apiextractor.cpp index 78fa9e313..6d29ed1e0 100644 --- a/sources/shiboken2/ApiExtractor/apiextractor.cpp +++ b/sources/shiboken2/ApiExtractor/apiextractor.cpp @@ -166,24 +166,6 @@ ContainerTypeEntryList ApiExtractor::containerTypes() const return TypeDatabase::instance()->containerTypes(); } -static const AbstractMetaEnum* findEnumOnClasses(AbstractMetaClassList metaClasses, const EnumTypeEntry* typeEntry) -{ - const AbstractMetaEnum *result = nullptr; - for (const AbstractMetaClass* metaClass : qAsConst(metaClasses)) { - const AbstractMetaEnumList &enums = metaClass->enums(); - for (const AbstractMetaEnum *metaEnum : enums) { - if (metaEnum->typeEntry() == typeEntry) { - result = metaEnum; - break; - } - } - if (result) - break; - result = findEnumOnClasses(metaClass->innerClasses(), typeEntry); - } - return result; -} - const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const TypeEntry* typeEntry) const { return m_builder->findEnum(typeEntry); diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp index a5b153499..78f34c87f 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp @@ -222,6 +222,7 @@ public: FunctionModelItem m_currentFunction; ArgumentModelItem m_currentArgument; VariableModelItem m_currentField; + QByteArrayList m_systemIncludes; int m_anonymousEnumCount = 0; CodeModel::FunctionType m_currentFunctionType = CodeModel::Normal; @@ -720,6 +721,12 @@ bool BuilderPrivate::visitHeader(const char *cFileName) const return true; } #endif // Q_OS_MACOS + if (baseName) { + for (const auto &systemInclude : m_systemIncludes) { + if (systemInclude == baseName) + return true; + } + } return false; } @@ -742,6 +749,11 @@ bool Builder::visitLocation(const CXSourceLocation &location) const return result; } +void Builder::setSystemIncludes(const QByteArrayList &systemIncludes) +{ + d->m_systemIncludes = systemIncludes; +} + FileModelItem Builder::dom() const { Q_ASSERT(!d->m_scopeStack.isEmpty()); @@ -765,6 +777,17 @@ static CodeModel::ClassType codeModelClassTypeFromCursor(CXCursorKind kind) return result; } +static NamespaceType namespaceType(const CXCursor &cursor) +{ + if (clang_Cursor_isAnonymous(cursor)) + return NamespaceType::Anonymous; +#if CINDEX_VERSION_MAJOR > 0 || CINDEX_VERSION_MINOR >= 59 + if (clang_Cursor_isInlineNamespace(cursor)) + return NamespaceType::Inline; +#endif + return NamespaceType::Default; +} + BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) { switch (cursor.kind) { @@ -890,6 +913,9 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) d->m_scopeStack.back()->addFunction(d->m_currentFunction); break; case CXCursor_Namespace: { + const auto type = namespaceType(cursor); + if (type == NamespaceType::Anonymous) + return Skip; const QString name = getCursorSpelling(cursor); const NamespaceModelItem parentNamespaceItem = qSharedPointerDynamicCast<_NamespaceModelItem>(d->m_scopeStack.back()); if (parentNamespaceItem.isNull()) { @@ -906,6 +932,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) namespaceItem.reset(new _NamespaceModelItem(d->m_model, name)); setFileName(cursor, namespaceItem.data()); namespaceItem->setScope(d->m_scope); + namespaceItem->setType(type); parentNamespaceItem->addNamespace(namespaceItem); d->pushScope(namespaceItem); } diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h index fa79acb2a..dc37dff0f 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h @@ -44,6 +44,8 @@ public: Builder(); ~Builder(); + void setSystemIncludes(const QByteArrayList &systemIncludes); + bool visitLocation(const CXSourceLocation &location) const override; StartTokenResult startToken(const CXCursor &cursor) override; diff --git a/sources/shiboken2/ApiExtractor/graph.cpp b/sources/shiboken2/ApiExtractor/graph.cpp index 95a80197e..53e20ebba 100644 --- a/sources/shiboken2/ApiExtractor/graph.cpp +++ b/sources/shiboken2/ApiExtractor/graph.cpp @@ -101,7 +101,7 @@ bool Graph::containsEdge(int from, int to) void Graph::addEdge(int from, int to) { - Q_ASSERT(to < (int)m_d->edges.size()); + Q_ASSERT(to < m_d->edges.size()); m_d->edges[from].insert(to); } diff --git a/sources/shiboken2/ApiExtractor/include.cpp b/sources/shiboken2/ApiExtractor/include.cpp index d6a451992..82cb1d95b 100644 --- a/sources/shiboken2/ApiExtractor/include.cpp +++ b/sources/shiboken2/ApiExtractor/include.cpp @@ -49,7 +49,7 @@ uint qHash(const Include& inc) QTextStream& operator<<(QTextStream& out, const Include& include) { if (include.isValid()) - out << include.toString() << endl; + out << include.toString() << Qt::endl; return out; } diff --git a/sources/shiboken2/ApiExtractor/messages.cpp b/sources/shiboken2/ApiExtractor/messages.cpp index 546e9c4ed..0c29249d3 100644 --- a/sources/shiboken2/ApiExtractor/messages.cpp +++ b/sources/shiboken2/ApiExtractor/messages.cpp @@ -28,6 +28,7 @@ #include "messages.h" #include "abstractmetalang.h" +#include "typedatabase.h" #include "typesystem.h" #include <codemodel.h> @@ -130,6 +131,22 @@ QString msgNoEnumTypeConflict(const EnumModelItem &enumItem, return result; } +QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te) +{ + QString result = QLatin1String("Ambiguous types of varying types found for \"") + qualifiedName + + QLatin1String("\": "); + QDebug(&result) << te; + return result; +} + +QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te) +{ + QString result = QLatin1String("Ambiguous types found for \"") + qualifiedName + + QLatin1String("\": "); + QDebug(&result) << te; + return result; +} + QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n, const QString &why) { @@ -196,6 +213,23 @@ QString msgCannotFindTypeEntry(const QString &t) return QLatin1String("Cannot find type entry for \"") + t + QLatin1String("\"."); } +QString msgCannotFindTypeEntryForSmartPointer(const QString &t, const QString &smartPointerType) +{ + return QLatin1String("Cannot find type entry \"") + t + + QLatin1String("\" for instantiation of \"") + smartPointerType + QLatin1String("\"."); +} + +QString msgInvalidSmartPointerType(const TypeInfo &i) +{ + return QLatin1String("Invalid smart pointer type \"") + i.toString() + QLatin1String("\"."); +} + +QString msgCannotFindSmartPointerInstantion(const TypeInfo &i) +{ + return QLatin1String("Cannot find instantiation of smart pointer type for \"") + + i.toString() + QLatin1String("\"."); +} + QString msgCannotTranslateTemplateArgument(int i, const TypeInfo &typeInfo, const QString &why) @@ -334,8 +368,10 @@ QString msgCannotFindSmartPointer(const QString &instantiationType, QString result; QTextStream str(&result); str << "Unable to find smart pointer type for " << instantiationType << " (known types:"; - for (auto t : pointers) - str << ' ' << t->fullName(); + for (auto t : pointers) { + auto typeEntry = t->typeEntry(); + str << ' ' << typeEntry->targetLangName() << '/' << typeEntry->qualifiedCppName(); + } str << ")."; return result; } diff --git a/sources/shiboken2/ApiExtractor/messages.h b/sources/shiboken2/ApiExtractor/messages.h index 2b7b75ba0..321a4a538 100644 --- a/sources/shiboken2/ApiExtractor/messages.h +++ b/sources/shiboken2/ApiExtractor/messages.h @@ -59,6 +59,9 @@ QString msgNoEnumTypeConflict(const EnumModelItem &enumItem, const QString &className, const TypeEntry *t); +QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te); +QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te); + QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n, const QString &why); @@ -79,6 +82,10 @@ QString msgUnableToTranslateType(const TypeInfo &typeInfo, QString msgCannotFindTypeEntry(const QString &t); +QString msgCannotFindTypeEntryForSmartPointer(const QString &t, const QString &smartPointerType); +QString msgInvalidSmartPointerType(const TypeInfo &i); +QString msgCannotFindSmartPointerInstantion(const TypeInfo &i); + QString msgCannotTranslateTemplateArgument(int i, const TypeInfo &typeInfo, const QString &why); diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp index 099ab8860..892a20bb7 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp @@ -923,6 +923,16 @@ void _NamespaceModelItem::appendNamespace(const _NamespaceModelItem &other) void _NamespaceModelItem::formatDebug(QDebug &d) const { _ScopeModelItem::formatDebug(d); + switch (m_type) { + case NamespaceType::Default: + break; + case NamespaceType::Anonymous: + d << ", anonymous"; + break; + case NamespaceType::Inline: + d << ", inline"; + break; + } formatScopeList(d, ", namespaces=", m_namespaces); } #endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h index 80db2cce5..2e33d6cd0 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h @@ -438,6 +438,9 @@ public: const NamespaceList &namespaces() const { return m_namespaces; } + NamespaceType type() const { return m_type; } + void setType(NamespaceType t) { m_type = t; } + void addNamespace(NamespaceModelItem item); NamespaceModelItem findNamespace(const QString &name) const; @@ -450,6 +453,7 @@ public: private: NamespaceList m_namespaces; + NamespaceType m_type = NamespaceType::Default; }; class _FileModelItem: public _NamespaceModelItem diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h index 1713ba42f..aebd59879 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h @@ -54,4 +54,11 @@ enum class ExceptionSpecification Throws }; +enum class NamespaceType +{ + Default, + Anonymous, + Inline +}; + #endif // CODEMODEL_ENUMS_H diff --git a/sources/shiboken2/ApiExtractor/reporthandler.cpp b/sources/shiboken2/ApiExtractor/reporthandler.cpp index c0c323029..d83154ba8 100644 --- a/sources/shiboken2/ApiExtractor/reporthandler.cpp +++ b/sources/shiboken2/ApiExtractor/reporthandler.cpp @@ -35,7 +35,7 @@ #include <cstdarg> #include <cstdio> -#if _WINDOWS || NOCOLOR +#if defined(_WINDOWS) || defined(NOCOLOR) #define COLOR_END "" #define COLOR_WHITE "" #define COLOR_YELLOW "" diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index f393bf3bf..775ed2f81 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -144,6 +144,25 @@ IncludeList TypeDatabase::extraIncludes(const QString& className) const return typeEntry ? typeEntry->extraIncludes() : IncludeList(); } +void TypeDatabase::addSystemInclude(const QString &name) +{ + m_systemIncludes.append(name.toUtf8()); +} + +// Add a lookup for the short name excluding inline namespaces +// so that "std::shared_ptr" finds "std::__1::shared_ptr" as well. +// Note: This inserts duplicate TypeEntry * into m_entries. +void TypeDatabase::addInlineNamespaceLookups(const NamespaceTypeEntry *n) +{ + QVector<TypeEntry *> additionalEntries; // Store before modifying the hash + for (TypeEntry *entry : m_entries) { + if (entry->isChildOf(n)) + additionalEntries.append(entry); + } + for (const auto &ae : additionalEntries) + m_entries.insert(ae->shortName(), ae); +} + ContainerTypeEntry* TypeDatabase::findContainerType(const QString &name) const { QString template_name = name; @@ -166,7 +185,7 @@ static bool inline useType(const TypeEntry *t) FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry->type() == TypeEntry::FunctionType && useType(entry)) return static_cast<FunctionTypeEntry*>(entry); @@ -201,7 +220,7 @@ QString TypeDatabase::defaultPackageName() const TypeEntry* TypeDatabase::findType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (useType(entry)) return entry; @@ -209,7 +228,53 @@ TypeEntry* TypeDatabase::findType(const QString& name) const return nullptr; } -TypeEntryMultiMapConstIteratorRange TypeDatabase::findTypes(const QString &name) const +template <class Predicate> +TypeEntries TypeDatabase::findTypesHelper(const QString &name, Predicate pred) const +{ + TypeEntries result; + const auto entries = findTypeRange(name); + for (TypeEntry *entry : entries) { + if (pred(entry)) + result.append(entry); + } + return result; +} + +TypeEntries TypeDatabase::findTypes(const QString &name) const +{ + return findTypesHelper(name, useType); +} + +static bool useCppType(const TypeEntry *t) +{ + bool result = false; + switch (t->type()) { + case TypeEntry::PrimitiveType: + case TypeEntry::VoidType: + case TypeEntry::FlagsType: + case TypeEntry::EnumType: + case TypeEntry::TemplateArgumentType: + case TypeEntry::BasicValueType: + case TypeEntry::ContainerType: + case TypeEntry::ObjectType: + case TypeEntry::ArrayType: + case TypeEntry::CustomType: + case TypeEntry::SmartPointerType: + case TypeEntry::TypedefType: + result = useType(t); + break; + default: + break; + } + return result; +} + +TypeEntries TypeDatabase::findCppTypes(const QString &name) const +{ + return findTypesHelper(name, useCppType); +} + +TypeEntryMultiMapConstIteratorRange TypeDatabase::findTypeRange(const QString &name) const { const auto range = m_entries.equal_range(name); return {range.first, range.second}; @@ -322,11 +387,10 @@ TypeEntry *TypeDatabase::resolveTypeDefEntry(TypedefEntry *typedefEntry, if (lessThanPos != -1) sourceName.truncate(lessThanPos); ComplexTypeEntry *source = nullptr; - for (TypeEntry *e : findTypes(sourceName)) { + for (TypeEntry *e : findTypeRange(sourceName)) { switch (e->type()) { case TypeEntry::BasicValueType: case TypeEntry::ContainerType: - case TypeEntry::InterfaceType: case TypeEntry::ObjectType: case TypeEntry::SmartPointerType: source = dynamic_cast<ComplexTypeEntry *>(e); @@ -581,7 +645,7 @@ bool TypeDatabase::parseFile(QIODevice* device, bool generate) PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry->isPrimitive()) { auto *pe = static_cast<PrimitiveTypeEntry *>(entry); @@ -595,7 +659,7 @@ PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry->isComplex() && useType(entry)) return static_cast<ComplexTypeEntry*>(entry); @@ -605,7 +669,7 @@ ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry && entry->isObject() && useType(entry)) return static_cast<ObjectTypeEntry*>(entry); @@ -616,7 +680,7 @@ ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const NamespaceTypeEntryList TypeDatabase::findNamespaceTypes(const QString& name) const { NamespaceTypeEntryList result; - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry->isNamespace()) result.append(static_cast<NamespaceTypeEntry*>(entry)); @@ -698,6 +762,35 @@ static void _computeTypeIndexes() computeTypeIndexes = false; } +// Build the C++ name excluding any inline namespaces +// ("std::__1::shared_ptr" -> "std::shared_ptr" +QString TypeEntry::shortName() const +{ + if (m_cachedShortName.isEmpty()) { + QVarLengthArray<const TypeEntry *> parents; + bool foundInlineNamespace = false; + for (auto p = m_parent; p != nullptr && p->type() != TypeEntry::TypeSystemType; p = p->parent()) { + if (p->type() == TypeEntry::NamespaceType + && static_cast<const NamespaceTypeEntry *>(p)->isInlineNamespace()) { + foundInlineNamespace = true; + } else { + parents.append(p); + } + } + if (foundInlineNamespace) { + m_cachedShortName.reserve(m_name.size()); + for (int i = parents.size() - 1; i >= 0; --i) { + m_cachedShortName.append(parents.at(i)->entryName()); + m_cachedShortName.append(QLatin1String("::")); + } + m_cachedShortName.append(m_entryName); + } else { + m_cachedShortName = m_name; + } + } + return m_cachedShortName; +} + void TypeEntry::setRevision(int r) { if (m_revision != r) { @@ -794,7 +887,7 @@ void TypeEntry::formatDebug(QDebug &d) const if (m_name != cppName) d << "\", cppName=\"" << cppName << '"'; d << ", type=" << m_type << ", codeGeneration=0x" - << hex << m_codeGeneration << dec + << Qt::hex << m_codeGeneration << Qt::dec << ", target=\"" << targetLangName() << '"'; FORMAT_NONEMPTY_STRING("package", m_targetLangPackage) FORMAT_BOOL("stream", m_stream) @@ -849,6 +942,9 @@ void NamespaceTypeEntry::formatDebug(QDebug &d) const ComplexTypeEntry::formatDebug(d); auto pattern = m_filePattern.pattern(); FORMAT_NONEMPTY_STRING("pattern", pattern) + d << ",visibility=" << m_visibility; + if (m_inlineNamespace) + d << "[inline]"; } void ContainerTypeEntry::formatDebug(QDebug &d) const @@ -857,6 +953,17 @@ void ContainerTypeEntry::formatDebug(QDebug &d) const d << ", type=" << m_type << ",\"" << typeName() << '"'; } +void SmartPointerTypeEntry::formatDebug(QDebug &d) const +{ + ComplexTypeEntry::formatDebug(d); + if (!m_instantiations.isEmpty()) { + d << ", instantiations[" << m_instantiations.size() << "]=("; + for (auto i : m_instantiations) + d << i->name() << ','; + d << ')'; + } +} + QDebug operator<<(QDebug d, const TypeEntry *te) { QDebugStateSaver saver(d); diff --git a/sources/shiboken2/ApiExtractor/typedatabase.h b/sources/shiboken2/ApiExtractor/typedatabase.h index f615b623d..0a0a4eed5 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.h +++ b/sources/shiboken2/ApiExtractor/typedatabase.h @@ -96,6 +96,11 @@ public: IncludeList extraIncludes(const QString &className) const; + const QByteArrayList &systemIncludes() const { return m_systemIncludes; } + void addSystemInclude(const QString &name); + + void addInlineNamespaceLookups(const NamespaceTypeEntry *n); + PrimitiveTypeEntry *findPrimitiveType(const QString &name) const; ComplexTypeEntry *findComplexType(const QString &name) const; ObjectTypeEntry *findObjectType(const QString &name) const; @@ -108,6 +113,8 @@ public: QString defaultPackageName() const; TypeEntry *findType(const QString &name) const; + TypeEntries findTypes(const QString &name) const; + TypeEntries findCppTypes(const QString &name) const; const TypeEntryMultiMap &entries() const { return m_entries; } const TypedefEntryMap &typedefEntries() const { return m_typedefEntries; } @@ -179,11 +186,13 @@ public: void formatDebug(QDebug &d) const; #endif private: - TypeEntryMultiMapConstIteratorRange findTypes(const QString &name) const; + TypeEntryMultiMapConstIteratorRange findTypeRange(const QString &name) const; + template <class Predicate> + TypeEntries findTypesHelper(const QString &name, Predicate pred) const; TypeEntry *resolveTypeDefEntry(TypedefEntry *typedefEntry, QString *errorMessage); bool m_suppressWarnings = true; - TypeEntryMultiMap m_entries; + TypeEntryMultiMap m_entries; // Contains duplicate entries (cf addInlineNamespaceLookups). TypeEntryMap m_flagsEntries; TypedefEntryMap m_typedefEntries; TemplateEntryMap m_templates; @@ -201,6 +210,7 @@ private: QVector<TypeRejection> m_rejections; QStringList m_dropTypeEntries; + QByteArrayList m_systemIncludes; }; #ifndef QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index abd2bfb07..0ec158ae1 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -433,7 +433,7 @@ QDebug operator<<(QDebug d, const CodeSnip &s) void Modification::formatDebug(QDebug &d) const { - d << "modifiers=" << hex << showbase << modifiers << noshowbase << dec; + d << "modifiers=" << Qt::hex << Qt::showbase << modifiers << Qt::noshowbase << Qt::dec; if (removal) d << ", removal"; if (!renamedToName.isEmpty()) @@ -684,6 +684,15 @@ TypeEntry::~TypeEntry() delete m_customConversion; } +bool TypeEntry::isChildOf(const TypeEntry *p) const +{ + for (auto e = m_parent; e; e = e->parent()) { + if (e == p) + return true; + } + return false; +} + const TypeSystemTypeEntry *TypeEntry::typeSystemTypeEntry() const { for (auto e = this; e; e = e->parent()) { @@ -693,6 +702,16 @@ const TypeSystemTypeEntry *TypeEntry::typeSystemTypeEntry() const return nullptr; } +const TypeEntry *TypeEntry::targetLangEnclosingEntry() const +{ + auto result = m_parent; + while (result && result->type() != TypeEntry::TypeSystemType + && !NamespaceTypeEntry::isVisibleScope(result)) { + result = result->parent(); + } + return result; +} + QString TypeEntry::targetLangName() const { if (m_cachedTargetLangName.isEmpty()) @@ -704,11 +723,13 @@ QString TypeEntry::buildTargetLangName() const { QString result = m_entryName; for (auto p = parent(); p && p->type() != TypeEntry::TypeSystemType; p = p->parent()) { - if (!result.isEmpty()) - result.prepend(QLatin1Char('.')); - QString n = p->m_entryName; - n.replace(QLatin1String("::"), QLatin1String(".")); // Primitive types may have "std::" - result.prepend(n); + if (NamespaceTypeEntry::isVisibleScope(p)) { + if (!result.isEmpty()) + result.prepend(QLatin1Char('.')); + QString n = p->m_entryName; + n.replace(QLatin1String("::"), QLatin1String(".")); // Primitive types may have "std::" + result.prepend(n); + } } return result; } @@ -752,6 +773,8 @@ TypeEntry *TypeEntry::clone() const // Take over parameters relevant for typedefs void TypeEntry::useAsTypedef(const TypeEntry *source) { + // XML Typedefs are in the global namespace for now. + m_parent = source->typeSystemTypeEntry(); m_entryName = source->m_entryName; m_name = source->m_name; m_targetLangPackage = source->m_targetLangPackage; @@ -933,6 +956,11 @@ TypeEntry *SmartPointerTypeEntry::clone() const SmartPointerTypeEntry::SmartPointerTypeEntry(const SmartPointerTypeEntry &) = default; +bool SmartPointerTypeEntry::matchesInstantiation(const TypeEntry *e) const +{ + return m_instantiations.isEmpty() || m_instantiations.contains(e); +} + NamespaceTypeEntry::NamespaceTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) : ComplexTypeEntry(entryName, NamespaceType, vr, parent) @@ -959,6 +987,18 @@ bool NamespaceTypeEntry::matchesFile(const QString &needle) const return m_filePattern.match(needle).hasMatch(); } +bool NamespaceTypeEntry::isVisible() const +{ + return m_visibility == TypeSystem::Visibility::Visible + || (m_visibility == TypeSystem::Visibility::Auto && !m_inlineNamespace); +} + +bool NamespaceTypeEntry::isVisibleScope(const TypeEntry *e) +{ + return e->type() != TypeEntry::NamespaceType + || static_cast<const NamespaceTypeEntry *>(e)->isVisible(); +} + ValueTypeEntry::ValueTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) : ComplexTypeEntry(entryName, BasicValueType, vr, parent) @@ -970,11 +1010,6 @@ bool ValueTypeEntry::isValue() const return true; } -bool ValueTypeEntry::isNativeIdBased() const -{ - return true; -} - TypeEntry *ValueTypeEntry::clone() const { return new ValueTypeEntry(*this); @@ -1122,30 +1157,6 @@ void CustomConversion::TargetToNativeConversion::setConversion(const QString& co m_d->conversion = conversion; } -InterfaceTypeEntry::InterfaceTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent) : - ComplexTypeEntry(entryName, InterfaceType, vr, parent) -{ -} - -bool InterfaceTypeEntry::isNativeIdBased() const -{ - return true; -} - -QString InterfaceTypeEntry::qualifiedCppName() const -{ - const int len = ComplexTypeEntry::qualifiedCppName().length() - interfaceName(QString()).length(); - return ComplexTypeEntry::qualifiedCppName().left(len); -} - -TypeEntry *InterfaceTypeEntry::clone() const -{ - return new InterfaceTypeEntry(*this); -} - -InterfaceTypeEntry::InterfaceTypeEntry(const InterfaceTypeEntry &) = default; - FunctionTypeEntry::FunctionTypeEntry(const QString &entryName, const QString &signature, const QVersionNumber &vr, const TypeEntry *parent) : @@ -1167,16 +1178,6 @@ ObjectTypeEntry::ObjectTypeEntry(const QString &entryName, const QVersionNumber { } -InterfaceTypeEntry *ObjectTypeEntry::designatedInterface() const -{ - return m_interface; -} - -bool ObjectTypeEntry::isNativeIdBased() const -{ - return true; -} - TypeEntry *ObjectTypeEntry::clone() const { return new ObjectTypeEntry(*this); diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index 4d0a23ca1..790fb95cb 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -228,7 +228,7 @@ struct ArgumentModification struct Modification { - enum Modifiers { + enum Modifiers : uint { InvalidModifier = 0x0000, Private = 0x0001, Protected = 0x0002, @@ -499,7 +499,6 @@ QDebug operator<<(QDebug d, const AddedFunction::Argument &a); QDebug operator<<(QDebug d, const AddedFunction &af); #endif -class InterfaceTypeEntry; class ObjectTypeEntry; class DocModification @@ -562,20 +561,13 @@ public: EnumValue, ConstantValueType, TemplateArgumentType, - ThreadType, BasicValueType, - StringType, ContainerType, - InterfaceType, ObjectType, NamespaceType, - VariantType, - JObjectWrapperType, - CharType, ArrayType, TypeSystemType, CustomType, - TargetLangType, FunctionType, SmartPointerType, TypedefType @@ -605,7 +597,10 @@ public: const TypeEntry *parent() const { return m_parent; } void setParent(const TypeEntry *p) { m_parent = p; } + bool isChildOf(const TypeEntry *p) const; const TypeSystemTypeEntry *typeSystemTypeEntry() const; + // cf AbstractMetaClass::targetLangEnclosingClass() + const TypeEntry *targetLangEnclosingEntry() const; bool isPrimitive() const { @@ -619,22 +614,10 @@ public: { return m_type == FlagsType; } - bool isInterface() const - { - return m_type == InterfaceType; - } bool isObject() const { return m_type == ObjectType; } - bool isString() const - { - return m_type == StringType; - } - bool isChar() const - { - return m_type == CharType; - } bool isNamespace() const { return m_type == NamespaceType; @@ -647,14 +630,6 @@ public: { return m_type == SmartPointerType; } - bool isVariant() const - { - return m_type == VariantType; - } - bool isJObjectWrapper() const - { - return m_type == JObjectWrapperType; - } bool isArray() const { return m_type == ArrayType; @@ -671,18 +646,10 @@ public: { return m_type == VarargsType; } - bool isThread() const - { - return m_type == ThreadType; - } bool isCustom() const { return m_type == CustomType; } - bool isBasicValue() const - { - return m_type == BasicValueType; - } bool isTypeSystem() const { return m_type == TypeSystemType; @@ -708,6 +675,8 @@ public: // The type's name in C++, fully qualified QString name() const { return m_name; } + // C++ excluding inline namespaces + QString shortName() const; // Name as specified in XML QString entryName() const { return m_entryName; } @@ -766,11 +735,6 @@ public: QString qualifiedTargetLangName() const; - virtual InterfaceTypeEntry *designatedInterface() const - { - return nullptr; - } - void setCustomConstructor(const CustomFunction &func) { m_customConstructor = func; @@ -798,11 +762,6 @@ public: return false; } - virtual bool isNativeIdBased() const - { - return false; - } - CodeSnipList codeSnips() const; void setCodeSnips(const CodeSnipList &codeSnips) { @@ -896,7 +855,8 @@ protected: private: const TypeEntry *m_parent; - QString m_name; // fully qualified + QString m_name; // C++ fully qualified + mutable QString m_cachedShortName; // C++ excluding inline namespaces QString m_entryName; QString m_targetLangPackage; mutable QString m_cachedTargetLangName; // "Foo.Bar" @@ -1489,6 +1449,8 @@ private: class SmartPointerTypeEntry : public ComplexTypeEntry { public: + using Instantiations = QVector<const TypeEntry *>; + explicit SmartPointerTypeEntry(const QString &entryName, const QString &getterName, const QString &smartPointerType, @@ -1508,6 +1470,13 @@ public: TypeEntry *clone() const override; + Instantiations instantiations() const { return m_instantiations; } + void setInstantiations(const Instantiations &i) { m_instantiations = i; } + bool matchesInstantiation(const TypeEntry *e) const; + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const override; +#endif protected: SmartPointerTypeEntry(const SmartPointerTypeEntry &); @@ -1515,6 +1484,7 @@ private: QString m_getterName; QString m_smartPointerType; QString m_refCountMethodName; + Instantiations m_instantiations; }; class NamespaceTypeEntry : public ComplexTypeEntry @@ -1535,6 +1505,15 @@ public: bool matchesFile(const QString &needle) const; + bool isVisible() const; + void setVisibility(TypeSystem::Visibility v) { m_visibility = v; } + + // C++ 11 inline namespace, from code model + bool isInlineNamespace() const { return m_inlineNamespace; } + void setInlineNamespace(bool i) { m_inlineNamespace = i; } + + static bool isVisibleScope(const TypeEntry *e); + #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; #endif @@ -1545,7 +1524,9 @@ protected: private: QRegularExpression m_filePattern; const NamespaceTypeEntry *m_extends = nullptr; + TypeSystem::Visibility m_visibility = TypeSystem::Visibility::Auto; bool m_hasPattern = false; + bool m_inlineNamespace = false; }; class ValueTypeEntry : public ComplexTypeEntry @@ -1556,8 +1537,6 @@ public: bool isValue() const override; - bool isNativeIdBased() const override; - TypeEntry *clone() const override; protected: @@ -1566,39 +1545,6 @@ protected: ValueTypeEntry(const ValueTypeEntry &); }; -class InterfaceTypeEntry : public ComplexTypeEntry -{ -public: - explicit InterfaceTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent); - - static QString interfaceName(const QString &name) - { - return name + QLatin1String("Interface"); - } - - ObjectTypeEntry *origin() const - { - return m_origin; - } - void setOrigin(ObjectTypeEntry *origin) - { - m_origin = origin; - } - - bool isNativeIdBased() const override; - QString qualifiedCppName() const override; - - TypeEntry *clone() const override; - -protected: - InterfaceTypeEntry(const InterfaceTypeEntry &); - -private: - ObjectTypeEntry *m_origin = nullptr; -}; - - class FunctionTypeEntry : public TypeEntry { public: @@ -1635,21 +1581,10 @@ public: explicit ObjectTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent); - InterfaceTypeEntry *designatedInterface() const override; - void setDesignatedInterface(InterfaceTypeEntry *entry) - { - m_interface = entry; - } - - bool isNativeIdBased() const override; - TypeEntry *clone() const override; protected: ObjectTypeEntry(const ObjectTypeEntry &); - -private: - InterfaceTypeEntry *m_interface = nullptr; }; struct TypeRejection diff --git a/sources/shiboken2/ApiExtractor/typesystem_enums.h b/sources/shiboken2/ApiExtractor/typesystem_enums.h index df83429d0..120c9417f 100644 --- a/sources/shiboken2/ApiExtractor/typesystem_enums.h +++ b/sources/shiboken2/ApiExtractor/typesystem_enums.h @@ -98,6 +98,13 @@ enum class ExceptionHandling { On }; +enum Visibility { // For namespaces + Unspecified, + Visible, + Invisible, + Auto +}; + } // namespace TypeSystem #endif // TYPESYSTEM_ENUMS_H diff --git a/sources/shiboken2/ApiExtractor/typesystem_typedefs.h b/sources/shiboken2/ApiExtractor/typesystem_typedefs.h index fd702793e..73f92b294 100644 --- a/sources/shiboken2/ApiExtractor/typesystem_typedefs.h +++ b/sources/shiboken2/ApiExtractor/typesystem_typedefs.h @@ -40,6 +40,7 @@ class DocModification; struct AddedFunction; struct FieldModification; struct FunctionModification; +class TypeEntry; using AddedFunctionPtr = QSharedPointer<AddedFunction>; using AddedFunctionList = QVector<AddedFunctionPtr>; @@ -47,5 +48,6 @@ using CodeSnipList = QVector<CodeSnip>; using DocModificationList = QVector<DocModification>; using FieldModificationList = QVector<FieldModification>; using FunctionModificationList = QVector<FunctionModification>; +using TypeEntries = QVector<const TypeEntry *>; #endif // TYPESYSTEM_TYPEDEFS_H diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.cpp b/sources/shiboken2/ApiExtractor/typesystemparser.cpp index 0bb56f0fe..55b079edd 100644 --- a/sources/shiboken2/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken2/ApiExtractor/typesystemparser.cpp @@ -62,6 +62,7 @@ static inline QString deleteInMainThreadAttribute() { return QStringLiteral("del static inline QString deprecatedAttribute() { return QStringLiteral("deprecated"); } static inline QString exceptionHandlingAttribute() { return QStringLiteral("exception-handling"); } static inline QString extensibleAttribute() { return QStringLiteral("extensible"); } +static inline QString fileNameAttribute() { return QStringLiteral("file-name"); } static inline QString flagsAttribute() { return QStringLiteral("flags"); } static inline QString forceAbstractAttribute() { return QStringLiteral("force-abstract"); } static inline QString forceIntegerAttribute() { return QStringLiteral("force-integer"); } @@ -94,6 +95,7 @@ static inline QString sourceAttribute() { return QStringLiteral("source"); } static inline QString streamAttribute() { return QStringLiteral("stream"); } static inline QString xPathAttribute() { return QStringLiteral("xpath"); } static inline QString virtualSlotAttribute() { return QStringLiteral("virtual-slot"); } +static inline QString visibleAttribute() { return QStringLiteral("visible"); } static inline QString enumIdentifiedByValueAttribute() { return QStringLiteral("identified-by-value"); } static inline QString noAttributeValue() { return QStringLiteral("no"); } @@ -382,6 +384,7 @@ ENUM_LOOKUP_BEGIN(StackElement::ElementType, Qt::CaseInsensitive, {u"replace-type", StackElement::ReplaceType}, {u"smart-pointer-type", StackElement::SmartPointerTypeEntry}, {u"suppress-warning", StackElement::SuppressedWarning}, + {u"system-include", StackElement::SystemInclude}, {u"target-to-native", StackElement::TargetToNative}, {u"template", StackElement::Template}, {u"typedef-type", StackElement::TypedefTypeEntry}, @@ -390,6 +393,17 @@ ENUM_LOOKUP_BEGIN(StackElement::ElementType, Qt::CaseInsensitive, }; ENUM_LOOKUP_BINARY_SEARCH() +ENUM_LOOKUP_BEGIN(TypeSystem::Visibility, Qt::CaseSensitive, + visibilityFromAttribute, TypeSystem::Visibility::Unspecified) +{ + {u"no", TypeSystem::Visibility::Invisible}, + {u"false", TypeSystem::Visibility::Invisible}, + {u"auto", TypeSystem::Visibility::Auto}, + {u"yes", TypeSystem::Visibility::Visible}, + {u"true", TypeSystem::Visibility::Visible}, +}; +ENUM_LOOKUP_LINEAR_SEARCH() + static int indexOfAttribute(const QXmlStreamAttributes &atts, QStringView name) { @@ -636,6 +650,14 @@ bool TypeSystemParser::parse(QXmlStreamReader &reader) { m_error.clear(); m_currentPath.clear(); + m_smartPointerInstantiations.clear(); + const bool result = parseXml(reader) && setupSmartPointerInstantiations(); + m_smartPointerInstantiations.clear(); + return result; +} + +bool TypeSystemParser::parseXml(QXmlStreamReader &reader) +{ const QString fileName = readerFileName(reader); if (!fileName.isEmpty()) m_currentPath = QFileInfo(fileName).absolutePath(); @@ -679,6 +701,62 @@ bool TypeSystemParser::parse(QXmlStreamReader &reader) return true; } +// Split a type list potentially with template types +// "A<B,C>,D" -> ("A<B,C>", "D") +static QStringList splitTypeList(const QString &s) +{ + QStringList result; + int templateDepth = 0; + int lastPos = 0; + const int size = s.size(); + for (int i = 0; i < size; ++i) { + switch (s.at(i).toLatin1()) { + case '<': + ++templateDepth; + break; + case '>': + --templateDepth; + break; + case ',': + if (templateDepth == 0) { + result.append(s.mid(lastPos, i - lastPos).trimmed()); + lastPos = i + 1; + } + break; + } + } + if (lastPos < size) + result.append(s.mid(lastPos, size - lastPos).trimmed()); + return result; +} + +bool TypeSystemParser::setupSmartPointerInstantiations() +{ + for (auto it = m_smartPointerInstantiations.cbegin(), + end = m_smartPointerInstantiations.cend(); it != end; ++it) { + auto smartPointerEntry = it.key(); + const auto instantiationNames = splitTypeList(it.value()); + SmartPointerTypeEntry::Instantiations instantiations; + instantiations.reserve(instantiationNames.size()); + for (const auto &instantiationName : instantiationNames) { + const auto types = m_database->findCppTypes(instantiationName); + if (types.isEmpty()) { + m_error = + msgCannotFindTypeEntryForSmartPointer(instantiationName, + smartPointerEntry->name()); + return false; + } + if (types.size() > 1) { + m_error = msgAmbiguousTypesFound(instantiationName, types); + return false; + } + instantiations.append(types.constFirst()); + } + smartPointerEntry->setInstantiations(instantiations); + } + return true; +} + bool TypeSystemParser::endElement(const QStringRef &localName) { if (m_ignoreDepth) { @@ -726,11 +804,6 @@ bool TypeSystemParser::endElement(const QStringRef &localName) centry->setFieldModifications(m_contextStack.top()->fieldMods); centry->setCodeSnips(m_contextStack.top()->codeSnips); centry->setDocModification(m_contextStack.top()->docModifications); - - if (centry->designatedInterface()) { - centry->designatedInterface()->setCodeSnips(m_contextStack.top()->codeSnips); - centry->designatedInterface()->setFunctionModifications(m_contextStack.top()->functionMods); - } } break; case StackElement::AddFunction: { @@ -813,7 +886,7 @@ bool TypeSystemParser::endElement(const QStringRef &localName) break; default: break; // nada - }; + } break; default: break; @@ -889,7 +962,7 @@ bool TypeSystemParser::characters(const String &ch) break; default: Q_ASSERT(false); - }; + } return true; } } @@ -1121,6 +1194,7 @@ SmartPointerTypeEntry * QString smartPointerType; QString getter; QString refCountMethodName; + QString instantiations; for (int i = attributes->size() - 1; i >= 0; --i) { const QStringRef name = attributes->at(i).qualifiedName(); if (name == QLatin1String("type")) { @@ -1129,6 +1203,8 @@ SmartPointerTypeEntry * getter = attributes->takeAt(i).value().toString(); } else if (name == QLatin1String("ref-count-method")) { refCountMethodName = attributes->takeAt(i).value().toString(); + } else if (name == QLatin1String("instantiations")) { + instantiations = attributes->takeAt(i).value().toString(); } } @@ -1163,6 +1239,7 @@ SmartPointerTypeEntry * auto *type = new SmartPointerTypeEntry(name, getter, smartPointerType, refCountMethodName, since, currentParentTypeEntry()); applyCommonAttributes(type, attributes); + m_smartPointerInstantiations.insert(type, instantiations); return type; } @@ -1262,40 +1339,6 @@ EnumTypeEntry * return entry; } -ObjectTypeEntry * - TypeSystemParser::parseInterfaceTypeEntry(const QXmlStreamReader &, - const QString &name, const QVersionNumber &since, - QXmlStreamAttributes *attributes) -{ - if (!checkRootElement()) - return nullptr; - auto *otype = new ObjectTypeEntry(name, since, currentParentTypeEntry()); - applyCommonAttributes(otype, attributes); - QString targetLangName = name; - bool generate = true; - for (int i = attributes->size() - 1; i >= 0; --i) { - const QStringRef name = attributes->at(i).qualifiedName(); - if (name == targetLangNameAttribute()) { - targetLangName = attributes->takeAt(i).value().toString(); - } else if (name == generateAttribute()) { - generate = convertBoolean(attributes->takeAt(i).value(), - generateAttribute(), true); - } - } - - auto itype = new InterfaceTypeEntry(InterfaceTypeEntry::interfaceName(targetLangName), - since, currentParentTypeEntry()); - itype->setTargetLangName(targetLangName); - - if (generate) - itype->setCodeGeneration(m_generate); - else - itype->setCodeGeneration(TypeEntry::GenerateForSubclass); - - otype->setDesignatedInterface(itype); - itype->setOrigin(otype); - return otype; -} NamespaceTypeEntry * TypeSystemParser::parseNamespaceTypeEntry(const QXmlStreamReader &reader, @@ -1305,8 +1348,8 @@ NamespaceTypeEntry * if (!checkRootElement()) return nullptr; QScopedPointer<NamespaceTypeEntry> result(new NamespaceTypeEntry(name, since, currentParentTypeEntry())); + auto visibility = TypeSystem::Visibility::Unspecified; applyCommonAttributes(result.data(), attributes); - applyComplexTypeAttributes(reader, result.data(), attributes); for (int i = attributes->size() - 1; i >= 0; --i) { const QStringRef attributeName = attributes->at(i).qualifiedName(); if (attributeName == QLatin1String("files")) { @@ -1329,9 +1372,24 @@ NamespaceTypeEntry * return nullptr; } result->setExtends(*extendsIt); + } else if (attributeName == visibleAttribute()) { + const auto attribute = attributes->takeAt(i); + visibility = visibilityFromAttribute(attribute.value()); + if (visibility == TypeSystem::Visibility::Unspecified) { + qCWarning(lcShiboken, "%s", + qPrintable(msgInvalidAttributeValue(attribute))); + } + } else if (attributeName == generateAttribute()) { + if (!convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true)) + visibility = TypeSystem::Visibility::Invisible; } } + if (visibility != TypeSystem::Visibility::Unspecified) + result->setVisibility(visibility); + // Handle legacy "generate" before the common handling + applyComplexTypeAttributes(reader, result.data(), attributes); + if (result->extends() && !result->hasPattern()) { m_error = msgExtendingNamespaceRequiresPattern(name); return nullptr; @@ -1493,9 +1551,6 @@ void TypeSystemParser::applyComplexTypeAttributes(const QXmlStreamReader &reader if (ctype->type() != TypeEntry::ContainerType) ctype->setTargetLangPackage(package); - if (InterfaceTypeEntry *di = ctype->designatedInterface()) - di->setTargetLangPackage(package); - if (generate) ctype->setCodeGeneration(m_generate); else @@ -2510,7 +2565,7 @@ bool TypeSystemParser::parseInclude(const QXmlStreamReader &, QString location; for (int i = attributes->size() - 1; i >= 0; --i) { const QStringRef name = attributes->at(i).qualifiedName(); - if (name == QLatin1String("file-name")) + if (name == fileNameAttribute()) fileName = attributes->takeAt(i).value().toString(); else if (name == locationAttribute()) location = attributes->takeAt(i).value().toString(); @@ -2531,10 +2586,18 @@ bool TypeSystemParser::parseInclude(const QXmlStreamReader &, m_error = QLatin1String("Only supported parent tags are primitive-type, complex types or extra-includes"); return false; } - if (InterfaceTypeEntry *di = entry->designatedInterface()) { - di->setInclude(entry->include()); - di->setExtraIncludes(entry->extraIncludes()); + return true; +} + +bool TypeSystemParser::parseSystemInclude(const QXmlStreamReader &, + QXmlStreamAttributes *attributes) +{ + const int index = indexOfAttribute(*attributes, fileNameAttribute()); + if (index == -1) { + m_error = msgMissingAttribute(fileNameAttribute()); + return false; } + TypeDatabase::instance()->addSystemInclude(attributes->takeAt(index).value().toString()); return true; } @@ -2772,14 +2835,6 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) element->entry = m_currentEnum; break; - case StackElement::InterfaceTypeEntry: - if (ObjectTypeEntry *oe = parseInterfaceTypeEntry(reader, name, versionRange.since, &attributes)) { - applyComplexTypeAttributes(reader, oe, &attributes); - element->entry = oe; - } else { - return false; - } - break; case StackElement::ValueTypeEntry: if (ValueTypeEntry *ve = parseValueTypeEntry(reader, name, versionRange.since, &attributes)) { applyComplexTypeAttributes(reader, ve, &attributes); @@ -2795,6 +2850,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) return false; break; case StackElement::ObjectTypeEntry: + case StackElement::InterfaceTypeEntry: if (!checkRootElement()) return false; element->entry = new ObjectTypeEntry(name, versionRange.since, currentParentTypeEntry()); @@ -2816,7 +2872,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) break; default: Q_ASSERT(false); - }; + } if (element->entry) { if (!m_database->addType(element->entry, &m_error)) @@ -2839,6 +2895,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) || element->type == StackElement::LoadTypesystem || element->type == StackElement::InjectCode || element->type == StackElement::ExtraIncludes + || element->type == StackElement::SystemInclude || element->type == StackElement::ConversionRule || element->type == StackElement::AddFunction || element->type == StackElement::Template; @@ -2991,6 +3048,10 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) if (!addRejection(m_database, &attributes, &m_error)) return false; break; + case StackElement::SystemInclude: + if (!parseSystemInclude(reader, &attributes)) + return false; + break; case StackElement::Template: { const int nameIndex = indexOfAttribute(attributes, nameAttribute()); if (nameIndex == -1) { diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.h b/sources/shiboken2/ApiExtractor/typesystemparser.h index d3ea54fc6..b4be2765c 100644 --- a/sources/shiboken2/ApiExtractor/typesystemparser.h +++ b/sources/shiboken2/ApiExtractor/typesystemparser.h @@ -31,6 +31,7 @@ #include "typesystem.h" #include <QtCore/QStack> +#include <QtCore/QHash> #include <QtCore/QScopedPointer> QT_FORWARD_DECLARE_CLASS(QXmlStreamAttributes) @@ -86,6 +87,7 @@ class StackElement NativeToTarget = 0x1100, TargetToNative = 0x1200, AddConversion = 0x1300, + SystemInclude = 0x1400, SimpleMask = 0x3f00, // Code snip tags (0x1000, 0x2000, ... , 0xf000) @@ -151,6 +153,8 @@ public: QString errorString() const { return m_error; } private: + bool parseXml(QXmlStreamReader &reader); + bool setupSmartPointerInstantiations(); bool startElement(const QXmlStreamReader &reader); SmartPointerTypeEntry *parseSmartPointerEntry(const QXmlStreamReader &, const QString &name, @@ -184,9 +188,6 @@ private: const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes); - ObjectTypeEntry * - parseInterfaceTypeEntry(const QXmlStreamReader &, const QString &name, - const QVersionNumber &since, QXmlStreamAttributes *); ValueTypeEntry * parseValueTypeEntry(const QXmlStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *); @@ -247,6 +248,7 @@ private: StackElement* element, QXmlStreamAttributes *); bool parseInclude(const QXmlStreamReader &, const StackElement &topElement, TypeEntry *entry, QXmlStreamAttributes *); + bool parseSystemInclude(const QXmlStreamReader &, QXmlStreamAttributes *); TemplateInstance *parseTemplateInstanceEnum(const QXmlStreamReader &, const StackElement &topElement, QXmlStreamAttributes *); @@ -271,6 +273,7 @@ private: QString m_currentSignature; QString m_currentPath; QScopedPointer<TypeSystemEntityResolver> m_entityResolver; + QHash<SmartPointerTypeEntry *, QString> m_smartPointerInstantiations; }; #endif // TYPESYSTEMPARSER_H |