summaryrefslogtreecommitdiff
path: root/src/qdoc/qmlcodeparser.cpp
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>2015-10-21 15:51:54 +0200
committerOswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>2015-10-23 10:47:25 +0000
commite15ca59111fe05f5ecc0f7fb48c34b5b22115a12 (patch)
tree1f66c3191f4745dea9bf126b8c22a4d8c5a90c58 /src/qdoc/qmlcodeparser.cpp
parent4e2d1893a89ce3dcfaacea091acae1f673c14a9e (diff)
downloadqttools-e15ca59111fe05f5ecc0f7fb48c34b5b22115a12.tar.gz
move qdoc back to qttools
we can do that now, as the bootstrap lib is now a properly exported module, and qmldevtools is now bootstrapped as well. this removes the abomination of a copy of the qml parser in qtbase. unfortunately qtbase/2422251ee5025a067b14b989153764ab36e43f10 is reverted, as qtdeclarative is still missing the respective change. this introduces no regression in discoverability or usability, as a full doc build already needed qttools - for qhelpgenerator. Change-Id: Ic9c4c9732ddf5998637b9e42e27939ba50b31479 Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@theqtcompany.com> Reviewed-by: Martin Smith <martin.smith@digia.com> Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com> Reviewed-by: Topi Reiniö <topi.reinio@digia.com>
Diffstat (limited to 'src/qdoc/qmlcodeparser.cpp')
-rw-r--r--src/qdoc/qmlcodeparser.cpp333
1 files changed, 333 insertions, 0 deletions
diff --git a/src/qdoc/qmlcodeparser.cpp b/src/qdoc/qmlcodeparser.cpp
new file mode 100644
index 000000000..e94df4753
--- /dev/null
+++ b/src/qdoc/qmlcodeparser.cpp
@@ -0,0 +1,333 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ qmlcodeparser.cpp
+*/
+
+#include "qmlcodeparser.h"
+
+#include "node.h"
+#include "config.h"
+#include "qmlvisitor.h"
+
+#include <private/qqmljsast_p.h>
+#include <private/qqmljsastvisitor_p.h>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+#define COMMAND_STARTPAGE Doc::alias("startpage")
+#define COMMAND_VARIABLE Doc::alias("variable")
+
+#define COMMAND_DEPRECATED Doc::alias("deprecated")
+#define COMMAND_INGROUP Doc::alias("ingroup")
+#define COMMAND_INTERNAL Doc::alias("internal")
+#define COMMAND_OBSOLETE Doc::alias("obsolete")
+#define COMMAND_PAGEKEYWORDS Doc::alias("pagekeywords")
+#define COMMAND_PRELIMINARY Doc::alias("preliminary")
+#define COMMAND_SINCE Doc::alias("since")
+#define COMMAND_WRAPPER Doc::alias("wrapper")
+#define COMMAND_NOAUTOLIST Doc::alias("noautolist")
+
+#define COMMAND_ABSTRACT Doc::alias("abstract")
+#define COMMAND_QMLABSTRACT Doc::alias("qmlabstract")
+#define COMMAND_QMLCLASS Doc::alias("qmlclass")
+#define COMMAND_QMLTYPE Doc::alias("qmltype")
+#define COMMAND_QMLMODULE Doc::alias("qmlmodule")
+#define COMMAND_QMLPROPERTY Doc::alias("qmlproperty")
+#define COMMAND_QMLPROPERTYGROUP Doc::alias("qmlpropertygroup")
+#define COMMAND_QMLATTACHEDPROPERTY Doc::alias("qmlattachedproperty")
+#define COMMAND_QMLINHERITS Doc::alias("inherits")
+#define COMMAND_QMLINSTANTIATES Doc::alias("instantiates")
+#define COMMAND_INQMLMODULE Doc::alias("inqmlmodule")
+#define COMMAND_QMLSIGNAL Doc::alias("qmlsignal")
+#define COMMAND_QMLATTACHEDSIGNAL Doc::alias("qmlattachedsignal")
+#define COMMAND_QMLMETHOD Doc::alias("qmlmethod")
+#define COMMAND_QMLATTACHEDMETHOD Doc::alias("qmlattachedmethod")
+#define COMMAND_QMLDEFAULT Doc::alias("default")
+#define COMMAND_QMLREADONLY Doc::alias("readonly")
+#define COMMAND_QMLBASICTYPE Doc::alias("qmlbasictype")
+#define COMMAND_QMLMODULE Doc::alias("qmlmodule")
+
+#define COMMAND_JSTYPE Doc::alias("jstype")
+#define COMMAND_JSMODULE Doc::alias("jsmodule")
+#define COMMAND_JSPROPERTY Doc::alias("jsproperty")
+#define COMMAND_JSPROPERTYGROUP Doc::alias("jspropertygroup")
+#define COMMAND_JSATTACHEDPROPERTY Doc::alias("jsattachedproperty")
+#define COMMAND_INJSMODULE Doc::alias("injsmodule")
+#define COMMAND_JSSIGNAL Doc::alias("jssignal")
+#define COMMAND_JSATTACHEDSIGNAL Doc::alias("jsattachedsignal")
+#define COMMAND_JSMETHOD Doc::alias("jsmethod")
+#define COMMAND_JSATTACHEDMETHOD Doc::alias("jsattachedmethod")
+#define COMMAND_JSBASICTYPE Doc::alias("jsbasictype")
+#define COMMAND_JSMODULE Doc::alias("jsmodule")
+
+/*!
+ Constructs the QML code parser.
+ */
+QmlCodeParser::QmlCodeParser()
+ : lexer( 0 ),
+ parser( 0 )
+{
+}
+
+/*!
+ Destroys the QML code parser.
+ */
+QmlCodeParser::~QmlCodeParser()
+{
+}
+
+/*!
+ Initializes the code parser base class. The \a config argument
+ is passed to the initialization functions in the base class.
+
+ Also creates a lexer and parser from QQmlJS.
+ */
+void QmlCodeParser::initializeParser(const Config &config)
+{
+ CodeParser::initializeParser(config);
+
+ lexer = new QQmlJS::Lexer(&engine);
+ parser = new QQmlJS::Parser(&engine);
+}
+
+/*!
+ Terminates the QML code parser. Deletes the lexer and parser
+ created by the constructor.
+ */
+void QmlCodeParser::terminateParser()
+{
+ delete lexer;
+ delete parser;
+}
+
+/*!
+ Returns "QML".
+ */
+QString QmlCodeParser::language()
+{
+ return "QML";
+}
+
+/*!
+ Returns a string list containing "*.qml". This is the only
+ file type parsed by the QMLN parser.
+ */
+QStringList QmlCodeParser::sourceFileNameFilter()
+{
+ return QStringList() << "*.qml";
+}
+
+/*!
+ Parses the source file at \a filePath and inserts the contents
+ into the database. The \a location is used for error reporting.
+
+ If it can't open the file at \a filePath, it reports an error
+ and returns without doing anything.
+ */
+void QmlCodeParser::parseSourceFile(const Location& location, const QString& filePath)
+{
+ QFile in(filePath);
+ currentFile_ = filePath;
+ if (!in.open(QIODevice::ReadOnly)) {
+ location.error(tr("Cannot open QML file '%1'").arg(filePath));
+ currentFile_.clear();
+ return;
+ }
+
+ QString document = in.readAll();
+ in.close();
+
+ Location fileLocation(filePath);
+
+ QString newCode = document;
+ extractPragmas(newCode);
+ lexer->setCode(newCode, 1);
+
+ const QSet<QString>& topicCommandsAllowed = topicCommands();
+ const QSet<QString>& otherMetacommandsAllowed = otherMetaCommands();
+ const QSet<QString>& metacommandsAllowed = topicCommandsAllowed + otherMetacommandsAllowed;
+
+ if (parser->parse()) {
+ QQmlJS::AST::UiProgram *ast = parser->ast();
+ QmlDocVisitor visitor(filePath,
+ newCode,
+ &engine,
+ metacommandsAllowed,
+ topicCommandsAllowed);
+ QQmlJS::AST::Node::accept(ast, &visitor);
+ }
+ foreach (const QQmlJS::DiagnosticMessage &msg, parser->diagnosticMessages()) {
+ qDebug().nospace() << qPrintable(filePath) << ':' << msg.loc.startLine
+ << ": QML syntax error at col " << msg.loc.startColumn
+ << ": " << qPrintable(msg.message);
+ }
+ currentFile_.clear();
+}
+
+/*!
+ Performs cleanup after qdoc is done parsing all the QML files.
+ Currently, no cleanup is required.
+ */
+void QmlCodeParser::doneParsingSourceFiles()
+{
+}
+
+static QSet<QString> topicCommands_;
+/*!
+ Returns the set of strings representing the topic commands.
+ */
+const QSet<QString>& QmlCodeParser::topicCommands()
+{
+ if (topicCommands_.isEmpty()) {
+ topicCommands_ << COMMAND_VARIABLE
+ << COMMAND_QMLCLASS
+ << COMMAND_QMLTYPE
+ << COMMAND_QMLPROPERTY
+ << COMMAND_QMLPROPERTYGROUP
+ << COMMAND_QMLATTACHEDPROPERTY
+ << COMMAND_QMLSIGNAL
+ << COMMAND_QMLATTACHEDSIGNAL
+ << COMMAND_QMLMETHOD
+ << COMMAND_QMLATTACHEDMETHOD
+ << COMMAND_QMLBASICTYPE
+ << COMMAND_JSTYPE
+ << COMMAND_JSPROPERTY
+ << COMMAND_JSPROPERTYGROUP
+ << COMMAND_JSATTACHEDPROPERTY
+ << COMMAND_JSSIGNAL
+ << COMMAND_JSATTACHEDSIGNAL
+ << COMMAND_JSMETHOD
+ << COMMAND_JSATTACHEDMETHOD
+ << COMMAND_JSBASICTYPE;
+ }
+ return topicCommands_;
+}
+
+static QSet<QString> otherMetaCommands_;
+/*!
+ Returns the set of strings representing the common metacommands
+ plus some other metacommands.
+ */
+const QSet<QString>& QmlCodeParser::otherMetaCommands()
+{
+ if (otherMetaCommands_.isEmpty()) {
+ otherMetaCommands_ = commonMetaCommands();
+ otherMetaCommands_ << COMMAND_STARTPAGE
+ << COMMAND_QMLINHERITS
+ << COMMAND_QMLDEFAULT
+ << COMMAND_QMLREADONLY
+ << COMMAND_DEPRECATED
+ << COMMAND_INGROUP
+ << COMMAND_INTERNAL
+ << COMMAND_OBSOLETE
+ << COMMAND_PRELIMINARY
+ << COMMAND_SINCE
+ << COMMAND_ABSTRACT
+ << COMMAND_QMLABSTRACT
+ << COMMAND_INQMLMODULE
+ << COMMAND_INJSMODULE
+ << COMMAND_WRAPPER
+ << COMMAND_NOAUTOLIST;
+ }
+ return otherMetaCommands_;
+}
+
+/*!
+ Copy and paste from src/declarative/qml/qdeclarativescriptparser.cpp.
+ This function blanks out the section of the \a str beginning at \a idx
+ and running for \a n characters.
+*/
+static void replaceWithSpace(QString &str, int idx, int n)
+{
+ QChar *data = str.data() + idx;
+ const QChar space(QLatin1Char(' '));
+ for (int ii = 0; ii < n; ++ii)
+ *data++ = space;
+}
+
+/*!
+ Copy & paste from src/declarative/qml/qdeclarativescriptparser.cpp,
+ then modified to return no values.
+
+ Searches for ".pragma <value>" declarations within \a script.
+ Currently supported pragmas are: library
+*/
+void QmlCodeParser::extractPragmas(QString &script)
+{
+ const QString pragma(QLatin1String("pragma"));
+ const QString library(QLatin1String("library"));
+
+ QQmlJS::Lexer l(0);
+ l.setCode(script, 0);
+
+ int token = l.lex();
+
+ while (true) {
+ if (token != QQmlJSGrammar::T_DOT)
+ return;
+
+ int startOffset = l.tokenOffset();
+ int startLine = l.tokenStartLine();
+
+ token = l.lex();
+
+ if (token != QQmlJSGrammar::T_IDENTIFIER ||
+ l.tokenStartLine() != startLine ||
+ script.mid(l.tokenOffset(), l.tokenLength()) != pragma)
+ return;
+
+ token = l.lex();
+
+ if (token != QQmlJSGrammar::T_IDENTIFIER ||
+ l.tokenStartLine() != startLine)
+ return;
+
+ QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength());
+ int endOffset = l.tokenLength() + l.tokenOffset();
+
+ token = l.lex();
+ if (l.tokenStartLine() == startLine)
+ return;
+
+ if (pragmaValue == QLatin1String("library"))
+ replaceWithSpace(script, startOffset, endOffset - startOffset);
+ else
+ return;
+ }
+ return;
+}
+
+QT_END_NAMESPACE