qdoc: qdoc was confused by namespace and module with same name

When qdoc searched for QtConncurrent::blockingFilter(),
it found the module node for QtConcurrent instead of the
namespace. This was because qdoc wasn't given specific
enough instructions on how to perform the search. Now
it searches for the namespace first, then the C++ class,
then the module.

Task-number: QTBUG-31535
Change-Id: I4f8aec503903508789738f2a77c76f47a3e80a93
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
This commit is contained in:
Martin Smith 2013-06-10 13:54:11 +02:00 committed by The Qt Project
parent 0d7d53fd46
commit 505a10baf7
7 changed files with 86 additions and 44 deletions

View File

@ -207,10 +207,10 @@ void CppCodeParser::parseSourceFile(const Location& location, const QString& fil
readToken();
/*
The set of active namespaces is cleared before parsing
The set of open namespaces is cleared before parsing
each source file. The word "source" here means cpp file.
*/
activeNamespaces_.clear();
qdb_->clearOpenNamespaces();
matchDocsAndStuff();
in.close();
@ -323,21 +323,18 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
doc.startLocation().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_FN));
}
else {
if (!activeNamespaces_.isEmpty()) {
foreach (const QString& usedNamespace_, activeNamespaces_) {
QStringList newPath = usedNamespace_.split("::") + parentPath;
func = qdb_->findFunctionNode(newPath, clone);
if (func)
break;
}
}
// Search the root namespace if no match was found.
if (func == 0)
func = qdb_->findNodeInOpenNamespace(parentPath, clone);
/*
Search the root namespace if no match was found.
*/
if (func == 0) {
func = qdb_->findFunctionNode(parentPath, clone);
}
if (func == 0) {
if (parentPath.isEmpty() && !lastPath_.isEmpty())
if (parentPath.isEmpty() && !lastPath_.isEmpty()) {
func = qdb_->findFunctionNode(lastPath_, clone);
}
if (func == 0) {
doc.location().warning(tr("Cannot find '%1' in '\\%2' %3")
.arg(clone->name() + "(...)")
@ -426,16 +423,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
C++ namespace, search for it first in all the known
C++ namespaces.
*/
if (!activeNamespaces_.isEmpty()) {
foreach (const QString& usedNamespace_, activeNamespaces_) {
QStringList newPath = usedNamespace_.split("::") + path;
node = qdb_->findNodeByNameAndType(newPath, type, subtype);
if (node) {
path = newPath;
break;
}
}
}
node = qdb_->findNodeInOpenNamespace(path, type, subtype);
/*
If the node was not found in a C++ namespace, search
@ -458,7 +446,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
if (path.size() > 1) {
path.pop_back();
QString ns = path.join("::");
activeNamespaces_.insert(ns);
qdb_->insertOpenNamespace(ns);
}
}
return node;
@ -1718,7 +1706,7 @@ bool CppCodeParser::matchUsingDecl()
/*
So far, so good. We have 'using namespace Foo;'.
*/
activeNamespaces_.insert(name);
qdb_->insertOpenNamespace(name);
return true;
}
@ -2125,13 +2113,7 @@ bool CppCodeParser::matchDocsAndStuff()
FunctionNode *func = 0;
if (matchFunctionDecl(0, &parentPath, &clone, QString(), extra)) {
foreach (const QString& usedNamespace_, activeNamespaces_) {
QStringList newPath = usedNamespace_.split("::") + parentPath;
func = qdb_->findFunctionNode(newPath, clone);
if (func) {
break;
}
}
func = qdb_->findNodeInOpenNamespace(parentPath, clone);
if (func == 0)
func = qdb_->findFunctionNode(parentPath, clone);
@ -2256,9 +2238,8 @@ bool CppCodeParser::makeFunctionNode(const QString& signature,
Tokenizer* outerTokenizer = tokenizer;
int outerTok = tok;
Location loc;
QByteArray latin1 = signature.toLatin1();
Tokenizer stringTokenizer(loc, latin1);
Tokenizer stringTokenizer(location(), latin1);
stringTokenizer.setParsingFnOrMacro(true);
tokenizer = &stringTokenizer;
readToken();

View File

@ -166,7 +166,6 @@ protected:
QStringList lastPath_;
QRegExp varComment;
QRegExp sep;
QSet<QString> activeNamespaces_;
private:
QString sequentialIteratorDefinition;

View File

@ -101,10 +101,10 @@ void PureDocParser::parseSourceFile(const Location& location, const QString& fil
readToken();
/*
The set of active namespaces is cleared before parsing
The set of open namespaces is cleared before parsing
each source file. The word "source" here means cpp file.
*/
activeNamespaces_.clear();
qdb_->clearOpenNamespaces();
processQdocComments();
in.close();

View File

@ -1126,4 +1126,56 @@ QString QDocDatabase::refForAtom(const Atom* atom)
return QString();
}
/*!
If there are open namespaces, search for the function node
having the same function name as the \a clone node in each
open namespace. The \a parentPath is a portion of the path
name provided with the function name at the point of
reference. \a parentPath is usually a class name. Return
the pointer to the function node if one is found in an
open namespace. Otherwise return 0.
This open namespace concept is of dubious value and might
be removed.
*/
FunctionNode* QDocDatabase::findNodeInOpenNamespace(const QStringList& parentPath,
const FunctionNode* clone)
{
FunctionNode* fn = 0;
if (!openNamespaces_.isEmpty()) {
foreach (const QString& t, openNamespaces_) {
QStringList path = t.split("::") + parentPath;
fn = findFunctionNode(path, clone);
if (fn)
break;
}
}
return fn;
}
/*!
Find a node of the specified \a type and \a subtype that is
reached with the specified \a path. If such a node is found
in an open namespace, prefix \a path with the name of the
open namespace and "::" and return a pointer to the node.
Othewrwise return 0.
*/
Node* QDocDatabase::findNodeInOpenNamespace(QStringList& path,
Node::Type type,
Node::SubType subtype)
{
Node* n = 0;
if (!openNamespaces_.isEmpty()) {
foreach (const QString& t, openNamespaces_) {
QStringList p = t.split("::") + path;
n = findNodeByNameAndType(p, type, subtype);
if (n) {
path = p;
break;
}
}
}
return n;
}
QT_END_NAMESPACE

View File

@ -196,6 +196,11 @@ class QDocDatabase
Generator* g,
bool generateInternalNodes = false);
void clearOpenNamespaces() { openNamespaces_.clear(); }
void insertOpenNamespace(const QString& path) { openNamespaces_.insert(path); }
FunctionNode* findNodeInOpenNamespace(const QStringList& parentPath, const FunctionNode* clone);
Node* findNodeInOpenNamespace(QStringList& path, Node::Type type, Node::SubType subtype);
/* debugging functions */
void printModules() const;
void printQmlModules() const;
@ -240,6 +245,7 @@ class QDocDatabase
TextToNodeMap legaleseTexts_;
DocNodeMultiMap docNodesByTitle_;
TargetRecMultiMap targetRecMultiMap_;
QSet<QString> openNamespaces_;
};
QT_END_NAMESPACE

View File

@ -367,7 +367,11 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& parentPath,
const Node* relative,
int findFlags) const
{
const Node* parent = findNode(parentPath, relative, findFlags);
const Node* parent = findNamespaceNode(parentPath);
if (parent == 0)
parent = findClassNode(parentPath, 0);
if (parent == 0)
parent = findNode(parentPath, relative, findFlags);
if (parent == 0 || !parent->isInnerNode())
return 0;
return ((InnerNode*)parent)->findFunctionNode(clone);
@ -658,7 +662,7 @@ Node* Tree::findNodeRecursive(const QStringList& path,
Node* start,
Node::Type type,
Node::SubType subtype,
bool acceptCollision)
bool acceptCollision) const
{
if (!start || path.isEmpty())
return 0; // no place to start, or nothing to search for.
@ -736,7 +740,7 @@ EnumNode* Tree::findEnumNode(const QStringList& path, Node* start)
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)
ClassNode* Tree::findClassNode(const QStringList& path, Node* start) const
{
if (!start)
start = const_cast<NamespaceNode*>(root());
@ -748,7 +752,7 @@ ClassNode* Tree::findClassNode(const QStringList& path, Node* start)
the root of the tree. Only a Namespace node named \a path
is acceptible. If one is not found, 0 is returned.
*/
NamespaceNode* Tree::findNamespaceNode(const QStringList& path)
NamespaceNode* Tree::findNamespaceNode(const QStringList& path) const
{
Node* start = const_cast<NamespaceNode*>(root());
return static_cast<NamespaceNode*>(findNodeRecursive(path, 0, start, Node::Namespace, Node::NoSubType));

View File

@ -82,9 +82,9 @@ class Tree
~Tree();
EnumNode* findEnumNode(const QStringList& path, Node* start = 0);
ClassNode* findClassNode(const QStringList& path, Node* start = 0);
ClassNode* findClassNode(const QStringList& path, Node* start = 0) const;
QmlClassNode* findQmlTypeNode(const QStringList& path);
NamespaceNode* findNamespaceNode(const QStringList& path);
NamespaceNode* findNamespaceNode(const QStringList& path) const;
DocNode* findQmlModuleNode(const QStringList& path, Node* start = 0);
Node* findNodeByNameAndType(const QStringList& path,
@ -98,7 +98,7 @@ class Tree
Node* start,
Node::Type type,
Node::SubType subtype,
bool acceptCollision = false);
bool acceptCollision = false) const;
const Node* findNode(const QStringList &path,
const Node* relative = 0,