From 2efbf2dbbe1ff65c0624ba05a432d0e0e4a7d92f Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Tue, 6 Nov 2012 13:44:35 +0100 Subject: qdoc: Added module attribute to most index elements The index file generated by qdoc when it is run in -prepare mode has been modified so that most elements have a module attribute. The value of the module attribute either came from an \inmodule command, or it is the value of the project variable specified in the qdocconf file that was read by qdoc. Task number: QTBUG-27626 Change-Id: I44198bbbc1738fafc110c6b905eb1d67bc745323 Reviewed-by: Jerome Pasion --- src/tools/qdoc/codeparser.cpp | 76 +++++++++++++++++++++++++++++++++++++++ src/tools/qdoc/codeparser.h | 1 + src/tools/qdoc/cppcodeparser.cpp | 4 +-- src/tools/qdoc/generator.h | 1 + src/tools/qdoc/puredocparser.cpp | 1 + src/tools/qdoc/qdocdatabase.cpp | 9 +++-- src/tools/qdoc/qdocindexfiles.cpp | 18 ++++++++-- 7 files changed, 100 insertions(+), 10 deletions(-) (limited to 'src/tools') diff --git a/src/tools/qdoc/codeparser.cpp b/src/tools/qdoc/codeparser.cpp index 6ecca78a70..ea3bdc25f4 100644 --- a/src/tools/qdoc/codeparser.cpp +++ b/src/tools/qdoc/codeparser.cpp @@ -387,4 +387,80 @@ bool CodeParser::isParsingQdoc() const return currentFile_.endsWith(".qdoc"); } +/*! + For each node that will produce a documentation page, this function + ensures that the node belongs to a module. Normally, the qdoc comment + for an entity that will produce a documentation page will contain an + \inmodule command to tell qdoc which module the entity belongs to. + + But now that we normally run qdoc on each module in two passes. The + first produces an index file; the second pass generates the docs + after reading all the index files it needs. + + This means that all the pages generated during each pass 2 run of + qdoc almost certainly belong to a single module, and the name of + that module is, as a rule, used as the project name in the qdocconf + file used when running qdoc on the module. + + So this function first asks if the node \a n has a non-empty module + name. If it it does not have a non-empty module name, it sets the + module name to be the project name. + + In some cases it prints a qdoc warning that it has done this. Namely, + for C++ classes and namespaces. + */ +void CodeParser::checkModuleInclusion(Node* n) +{ + if (n->moduleName().isEmpty()) { + switch (n->type()) { + case Node::Class: + if (n->access() != Node::Private && !n->doc().isEmpty()) { + n->setModuleName(Generator::defaultModuleName()); + n->doc().location().warning(tr("Class %1 has no \\inmodule command; " + "using project name by default: %2") + .arg(n->name()).arg(Generator::defaultModuleName())); + } + break; + case Node::Namespace: + if (n->access() != Node::Private && !n->name().isEmpty() && !n->doc().isEmpty()) { + n->setModuleName(Generator::defaultModuleName()); + n->doc().location().warning(tr("Namespace %1 has no \\inmodule command; " + "using project name by default: %2") + .arg(n->name()).arg(Generator::defaultModuleName())); + } + break; + case Node::Document: + if (n->access() != Node::Private && !n->doc().isEmpty()) { + if (n->subType() == Node::HeaderFile) { + n->setModuleName(Generator::defaultModuleName()); +#if 0 + n->doc().location().warning(tr("Header file with title \"%1\" has no \\inmodule command; " + "using project name by default: %2") + .arg(n->title()).arg(Generator::defaultModuleName())); +#endif + } + else if (n->subType() == Node::Page) { + n->setModuleName(Generator::defaultModuleName()); +#if 0 + n->doc().location().warning(tr("Page with title \"%1\" has no \\inmodule command; " + "using project name by default: %2") + .arg(n->title()).arg(Generator::defaultModuleName())); +#endif + } + else if (n->subType() == Node::Example) { + n->setModuleName(Generator::defaultModuleName()); +#if 0 + n->doc().location().warning(tr("Example with title \"%1\" has no \\inmodule command; " + "using project name by default: %2") + .arg(n->title()).arg(Generator::defaultModuleName())); +#endif + } + } + break; + default: + break; + } + } +} + QT_END_NAMESPACE diff --git a/src/tools/qdoc/codeparser.h b/src/tools/qdoc/codeparser.h index 3d6bf89070..06839ffd80 100644 --- a/src/tools/qdoc/codeparser.h +++ b/src/tools/qdoc/codeparser.h @@ -72,6 +72,7 @@ public: bool isParsingCpp() const; bool isParsingQdoc() const; const QString& currentFile() const { return currentFile_; } + void checkModuleInclusion(Node* n); static void initialize(const Config& config); static void terminate(); diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp index d4fe0ff5f7..2fc3a6c477 100644 --- a/src/tools/qdoc/cppcodeparser.cpp +++ b/src/tools/qdoc/cppcodeparser.cpp @@ -2156,8 +2156,8 @@ bool CppCodeParser::matchDocsAndStuff() while (n != nodes.end()) { processOtherMetaCommands(*d, *n); (*n)->setDoc(*d); - if ((*n)->isInnerNode() && - ((InnerNode *)*n)->includes().isEmpty()) { + checkModuleInclusion(*n); + if ((*n)->isInnerNode() && ((InnerNode *)*n)->includes().isEmpty()) { InnerNode *m = static_cast(*n); while (m->parent() != qdb_->treeRoot()) m = m->parent(); diff --git a/src/tools/qdoc/generator.h b/src/tools/qdoc/generator.h index 3dc3b84767..8997ef0628 100644 --- a/src/tools/qdoc/generator.h +++ b/src/tools/qdoc/generator.h @@ -95,6 +95,7 @@ public: static void setQDocPass(Passes pass) { qdocPass_ = pass; } static bool runPrepareOnly() { return (qdocPass_ == Prepare); } static bool runGenerateOnly() { return (qdocPass_ == Generate); } + static QString defaultModuleName() { return project; } protected: virtual void beginSubPage(const InnerNode* node, const QString& fileName); diff --git a/src/tools/qdoc/puredocparser.cpp b/src/tools/qdoc/puredocparser.cpp index cd726c3497..9f76596e46 100644 --- a/src/tools/qdoc/puredocparser.cpp +++ b/src/tools/qdoc/puredocparser.cpp @@ -195,6 +195,7 @@ bool PureDocParser::processQdocComments() while (n != nodes.end()) { processOtherMetaCommands(*d, *n); (*n)->setDoc(*d); + checkModuleInclusion(*n); if ((*n)->isInnerNode() && ((InnerNode *)*n)->includes().isEmpty()) { InnerNode *m = static_cast(*n); while (m->parent() && m->parent() != treeRoot) diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index cb93a92d33..d5dbb84386 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -344,8 +344,9 @@ void QDocDatabase::findAllClasses(const InnerNode* node) } QString serviceName = (static_cast(*c))->serviceName(); - if (!serviceName.isEmpty()) + if (!serviceName.isEmpty()) { serviceClasses_.insert(serviceName, *c); + } } else if ((*c)->type() == Node::Document && (*c)->subType() == Node::QmlClass && @@ -418,12 +419,10 @@ void QDocDatabase::findAllNamespaces(const InnerNode* node) if ((*c)->isInnerNode()) { findAllNamespaces(static_cast(*c)); if ((*c)->type() == Node::Namespace) { - const NamespaceNode* nspace = static_cast(*c); // Ensure that the namespace's name is not empty (the root // namespace has no name). - if (!nspace->name().isEmpty()) { - namespaceIndex_.insert(nspace->name(), *c); - } + if (!(*c)->name().isEmpty()) + namespaceIndex_.insert((*c)->name(), *c); } } } diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp index 14dfa334ae..3f79675b3b 100644 --- a/src/tools/qdoc/qdocindexfiles.cpp +++ b/src/tools/qdoc/qdocindexfiles.cpp @@ -435,7 +435,9 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element, else section->setStatus(Node::Commendable); - section->setModuleName(element.attribute("module")); + QString moduleName = element.attribute("module"); + if (!moduleName.isEmpty()) + section->setModuleName(moduleName); if (!indexUrl.isEmpty()) { section->setUrl(indexUrl + QLatin1Char('/') + href); } @@ -660,11 +662,13 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, baseStrings.insert(baseClassNode->name()); } writer.writeAttribute("bases", QStringList(baseStrings.toList()).join(",")); - writer.writeAttribute("module", node->moduleName()); + if (!node->moduleName().isEmpty()) + writer.writeAttribute("module", node->moduleName()); } break; case Node::Namespace: - writer.writeAttribute("module", node->moduleName()); + if (!node->moduleName().isEmpty()) + writer.writeAttribute("module", node->moduleName()); break; case Node::Document: { @@ -672,25 +676,30 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, Document nodes (such as manual pages) contain subtypes, titles and other attributes. */ + bool writeModuleName = false; const DocNode* docNode = static_cast(node); switch (docNode->subType()) { case Node::Example: writer.writeAttribute("subtype", "example"); + writeModuleName = true; break; case Node::HeaderFile: writer.writeAttribute("subtype", "header"); + writeModuleName = true; break; case Node::File: writer.writeAttribute("subtype", "file"); break; case Node::Group: writer.writeAttribute("subtype", "group"); + writeModuleName = true; break; case Node::Module: writer.writeAttribute("subtype", "module"); break; case Node::Page: writer.writeAttribute("subtype", "page"); + writeModuleName = true; break; case Node::ExternalPage: writer.writeAttribute("subtype", "externalpage"); @@ -708,6 +717,9 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, writer.writeAttribute("fulltitle", docNode->fullTitle()); writer.writeAttribute("subtitle", docNode->subTitle()); writer.writeAttribute("location", docNode->doc().location().fileName()); + if (!node->moduleName().isEmpty() && writeModuleName) { + writer.writeAttribute("module", node->moduleName()); + } } break; case Node::Function: -- cgit v1.2.3