From b7a6b1f290ae6f9dc9922590f8976f355da4913b Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 8 May 2020 12:24:51 +0200 Subject: 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 (cherry picked from commit 4f97a639cc39e8b1a42181a662b1059cd9c1d581) Reviewed-by: Qt Cherry-pick Bot --- src/qdoc/clangcodeparser.cpp | 32 +++++++++++++++------- src/qdoc/cppcodemarker.cpp | 13 ++++++--- .../expected_output/template/baz.html | 6 ++-- .../template/testqdoc-test-struct.html | 32 ++++++++++++++++++++++ .../expected_output/template/testqdoc-test.html | 6 ++++ .../generatedoutput/testdata/testcpp/testcpp.cpp | 18 ++++++++++++ .../generatedoutput/testdata/testcpp/testcpp.h | 7 +++++ .../testdata/testtemplate/testtemplate.cpp | 1 + .../qdoc/generatedoutput/tst_generatedoutput.cpp | 1 + 9 files changed, 99 insertions(+), 17 deletions(-) create mode 100644 tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test-struct.html 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 @@ - Baz Class | TestCPP + Baz Struct | TestCPP
  • Baz
  • @@ -15,8 +15,8 @@ -

    Baz Class

    -template <template <typename> class X, typename Y> class Baz +

    Baz Struct

    +template <template <typename> class X, typename Y> struct Baz

    Class template template. More...

    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 @@ + + + + + + Struct Struct | TestCPP + + +
  • Struct
  • + +

    Struct Struct

    +template <typename D, typename T> struct TestQDoc::Test::Struct + +

    Templated struct. More...

    + +
      +
    + + +
    +

    Detailed Description

    +
    + + + 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 @@

    Public Types

    + +
    struct Struct
    typedef SomeType
    (alias) Specialized

    Public Functions

    @@ -68,6 +70,10 @@

    typedef Test::SomeType

    A typedef.

    + +

    [alias] template<typename T> Test::Specialized

    +

    This is a type alias for Struct<int, T>.

    +

    Member Function Documentation

    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 struct Struct {}; +template +using Specialized = Struct; +#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"); -- cgit v1.2.3