use Xml stream reader to read qdoc index files

We get rid of the last usage of QDom and the old
xml parser in our build tools, and it makes parsing
of index files a lot faster.

Change-Id: Iccf01a4a73cc74a77806470fb4c4625f5331a7be
Reviewed-by: Martin Smith <martin.smith@digia.com>
This commit is contained in:
Lars Knoll 2015-07-22 23:27:23 +02:00
parent 1945441986
commit 57bd6e67f7
4 changed files with 291 additions and 270 deletions

View File

@ -1,11 +1,10 @@
!force_bootstrap { !force_bootstrap {
load(qfeatures) load(qfeatures)
requires(!contains(QT_DISABLED_FEATURES, xmlstreamwriter)) requires(!contains(QT_DISABLED_FEATURES, xmlstreamwriter))
requires(!contains(QT_DISABLED_FEATURES, dom))
} }
option(host_build) option(host_build)
QT = core xml QT = core
DEFINES += \ DEFINES += \
QT_QMLDEVTOOLS_LIB \ # force static exports even if not bootstrapping QT_QMLDEVTOOLS_LIB \ # force static exports even if not bootstrapping

View File

@ -31,7 +31,6 @@
** **
****************************************************************************/ ****************************************************************************/
#include "qdom.h"
#include "qxmlstream.h" #include "qxmlstream.h"
#include "qdocindexfiles.h" #include "qdocindexfiles.h"
#include "qdoctagfiles.h" #include "qdoctagfiles.h"
@ -117,72 +116,83 @@ static bool readingRoot = true;
void QDocIndexFiles::readIndexFile(const QString& path) void QDocIndexFiles::readIndexFile(const QString& path)
{ {
QFile file(path); QFile file(path);
if (file.open(QFile::ReadOnly)) { if (!file.open(QFile::ReadOnly)) {
QDomDocument document; qWarning() << "Could not read index file" << path;
document.setContent(&file); return;
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();
} }
QXmlStreamReader reader(&file);
reader.setNamespaceProcessing(false);
if (!reader.readNextStartElement())
return;
if (reader.name() != QLatin1String("INDEX"))
return;
QXmlStreamAttributes attrs = reader.attributes();
// 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 = attrs.value(QLatin1String("url")).toString();
}
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_ = attrs.value(QLatin1String("project")).toString();
basesList_.clear();
relatedList_.clear();
NamespaceNode* root = qdb_->newIndexTree(project_);
// Scan all elements in the XML file, constructing a map that contains
// base classes for each class found.
while (reader.readNextStartElement()) {
readingRoot = true;
readIndexSection(reader, root, indexUrl);
}
// 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 Read a <section> element from the index file and create the
appropriate node(s). appropriate node(s).
*/ */
void QDocIndexFiles::readIndexSection(const QDomElement& element, void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader,
Node* current, Node* current,
const QString& indexUrl) const QString& indexUrl)
{ {
QString name = element.attribute("name"); QXmlStreamAttributes attributes = reader.attributes();
QString href = element.attribute("href"); QStringRef elementName = reader.name();
QString name = attributes.value(QLatin1String("name")).toString();
QString href = attributes.value(QLatin1String("href")).toString();
Node* node; Node* node;
Location location; Location location;
Aggregate* parent = 0; Aggregate* parent = 0;
bool hasReadChildren = false;
if (current->isAggregate()) if (current->isAggregate())
parent = static_cast<Aggregate*>(current); parent = static_cast<Aggregate*>(current);
QString filePath; QString filePath;
int lineNo = 0; int lineNo = 0;
if (element.hasAttribute("filepath")) { if (attributes.hasAttribute(QLatin1String("filepath"))) {
filePath = element.attribute("filepath", QString()); filePath = attributes.value(QLatin1String("filepath")).toString();
lineNo = element.attribute("lineno", QString()).toInt(); lineNo = attributes.value("lineno").toInt();
} }
if (element.nodeName() == "namespace") { if (elementName == QLatin1String("namespace")) {
node = new NamespaceNode(parent, name); node = new NamespaceNode(parent, name);
if (!indexUrl.isEmpty()) if (!indexUrl.isEmpty())
@ -191,10 +201,10 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
location = Location(name.toLower() + ".html"); location = Location(name.toLower() + ".html");
} }
else if (element.nodeName() == "class") { else if (elementName == QLatin1String("class")) {
node = new ClassNode(parent, name); node = new ClassNode(parent, name);
if (element.hasAttribute("bases")) { if (attributes.hasAttribute(QLatin1String("bases"))) {
QString bases = element.attribute("bases"); QString bases = attributes.value(QLatin1String("bases")).toString();
if (!bases.isEmpty()) if (!bases.isEmpty())
basesList_.append(QPair<ClassNode*,QString>(static_cast<ClassNode*>(node), bases)); basesList_.append(QPair<ClassNode*,QString>(static_cast<ClassNode*>(node), bases));
} }
@ -203,108 +213,108 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
else if (!indexUrl.isNull()) else if (!indexUrl.isNull())
location = Location(name.toLower() + ".html"); location = Location(name.toLower() + ".html");
bool abstract = false; bool abstract = false;
if (element.attribute("abstract") == "true") if (attributes.value(QLatin1String("abstract")) == QLatin1String("true"))
abstract = true; abstract = true;
node->setAbstract(abstract); node->setAbstract(abstract);
} }
else if (element.nodeName() == "qmlclass") { else if (elementName == QLatin1String("qmlclass")) {
QmlTypeNode* qcn = new QmlTypeNode(parent, name); QmlTypeNode* qcn = new QmlTypeNode(parent, name);
qcn->setTitle(element.attribute("title")); qcn->setTitle(attributes.value(QLatin1String("title")).toString());
QString logicalModuleName = element.attribute("qml-module-name"); QString logicalModuleName = attributes.value(QLatin1String("qml-module-name")).toString();
if (!logicalModuleName.isEmpty()) if (!logicalModuleName.isEmpty())
qdb_->addToQmlModule(logicalModuleName, qcn); qdb_->addToQmlModule(logicalModuleName, qcn);
bool abstract = false; bool abstract = false;
if (element.attribute("abstract") == "true") if (attributes.value(QLatin1String("abstract")) == QLatin1String("true"))
abstract = true; abstract = true;
qcn->setAbstract(abstract); qcn->setAbstract(abstract);
QString qmlFullBaseName = element.attribute("qml-base-type"); QString qmlFullBaseName = attributes.value(QLatin1String("qml-base-type")).toString();
if (!qmlFullBaseName.isEmpty()) { if (!qmlFullBaseName.isEmpty()) {
qcn->setQmlBaseName(qmlFullBaseName); qcn->setQmlBaseName(qmlFullBaseName);
} }
if (element.hasAttribute("location")) if (attributes.hasAttribute(QLatin1String("location")))
name = element.attribute("location", QString()); name = attributes.value("location").toString();
if (!indexUrl.isEmpty()) if (!indexUrl.isEmpty())
location = Location(indexUrl + QLatin1Char('/') + name); location = Location(indexUrl + QLatin1Char('/') + name);
else if (!indexUrl.isNull()) else if (!indexUrl.isNull())
location = Location(name); location = Location(name);
node = qcn; node = qcn;
} }
else if (element.nodeName() == "jstype") { else if (elementName == QLatin1String("jstype")) {
QmlTypeNode* qcn = new QmlTypeNode(parent, name); QmlTypeNode* qcn = new QmlTypeNode(parent, name);
qcn->setGenus(Node::JS); qcn->setGenus(Node::JS);
qcn->setTitle(element.attribute("title")); qcn->setTitle(attributes.value(QLatin1String("title")).toString());
QString logicalModuleName = element.attribute("js-module-name"); QString logicalModuleName = attributes.value(QLatin1String("js-module-name")).toString();
if (!logicalModuleName.isEmpty()) if (!logicalModuleName.isEmpty())
qdb_->addToQmlModule(logicalModuleName, qcn); qdb_->addToQmlModule(logicalModuleName, qcn);
bool abstract = false; bool abstract = false;
if (element.attribute("abstract") == "true") if (attributes.value(QLatin1String("abstract")) == QLatin1String("true"))
abstract = true; abstract = true;
qcn->setAbstract(abstract); qcn->setAbstract(abstract);
QString qmlFullBaseName = element.attribute("js-base-type"); QString qmlFullBaseName = attributes.value(QLatin1String("js-base-type")).toString();
if (!qmlFullBaseName.isEmpty()) { if (!qmlFullBaseName.isEmpty()) {
qcn->setQmlBaseName(qmlFullBaseName); qcn->setQmlBaseName(qmlFullBaseName);
} }
if (element.hasAttribute("location")) if (attributes.hasAttribute(QLatin1String("location")))
name = element.attribute("location", QString()); name = attributes.value("location").toString();
if (!indexUrl.isEmpty()) if (!indexUrl.isEmpty())
location = Location(indexUrl + QLatin1Char('/') + name); location = Location(indexUrl + QLatin1Char('/') + name);
else if (!indexUrl.isNull()) else if (!indexUrl.isNull())
location = Location(name); location = Location(name);
node = qcn; node = qcn;
} }
else if (element.nodeName() == "qmlbasictype") { else if (elementName == QLatin1String("qmlbasictype")) {
QmlBasicTypeNode* qbtn = new QmlBasicTypeNode(parent, name); QmlBasicTypeNode* qbtn = new QmlBasicTypeNode(parent, name);
qbtn->setTitle(element.attribute("title")); qbtn->setTitle(attributes.value(QLatin1String("title")).toString());
if (element.hasAttribute("location")) if (attributes.hasAttribute(QLatin1String("location")))
name = element.attribute("location", QString()); name = attributes.value("location").toString();
if (!indexUrl.isEmpty()) if (!indexUrl.isEmpty())
location = Location(indexUrl + QLatin1Char('/') + name); location = Location(indexUrl + QLatin1Char('/') + name);
else if (!indexUrl.isNull()) else if (!indexUrl.isNull())
location = Location(name); location = Location(name);
node = qbtn; node = qbtn;
} }
else if (element.nodeName() == "jsbasictype") { else if (elementName == QLatin1String("jsbasictype")) {
QmlBasicTypeNode* qbtn = new QmlBasicTypeNode(parent, name); QmlBasicTypeNode* qbtn = new QmlBasicTypeNode(parent, name);
qbtn->setGenus(Node::JS); qbtn->setGenus(Node::JS);
qbtn->setTitle(element.attribute("title")); qbtn->setTitle(attributes.value(QLatin1String("title")).toString());
if (element.hasAttribute("location")) if (attributes.hasAttribute(QLatin1String("location")))
name = element.attribute("location", QString()); name = attributes.value("location").toString();
if (!indexUrl.isEmpty()) if (!indexUrl.isEmpty())
location = Location(indexUrl + QLatin1Char('/') + name); location = Location(indexUrl + QLatin1Char('/') + name);
else if (!indexUrl.isNull()) else if (!indexUrl.isNull())
location = Location(name); location = Location(name);
node = qbtn; node = qbtn;
} }
else if (element.nodeName() == "qmlpropertygroup") { else if (elementName == QLatin1String("qmlpropertygroup")) {
QmlTypeNode* qcn = static_cast<QmlTypeNode*>(parent); QmlTypeNode* qcn = static_cast<QmlTypeNode*>(parent);
QmlPropertyGroupNode* qpgn = new QmlPropertyGroupNode(qcn, name); QmlPropertyGroupNode* qpgn = new QmlPropertyGroupNode(qcn, name);
if (element.hasAttribute("location")) if (attributes.hasAttribute(QLatin1String("location")))
name = element.attribute("location", QString()); name = attributes.value("location").toString();
if (!indexUrl.isEmpty()) if (!indexUrl.isEmpty())
location = Location(indexUrl + QLatin1Char('/') + name); location = Location(indexUrl + QLatin1Char('/') + name);
else if (!indexUrl.isNull()) else if (!indexUrl.isNull())
location = Location(name); location = Location(name);
node = qpgn; node = qpgn;
} }
else if (element.nodeName() == "jspropertygroup") { else if (elementName == QLatin1String("jspropertygroup")) {
QmlTypeNode* qcn = static_cast<QmlTypeNode*>(parent); QmlTypeNode* qcn = static_cast<QmlTypeNode*>(parent);
QmlPropertyGroupNode* qpgn = new QmlPropertyGroupNode(qcn, name); QmlPropertyGroupNode* qpgn = new QmlPropertyGroupNode(qcn, name);
qpgn->setGenus(Node::JS); qpgn->setGenus(Node::JS);
if (element.hasAttribute("location")) if (attributes.hasAttribute(QLatin1String("location")))
name = element.attribute("location", QString()); name = attributes.value("location").toString();
if (!indexUrl.isEmpty()) if (!indexUrl.isEmpty())
location = Location(indexUrl + QLatin1Char('/') + name); location = Location(indexUrl + QLatin1Char('/') + name);
else if (!indexUrl.isNull()) else if (!indexUrl.isNull())
location = Location(name); location = Location(name);
node = qpgn; node = qpgn;
} }
else if (element.nodeName() == "qmlproperty") { else if (elementName == QLatin1String("qmlproperty")) {
QString type = element.attribute("type"); QString type = attributes.value(QLatin1String("type")).toString();
bool attached = false; bool attached = false;
if (element.attribute("attached") == "true") if (attributes.value(QLatin1String("attached")) == QLatin1String("true"))
attached = true; attached = true;
bool readonly = false; bool readonly = false;
if (element.attribute("writable") == "false") if (attributes.value(QLatin1String("writable")) == QLatin1String("false"))
readonly = true; readonly = true;
QmlPropertyNode* qpn = 0; QmlPropertyNode* qpn = 0;
if (parent->isQmlType()) { if (parent->isQmlType()) {
@ -318,13 +328,13 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
qpn->setReadOnly(readonly); qpn->setReadOnly(readonly);
node = qpn; node = qpn;
} }
else if (element.nodeName() == "jsproperty") { else if (elementName == QLatin1String("jsproperty")) {
QString type = element.attribute("type"); QString type = attributes.value(QLatin1String("type")).toString();
bool attached = false; bool attached = false;
if (element.attribute("attached") == "true") if (attributes.value(QLatin1String("attached")) == QLatin1String("true"))
attached = true; attached = true;
bool readonly = false; bool readonly = false;
if (element.attribute("writable") == "false") if (attributes.value(QLatin1String("writable")) == QLatin1String("false"))
readonly = true; readonly = true;
QmlPropertyNode* qpn = 0; QmlPropertyNode* qpn = 0;
if (parent->isJsType()) { if (parent->isJsType()) {
@ -339,103 +349,103 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
qpn->setReadOnly(readonly); qpn->setReadOnly(readonly);
node = qpn; node = qpn;
} }
else if ((element.nodeName() == "qmlmethod") || else if ((elementName == QLatin1String("qmlmethod")) ||
(element.nodeName() == "qmlsignal") || (elementName == QLatin1String("qmlsignal")) ||
(element.nodeName() == "qmlsignalhandler")) { (elementName == QLatin1String("qmlsignalhandler"))) {
Node::NodeType t = Node::QmlMethod; Node::NodeType t = Node::QmlMethod;
if (element.nodeName() == "qmlsignal") if (elementName == QLatin1String("qmlsignal"))
t = Node::QmlSignal; t = Node::QmlSignal;
else if (element.nodeName() == "qmlsignalhandler") else if (elementName == QLatin1String("qmlsignalhandler"))
t = Node::QmlSignalHandler; t = Node::QmlSignalHandler;
bool attached = false; bool attached = false;
FunctionNode* fn = new FunctionNode(t, parent, name, attached); FunctionNode* fn = new FunctionNode(t, parent, name, attached);
node = fn; node = fn;
} }
else if ((element.nodeName() == "jsmethod") || else if ((elementName == QLatin1String("jsmethod")) ||
(element.nodeName() == "jssignal") || (elementName == QLatin1String("jssignal")) ||
(element.nodeName() == "jssignalhandler")) { (elementName == QLatin1String("jssignalhandler"))) {
Node::NodeType t = Node::QmlMethod; Node::NodeType t = Node::QmlMethod;
if (element.nodeName() == "jssignal") if (elementName == QLatin1String("jssignal"))
t = Node::QmlSignal; t = Node::QmlSignal;
else if (element.nodeName() == "jssignalhandler") else if (elementName == QLatin1String("jssignalhandler"))
t = Node::QmlSignalHandler; t = Node::QmlSignalHandler;
bool attached = false; bool attached = false;
FunctionNode* fn = new FunctionNode(t, parent, name, attached); FunctionNode* fn = new FunctionNode(t, parent, name, attached);
fn->setGenus(Node::JS); fn->setGenus(Node::JS);
node = fn; node = fn;
} }
else if (element.nodeName() == "group") { else if (elementName == QLatin1String("group")) {
CollectionNode* cn = qdb_->addGroup(name); CollectionNode* cn = qdb_->addGroup(name);
cn->setTitle(element.attribute("title")); cn->setTitle(attributes.value(QLatin1String("title")).toString());
cn->setSubTitle(element.attribute("subtitle")); cn->setSubTitle(attributes.value(QLatin1String("subtitle")).toString());
if (element.attribute("seen") == "true") if (attributes.value(QLatin1String("seen")) == QLatin1String("true"))
cn->markSeen(); cn->markSeen();
node = cn; node = cn;
} }
else if (element.nodeName() == "module") { else if (elementName == QLatin1String("module")) {
CollectionNode* cn = qdb_->addModule(name); CollectionNode* cn = qdb_->addModule(name);
cn->setTitle(element.attribute("title")); cn->setTitle(attributes.value(QLatin1String("title")).toString());
cn->setSubTitle(element.attribute("subtitle")); cn->setSubTitle(attributes.value(QLatin1String("subtitle")).toString());
if (element.attribute("seen") == "true") if (attributes.value(QLatin1String("seen")) == QLatin1String("true"))
cn->markSeen(); cn->markSeen();
node = cn; node = cn;
} }
else if (element.nodeName() == "qmlmodule") { else if (elementName == QLatin1String("qmlmodule")) {
QString t = element.attribute("qml-module-name"); QString t = attributes.value(QLatin1String("qml-module-name")).toString();
CollectionNode* cn = qdb_->addQmlModule(t); CollectionNode* cn = qdb_->addQmlModule(t);
QStringList info; QStringList info;
info << t << element.attribute("qml-module-version"); info << t << attributes.value(QLatin1String("qml-module-version")).toString();
cn->setLogicalModuleInfo(info); cn->setLogicalModuleInfo(info);
cn->setTitle(element.attribute("title")); cn->setTitle(attributes.value(QLatin1String("title")).toString());
cn->setSubTitle(element.attribute("subtitle")); cn->setSubTitle(attributes.value(QLatin1String("subtitle")).toString());
if (element.attribute("seen") == "true") if (attributes.value(QLatin1String("seen")) == QLatin1String("true"))
cn->markSeen(); cn->markSeen();
node = cn; node = cn;
} }
else if (element.nodeName() == "jsmodule") { else if (elementName == QLatin1String("jsmodule")) {
QString t = element.attribute("js-module-name"); QString t = attributes.value(QLatin1String("js-module-name")).toString();
CollectionNode* cn = qdb_->addJsModule(t); CollectionNode* cn = qdb_->addJsModule(t);
QStringList info; QStringList info;
info << t << element.attribute("js-module-version"); info << t << attributes.value(QLatin1String("js-module-version")).toString();
cn->setLogicalModuleInfo(info); cn->setLogicalModuleInfo(info);
cn->setTitle(element.attribute("title")); cn->setTitle(attributes.value(QLatin1String("title")).toString());
cn->setSubTitle(element.attribute("subtitle")); cn->setSubTitle(attributes.value(QLatin1String("subtitle")).toString());
if (element.attribute("seen") == "true") if (attributes.value(QLatin1String("seen")) == QLatin1String("true"))
cn->markSeen(); cn->markSeen();
node = cn; node = cn;
} }
else if (element.nodeName() == "page") { else if (elementName == QLatin1String("page")) {
Node::DocSubtype subtype; Node::DocSubtype subtype;
Node::PageType ptype = Node::NoPageType; Node::PageType ptype = Node::NoPageType;
QString attr = element.attribute("subtype"); QString attr = attributes.value(QLatin1String("subtype")).toString();
if (attr == "example") { if (attr == QLatin1String("example")) {
subtype = Node::Example; subtype = Node::Example;
ptype = Node::ExamplePage; ptype = Node::ExamplePage;
} }
else if (attr == "header") { else if (attr == QLatin1String("header")) {
subtype = Node::HeaderFile; subtype = Node::HeaderFile;
ptype = Node::ApiPage; ptype = Node::ApiPage;
} }
else if (attr == "file") { else if (attr == QLatin1String("file")) {
subtype = Node::File; subtype = Node::File;
ptype = Node::NoPageType; ptype = Node::NoPageType;
} }
else if (attr == "page") { else if (attr == QLatin1String("page")) {
subtype = Node::Page; subtype = Node::Page;
ptype = Node::ArticlePage; ptype = Node::ArticlePage;
} }
else if (attr == "externalpage") { else if (attr == QLatin1String("externalpage")) {
subtype = Node::ExternalPage; subtype = Node::ExternalPage;
ptype = Node::ArticlePage; ptype = Node::ArticlePage;
} }
else else
return; goto done;
DocumentNode* docNode = new DocumentNode(parent, name, subtype, ptype); DocumentNode* docNode = new DocumentNode(parent, name, subtype, ptype);
docNode->setTitle(element.attribute("title")); docNode->setTitle(attributes.value(QLatin1String("title")).toString());
if (element.hasAttribute("location")) if (attributes.hasAttribute(QLatin1String("location")))
name = element.attribute("location", QString()); name = attributes.value(QLatin1String("location")).toString();
if (!indexUrl.isEmpty()) if (!indexUrl.isEmpty())
location = Location(indexUrl + QLatin1Char('/') + name); location = Location(indexUrl + QLatin1Char('/') + name);
@ -445,7 +455,7 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
node = docNode; node = docNode;
} }
else if (element.nodeName() == "enum") { else if (elementName == QLatin1String("enum")) {
EnumNode* enumNode = new EnumNode(parent, name); EnumNode* enumNode = new EnumNode(parent, name);
if (!indexUrl.isEmpty()) if (!indexUrl.isEmpty())
@ -453,17 +463,20 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
else if (!indexUrl.isNull()) else if (!indexUrl.isNull())
location = Location(parent->name().toLower() + ".html"); location = Location(parent->name().toLower() + ".html");
QDomElement child = element.firstChildElement("value"); while (reader.readNextStartElement()) {
while (!child.isNull()) { if (reader.name() == QLatin1String("value")) {
EnumItem item(child.attribute("name"), child.attribute("value")); QXmlStreamAttributes childAttributes = reader.attributes();
enumNode->addItem(item); EnumItem item(childAttributes.value(QLatin1String("name")).toString(), childAttributes.value(QLatin1String("value")).toString());
child = child.nextSiblingElement("value"); enumNode->addItem(item);
}
reader.skipCurrentElement();
} }
node = enumNode; node = enumNode;
hasReadChildren = true;
} }
else if (element.nodeName() == "typedef") { else if (elementName == QLatin1String("typedef")) {
node = new TypedefNode(parent, name); node = new TypedefNode(parent, name);
if (!indexUrl.isEmpty()) if (!indexUrl.isEmpty())
@ -472,7 +485,7 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
location = Location(parent->name().toLower() + ".html"); location = Location(parent->name().toLower() + ".html");
} }
else if (element.nodeName() == "property") { else if (elementName == QLatin1String("property")) {
node = new PropertyNode(parent, name); node = new PropertyNode(parent, name);
if (!indexUrl.isEmpty()) if (!indexUrl.isEmpty())
@ -481,74 +494,76 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
location = Location(parent->name().toLower() + ".html"); location = Location(parent->name().toLower() + ".html");
} }
else if (element.nodeName() == "function") { else if (elementName == QLatin1String("function")) {
FunctionNode::Virtualness virt; FunctionNode::Virtualness virt;
QString t = element.attribute("virtual"); QString t = attributes.value(QLatin1String("virtual")).toString();
if (t == "non") if (t == QLatin1String("non"))
virt = FunctionNode::NonVirtual; virt = FunctionNode::NonVirtual;
else if (t == "virtual") else if (t == QLatin1String("virtual"))
virt = FunctionNode::NormalVirtual; virt = FunctionNode::NormalVirtual;
else if (t == "pure") else if (t == QLatin1String("pure"))
virt = FunctionNode::PureVirtual; virt = FunctionNode::PureVirtual;
else else
return; goto done;
t = element.attribute("meta"); t = attributes.value(QLatin1String("meta")).toString();
FunctionNode::Metaness meta; FunctionNode::Metaness meta;
if (t == "plain") if (t == QLatin1String("plain"))
meta = FunctionNode::Plain; meta = FunctionNode::Plain;
else if (t == "signal") else if (t == QLatin1String("signal"))
meta = FunctionNode::Signal; meta = FunctionNode::Signal;
else if (t == "slot") else if (t == QLatin1String("slot"))
meta = FunctionNode::Slot; meta = FunctionNode::Slot;
else if (t == "constructor") else if (t == QLatin1String("constructor"))
meta = FunctionNode::Ctor; meta = FunctionNode::Ctor;
else if (t == "destructor") else if (t == QLatin1String("destructor"))
meta = FunctionNode::Dtor; meta = FunctionNode::Dtor;
else if (t == "macro") else if (t == QLatin1String("macro"))
meta = FunctionNode::MacroWithParams; meta = FunctionNode::MacroWithParams;
else if (t == "macrowithparams") else if (t == QLatin1String("macrowithparams"))
meta = FunctionNode::MacroWithParams; meta = FunctionNode::MacroWithParams;
else if (t == "macrowithoutparams") else if (t == QLatin1String("macrowithoutparams"))
meta = FunctionNode::MacroWithoutParams; meta = FunctionNode::MacroWithoutParams;
else else
return; goto done;
FunctionNode* functionNode = new FunctionNode(parent, name); FunctionNode* functionNode = new FunctionNode(parent, name);
functionNode->setReturnType(element.attribute("return")); functionNode->setReturnType(attributes.value(QLatin1String("return")).toString());
functionNode->setVirtualness(virt); functionNode->setVirtualness(virt);
functionNode->setMetaness(meta); functionNode->setMetaness(meta);
functionNode->setConst(element.attribute("const") == "true"); functionNode->setConst(attributes.value(QLatin1String("const")) == QLatin1String("true"));
functionNode->setStatic(element.attribute("static") == "true"); functionNode->setStatic(attributes.value(QLatin1String("static")) == QLatin1String("true"));
if (element.attribute("overload") == "true") { if (attributes.value(QLatin1String("overload")) == QLatin1String("true")) {
functionNode->setOverloadFlag(true); functionNode->setOverloadFlag(true);
functionNode->setOverloadNumber(element.attribute("overload-number").toUInt()); functionNode->setOverloadNumber(attributes.value(QLatin1String("overload-number")).toUInt());
} }
else { else {
functionNode->setOverloadFlag(false); functionNode->setOverloadFlag(false);
functionNode->setOverloadNumber(0); functionNode->setOverloadNumber(0);
} }
if (element.hasAttribute("relates") if (attributes.hasAttribute(QLatin1String("relates"))
&& element.attribute("relates") != parent->name()) { && attributes.value(QLatin1String("relates")) != parent->name()) {
relatedList_.append( relatedList_.append(
QPair<FunctionNode*,QString>(functionNode, QPair<FunctionNode*,QString>(functionNode,
element.attribute("relates"))); attributes.value(QLatin1String("relates")).toString()));
} }
/* /*
Note: The "signature" attribute was written to the Note: The "signature" attribute was written to the
index file, but it is not read back in. Is that ok? index file, but it is not read back in. Is that ok?
*/ */
QDomElement child = element.firstChildElement("parameter"); while (reader.readNextStartElement()) {
while (!child.isNull()) { if (reader.name() == QLatin1String("parameter")) {
// Do not use the default value for the parameter; it is not QXmlStreamAttributes childAttributes = reader.attributes();
// required, and has been known to cause problems. // Do not use the default value for the parameter; it is not
Parameter parameter(child.attribute("left"), // required, and has been known to cause problems.
child.attribute("right"), Parameter parameter(childAttributes.value(QLatin1String("left")).toString(),
child.attribute("name"), childAttributes.value(QLatin1String("right")).toString(),
QString()); // child.attribute("default") childAttributes.value(QLatin1String("name")).toString(),
functionNode->addParameter(parameter); QString()); // childAttributes.value(QLatin1String("default"))
child = child.nextSiblingElement("parameter"); functionNode->addParameter(parameter);
}
reader.skipCurrentElement();
} }
node = functionNode; node = functionNode;
@ -556,125 +571,134 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
location = Location(indexUrl + QLatin1Char('/') + parent->name().toLower() + ".html"); location = Location(indexUrl + QLatin1Char('/') + parent->name().toLower() + ".html");
else if (!indexUrl.isNull()) else if (!indexUrl.isNull())
location = Location(parent->name().toLower() + ".html"); location = Location(parent->name().toLower() + ".html");
hasReadChildren = true;
} }
else if (element.nodeName() == "variable") { else if (elementName == QLatin1String("variable")) {
node = new VariableNode(parent, name); node = new VariableNode(parent, name);
if (!indexUrl.isEmpty()) if (!indexUrl.isEmpty())
location = Location(indexUrl + QLatin1Char('/') + parent->name().toLower() + ".html"); location = Location(indexUrl + QLatin1Char('/') + parent->name().toLower() + ".html");
else if (!indexUrl.isNull()) else if (!indexUrl.isNull())
location = Location(parent->name().toLower() + ".html"); location = Location(parent->name().toLower() + ".html");
} }
else if (element.nodeName() == "keyword") { else if (elementName == QLatin1String("keyword")) {
QString title = element.attribute("title"); QString title = attributes.value(QLatin1String("title")).toString();
qdb_->insertTarget(name, title, TargetRec::Keyword, current, 1); qdb_->insertTarget(name, title, TargetRec::Keyword, current, 1);
return; goto done;
} }
else if (element.nodeName() == "target") { else if (elementName == QLatin1String("target")) {
QString title = element.attribute("title"); QString title = attributes.value(QLatin1String("title")).toString();
qdb_->insertTarget(name, title, TargetRec::Target, current, 2); qdb_->insertTarget(name, title, TargetRec::Target, current, 2);
return; goto done;
} }
else if (element.nodeName() == "contents") { else if (elementName == QLatin1String("contents")) {
QString title = element.attribute("title"); QString title = attributes.value(QLatin1String("title")).toString();
qdb_->insertTarget(name, title, TargetRec::Contents, current, 3); qdb_->insertTarget(name, title, TargetRec::Contents, current, 3);
return; goto done;
} }
else else
return; goto done;
QString access = element.attribute("access"); {
if (access == "public") QString access = attributes.value(QLatin1String("access")).toString();
node->setAccess(Node::Public); if (access == "public")
else if (access == "protected") node->setAccess(Node::Public);
node->setAccess(Node::Protected); else if (access == "protected")
else if ((access == "private") || (access == "internal")) node->setAccess(Node::Protected);
node->setAccess(Node::Private); else if ((access == "private") || (access == "internal"))
else node->setAccess(Node::Private);
node->setAccess(Node::Public); else
node->setAccess(Node::Public);
if ((element.nodeName() != "page") && if ((elementName != QLatin1String("page")) &&
(element.nodeName() != "qmlclass") && (elementName != QLatin1String("qmlclass")) &&
(element.nodeName() != "qmlbasictype") && (elementName != QLatin1String("qmlbasictype")) &&
(element.nodeName() != "jstype") && (elementName != QLatin1String("jstype")) &&
(element.nodeName() != "jsbasictype")) { (elementName != QLatin1String("jsbasictype"))) {
QString threadSafety = element.attribute("threadsafety"); QString threadSafety = attributes.value(QLatin1String("threadsafety")).toString();
if (threadSafety == "non-reentrant") if (threadSafety == QLatin1String("non-reentrant"))
node->setThreadSafeness(Node::NonReentrant); node->setThreadSafeness(Node::NonReentrant);
else if (threadSafety == "reentrant") else if (threadSafety == QLatin1String("reentrant"))
node->setThreadSafeness(Node::Reentrant); node->setThreadSafeness(Node::Reentrant);
else if (threadSafety == "thread safe") else if (threadSafety == QLatin1String("thread safe"))
node->setThreadSafeness(Node::ThreadSafe); node->setThreadSafeness(Node::ThreadSafe);
else
node->setThreadSafeness(Node::UnspecifiedSafeness);
}
else else
node->setThreadSafeness(Node::UnspecifiedSafeness); node->setThreadSafeness(Node::UnspecifiedSafeness);
}
else
node->setThreadSafeness(Node::UnspecifiedSafeness);
QString status = element.attribute("status"); QString status = attributes.value(QLatin1String("status")).toString();
if (status == "compat") if (status == QLatin1String("compat"))
node->setStatus(Node::Compat); node->setStatus(Node::Compat);
else if (status == "obsolete") else if (status == QLatin1String("obsolete"))
node->setStatus(Node::Obsolete); node->setStatus(Node::Obsolete);
else if (status == "deprecated") else if (status == QLatin1String("deprecated"))
node->setStatus(Node::Obsolete); node->setStatus(Node::Obsolete);
else if (status == "preliminary") else if (status == QLatin1String("preliminary"))
node->setStatus(Node::Preliminary); node->setStatus(Node::Preliminary);
else if (status == "active") else if (status == QLatin1String("active"))
node->setStatus(Node::Active); node->setStatus(Node::Active);
else if (status == "internal") else if (status == QLatin1String("internal"))
node->setStatus(Node::Internal); node->setStatus(Node::Internal);
else else
node->setStatus(Node::Active); node->setStatus(Node::Active);
QString physicalModuleName = element.attribute("module"); QString physicalModuleName = attributes.value(QLatin1String("module")).toString();
if (!physicalModuleName.isEmpty()) if (!physicalModuleName.isEmpty())
qdb_->addToModule(physicalModuleName, node); qdb_->addToModule(physicalModuleName, node);
if (!href.isEmpty()) { if (!href.isEmpty()) {
if (node->isExternalPage()) if (node->isExternalPage())
node->setUrl(href); node->setUrl(href);
else if (!indexUrl.isEmpty()) else if (!indexUrl.isEmpty())
node->setUrl(indexUrl + QLatin1Char('/') + href); node->setUrl(indexUrl + QLatin1Char('/') + href);
} }
QString since = element.attribute("since"); QString since = attributes.value(QLatin1String("since")).toString();
if (!since.isEmpty()) { if (!since.isEmpty()) {
node->setSince(since); node->setSince(since);
} }
QString groupsAttr = element.attribute("groups"); QString groupsAttr = attributes.value(QLatin1String("groups")).toString();
if (!groupsAttr.isEmpty()) { if (!groupsAttr.isEmpty()) {
QStringList groupNames = groupsAttr.split(","); QStringList groupNames = groupsAttr.split(",");
foreach (const QString &name, groupNames) { foreach (const QString &name, groupNames) {
qdb_->addToGroup(name, node); 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 = attributes.value(QLatin1String("brief")).toString();
if (!briefAttr.isEmpty()) {
node->setReconstitutedBrief(briefAttr);
}
if (!hasReadChildren) {
bool useParent = (elementName == QLatin1String("namespace") && name.isEmpty());
while (reader.readNextStartElement()) {
if (useParent)
readIndexSection(reader, parent, indexUrl);
else
readIndexSection(reader, node, indexUrl);
}
} }
} }
// Create some content for the node. done:
QSet<QString> emptySet; while (!reader.isEndElement()) {
Location t(filePath); if (reader.readNext() == QXmlStreamReader::Invalid) {
if (!filePath.isEmpty()) { break;
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();
} }
} }
} }

View File

@ -42,7 +42,6 @@ class Atom;
class Generator; class Generator;
class QStringList; class QStringList;
class QDocDatabase; class QDocDatabase;
class QDomElement;
class QXmlStreamWriter; class QXmlStreamWriter;
class QDocIndexFiles class QDocIndexFiles
@ -64,7 +63,7 @@ class QDocIndexFiles
bool generateInternalNodes = false); bool generateInternalNodes = false);
void readIndexFile(const QString& path); void readIndexFile(const QString& path);
void readIndexSection(const QDomElement& element, Node* current, const QString& indexUrl); void readIndexSection(QXmlStreamReader &reader, Node* current, const QString& indexUrl);
void resolveIndex(); void resolveIndex();
bool generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false); bool generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
void generateIndexSections(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false); void generateIndexSections(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);

View File

@ -35,7 +35,6 @@
#include "qdoctagfiles.h" #include "qdoctagfiles.h"
#include "qdocdatabase.h" #include "qdocdatabase.h"
#include "qdom.h"
#include "atom.h" #include "atom.h"
#include "doc.h" #include "doc.h"
#include "htmlgenerator.h" #include "htmlgenerator.h"