summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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 5c699b05469..0c17a38e51e 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 36a7390ae21..65ba2a9b5cf 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 c2a5cdb8b8f..83d89d01873 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 dd665ea8854..44de7e11540 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 87a055ae0fb..fa91d67f1c4 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 37fbe482b03..67ad006e2cb 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 d43fdf49705..e9e62fb7f3c 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 99d1c46ca29..12105842b8f 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 4531ce8eeaf..ba09bfea3b5 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 fbe4940c19f..026f3bd0a2a 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 e689227bf18..d43f82949a6 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 a9537519684..c9c695d119d 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_;