diff options
author | Topi Reinio <topi.reinio@qt.io> | 2022-12-07 22:17:08 +0000 |
---|---|---|
committer | Topi Reiniƶ <topi.reinio@qt.io> | 2022-12-12 08:11:09 +0000 |
commit | f003dd86a9b7a6edea2d0266ba8284871c480dd8 (patch) | |
tree | 2fea7debf84b04966c753da1aaa53a456947d6b5 | |
parent | f443f635e942fab8770a8eff6884bc60accb7e1d (diff) | |
download | qttools-f003dd86a9b7a6edea2d0266ba8284871c480dd8.tar.gz |
qdoc: Unify handling of QML types and QML value types
QML value types, formerly known as basic types, are nowadays provided
by multiple modules and contain also properties and methods.
QDoc's support for value types was rather basic (pun intended):
No import/since statements nor sections for properties etc. was
generated, the reference page had essentially a flat structure
similar to a generic \page.
As QML and QML value types are closely related, eliminate the dedicated
Node subclass for value types (QmlValueTypeNode), handle both with
QmlTypeNode class, differentiating them only with NodeType enumeration.
Make Node::isQmlType() return true for both to provide similar behavior
for all QML types, with a few exceptions:
* Do not warn if \qmlvaluetype command is missing \inqmlmodule
info as many of the original value types do not document it
* Do not generate 'all members' file for value types as they're
not expected to inherit other types.
* Do not include the QML module name qualifier into the filenames
generated for value types. This is done in order to keep the
existing behavior for value types and to avoid creating
redirects for online documentation.
Related to the last point, remove code from
Generator::fullDocumentLocation() that was never executed as it was
a duplicate from Generator::fileBase().
Unifying the types under a single Node subclass allows for removal of
multiple functions and code paths related to value types. They have
some constraints compared to proper QML types, but QDoc does not
currently enforce them.
[ChangeLog][QDoc][QDoc now properly outputs documentation for QML
value types with properties and methods.]
Pick-to: 6.4
Fixes: QTBUG-109132
Change-Id: I418660b0a6e0461c82fd5cb67e4f955a0d9a712c
Reviewed-by: Topi Reiniƶ <topi.reinio@qt.io>
27 files changed, 110 insertions, 278 deletions
diff --git a/src/qdoc/aggregate.cpp b/src/qdoc/aggregate.cpp index 3ba8faa62..f1ac8f242 100644 --- a/src/qdoc/aggregate.cpp +++ b/src/qdoc/aggregate.cpp @@ -79,8 +79,8 @@ Node *Aggregate::findChildNode(const QString &name, Node::Genus genus, int findF for (auto *node : nodes) { if (genus & node->genus()) { if (findFlags & TypesOnly) { - if (!node->isTypedef() && !node->isClassNode() && !node->isQmlType() - && !node->isQmlBasicType() && !node->isEnumType()) + if (!node->isTypedef() && !node->isClassNode() + && !node->isQmlType() && !node->isEnumType()) continue; } else if (findFlags & IgnoreModules && node->isModule()) continue; @@ -695,7 +695,7 @@ void Aggregate::findAllClasses() && node->tree()->camelCaseModuleName() != QString("QDoc")) { if (node->isClassNode()) { QDocDatabase::cppClasses().insert(node->qualifyCppName().toLower(), node); - } else if (node->isQmlType() || node->isQmlBasicType()) { + } else if (node->isQmlType()) { QString name = node->name().toLower(); QDocDatabase::qmlTypes().insert(name, node); // also add to the QML basic type map diff --git a/src/qdoc/cppcodeparser.cpp b/src/qdoc/cppcodeparser.cpp index aa9c8864d..3e16626fc 100644 --- a/src/qdoc/cppcodeparser.cpp +++ b/src/qdoc/cppcodeparser.cpp @@ -265,19 +265,17 @@ Node *CppCodeParser::processTopicCommand(const Doc &doc, const QString &command, auto *pn = new PageNode(m_qdb->primaryTreeRoot(), arg.first.split(' ').front()); pn->setLocation(doc.startLocation()); return pn; - } else if (command == COMMAND_QMLTYPE) { + } else if (command == COMMAND_QMLTYPE || + command == COMMAND_QMLVALUETYPE || + command == COMMAND_QMLBASICTYPE) { QmlTypeNode *qcn = nullptr; + auto nodeType = (command == COMMAND_QMLTYPE) ? Node::QmlType : Node::QmlValueType; Node *candidate = m_qdb->primaryTreeRoot()->findChildNode(arg.first, Node::QML); - if (candidate != nullptr && candidate->isQmlType()) - qcn = static_cast<QmlTypeNode *>(candidate); - else - qcn = new QmlTypeNode(m_qdb->primaryTreeRoot(), arg.first); + qcn = (candidate && candidate->nodeType() == nodeType) ? + static_cast<QmlTypeNode *>(candidate) : + new QmlTypeNode(m_qdb->primaryTreeRoot(), arg.first, nodeType); qcn->setLocation(doc.startLocation()); return qcn; - } else if (command == COMMAND_QMLVALUETYPE || command == COMMAND_QMLBASICTYPE) { - auto *node = new QmlValueTypeNode(m_qdb->primaryTreeRoot(), arg.first); - node->setLocation(doc.startLocation()); - return node; } else if ((command == COMMAND_QMLSIGNAL) || (command == COMMAND_QMLMETHOD) || (command == COMMAND_QMLATTACHEDSIGNAL) || (command == COMMAND_QMLATTACHEDMETHOD)) { Q_UNREACHABLE(); @@ -357,8 +355,11 @@ void CppCodeParser::processQmlProperties(const Doc &doc, NodeList &nodes, DocLis NodeList sharedNodes; QmlTypeNode *qmlType = m_qdb->findQmlType(module, qmlTypeName); + // Note: Constructing a QmlType node by default, as opposed to QmlValueType. + // This may lead to unexpected behavior if documenting \qmlvaluetype's properties + // before the type itself. if (qmlType == nullptr) - qmlType = new QmlTypeNode(m_qdb->primaryTreeRoot(), qmlTypeName); + qmlType = new QmlTypeNode(m_qdb->primaryTreeRoot(), qmlTypeName, Node::QmlType); for (const auto &topicCommand : topics) { QString cmd = topicCommand.m_topic; @@ -721,8 +722,6 @@ FunctionNode *CppCodeParser::parseOtherFuncArg(const QString &topic, const Locat Aggregate *aggregate = m_qdb->findQmlType(moduleName, elementName); if (aggregate == nullptr) - aggregate = m_qdb->findQmlBasicType(moduleName, elementName); - if (aggregate == nullptr) return nullptr; QString params; diff --git a/src/qdoc/docbookgenerator.cpp b/src/qdoc/docbookgenerator.cpp index 30a58fa15..6f84aa401 100644 --- a/src/qdoc/docbookgenerator.cpp +++ b/src/qdoc/docbookgenerator.cpp @@ -2620,7 +2620,7 @@ void DocBookGenerator::generateObsoleteQmlMembers(const Sections §ions) static QString nodeToSynopsisTag(const Node *node) { // Order from Node::nodeTypeString. - if (node->isClass() || node->isQmlType() || node->isQmlBasicType()) + if (node->isClass() || node->isQmlType()) return QStringLiteral("classsynopsis"); if (node->isNamespace()) return QStringLiteral("packagesynopsis"); @@ -2874,8 +2874,11 @@ void DocBookGenerator::generateQmlRequisites(const QmlTypeNode *qcn) base = base->qmlBaseNode(); } + // Skip import statement for \internal collections + const bool generate_import_statement = !qcn->logicalModuleName().isEmpty() && (!collection || !collection->isInternal() || m_showInternal); // Detect if anything is generated in this method. If not, exit early to avoid having an empty list. - const bool generates_something = !collection || !collection->isInternal() || m_showInternal || !qcn->since().isEmpty() || !subs.isEmpty() || base; + const bool generates_something = generate_import_statement || !qcn->since().isEmpty() || !subs.isEmpty() || base; + if (!generates_something) return; @@ -2883,16 +2886,9 @@ void DocBookGenerator::generateQmlRequisites(const QmlTypeNode *qcn) m_writer->writeStartElement(dbNamespace, "variablelist"); newLine(); - // skip import statement for \internal collections - if (!collection || !collection->isInternal() || m_showInternal) { - QString logicalModuleVersion = - collection ? collection->logicalModuleVersion() : qcn->logicalModuleVersion(); - - QStringList importText; - importText << "import " + qcn->logicalModuleName(); - if (!logicalModuleVersion.isEmpty()) - importText << logicalModuleVersion; - generateRequisite("Import Statement", importText.join(' ')); + if (generate_import_statement) { + QStringList parts = QStringList() << "import" << qcn->logicalModuleName() << qcn->logicalModuleVersion(); + generateRequisite("Import Statement", parts.join(' ').trimmed()); } // Since and project. @@ -4930,7 +4926,11 @@ void DocBookGenerator::generateQmlTypePage(QmlTypeNode *qcn) m_writer = startDocument(qcn); Generator::setQmlTypeContext(qcn); - const QString title = qcn->fullTitle() + " QML Type"; + QString title = qcn->fullTitle(); + if (qcn->isQmlBasicType()) + title.append(" QML Value Type"); + else + title.append(" QML Type"); generateHeader(title, qcn->subtitle(), qcn); generateQmlRequisites(qcn); @@ -4966,52 +4966,6 @@ void DocBookGenerator::generateQmlTypePage(QmlTypeNode *qcn) } /*! - Generate the DocBook page for the QML basic type represented - by the QML basic type node \a qbtn. - */ -void DocBookGenerator::generateQmlBasicTypePage(QmlValueTypeNode *qbtn) -{ - // From HtmlGenerator::generateQmlBasicTypePage. - // Start producing the DocBook file. - Q_ASSERT(m_writer == nullptr); - m_writer = startDocument(qbtn); - - const QString title = qbtn->fullTitle() + " QML Basic Type"; - - Sections sections(qbtn); - generateHeader(title, qbtn->subtitle(), qbtn); - - startSection("details", "Detailed Description"); - - generateBody(qbtn); - generateAlsoList(qbtn); - - endSection(); - - // Compared to HTML, skip sections.stdQmlTypeSummarySections(): it only - // generates a part of the table of contents. - - SectionVector::ConstIterator s = sections.stdQmlTypeDetailsSections().constBegin(); - while (s != sections.stdQmlTypeDetailsSections().constEnd()) { - if (!s->isEmpty()) { - startSection(s->title().toLower(), s->title()); - - NodeVector::ConstIterator m = s->members().constBegin(); - while (m != s->members().constEnd()) { - generateDetailedQmlMember(*m, qbtn); - ++m; - } - - endSection(); - } - ++s; - } - generateFooter(); - - endDocument(); -} - -/*! Outputs the DocBook detailed documentation for a section on a QML element reference page. */ @@ -5205,10 +5159,8 @@ void DocBookGenerator::generateDocumentation(Node *node) if ((node->isClassNode() || node->isHeader() || node->isNamespace()) && node->docMustBeGenerated()) { generateCppReferencePage(static_cast<Aggregate *>(node)); - } else if (node->isQmlType()) { + } else if (node->isQmlType()) { // Includes QML value types generateQmlTypePage(static_cast<QmlTypeNode *>(node)); - } else if (node->isQmlBasicType()) { - generateQmlBasicTypePage(static_cast<QmlValueTypeNode *>(node)); } else if (node->isProxyNode()) { generateProxyPage(static_cast<Aggregate *>(node)); } diff --git a/src/qdoc/docbookgenerator.h b/src/qdoc/docbookgenerator.h index 707ed9a74..c5b0849f0 100644 --- a/src/qdoc/docbookgenerator.h +++ b/src/qdoc/docbookgenerator.h @@ -36,8 +36,6 @@ protected: void generatePageNode(PageNode *pn); using Generator::generateQmlTypePage; void generateQmlTypePage(QmlTypeNode *qcn); - using Generator::generateQmlBasicTypePage; - void generateQmlBasicTypePage(QmlValueTypeNode *qbtn); using Generator::generateCollectionNode; void generateCollectionNode(CollectionNode *cn); using Generator::generateGenericCollectionPage; diff --git a/src/qdoc/generator.cpp b/src/qdoc/generator.cpp index 19c0c1e9e..6068afd22 100644 --- a/src/qdoc/generator.cpp +++ b/src/qdoc/generator.cpp @@ -295,15 +295,18 @@ QString Generator::fileBase(const Node *node) const base.prepend(s_project.toLower() + QLatin1Char('-')); base.append(QLatin1String("-example")); } - } else if (node->isQmlType() || node->isQmlBasicType()) { + } else if (node->isQmlType()) { base = node->name(); /* To avoid file name conflicts in the html directory, we prepend a prefix (by default, "qml-") and an optional suffix to the file name. The suffix, if one exists, is appended to the module name. + + For historical reasons, skip the module name qualifier for QML value types + in order to avoid excess redirects in the online docs. TODO: re-assess */ - if (!node->logicalModuleName().isEmpty() + if (!node->logicalModuleName().isEmpty() && !node->isQmlBasicType() && (!node->logicalModule()->isInternal() || m_showInternal)) base.prepend(node->logicalModuleName() + outputSuffix(node) + QLatin1Char('-')); @@ -494,19 +497,8 @@ QString Generator::fullDocumentLocation(const Node *node, bool useSubdir) parentName = fileBase(node) + QLatin1Char('.') + currentGenerator()->fileExtension(); else return QString(); - } else if (node->isQmlType() || node->isQmlBasicType()) { - QString fb = fileBase(node); - if (fb.startsWith(outputPrefix(node))) - return fb + QLatin1Char('.') + currentGenerator()->fileExtension(); - else { - QString mq; - if (!node->logicalModuleName().isEmpty()) { - mq = node->logicalModuleName().replace(QChar('.'), QChar('-')); - mq = mq.toLower() + QLatin1Char('-'); - } - return fdl + outputPrefix(node) + mq + fileBase(node) + QLatin1Char('.') - + currentGenerator()->fileExtension(); - } + } else if (node->isQmlType()) { + return fileBase(node) + QLatin1Char('.') + currentGenerator()->fileExtension(); } else if (node->isTextPageNode() || node->isCollectionNode()) { parentName = fileBase(node) + QLatin1Char('.') + currentGenerator()->fileExtension(); } else if (fileBase(node).isEmpty()) @@ -1072,11 +1064,6 @@ void Generator::generateDocumentation(Node *node) auto *qcn = static_cast<QmlTypeNode *>(node); generateQmlTypePage(qcn, marker); endSubPage(); - } else if (node->isQmlBasicType()) { - beginSubPage(node, fileName(node)); - auto *qbtn = static_cast<QmlValueTypeNode *>(node); - generateQmlBasicTypePage(qbtn, marker); - endSubPage(); } else if (node->isProxyNode()) { beginSubPage(node, fileName(node)); generateProxyPage(static_cast<Aggregate *>(node), marker); @@ -1806,7 +1793,7 @@ QString Generator::outFileName() QString Generator::outputPrefix(const Node *node) { // Prefix is applied to QML types - if (node->isQmlType() || node->isQmlBasicType()) + if (node->isQmlType()) return s_outputPrefixes[QLatin1String("QML")]; return QString(); @@ -1816,7 +1803,7 @@ QString Generator::outputSuffix(const Node *node) { // Suffix is applied to QML types, as // well as module pages. - if (node->isQmlModule() || node->isQmlType() || node->isQmlBasicType()) + if (node->isQmlModule() || node->isQmlType()) return s_outputSuffixes[QLatin1String("QML")]; return QString(); diff --git a/src/qdoc/generator.h b/src/qdoc/generator.h index 173a28686..81098396d 100644 --- a/src/qdoc/generator.h +++ b/src/qdoc/generator.h @@ -25,7 +25,6 @@ class FunctionNode; class Location; class Node; class QDocDatabase; -class QmlValueTypeNode; class Generator { @@ -89,7 +88,6 @@ protected: virtual void generateCppReferencePage(Aggregate *, CodeMarker *) {} virtual void generateProxyPage(Aggregate *, CodeMarker *) {} virtual void generateQmlTypePage(QmlTypeNode *, CodeMarker *) {} - virtual void generateQmlBasicTypePage(QmlValueTypeNode *, CodeMarker *) {} virtual void generatePageNode(PageNode *, CodeMarker *) {} virtual void generateCollectionNode(CollectionNode *, CodeMarker *) {} virtual void generateGenericCollectionPage(CollectionNode *, CodeMarker *) {} diff --git a/src/qdoc/helpprojectwriter.cpp b/src/qdoc/helpprojectwriter.cpp index 3fc669de2..d2ea24c71 100644 --- a/src/qdoc/helpprojectwriter.cpp +++ b/src/qdoc/helpprojectwriter.cpp @@ -173,7 +173,7 @@ Keyword HelpProjectWriter::keywordDetails(const Node *node) const ? node->parent()->name()+"::"+node->name() : node->name(); return Keyword(name, id, ref); - } else if (node->isQmlType() || node->isQmlBasicType()) { + } else if (node->isQmlType()) { const QString &name = node->name(); QString moduleName = node->logicalModuleName(); QStringList ids("QML." + name); @@ -483,9 +483,6 @@ void HelpProjectWriter::writeSection(QXmlStreamWriter &writer, const QString &pa */ void HelpProjectWriter::addMembers(HelpProject &project, QXmlStreamWriter &writer, const Node *node) { - if (node->isQmlBasicType()) - return; - QString href = m_gen->fullDocumentLocation(node, false); href = href.left(href.size() - 5); if (href.isEmpty()) @@ -496,8 +493,8 @@ void HelpProjectWriter::addMembers(HelpProject &project, QXmlStreamWriter &write derivedClass = !(static_cast<const ClassNode *>(node)->baseClasses().isEmpty()); // Do not generate a 'List of all members' for namespaces or header files, - // but always generate it for derived classes and QML classes - if (!node->isNamespace() && !node->isHeader() + // but always generate it for derived classes and QML types (but not QML value types) + if (!node->isNamespace() && !node->isHeader() && !node->isQmlBasicType() && (derivedClass || node->isQmlType() || !project.m_memberStatus[node].isEmpty())) { QString membersPath = href + QStringLiteral("-members.html"); writeSection(writer, membersPath, QStringLiteral("List of all members")); diff --git a/src/qdoc/htmlgenerator.cpp b/src/qdoc/htmlgenerator.cpp index cfffee4c2..4fcf966df 100644 --- a/src/qdoc/htmlgenerator.cpp +++ b/src/qdoc/htmlgenerator.cpp @@ -1362,7 +1362,12 @@ void HtmlGenerator::generateQmlTypePage(QmlTypeNode *qcn, CodeMarker *marker) { Generator::setQmlTypeContext(qcn); SubTitleSize subTitleSize = LargeSubTitle; - QString htmlTitle = qcn->fullTitle() + " QML Type"; + QString htmlTitle = qcn->fullTitle(); + if (qcn->isQmlBasicType()) + htmlTitle.append(" QML Value Type"); + else + htmlTitle.append(" QML Type"); + generateHeader(htmlTitle, qcn, marker); Sections sections(qcn); @@ -1372,7 +1377,11 @@ void HtmlGenerator::generateQmlTypePage(QmlTypeNode *qcn, CodeMarker *marker) generateBrief(qcn, marker); generateQmlRequisites(qcn, marker); - QString allQmlMembersLink = generateAllQmlMembersFile(sections, marker); + QString allQmlMembersLink; + + // No 'All Members' file for QML value types + if (!qcn->isQmlBasicType()) + allQmlMembersLink = generateAllQmlMembersFile(sections, marker); QString obsoleteLink = generateObsoleteQmlMembersFile(sections, marker); if (!allQmlMembersLink.isEmpty() || !obsoleteLink.isEmpty()) { openUnorderedList(); @@ -1431,56 +1440,6 @@ void HtmlGenerator::generateQmlTypePage(QmlTypeNode *qcn, CodeMarker *marker) } /*! - Generate the HTML page for the QML basic type represented - by the QML basic type node \a qbtn. - */ -void HtmlGenerator::generateQmlBasicTypePage(QmlValueTypeNode *qbtn, CodeMarker *marker) -{ - SubTitleSize subTitleSize = LargeSubTitle; - QString htmlTitle = qbtn->fullTitle() + " QML Basic Type"; - - marker = CodeMarker::markerForLanguage(QLatin1String("QML")); - - generateHeader(htmlTitle, qbtn, marker); - Sections sections(qbtn); - generateTableOfContents(qbtn, marker, §ions.stdQmlTypeSummarySections()); - generateTitle(htmlTitle, Text() << qbtn->subtitle(), subTitleSize, qbtn, marker); - generateBrief(qbtn, marker); - - const QList<Section> &stdQmlTypeSummarySections = sections.stdQmlTypeSummarySections(); - for (const auto §ion : stdQmlTypeSummarySections) { - if (!section.isEmpty()) { - const QString &ref = registerRef(section.title().toLower()); - out() << "<h2 id=\"" << ref << "\">" << protectEnc(section.title()) << "</h2>\n"; - generateQmlSummary(section.members(), qbtn, marker); - } - } - - generateExtractionMark(qbtn, DetailedDescriptionMark); - out() << R"(<div class="descr" id=")" << registerRef("details") - << "\">\n"; - - generateBody(qbtn, marker); - out() << "</div>\n"; - generateAlsoList(qbtn, marker); - generateExtractionMark(qbtn, EndMark); - - const QList<Section> &stdQmlTypeDetailsSections = sections.stdQmlTypeDetailsSections(); - for (const auto §ion : stdQmlTypeDetailsSections) { - if (!section.isEmpty()) { - out() << "<h2>" << protectEnc(section.title()) << "</h2>\n"; - const QList<Node *> &members = section.members(); - for (const auto member : members) { - generateDetailedQmlMember(member, qbtn, marker); - out() << "<br/>\n"; - } - } - } - - generateFooter(qbtn); -} - -/*! Generate the HTML page for an entity that doesn't map to any underlying parsable C++ or QML element. */ @@ -1692,7 +1651,7 @@ void HtmlGenerator::generateNavigationBar(const QString &title, const Node *node addNavItemNode(moduleNode, moduleNode->name() + moduleState); } navigationbar << Atom(itemLeft) << Atom(Atom::String, node->name()) << Atom(itemRight); - } else if (node->isQmlType() || node->isQmlBasicType()) { + } else if (node->isQmlType()) { if (!m_qmltypespage.isEmpty() && !m_qmltypestitle.isEmpty()) addNavItem(m_qmltypespage, m_qmltypestitle); // Add explicit link to the \qmlmodule page if: @@ -2170,23 +2129,14 @@ void HtmlGenerator::generateQmlRequisites(QmlTypeNode *qcn, CodeMarker *marker) const CollectionNode *collection = qcn->logicalModule(); // skip import statement of \internal collections - if (!collection || !collection->isInternal() || m_showInternal) { - logicalModuleVersion = - collection ? collection->logicalModuleVersion() : qcn->logicalModuleVersion(); - - if (qcn->logicalModuleName().isEmpty()) - qcn->doc().location().warning(QStringLiteral("Could not resolve QML import " - "statement for type '%1'") - .arg(qcn->name()), - QStringLiteral("Maybe you forgot to use the " - "'\\%1' command?") - .arg(COMMAND_INQMLMODULE)); - + if (!qcn->logicalModuleName().isEmpty() && (!collection || !collection->isInternal() || m_showInternal)) { + QStringList parts = QStringList() << "import" << qcn->logicalModuleName() << qcn->logicalModuleVersion(); text.clear(); - text << "import " + qcn->logicalModuleName(); - if (!logicalModuleVersion.isEmpty()) - text << QLatin1Char(' ') + logicalModuleVersion; + text << parts.join(' ').trimmed(); requisites.insert(importText, text); + } else if (!qcn->isQmlBasicType() && qcn->logicalModuleName().isEmpty()) { + qcn->doc().location().warning(QStringLiteral("Could not resolve QML import statement for type '%1'").arg(qcn->name()), + QStringLiteral("Maybe you forgot to use the '\\%1' command?").arg(COMMAND_INQMLMODULE)); } // add the since and project into the map @@ -2330,7 +2280,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node, CodeMarker *marker break; } } - } else if (sections && (node->isClassNode() || node->isNamespace() || node->isQmlType() || node->isQmlBasicType())) { + } else if (sections && (node->isClassNode() || node->isNamespace() || node->isQmlType())) { for (const auto §ion : std::as_const(*sections)) { if (!section.members().isEmpty()) { openUnorderedList(); diff --git a/src/qdoc/htmlgenerator.h b/src/qdoc/htmlgenerator.h index 2d4c4d417..3c12ce328 100644 --- a/src/qdoc/htmlgenerator.h +++ b/src/qdoc/htmlgenerator.h @@ -40,7 +40,6 @@ protected: void generateCppReferencePage(Aggregate *aggregate, CodeMarker *marker) override; void generateProxyPage(Aggregate *aggregate, CodeMarker *marker) override; void generateQmlTypePage(QmlTypeNode *qcn, CodeMarker *marker) override; - void generateQmlBasicTypePage(QmlValueTypeNode *qbtn, CodeMarker *marker) override; void generatePageNode(PageNode *pn, CodeMarker *marker) override; void generateCollectionNode(CollectionNode *cn, CodeMarker *marker) override; void generateGenericCollectionPage(CollectionNode *cn, CodeMarker *marker) override; diff --git a/src/qdoc/node.cpp b/src/qdoc/node.cpp index 6ec85e40c..4b6189b0a 100644 --- a/src/qdoc/node.cpp +++ b/src/qdoc/node.cpp @@ -119,8 +119,8 @@ bool Node::nodeNameLessThan(const Node *n1, const Node *n2) module. \value QmlProperty The Node subclass is QmlPropertyNode, which represents a property in a QML type. - \value QmlBasicType The Node subclass is QmlBasicTypeNode, which represents a - basic type like int, etc. + \value QmlBasicType The Node subclass is QmlTypeNode, which represents a + value type like int, etc. \value SharedComment The Node subclass is SharedCommentNode, which represents a collection of nodes that share the same documentation comment. \omitvalue Collection @@ -311,7 +311,7 @@ bool Node::nodeNameLessThan(const Node *n1, const Node *n2) */ /*! \fn bool Node::isQmlType() const - Returns true if the node type is \c QmlType. + Returns true if the node type is \c QmlType or \c QmlValueType. */ /*! \fn bool Node::isRelatedNonmember() const @@ -675,7 +675,7 @@ QString Node::nodeTypeString(NodeType t) case QmlType: return QLatin1String("QML type"); case QmlValueType: - return QLatin1String("QML basic type"); + return QLatin1String("QML value type"); case QmlModule: return QLatin1String("QML module"); case QmlProperty: diff --git a/src/qdoc/node.h b/src/qdoc/node.h index 5a85d78ec..85643add6 100644 --- a/src/qdoc/node.h +++ b/src/qdoc/node.h @@ -142,7 +142,7 @@ public: [[nodiscard]] bool isQmlModule() const { return m_nodeType == QmlModule; } [[nodiscard]] bool isQmlNode() const { return genus() == QML; } [[nodiscard]] bool isQmlProperty() const { return m_nodeType == QmlProperty; } - [[nodiscard]] bool isQmlType() const { return m_nodeType == QmlType; } + [[nodiscard]] bool isQmlType() const { return m_nodeType == QmlType || m_nodeType == QmlValueType; } [[nodiscard]] bool isRelatedNonmember() const { return m_relatedNonmember; } [[nodiscard]] bool isStruct() const { return m_nodeType == Struct; } [[nodiscard]] bool isSharedCommentNode() const { return m_nodeType == SharedComment; } diff --git a/src/qdoc/qdocdatabase.cpp b/src/qdoc/qdocdatabase.cpp index 49a882f56..b31348a76 100644 --- a/src/qdoc/qdocdatabase.cpp +++ b/src/qdoc/qdocdatabase.cpp @@ -668,30 +668,6 @@ QmlTypeNode *QDocDatabase::findQmlType(const QString &qmid, const QString &name) } /*! - Looks up the QML basic type node identified by the Qml module id - \a qmid and QML basic type \a name and returns a pointer to the - QML basic type node. The key is \a qmid + "::" + \a name. - - If the QML module id is empty, it looks up the QML basic type by - \a name only. - */ -Aggregate *QDocDatabase::findQmlBasicType(const QString &qmid, const QString &name) -{ - if (!qmid.isEmpty()) { - QString t = qmid + "::" + name; - Aggregate *a = m_forest.lookupQmlBasicType(t); - if (a) - return a; - } - - QStringList path(name); - Node *n = m_forest.findNodeByNameAndType(path, &Node::isQmlBasicType); - if (n && n->isQmlBasicType()) - return static_cast<Aggregate *>(n); - return nullptr; -} - -/*! Looks up the QML type node identified by the Qml module id constructed from the strings in the \a import record and the QML type \a name and returns a pointer to the QML type node. diff --git a/src/qdoc/qdocdatabase.h b/src/qdoc/qdocdatabase.h index efa2ce228..c4aada4b7 100644 --- a/src/qdoc/qdocdatabase.h +++ b/src/qdoc/qdocdatabase.h @@ -148,15 +148,6 @@ private: return nullptr; } - Aggregate *lookupQmlBasicType(const QString &name) - { - for (const auto *tree : searchOrder()) { - Aggregate *a = tree->lookupQmlBasicType(name); - if (a) - return a; - } - return nullptr; - } void clearSearchOrder() { m_searchOrder.clear(); } void newPrimaryTree(const QString &module); void setPrimaryTree(const QString &t); @@ -208,7 +199,6 @@ public: QmlTypeNode *findQmlType(const QString &name); QmlTypeNode *findQmlType(const QString &qmid, const QString &name); QmlTypeNode *findQmlType(const ImportRec &import, const QString &name); - Aggregate *findQmlBasicType(const QString &qmid, const QString &name); static NodeMultiMap &obsoleteClasses() { return s_obsoleteClasses; } static NodeMultiMap &obsoleteQmlTypes() { return s_obsoleteQmlTypes; } diff --git a/src/qdoc/qdocindexfiles.cpp b/src/qdoc/qdocindexfiles.cpp index 1ac610238..bd81cc556 100644 --- a/src/qdoc/qdocindexfiles.cpp +++ b/src/qdoc/qdocindexfiles.cpp @@ -248,8 +248,10 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader &reader, Node *current, location = Location(indexUrl + QLatin1Char('/') + name); else if (!indexUrl.isNull()) location = Location(name); - } else if (elementName == QLatin1String("qmlclass")) { - auto *qmlTypeNode = new QmlTypeNode(parent, name); + } else if (elementName == QLatin1String("qmlclass") || elementName == QLatin1String("qmlvaluetype") + || elementName == QLatin1String("qmlbasictype")) { + auto *qmlTypeNode = new QmlTypeNode(parent, name, + elementName == QLatin1String("qmlclass") ? Node::QmlType : Node::QmlValueType); qmlTypeNode->setTitle(attributes.value(QLatin1String("title")).toString()); QString logicalModuleName = attributes.value(QLatin1String("qml-module-name")).toString(); if (!logicalModuleName.isEmpty()) @@ -269,17 +271,6 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader &reader, Node *current, else if (!indexUrl.isNull()) location = Location(name); node = qmlTypeNode; - } else if (elementName == QLatin1String("qmlvaluetype") - || elementName == QLatin1String("qmlbasictype")) { - auto *qbtn = new QmlValueTypeNode(parent, name); - qbtn->setTitle(attributes.value(QLatin1String("title")).toString()); - if (attributes.hasAttribute(QLatin1String("location"))) - name = attributes.value("location").toString(); - if (!indexUrl.isEmpty()) - location = Location(indexUrl + QLatin1Char('/') + name); - else if (!indexUrl.isNull()) - location = Location(name); - node = qbtn; } else if (elementName == QLatin1String("qmlproperty")) { QString type = attributes.value(QLatin1String("type")).toString(); bool attached = false; @@ -791,7 +782,8 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter &writer, Node *node, nodeName = "header"; break; case Node::QmlType: - nodeName = "qmlclass"; + case Node::QmlValueType: + nodeName = (node->nodeType() == Node::QmlType) ? "qmlclass" : "qmlvaluetype"; if (node->logicalModule() != nullptr) logicalModuleName = node->logicalModule()->logicalModuleName(); baseNameAttr = "qml-base-type"; @@ -799,9 +791,6 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter &writer, Node *node, moduleVerAttr = "qml-module-version"; qmlFullBaseName = node->qmlFullBaseName(); break; - case Node::QmlValueType: - nodeName = "qmlvaluetype"; - break; case Node::Page: case Node::Example: case Node::ExternalPage: @@ -962,6 +951,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter &writer, Node *node, if (!brief.isEmpty()) writer.writeAttribute("brief", brief); } break; + case Node::QmlValueType: case Node::QmlType: { const auto *qmlTypeNode = static_cast<const QmlTypeNode *>(node); writer.writeAttribute("title", qmlTypeNode->title()); diff --git a/src/qdoc/qmltypenode.cpp b/src/qdoc/qmltypenode.cpp index e187c076b..b3ada1c45 100644 --- a/src/qdoc/qmltypenode.cpp +++ b/src/qdoc/qmltypenode.cpp @@ -14,11 +14,13 @@ QMultiMap<const Node *, Node *> QmlTypeNode::s_inheritedBy; /*! Constructs a Qml type. - The new node has the given \a parent and \a name. + The new node has the given \a parent, name \a name, and a specific node + \a type. Valid types are Node::QmlType and Node::QmlValueType. */ -QmlTypeNode::QmlTypeNode(Aggregate *parent, const QString &name) - : Aggregate(QmlType, parent, name) +QmlTypeNode::QmlTypeNode(Aggregate *parent, const QString &name, Node::NodeType type) + : Aggregate(type, parent, name) { + Q_ASSERT(type == Node::QmlType || type == Node::QmlValueType); setTitle(name); } @@ -148,15 +150,4 @@ void QmlTypeNode::resolveInheritance(NodeMap &previousSearches) } } -/*! - Constructs a Qml basic type node. - - The new node has the given \a parent and \a name. - */ -QmlValueTypeNode::QmlValueTypeNode(Aggregate *parent, const QString &name) - : Aggregate(QmlValueType, parent, name) -{ - setTitle(name); -} - QT_END_NAMESPACE diff --git a/src/qdoc/qmltypenode.h b/src/qdoc/qmltypenode.h index d79e2e619..d43962157 100644 --- a/src/qdoc/qmltypenode.h +++ b/src/qdoc/qmltypenode.h @@ -21,7 +21,7 @@ typedef QList<ImportRec> ImportList; class QmlTypeNode : public Aggregate { public: - QmlTypeNode(Aggregate *parent, const QString &name); + QmlTypeNode(Aggregate *parent, const QString &name, Node::NodeType type); [[nodiscard]] bool isFirstClassAggregate() const override { return true; } [[nodiscard]] bool isQtQuickNode() const override { @@ -67,13 +67,6 @@ private: ImportList m_importList {}; }; -class QmlValueTypeNode : public Aggregate -{ -public: - QmlValueTypeNode(Aggregate *parent, const QString &name); - [[nodiscard]] bool isFirstClassAggregate() const override { return true; } -}; - QT_END_NAMESPACE #endif // QMLTYPENODE_H diff --git a/src/qdoc/qmlvisitor.cpp b/src/qdoc/qmlvisitor.cpp index ded3da8d4..a2d6c25af 100644 --- a/src/qdoc/qmlvisitor.cpp +++ b/src/qdoc/qmlvisitor.cpp @@ -480,7 +480,7 @@ bool QmlDocVisitor::visit(QQmlJS::AST::UiObjectDefinition *definition) if (candidate != nullptr) component = static_cast<QmlTypeNode *>(candidate); else - component = new QmlTypeNode(m_current, m_name); + component = new QmlTypeNode(m_current, m_name, Node::QmlType); component->setTitle(m_name); component->setImportList(m_importList); m_importList.clear(); diff --git a/src/qdoc/sections.cpp b/src/qdoc/sections.cpp index 616590047..f2be10de2 100644 --- a/src/qdoc/sections.cpp +++ b/src/qdoc/sections.cpp @@ -958,7 +958,7 @@ bool Sections::hasObsoleteMembers(SectionPtrVector *summary_spv, const SectionVector *sections = nullptr; if (m_aggregate->isClassNode()) sections = &stdCppClassSummarySections(); - else if (m_aggregate->isQmlType() || m_aggregate->isQmlBasicType()) + else if (m_aggregate->isQmlType()) sections = &stdQmlTypeSummarySections(); else sections = &stdSummarySections(); @@ -968,7 +968,7 @@ bool Sections::hasObsoleteMembers(SectionPtrVector *summary_spv, } if (m_aggregate->isClassNode()) sections = &stdCppClassDetailsSections(); - else if (m_aggregate->isQmlType() || m_aggregate->isQmlBasicType()) + else if (m_aggregate->isQmlType()) sections = &stdQmlTypeDetailsSections(); else sections = &stdDetailsSections(); diff --git a/src/qdoc/tree.h b/src/qdoc/tree.h index 7e1b9a131..b9dbebbd3 100644 --- a/src/qdoc/tree.h +++ b/src/qdoc/tree.h @@ -144,10 +144,6 @@ private: // The rest of the class is private. { return m_qmlTypeMap.value(name); } - [[nodiscard]] Aggregate *lookupQmlBasicType(const QString &name) const - { - return m_qmlTypeMap.value(name); - } void insertQmlType(const QString &key, QmlTypeNode *n); void addExampleNode(ExampleNode *n) { m_exampleNodeMap.insert(n->title(), n); } ExampleNodeMap &exampleNodeMap() { return m_exampleNodeMap; } diff --git a/tests/auto/qdoc/generatedoutput/expected_output/docbook/qdoc-test-qmlmodule.xml b/tests/auto/qdoc/generatedoutput/expected_output/docbook/qdoc-test-qmlmodule.xml index 340a83f53..cbdeb19b1 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/docbook/qdoc-test-qmlmodule.xml +++ b/tests/auto/qdoc/generatedoutput/expected_output/docbook/qdoc-test-qmlmodule.xml @@ -35,7 +35,7 @@ <db:varlistentry> <db:term><db:link xlink:href="qml-int.xml" xlink:role="">int</db:link></db:term> <db:listitem> -<db:para>An integer basic type.</db:para> +<db:para>An integer value type.</db:para> </db:listitem> </db:varlistentry> <db:varlistentry> diff --git a/tests/auto/qdoc/generatedoutput/expected_output/docbook/qml-int.xml b/tests/auto/qdoc/generatedoutput/expected_output/docbook/qml-int.xml index 00ef9ec39..c7ce09e55 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/docbook/qml-int.xml +++ b/tests/auto/qdoc/generatedoutput/expected_output/docbook/qml-int.xml @@ -1,13 +1,28 @@ <?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>int QML Basic Type</db:title> +<db:title>int QML Value Type</db:title> <db:productname>Test</db:productname> <db:titleabbrev>A test project for QDoc build artifacts</db:titleabbrev> <db:abstract> -<db:para>An integer basic type.</db:para> +<db:para>An integer value type.</db:para> +<db:para>This type was introduced in Qt 1.1.</db:para> </db:abstract> </db:info> +<db:variablelist> +<db:varlistentry> +<db:term>Import Statement</db:term> +<db:listitem> +<db:para>import QDoc.Test 1.1</db:para> +</db:listitem> +</db:varlistentry> +<db:varlistentry> +<db:term>Since:</db:term> +<db:listitem> +<db:para>Qt 1.1</db:para> +</db:listitem> +</db:varlistentry> +</db:variablelist> <db:section xml:id="details"> <db:title>Detailed Description</db:title> </db:section> diff --git a/tests/auto/qdoc/generatedoutput/expected_output/includefromexampledirs/index.html b/tests/auto/qdoc/generatedoutput/expected_output/includefromexampledirs/index.html index 027d13955..f6a73d1dc 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/includefromexampledirs/index.html +++ b/tests/auto/qdoc/generatedoutput/expected_output/includefromexampledirs/index.html @@ -18,7 +18,7 @@ <div class="table"><table class="annotated"> <tr class="odd topAlign"><td class="tblName" translate="no"><p><a href="qml-qdoc-test-abstractparent.html">AbstractParent</a></p></td><td class="tblDescr"><p>Abstract base QML type</p></td></tr> <tr class="even topAlign"><td class="tblName" translate="no"><p><a href="qml-qdoc-test-child.html">Child</a></p></td><td class="tblDescr"><p>A Child inheriting its parent</p></td></tr> -<tr class="odd topAlign"><td class="tblName" translate="no"><p><a href="qml-int.html">int</a></p></td><td class="tblDescr"><p>An integer basic type</p></td></tr> +<tr class="odd topAlign"><td class="tblName" translate="no"><p><a href="qml-int.html">int</a></p></td><td class="tblDescr"><p>An integer value type</p></td></tr> </table></div> <p>Test include file that is part of the sourcedirs.</p> </div> diff --git a/tests/auto/qdoc/generatedoutput/expected_output/qdoc-test-qmlmodule.html b/tests/auto/qdoc/generatedoutput/expected_output/qdoc-test-qmlmodule.html index 121d24018..a603ae147 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/qdoc-test-qmlmodule.html +++ b/tests/auto/qdoc/generatedoutput/expected_output/qdoc-test-qmlmodule.html @@ -20,7 +20,7 @@ <tr class="odd topAlign"><td class="tblName" translate="no"><p><a href="qml-qdoc-test-doctest.html">DocTest</a></p></td><td class="tblDescr"><p>Represents a doc test case</p></td></tr> <tr class="even topAlign"><td class="tblName" translate="no"><p><a href="qml-qdoc-test-type.html">Type</a></p></td><td class="tblDescr"><p>A QML type documented in a .cpp file</p></td></tr> <tr class="odd topAlign"><td class="tblName" translate="no"><p><a href="qml-qdoc-test-yetanotherchild.html">YetAnotherChild</a></p></td><td class="tblDescr"><p>A type inheriting from internal abstract parent</p></td></tr> -<tr class="even topAlign"><td class="tblName" translate="no"><p><a href="qml-int.html">int</a></p></td><td class="tblDescr"><p>An integer basic type</p></td></tr> +<tr class="even topAlign"><td class="tblName" translate="no"><p><a href="qml-int.html">int</a></p></td><td class="tblDescr"><p>An integer value type</p></td></tr> </table></div> </body> </html> diff --git a/tests/auto/qdoc/generatedoutput/expected_output/qml-int.html b/tests/auto/qdoc/generatedoutput/expected_output/qml-int.html index 53b91bc8b..8843b9474 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/qml-int.html +++ b/tests/auto/qdoc/generatedoutput/expected_output/qml-int.html @@ -3,7 +3,7 @@ <head> <meta charset="utf-8"> <!-- parent.qdoc --> - <title>int QML Basic Type | Test</title> + <title>int QML Value Type | Test</title> </head> <body> <li><a href="qdoc-test-qmlmodule.html" translate="no">Types</a></li> @@ -17,17 +17,17 @@ </ul> </div> <div class="sidebar-content" id="sidebar-content"></div></div> -<h1 class="title" translate="no">int QML Basic Type</h1> +<h1 class="title" translate="no">int QML Value Type</h1> <!-- $$$int-brief --> -<p>An integer basic type. <a href="#details">More...</a></p> +<p>An integer value type. <a href="#details">More...</a></p> <!-- @@@int --> -<h2 id="methods">Methods</h2> +<div class="table"><table class="alignedsummary" translate="no"> +<tr><td class="memItemLeft rightAlign topAlign"> Import Statement:</td><td class="memItemRight bottomAlign"> import QDoc.Test 1.1</td></tr><tr><td class="memItemLeft rightAlign topAlign"> Since:</td><td class="memItemRight bottomAlign"> Qt 1.1</td></tr></table></div><h2 id="methods">Methods</h2> <ul> <li class="fn" translate="no">int <b><a href="qml-int.html#abs-method" translate="no">abs</a></b>()</li> </ul> <!-- $$$int-description --> -<div class="descr" id="details"> -</div> +<h2 id="details">Detailed Description</h2> <!-- @@@int --> <h2>Method Documentation</h2> <!-- $$$abs[overload1]$$$abs --> diff --git a/tests/auto/qdoc/generatedoutput/expected_output/test.qhp b/tests/auto/qdoc/generatedoutput/expected_output/test.qhp index 484e167ce..417f5a7fb 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/test.qhp +++ b/tests/auto/qdoc/generatedoutput/expected_output/test.qhp @@ -49,6 +49,7 @@ <section ref="qml-qdoc-test-yetanotherchild.html" title="YetAnotherChild Type Reference"> <section ref="qml-qdoc-test-yetanotherchild-members.html" title="List of all members"/> </section> + <section ref="qml-int.html" title="int Type Reference"/> <section ref="qml-uicomponents-progressbar.html" title="ProgressBar Type Reference"> <section ref="qml-uicomponents-progressbar-members.html" title="List of all members"/> </section> @@ -58,7 +59,6 @@ <section ref="qml-uicomponents-tabwidget.html" title="TabWidget Type Reference"> <section ref="qml-uicomponents-tabwidget-members.html" title="List of all members"/> </section> - <section ref="qml-int.html" title="int Type Reference"/> </section> </section> </toc> @@ -127,6 +127,7 @@ <keyword name="id" id="Type::id" ref="qml-qdoc-test-type.html#id-prop"/> <keyword name="inlineFunction" id="Test::inlineFunction" ref="testqdoc-test.html#inlineFunction"/> <keyword name="int" id="QML.int" ref="qml-int.html"/> + <keyword name="int" id="QML.QDoc.Test1.int" ref="qml-int.html"/> <keyword name="itsHappening" id="DocTest::itsHappening" ref="qml-qdoc-test-doctest.html#itsHappening-signal"/> <keyword name="maximum" id="ProgressBar::maximum" ref="qml-uicomponents-progressbar.html#maximum-prop"/> <keyword name="methodWithEmDashInItsDocs" id="Test::methodWithEmDashInItsDocs" ref="testqdoc-test.html#methodWithEmDashInItsDocs"/> diff --git a/tests/auto/qdoc/generatedoutput/testdata/includefromexampledirs/src/includefromparent.qdoc b/tests/auto/qdoc/generatedoutput/testdata/includefromexampledirs/src/includefromparent.qdoc index bcf2788d5..ee3ccbe25 100644 --- a/tests/auto/qdoc/generatedoutput/testdata/includefromexampledirs/src/includefromparent.qdoc +++ b/tests/auto/qdoc/generatedoutput/testdata/includefromexampledirs/src/includefromparent.qdoc @@ -37,5 +37,5 @@ \qmlvaluetype int \inqmlmodule QDoc.Test \ingroup qmltypes - \brief An integer basic type. + \brief An integer value type. */ diff --git a/tests/auto/qdoc/generatedoutput/testdata/qml/parent.qdoc b/tests/auto/qdoc/generatedoutput/testdata/qml/parent.qdoc index db7ea37d8..d6bbb5738 100644 --- a/tests/auto/qdoc/generatedoutput/testdata/qml/parent.qdoc +++ b/tests/auto/qdoc/generatedoutput/testdata/qml/parent.qdoc @@ -58,7 +58,7 @@ \qmlvaluetype int \inqmlmodule QDoc.Test - \brief An integer basic type. + \brief An integer value type. */ /*! |