summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTopi Reinio <topi.reinio@qt.io>2020-05-08 12:24:51 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2020-06-04 10:22:05 +0000
commitb7a6b1f290ae6f9dc9922590f8976f355da4913b (patch)
treed2972ccde8a60a77ba7002774189b47c29021c82
parentd96603fd7d3340fc925d05fd059c727b69b63636 (diff)
qdoc: Improve handling of templated types
The Clang visitor did not differentiate between templated class-like types, always assuming that it is a 'class'. Fix this by retrieving the type of the specialization the template refers to. Ensure that templated structs and unions are named correctly in the generated output. Handle the type of the cursor that refers to a templated type alias, and improve the code for resolving the template parameters for aliases. [ChangeLog][qdoc] QDoc now correctly handles templated structs, unions, and type aliases. Fixes: QTBUG-67432 Change-Id: Ia0fbfe7b7f22a54270650d96d0d67a4b8b8fd182 Reviewed-by: Paul Wicking <paul.wicking@qt.io> (cherry picked from commit 4f97a639cc39e8b1a42181a662b1059cd9c1d581) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/qdoc/clangcodeparser.cpp32
-rw-r--r--src/qdoc/cppcodemarker.cpp13
-rw-r--r--tests/auto/qdoc/generatedoutput/expected_output/template/baz.html6
-rw-r--r--tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test-struct.html32
-rw-r--r--tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test.html6
-rw-r--r--tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.cpp18
-rw-r--r--tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h7
-rw-r--r--tests/auto/qdoc/generatedoutput/testdata/testtemplate/testtemplate.cpp1
-rw-r--r--tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp1
9 files changed, 99 insertions, 17 deletions
diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp
index 0a0b7e7ac..99a74e9cb 100644
--- a/src/qdoc/clangcodeparser.cpp
+++ b/src/qdoc/clangcodeparser.cpp
@@ -631,15 +631,25 @@ CXChildVisitResult ClangVisitor::visitHeader(CXCursor cursor, CXSourceLocation l
auto kind = clang_getCursorKind(cursor);
QString templateString;
switch (kind) {
+ case CXCursor_TypeAliasTemplateDecl:
case CXCursor_TypeAliasDecl: {
QString aliasDecl = getSpelling(clang_getCursorExtent(cursor)).simplified();
QStringList typeAlias = aliasDecl.split(QLatin1Char('='));
if (typeAlias.size() == 2) {
- typeAlias[0] = typeAlias[0].trimmed().split(QLatin1Char(' ')).last();
- typeAlias[1] = typeAlias[1].trimmed();
- TypeAliasNode *ta = new TypeAliasNode(parent_, typeAlias[0], typeAlias[1]);
- ta->setAccess(fromCX_CXXAccessSpecifier(clang_getCXXAccessSpecifier(cursor)));
- ta->setLocation(fromCXSourceLocation(clang_getCursorLocation(cursor)));
+ typeAlias[0] = typeAlias[0].trimmed();
+ const QLatin1String usingString("using ");
+ int usingPos = typeAlias[0].indexOf(usingString);
+ if (usingPos != -1) {
+ if (kind == CXCursor_TypeAliasTemplateDecl)
+ templateString = typeAlias[0].left(usingPos).trimmed();
+ typeAlias[0].remove(0, usingPos + usingString.size());
+ typeAlias[0] = typeAlias[0].split(QLatin1Char(' ')).first();
+ typeAlias[1] = typeAlias[1].trimmed();
+ TypeAliasNode *ta = new TypeAliasNode(parent_, typeAlias[0], typeAlias[1]);
+ ta->setAccess(fromCX_CXXAccessSpecifier(clang_getCXXAccessSpecifier(cursor)));
+ ta->setLocation(fromCXSourceLocation(clang_getCursorLocation(cursor)));
+ ta->setTemplateDecl(templateString);
+ }
}
return CXChildVisit_Continue;
}
@@ -666,13 +676,15 @@ CXChildVisitResult ClangVisitor::visitHeader(CXCursor cursor, CXSourceLocation l
return CXChildVisit_Continue;
}
- Node::NodeType type;
- if (kind == CXCursor_ClassDecl || kind == CXCursor_ClassTemplate)
- type = Node::Class;
- else if (kind == CXCursor_StructDecl)
+ CXCursorKind actualKind = (kind == CXCursor_ClassTemplate) ?
+ clang_getTemplateCursorKind(cursor) : kind;
+
+ Node::NodeType type = Node::Class;
+ if (actualKind == CXCursor_StructDecl)
type = Node::Struct;
- else
+ else if (actualKind == CXCursor_UnionDecl)
type = Node::Union;
+
ClassNode *classe = new ClassNode(type, semanticParent, className);
classe->setAccess(fromCX_CXXAccessSpecifier(clang_getCXXAccessSpecifier(cursor)));
classe->setLocation(fromCXSourceLocation(clang_getCursorLocation(cursor)));
diff --git a/src/qdoc/cppcodemarker.cpp b/src/qdoc/cppcodemarker.cpp
index 79313e2dd..bd4aa6eb7 100644
--- a/src/qdoc/cppcodemarker.cpp
+++ b/src/qdoc/cppcodemarker.cpp
@@ -129,10 +129,11 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, const Node * /* relati
switch (node->nodeType()) {
case Node::Namespace:
- synopsis = "namespace " + name;
- break;
case Node::Class:
- synopsis = "class " + name;
+ case Node::Struct:
+ case Node::Union:
+ synopsis = Node::nodeTypeString(node->nodeType());
+ synopsis += QLatin1Char(' ') + name;
break;
case Node::Function:
func = (const FunctionNode *)node;
@@ -255,8 +256,12 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, const Node * /* relati
case Node::TypeAlias:
if (style == Section::Summary)
synopsis = "(alias) ";
- else if (style == Section::Details)
+ else if (style == Section::Details) {
extra = QStringLiteral("[alias] ");
+ QString templateDecl = node->templateDecl();
+ if (!templateDecl.isEmpty())
+ synopsis = templateDecl + QLatin1Char(' ');
+ }
synopsis += name;
break;
case Node::Typedef:
diff --git a/tests/auto/qdoc/generatedoutput/expected_output/template/baz.html b/tests/auto/qdoc/generatedoutput/expected_output/template/baz.html
index 4ab135c20..f9a3e24af 100644
--- a/tests/auto/qdoc/generatedoutput/expected_output/template/baz.html
+++ b/tests/auto/qdoc/generatedoutput/expected_output/template/baz.html
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<!-- testtemplate.cpp -->
- <title>Baz Class | TestCPP</title>
+ <title>Baz Struct | TestCPP</title>
</head>
<body>
<li>Baz</li>
@@ -15,8 +15,8 @@
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
-<h1 class="title">Baz Class</h1>
-<span class="small-subtitle">template &lt;template &lt;typename&gt; class X, typename Y&gt; class Baz</span>
+<h1 class="title">Baz Struct</h1>
+<span class="small-subtitle">template &lt;template &lt;typename&gt; class X, typename Y&gt; struct Baz</span>
<!-- $$$Baz-brief -->
<p>Class template template. <a href="#details">More...</a></p>
<!-- @@@Baz -->
diff --git a/tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test-struct.html b/tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test-struct.html
new file mode 100644
index 000000000..1624e4fd2
--- /dev/null
+++ b/tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test-struct.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+<!-- testcpp.cpp -->
+ <title>Struct Struct | TestCPP</title>
+</head>
+<body>
+<li>Struct</li>
+<div class="sidebar">
+<div class="toc">
+<h3><a name="toc">Contents</a></h3>
+<ul>
+<li class="level1"><a href="#details">Detailed Description</a></li>
+</ul>
+</div>
+<div class="sidebar-content" id="sidebar-content"></div></div>
+<h1 class="title">Struct Struct</h1>
+<span class="small-subtitle">template &lt;typename D, typename T&gt; struct <a href="testqdoc.html">TestQDoc</a>::<a href="testqdoc-test.html">Test</a>::Struct</span>
+<!-- $$$Struct-brief -->
+<p>Templated struct. <a href="#details">More...</a></p>
+<!-- @@@Struct -->
+<ul>
+</ul>
+<a name="details"></a>
+<!-- $$$Struct-description -->
+<div class="descr">
+<h2 id="details">Detailed Description</h2>
+</div>
+<!-- @@@Struct -->
+</body>
+</html>
diff --git a/tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test.html b/tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test.html
index 0ec969042..de5eb904a 100644
--- a/tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test.html
+++ b/tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test.html
@@ -34,7 +34,9 @@
<a name="public-types"></a>
<h2 id="public-types">Public Types</h2>
<div class="table"><table class="alignedsummary">
+<tr><td class="memItemLeft rightAlign topAlign"> struct </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test-struct.html">Struct</a></b></td></tr>
<tr><td class="memItemLeft rightAlign topAlign"> typedef </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#SomeType-typedef">SomeType</a></b></td></tr>
+<tr><td class="memItemLeft rightAlign topAlign"> (alias) </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#Specialized-alias">Specialized</a></b></td></tr>
</table></div>
<a name="public-functions"></a>
<h2 id="public-functions">Public Functions</h2>
@@ -68,6 +70,10 @@
<h3 class="fn" id="SomeType-typedef"><a name="SomeType-typedef"></a>typedef Test::<span class="name">SomeType</span></h3>
<p>A typedef.</p>
<!-- @@@SomeType -->
+<!-- $$$Specialized -->
+<h3 class="fn" id="Specialized-alias"><a name="Specialized-alias"></a><code>[alias] </code>template&lt;typename T&gt; Test::<span class="name">Specialized</span></h3>
+<p>This is a type alias for Struct&lt;int, T&gt;.</p>
+<!-- @@@Specialized -->
</div>
<div class="func">
<h2>Member Function Documentation</h2>
diff --git a/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.cpp b/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.cpp
index e43ecf0b7..2f6cd8805 100644
--- a/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.cpp
+++ b/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.cpp
@@ -196,4 +196,22 @@ void TestDerived::virtualFun()
\endif
*/
+/*!
+\if defined(test_template)
+ \struct TestQDoc::Test::Struct
+ \inmodule TestCPP
+ \brief Templated struct.
+\else
+ \nothing
+\endif
+*/
+
+/*!
+\if defined(test_template)
+ \typealias TestQDoc::Test::Specialized
+\else
+ \nothing
+\endif
+*/
+
} // namespace TestQDoc
diff --git a/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h b/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h
index b9644eb94..b3dc3df2a 100644
--- a/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h
+++ b/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h
@@ -33,6 +33,13 @@ namespace TestQDoc {
class Test {
public:
+
+#ifdef test_template
+template<typename D, typename T> struct Struct {};
+template<typename T>
+using Specialized = Struct<int, T>;
+#endif
+
#ifdef test_scopedenum
enum class ScopedEnum : unsigned char {
This = 0x01,
diff --git a/tests/auto/qdoc/generatedoutput/testdata/testtemplate/testtemplate.cpp b/tests/auto/qdoc/generatedoutput/testdata/testtemplate/testtemplate.cpp
index e9755769f..3214f4061 100644
--- a/tests/auto/qdoc/generatedoutput/testdata/testtemplate/testtemplate.cpp
+++ b/tests/auto/qdoc/generatedoutput/testdata/testtemplate/testtemplate.cpp
@@ -41,6 +41,7 @@
*/
/*!
+ //! Baz is a struct, QDoc auto-converts this to the correct type
\class Baz
\inmodule TestCPP
\brief Class template template.
diff --git a/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp b/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp
index 1cc15a10d..6aac203c9 100644
--- a/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp
+++ b/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp
@@ -332,6 +332,7 @@ void tst_generatedOutput::templateParameters()
{
testAndCompare("testdata/configs/testtemplate.qdocconf",
"template/testqdoc-test.html "
+ "template/testqdoc-test-struct.html "
"template/foo.html "
"template/bar.html "
"template/baz.html");