summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTopi Reinio <topi.reinio@qt.io>2021-04-23 13:33:58 +0200
committerTopi Reinio <topi.reinio@qt.io>2021-04-23 16:15:51 +0200
commitce05219da0750a3be429b396ea0d13980aa14d70 (patch)
tree3f4567180adfad69b69c2e0f866646ac6f2198a8 /src
parent9bb5dd9230941319bf60c3ccf62335b02eedfd87 (diff)
downloadqttools-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.cpp71
-rw-r--r--src/qdoc/tree.h1
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);