diff options
Diffstat (limited to 'src/tools/qdoc/qdocindexfiles.cpp')
-rw-r--r-- | src/tools/qdoc/qdocindexfiles.cpp | 1561 |
1 files changed, 0 insertions, 1561 deletions
diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp deleted file mode 100644 index 226280132f..0000000000 --- a/src/tools/qdoc/qdocindexfiles.cpp +++ /dev/null @@ -1,1561 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdom.h" -#include "qxmlstream.h" -#include "qdocindexfiles.h" -#include "qdoctagfiles.h" -#include "config.h" -#include "qdocdatabase.h" -#include "location.h" -#include "atom.h" -#include "generator.h" -#include <qdebug.h> - -#include <algorithm> - -QT_BEGIN_NAMESPACE - -static Node* top = 0; - -/*! - \class QDocIndexFiles - - This class handles qdoc index files. - */ - -QDocIndexFiles* QDocIndexFiles::qdocIndexFiles_ = NULL; - -/*! - Constructs the singleton QDocIndexFiles. - */ -QDocIndexFiles::QDocIndexFiles() - : gen_( 0 ) -{ - qdb_ = QDocDatabase::qdocDB(); -} - -/*! - Destroys the singleton QDocIndexFiles. - */ -QDocIndexFiles::~QDocIndexFiles() -{ - qdb_ = 0; - gen_ = 0; -} - -/*! - Creates the singleton. Allows only one instance of the class - to be created. Returns a pointer to the singleton. - */ -QDocIndexFiles* QDocIndexFiles::qdocIndexFiles() -{ - if (!qdocIndexFiles_) - qdocIndexFiles_ = new QDocIndexFiles; - return qdocIndexFiles_; -} - -/*! - Destroys the singleton. - */ -void QDocIndexFiles::destroyQDocIndexFiles() -{ - if (qdocIndexFiles_) { - delete qdocIndexFiles_; - qdocIndexFiles_ = 0; - } -} - -/*! - Reads and parses the list of index files in \a indexFiles. - */ -void QDocIndexFiles::readIndexes(const QStringList& indexFiles) -{ - foreach (const QString& indexFile, indexFiles) { - QString msg = "Loading index file: " + indexFile; - Location::logToStdErr(msg); - //qDebug() << msg; - readIndexFile(indexFile); - } -} - -static bool readingRoot = true; - -/*! - Reads and parses the index file at \a path. - */ -void QDocIndexFiles::readIndexFile(const QString& path) -{ - QFile file(path); - if (file.open(QFile::ReadOnly)) { - QDomDocument document; - document.setContent(&file); - file.close(); - - QDomElement indexElement = document.documentElement(); - - // Generate a relative URL between the install dir and the index file - // when the -installdir command line option is set. - QString indexUrl; - if (Config::installDir.isEmpty()) { - indexUrl = indexElement.attribute("url", QString()); - } - else { - // Use a fake directory, since we will copy the output to a sub directory of - // installDir when using "make install". This is just for a proper relative path. - //QDir installDir(path.section('/', 0, -3) + "/outputdir"); - QDir installDir(path.section('/', 0, -3) + '/' + Generator::outputSubdir()); - indexUrl = installDir.relativeFilePath(path).section('/', 0, -2); - } - project_ = indexElement.attribute("project", QString()); - - basesList_.clear(); - relatedList_.clear(); - - readingRoot = true; - NamespaceNode* root = qdb_->newIndexTree(project_); - - // Scan all elements in the XML file, constructing a map that contains - // base classes for each class found. - QDomElement child = indexElement.firstChildElement(); - while (!child.isNull()) { - readIndexSection(child, root, indexUrl); - child = child.nextSiblingElement(); - readingRoot = true; - } - - // Now that all the base classes have been found for this index, - // arrange them into an inheritance hierarchy. - resolveIndex(); - } -} - -/*! - Read a <section> element from the index file and create the - appropriate node(s). - */ -void QDocIndexFiles::readIndexSection(const QDomElement& element, - Node* current, - const QString& indexUrl) -{ - QString name = element.attribute("name"); - QString href = element.attribute("href"); - Node* node; - Location location; - InnerNode* parent = 0; - if (current->isInnerNode()) - parent = static_cast<InnerNode*>(current); - - QString filePath; - int lineNo = 0; - if (element.hasAttribute("filepath")) { - filePath = element.attribute("filepath", QString()); - lineNo = element.attribute("lineno", QString()).toInt(); - } - if (element.nodeName() == "namespace") { - node = new NamespaceNode(parent, name); - - if (!indexUrl.isEmpty()) - location = Location(indexUrl + QLatin1Char('/') + name.toLower() + ".html"); - else if (!indexUrl.isNull()) - location = Location(name.toLower() + ".html"); - - } - else if (element.nodeName() == "class") { - node = new ClassNode(parent, name); - if (element.hasAttribute("bases")) { - QString bases = element.attribute("bases"); - if (!bases.isEmpty()) - basesList_.append(QPair<ClassNode*,QString>(static_cast<ClassNode*>(node), bases)); - } - if (!indexUrl.isEmpty()) - location = Location(indexUrl + QLatin1Char('/') + name.toLower() + ".html"); - else if (!indexUrl.isNull()) - location = Location(name.toLower() + ".html"); - bool abstract = false; - if (element.attribute("abstract") == "true") - abstract = true; - node->setAbstract(abstract); - } - else if (element.nodeName() == "qmlclass") { - QmlTypeNode* qcn = new QmlTypeNode(parent, name); - qcn->setTitle(element.attribute("title")); - QString logicalModuleName = element.attribute("qml-module-name"); - if (!logicalModuleName.isEmpty()) - qdb_->addToQmlModule(logicalModuleName, qcn); - bool abstract = false; - if (element.attribute("abstract") == "true") - abstract = true; - qcn->setAbstract(abstract); - 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()) - location = Location(indexUrl + QLatin1Char('/') + name); - else if (!indexUrl.isNull()) - location = Location(name); - node = qcn; - } - else if (element.nodeName() == "jstype") { - QmlTypeNode* qcn = new QmlTypeNode(parent, name); - qcn->setGenus(Node::JS); - qcn->setTitle(element.attribute("title")); - QString logicalModuleName = element.attribute("js-module-name"); - if (!logicalModuleName.isEmpty()) - qdb_->addToQmlModule(logicalModuleName, qcn); - bool abstract = false; - if (element.attribute("abstract") == "true") - abstract = true; - qcn->setAbstract(abstract); - QString qmlFullBaseName = element.attribute("js-base-type"); - if (!qmlFullBaseName.isEmpty()) { - qcn->setQmlBaseName(qmlFullBaseName); - } - if (element.hasAttribute("location")) - name = element.attribute("location", QString()); - if (!indexUrl.isEmpty()) - location = Location(indexUrl + QLatin1Char('/') + name); - else if (!indexUrl.isNull()) - location = Location(name); - node = qcn; - } - else if (element.nodeName() == "qmlbasictype") { - QmlBasicTypeNode* qbtn = new QmlBasicTypeNode(parent, name); - qbtn->setTitle(element.attribute("title")); - if (element.hasAttribute("location")) - name = element.attribute("location", QString()); - if (!indexUrl.isEmpty()) - location = Location(indexUrl + QLatin1Char('/') + name); - else if (!indexUrl.isNull()) - location = Location(name); - node = qbtn; - } - else if (element.nodeName() == "jsbasictype") { - QmlBasicTypeNode* qbtn = new QmlBasicTypeNode(parent, name); - qbtn->setGenus(Node::JS); - qbtn->setTitle(element.attribute("title")); - if (element.hasAttribute("location")) - name = element.attribute("location", QString()); - if (!indexUrl.isEmpty()) - location = Location(indexUrl + QLatin1Char('/') + name); - else if (!indexUrl.isNull()) - location = Location(name); - node = qbtn; - } - else if (element.nodeName() == "qmlpropertygroup") { - QmlTypeNode* qcn = static_cast<QmlTypeNode*>(parent); - QmlPropertyGroupNode* qpgn = new QmlPropertyGroupNode(qcn, name); - if (element.hasAttribute("location")) - name = element.attribute("location", QString()); - if (!indexUrl.isEmpty()) - location = Location(indexUrl + QLatin1Char('/') + name); - else if (!indexUrl.isNull()) - location = Location(name); - node = qpgn; - } - else if (element.nodeName() == "jspropertygroup") { - QmlTypeNode* qcn = static_cast<QmlTypeNode*>(parent); - QmlPropertyGroupNode* qpgn = new QmlPropertyGroupNode(qcn, name); - qpgn->setGenus(Node::JS); - if (element.hasAttribute("location")) - name = element.attribute("location", QString()); - if (!indexUrl.isEmpty()) - location = Location(indexUrl + QLatin1Char('/') + name); - else if (!indexUrl.isNull()) - location = Location(name); - node = qpgn; - } - else if (element.nodeName() == "qmlproperty") { - 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 = 0; - if (parent->isQmlType()) { - QmlTypeNode* qcn = static_cast<QmlTypeNode*>(parent); - qpn = new QmlPropertyNode(qcn, name, type, attached); - } - else if (parent->isQmlPropertyGroup()) { - QmlPropertyGroupNode* qpgn = static_cast<QmlPropertyGroupNode*>(parent); - qpn = new QmlPropertyNode(qpgn, name, type, attached); - } - qpn->setReadOnly(readonly); - node = qpn; - } - else if (element.nodeName() == "jsproperty") { - 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 = 0; - if (parent->isJsType()) { - QmlTypeNode* qcn = static_cast<QmlTypeNode*>(parent); - qpn = new QmlPropertyNode(qcn, name, type, attached); - } - else if (parent->isJsPropertyGroup()) { - QmlPropertyGroupNode* qpgn = static_cast<QmlPropertyGroupNode*>(parent); - qpn = new QmlPropertyNode(qpgn, name, type, attached); - } - qpn->setGenus(Node::JS); - 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() == "jsmethod") || - (element.nodeName() == "jssignal") || - (element.nodeName() == "jssignalhandler")) { - Node::Type t = Node::QmlMethod; - if (element.nodeName() == "jssignal") - t = Node::QmlSignal; - else if (element.nodeName() == "jssignalhandler") - t = Node::QmlSignalHandler; - bool attached = false; - FunctionNode* fn = new FunctionNode(t, parent, name, attached); - fn->setGenus(Node::JS); - node = fn; - } - else if (element.nodeName() == "group") { - CollectionNode* cn = qdb_->addGroup(name); - cn->setTitle(element.attribute("title")); - cn->setSubTitle(element.attribute("subtitle")); - if (element.attribute("seen") == "true") - cn->markSeen(); - node = cn; - } - else if (element.nodeName() == "module") { - CollectionNode* cn = qdb_->addModule(name); - cn->setTitle(element.attribute("title")); - cn->setSubTitle(element.attribute("subtitle")); - if (element.attribute("seen") == "true") - cn->markSeen(); - node = cn; - } - else if (element.nodeName() == "qmlmodule") { - QString t = element.attribute("qml-module-name"); - CollectionNode* cn = qdb_->addQmlModule(t); - QStringList info; - info << t << element.attribute("qml-module-version"); - cn->setLogicalModuleInfo(info); - cn->setTitle(element.attribute("title")); - cn->setSubTitle(element.attribute("subtitle")); - if (element.attribute("seen") == "true") - cn->markSeen(); - node = cn; - } - else if (element.nodeName() == "jsmodule") { - QString t = element.attribute("js-module-name"); - CollectionNode* cn = qdb_->addJsModule(t); - QStringList info; - info << t << element.attribute("js-module-version"); - cn->setLogicalModuleInfo(info); - cn->setTitle(element.attribute("title")); - cn->setSubTitle(element.attribute("subtitle")); - if (element.attribute("seen") == "true") - cn->markSeen(); - node = cn; - } - else if (element.nodeName() == "page") { - Node::SubType subtype; - Node::PageType ptype = Node::NoPageType; - QString attr = element.attribute("subtype"); - if (attr == "example") { - subtype = Node::Example; - ptype = Node::ExamplePage; - } - else if (attr == "header") { - subtype = Node::HeaderFile; - ptype = Node::ApiPage; - } - else if (attr == "file") { - subtype = Node::File; - ptype = Node::NoPageType; - } - else if (attr == "page") { - subtype = Node::Page; - ptype = Node::ArticlePage; - } - else if (attr == "externalpage") { - subtype = Node::ExternalPage; - ptype = Node::ArticlePage; - } - else - return; - - DocumentNode* docNode = new DocumentNode(parent, name, subtype, ptype); - docNode->setTitle(element.attribute("title")); - - if (element.hasAttribute("location")) - name = element.attribute("location", QString()); - - if (!indexUrl.isEmpty()) - location = Location(indexUrl + QLatin1Char('/') + name); - else if (!indexUrl.isNull()) - location = Location(name); - - node = docNode; - - } - else if (element.nodeName() == "enum") { - EnumNode* enumNode = new EnumNode(parent, name); - - if (!indexUrl.isEmpty()) - location = Location(indexUrl + QLatin1Char('/') + parent->name().toLower() + ".html"); - else if (!indexUrl.isNull()) - location = Location(parent->name().toLower() + ".html"); - - QDomElement child = element.firstChildElement("value"); - while (!child.isNull()) { - EnumItem item(child.attribute("name"), child.attribute("value")); - enumNode->addItem(item); - child = child.nextSiblingElement("value"); - } - - node = enumNode; - - } - else if (element.nodeName() == "typedef") { - node = new TypedefNode(parent, name); - - if (!indexUrl.isEmpty()) - location = Location(indexUrl + QLatin1Char('/') + parent->name().toLower() + ".html"); - else if (!indexUrl.isNull()) - location = Location(parent->name().toLower() + ".html"); - - } - else if (element.nodeName() == "property") { - node = new PropertyNode(parent, name); - - if (!indexUrl.isEmpty()) - location = Location(indexUrl + QLatin1Char('/') + parent->name().toLower() + ".html"); - else if (!indexUrl.isNull()) - location = Location(parent->name().toLower() + ".html"); - - } - else if (element.nodeName() == "function") { - FunctionNode::Virtualness virt; - QString t = element.attribute("virtual"); - if (t == "non") - virt = FunctionNode::NonVirtual; - else if (t == "impure") - virt = FunctionNode::ImpureVirtual; - else if (t == "pure") - virt = FunctionNode::PureVirtual; - else - return; - - t = element.attribute("meta"); - FunctionNode::Metaness meta; - if (t == "plain") - meta = FunctionNode::Plain; - else if (t == "signal") - meta = FunctionNode::Signal; - else if (t == "slot") - meta = FunctionNode::Slot; - else if (t == "constructor") - meta = FunctionNode::Ctor; - else if (t == "destructor") - meta = FunctionNode::Dtor; - else if (t == "macro") - meta = FunctionNode::MacroWithParams; - else if (t == "macrowithparams") - meta = FunctionNode::MacroWithParams; - else if (t == "macrowithoutparams") - meta = FunctionNode::MacroWithoutParams; - else - return; - - FunctionNode* functionNode = new FunctionNode(parent, name); - functionNode->setReturnType(element.attribute("return")); - functionNode->setVirtualness(virt); - functionNode->setMetaness(meta); - functionNode->setConst(element.attribute("const") == "true"); - functionNode->setStatic(element.attribute("static") == "true"); - functionNode->setOverload(element.attribute("overload") == "true"); - - if (element.hasAttribute("relates") - && element.attribute("relates") != parent->name()) { - relatedList_.append( - QPair<FunctionNode*,QString>(functionNode, - element.attribute("relates"))); - } - /* - Note: The "signature" attribute was written to the - index file, but it is not read back in. Is that ok? - */ - - QDomElement child = element.firstChildElement("parameter"); - while (!child.isNull()) { - // Do not use the default value for the parameter; it is not - // required, and has been known to cause problems. - Parameter parameter(child.attribute("left"), - child.attribute("right"), - child.attribute("name"), - QString()); // child.attribute("default") - functionNode->addParameter(parameter); - child = child.nextSiblingElement("parameter"); - } - - node = functionNode; - if (!indexUrl.isEmpty()) - location = Location(indexUrl + QLatin1Char('/') + parent->name().toLower() + ".html"); - else if (!indexUrl.isNull()) - location = Location(parent->name().toLower() + ".html"); - } - else if (element.nodeName() == "variable") { - node = new VariableNode(parent, name); - if (!indexUrl.isEmpty()) - location = Location(indexUrl + QLatin1Char('/') + parent->name().toLower() + ".html"); - else if (!indexUrl.isNull()) - location = Location(parent->name().toLower() + ".html"); - } - else if (element.nodeName() == "keyword") { - QString title = element.attribute("title"); - qdb_->insertTarget(name, title, TargetRec::Keyword, current, 1); - return; - } - else if (element.nodeName() == "target") { - QString title = element.attribute("title"); - qdb_->insertTarget(name, title, TargetRec::Target, current, 2); - return; - } - else if (element.nodeName() == "contents") { - QString title = element.attribute("title"); - qdb_->insertTarget(name, title, TargetRec::Contents, current, 3); - return; - } - else - return; - - QString access = element.attribute("access"); - if (access == "public") - node->setAccess(Node::Public); - else if (access == "protected") - node->setAccess(Node::Protected); - else if ((access == "private") || (access == "internal")) - node->setAccess(Node::Private); - else - node->setAccess(Node::Public); - - if ((element.nodeName() != "page") && - (element.nodeName() != "qmlclass") && - (element.nodeName() != "qmlbasictype") && - (element.nodeName() != "jstype") && - (element.nodeName() != "jsbasictype")) { - QString threadSafety = element.attribute("threadsafety"); - if (threadSafety == "non-reentrant") - node->setThreadSafeness(Node::NonReentrant); - else if (threadSafety == "reentrant") - node->setThreadSafeness(Node::Reentrant); - else if (threadSafety == "thread safe") - node->setThreadSafeness(Node::ThreadSafe); - else - node->setThreadSafeness(Node::UnspecifiedSafeness); - } - else - node->setThreadSafeness(Node::UnspecifiedSafeness); - - QString status = element.attribute("status"); - if (status == "compat") - node->setStatus(Node::Compat); - else if (status == "obsolete") - node->setStatus(Node::Obsolete); - else if (status == "deprecated") - node->setStatus(Node::Obsolete); - else if (status == "preliminary") - node->setStatus(Node::Preliminary); - else if (status == "commendable") - node->setStatus(Node::Commendable); - else if (status == "internal") - node->setStatus(Node::Internal); - else - node->setStatus(Node::Commendable); - - QString physicalModuleName = element.attribute("module"); - if (!physicalModuleName.isEmpty()) - qdb_->addToModule(physicalModuleName, node); - if (!href.isEmpty()) { - if (node->isExternalPage()) - node->setUrl(href); - else if (!indexUrl.isEmpty()) - node->setUrl(indexUrl + QLatin1Char('/') + href); - } - - QString since = element.attribute("since"); - if (!since.isEmpty()) { - node->setSince(since); - } - - QString groupsAttr = element.attribute("groups"); - if (!groupsAttr.isEmpty()) { - QStringList groupNames = groupsAttr.split(","); - foreach (const QString &name, groupNames) { - qdb_->addToGroup(name, node); - } - } - - // Create some content for the node. - QSet<QString> emptySet; - Location t(filePath); - if (!filePath.isEmpty()) { - t.setLineNo(lineNo); - node->setLocation(t); - location = t; - } - Doc doc(location, location, " ", emptySet, emptySet); // placeholder - node->setDoc(doc); - node->setIndexNodeFlag(); - node->setOutputSubdirectory(project_.toLower()); - QString briefAttr = element.attribute("brief"); - if (!briefAttr.isEmpty()) { - node->setReconstitutedBrief(briefAttr); - } - - bool useParent = (element.nodeName() == "namespace" && name.isEmpty()); - if (element.hasChildNodes()) { - QDomElement child = element.firstChildElement(); - while (!child.isNull()) { - if (useParent) - readIndexSection(child, parent, indexUrl); - else - readIndexSection(child, node, indexUrl); - child = child.nextSiblingElement(); - } - } -} - -/*! - This function tries to resolve class inheritance immediately - after the index file is read. It is not always possible to - resolve a class inheritance at this point, because the base - class might be in an index file that hasn't been read yet, or - it might be in one of the header files that will be read for - the current module. These cases will be resolved after all - the index files and header and source files have been read, - just prior to beginning the generate phase for the current - module. - - I don't think this is completely correct because it always - sets the access to public. - */ -void QDocIndexFiles::resolveIndex() -{ - QPair<ClassNode*,QString> pair; - foreach (pair, basesList_) { - foreach (const QString& base, pair.second.split(QLatin1Char(','))) { - QStringList basePath = base.split(QString("::")); - Node* n = qdb_->findClassNode(basePath); - if (n) - pair.first->addResolvedBaseClass(Node::Public, static_cast<ClassNode*>(n)); - else - pair.first->addUnresolvedBaseClass(Node::Public, basePath, QString()); - } - } - - QPair<FunctionNode*,QString> relatedPair; - foreach (relatedPair, relatedList_) { - QStringList path = relatedPair.second.split("::"); - Node* n = qdb_->findRelatesNode(path); - if (n) - relatedPair.first->setRelates(static_cast<ClassNode*>(n)); - } - - // No longer needed. - basesList_.clear(); - relatedList_.clear(); -} - -/*! - Generate the index section with the given \a writer for the \a node - specified, returning true if an element was written; otherwise returns - false. - */ -bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, - Node* node, - bool generateInternalNodes) -{ - /* - Don't include index nodes in a new index file. Or DITA map nodes. - */ - if (node->isIndexNode() || node->subType() == Node::DitaMap) - return false; - - QString nodeName; - QString logicalModuleName; - QString logicalModuleVersion; - QString qmlFullBaseName; - switch (node->type()) { - case Node::Namespace: - nodeName = "namespace"; - break; - case Node::Class: - nodeName = "class"; - break; - case Node::QmlType: - { - if (node->isQmlNode()) - nodeName = "qmlclass"; - else - nodeName = "jstype"; - CollectionNode* cn = node->logicalModule(); - if (cn) - logicalModuleName = cn->logicalModuleName(); - qmlFullBaseName = node->qmlFullBaseName(); - } - break; - case Node::QmlBasicType: - if (node->isQmlNode()) - nodeName = "qmlbasictype"; - else - nodeName = "jsbasictype"; - break; - case Node::Document: - nodeName = "page"; - break; - case Node::Group: - nodeName = "group"; - break; - case Node::Module: - nodeName = "module"; - break; - case Node::QmlModule: - if (node->isQmlNode()) - nodeName = "qmlmodule"; - else - nodeName = "jsmodule"; - break; - case Node::Enum: - nodeName = "enum"; - break; - case Node::Typedef: - nodeName = "typedef"; - break; - case Node::Property: - nodeName = "property"; - break; - case Node::Function: - nodeName = "function"; - break; - case Node::Variable: - nodeName = "variable"; - break; - case Node::QmlProperty: - if (node->isQmlNode()) - nodeName = "qmlproperty"; - else - nodeName = "jsProperty"; - break; - case Node::QmlPropertyGroup: - if (node->isQmlNode()) - nodeName = "qmlpropertygroup"; - else - nodeName = "jspropertygroup"; - break; - case Node::QmlSignal: - if (node->isQmlNode()) - nodeName = "qmlsignal"; - else - nodeName = "jssignal"; - break; - case Node::QmlSignalHandler: - if (node->isQmlNode()) - nodeName = "qmlsignalhandler"; - else - nodeName = "jssignalhandler"; - break; - case Node::QmlMethod: - if (node->isQmlNode()) - nodeName = "qmlmethod"; - else - nodeName = "jsmethod"; - break; - default: - return false; - } - - QString access; - switch (node->access()) { - case Node::Public: - access = "public"; - break; - case Node::Protected: - access = "protected"; - break; - case Node::Private: - { - access = "private"; - bool b = generateInternalNodes; - if (b) - b = false; - } - break; - default: - return false; - } - - QString objName = node->name(); - // Special case: only the root node should have an empty name. - if (objName.isEmpty() && node != qdb_->primaryTreeRoot()) - return false; - - writer.writeStartElement(nodeName); - - QXmlStreamAttributes attributes; - - if (!node->isDocumentNode() && !node->isCollectionNode()) { - QString threadSafety; - switch (node->threadSafeness()) { - case Node::NonReentrant: - threadSafety = "non-reentrant"; - break; - case Node::Reentrant: - threadSafety = "reentrant"; - break; - case Node::ThreadSafe: - threadSafety = "thread safe"; - break; - case Node::UnspecifiedSafeness: - default: - threadSafety = "unspecified"; - break; - } - writer.writeAttribute("threadsafety", threadSafety); - } - - QString status; - switch (node->status()) { - case Node::Compat: - status = "compat"; - break; - case Node::Obsolete: - status = "obsolete"; - break; - case Node::Deprecated: - status = "obsolete"; - break; - case Node::Preliminary: - status = "preliminary"; - break; - case Node::Commendable: - status = "commendable"; - break; - case Node::Internal: - status = "internal"; - break; - default: - status = "main"; - break; - } - - writer.writeAttribute("name", objName); - if (node->isQmlModule()) { - logicalModuleName = node->logicalModuleName(); - logicalModuleVersion = node->logicalModuleVersion(); - if (logicalModuleName.isEmpty()) { - logicalModuleName = node->name(); - } - if (!logicalModuleName.isEmpty()) { - writer.writeAttribute("qml-module-name", logicalModuleName); - if (node->isQmlModule()) - writer.writeAttribute("qml-module-version", logicalModuleVersion); - if (!qmlFullBaseName.isEmpty()) - writer.writeAttribute("qml-base-type", qmlFullBaseName); - } - } - else if (node->isJsModule()) { - logicalModuleName = node->logicalModuleName(); - logicalModuleVersion = node->logicalModuleVersion(); - if (!logicalModuleName.isEmpty()) { - writer.writeAttribute("js-module-name", logicalModuleName); - if (node->isQmlModule()) - writer.writeAttribute("js-module-version", logicalModuleVersion); - if (!qmlFullBaseName.isEmpty()) - writer.writeAttribute("js-base-type", qmlFullBaseName); - } - } - - QString href; - if (!node->isExternalPage()) { - QString fullName = node->fullDocumentName(); - if (fullName != objName) - writer.writeAttribute("fullname", fullName); -#if 0 - if (Generator::useOutputSubdirs()) - href = node->outputSubdirectory(); - if (!href.isEmpty()) - href.append(QLatin1Char('/')); - href.append(gen_->fullDocumentLocation(node)); -#endif - href = gen_->fullDocumentLocation(node); - } - else - href = node->name(); - if (node->isQmlNode() || node->isJsNode()) { - InnerNode* p = node->parent(); - if (p) { - if (p->isQmlPropertyGroup() || p->isJsPropertyGroup()) - p = p->parent(); - if (p && (p->isQmlType() || p->isJsType()) && p->isAbstract()) - href.clear(); - } - } - if (!href.isEmpty()) - writer.writeAttribute("href", href); - - writer.writeAttribute("status", status); - if (!node->isDocumentNode() && !node->isCollectionNode()) { - writer.writeAttribute("access", access); - if (node->isAbstract()) - writer.writeAttribute("abstract", "true"); - } - if (!node->location().fileName().isEmpty()) - writer.writeAttribute("location", node->location().fileName()); - if (!node->location().filePath().isEmpty()) { - writer.writeAttribute("filepath", node->location().filePath()); - writer.writeAttribute("lineno", QString("%1").arg(node->location().lineNo())); - } - - if (!node->since().isEmpty()) { - writer.writeAttribute("since", node->since()); - } - - QString brief = node->doc().trimmedBriefText(node->name()).toString(); - switch (node->type()) { - case Node::Class: - { - // Classes contain information about their base classes. - const ClassNode* classNode = static_cast<const ClassNode*>(node); - QList<RelatedClass> bases = classNode->baseClasses(); - QSet<QString> baseStrings; - foreach (const RelatedClass& related, bases) { - ClassNode* n = related.node_; - if (n) - baseStrings.insert(n->fullName()); - } - if (!baseStrings.isEmpty()) - writer.writeAttribute("bases", QStringList(baseStrings.toList()).join(",")); - if (!node->physicalModuleName().isEmpty()) - writer.writeAttribute("module", node->physicalModuleName()); - if (!classNode->groupNames().isEmpty()) - writer.writeAttribute("groups", classNode->groupNames().join(",")); - if (!brief.isEmpty()) - writer.writeAttribute("brief", brief); - } - break; - case Node::Namespace: - { - const NamespaceNode* namespaceNode = static_cast<const NamespaceNode*>(node); - if (!namespaceNode->physicalModuleName().isEmpty()) - writer.writeAttribute("module", namespaceNode->physicalModuleName()); - if (!namespaceNode->groupNames().isEmpty()) - writer.writeAttribute("groups", namespaceNode->groupNames().join(",")); - if (!brief.isEmpty()) - writer.writeAttribute("brief", brief); - } - break; - case Node::QmlType: - { - const QmlTypeNode* qcn = static_cast<const QmlTypeNode*>(node); - writer.writeAttribute("title", qcn->title()); - writer.writeAttribute("fulltitle", qcn->fullTitle()); - writer.writeAttribute("subtitle", qcn->subTitle()); - if (!qcn->groupNames().isEmpty()) - writer.writeAttribute("groups", qcn->groupNames().join(",")); - if (!brief.isEmpty()) - writer.writeAttribute("brief", brief); - } - break; - case Node::Document: - { - /* - Document nodes (such as manual pages) have a subtype, - a title, and other attributes. - */ - bool writeModuleName = false; - const DocumentNode* docNode = static_cast<const DocumentNode*>(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::Page: - writer.writeAttribute("subtype", "page"); - writeModuleName = true; - break; - case Node::ExternalPage: - writer.writeAttribute("subtype", "externalpage"); - break; - default: - break; - } - writer.writeAttribute("title", docNode->title()); - writer.writeAttribute("fulltitle", docNode->fullTitle()); - writer.writeAttribute("subtitle", docNode->subTitle()); - if (!node->physicalModuleName().isEmpty() && writeModuleName) { - writer.writeAttribute("module", node->physicalModuleName()); - } - if (!docNode->groupNames().isEmpty()) - writer.writeAttribute("groups", docNode->groupNames().join(",")); - if (!brief.isEmpty()) - writer.writeAttribute("brief", brief); - } - break; - case Node::Group: - { - const CollectionNode* cn = static_cast<const CollectionNode*>(node); - writer.writeAttribute("seen", cn->wasSeen() ? "true" : "false"); - writer.writeAttribute("title", cn->title()); - if (!cn->subTitle().isEmpty()) - writer.writeAttribute("subtitle", cn->subTitle()); - if (!cn->physicalModuleName().isEmpty()) - writer.writeAttribute("module", cn->physicalModuleName()); - if (!cn->groupNames().isEmpty()) - writer.writeAttribute("groups", cn->groupNames().join(",")); - /* - This is not read back in, so it probably - shouldn't be written out in the first place. - */ - if (!cn->members().isEmpty()) { - QStringList names; - foreach (const Node* member, cn->members()) - names.append(member->name()); - writer.writeAttribute("members", names.join(",")); - } - if (!brief.isEmpty()) - writer.writeAttribute("brief", brief); - } - break; - case Node::Module: - { - const CollectionNode* cn = static_cast<const CollectionNode*>(node); - writer.writeAttribute("seen", cn->wasSeen() ? "true" : "false"); - writer.writeAttribute("title", cn->title()); - if (!cn->subTitle().isEmpty()) - writer.writeAttribute("subtitle", cn->subTitle()); - if (!cn->physicalModuleName().isEmpty()) - writer.writeAttribute("module", cn->physicalModuleName()); - if (!cn->groupNames().isEmpty()) - writer.writeAttribute("groups", cn->groupNames().join(",")); - /* - This is not read back in, so it probably - shouldn't be written out in the first place. - */ - if (!cn->members().isEmpty()) { - QStringList names; - foreach (const Node* member, cn->members()) - names.append(member->name()); - writer.writeAttribute("members", names.join(",")); - } - if (!brief.isEmpty()) - writer.writeAttribute("brief", brief); - } - break; - case Node::QmlModule: - { - const CollectionNode* cn = static_cast<const CollectionNode*>(node); - writer.writeAttribute("seen", cn->wasSeen() ? "true" : "false"); - writer.writeAttribute("title", cn->title()); - if (!cn->subTitle().isEmpty()) - writer.writeAttribute("subtitle", cn->subTitle()); - if (!cn->physicalModuleName().isEmpty()) - writer.writeAttribute("module", cn->physicalModuleName()); - if (!cn->groupNames().isEmpty()) - writer.writeAttribute("groups", cn->groupNames().join(",")); - /* - This is not read back in, so it probably - shouldn't be written out in the first place. - */ - if (!cn->members().isEmpty()) { - QStringList names; - foreach (const Node* member, cn->members()) - names.append(member->name()); - writer.writeAttribute("members", names.join(",")); - } - if (!brief.isEmpty()) - writer.writeAttribute("brief", brief); - } - break; - case Node::Function: - { - /* - Function nodes contain information about the type of - function being described. - */ - const FunctionNode* functionNode = static_cast<const FunctionNode*>(node); - switch (functionNode->virtualness()) { - case FunctionNode::NonVirtual: - writer.writeAttribute("virtual", "non"); - break; - case FunctionNode::ImpureVirtual: - writer.writeAttribute("virtual", "impure"); - break; - case FunctionNode::PureVirtual: - writer.writeAttribute("virtual", "pure"); - break; - default: - break; - } - - switch (functionNode->metaness()) { - case FunctionNode::Plain: - writer.writeAttribute("meta", "plain"); - break; - case FunctionNode::Signal: - writer.writeAttribute("meta", "signal"); - break; - case FunctionNode::Slot: - writer.writeAttribute("meta", "slot"); - break; - case FunctionNode::Ctor: - writer.writeAttribute("meta", "constructor"); - break; - case FunctionNode::Dtor: - writer.writeAttribute("meta", "destructor"); - break; - case FunctionNode::MacroWithParams: - writer.writeAttribute("meta", "macrowithparams"); - break; - case FunctionNode::MacroWithoutParams: - writer.writeAttribute("meta", "macrowithoutparams"); - break; - default: - break; - } - writer.writeAttribute("const", functionNode->isConst()?"true":"false"); - writer.writeAttribute("static", functionNode->isStatic()?"true":"false"); - writer.writeAttribute("overload", functionNode->isOverload()?"true":"false"); - if (functionNode->isOverload()) - writer.writeAttribute("overload-number", QString::number(functionNode->overloadNumber())); - if (functionNode->relates()) { - writer.writeAttribute("relates", functionNode->relates()->name()); - } - const PropertyNode* propertyNode = functionNode->associatedProperty(); - if (propertyNode) - writer.writeAttribute("associated-property", propertyNode->name()); - writer.writeAttribute("type", functionNode->returnType()); - if (!brief.isEmpty()) - writer.writeAttribute("brief", brief); - - /* - Note: The "signature" attribute is written to the - index file, but it is not read back in. Is that ok? - */ - QString signature = functionNode->signature(); - if (functionNode->isConst()) - signature += " const"; - writer.writeAttribute("signature", signature); - - for (int i = 0; i < functionNode->parameters().size(); ++i) { - Parameter parameter = functionNode->parameters()[i]; - writer.writeStartElement("parameter"); - writer.writeAttribute("left", parameter.leftType()); - writer.writeAttribute("right", parameter.rightType()); - writer.writeAttribute("name", parameter.name()); - writer.writeAttribute("default", parameter.defaultValue()); - writer.writeEndElement(); // parameter - } - } - break; - case Node::QmlProperty: - { - QmlPropertyNode* qpn = static_cast<QmlPropertyNode*>(node); - writer.writeAttribute("type", qpn->dataType()); - writer.writeAttribute("attached", qpn->isAttached() ? "true" : "false"); - writer.writeAttribute("writable", qpn->isWritable() ? "true" : "false"); - if (!brief.isEmpty()) - writer.writeAttribute("brief", brief); - } - break; - case Node::QmlPropertyGroup: - { - if (!brief.isEmpty()) - writer.writeAttribute("brief", brief); - } - break; - case Node::Property: - { - const PropertyNode* propertyNode = static_cast<const PropertyNode*>(node); - writer.writeAttribute("type", propertyNode->dataType()); - if (!brief.isEmpty()) - writer.writeAttribute("brief", brief); - foreach (const Node* fnNode, propertyNode->getters()) { - if (fnNode) { - const FunctionNode* functionNode = static_cast<const FunctionNode*>(fnNode); - writer.writeStartElement("getter"); - writer.writeAttribute("name", functionNode->name()); - writer.writeEndElement(); // getter - } - } - foreach (const Node* fnNode, propertyNode->setters()) { - if (fnNode) { - const FunctionNode* functionNode = static_cast<const FunctionNode*>(fnNode); - writer.writeStartElement("setter"); - writer.writeAttribute("name", functionNode->name()); - writer.writeEndElement(); // setter - } - } - foreach (const Node* fnNode, propertyNode->resetters()) { - if (fnNode) { - const FunctionNode* functionNode = static_cast<const FunctionNode*>(fnNode); - writer.writeStartElement("resetter"); - writer.writeAttribute("name", functionNode->name()); - writer.writeEndElement(); // resetter - } - } - foreach (const Node* fnNode, propertyNode->notifiers()) { - if (fnNode) { - const FunctionNode* functionNode = static_cast<const FunctionNode*>(fnNode); - writer.writeStartElement("notifier"); - writer.writeAttribute("name", functionNode->name()); - writer.writeEndElement(); // notifier - } - } - } - break; - case Node::Variable: - { - const VariableNode* variableNode = static_cast<const VariableNode*>(node); - writer.writeAttribute("type", variableNode->dataType()); - writer.writeAttribute("static", variableNode->isStatic() ? "true" : "false"); - if (!brief.isEmpty()) - writer.writeAttribute("brief", brief); - } - break; - case Node::Enum: - { - const EnumNode* enumNode = static_cast<const EnumNode*>(node); - if (enumNode->flagsType()) { - writer.writeAttribute("typedef",enumNode->flagsType()->fullDocumentName()); - } - foreach (const EnumItem& item, enumNode->items()) { - writer.writeStartElement("value"); - writer.writeAttribute("name", item.name()); - writer.writeAttribute("value", item.value()); - writer.writeEndElement(); // value - } - } - break; - case Node::Typedef: - { - const TypedefNode* typedefNode = static_cast<const TypedefNode*>(node); - if (typedefNode->associatedEnum()) { - writer.writeAttribute("enum",typedefNode->associatedEnum()->fullDocumentName()); - } - } - break; - default: - break; - } - - /* - For our pages, we canonicalize the target, keyword and content - item names so that they can be used by qdoc for other sets of - documentation. - - The reason we do this here is that we don't want to ruin - externally composed indexes, containing non-qdoc-style target names - when reading in indexes. - - targets and keywords are now allowed in any node, not just inner nodes. - */ - - if (node->doc().hasTargets()) { - bool external = false; - if (node->type() == Node::Document) { - const DocumentNode* docNode = static_cast<const DocumentNode*>(node); - if (docNode->subType() == Node::ExternalPage) - external = true; - } - foreach (const Atom* target, node->doc().targets()) { - QString title = target->string(); - QString name = Doc::canonicalTitle(title); - writer.writeStartElement("target"); - if (!external) - writer.writeAttribute("name", name); - else - writer.writeAttribute("name", title); - if (name != title) - writer.writeAttribute("title", title); - writer.writeEndElement(); // target - } - } - if (node->doc().hasKeywords()) { - foreach (const Atom* keyword, node->doc().keywords()) { - QString title = keyword->string(); - QString name = Doc::canonicalTitle(title); - writer.writeStartElement("keyword"); - writer.writeAttribute("name", name); - if (name != title) - writer.writeAttribute("title", title); - writer.writeEndElement(); // keyword - } - } - - // Inner nodes and function nodes contain child nodes of some sort, either - // actual child nodes or function parameters. For these, we close the - // opening tag, create child elements, then add a closing tag for the - // element. Elements for all other nodes are closed in the opening tag. - - if (node->isInnerNode()) { - const InnerNode* inner = static_cast<const InnerNode*>(node); - - if (inner->doc().hasTableOfContents()) { - for (int i = 0; i < inner->doc().tableOfContents().size(); ++i) { - Atom* item = inner->doc().tableOfContents()[i]; - int level = inner->doc().tableOfContentsLevels()[i]; - QString title = Text::sectionHeading(item).toString(); - writer.writeStartElement("contents"); - writer.writeAttribute("name", Doc::canonicalTitle(title)); - writer.writeAttribute("title", title); - writer.writeAttribute("level", QString::number(level)); - writer.writeEndElement(); // contents - } - } - } - return true; -} - -/*! - Returns \c true if the node \a n1 is less than node \a n2. The - comparison is performed by comparing properties of the nodes - in order of increasing complexity. -*/ -bool compareNodes(const Node* n1, const Node* n2) -{ - // Private nodes can occur in any order since they won't normally be - // written to the index. - if (n1->access() == Node::Private && n2->access() == Node::Private) - return false; - - if (n1->location().filePath() < n2->location().filePath()) - return true; - else if (n1->location().filePath() > n2->location().filePath()) - return false; - - if (n1->type() < n2->type()) - return true; - else if (n1->type() > n2->type()) - return false; - - if (n1->name() < n2->name()) - return true; - else if (n1->name() > n2->name()) - return false; - - if (n1->access() < n2->access()) - return true; - else if (n1->access() > n2->access()) - return false; - - if (n1->type() == Node::Function && n2->type() == Node::Function) { - const FunctionNode* f1 = static_cast<const FunctionNode*>(n1); - const FunctionNode* f2 = static_cast<const FunctionNode*>(n2); - - if (f1->isConst() < f2->isConst()) - return true; - else if (f1->isConst() > f2->isConst()) - return false; - - if (f1->signature() < f2->signature()) - return true; - else if (f1->signature() > f2->signature()) - return false; - } - - if (n1->isDocumentNode() && n2->isDocumentNode()) { - const DocumentNode* f1 = static_cast<const DocumentNode*>(n1); - const DocumentNode* f2 = static_cast<const DocumentNode*>(n2); - if (f1->fullTitle() < f2->fullTitle()) - return true; - else if (f1->fullTitle() > f2->fullTitle()) - return false; - } - else if (n1->isCollectionNode() && n2->isCollectionNode()) { - const CollectionNode* f1 = static_cast<const CollectionNode*>(n1); - const CollectionNode* f2 = static_cast<const CollectionNode*>(n2); - if (f1->fullTitle() < f2->fullTitle()) - return true; - else if (f1->fullTitle() > f2->fullTitle()) - return false; - } - - return false; -} - -/*! - Generate index sections for the child nodes of the given \a node - using the \a writer specified. If \a generateInternalNodes is true, - nodes marked as internal will be included in the index; otherwise, - they will be omitted. -*/ -void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer, - Node* node, - bool generateInternalNodes) -{ - /* - Note that groups, modules, and QML modules are written - after all the other nodes. - */ - if (node->isGroup() || node->isModule() || node->isQmlModule() || node->isJsModule()) - return; - - if (generateIndexSection(writer, node, generateInternalNodes)) { - if (node->isInnerNode()) { - const InnerNode* inner = static_cast<const InnerNode*>(node); - - NodeList cnodes = inner->childNodes(); - std::sort(cnodes.begin(), cnodes.end(), compareNodes); - - foreach (Node* child, cnodes) { - generateIndexSections(writer, child, generateInternalNodes); - } - } - - if (node == top) { - /* - We wait until the end of the index file to output the group, module, - and QML module elements. By outputting them at the end, when we read - the index file back in, all the group, module, and QML module member - elements will have already been created. It is then only necessary to - create the group, module, or QML module element and add each member to - its member list. - */ - const CNMap& groups = qdb_->groups(); - if (!groups.isEmpty()) { - CNMap::ConstIterator g = groups.constBegin(); - while (g != groups.constEnd()) { - if (generateIndexSection(writer, g.value(), generateInternalNodes)) - writer.writeEndElement(); - ++g; - } - } - - const CNMap& modules = qdb_->modules(); - if (!modules.isEmpty()) { - CNMap::ConstIterator g = modules.constBegin(); - while (g != modules.constEnd()) { - if (generateIndexSection(writer, g.value(), generateInternalNodes)) - writer.writeEndElement(); - ++g; - } - } - - const CNMap& qmlModules = qdb_->qmlModules(); - if (!qmlModules.isEmpty()) { - CNMap::ConstIterator g = qmlModules.constBegin(); - while (g != qmlModules.constEnd()) { - if (generateIndexSection(writer, g.value(), generateInternalNodes)) - writer.writeEndElement(); - ++g; - } - } - - const CNMap& jsModules = qdb_->jsModules(); - if (!jsModules.isEmpty()) { - CNMap::ConstIterator g = jsModules.constBegin(); - while (g != jsModules.constEnd()) { - if (generateIndexSection(writer, g.value(), generateInternalNodes)) - writer.writeEndElement(); - ++g; - } - } - } - - writer.writeEndElement(); - } -} - -/*! - Outputs an index file. - */ -void QDocIndexFiles::generateIndex(const QString& fileName, - const QString& url, - const QString& title, - Generator* g, - bool generateInternalNodes) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) - return; - - QString msg = "Writing index file: " + fileName; - Location::logToStdErr(msg); - - gen_ = g; - QXmlStreamWriter writer(&file); - writer.setAutoFormatting(true); - writer.writeStartDocument(); - writer.writeDTD("<!DOCTYPE QDOCINDEX>"); - - writer.writeStartElement("INDEX"); - writer.writeAttribute("url", url); - writer.writeAttribute("title", title); - writer.writeAttribute("version", qdb_->version()); - writer.writeAttribute("project", g->config()->getString(CONFIG_PROJECT)); - - top = qdb_->primaryTreeRoot(); - generateIndexSections(writer, top, generateInternalNodes); - - writer.writeEndElement(); // INDEX - writer.writeEndElement(); // QDOCINDEX - writer.writeEndDocument(); - file.close(); -} - -QT_END_NAMESPACE |