diff options
author | Martin Smith <martin.smith@digia.com> | 2014-07-28 14:21:37 +0200 |
---|---|---|
committer | Martin Smith <martin.smith@digia.com> | 2014-08-20 21:59:23 +0200 |
commit | a2c432e97818ec16ead9be0d0aee3e43cf10929e (patch) | |
tree | 200d7aab7de7bda12ae46303a131920d6fe325dd /src/tools | |
parent | 0da4ddfcc59a639b014296a4544c8aff5d91f3f9 (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.cpp | 24 | ||||
-rw-r--r-- | src/tools/qdoc/atom.h | 8 | ||||
-rw-r--r-- | src/tools/qdoc/ditaxmlgenerator.cpp | 147 | ||||
-rw-r--r-- | src/tools/qdoc/htmlgenerator.cpp | 75 | ||||
-rw-r--r-- | src/tools/qdoc/node.cpp | 89 | ||||
-rw-r--r-- | src/tools/qdoc/node.h | 33 | ||||
-rw-r--r-- | src/tools/qdoc/qdocdatabase.cpp | 158 | ||||
-rw-r--r-- | src/tools/qdoc/qdocdatabase.h | 79 | ||||
-rw-r--r-- | src/tools/qdoc/qdocindexfiles.cpp | 27 | ||||
-rw-r--r-- | src/tools/qdoc/qmlvisitor.cpp | 2 | ||||
-rw-r--r-- | src/tools/qdoc/tree.cpp | 463 | ||||
-rw-r--r-- | src/tools/qdoc/tree.h | 59 |
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_; |