summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTopi Reinio <topi.reinio@qt.io>2018-01-05 14:36:07 +0100
committerTopi Reiniƶ <topi.reinio@qt.io>2018-01-05 14:09:39 +0000
commitd7bafcaf801cbcf246b4413ef5c91c7665475d7c (patch)
tree53768f6fad514b6f4ddc1d0e39a094010759a3ef
parent0848d3f79a87c3e2055a7b435bfd4930ef06cf6e (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.cpp127
-rw-r--r--src/qdoc/clangcodeparser.h4
-rw-r--r--src/qdoc/cppcodeparser.cpp122
-rw-r--r--src/qdoc/cppcodeparser.h4
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 &macroArg) 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 &macroArg) 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);