From a595ac15cd723dbfcdc5a9d4c318334d959a06f9 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Mon, 18 Feb 2013 13:55:37 +0100 Subject: Doc: Document example manifest files in QDoc manual Adds documentation for example manifest files and the related qdoc configuration command \manifestmeta into QDoc manual. Change-Id: I6a627698ab14f57c9a117b6d4b794f352959f5ac Reviewed-by: Martin Smith Reviewed-by: Jerome Pasion --- src/tools/qdoc/doc/qdoc-manual.qdoc | 93 +++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) (limited to 'src/tools/qdoc') diff --git a/src/tools/qdoc/doc/qdoc-manual.qdoc b/src/tools/qdoc/doc/qdoc-manual.qdoc index 4d70faa968..b715b200bf 100644 --- a/src/tools/qdoc/doc/qdoc-manual.qdoc +++ b/src/tools/qdoc/doc/qdoc-manual.qdoc @@ -65,6 +65,7 @@ \li \l {C++ Specific Configuration Variables} \li \l {HTML Specific Configuration Variables} \li \l {Supporting Derived Projects} + \li \l {Example Manifest Files} \li \l {qt.qdocconf} \li \l {minimum.qdocconf} \li \l {Generating DITA XML Output} @@ -7154,6 +7155,7 @@ \li \l {22-qdoc-configuration-generalvariables.html#images.fileextensions-variable} {images.fileextensions} \li \l {22-qdoc-configuration-generalvariables.html#language-variable} {language} \li \l {22-qdoc-configuration-generalvariables.html#macro-variable} {macro} + \li \l {22-qdoc-configuration-generalvariables.html#manifestmeta-variable} {manifestmeta} \li \l {22-qdoc-configuration-generalvariables.html#outputdir-variable} {outputdir} \li \l {22-qdoc-configuration-generalvariables.html#outputformats-variable} {outputformats} \li \l {22-qdoc-configuration-generalvariables.html#sourcedirs-variable} {sourcedirs} @@ -7850,6 +7852,14 @@ See also \l {alias-variable} {alias}. + \target manifestmeta-variable + \section1 manifestmeta + + The \c manifestmeta variable specifies additional meta-content + for the example manifest files generated by QDoc. + + See the \l{Manifest Meta Content} section for more information. + \target naturallanguage-variable \section1 naturallanguage @@ -8472,6 +8482,7 @@ \page 25-qdoc-configuration-derivedprojects.html \previouspage HTML Specific Configuration Variables \contentspage QDoc Manual + \nextpage Example Manifest Files \title Supporting Derived Projects @@ -8609,6 +8620,88 @@ write a new document. */ +/*! + \page 26-qdoc-configuration-example-manifest-files.html + \previouspage Supporting Derived Projects + \contentspage QDoc Manual + + \title Example Manifest Files + + QDoc generates XML files that contain information about all documented + examples and demos. These files, named \c {examples-manifest.xml} and + \c {demos-manifest.xml}, are used by Qt Creator to present a list of + examples in its welcome screen and to link to their documentation. + + \section1 Manifest XML Structure + + A manifest file has the following structure: + + \code + + + + + + analog,clock,window + gui/analogclock/main.cpp + + ... + + + \endcode + + Each \c {} element contains information about a name, + description, the location of the project file and documentation, + as well as a list of tags associated with the example. + + \target metacontent + \section1 Manifest Meta Content + + It is possible to augment the manifest files with additional + meta-content - that is, extra attributes and tags for selected + examples, using the \c manifestmeta configuration command. + + One use case for meta-content is highlighting a number of prominent + examples. Another is improving search functionality by adding + relevant keywords as tags for a certain category of examples. + + The examples for which meta-content is applied to is specified using + one or more filters. Matching examples to filters is done based on + names, with each example name prefixed with a module name and a + slash. Simple wildcard matching is supported; by using \c {*} at the + end it's possible to match multiple examples with a single string. + + Example: + + \code + manifestmeta.filters = highlighted sql webkit global + + manifestmeta.highlighted.names = "QtGui/Analog Clock Window Example" \ + "QtWidgets/Analog Clock Example" + manifestmeta.highlighted.attributes = isHighlighted:true + + manifestmeta.sql.names = "QtSql/*" + manifestmeta.sql.tags = database,sql + + manifestmeta.webkit.names = "QtWebKitExamples/*" + manifestmeta.webkit.tags = webkit + + manifestmeta.global.names = * + manifestmeta.global.tags = qt5 + \endcode + + Above, an \c isHighlighted attribute is added to two examples. If + the attribute value is omitted, QDoc uses the string \c {true} by + default. Extra tags are added for Qt WebKit and Qt SQL examples, and + another tag is applied to all examples by using just \c {*} as the + match string. +*/ + /*! \page 27-qdoc-commands-alphabetical.html \previouspage Introduction to QDoc -- cgit v1.2.3 From 2cb22c6cc01627700ebfb8d2528ab4f700917a9b Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Wed, 20 Feb 2013 12:03:32 +0100 Subject: qdoc: QML Inheritance is not resolved correctly. This change adds some QML property, signal, and method data to the .index file. It also provides more robust resolving of QML inheritance for qml types. Task-number: QTBUG-29778 Change-Id: Iaefd64227913a19f427b21e904ca5e32c82d7b29 Reviewed-by: Jerome Pasion --- src/tools/qdoc/cppcodemarker.cpp | 18 ++++--- src/tools/qdoc/ditaxmlgenerator.cpp | 5 +- src/tools/qdoc/htmlgenerator.cpp | 5 +- src/tools/qdoc/node.cpp | 11 +++-- src/tools/qdoc/node.h | 30 ++++++++++-- src/tools/qdoc/qdocdatabase.cpp | 96 +++++++++++++++++++++++++++++++++---- src/tools/qdoc/qdocdatabase.h | 1 + src/tools/qdoc/qdocindexfiles.cpp | 54 ++++++++++++++++++--- src/tools/qdoc/qmlvisitor.cpp | 41 +++++++++++----- src/tools/qdoc/qmlvisitor.h | 3 +- 10 files changed, 215 insertions(+), 49 deletions(-) (limited to 'src/tools/qdoc') diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp index c85c5c64ef..ff7d9254fc 100644 --- a/src/tools/qdoc/cppcodemarker.cpp +++ b/src/tools/qdoc/cppcodemarker.cpp @@ -1287,17 +1287,15 @@ QList
CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno } ++c; } - const DocNode* dn = current->qmlBaseNode(); - if (dn) { - if (dn->subType() == Node::QmlClass) - current = static_cast(dn); - else { - dn->doc().location().warning(tr("Base class of QML class '%1' is ambgiguous").arg(current->name())); - current = 0; - } + current = current->qmlBaseNode(); + while (current) { + if (current->isAbstract()) + break; + if (current->isInternal()) + current = current->qmlBaseNode(); + else + break; } - else - current = 0; } append(sections, all, true); } diff --git a/src/tools/qdoc/ditaxmlgenerator.cpp b/src/tools/qdoc/ditaxmlgenerator.cpp index 22694dd0d3..21bbdafaf5 100644 --- a/src/tools/qdoc/ditaxmlgenerator.cpp +++ b/src/tools/qdoc/ditaxmlgenerator.cpp @@ -4198,7 +4198,10 @@ void DitaXmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker* { if (!qcn) return; - const DocNode* base = qcn->qmlBaseNode(); + const QmlClassNode* base = qcn->qmlBaseNode(); + while (base && base->isInternal()) { + base = base->qmlBaseNode(); + } if (base) { writeStartTag(DT_qmlInherits); //writeStartTag(DT_qmlTypeDef); diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index 2666f10eb4..69d1a69d31 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -3870,7 +3870,10 @@ void HtmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker* mar { if (!qcn) return; - const DocNode* base = qcn->qmlBaseNode(); + const QmlClassNode* base = qcn->qmlBaseNode(); + while (base && base->isInternal()) { + base = base->qmlBaseNode(); + } if (base) { Text text; text << Atom::ParaLeft << "Inherits "; diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index 5fbdb487db..abb348eb51 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -2161,10 +2161,13 @@ void QmlClassNode::subclasses(const QString& base, NodeList& subs) This function splits \a arg on the blank character to get a QML module name and version number. It then spilts the version number on the '.' character to get a major version number and - a minor vrsion number. Both version numbers must be present. - It stores these components separately. If all three are found, - true is returned. If any of the three is not found or is not - correct, false is returned. + a minor vrsion number. Both major the major and minor version + numbers should be present, but the minor version number is not + absolutely necessary. + + It stores the three components separately in this node. If all + three are found, true is returned. If any of the three is not + found or is not in the correct format, false is returned. */ bool Node::setQmlModuleInfo(const QString& arg) { diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h index ecb3c5771e..f76b115416 100644 --- a/src/tools/qdoc/node.h +++ b/src/tools/qdoc/node.h @@ -65,7 +65,6 @@ typedef QList NodeList; typedef QMap NodeMap; typedef QMultiMap NodeMultiMap; typedef QMultiMap ExampleNodeMap; -typedef QList > ImportList; class Node { @@ -206,7 +205,7 @@ public: virtual bool hasProperty(const QString& ) const { return false; } virtual void getMemberNamespaces(NodeMap& ) { } virtual void getMemberClasses(NodeMap& ) { } - bool isInternal() const; + virtual bool isInternal() const; bool isIndexNode() const { return indexNodeFlag_; } bool wasSeen() const { return seen_; } Type type() const { return nodeType_; } @@ -530,6 +529,26 @@ private: QString imageFileName_; }; +struct ImportRec { + QString name_; // module name + QString version_; // . + QString importId_; // "as" name + QString importUri_; // subdirectory of module directory + + ImportRec(const QString& name, + const QString& version, + const QString& importId, + const QString& importUri) + : name_(name), version_(version), importId_(importId), importUri_(importUri) { } + QString& name() { return name_; } + QString& version() { return version_; } + QString& importId() { return importId_; } + QString& importUri() { return importUri_; } + bool isEmpty() const { return name_.isEmpty(); } +}; + +typedef QList ImportList; + class QmlClassNode : public DocNode { public: @@ -543,12 +562,13 @@ public: virtual void clearCurrentChild(); virtual bool isAbstract() const { return abstract_; } virtual void setAbstract(bool b) { abstract_ = b; } + virtual bool isInternal() const { return (status() == Internal); } const ImportList& importList() const { return importList_; } void setImportList(const ImportList& il) { importList_ = il; } const QString& qmlBaseName() const { return baseName_; } void setQmlBaseName(const QString& name) { baseName_ = name; } - const DocNode* qmlBaseNode() const { return baseNode_; } - void setQmlBaseNode(DocNode* b) { baseNode_ = b; } + const QmlClassNode* qmlBaseNode() const { return baseNode_; } + void setQmlBaseNode(QmlClassNode* b) { baseNode_ = b; } void requireCppClass() { cnodeRequired_ = true; } bool cppClassRequired() const { return cnodeRequired_; } static void addInheritedBy(const QString& base, Node* sub); @@ -564,7 +584,7 @@ private: bool cnodeRequired_; ClassNode* cnode_; QString baseName_; - DocNode* baseNode_; + QmlClassNode* baseNode_; ImportList importList_; }; diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index 4208d529c8..256bc62dd2 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -291,18 +291,29 @@ DocNode* QDocDatabase::addToModule(const QString& name, Node* node) */ DocNode* QDocDatabase::addToQmlModule(const QString& name, Node* node) { + QString longQmid, shortQmid; + QStringList dotSplit; + QStringList blankSplit = name.split(QLatin1Char(' ')); + if (blankSplit.size() > 1) { + longQmid = blankSplit[0] + blankSplit[1]; + dotSplit = blankSplit[1].split(QLatin1Char('.')); + shortQmid = blankSplit[0] + dotSplit[0]; + } DocNode* dn = findQmlModule(name); dn->addMember(node); node->setQmlModuleInfo(name); if (node->subType() == Node::QmlClass) { - QString t = node->qmlModuleIdentifier() + "::" + node->name(); QmlClassNode* n = static_cast(node); - if (!qmlTypeMap_.contains(t)) - qmlTypeMap_.insert(t,n); - if (!masterMap_.contains(t)) - masterMap_.insert(t,node); - if (!masterMap_.contains(node->name(),node)) - masterMap_.insert(node->name(),node); + QString key = longQmid + "::" + node->name(); + for (int i=0; i<2; ++i) { + if (!qmlTypeMap_.contains(key)) + qmlTypeMap_.insert(key,n); + if (!masterMap_.contains(key)) + masterMap_.insert(key,node); + if (!masterMap_.contains(node->name(),node)) + masterMap_.insert(node->name(),node); + key = shortQmid + "::" + node->name(); + } } return dn; } @@ -332,7 +343,45 @@ QmlClassNode* QDocDatabase::findQmlType(const QString& qmid, const QString& name } } return 0; +} +/*! + 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. + If a QML type node is not found, 0 is returned. + */ +QmlClassNode* QDocDatabase::findQmlType(const ImportRec& import, const QString& name) const +{ + if (!import.isEmpty()) { + QStringList dotSplit; + dotSplit = name.split(QLatin1Char('.')); + QString qmName; + if (import.importUri_.isEmpty()) + qmName = import.name_; + else + qmName = import.importUri_; + for (int i=0; i 1) { + int dot = import.version_.lastIndexOf(QChar('.')); + if (dot > 0) { + qmid = import.name_ + import.version_.left(dot); + qualifiedName = qmid + "::" + dotSplit[i]; + qcn = qmlTypeMap_.value(qualifiedName); + if (qcn) { + return qcn; + } + } + } + } + } + return 0; } /*! @@ -836,14 +885,23 @@ void QDocDatabase::resolveQmlInheritance(InnerNode* root) if (child->type() == Node::Document && child->subType() == Node::QmlClass) { QmlClassNode* qcn = static_cast(child); if ((qcn->qmlBaseNode() == 0) && !qcn->qmlBaseName().isEmpty()) { - QmlClassNode* bqcn = findQmlType(QString(), qcn->qmlBaseName()); + QmlClassNode* bqcn = 0; + const ImportList& imports = qcn->importList(); + for (int i=0; iqmlBaseName()); + if (bqcn) + break; + } + if (bqcn == 0) { + bqcn = findQmlType(QString(), qcn->qmlBaseName()); + } if (bqcn) { qcn->setQmlBaseNode(bqcn); } #if 0 else { - qDebug() << "Unable to resolve QML base type:" << qcn->qmlBaseName() - << "for QML type:" << qcn->name(); + qDebug() << "Temporary error message (ignore): UNABLE to resolve QML base type:" + << qcn->qmlBaseName() << "for QML type:" << qcn->name(); } #endif } @@ -851,6 +909,24 @@ void QDocDatabase::resolveQmlInheritance(InnerNode* root) } } +#if 0 +void QDocDatabase::resolveQmlInheritance(InnerNode* root) +{ + // Dop we need recursion? + foreach (Node* child, root->childNodes()) { + if (child->type() == Node::Document && child->subType() == Node::QmlClass) { + QmlClassNode* qcn = static_cast(child); + if ((qcn->qmlBaseNode() == 0) && !qcn->qmlBaseName().isEmpty()) { + QmlClassNode* bqcn = findQmlType(QString(), qcn->qmlBaseName()); + if (bqcn) { + qcn->setQmlBaseNode(bqcn); + } + } + } + } +} +#endif + /*! */ void QDocDatabase::resolveTargets(InnerNode* root) diff --git a/src/tools/qdoc/qdocdatabase.h b/src/tools/qdoc/qdocdatabase.h index 9c6810941d..19dde361f8 100644 --- a/src/tools/qdoc/qdocdatabase.h +++ b/src/tools/qdoc/qdocdatabase.h @@ -107,6 +107,7 @@ class QDocDatabase DocNode* addToQmlModule(const QString& name, Node* node); QmlClassNode* findQmlType(const QString& qmid, const QString& name) const; + QmlClassNode* findQmlType(const ImportRec& import, const QString& name) const; void findAllClasses(const InnerNode *node); void findAllFunctions(const InnerNode *node); diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp index 358c2a14d9..63d8639d0f 100644 --- a/src/tools/qdoc/qdocindexfiles.cpp +++ b/src/tools/qdoc/qdocindexfiles.cpp @@ -190,6 +190,9 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element, ((element.nodeName() == "page") && (element.attribute("subtype") == "qmlclass"))) { QmlClassNode* qcn = new QmlClassNode(parent, name); qcn->setTitle(element.attribute("title")); + QString qmlModuleName = element.attribute("qml-module-name"); + QString qmlModuleVersion = element.attribute("qml-module-version"); + qdb_->addToQmlModule(qmlModuleName + " " + qmlModuleVersion, qcn); if (element.hasAttribute("location")) name = element.attribute("location", QString()); if (!indexUrl.isEmpty()) @@ -209,6 +212,31 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element, location = Location(name); node = qbtn; } + else if (element.nodeName() == "qmlproperty") { + QmlClassNode* qcn = static_cast(parent); + QString type = element.attribute("type"); + bool attached = false; + if (element.attribute("attached") == "true") + attached = true; + bool readonly = false; + if (element.attribute("writable") == "false") + readonly = true; + QmlPropertyNode* qpn = new QmlPropertyNode(qcn, name, type, attached); + qpn->setReadOnly(readonly); + node = qpn; + } + else if ((element.nodeName() == "qmlmethod") || + (element.nodeName() == "qmlsignal") || + (element.nodeName() == "qmlsignalhandler")) { + Node::Type t = Node::QmlMethod; + if (element.nodeName() == "qmlsignal") + t = Node::QmlSignal; + else if (element.nodeName() == "qmlsignalhandler") + t = Node::QmlSignalHandler; + bool attached = false; + FunctionNode* fn = new FunctionNode(t, parent, name, attached); + node = fn; + } else if (element.nodeName() == "page") { Node::SubType subtype; Node::PageType ptype = Node::NoPageType; @@ -476,17 +504,22 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element, InnerNode* inner = static_cast(node); QDomElement child = element.firstChildElement(); while (!child.isNull()) { - if (element.nodeName() == "class") + if (element.nodeName() == "class") { readIndexSection(child, inner, indexUrl); - else if (element.nodeName() == "qmlclass") + } + else if (element.nodeName() == "qmlclass") { readIndexSection(child, inner, indexUrl); - else if (element.nodeName() == "page") + } + else if (element.nodeName() == "page") { readIndexSection(child, inner, indexUrl); - else if (element.nodeName() == "namespace" && !name.isEmpty()) + } + else if (element.nodeName() == "namespace" && !name.isEmpty()) { // The root node in the index is a namespace with an empty name. readIndexSection(child, inner, indexUrl); - else + } + else { readIndexSection(child, parent, indexUrl); + } child = child.nextSiblingElement(); } } @@ -562,6 +595,8 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, return false; QString nodeName; + QString qmlModuleName; + QString qmlModuleVersion; switch (node->type()) { case Node::Namespace: nodeName = "namespace"; @@ -571,8 +606,11 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, break; case Node::Document: nodeName = "page"; - if (node->subType() == Node::QmlClass) + if (node->subType() == Node::QmlClass) { nodeName = "qmlclass"; + qmlModuleName = node->qmlModuleName(); + qmlModuleVersion = node->qmlModuleVersion(); + } else if (node->subType() == Node::QmlBasicType) nodeName = "qmlbasictype"; break; @@ -687,6 +725,10 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, writer.writeAttribute("status", status); writer.writeAttribute("name", objName); + if (!qmlModuleName.isEmpty()) { + writer.writeAttribute("qml-module-name", qmlModuleName); + writer.writeAttribute("qml-module-version", qmlModuleVersion); + } QString fullName = node->fullDocumentName(); if (fullName != objName) writer.writeAttribute("fullname", fullName); diff --git a/src/tools/qdoc/qmlvisitor.cpp b/src/tools/qdoc/qmlvisitor.cpp index 15af03d9ba..8b6f81de3e 100644 --- a/src/tools/qdoc/qmlvisitor.cpp +++ b/src/tools/qdoc/qmlvisitor.cpp @@ -373,6 +373,24 @@ void QmlDocVisitor::applyMetacommands(QQmlJS::AST::SourceLocation, } } +/*! + Reconstruct the qualified \a id using dot notation + and return the fully qualified string. + */ +QString QmlDocVisitor::getFullyQualifiedId(QQmlJS::AST::UiQualifiedId *id) +{ + QString result; + if (id) { + result = id->name.toString(); + id = id->next; + while (id != 0) { + result += QChar('.') + id->name.toString(); + id = id->next; + } + } + return result; +} + /*! Begin the visit of the object \a definition, recording it in the qdoc database. Increment the object nesting level, which is used @@ -381,7 +399,7 @@ void QmlDocVisitor::applyMetacommands(QQmlJS::AST::SourceLocation, */ bool QmlDocVisitor::visit(QQmlJS::AST::UiObjectDefinition *definition) { - QString type = definition->qualifiedTypeNameId->name.toString(); + QString type = getFullyQualifiedId(definition->qualifiedTypeNameId); nestingLevel++; if (current->type() == Node::Namespace) { @@ -420,17 +438,18 @@ void QmlDocVisitor::endVisit(QQmlJS::AST::UiObjectDefinition *definition) */ bool QmlDocVisitor::visit(QQmlJS::AST::UiImportList *imports) { - QQmlJS::AST::UiImport* imp = imports->import; - quint32 length = imp->versionToken.offset - imp->fileNameToken.offset - 1; - QString module = document.mid(imp->fileNameToken.offset,length); - QString version = document.mid(imp->versionToken.offset, imp->versionToken.length); - if (version.size() > 1) { - int dot = version.lastIndexOf(QChar('.')); - if (dot > 0) - version = version.left(dot); + while (imports != 0) { + QQmlJS::AST::UiImport* imp = imports->import; + + QString name = document.mid(imp->fileNameToken.offset, imp->fileNameToken.length); + if (name[0] == '\"') + name = name.mid(1, name.length()-2); + QString version = document.mid(imp->versionToken.offset, imp->versionToken.length); + QString importId = document.mid(imp->importIdToken.offset, imp->importIdToken.length); + QString importUri = getFullyQualifiedId(imp->importUri); + importList.append(ImportRec(name, version, importId, importUri)); + imports = imports->next; } - importList.append(QPair(module, version)); - return true; } diff --git a/src/tools/qdoc/qmlvisitor.h b/src/tools/qdoc/qmlvisitor.h index 172aca579a..bfec61eb34 100644 --- a/src/tools/qdoc/qmlvisitor.h +++ b/src/tools/qdoc/qmlvisitor.h @@ -97,6 +97,7 @@ public: void endVisit(QQmlJS::AST::UiQualifiedId *); private: + QString getFullyQualifiedId(QQmlJS::AST::UiQualifiedId *id); QQmlJS::AST::SourceLocation precedingComment(quint32 offset) const; bool applyDocumentation(QQmlJS::AST::SourceLocation location, Node *node); void applyMetacommands(QQmlJS::AST::SourceLocation location, Node* node, Doc& doc); @@ -110,7 +111,7 @@ private: QString filePath; QString name; QString document; - QList > importList; + ImportList importList; QSet commands; QSet topics; QSet usedComments; -- cgit v1.2.3 From bfce04fe5bef507ed1360198d1b0b71665aa8a25 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Thu, 21 Feb 2013 12:53:06 +0100 Subject: doc: QML Inheritance is not resolved correctly. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qdoc did not resolve QML Inheritance correctly and the result was that QML inheritance was not shown correctly in the documentation. Part of the problem was that information was missing for QML types in the .index files produced by qdoc. qdoc also did not show inheritance properly when one of its base types was marked internal. These problems have now been fixed. This update also fixes the problem that caused qdoc to slow down to a snail's pace over time. The group members list for certain group pages was getting longer and longer, because qdoc added the same member to the member list an additional time every time qdoc was run in -prepare mode if you didn't clear the index files first. Now, qdoc only adds a member to the member list if it isn't already in the member list. Task-number: QTBUG-29778 Change-Id: Ie4f0458a2ea4ceb1a64cdcd7f60f16b124a20790 Reviewed-by: Topi Reiniƶ Reviewed-by: Jerome Pasion --- src/tools/qdoc/cppcodemarker.cpp | 9 ++++----- src/tools/qdoc/node.cpp | 24 ++++++++++++++++++++++++ src/tools/qdoc/node.h | 4 +++- src/tools/qdoc/qdocdatabase.cpp | 15 ++++++++++----- src/tools/qdoc/qdocindexfiles.cpp | 7 +++++++ 5 files changed, 48 insertions(+), 11 deletions(-) (limited to 'src/tools/qdoc') diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp index ff7d9254fc..f0cfc18515 100644 --- a/src/tools/qdoc/cppcodemarker.cpp +++ b/src/tools/qdoc/cppcodemarker.cpp @@ -1259,7 +1259,6 @@ QList
CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno } else { FastSection all(qmlClassNode,QString(),QString(),"member","members"); - const QmlClassNode* current = qmlClassNode; while (current != 0) { NodeList::ConstIterator c = current->childNodes().constBegin(); @@ -1271,9 +1270,9 @@ QList
CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno if ((*p)->type() == Node::QmlProperty) { QString key = current->name() + "::" + (*p)->name(); key = sortName(*p, &key); - if (!all.memberMap.contains(key)) + if (!all.memberMap.contains(key)) { all.memberMap.insert(key,*p); - //insert(all,*p,style,Okay); + } } ++p; } @@ -1281,9 +1280,9 @@ QList
CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno else { QString key = current->name() + "::" + (*c)->name(); key = sortName(*c, &key); - if (!all.memberMap.contains(key)) + if (!all.memberMap.contains(key)) { all.memberMap.insert(key,*c); - //insert(all,*c,style,Okay); + } } ++c; } diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index abb348eb51..c293d48673 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -661,6 +661,16 @@ bool InnerNode::hasMembers() const return !members_.isEmpty(); } +/*! + Appends \a node to the members list, if and only if it + isn't already in the members list. + */ +void InnerNode::addMember(Node* node) +{ + if (!members_.contains(node)) + members_.append(node); +} + /*! Returns true if this node's members collection contains at least one namespace node. @@ -2187,6 +2197,20 @@ bool Node::setQmlModuleInfo(const QString& arg) return false; } +/*! + If this QML type node has a base type node, + return the fully qualified name of that QML + type, i.e. ::. + */ +QString QmlClassNode::qmlFullBaseName() const +{ + QString result; + if (baseNode_) { + result = baseNode_->qmlModuleIdentifier() + "::" + baseNode_->name(); + } + return result; +} + /*! The name of this QML class node might be the same as the name of some other QML class node. If so, then this node's diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h index f76b115416..4802b6de54 100644 --- a/src/tools/qdoc/node.h +++ b/src/tools/qdoc/node.h @@ -240,6 +240,7 @@ public: QString guid() const; QString extractClassName(const QString &string) const; virtual QString qmlTypeName() const { return name_; } + virtual QString qmlFullBaseName() const { return QString(); } virtual QString qmlModuleName() const { return qmlModuleName_; } virtual QString qmlModuleVersion() const { return qmlModuleVersionMajor_ + "." + qmlModuleVersionMinor_; } virtual QString qmlModuleIdentifier() const { return qmlModuleName_ + qmlModuleVersionMajor_; } @@ -332,7 +333,7 @@ public: const NodeList & childNodes() const { return children_; } const NodeList & relatedNodes() const { return related_; } - virtual void addMember(Node* node) { members_.append(node); } + virtual void addMember(Node* node); const NodeList& members() const { return members_; } virtual bool hasMembers() const; virtual bool hasNamespaces() const; @@ -563,6 +564,7 @@ public: virtual bool isAbstract() const { return abstract_; } virtual void setAbstract(bool b) { abstract_ = b; } virtual bool isInternal() const { return (status() == Internal); } + virtual QString qmlFullBaseName() const; const ImportList& importList() const { return importList_; } void setImportList(const ImportList& il) { importList_ = il; } const QString& qmlBaseName() const { return baseName_; } diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index 256bc62dd2..58c674de7a 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -886,11 +886,16 @@ void QDocDatabase::resolveQmlInheritance(InnerNode* root) QmlClassNode* qcn = static_cast(child); if ((qcn->qmlBaseNode() == 0) && !qcn->qmlBaseName().isEmpty()) { QmlClassNode* bqcn = 0; - const ImportList& imports = qcn->importList(); - for (int i=0; iqmlBaseName()); - if (bqcn) - break; + if (qcn->qmlBaseName().contains("::")) { + bqcn = qmlTypeMap_.value(qcn->qmlBaseName()); + } + else { + const ImportList& imports = qcn->importList(); + for (int i=0; iqmlBaseName()); + if (bqcn) + break; + } } if (bqcn == 0) { bqcn = findQmlType(QString(), qcn->qmlBaseName()); diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp index 63d8639d0f..466742ee3a 100644 --- a/src/tools/qdoc/qdocindexfiles.cpp +++ b/src/tools/qdoc/qdocindexfiles.cpp @@ -193,6 +193,9 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element, QString qmlModuleName = element.attribute("qml-module-name"); QString qmlModuleVersion = element.attribute("qml-module-version"); qdb_->addToQmlModule(qmlModuleName + " " + qmlModuleVersion, qcn); + QString qmlFullBaseName = element.attribute("qml-base-type"); + if (!qmlFullBaseName.isEmpty()) + qcn->setQmlBaseName(qmlFullBaseName); if (element.hasAttribute("location")) name = element.attribute("location", QString()); if (!indexUrl.isEmpty()) @@ -597,6 +600,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, QString nodeName; QString qmlModuleName; QString qmlModuleVersion; + QString qmlFullBaseName; switch (node->type()) { case Node::Namespace: nodeName = "namespace"; @@ -610,6 +614,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, nodeName = "qmlclass"; qmlModuleName = node->qmlModuleName(); qmlModuleVersion = node->qmlModuleVersion(); + qmlFullBaseName = node->qmlFullBaseName(); } else if (node->subType() == Node::QmlBasicType) nodeName = "qmlbasictype"; @@ -728,6 +733,8 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, if (!qmlModuleName.isEmpty()) { writer.writeAttribute("qml-module-name", qmlModuleName); writer.writeAttribute("qml-module-version", qmlModuleVersion); + if (!qmlFullBaseName.isEmpty()) + writer.writeAttribute("qml-base-type", qmlFullBaseName); } QString fullName = node->fullDocumentName(); if (fullName != objName) -- cgit v1.2.3