summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTopi Reinio <topi.reinio@qt.io>2021-04-23 13:33:58 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-04-23 16:33:32 +0000
commit4a0503bd8cf8a7fb08e933c4e52f9122057aabd6 (patch)
treefa239f259e35817fce3a0ceebd9f3d0cbc757961
parent0223b8733a078dde7f963e291f57062b8971b44b (diff)
downloadqttools-4a0503bd8cf8a7fb08e933c4e52f9122057aabd6.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. Fixes: QTBUG-92355 Change-Id: I74246158f7c5ca7c5c1712bc642905bc267cb7e1 Reviewed-by: Paul Wicking <paul.wicking@qt.io> (cherry picked from commit ce05219da0750a3be429b396ea0d13980aa14d70) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/qdoc/tree.cpp71
-rw-r--r--src/qdoc/tree.h1
-rw-r--r--tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/scoped-enum-linking.xml12
-rw-r--r--tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/testqdoc-test.xml46
-rw-r--r--tests/auto/qdoc/generatedoutput/expected_output/scopedenum/scoped-enum-linking.html19
-rw-r--r--tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html10
-rw-r--r--tests/auto/qdoc/generatedoutput/testdata/configs/scopedenum.qdocconf2
-rw-r--r--tests/auto/qdoc/generatedoutput/testdata/scopedenum/scopedenum.qdoc19
-rw-r--r--tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h2
-rw-r--r--tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp2
10 files changed, 159 insertions, 25 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);
diff --git a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/scoped-enum-linking.xml b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/scoped-enum-linking.xml
new file mode 100644
index 000000000..f5c4a05cd
--- /dev/null
+++ b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/scoped-enum-linking.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<db:article xmlns:db="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.2" xml:lang="en">
+<db:info>
+<db:title>Enum Linking</db:title>
+<db:productname>TestCPP</db:productname>
+<db:titleabbrev>TestCPP Reference Documentation</db:titleabbrev>
+<db:abstract>
+<db:para>TestCPP Reference Documentation.</db:para></db:abstract>
+</db:info>
+<db:para>Linking to <db:link xlink:href="testqdoc-test.xml#ScopedEnum-enum">All</db:link>.</db:para>
+<db:para>TestQDoc::Test::ClassicEnum::Howdy does not link, but <db:link xlink:href="testqdoc-test.xml#ClassicEnum-enum">TestQDoc::Test::Howdy</db:link> might.</db:para>
+</db:article>
diff --git a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/testqdoc-test.xml b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/testqdoc-test.xml
index 9db4ebb75..f7cee4513 100644
--- a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/testqdoc-test.xml
+++ b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/testqdoc-test.xml
@@ -41,6 +41,52 @@
</db:section>
<db:section xml:id="member-type-documentation">
<db:title>Member Type Documentation</db:title>
+<db:section xml:id="ClassicEnum-enum">
+<db:title>Test::enum ClassicEnum</db:title>
+<db:enumsynopsis>
+<db:enumname>ClassicEnum</db:enumname>
+<db:synopsisinfo db:role="access">public</db:synopsisinfo>
+<db:synopsisinfo db:role="status">active</db:synopsisinfo>
+<db:synopsisinfo db:role="threadsafeness">unspecified</db:synopsisinfo>
+<db:synopsisinfo db:role="module">TestCPP</db:synopsisinfo>
+<db:enumitem db:enumidentifier="Yee" db:enumvalue="0"/>
+<db:enumitem db:enumidentifier="Haw" db:enumvalue="1"/>
+<db:enumitem db:enumidentifier="Howdy" db:enumvalue="2"/>
+<db:enumitem db:enumidentifier="Partner" db:enumvalue="3"/>
+</db:enumsynopsis>
+<db:informaltable>
+<db:thead>
+<db:tr>
+<db:th>Constant</db:th>
+<db:th>Description</db:th>
+</db:tr>
+</db:thead>
+<db:tr>
+<db:td>
+<db:para><db:code><db:emphasis role="bold"><db:link xlink:href="testqdoc.xml">TestQDoc</db:link></db:emphasis>::<db:emphasis role="bold"><db:link xlink:href="testqdoc-test.xml">Test</db:link></db:emphasis>::Yee</db:code></db:para>
+</db:td>
+<db:td><db:code>0</db:code></db:td>
+</db:tr>
+<db:tr>
+<db:td>
+<db:para><db:code><db:emphasis role="bold"><db:link xlink:href="testqdoc.xml">TestQDoc</db:link></db:emphasis>::<db:emphasis role="bold"><db:link xlink:href="testqdoc-test.xml">Test</db:link></db:emphasis>::Haw</db:code></db:para>
+</db:td>
+<db:td><db:code>1</db:code></db:td>
+</db:tr>
+<db:tr>
+<db:td>
+<db:para><db:code><db:emphasis role="bold"><db:link xlink:href="testqdoc.xml">TestQDoc</db:link></db:emphasis>::<db:emphasis role="bold"><db:link xlink:href="testqdoc-test.xml">Test</db:link></db:emphasis>::Howdy</db:code></db:para>
+</db:td>
+<db:td><db:code>2</db:code></db:td>
+</db:tr>
+<db:tr>
+<db:td>
+<db:para><db:code><db:emphasis role="bold"><db:link xlink:href="testqdoc.xml">TestQDoc</db:link></db:emphasis>::<db:emphasis role="bold"><db:link xlink:href="testqdoc-test.xml">Test</db:link></db:emphasis>::Partner</db:code></db:para>
+</db:td>
+<db:td><db:code>3</db:code></db:td>
+</db:tr>
+</db:informaltable>
+</db:section>
<db:section xml:id="ScopedEnum-enum">
<db:title>Test::enum ScopedEnum</db:title>
<db:enumsynopsis>
diff --git a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/scoped-enum-linking.html b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/scoped-enum-linking.html
new file mode 100644
index 000000000..f07306f1e
--- /dev/null
+++ b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/scoped-enum-linking.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+<!-- scopedenum.qdoc -->
+ <title>Enum Linking | TestCPP</title>
+</head>
+<body>
+<div class="sidebar"><div class="sidebar-content" id="sidebar-content"></div></div>
+<h1 class="title">Enum Linking</h1>
+<span class="subtitle"></span>
+<!-- $$$scoped-enum-linking.html-description -->
+<div class="descr"> <a name="details"></a>
+<p>Linking to <a href="testqdoc-test.html#ScopedEnum-enum">All</a>.</p>
+<p>TestQDoc::Test::ClassicEnum::Howdy does not link, but <a href="testqdoc-test.html#ClassicEnum-enum">TestQDoc::Test::Howdy</a> might.</p>
+</div>
+<!-- @@@scoped-enum-linking.html -->
+</body>
+</html>
diff --git a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html
index 6f2e048aa..69dd5eb15 100644
--- a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html
+++ b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html
@@ -36,6 +36,7 @@ target_link_libraries(mytarget PRIVATE Qt6::QDocTest)</td></tr><tr><td class="me
<a name="public-types"></a>
<h2 id="public-types">Public Types</h2>
<div class="table"><table class="alignedsummary">
+<tr><td class="memItemLeft rightAlign topAlign"> enum </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#ClassicEnum-enum">ClassicEnum</a></b> { Yee, Haw, Howdy, Partner }</td></tr>
<tr><td class="memItemLeft rightAlign topAlign"> enum class </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#ScopedEnum-enum">ScopedEnum</a></b> { This, That, All }</td></tr>
<tr><td class="memItemLeft rightAlign topAlign"> </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#SomeType-typedef">SomeType</a></b></td></tr>
</table></div>
@@ -74,6 +75,15 @@ target_link_libraries(mytarget PRIVATE Qt6::QDocTest)</td></tr><tr><td class="me
<!-- @@@Test -->
<div class="types">
<h2>Member Type Documentation</h2>
+<!-- $$$ClassicEnum$$$Yee$$$Haw$$$Howdy$$$Partner -->
+<h3 class="fn" id="ClassicEnum-enum"><a name="ClassicEnum-enum"></a>enum Test::<span class="name">ClassicEnum</span></h3>
+<div class="table"><table class="valuelist"><tr><th class="tblConst">Constant</th><th class="tblVal">Value</th></tr>
+<tr><td class="topAlign"><code>TestQDoc::Test::Yee</code></td><td class="topAlign tblval"><code>0</code></td></tr>
+<tr><td class="topAlign"><code>TestQDoc::Test::Haw</code></td><td class="topAlign tblval"><code>1</code></td></tr>
+<tr><td class="topAlign"><code>TestQDoc::Test::Howdy</code></td><td class="topAlign tblval"><code>2</code></td></tr>
+<tr><td class="topAlign"><code>TestQDoc::Test::Partner</code></td><td class="topAlign tblval"><code>3</code></td></tr>
+</table></div>
+<!-- @@@ClassicEnum -->
<!-- $$$ScopedEnum$$$This$$$That$$$All$$$OmittedValue -->
<h3 class="fn" id="ScopedEnum-enum"><a name="ScopedEnum-enum"></a>enum class Test::<span class="name">ScopedEnum</span></h3>
<div class="table"><table class="valuelist"><tr valign="top" class="odd"><th class="tblConst">Constant</th><th class="tblval">Value</th><th class="tbldscr">Description</th></tr>
diff --git a/tests/auto/qdoc/generatedoutput/testdata/configs/scopedenum.qdocconf b/tests/auto/qdoc/generatedoutput/testdata/configs/scopedenum.qdocconf
index 0c1501213..d142e07fe 100644
--- a/tests/auto/qdoc/generatedoutput/testdata/configs/scopedenum.qdocconf
+++ b/tests/auto/qdoc/generatedoutput/testdata/configs/scopedenum.qdocconf
@@ -9,5 +9,3 @@ outputformats = HTML DocBook
{HTML.nosubdirs,DocBook.nosubdirs} = true
HTML.outputsubdir = scopedenum
DocBook.outputsubdir = scopedenum-docbook
-
-warninglimit += 2
diff --git a/tests/auto/qdoc/generatedoutput/testdata/scopedenum/scopedenum.qdoc b/tests/auto/qdoc/generatedoutput/testdata/scopedenum/scopedenum.qdoc
index 4262c1ce6..fdef9dd18 100644
--- a/tests/auto/qdoc/generatedoutput/testdata/scopedenum/scopedenum.qdoc
+++ b/tests/auto/qdoc/generatedoutput/testdata/scopedenum/scopedenum.qdoc
@@ -26,6 +26,15 @@
****************************************************************************/
/*!
+ \enum TestQDoc::Test::ClassicEnum
+
+ \value Yee
+ \value Haw
+ \value Howdy
+ \value Partner
+*/
+
+/*!
\enum TestQDoc::Test::ScopedEnum
\value This Something
@@ -33,3 +42,13 @@
\value All Everything
\omitvalue OmittedValue
*/
+
+/*!
+ \page scoped-enum-linking.html
+ \title Enum Linking
+
+ Linking to \l {TestQDoc::Test::ScopedEnum::}{All}.
+
+ TestQDoc::Test::ClassicEnum::Howdy does not link,
+ but TestQDoc::Test::Howdy might.
+*/
diff --git a/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h b/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h
index af2165d07..5fb323eed 100644
--- a/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h
+++ b/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h
@@ -48,6 +48,8 @@ using Specialized = Struct<int, T>;
#endif
#ifdef test_scopedenum
+ enum ClassicEnum { Yee, Haw, Howdy, Partner };
+
enum class ScopedEnum : unsigned char {
This = 0x01,
That = 0x02,
diff --git a/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp b/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp
index 31885fec2..9bfe6ed35 100644
--- a/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp
+++ b/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp
@@ -379,6 +379,8 @@ void tst_generatedOutput::scopedEnum()
{
testAndCompare("testdata/configs/scopedenum.qdocconf",
"scopedenum/testqdoc-test.html "
+ "scopedenum/scoped-enum-linking.html "
+ "scopedenum-docbook/scoped-enum-linking.xml "
"scopedenum-docbook/testqdoc-test.xml");
}