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 <martin.smith@digia.com>
This commit is contained in:
parent
900c150a07
commit
2ea15849a0
@ -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(); // </i>
|
||||
}
|
||||
else if (k == 5) { // <@extra>
|
||||
if (!text.isEmpty()) {
|
||||
writeCharacters(text);
|
||||
text.clear();
|
||||
}
|
||||
writeStartTag(DT_tt);
|
||||
writeCharacters(arg.toString());
|
||||
writeEndTag(); // </tt>
|
||||
}
|
||||
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(); // </i>
|
||||
break;
|
||||
case 5: // <@extra>
|
||||
if (!text.isEmpty()) {
|
||||
writeCharacters(text);
|
||||
text.clear();
|
||||
}
|
||||
writeStartTag(DT_tt);
|
||||
writeCharacters(arg.toString());
|
||||
writeEndTag(); // </tt>
|
||||
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)
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
#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);
|
||||
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;
|
||||
|
@ -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.
|
||||
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::resolveTargetHelper(const QString& target,
|
||||
const Node* relative,
|
||||
Tree* t)
|
||||
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;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -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_;
|
||||
|
@ -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<const FunctionNode*>(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<QmlClassNode*>(n);
|
||||
else if (n->subType() == Node::Collision) {
|
||||
NameCollisionNode* ncn;
|
||||
ncn = static_cast<NameCollisionNode*>(n);
|
||||
qcn = static_cast<QmlClassNode*>(ncn->findAny(Node::Document, Node::QmlClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (qcn)
|
||||
return static_cast<const FunctionNode*>(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<Node*>(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<InnerNode*>(start);
|
||||
InnerNode* current = static_cast<InnerNode*>(node);
|
||||
const NodeList& children = current->childNodes();
|
||||
const QString& name = path.at(pathIndex);
|
||||
for (int i=0; i<children.size(); ++i) {
|
||||
@ -714,7 +721,9 @@ const Node* Tree::findNode(const QStringList& path, const Node* start, int findF
|
||||
QML node.
|
||||
*/
|
||||
const Node* n = findNode(path, current, findFlags, false);
|
||||
return (n ? n : findNode(path, current, findFlags, true));
|
||||
if (n)
|
||||
return n;
|
||||
return findNode(path, current, findFlags, true);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -745,7 +754,7 @@ const Node* Tree::findNode(const QStringList& path, const Node* start, int findF
|
||||
class node.
|
||||
*/
|
||||
if (qml && path.size() >= 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<const InnerNode*>(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<const InnerNode*>(node)->findEnumNodeForValue(path.at(i));
|
||||
|
||||
}
|
||||
if (!next && !qml && node->type() == Node::Class && (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));
|
||||
if (!next && (findFlags & SearchEnumValues) && i == path.size() - 1)
|
||||
next = static_cast<const InnerNode*>(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; i<bestTargetList.size(); ++i) {
|
||||
const Node* n = bestTargetList.at(i).node_;
|
||||
if (n && relative->qmlModuleName() == n->qmlModuleName()) {
|
||||
ref = bestTargetList.at(i).ref_;
|
||||
return n;
|
||||
}
|
||||
}
|
||||
#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_;
|
||||
}
|
||||
}
|
||||
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<const DocNode*>(*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
|
||||
|
@ -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_; }
|
||||
|
Loading…
Reference in New Issue
Block a user