summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Smith <martin.smith@digia.com>2015-03-11 14:58:54 +0100
committerMartin Smith <martin.smith@digia.com>2015-03-12 13:47:20 +0000
commit70f92f8cee3f76385a426f62f4ee7e79945da5f2 (patch)
treed8196246b0f473231c71994a9a80b527153d2264 /src
parent53207e820c894a1408aa77aa2237cc664eabc119 (diff)
qdoc: Show correct method signatures for QML types
The return type was not printed, for \qmlmethod commands used in QML files. The parameter types and default values weren't being printed either. This update corrects those problems. Change-Id: I68301fb2040c9dc5f5650e7dd3fee9c42197e3f7 Task-number: QTBUG-44064 Reviewed-by: Caroline Chao <caroline.chao@theqtcompany.com> Reviewed-by: Topi Reiniƶ <topi.reinio@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/tools/qdoc/codechunk.h1
-rw-r--r--src/tools/qdoc/htmlgenerator.cpp1
-rw-r--r--src/tools/qdoc/node.cpp1
-rw-r--r--src/tools/qdoc/node.h1
-rw-r--r--src/tools/qdoc/qmlvisitor.cpp199
5 files changed, 203 insertions, 0 deletions
diff --git a/src/tools/qdoc/codechunk.h b/src/tools/qdoc/codechunk.h
index ed898bcdc7..259012df90 100644
--- a/src/tools/qdoc/codechunk.h
+++ b/src/tools/qdoc/codechunk.h
@@ -76,6 +76,7 @@ public:
void appendHotspot();
bool isEmpty() const { return s.isEmpty(); }
+ void clear() { s.clear(); }
QString toString() const;
QStringList toPath() const;
QString left() const { return s.left(hotspot == -1 ? s.length() : hotspot); }
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index f0369c989a..00a292b17f 100644
--- a/src/tools/qdoc/htmlgenerator.cpp
+++ b/src/tools/qdoc/htmlgenerator.cpp
@@ -3349,6 +3349,7 @@ void HtmlGenerator::generateSectionInheritedList(const Section& section, const N
}
}
+// generateSynopsis(qmn,relative,marker,CodeMarker::Detailed,false);
void HtmlGenerator::generateSynopsis(const Node *node,
const Node *relative,
CodeMarker *marker,
diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp
index a5b1f466bc..a6999d3856 100644
--- a/src/tools/qdoc/node.cpp
+++ b/src/tools/qdoc/node.cpp
@@ -1863,6 +1863,7 @@ void FunctionNode::setReimp(bool r)
}
/*!
+ Append \a parameter to the parameter list.
*/
void FunctionNode::addParameter(const Parameter& parameter)
{
diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h
index 2c6e703103..654004e425 100644
--- a/src/tools/qdoc/node.h
+++ b/src/tools/qdoc/node.h
@@ -904,6 +904,7 @@ public:
}
int overloadNumber() const;
const QList<Parameter>& parameters() const { return params; }
+ void clearParams() { params.clear(); }
QStringList parameterNames() const;
QString rawParameters(bool names = false, bool values = false) const;
const FunctionNode* reimplementedFrom() const { return rf; }
diff --git a/src/tools/qdoc/qmlvisitor.cpp b/src/tools/qdoc/qmlvisitor.cpp
index 6179e80085..190c9f0444 100644
--- a/src/tools/qdoc/qmlvisitor.cpp
+++ b/src/tools/qdoc/qmlvisitor.cpp
@@ -42,6 +42,7 @@
#include "codeparser.h"
#include "qmlvisitor.h"
#include "qdocdatabase.h"
+#include "tokenizer.h"
QT_BEGIN_NAMESPACE
@@ -146,6 +147,29 @@ QQmlJS::AST::SourceLocation QmlDocVisitor::precedingComment(quint32 offset) cons
return QQmlJS::AST::SourceLocation();
}
+class QmlSignatureParser
+{
+ public:
+ QmlSignatureParser(FunctionNode* func, const QString& signature, const Location& loc);
+ void readToken() { tok_ = tokenizer_->getToken(); }
+ QString lexeme() { return tokenizer_->lexeme(); }
+ QString previousLexeme() { return tokenizer_->previousLexeme(); }
+
+ bool match(int target);
+ bool matchDataType(CodeChunk* dataType, QString* var);
+ bool matchParameter();
+ bool matchFunctionDecl();
+
+ private:
+ QString signature_;
+ QStringList names_;
+ QString funcName_;
+ Tokenizer* tokenizer_;
+ int tok_;
+ FunctionNode* func_;
+ const Location& location_;
+};
+
/*!
Finds the nearest unused qdoc comment above the QML entity
represented by the \a node and processes the qdoc commands
@@ -216,6 +240,13 @@ bool QmlDocVisitor::applyDocumentation(QQmlJS::AST::SourceLocation location, Nod
else
qDebug() << " FAILED TO PARSE QML OR JS PROPERTY:" << topic << args;
}
+ else if ((topic == COMMAND_QMLMETHOD) || (topic == COMMAND_QMLATTACHEDMETHOD) ||
+ (topic == COMMAND_JSMETHOD) || (topic == COMMAND_JSATTACHEDMETHOD)) {
+ if (node->isFunction()) {
+ FunctionNode* fn = static_cast<FunctionNode*>(node);
+ QmlSignatureParser qsp(fn, args, doc.location());
+ }
+ }
}
}
for (int i=0; i<nodes.size(); ++i)
@@ -232,6 +263,174 @@ bool QmlDocVisitor::applyDocumentation(QQmlJS::AST::SourceLocation location, Nod
return false;
}
+QmlSignatureParser::QmlSignatureParser(FunctionNode* func, const QString& signature, const Location& loc)
+ : signature_(signature), func_(func), location_(loc)
+{
+ QByteArray latin1 = signature.toLatin1();
+ Tokenizer stringTokenizer(location_, latin1);
+ stringTokenizer.setParsingFnOrMacro(true);
+ tokenizer_ = &stringTokenizer;
+ readToken();
+ matchFunctionDecl();
+}
+
+/*!
+ If the current token matches \a target, read the next
+ token and return true. Otherwise, don't read the next
+ token, and return false.
+ */
+bool QmlSignatureParser::match(int target)
+{
+ if (tok_ == target) {
+ readToken();
+ return true;
+ }
+ return false;
+}
+
+/*!
+ Parse a QML data type into \a dataType and an optional
+ variable name into \a var.
+ */
+bool QmlSignatureParser::matchDataType(CodeChunk* dataType, QString* var)
+{
+ /*
+ 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) {
+ while (match(Tok_signed) ||
+ match(Tok_unsigned) ||
+ match(Tok_short) ||
+ match(Tok_long) ||
+ match(Tok_int64)) {
+ dataType->append(previousLexeme());
+ virgin = false;
+ }
+ }
+
+ if (virgin) {
+ if (match(Tok_Ident)) {
+ 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());
+ }
+
+ if (match(Tok_Gulbrandsen))
+ dataType->append(previousLexeme());
+ else
+ break;
+ }
+
+ while (match(Tok_Ampersand) ||
+ match(Tok_Aster) ||
+ match(Tok_const) ||
+ match(Tok_Caret))
+ dataType->append(previousLexeme());
+
+ /*
+ The usual case: Look for an optional identifier, then for
+ some array brackets.
+ */
+ dataType->appendHotspot();
+
+ if ((var != 0) && match(Tok_Ident))
+ *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;
+}
+
+bool QmlSignatureParser::matchParameter()
+{
+ QString name;
+ CodeChunk dataType;
+ CodeChunk defaultValue;
+
+ bool result = matchDataType(&dataType, &name);
+ if (name.isEmpty()) {
+ name = dataType.toString();
+ dataType.clear();
+ }
+
+ if (!result)
+ return false;
+ if (match(Tok_Equal)) {
+ int parenDepth0 = tokenizer_->parenDepth();
+ while (tokenizer_->parenDepth() >= parenDepth0 &&
+ (tok_ != Tok_Comma ||
+ tokenizer_->parenDepth() > parenDepth0) &&
+ tok_ != Tok_Eoi) {
+ defaultValue.append(lexeme());
+ readToken();
+ }
+ }
+ func_->addParameter(Parameter(dataType.toString(), "", name, defaultValue.toString()));
+ return true;
+}
+
+bool QmlSignatureParser::matchFunctionDecl()
+{
+ CodeChunk returnType;
+
+ int firstBlank = signature_.indexOf(QChar(' '));
+ int leftParen = signature_.indexOf(QChar('('));
+ if ((firstBlank > 0) && (leftParen - firstBlank) > 1) {
+ if (!matchDataType(&returnType, 0))
+ return false;
+ }
+
+ while (match(Tok_Ident)) {
+ names_.append(previousLexeme());
+ if (!match(Tok_Gulbrandsen)) {
+ funcName_ = previousLexeme();
+ names_.pop_back();
+ break;
+ }
+ }
+
+ if (tok_ != Tok_LeftParen)
+ return false;
+
+ readToken();
+
+ func_->setLocation(location_);
+ func_->setReturnType(returnType.toString());
+
+ if (tok_ != Tok_RightParen) {
+ func_->clearParams();
+ do {
+ if (!matchParameter())
+ return false;
+ } while (match(Tok_Comma));
+ }
+ if (!match(Tok_RightParen))
+ return false;
+ return true;
+}
+
/*!
A QML property argument has the form...