QMLJS: update to qmljsparser from Qt 5.6

Change-Id: I29a8e07b0b34aa5e8466021cbb71450687f7e11c
Reviewed-by: Tim Jenssen <tim.jenssen@theqtcompany.com>
This commit is contained in:
Tim Jenssen
2016-04-29 11:00:30 +02:00
parent 5c45e9ec34
commit c90a356be6
18 changed files with 1503 additions and 1279 deletions

View File

@@ -46,5 +46,3 @@ sed -i -e 's|#include <QtCore/qset.h>|#include <QSet>|g' $me/qmljsengine_p.h
perl -p -0777 -i -e 's/QT_QML_BEGIN_NAMESPACE/#include <qmljs\/qmljsconstants.h>\nQT_QML_BEGIN_NAMESPACE/' qmljsengine_p.h
./changeLicense.py $me/../qmljs_global.h qml*.{cpp,h}
#patch -R -p5 < parser.patch

View File

@@ -26,8 +26,6 @@
#include "qmldirparser_p.h"
#include "qmlerror.h"
#include <QtCore/QtDebug>
QT_BEGIN_NAMESPACE
@@ -49,7 +47,20 @@ static int parseInt(const QStringRef &str, bool *ok)
return number;
}
QmlDirParser::QmlDirParser()
static bool parseVersion(const QString &str, int *major, int *minor)
{
const int dotIndex = str.indexOf(QLatin1Char('.'));
if (dotIndex != -1 && str.indexOf(QLatin1Char('.'), dotIndex + 1) == -1) {
bool ok = false;
*major = parseInt(QStringRef(&str, 0, dotIndex), &ok);
if (ok)
*minor = parseInt(QStringRef(&str, dotIndex + 1, str.length() - dotIndex - 1), &ok);
return ok;
}
return false;
}
QmlDirParser::QmlDirParser() : _designerSupported(false)
{
}
@@ -81,6 +92,7 @@ bool QmlDirParser::parse(const QString &source)
_plugins.clear();
_components.clear();
_scripts.clear();
_designerSupported = false;
quint16 lineNumber = 0;
bool firstLine = true;
@@ -126,7 +138,7 @@ bool QmlDirParser::parse(const QString &source)
if (invalidLine) {
reportError(lineNumber, 0,
QString::fromLatin1("invalid qmldir directive contains too many tokens"));
QStringLiteral("invalid qmldir directive contains too many tokens"));
continue;
} else if (sectionCount == 0) {
continue; // no sections, no party.
@@ -134,17 +146,17 @@ bool QmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("module")) {
if (sectionCount != 2) {
reportError(lineNumber, 0,
QString::fromLatin1("module identifier directive requires one argument, but %1 were provided").arg(sectionCount - 1));
QStringLiteral("module identifier directive requires one argument, but %1 were provided").arg(sectionCount - 1));
continue;
}
if (!_typeNamespace.isEmpty()) {
reportError(lineNumber, 0,
QString::fromLatin1("only one module identifier directive may be defined in a qmldir file"));
QStringLiteral("only one module identifier directive may be defined in a qmldir file"));
continue;
}
if (!firstLine) {
reportError(lineNumber, 0,
QString::fromLatin1("module identifier directive must be the first directive in a qmldir file"));
QStringLiteral("module identifier directive must be the first directive in a qmldir file"));
continue;
}
@@ -153,7 +165,7 @@ bool QmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("plugin")) {
if (sectionCount < 2 || sectionCount > 3) {
reportError(lineNumber, 0,
QString::fromLatin1("plugin directive requires one or two arguments, but %1 were provided").arg(sectionCount - 1));
QStringLiteral("plugin directive requires one or two arguments, but %1 were provided").arg(sectionCount - 1));
continue;
}
@@ -165,7 +177,7 @@ bool QmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("internal")) {
if (sectionCount != 3) {
reportError(lineNumber, 0,
QString::fromLatin1("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1));
QStringLiteral("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1));
continue;
}
Component entry(sections[1], sections[2], -1, -1);
@@ -174,7 +186,7 @@ bool QmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("singleton")) {
if (sectionCount < 3 || sectionCount > 4) {
reportError(lineNumber, 0,
QString::fromLatin1("singleton types require 2 or 3 arguments, but %1 were provided").arg(sectionCount - 1));
QStringLiteral("singleton types require 2 or 3 arguments, but %1 were provided").arg(sectionCount - 1));
continue;
} else if (sectionCount == 3) {
// handle qmldir directory listing case where singleton is defined in the following pattern:
@@ -185,33 +197,20 @@ bool QmlDirParser::parse(const QString &source)
} else {
// handle qmldir module listing case where singleton is defined in the following pattern:
// singleton TestSingletonType 2.0 TestSingletonType20.qml
const QString &version = sections[2];
const int dotIndex = version.indexOf(QLatin1Char('.'));
if (dotIndex == -1) {
reportError(lineNumber, 0, QLatin1String("expected '.'"));
} else if (version.indexOf(QLatin1Char('.'), dotIndex + 1) != -1) {
reportError(lineNumber, 0, QLatin1String("unexpected '.'"));
int major, minor;
if (parseVersion(sections[2], &major, &minor)) {
const QString &fileName = sections[3];
Component entry(sections[1], fileName, major, minor);
entry.singleton = true;
_components.insertMulti(entry.typeName, entry);
} else {
bool validVersionNumber = false;
const int majorVersion = parseInt(QStringRef(&version, 0, dotIndex), &validVersionNumber);
if (validVersionNumber) {
const int minorVersion = parseInt(QStringRef(&version, dotIndex+1, version.length()-dotIndex-1), &validVersionNumber);
if (validVersionNumber) {
const QString &fileName = sections[3];
Component entry(sections[1], fileName, majorVersion, minorVersion);
entry.singleton = true;
_components.insertMulti(entry.typeName, entry);
}
}
reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected <major>.<minor>").arg(sections[2]));
}
}
} else if (sections[0] == QLatin1String("typeinfo")) {
if (sectionCount != 2) {
reportError(lineNumber, 0,
QString::fromLatin1("typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1));
QStringLiteral("typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1));
continue;
}
#ifdef QT_CREATOR
@@ -219,42 +218,49 @@ bool QmlDirParser::parse(const QString &source)
_typeInfos.append(typeInfo);
#endif
} else if (sections[0] == QLatin1String("designersupported")) {
if (sectionCount != 1)
reportError(lineNumber, 0, QStringLiteral("designersupported does not expect any argument"));
else
_designerSupported = true;
} else if (sections[0] == QLatin1String("depends")) {
if (sectionCount != 3) {
reportError(lineNumber, 0,
QStringLiteral("depends requires 2 arguments, but %1 were provided").arg(sectionCount - 1));
continue;
}
int major, minor;
if (parseVersion(sections[2], &major, &minor)) {
Component entry(sections[1], QString(), major, minor);
entry.internal = true;
_dependencies.insert(entry.typeName, entry);
} else {
reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected <major>.<minor>").arg(sections[2]));
}
} else if (sectionCount == 2) {
// No version specified (should only be used for relative qmldir files)
const Component entry(sections[0], sections[1], -1, -1);
_components.insertMulti(entry.typeName, entry);
} else if (sectionCount == 3) {
const QString &version = sections[1];
const int dotIndex = version.indexOf(QLatin1Char('.'));
int major, minor;
if (parseVersion(sections[1], &major, &minor)) {
const QString &fileName = sections[2];
if (dotIndex == -1) {
reportError(lineNumber, 0, QLatin1String("expected '.'"));
} else if (version.indexOf(QLatin1Char('.'), dotIndex + 1) != -1) {
reportError(lineNumber, 0, QLatin1String("unexpected '.'"));
} else {
bool validVersionNumber = false;
const int majorVersion = parseInt(QStringRef(&version, 0, dotIndex), &validVersionNumber);
if (validVersionNumber) {
const int minorVersion = parseInt(QStringRef(&version, dotIndex+1, version.length()-dotIndex-1), &validVersionNumber);
if (validVersionNumber) {
const QString &fileName = sections[2];
if (fileName.endsWith(QLatin1String(".js"))) {
// A 'js' extension indicates a namespaced script import
const Script entry(sections[0], fileName, majorVersion, minorVersion);
_scripts.append(entry);
} else {
const Component entry(sections[0], fileName, majorVersion, minorVersion);
_components.insertMulti(entry.typeName, entry);
}
}
if (fileName.endsWith(QLatin1String(".js"))) {
// A 'js' extension indicates a namespaced script import
const Script entry(sections[0], fileName, major, minor);
_scripts.append(entry);
} else {
const Component entry(sections[0], fileName, major, minor);
_components.insertMulti(entry.typeName, entry);
}
} else {
reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected <major>.<minor>").arg(sections[1]));
}
} else {
reportError(lineNumber, 0,
QString::fromLatin1("a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount));
QStringLiteral("a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount));
}
firstLine = false;
@@ -265,10 +271,10 @@ bool QmlDirParser::parse(const QString &source)
void QmlDirParser::reportError(quint16 line, quint16 column, const QString &description)
{
QmlError error;
error.setLine(line);
error.setColumn(column);
error.setDescription(description);
QmlJS::DiagnosticMessage error;
error.loc.startLine = line;
error.loc.startColumn = column;
error.message = description;
_errors.append(error);
}
@@ -283,19 +289,25 @@ bool QmlDirParser::hasError() const
void QmlDirParser::setError(const QmlError &e)
{
_errors.clear();
_errors.append(e);
reportError(e.line(), e.column(), e.description());
}
QList<QmlError> QmlDirParser::errors(const QString &uri) const
{
QUrl url(uri);
QList<QmlError> errors = _errors;
for (int i = 0; i < errors.size(); ++i) {
QmlError &e = errors[i];
QString description = e.description();
QList<QmlError> errors;
const int numErrors = _errors.size();
errors.reserve(numErrors);
for (int i = 0; i < numErrors; ++i) {
const QmlJS::DiagnosticMessage &msg = _errors.at(i);
QmlError e;
QString description = msg.message;
description.replace(QLatin1String("$$URI$$"), uri);
e.setDescription(description);
e.setUrl(url);
e.setLine(msg.loc.startLine);
e.setColumn(msg.loc.startColumn);
errors << e;
}
return errors;
}
@@ -315,11 +327,16 @@ QList<QmlDirParser::Plugin> QmlDirParser::plugins() const
return _plugins;
}
QHash<QString,QmlDirParser::Component> QmlDirParser::components() const
QHash<QString, QmlDirParser::Component> QmlDirParser::components() const
{
return _components;
}
QHash<QString, QmlDirParser::Component> QmlDirParser::dependencies() const
{
return _dependencies;
}
QList<QmlDirParser::Script> QmlDirParser::scripts() const
{
return _scripts;
@@ -332,16 +349,21 @@ QList<QmlDirParser::TypeInfo> QmlDirParser::typeInfos() const
}
#endif
bool QmlDirParser::designerSupported() const
{
return _designerSupported;
}
QDebug &operator<< (QDebug &debug, const QmlDirParser::Component &component)
{
const QString output = QString::fromLatin1("{%1 %2.%3}").
const QString output = QStringLiteral("{%1 %2.%3}").
arg(component.typeName).arg(component.majorVersion).arg(component.minorVersion);
return debug << qPrintable(output);
}
QDebug &operator<< (QDebug &debug, const QmlDirParser::Script &script)
{
const QString output = QString::fromLatin1("{%1 %2.%3}").
const QString output = QStringLiteral("{%1 %2.%3}").
arg(script.nameSpace).arg(script.majorVersion).arg(script.minorVersion);
return debug << qPrintable(output);
}

View File

@@ -40,8 +40,7 @@
#include <QtCore/QHash>
#include <QtCore/QDebug>
#include "qmljsglobal_p.h"
#include "qmljsengine_p.h"
QT_BEGIN_NAMESPACE
@@ -107,8 +106,10 @@ public:
};
QHash<QString,Component> components() const;
QHash<QString,Component> dependencies() const;
QList<Script> scripts() const;
QList<Plugin> plugins() const;
bool designerSupported() const;
#ifdef QT_CREATOR
struct TypeInfo
@@ -124,14 +125,17 @@ public:
#endif
private:
bool maybeAddComponent(const QString &typeName, const QString &fileName, const QString &version, QHash<QString,Component> &hash, int lineNumber = -1, bool multi = true);
void reportError(quint16 line, quint16 column, const QString &message);
private:
QList<QmlError> _errors;
QList<QmlJS::DiagnosticMessage> _errors;
QString _typeNamespace;
QHash<QString,Component> _components; // multi hash
QHash<QString,Component> _dependencies;
QList<Script> _scripts;
QList<Plugin> _plugins;
bool _designerSupported;
#ifdef QT_CREATOR
QList<TypeInfo> _typeInfos;
#endif

View File

@@ -48,8 +48,8 @@ QT_BEGIN_NAMESPACE
file:///home/user/test.qml:7:8: Invalid property assignment: double expected
\endcode
You can use qDebug() or qWarning() to output errors to the console. This method
will attempt to open the file indicated by the error
You can use qDebug(), qInfo(), or qWarning() to output errors to the console.
This method will attempt to open the file indicated by the error
and include additional contextual information.
\code
file:///home/user/test.qml:7:8: Invalid property assignment: double expected
@@ -239,16 +239,17 @@ QString QmlError::toString() const
QUrl u(url());
int l(line());
if (u.isEmpty()) {
if (u.isEmpty() || (u.isLocalFile() && u.path().isEmpty()))
rv = QLatin1String("<Unknown File>");
} else if (l != -1) {
rv = u.toString() + QLatin1Char(':') + QString::number(l);
else
rv = u.toString();
if (l != -1) {
rv += QLatin1Char(':') + QString::number(l);
int c(column());
if (c != -1)
rv += QLatin1Char(':') + QString::number(c);
} else {
rv = u.toString();
}
rv += QLatin1String(": ") + description();

View File

@@ -1,22 +1,31 @@
----------------------------------------------------------------------------
--
-- Copyright (C) 2015 The Qt Company Ltd.
-- Contact: https://www.qt.io/licensing/
-- Contact: http://www.qt.io/licensing/
--
-- This file is part of the QtQml module of the Qt Toolkit.
--
-- $QT_BEGIN_LICENSE:LGPL-ONLY$
-- $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
-- This file may be used under the terms of the GNU Lesser
-- 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
-- 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.
--
-- If you have questions regarding the use of this file, please contact
-- us via http://www.qt.io/contact-us.
-- 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$
--
@@ -90,38 +99,32 @@
/./****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** $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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** 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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
** 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.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.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$
**
@@ -141,43 +144,38 @@
/:/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** $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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** 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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
** 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.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
@@ -507,7 +505,24 @@ bool Parser::parse(int startToken)
token_buffer[0].token = startToken;
first_token = &token_buffer[0];
last_token = &token_buffer[1];
if (startToken == T_FEED_JS_PROGRAM && !lexer->qmlMode()) {
Directives ignoreDirectives;
Directives *directives = driver->directives();
if (!directives)
directives = &ignoreDirectives;
DiagnosticMessage error;
if (!lexer->scanDirectives(directives, &error)) {
diagnostic_messages.append(error);
return false;
}
token_buffer[1].token = lexer->tokenKind();
token_buffer[1].dval = lexer->tokenValue();
token_buffer[1].loc = location(lexer);
token_buffer[1].spell = lexer->tokenSpell();
last_token = &token_buffer[2];
} else {
last_token = &token_buffer[1];
}
tos = -1;
program = 0;
@@ -1085,6 +1100,31 @@ case $rule_number: {
} break;
./
UiObjectMember: T_READONLY T_PROPERTY UiPropertyType JsIdentifier T_COLON UiQualifiedId UiObjectInitializer ;
/.
case $rule_number: {
AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4));
node->isReadonlyMember = true;
node->readonlyToken = loc(1);
node->propertyToken = loc(2);
node->typeToken = loc(3);
node->identifierToken = loc(4);
node->semicolonToken = loc(5); // insert a fake ';' before ':'
AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(4));
propertyName->identifierToken = loc(4);
propertyName->next = 0;
AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding(
propertyName, sym(6).UiQualifiedId, sym(7).UiObjectInitializer);
binding->colonToken = loc(5);
node->binding = binding;
sym(1).Node = node;
} break;
./
UiObjectMember: FunctionDeclaration ;
/.
case $rule_number: {
@@ -3031,9 +3071,9 @@ PropertyAssignmentListOpt: PropertyAssignmentList ;
QString msg;
int token = token_buffer[0].token;
if (token < 0 || token >= TERMINAL_COUNT)
msg = qApp->translate("QmlParser", "Syntax error");
msg = QCoreApplication::translate("QmlParser", "Syntax error");
else
msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token]));
msg = QCoreApplication::translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token]));
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
action = errorState;
@@ -3061,7 +3101,7 @@ PropertyAssignmentListOpt: PropertyAssignmentList ;
for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) {
int a = t_action(errorState, *tk);
if (a > 0 && t_action(a, yytoken)) {
const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk]));
const QString msg = QCoreApplication::translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk]));
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
yytoken = *tk;
@@ -3085,7 +3125,7 @@ PropertyAssignmentListOpt: PropertyAssignmentList ;
int a = t_action(errorState, tk);
if (a > 0 && t_action(a, yytoken)) {
const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk]));
const QString msg = QCoreApplication::translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk]));
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
yytoken = tk;
@@ -3098,7 +3138,7 @@ PropertyAssignmentListOpt: PropertyAssignmentList ;
}
}
const QString msg = qApp->translate("QmlParser", "Syntax error");
const QString msg = QCoreApplication::translate("QmlParser", "Syntax error");
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
}

View File

@@ -94,11 +94,11 @@ namespace QmlJS {
namespace AST {
template <typename _T1, typename _T2>
_T1 cast(_T2 *ast)
template <typename T1, typename T2>
T1 cast(T2 *ast)
{
if (ast && ast->kind == static_cast<_T1>(0)->K)
return static_cast<_T1>(ast);
if (ast && ast->kind == static_cast<T1>(0)->K)
return static_cast<T1>(ast);
return 0;
}
@@ -586,6 +586,8 @@ public:
virtual SourceLocation lastSourceLocation() const
{ return propertyNameToken; }
virtual QString asString() const = 0;
// attributes
SourceLocation propertyNameToken;
};
@@ -593,7 +595,11 @@ public:
class QML_PARSER_EXPORT PropertyAssignment: public Node
{
public:
PropertyAssignment() {}
PropertyAssignment(PropertyName *n)
: name(n)
{}
// attributes
PropertyName *name;
};
class QML_PARSER_EXPORT PropertyAssignmentList: public Node
@@ -641,7 +647,7 @@ public:
QMLJS_DECLARE_AST_NODE(PropertyNameAndValue)
PropertyNameAndValue(PropertyName *n, ExpressionNode *v)
: name(n), value(v)
: PropertyAssignment(n), value(v)
{ kind = K; }
virtual void accept0(Visitor *visitor);
@@ -653,7 +659,6 @@ public:
{ return value->lastSourceLocation(); }
// attributes
PropertyName *name;
SourceLocation colonToken;
ExpressionNode *value;
SourceLocation commaToken;
@@ -670,11 +675,11 @@ public:
};
PropertyGetterSetter(PropertyName *n, FunctionBody *b)
: type(Getter), name(n), formals(0), functionBody (b)
: PropertyAssignment(n), type(Getter), formals(0), functionBody (b)
{ kind = K; }
PropertyGetterSetter(PropertyName *n, FormalParameterList *f, FunctionBody *b)
: type(Setter), name(n), formals(f), functionBody (b)
: PropertyAssignment(n), type(Setter), formals(f), functionBody (b)
{ kind = K; }
virtual void accept0(Visitor *visitor);
@@ -688,7 +693,6 @@ public:
// attributes
Type type;
SourceLocation getSetToken;
PropertyName *name;
SourceLocation lparenToken;
FormalParameterList *formals;
SourceLocation rparenToken;
@@ -707,6 +711,8 @@ public:
virtual void accept0(Visitor *visitor);
virtual QString asString() const { return id.toString(); }
// attributes
QStringRef id;
};
@@ -721,6 +727,8 @@ public:
virtual void accept0(Visitor *visitor);
virtual QString asString() const { return id.toString(); }
// attributes
QStringRef id;
};
@@ -735,6 +743,8 @@ public:
virtual void accept0(Visitor *visitor);
virtual QString asString() const { return QString::number(id, 'g', 16); }
// attributes
double id;
};

View File

@@ -47,7 +47,7 @@ namespace QmlJS { namespace AST {
class SourceLocation
{
public:
SourceLocation(quint32 offset = 0, quint32 length = 0, quint32 line = 0, quint32 column = 0)
explicit SourceLocation(quint32 offset = 0, quint32 length = 0, quint32 line = 0, quint32 column = 0)
: offset(offset), length(length),
startLine(line), startColumn(column)
{ }

View File

@@ -127,12 +127,12 @@ Lexer *Engine::lexer() const
void Engine::setLexer(Lexer *lexer)
{ _lexer = lexer; }
void Engine::setDirectives(Directives *directives)
{ _directives = directives; }
Directives *Engine::directives() const
{ return _directives; }
void Engine::setDirectives(Directives *directives)
{ _directives = directives; }
MemoryPool *Engine::pool()
{ return &_pool; }

View File

@@ -39,11 +39,11 @@
#include "qmljsglobal_p.h"
#include "qmljsastfwd_p.h"
#include "qmljsmemorypool_p.h"
#include <qmljs/qmljsconstants.h>
#include <QString>
#include <QSet>
#include <qmljs/qmljsconstants.h>
QT_QML_BEGIN_NAMESPACE
namespace QmlJS {
@@ -94,8 +94,8 @@ public:
Lexer *lexer() const;
void setLexer(Lexer *lexer);
void setDirectives(Directives *directives);
Directives *directives() const;
void setDirectives(Directives *directives);
MemoryPool *pool();

View File

@@ -25,6 +25,17 @@
#pragma once
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qglobal.h>
#ifdef QT_CREATOR
@@ -46,8 +57,8 @@
// QmlDevTools is a static library
# define QML_PARSER_EXPORT
# elif defined(QT_BUILD_QML_LIB)
# define QML_PARSER_EXPORT Q_AUTOTEST_EXPORT
# define QML_PARSER_EXPORT Q_DECL_EXPORT
# else
# define QML_PARSER_EXPORT
# define QML_PARSER_EXPORT Q_DECL_IMPORT
# endif
#endif // QT_CREATOR

File diff suppressed because it is too large Load Diff

View File

@@ -153,15 +153,15 @@ public:
T_XOR = 79,
T_XOR_EQ = 80,
ACCEPT_STATE = 663,
RULE_COUNT = 357,
STATE_COUNT = 664,
ACCEPT_STATE = 665,
RULE_COUNT = 358,
STATE_COUNT = 666,
TERMINAL_COUNT = 106,
NON_TERMINAL_COUNT = 111,
GOTO_INDEX_OFFSET = 664,
GOTO_INFO_OFFSET = 3104,
GOTO_CHECK_OFFSET = 3104
GOTO_INDEX_OFFSET = 666,
GOTO_INFO_OFFSET = 3018,
GOTO_CHECK_OFFSET = 3018
};
static const char *const spell [];

View File

@@ -341,7 +341,7 @@ static inline bool isIdentifierStart(QChar ch)
// fast path for ascii
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') ||
(ch.unicode() >= 'A' && ch.unicode() <= 'Z') ||
ch == QLatin1Char('$') || ch == QLatin1Char('_'))
ch == '$' || ch == '_')
return true;
switch (ch.category()) {
@@ -364,7 +364,7 @@ static bool isIdentifierPart(QChar ch)
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') ||
(ch.unicode() >= 'A' && ch.unicode() <= 'Z') ||
(ch.unicode() >= '0' && ch.unicode() <= '9') ||
ch == QLatin1Char('$') || ch == QLatin1Char('_') ||
ch == '$' || ch == '_' ||
ch.unicode() == 0x200c /* ZWNJ */ || ch.unicode() == 0x200d /* ZWJ */)
return true;
@@ -691,7 +691,7 @@ again:
_validTokenText = true;
_tokenText.resize(0);
startCode--;
while (startCode != _codePtr - 1)
while (startCode != _codePtr - 1)
_tokenText += *startCode++;
while (_codePtr <= _endPtr) {
@@ -879,8 +879,7 @@ again:
int Lexer::scanNumber(QChar ch)
{
if (ch != QLatin1Char('0')) {
QByteArray buf;
buf.reserve(64);
QVarLengthArray<char, 64> buf;
buf += ch.toLatin1();
QChar n = _char;
@@ -1217,12 +1216,60 @@ bool Lexer::canInsertAutomaticSemicolon(int token) const
|| _followsClosingBrace;
}
bool Lexer::scanDirectives(Directives *directives)
static const int uriTokens[] = {
QmlJSGrammar::T_IDENTIFIER,
QmlJSGrammar::T_PROPERTY,
QmlJSGrammar::T_SIGNAL,
QmlJSGrammar::T_READONLY,
QmlJSGrammar::T_ON,
QmlJSGrammar::T_BREAK,
QmlJSGrammar::T_CASE,
QmlJSGrammar::T_CATCH,
QmlJSGrammar::T_CONTINUE,
QmlJSGrammar::T_DEFAULT,
QmlJSGrammar::T_DELETE,
QmlJSGrammar::T_DO,
QmlJSGrammar::T_ELSE,
QmlJSGrammar::T_FALSE,
QmlJSGrammar::T_FINALLY,
QmlJSGrammar::T_FOR,
QmlJSGrammar::T_FUNCTION,
QmlJSGrammar::T_IF,
QmlJSGrammar::T_IN,
QmlJSGrammar::T_INSTANCEOF,
QmlJSGrammar::T_NEW,
QmlJSGrammar::T_NULL,
QmlJSGrammar::T_RETURN,
QmlJSGrammar::T_SWITCH,
QmlJSGrammar::T_THIS,
QmlJSGrammar::T_THROW,
QmlJSGrammar::T_TRUE,
QmlJSGrammar::T_TRY,
QmlJSGrammar::T_TYPEOF,
QmlJSGrammar::T_VAR,
QmlJSGrammar::T_VOID,
QmlJSGrammar::T_WHILE,
QmlJSGrammar::T_CONST,
QmlJSGrammar::T_DEBUGGER,
QmlJSGrammar::T_RESERVED_WORD,
QmlJSGrammar::T_WITH,
QmlJSGrammar::EOF_SYMBOL
};
static inline bool isUriToken(int token)
{
if (_qmlMode) {
// the directives are a Javascript-only extension.
return false;
const int *current = uriTokens;
while (*current != QmlJSGrammar::EOF_SYMBOL) {
if (*current == token)
return true;
++current;
}
return false;
}
bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
{
Q_ASSERT(!_qmlMode);
lex(); // fetch the first token
@@ -1230,24 +1277,33 @@ bool Lexer::scanDirectives(Directives *directives)
return true;
do {
const int lineNumber = tokenStartLine();
const int column = tokenStartColumn();
lex(); // skip T_DOT
const int lineNumber = tokenStartLine();
if (! (_tokenKind == T_IDENTIFIER || _tokenKind == T_RESERVED_WORD))
return false; // expected a valid QML/JS directive
return true; // expected a valid QML/JS directive
const QString directiveName = tokenText();
if (! (directiveName == QLatin1String("pragma") ||
directiveName == QLatin1String("import")))
directiveName == QLatin1String("import"))) {
error->message = QCoreApplication::translate("QmlParser", "Syntax error");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false; // not a valid directive name
}
// it must be a pragma or an import directive.
if (directiveName == QLatin1String("pragma")) {
// .pragma library
if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("library")))
if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("library"))) {
error->message = QCoreApplication::translate("QmlParser", "Syntax error");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false; // expected `library
}
// we found a .pragma library directive
directives->pragmaLibrary();
@@ -1266,22 +1322,53 @@ bool Lexer::scanDirectives(Directives *directives)
fileImport = true;
pathOrUri = tokenText();
if (!pathOrUri.endsWith(QLatin1String("js"))) {
error->message = QCoreApplication::translate("QmlParser","Imported file must be a script");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false;
}
} else if (_tokenKind == T_IDENTIFIER) {
// .import T_IDENTIFIER (. T_IDENTIFIER)* T_NUMERIC_LITERAL as T_IDENTIFIER
pathOrUri = tokenText();
lex(); // skip the first T_IDENTIFIER
for (; _tokenKind == T_DOT; lex()) {
if (lex() != T_IDENTIFIER)
while (true) {
if (!isUriToken(_tokenKind)) {
error->message = QCoreApplication::translate("QmlParser","Invalid module URI");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false;
}
pathOrUri += QLatin1Char('.');
pathOrUri += tokenText();
pathOrUri.append(tokenText());
lex();
if (tokenStartLine() != lineNumber) {
error->message = QCoreApplication::translate("QmlParser","Invalid module URI");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false;
}
if (_tokenKind != QmlJSGrammar::T_DOT)
break;
pathOrUri.append(QLatin1Char('.'));
lex();
if (tokenStartLine() != lineNumber) {
error->message = QCoreApplication::translate("QmlParser","Invalid module URI");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false;
}
}
if (_tokenKind != T_NUMERIC_LITERAL)
if (_tokenKind != T_NUMERIC_LITERAL) {
error->message = QCoreApplication::translate("QmlParser","Module import requires a version");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false; // expected the module version number
}
version = tokenText();
}
@@ -1289,22 +1376,51 @@ bool Lexer::scanDirectives(Directives *directives)
//
// recognize the mandatory `as' followed by the module name
//
if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("as")))
if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("as") && tokenStartLine() == lineNumber)) {
if (fileImport)
error->message = QCoreApplication::translate("QmlParser", "File import requires a qualifier");
else
error->message = QCoreApplication::translate("QmlParser", "Module import requires a qualifier");
if (tokenStartLine() != lineNumber) {
error->loc.startLine = lineNumber;
error->loc.startColumn = column;
} else {
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
}
return false; // expected `as'
}
if (lex() != T_IDENTIFIER)
if (lex() != T_IDENTIFIER || tokenStartLine() != lineNumber) {
if (fileImport)
error->message = QCoreApplication::translate("QmlParser", "File import requires a qualifier");
else
error->message = QCoreApplication::translate("QmlParser", "Module import requires a qualifier");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false; // expected module name
}
const QString module = tokenText();
if (!module.at(0).isUpper()) {
error->message = QCoreApplication::translate("QmlParser","Invalid import qualifier");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false;
}
if (fileImport)
directives->importFile(pathOrUri, module);
directives->importFile(pathOrUri, module, lineNumber, column);
else
directives->importModule(pathOrUri, version, module);
directives->importModule(pathOrUri, version, module, lineNumber, column);
}
if (tokenStartLine() != lineNumber)
if (tokenStartLine() != lineNumber) {
error->message = QCoreApplication::translate("QmlParser", "Syntax error");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false; // the directives cannot span over multiple lines
}
// fetch the first token after the .pragma/.import directive
lex();

View File

@@ -46,6 +46,7 @@ QT_QML_BEGIN_NAMESPACE
namespace QmlJS {
class Engine;
class DiagnosticMessage;
class QML_PARSER_EXPORT Directives {
public:
@@ -55,17 +56,21 @@ public:
{
}
virtual void importFile(const QString &jsfile, const QString &module)
virtual void importFile(const QString &jsfile, const QString &module, int line, int column)
{
Q_UNUSED(jsfile);
Q_UNUSED(module);
Q_UNUSED(line);
Q_UNUSED(column);
}
virtual void importModule(const QString &uri, const QString &version, const QString &module)
virtual void importModule(const QString &uri, const QString &version, const QString &module, int line, int column)
{
Q_UNUSED(uri);
Q_UNUSED(version);
Q_UNUSED(module);
Q_UNUSED(line);
Q_UNUSED(column);
}
};
@@ -137,7 +142,7 @@ public:
int lex();
bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix);
bool scanDirectives(Directives *directives);
bool scanDirectives(Directives *directives, DiagnosticMessage *error);
int regExpFlags() const { return _patternFlags; }
QString regExpPattern() const { return _tokenText; }

View File

@@ -48,6 +48,8 @@ QT_QML_BEGIN_NAMESPACE
namespace QmlJS {
class Managed;
class QML_PARSER_EXPORT MemoryPool : public QSharedData
{
MemoryPool(const MemoryPool &other);
@@ -91,6 +93,8 @@ public:
_ptr = _end = 0;
}
template <typename Tp> Tp *New() { return new (this->allocate(sizeof(Tp))) Tp(); }
private:
void *allocate_helper(size_t size)
{

File diff suppressed because it is too large Load Diff

View File

@@ -23,6 +23,7 @@
**
****************************************************************************/
//
// W A R N I N G
// -------------
@@ -230,8 +231,8 @@ protected:
#define J_SCRIPT_REGEXPLITERAL_RULE1 87
#define J_SCRIPT_REGEXPLITERAL_RULE1 88
#define J_SCRIPT_REGEXPLITERAL_RULE2 88
#define J_SCRIPT_REGEXPLITERAL_RULE2 89
QT_QML_END_NAMESPACE

View File

@@ -1448,13 +1448,13 @@ ModelNode TextToModelMerger::createModelNode(const TypeName &typeName,
if (isCustomParserType(typeName))
nodeSource = textAt(context->doc(),
astObjectType->identifierToken.offset,
astObjectType->identifierToken,
astNode->lastSourceLocation());
if (isComponentType(typeName) || isImplicitComponent) {
QString componentSource = extractComponentFromQml(textAt(context->doc(),
astObjectType->identifierToken.offset,
astObjectType->identifierToken,
astNode->lastSourceLocation()));