diff options
Diffstat (limited to 'src/qdoc/cppcodeparser.cpp')
-rw-r--r-- | src/qdoc/cppcodeparser.cpp | 622 |
1 files changed, 2 insertions, 620 deletions
diff --git a/src/qdoc/cppcodeparser.cpp b/src/qdoc/cppcodeparser.cpp index 07d0f8d4a..47cb455eb 100644 --- a/src/qdoc/cppcodeparser.cpp +++ b/src/qdoc/cppcodeparser.cpp @@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE /* qmake ignore Q_OBJECT */ static bool inMacroCommand_ = false; -static bool parsingHeaderFile_ = false; QStringList CppCodeParser::exampleFiles; QStringList CppCodeParser::exampleDirs; QSet<QString> CppCodeParser::excludeDirs; @@ -201,63 +200,6 @@ const QSet<QString>& CppCodeParser::topicCommands() } /*! - - */ -Node* CppCodeParser::processFnCommand(const ArgLocPair& arg, const Doc& doc) -{ - ExtraFuncData extra; - 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)); - } - 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(parentPath, clone); - if (func) { - lastPath_ = parentPath; - } else if (isWorthWarningAbout(doc)) { - if (clone && clone->isSpecialMemberFunction()) { - ClassNode* cn = qdb_->findClassNode(parentPath); - if (cn) { - cn->addChild(clone); - clone->setImplicit(true); - return clone; - } - } - 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.")); - } - if (func) { - func->borrowParameterNames(clone); - func->setParentPath(clone->parentPath()); - } - delete clone; - } - return func; -} - -/*! Process the topic \a command found in the \a doc with argument \a arg. */ Node* CppCodeParser::processTopicCommand(const Doc& doc, @@ -266,44 +208,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, { ExtraFuncData extra; if (command == COMMAND_FN) { - return processFnCommand(arg, doc); - } - else if (command == COMMAND_MACRO) { - 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 { - 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()); - } - func->setParameters(params); - } - return func; - } - else if (QRegExp("[A-Za-z_][A-Za-z0-9_]+").exactMatch(arg.first)) { - 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 func; + Q_UNREACHABLE(); } else if (nodeTypeMap.contains(command)) { /* @@ -465,50 +370,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, (command == COMMAND_JSMETHOD) || (command == COMMAND_JSATTACHEDSIGNAL) || (command == COMMAND_JSATTACHEDMETHOD)) { - QString module; - QString name; - QString type; - if (splitQmlMethodArg(arg.first, type, module, name, doc.location())) { - Aggregate* aggregate = qdb_->findQmlType(module, name); - if (!aggregate) - aggregate = qdb_->findQmlBasicType(module, name); - if (aggregate) { - bool attached = false; - Node::NodeType nodeType = Node::QmlMethod; - if ((command == COMMAND_QMLSIGNAL) || - (command == COMMAND_JSSIGNAL)) - nodeType = Node::QmlSignal; - else if ((command == COMMAND_QMLATTACHEDSIGNAL) || - (command == COMMAND_JSATTACHEDSIGNAL)) { - nodeType = Node::QmlSignal; - attached = true; - } - else if ((command == COMMAND_QMLMETHOD) || - (command == COMMAND_JSMETHOD)) { - // do nothing - } - else if ((command == COMMAND_QMLATTACHEDMETHOD) || - (command == COMMAND_JSATTACHEDMETHOD)) - attached = true; - else - return 0; // never get here. - FunctionNode* fn = makeFunctionNode(doc, - arg.first, - aggregate, - nodeType, - attached, - command); - if (fn) { - fn->setLocation(doc.startLocation()); - if ((command == COMMAND_JSSIGNAL) || - (command == COMMAND_JSMETHOD) || - (command == COMMAND_JSATTACHEDSIGNAL) || - (command == COMMAND_JSATTACHEDMETHOD)) - fn->setGenus(Node::JS); - } - return fn; - } - } + Q_UNREACHABLE(); } return 0; } @@ -596,57 +458,6 @@ bool CppCodeParser::splitQmlPropertyArg(const QString& arg, } /*! - A QML signal or method argument has the form... - - <type> <QML-type>::<name>(<param>, <param>, ...) - <type> <QML-module>::<QML-type>::<name>(<param>, <param>, ...) - - This function splits the \a{arg}ument into one of those - two forms, sets \a type, \a module, and \a qmlTypeName, - and returns true. If the argument doesn't match either - form, an error message is emitted and false is returned. - - \note The two QML types \e{Component} and \e{QtObject} never - have a module qualifier. - */ -bool CppCodeParser::splitQmlMethodArg(const QString& arg, - QString& type, - QString& module, - QString& qmlTypeName, - const Location& location) -{ - QString name; - int leftParen = arg.indexOf(QChar('(')); - if (leftParen > 0) - name = arg.left(leftParen); - else - name = arg; - int firstBlank = name.indexOf(QChar(' ')); - if (firstBlank > 0) { - type = name.left(firstBlank); - name = name.right(name.length() - firstBlank - 1); - } - else - type.clear(); - - QStringList colonSplit(name.split("::")); - if (colonSplit.size() > 1) { - if (colonSplit.size() > 2) { - module = colonSplit[0]; - qmlTypeName = colonSplit[1]; - } - else { - module.clear(); - qmlTypeName = colonSplit[0]; - } - return true; - } - QString msg = "Unrecognizable QML module/component qualifier for " + arg; - location.warning(tr(msg.toLatin1().data())); - return false; -} - -/*! Process the topic \a command group found in the \a doc with arguments \a args. Currently, this function is called only for \e{qmlproperty} @@ -1309,376 +1120,6 @@ bool CppCodeParser::matchParameter(QVector<Parameter>& pvect, bool& isQPrivateSi } /*! - 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, - 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: - 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: - matched_QT_DEPRECATED = true; - Q_FALLTHROUGH(); // no break here. - case Tok_QT_COMPAT: - matched_compat = true; - break; - } - token = matchFunctionModifier(); - } - - FunctionNode::Virtualness virtuality = FunctionNode::NonVirtual; - if (match(Tok_virtual)) { - virtuality = FunctionNode::NormalVirtual; - if (!matched_compat) - matched_compat = matchCompat(); - } - - if (!matchDataType(&returnType)) { - if (tokenizer->parsingFnOrMacro() - && (match(Tok_Q_DECLARE_FLAGS) || - match(Tok_Q_PROPERTY) || - match(Tok_Q_PRIVATE_PROPERTY))) - returnType = CodeChunk(previousLexeme()); - else { - return false; - } - } - - if (returnType.toString() == "QBool") - returnType = CodeChunk("bool"); - - if (!matched_compat) - matched_compat = matchCompat(); - - if (tok == Tok_operator && - (returnType.toString().isEmpty() || - returnType.toString().endsWith("::"))) { - // 'QString::operator const char *()' - parentPath = returnType.toString().split(sep); - parentPath.removeAll(QString()); - returnType = CodeChunk(); - readToken(); - - CodeChunk restOfName; - if (tok != Tok_Tilde && matchDataType(&restOfName)) { - name = "operator " + restOfName.toString(); - } - else { - name = previousLexeme() + lexeme(); - readToken(); - while (tok != Tok_LeftParen && tok != Tok_Eoi) { - name += lexeme(); - readToken(); - } - } - if (tok != Tok_LeftParen) { - return false; - } - } - else if (tok == Tok_LeftParen) { - // constructor or destructor - parentPath = returnType.toString().split(sep); - if (!parentPath.isEmpty()) { - name = parentPath.last(); - parentPath.erase(parentPath.end() - 1); - } - returnType = CodeChunk(); - } - else { - while (match(Tok_Ident)) { - name = previousLexeme(); - /* - This is a hack to let QML module identifiers through. - */ - matchModuleQualifier(name); - matchTemplateAngles(); - - if (match(Tok_Gulbrandsen)) - parentPath.append(name); - else - break; - } - - if (tok == Tok_operator) { - name = lexeme(); - readToken(); - while (tok != Tok_Eoi) { - name += lexeme(); - readToken(); - if (tok == Tok_LeftParen) - break; - } - } - if (parent && (tok == Tok_Semicolon || - tok == Tok_LeftBracket || - tok == Tok_Colon || tok == Tok_Equal) - && 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 || tok == Tok_Equal) { - 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); - if (parsingHeaderFile_) - var->setLocation(declLoc()); - else - 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(); - - // A left paren was seen. Parse the parameters - bool isQPrivateSignal = false; - QVector<Parameter> pvect; - if (tok != Tok_RightParen) { - do { - if (!matchParameter(pvect, isQPrivateSignal)) - return false; - } while (match(Tok_Comma)); - } - // The parameters must end with a right paren - if (!match(Tok_RightParen)) - return false; - - // look for const - bool matchedConst = match(Tok_const); - bool matchedRef = match(Tok_Ampersand); - bool matchedRefRef = false; - if (match(Tok_Ampersand)) { - matchedRef = false; - matchedRefRef = true; - } - bool matchFinal = match(Tok_final); - bool matchOverride = match(Tok_override); - - bool isDeleted = false; - bool isDefaulted = false; - if (match(Tok_Equal)) { - if (match(Tok_Number)) // look for 0 indicating pure virtual - virtuality = FunctionNode::PureVirtual; - else if (match(Tok_delete)) - isDeleted = true; - else if (match(Tok_default)) - isDefaulted = true; - } - // 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) { - body_expected = true; - int nesting = tokenizer->braceDepth(); - if (!match(Tok_LeftBrace)) - return false; - // 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 (matched_inline) { - // nothing yet - } - if (body_present) { - if (body_expected) { - // nothing yet - } - 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); - if (matched_friend) - access = Node::Public; - func->setAccess(access); - if (parsingHeaderFile_) - func->setLocation(declLoc()); - else - 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? */ } - if (!pvect.isEmpty()) { - func->setParameters(pvect); - } - func->setMetaness(metaness_); - if ((parent && (name == parent->name())) || - (!parentPath.isEmpty() && name == parentPath.at(parentPath.size()-1))) { - FunctionNode::Metaness m = FunctionNode::Ctor; - if (!pvect.isEmpty()) { - for (int i=0; i<pvect.size(); i++) { - const Parameter& p = pvect.at(i); - if (p.dataType().contains(name)) { - if (p.dataType().endsWith(QLatin1String("&&"))) { - m = FunctionNode::MCtor; - break; - } - if (p.dataType().endsWith(QLatin1String("&"))) { - m = FunctionNode::CCtor; - break; - } - } - } - } - func->setMetaness(m); - } - else if (name.startsWith(QLatin1Char('~'))) - func->setMetaness(FunctionNode::Dtor); - else if (name == QLatin1String("operator=")) { - FunctionNode::Metaness m = FunctionNode::Plain; - if (pvect.size() == 1) { - if (parent) { - if (pvect.at(0).dataType().contains(parent->name())) { - if (pvect.at(0).dataType().endsWith(QLatin1String("&&"))) { - m = FunctionNode::MAssign; - } - else if (pvect.at(0).dataType().endsWith(QLatin1String("&"))) { - m = FunctionNode::CAssign; - } - } - } - else if (!parentPath.isEmpty()) { - if (pvect.at(0).dataType().contains(parentPath.at(parentPath.size()-1))) { - if (pvect.at(0).dataType().endsWith(QLatin1String("&&"))) { - m = FunctionNode::MAssign; - } - else if (pvect.at(0).dataType().endsWith(QLatin1String("&"))) { - m = FunctionNode::CAssign; - } - } - } - } - func->setMetaness(m); - } - func->setStatic(matched_static); - func->setConst(matchedConst); - func->setVirtualness(virtuality); - func->setIsDeleted(isDeleted); - func->setIsDefaulted(isDefaulted); - func->setFinal(matchFinal); - func->setOverride(matchOverride); - if (isQPrivateSignal) - func->setPrivateSignal(); - func->setRef(matchedRef); - func->setRefRef(matchedRefRef); - } - if (parentPathPtr != 0) - *parentPathPtr = parentPath; - if (funcPtr != 0) - *funcPtr = func; - return true; -} - -/*! Match a C++ \c using clause. Return \c true if the match is successful. Otherwise false. @@ -1752,37 +1193,6 @@ bool CppCodeParser::matchUsingDecl(Aggregate* parent) } /*! - This function uses a Tokenizer to parse the function \a signature - in an attempt to match it to the signature of a child node of \a root. - If a match is found, \a funcPtr is set to point to the matching node - and true is returned. - */ -bool CppCodeParser::makeFunctionNode(const QString& signature, - QStringList* parentPathPtr, - FunctionNode** funcPtr, - ExtraFuncData& extra) -{ - Tokenizer* outerTokenizer = tokenizer; - int outerTok = tok; - - QByteArray latin1 = signature.toLatin1(); - Location tmpLoc(signature); // FIXME give a proper location with a filename. - Tokenizer stringTokenizer(tokenizer ? location() : tmpLoc, latin1); - stringTokenizer.setParsingFnOrMacro(true); - tokenizer = &stringTokenizer; - readToken(); - - 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; -} - -/*! This function uses a Tokenizer to parse the \a parameters of a function into the parameter vector \a {pvect}. */ @@ -1810,34 +1220,6 @@ 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::createExampleFileNodes(DocumentNode *dn) { QString examplePath = dn->name(); |