diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp index 405be6f500..6cb86a7515 100644 --- a/src/tools/qdoc/cppcodeparser.cpp +++ b/src/tools/qdoc/cppcodeparser.cpp @@ -1692,35 +1692,76 @@ bool CppCodeParser::matchNamespaceDecl(InnerNode *parent) return matched && match(Tok_RightBrace); } -bool CppCodeParser::matchUsingDecl() +/*! + Match a C++ \c using clause. Return \c true if the match + is successful. Otherwise false. + + If the \c using clause is for a namespace, an open namespace + insertOpenNamespace(name); + int openLeftAngles = 0; + int openLeftParens = 0; + bool usingOperator = false; + QString name; + while (tok != Tok_Semicolon) { + if ((tok != Tok_Ident) && (tok != Tok_Gulbrandsen)) { + if (tok == Tok_LeftAngle) { + ++openLeftAngles; + } + else if (tok == Tok_RightAngle) { + if (openLeftAngles <= 0) + return false; + --openLeftAngles; + } + else if (tok == Tok_Comma) { + if (openLeftAngles <= 0) + return false; + } + else if (tok == Tok_operator) { + usingOperator = true; + } + else if (tok == Tok_SomeOperator) { + if (!usingOperator) + return false; + } + else if (tok == Tok_LeftParen) { + ++openLeftParens; + } + else if (tok == Tok_RightParen) { + if (openLeftParens <= 0) + return false; + --openLeftParens; + } + else { + return false; + } + } + name += lexeme(); + readToken(); + } + + if (usingNamespace) { + // 'using namespace Foo;'. + qdb_->insertOpenNamespace(name); + } + else if (parent && parent->isClass()) { + ClassNode* cn = static_cast(parent); + cn->addUnresolvedUsingClause(name); + } return true; } @@ -1961,7 +2002,7 @@ bool CppCodeParser::matchDeclList(InnerNode *parent) matchNamespaceDecl(parent); break; case Tok_using: - matchUsingDecl(); + matchUsingDecl(parent); break; case Tok_template: { @@ -2221,7 +2262,7 @@ bool CppCodeParser::matchDocsAndStuff() } } else if (tok == Tok_using) { - matchUsingDecl(); + matchUsingDecl(0); } else { QStringList parentPath; diff --git a/src/tools/qdoc/cppcodeparser.h b/src/tools/qdoc/cppcodeparser.h index dc5c8ca8bd..f9ddcab88c 100644 --- a/src/tools/qdoc/cppcodeparser.h +++ b/src/tools/qdoc/cppcodeparser.h @@ -127,7 +127,7 @@ protected: bool matchClassDecl(InnerNode *parent, const QString &templateStuff = QString()); bool matchNamespaceDecl(InnerNode *parent); - bool matchUsingDecl(); + bool matchUsingDecl(InnerNode* parent); bool matchEnumItem(InnerNode *parent, EnumNode *enume); bool matchEnumDecl(InnerNode *parent); bool matchTypedefDecl(InnerNode *parent); diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index f65b4ec942..e14ca4af3e 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -1414,6 +1414,17 @@ void ClassNode::addUnresolvedBaseClass(Access access, bases_.append(RelatedClass(access, path, signature)); } +/*! + Add an unresolved \c using clause to this class node's list + of \c using clauses. The unresolved \c using clause will be + resolved before the generate phase of qdoc. In an unresolved + \c using clause, the pointer to the function node is 0. + */ +void ClassNode::addUnresolvedUsingClause(const QString& signature) +{ + usingClauses_.append(UsingClause(signature)); +} + /*! */ void ClassNode::fixBaseClasses() diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h index 8e25aac9c1..b6717b3b1b 100644 --- a/src/tools/qdoc/node.h +++ b/src/tools/qdoc/node.h @@ -479,6 +479,18 @@ struct RelatedClass QString signature_; }; +struct UsingClause +{ + UsingClause() { } + UsingClause(const QString& signature) : node_(0), signature_(signature) { } + const QString& signature() const { return signature_; } + const Node* node() { return node_; } + void setNode(const Node* n) { node_ = n; } + + const Node* node_; + QString signature_; +}; + class ClassNode : public InnerNode { public: @@ -493,16 +505,19 @@ public: void addResolvedBaseClass(Access access, ClassNode* node); void addDerivedClass(Access access, ClassNode* node); void addUnresolvedBaseClass(Access access, const QStringList& path, const QString& signature); + void addUnresolvedUsingClause(const QString& signature); void fixBaseClasses(); void fixPropertyUsingBaseClasses(PropertyNode* pn); QList& baseClasses() { return bases_; } QList& derivedClasses() { return derived_; } QList& ignoredBaseClasses() { return ignoredBases_; } + QList& usingClauses() { return usingClauses_; } const QList &baseClasses() const { return bases_; } const QList &derivedClasses() const { return derived_; } const QList &ignoredBaseClasses() const { return ignoredBases_; } + const QList& usingClauses() const { return usingClauses_; } QString serviceName() const { return sname; } void setServiceName(const QString& value) { sname = value; } @@ -517,6 +532,7 @@ private: QList bases_; QList derived_; QList ignoredBases_; + QList usingClauses_; bool abstract_; bool wrapper_; QString sname; diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index 2f7c2eaeb7..75295613f7 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -1331,6 +1331,7 @@ void QDocDatabase::resolveStuff() resolveQmlInheritance(primaryTreeRoot()); //primaryTree()->resolveTargets(primaryTreeRoot()); primaryTree()->resolveCppToQmlLinks(); + primaryTree()->resolveUsingClauses(); } /*! diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp index ed4b4e3979..6393ad4e6f 100644 --- a/src/tools/qdoc/tree.cpp +++ b/src/tools/qdoc/tree.cpp @@ -498,6 +498,29 @@ void Tree::resolveCppToQmlLinks() } } +/*! + For each C++ class node, resolve any \c using clauses + that appeared in the class declaration. + */ +void Tree::resolveUsingClauses() +{ + foreach (Node* child, root_.childNodes()) { + if (child->isClass()) { + ClassNode* cn = static_cast(child); + QList& usingClauses = cn->usingClauses(); + QList::iterator uc = usingClauses.begin(); + while (uc != usingClauses.end()) { + if (!(*uc).node()) { + const Node* n = qdb_->findFunctionNode((*uc).signature(), cn, Node::CPP); + if (n) + (*uc).setNode(n); + } + ++uc; + } + } + } +} + /*! */ void Tree::fixInheritance(NamespaceNode* rootNode) @@ -1427,7 +1450,8 @@ void Tree::insertQmlType(const QString& key, QmlTypeNode* n) const Node* Tree::findFunctionNode(const QString& target, const Node* relative, Node::Genus genus) { QString t = target; - t.chop(2); + if (t.endsWith("()")) + t.chop(2); QStringList path = t.split("::"); const FunctionNode* fn = findFunctionNode(path, relative, SearchBaseClasses, genus); if (fn && fn->metaness() != FunctionNode::MacroWithoutParams) diff --git a/src/tools/qdoc/tree.h b/src/tools/qdoc/tree.h index 2e6f766770..67063ef86a 100644 --- a/src/tools/qdoc/tree.h +++ b/src/tools/qdoc/tree.h @@ -153,6 +153,7 @@ class Tree void resolveInheritanceHelper(int pass, ClassNode* cn); void resolveProperties(); void resolveCppToQmlLinks(); + void resolveUsingClauses(); void fixInheritance(NamespaceNode *rootNode = 0); NamespaceNode *root() { return &root_; }