summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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...