diff options
author | Topi Reinio <topi.reinio@qt.io> | 2018-01-05 14:36:07 +0100 |
---|---|---|
committer | Topi Reiniƶ <topi.reinio@qt.io> | 2018-01-05 14:09:39 +0000 |
commit | d7bafcaf801cbcf246b4413ef5c91c7665475d7c (patch) | |
tree | 53768f6fad514b6f4ddc1d0e39a094010759a3ef | |
parent | 0848d3f79a87c3e2055a7b435bfd4930ef06cf6e (diff) |
qdoc: Fix processing for \macro and QML method/signal topic commands
Because processing these commands do not use clang, their implementation
is moved from ClangCodeParser to CppCodeParser - this ensures
that these topic commands are processed also when they appear in
.qdoc files (PureDocParser, used for .qdoc, derives from CppCodeParser).
Also, these functions did nothing when qdoc was running in prepare
phase which in turn meant that they were not written to .index, thus
breaking cross-module linking for macros/QML methods/signals. That
check is now removed and the functions always do their thing.
Change-Id: I8d9333b02092708955b619b573254eda5d82f038
Reviewed-by: Martin Smith <martin.smith@qt.io>
-rw-r--r-- | src/qdoc/clangcodeparser.cpp | 127 | ||||
-rw-r--r-- | src/qdoc/clangcodeparser.h | 4 | ||||
-rw-r--r-- | src/qdoc/cppcodeparser.cpp | 122 | ||||
-rw-r--r-- | src/qdoc/cppcodeparser.h | 4 |
4 files changed, 126 insertions, 131 deletions
diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp index f35ce3460..bed70573d 100644 --- a/src/qdoc/clangcodeparser.cpp +++ b/src/qdoc/clangcodeparser.cpp @@ -1308,133 +1308,6 @@ void ClangCodeParser::parseSourceFile(const Location& /*location*/, const QStrin } /*! - */ -Node* ClangCodeParser::parseOtherFuncArg(const QString& topic, - const Location& location, - const QString& funcArg) -{ - if (Generator::preparing() && !Generator::singleExec()) - return 0; - - QString funcName; - QString returnType; - - int leftParen = funcArg.indexOf(QChar('(')); - if (leftParen > 0) - funcName = funcArg.left(leftParen); - else - funcName = funcArg; - int firstBlank = funcName.indexOf(QChar(' ')); - if (firstBlank > 0) { - returnType = funcName.left(firstBlank); - funcName = funcName.right(funcName.length() - firstBlank - 1); - } - - QStringList colonSplit(funcName.split("::")); - if (colonSplit.size() < 2) { - QString msg = "Unrecognizable QML module/component qualifier for " + funcArg; - location.warning(tr(msg.toLatin1().data())); - return 0; - } - QString moduleName; - QString elementName; - if (colonSplit.size() > 2) { - moduleName = colonSplit[0]; - elementName = colonSplit[1]; - } else { - elementName = colonSplit[0]; - } - funcName = colonSplit.last(); - - Aggregate *aggregate = qdb_->findQmlType(moduleName, elementName); - bool attached = false; - if (!aggregate) - aggregate = qdb_->findQmlBasicType(moduleName, elementName); - if (!aggregate) - return 0; - - Node::NodeType nodeType = Node::QmlMethod; - if (topic == COMMAND_QMLSIGNAL || topic == COMMAND_JSSIGNAL) { - nodeType = Node::QmlSignal; - } else if (topic == COMMAND_QMLATTACHEDSIGNAL || topic == COMMAND_JSATTACHEDSIGNAL) { - nodeType = Node::QmlSignal; - attached = true; - } else if (topic == COMMAND_QMLATTACHEDMETHOD || topic == COMMAND_JSATTACHEDMETHOD) { - attached = true; - } else { - Q_ASSERT(topic == COMMAND_QMLMETHOD || topic == COMMAND_JSMETHOD); - } - - QString params; - QStringList leftParenSplit = funcArg.split('('); - if (leftParenSplit.size() > 1) { - QStringList rightParenSplit = leftParenSplit[1].split(')'); - if (rightParenSplit.size() > 0) - params = rightParenSplit[0]; - } - FunctionNode *funcNode = static_cast<FunctionNode*>(new FunctionNode(nodeType, aggregate, funcName, attached)); - funcNode->setAccess(Node::Public); - funcNode->setLocation(location); - funcNode->setReturnType(returnType); - funcNode->setParameters(params); - return funcNode; -} - -/*! - Parse the macroArg ad hoc, without using clang and without - using the old qdoc C++ parser. - */ -Node* ClangCodeParser::parseMacroArg(const Location& location, const QString& macroArg) -{ - if (Generator::preparing() && !Generator::singleExec()) - return 0; - FunctionNode* newMacroNode = 0; - QStringList leftParenSplit = macroArg.split('('); - if (leftParenSplit.size() > 0) { - QString macroName; - FunctionNode* oldMacroNode = 0; - QStringList blankSplit = leftParenSplit[0].split(' '); - if (blankSplit.size() > 0) { - macroName = blankSplit.last(); - oldMacroNode = static_cast<FunctionNode*>(qdb_->findMacroNode(macroName)); - } - QString returnType; - if (blankSplit.size() > 1) { - blankSplit.removeLast(); - returnType = blankSplit.join(' '); - } - QString params; - if (leftParenSplit.size() > 1) { - const QString &afterParen = leftParenSplit.at(1); - int rightParen = afterParen.indexOf(')'); - if (rightParen >= 0) - params = afterParen.left(rightParen); - } - int i = 0; - while (i < macroName.length() && !macroName.at(i).isLetter()) - i++; - if (i > 0) { - returnType += QChar(' ') + macroName.left(i); - macroName = macroName.mid(i); - } - newMacroNode = static_cast<FunctionNode*>(new FunctionNode(qdb_->primaryTreeRoot(), macroName)); - newMacroNode->setAccess(Node::Public); - newMacroNode->setLocation(location); - if (params.isEmpty()) - newMacroNode->setMetaness(FunctionNode::MacroWithoutParams); - else - newMacroNode->setMetaness(FunctionNode::MacroWithParams); - newMacroNode->setReturnType(returnType); - newMacroNode->setParameters(params); - if (oldMacroNode && newMacroNode->compare(oldMacroNode)) { - location.warning(ClangCodeParser::tr("\\macro %1 documented more than once").arg(macroArg)); - oldMacroNode->doc().location().warning(tr("(The previous doc is here)")); - } - } - return newMacroNode; - } - -/*! Use clang to parse the function signature from a function command. \a location is used for reporting errors. \a fnArg is the string to parse. It is always a function decl. diff --git a/src/qdoc/clangcodeparser.h b/src/qdoc/clangcodeparser.h index 7d9cf31cf..c5a57416b 100644 --- a/src/qdoc/clangcodeparser.h +++ b/src/qdoc/clangcodeparser.h @@ -56,10 +56,6 @@ public: virtual void parseSourceFile(const Location& location, const QString& filePath) Q_DECL_OVERRIDE; virtual void precompileHeaders() Q_DECL_OVERRIDE; virtual Node *parseFnArg(const Location &location, const QString &fnArg) Q_DECL_OVERRIDE; - virtual Node *parseMacroArg(const Location &location, const QString ¯oArg) Q_DECL_OVERRIDE; - virtual Node *parseOtherFuncArg(const QString &topic, - const Location &location, - const QString &funcArg) Q_DECL_OVERRIDE; private: void getDefaultArgs(); diff --git a/src/qdoc/cppcodeparser.cpp b/src/qdoc/cppcodeparser.cpp index 360e5fef4..a7db13a94 100644 --- a/src/qdoc/cppcodeparser.cpp +++ b/src/qdoc/cppcodeparser.cpp @@ -1220,6 +1220,128 @@ bool CppCodeParser::parseParameters(const QString& parameters, return true; } +/*! + Parse QML/JS signal/method topic commands. + */ +Node* CppCodeParser::parseOtherFuncArg(const QString& topic, + const Location& location, + const QString& funcArg) +{ + QString funcName; + QString returnType; + + int leftParen = funcArg.indexOf(QChar('(')); + if (leftParen > 0) + funcName = funcArg.left(leftParen); + else + funcName = funcArg; + int firstBlank = funcName.indexOf(QChar(' ')); + if (firstBlank > 0) { + returnType = funcName.left(firstBlank); + funcName = funcName.right(funcName.length() - firstBlank - 1); + } + + QStringList colonSplit(funcName.split("::")); + if (colonSplit.size() < 2) { + QString msg = "Unrecognizable QML module/component qualifier for " + funcArg; + location.warning(tr(msg.toLatin1().data())); + return 0; + } + QString moduleName; + QString elementName; + if (colonSplit.size() > 2) { + moduleName = colonSplit[0]; + elementName = colonSplit[1]; + } else { + elementName = colonSplit[0]; + } + funcName = colonSplit.last(); + + Aggregate *aggregate = qdb_->findQmlType(moduleName, elementName); + bool attached = false; + if (!aggregate) + aggregate = qdb_->findQmlBasicType(moduleName, elementName); + if (!aggregate) + return 0; + + Node::NodeType nodeType = Node::QmlMethod; + if (topic == COMMAND_QMLSIGNAL || topic == COMMAND_JSSIGNAL) { + nodeType = Node::QmlSignal; + } else if (topic == COMMAND_QMLATTACHEDSIGNAL || topic == COMMAND_JSATTACHEDSIGNAL) { + nodeType = Node::QmlSignal; + attached = true; + } else if (topic == COMMAND_QMLATTACHEDMETHOD || topic == COMMAND_JSATTACHEDMETHOD) { + attached = true; + } else { + Q_ASSERT(topic == COMMAND_QMLMETHOD || topic == COMMAND_JSMETHOD); + } + + QString params; + QStringList leftParenSplit = funcArg.split('('); + if (leftParenSplit.size() > 1) { + QStringList rightParenSplit = leftParenSplit[1].split(')'); + if (rightParenSplit.size() > 0) + params = rightParenSplit[0]; + } + FunctionNode *funcNode = static_cast<FunctionNode*>(new FunctionNode(nodeType, aggregate, funcName, attached)); + funcNode->setAccess(Node::Public); + funcNode->setLocation(location); + funcNode->setReturnType(returnType); + funcNode->setParameters(params); + return funcNode; +} + +/*! + Parse the \macro arguments ad hoc, without using any actual parser. + */ +Node* CppCodeParser::parseMacroArg(const Location& location, const QString& macroArg) +{ + FunctionNode* newMacroNode = 0; + QStringList leftParenSplit = macroArg.split('('); + if (leftParenSplit.size() > 0) { + QString macroName; + FunctionNode* oldMacroNode = 0; + QStringList blankSplit = leftParenSplit[0].split(' '); + if (blankSplit.size() > 0) { + macroName = blankSplit.last(); + oldMacroNode = static_cast<FunctionNode*>(qdb_->findMacroNode(macroName)); + } + QString returnType; + if (blankSplit.size() > 1) { + blankSplit.removeLast(); + returnType = blankSplit.join(' '); + } + QString params; + if (leftParenSplit.size() > 1) { + const QString &afterParen = leftParenSplit.at(1); + int rightParen = afterParen.indexOf(')'); + if (rightParen >= 0) + params = afterParen.left(rightParen); + } + int i = 0; + while (i < macroName.length() && !macroName.at(i).isLetter()) + i++; + if (i > 0) { + returnType += QChar(' ') + macroName.left(i); + macroName = macroName.mid(i); + } + newMacroNode = static_cast<FunctionNode*>(new FunctionNode(qdb_->primaryTreeRoot(), macroName)); + newMacroNode->setAccess(Node::Public); + newMacroNode->setLocation(location); + if (params.isEmpty()) + newMacroNode->setMetaness(FunctionNode::MacroWithoutParams); + else + newMacroNode->setMetaness(FunctionNode::MacroWithParams); + newMacroNode->setReturnType(returnType); + newMacroNode->setParameters(params); + if (oldMacroNode && newMacroNode->compare(oldMacroNode)) { + location.warning(tr("\\macro %1 documented more than once").arg(macroArg)); + oldMacroNode->doc().location().warning(tr("(The previous doc is here)")); + } + } + return newMacroNode; + } + void CppCodeParser::createExampleFileNodes(DocumentNode *dn) { QString examplePath = dn->name(); diff --git a/src/qdoc/cppcodeparser.h b/src/qdoc/cppcodeparser.h index 9069d4fce..a1bc5079e 100644 --- a/src/qdoc/cppcodeparser.h +++ b/src/qdoc/cppcodeparser.h @@ -66,6 +66,10 @@ public: QStringList headerFileNameFilter() override; QStringList sourceFileNameFilter() override; bool parseParameters(const QString& parameters, QVector<Parameter>& pvect, bool& isQPrivateSignal); + Node *parseMacroArg(const Location &location, const QString ¯oArg) override; + Node *parseOtherFuncArg(const QString &topic, + const Location &location, + const QString &funcArg) override; const Location& declLoc() const { return declLoc_; } void setDeclLoc() { declLoc_ = location(); } static bool isJSMethodTopic(const QString &t); |