summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tools/qdoc/cppcodeparser.cpp236
-rw-r--r--src/tools/qdoc/cppcodeparser.h12
-rw-r--r--src/tools/qdoc/tokenizer.cpp2
-rw-r--r--src/tools/qdoc/tokenizer.h1
4 files changed, 177 insertions, 74 deletions
diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp
index ab79f8f3206..1b18892e93b 100644
--- a/src/tools/qdoc/cppcodeparser.cpp
+++ b/src/tools/qdoc/cppcodeparser.cpp
@@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE
/* qmake ignore Q_OBJECT */
static bool inMacroCommand_ = false;
+static bool parsingHeaderFile_ = false;
QStringList CppCodeParser::exampleFiles;
QStringList CppCodeParser::exampleDirs;
@@ -166,7 +167,9 @@ void CppCodeParser::parseHeaderFile(const Location& location, const QString& fil
Tokenizer fileTokenizer(fileLocation, in);
tokenizer = &fileTokenizer;
readToken();
+ parsingHeaderFile_ = true;
matchDeclList(qdb_->primaryTreeRoot());
+ parsingHeaderFile_ = false;
if (!fileTokenizer.version().isEmpty())
qdb_->setVersion(fileTokenizer.version());
in.close();
@@ -1076,8 +1079,7 @@ bool CppCodeParser::match(int target)
readToken();
return true;
}
- else
- return false;
+ return false;
}
/*!
@@ -1216,8 +1218,9 @@ bool CppCodeParser::matchDataType(CodeChunk *dataType, QString *var)
dataType->append(previousLexeme());
}
else if (match(Tok_void) || match(Tok_int) || match(Tok_char) ||
- match(Tok_double) || match(Tok_Ellipsis))
+ match(Tok_double) || match(Tok_Ellipsis)) {
dataType->append(previousLexeme());
+ }
else {
return false;
}
@@ -1303,36 +1306,71 @@ bool CppCodeParser::matchDataType(CodeChunk *dataType, QString *var)
return true;
}
-bool CppCodeParser::matchParameter(FunctionNode *func)
+/*!
+ Parse the next function parameter, if there is one, and
+ append it to parameter list \a p. Return true if a parameter
+ is parsed and appended to \a p. Otherwise return false.
+ */
+bool CppCodeParser::matchParameter(ParsedParameterList& pplist)
{
- CodeChunk dataType;
- QString name;
- CodeChunk defaultValue;
-
+ ParsedParameter pp;
if (match(Tok_QPrivateSignal)) {
- func->setPrivateSignal();
+ pp.qPrivateSignal_ = true;
+ pplist.append(pp);
return true;
}
- if (!matchDataType(&dataType, &name)) {
+ CodeChunk chunk;
+ if (!matchDataType(&chunk, &pp.name_)) {
return false;
}
+ pp.dataType_ = chunk.toString();
+ chunk.clear();
match(Tok_Comment);
if (match(Tok_Equal)) {
- int parenDepth0 = tokenizer->parenDepth();
-
- while (tokenizer->parenDepth() >= parenDepth0 &&
- (tok != Tok_Comma ||
- tokenizer->parenDepth() > parenDepth0) &&
+ int pdepth = tokenizer->parenDepth();
+ while (tokenizer->parenDepth() >= pdepth &&
+ (tok != Tok_Comma || (tokenizer->parenDepth() > pdepth)) &&
tok != Tok_Eoi) {
- defaultValue.append(lexeme());
+ chunk.append(lexeme());
readToken();
}
}
- func->addParameter(Parameter(dataType.toString(), "", name, defaultValue.toString())); // ###
+ pp.defaultValue_ = chunk.toString();
+ pplist.append(pp);
return true;
}
+/*!
+ If the current token is any of several function modifiers,
+ return that token value after reading the next token. If it
+ is not one of the function modieifer tokens, return -1 but
+ don\t read the next token.
+ */
+int CppCodeParser::matchFunctionModifier()
+{
+ switch (tok) {
+ case Tok_friend:
+ case Tok_inline:
+ case Tok_explicit:
+ case Tok_static:
+ case Tok_QT_DEPRECATED:
+ readToken();
+ return tok;
+ case Tok_QT_COMPAT:
+ case Tok_QT_COMPAT_CONSTRUCTOR:
+ case Tok_QT_MOC_COMPAT:
+ case Tok_QT3_SUPPORT:
+ case Tok_QT3_SUPPORT_CONSTRUCTOR:
+ case Tok_QT3_MOC_SUPPORT:
+ readToken();
+ return Tok_QT_COMPAT;
+ default:
+ break;
+ }
+ return -1;
+}
+
bool CppCodeParser::matchFunctionDecl(Aggregate *parent,
QStringList *parentPathPtr,
FunctionNode **funcPtr,
@@ -1342,25 +1380,44 @@ bool CppCodeParser::matchFunctionDecl(Aggregate *parent,
CodeChunk returnType;
QStringList parentPath;
QString name;
- bool compat = false;
- if (match(Tok_friend)) {
- return false;
- }
- match(Tok_explicit);
- if (matchCompat())
- compat = true;
- bool sta = false;
- if (match(Tok_static)) {
- sta = true;
- if (matchCompat())
- compat = true;
+ bool matched_QT_DEPRECATED = false;
+ bool matched_friend = false;
+ bool matched_static = false;
+ bool matched_inline = false;
+ bool matched_explicit = false;
+ bool matched_compat = false;
+
+ int token = tok;
+ while (token != -1) {
+ switch (token) {
+ case Tok_friend:
+ matched_friend = true;
+ break;
+ case Tok_inline:
+ matched_inline = true;
+ break;
+ case Tok_explicit:
+ matched_explicit = true;
+ break;
+ case Tok_static:
+ matched_static = true;
+ break;
+ case Tok_QT_DEPRECATED:
+ // no break here.
+ matched_QT_DEPRECATED = true;
+ case Tok_QT_COMPAT:
+ matched_compat = true;
+ break;
+ }
+ token = matchFunctionModifier();
}
- FunctionNode::Virtualness vir = FunctionNode::NonVirtual;
+
+ FunctionNode::Virtualness virtuality = FunctionNode::NonVirtual;
if (match(Tok_virtual)) {
- vir = FunctionNode::NormalVirtual;
- if (matchCompat())
- compat = true;
+ virtuality = FunctionNode::NormalVirtual;
+ if (!matched_compat)
+ matched_compat = matchCompat();
}
if (!matchDataType(&returnType)) {
@@ -1377,8 +1434,8 @@ bool CppCodeParser::matchFunctionDecl(Aggregate *parent,
if (returnType.toString() == "QBool")
returnType = CodeChunk("bool");
- if (matchCompat())
- compat = true;
+ if (!matched_compat)
+ matched_compat = matchCompat();
if (tok == Tok_operator &&
(returnType.toString().isEmpty() ||
@@ -1417,12 +1474,10 @@ bool CppCodeParser::matchFunctionDecl(Aggregate *parent,
else {
while (match(Tok_Ident)) {
name = previousLexeme();
-
/*
This is a hack to let QML module identifiers through.
*/
matchModuleQualifier(name);
-
matchTemplateAngles();
if (match(Tok_Gulbrandsen))
@@ -1476,68 +1531,105 @@ bool CppCodeParser::matchFunctionDecl(Aggregate *parent,
var->setLocation(location());
var->setLeftType(returnType.left());
var->setRightType(returnType.right());
- if (compat)
+ if (matched_compat)
var->setStatus(Node::Compat);
- var->setStatic(sta);
+ var->setStatic(matched_static);
return false;
}
- if (tok != Tok_LeftParen) {
+ if (tok != Tok_LeftParen)
return false;
- }
}
readToken();
- FunctionNode *func = new FunctionNode(extra.type, parent, name, extra.isAttached);
- func->setAccess(access);
- func->setLocation(location());
- func->setReturnType(returnType.toString());
- func->setParentPath(parentPath);
- func->setTemplateStuff(templateStuff);
- if (compat)
- func->setStatus(Node::Compat);
-
- func->setMetaness(metaness_);
- if (parent) {
- if (name == parent->name()) {
- func->setMetaness(FunctionNode::Ctor);
- } else if (name.startsWith(QLatin1Char('~'))) {
- func->setMetaness(FunctionNode::Dtor);
- }
- }
- func->setStatic(sta);
-
+ // A left paren was seen. Parse the parameters
+ ParsedParameterList pplist;
if (tok != Tok_RightParen) {
do {
- if (!matchParameter(func)) {
+ if (!matchParameter(pplist))
return false;
- }
} while (match(Tok_Comma));
}
- if (!match(Tok_RightParen)) {
+ // The parameters must end with a right paren
+ if (!match(Tok_RightParen))
return false;
- }
- func->setConst(match(Tok_const));
+ // look for const
+ bool matchedConst = match(Tok_const);
+ // look for 0 indicating pure virtual
if (match(Tok_Equal) && match(Tok_Number))
- vir = FunctionNode::PureVirtual;
- func->setVirtualness(vir);
+ virtuality = FunctionNode::PureVirtual;
+ // look for colon indicating ctors which must be skipped
if (match(Tok_Colon)) {
while (tok != Tok_LeftBrace && tok != Tok_Eoi)
readToken();
}
+ // If no ';' expect a body, which must be skipped.
+ bool body_expected = false;
+ bool body_present = false;
if (!match(Tok_Semicolon) && tok != Tok_Eoi) {
- int braceDepth0 = tokenizer->braceDepth();
-
- if (!match(Tok_LeftBrace)) {
+ body_expected = true;
+ int nesting = tokenizer->braceDepth();
+ if (!match(Tok_LeftBrace))
return false;
- }
- while (tokenizer->braceDepth() >= braceDepth0 && tok != Tok_Eoi)
+ // skip the body
+ while (tokenizer->braceDepth() >= nesting && tok != Tok_Eoi)
readToken();
+ body_present = true;
match(Tok_RightBrace);
}
+
+ FunctionNode *func = 0;
+ bool createFunctionNode = false;
+ if (parsingHeaderFile_) {
+ if (matched_friend) {
+ if (body_present) {
+ createFunctionNode = true;
+ if (parent && parent->parent())
+ parent = parent->parent();
+ else
+ return false;
+ }
+ }
+ else
+ createFunctionNode = true;
+ }
+ else
+ createFunctionNode = true;
+
+ if (createFunctionNode) {
+ func = new FunctionNode(extra.type, parent, name, extra.isAttached);
+ func->setAccess(access);
+ func->setLocation(location());
+ func->setReturnType(returnType.toString());
+ func->setParentPath(parentPath);
+ func->setTemplateStuff(templateStuff);
+ if (matched_compat)
+ func->setStatus(Node::Compat);
+ if (matched_QT_DEPRECATED)
+ func->setStatus(Node::Deprecated);
+ if (matched_explicit) { /* What can be done? */ }
+ func->setMetaness(metaness_);
+ if (parent) {
+ if (name == parent->name())
+ func->setMetaness(FunctionNode::Ctor);
+ else if (name.startsWith(QLatin1Char('~')))
+ func->setMetaness(FunctionNode::Dtor);
+ }
+ func->setStatic(matched_static);
+ func->setConst(matchedConst);
+ func->setVirtualness(virtuality);
+ if (!pplist.isEmpty()) {
+ foreach (const ParsedParameter& pp, pplist) {
+ if (pp.qPrivateSignal_)
+ func->setPrivateSignal();
+ else
+ func->addParameter(Parameter(pp.dataType_, "", pp.name_, pp.defaultValue_));
+ }
+ }
+ }
if (parentPathPtr != 0)
*parentPathPtr = parentPath;
if (funcPtr != 0)
diff --git a/src/tools/qdoc/cppcodeparser.h b/src/tools/qdoc/cppcodeparser.h
index 31964699a20..4fb428fc725 100644
--- a/src/tools/qdoc/cppcodeparser.h
+++ b/src/tools/qdoc/cppcodeparser.h
@@ -51,6 +51,15 @@ class CppCodeParser : public CodeParser
{
Q_DECLARE_TR_FUNCTIONS(QDoc::CppCodeParser)
+ struct ParsedParameter {
+ bool qPrivateSignal_;
+ QString dataType_;
+ QString name_;
+ QString defaultValue_;
+ ParsedParameter() : qPrivateSignal_(false) { }
+ };
+ typedef QList<ParsedParameter> ParsedParameterList;
+
struct ExtraFuncData {
Aggregate* root; // Used as the parent.
Node::NodeType type; // The node type: Function, etc.
@@ -116,7 +125,7 @@ protected:
bool matchTemplateAngles(CodeChunk *type = 0);
bool matchTemplateHeader();
bool matchDataType(CodeChunk *type, QString *var = 0);
- bool matchParameter(FunctionNode *func);
+ bool matchParameter(ParsedParameterList& pplist);
bool matchFunctionDecl(Aggregate *parent,
QStringList *parentPathPtr,
FunctionNode **funcPtr,
@@ -149,6 +158,7 @@ protected:
const QString &includeFile,
const QString &macroDef);
void createExampleFileNodes(DocumentNode *dn);
+ int matchFunctionModifier();
protected:
QMap<QString, Node::NodeType> nodeTypeMap;
diff --git a/src/tools/qdoc/tokenizer.cpp b/src/tools/qdoc/tokenizer.cpp
index 68c6fb7831a..a85c3b00d83 100644
--- a/src/tools/qdoc/tokenizer.cpp
+++ b/src/tools/qdoc/tokenizer.cpp
@@ -186,7 +186,7 @@ int Tokenizer::getToken()
}
else if (strcmp(yyLex, kwords[i - 1]) == 0) {
int ret = (int) Tok_FirstKeyword + i - 1;
- if (ret != Tok_explicit && ret != Tok_inline && ret != Tok_typename)
+ if (ret != Tok_typename)
return ret;
break;
}
diff --git a/src/tools/qdoc/tokenizer.h b/src/tools/qdoc/tokenizer.h
index 2b79320567d..41a3ffd9313 100644
--- a/src/tools/qdoc/tokenizer.h
+++ b/src/tools/qdoc/tokenizer.h
@@ -107,6 +107,7 @@ public:
int braceDepth() const { return yyBraceDepth; }
int parenDepth() const { return yyParenDepth; }
int bracketDepth() const { return yyBracketDepth; }
+ Location& tokenLocation() { return yyTokLoc; }
static void initialize(const Config &config);
static void terminate();