summaryrefslogtreecommitdiffstats
path: root/src/tools
diff options
context:
space:
mode:
authorMartin Smith <martin.smith@digia.com>2014-07-28 14:21:37 +0200
committerMartin Smith <martin.smith@digia.com>2014-08-20 21:59:23 +0200
commita2c432e97818ec16ead9be0d0aee3e43cf10929e (patch)
tree200d7aab7de7bda12ae46303a131920d6fe325dd /src/tools
parent0da4ddfcc59a639b014296a4544c8aff5d91f3f9 (diff)
qdoc: Allow choice of linking to QML or CPP
This update enables using QML or CPP as the parameter in square brackets for the \l command. You will use this when, for example, there exist both a C++ class named QWidget and a QML type named QWidget and your \l {QWidget} links to the wrong one. Suppose you write \l {QWidget} expecting it to link to the QML type named QWidget, but it links to the C++ class named QWidget. Then write this instead: \l [QML] {QWidget} Or if you wrote \l {QWidget} expecting it to link to the C++ class, but it links to the QML type, write this instead: \l [CPP] {QWidget} A qdoc warning is printed if qdoc can not recognize the parameter in square brackets. There will be a further update to complete this task for implementing the other type of parameter that can be in the square brackets. Task-number: QTBUG-39221 Change-Id: I5dd85478f968025ecbe337a8aabcc31d8b12a86d Reviewed-by: Topi Reiniƶ <topi.reinio@digia.com>
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/qdoc/atom.cpp24
-rw-r--r--src/tools/qdoc/atom.h8
-rw-r--r--src/tools/qdoc/ditaxmlgenerator.cpp147
-rw-r--r--src/tools/qdoc/htmlgenerator.cpp75
-rw-r--r--src/tools/qdoc/node.cpp89
-rw-r--r--src/tools/qdoc/node.h33
-rw-r--r--src/tools/qdoc/qdocdatabase.cpp158
-rw-r--r--src/tools/qdoc/qdocdatabase.h79
-rw-r--r--src/tools/qdoc/qdocindexfiles.cpp27
-rw-r--r--src/tools/qdoc/qmlvisitor.cpp2
-rw-r--r--src/tools/qdoc/tree.cpp463
-rw-r--r--src/tools/qdoc/tree.h59
12 files changed, 697 insertions, 467 deletions
diff --git a/src/tools/qdoc/atom.cpp b/src/tools/qdoc/atom.cpp
index 5c699b0546..0c17a38e51 100644
--- a/src/tools/qdoc/atom.cpp
+++ b/src/tools/qdoc/atom.cpp
@@ -369,12 +369,15 @@ void Atom::dump() const
}
/*!
- The only constructor for LinkAtom. It only create an Atom
- of type Atom::Link with \a p1 being the link text. \a p2
- contains some search parameters.
+ The only constructor for LinkAtom. It creates an Atom of
+ type Atom::Link. \a p1 being the link target. \a p2 is the
+ parameters in square brackets. Normally there is just one
+ word in the square brackets, but there can be up to three
+ words separated by spaces. The constructor splits \a p2 on
+ the space character.
*/
LinkAtom::LinkAtom(const QString& p1, const QString& p2)
- : Atom(p1), genus_(DontCare), goal_(Node::NoType), domain_(0)
+ : Atom(p1), genus_(Node::DontCare), goal_(Node::NoType), domain_(0)
{
QStringList params = p2.toLower().split(QLatin1Char(' '));
foreach (const QString& p, params) {
@@ -388,10 +391,15 @@ LinkAtom::LinkAtom(const QString& p1, const QString& p2)
if (goal_ != Node::NoType)
continue;
}
- if (p == "qml")
- genus_ = QML;
- else if (p == "cpp")
- genus_ = CPP;
+ if (p == "qml") {
+ genus_ = Node::QML;
+ continue;
+ }
+ if (p == "cpp") {
+ genus_ = Node::CPP;
+ continue;
+ }
+ break;
}
}
diff --git a/src/tools/qdoc/atom.h b/src/tools/qdoc/atom.h
index 36a7390ae2..65ba2a9b5c 100644
--- a/src/tools/qdoc/atom.h
+++ b/src/tools/qdoc/atom.h
@@ -140,8 +140,6 @@ public:
Last = UnknownCommand
};
- enum NodeGenus { DontCare, CPP, QML };
-
friend class LinkAtom;
Atom(const QString& string)
@@ -201,7 +199,7 @@ public:
const QStringList& strings() const { return strs; }
virtual bool isLinkAtom() const { return false; }
- virtual NodeGenus genus() const { return DontCare; }
+ virtual Node::Genus genus() const { return Node::DontCare; }
virtual bool specifiesDomain() const { return false; }
virtual Tree* domain() const { return 0; }
virtual Node::Type goal() const { return Node::NoType; }
@@ -221,13 +219,13 @@ class LinkAtom : public Atom
virtual ~LinkAtom() { }
virtual bool isLinkAtom() const { return true; }
- virtual NodeGenus genus() const { return genus_; }
+ virtual Node::Genus genus() const { return genus_; }
virtual bool specifiesDomain() const { return (domain_ != 0); }
virtual Tree* domain() const { return domain_; }
virtual Node::Type goal() const { return goal_; }
protected:
- NodeGenus genus_;
+ Node::Genus genus_;
Node::Type goal_;
Tree* domain_;
};
diff --git a/src/tools/qdoc/ditaxmlgenerator.cpp b/src/tools/qdoc/ditaxmlgenerator.cpp
index c2a5cdb8b8..83d89d0187 100644
--- a/src/tools/qdoc/ditaxmlgenerator.cpp
+++ b/src/tools/qdoc/ditaxmlgenerator.cpp
@@ -3444,7 +3444,7 @@ void DitaXmlGenerator::writeText(const QString& markedCode, const Node* relative
text.clear();
}
par1 = QStringRef();
- n = qdb_->resolveFunctionTarget(arg.toString(), relative);
+ n = qdb_->findFunctionNode(arg.toString(), relative, Node::DontCare);
addLink(linkForNode(n, relative), arg);
break;
case 1:
@@ -3455,7 +3455,7 @@ void DitaXmlGenerator::writeText(const QString& markedCode, const Node* relative
text.clear();
}
par1 = QStringRef();
- n = qdb_->resolveType(arg.toString(), relative);
+ n = qdb_->findTypeNode(arg.toString(), relative);
if (n && n->isQmlBasicType()) {
if (relative && relative->isQmlType())
addLink(linkForNode(n, relative), arg);
@@ -3733,65 +3733,50 @@ QString DitaXmlGenerator::fileName(const Node* node)
*/
QString DitaXmlGenerator::getLink(const Atom *atom, const Node *relative, const Node** node)
{
- if (atom->string().contains(QLatin1Char(':')) && (atom->string().startsWith("file:") ||
- atom->string().startsWith("http:") ||
- atom->string().startsWith("https:") ||
- atom->string().startsWith("ftp:") ||
- atom->string().startsWith("mailto:"))) {
- return atom->string(); // It's some kind of protocol.
+ const QString& t = atom->string();
+ if (t.at(0) == QChar('h')) {
+ if (t.startsWith("http:") || t.startsWith("https:"))
+ return t;
+ }
+ else if (t.at(0) == QChar('f')) {
+ if (t.startsWith("file:") || t.startsWith("ftp:"))
+ return t;
+ }
+ else if (t.at(0) == QChar('m')) {
+ if (t.startsWith("mailto:"))
+ return t;
}
QString ref;
- QString link;
- QStringList path = atom->string().split("#");
- QString first = path.first().trimmed();
- *node = 0;
- if (first.isEmpty())
- *node = relative; // search for a target on the current page.
- else {
- if (first.endsWith(".html")) { // The target is an html file.
- *node = qdb_->findNodeByNameAndType(QStringList(first), Node::Document);
- }
- else if (first.endsWith("()")) { // The target is a C++ function or QML method.
- *node = qdb_->resolveFunctionTarget(first, relative);
- }
- else {
- *node = qdb_->resolveTarget(first, relative);
- if (!(*node))
- *node = qdb_->findDocNodeByTitle(first);
- if (!(*node)) {
- *node = qdb_->findUnambiguousTarget(first, ref);
- if (*node && !(*node)->url().isEmpty() && !ref.isEmpty()) {
- QString final = (*node)->url() + "#" + ref;
- return final;
- }
- }
- }
- }
+ *node = qdb_->findNodeForAtom(atom, relative, ref);
if (!(*node))
- return link; // empty
-
- if (!(*node)->url().isEmpty())
- return (*node)->url();
+ return QString();
- if (!path.isEmpty()) {
- ref = qdb_->findTarget(path.first(), *node);
+ QString url = (*node)->url();
+ if (!url.isEmpty()) {
if (ref.isEmpty())
- return link; // empty
+ return url;
+ int hashtag = url.lastIndexOf(QChar('#'));
+ if (hashtag != -1)
+ url.truncate(hashtag);
+ return url + "#" + ref;
}
-
/*
Given that *node is not null, we now cconstruct a link
to the page that *node represents, and then if we found
a target on that page, we connect the target to the link
with '#'.
*/
- link = linkForNode(*node, relative);
+ QString link = linkForNode(*node, relative);
if (*node && (*node)->subType() == Node::Image)
link = "images/used-in-examples/" + link;
- if (!ref.isEmpty())
+ if (!ref.isEmpty()) {
+ int hashtag = link.lastIndexOf(QChar('#'));
+ if (hashtag != -1)
+ link.truncate(hashtag);
link += QLatin1Char('#') + ref;
+ }
return link;
}
@@ -3810,31 +3795,20 @@ QString DitaXmlGenerator::getAutoLink(const Atom *atom, const Node *relative, co
{
QString ref;
QString link;
- QString target = atom->string().trimmed();
- *node = 0;
-
- if (target.endsWith("()")) { // The target is a C++ function or QML method.
- *node = qdb_->resolveFunctionTarget(target, relative);
- }
- else {
- *node = qdb_->resolveTarget(target, relative);
- if (!(*node)) {
- *node = qdb_->findDocNodeByTitle(target);
- }
- if (!(*node)) {
- *node = qdb_->findUnambiguousTarget(target, ref);
- if (*node && !(*node)->url().isEmpty() && !ref.isEmpty()) {
- QString final = (*node)->url() + "#" + ref;
- return final;
- }
- }
- }
+ *node = qdb_->findNodeForAtom(atom, relative, ref);
if (!(*node))
- return link; // empty
+ return QString();
- if (!(*node)->url().isEmpty())
- return (*node)->url();
+ QString url = (*node)->url();
+ if (!url.isEmpty()) {
+ if (ref.isEmpty())
+ return url;
+ int hashtag = url.lastIndexOf(QChar('#'));
+ if (hashtag != -1)
+ url.truncate(hashtag);
+ return url + "#" + ref;
+ }
link = linkForNode(*node, relative);
if (!ref.isEmpty())
@@ -3963,40 +3937,7 @@ void DitaXmlGenerator::generateStatus(const Node* node, CodeMarker* marker)
Generator::generateStatus(node, marker);
break;
case Node::Compat:
- if (node->isInnerNode()) {
- text << Atom::ParaLeft
- << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
- << "This "
- << typeString(node)
- << " is part of the Qt 3 support library."
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
- << " It is provided to keep old source code working. "
- << "We strongly advise against "
- << "using it in new code. See ";
-
- const DocNode *docNode = qdb_->findDocNodeByTitle("Porting To Qt 4");
- QString ref;
- if (docNode && node->type() == Node::Class) {
- QString oldName(node->name());
- oldName.remove(QLatin1Char('3'));
- ref = qdb_->findTarget(oldName,docNode);
- }
-
- if (!ref.isEmpty()) {
- QString fn = fileName(docNode);
- QString guid = lookupGuid(fn, ref);
- text << Atom(Atom::GuidLink, fn + QLatin1Char('#') + guid);
- }
- else
- text << Atom(Atom::Link, "Porting to Qt 4");
-
- text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, "Porting to Qt 4")
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
- << " for more information."
- << Atom::ParaRight;
- }
- generateText(text, node, marker);
+ // Porting to Qt 4 no longer supported
break;
default:
Generator::generateStatus(node, marker);
@@ -4652,7 +4593,7 @@ void DitaXmlGenerator::replaceTypesWithLinks(const Node* n, const InnerNode* par
}
i += 2;
if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
- const Node* tn = qdb_->resolveType(arg.toString(), parent);
+ const Node* tn = qdb_->findTypeNode(arg.toString(), parent);
if (tn) {
//Do not generate a link from a C++ function to a QML Basic Type (such as int)
if (n->isFunction() && tn->isQmlBasicType())
@@ -6159,7 +6100,7 @@ void DitaXmlGenerator::generateCollisionPages()
int count = 0;
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
- if (n->findChildNode(t.key())) {
+ if (n->findChildNode(t.key(), Node::DontCare)) {
++count;
if (count > 1) {
targets.append(t.key());
@@ -6181,7 +6122,7 @@ void DitaXmlGenerator::generateCollisionPages()
writeStartTag(DT_ul);
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
- Node* p = n->findChildNode(*t);
+ Node* p = n->findChildNode(*t, Node::DontCare);
if (p) {
QString link = linkForNode(p,0);
QString label;
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index dd665ea885..44de7e1154 100644
--- a/src/tools/qdoc/htmlgenerator.cpp
+++ b/src/tools/qdoc/htmlgenerator.cpp
@@ -816,7 +816,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
inObsoleteLink = false;
const Node *node = 0;
QString link = getLink(atom, relative, &node);
- if (link.isEmpty() && !noLinkErrors()) {
+ if (link.isEmpty() && (node != relative) && !noLinkErrors()) {
relative->doc().location().warning(tr("Can't link to '%1'").arg(atom->string()));
}
else {
@@ -1493,7 +1493,7 @@ void HtmlGenerator::generateCollisionPages()
int count = 0;
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
- if (n->findChildNode(t.key())) {
+ if (n->findChildNode(t.key(), Node::DontCare)) {
++count;
if (count > 1) {
targets.append(t.key());
@@ -1512,7 +1512,7 @@ void HtmlGenerator::generateCollisionPages()
out() << "<ul>\n";
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
- Node* p = n->findChildNode(*t);
+ Node* p = n->findChildNode(*t, Node::DontCare);
if (p) {
QString link = linkForNode(p,0);
QString label;
@@ -3287,7 +3287,7 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
i += 2;
if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
- const Node* n = qdb_->resolveFunctionTarget(par1.toString(), relative);
+ const Node* n = qdb_->findFunctionNode(par1.toString(), relative, Node::DontCare);
QString link = linkForNode(n, relative);
addLink(link, arg, &html);
par1 = QStringRef();
@@ -3312,7 +3312,7 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
bool handled = false;
if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
par1 = QStringRef();
- const Node* n = qdb_->resolveType(arg.toString(), relative);
+ const Node* n = qdb_->findTypeNode(arg.toString(), relative);
html += QLatin1String("<span class=\"type\">");
if (n && n->isQmlBasicType()) {
if (relative && relative->isQmlType())
@@ -3330,9 +3330,8 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
if (arg.at(0) == QChar('&'))
html += arg;
else {
- // zzz resolveClassTarget()
- const Node* n = qdb_->resolveTarget(arg.toString(), relative);
- if (n)
+ const Node* n = qdb_->findNodeForInclude(QStringList(arg.toString()));
+ if (n && n != relative)
addLink(linkForNode(n,relative), arg, &html);
else
html += arg;
@@ -3659,8 +3658,6 @@ QString HtmlGenerator::refForNode(const Node *node)
return registerRef(ref);
}
-#define DEBUG_ABSTRACT 0
-
/*!
This function is called for links, i.e. for words that
are marked with the qdoc link command. For autolinks
@@ -3691,7 +3688,7 @@ QString HtmlGenerator::getLink(const Atom *atom, const Node *relative, const Nod
QString ref;
- *node = qdb_->findNode(atom, relative, ref);
+ *node = qdb_->findNodeForAtom(atom, relative, ref);
if (!(*node))
return QString();
@@ -3734,31 +3731,20 @@ QString HtmlGenerator::getAutoLink(const Atom *atom, const Node *relative, const
{
QString ref;
QString link;
- QString target = atom->string().trimmed();
- *node = 0;
-
- if (target.endsWith("()")) { // The target is a C++ function or QML method.
- *node = qdb_->resolveFunctionTarget(target, relative);
- }
- else {
- *node = qdb_->resolveTarget(target, relative);
- if (!(*node)) {
- *node = qdb_->findDocNodeByTitle(target);
- }
- if (!(*node)) {
- *node = qdb_->findUnambiguousTarget(target, ref);
- if (*node && !(*node)->url().isEmpty() && !ref.isEmpty()) {
- QString final = (*node)->url() + "#" + ref;
- return final;
- }
- }
- }
+ *node = qdb_->findNodeForAtom(atom, relative, ref);
if (!(*node))
- return link; // empty
+ return QString();
- if (!(*node)->url().isEmpty())
- return (*node)->url();
+ QString url = (*node)->url();
+ if (!url.isEmpty()) {
+ if (ref.isEmpty())
+ return url;
+ int hashtag = url.lastIndexOf(QChar('#'));
+ if (hashtag != -1)
+ url.truncate(hashtag);
+ return url + "#" + ref;
+ }
link = linkForNode(*node, relative);
if (!ref.isEmpty())
@@ -3776,7 +3762,7 @@ QString HtmlGenerator::getAutoLink(const Atom *atom, const Node *relative, const
*/
QString HtmlGenerator::linkForNode(const Node *node, const Node *relative)
{
- if (node == 0 || node == relative)
+ if (node == 0)
return QString();
if (!node->url().isEmpty())
return node->url();
@@ -3977,26 +3963,7 @@ void HtmlGenerator::generateStatus(const Node *node, CodeMarker *marker)
Generator::generateStatus(node, marker);
break;
case Node::Compat:
- if (node->isInnerNode()) {
- text << Atom::ParaLeft
- << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
- << "This "
- << typeString(node)
- << " is part of the Qt 3 support library."
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
- << " It is provided to keep old source code working. "
- << "We strongly advise against "
- << "using it in new code. See ";
-
- text << Atom(Atom::Link, "Porting to Qt 4");
-
- text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, "Porting to Qt 4")
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
- << " for more information."
- << Atom::ParaRight;
- }
- generateText(text, node, marker);
+ // Porting to Qt 4 no longer supported
break;
default:
Generator::generateStatus(node, marker);
diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp
index 87a055ae0f..fa91d67f1c 100644
--- a/src/tools/qdoc/node.cpp
+++ b/src/tools/qdoc/node.cpp
@@ -46,6 +46,7 @@
#include <quuid.h>
#include "qdocdatabase.h"
#include <qdebug.h>
+#include "generator.h"
QT_BEGIN_NAMESPACE
@@ -717,22 +718,38 @@ InnerNode::~InnerNode()
}
/*!
- Find the node in this node's children that has the
- given \a name. If this node is a QML class node, be
- sure to also look in the children of its property
- group nodes. Return the matching node or 0.
+ If \a genus is \c{Node::DontCare}, find the first node in
+ this node's child list that has the given \a name. If this
+ node is a QML type, be sure to also look in the children
+ of its property group nodes. Return the matching node or 0.
+
+ If \a genus is either \c{Node::CPP} or \c {Node::QML}, then
+ find all this node's children that have the given \a name,
+ and return the one that satisfies the \a genus requirement.
*/
-Node *InnerNode::findChildNode(const QString& name) const
+Node *InnerNode::findChildNode(const QString& name, Node::Genus genus) const
{
- Node *node = childMap.value(name);
- if (node && !node->isQmlPropertyGroup())
- return node;
- if (isQmlType()) {
- for (int i=0; i<children_.size(); ++i) {
- Node* n = children_.at(i);
- if (n->isQmlPropertyGroup()) {
- node = static_cast<InnerNode*>(n)->findChildNode(name);
- if (node)
+ if (genus == Node::DontCare) {
+ Node *node = childMap.value(name);
+ if (node && !node->isQmlPropertyGroup()) // mws asks: Why not property group?
+ return node;
+ if (isQmlType()) {
+ for (int i=0; i<children_.size(); ++i) {
+ Node* n = children_.at(i);
+ if (n->isQmlPropertyGroup()) {
+ node = static_cast<InnerNode*>(n)->findChildNode(name, genus);
+ if (node)
+ return node;
+ }
+ }
+ }
+ }
+ else {
+ NodeList nodes = childMap.values(name);
+ if (!nodes.isEmpty()) {
+ for (int i=0; i<nodes.size(); ++i) {
+ Node* node = nodes.at(i);
+ if (genus == node->genus() || genus == Node::DontCare)
return node;
}
}
@@ -741,6 +758,39 @@ Node *InnerNode::findChildNode(const QString& name) const
}
/*!
+ Find all the child nodes of this node that are named
+ \a name and return them in \a nodes.
+ */
+void InnerNode::findChildren(const QString& name, NodeList& nodes) const
+{
+ nodes = childMap.values(name);
+ Node* n = primaryFunctionMap.value(name);
+ if (n) {
+ nodes.append(n);
+ NodeList t = secondaryFunctionMap.value(name);
+ if (!t.isEmpty())
+ nodes.append(t);
+ }
+ if (!nodes.isEmpty() || !isQmlNode())
+ return;
+ int i = name.indexOf(QChar('.'));
+ if (i < 0)
+ return;
+ QString qmlPropGroup = name.left(i);
+ NodeList t = childMap.values(qmlPropGroup);
+ if (t.isEmpty())
+ return;
+ foreach (Node* n, t) {
+ if (n->isQmlPropertyGroup()) {
+ n->findChildren(name, nodes);
+ if (!nodes.isEmpty())
+ break;
+ }
+ }
+}
+
+#if 0
+/*!
Find the node in this node's children that has the given \a name. If
this node is a QML class node, be sure to also look in the children
of its property group nodes. Return the matching node or 0. This is
@@ -752,7 +802,7 @@ Node *InnerNode::findChildNode(const QString& name) const
*/
Node* InnerNode::findChildNode(const QString& name, bool qml) const
{
- QList<Node*> nodes = childMap.values(name);
+ NodeList nodes = childMap.values(name);
if (!nodes.isEmpty()) {
for (int i=0; i<nodes.size(); ++i) {
Node* node = nodes.at(i);
@@ -776,6 +826,7 @@ Node* InnerNode::findChildNode(const QString& name, bool qml) const
}
return primaryFunctionMap.value(name);
}
+#endif
/*!
This function is like findChildNode(), but if a node
@@ -793,7 +844,7 @@ Node* InnerNode::findChildNode(const QString& name, Type type)
if (type == Function)
return primaryFunctionMap.value(name);
else {
- QList<Node*> nodes = childMap.values(name);
+ NodeList nodes = childMap.values(name);
for (int i=0; i<nodes.size(); ++i) {
Node* node = nodes.at(i);
if (node->type() == type)
@@ -803,13 +854,14 @@ Node* InnerNode::findChildNode(const QString& name, Type type)
return 0;
}
+#if 0
/*!
*/
-void InnerNode::findNodes(const QString& name, QList<Node*>& n)
+void InnerNode::findNodes(const QString& name, NodeList& n)
{
n.clear();
Node* node = 0;
- QList<Node*> nodes = childMap.values(name);
+ NodeList nodes = childMap.values(name);
/*
<sigh> If this node's child map contains no nodes named
name, then if this node is a QML class, search each of its
@@ -857,6 +909,7 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n)
if (node)
n.append(node);
}
+#endif
/*!
Find a function node that is a child of this nose, such
diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h
index 37fbe482b0..67ad006e2c 100644
--- a/src/tools/qdoc/node.h
+++ b/src/tools/qdoc/node.h
@@ -117,6 +117,8 @@ public:
LastSubtype
};
+ enum Genus { DontCare, CPP, QML };
+
enum Access { Public, Protected, Private };
enum Status {
@@ -217,6 +219,7 @@ public:
virtual bool isNamespace() const { return false; }
virtual bool isClass() const { return false; }
virtual bool isQmlNode() const { return false; }
+ virtual bool isCppNode() const { return false; }
virtual bool isQtQuickNode() const { return false; }
virtual bool isAbstract() const { return false; }
virtual bool isQmlPropertyGroup() const { return false; }
@@ -233,6 +236,7 @@ public:
virtual bool hasClasses() const { return false; }
virtual void setAbstract(bool ) { }
virtual void setWrapper() { }
+ virtual Node::Genus genus() const { return DontCare; }
virtual QString title() const { return name(); }
virtual QString fullTitle() const { return name(); }
virtual QString subTitle() const { return QString(); }
@@ -250,6 +254,7 @@ public:
virtual void appendGroupName(const QString& ) { }
virtual QString element() const { return QString(); }
virtual Tree* tree() const;
+ virtual void findChildren(const QString& , NodeList& nodes) const { nodes.clear(); }
bool isIndexNode() const { return indexNodeFlag_; }
Type type() const { return nodeType_; }
virtual SubType subType() const { return NoSubType; }
@@ -271,6 +276,7 @@ public:
void setLink(LinkType linkType, const QString &link, const QString &desc);
Access access() const { return access_; }
+ bool isPrivate() const { return access_ == Private; }
QString accessString() const;
const Location& location() const { return loc_; }
const Doc& doc() const { return doc_; }
@@ -360,10 +366,11 @@ class InnerNode : public Node
public:
virtual ~InnerNode();
- Node* findChildNode(const QString& name) const;
- Node* findChildNode(const QString& name, bool qml) const;
+ Node* findChildNode(const QString& name, Node::Genus genus) const;
+ //Node* findChildNode(const QString& name, bool qml) const;
Node* findChildNode(const QString& name, Type type);
- void findNodes(const QString& name, QList<Node*>& n);
+ //void findNodes(const QString& name, NodeList& n);
+ virtual void findChildren(const QString& name, NodeList& nodes) const;
FunctionNode* findFunctionNode(const QString& name) const;
FunctionNode* findFunctionNode(const FunctionNode* clone);
void addInclude(const QString &include);
@@ -443,6 +450,8 @@ public:
virtual ~NamespaceNode() { }
virtual bool isNamespace() const { return true; }
virtual Tree* tree() const { return (parent() ? parent()->tree() : tree_); }
+ virtual bool isCppNode() const { return true; }
+ virtual Node::Genus genus() const { return Node::CPP; }
void setTree(Tree* t) { tree_ = t; }
private:
@@ -473,7 +482,9 @@ public:
ClassNode(InnerNode* parent, const QString& name);
virtual ~ClassNode() { }
virtual bool isClass() const { return true; }
+ virtual bool isCppNode() const { return true; }
virtual bool isWrapper() const { return wrapper_; }
+ virtual Node::Genus genus() const { return Node::CPP; }
virtual QString obsoleteLink() const { return obsoleteLink_; }
virtual void setObsoleteLink(const QString& t) { obsoleteLink_ = t; }
virtual void setWrapper() { wrapper_ = true; }
@@ -618,6 +629,7 @@ public:
virtual QString qmlModuleIdentifier() const;
virtual QmlModuleNode* qmlModule() const { return qmlModule_; }
virtual void setQmlModule(QmlModuleNode* t) { qmlModule_ = t; }
+ virtual Node::Genus genus() const { return Node::QML; }
const ImportList& importList() const { return importList_; }
void setImportList(const ImportList& il) { importList_ = il; }
const QString& qmlBaseName() const { return qmlBaseName_; }
@@ -655,6 +667,7 @@ public:
virtual ~QmlBasicTypeNode() { }
virtual bool isQmlNode() const { return true; }
virtual bool isQmlBasicType() const { return true; }
+ virtual Node::Genus genus() const { return Node::QML; }
};
class QmlPropertyGroupNode : public InnerNode
@@ -670,6 +683,7 @@ public:
virtual QString qmlModuleIdentifier() const { return parent()->qmlModuleIdentifier(); }
virtual QString idNumber();
virtual bool isQmlPropertyGroup() const { return true; }
+ virtual Node::Genus genus() const { return Node::QML; }
virtual QString element() const { return parent()->name(); }
@@ -688,6 +702,7 @@ public:
bool attached);
virtual ~QmlPropertyNode() { }
+ virtual Node::Genus genus() const { return Node::QML; }
virtual void setDataType(const QString& dataType) { type_ = dataType; }
void setStored(bool stored) { stored_ = toFlagValue(stored); }
void setDesignable(bool designable) { designable_ = toFlagValue(designable); }
@@ -746,6 +761,8 @@ public:
EnumNode(InnerNode* parent, const QString& name);
virtual ~EnumNode() { }
+ virtual Node::Genus genus() const { return Node::CPP; }
+ virtual bool isCppNode() const { return true; }
void addItem(const EnumItem& item);
void setFlagsType(TypedefNode* typedeff);
bool hasItem(const QString &name) const { return names.contains(name); }
@@ -767,6 +784,8 @@ public:
TypedefNode(InnerNode* parent, const QString& name);
virtual ~TypedefNode() { }
+ virtual Node::Genus genus() const { return Node::CPP; }
+ virtual bool isCppNode() const { return true; }
const EnumNode* associatedEnum() const { return ae; }
private:
@@ -873,6 +892,8 @@ public:
(type() == QmlMethod) ||
(type() == QmlSignalHandler));
}
+ virtual bool isCppNode() const { return !isQmlNode(); }
+ virtual Node::Genus genus() const { return (isQmlNode() ? Node::QML : Node::CPP); }
virtual bool isQtQuickNode() const { return parent()->isQtQuickNode(); }
virtual QString qmlTypeName() const { return parent()->qmlTypeName(); }
virtual QString qmlModuleName() const { return parent()->qmlModuleName(); }
@@ -911,6 +932,8 @@ public:
PropertyNode(InnerNode* parent, const QString& name);
virtual ~PropertyNode() { }
+ virtual Node::Genus genus() const { return Node::CPP; }
+ virtual bool isCppNode() const { return true; }
virtual void setDataType(const QString& dataType) { type_ = dataType; }
void addFunction(FunctionNode* function, FunctionRole role);
void addSignal(FunctionNode* function, FunctionRole role);
@@ -998,6 +1021,8 @@ public:
VariableNode(InnerNode* parent, const QString &name);
virtual ~VariableNode() { }
+ virtual Node::Genus genus() const { return Node::CPP; }
+ virtual bool isCppNode() const { return true; }
void setLeftType(const QString &leftType) { lt = leftType; }
void setRightType(const QString &rightType) { rt = rightType; }
void setStatic(bool statique) { sta = statique; }
@@ -1084,6 +1109,7 @@ class ModuleNode : public CollectionNode
virtual ~ModuleNode() { }
virtual bool isModule() const { return true; }
+ virtual bool isCppNode() const { return true; }
virtual void setQtVariable(const QString& v) { qtVariable_ = v; }
virtual QString qtVariable() const { return qtVariable_; }
@@ -1098,6 +1124,7 @@ class QmlModuleNode : public CollectionNode
: CollectionNode(Node::QmlModule, parent, name) { }
virtual ~QmlModuleNode() { }
+ virtual bool isQmlNode() const { return true; }
virtual bool isQmlModule() const { return true; }
virtual QString qmlModuleName() const { return qmlModuleName_; }
virtual QString qmlModuleVersion() const {
diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp
index d43fdf4970..e9e62fb7f3 100644
--- a/src/tools/qdoc/qdocdatabase.cpp
+++ b/src/tools/qdoc/qdocdatabase.cpp
@@ -379,20 +379,34 @@ void QDocForest::newPrimaryTree(const QString& module)
}
/*!
- Searches the trees for a node named \a target and returns
- a pointer to it if found. The \a relative node is the starting
- point, but it only makes sense in the primary tree, which is
- searched first. After the primary tree is searched, \a relative
- is set to 0 for searching the index trees. When relative is 0,
- the root nodes of the index trees are the starting points.
- */
-const Node* QDocForest::resolveTarget(const QString& target, const Node* relative)
+ Searches through the forest for a node named \a targetPath
+ and returns a pointer to it if found. The \a relative node
+ is the starting point. It only makes sense for the primary
+ tree, which is searched first. After the primary tree has
+ been searched, \a relative is set to 0 for searching the
+ other trees, which are all index trees. With relative set
+ to 0, the starting point for each index tree is the root
+ of the index tree.
+ */
+const Node* QDocForest::findNodeForTarget(QStringList& targetPath,
+ const Node* relative,
+ Node::Genus genus,
+ QString& ref)
{
- QStringList path = target.split("::");
- int flags = SearchBaseClasses | SearchEnumValues | NonFunction;
+ int flags = SearchBaseClasses | SearchEnumValues;
+
+ QString entity = targetPath.at(0);
+ targetPath.removeFirst();
+ QStringList entityPath = entity.split("::");
+
+ QString target;
+ if (!targetPath.isEmpty()) {
+ target = targetPath.at(0);
+ targetPath.removeFirst();
+ }
foreach (Tree* t, searchOrder()) {
- const Node* n = t->findNode(path, relative, flags);
+ const Node* n = t->findNodeForTarget(entityPath, target, relative, flags, genus, ref);
if (n)
return n;
relative = 0;
@@ -401,20 +415,6 @@ const Node* QDocForest::resolveTarget(const QString& target, const Node* relativ
}
/*!
- Searches the Tree \a t for a type node named by the \a path
- and returns a pointer to it if found. The \a relative node
- is the starting point, but it only makes sense when searching
- the primary tree. Therefore, when this function is called with
- \a t being an index tree, \a relative is 0. When relative is 0,
- the root node of \a t is the starting point.
- */
-const Node* QDocForest::resolveTypeHelper(const QStringList& path, const Node* relative, Tree* t)
-{
- int flags = SearchBaseClasses | SearchEnumValues | NonFunction;
- return t->findNode(path, relative, flags);
-}
-
-/*!
This function merges all the collection maps for collection
nodes of node type \a t into the collection multimap \a cnmm,
which is cleared before starting.
@@ -1343,7 +1343,7 @@ void QDocDatabase::resolveIssues() {
When searching the index trees, the search begins at the
root.
*/
-const Node* QDocDatabase::resolveType(const QString& type, const Node* relative)
+const Node* QDocDatabase::findTypeNode(const QString& type, const Node* relative)
{
QStringList path = type.split("::");
if ((path.size() == 1) && (path.at(0)[0].isLower() || path.at(0) == QString("T"))) {
@@ -1351,7 +1351,7 @@ const Node* QDocDatabase::resolveType(const QString& type, const Node* relative)
if (i != typeNodeMap_.end())
return i.value();
}
- return forest_.resolveType(path, relative);
+ return forest_.findTypeNode(path, relative);
}
/*!
@@ -1369,9 +1369,15 @@ const Node* QDocDatabase::findNodeForTarget(const QString& target, const Node* r
node = findNodeByNameAndType(QStringList(target), Node::Document);
}
else {
- node = resolveTarget(target, relative);
- if (!node)
- node = findDocNodeByTitle(target);
+ QStringList path = target.split("::");
+ int flags = SearchBaseClasses | SearchEnumValues; // | NonFunction;
+ foreach (Tree* t, searchOrder()) {
+ const Node* n = t->findNode(path, relative, flags, Node::DontCare);
+ if (n)
+ return n;
+ relative = 0;
+ }
+ node = findDocNodeByTitle(target);
}
return node;
}
@@ -1578,27 +1584,6 @@ void QDocDatabase::mergeCollections(CollectionNode* cn)
}
}
-
-/*!
- This function is called when the \a{atom} might be a link
- atom. It handles the optional, square bracket parameters
- for the link command.
- */
-Node* QDocDatabase::findNode(const Atom* atom)
-{
- QStringList path(atom->string());
- if (atom->specifiesDomain()) {
- return atom->domain()->findNodeByNameAndType(path, atom->goal());
- }
- qDebug() << "FINDNODE:" << path << atom->goal();
- return forest_.findNodeByNameAndType(path, atom->goal());
-}
-
-const DocNode* QDocDatabase::findDocNodeByTitle(const Atom* atom)
-{
- return forest_.findDocNodeByTitle(atom->string());
-}
-
/*!
Searches for the node that matches the path in \a atom. The
\a relative node is used if the first leg of the path is
@@ -1608,51 +1593,62 @@ const DocNode* QDocDatabase::findDocNodeByTitle(const Atom* atom)
\a ref. If the returned node pointer is null, \a ref is not
valid.
*/
-const Node* QDocDatabase::findNode(const Atom* atom, const Node* relative, QString& ref)
+const Node* QDocDatabase::findNodeForAtom(const Atom* atom, const Node* relative, QString& ref)
{
const Node* node = 0;
- QStringList path = atom->string().split("#");
- QString first = path.first().trimmed();
- path.removeFirst();
+
+ QStringList targetPath = atom->string().split("#");
+ QString first = targetPath.first().trimmed();
+
+ Tree* domain = 0;
+ Node::Genus genus = Node::DontCare;
+ // Reserved for future use
+ //Node::Type goal = Node::NoType;
+
+ if (atom->isLinkAtom()) {
+ domain = atom->domain();
+ genus = atom->genus();
+ // Reserved for future use
+ //goal = atom->goal();
+ }
if (first.isEmpty())
node = relative; // search for a target on the current page.
- else if (atom->specifiesDomain()) {
- qDebug() << "Processing LinkAtom";
- if (first.endsWith(".html")) { // The target is an html file.
- node = atom->domain()->findNodeByNameAndType(QStringList(first), Node::Document);
- }
- else if (first.endsWith("()")) { // The target is a C++ function or QML method.
- node = atom->domain()->resolveFunctionTarget(first, 0); //relative);
- }
+ else if (domain) {
+ if (first.endsWith(".html"))
+ node = domain->findNodeByNameAndType(QStringList(first), Node::Document);
+ else if (first.endsWith("()"))
+ node = domain->findFunctionNode(first, 0, genus);
else {
- node = atom->domain()->resolveTarget(first, 0); // relative);
- if (!node)
- node = atom->domain()->findUnambiguousTarget(first, ref); // ref
- if (!node && path.isEmpty())
- node = atom->domain()->findDocNodeByTitle(first);
+ int flags = SearchBaseClasses | SearchEnumValues;
+ QStringList nodePath = first.split("::");
+ QString target;
+ targetPath.removeFirst();
+ if (!targetPath.isEmpty()) {
+ target = targetPath.at(0);
+ targetPath.removeFirst();
+ }
+ node = domain->findNodeForTarget(nodePath, target, relative, flags, genus, ref);
+ return node;
}
}
else {
- if (first.endsWith(".html")) { // The target is an html file.
- node = findNodeByNameAndType(QStringList(first), Node::Document); // ref
- }
- else if (first.endsWith("()")) { // The target is a C++ function or QML method.
- node = resolveFunctionTarget(first, relative);
- }
+ if (first.endsWith(".html"))
+ node = findNodeByNameAndType(QStringList(first), Node::Document);
+ else if (first.endsWith("()"))
+ node = findFunctionNode(first, relative, genus);
else {
- node = resolveTarget(first, relative); // ref
- if (!node)
- node = findUnambiguousTarget(first, ref); // ref
- if (!node && path.isEmpty())
- node = findDocNodeByTitle(first);
+ node = findNodeForTarget(targetPath, relative, genus, ref);
+ return node;
}
}
+
if (node && ref.isEmpty()) {
if (!node->url().isEmpty())
return node;
- if (!path.isEmpty()) {
- ref = findTarget(path.first(), node);
+ targetPath.removeFirst();
+ if (!targetPath.isEmpty()) {
+ ref = node->root()->tree()->getRef(targetPath.first(), node);
if (ref.isEmpty())
node = 0;
}
diff --git a/src/tools/qdoc/qdocdatabase.h b/src/tools/qdoc/qdocdatabase.h
index 99d1c46ca2..12105842b8 100644
--- a/src/tools/qdoc/qdocdatabase.h
+++ b/src/tools/qdoc/qdocdatabase.h
@@ -88,9 +88,12 @@ class QDocForest
const QVector<Tree*>& indexSearchOrder();
void setSearchOrder();
- const Node* findNode(const QStringList& path, const Node* relative, int findFlags) {
+ const Node* findNode(const QStringList& path,
+ const Node* relative,
+ int findFlags,
+ Node::Genus genus) {
foreach (Tree* t, searchOrder()) {
- const Node* n = t->findNode(path, relative, findFlags);
+ const Node* n = t->findNode(path, relative, findFlags, genus);
if (n)
return n;
relative = 0;
@@ -116,43 +119,48 @@ class QDocForest
return 0;
}
- InnerNode* findRelatesNode(const QStringList& path) {
+ Node* findNodeForInclude(const QStringList& path) {
foreach (Tree* t, searchOrder()) {
- InnerNode* n = t->findRelatesNode(path);
+ Node* n = t->findNodeForInclude(path);
if (n)
return n;
}
return 0;
}
- const Node* resolveFunctionTarget(const QString& target, const Node* relative) {
+ InnerNode* findRelatesNode(const QStringList& path) {
foreach (Tree* t, searchOrder()) {
- const Node* n = t->resolveFunctionTarget(target, relative);
+ InnerNode* n = t->findRelatesNode(path);
if (n)
return n;
- relative = 0;
}
return 0;
}
- const Node* resolveTarget(const QString& target, const Node* relative);
- const Node* resolveType(const QStringList& path, const Node* relative)
- {
+ const Node* findFunctionNode(const QString& target,
+ const Node* relative,
+ Node::Genus genus) {
foreach (Tree* t, searchOrder()) {
- const Node* n = resolveTypeHelper(path, relative, t);
+ const Node* n = t->findFunctionNode(target, relative, genus);
if (n)
return n;
relative = 0;
}
return 0;
}
+ const Node* findNodeForTarget(QStringList& targetPath,
+ const Node* relative,
+ Node::Genus genus,
+ QString& ref);
- const Node* findUnambiguousTarget(const QString& target, QString& ref)
+ const Node* findTypeNode(const QStringList& path, const Node* relative)
{
foreach (Tree* t, searchOrder()) {
- const Node* n = t->findUnambiguousTarget(target, ref);
+ int flags = SearchBaseClasses | SearchEnumValues | NonFunction;
+ const Node* n = t->findNode(path, relative, flags, Node::DontCare);
if (n)
return n;
+ relative = 0;
}
return 0;
}
@@ -189,7 +197,6 @@ class QDocForest
private:
void newPrimaryTree(const QString& module);
NamespaceNode* newIndexTree(const QString& module);
- const Node* resolveTypeHelper(const QStringList& path, const Node* relative, Tree* t);
private:
QDocDatabase* qdb_;
@@ -281,8 +288,12 @@ class QDocDatabase
void resolveTargets() {
primaryTree()->resolveTargets(primaryTreeRoot());
}
- void insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority) {
- primaryTree()->insertTarget(name, type, node, priority);
+ void insertTarget(const QString& name,
+ const QString& title,
+ TargetRec::Type type,
+ Node* node,
+ int priority) {
+ primaryTree()->insertTarget(name, title, type, node, priority);
}
/*******************************************************************
@@ -304,38 +315,37 @@ class QDocDatabase
/*******************************************************************
The functions declared below handle the parameters in '[' ']'.
********************************************************************/
- Node* findNode(const Atom* atom);
- const Node* findNode(const Atom* atom, const Node* relative, QString& ref);
- const DocNode* findDocNodeByTitle(const Atom* atom);
+ const Node* findNodeForAtom(const Atom* atom, const Node* relative, QString& ref);
/*******************************************************************/
/*******************************************************************
The functions declared below are called for all trees.
********************************************************************/
ClassNode* findClassNode(const QStringList& path) { return forest_.findClassNode(path); }
+ Node* findNodeForInclude(const QStringList& path) { return forest_.findNodeForInclude(path); }
InnerNode* findRelatesNode(const QStringList& path) { return forest_.findRelatesNode(path); }
- const Node* resolveTarget(const QString& target, const Node* relative) {
- return forest_.resolveTarget(target, relative);
+ const Node* findFunctionNode(const QString& target, const Node* relative, Node::Genus genus) {
+ return forest_.findFunctionNode(target, relative, genus);
}
- const Node* resolveFunctionTarget(const QString& target, const Node* relative) {
- return forest_.resolveFunctionTarget(target, relative);
- }
- const Node* resolveType(const QString& type, const Node* relative);
+ const Node* findTypeNode(const QString& type, const Node* relative);
const Node* findNodeForTarget(const QString& target, const Node* relative);
const DocNode* findDocNodeByTitle(const QString& title) {
return forest_.findDocNodeByTitle(title);
}
- const Node* findUnambiguousTarget(const QString& target, QString& ref) {
- return forest_.findUnambiguousTarget(target, ref);
- }
Node* findNodeByNameAndType(const QStringList& path, Node::Type type) {
return forest_.findNodeByNameAndType(path, type);
}
- /*******************************************************************/
- QString findTarget(const QString& target, const Node* node) {
- return node->root()->tree()->findTarget(target, node);
+ private:
+ const Node* findNodeForTarget(QStringList& targetPath,
+ const Node* relative,
+ Node::Genus genus,
+ QString& ref) {
+ return forest_.findNodeForTarget(targetPath, relative, genus, ref);
}
+
+ /*******************************************************************/
+ public:
void addPropertyFunction(PropertyNode* property,
const QString& funcName,
PropertyNode::FunctionRole funcRole) {
@@ -371,8 +381,11 @@ class QDocDatabase
friend class QDocIndexFiles;
friend class QDocTagFiles;
- const Node* findNode(const QStringList& path, const Node* relative, int findFlags) {
- return forest_.findNode(path, relative, findFlags);
+ const Node* findNode(const QStringList& path,
+ const Node* relative,
+ int findFlags,
+ Node::Genus genus) {
+ return forest_.findNode(path, relative, findFlags, genus);
}
void processForest(void (QDocDatabase::*) (InnerNode*));
static void initializeDB();
diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp
index 4531ce8eea..ba09bfea3b 100644
--- a/src/tools/qdoc/qdocindexfiles.cpp
+++ b/src/tools/qdoc/qdocindexfiles.cpp
@@ -471,15 +471,18 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
location = Location(parent->name().toLower() + ".html");
}
else if (element.nodeName() == "keyword") {
- qdb_->insertTarget(name, TargetRec::Keyword, current, 1);
+ QString title = element.attribute("title");
+ qdb_->insertTarget(name, title, TargetRec::Keyword, current, 1);
return;
}
else if (element.nodeName() == "target") {
- qdb_->insertTarget(name, TargetRec::Target, current, 2);
+ QString title = element.attribute("title");
+ qdb_->insertTarget(name, title, TargetRec::Target, current, 2);
return;
}
else if (element.nodeName() == "contents") {
- qdb_->insertTarget(name, TargetRec::Contents, current, 3);
+ QString title = element.attribute("title");
+ qdb_->insertTarget(name, title, TargetRec::Contents, current, 3);
return;
}
else
@@ -1202,18 +1205,26 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
external = true;
}
foreach (const Atom* target, node->doc().targets()) {
- QString targetName = target->string();
- if (!external)
- targetName = Doc::canonicalTitle(targetName);
+ QString title = target->string();
+ QString name = Doc::canonicalTitle(title);
writer.writeStartElement("target");
- writer.writeAttribute("name", targetName);
+ 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", Doc::canonicalTitle(keyword->string()));
+ writer.writeAttribute("name", name);
+ if (name != title)
+ writer.writeAttribute("title", title);
writer.writeEndElement(); // keyword
}
}
diff --git a/src/tools/qdoc/qmlvisitor.cpp b/src/tools/qdoc/qmlvisitor.cpp
index fbe4940c19..026f3bd0a2 100644
--- a/src/tools/qdoc/qmlvisitor.cpp
+++ b/src/tools/qdoc/qmlvisitor.cpp
@@ -249,7 +249,7 @@ bool QmlDocVisitor::applyDocumentation(QQmlJS::AST::SourceLocation location, Nod
nodes.append(node);
if (topicsUsed.size() > 0) {
for (int i=0; i<topicsUsed.size(); ++i) {
- if (topicsUsed.at(i).topic == QString("qmlpropertygroup")) {
+ if (topicsUsed.at(i).topic == COMMAND_QMLPROPERTYGROUP) {
qDebug() << "PROPERTY GROUP COMMAND SEEN:" << topicsUsed.at(i).args << filePath_;
break;
}
diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp
index e689227bf1..d43f82949a 100644
--- a/src/tools/qdoc/tree.cpp
+++ b/src/tools/qdoc/tree.cpp
@@ -86,21 +86,48 @@ Tree::Tree(const QString& module, QDocDatabase* qdb)
destructor of each child node is called, and these
destructors are recursive. Thus the entire tree is
destroyed.
+
+ There are two maps of targets, keywords, and contents.
+ One map is indexed by ref, the other by title. The ref
+ is just the canonical form of the title. Both maps
+ use the same set of TargetRec objects as the values,
+ so the destructor only deletes the values from one of
+ the maps. Then it clears both maps.
*/
Tree::~Tree()
{
- // nothing
+ TargetMap::iterator i = nodesByTargetRef_.begin();
+ while (i != nodesByTargetRef_.end()) {
+ delete i.value();
+ ++i;
+ }
+ nodesByTargetRef_.clear();
+ nodesByTargetTitle_.clear();
}
/* API members */
/*!
+ Calls findClassNode() first with \a path and \a start. If
+ it finds a node, the node is returned. If not, it calls
+ findNamespaceNode() with the same parameters. The result
+ is returned.
+ */
+Node* Tree::findNodeForInclude(const QStringList& path) const
+{
+ Node* n = findClassNode(path);
+ if (!n)
+ n = findNamespaceNode(path);
+ return n;
+}
+
+/*!
Find the C++ class node named \a path. Begin the search at the
\a start node. If the \a start node is 0, begin the search
at the root of the tree. Only a C++ class node named \a path is
acceptible. If one is not found, 0 is returned.
*/
-ClassNode* Tree::findClassNode(const QStringList& path, Node* start) const
+ClassNode* Tree::findClassNode(const QStringList& path, const Node* start) const
{
if (!start)
start = const_cast<NamespaceNode*>(root());
@@ -125,8 +152,9 @@ NamespaceNode* Tree::findNamespaceNode(const QStringList& path) const
matches the \a clone node. If it finds a node that is just
like the \a clone, it returns a pointer to the found node.
- There should be a way to avoid creating the clone in the
- first place. Investigate when time allows.
+ Apparently the search order is important here. Don't change
+ it unless you know what you are doing, or you will introduce
+ qdoc warnings.
*/
FunctionNode* Tree::findFunctionNode(const QStringList& parentPath, const FunctionNode* clone)
{
@@ -134,7 +162,7 @@ FunctionNode* Tree::findFunctionNode(const QStringList& parentPath, const Functi
if (parent == 0)
parent = findClassNode(parentPath, 0);
if (parent == 0)
- parent = findNode(parentPath);
+ parent = findNode(parentPath, 0, 0, Node::DontCare);
if (parent == 0 || !parent->isInnerNode())
return 0;
return ((InnerNode*)parent)->findFunctionNode(clone);
@@ -176,7 +204,7 @@ QmlClassNode* Tree::findQmlTypeNode(const QStringList& path)
*/
NameCollisionNode* Tree::checkForCollision(const QString& name)
{
- Node* n = const_cast<Node*>(findNode(QStringList(name)));
+ Node* n = const_cast<Node*>(findNode(QStringList(name), 0, 0, Node::DontCare));
if (n) {
if (n->subType() == Node::Collision) {
NameCollisionNode* ncn = static_cast<NameCollisionNode*>(n);
@@ -196,7 +224,7 @@ NameCollisionNode* Tree::checkForCollision(const QString& name)
*/
NameCollisionNode* Tree::findCollisionNode(const QString& name) const
{
- Node* n = const_cast<Node*>(findNode(QStringList(name)));
+ Node* n = const_cast<Node*>(findNode(QStringList(name), 0, 0, Node::DontCare));
if (n) {
if (n->subType() == Node::Collision) {
NameCollisionNode* ncn = static_cast<NameCollisionNode*>(n);
@@ -216,12 +244,10 @@ NameCollisionNode* Tree::findCollisionNode(const QString& name) const
*/
const FunctionNode* Tree::findFunctionNode(const QStringList& path,
const Node* relative,
- int findFlags) const
+ int findFlags,
+ Node::Genus genus) const
{
- if (!relative)
- relative = root();
-
- if (path.size() == 3 && !path[0].isEmpty()) {
+ if (path.size() == 3 && !path[0].isEmpty() && (genus != Node::CPP)) {
QmlClassNode* qcn = lookupQmlType(QString(path[0] + "::" + path[1]));
if (!qcn) {
QStringList p(path[1]);
@@ -240,6 +266,13 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
return static_cast<const FunctionNode*>(qcn->findFunctionNode(path[2]));
}
+ if (!relative)
+ relative = root();
+ else if (genus != Node::DontCare) {
+ if (genus != relative->genus())
+ relative = root();
+ }
+
do {
const Node* node = relative;
int i;
@@ -252,7 +285,7 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
if (i == path.size() - 1)
next = ((InnerNode*) node)->findFunctionNode(path.at(i));
else
- next = ((InnerNode*) node)->findChildNode(path.at(i));
+ next = ((InnerNode*) node)->findChildNode(path.at(i), genus);
if (!next && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
@@ -260,7 +293,7 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
if (i == path.size() - 1)
next = static_cast<const InnerNode*>(baseClass)->findFunctionNode(path.at(i));
else
- next = static_cast<const InnerNode*>(baseClass)->findChildNode(path.at(i));
+ next = static_cast<const InnerNode*>(baseClass)->findChildNode(path.at(i), genus);
if (next)
break;
@@ -670,44 +703,197 @@ Node* Tree::findNodeRecursive(const QStringList& path,
}
/*!
- Searches the tree for a node that matches the \a path. The
- search begins at \a start but can move up the parent chain
- recursively if no match is found.
+ Searches the tree for a node that matches the \a path plus
+ the \a target. The search begins at \a start and moves up
+ the parent chain from there, or, if \a start is 0, the search
+ begins at the root.
- This findNode() callse the other findNode(), which is not
- called anywhere else.
+ The \a flags can indicate whether to search base classes and/or
+ the enum values in enum types. \a genus can be a further restriction
+ on what kind of node is an acceptible match, i.e. CPP or QML.
+
+ If a matching node is found, \a ref is an output parameter that
+ is set to the HTML reference to use for the link.
*/
-const Node* Tree::findNode(const QStringList& path, const Node* start, int findFlags) const
+const Node* Tree::findNodeForTarget(const QStringList& path,
+ const QString& target,
+ const Node* start,
+ int flags,
+ Node::Genus genus,
+ QString& ref) const
{
+ const Node* node = 0;
+ QString p;
+ if (path.size() > 1)
+ p = path.join(QString("::"));
+ else {
+ p = path.at(0);
+ node = findDocNodeByTitle(p);
+ if (node) {
+ if (!target.isEmpty()) {
+ ref = getRef(target, node);
+ if (ref.isEmpty())
+ node = 0;
+ }
+ if (node)
+ return node;
+ }
+ }
+ node = findUnambiguousTarget(p, ref);
+ if (node) {
+ if (!target.isEmpty()) {
+ ref = getRef(target, node);
+ if (ref.isEmpty())
+ node = 0;
+ }
+ if (node)
+ return node;
+ }
+
const Node* current = start;
if (!current)
current = root();
/*
- First, search for a node assuming we don't want a QML node.
- If that search fails, search again assuming we do want a
- QML node.
+ If the path contains one or two double colons ("::"),
+ check first to see if the first two path strings refer
+ to a QML element. If they do, path[0] will be the QML
+ module identifier, and path[1] will be the QML type.
+ If the answer is yes, the reference identifies a QML
+ type node.
+ */
+ int path_idx = 0;
+ if ((genus != Node::CPP) && (path.size() >= 2) && !path[0].isEmpty()) {
+ QmlClassNode* qcn = lookupQmlType(QString(path[0] + "::" + path[1]));
+ if (qcn) {
+ current = qcn;
+ if (path.size() == 2) {
+ if (!target.isEmpty()) {
+ ref = getRef(target, current);
+ if (!ref.isEmpty())
+ return current;
+ else if (genus == Node::QML)
+ return 0;
+ }
+ else
+ return current;
+ }
+ path_idx = 2;
+ }
+ }
+
+ while (current) {
+ if (current->isInnerNode()) {
+ const Node* node = matchPathAndTarget(path, path_idx, target, current, flags, genus, ref);
+ if (node)
+ return node;
+ }
+ current = current->parent();
+ path_idx = 0;
+ }
+ return 0;
+}
+
+/*!
+ First, the \a path is used to find a node. The \a path
+ matches some part of the node's fully quallified name.
+ If the \a target is not empty, it must match a target
+ in the matching node. If the matching of the \a path
+ and the \a target (if present) is successful, \a ref
+ is set from the \a target, and the pointer to the
+ matching node is returned. \a idx is the index into the
+ \a path where to begin the matching. The function is
+ recursive with idx being incremented for each recursive
+ call.
+
+ The matching node must be of the correct \a genus, i.e.
+ either QML or C++, but \a genus can be set to \c DontCare.
+ \a flags indicates whether to search base classes and
+ whether to search for an enum value. \a node points to
+ the node where the search should begin, assuming the
+ \a path is a not a fully-qualified name. \a node is
+ most often the root of this Tree.
+ */
+const Node* Tree::matchPathAndTarget(const QStringList& path,
+ int idx,
+ const QString& target,
+ const Node* node,
+ int flags,
+ Node::Genus genus,
+ QString& ref) const
+{
+ /*
+ If the path has been matched, then if there is a target,
+ try to match the target. If there is a target, but you
+ can't match it at the end of the path, give up; return 0.
*/
- const Node* n = findNode(path, current, findFlags, false);
- if (n)
- return n;
- return findNode(path, current, findFlags, true);
+ if (idx == path.size()) {
+ if (!target.isEmpty()) {
+ ref = getRef(target, node);
+ if (ref.isEmpty())
+ return 0;
+ }
+ if (node->isFunction() && node->name() == node->parent()->name())
+ node = node->parent();
+ return node;
+ }
+
+ const Node* t = 0;
+ QString name = path.at(idx);
+ QList<Node*> nodes;
+ node->findChildren(name, nodes);
+
+ foreach (const Node* n, nodes) {
+ if (genus != Node::DontCare) {
+ if (n->genus() != genus)
+ continue;
+ }
+ t = matchPathAndTarget(path, idx+1, target, n, flags, genus, ref);
+ if (t && !t->isPrivate())
+ return t;
+ }
+ if (target.isEmpty()) {
+ if ((idx) == (path.size()-1) && node->isInnerNode() && (flags & SearchEnumValues)) {
+ t = static_cast<const InnerNode*>(node)->findEnumNodeForValue(path.at(idx));
+ if (t)
+ return t;
+ }
+ }
+ if ((genus != Node::QML) && node->isClass() && (flags & SearchBaseClasses)) {
+ NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
+ foreach (const Node* bc, baseClasses) {
+ t = matchPathAndTarget(path, idx, target, bc, flags, genus, ref);
+ if (t && ! t->isPrivate())
+ return t;
+ if (target.isEmpty()) {
+ if ((idx) == (path.size()-1) && (flags & SearchEnumValues)) {
+ t = static_cast<const InnerNode*>(bc)->findEnumNodeForValue(path.at(idx));
+ if (t)
+ return t;
+ }
+ }
+ }
+ }
+ return 0;
}
/*!
- This overload function was extracted from the one above that has the
- same signature without the last bool parameter, \a qml. This version
- is called only by that other one. It is therefore private. It can
- be called a second time by that other version, if the first call
- returns null. If \a qml is false, the search will only match a node
- that is not a QML node. If \a qml is true, the search will only
- match a node that is a QML node.
-
- This findNode() is only called by the other findNode().
-*/
-const Node* Tree::findNode(const QStringList& path, const Node* start, int findFlags, bool qml) const
+ Searches the tree for a node that matches the \a path. The
+ search begins at \a start but can move up the parent chain
+ recursively if no match is found.
+
+ This findNode() callse the other findNode(), which is not
+ called anywhere else.
+ */
+const Node* Tree::findNode(const QStringList& path,
+ const Node* start,
+ int findFlags,
+ Node::Genus genus) const
{
const Node* current = start;
+ if (!current)
+ current = root();
+
do {
const Node* node = current;
int i;
@@ -718,10 +904,10 @@ const Node* Tree::findNode(const QStringList& path, const Node* start, int findF
check first to see if the first two path strings refer
to a QML element. If they do, path[0] will be the QML
module identifier, and path[1] will be the QML type.
- If the anser is yes, the reference identifies a QML
- class node.
+ If the answer is yes, the reference identifies a QML
+ type node.
*/
- if (qml && path.size() >= 2 && !path[0].isEmpty()) {
+ if ((genus != Node::CPP) && (path.size() >= 2) && !path[0].isEmpty()) {
QmlClassNode* qcn = lookupQmlType(QString(path[0] + "::" + path[1]));
if (qcn) {
node = qcn;
@@ -735,14 +921,14 @@ const Node* Tree::findNode(const QStringList& path, const Node* start, int findF
if (node == 0 || !node->isInnerNode())
break;
- const Node* next = static_cast<const InnerNode*>(node)->findChildNode(path.at(i), qml);
+ const Node* next = static_cast<const InnerNode*>(node)->findChildNode(path.at(i), genus);
if (!next && (findFlags & SearchEnumValues) && i == path.size()-1) {
next = static_cast<const InnerNode*>(node)->findEnumNodeForValue(path.at(i));
}
- if (!next && !qml && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
+ if (!next && (genus != Node::QML) && node->isClass() && (findFlags & SearchBaseClasses)) {
NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
foreach (const Node* baseClass, baseClasses) {
- next = static_cast<const InnerNode*>(baseClass)->findChildNode(path.at(i));
+ next = static_cast<const InnerNode*>(baseClass)->findChildNode(path.at(i), genus);
if (!next && (findFlags & SearchEnumValues) && i == path.size() - 1)
next = static_cast<const InnerNode*>(baseClass)->findEnumNodeForValue(path.at(i));
if (next) {
@@ -752,13 +938,8 @@ const Node* Tree::findNode(const QStringList& path, const Node* start, int findF
}
node = next;
}
- if (node && i == path.size()
- && (!(findFlags & NonFunction) || node->type() != Node::Function
- || ((FunctionNode*)node)->metaness() == FunctionNode::MacroWithoutParams)) {
- if (node->isCollisionNode())
- node = node->applyModuleName(start);
- return node;
- }
+ if (node && i == path.size())
+ return node;
current = current->parent();
} while (current);
@@ -771,16 +952,24 @@ const Node* Tree::findNode(const QStringList& path, const Node* start, int findF
it returns the ref from that node. Otherwise it returns an
empty string.
*/
-QString Tree::findTarget(const QString& target, const Node* node) const
+QString Tree::getRef(const QString& target, const Node* node) const
{
+ TargetMap::const_iterator i = nodesByTargetTitle_.constFind(target);
+ if (i != nodesByTargetTitle_.constEnd()) {
+ do {
+ if (i.value()->node_ == node)
+ return i.value()->ref_;
+ ++i;
+ } while (i != nodesByTargetTitle_.constEnd() && i.key() == target);
+ }
QString key = Doc::canonicalTitle(target);
- TargetMap::const_iterator i = nodesByTarget_.constFind(key);
- if (i != nodesByTarget_.constEnd()) {
+ i = nodesByTargetRef_.constFind(key);
+ if (i != nodesByTargetRef_.constEnd()) {
do {
- if (i.value().node_ == node)
- return i.value().ref_;
+ if (i.value()->node_ == node)
+ return i.value()->ref_;
++i;
- } while (i != nodesByTarget_.constEnd() && i.key() == key);
+ } while (i != nodesByTargetRef_.constEnd() && i.key() == key);
}
return QString();
}
@@ -791,31 +980,15 @@ QString Tree::findTarget(const QString& target, const Node* node) const
the \a node, the \a priority. and a canonicalized form of
the \a name, which is later used.
*/
-void Tree::insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority)
-{
- TargetRec target;
- target.type_ = type;
- target.node_ = node;
- target.priority_ = priority;
- target.ref_ = Doc::canonicalTitle(name);
- nodesByTarget_.insert(name, target);
-}
-
-/*!
- Searches this tree for a node named \a target and returns
- a pointer to it if found. The \a start node is the starting
- point, but it only makes sense if \a start is in this tree.
- If \a start is not in this tree, \a start is set to 0 before
- beginning the search to ensure that the search starts at the
- root.
- */
-const Node* Tree::resolveTarget(const QString& target, const Node* start)
+void Tree::insertTarget(const QString& name,
+ const QString& title,
+ TargetRec::Type type,
+ Node* node,
+ int priority)
{
- QStringList path = target.split("::");
- int flags = SearchBaseClasses | SearchEnumValues | NonFunction;
- if (start && start->tree() != this)
- start = 0;
- return findNode(path, start, flags);
+ TargetRec* target = new TargetRec(name, title, type, node, priority);
+ nodesByTargetRef_.insert(name, target);
+ nodesByTargetTitle_.insert(title, target);
}
/*!
@@ -826,8 +999,10 @@ void Tree::resolveTargets(InnerNode* root)
foreach (Node* child, root->childNodes()) {
if (child->type() == Node::Document) {
DocNode* node = static_cast<DocNode*>(child);
- if (!node->title().isEmpty()) {
- QString key = Doc::canonicalTitle(node->title());
+ QString key = node->title();
+ if (!key.isEmpty()) {
+ if (key.contains(QChar(' ')))
+ key = Doc::canonicalTitle(key);
QList<DocNode*> nodes = docNodesByTitle_.values(key);
bool alreadyThere = false;
if (!nodes.empty()) {
@@ -840,9 +1015,8 @@ void Tree::resolveTargets(InnerNode* root)
}
}
}
- if (!alreadyThere) {
+ if (!alreadyThere)
docNodesByTitle_.insert(key, node);
- }
}
if (node->subType() == Node::Collision) {
resolveTargets(node);
@@ -851,41 +1025,41 @@ void Tree::resolveTargets(InnerNode* root)
if (child->doc().hasTableOfContents()) {
const QList<Atom*>& toc = child->doc().tableOfContents();
- TargetRec target;
- target.node_ = child;
- target.priority_ = 3;
-
for (int i = 0; i < toc.size(); ++i) {
- target.ref_ = refForAtom(toc.at(i));
+ QString ref = refForAtom(toc.at(i));
QString title = Text::sectionHeading(toc.at(i)).toString();
- if (!title.isEmpty()) {
+ if (!ref.isEmpty() && !title.isEmpty()) {
QString key = Doc::canonicalTitle(title);
- nodesByTarget_.insert(key, target);
+ TargetRec* target = new TargetRec(ref, title, TargetRec::Contents, child, 3);
+ nodesByTargetRef_.insert(key, target);
+ nodesByTargetTitle_.insert(title, target);
}
}
}
if (child->doc().hasKeywords()) {
const QList<Atom*>& keywords = child->doc().keywords();
- TargetRec target;
- target.node_ = child;
- target.priority_ = 1;
-
for (int i = 0; i < keywords.size(); ++i) {
- target.ref_ = refForAtom(keywords.at(i));
- QString key = Doc::canonicalTitle(keywords.at(i)->string());
- nodesByTarget_.insert(key, target);
+ QString ref = refForAtom(keywords.at(i));
+ QString title = keywords.at(i)->string();
+ if (!ref.isEmpty() && !title.isEmpty()) {
+ QString key = Doc::canonicalTitle(title);
+ TargetRec* target = new TargetRec(ref, title, TargetRec::Keyword, child, 1);
+ nodesByTargetRef_.insert(key, target);
+ nodesByTargetTitle_.insert(title, target);
+ }
}
}
if (child->doc().hasTargets()) {
- const QList<Atom*>& toc = child->doc().targets();
- TargetRec target;
- target.node_ = child;
- target.priority_ = 2;
-
- for (int i = 0; i < toc.size(); ++i) {
- target.ref_ = refForAtom(toc.at(i));
- QString key = Doc::canonicalTitle(toc.at(i)->string());
- nodesByTarget_.insert(key, target);
+ const QList<Atom*>& targets = child->doc().targets();
+ for (int i = 0; i < targets.size(); ++i) {
+ QString ref = refForAtom(targets.at(i));
+ QString title = targets.at(i)->string();
+ if (!ref.isEmpty() && !title.isEmpty()) {
+ QString key = Doc::canonicalTitle(title);
+ TargetRec* target = new TargetRec(ref, title, TargetRec::Target, child, 2);
+ nodesByTargetRef_.insert(key, target);
+ nodesByTargetTitle_.insert(title, target);
+ }
}
}
}
@@ -896,46 +1070,58 @@ void Tree::resolveTargets(InnerNode* root)
finds one, it sets \a ref and returns the found node.
*/
const Node*
-Tree::findUnambiguousTarget(const QString& target, QString& ref)
+Tree::findUnambiguousTarget(const QString& target, QString& ref) const
{
- TargetRec bestTarget;
int numBestTargets = 0;
- QList<TargetRec> bestTargetList;
+ TargetRec* bestTarget = 0;
+ QList<TargetRec*> bestTargetList;
- QString key = Doc::canonicalTitle(target);
- TargetMap::iterator i = nodesByTarget_.find(key);
- while (i != nodesByTarget_.end()) {
+ QString key = target;
+ TargetMap::const_iterator i = nodesByTargetTitle_.find(key);
+ while (i != nodesByTargetTitle_.constEnd()) {
if (i.key() != key)
break;
- const TargetRec& candidate = i.value();
- if (candidate.priority_ < bestTarget.priority_) {
+ TargetRec* candidate = i.value();
+ if (!bestTarget || (candidate->priority_ < bestTarget->priority_)) {
bestTarget = candidate;
bestTargetList.clear();
bestTargetList.append(candidate);
numBestTargets = 1;
- } else if (candidate.priority_ == bestTarget.priority_) {
+ } else if (candidate->priority_ == bestTarget->priority_) {
bestTargetList.append(candidate);
++numBestTargets;
}
++i;
}
- if (numBestTargets > 0) {
- if (numBestTargets == 1) {
- ref = bestTarget.ref_;
- return bestTarget.node_;
- }
- else if (bestTargetList.size() > 1) {
-#if 0
- qDebug() << "TARGET:" << target << numBestTargets;
- for (int i=0; i<bestTargetList.size(); ++i) {
- const Node* n = bestTargetList.at(i).node_;
- qDebug() << " " << n->name() << n->title();
- }
-#endif
- ref = bestTargetList.at(0).ref_;
- return bestTargetList.at(0).node_;
+ if (bestTarget) {
+ ref = bestTarget->ref_;
+ return bestTarget->node_;
+ }
+
+ numBestTargets = 0;
+ bestTarget = 0;
+ key = Doc::canonicalTitle(target);
+ i = nodesByTargetRef_.find(key);
+ while (i != nodesByTargetRef_.constEnd()) {
+ if (i.key() != key)
+ break;
+ TargetRec* candidate = i.value();
+ if (!bestTarget || (candidate->priority_ < bestTarget->priority_)) {
+ bestTarget = candidate;
+ bestTargetList.clear();
+ bestTargetList.append(candidate);
+ numBestTargets = 1;
+ } else if (candidate->priority_ == bestTarget->priority_) {
+ bestTargetList.append(candidate);
+ ++numBestTargets;
}
+ ++i;
}
+ if (bestTarget) {
+ ref = bestTarget->ref_;
+ return bestTarget->node_;
+ }
+
ref.clear();
return 0;
}
@@ -945,8 +1131,11 @@ Tree::findUnambiguousTarget(const QString& target, QString& ref)
*/
const DocNode* Tree::findDocNodeByTitle(const QString& title) const
{
- QString key = Doc::canonicalTitle(title);
- DocNodeMultiMap::const_iterator i = docNodesByTitle_.constFind(key);
+ DocNodeMultiMap::const_iterator i;
+ if (title.contains(QChar(' ')))
+ i = docNodesByTitle_.constFind(Doc::canonicalTitle(title));
+ else
+ i = docNodesByTitle_.constFind(title);
if (i != docNodesByTitle_.constEnd()) {
/*
Reporting all these duplicate section titles is probably
@@ -1241,13 +1430,15 @@ void Tree::insertQmlType(const QString& key, QmlClassNode* n)
/*!
Split \a target on "::" and find the function node with that
path.
+
+ Called in HtmlGenerator, DitaXmlGenerator, and QdocDatabase.
*/
-const Node* Tree::resolveFunctionTarget(const QString& target, const Node* relative)
+const Node* Tree::findFunctionNode(const QString& target, const Node* relative, Node::Genus genus)
{
QString t = target;
t.chop(2);
QStringList path = t.split("::");
- const FunctionNode* fn = findFunctionNode(path, relative, SearchBaseClasses);
+ const FunctionNode* fn = findFunctionNode(path, relative, SearchBaseClasses, genus);
if (fn && fn->metaness() != FunctionNode::MacroWithoutParams)
return fn;
return 0;
diff --git a/src/tools/qdoc/tree.h b/src/tools/qdoc/tree.h
index a953751968..c9c695d119 100644
--- a/src/tools/qdoc/tree.h
+++ b/src/tools/qdoc/tree.h
@@ -58,15 +58,24 @@ struct TargetRec
{
public:
enum Type { Unknown, Target, Keyword, Contents, Class, Function, Page, Subtitle };
- TargetRec() : node_(0), priority_(INT_MAX), type_(Unknown) { }
+
+ TargetRec(const QString& name,
+ const QString& title,
+ TargetRec::Type type,
+ Node* node,
+ int priority)
+ : node_(node), ref_(name), title_(title), priority_(priority), type_(type) { }
+
bool isEmpty() const { return ref_.isEmpty(); }
+
Node* node_;
QString ref_;
+ QString title_;
int priority_;
Type type_;
};
-typedef QMultiMap<QString, TargetRec> TargetMap;
+typedef QMultiMap<QString, TargetRec*> TargetMap;
typedef QMultiMap<QString, DocNode*> DocNodeMultiMap;
typedef QMap<QString, QmlClassNode*> QmlTypeMap;
typedef QMultiMap<QString, const ExampleNode*> ExampleNodeMap;
@@ -83,10 +92,11 @@ class Tree
Tree(const QString& module, QDocDatabase* qdb);
~Tree();
- ClassNode* findClassNode(const QStringList& path, Node* start = 0) const;
+ Node* findNodeForInclude(const QStringList& path) const;
+ ClassNode* findClassNode(const QStringList& path, const Node* start = 0) const;
NamespaceNode* findNamespaceNode(const QStringList& path) const;
FunctionNode* findFunctionNode(const QStringList& parentPath, const FunctionNode* clone);
- const Node* resolveFunctionTarget(const QString& target, const Node* relative);
+ const Node* findFunctionNode(const QString& target, const Node* relative, Node::Genus genus);
Node* findNodeRecursive(const QStringList& path,
int pathIndex,
@@ -97,14 +107,24 @@ class Tree
Node* start,
const NodeTypeList& types) const;
- const Node* findNode(const QStringList &path,
- const Node* relative = 0,
- int findFlags = 0) const;
+ const Node* findNodeForTarget(const QStringList& path,
+ const QString& target,
+ const Node* node,
+ int flags,
+ Node::Genus genus,
+ QString& ref) const;
+ const Node* matchPathAndTarget(const QStringList& path,
+ int idx,
+ const QString& target,
+ const Node* node,
+ int flags,
+ Node::Genus genus,
+ QString& ref) const;
- const Node* findNode(const QStringList& path,
- const Node* start,
- int findFlags,
- bool qml) const;
+ const Node* findNode(const QStringList &path,
+ const Node* relative, // = 0,
+ int findFlags, // = 0,
+ Node::Genus genus) const; // = Node::DontCare) const;
QmlClassNode* findQmlTypeNode(const QStringList& path);
@@ -112,11 +132,14 @@ class Tree
InnerNode* findRelatesNode(const QStringList& path);
NameCollisionNode* checkForCollision(const QString& name);
NameCollisionNode* findCollisionNode(const QString& name) const;
- QString findTarget(const QString& target, const Node* node) const;
- void insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority);
- const Node* resolveTarget(const QString& target, const Node* start);
+ QString getRef(const QString& target, const Node* node) const;
+ void insertTarget(const QString& name,
+ const QString& title,
+ TargetRec::Type type,
+ Node* node,
+ int priority);
void resolveTargets(InnerNode* root);
- const Node* findUnambiguousTarget(const QString& target, QString& ref);
+ const Node* findUnambiguousTarget(const QString& target, QString& ref) const;
const DocNode* findDocNodeByTitle(const QString& title) const;
void addPropertyFunction(PropertyNode *property,
@@ -131,7 +154,8 @@ class Tree
const FunctionNode *findFunctionNode(const QStringList &path,
const Node *relative = 0,
- int findFlags = 0) const;
+ int findFlags = 0,
+ Node::Genus genus = Node::DontCare) const;
const NamespaceNode *root() const { return &root_; }
FunctionNode *findVirtualFunctionInBaseClasses(ClassNode *classe,
@@ -182,7 +206,8 @@ private:
NamespaceNode root_;
PropertyMap unresolvedPropertyMap;
DocNodeMultiMap docNodesByTitle_;
- TargetMap nodesByTarget_;
+ TargetMap nodesByTargetRef_;
+ TargetMap nodesByTargetTitle_;
CNMap groups_;
CNMap modules_;
CNMap qmlModules_;