qdoc: Correct parsing of the using clause
qdoc could only parse the using clause where the 'using' keyword was followed by 'namespace'. Now it can parse using clauses with or without 'namespace'. Change-Id: Ic4aad025c00b3bda2bc1cbd52d0ba8dbbad653e5 Task-number: QTBUG-44553 Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com> Reviewed-by: Topi Reiniö <topi.reinio@digia.com>
This commit is contained in:
parent
cd46d94906
commit
99120ca3cf
@ -1692,35 +1692,76 @@ bool CppCodeParser::matchNamespaceDecl(InnerNode *parent)
|
|||||||
return matched && match(Tok_RightBrace);
|
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'
|
readToken(); // skip 'using'
|
||||||
|
|
||||||
// 'namespace'
|
if (tok == Tok_namespace) {
|
||||||
if (tok != Tok_namespace)
|
usingNamespace = true;
|
||||||
return false;
|
|
||||||
|
|
||||||
readToken();
|
|
||||||
// identifier
|
|
||||||
if (tok != Tok_Ident)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
QString name;
|
|
||||||
while (tok == Tok_Ident) {
|
|
||||||
name += lexeme();
|
|
||||||
readToken();
|
|
||||||
if (tok == Tok_Semicolon)
|
|
||||||
break;
|
|
||||||
else if (tok != Tok_Gulbrandsen)
|
|
||||||
return false;
|
|
||||||
name += "::";
|
|
||||||
readToken();
|
readToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
int openLeftAngles = 0;
|
||||||
So far, so good. We have 'using namespace Foo;'.
|
int openLeftParens = 0;
|
||||||
*/
|
bool usingOperator = false;
|
||||||
qdb_->insertOpenNamespace(name);
|
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<ClassNode*>(parent);
|
||||||
|
cn->addUnresolvedUsingClause(name);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1961,7 +2002,7 @@ bool CppCodeParser::matchDeclList(InnerNode *parent)
|
|||||||
matchNamespaceDecl(parent);
|
matchNamespaceDecl(parent);
|
||||||
break;
|
break;
|
||||||
case Tok_using:
|
case Tok_using:
|
||||||
matchUsingDecl();
|
matchUsingDecl(parent);
|
||||||
break;
|
break;
|
||||||
case Tok_template:
|
case Tok_template:
|
||||||
{
|
{
|
||||||
@ -2221,7 +2262,7 @@ bool CppCodeParser::matchDocsAndStuff()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tok == Tok_using) {
|
else if (tok == Tok_using) {
|
||||||
matchUsingDecl();
|
matchUsingDecl(0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
QStringList parentPath;
|
QStringList parentPath;
|
||||||
|
@ -127,7 +127,7 @@ protected:
|
|||||||
bool matchClassDecl(InnerNode *parent,
|
bool matchClassDecl(InnerNode *parent,
|
||||||
const QString &templateStuff = QString());
|
const QString &templateStuff = QString());
|
||||||
bool matchNamespaceDecl(InnerNode *parent);
|
bool matchNamespaceDecl(InnerNode *parent);
|
||||||
bool matchUsingDecl();
|
bool matchUsingDecl(InnerNode* parent);
|
||||||
bool matchEnumItem(InnerNode *parent, EnumNode *enume);
|
bool matchEnumItem(InnerNode *parent, EnumNode *enume);
|
||||||
bool matchEnumDecl(InnerNode *parent);
|
bool matchEnumDecl(InnerNode *parent);
|
||||||
bool matchTypedefDecl(InnerNode *parent);
|
bool matchTypedefDecl(InnerNode *parent);
|
||||||
|
@ -1414,6 +1414,17 @@ void ClassNode::addUnresolvedBaseClass(Access access,
|
|||||||
bases_.append(RelatedClass(access, path, signature));
|
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()
|
void ClassNode::fixBaseClasses()
|
||||||
|
@ -479,6 +479,18 @@ struct RelatedClass
|
|||||||
QString signature_;
|
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
|
class ClassNode : public InnerNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -493,16 +505,19 @@ public:
|
|||||||
void addResolvedBaseClass(Access access, ClassNode* node);
|
void addResolvedBaseClass(Access access, ClassNode* node);
|
||||||
void addDerivedClass(Access access, ClassNode* node);
|
void addDerivedClass(Access access, ClassNode* node);
|
||||||
void addUnresolvedBaseClass(Access access, const QStringList& path, const QString& signature);
|
void addUnresolvedBaseClass(Access access, const QStringList& path, const QString& signature);
|
||||||
|
void addUnresolvedUsingClause(const QString& signature);
|
||||||
void fixBaseClasses();
|
void fixBaseClasses();
|
||||||
void fixPropertyUsingBaseClasses(PropertyNode* pn);
|
void fixPropertyUsingBaseClasses(PropertyNode* pn);
|
||||||
|
|
||||||
QList<RelatedClass>& baseClasses() { return bases_; }
|
QList<RelatedClass>& baseClasses() { return bases_; }
|
||||||
QList<RelatedClass>& derivedClasses() { return derived_; }
|
QList<RelatedClass>& derivedClasses() { return derived_; }
|
||||||
QList<RelatedClass>& ignoredBaseClasses() { return ignoredBases_; }
|
QList<RelatedClass>& ignoredBaseClasses() { return ignoredBases_; }
|
||||||
|
QList<UsingClause>& usingClauses() { return usingClauses_; }
|
||||||
|
|
||||||
const QList<RelatedClass> &baseClasses() const { return bases_; }
|
const QList<RelatedClass> &baseClasses() const { return bases_; }
|
||||||
const QList<RelatedClass> &derivedClasses() const { return derived_; }
|
const QList<RelatedClass> &derivedClasses() const { return derived_; }
|
||||||
const QList<RelatedClass> &ignoredBaseClasses() const { return ignoredBases_; }
|
const QList<RelatedClass> &ignoredBaseClasses() const { return ignoredBases_; }
|
||||||
|
const QList<UsingClause>& usingClauses() const { return usingClauses_; }
|
||||||
|
|
||||||
QString serviceName() const { return sname; }
|
QString serviceName() const { return sname; }
|
||||||
void setServiceName(const QString& value) { sname = value; }
|
void setServiceName(const QString& value) { sname = value; }
|
||||||
@ -517,6 +532,7 @@ private:
|
|||||||
QList<RelatedClass> bases_;
|
QList<RelatedClass> bases_;
|
||||||
QList<RelatedClass> derived_;
|
QList<RelatedClass> derived_;
|
||||||
QList<RelatedClass> ignoredBases_;
|
QList<RelatedClass> ignoredBases_;
|
||||||
|
QList<UsingClause> usingClauses_;
|
||||||
bool abstract_;
|
bool abstract_;
|
||||||
bool wrapper_;
|
bool wrapper_;
|
||||||
QString sname;
|
QString sname;
|
||||||
|
@ -1331,6 +1331,7 @@ void QDocDatabase::resolveStuff()
|
|||||||
resolveQmlInheritance(primaryTreeRoot());
|
resolveQmlInheritance(primaryTreeRoot());
|
||||||
//primaryTree()->resolveTargets(primaryTreeRoot());
|
//primaryTree()->resolveTargets(primaryTreeRoot());
|
||||||
primaryTree()->resolveCppToQmlLinks();
|
primaryTree()->resolveCppToQmlLinks();
|
||||||
|
primaryTree()->resolveUsingClauses();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -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<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)
|
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)
|
const Node* Tree::findFunctionNode(const QString& target, const Node* relative, Node::Genus genus)
|
||||||
{
|
{
|
||||||
QString t = target;
|
QString t = target;
|
||||||
t.chop(2);
|
if (t.endsWith("()"))
|
||||||
|
t.chop(2);
|
||||||
QStringList path = t.split("::");
|
QStringList path = t.split("::");
|
||||||
const FunctionNode* fn = findFunctionNode(path, relative, SearchBaseClasses, genus);
|
const FunctionNode* fn = findFunctionNode(path, relative, SearchBaseClasses, genus);
|
||||||
if (fn && fn->metaness() != FunctionNode::MacroWithoutParams)
|
if (fn && fn->metaness() != FunctionNode::MacroWithoutParams)
|
||||||
|
@ -153,6 +153,7 @@ class Tree
|
|||||||
void resolveInheritanceHelper(int pass, ClassNode* cn);
|
void resolveInheritanceHelper(int pass, ClassNode* cn);
|
||||||
void resolveProperties();
|
void resolveProperties();
|
||||||
void resolveCppToQmlLinks();
|
void resolveCppToQmlLinks();
|
||||||
|
void resolveUsingClauses();
|
||||||
void fixInheritance(NamespaceNode *rootNode = 0);
|
void fixInheritance(NamespaceNode *rootNode = 0);
|
||||||
NamespaceNode *root() { return &root_; }
|
NamespaceNode *root() { return &root_; }
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user