summaryrefslogtreecommitdiffstats
path: root/src/tools/qdoc/qdocindexfiles.cpp
diff options
context:
space:
mode:
authorMartin Smith <martin.smith@digia.com>2015-02-13 13:00:22 +0100
committerMartin Smith <martin.smith@digia.com>2015-02-20 11:37:18 +0000
commit62a2f46d290c67343366cb4f707830fe7d8b3d63 (patch)
tree4bde42e59c1d54e93fa42d2050f955782bc17ca9 /src/tools/qdoc/qdocindexfiles.cpp
parentfe7c2662b5a6a458459bf11b8d06a2b34318918d (diff)
qdoc: Support documentation of JavaScript
This update provides the actual support for documenting JavaScript. It has been tested with JavaScript commands in qdoc comments in .qdoc files but not in .js files. Currently, we have the use case of needing to document JavaScript using qdoc comments in .qdoc files. For each qdoc command for QML, i.e. \qmltype, \qmlproperty, etc, there is now a corresponding JavaScript command, i.e. \jstype, \jsproperty, etc. Some of these might not be needed, but they are all provided. Briefly, document JavaScript in a .qdoc file the same way you would document QML in a .qdoc file, but instead of using the \qmlxxx commands, use \jsxxx commands. Change-Id: Ib68a5f66c16472af87d9f776db162332ca13fbb7 Task-number: QTBUG-43715 Reviewed-by: Topi Reiniƶ <topi.reinio@digia.com>
Diffstat (limited to 'src/tools/qdoc/qdocindexfiles.cpp')
-rw-r--r--src/tools/qdoc/qdocindexfiles.cpp319
1 files changed, 230 insertions, 89 deletions
diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp
index efc0eb1e0f2..026c64b587d 100644
--- a/src/tools/qdoc/qdocindexfiles.cpp
+++ b/src/tools/qdoc/qdocindexfiles.cpp
@@ -229,6 +229,29 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
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"));
@@ -240,6 +263,18 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
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);
@@ -251,6 +286,18 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
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;
@@ -271,6 +318,27 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
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")) {
@@ -283,30 +351,58 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
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") {
- GroupNode* gn = qdb_->addGroup(name);
- gn->setTitle(element.attribute("title"));
- gn->setSubTitle(element.attribute("subtitle"));
+ CollectionNode* cn = qdb_->addGroup(name);
+ cn->setTitle(element.attribute("title"));
+ cn->setSubTitle(element.attribute("subtitle"));
if (element.attribute("seen") == "true")
- gn->markSeen();
- node = gn;
+ cn->markSeen();
+ node = cn;
}
else if (element.nodeName() == "module") {
- ModuleNode* mn = qdb_->addModule(name);
- mn->setTitle(element.attribute("title"));
- mn->setSubTitle(element.attribute("subtitle"));
+ CollectionNode* cn = qdb_->addModule(name);
+ cn->setTitle(element.attribute("title"));
+ cn->setSubTitle(element.attribute("subtitle"));
if (element.attribute("seen") == "true")
- mn->markSeen();
- node = mn;
+ cn->markSeen();
+ node = cn;
}
else if (element.nodeName() == "qmlmodule") {
- QString t = element.attribute("qml-module-name") + " " + element.attribute("qml-module-version");
- QmlModuleNode* qmn = qdb_->addQmlModule(t);
- qmn->setTitle(element.attribute("title"));
- qmn->setSubTitle(element.attribute("subtitle"));
+ 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")
- qmn->markSeen();
- node = qmn;
+ 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;
@@ -335,7 +431,7 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
else
return;
- DocNode* docNode = new DocNode(parent, name, subtype, ptype);
+ DocumentNode* docNode = new DocumentNode(parent, name, subtype, ptype);
docNode->setTitle(element.attribute("title"));
if (element.hasAttribute("location"))
@@ -492,7 +588,9 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
if ((element.nodeName() != "page") &&
(element.nodeName() != "qmlclass") &&
- (element.nodeName() != "qmlbasictype")) {
+ (element.nodeName() != "qmlbasictype") &&
+ (element.nodeName() != "jstype") &&
+ (element.nodeName() != "jsbasictype")) {
QString threadSafety = element.attribute("threadsafety");
if (threadSafety == "non-reentrant")
node->setThreadSafeness(Node::NonReentrant);
@@ -646,15 +744,21 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
break;
case Node::QmlType:
{
- nodeName = "qmlclass";
- QmlModuleNode* qmn = node->logicalModule();
- if (qmn)
- logicalModuleName = qmn->logicalModuleName();
+ if (node->isQmlNode())
+ nodeName = "qmlclass";
+ else
+ nodeName = "jstype";
+ CollectionNode* cn = node->logicalModule();
+ if (cn)
+ logicalModuleName = cn->logicalModuleName();
qmlFullBaseName = node->qmlFullBaseName();
}
break;
case Node::QmlBasicType:
- nodeName = "qmlbasictype";
+ if (node->isQmlNode())
+ nodeName = "qmlbasictype";
+ else
+ nodeName = "jsbasictype";
break;
case Node::Document:
nodeName = "page";
@@ -666,7 +770,10 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
nodeName = "module";
break;
case Node::QmlModule:
- nodeName = "qmlmodule";
+ if (node->isQmlNode())
+ nodeName = "qmlmodule";
+ else
+ nodeName = "jsmodule";
break;
case Node::Enum:
nodeName = "enum";
@@ -684,19 +791,34 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
nodeName = "variable";
break;
case Node::QmlProperty:
- nodeName = "qmlproperty";
+ if (node->isQmlNode())
+ nodeName = "qmlproperty";
+ else
+ nodeName = "jsProperty";
break;
case Node::QmlPropertyGroup:
- nodeName = "qmlpropertygroup";
+ if (node->isQmlNode())
+ nodeName = "qmlpropertygroup";
+ else
+ nodeName = "jspropertygroup";
break;
case Node::QmlSignal:
- nodeName = "qmlsignal";
+ if (node->isQmlNode())
+ nodeName = "qmlsignal";
+ else
+ nodeName = "jssignal";
break;
case Node::QmlSignalHandler:
- nodeName = "qmlsignalhandler";
+ if (node->isQmlNode())
+ nodeName = "qmlsignalhandler";
+ else
+ nodeName = "jssignalhandler";
break;
case Node::QmlMethod:
- nodeName = "qmlmethod";
+ if (node->isQmlNode())
+ nodeName = "qmlmethod";
+ else
+ nodeName = "jsmethod";
break;
default:
return false;
@@ -711,16 +833,6 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
access = "protected";
break;
case Node::Private:
-#if 0
- // Do not include private non-internal nodes in the index.
- // (Internal public and protected nodes are marked as private
- // by qdoc. We can check their internal status to determine
- // whether they were really private to begin with.)
- if (node->status() == Node::Internal && generateInternalNodes)
- access = "internal";
- else
- return false;
-#endif
{
access = "private";
bool b = generateInternalNodes;
@@ -741,7 +853,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
QXmlStreamAttributes attributes;
- if (!node->isDocNode() && !node->isGroup() && !node->isModule() && !node->isQmlModule()) {
+ if (!node->isDocumentNode() && !node->isCollectionNode()) {
QString threadSafety;
switch (node->threadSafeness()) {
case Node::NonReentrant:
@@ -791,13 +903,24 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
if (node->isQmlModule()) {
logicalModuleName = node->logicalModuleName();
logicalModuleVersion = node->logicalModuleVersion();
+ 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);
+ }
}
- 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;
@@ -816,12 +939,12 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
}
else
href = node->name();
- if (node->isQmlNode()) {
+ if (node->isQmlNode() || node->isJsNode()) {
InnerNode* p = node->parent();
if (p) {
- if (p->isQmlPropertyGroup())
+ if (p->isQmlPropertyGroup() || p->isJsPropertyGroup())
p = p->parent();
- if (p && p->isQmlType() && p->isAbstract())
+ if (p && (p->isQmlType() || p->isJsType()) && p->isAbstract())
href.clear();
}
}
@@ -829,7 +952,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
writer.writeAttribute("href", href);
writer.writeAttribute("status", status);
- if (!node->isDocNode() && !node->isGroup() && !node->isModule() && !node->isQmlModule()) {
+ if (!node->isDocumentNode() && !node->isCollectionNode()) {
writer.writeAttribute("access", access);
if (node->isAbstract())
writer.writeAttribute("abstract", "true");
@@ -898,7 +1021,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
a title, and other attributes.
*/
bool writeModuleName = false;
- const DocNode* docNode = static_cast<const DocNode*>(node);
+ const DocumentNode* docNode = static_cast<const DocumentNode*>(node);
switch (docNode->subType()) {
case Node::Example:
writer.writeAttribute("subtype", "example");
@@ -935,22 +1058,22 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
break;
case Node::Group:
{
- const GroupNode* gn = static_cast<const GroupNode*>(node);
- writer.writeAttribute("seen", gn->wasSeen() ? "true" : "false");
- writer.writeAttribute("title", gn->title());
- if (!gn->subTitle().isEmpty())
- writer.writeAttribute("subtitle", gn->subTitle());
- if (!gn->physicalModuleName().isEmpty())
- writer.writeAttribute("module", gn->physicalModuleName());
- if (!gn->groupNames().isEmpty())
- writer.writeAttribute("groups", gn->groupNames().join(","));
+ 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 (!gn->members().isEmpty()) {
+ if (!cn->members().isEmpty()) {
QStringList names;
- foreach (const Node* member, gn->members())
+ foreach (const Node* member, cn->members())
names.append(member->name());
writer.writeAttribute("members", names.join(","));
}
@@ -960,22 +1083,22 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
break;
case Node::Module:
{
- const ModuleNode* mn = static_cast<const ModuleNode*>(node);
- writer.writeAttribute("seen", mn->wasSeen() ? "true" : "false");
- writer.writeAttribute("title", mn->title());
- if (!mn->subTitle().isEmpty())
- writer.writeAttribute("subtitle", mn->subTitle());
- if (!mn->physicalModuleName().isEmpty())
- writer.writeAttribute("module", mn->physicalModuleName());
- if (!mn->groupNames().isEmpty())
- writer.writeAttribute("groups", mn->groupNames().join(","));
+ 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 (!mn->members().isEmpty()) {
+ if (!cn->members().isEmpty()) {
QStringList names;
- foreach (const Node* member, mn->members())
+ foreach (const Node* member, cn->members())
names.append(member->name());
writer.writeAttribute("members", names.join(","));
}
@@ -985,22 +1108,22 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
break;
case Node::QmlModule:
{
- const QmlModuleNode* qmn = static_cast<const QmlModuleNode*>(node);
- writer.writeAttribute("seen", qmn->wasSeen() ? "true" : "false");
- writer.writeAttribute("title", qmn->title());
- if (!qmn->subTitle().isEmpty())
- writer.writeAttribute("subtitle", qmn->subTitle());
- if (!qmn->physicalModuleName().isEmpty())
- writer.writeAttribute("module", qmn->physicalModuleName());
- if (!qmn->groupNames().isEmpty())
- writer.writeAttribute("groups", qmn->groupNames().join(","));
+ 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 (!qmn->members().isEmpty()) {
+ if (!cn->members().isEmpty()) {
QStringList names;
- foreach (const Node* member, qmn->members())
+ foreach (const Node* member, cn->members())
names.append(member->name());
writer.writeAttribute("members", names.join(","));
}
@@ -1195,7 +1318,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
if (node->doc().hasTargets()) {
bool external = false;
if (node->type() == Node::Document) {
- const DocNode* docNode = static_cast<const DocNode*>(node);
+ const DocumentNode* docNode = static_cast<const DocumentNode*>(node);
if (docNode->subType() == Node::ExternalPage)
external = true;
}
@@ -1295,9 +1418,17 @@ bool compareNodes(const Node* n1, const Node* n2)
return false;
}
- if (n1->isDocNode() && n2->isDocNode()) {
- const DocNode* f1 = static_cast<const DocNode*>(n1);
- const DocNode* f2 = static_cast<const DocNode*>(n2);
+ 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())
@@ -1321,7 +1452,7 @@ void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer,
Note that groups, modules, and QML modules are written
after all the other nodes.
*/
- if (node->isGroup() || node->isModule() || node->isQmlModule())
+ if (node->isGroup() || node->isModule() || node->isQmlModule() || node->isJsModule())
return;
if (generateIndexSection(writer, node, generateInternalNodes)) {
@@ -1374,6 +1505,16 @@ void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer,
++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();