From 03f1c6e3ed01f8270463ab8aa4afb4f7c2321cdb Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 17 Jan 2020 14:21:46 +0100 Subject: qdoc: Teach QDoc to output function and class template parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a visitor functor that reconstructs template parameters from the Clang AST, and use it when either a class or a method template is detected. Store this information in the node - for now, they are used only in the class reference page subtitle (for classes), and detailed section of function documentation. Template parameters are not considered when searching/linking to entities, they are for display only. [ChangeLog][qdoc] Added capability to display class/method template parameters in the generated documentation. Fixes: QTBUG-17456 Change-Id: I300cc63b9fa20d4f6efaeaa27ea3769635a7b32c Reviewed-by: Topi Reiniƶ --- src/qdoc/clangcodeparser.cpp | 67 +++++++++++++-- src/qdoc/cppcodemarker.cpp | 8 +- src/qdoc/docbookgenerator.cpp | 7 +- src/qdoc/htmlgenerator.cpp | 16 ++-- src/qdoc/node.cpp | 50 ++++++----- src/qdoc/node.h | 10 +-- tests/auto/qdoc/generatedoutput/TestCPP | 4 + .../expected_output/docbook/testqdoc-test.xml | 2 +- .../docbook/testqdoc-testderived.xml | 2 +- .../expected_output/ignoresince/testqdoc-test.html | 2 +- .../expected_output/template/bar.html | 34 ++++++++ .../expected_output/template/baz.html | 34 ++++++++ .../expected_output/template/foo.html | 34 ++++++++ .../expected_output/template/testqdoc-test.html | 96 ++++++++++++++++++++++ .../expected_output/testqdoc-test.html | 2 +- tests/auto/qdoc/generatedoutput/testcpp.cpp | 9 ++ tests/auto/qdoc/generatedoutput/testcpp.h | 5 ++ tests/auto/qdoc/generatedoutput/testtemplate.cpp | 47 +++++++++++ tests/auto/qdoc/generatedoutput/testtemplate.h | 53 ++++++++++++ .../qdoc/generatedoutput/testtemplate.qdocconf | 8 ++ .../qdoc/generatedoutput/tst_generatedoutput.cpp | 9 ++ 21 files changed, 451 insertions(+), 48 deletions(-) create mode 100644 tests/auto/qdoc/generatedoutput/expected_output/template/bar.html create mode 100644 tests/auto/qdoc/generatedoutput/expected_output/template/baz.html create mode 100644 tests/auto/qdoc/generatedoutput/expected_output/template/foo.html create mode 100644 tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test.html create mode 100644 tests/auto/qdoc/generatedoutput/testtemplate.cpp create mode 100644 tests/auto/qdoc/generatedoutput/testtemplate.h create mode 100644 tests/auto/qdoc/generatedoutput/testtemplate.qdocconf diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp index 7d10ae089..848f2b828 100644 --- a/src/qdoc/clangcodeparser.cpp +++ b/src/qdoc/clangcodeparser.cpp @@ -110,6 +110,55 @@ static QString fromCXString(CXString &&string) return ret; } +static QString templateDecl(CXCursor cursor); + +/*! + Returns a list of template parameters at \a cursor. +*/ +static QStringList getTemplateParameters(CXCursor cursor) +{ + QStringList parameters; + visitChildrenLambda(cursor, [¶meters](CXCursor cur) { + QString name = fromCXString(clang_getCursorSpelling(cur)); + QString type; + + switch (clang_getCursorKind(cur)) { + case CXCursor_TemplateTypeParameter: + type = QStringLiteral("typename"); + break; + case CXCursor_NonTypeTemplateParameter: + type = fromCXString(clang_getTypeSpelling(clang_getCursorType(cur))); + // Hack: Omit QtPrivate template parameters from public documentation + if (type.startsWith(QLatin1String("QtPrivate"))) + return CXChildVisit_Continue; + break; + case CXCursor_TemplateTemplateParameter: + type = templateDecl(cur) + QLatin1String(" class"); + break; + default: + return CXChildVisit_Continue; + } + + if (!name.isEmpty()) + name.prepend(QLatin1Char(' ')); + + parameters << type + name; + return CXChildVisit_Continue; + }); + + return parameters; +} + +/*! + Gets the template declaration at specified \a cursor. + */ +static QString templateDecl(CXCursor cursor) +{ + QStringList params = getTemplateParameters(cursor); + return QLatin1String("template <") + params.join(QLatin1String(", ")) + + QLatin1Char('>'); +} + /*! convert a CXSourceLocation to a qdoc Location */ @@ -573,6 +622,7 @@ CXChildVisitResult ClangVisitor::visitFnSignature(CXCursor cursor, CXSourceLocat CXChildVisitResult ClangVisitor::visitHeader(CXCursor cursor, CXSourceLocation loc) { auto kind = clang_getCursorKind(cursor); + QString templateString; switch (kind) { case CXCursor_TypeAliasDecl: { QString spelling = getSpelling(clang_getCursorExtent(cursor)); @@ -595,8 +645,10 @@ CXChildVisitResult ClangVisitor::visitHeader(CXCursor cursor, CXSourceLocation l if (fromCXString(clang_getCursorSpelling(cursor)).isEmpty()) // anonymous struct or union return CXChildVisit_Continue; Q_FALLTHROUGH(); - case CXCursor_ClassDecl: - case CXCursor_ClassTemplate: { + case CXCursor_ClassTemplate: + templateString = templateDecl(cursor); + Q_FALLTHROUGH(); + case CXCursor_ClassDecl: { if (!clang_isCursorDefinition(cursor)) return CXChildVisit_Continue; @@ -622,10 +674,8 @@ CXChildVisitResult ClangVisitor::visitHeader(CXCursor cursor, CXSourceLocation l classe->setAccess(fromCX_CXXAccessSpecifier(clang_getCXXAccessSpecifier(cursor))); classe->setLocation(fromCXSourceLocation(clang_getCursorLocation(cursor))); - if (kind == CXCursor_ClassTemplate) { - QString displayName = fromCXString(clang_getCursorSpelling(cursor)); - classe->setTemplateStuff(displayName.mid(className.size())); - } + if (kind == CXCursor_ClassTemplate) + classe->setTemplateDecl(templateString); QScopedValueRollback setParent(parent_, classe); return visitChildren(cursor); @@ -661,8 +711,10 @@ CXChildVisitResult ClangVisitor::visitHeader(CXCursor cursor, CXSourceLocation l QScopedValueRollback setParent(parent_, ns); return visitChildren(cursor); } - case CXCursor_FunctionDecl: case CXCursor_FunctionTemplate: + templateString = templateDecl(cursor); + Q_FALLTHROUGH(); + case CXCursor_FunctionDecl: case CXCursor_CXXMethod: case CXCursor_Constructor: case CXCursor_Destructor: @@ -760,6 +812,7 @@ CXChildVisitResult ClangVisitor::visitHeader(CXCursor cursor, CXSourceLocation l if (clang_isFunctionTypeVariadic(funcType)) parameters.append(QStringLiteral("...")); readParameterNamesAndAttributes(fn, cursor); + fn->setTemplateDecl(templateString); return CXChildVisit_Continue; } #if CINDEX_VERSION >= 36 diff --git a/src/qdoc/cppcodemarker.cpp b/src/qdoc/cppcodemarker.cpp index b23312d19..25c2f630b 100644 --- a/src/qdoc/cppcodemarker.cpp +++ b/src/qdoc/cppcodemarker.cpp @@ -136,9 +136,13 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, const Node * /* relati break; case Node::Function: func = (const FunctionNode *)node; - + if (style == Section::Details) { + QString templateDecl = node->templateDecl(); + if (!templateDecl.isEmpty()) + synopsis = templateDecl + QLatin1Char(' '); + } if (style != Section::AllMembers && !func->returnType().isEmpty()) - synopsis = typified(func->returnType(), true); + synopsis += typified(func->returnType(), true); synopsis += name; if (!func->isMacroWithoutParams()) { synopsis += QLatin1Char('('); diff --git a/src/qdoc/docbookgenerator.cpp b/src/qdoc/docbookgenerator.cpp index 36149a8ca..7653261e1 100644 --- a/src/qdoc/docbookgenerator.cpp +++ b/src/qdoc/docbookgenerator.cpp @@ -2425,8 +2425,11 @@ void DocBookGenerator::generateCppReferencePage(Node *node) ns = static_cast(aggregate); } else if (aggregate->isClass()) { rawTitle = aggregate->plainName(); - fullTitle = aggregate->plainFullName(); - title = rawTitle + " Class"; + QString templateDecl = node->templateDecl(); + if (!templateDecl.isEmpty()) + fullTitle = QString("%1 %2 ").arg(templateDecl, aggregate->typeWord(false)); + fullTitle += aggregate->plainFullName(); + title = rawTitle + QLatin1Char(' ') + aggregate->typeWord(true); } QString subtitleText; diff --git a/src/qdoc/htmlgenerator.cpp b/src/qdoc/htmlgenerator.cpp index 6196a6641..3f38ba96d 100644 --- a/src/qdoc/htmlgenerator.cpp +++ b/src/qdoc/htmlgenerator.cpp @@ -1171,6 +1171,7 @@ void HtmlGenerator::generateCppReferencePage(Aggregate *aggregate, CodeMarker *m Sections sections(aggregate); QString word = aggregate->typeWord(true); + QString templateDecl = aggregate->templateDecl(); if (aggregate->isNamespace()) { rawTitle = aggregate->plainName(); fullTitle = aggregate->plainFullName(); @@ -1181,11 +1182,7 @@ void HtmlGenerator::generateCppReferencePage(Aggregate *aggregate, CodeMarker *m } else if (aggregate->isClassNode()) { rawTitle = aggregate->plainName(); fullTitle = aggregate->plainFullName(); - if (aggregate->isStruct()) - word = QLatin1String("Struct"); - else if (aggregate->isUnion()) - word = QLatin1String("Union"); - title = rawTitle + " " + word; + title = rawTitle + QLatin1Char(' ') + word; summarySections = §ions.stdCppClassSummarySections(); detailsSections = §ions.stdCppClassDetailsSections(); } else if (aggregate->isHeader()) { @@ -1195,10 +1192,13 @@ void HtmlGenerator::generateCppReferencePage(Aggregate *aggregate, CodeMarker *m } Text subtitleText; - if (rawTitle != fullTitle) { - if (aggregate->parent()->isClassNode()) { + if (rawTitle != fullTitle || !templateDecl.isEmpty()) { + if (aggregate->isClassNode()) { + if (!templateDecl.isEmpty()) + subtitleText << templateDecl + QLatin1Char(' '); + subtitleText << aggregate->typeWord(false) + QLatin1Char(' '); const QStringList ancestors = fullTitle.split(QLatin1String("::")); - for (const auto a : ancestors) { + for (const auto &a : ancestors) { if (a == rawTitle) { subtitleText << a; break; diff --git a/src/qdoc/node.cpp b/src/qdoc/node.cpp index ed88de6e5..cd89737d7 100644 --- a/src/qdoc/node.cpp +++ b/src/qdoc/node.cpp @@ -1488,11 +1488,13 @@ QString Node::physicalModuleName() const \sa PageType */ -/*! \fn QString Node::signature(bool values, bool noReturnType) const +/*! \fn QString Node::signature(bool values, bool noReturnType, bool templateParams) const If this node is a FunctionNode, this function returns the function's - signature, including default values if \a values is \c true, and - including the function's return type if \a noReturnType is \c false. + signature, including default values if \a values is \c true, + function's return type if \a noReturnType is \c false, and + prefixed with 'template ' for function templates + if templateParams is \true. If this node is not a FunctionNode, this function returns plainName(). */ @@ -4240,27 +4242,35 @@ bool FunctionNode::hasActiveAssociatedProperty() const /*! Reconstructs and returns the function's signature. If \a values - is true, the default values of the parameters are included, if - present. + is \c true, the default values of the parameters are included. + The return type is included unless \a noReturnType is \c true. + Function templates are prefixed with \c {template } + if \a templateParams is \c true. */ -QString FunctionNode::signature(bool values, bool noReturnType) const +QString FunctionNode::signature(bool values, bool noReturnType, bool templateParams) const { - QString result; - if (!noReturnType && !returnType().isEmpty()) - result = returnType() + QLatin1Char(' '); - result += name(); + QStringList elements; + + if (templateParams) + elements << templateDecl(); + if (!noReturnType) + elements << returnType_; + elements.removeAll({}); + if (!isMacroWithoutParams()) { - result += QLatin1Char('(') + parameters_.signature(values) + QLatin1Char(')'); - if (isMacro()) - return result; + elements << name() + QLatin1Char('(') + parameters_.signature(values) + QLatin1Char(')'); + if (!isMacro()) { + if (isConst()) + elements << QStringLiteral("const"); + if (isRef()) + elements << QStringLiteral("&"); + else if (isRefRef()) + elements << QStringLiteral("&&"); + } + } else { + elements << name(); } - if (isConst()) - result += " const"; - if (isRef()) - result += " &"; - else if (isRefRef()) - result += " &&"; - return result; + return elements.join(QLatin1Char(' ')); } /*! diff --git a/src/qdoc/node.h b/src/qdoc/node.h index d400fc1d4..ea075e6ed 100644 --- a/src/qdoc/node.h +++ b/src/qdoc/node.h @@ -232,7 +232,7 @@ public: QString plainFullName(const Node *relative = nullptr) const; QString plainSignature() const; QString fullName(const Node *relative = nullptr) const; - virtual QString signature(bool, bool) const { return plainName(); } + virtual QString signature(bool, bool, bool = false) const { return plainName(); } const QString &fileNameBase() const { return fileNameBase_; } bool hasFileNameBase() const { return !fileNameBase_.isEmpty(); } @@ -251,7 +251,7 @@ public: void setSince(const QString &since); void setPhysicalModuleName(const QString &name) { physicalModuleName_ = name; } void setUrl(const QString &url) { url_ = url; } - void setTemplateStuff(const QString &t) { templateStuff_ = t; } + void setTemplateDecl(const QString &t) { templateDecl_ = t; } void setReconstitutedBrief(const QString &t) { reconstitutedBrief_ = t; } void setParent(Aggregate *n) { parent_ = n; } void setIndexNodeFlag(bool isIndexNode = true) { indexNodeFlag_ = isIndexNode; } @@ -319,7 +319,7 @@ public: ThreadSafeness threadSafeness() const; ThreadSafeness inheritedThreadSafeness() const; QString since() const { return since_; } - QString templateStuff() const { return templateStuff_; } + const QString &templateDecl() const { return templateDecl_; } const QString &reconstitutedBrief() const { return reconstitutedBrief_; } QString nodeSubtypeString() const; virtual void addPageKeywords(const QString &) {} @@ -387,7 +387,7 @@ private: QString physicalModuleName_; QString url_; QString since_; - QString templateStuff_; + QString templateDecl_; QString reconstitutedBrief_; // mutable QString uuid_; QString outSubDir_; @@ -1053,7 +1053,7 @@ public: const Parameters ¶meters() const { return parameters_; } bool isPrivateSignal() const { return parameters_.isPrivateSignal(); } void setParameters(const QString &signature) { parameters_.set(signature); } - QString signature(bool values, bool noReturnType) const override; + QString signature(bool values, bool noReturnType, bool templateParams = false) const override; const QString &overridesThis() const { return overridesThis_; } const NodeList &associatedProperties() const { return associatedProperties_; } diff --git a/tests/auto/qdoc/generatedoutput/TestCPP b/tests/auto/qdoc/generatedoutput/TestCPP index 50cce69ff..4ed786108 100644 --- a/tests/auto/qdoc/generatedoutput/TestCPP +++ b/tests/auto/qdoc/generatedoutput/TestCPP @@ -1 +1,5 @@ #include "testcpp.h" + +#ifdef test_template +# include "testtemplate.h" +#endif diff --git a/tests/auto/qdoc/generatedoutput/expected_output/docbook/testqdoc-test.xml b/tests/auto/qdoc/generatedoutput/expected_output/docbook/testqdoc-test.xml index 39292e2dc..0cfeb1724 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/docbook/testqdoc-test.xml +++ b/tests/auto/qdoc/generatedoutput/expected_output/docbook/testqdoc-test.xml @@ -2,7 +2,7 @@ Test Class -(TestQDoc::Test) +TestQDoc::Test TestCPP TestCPP Reference Documentation diff --git a/tests/auto/qdoc/generatedoutput/expected_output/docbook/testqdoc-testderived.xml b/tests/auto/qdoc/generatedoutput/expected_output/docbook/testqdoc-testderived.xml index 7a07adb85..9bb613cfc 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/docbook/testqdoc-testderived.xml +++ b/tests/auto/qdoc/generatedoutput/expected_output/docbook/testqdoc-testderived.xml @@ -2,7 +2,7 @@ TestDerived Class -(TestQDoc::TestDerived) +TestQDoc::TestDerived TestCPP TestCPP Reference Documentation diff --git a/tests/auto/qdoc/generatedoutput/expected_output/ignoresince/testqdoc-test.html b/tests/auto/qdoc/generatedoutput/expected_output/ignoresince/testqdoc-test.html index 0cb766e42..71c54c2e9 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/ignoresince/testqdoc-test.html +++ b/tests/auto/qdoc/generatedoutput/expected_output/ignoresince/testqdoc-test.html @@ -19,7 +19,7 @@

Test Class

-(TestQDoc::Test)
+class TestQDoc::Test

A class in a namespace. More...

diff --git a/tests/auto/qdoc/generatedoutput/expected_output/template/bar.html b/tests/auto/qdoc/generatedoutput/expected_output/template/bar.html new file mode 100644 index 000000000..552cbe9cd --- /dev/null +++ b/tests/auto/qdoc/generatedoutput/expected_output/template/bar.html @@ -0,0 +1,34 @@ + + + + + + Bar Class | TestCPP + + +
  • Bar
  • + +

    Bar Class

    +template <typename T, typename D> class Bar + +

    Another class template. More...

    + +
    +
    Header: #include <Bar> +
    qmake: QT += testcpp
      +
    + + +
    +

    Detailed Description

    +
    + + + diff --git a/tests/auto/qdoc/generatedoutput/expected_output/template/baz.html b/tests/auto/qdoc/generatedoutput/expected_output/template/baz.html new file mode 100644 index 000000000..4ab135c20 --- /dev/null +++ b/tests/auto/qdoc/generatedoutput/expected_output/template/baz.html @@ -0,0 +1,34 @@ + + + + + + Baz Class | TestCPP + + +
  • Baz
  • + +

    Baz Class

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

    Class template template. More...

    + +
    +
    Header: #include <Baz> +
    qmake: QT += testcpp
      +
    + + +
    +

    Detailed Description

    +
    + + + diff --git a/tests/auto/qdoc/generatedoutput/expected_output/template/foo.html b/tests/auto/qdoc/generatedoutput/expected_output/template/foo.html new file mode 100644 index 000000000..9e92a01b5 --- /dev/null +++ b/tests/auto/qdoc/generatedoutput/expected_output/template/foo.html @@ -0,0 +1,34 @@ + + + + + + Foo Class | TestCPP + + +
  • Foo
  • + +

    Foo Class

    +template <typename T> class Foo + +

    Class template. More...

    + +
    +
    Header: #include <Foo> +
    qmake: QT += testcpp
      +
    + + +
    +

    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 new file mode 100644 index 000000000..d19d15535 --- /dev/null +++ b/tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test.html @@ -0,0 +1,96 @@ + + + + + + Test Class | TestCPP + + +
  • Test
  • + +

    Test Class

    +class TestQDoc::Test + +

    A class in a namespace. More...

    + +
    +
    Header: #include <Test> +
    qmake: QT += testcpp
    Inherited By:

    TestQDoc::TestDerived

    +
    + +

    Public Functions

    +
    + + + + +
    void inlineFunction()
    int someFunction(int v)
    void someFunctionDefaultArg(int i, bool b = false)
    virtual void virtualFun()
    + +

    Protected Functions

    +
    + + + +
    void funcTemplate(T1 a, T2 b)
    void overload()
    void overload(bool b)
    + +

    Macros

    + + + +
    +

    Detailed Description

    +
    + +
    +

    Member Function Documentation

    + +
    +

    [protected] void Test::overload()

    [protected] void Test::overload(bool b)

    +

    Overloads that share a documentation comment, optionally taking a parameter b.

    + + +

    [protected] template <typename T1, typename T2> void Test::funcTemplate(T1 a, T2 b)

    +

    Function template with two parameters, a and b.

    + + +

    void Test::inlineFunction()

    +

    An inline function, documented using the \fn QDoc command.

    + + +

    int Test::someFunction(int v)

    +

    Function that takes a parameter v. Also returns the value of v.

    + + +

    void Test::someFunctionDefaultArg(int i, bool b = false)

    +

    Function that takes a parameter i and b.

    + + +

    [virtual] void Test::virtualFun()

    +

    Function that must be reimplemented.

    + +
    +
    +

    Macro Documentation

    + +

    QDOCTEST_MACRO2(x)

    +

    A macro with argument x.

    +

    This function was introduced in Test 1.1.

    + +
    + + diff --git a/tests/auto/qdoc/generatedoutput/expected_output/testqdoc-test.html b/tests/auto/qdoc/generatedoutput/expected_output/testqdoc-test.html index f373f725a..f3c8d55d0 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/testqdoc-test.html +++ b/tests/auto/qdoc/generatedoutput/expected_output/testqdoc-test.html @@ -19,7 +19,7 @@

    Test Class

    -(TestQDoc::Test)
    +class TestQDoc::Test

    A class in a namespace. More...

    diff --git a/tests/auto/qdoc/generatedoutput/testcpp.cpp b/tests/auto/qdoc/generatedoutput/testcpp.cpp index 3073148c2..b703a844b 100644 --- a/tests/auto/qdoc/generatedoutput/testcpp.cpp +++ b/tests/auto/qdoc/generatedoutput/testcpp.cpp @@ -162,4 +162,13 @@ void TestDerived::virtualFun() a parameter \a b. */ +/*! +\if defined(test_template) + \fn template void TestQDoc::Test::funcTemplate(T1 a, T2 b) + \brief Function template with two parameters, \a a and \a b. +\else + //! nothing +\endif +*/ + } // namespace TestQDoc diff --git a/tests/auto/qdoc/generatedoutput/testcpp.h b/tests/auto/qdoc/generatedoutput/testcpp.h index c34ada99b..5cb542dc4 100644 --- a/tests/auto/qdoc/generatedoutput/testcpp.h +++ b/tests/auto/qdoc/generatedoutput/testcpp.h @@ -44,6 +44,11 @@ public: protected: void overload() {} void overload(bool b) { if (!b) return; } +#ifdef test_template + template void funcTemplate(T1 a, T2 b) { + a = b; + } +#endif }; class TestDerived : public Test { diff --git a/tests/auto/qdoc/generatedoutput/testtemplate.cpp b/tests/auto/qdoc/generatedoutput/testtemplate.cpp new file mode 100644 index 000000000..e9755769f --- /dev/null +++ b/tests/auto/qdoc/generatedoutput/testtemplate.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testtemplate.h" + +/*! + \class Foo + \inmodule TestCPP + \brief Class template. +*/ + +/*! + \class Bar + \inmodule TestCPP + \brief Another class template. +*/ + +/*! + \class Baz + \inmodule TestCPP + \brief Class template template. +*/ diff --git a/tests/auto/qdoc/generatedoutput/testtemplate.h b/tests/auto/qdoc/generatedoutput/testtemplate.h new file mode 100644 index 000000000..d60ab0da4 --- /dev/null +++ b/tests/auto/qdoc/generatedoutput/testtemplate.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once + +template +class Foo { +public: + Foo() {} +private: + T t; +}; + +template +class Bar { +public: + Bar() {} +private: + T t; + D d; +}; + +template class X, typename Y> +struct Baz +{ + X z; + Baz() : z() {} +}; diff --git a/tests/auto/qdoc/generatedoutput/testtemplate.qdocconf b/tests/auto/qdoc/generatedoutput/testtemplate.qdocconf new file mode 100644 index 000000000..437319683 --- /dev/null +++ b/tests/auto/qdoc/generatedoutput/testtemplate.qdocconf @@ -0,0 +1,8 @@ +include(testcpp.qdocconf) +defines += test_template + +headers += testtemplate.h +sources += testtemplate.cpp + +HTML.nosubdirs = true +HTML.outputsubdir = template diff --git a/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp b/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp index 01608e95f..a47f4735f 100644 --- a/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp +++ b/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp @@ -57,6 +57,7 @@ private slots: // Output format independent tests void examplesManifestXml(); void ignoresinceVariable(); + void templateParameters(); private: QScopedPointer m_outputDir; @@ -275,6 +276,14 @@ void tst_generatedOutput::ignoresinceVariable() "ignoresince/testqdoc-test.html"); } +void tst_generatedOutput::templateParameters() +{ + testAndCompare("testtemplate.qdocconf", "template/testqdoc-test.html " + "template/foo.html " + "template/bar.html " + "template/baz.html"); +} + QTEST_APPLESS_MAIN(tst_generatedOutput) #include "tst_generatedoutput.moc" -- cgit v1.2.3