diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2016-02-19 15:20:39 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2016-02-19 15:26:41 +0000 |
commit | 863a6621d14caf67adcf3f30cb955a268765f0f1 (patch) | |
tree | 259e076b43ea65aec0284e0b2edad95b88f3f764 | |
parent | 1735c0c7e68e754aee16aa24fbcd002b174f547e (diff) |
Revert "qdoc: Remove creation of redundant function & variable nodes"
This reverts commit 18fe6a9a5eb4a1c2ce62cd64b42b6db5e581e152.
Because we are changing the C++ parser to clang, we won't need this
anymore.
Task-number: QTBUG-48191
Change-Id: Iacf134ab91517a0eb3e28ea6bce41f74e3c957a0
Reviewed-by: Martin Smith <martin.smith@theqtcompany.com>
-rw-r--r-- | src/qdoc/cppcodeparser.cpp | 639 | ||||
-rw-r--r-- | src/qdoc/cppcodeparser.h | 32 | ||||
-rw-r--r-- | src/qdoc/generator.cpp | 2 | ||||
-rw-r--r-- | src/qdoc/main.cpp | 6 | ||||
-rw-r--r-- | src/qdoc/node.cpp | 107 | ||||
-rw-r--r-- | src/qdoc/node.h | 166 | ||||
-rw-r--r-- | src/qdoc/qdocdatabase.cpp | 24 | ||||
-rw-r--r-- | src/qdoc/qdocdatabase.h | 6 | ||||
-rw-r--r-- | src/qdoc/qdocindexfiles.cpp | 6 | ||||
-rw-r--r-- | src/qdoc/qdoctagfiles.cpp | 2 | ||||
-rw-r--r-- | src/qdoc/tokenizer.cpp | 9 | ||||
-rw-r--r-- | src/qdoc/tokenizer.h | 4 | ||||
-rw-r--r-- | src/qdoc/tree.cpp | 25 | ||||
-rw-r--r-- | src/qdoc/tree.h | 4 |
14 files changed, 446 insertions, 586 deletions
diff --git a/src/qdoc/cppcodeparser.cpp b/src/qdoc/cppcodeparser.cpp index 98800164f..0405cc2c2 100644 --- a/src/qdoc/cppcodeparser.cpp +++ b/src/qdoc/cppcodeparser.cpp @@ -316,80 +316,88 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, const QString& command, const ArgLocPair& arg) { + ExtraFuncData extra; if (command == COMMAND_FN) { - Declaration declData; - if (!parseDeclaration(arg.first, declData)) { - declData.clear(); - if (!parseDeclaration("void " + arg.first, declData)) { - doc.startLocation().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_FN)); - return 0; - } + QStringList parentPath; + FunctionNode *func = 0; + FunctionNode *clone = 0; + + if (!makeFunctionNode(arg.first, &parentPath, &clone, extra) && + !makeFunctionNode("void " + arg.first, &parentPath, &clone, extra)) { + doc.startLocation().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_FN)); } - FunctionNode* func = qdb_->findFunctionNode(declData.parentPath_, declData); - if (func == 0) { - if (declData.parentPath_.isEmpty() && !lastPath_.isEmpty()) { - func = qdb_->findFunctionNode(lastPath_, declData); + else { + func = qdb_->findFunctionNode(parentPath, clone); + if (func == 0) { + if (parentPath.isEmpty() && !lastPath_.isEmpty()) + func = qdb_->findFunctionNode(lastPath_, clone); } - } - /* - If the node was not found, then search for it in the - open C++ namespaces. We don't expect this search to - be necessary often. Nor do we expect it to succeed - very often. - */ - if (func == 0) - func = qdb_->findNodeInOpenNamespace(declData.parentPath_, declData); - - if (func == 0) { - doc.location().warning(tr("Cannot find '%1' in '\\%2' %3") - .arg(declData.name_ + "(...)") - .arg(COMMAND_FN) - .arg(arg.first), - tr("I cannot find any function of that name with the " - "specified signature. Make sure that the signature " - "is identical to the declaration, including 'const' " - "qualifiers.")); - } - else - lastPath_ = declData.parentPath_; - if (func) { - func->borrowParameterNames(declData); - func->setParentPath(declData.parentPath_); + + /* + If the node was not found, then search for it in the + open C++ namespaces. We don't expect this search to + be necessary often. Nor do we expect it to succeed + very often. + */ + if (func == 0) + func = qdb_->findNodeInOpenNamespace(parentPath, clone); + + if (func == 0) { + doc.location().warning(tr("Cannot find '%1' in '\\%2' %3") + .arg(clone->name() + "(...)") + .arg(COMMAND_FN) + .arg(arg.first), + tr("I cannot find any function of that name with the " + "specified signature. Make sure that the signature " + "is identical to the declaration, including 'const' " + "qualifiers.")); + } + else + lastPath_ = parentPath; + if (func) { + func->borrowParameterNames(clone); + func->setParentPath(clone->parentPath()); + } + delete clone; } return func; } else if (command == COMMAND_MACRO) { - FunctionNode* fn = 0; - Declaration declData(qdb_->primaryTreeRoot(), true); - if (parseDeclaration(arg.first, declData)) { - if (!declData.parentPath_.isEmpty()) { + QStringList parentPath; + FunctionNode *func = 0; + + extra.root = qdb_->primaryTreeRoot(); + extra.isMacro = true; + if (makeFunctionNode(arg.first, &parentPath, &func, extra)) { + if (!parentPath.isEmpty()) { doc.startLocation().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_MACRO)); + delete func; + func = 0; } - else if (declData.isFunction()) { - fn = createFunctionNode(declData); - fn->setMetaness(FunctionNode::MacroWithParams); - QVector<Parameter> params = fn->parameters(); + else { + func->setMetaness(FunctionNode::MacroWithParams); + QVector<Parameter> params = func->parameters(); for (int i = 0; i < params.size(); ++i) { Parameter ¶m = params[i]; if (param.name().isEmpty() && !param.dataType().isEmpty() && param.dataType() != "...") param = Parameter("", "", param.dataType()); } - fn->setParameters(params); + func->setParameters(params); } - return fn; + return func; } else if (QRegExp("[A-Za-z_][A-Za-z0-9_]+").exactMatch(arg.first)) { - fn = new FunctionNode(qdb_->primaryTreeRoot(), arg.first); - fn->setAccess(Node::Public); - fn->setLocation(doc.startLocation()); - fn->setMetaness(FunctionNode::MacroWithoutParams); + func = new FunctionNode(qdb_->primaryTreeRoot(), arg.first); + func->setAccess(Node::Public); + func->setLocation(doc.startLocation()); + func->setMetaness(FunctionNode::MacroWithoutParams); } else { doc.location().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_MACRO)); } - return fn; + return func; } else if (nodeTypeMap.contains(command)) { /* @@ -572,17 +580,12 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, attached = true; else return 0; // never get here. - FunctionNode* fn = 0; - Declaration declData(qmlType, nodeType, attached); - if (parseDeclaration(arg.first, declData)) { - fn = createFunctionNode(declData); - } - else { - Declaration declData(qmlType, nodeType, attached); - if (parseDeclaration("void " + arg.first, declData)) { - fn = createFunctionNode(declData); - } - } + FunctionNode* fn = makeFunctionNode(doc, + arg.first, + qmlType, + nodeType, + attached, + command); if (fn) { fn->setLocation(doc.startLocation()); if ((command == COMMAND_JSSIGNAL) || @@ -591,8 +594,6 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, (command == COMMAND_JSATTACHEDMETHOD)) fn->setGenus(Node::JS); } - else - doc.location().warning(tr("Invalid syntax in '\\%1'").arg(command)); return fn; } } @@ -1046,7 +1047,7 @@ void CppCodeParser::reset() { tokenizer = 0; tok = 0; - access_ = Node::Public; + access = Node::Public; metaness_ = FunctionNode::Plain; lastPath_.clear(); physicalModuleName.clear(); @@ -1384,308 +1385,276 @@ int CppCodeParser::matchFunctionModifier() return -1; } -bool CppCodeParser::matchDeclaration(Declaration& declData) +bool CppCodeParser::matchFunctionDecl(Aggregate *parent, + QStringList *parentPathPtr, + FunctionNode **funcPtr, + const QString &templateStuff, + ExtraFuncData& extra) { + CodeChunk returnType; + QStringList parentPath; + QString name; + + 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: - declData.isFriend_ = true; + matched_friend = true; break; case Tok_inline: - declData.isInline_ = true; + matched_inline = true; break; case Tok_explicit: - declData.isExplicit_ = true; + matched_explicit = true; break; case Tok_static: - declData.isStatic_ = true; + matched_static = true; break; case Tok_QT_DEPRECATED: // no break here. - declData.isQT_DEPRECATED_ = true; + matched_QT_DEPRECATED = true; case Tok_QT_COMPAT: - declData.isCompat_ = true; + matched_compat = true; break; } token = matchFunctionModifier(); } - declData.virtuality_ = FunctionNode::NonVirtual; + FunctionNode::Virtualness virtuality = FunctionNode::NonVirtual; if (match(Tok_virtual)) { - declData.virtuality_ = FunctionNode::NormalVirtual; - if (!declData.isCompat_) - declData.isCompat_ = matchCompat(); + virtuality = FunctionNode::NormalVirtual; + if (!matched_compat) + matched_compat = matchCompat(); } - if (!matchDataType(&declData.returnType_)) { + if (!matchDataType(&returnType)) { if (tokenizer->parsingFnOrMacro() && (match(Tok_Q_DECLARE_FLAGS) || match(Tok_Q_PROPERTY) || match(Tok_Q_PRIVATE_PROPERTY))) - declData.returnType_ = CodeChunk(previousLexeme()); - else + returnType = CodeChunk(previousLexeme()); + else { return false; + } } - if (!declData.isCompat_) - declData.isCompat_ = matchCompat(); + if (returnType.toString() == "QBool") + returnType = CodeChunk("bool"); + + if (!matched_compat) + matched_compat = matchCompat(); if (tok == Tok_operator && - (declData.returnType_.toString().isEmpty() || - declData.returnType_.toString().endsWith("::"))) { + (returnType.toString().isEmpty() || + returnType.toString().endsWith("::"))) { // 'QString::operator const char *()' - declData.parentPath_ = declData.returnType_.toString().split(sep); - declData.parentPath_.removeAll(QString()); - declData.returnType_ = CodeChunk(); + parentPath = returnType.toString().split(sep); + parentPath.removeAll(QString()); + returnType = CodeChunk(); readToken(); CodeChunk restOfName; if (tok != Tok_Tilde && matchDataType(&restOfName)) { - declData.name_ = "operator " + restOfName.toString(); + name = "operator " + restOfName.toString(); } else { - declData.name_ = previousLexeme() + lexeme(); + name = previousLexeme() + lexeme(); readToken(); while (tok != Tok_LeftParen && tok != Tok_Eoi) { - declData.name_ += lexeme(); + name += lexeme(); readToken(); } } - if (tok != Tok_LeftParen) - return false; // This exit is never used. + if (tok != Tok_LeftParen) { + return false; + } } else if (tok == Tok_LeftParen) { // constructor or destructor - declData.parentPath_ = declData.returnType_.toString().split(sep); - if (!declData.parentPath_.isEmpty()) { - declData.name_ = declData.parentPath_.last(); - declData.parentPath_.erase(declData.parentPath_.end() - 1); + parentPath = returnType.toString().split(sep); + if (!parentPath.isEmpty()) { + name = parentPath.last(); + parentPath.erase(parentPath.end() - 1); } - declData.returnType_ = CodeChunk(); + returnType = CodeChunk(); } else { while (match(Tok_Ident)) { - declData.name_ = previousLexeme(); + name = previousLexeme(); /* This is a hack to let QML module identifiers through. */ - matchModuleQualifier(declData.name_); + matchModuleQualifier(name); matchTemplateAngles(); if (match(Tok_Gulbrandsen)) - declData.parentPath_.append(declData.name_); + parentPath.append(name); else break; } + if (tok == Tok_operator) { - declData.name_ = lexeme(); + name = lexeme(); readToken(); while (tok != Tok_Eoi) { - declData.name_ += lexeme(); + name += lexeme(); readToken(); if (tok == Tok_LeftParen) break; } } - if (declData.parent_ && (tok == Tok_Semicolon || - tok == Tok_LeftBracket || - tok == Tok_Colon) - && access_ == Node::Public) { - matchVariableDecl(declData); - return true; - } - if (tok != Tok_LeftParen) { - return false; // mws says these failures should be investigated. + if (parent && (tok == Tok_Semicolon || + tok == Tok_LeftBracket || + tok == Tok_Colon) + && access != Node::Private) { + if (tok == Tok_LeftBracket) { + returnType.appendHotspot(); + + int bracketDepth0 = tokenizer->bracketDepth(); + while ((tokenizer->bracketDepth() >= bracketDepth0 && + tok != Tok_Eoi) || + tok == Tok_RightBracket) { + returnType.append(lexeme()); + readToken(); + } + if (tok != Tok_Semicolon) { + return false; + } + } + else if (tok == Tok_Colon) { + returnType.appendHotspot(); + + while (tok != Tok_Semicolon && tok != Tok_Eoi) { + returnType.append(lexeme()); + readToken(); + } + if (tok != Tok_Semicolon) { + return false; + } + } + + VariableNode *var = new VariableNode(parent, name); + var->setAccess(access); + var->setLocation(location()); + var->setLeftType(returnType.left()); + var->setRightType(returnType.right()); + if (matched_compat) + var->setStatus(Node::Compat); + var->setStatic(matched_static); + return false; } + if (tok != Tok_LeftParen) + return false; } readToken(); - declData.location_ = location(); - declData.access_ = access_; - declData.metaness_ = metaness_; // A left paren was seen. Parse the parameters + bool isQPrivateSignal = false; + QVector<Parameter> pvect; if (tok != Tok_RightParen) { do { - if (!matchParameter(declData.pvect_, declData.isQPrivateSignal_)) - return false; // mws says these failures should be investigated. + if (!matchParameter(pvect, isQPrivateSignal)) + return false; } while (match(Tok_Comma)); } // The parameters must end with a right paren if (!match(Tok_RightParen)) - return false; // mws says these failures should be investigated. - - /* - When the right paren is matched, it might be the end without a semicolon. - e.g., if it is a macro. But there might be more for this declaration... - */ + return false; // look for const - declData.isConst_ = match(Tok_const); - - if (match(Tok_throw)) { - if (match(Tok_LeftParen)) { - while (tok != Tok_RightParen && tok != Tok_Eoi) - readToken(); - if (tok != Tok_RightParen) - return false; - else - readToken(); - } - } - else - match(Tok_noexcept); + bool matchedConst = match(Tok_const); - // look for "= 0" indicating pure virtual + // look for 0 indicating pure virtual if (match(Tok_Equal) && match(Tok_Number)) - declData.virtuality_ = FunctionNode::PureVirtual; + virtuality = FunctionNode::PureVirtual; - // look for ":" indicating ctors which must be skipped + // 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) { - declData.bodyExpected_ = true; + body_expected = true; int nesting = tokenizer->braceDepth(); - if (!match(Tok_LeftBrace)) { - // It is correct for macro calls to return here. - return false; // mws says these failures should be investigated - } + if (!match(Tok_LeftBrace)) + return false; // skip the body while (tokenizer->braceDepth() >= nesting && tok != Tok_Eoi) readToken(); - declData.bodyPresent_ = true; + body_present = true; match(Tok_RightBrace); } + + FunctionNode *func = 0; + bool createFunctionNode = false; if (parsingHeaderFile_) { - if (declData.isFriend_) { - if (declData.isInline_) { + if (matched_friend) { + if (matched_inline) { // nothing yet } - if (declData.bodyPresent_) { - if (declData.bodyExpected_) { + if (body_present) { + if (body_expected) { // nothing yet } - if (declData.parent_ && declData.parent_->parent()) - declData.parent_ = declData.parent_->parent(); + createFunctionNode = true; + if (parent && parent->parent()) + parent = parent->parent(); else - return false; // This exit is never used. + return false; } } + else + createFunctionNode = true; } - declData.result_ = Function; - return true; -} - -/*! - This function creates a variable node from the data in \a declData. - This should be the only place where a variable node is created. - */ -VariableNode* CppCodeParser::createVariableNode(Declaration& declData) -{ - /* - Don't create a variable node if the access mode - is not public. - */ - VariableNode* var = 0; - if (declData.access_ == Node::Public) { - var = new VariableNode(declData.parent_, declData.name_); - var->setAccess(declData.access_); - var->setLocation(location()); - var->setLeftType(declData.returnType_.left()); - var->setRightType(declData.returnType_.right()); - if (declData.isCompat_) - var->setStatus(Node::Compat); - var->setStatic(declData.isStatic_); - } - return var; -} - -/*! - This function creates a function node from the data in \a declData. - This should be the only place where a function node is created. - */ -FunctionNode* CppCodeParser::createFunctionNode(Declaration& declData) -{ - FunctionNode* fn = new FunctionNode(declData.type_, declData.parent_, declData.name_, declData.isAttached_); - if (declData.isFriend_) - declData.access_ = Node::Public; - fn->setAccess(declData.access_); - fn->setLocation(declData.location_); - fn->setReturnType(declData.returnType_.toString()); - fn->setParentPath(declData.parentPath_); - fn->setTemplateStuff(declData.templateStuff_); - if (declData.isCompat_) - fn->setStatus(Node::Compat); - if (declData.isQT_DEPRECATED_) - fn->setStatus(Node::Deprecated); - if (declData.isExplicit_) { /* What can be done? */ } - fn->setMetaness(declData.metaness_); - if (declData.parent_) { - if (declData.name_ == declData.parent_->name()) - fn->setMetaness(FunctionNode::Ctor); - else if (declData.name_.startsWith(QLatin1Char('~'))) - fn->setMetaness(FunctionNode::Dtor); - } - fn->setStatic(declData.isStatic_); - fn->setConst(declData.isConst_); - fn->setVirtualness(declData.virtuality_); - if (declData.isQPrivateSignal_) - fn->setPrivateSignal(); - if (!declData.pvect_.isEmpty()) { - fn->setParameters(declData.pvect_); - } - return fn; -} - -/*! - Variable declarations get parsed by the same function that - parses function declarations, because variable declarations - look like function declarations until the end. As input, it - gets access to the data saved from parsing what it thought - was a function declaration in \a declData. - */ -void CppCodeParser::matchVariableDecl(Declaration& declData) -{ - if (tok == Tok_LeftBracket) { - declData.returnType_.appendHotspot(); - - int bracketDepth0 = tokenizer->bracketDepth(); - while ((tokenizer->bracketDepth() >= bracketDepth0 && - tok != Tok_Eoi) || - tok == Tok_RightBracket) { - declData.returnType_.append(lexeme()); - readToken(); - } - } - else if (tok == Tok_Colon) { - declData.returnType_.appendHotspot(); - - while (tok != Tok_Semicolon && tok != Tok_Eoi) { - declData.returnType_.append(lexeme()); - readToken(); - } - } - if (match(Tok_Equal)) { - int nesting = tokenizer->braceDepth(); - if (match(Tok_LeftBrace)) { - // skip the body - while (tokenizer->braceDepth() >= nesting && tok != Tok_Eoi) - readToken(); - } - while (tok != Tok_Semicolon && tok != Tok_Eoi) { - readToken(); - } - } - declData.access_ = access_; - - if (tok == Tok_Semicolon) - declData.result_ = Variable; else - declData.result_ = Ignore; + createFunctionNode = true; + + if (createFunctionNode) { + func = new FunctionNode(extra.type, parent, name, extra.isAttached); + if (matched_friend) + access = Node::Public; + 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 (isQPrivateSignal) + func->setPrivateSignal(); + if (!pvect.isEmpty()) { + func->setParameters(pvect); + } + } + if (parentPathPtr != 0) + *parentPathPtr = parentPath; + if (funcPtr != 0) + *funcPtr = func; + return true; } bool CppCodeParser::matchBaseSpecifier(ClassNode *classe, bool isClass) @@ -1771,7 +1740,7 @@ bool CppCodeParser::matchClassDecl(Aggregate *parent, This is enough to recognize a class definition. */ ClassNode *classe = new ClassNode(parent, previousLexeme()); - classe->setAccess(access_); + classe->setAccess(access); classe->setLocation(location()); if (compat) classe->setStatus(Node::Compat); @@ -1784,14 +1753,14 @@ bool CppCodeParser::matchClassDecl(Aggregate *parent, if (!match(Tok_LeftBrace)) return false; - Node::Access outerAccess = access_; - access_ = isClass ? Node::Private : Node::Public; + Node::Access outerAccess = access; + access = isClass ? Node::Private : Node::Public; FunctionNode::Metaness outerMetaness = metaness_; metaness_ = FunctionNode::Plain; bool matches = (matchDeclList(classe) && match(Tok_RightBrace) && match(Tok_Semicolon)); - access_ = outerAccess; + access = outerAccess; metaness_ = outerMetaness; return matches; } @@ -1815,7 +1784,7 @@ bool CppCodeParser::matchNamespaceDecl(Aggregate *parent) ns = static_cast<NamespaceNode*>(parent->findChildNode(namespaceName, Node::Namespace)); if (!ns) { ns = new NamespaceNode(parent, namespaceName); - ns->setAccess(access_); + ns->setAccess(access); ns->setLocation(location()); } @@ -1897,7 +1866,7 @@ bool CppCodeParser::matchUsingDecl(Aggregate* parent) return true; } -bool CppCodeParser::matchEnumItem(Aggregate *parent, EnumNode* en) +bool CppCodeParser::matchEnumItem(Aggregate *parent, EnumNode *enume) { if (!match(Tok_Ident)) return false; @@ -1921,14 +1890,14 @@ bool CppCodeParser::matchEnumItem(Aggregate *parent, EnumNode* en) } } - if (en) { + if (enume) { QString strVal = val.toString(); if (strVal.isEmpty()) { - if (en->items().isEmpty()) { + if (enume->items().isEmpty()) { strVal = "0"; } else { - QString last = en->items().last().value(); + QString last = enume->items().last().value(); bool ok; int n = last.toInt(&ok); if (ok) { @@ -1944,11 +1913,11 @@ bool CppCodeParser::matchEnumItem(Aggregate *parent, EnumNode* en) } } - en->addItem(EnumItem(name, strVal)); + enume->addItem(EnumItem(name, strVal)); } else { VariableNode *var = new VariableNode(parent, name); - var->setAccess(access_); + var->setAccess(access); var->setLocation(location()); var->setLeftType("const int"); var->setStatic(true); @@ -1967,21 +1936,21 @@ bool CppCodeParser::matchEnumDecl(Aggregate *parent) if (tok != Tok_LeftBrace) return false; - EnumNode* en = 0; + EnumNode *enume = 0; if (!name.isEmpty()) { - en = new EnumNode(parent, name); - en->setAccess(access_); - en->setLocation(location()); + enume = new EnumNode(parent, name); + enume->setAccess(access); + enume->setLocation(location()); } readToken(); - if (!matchEnumItem(parent, en)) + if (!matchEnumItem(parent, enume)) return false; while (match(Tok_Comma)) { - if (!matchEnumItem(parent, en)) + if (!matchEnumItem(parent, enume)) return false; } return match(Tok_RightBrace) && match(Tok_Semicolon); @@ -2001,7 +1970,7 @@ bool CppCodeParser::matchTypedefDecl(Aggregate *parent) if (parent && !parent->findChildNode(name, Node::Typedef)) { TypedefNode* td = new TypedefNode(parent, name); - td->setAccess(access_); + td->setAccess(access); td->setLocation(location()); } return true; @@ -2122,6 +2091,7 @@ bool CppCodeParser::matchProperty(Aggregate *parent) */ bool CppCodeParser::matchDeclList(Aggregate *parent) { + ExtraFuncData extra; QString templateStuff; int braceDepth0 = tokenizer->braceDepth(); if (tok == Tok_RightBrace) // prevents failure on empty body @@ -2159,23 +2129,23 @@ bool CppCodeParser::matchDeclList(Aggregate *parent) break; case Tok_private: readToken(); - access_ = Node::Private; + access = Node::Private; metaness_ = FunctionNode::Plain; break; case Tok_protected: readToken(); - access_ = Node::Protected; + access = Node::Protected; metaness_ = FunctionNode::Plain; break; case Tok_public: readToken(); - access_ = Node::Public; + access = Node::Public; metaness_ = FunctionNode::Plain; break; case Tok_signals: case Tok_Q_SIGNALS: readToken(); - access_ = Node::Public; + access = Node::Public; metaness_ = FunctionNode::Signal; break; case Tok_slots: @@ -2227,7 +2197,7 @@ bool CppCodeParser::matchDeclList(Aggregate *parent) if (match(Tok_Comma) && match(Tok_Ident)) { QString name = previousLexeme(); TypedefNode *flagsNode = new TypedefNode(parent, flagsType); - flagsNode->setAccess(access_); + flagsNode->setAccess(access); flagsNode->setLocation(location()); EnumNode* en = static_cast<EnumNode*>(parent->findChildNode(name, Node::Enum)); if (en) @@ -2245,19 +2215,7 @@ bool CppCodeParser::matchDeclList(Aggregate *parent) match(Tok_RightParen); break; default: - Declaration declData(parent, templateStuff); - if (matchDeclaration(declData)) { - if (declData.isFunction() && !declData.ignoreThisDecl()) - (void) createFunctionNode(declData); - else if (declData.isVariable()) { - /* - Always create the variable node because - we are parsing a .h file - */ - (void) createVariableNode(declData); - } - } - else { + if (!matchFunctionDecl(parent, 0, 0, templateStuff, extra)) { while (tok != Tok_Eoi && (tokenizer->braceDepth() > braceDepth0 || (!match(Tok_Semicolon) && @@ -2278,6 +2236,7 @@ bool CppCodeParser::matchDeclList(Aggregate *parent) */ bool CppCodeParser::matchDocsAndStuff() { + ExtraFuncData extra; const QSet<QString>& topicCommandsAllowed = topicCommands(); const QSet<QString>& otherMetacommandsAllowed = otherMetaCommands(); const QSet<QString>& metacommandsAllowed = topicCommandsAllowed + otherMetacommandsAllowed; @@ -2305,30 +2264,27 @@ bool CppCodeParser::matchDocsAndStuff() const TopicList& topics = doc.topicsUsed(); if (!topics.isEmpty()) { topic = topics[0].topic; - if (topic.startsWith("qml")) { - if ((topic == COMMAND_QMLPROPERTY) || - (topic == COMMAND_QMLPROPERTYGROUP) || - (topic == COMMAND_QMLATTACHEDPROPERTY)) { - isQmlPropertyTopic = true; - } + if ((topic == COMMAND_QMLPROPERTY) || + (topic == COMMAND_QMLPROPERTYGROUP) || + (topic == COMMAND_QMLATTACHEDPROPERTY)) { + isQmlPropertyTopic = true; } - else if (topic.startsWith("js")) { - if ((topic == COMMAND_JSPROPERTY) || - (topic == COMMAND_JSPROPERTYGROUP) || - (topic == COMMAND_JSATTACHEDPROPERTY)) { - isJsPropertyTopic = true; - } + else if ((topic == COMMAND_JSPROPERTY) || + (topic == COMMAND_JSPROPERTYGROUP) || + (topic == COMMAND_JSATTACHEDPROPERTY)) { + isJsPropertyTopic = true; } } NodeList nodes; DocList docs; if (topic.isEmpty()) { + QStringList parentPath; + FunctionNode *clone; FunctionNode *func = 0; - Declaration declData(qdb_->primaryTreeRoot()); - matchDeclaration(declData); - if (declData.isFunction()) { - func = qdb_->findFunctionNode(declData.parentPath_, declData); + + if (matchFunctionDecl(0, &parentPath, &clone, QString(), extra)) { + func = qdb_->findFunctionNode(parentPath, clone); /* If the node was not found, then search for it in the open C++ namespaces. We don't expect this search to @@ -2336,13 +2292,14 @@ bool CppCodeParser::matchDocsAndStuff() very often. */ if (func == 0) - func = qdb_->findNodeInOpenNamespace(declData.parentPath_, declData); + func = qdb_->findNodeInOpenNamespace(parentPath, clone); if (func) { - func->borrowParameterNames(declData); + func->borrowParameterNames(clone); nodes.append(func); docs.append(doc); } + delete clone; } else { doc.location().warning(tr("Cannot tie this documentation to anything"), @@ -2413,9 +2370,11 @@ bool CppCodeParser::matchDocsAndStuff() matchUsingDecl(0); } else { - Declaration declData(qdb_->primaryTreeRoot()); - matchDeclaration(declData); - if (declData.isFunction()) { + QStringList parentPath; + FunctionNode *clone; + FunctionNode *node = 0; + + if (matchFunctionDecl(0, &parentPath, &clone, QString(), extra)) { /* The location of the definition is more interesting than that of the declaration. People equipped with @@ -2425,9 +2384,10 @@ bool CppCodeParser::matchDocsAndStuff() Signals are implemented in uninteresting files generated by moc. */ - FunctionNode* node = qdb_->findFunctionNode(declData.parentPath_, declData); - if (node && node->metaness() != FunctionNode::Signal) - node->setLocation(declData.location_); + node = qdb_->findFunctionNode(parentPath, clone); + if (node != 0 && node->metaness() != FunctionNode::Signal) + node->setLocation(clone->location()); + delete clone; } else { if (tok != Tok_Doc) @@ -2444,7 +2404,10 @@ bool CppCodeParser::matchDocsAndStuff() If a match is found, \a funcPtr is set to point to the matching node and true is returned. */ -bool CppCodeParser::parseDeclaration(const QString& signature, Declaration& declData) +bool CppCodeParser::makeFunctionNode(const QString& signature, + QStringList* parentPathPtr, + FunctionNode** funcPtr, + ExtraFuncData& extra) { Tokenizer* outerTokenizer = tokenizer; int outerTok = tok; @@ -2455,9 +2418,11 @@ bool CppCodeParser::parseDeclaration(const QString& signature, Declaration& decl tokenizer = &stringTokenizer; readToken(); - inMacroCommand_ = declData.isMacro_; - bool ok = matchDeclaration(declData); + inMacroCommand_ = extra.isMacro; + bool ok = matchFunctionDecl(extra.root, parentPathPtr, funcPtr, QString(), extra); inMacroCommand_ = false; + // potential memory leak with funcPtr + tokenizer = outerTokenizer; tok = outerTok; return ok; @@ -2491,6 +2456,34 @@ bool CppCodeParser::parseParameters(const QString& parameters, return true; } +/*! + Create a new FunctionNode for a QML method or signal, as + specified by \a type, as a child of \a parent. \a sig is + the complete signature, and if \a attached is true, the + method or signal is "attached". \a qdoctag is the text of + the \a type. + + \a parent is the QML class node. The QML module and QML + type names have already been consumed to find \a parent. + What remains in \a sig is the method signature. The method + must be a child of \a parent. + */ +FunctionNode* CppCodeParser::makeFunctionNode(const Doc& doc, + const QString& sig, + Aggregate* parent, + Node::NodeType type, + bool attached, + QString qdoctag) +{ + QStringList pp; + FunctionNode* fn = 0; + ExtraFuncData extra(parent, type, attached); + if (!makeFunctionNode(sig, &pp, &fn, extra) && !makeFunctionNode("void " + sig, &pp, &fn, extra)) { + doc.location().warning(tr("Invalid syntax in '\\%1'").arg(qdoctag)); + } + return fn; +} + void CppCodeParser::parseQiteratorDotH(const Location &location, const QString &filePath) { QFile file(filePath); diff --git a/src/qdoc/cppcodeparser.h b/src/qdoc/cppcodeparser.h index cc0b0f2fe..ec0448232 100644 --- a/src/qdoc/cppcodeparser.h +++ b/src/qdoc/cppcodeparser.h @@ -51,6 +51,16 @@ class CppCodeParser : public CodeParser { Q_DECLARE_TR_FUNCTIONS(QDoc::CppCodeParser) + struct ExtraFuncData { + Aggregate* root; // Used as the parent. + Node::NodeType type; // The node type: Function, etc. + bool isAttached; // If true, the method is attached. + bool isMacro; // If true, we are parsing a macro signature. + ExtraFuncData() : root(0), type(Node::Function), isAttached(false), isMacro(false) { } + ExtraFuncData(Aggregate* r, Node::NodeType t, bool a) + : root(r), type(t), isAttached(a), isMacro(false) { } + }; + public: CppCodeParser(); ~CppCodeParser(); @@ -109,7 +119,11 @@ protected: bool matchTemplateHeader(); bool matchDataType(CodeChunk *type, QString *var = 0); bool matchParameter(QVector<Parameter>& pvect, bool& isQPrivateSignal); - bool matchDeclaration(Declaration& declData); + bool matchFunctionDecl(Aggregate *parent, + QStringList *parentPathPtr, + FunctionNode **funcPtr, + const QString &templateStuff, + ExtraFuncData& extra); bool matchBaseSpecifier(ClassNode *classe, bool isClass); bool matchBaseList(ClassNode *classe, bool isClass); bool matchClassDecl(Aggregate *parent, @@ -122,22 +136,28 @@ protected: bool matchProperty(Aggregate *parent); bool matchDeclList(Aggregate *parent); bool matchDocsAndStuff(); - bool parseDeclaration(const QString &synopsis, Declaration& declData); + bool makeFunctionNode(const QString &synopsis, + QStringList *parentPathPtr, + FunctionNode **funcPtr, + ExtraFuncData& params); + FunctionNode* makeFunctionNode(const Doc& doc, + const QString& sig, + Aggregate* parent, + Node::NodeType type, + bool attached, + QString qdoctag); void parseQiteratorDotH(const Location &location, const QString &filePath); void instantiateIteratorMacro(const QString &container, const QString &includeFile, const QString ¯oDef); void createExampleFileNodes(DocumentNode *dn); - FunctionNode* createFunctionNode(Declaration& declData); - VariableNode* createVariableNode(Declaration& declData); int matchFunctionModifier(); - void matchVariableDecl(Declaration& declData); protected: QMap<QString, Node::NodeType> nodeTypeMap; Tokenizer *tokenizer; int tok; - Node::Access access_; + Node::Access access; FunctionNode::Metaness metaness_; QString physicalModuleName; QStringList lastPath_; diff --git a/src/qdoc/generator.cpp b/src/qdoc/generator.cpp index b4c2b513a..81ad2a94b 100644 --- a/src/qdoc/generator.cpp +++ b/src/qdoc/generator.cpp @@ -753,7 +753,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) } if (node->doc().isEmpty()) { if (!node->isWrapper() && !quiet && !node->isReimplemented()) { // ### might be unnecessary - node->location().warning(tr("No documentation for '%1'").arg(node->plainSignature())); + node->location().warning(tr("No documentation for '%1'").arg(node->plainFullName())); } } else { diff --git a/src/qdoc/main.cpp b/src/qdoc/main.cpp index 4c4354773..8ebebda79 100644 --- a/src/qdoc/main.cpp +++ b/src/qdoc/main.cpp @@ -788,13 +788,13 @@ int main(int argc, char **argv) translators.clear(); #endif QmlTypeNode::terminate(); - //#define DEBUG_SHUTDOWN_CRASH + #ifdef DEBUG_SHUTDOWN_CRASH - Generator::startDebugging("main(): Delete qdoc database"); + qDebug() << "main(): Delete qdoc database"; #endif QDocDatabase::destroyQdocDB(); #ifdef DEBUG_SHUTDOWN_CRASH - Generator::stopDebugging("main(): qdoc database deleted"); + qDebug() << "main(): qdoc database deleted"; #endif return EXIT_SUCCESS; diff --git a/src/qdoc/node.cpp b/src/qdoc/node.cpp index de8c2815f..9740f984f 100644 --- a/src/qdoc/node.cpp +++ b/src/qdoc/node.cpp @@ -165,29 +165,6 @@ QString Node::plainFullName(const Node* relative) const } /*! - Constructs and returns the node's fully qualified signature - by recursively ascending the parent links and prepending each - parent name + "::" to the plain signature. The return type is - not included. - */ -QString Node::plainSignature() const -{ - if (name_.isEmpty()) - return QLatin1String("global"); - - QString fullName; - const Node* node = this; - while (node) { - fullName.prepend(node->signature(false, true)); - if (node->parent()->name().isEmpty()) - break; - fullName.prepend(QLatin1String("::")); - node = node->parent(); - } - return fullName; -} - -/*! Constructs and returns this node's full name. */ QString Node::fullName(const Node* relative) const @@ -861,7 +838,7 @@ Node* Aggregate::findChildNode(const QString& name, NodeType type) } /*! - Find a function node that is a child of this node, such + Find a function node that is a child of this nose, such that the function node has the specified \a name. */ FunctionNode *Aggregate::findFunctionNode(const QString& name, const QString& params) const @@ -930,58 +907,21 @@ FunctionNode *Aggregate::findFunctionNode(const QString& name, const QString& pa /*! Find the function node that is a child of this node, such that the function has the same name and signature as the - function described in \a f1. + \a clone node. */ -FunctionNode *Aggregate::findFunctionNode(const Declaration& f1) const +FunctionNode *Aggregate::findFunctionNode(const FunctionNode *clone) const { - QMap<QString,Node*>::ConstIterator c = primaryFunctionMap_.constFind(f1.name_); + QMap<QString,Node*>::ConstIterator c = primaryFunctionMap_.constFind(clone->name()); if (c != primaryFunctionMap_.constEnd()) { - FunctionNode* f2 = (FunctionNode*) *c; - if (f1.isConst_ == f2->isConst()) { - if (isSameSignature(f1.pvect_, f2)) { - return f2; - } + if (isSameSignature(clone, (FunctionNode *) *c)) { + return (FunctionNode *) *c; } - if (secondaryFunctionMap_.contains(f1.name_)) { - const NodeList& secs = secondaryFunctionMap_[f1.name_]; + else if (secondaryFunctionMap_.contains(clone->name())) { + const NodeList& secs = secondaryFunctionMap_[clone->name()]; NodeList::ConstIterator s = secs.constBegin(); while (s != secs.constEnd()) { - f2 = (FunctionNode*) *s; - if (f1.isConst_ == f2->isConst()) { - if (isSameSignature(f1.pvect_, f2)) - return f2; - } - ++s; - } - } - } - return 0; -} - -/*! - Find the function node that is a child of this node, such - that the function has the same name and signature as the - function node \a f1. - */ -FunctionNode *Aggregate::findFunctionNode(const FunctionNode* f1) const -{ - QMap<QString,Node*>::ConstIterator c = primaryFunctionMap_.constFind(f1->name()); - if (c != primaryFunctionMap_.constEnd()) { - FunctionNode* f2 = (FunctionNode*) *c; - if (f1->isConst() == f2->isConst()) { - if (isSameSignature(f1->parameters(), f2)) { - return f2; - } - } - if (secondaryFunctionMap_.contains(f1->name())) { - const NodeList& secs = secondaryFunctionMap_[f1->name()]; - NodeList::ConstIterator s = secs.constBegin(); - while (s != secs.constEnd()) { - f2 = (FunctionNode*) *s; - if (f1->isConst() == f2->isConst()) { - if (isSameSignature(f1->parameters(), f2)) - return f2; - } + if (isSameSignature(clone, (FunctionNode *) *s)) + return (FunctionNode *) *s; ++s; } } @@ -1225,19 +1165,18 @@ void Aggregate::setIncludes(const QStringList& includes) } /*! - Compare the function signature contained parameter vector - \a pv1 with the signature of the function node \a f2, and - return \c true if they are the same. + f1 is always the clone */ -bool Aggregate::isSameSignature(const QVector<Parameter>& pv1, const FunctionNode* f2) +bool Aggregate::isSameSignature(const FunctionNode *f1, const FunctionNode *f2) { - const QVector<Parameter>& pv2 = f2->parameters(); - if (pv1.size() != pv2.size()) + if (f1->parameters().size() != f2->parameters().size()) + return false; + if (f1->isConst() != f2->isConst()) return false; - QVector<Parameter>::ConstIterator p1 = pv1.constBegin(); - QVector<Parameter>::ConstIterator p2 = pv2.constBegin(); - while (p2 != pv2.constEnd()) { + QVector<Parameter>::ConstIterator p1 = f1->parameters().constBegin(); + QVector<Parameter>::ConstIterator p2 = f2->parameters().constBegin(); + while (p2 != f2->parameters().constEnd()) { if ((*p1).hasType() && (*p2).hasType()) { if ((*p1).rightType() != (*p2).rightType()) return false; @@ -2090,11 +2029,11 @@ void FunctionNode::addParameter(const Parameter& parameter) /*! */ -void FunctionNode::borrowParameterNames(const Declaration& declData) +void FunctionNode::borrowParameterNames(const FunctionNode *source) { QVector<Parameter>::Iterator t = parameters_.begin(); - QVector<Parameter>::ConstIterator s = declData.pvect_.constBegin(); - while (s != declData.pvect_.constEnd() && t != parameters_.end()) { + QVector<Parameter>::ConstIterator s = source->parameters_.constBegin(); + while (s != source->parameters_.constEnd() && t != parameters_.end()) { if (!(*s).name().isEmpty()) (*t).setName((*s).name()); ++s; @@ -2194,10 +2133,10 @@ QStringList FunctionNode::reconstructParameters(bool values) const is true, the default values of the parameters are included, if present. */ -QString FunctionNode::signature(bool values, bool noReturnType) const +QString FunctionNode::signature(bool values) const { QString s; - if (!noReturnType && !returnType().isEmpty()) + if (!returnType().isEmpty()) s = returnType() + QLatin1Char(' '); s += name() + QLatin1Char('('); QStringList reconstructedParameters = reconstructParameters(values); diff --git a/src/qdoc/node.h b/src/qdoc/node.h index cc2c784fa..945bc2187 100644 --- a/src/qdoc/node.h +++ b/src/qdoc/node.h @@ -53,7 +53,6 @@ class ExampleNode; class TypedefNode; class QmlTypeNode; class QDocDatabase; -class Declaration; class FunctionNode; class PropertyNode; class CollectionNode; @@ -160,9 +159,7 @@ public: QString plainName() const; QString plainFullName(const Node* relative = 0) const; - QString plainSignature() const; QString fullName(const Node* relative=0) const; - virtual QString signature(bool , bool ) const { return plainName(); } const QString& fileNameBase() const { return fileNameBase_; } bool hasFileNameBase() const { return !fileNameBase_.isEmpty(); } @@ -373,37 +370,6 @@ private: }; Q_DECLARE_TYPEINFO(Node::DocSubtype, Q_PRIMITIVE_TYPE); -class Parameter -{ -public: - Parameter() {} - Parameter(const QString& dataType, - const QString& rightType = QString(), - const QString& name = QString(), - const QString& defaultValue = QString()); - Parameter(const Parameter& p); - - Parameter& operator=(const Parameter& p); - - void setName(const QString& name) { name_ = name; } - - bool hasType() const { return dataType_.length() + rightType_.length() > 0; } - const QString& dataType() const { return dataType_; } - const QString& rightType() const { return rightType_; } - const QString& name() const { return name_; } - const QString& defaultValue() const { return defaultValue_; } - - QString reconstruct(bool value = false) const; - - public: - QString dataType_; - QString rightType_; // mws says remove this 04/08/2015 - QString name_; - QString defaultValue_; -}; -//friend class QTypeInfo<Parameter>; -//Q_DECLARE_TYPEINFO(Parameter, Q_MOVABLE_TYPE); - class Aggregate : public Node { public: @@ -413,8 +379,7 @@ public: Node* findChildNode(const QString& name, NodeType type); virtual void findChildren(const QString& name, NodeList& nodes) const Q_DECL_OVERRIDE; FunctionNode* findFunctionNode(const QString& name, const QString& params) const; - FunctionNode* findFunctionNode(const Declaration& declData) const; - FunctionNode* findFunctionNode(const FunctionNode* f1) const; + FunctionNode* findFunctionNode(const FunctionNode* clone) const; void addInclude(const QString &include); void setIncludes(const QStringList &includes); void normalizeOverloads(); @@ -456,7 +421,7 @@ protected: private: friend class Node; - static bool isSameSignature(const QVector<Parameter>& pv1, const FunctionNode* f2); + static bool isSameSignature(const FunctionNode* f1, const FunctionNode* f2); void removeRelated(Node* pseudoChild); void addRelated(Node* pseudoChild); @@ -853,6 +818,38 @@ inline void EnumNode::setFlagsType(TypedefNode* t) t->setAssociatedEnum(this); } +class Parameter +{ +public: + Parameter() {} + Parameter(const QString& dataType, + const QString& rightType = QString(), + const QString& name = QString(), + const QString& defaultValue = QString()); + Parameter(const Parameter& p); + + Parameter& operator=(const Parameter& p); + + void setName(const QString& name) { name_ = name; } + + bool hasType() const { return dataType_.length() + rightType_.length() > 0; } + const QString& dataType() const { return dataType_; } + const QString& rightType() const { return rightType_; } + const QString& name() const { return name_; } + const QString& defaultValue() const { return defaultValue_; } + + QString reconstruct(bool value = false) const; + + public: + QString dataType_; + QString rightType_; // mws says remove this 04/08/2015 + QString name_; + QString defaultValue_; +}; + +//friend class QTypeInfo<Parameter>; +//Q_DECLARE_TYPEINFO(Parameter, Q_MOVABLE_TYPE); + class FunctionNode : public LeafNode { public: @@ -883,7 +880,7 @@ public: void setReimplemented(bool b); void addParameter(const Parameter& parameter); inline void setParameters(const QVector<Parameter>& parameters); - void borrowParameterNames(const Declaration& declData); + void borrowParameterNames(const FunctionNode* source); void setReimplementedFrom(FunctionNode* from); const QString& returnType() const { return returnType_; } @@ -929,7 +926,7 @@ public: bool hasActiveAssociatedProperty() const; QStringList reconstructParameters(bool values = false) const; - virtual QString signature(bool values, bool noReturnType = false) const; + QString signature(bool values = false) const; virtual QString element() const Q_DECL_OVERRIDE { return parent()->name(); } virtual bool isAttached() const Q_DECL_OVERRIDE { return attached_; } virtual bool isQtQuickNode() const Q_DECL_OVERRIDE { return parent()->isQtQuickNode(); } @@ -971,97 +968,6 @@ private: QList<FunctionNode*> reimplementedBy_; }; -enum ParseResult { Ignore, SyntaxError, Function, Variable }; - -class Declaration -{ - public: - Declaration() - : result_(Ignore), parent_(0), type_(Node::Function), access_(Node::Public), - metaness_(FunctionNode::Plain), bodyExpected_(false), bodyPresent_(false), - isAttached_(false), isMacro_(false), isQPrivateSignal_(false), isQT_DEPRECATED_(false), - isFriend_(false), isStatic_(false), isInline_(false), isExplicit_(false), isCompat_(false), - isConst_(false), virtuality_(FunctionNode::NonVirtual) { } - - Declaration(Aggregate* p) - : result_(Ignore), parent_(p), type_(Node::Function), access_(Node::Public), - metaness_(FunctionNode::Plain), bodyExpected_(false), bodyPresent_(false), - isAttached_(false), isMacro_(false), isQPrivateSignal_(false), isQT_DEPRECATED_(false), - isFriend_(false), isStatic_(false), isInline_(false), isExplicit_(false), isCompat_(false), - isConst_(false), virtuality_(FunctionNode::NonVirtual) { } - - Declaration(Aggregate* p, Node::NodeType t, bool isAttached) - : result_(Ignore), parent_(p), type_(t), access_(Node::Public), - metaness_(FunctionNode::Plain), bodyExpected_(false), bodyPresent_(false), - isAttached_(isAttached), isMacro_(false), isQPrivateSignal_(false), isQT_DEPRECATED_(false), - isFriend_(false), isStatic_(false), isInline_(false), isExplicit_(false), isCompat_(false), - isConst_(false), virtuality_(FunctionNode::NonVirtual) { } - - Declaration(Aggregate* p, const QString& t) - : result_(Ignore), parent_(p), templateStuff_(t), type_(Node::Function), access_(Node::Public), - metaness_(FunctionNode::Plain), bodyExpected_(false), bodyPresent_(false), - isAttached_(false), isMacro_(false), isQPrivateSignal_(false), isQT_DEPRECATED_(false), - isFriend_(false), isStatic_(false), isInline_(false), isExplicit_(false), isCompat_(false), - isConst_(false), virtuality_(FunctionNode::NonVirtual) { } - - Declaration(Aggregate* p, bool isMacro) - : result_(Ignore), parent_(p), type_(Node::Function), access_(Node::Public), - metaness_(FunctionNode::Plain), bodyExpected_(false), bodyPresent_(false), - isAttached_(false), isMacro_(isMacro), isQPrivateSignal_(false), isQT_DEPRECATED_(false), - isFriend_(false), isStatic_(false), isInline_(false), isExplicit_(false), isCompat_(false), - isConst_(false), virtuality_(FunctionNode::NonVirtual) { } - - void clear() { - parent_ = 0; - type_ = Node::Function; - access_ = Node::Public; - metaness_ = FunctionNode::Plain; - bodyExpected_ = false; - bodyPresent_ = false; - isAttached_ = false; - isMacro_ = false; - isQPrivateSignal_ = false; - isQT_DEPRECATED_ = false; - isFriend_ = false; - isStatic_ = false; - isInline_ = false; - isExplicit_ = false; - isCompat_ = false; - isConst_ = false; - virtuality_ = FunctionNode::NonVirtual; - } - - bool ignoreThisDecl() const { return (isFriend_ && !bodyPresent_); } - bool isFunction() const { return (result_ == Function); } - bool isVariable() const { return (result_ == Variable); } - - public: - ParseResult result_; - Aggregate* parent_; - QStringList parentPath_; - QString name_; - QString templateStuff_; - Node::NodeType type_; - Node::Access access_; - FunctionNode::Metaness metaness_; - bool bodyExpected_; - bool bodyPresent_; - bool isAttached_; - bool isMacro_; - bool isQPrivateSignal_; - bool isQT_DEPRECATED_; - bool isFriend_; - bool isStatic_; - bool isInline_; - bool isExplicit_; - bool isCompat_; - bool isConst_; - FunctionNode::Virtualness virtuality_; - CodeChunk returnType_; - Location location_; - QVector<Parameter> pvect_; -}; - class PropertyNode : public LeafNode { public: diff --git a/src/qdoc/qdocdatabase.cpp b/src/qdoc/qdocdatabase.cpp index 795da4484..e3331a4f0 100644 --- a/src/qdoc/qdocdatabase.cpp +++ b/src/qdoc/qdocdatabase.cpp @@ -68,9 +68,8 @@ bool QDocDatabase::debug = false; */ QDocForest::~QDocForest() { - for (int i=0; i<searchOrder_.size(); ++i) { + for (int i=0; i<searchOrder_.size(); ++i) delete searchOrder_.at(i); - } forest_.clear(); searchOrder_.clear(); indexSearchOrder_.clear(); @@ -1387,7 +1386,16 @@ void QDocDatabase::resolveNamespaces() } } } - +#if 0 +/*! + */ +const Node* QDocDatabase::findFunctionNode(const QString& target, + const Node* relative, + Node::Genus genus) +{ + return forest_.findFunctionNode(target, relative, genus); +} +#endif /*! This function is called for autolinking to a \a type, which could be a function return type or a parameter @@ -1527,9 +1535,9 @@ void QDocDatabase::generateIndex(const QString& fileName, } /*! - If there are open namespaces, search each one for a function - node having the same function name as the function described - in \a declData. The \a parentPath is a portion of the path + If there are open namespaces, search for the function node + having the same function name as the \a clone node in each + open namespace. The \a parentPath is a portion of the path name provided with the function name at the point of reference. \a parentPath is usually a class name. Return the pointer to the function node if one is found in an @@ -1539,13 +1547,13 @@ void QDocDatabase::generateIndex(const QString& fileName, be removed. */ FunctionNode* QDocDatabase::findNodeInOpenNamespace(const QStringList& parentPath, - const Declaration& declData) + const FunctionNode* clone) { FunctionNode* fn = 0; if (!openNamespaces_.isEmpty()) { foreach (const QString& t, openNamespaces_) { QStringList path = t.split("::") + parentPath; - fn = findFunctionNode(path, declData); + fn = findFunctionNode(path, clone); if (fn) break; } diff --git a/src/qdoc/qdocdatabase.h b/src/qdoc/qdocdatabase.h index 941c7b61b..d51f9476d 100644 --- a/src/qdoc/qdocdatabase.h +++ b/src/qdoc/qdocdatabase.h @@ -302,10 +302,10 @@ class QDocDatabase /******************************************************************* The functions declared below are called for the current tree only. ********************************************************************/ - FunctionNode* findFunctionNode(const QStringList& parentPath, const Declaration& declData) { - return primaryTree()->findFunctionNode(parentPath, declData); + FunctionNode* findFunctionNode(const QStringList& parentPath, const FunctionNode* clone) { + return primaryTree()->findFunctionNode(parentPath, clone); } - FunctionNode* findNodeInOpenNamespace(const QStringList& parentPath, const Declaration& declData); + FunctionNode* findNodeInOpenNamespace(const QStringList& parentPath, const FunctionNode* clone); Node* findNodeInOpenNamespace(QStringList& path, Node::NodeType type); const Node* checkForCollision(const QString& name) { return primaryTree()->checkForCollision(name); diff --git a/src/qdoc/qdocindexfiles.cpp b/src/qdoc/qdocindexfiles.cpp index 25bfa259e..b3bf064fa 100644 --- a/src/qdoc/qdocindexfiles.cpp +++ b/src/qdoc/qdocindexfiles.cpp @@ -1267,7 +1267,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, Note: The "signature" attribute is written to the index file, but it is not read back in. Is that ok? */ - QString signature = functionNode->signature(false); + QString signature = functionNode->signature(); if (functionNode->isConst()) signature += " const"; writer.writeAttribute("signature", signature); @@ -1483,9 +1483,9 @@ bool compareNodes(const Node* n1, const Node* n2) else if (f1->isConst() > f2->isConst()) return false; - if (f1->signature(false) < f2->signature(false)) + if (f1->signature() < f2->signature()) return true; - else if (f1->signature(false) > f2->signature(false)) + else if (f1->signature() > f2->signature()) return false; } diff --git a/src/qdoc/qdoctagfiles.cpp b/src/qdoc/qdoctagfiles.cpp index 26f5342c1..1210ac7c3 100644 --- a/src/qdoc/qdoctagfiles.cpp +++ b/src/qdoc/qdoctagfiles.cpp @@ -287,7 +287,7 @@ void QDocTagFiles::generateTagFileMembers(QXmlStreamWriter& writer, const Aggreg QStringList pieces = gen_->fullDocumentLocation(node, false).split(QLatin1Char('#')); writer.writeTextElement("anchorfile", pieces[0]); writer.writeTextElement("anchor", pieces[1]); - QString signature = functionNode->signature(false); + QString signature = functionNode->signature(); signature = signature.mid(signature.indexOf(QChar('('))).trimmed(); if (functionNode->isConst()) signature += " const"; diff --git a/src/qdoc/tokenizer.cpp b/src/qdoc/tokenizer.cpp index b2cd906e6..987fff548 100644 --- a/src/qdoc/tokenizer.cpp +++ b/src/qdoc/tokenizer.cpp @@ -55,11 +55,10 @@ QT_BEGIN_NAMESPACE */ static const char *kwords[] = { "char", "class", "const", "double", "enum", "explicit", - "friend", "inline", "int", "long", "namespace", "noexcept", - "operator", "private", "protected", "public", "short", - "signals", "signed", "slots", "static", "struct", "template", - "throw", "typedef", "typename", "union", "unsigned", "using", - "virtual", "void", "volatile", + "friend", "inline", "int", "long", "namespace", "operator", + "private", "protected", "public", "short", "signals", "signed", + "slots", "static", "struct", "template", "typedef", "typename", + "union", "unsigned", "using", "virtual", "void", "volatile", "__int64", "Q_OBJECT", "Q_OVERRIDE", diff --git a/src/qdoc/tokenizer.h b/src/qdoc/tokenizer.h index 456be7335..41a3ffd93 100644 --- a/src/qdoc/tokenizer.h +++ b/src/qdoc/tokenizer.h @@ -62,9 +62,9 @@ enum { Tok_Eoi, Tok_Ampersand, Tok_Aster, Tok_Caret, Tok_LeftParen, Tok_Number, Tok_String, Tok_Doc, Tok_Comment, Tok_Ident, Tok_At, Tok_char, Tok_class, Tok_const, Tok_double, Tok_enum, Tok_explicit, Tok_friend, Tok_inline, Tok_int, Tok_long, - Tok_namespace, Tok_noexcept, Tok_operator, Tok_private, Tok_protected, + Tok_namespace, Tok_operator, Tok_private, Tok_protected, Tok_public, Tok_short, Tok_signals, Tok_signed, Tok_slots, - Tok_static, Tok_struct, Tok_template, Tok_throw, Tok_typedef, + Tok_static, Tok_struct, Tok_template, Tok_typedef, Tok_typename, Tok_union, Tok_unsigned, Tok_using, Tok_virtual, Tok_void, Tok_volatile, Tok_int64, Tok_Q_OBJECT, Tok_Q_OVERRIDE, Tok_Q_PROPERTY, Tok_Q_PRIVATE_PROPERTY, Tok_Q_DECLARE_SEQUENTIAL_ITERATOR, diff --git a/src/qdoc/tree.cpp b/src/qdoc/tree.cpp index 10b46f712..f8f88e6b9 100644 --- a/src/qdoc/tree.cpp +++ b/src/qdoc/tree.cpp @@ -102,8 +102,6 @@ Tree::Tree(const QString& camelCaseModuleName, QDocDatabase* qdb) */ Tree::~Tree() { - if (Generator::debugging()) - qDebug() << " Deleting tree:" << physicalModuleName_; TargetMap::iterator i = nodesByTargetRef_.begin(); while (i != nodesByTargetRef_.end()) { delete i.value(); @@ -123,8 +121,6 @@ Tree::~Tree() ++i; } } - if (Generator::debugging()) - qDebug() << " Deleted tree:" << physicalModuleName_; } /* API members */ @@ -168,18 +164,17 @@ NamespaceNode* Tree::findNamespaceNode(const QStringList& path) const } /*! - This function first ignores the \a declData parameter and - searches for the parent node with \a parentPath. If that - search is successful, it searches for a child node of the - parent that matches the function described in \a declData. - If it finds a match, it returns a pointer to the matching - node. + This function first ignores the \a clone node and searches + for the parent node with \a parentPath. If that search is + successful, it searches for a child node of the parent that + matches the \a clone node. If it finds a node that is just + like the \a clone, it returns a pointer to the found node. Apparently the search order is important here. Don't change it unless you know what you are doing, or you will introduce qdoc warnings. */ -FunctionNode* Tree::findFunctionNode(const QStringList& parentPath, const Declaration& declData) +FunctionNode* Tree::findFunctionNode(const QStringList& parentPath, const FunctionNode* clone) { const Node* parent = findNamespaceNode(parentPath); if (parent == 0) @@ -188,7 +183,7 @@ FunctionNode* Tree::findFunctionNode(const QStringList& parentPath, const Declar parent = findNode(parentPath, 0, 0, Node::DontCare); if (parent == 0 || !parent->isAggregate()) return 0; - return ((const Aggregate*)parent)->findFunctionNode(declData); + return ((const Aggregate*)parent)->findFunctionNode(clone); } @@ -556,15 +551,15 @@ void Tree::fixInheritance(NamespaceNode* rootNode) /*! */ -FunctionNode* Tree::findVirtualFunctionInBaseClasses(ClassNode* cn, FunctionNode* virtualFunc) +FunctionNode* Tree::findVirtualFunctionInBaseClasses(ClassNode* cn, FunctionNode* clone) { const QList<RelatedClass>& rc = cn->baseClasses(); QList<RelatedClass>::ConstIterator r = rc.constBegin(); while (r != rc.constEnd()) { FunctionNode* func; if ((*r).node_) { - if (((func = findVirtualFunctionInBaseClasses((*r).node_, virtualFunc)) != 0 || - (func = (*r).node_->findFunctionNode(virtualFunc)) != 0)) { + if (((func = findVirtualFunctionInBaseClasses((*r).node_, clone)) != 0 || + (func = (*r).node_->findFunctionNode(clone)) != 0)) { if (func->virtualness() != FunctionNode::NonVirtual) return func; } diff --git a/src/qdoc/tree.h b/src/qdoc/tree.h index 649400e78..0558d693c 100644 --- a/src/qdoc/tree.h +++ b/src/qdoc/tree.h @@ -106,7 +106,7 @@ class Tree Node* findNodeForInclude(const QStringList& path) const; ClassNode* findClassNode(const QStringList& path, const Node* start = 0) const; NamespaceNode* findNamespaceNode(const QStringList& path) const; - FunctionNode* findFunctionNode(const QStringList& parentPath, const Declaration& declData); + FunctionNode* findFunctionNode(const QStringList& parentPath, const FunctionNode* clone); const Node* findFunctionNode(const QString& target, const QString& params, const Node* relative, @@ -173,7 +173,7 @@ class Tree const NamespaceNode *root() const { return &root_; } FunctionNode *findVirtualFunctionInBaseClasses(ClassNode *classe, - FunctionNode *virtualFunc); + FunctionNode *clone); NodeList allBaseClasses(const ClassNode *classe) const; QString refForAtom(const Atom* atom); |