summaryrefslogtreecommitdiffstats
path: root/src/tools/qdoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/qdoc')
-rw-r--r--src/tools/qdoc/cppcodeparser.cpp85
-rw-r--r--src/tools/qdoc/cppcodeparser.h2
-rw-r--r--src/tools/qdoc/node.cpp11
-rw-r--r--src/tools/qdoc/node.h16
-rw-r--r--src/tools/qdoc/qdocdatabase.cpp1
-rw-r--r--src/tools/qdoc/tree.cpp26
-rw-r--r--src/tools/qdoc/tree.h1
7 files changed, 118 insertions, 24 deletions
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
+ <is inserted for qdoc to look in to find things.
+
+ If the \c using clause is a base class member function, the
+ member function is added to \a parent as an unresolved
+ \c using clause.
+ */
+bool CppCodeParser::matchUsingDecl(InnerNode* parent)
{
+ bool usingNamespace = false;
readToken(); // skip 'using'
- // 'namespace'
- if (tok != Tok_namespace)
- return false;
-
- readToken();
- // identifier
- if (tok != Tok_Ident)
- return false;
+ if (tok == Tok_namespace) {
+ usingNamespace = true;
+ readToken();
+ }
+ int openLeftAngles = 0;
+ int openLeftParens = 0;
+ bool usingOperator = false;
QString name;
- while (tok == Tok_Ident) {
+ 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 (tok == Tok_Semicolon)
- break;
- else if (tok != Tok_Gulbrandsen)
- return false;
- name += "::";
- readToken();
}
- /*
- So far, so good. We have 'using namespace Foo;'.
- */
- qdb_->insertOpenNamespace(name);
+ if (usingNamespace) {
+ // 'using namespace Foo;'.
+ qdb_->insertOpenNamespace(name);
+ }
+ else if (parent && parent->isClass()) {
+ ClassNode* cn = static_cast<ClassNode*>(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
@@ -1415,6 +1415,17 @@ void ClassNode::addUnresolvedBaseClass(Access access,
}
/*!
+ 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<RelatedClass>& baseClasses() { return bases_; }
QList<RelatedClass>& derivedClasses() { return derived_; }
QList<RelatedClass>& ignoredBaseClasses() { return ignoredBases_; }
+ QList<UsingClause>& usingClauses() { return usingClauses_; }
const QList<RelatedClass> &baseClasses() const { return bases_; }
const QList<RelatedClass> &derivedClasses() const { return derived_; }
const QList<RelatedClass> &ignoredBaseClasses() const { return ignoredBases_; }
+ const QList<UsingClause>& usingClauses() const { return usingClauses_; }
QString serviceName() const { return sname; }
void setServiceName(const QString& value) { sname = value; }
@@ -517,6 +532,7 @@ private:
QList<RelatedClass> bases_;
QList<RelatedClass> derived_;
QList<RelatedClass> ignoredBases_;
+ QList<UsingClause> 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
@@ -499,6 +499,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<ClassNode*>(child);
+ QList<UsingClause>& usingClauses = cn->usingClauses();
+ QList<UsingClause>::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_; }