From 2ea15849a09208ac19d189acdc51c313b64a0b3a Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Wed, 19 Mar 2014 15:12:07 +0100 Subject: qdoc: \l{Qt::Window} links to the wrong page kThis update fixes a bug introduced by the extensive changes for QTBUG-35377. The name Qt represents two namespaces, one in C++ and one in QML. The name "Window" is used in both of them, so the link \l{Qt::Window} would cause a collision in the single tree qdoc. In the multiple tree qdoc, there is no collision, but in this case the link should have gone to the C++ page and it went to the QML page instead. The fix involved correcting the way qdoc searches for link targets. Task-number: QTBUG-37633 Change-Id: Ib9b209eced937a0be0d3299f300ebf22b2776012 Reviewed-by: Martin Smith --- src/tools/qdoc/ditaxmlgenerator.cpp | 125 ++++++++++++++++++------------------ src/tools/qdoc/htmlgenerator.cpp | 69 +++++++++----------- src/tools/qdoc/qdocdatabase.cpp | 53 +++++++-------- src/tools/qdoc/qdocdatabase.h | 86 +++++++++++++------------ src/tools/qdoc/tree.cpp | 105 +++++++++++++++--------------- src/tools/qdoc/tree.h | 11 ++-- 6 files changed, 220 insertions(+), 229 deletions(-) diff --git a/src/tools/qdoc/ditaxmlgenerator.cpp b/src/tools/qdoc/ditaxmlgenerator.cpp index 8ac1b1ef82..90661d80e0 100644 --- a/src/tools/qdoc/ditaxmlgenerator.cpp +++ b/src/tools/qdoc/ditaxmlgenerator.cpp @@ -3389,68 +3389,71 @@ void DitaXmlGenerator::writeText(const QString& markedCode, const Node* relative for (int k = 0; k != 6; ++k) { if (parseArg(src, markTags[k], &i, n, &arg, &par1)) { const Node* n = 0; - if (k == 0) { // <@link> - if (!text.isEmpty()) { - writeCharacters(text); - text.clear(); - } - n = CodeMarker::nodeForString(par1.toString()); - QString link = linkForNode(n, relative); - addLink(link, arg); - } - else if (k == 4) { // <@param> - if (!text.isEmpty()) { - writeCharacters(text); - text.clear(); - } - writeStartTag(DT_i); - //writeCharacters(" " + arg.toString()); - writeCharacters(arg.toString()); - writeEndTag(); // - } - else if (k == 5) { // <@extra> - if (!text.isEmpty()) { - writeCharacters(text); - text.clear(); - } - writeStartTag(DT_tt); - writeCharacters(arg.toString()); - writeEndTag(); // - } - else { - if (!text.isEmpty()) { - writeCharacters(text); - text.clear(); - } - par1 = QStringRef(); - QString link; - n = qdb_->resolveTarget(arg.toString(), relative); - if (n && n->subType() == Node::QmlBasicType) { - if (relative && relative->subType() == Node::QmlClass) { - link = linkForNode(n,relative); - addLink(link, arg); + switch (k) { + case 0: // <@link> + if (!text.isEmpty()) { + writeCharacters(text); + text.clear(); } - else { - writeCharacters(arg.toString()); + n = CodeMarker::nodeForString(par1.toString()); + addLink(linkForNode(n, relative), arg); + break; + case 4: // <@param> + if (!text.isEmpty()) { + writeCharacters(text); + text.clear(); } - } - else { - // (zzz) Is this correct for all cases? - link = linkForNode(n,relative); - addLink(link, arg); - } - } + writeStartTag(DT_i); + //writeCharacters(" " + arg.toString()); + writeCharacters(arg.toString()); + writeEndTag(); // + break; + case 5: // <@extra> + if (!text.isEmpty()) { + writeCharacters(text); + text.clear(); + } + writeStartTag(DT_tt); + writeCharacters(arg.toString()); + writeEndTag(); // + break; + case 3: + if (!text.isEmpty()) { + writeCharacters(text); + text.clear(); + } + par1 = QStringRef(); + n = qdb_->resolveFunctionTarget(arg.toString(), relative); + addLink(linkForNode(n, relative), arg); + break; + case 1: + case 2: + default: + if (!text.isEmpty()) { + writeCharacters(text); + text.clear(); + } + par1 = QStringRef(); + n = qdb_->resolveType(arg.toString(), relative); + if (n && n->subType() == Node::QmlBasicType) { + if (relative && relative->subType() == Node::QmlClass) + addLink(linkForNode(n, relative), arg); + else + writeCharacters(arg.toString()); + } + else + addLink(linkForNode(n, relative), arg); // (zzz) Is this correct for all cases? + break; + } // switch break; } } } - else { + else text += src.at(i++); - } } - if (!text.isEmpty()) { + if (!text.isEmpty()) writeCharacters(text); - } } void DitaXmlGenerator::generateLink(const Atom* atom, CodeMarker* marker) @@ -3830,18 +3833,18 @@ QString DitaXmlGenerator::getLink(const Atom* atom, const Node* relative, const QString ref; QString first = path.first().trimmed(); - if (first.isEmpty()) { + if (first.isEmpty()) *node = relative; - } - else if (first.endsWith(".html")) { + else if (first.endsWith(".html")) *node = qdb_->findNodeByNameAndType(QStringList(first), Node::Document, Node::NoSubType); - } + 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_->findDocNodeByTitle(first, relative); - if (!*node) - *node = qdb_->findUnambiguousTarget(first, ref, relative); + *node = qdb_->findUnambiguousTarget(first, ref); } if (*node) { @@ -4601,7 +4604,7 @@ void DitaXmlGenerator::replaceTypesWithLinks(const Node* n, const InnerNode* par } i += 2; if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) { - const Node* tn = qdb_->resolveTarget(arg.toString(), parent); + const Node* tn = qdb_->resolveType(arg.toString(), parent); if (tn) { //Do not generate a link from a C++ function to a QML Basic Type (such as int) if (n->type() == Node::Function && tn->subType() == Node::QmlBasicType) diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index ec430d0951..ceed09a7cf 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -320,6 +320,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark if (!inLink_ && !inContents_ && !inSectionHeading_) { const Node *node = 0; QString link = getLink(atom, relative, &node); + QDocDatabase::debug = false; if (!link.isEmpty()) { beginLink(link, node, relative); generateLink(atom, marker); @@ -3188,7 +3189,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_->resolveTarget(par1.toString(), relative); + const Node* n = qdb_->resolveFunctionTarget(par1.toString(), relative); QString link = linkForNode(n, relative); addLink(link, arg, &html); par1 = QStringRef(); @@ -3228,20 +3229,18 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, } else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) { par1 = QStringRef(); - const Node* n = qdb_->resolveTarget(arg.toString(), relative); - addLink(linkForNode(n,relative), arg, &html); - handled = true; - } -#if 0 - // Apparently, this clause was never used. - // <@func> is taken out above. - else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) { - par1 = QStringRef(); - const Node* n = qdb_->resolveTarget(arg.toString(), relative); - addLink(linkForNode(n,relative), arg, &html); + if (arg.at(0) == QChar('&')) + html += arg.toString(); + else { + // zzz resolveClassTarget() + const Node* n = qdb_->resolveTarget(arg.toString(), relative); + if (n) + addLink(linkForNode(n,relative), arg, &html); + else + html += arg.toString(); + } handled = true; } -#endif if (!handled) { html += charLangle; html += charAt; @@ -3763,45 +3762,35 @@ QString HtmlGenerator::getLink(const Atom *atom, const Node *relative, const Nod *node = 0; inObsoleteLink = false; - 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:"))) { - - link = atom->string(); + 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:"))) { + link = atom->string(); // It's some kind of protocol. } else { QStringList path; - if (atom->string().contains('#')) { - path = atom->string().split('#'); - } - else { - path.append(atom->string()); - } + if (atom->string().contains('#')) + path = atom->string().split('#'); // The target is in the html file. + else + path.append(atom->string()); // It's a general case target. QString ref; QString first = path.first().trimmed(); - if (first.isEmpty()) { + if (first.isEmpty()) *node = relative; - } - else if (first.endsWith(".html")) { - /* - This is not a recursive search. That's ok in - this case, because we are searching for a page - node, which must be a direct child of the tree - root. - */ + else if (first.endsWith(".html")) // The target is an html file. *node = qdb_->findNodeByNameAndType(QStringList(first), Node::Document, Node::NoSubType); + 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_->resolveTarget(first, relative); - if (!(*node)) - *node = qdb_->findDocNodeByTitle(first, relative); + *node = qdb_->findDocNodeByTitle(first); if (!(*node)) { - *node = qdb_->findUnambiguousTarget(first, ref, relative); + *node = qdb_->findUnambiguousTarget(first, ref); if (*node && !(*node)->url().isEmpty() && !ref.isEmpty()) { QString final = (*node)->url() + "#" + ref; return final; diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index 289e57d16c..ffd2dd9b3b 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE static NodeMap emptyNodeMap_; static NodeMultiMap emptyNodeMultiMap_; +bool QDocDatabase::debug = false; /*! \class QDocForest This class manages a collection of trees. Each tree is an @@ -368,38 +369,30 @@ void QDocForest::newPrimaryTree(const QString& module) } /*! - Searches the Tree \a t for a node named \a target and returns + 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. 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::resolveTargetHelper(const QString& target, - const Node* relative, - Tree* t) + 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 node of the index tree is the starting point. + */ +const Node* QDocForest::resolveTarget(const QString& target, const Node* relative) { - const Node* node = 0; - if (target.endsWith("()")) { - QString funcName = target; - funcName.chop(2); - QStringList path = funcName.split("::"); - const FunctionNode* fn = t->findFunctionNode(path, relative, SearchBaseClasses); - if (fn && fn->metaness() != FunctionNode::MacroWithoutParams) - node = fn; - } - else { - QStringList path = target.split("::"); - int flags = SearchBaseClasses | SearchEnumValues | NonFunction; - node = t->findNode(path, relative, flags); - if (!node) { - QStringList path = target.split("::"); - const FunctionNode* fn = t->findFunctionNode(path, relative, SearchBaseClasses); - if (fn && fn->metaness() != FunctionNode::MacroWithoutParams) - node = fn; - } + QStringList path = target.split("::"); + int flags = SearchBaseClasses | SearchEnumValues | NonFunction; + + foreach (Tree* t, searchOrder()) { + const Node* n = t->findNode(path, relative, flags); + if (n) + return n; +#if 0 + n = t->findDocNodeByTitle(target); + if (n) + return n; +#endif + relative = 0; } - return node; + return 0; } /*! @@ -1356,7 +1349,7 @@ const Node* QDocDatabase::findNodeForTarget(const QString& target, const Node* r else { node = resolveTarget(target, relative); if (!node) - node = findDocNodeByTitle(target, relative); + node = findDocNodeByTitle(target); } return node; } diff --git a/src/tools/qdoc/qdocdatabase.h b/src/tools/qdoc/qdocdatabase.h index 1fff24cb65..7bbff89fa3 100644 --- a/src/tools/qdoc/qdocdatabase.h +++ b/src/tools/qdoc/qdocdatabase.h @@ -89,11 +89,11 @@ class QDocForest const Node* findNode(const QStringList& path, const Node* relative, int findFlags) { foreach (Tree* t, searchOrder()) { const Node* n = t->findNode(path, relative, findFlags); - if (n) return n; + if (n) + return n; relative = 0; } - if (Config::debug_) - qDebug() << "FAILED SEARCH 1" << path; + //qDebug() << "FAILED SEARCH 1" << path; return 0; } @@ -103,55 +103,53 @@ class QDocForest bool acceptCollision = false) { foreach (Tree* t, searchOrder()) { Node* n = t->findNodeByNameAndType(path, type, subtype, acceptCollision); - if (n) return n; + if (n) + return n; } - if (Config::debug_) - qDebug() << "FAILED SEARCH 2" << path << type << subtype; + //qDebug() << "FAILED SEARCH 2" << path << type << subtype; return 0; } ClassNode* findClassNode(const QStringList& path) { foreach (Tree* t, searchOrder()) { ClassNode* n = t->findClassNode(path); - if (n) return n; + if (n) + return n; } - if (Config::debug_) - qDebug() << "FAILED SEARCH 3" << path; + //qDebug() << "FAILED SEARCH 3" << path; return 0; } InnerNode* findRelatesNode(const QStringList& path) { foreach (Tree* t, searchOrder()) { InnerNode* n = t->findRelatesNode(path); - if (n) return n; + if (n) + return n; } - if (Config::debug_) - qDebug() << "FAILED SEARCH 4" << path; + //qDebug() << "FAILED SEARCH 4" << path; return 0; } - const Node* resolveTarget(const QString& target, const Node* relative) { - const Node* r = relative; + const Node* resolveFunctionTarget(const QString& target, const Node* relative) { foreach (Tree* t, searchOrder()) { - const Node* n = resolveTargetHelper(target, relative, t); - if (n) return n; + const Node* n = t->resolveFunctionTarget(target, relative); + if (n) + return n; relative = 0; } - if (Config::debug_) { - qDebug() << "FAILED SEARCH 6" << target << r; - } return 0; } + const Node* resolveTarget(const QString& target, const Node* relative); const Node* resolveType(const QStringList& path, const Node* relative) { foreach (Tree* t, searchOrder()) { const Node* n = resolveTypeHelper(path, relative, t); - if (n) return n; + if (n) + return n; relative = 0; } - if (Config::debug_) - qDebug() << "FAILED SEARCH 5" << path; + //qDebug() << "FAILED SEARCH 5" << path; return 0; } @@ -159,32 +157,32 @@ class QDocForest { foreach (Tree* t, searchOrder()) { QString ref = t->findTarget(target, node); - if (!ref.isEmpty()) return ref; + if (!ref.isEmpty()) + return ref; } - if (Config::debug_) - qDebug() << "FAILED SEARCH 7" << target; + //qDebug() << "FAILED SEARCH 7" << target; return QString(); } - const Node* findUnambiguousTarget(const QString& target, QString& ref, const Node* relative) + const Node* findUnambiguousTarget(const QString& target, QString& ref) { foreach (Tree* t, searchOrder()) { - const Node* n = t->findUnambiguousTarget(target, ref, relative); - if (n) return n; + const Node* n = t->findUnambiguousTarget(target, ref); + if (n) + return n; } - if (Config::debug_) - qDebug() << "FAILED SEARCH 8" << target; + //qDebug() << "FAILED SEARCH 8" << target; return 0; } - const DocNode* findDocNodeByTitle(const QString& title, const Node* relative) + const DocNode* findDocNodeByTitle(const QString& title) { foreach (Tree* t, searchOrder()) { - const DocNode* n = t->findDocNodeByTitle(title, relative); - if (n) return n; + const DocNode* n = t->findDocNodeByTitle(title); + if (n) + return n; } - if (Config::debug_) - qDebug() << "FAILED SEARCH 9" << title; + //qDebug() << "FAILED SEARCH 9" << title; return 0; } @@ -192,7 +190,8 @@ class QDocForest { foreach (Tree* t, searchOrder()) { QmlClassNode* qcn = t->lookupQmlType(name); - if (qcn) return qcn; + if (qcn) + return qcn; } return 0; } @@ -209,7 +208,6 @@ class QDocForest private: void newPrimaryTree(const QString& module); NamespaceNode* newIndexTree(const QString& module); - const Node* resolveTargetHelper(const QString& target, const Node* relative, Tree* t); const Node* resolveTypeHelper(const QStringList& path, const Node* relative, Tree* t); private: @@ -329,13 +327,16 @@ class QDocDatabase const Node* resolveTarget(const QString& target, const Node* relative) { return forest_.resolveTarget(target, relative); } + 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* findNodeForTarget(const QString& target, const Node* relative); - const DocNode* findDocNodeByTitle(const QString& title, const Node* relative = 0) { - return forest_.findDocNodeByTitle(title, relative); + const DocNode* findDocNodeByTitle(const QString& title) { + return forest_.findDocNodeByTitle(title); } - const Node* findUnambiguousTarget(const QString& target, QString& ref, const Node* relative) { - return forest_.findUnambiguousTarget(target, ref, relative); + const Node* findUnambiguousTarget(const QString& target, QString& ref) { + return forest_.findUnambiguousTarget(target, ref); } Node* findNodeByNameAndType(const QStringList& path, Node::Type type, Node::SubType subtype){ return forest_.findNodeByNameAndType(path, type, subtype, false); @@ -389,6 +390,9 @@ class QDocDatabase QDocDatabase& operator=(QDocDatabase const& ); Tree* primaryTree() { return forest_.primaryTree(); } + public: + static bool debug; + private: static QDocDatabase* qdocDB_; static NodeMap typeNodeMap_; diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp index e3dc4c657a..d17468f3a9 100644 --- a/src/tools/qdoc/tree.cpp +++ b/src/tools/qdoc/tree.cpp @@ -220,17 +220,23 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path, if (!relative) relative = root(); - /* - If the path contains two double colons ("::"), check - first to see if it is a reference to a QML method. If - it is a reference to a QML method, first look up the - QML class node in the QML module map. - */ if (path.size() == 3 && !path[0].isEmpty()) { - QmlClassNode* qcn = qdb_->findQmlType(path[0], path[1]); - if (qcn) { - return static_cast(qcn->findFunctionNode(path[2])); + QmlClassNode* qcn = lookupQmlType(QString(path[0] + "::" + path[1])); + if (!qcn) { + QStringList p(path[1]); + Node* n = findNodeByNameAndType(p, Node::Document, Node::QmlClass, true); + if (n) { + if (n->subType() == Node::QmlClass) + qcn = static_cast(n); + else if (n->subType() == Node::Collision) { + NameCollisionNode* ncn; + ncn = static_cast(n); + qcn = static_cast(ncn->findAny(Node::Document, Node::QmlClass)); + } + } } + if (qcn) + return static_cast(qcn->findFunctionNode(path[2])); } do { @@ -555,7 +561,7 @@ NodeList Tree::allBaseClasses(const ClassNode* classNode) const Node* Tree::findNodeByNameAndType(const QStringList& path, Node::Type type, Node::SubType subtype, - bool acceptCollision) + bool acceptCollision) const { Node* result = findNodeRecursive(path, 0, root(), type, subtype, acceptCollision); return result; @@ -581,22 +587,23 @@ Node* Tree::findNodeByNameAndType(const QStringList& path, */ Node* Tree::findNodeRecursive(const QStringList& path, int pathIndex, - Node* start, + const Node* start, Node::Type type, Node::SubType subtype, bool acceptCollision) const { if (!start || path.isEmpty()) return 0; // no place to start, or nothing to search for. + Node* node = const_cast(start); if (start->isLeaf()) { if (pathIndex >= path.size()) - return start; // found a match. + return node; // found a match. return 0; // premature leaf } if (pathIndex >= path.size()) return 0; // end of search path. - InnerNode* current = static_cast(start); + InnerNode* current = static_cast(node); const NodeList& children = current->childNodes(); const QString& name = path.at(pathIndex); for (int i=0; i= 2 && !path[0].isEmpty()) { - QmlClassNode* qcn = qdb_->findQmlType(path[0], path[1]); + QmlClassNode* qcn = lookupQmlType(QString(path[0] + "::" + path[1])); if (qcn) { node = qcn; if (path.size() == 2) @@ -759,17 +768,18 @@ const Node* Tree::findNode(const QStringList& path, const Node* start, int findF break; const Node* next = static_cast(node)->findChildNode(path.at(i), qml); - if (!next && (findFlags & SearchEnumValues) && i == path.size()-1) + if (!next && (findFlags & SearchEnumValues) && i == path.size()-1) { next = static_cast(node)->findEnumNodeForValue(path.at(i)); - + } if (!next && !qml && node->type() == Node::Class && (findFlags & SearchBaseClasses)) { NodeList baseClasses = allBaseClasses(static_cast(node)); foreach (const Node* baseClass, baseClasses) { next = static_cast(baseClass)->findChildNode(path.at(i)); if (!next && (findFlags & SearchEnumValues) && i == path.size() - 1) next = static_cast(baseClass)->findEnumNodeForValue(path.at(i)); - if (next) + if (next) { break; + } } } node = next; @@ -903,7 +913,7 @@ 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, const Node* relative) +Tree::findUnambiguousTarget(const QString& target, QString& ref) { TargetRec bestTarget; int numBestTargets = 0; @@ -932,15 +942,15 @@ Tree::findUnambiguousTarget(const QString& target, QString& ref, const Node* rel return bestTarget.node_; } else if (bestTargetList.size() > 1) { - if (relative && !relative->qmlModuleName().isEmpty()) { - for (int i=0; iqmlModuleName() == n->qmlModuleName()) { - ref = bestTargetList.at(i).ref_; - return n; - } - } +#if 0 + qDebug() << "TARGET:" << target << numBestTargets; + for (int i=0; iname() << n->title(); } +#endif + ref = bestTargetList.at(0).ref_; + return bestTargetList.at(0).node_; } } ref.clear(); @@ -949,36 +959,12 @@ Tree::findUnambiguousTarget(const QString& target, QString& ref, const Node* rel /*! This function searches for a node with the specified \a title. - If \a relative node is provided, it is used to disambiguate if - it has a QML module identifier. */ -const DocNode* Tree::findDocNodeByTitle(const QString& title, const Node* relative) const +const DocNode* Tree::findDocNodeByTitle(const QString& title) const { QString key = Doc::canonicalTitle(title); DocNodeMultiMap::const_iterator i = docNodesByTitle_.constFind(key); if (i != docNodesByTitle_.constEnd()) { - if (relative && !relative->qmlModuleName().isEmpty()) { - const DocNode* dn = i.value(); - InnerNode* parent = dn->parent(); - if (parent && parent->type() == Node::Document && parent->subType() == Node::Collision) { - const NodeList& nl = parent->childNodes(); - NodeList::ConstIterator it = nl.constBegin(); - while (it != nl.constEnd()) { - if ((*it)->qmlModuleName() == relative->qmlModuleName()) { - /* - By returning here, we avoid printing - all the duplicate header warnings, - which are not really duplicates now, - because of the QML module name being - used as a namespace qualifier. - */ - dn = static_cast(*it); - return dn; - } - ++it; - } - } - } /* Reporting all these duplicate section titles is probably overkill. We should report the duplicate file and let @@ -1269,4 +1255,19 @@ void Tree::insertQmlType(const QString& key, QmlClassNode* n) qmlTypeMap_.insert(key,n); } +/*! + Split \a target on "::" and find the function node with that + path. + */ +const Node* Tree::resolveFunctionTarget(const QString& target, const Node* relative) +{ + QString t = target; + t.chop(2); + QStringList path = t.split("::"); + const FunctionNode* fn = findFunctionNode(path, relative, SearchBaseClasses); + if (fn && fn->metaness() != FunctionNode::MacroWithoutParams) + return fn; + return 0; +} + QT_END_NAMESPACE diff --git a/src/tools/qdoc/tree.h b/src/tools/qdoc/tree.h index 565cb9c471..916682daad 100644 --- a/src/tools/qdoc/tree.h +++ b/src/tools/qdoc/tree.h @@ -86,10 +86,11 @@ class Tree ClassNode* findClassNode(const QStringList& path, 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); Node* findNodeRecursive(const QStringList& path, int pathIndex, - Node* start, + const Node* start, Node::Type type, Node::SubType subtype, bool acceptCollision = false) const; @@ -112,7 +113,7 @@ class Tree Node* findNodeByNameAndType(const QStringList& path, Node::Type type, Node::SubType subtype, - bool acceptCollision = false); + bool acceptCollision = false) const; InnerNode* findRelatesNode(const QStringList& path); @@ -121,8 +122,8 @@ class Tree QString findTarget(const QString& target, const Node* node) const; void insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority); void resolveTargets(InnerNode* root); - const Node* findUnambiguousTarget(const QString& target, QString& ref, const Node* relative); - const DocNode* findDocNodeByTitle(const QString& title, const Node* relative = 0) const; + const Node* findUnambiguousTarget(const QString& target, QString& ref); + const DocNode* findDocNodeByTitle(const QString& title) const; void addPropertyFunction(PropertyNode *property, const QString &funcName, @@ -173,7 +174,7 @@ class Tree ModuleNode* addToModule(const QString& name, Node* node); QmlModuleNode* addToQmlModule(const QString& name, Node* node); - QmlClassNode* lookupQmlType(const QString& name) { return qmlTypeMap_.value(name); } + QmlClassNode* lookupQmlType(const QString& name) const { return qmlTypeMap_.value(name); } void insertQmlType(const QString& key, QmlClassNode* n); void addExampleNode(ExampleNode* n) { exampleNodeMap_.insert(n->title(), n); } ExampleNodeMap& exampleNodeMap() { return exampleNodeMap_; } -- cgit v1.2.3