aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder.h2
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp19
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel.cpp93
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel.h23
4 files changed, 114 insertions, 23 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder.h
index 022c29cdd..82503ae44 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.h
@@ -109,8 +109,6 @@ public:
static QString resolveScopePrefix(const AbstractMetaClass *scope,
QStringView value);
- static QString searchForEnumScope(const AbstractMetaClass *metaClass,
- QStringView value);
// For testing purposes
QString fixEnumDefault(const AbstractMetaType &type, const QString &expr) const;
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp
index 068c67241..f153d0594 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp
@@ -79,25 +79,6 @@ static QString resolveEnumValueScopePrefix(const AbstractMetaEnum &metaEnum,
return resolveScopePrefixHelper(parts, value);
}
-// Return the scope for fully qualifying an enumeration value from
-// an unknown enum in the class scope including trailing "::".
-QString AbstractMetaBuilder::searchForEnumScope(const AbstractMetaClass *metaClass,
- QStringView value)
-{
- if (!metaClass)
- return QString();
- for (const AbstractMetaEnum &metaEnum : metaClass->enums()) {
- auto v = metaEnum.findEnumValue(value);
- if (v.has_value())
- return resolveEnumValueScopePrefix(metaEnum, value);
- }
- // PYSIDE-331: We need to also search the base classes.
- QString ret = searchForEnumScope(metaClass->enclosingClass(), value);
- if (ret.isEmpty())
- ret = searchForEnumScope(metaClass->baseClass(), value);
- return ret;
-}
-
static bool isQualifiedCppIdentifier(QStringView e)
{
return !e.isEmpty() && e.at(0).isLetter()
diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp
index d1f3e552b..ac7445c13 100644
--- a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp
+++ b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp
@@ -700,6 +700,90 @@ EnumModelItem _ScopeModelItem::findEnum(const QString &name) const
return findModelItem(m_enums, name);
}
+_ScopeModelItem::FindEnumByValueReturn
+ _ScopeModelItem::findEnumByValueHelper(QStringView fullValue,
+ QStringView enumValue) const
+{
+ const bool unqualified = fullValue.size() == enumValue.size();
+ QString scopePrefix = scope().join(u"::");
+ if (!scopePrefix.isEmpty())
+ scopePrefix += u"::"_qs;
+ scopePrefix += name() + u"::"_qs;
+
+ for (const auto &e : m_enums) {
+ const auto index = e->indexOfValue(enumValue);
+ if (index != -1) {
+ QString fullyQualifiedName = scopePrefix;
+ if (e->enumKind() != AnonymousEnum)
+ fullyQualifiedName += e->name() + u"::"_qs;
+ fullyQualifiedName += e->enumerators().at(index)->name();
+ if (unqualified || fullyQualifiedName.endsWith(fullValue))
+ return {e, fullyQualifiedName};
+ // For standard enums, check the name without enum name
+ if (e->enumKind() == CEnum) {
+ const QString qualifiedName =
+ scopePrefix + e->enumerators().at(index)->name();
+ if (qualifiedName.endsWith(fullValue))
+ return {e, fullyQualifiedName};
+ }
+ }
+ }
+
+ return {};
+}
+
+// Helper to recursively find the scope of an enum value
+_ScopeModelItem::FindEnumByValueReturn
+ _ScopeModelItem::findEnumByValueRecursion(const _ScopeModelItem *scope,
+ QStringView fullValue,
+ QStringView enumValue,
+ bool searchSiblingNamespaces)
+{
+ if (const auto e = scope->findEnumByValueHelper(fullValue, enumValue))
+ return e;
+
+ if (auto *enclosingScope = scope->enclosingScope()) {
+ // The enclosing scope may have several sibling namespaces of that name.
+ if (searchSiblingNamespaces && scope->kind() == Kind_Namespace) {
+ if (auto *enclosingNamespace = dynamic_cast<const _NamespaceModelItem *>(enclosingScope)) {
+ for (const auto &sibling : enclosingNamespace->namespaces()) {
+ if (sibling.data() != scope && sibling->name() == scope->name()) {
+ if (const auto e = findEnumByValueRecursion(sibling.data(),
+ fullValue, enumValue, false)) {
+ return e;
+ }
+ }
+ }
+ }
+ }
+
+ if (const auto e = findEnumByValueRecursion(enclosingScope, fullValue, enumValue))
+ return e;
+ }
+
+ // PYSIDE-331: We need to also search the base classes.
+ if (auto *classItem = dynamic_cast<const _ClassModelItem *>(scope)) {
+ for (const auto &base : classItem->baseClasses()) {
+ if (!base.klass.isNull()) {
+ auto *c = base.klass.data();
+ if (const auto e = findEnumByValueRecursion(c, fullValue, enumValue))
+ return e;
+ }
+ }
+ }
+
+ return {};
+}
+
+_ScopeModelItem::FindEnumByValueReturn
+ _ScopeModelItem::findEnumByValue(QStringView value) const
+{
+ const auto lastQualifier = value.lastIndexOf(u"::");
+ const auto enumValue = lastQualifier == -1
+ ? value : value.mid(lastQualifier + 2);
+ return findEnumByValueRecursion(this, value, enumValue);
+}
+
FunctionList _ScopeModelItem::findFunctions(const QString &name) const
{
FunctionList result;
@@ -1185,6 +1269,15 @@ void _EnumModelItem::addEnumerator(const EnumeratorModelItem &item)
m_enumerators.append(item);
}
+qsizetype _EnumModelItem::indexOfValue(QStringView value) const
+{
+ for (qsizetype i = 0, size = m_enumerators.size(); i < size; ++i) {
+ if (m_enumerators.at(i)->name() == value)
+ return i;
+ }
+ return -1;
+}
+
bool _EnumModelItem::isSigned() const
{
return m_signed;
diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.h b/sources/shiboken6/ApiExtractor/parser/codemodel.h
index db3675d17..38652aa7e 100644
--- a/sources/shiboken6/ApiExtractor/parser/codemodel.h
+++ b/sources/shiboken6/ApiExtractor/parser/codemodel.h
@@ -205,7 +205,7 @@ public:
~_ScopeModelItem();
ClassList classes() const { return m_classes; }
- EnumList enums() const { return m_enums; }
+ const EnumList &enums() const { return m_enums; }
inline const FunctionList &functions() const { return m_functions; }
TypeDefList typeDefs() const { return m_typeDefs; }
TemplateTypeAliasList templateTypeAliases() const { return m_templateTypeAliases; }
@@ -220,6 +220,16 @@ public:
ClassModelItem findClass(const QString &name) const;
EnumModelItem findEnum(const QString &name) const;
+
+ struct FindEnumByValueReturn
+ {
+ operator bool() const { return !item.isNull(); }
+
+ EnumModelItem item;
+ QString qualifiedName;
+ };
+ FindEnumByValueReturn findEnumByValue(QStringView value) const;
+
FunctionList findFunctions(const QString &name) const;
TypeDefModelItem findTypeDef(const QString &name) const;
TemplateTypeAliasModelItem findTemplateTypeAlias(const QString &name) const;
@@ -252,6 +262,13 @@ protected:
private:
qsizetype indexOfEnum(const QString &name) const;
+ FindEnumByValueReturn findEnumByValueHelper(QStringView fullValue,
+ QStringView value) const;
+ static FindEnumByValueReturn
+ findEnumByValueRecursion(const _ScopeModelItem *scope,
+ QStringView fullValue, QStringView value,
+ bool searchSiblingNamespaces = true);
+
ClassList m_classes;
EnumList m_enums;
TypeDefList m_typeDefs;
@@ -288,7 +305,7 @@ public:
: _ScopeModelItem(model, name, kind), m_classType(CodeModel::Class) {}
~_ClassModelItem();
- QList<BaseClass> baseClasses() const { return m_baseClasses; }
+ const QList<BaseClass> &baseClasses() const { return m_baseClasses; }
const QList<UsingMember> &usingMembers() const;
void addUsingMember(const QString &className, const QString &memberName,
@@ -636,6 +653,8 @@ public:
EnumKind enumKind() const { return m_enumKind; }
void setEnumKind(EnumKind kind) { m_enumKind = kind; }
+ qsizetype indexOfValue(QStringView value) const;
+
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const override;
#endif