diff options
Diffstat (limited to 'src/qdoc/qdocindexfiles.cpp')
-rw-r--r-- | src/qdoc/qdocindexfiles.cpp | 534 |
1 files changed, 265 insertions, 269 deletions
diff --git a/src/qdoc/qdocindexfiles.cpp b/src/qdoc/qdocindexfiles.cpp index cdba1b548..2b957a439 100644 --- a/src/qdoc/qdocindexfiles.cpp +++ b/src/qdoc/qdocindexfiles.cpp @@ -105,7 +105,6 @@ void QDocIndexFiles::destroyQDocIndexFiles() */ void QDocIndexFiles::readIndexes(const QStringList& indexFiles) { - relatedList_.clear(); foreach (const QString& indexFile, indexFiles) { QString msg = "Loading index file: " + indexFile; Location::logToStdErr(msg); @@ -209,8 +208,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, ns->setDocumented(); } - } - else if (elementName == QLatin1String("class")) { + } else if (elementName == QLatin1String("class")) { node = new ClassNode(parent, name); if (attributes.hasAttribute(QLatin1String("bases"))) { QString bases = attributes.value(QLatin1String("bases")).toString(); @@ -225,8 +223,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, if (attributes.value(QLatin1String("abstract")) == QLatin1String("true")) abstract = true; node->setAbstract(abstract); - } - else if (elementName == QLatin1String("header")) { + } else if (elementName == QLatin1String("header")) { node = new HeaderNode(parent, name); if (attributes.hasAttribute(QLatin1String("location"))) @@ -236,8 +233,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, location = Location(indexUrl + QLatin1Char('/') + name); else if (!indexUrl.isNull()) location = Location(name); - } - else if (elementName == QLatin1String("qmlclass")) { + } else if (elementName == QLatin1String("qmlclass")) { QmlTypeNode* qcn = new QmlTypeNode(parent, name); qcn->setTitle(attributes.value(QLatin1String("title")).toString()); QString logicalModuleName = attributes.value(QLatin1String("qml-module-name")).toString(); @@ -258,8 +254,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, else if (!indexUrl.isNull()) location = Location(name); node = qcn; - } - else if (elementName == QLatin1String("jstype")) { + } else if (elementName == QLatin1String("jstype")) { QmlTypeNode* qcn = new QmlTypeNode(parent, name); qcn->setGenus(Node::JS); qcn->setTitle(attributes.value(QLatin1String("title")).toString()); @@ -281,8 +276,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, else if (!indexUrl.isNull()) location = Location(name); node = qcn; - } - else if (elementName == QLatin1String("qmlbasictype")) { + } else if (elementName == QLatin1String("qmlbasictype")) { QmlBasicTypeNode* qbtn = new QmlBasicTypeNode(parent, name); qbtn->setTitle(attributes.value(QLatin1String("title")).toString()); if (attributes.hasAttribute(QLatin1String("location"))) @@ -292,8 +286,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, else if (!indexUrl.isNull()) location = Location(name); node = qbtn; - } - else if (elementName == QLatin1String("jsbasictype")) { + } else if (elementName == QLatin1String("jsbasictype")) { QmlBasicTypeNode* qbtn = new QmlBasicTypeNode(parent, name); qbtn->setGenus(Node::JS); qbtn->setTitle(attributes.value(QLatin1String("title")).toString()); @@ -304,8 +297,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, else if (!indexUrl.isNull()) location = Location(name); node = qbtn; - } - else if (elementName == QLatin1String("qmlpropertygroup")) { + } else if (elementName == QLatin1String("qmlpropertygroup")) { QmlTypeNode* qcn = static_cast<QmlTypeNode*>(parent); QmlPropertyGroupNode* qpgn = new QmlPropertyGroupNode(qcn, name); if (attributes.hasAttribute(QLatin1String("location"))) @@ -315,8 +307,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, else if (!indexUrl.isNull()) location = Location(name); node = qpgn; - } - else if (elementName == QLatin1String("jspropertygroup")) { + } else if (elementName == QLatin1String("jspropertygroup")) { QmlTypeNode* qcn = static_cast<QmlTypeNode*>(parent); QmlPropertyGroupNode* qpgn = new QmlPropertyGroupNode(qcn, name); qpgn->setGenus(Node::JS); @@ -327,8 +318,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, else if (!indexUrl.isNull()) location = Location(name); node = qpgn; - } - else if (elementName == QLatin1String("qmlproperty")) { + } else if (elementName == QLatin1String("qmlproperty")) { QString type = attributes.value(QLatin1String("type")).toString(); bool attached = false; if (attributes.value(QLatin1String("attached")) == QLatin1String("true")) @@ -337,10 +327,9 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, if (attributes.value(QLatin1String("writable")) == QLatin1String("false")) readonly = true; QmlPropertyNode* qpn = new QmlPropertyNode(parent, name, type, attached); - qpn->setReadOnly(readonly); + qpn->markReadOnly(readonly); node = qpn; - } - else if (elementName == QLatin1String("jsproperty")) { + } else if (elementName == QLatin1String("jsproperty")) { QString type = attributes.value(QLatin1String("type")).toString(); bool attached = false; if (attributes.value(QLatin1String("attached")) == QLatin1String("true")) @@ -350,26 +339,23 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, readonly = true; QmlPropertyNode* qpn = new QmlPropertyNode(parent, name, type, attached); qpn->setGenus(Node::JS); - qpn->setReadOnly(readonly); + qpn->markReadOnly(readonly); node = qpn; - } - else if (elementName == QLatin1String("group")) { + } else if (elementName == QLatin1String("group")) { CollectionNode* cn = qdb_->addGroup(name); cn->setTitle(attributes.value(QLatin1String("title")).toString()); cn->setSubtitle(attributes.value(QLatin1String("subtitle")).toString()); if (attributes.value(QLatin1String("seen")) == QLatin1String("true")) cn->markSeen(); node = cn; - } - else if (elementName == QLatin1String("module")) { + } else if (elementName == QLatin1String("module")) { CollectionNode* cn = qdb_->addModule(name); cn->setTitle(attributes.value(QLatin1String("title")).toString()); cn->setSubtitle(attributes.value(QLatin1String("subtitle")).toString()); if (attributes.value(QLatin1String("seen")) == QLatin1String("true")) cn->markSeen(); node = cn; - } - else if (elementName == QLatin1String("qmlmodule")) { + } else if (elementName == QLatin1String("qmlmodule")) { QString t = attributes.value(QLatin1String("qml-module-name")).toString(); CollectionNode* cn = qdb_->addQmlModule(t); QStringList info; @@ -380,8 +366,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, if (attributes.value(QLatin1String("seen")) == QLatin1String("true")) cn->markSeen(); node = cn; - } - else if (elementName == QLatin1String("jsmodule")) { + } else if (elementName == QLatin1String("jsmodule")) { QString t = attributes.value(QLatin1String("js-module-name")).toString(); CollectionNode* cn = qdb_->addJsModule(t); QStringList info; @@ -392,36 +377,29 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, if (attributes.value(QLatin1String("seen")) == QLatin1String("true")) cn->markSeen(); node = cn; - } - else if (elementName == QLatin1String("page")) { + } else if (elementName == QLatin1String("page")) { QDocAttr subtype = QDocAttrNone; Node::PageType ptype = Node::NoPageType; QString attr = attributes.value(QLatin1String("subtype")).toString(); if (attr == QLatin1String("attribution")) { subtype = QDocAttrDocument; ptype = Node::AttributionPage; - } - else if (attr == QLatin1String("example")) { + } else if (attr == QLatin1String("example")) { subtype = QDocAttrExample; ptype = Node::ExamplePage; - } - else if (attr == QLatin1String("file")) { + } else if (attr == QLatin1String("file")) { subtype = QDocAttrFile; ptype = Node::NoPageType; - } - else if (attr == QLatin1String("image")) { + } else if (attr == QLatin1String("image")) { subtype = QDocAttrImage; ptype = Node::NoPageType; - } - else if (attr == QLatin1String("page")) { + } else if (attr == QLatin1String("page")) { subtype = QDocAttrDocument; ptype = Node::ArticlePage; - } - else if (attr == QLatin1String("externalpage")) { + } else if (attr == QLatin1String("externalpage")) { subtype = QDocAttrExternalPage; ptype = Node::ArticlePage; - } - else + } else goto done; if (current && current->isExample()) { @@ -454,8 +432,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, node = pn; - } - else if (elementName == QLatin1String("enum")) { + } else if (elementName == QLatin1String("enum")) { EnumNode* enumNode = new EnumNode(parent, name); if (!indexUrl.isEmpty()) @@ -480,8 +457,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, node = enumNode; hasReadChildren = true; - } - else if (elementName == QLatin1String("typedef")) { + } else if (elementName == QLatin1String("typedef")) { node = new TypedefNode(parent, name); if (!indexUrl.isEmpty()) @@ -489,8 +465,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, else if (!indexUrl.isNull()) location = Location(parent->name().toLower() + ".html"); - } - else if (elementName == QLatin1String("property")) { + } else if (elementName == QLatin1String("property")) { node = new PropertyNode(parent, name); if (!indexUrl.isEmpty()) @@ -508,12 +483,10 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, attached = true; FunctionNode* fn = new FunctionNode(metaness, parent, name, attached); if (fn->isCppNode()) { - fn->setReturnType(attributes.value(QLatin1String("return")).toString()); + fn->setReturnType(attributes.value(QLatin1String("type")).toString()); fn->setVirtualness(attributes.value(QLatin1String("virtual")).toString()); fn->setConst(attributes.value(QLatin1String("const")) == QLatin1String("true")); fn->setStatic(attributes.value(QLatin1String("static")) == QLatin1String("true")); - fn->setIsDeleted(attributes.value(QLatin1String("delete")) == QLatin1String("true")); - fn->setIsDefaulted(attributes.value(QLatin1String("default")) == QLatin1String("true")); fn->setFinal(attributes.value(QLatin1String("final")) == QLatin1String("true")); fn->setOverride(attributes.value(QLatin1String("override")) == QLatin1String("true")); int refness = attributes.value(QLatin1String("refness")).toUInt(); @@ -521,32 +494,31 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, fn->setRef(true); else if (refness == 2) fn->setRefRef(true); - if (attributes.value(QLatin1String("overload")) == QLatin1String("true")) { - fn->setOverloadFlag(true); + /* + Theoretically, this should ensure that each function + node receives the same overload number and overload + flag it was written with, and it should be unnecessary + to call normalizeOverloads() for index nodes. + */ + if (attributes.value(QLatin1String("overload")) == QLatin1String("true")) fn->setOverloadNumber(attributes.value(QLatin1String("overload-number")).toUInt()); - } - else { - fn->setOverloadFlag(false); + else fn->setOverloadNumber(0); - } - if (attributes.hasAttribute(QLatin1String("relates"))) { - QString relatesName = attributes.value(QLatin1String("relates")).toString(); - if (relatesName != parent->name()) - relatedList_.append(QPair<FunctionNode*, QString>(fn, relatesName)); - } /* 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. That is ok + because we reconstruct the parameter list and the + return type, from which the signature was built in + the first place and from which it can be rebuilt. */ while (reader.readNextStartElement()) { QXmlStreamAttributes childAttributes = reader.attributes(); if (reader.name() == QLatin1String("parameter")) { // Do not use the default value for the parameter; it is not // required, and has been known to cause problems. - Parameter parameter(childAttributes.value(QLatin1String("type")).toString(), - childAttributes.value(QLatin1String("name")).toString(), - QString()); // childAttributes.value(QLatin1String("default")) - fn->addParameter(parameter); + QString type = childAttributes.value(QLatin1String("type")).toString(); + QString name = childAttributes.value(QLatin1String("name")).toString(); + fn->parameters().append(type, name); } else if (reader.name() == QLatin1String("keyword")) { insertTarget(TargetRec::Keyword, childAttributes, fn); } else if (reader.name() == QLatin1String("target")) { @@ -563,28 +535,30 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, location = Location(parent->name().toLower() + ".html"); hasReadChildren = true; - } - else if (elementName == QLatin1String("variable")) { + } else if (elementName == QLatin1String("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 (elementName == QLatin1String("keyword")) { + } else if (elementName == QLatin1String("keyword")) { insertTarget(TargetRec::Keyword, attributes, current); goto done; - } - else if (elementName == QLatin1String("target")) { + } else if (elementName == QLatin1String("target")) { insertTarget(TargetRec::Target, attributes, current); goto done; - } - else if (elementName == QLatin1String("contents")) { + } else if (elementName == QLatin1String("contents")) { insertTarget(TargetRec::Contents, attributes, current); goto done; - } - else + } else if (elementName == QLatin1String("proxy")) { + node = new ProxyNode(parent, name); + if (!indexUrl.isEmpty()) + location = Location(indexUrl + QLatin1Char('/') + name.toLower() + ".html"); + else if (!indexUrl.isNull()) + location = Location(name.toLower() + ".html"); + } else { goto done; + } { QString access = attributes.value(QLatin1String("access")).toString(); @@ -596,12 +570,10 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, node->setAccess(Node::Private); else node->setAccess(Node::Public); + if (attributes.hasAttribute(QLatin1String("related"))) + node->setRelatedNonmember(attributes.value(QLatin1String("related")) == QLatin1String("true")); - if ((elementName != QLatin1String("page")) && - (elementName != QLatin1String("qmlclass")) && - (elementName != QLatin1String("qmlbasictype")) && - (elementName != QLatin1String("jstype")) && - (elementName != QLatin1String("jsbasictype"))) { + if (attributes.hasAttribute(QLatin1String("threadsafety"))) { QString threadSafety = attributes.value(QLatin1String("threadsafety")).toString(); if (threadSafety == QLatin1String("non-reentrant")) node->setThreadSafeness(Node::NonReentrant); @@ -662,7 +634,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, } Doc doc(location, location, QString(), emptySet, emptySet); // placeholder node->setDoc(doc); - node->setIndexNodeFlag(); + node->setIndexNodeFlag(); // Important: This node came from an index file. node->setOutputSubdirectory(project_.toLower()); QString briefAttr = attributes.value(QLatin1String("brief")).toString(); if (!briefAttr.isEmpty()) { @@ -743,34 +715,54 @@ void QDocIndexFiles::resolveIndex() basesList_.clear(); } -/* - Goes though the list of nodes that are related to other aggregates - that were read from all index files, and tries to find the aggregate - nodes from the database. Calls the node's setRelates() for each - aggregate that is found in the local module (primary tree). - - This function is meant to be called before starting the doc generation, - after all the index files are read. - */ -void QDocIndexFiles::resolveRelates() +static const QString getAccessString(Node::Access t) { - if (relatedList_.isEmpty()) - return; - // Restrict searching only to the local (primary) tree - QVector<Tree*> searchOrder = qdb_->searchOrder(); - qdb_->setLocalSearch(); + switch (t) { + case Node::Public: + return QLatin1String("public"); + case Node::Protected: + return QLatin1String("protected"); + case Node::Private: + return QLatin1String("private"); + default: + break; + } + return QLatin1String("public"); +} - QPair<FunctionNode*,QString> relatedPair; - foreach (relatedPair, relatedList_) { - QStringList path = relatedPair.second.split("::"); - Node* n = qdb_->findRelatesNode(path); - if (n) - relatedPair.first->setRelates(static_cast<PageNode*>(n)); +static const QString getStatusString(Node::Status t) +{ + switch (t) { + case Node::Obsolete: + case Node::Deprecated: + return QLatin1String("obsolete"); + case Node::Preliminary: + return QLatin1String("preliminary"); + case Node::Active: + return QLatin1String("active"); + case Node::Internal: + return QLatin1String("internal"); + default: + break; } - // Restore original search order - qdb_->setSearchOrder(searchOrder); - relatedList_.clear(); + return QLatin1String("active"); +} + +static const QString getThreadSafenessString(Node::ThreadSafeness t) +{ + switch (t) { + case Node::NonReentrant: + return QLatin1String("non-reentrant"); + case Node::Reentrant: + return QLatin1String("reentrant"); + case Node::ThreadSafe: + return QLatin1String("thread safe"); + case Node::UnspecifiedSafeness: + default: + break; + } + return QLatin1String("unspecified"); } /*! @@ -778,12 +770,9 @@ void QDocIndexFiles::resolveRelates() specified, returning true if an element was written, and returning false if an element is not written. - \node Currently \a generateInternalNodes is always \c true. If it is - passed as \c false, then nodes marked internal or private are skipped. + \note Function nodes are processed in generateFunctionSection() */ -bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, - Node* node, - bool generateInternalNodes) +bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter &writer, Node *node) { if (!gen_) gen_ = Generator::currentGenerator(); @@ -794,8 +783,6 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, */ if (node->isIndexNode()) return false; - if (!generateInternalNodes && (node->isInternal() || node->isPrivate())) - return false; QString nodeName; QString logicalModuleName; @@ -873,9 +860,6 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, case Node::Property: nodeName = "property"; break; - case Node::Function: - nodeName = "function"; - break; case Node::Variable: nodeName = "variable"; break; @@ -891,27 +875,10 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, case Node::JsPropertyGroup: nodeName = "jspropertygroup"; break; - default: - return false; - } - - QString access; - switch (node->access()) { - case Node::Public: - access = "public"; - break; - case Node::Protected: - access = "protected"; - break; - case Node::Private: - /* - Should we test generateInternalNodes here and return - false immediately if it is set? As it is now, we are - always writing all internal and private nodes to the - index file. - */ - access = "private"; + case Node::Proxy: + nodeName = "proxy"; break; + case Node::Function: // Now processed in generateFunctionSection() default: return false; } @@ -923,46 +890,9 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, writer.writeStartElement(nodeName); - QXmlStreamAttributes attributes; - if (!node->isTextPageNode() && !node->isCollectionNode() && !node->isHeader()) { - 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::Obsolete: - case Node::Deprecated: - status = "obsolete"; - break; - case Node::Preliminary: - status = "preliminary"; - break; - case Node::Active: - status = "active"; - break; - case Node::Internal: - status = "internal"; - break; - default: - status = "main"; - break; + if (node->threadSafeness() != Node::UnspecifiedSafeness) + writer.writeAttribute("threadsafety", getThreadSafenessString(node->threadSafeness())); } writer.writeAttribute("name", objName); @@ -1000,9 +930,9 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, if (!href.isEmpty()) writer.writeAttribute("href", href); - writer.writeAttribute("status", status); + writer.writeAttribute("status", getStatusString(node->status())); if (!node->isTextPageNode() && !node->isCollectionNode() && !node->isHeader()) { - writer.writeAttribute("access", access); + writer.writeAttribute("access", getAccessString(node->access())); if (node->isAbstract()) writer.writeAttribute("abstract", "true"); } @@ -1014,9 +944,11 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, writer.writeAttribute("lineno", QString("%1").arg(declLocation.lineNo())); } - if (!node->since().isEmpty()) { + if (node->isRelatedNonmember()) + writer.writeAttribute("related", "true"); + + if (!node->since().isEmpty()) writer.writeAttribute("since", node->since()); - } QString brief = node->doc().trimmedBriefText(node->name()).toString(); switch (node->nodeType()) { @@ -1202,68 +1134,6 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, writer.writeAttribute("brief", brief); } break; - case Node::Function: - { - const FunctionNode* fn = static_cast<const FunctionNode*>(node); - writer.writeAttribute("meta", fn->metanessString()); - if (fn->isCppNode()) { - writer.writeAttribute("virtual", fn->virtualness()); - writer.writeAttribute("const", fn->isConst() ? "true":"false"); - writer.writeAttribute("static", fn->isStatic() ? "true":"false"); - writer.writeAttribute("overload", fn->isOverload() ? "true":"false"); - writer.writeAttribute("delete", fn->isDeleted() ? "true" : "false"); - writer.writeAttribute("default", fn->isDefaulted() ? "true" : "false"); - writer.writeAttribute("final", fn->isFinal() ? "true" : "false"); - writer.writeAttribute("override", fn->isOverride() ? "true" : "false"); - if (fn->isRef()) - writer.writeAttribute("refness", QString::number(1)); - else if (fn->isRefRef()) - writer.writeAttribute("refness", QString::number(2)); - if (fn->isOverload()) - writer.writeAttribute("overload-number", QString::number(fn->overloadNumber())); - if (fn->relates()) - writer.writeAttribute("relates", fn->relates()->name()); - if (fn->hasAssociatedProperties()) { - QStringList associatedProperties; - foreach (PropertyNode* pn, fn->associatedProperties()) { - associatedProperties << pn->name(); - } - associatedProperties.sort(); - writer.writeAttribute("associated-property", associatedProperties.join(QLatin1Char(','))); - } - writer.writeAttribute("type", fn->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 by qdoc. However, - we need it for the webxml generator. - */ - QString signature = fn->signature(false); - // 'const' is already part of FunctionNode::signature() - if (fn->isFinal()) - signature += " final"; - if (fn->isOverride()) - signature += " override"; - if (fn->isPureVirtual()) - signature += " = 0"; - else if (fn->isDeleted()) - signature += " = delete"; - else if (fn->isDefaulted()) - signature += " = default"; - writer.writeAttribute("signature", signature); - - for (int i = 0; i < fn->parameters().size(); ++i) { - Parameter parameter = fn->parameters()[i]; - writer.writeStartElement("parameter"); - writer.writeAttribute("type", parameter.dataType()); - writer.writeAttribute("name", parameter.name()); - writer.writeAttribute("default", parameter.defaultValue()); - writer.writeEndElement(); // parameter - } - } - } - break; case Node::JsProperty: case Node::QmlProperty: { @@ -1351,6 +1221,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, writer.writeAttribute("enum",typedefNode->associatedEnum()->fullDocumentName()); } break; + case Node::Function: // Now processed in generateFunctionSection() default: break; } @@ -1448,32 +1319,154 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, } /*! + This function writes a <function> element for \a fn to the + index file using \a writer. + */ +void QDocIndexFiles::generateFunctionSection(QXmlStreamWriter &writer, FunctionNode *fn) +{ + QString objName = fn->name(); + writer.writeStartElement("function"); + writer.writeAttribute("name", objName); + + QString fullName = fn->fullDocumentName(); + if (fullName != objName) + writer.writeAttribute("fullname", fullName); + QString href = gen_->fullDocumentLocation(fn); + if (!href.isEmpty()) + writer.writeAttribute("href", href); + if (fn->threadSafeness() != Node::UnspecifiedSafeness) + writer.writeAttribute("threadsafety", getThreadSafenessString(fn->threadSafeness())); + writer.writeAttribute("status", getStatusString(fn->status())); + writer.writeAttribute("access", getAccessString(fn->access())); + + const Location &declLocation = fn->declLocation(); + if (!declLocation.fileName().isEmpty()) + writer.writeAttribute("location", declLocation.fileName()); + if (!declLocation.filePath().isEmpty()) { + writer.writeAttribute("filepath", declLocation.filePath()); + writer.writeAttribute("lineno", QString("%1").arg(declLocation.lineNo())); + } + + if (fn->isRelatedNonmember()) + writer.writeAttribute("related", "true"); + if (!fn->since().isEmpty()) + writer.writeAttribute("since", fn->since()); + + QString brief = fn->doc().trimmedBriefText(fn->name()).toString(); + writer.writeAttribute("meta", fn->metanessString()); + if (fn->isCppNode()) { + writer.writeAttribute("virtual", fn->virtualness()); + writer.writeAttribute("const", fn->isConst() ? "true" : "false"); + writer.writeAttribute("static", fn->isStatic() ? "true" : "false"); + writer.writeAttribute("final", fn->isFinal() ? "true" : "false"); + writer.writeAttribute("override", fn->isOverride() ? "true" : "false"); + /* + This ensures that for functions that have overloads, + the first function written is the one that is not an + overload, and the overloads follow it immediately in + the index file numbered from 1 to n. + */ + if (fn->isOverload() && (fn->overloadNumber() > 0)) { + writer.writeAttribute("overload", "true"); + writer.writeAttribute("overload-number", QString::number(fn->overloadNumber())); + } + if (fn->isRef()) + writer.writeAttribute("refness", QString::number(1)); + else if (fn->isRefRef()) + writer.writeAttribute("refness", QString::number(2)); + if (fn->hasAssociatedProperties()) { + QStringList associatedProperties; + foreach (Node *n, fn->associatedProperties()) { + associatedProperties << n->name(); + } + associatedProperties.sort(); + writer.writeAttribute("associated-property", associatedProperties.join(QLatin1Char(','))); + } + writer.writeAttribute("type", fn->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 by qdoc. However, + we need it for the webxml generator. + */ + QString signature = fn->signature(false, false); + // 'const' is already part of FunctionNode::signature() + if (fn->isFinal()) + signature += " final"; + if (fn->isOverride()) + signature += " override"; + if (fn->isPureVirtual()) + signature += " = 0"; + writer.writeAttribute("signature", signature); + + for (int i = 0; i < fn->parameters().count(); ++i) { + const Parameter ¶meter = fn->parameters().at(i); + writer.writeStartElement("parameter"); + writer.writeAttribute("type", parameter.type()); + writer.writeAttribute("name", parameter.name()); + writer.writeAttribute("default", parameter.defaultValue()); + writer.writeEndElement(); // parameter + } + } + writer.writeEndElement(); +} + +/*! + This function outputs a <function> element to the index file + for each FunctionNode in \a aggregate using the \a writer. + The \a aggregate has a function map that contains all the + function nodes indexed by function name. But the map is not + used as a multimap, so if the \a aggregate contains multiple + functions with the same name, only one of those functions is + in the function map index. The others are linked to that + function using the next overload pointer. + + So this function generates a <function> element for a function + followed by a function element for each of its overloads. If a + <function> element represents an overload, it has an \c overload + attribute set to \c true and an \c {overload-number} attribute + set to the function's overload number. If the <function> + element does not represent an overload, the <function> element + has neither of these attributes. + */ +void QDocIndexFiles::generateFunctionSections(QXmlStreamWriter &writer, Aggregate *aggregate) +{ + FunctionMap &functionMap = aggregate->functionMap(); + if (!functionMap.isEmpty()) { + FunctionMap::iterator i = functionMap.begin(); + while (i != functionMap.end()) { + FunctionNode *fn = i.value(); + while (fn != nullptr) { + generateFunctionSection(writer, fn); + fn = fn->nextOverload(); + } + i++; + } + } +} + +/*! 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. + using the \a writer specified. */ -void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer, - Node* node, - bool generateInternalNodes) +void QDocIndexFiles::generateIndexSections(QXmlStreamWriter &writer, Node *node) { /* Note that groups, modules, and QML modules are written after all the other nodes. */ - if (node->isGroup() || node->isModule() || node->isQmlModule() || node->isJsModule()) + if (node->isCollectionNode() || + node->isGroup() || node->isModule() || node->isQmlModule() || node->isJsModule()) return; - if (generateIndexSection(writer, node, generateInternalNodes)) { + if (generateIndexSection(writer, node)) { if (node->isAggregate()) { - const Aggregate* aggregate = static_cast<const Aggregate*>(node); - - NodeList cnodes = aggregate->childNodes(); - std::sort(cnodes.begin(), cnodes.end(), Node::nodeNameLessThan); - - foreach (Node* child, cnodes) { - generateIndexSections(writer, child, generateInternalNodes); - } + Aggregate *aggregate = static_cast<Aggregate *>(node); + // First write the function children, then write the nonfunction children. + generateFunctionSections(writer, aggregate); + foreach (Node *n, aggregate->nonfunctionList()) + generateIndexSections(writer, n); } if (node == root_) { @@ -1489,7 +1482,7 @@ void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer, if (!groups.isEmpty()) { CNMap::ConstIterator g = groups.constBegin(); while (g != groups.constEnd()) { - if (generateIndexSection(writer, g.value(), generateInternalNodes)) + if (generateIndexSection(writer, g.value())) writer.writeEndElement(); ++g; } @@ -1499,7 +1492,7 @@ void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer, if (!modules.isEmpty()) { CNMap::ConstIterator g = modules.constBegin(); while (g != modules.constEnd()) { - if (generateIndexSection(writer, g.value(), generateInternalNodes)) + if (generateIndexSection(writer, g.value())) writer.writeEndElement(); ++g; } @@ -1509,7 +1502,7 @@ void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer, if (!qmlModules.isEmpty()) { CNMap::ConstIterator g = qmlModules.constBegin(); while (g != qmlModules.constEnd()) { - if (generateIndexSection(writer, g.value(), generateInternalNodes)) + if (generateIndexSection(writer, g.value())) writer.writeEndElement(); ++g; } @@ -1519,7 +1512,7 @@ void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer, if (!jsModules.isEmpty()) { CNMap::ConstIterator g = jsModules.constBegin(); while (g != jsModules.constEnd()) { - if (generateIndexSection(writer, g.value(), generateInternalNodes)) + if (generateIndexSection(writer, g.value())) writer.writeEndElement(); ++g; } @@ -1531,13 +1524,16 @@ void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer, } /*! - Outputs an index file. + Writes aqdoc module index in XML to a file named \afilerName. + \a url becaomes the \c url attribute of the <INDEX> element. + \a title becomes the \c title attribute of the <INDEX> element. + \a g is used to get the Config object that contains the variables + from the module's .qdocconf file. */ void QDocIndexFiles::generateIndex(const QString& fileName, const QString& url, const QString& title, - Generator* g, - bool generateInternalNodes) + Generator *g) { QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) @@ -1562,7 +1558,7 @@ void QDocIndexFiles::generateIndex(const QString& fileName, if (!root_->tree()->indexTitle().isEmpty()) writer.writeAttribute("indexTitle", root_->tree()->indexTitle()); - generateIndexSections(writer, root_, generateInternalNodes); + generateIndexSections(writer, root_); writer.writeEndElement(); // INDEX writer.writeEndElement(); // QDOCINDEX |