diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/tools/qdoc/cppcodeparser.cpp | 236 | ||||
| -rw-r--r-- | src/tools/qdoc/cppcodeparser.h | 12 | ||||
| -rw-r--r-- | src/tools/qdoc/tokenizer.cpp | 2 | ||||
| -rw-r--r-- | src/tools/qdoc/tokenizer.h | 1 |
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 ¯oDef); 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(); |
