diff options
author | Topi Reinio <topi.reinio@qt.io> | 2021-04-23 13:33:58 +0200 |
---|---|---|
committer | Topi Reinio <topi.reinio@qt.io> | 2021-04-23 16:15:51 +0200 |
commit | ce05219da0750a3be429b396ea0d13980aa14d70 (patch) | |
tree | 3f4567180adfad69b69c2e0f866646ac6f2198a8 /src | |
parent | 9bb5dd9230941319bf60c3ccf62335b02eedfd87 (diff) | |
download | qttools-ce05219da0750a3be429b396ea0d13980aa14d70.tar.gz |
qdoc: Fix linking to scoped enums
The code that resolved qualified names of enum values did not expect
the name of the enum to appear in the path, as is the case for enum
classes.
Pick-to: 6.1
Fixes: QTBUG-92355
Change-Id: I74246158f7c5ca7c5c1712bc642905bc267cb7e1
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qdoc/tree.cpp | 71 | ||||
-rw-r--r-- | src/qdoc/tree.h | 1 |
2 files changed, 49 insertions, 23 deletions
diff --git a/src/qdoc/tree.cpp b/src/qdoc/tree.cpp index 9d220d9d7..775c4326a 100644 --- a/src/qdoc/tree.cpp +++ b/src/qdoc/tree.cpp @@ -594,21 +594,20 @@ const Node *Tree::matchPathAndTarget(const QStringList &path, int idx, const QSt if (node->isAggregate()) { NodeVector nodes; static_cast<const Aggregate *>(node)->findChildren(name, nodes); - for (const auto *node : qAsConst(nodes)) { - if (genus != Node::DontCare && !(genus & node->genus())) + for (const auto *child : qAsConst(nodes)) { + if (genus != Node::DontCare && !(genus & child->genus())) continue; - const Node *t = matchPathAndTarget(path, idx + 1, target, node, flags, genus, ref); + const Node *t = matchPathAndTarget(path, idx + 1, target, child, flags, genus, ref); if (t && !t->isPrivate()) return t; } } - if (target.isEmpty()) { - if ((idx) == (path.size() - 1) && node->isAggregate() && (flags & SearchEnumValues)) { - const Node *t = - static_cast<const Aggregate *>(node)->findEnumNodeForValue(path.at(idx)); - if (t) - return t; - } + if (target.isEmpty() && (flags & SearchEnumValues)) { + const auto *enumNode = node->isAggregate() ? + findEnumNode(nullptr, node, path, idx) : + findEnumNode(node, nullptr, path, idx); + if (enumNode) + return enumNode; } if (((genus == Node::CPP) || (genus == Node::DontCare)) && node->isClassNode() && (flags & SearchBaseClasses)) { @@ -617,12 +616,9 @@ const Node *Tree::matchPathAndTarget(const QStringList &path, int idx, const QSt const Node *t = matchPathAndTarget(path, idx, target, base, flags, genus, ref); if (t && !t->isPrivate()) return t; - if (target.isEmpty()) { - if ((idx) == (path.size() - 1) && (flags & SearchEnumValues)) { - t = base->findEnumNodeForValue(path.at(idx)); - if (t) - return t; - } + if (target.isEmpty() && (flags & SearchEnumValues)) { + if ((t = findEnumNode(base->findChildNode(path.at(idx), genus, flags), base, path, idx))) + return t; } } } @@ -677,17 +673,22 @@ const Node *Tree::findNode(const QStringList &path, const Node *start, int flags const Node *next = static_cast<const Aggregate *>(node)->findChildNode(path.at(i), genus, tmpFlags); - if ((next == nullptr) && (flags & SearchEnumValues) && i == path.size() - 1) { - next = static_cast<const Aggregate *>(node)->findEnumNodeForValue(path.at(i)); - } - if ((next == nullptr) && ((genus == Node::CPP) || (genus == Node::DontCare)) + const Node *enumNode = (flags & SearchEnumValues) ? + findEnumNode(next, node, path, i) : nullptr; + + if (enumNode) + return enumNode; + + + if (!next && ((genus == Node::CPP) || (genus == Node::DontCare)) && node->isClassNode() && (flags & SearchBaseClasses)) { const ClassList bases = allBaseClasses(static_cast<const ClassNode *>(node)); for (const auto *base : bases) { next = base->findChildNode(path.at(i), genus, tmpFlags); - if ((next == nullptr) && (flags & SearchEnumValues) && i == path.size() - 1) - next = base->findEnumNodeForValue(path.at(i)); - if (next != nullptr) + if (flags & SearchEnumValues) + if ((enumNode = findEnumNode(next, base, path, i))) + return enumNode; + if (next) break; } } @@ -701,6 +702,30 @@ const Node *Tree::findNode(const QStringList &path, const Node *start, int flags return nullptr; } + +/*! + \internal + + Helper function to return an enum that matches the \a path at a specified \a offset. + If \a node is a valid enum node, the enum name is assumed to be included in the path + (i.e, a scoped enum). Otherwise, query the \a aggregate (typically, the class node) + for enum node that includes the value at the last position in \a path. + */ +const Node *Tree::findEnumNode(const Node *node, const Node *aggregate, const QStringList &path, int offset) const +{ + // Scoped enum (path ends in enum_name :: enum_value) + if (node && node->isEnumType() && offset == path.size() - 1) { + const auto *en = static_cast<const EnumNode*>(node); + if (en->isScoped() && en->hasItem(path.last())) + return en; + } + + // Standard enum (path ends in class_name :: enum_value) + return (!node && aggregate && offset == path.size() - 1) ? + static_cast<const Aggregate *>(aggregate)->findEnumNodeForValue(path.last()) : + nullptr; +} + /*! This function searches for a node with a canonical title constructed from \a target. If the node it finds is \a node, diff --git a/src/qdoc/tree.h b/src/qdoc/tree.h index 0a2352903..97949314c 100644 --- a/src/qdoc/tree.h +++ b/src/qdoc/tree.h @@ -143,6 +143,7 @@ private: // The rest of the class is private. Node *findNodeByNameAndType(const QStringList &path, bool (Node::*isMatch)() const) const; Aggregate *findRelatesNode(const QStringList &path); + const Node *findEnumNode(const Node *node, const Node *aggregate, const QStringList &path, int offset) const; QString getRef(const QString &target, const Node *node) const; void insertTarget(const QString &name, const QString &title, TargetRec::TargetType type, Node *node, int priority); |