From bf8ee4c99d56c2bf770343b7db07f68a2c6a7617 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Tue, 22 Jan 2019 12:11:13 +0100 Subject: qdoc: Major clean-up of FunctionNode and parameter processing This update was motivated by the need to correct two known issues in qdoc. First, linking to overloaded functions failed in some cases because the overloads were not numbered consistently, causing links to go to the wrong overload or to nowhere at all. Second, the mechanism for handling the \relates command didn't support using it to relate a function to more than one class. For example, there are many global qHash() functions spread around QtBase. Each is meant to compute a hash index for an object of some class type, so the object can be inserted into a QHash map for that class type. It is then desired to relate qHash(type Xxx, int seed) to both QHash and class Xxx, so that the documentation for that qHash() function appears as a related non-member function of both QHash and class Xxx. The example above also illustrates the overload numbering problem, because all these qHash() functions are overloads of the name qHash. To make matters worse, they are not all in the same module. Most of them are in QtCore, but a few are in QtNetwork, and this distribution problem will become worse over time as more qHash() functions are added. Prior to this update, qdoc was unable to relate a function to something in a different module, or it didn't always work. While designing a fix for these issues, it became clear that the processing of the FunctionNode and the function parameters would have to be rewritten. That's what this update does. These are the main points: 1. A new subclass of Node is added to act as a proxy for a class in another module. This ProxyNode acts as a place holder for the functions (and possibly other elements) that are related to a class in another module. This is used for the qHash() functions in QtNetwork that are related to QHash in QtCore. qdoc generates an html file named qtnetwork/qhash-proxy.html that contains the documentation for these functions. But these functions are listed as related non-members on the QHash class reference page in the qtcore output directory. They are listed there in the summary, but they link to the qhash-proxy.html page in qtnetwork. 2. A new, Parameters class is added to qdoc (parameters.h and parameters.cpp), and the class Parameter is moved there from node.h. class Parameters replaces the old QVector wherever it was used. This encapsulates all the parameter processing and matching in the Parameters class and simplifies the code at all the places where QVector had been used. 3. The assignment of overload numbers is now done in the normalizeOverloads() function, which is called after all the headers and sources have been processed but before the generate phase begins. This assignment is a simple renumbering now because all the overloads of a function are linked to each other via a nextOverload_ link in the FunctionNode. The first function named qHash() is inserted into the Aggregate node's function map, but subsequent qHash() FunctionNodes are not entered into the function map but are linked to the first qHash() via its nextOverload_ link. 4. The \relates command can now be used multiple times in a single qdoc comment. There remains some work to be done here because this currently only works for global entities, but there are several cases where \relates has been used in the qdoc comment of a member of a class. This will be fixed soon, I believe. When qdoc sees the first \relates Xxx command, for example for qHash(Yyy, seed), that qHash() is a child of the global namespace. qdoc allows it to remain as a child of the global namespace but it tells class Xxx to "adopt" that child (see Node::adoptChild()). This function makes this instance of qHash() be a child of class Xxx (in this case QHash), so that the parent of this qHash() becomes Xxx. After this "adoption," qHash() is a child of both the global namespace and class Xxx, but qHash() only knows it is a child of Xxx, i.e. its parent pointer is Xxx. If this is the first qHash() to become a child of Xxx, it is inserted into the function map of Xxx, but its nextOverload_ link is not changed. This is because all the global qHash() functions have already been linked into the nextOverload_ linked list, and this list must not be changed. Hence, when qdoc searches for qHash(something) to make a link to it, it will find it as a child of the global namespace, but it will correctly link to it using its actual parent pointer. When qdoc sees the second \relates Yyy for this qHash() function, qdoc sees that this FunctionNode has already been made a related non-member of Xxx, so it can't let Yyy "adopt" it. Instead, it tells Yyy to clone this qHash(), which creates a shallow copy of it but resets its nextOverload_ pointer to nullptr. I believe this clone of qHash() won't be found in a search for a function named qHash(), because the global one (the adopted one) will be found first. Or, if it is found, a link to the clone will be generated, but that's ok because the documentation is identical. Note that the existence of qHash in two child lists is taken into account at destruction time. The only place where a Node is destroyed is in the destructor of Tree, which destroys the Node tree from the root down to the leaves. Each aggregate node is responsible for deleting each of its child nodes, but it only deletes a child node if it is the parent of that child node. All of the above revealed that some of the findFunctionNode() functions were either no longer needed or weren't being called in the first place, so they were deleted. This change is now ready for testing. Change-Id: I6da3e2e9e71d39a29d90e073ed614309a49e3d4c Reviewed-by: Qt CI Bot Reviewed-by: Paul Wicking --- src/qdoc/cppcodeparser.cpp | 643 +++++++-------------------------------------- 1 file changed, 99 insertions(+), 544 deletions(-) (limited to 'src/qdoc/cppcodeparser.cpp') diff --git a/src/qdoc/cppcodeparser.cpp b/src/qdoc/cppcodeparser.cpp index c80ab745b..a889c988e 100644 --- a/src/qdoc/cppcodeparser.cpp +++ b/src/qdoc/cppcodeparser.cpp @@ -33,10 +33,8 @@ #include #include #include -#include "codechunk.h" #include "config.h" #include "cppcodeparser.h" -#include "tokenizer.h" #include "qdocdatabase.h" #include #include "generator.h" @@ -45,23 +43,20 @@ QT_BEGIN_NAMESPACE /* qmake ignore Q_OBJECT */ -static bool inMacroCommand_ = false; QStringList CppCodeParser::exampleFiles; QStringList CppCodeParser::exampleDirs; QSet CppCodeParser::excludeDirs; QSet CppCodeParser::excludeFiles; static QSet topicCommands_; -static QSet otherMetaCommands_; +static QSet metaCommands_; /*! The constructor initializes some regular expressions - and calls reset(). + and initializes the tokenizer variables. */ CppCodeParser::CppCodeParser() - : varComment("/\\*\\s*([a-zA-Z_0-9]+)\\s*\\*/"), sep("(?:<[^>]+>)?::") { - reset(); if (topicCommands_.isEmpty()) { topicCommands_ << COMMAND_CLASS << COMMAND_DITAMAP @@ -100,22 +95,16 @@ CppCodeParser::CppCodeParser() << COMMAND_JSBASICTYPE << COMMAND_JSMODULE; } - if (otherMetaCommands_.isEmpty()) { - otherMetaCommands_ = commonMetaCommands(); - otherMetaCommands_ << COMMAND_INHEADERFILE - << COMMAND_OVERLOAD - << COMMAND_REIMP - << COMMAND_RELATES - << COMMAND_CONTENTSPAGE - << COMMAND_NEXTPAGE - << COMMAND_PREVIOUSPAGE - << COMMAND_STARTPAGE - << COMMAND_QMLINHERITS - << COMMAND_QMLINSTANTIATES - << COMMAND_QMLDEFAULT - << COMMAND_QMLREADONLY - << COMMAND_QMLABSTRACT - << COMMAND_ABSTRACT; + if (metaCommands_.isEmpty()) { + metaCommands_ = commonMetaCommands(); + metaCommands_ << COMMAND_CONTENTSPAGE + << COMMAND_INHEADERFILE + << COMMAND_NEXTPAGE + << COMMAND_OVERLOAD + << COMMAND_PREVIOUSPAGE + << COMMAND_QMLINSTANTIATES + << COMMAND_REIMP + << COMMAND_RELATES; } } @@ -238,8 +227,6 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, doc.location().warning(tr("Cannot find '%1' specified with '\\%2' in any header file") .arg(arg.first).arg(command)); } - lastPath_ = path; - } else if (node->isAggregate()) { if (type == Node::Namespace) { @@ -556,48 +543,60 @@ void CppCodeParser::processQmlProperties(const Doc& doc, Returns the set of strings representing the common metacommands plus some other metacommands. */ -const QSet& CppCodeParser::otherMetaCommands() +const QSet& CppCodeParser::metaCommands() { - return otherMetaCommands_; + return metaCommands_; } /*! Process the metacommand \a command in the context of the \a node associated with the topic command and the \a doc. \a arg is the argument to the metacommand. + + \a node is guaranteed to be non-null. */ -void CppCodeParser::processOtherMetaCommand(const Doc& doc, - const QString& command, - const ArgLocPair& argLocPair, - Node *node) +void CppCodeParser::processMetaCommand(const Doc &doc, + const QString &command, + const ArgLocPair &argLocPair, + Node *node) { QString arg = argLocPair.first; if (command == COMMAND_INHEADERFILE) { - if (node != 0 && node->isAggregate()) { - ((Aggregate *) node)->addInclude(arg); - } - else { + if (node->isAggregate()) + static_cast(node)->addIncludeFile(arg); + else doc.location().warning(tr("Ignored '\\%1'").arg(COMMAND_INHEADERFILE)); - } } else if (command == COMMAND_OVERLOAD) { - if (node && (node->isFunction() || node->isSharedCommentNode())) - node->setOverloadFlag(true); + /* + Note that this might set the overload flag of the + primary function. This is ok because the overload + flags and overload numbers will be resolved later + in resolveOverloadNumbers(). + */ + if (node->isFunction()) + static_cast(node)->setOverloadFlag(); + else if (node->isSharedCommentNode()) + static_cast(node)->setOverloadFlags(); else doc.location().warning(tr("Ignored '\\%1'").arg(COMMAND_OVERLOAD)); } else if (command == COMMAND_REIMP) { - if (node != 0 && node->parent() && !node->parent()->isInternal()) { + if (node->parent() && !node->parent()->isInternal()) { if (node->isFunction()) { - FunctionNode *func = (FunctionNode *) node; - if (func->reimplementedFrom().isEmpty() && isWorthWarningAbout(doc)) { + FunctionNode *fn = static_cast(node); + // The clang visitor class will have set the + // qualified name of the ovverridden function. + // If the name of the overridden function isn't + // set, issue a warning. + if (fn->overridesThis().isEmpty() && isWorthWarningAbout(doc)) { doc.location().warning(tr("Cannot find base function for '\\%1' in %2()") .arg(COMMAND_REIMP).arg(node->name()), tr("The function either doesn't exist in any " "base class with the same signature or it " "exists but isn't virtual.")); } - func->setReimplemented(true); + fn->setReimpFlag(); } else { doc.location().warning(tr("Ignored '\\%1' in %2").arg(COMMAND_REIMP).arg(node->name())); @@ -606,20 +605,42 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, } else if (command == COMMAND_RELATES) { QStringList path = arg.split("::"); - Node* n = qdb_->findRelatesNode(path); - if (!n) { - // Store just a string to write to the index file - if (Generator::preparing()) - node->setRelates(arg); - else - doc.location().warning(tr("Cannot find '%1' in '\\%2'").arg(arg).arg(COMMAND_RELATES)); + Aggregate *aggregate = qdb_->findRelatesNode(path); + if (!aggregate) + aggregate = new ProxyNode(node->root(), arg); - } - else if (node->parent() != n) - node->setRelates(static_cast(n)); - else - doc.location().warning(tr("Invalid use of '\\%1' (already a member of '%2')") + if (node->parent() == aggregate) { // node is already a child of aggregate + doc.location().warning(tr("Invalid '\\%1' (already a member of '%2')") .arg(COMMAND_RELATES, arg)); + } else { + if (node->isAggregate()) { + doc.location().warning(tr("Invalid '\\%1' not allowed in '\\%2'") + .arg(COMMAND_RELATES, node->nodeTypeString())); + } else if (!node->isRelatedNonmember() && + !node->parent()->name().isEmpty() && + !node->parent()->isHeader()) { + if (!doc.isInternal()) { + doc.location().warning(tr("Invalid '\\%1' ('%2' must be global)") + .arg(COMMAND_RELATES, node->name())); + } + } else if (!node->isRelatedNonmember() && !node->parent()->isHeader()) { + aggregate->adoptChild(node); + node->setRelatedNonmember(true); + } else { + /* + There are multiple \relates commands. This + one is not the first, so clone the node as + a child of aggregate. + */ + Node *clone = node->clone(aggregate); + if (clone == nullptr) { + doc.location().warning(tr("Invalid '\\%1' (multiple uses not allowed in '%2')") + .arg(COMMAND_RELATES, node->nodeTypeString())); + } else { + clone->setRelatedNonmember(true); + } + } + } } else if (command == COMMAND_CONTENTSPAGE) { setLink(node, Node::ContentsLink, arg); @@ -653,38 +674,10 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, doc.location().warning(tr("\\instantiates is only allowed in \\qmltype")); } else if (command == COMMAND_QMLDEFAULT) { - if (node->nodeType() == Node::QmlProperty) { - QmlPropertyNode* qpn = static_cast(node); - qpn->setDefault(); - } - else if (node->nodeType() == Node::QmlPropertyGroup) { - QmlPropertyGroupNode* qpgn = static_cast(node); - NodeList::ConstIterator p = qpgn->childNodes().constBegin(); - while (p != qpgn->childNodes().constEnd()) { - if ((*p)->nodeType() == Node::QmlProperty) { - QmlPropertyNode* qpn = static_cast(*p); - qpn->setDefault(); - } - ++p; - } - } + node->markDefault(); } else if (command == COMMAND_QMLREADONLY) { - if (node->nodeType() == Node::QmlProperty) { - QmlPropertyNode* qpn = static_cast(node); - qpn->setReadOnly(1); - } - else if (node->nodeType() == Node::QmlPropertyGroup) { - QmlPropertyGroupNode* qpgn = static_cast(node); - NodeList::ConstIterator p = qpgn->childNodes().constBegin(); - while (p != qpgn->childNodes().constEnd()) { - if ((*p)->nodeType() == Node::QmlProperty) { - QmlPropertyNode* qpn = static_cast(*p); - qpn->setReadOnly(1); - } - ++p; - } - } + node->markReadOnly(1); } else if ((command == COMMAND_QMLABSTRACT) || (command == COMMAND_ABSTRACT)) { if (node->isQmlType() || node->isJsType()) @@ -711,21 +704,8 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, if (!node->isInternal()) node->setStatus(Node::Preliminary); } else if (command == COMMAND_INTERNAL) { - if (!showInternal()) { - node->setAccess(Node::Private); - node->setStatus(Node::Internal); - if (node->nodeType() == Node::QmlPropertyGroup) { - const QmlPropertyGroupNode* qpgn = static_cast(node); - NodeList::ConstIterator p = qpgn->childNodes().constBegin(); - while (p != qpgn->childNodes().constEnd()) { - if ((*p)->nodeType() == Node::QmlProperty) { - (*p)->setAccess(Node::Private); - (*p)->setStatus(Node::Internal); - } - ++p; - } - } - } + if (!showInternal()) + node->markInternal(); } else if (command == COMMAND_REENTRANT) { node->setThreadSafeness(Node::Reentrant); } else if (command == COMMAND_SINCE) { @@ -755,456 +735,31 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, } /*! - The topic command has been processed resulting in the \a doc - and \a node passed in here. Process the other meta commands, - which are found in \a doc, in the context of the topic \a node. + The topic command has been processed, and now \a doc and + \a node are passed to this function to get the metacommands + from \a doc and process them one at a time. \a node is the + node where \a doc resides. */ -void CppCodeParser::processOtherMetaCommands(const Doc& doc, Node *node) +void CppCodeParser::processMetaCommands(const Doc &doc, Node *node) { - QStringList metaCommands = doc.metaCommandsUsed().toList(); - metaCommands.sort(); - QStringList::ConstIterator cmd = metaCommands.constBegin(); - while (cmd != metaCommands.constEnd()) { + QStringList metaCommandsUsed = doc.metaCommandsUsed().toList(); + metaCommandsUsed.sort(); // TODO: why are these sorted? mws 24/12/2018 + QStringList::ConstIterator cmd = metaCommandsUsed.constBegin(); + while (cmd != metaCommandsUsed.constEnd()) { ArgList args = doc.metaCommandArgs(*cmd); ArgList::ConstIterator arg = args.constBegin(); while (arg != args.constEnd()) { - processOtherMetaCommand(doc, *cmd, *arg, node); + processMetaCommand(doc, *cmd, *arg, node); ++arg; } ++cmd; } } -/*! - Resets the C++ code parser to its default initialized state. - */ -void CppCodeParser::reset() -{ - tokenizer = 0; - tok = 0; - access = Node::Public; - metaness_ = FunctionNode::Plain; - lastPath_.clear(); - physicalModuleName.clear(); -} - -/*! - Get the next token from the file being parsed and store it - in the token variable. - */ -void CppCodeParser::readToken() -{ - tok = tokenizer->getToken(); -} - -/*! - Return the current location in the file being parsed, - i.e. the file name, line number, and column number. - */ -const Location& CppCodeParser::location() -{ - return tokenizer->location(); -} - -/*! - Return the previous string read from the file being parsed. - */ -QString CppCodeParser::previousLexeme() -{ - return tokenizer->previousLexeme(); -} - -/*! - Return the current string string from the file being parsed. - */ -QString CppCodeParser::lexeme() -{ - return tokenizer->lexeme(); -} - -bool CppCodeParser::match(int target) -{ - if (tok == target) { - readToken(); - return true; - } - return false; -} - -/*! - Skip to \a target. If \a target is found before the end - of input, return true. Otherwise return false. - */ -bool CppCodeParser::skipTo(int target) -{ - while ((tok != Tok_Eoi) && (tok != target)) - readToken(); - return tok == target; -} - -bool CppCodeParser::matchModuleQualifier(QString& name) -{ - bool matches = (lexeme() == QString('.')); - if (matches) { - do { - name += lexeme(); - readToken(); - } while ((tok == Tok_Ident) || (lexeme() == QString('.'))); - } - return matches; -} - -bool CppCodeParser::matchTemplateAngles(CodeChunk *dataType) -{ - bool matches = (tok == Tok_LeftAngle); - if (matches) { - int leftAngleDepth = 0; - int parenAndBraceDepth = 0; - do { - if (tok == Tok_LeftAngle) { - leftAngleDepth++; - } - else if (tok == Tok_RightAngle) { - leftAngleDepth--; - } - else if (tok == Tok_LeftParen || tok == Tok_LeftBrace) { - ++parenAndBraceDepth; - } - else if (tok == Tok_RightParen || tok == Tok_RightBrace) { - if (--parenAndBraceDepth < 0) - return false; - } - if (dataType != 0) - dataType->append(lexeme()); - readToken(); - } while (leftAngleDepth > 0 && tok != Tok_Eoi); - } - return matches; -} - -bool CppCodeParser::matchDataType(CodeChunk *dataType, QString *var, bool qProp) -{ - /* - This code is really hard to follow... sorry. The loop is there to match - Alpha::Beta::Gamma::...::Omega. - */ - for (;;) { - bool virgin = true; - - if (tok != Tok_Ident) { - /* - There is special processing for 'Foo::operator int()' - and such elsewhere. This is the only case where we - return something with a trailing gulbrandsen ('Foo::'). - */ - if (tok == Tok_operator) - return true; - - /* - People may write 'const unsigned short' or - 'short unsigned const' or any other permutation. - */ - while (match(Tok_const) || match(Tok_volatile)) - dataType->append(previousLexeme()); - QString pending; - while (tok == Tok_signed || tok == Tok_int || tok == Tok_unsigned || - tok == Tok_short || tok == Tok_long || tok == Tok_int64) { - if (tok == Tok_signed) - pending = lexeme(); - else { - if (tok == Tok_unsigned && !pending.isEmpty()) - dataType->append(pending); - pending.clear(); - dataType->append(lexeme()); - } - readToken(); - virgin = false; - } - if (!pending.isEmpty()) { - dataType->append(pending); - pending.clear(); - } - while (match(Tok_const) || match(Tok_volatile)) - dataType->append(previousLexeme()); - - if (match(Tok_Tilde)) - dataType->append(previousLexeme()); - } - - if (virgin) { - if (match(Tok_Ident)) { - /* - This is a hack until we replace this "parser" - with the real one used in Qt Creator. - */ - if (!inMacroCommand_ && lexeme() == "(" && - ((previousLexeme() == "QT_PREPEND_NAMESPACE") || (previousLexeme() == "NS"))) { - readToken(); - readToken(); - dataType->append(previousLexeme()); - readToken(); - } - else - dataType->append(previousLexeme()); - } - else if (match(Tok_void) || match(Tok_int) || match(Tok_char) || - match(Tok_double) || match(Tok_Ellipsis)) { - dataType->append(previousLexeme()); - } - else { - return false; - } - } - else if (match(Tok_int) || match(Tok_char) || match(Tok_double)) { - dataType->append(previousLexeme()); - } - - matchTemplateAngles(dataType); - - while (match(Tok_const) || match(Tok_volatile)) - dataType->append(previousLexeme()); - - if (match(Tok_Gulbrandsen)) - dataType->append(previousLexeme()); - else - break; - } - - while (match(Tok_Ampersand) || match(Tok_Aster) || match(Tok_const) || - match(Tok_Caret) || match(Tok_Ellipsis)) - dataType->append(previousLexeme()); - - if (match(Tok_LeftParenAster)) { - /* - A function pointer. This would be rather hard to handle without a - tokenizer hack, because a type can be followed with a left parenthesis - in some cases (e.g., 'operator int()'). The tokenizer recognizes '(*' - as a single token. - */ - dataType->append(" "); // force a space after the type - dataType->append(previousLexeme()); - dataType->appendHotspot(); - if (var != 0 && match(Tok_Ident)) - *var = previousLexeme(); - if (!match(Tok_RightParen)) - return false; - dataType->append(previousLexeme()); - if (!match(Tok_LeftParen)) - return false; - dataType->append(previousLexeme()); - - /* parse the parameters. Ignore the parameter name from the type */ - while (tok != Tok_RightParen && tok != Tok_Eoi) { - QString dummy; - if (!matchDataType(dataType, &dummy)) - return false; - if (match(Tok_Comma)) - dataType->append(previousLexeme()); - } - if (!match(Tok_RightParen)) - return false; - dataType->append(previousLexeme()); - } - else { - /* - The common case: Look for an optional identifier, then for - some array brackets. - */ - dataType->appendHotspot(); - - if (var != 0) { - if (match(Tok_Ident)) { - *var = previousLexeme(); - } - else if (match(Tok_Comment)) { - /* - A neat hack: Commented-out parameter names are - recognized by qdoc. It's impossible to illustrate - here inside a C-style comment, because it requires - an asterslash. It's also impossible to illustrate - inside a C++-style comment, because the explanation - does not fit on one line. - */ - if (varComment.exactMatch(previousLexeme())) - *var = varComment.cap(1); - } - else if (match(Tok_LeftParen)) { - *var = "("; - while (tok != Tok_RightParen && tok != Tok_Eoi) { - (*var).append(lexeme()); - readToken(); - } - (*var).append(")"); - readToken(); - if (match(Tok_LeftBracket)) { - (*var).append("["); - while (tok != Tok_RightBracket && tok != Tok_Eoi) { - (*var).append(lexeme()); - readToken(); - } - (*var).append("]"); - readToken(); - } - } - else if (qProp && (match(Tok_default) || match(Tok_final) || match(Tok_override))) { - // Hack to make 'default', 'final' and 'override' work again in Q_PROPERTY - *var = previousLexeme(); - } - } - - if (tok == Tok_LeftBracket) { - int bracketDepth0 = tokenizer->bracketDepth(); - while ((tokenizer->bracketDepth() >= bracketDepth0 && - tok != Tok_Eoi) || - tok == Tok_RightBracket) { - dataType->append(lexeme()); - readToken(); - } - } - } - return true; -} - -/*! - Parse the next function parameter, if there is one, and - append it to parameter vector \a pvect. Return true if - a parameter is parsed and appended to \a pvect. - Otherwise return false. - */ -bool CppCodeParser::matchParameter(QVector& pvect, bool& isQPrivateSignal) -{ - if (match(Tok_QPrivateSignal)) { - isQPrivateSignal = true; - return true; - } - - Parameter p; - CodeChunk chunk; - if (!matchDataType(&chunk, &p.name_)) { - return false; - } - p.dataType_ = chunk.toString(); - chunk.clear(); - match(Tok_Comment); - if (match(Tok_Equal)) { - int pdepth = tokenizer->parenDepth(); - while (tokenizer->parenDepth() >= pdepth && - (tok != Tok_Comma || (tokenizer->parenDepth() > pdepth)) && - tok != Tok_Eoi) { - chunk.append(lexeme()); - readToken(); - } - } - p.defaultValue_ = chunk.toString(); - pvect.append(p); - return true; -} - -/*! - Match a C++ \c using clause. Return \c true if the match - is successful. Otherwise false. - - If the \c using clause is for a namespace, an open namespace - insertOpenNamespace(name); - } - else if (parent && parent->isClass()) { - ClassNode* cn = static_cast(parent); - cn->addUnresolvedUsingClause(name); - } - return true; -} - -/*! - This function uses a Tokenizer to parse the \a parameters of a - function into the parameter vector \a {pvect}. - */ -bool CppCodeParser::parseParameters(const QString& parameters, - QVector& pvect, - bool& isQPrivateSignal) -{ - Tokenizer* outerTokenizer = tokenizer; - int outerTok = tok; - - QByteArray latin1 = parameters.toLatin1(); - Tokenizer stringTokenizer(Location(), latin1); - stringTokenizer.setParsingFnOrMacro(true); - tokenizer = &stringTokenizer; - readToken(); - - inMacroCommand_ = false; - do { - if (!matchParameter(pvect, isQPrivateSignal)) - return false; - } while (match(Tok_Comma)); - - tokenizer = outerTokenizer; - tok = outerTok; - return true; -} - /*! Parse QML/JS signal/method topic commands. */ -Node* CppCodeParser::parseOtherFuncArg(const QString& topic, const Location& location, const QString& funcArg) +FunctionNode *CppCodeParser::parseOtherFuncArg(const QString &topic, const Location &location, const QString &funcArg) { QString funcName; QString returnType; @@ -1224,7 +779,7 @@ Node* CppCodeParser::parseOtherFuncArg(const QString& topic, const Location& loc if (colonSplit.size() < 2) { QString msg = "Unrecognizable QML module/component qualifier for " + funcArg; location.warning(tr(msg.toLatin1().data())); - return 0; + return nullptr; } QString moduleName; QString elementName; @@ -1240,7 +795,7 @@ Node* CppCodeParser::parseOtherFuncArg(const QString& topic, const Location& loc if (!aggregate) aggregate = qdb_->findQmlBasicType(moduleName, elementName); if (!aggregate) - return 0; + return nullptr; QString params; QStringList leftParenSplit = funcArg.split('('); @@ -1266,7 +821,7 @@ Node* CppCodeParser::parseOtherFuncArg(const QString& topic, const Location& loc FunctionNode for the macro. Otherwise return null. \a location is used for reporting errors. */ -Node* CppCodeParser::parseMacroArg(const Location& location, const QString& macroArg) +FunctionNode *CppCodeParser::parseMacroArg(const Location &location, const QString ¯oArg) { QStringList leftParenSplit = macroArg.split('('); if (leftParenSplit.isEmpty()) @@ -1276,7 +831,7 @@ Node* CppCodeParser::parseMacroArg(const Location& location, const QString& macr QStringList blankSplit = leftParenSplit[0].split(' '); if (blankSplit.size() > 0) { macroName = blankSplit.last(); - oldMacroNode = static_cast(qdb_->findMacroNode(macroName)); + oldMacroNode = qdb_->findMacroNode(macroName); } QString returnType; if (blankSplit.size() > 1) { @@ -1495,25 +1050,25 @@ void CppCodeParser::processTopicArgs(const Doc &doc, const QString &topic, NodeL } } -void CppCodeParser::processOtherMetaCommands(NodeList &nodes, DocList& docs) +void CppCodeParser::processMetaCommands(NodeList &nodes, DocList &docs) { NodeList::Iterator n = nodes.begin(); QList::Iterator d = docs.begin(); while (n != nodes.end()) { if (*n != nullptr) { - processOtherMetaCommands(*d, *n); + processMetaCommands(*d, *n); (*n)->setDoc(*d); checkModuleInclusion(*n); if ((*n)->isAggregate()) { Aggregate *aggregate = static_cast(*n); - if (aggregate->includes().isEmpty()) { + if (aggregate->includeFiles().isEmpty()) { Aggregate *parent = aggregate; while (parent->physicalModuleName().isEmpty() && (parent->parent() != nullptr)) parent = parent->parent(); if (parent == aggregate) - aggregate->addInclude(aggregate->name()); + aggregate->addIncludeFile(aggregate->name()); else - aggregate->setIncludes(parent->includes()); + aggregate->setIncludeFiles(parent->includeFiles()); } } } -- cgit v1.2.1