diff options
Diffstat (limited to 'sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp')
-rw-r--r-- | sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp | 136 |
1 files changed, 101 insertions, 35 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp index ce361245c..9807e1ea6 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp @@ -531,13 +531,22 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, ReportHandler::startProgress("Generated enum model (" + QByteArray::number(enums.size()) + ")."); for (const EnumModelItem &item : enums) { - auto metaEnum = traverseEnum(item, nullptr, QSet<QString>()); + auto metaEnum = traverseEnum(item, nullptr); if (metaEnum.has_value()) { if (metaEnum->typeEntry()->generateCode()) m_globalEnums << metaEnum.value(); } } + const auto &globalTypeDefs = dom->typeDefs(); + for (const auto &typeDef : globalTypeDefs) { + if (typeDef->underlyingTypeCategory() == TypeCategory::Enum) { + const auto metaEnum = traverseTypedefedEnum(dom, typeDef, {}); + if (metaEnum.has_value()) + m_globalEnums.append(metaEnum.value()); + } + } + const auto &namespaceTypeValues = dom->namespaces(); ReportHandler::startProgress("Generated namespace model (" + QByteArray::number(namespaceTypeValues.size()) + ")."); @@ -765,7 +774,7 @@ AbstractMetaClassPtr AbstractMetaBuilderPrivate::traverseNamespace(const FileModelItem &dom, const NamespaceModelItem &namespaceItem) { - QString namespaceName = currentScope()->qualifiedName().join(u"::"_s); + QString namespaceName = currentScope()->qualifiedNameString(); if (!namespaceName.isEmpty()) namespaceName.append(u"::"_s); namespaceName.append(namespaceItem->name()); @@ -809,7 +818,7 @@ AbstractMetaClassPtr m_itemToClass.insert(namespaceItem.get(), metaClass); } - traverseEnums(namespaceItem, metaClass, namespaceItem->enumsDeclarations()); + traverseEnums(namespaceItem, metaClass); pushScope(namespaceItem); @@ -827,11 +836,20 @@ AbstractMetaClassPtr // specific typedefs to be used as classes. const TypeDefList typeDefs = namespaceItem->typeDefs(); for (const TypeDefModelItem &typeDef : typeDefs) { - const auto cls = traverseTypeDef(dom, typeDef, metaClass); - if (cls) { - metaClass->addInnerClass(cls); - cls->setEnclosingClass(metaClass); - addAbstractMetaClass(cls, typeDef.get()); + switch (typeDef->underlyingTypeCategory()) { + case TypeCategory::Enum: { + const auto metaEnum = traverseTypedefedEnum(dom, typeDef, metaClass); + if (metaEnum.has_value()) + metaClass->addEnum(metaEnum.value()); + } + break; + default: + if (const auto cls = traverseTypeDef(dom, typeDef, metaClass)) { + metaClass->addInnerClass(cls); + cls->setEnclosingClass(metaClass); + addAbstractMetaClass(cls, typeDef.get()); + } + break; } } @@ -856,16 +874,15 @@ AbstractMetaClassPtr std::optional<AbstractMetaEnum> AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &enumItem, - const AbstractMetaClassPtr &enclosing, - const QSet<QString> &enumsDeclarations) + const AbstractMetaClassPtr &enclosing) { - QString qualifiedName = enumItem->qualifiedName().join(u"::"_s); + QString qualifiedName = enumItem->qualifiedNameString(); TypeEntryPtr typeEntry; - const auto enclosingTypeEntry = enclosing ? enclosing->typeEntry() : TypeEntryCPtr{}; if (enumItem->accessPolicy() == Access::Private) { + Q_ASSERT(enclosing); typeEntry = std::make_shared<EnumTypeEntry>(enumItem->qualifiedName().constLast(), - QVersionNumber(0, 0), enclosingTypeEntry); + QVersionNumber(0, 0), enclosing->typeEntry()); TypeDatabase::instance()->addType(typeEntry); } else if (enumItem->enumKind() != AnonymousEnum) { typeEntry = TypeDatabase::instance()->findType(qualifiedName); @@ -881,12 +898,17 @@ std::optional<AbstractMetaEnum> break; } } + return createMetaEnum(enumItem, qualifiedName, typeEntry, enclosing); +} - QString enumName = enumItem->name(); - - QString className; - if (enclosingTypeEntry) - className = enclosingTypeEntry->qualifiedCppName(); +std::optional<AbstractMetaEnum> + AbstractMetaBuilderPrivate::createMetaEnum(const EnumModelItem &enumItem, + const QString &qualifiedName, + const TypeEntryPtr &typeEntry, + const AbstractMetaClassPtr &enclosing) +{ + const QString enumName = enumItem->name(); + const QString className = enclosing ? enclosing->typeEntry()->qualifiedCppName() : QString{}; QString rejectReason; if (TypeDatabase::instance()->isEnumRejected(className, enumName, &rejectReason)) { @@ -922,10 +944,6 @@ std::optional<AbstractMetaEnum> metaEnum.setDeprecated(enumItem->isDeprecated()); metaEnum.setUnderlyingType(enumItem->underlyingType()); metaEnum.setSigned(enumItem->isSigned()); - if (enumsDeclarations.contains(qualifiedName) - || enumsDeclarations.contains(enumName)) { - metaEnum.setHasQEnumsDeclaration(true); - } auto enumTypeEntry = std::static_pointer_cast<EnumTypeEntry>(typeEntry); metaEnum.setTypeEntry(enumTypeEntry); @@ -972,6 +990,49 @@ std::optional<AbstractMetaEnum> return metaEnum; } +// Add typedef'ed enumerations ("Using MyEnum=SomeNamespace::MyEnum") for which +// a type entry exists. +std::optional<AbstractMetaEnum> + AbstractMetaBuilderPrivate::traverseTypedefedEnum(const FileModelItem &dom, + const TypeDefModelItem &typeDefItem, + const AbstractMetaClassPtr &enclosing) +{ + if (enclosing && typeDefItem->accessPolicy() != Access::Public) + return std::nullopt; // Only for global/public enums typedef'ed into classes/namespaces + auto modelItem = CodeModel::findItem(typeDefItem->type().qualifiedName(), dom); + if (!modelItem || modelItem->kind() != _CodeModelItem::Kind_Enum) + return std::nullopt; + auto enumItem = std::static_pointer_cast<_EnumModelItem>(modelItem); + if (enumItem->accessPolicy() != Access::Public) + return std::nullopt; + // Name in class + QString qualifiedName = enclosing + ? enclosing->qualifiedCppName() + "::"_L1 + typeDefItem->name() : typeDefItem->name(); + auto targetTypeEntry = TypeDatabase::instance()->findType(qualifiedName); + if (!targetTypeEntry || !targetTypeEntry->isEnum() || !targetTypeEntry->generateCode()) + return std::nullopt; + auto targetEnumTypeEntry = std::static_pointer_cast<EnumTypeEntry>(targetTypeEntry); + auto sourceTypeEntry = TypeDatabase::instance()->findType(enumItem->qualifiedNameString()); + if (!sourceTypeEntry || !sourceTypeEntry->isEnum()) + return std::nullopt; + + auto sourceEnumTypeEntry = std::static_pointer_cast<EnumTypeEntry>(sourceTypeEntry); + if (sourceEnumTypeEntry == targetEnumTypeEntry) // Reject "typedef Enum1 { V1 } Enum1;" + return std::nullopt; + + const QString message = "Enum \""_L1 + qualifiedName + "\" is an alias to \""_L1 + + enumItem->qualifiedNameString() + "\"."_L1; + ReportHandler::addGeneralMessage(message); + auto result = createMetaEnum(enumItem, qualifiedName, targetTypeEntry, enclosing); + if (result.has_value()) { + targetEnumTypeEntry->setAliasMode(EnumTypeEntry::AliasTarget); + targetEnumTypeEntry->setAliasTypeEntry(sourceEnumTypeEntry); + sourceEnumTypeEntry->setAliasMode(EnumTypeEntry::AliasSource); + sourceEnumTypeEntry->setAliasTypeEntry(targetEnumTypeEntry); + } + return result; +} + AbstractMetaClassPtr AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &dom, const TypeDefModelItem &typeDef, @@ -1177,7 +1238,7 @@ AbstractMetaClassPtr AbstractMetaBuilderPrivate::traverseClass(const FileModelIt parseQ_Properties(metaClass, classItem->propertyDeclarations()); - traverseEnums(classItem, metaClass, classItem->enumsDeclarations()); + traverseEnums(classItem, metaClass); // Inner classes { @@ -1197,10 +1258,20 @@ AbstractMetaClassPtr AbstractMetaBuilderPrivate::traverseClass(const FileModelIt // specific typedefs to be used as classes. const TypeDefList typeDefs = classItem->typeDefs(); for (const TypeDefModelItem &typeDef : typeDefs) { - const auto cls = traverseTypeDef(dom, typeDef, metaClass); - if (cls) { - cls->setEnclosingClass(metaClass); - addAbstractMetaClass(cls, typeDef.get()); + if (typeDef->accessPolicy() != Access::Private) { + switch (typeDef->underlyingTypeCategory()) { + case TypeCategory::Enum: { + const auto metaEnum = traverseTypedefedEnum(dom, typeDef, metaClass); + if (metaEnum.has_value()) + metaClass->addEnum(metaEnum.value()); + } + break; + default: + if (const auto cls = traverseTypeDef(dom, typeDef, metaClass)) { + cls->setEnclosingClass(metaClass); + addAbstractMetaClass(cls, typeDef.get()); + } + } } } @@ -1648,13 +1719,11 @@ bool AbstractMetaBuilderPrivate::setupInheritance(const AbstractMetaClassPtr &me } void AbstractMetaBuilderPrivate::traverseEnums(const ScopeModelItem &scopeItem, - const AbstractMetaClassPtr &metaClass, - const QStringList &enumsDeclarations) + const AbstractMetaClassPtr &metaClass) { const EnumList &enums = scopeItem->enums(); - const QSet<QString> enumsDeclarationSet(enumsDeclarations.cbegin(), enumsDeclarations.cend()); for (const EnumModelItem &enumItem : enums) { - auto metaEnum = traverseEnum(enumItem, metaClass, enumsDeclarationSet); + auto metaEnum = traverseEnum(enumItem, metaClass); if (metaEnum.has_value()) { metaClass->addEnum(metaEnum.value()); } @@ -1713,10 +1782,7 @@ AbstractMetaFunctionPtr const auto &args = addedFunc->arguments(); - qsizetype argCount = args.size(); - // Check "foo(void)" - if (argCount == 1 && args.constFirst().typeInfo.isVoid()) - argCount = 0; + const qsizetype argCount = args.size(); for (qsizetype i = 0; i < argCount; ++i) { const AddedFunction::Argument &arg = args.at(i); auto type = translateType(arg.typeInfo, metaClass, {}, errorMessage); |