diff options
author | Topi Reinio <topi.reinio@qt.io> | 2020-04-21 23:57:46 +0200 |
---|---|---|
committer | Topi Reinio <topi.reinio@qt.io> | 2020-04-23 10:19:54 +0200 |
commit | e967772fe884dd8a488a359c122c9cbae9d94c55 (patch) | |
tree | 570c6bb5f46ef5409f4508a746dbde4542f7d7a9 /src | |
parent | 95cd9078938bcd88fdfbba707911e8111f59f195 (diff) |
qdoc: properly implement \typealias command
\typealias was already a command recognized by QDoc, but it was simply
treated as a synonym for \typedef and was not documented. Implement
proper support for the command:
- Add [alias] designation both in type summary and details.
- Auto-generate information about the aliased type, including a link
if aliasing a public, documented type.
- Auto-convert aliases documented with \typedef to type aliases.
- Add basic support for aliases also to DocBook and WebXML generators.
- Document \typealias.
Fixes: QTBUG-82712
Change-Id: Iafa8c7def0a7488d7521fbc2862290a9bb3167ff
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qdoc/clangcodeparser.cpp | 16 | ||||
-rw-r--r-- | src/qdoc/cppcodemarker.cpp | 7 | ||||
-rw-r--r-- | src/qdoc/cppcodeparser.cpp | 4 | ||||
-rw-r--r-- | src/qdoc/doc/qdoc-manual-cmdindex.qdoc | 1 | ||||
-rw-r--r-- | src/qdoc/doc/qdoc-manual-topiccmds.qdoc | 36 | ||||
-rw-r--r-- | src/qdoc/docbookgenerator.cpp | 64 | ||||
-rw-r--r-- | src/qdoc/docbookgenerator.h | 3 | ||||
-rw-r--r-- | src/qdoc/generator.cpp | 41 | ||||
-rw-r--r-- | src/qdoc/generator.h | 5 | ||||
-rw-r--r-- | src/qdoc/helpprojectwriter.cpp | 3 | ||||
-rw-r--r-- | src/qdoc/node.cpp | 4 | ||||
-rw-r--r-- | src/qdoc/node.h | 20 | ||||
-rw-r--r-- | src/qdoc/qdocindexfiles.cpp | 13 | ||||
-rw-r--r-- | src/qdoc/qdoctagfiles.cpp | 2 | ||||
-rw-r--r-- | src/qdoc/sections.cpp | 5 | ||||
-rw-r--r-- | src/qdoc/sections.h | 1 | ||||
-rw-r--r-- | src/qdoc/tree.cpp | 15 | ||||
-rw-r--r-- | src/qdoc/tree.h | 2 | ||||
-rw-r--r-- | src/qdoc/xmlgenerator.cpp | 6 |
19 files changed, 196 insertions, 52 deletions
diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp index b5c6a8ac6..0a0b7e7ac 100644 --- a/src/qdoc/clangcodeparser.cpp +++ b/src/qdoc/clangcodeparser.cpp @@ -632,18 +632,14 @@ CXChildVisitResult ClangVisitor::visitHeader(CXCursor cursor, CXSourceLocation l QString templateString; switch (kind) { case CXCursor_TypeAliasDecl: { - QString spelling = getSpelling(clang_getCursorExtent(cursor)); - QStringList typeAlias = spelling.split(QChar('=')); + QString aliasDecl = getSpelling(clang_getCursorExtent(cursor)).simplified(); + QStringList typeAlias = aliasDecl.split(QLatin1Char('=')); if (typeAlias.size() == 2) { - typeAlias[0] = typeAlias[0].trimmed(); + typeAlias[0] = typeAlias[0].trimmed().split(QLatin1Char(' ')).last(); typeAlias[1] = typeAlias[1].trimmed(); - int lastBlank = typeAlias[0].lastIndexOf(QChar(' ')); - if (lastBlank > 0) { - typeAlias[0] = typeAlias[0].right(typeAlias[0].size() - (lastBlank + 1)); - TypeAliasNode *ta = new TypeAliasNode(parent_, typeAlias[0], typeAlias[1]); - ta->setAccess(fromCX_CXXAccessSpecifier(clang_getCXXAccessSpecifier(cursor))); - ta->setLocation(fromCXSourceLocation(clang_getCursorLocation(cursor))); - } + TypeAliasNode *ta = new TypeAliasNode(parent_, typeAlias[0], typeAlias[1]); + ta->setAccess(fromCX_CXXAccessSpecifier(clang_getCXXAccessSpecifier(cursor))); + ta->setLocation(fromCXSourceLocation(clang_getCursorLocation(cursor))); } return CXChildVisit_Continue; } diff --git a/src/qdoc/cppcodemarker.cpp b/src/qdoc/cppcodemarker.cpp index 38dd8e79f..79313e2dd 100644 --- a/src/qdoc/cppcodemarker.cpp +++ b/src/qdoc/cppcodemarker.cpp @@ -252,6 +252,13 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, const Node * /* relati synopsis += QLatin1Char('}'); } break; + case Node::TypeAlias: + if (style == Section::Summary) + synopsis = "(alias) "; + else if (style == Section::Details) + extra = QStringLiteral("[alias] "); + synopsis += name; + break; case Node::Typedef: typedeff = static_cast<const TypedefNode *>(node); if (typedeff->associatedEnum()) { diff --git a/src/qdoc/cppcodeparser.cpp b/src/qdoc/cppcodeparser.cpp index 5248c990d..cccc1d86d 100644 --- a/src/qdoc/cppcodeparser.cpp +++ b/src/qdoc/cppcodeparser.cpp @@ -102,7 +102,7 @@ void CppCodeParser::initializeParser() nodeTypeMap_.insert(COMMAND_STRUCT, Node::Struct); nodeTypeMap_.insert(COMMAND_UNION, Node::Union); nodeTypeMap_.insert(COMMAND_ENUM, Node::Enum); - nodeTypeMap_.insert(COMMAND_TYPEALIAS, Node::Typedef); + nodeTypeMap_.insert(COMMAND_TYPEALIAS, Node::TypeAlias); nodeTypeMap_.insert(COMMAND_TYPEDEF, Node::Typedef); nodeTypeMap_.insert(COMMAND_PROPERTY, Node::Property); nodeTypeMap_.insert(COMMAND_VARIABLE, Node::Variable); @@ -112,7 +112,7 @@ void CppCodeParser::initializeParser() nodeTypeTestFuncMap_.insert(COMMAND_STRUCT, &Node::isStruct); nodeTypeTestFuncMap_.insert(COMMAND_UNION, &Node::isUnion); nodeTypeTestFuncMap_.insert(COMMAND_ENUM, &Node::isEnumType); - nodeTypeTestFuncMap_.insert(COMMAND_TYPEALIAS, &Node::isTypedef); + nodeTypeTestFuncMap_.insert(COMMAND_TYPEALIAS, &Node::isTypeAlias); nodeTypeTestFuncMap_.insert(COMMAND_TYPEDEF, &Node::isTypedef); nodeTypeTestFuncMap_.insert(COMMAND_PROPERTY, &Node::isProperty); nodeTypeTestFuncMap_.insert(COMMAND_VARIABLE, &Node::isVariable); diff --git a/src/qdoc/doc/qdoc-manual-cmdindex.qdoc b/src/qdoc/doc/qdoc-manual-cmdindex.qdoc index 430fdf0f8..5cd55c667 100644 --- a/src/qdoc/doc/qdoc-manual-cmdindex.qdoc +++ b/src/qdoc/doc/qdoc-manual-cmdindex.qdoc @@ -144,6 +144,7 @@ \li \l {threadsafe-command} {\\threadsafe} \li \l {title-command} {\\title} \li \l {tt-command} {\\tt} + \li \l {typealias-command} {\\typealias} \li \l {typedef-command} {\\typedef} \li \l {uicontrol-command} {\\uicontrol} \li \l {underline-command} {\\underline} diff --git a/src/qdoc/doc/qdoc-manual-topiccmds.qdoc b/src/qdoc/doc/qdoc-manual-topiccmds.qdoc index 8e142f5af..a537c7499 100644 --- a/src/qdoc/doc/qdoc-manual-topiccmds.qdoc +++ b/src/qdoc/doc/qdoc-manual-topiccmds.qdoc @@ -1410,6 +1410,40 @@ {\\instantiates} to specify that a Transform is instantiated by the C++ class QGraphicsTransform. A \\qmltype comment should + \target typealias-command + \section1 \\typealias + + The \\typealias command is similar to \l {typedef-command}{\\typedef}, + but specific to documenting a C++ type alias: + + \code + class Foo + { + public: + using ptr = void*; + // ... + } + \endcode + + This can be documented as + + \badcode * + /\1! + \typealias Foo::ptr + \1/ + \endcode + + QDoc will automatically generate a sentence in the documentation describing + the alias: + + \quotation + This is a type alias for \c {void*}. + \endquotation + + The \\typealias command was introduced in QDoc 5.15. + + See also \l {typedef-command}{\\typedef}. + \target typedef-command \section1 \\typedef @@ -1498,6 +1532,8 @@ Qt-style synonym for QList::iterator. \endquotation + See also \l {typealias-command}{\\typealias}. + \target variable-command \section1 \\variable diff --git a/src/qdoc/docbookgenerator.cpp b/src/qdoc/docbookgenerator.cpp index f6476c9ec..a7e5df290 100644 --- a/src/qdoc/docbookgenerator.cpp +++ b/src/qdoc/docbookgenerator.cpp @@ -2105,10 +2105,11 @@ void DocBookGenerator::generateBody(const Node *node) writer->writeTextElement(dbNamespace, "para", t); } } else if (!node->isSharingComment()) { - if (fn) { - if (!fn->overridesThis().isEmpty()) - generateReimplementsClause(fn); - } + // Reimplements clause and type alias info precede body text + if (fn && !fn->overridesThis().isEmpty()) + generateReimplementsClause(fn); + else if (node->isTypeAlias()) + generateAddendum(node, TypeAlias, nullptr, false); if (!generateText(node->doc().body(), node)) { if (node->isMarkedReimp()) @@ -2726,6 +2727,8 @@ void DocBookGenerator::generateDocBookSynopsis(const Node *node) else if (functionNode->isDefault()) signature += " = default"; generateSynopsisInfo("signature", signature); + } else if (node->isTypedef()) { + writer->writeTextElement(dbNamespace, "type", node->plainName()); } else { node->doc().location().warning(tr("Unexpected node type in generateDocBookSynopsis: %1") .arg(node->nodeTypeString())); @@ -3157,10 +3160,10 @@ void DocBookGenerator::generateSynopsis(const Node *node, const Node *relative, // First generate the extra part if needed (condition from HtmlGenerator::generateSynopsis). if (generateExtra) { - if (node->nodeType() == Node::Function) { - const auto func = static_cast<const FunctionNode *>(node); - if (style != Section::Summary && style != Section::Accessors) { - QStringList bracketed; + if (style != Section::Summary && style != Section::Accessors) { + QStringList bracketed; + if (node->isFunction()) { + const auto func = static_cast<const FunctionNode *>(node); if (func->isStatic()) { bracketed += "static"; } else if (!func->isNonvirtual()) { @@ -3182,11 +3185,12 @@ void DocBookGenerator::generateSynopsis(const Node *node, const Node *relative, bracketed += "signal"; else if (func->isSlot()) bracketed += "slot"; - - if (!bracketed.isEmpty()) - writer->writeCharacters(QLatin1Char('[') + bracketed.join(' ') - + QStringLiteral("] ")); + } else if (node->isTypeAlias()) { + bracketed += "alias"; } + if (!bracketed.isEmpty()) + writer->writeCharacters(QLatin1Char('[') + bracketed.join(' ') + + QStringLiteral("] ")); } if (style == Section::Summary) { @@ -3197,6 +3201,8 @@ void DocBookGenerator::generateSynopsis(const Node *node, const Node *relative, extra = "(deprecated) "; else if (node->isObsolete()) extra = "(obsolete) "; + else if (node->isTypeAlias()) + extra = "(alias) "; if (!extra.isEmpty()) writer->writeCharacters(extra); @@ -3407,12 +3413,15 @@ void DocBookGenerator::generateOverloadedSignal(const Node *node) Generates an addendum note of type \a type for \a node. \a marker is unused in this generator. */ -void DocBookGenerator::generateAddendum(const Node *node, Addendum type, CodeMarker *marker) +void DocBookGenerator::generateAddendum(const Node *node, Addendum type, CodeMarker *marker, + bool generateNote) { Q_UNUSED(marker); Q_ASSERT(node && !node->name().isEmpty()); - writer->writeStartElement(dbNamespace, "note"); - newLine(); + if (generateNote) { + writer->writeStartElement(dbNamespace, "note"); + newLine(); + } switch (type) { case Invokable: writer->writeStartElement(dbNamespace, "para"); @@ -3475,12 +3484,33 @@ void DocBookGenerator::generateAddendum(const Node *node, Addendum type, CodeMar } break; } + case TypeAlias: + { + if (!node->isTypeAlias()) + return; + writer->writeStartElement(dbNamespace, "para"); + const auto *ta = static_cast<const TypeAliasNode *>(node); + writer->writeCharacters("This is a type alias for "); + if (ta->aliasedNode() && ta->aliasedNode()->isInAPI()) + generateSimpleLink(linkForNode(ta->aliasedNode(), nullptr), + ta->aliasedNode()->plainFullName(ta->parent())); + else + writer->writeTextElement(dbNamespace, "code", ta->aliasedType()); + + writer->writeCharacters("."); + writer->writeEndElement(); // para + newLine(); + break; + } + default: break; } - writer->writeEndElement(); // note - newLine(); + if (generateNote) { + writer->writeEndElement(); // note + newLine(); + } } void DocBookGenerator::generateDetailedMember(const Node *node, const PageNode *relative) diff --git a/src/qdoc/docbookgenerator.h b/src/qdoc/docbookgenerator.h index 5eea595f7..753f5be33 100644 --- a/src/qdoc/docbookgenerator.h +++ b/src/qdoc/docbookgenerator.h @@ -81,7 +81,8 @@ protected: bool generateStatus(const Node *node); bool generateThreadSafeness(const Node *node); bool generateSince(const Node *node); - void generateAddendum(const Node *node, Generator::Addendum type, CodeMarker *marker = nullptr) override; + void generateAddendum(const Node *node, Generator::Addendum type, CodeMarker *marker = nullptr, + bool generateNote = true) override; using Generator::generateBody; void generateBody(const Node *node); diff --git a/src/qdoc/generator.cpp b/src/qdoc/generator.cpp index bdeeec2be..b3aacb623 100644 --- a/src/qdoc/generator.cpp +++ b/src/qdoc/generator.cpp @@ -644,6 +644,9 @@ QString Generator::fullDocumentLocation(const Node *node, bool useSubdir) case Node::Enum: anchorRef = QLatin1Char('#') + node->name() + "-enum"; break; + case Node::TypeAlias: + anchorRef = QLatin1Char('#') + node->name() + "-alias"; + break; case Node::Typedef: { const TypedefNode *tdef = static_cast<const TypedefNode *>(node); if (tdef->associatedEnum()) { @@ -818,10 +821,11 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) tr("No documentation for '%1'").arg(node->plainSignature())); } } else if (!node->isSharingComment()) { - if (fn) { - if (!fn->overridesThis().isEmpty()) - generateReimplementsClause(fn, marker); - } + // Reimplements clause and type alias info precede body text + if (fn && !fn->overridesThis().isEmpty()) + generateReimplementsClause(fn, marker); + else if (node->isTypeAlias()) + generateAddendum(node, TypeAlias, marker, false); if (!generateText(node->doc().body(), node, marker)) { if (node->isMarkedReimp()) @@ -1357,12 +1361,17 @@ void Generator::generateStatus(const Node *node, CodeMarker *marker) Generates an addendum note of type \a type for \a node, using \a marker as the code marker. */ -void Generator::generateAddendum(const Node *node, Addendum type, CodeMarker *marker) +void Generator::generateAddendum(const Node *node, Addendum type, CodeMarker *marker, + bool generateNote) { Q_ASSERT(node && !node->name().isEmpty()); Text text; - text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) - << "Note: " << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD); + text << Atom::ParaLeft; + + if (generateNote) { + text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) + << "Note: " << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD); + } switch (type) { case Invokable: @@ -1419,6 +1428,22 @@ void Generator::generateAddendum(const Node *node, Addendum type, CodeMarker *ma } break; } + case TypeAlias: + { + if (!node->isTypeAlias()) + return; + const auto *ta = static_cast<const TypeAliasNode *>(node); + text << "This is a type alias for "; + if (ta->aliasedNode() && ta->aliasedNode()->isInAPI()) { + text << Atom(Atom::LinkNode, CodeMarker::stringForNode(ta->aliasedNode())) + << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) + << Atom(Atom::String, ta->aliasedNode()->plainFullName(ta->parent())) + << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK) << "."; + } else { + text << Atom(Atom::String, ta->aliasedType()) << "."; + } + break; + } default: return; } @@ -2195,6 +2220,8 @@ QString Generator::typeString(const Node *node) return "enum"; case Node::Typedef: return "typedef"; + case Node::TypeAlias: + return "alias"; case Node::Function: { const auto fn = static_cast<const FunctionNode *>(node); switch (fn->metaness()) { diff --git a/src/qdoc/generator.h b/src/qdoc/generator.h index dca915ba7..8a613224f 100644 --- a/src/qdoc/generator.h +++ b/src/qdoc/generator.h @@ -53,7 +53,7 @@ class Generator public: enum ListType { Generic, Obsolete }; - enum Addendum { Invokable, PrivateSignal, QmlSignalHandler, AssociatedProperties }; + enum Addendum { Invokable, PrivateSignal, QmlSignalHandler, AssociatedProperties, TypeAlias }; Generator(); virtual ~Generator(); @@ -141,7 +141,8 @@ protected: static QString formatSince(const Node *node); void generateSince(const Node *node, CodeMarker *marker); void generateStatus(const Node *node, CodeMarker *marker); - virtual void generateAddendum(const Node *node, Addendum type, CodeMarker *marker); + virtual void generateAddendum(const Node *node, Addendum type, CodeMarker *marker, + bool generateNote = true); void generateThreadSafeness(const Node *node, CodeMarker *marker); QString getMetadataElement(const Aggregate *inner, const QString &t); QStringList getMetadataElements(const Aggregate *inner, const QString &t); diff --git a/src/qdoc/helpprojectwriter.cpp b/src/qdoc/helpprojectwriter.cpp index a372ea762..d411802dc 100644 --- a/src/qdoc/helpprojectwriter.cpp +++ b/src/qdoc/helpprojectwriter.cpp @@ -137,6 +137,7 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList typeHash["example"] = Node::Example; typeHash["externalpage"] = Node::ExternalPage; typeHash["typedef"] = Node::Typedef; + typeHash["typealias"] = Node::TypeAlias; typeHash["function"] = Node::Function; typeHash["property"] = Node::Property; typeHash["variable"] = Node::Variable; @@ -389,7 +390,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project, QXmlStreamWriter & if (node->parent()) project.memberStatus[node->parent()].insert(node->status()); } break; - + case Node::TypeAlias: case Node::Typedef: { const TypedefNode *typedefNode = static_cast<const TypedefNode *>(node); QStringList typedefDetails = keywordDetails(node); diff --git a/src/qdoc/node.cpp b/src/qdoc/node.cpp index 634cce3ec..cf8fa00f5 100644 --- a/src/qdoc/node.cpp +++ b/src/qdoc/node.cpp @@ -94,7 +94,7 @@ void Node::initialize() goals_.insert("example", Node::Example); goals_.insert("externalpage", Node::ExternalPage); goals_.insert("typedef", Node::Typedef); - goals_.insert("typealias", Node::Typedef); + goals_.insert("typealias", Node::TypeAlias); goals_.insert("function", Node::Function); goals_.insert("proxy", Node::Proxy); goals_.insert("property", Node::Property); @@ -938,6 +938,8 @@ QString Node::nodeTypeString(NodeType t) return QLatin1String("example"); case ExternalPage: return QLatin1String("external page"); + case TypeAlias: + return QLatin1String("alias"); case Typedef: return QLatin1String("typedef"); case Function: diff --git a/src/qdoc/node.h b/src/qdoc/node.h index b7293f408..4ec01673f 100644 --- a/src/qdoc/node.h +++ b/src/qdoc/node.h @@ -86,6 +86,7 @@ public: ExternalPage, Function, Typedef, + TypeAlias, Property, Variable, Group, @@ -198,8 +199,8 @@ public: bool isRelatedNonmember() const { return relatedNonmember_; } bool isStruct() const { return nodeType_ == Struct; } bool isSharedCommentNode() const { return nodeType_ == SharedComment; } - bool isTypeAlias() const { return nodeType_ == Typedef; } - bool isTypedef() const { return nodeType_ == Typedef; } + bool isTypeAlias() const { return nodeType_ == TypeAlias; } + bool isTypedef() const { return nodeType_ == Typedef || nodeType_ == TypeAlias; } bool isUnion() const { return nodeType_ == Union; } bool isVariable() const { return nodeType_ == Variable; } bool isGenericCollection() const { return (nodeType_ == Node::Collection); } @@ -892,8 +893,8 @@ private: class TypedefNode : public Node { public: - TypedefNode(Aggregate *parent, const QString &name) - : Node(Typedef, parent, name), associatedEnum_(nullptr) + TypedefNode(Aggregate *parent, const QString &name, NodeType type = Typedef) + : Node(type, parent, name), associatedEnum_(nullptr) { } @@ -912,16 +913,21 @@ private: class TypeAliasNode : public TypedefNode { public: - TypeAliasNode(Aggregate *parent, const QString &name, const QString &aliasedType) - : TypedefNode(parent, name), aliasedType_(aliasedType) + TypeAliasNode(Aggregate *parent, + const QString &name, + const QString &aliasedType) + : TypedefNode(parent, name, NodeType::TypeAlias), aliasedType_(aliasedType) { } - QString aliasedType() { return aliasedType_; } + const QString &aliasedType() const { return aliasedType_; } + const Node *aliasedNode() const { return aliasedNode_; } + void setAliasedNode(const Node *node) { aliasedNode_ = node; } Node *clone(Aggregate *parent) override; private: QString aliasedType_; + const Node *aliasedNode_ {}; }; inline void EnumNode::setFlagsType(TypedefNode *t) diff --git a/src/qdoc/qdocindexfiles.cpp b/src/qdoc/qdocindexfiles.cpp index 60cace3c9..d2768803d 100644 --- a/src/qdoc/qdocindexfiles.cpp +++ b/src/qdoc/qdocindexfiles.cpp @@ -454,6 +454,13 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader &reader, Node *current, else if (!indexUrl.isNull()) location = Location(parent->name().toLower() + ".html"); + } else if (elementName == QLatin1String("alias")) { + node = new TypeAliasNode(parent, name, attributes.value(QLatin1String("aliasedtype")).toString()); + if (!indexUrl.isEmpty()) + location = Location(indexUrl + QLatin1Char('/') + parent->name().toLower() + ".html"); + else if (!indexUrl.isNull()) + location = Location(parent->name().toLower() + ".html"); + } else if (elementName == QLatin1String("property")) { node = new PropertyNode(parent, name); @@ -864,6 +871,9 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter &writer, Node *node, case Node::Typedef: nodeName = "typedef"; break; + case Node::TypeAlias: + nodeName = "alias"; + break; case Node::Property: nodeName = "property"; break; @@ -1196,6 +1206,9 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter &writer, Node *node, if (typedefNode->associatedEnum()) writer.writeAttribute("enum", typedefNode->associatedEnum()->fullDocumentName()); } break; + case Node::TypeAlias: + writer.writeAttribute("aliasedtype", static_cast<const TypeAliasNode *>(node)->aliasedType()); + break; case Node::Function: // Now processed in generateFunctionSection() default: break; diff --git a/src/qdoc/qdoctagfiles.cpp b/src/qdoc/qdoctagfiles.cpp index 0d9b0aee0..2d9bce006 100644 --- a/src/qdoc/qdoctagfiles.cpp +++ b/src/qdoc/qdoctagfiles.cpp @@ -183,6 +183,7 @@ void QDocTagFiles::generateTagFileMembers(QXmlStreamWriter &writer, const Aggreg nodeName = "member"; kind = "enumeration"; break; + case Node::TypeAlias: // Treated as typedef case Node::Typedef: nodeName = "member"; kind = "typedef"; @@ -309,6 +310,7 @@ void QDocTagFiles::generateTagFileMembers(QXmlStreamWriter &writer, const Aggreg writer.writeEndElement(); // member } } break; + case Node::TypeAlias: // Treated as typedef case Node::Typedef: { const TypedefNode *typedefNode = static_cast<const TypedefNode *>(node); if (typedefNode->associatedEnum()) diff --git a/src/qdoc/sections.cpp b/src/qdoc/sections.cpp index c9012e21c..00357c246 100644 --- a/src/qdoc/sections.cpp +++ b/src/qdoc/sections.cpp @@ -373,6 +373,9 @@ Sections::Sections(const NodeMultiMap &nsmap) : aggregate_(nullptr) case Node::Typedef: sections[SinceTypedefs].appendMember(node); break; + case Node::TypeAlias: + sections[SinceTypeAliases].appendMember(node); + break; case Node::Function: { const FunctionNode *fn = static_cast<const FunctionNode *>(node); switch (fn->metaness()) { @@ -552,6 +555,7 @@ void Sections::initSections() v[SinceMacros].init(" New Macros"); v[SinceEnumTypes].init(" New Enum Types"); v[SinceTypedefs].init(" New Typedefs"); + v[SinceTypeAliases].init(" New Type Aliases"); v[SinceProperties].init(" New Properties"); v[SinceVariables].init(" New Variables"); v[SinceQmlTypes].init(" New QML Types"); @@ -623,6 +627,7 @@ void Sections::stdRefPageSwitch(SectionVector &v, Node *n, Node *t) return; case Node::Enum: case Node::Typedef: + case Node::TypeAlias: v[StdTypes].insert(n); return; case Node::Function: { diff --git a/src/qdoc/sections.h b/src/qdoc/sections.h index c8d17b141..dfcaaed7b 100644 --- a/src/qdoc/sections.h +++ b/src/qdoc/sections.h @@ -180,6 +180,7 @@ public: QmlAttachedMethods = 6, ProtectedTypes = 7, SinceTypedefs = 7, + SinceTypeAliases = 7, ProtectedFunctions = 8, SinceProperties = 8, ProtectedSlots = 9, diff --git a/src/qdoc/tree.cpp b/src/qdoc/tree.cpp index f6477b6b1..e20b8cc65 100644 --- a/src/qdoc/tree.cpp +++ b/src/qdoc/tree.cpp @@ -355,11 +355,14 @@ void Tree::resolveCppToQmlLinks() /*! For each C++ class node, resolve any \c using clauses that appeared in the class declaration. + + For type aliases, resolve the aliased node. */ -void Tree::resolveUsingClauses() +void Tree::resolveUsingClauses(Aggregate *parent) { - const NodeList &children = root_.childNodes(); - for (auto *child : children) { + if (!parent) + parent = &root_; + for (auto *child : parent->childNodes()) { if (child->isClassNode()) { ClassNode *cn = static_cast<ClassNode *>(child); QVector<UsingClause> &usingClauses = cn->usingClauses(); @@ -370,7 +373,13 @@ void Tree::resolveUsingClauses() usingClause.setNode(n); } } + } else if (child->isTypeAlias()) { + TypeAliasNode *ta = static_cast<TypeAliasNode *>(child); + ta->setAliasedNode(qdb_->findNodeForTarget(ta->aliasedType(), child->parent())); } + + if (child->genus() == Node::CPP && child->isAggregate()) + resolveUsingClauses(static_cast<Aggregate *>(child)); } } diff --git a/src/qdoc/tree.h b/src/qdoc/tree.h index b7e4dce75..10272ec84 100644 --- a/src/qdoc/tree.h +++ b/src/qdoc/tree.h @@ -151,7 +151,7 @@ private: // The rest of the class is private. void resolvePropertyOverriddenFromPtrs(Aggregate *n); void resolveProperties(); void resolveCppToQmlLinks(); - void resolveUsingClauses(); + void resolveUsingClauses(Aggregate *parent = nullptr); void removePrivateAndInternalBases(NamespaceNode *rootNode); NamespaceNode *root() { return &root_; } const NamespaceNode *root() const { return &root_; } diff --git a/src/qdoc/xmlgenerator.cpp b/src/qdoc/xmlgenerator.cpp index 8b266ca18..ffffc283a 100644 --- a/src/qdoc/xmlgenerator.cpp +++ b/src/qdoc/xmlgenerator.cpp @@ -76,6 +76,7 @@ int XmlGenerator::hOffset(const Node *node) case Node::Page: return 1; case Node::Enum: + case Node::TypeAlias: case Node::Typedef: case Node::Function: case Node::Property: @@ -239,6 +240,9 @@ QString XmlGenerator::refForNode(const Node *node) case Node::Enum: ref = node->name() + "-enum"; break; + case Node::TypeAlias: + ref = node->name() + "-alias"; + break; case Node::Typedef: { const auto tdn = static_cast<const TypedefNode *>(node); if (tdn->associatedEnum()) @@ -450,6 +454,8 @@ QString XmlGenerator::targetType(const Node *node) return QStringLiteral("page"); case Node::Enum: return QStringLiteral("enum"); + case Node::TypeAlias: + return QStringLiteral("alias"); case Node::Typedef: return QStringLiteral("typedef"); case Node::Property: |