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

View File

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

View File

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

View File

@@ -1,22 +1,31 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- --
-- Copyright (C) 2015 The Qt Company Ltd. -- 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. -- 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 -- 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 -- General Public License version 2.1 or version 3 as published by the Free
-- Software Foundation and appearing in the file LICENSE.LGPLv21 and -- 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 -- following information to ensure the GNU Lesser General Public License
-- requirements will be met: https://www.gnu.org/licenses/lgpl.html and -- requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-- http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -- http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-- --
-- If you have questions regarding the use of this file, please contact -- As a special exception, The Qt Company gives you certain additional
-- us via http://www.qt.io/contact-us. -- 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$ -- $QT_END_LICENSE$
-- --
@@ -90,38 +99,32 @@
/./**************************************************************************** /./****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** 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. ** This file is part of the QtQml module of the Qt Toolkit.
** **
** $QT_BEGIN_LICENSE:LGPL$ ** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage ** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in ** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the ** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in ** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms ** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further ** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us. ** information use the contact form at http://www.qt.io/contact-us.
** **
** GNU Lesser General Public License Usage ** GNU Lesser General Public License Usage
** Alternatively, 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 3 as published by the Free Software ** General Public License version 2.1 or version 3 as published by the Free
** Foundation and appearing in the file LICENSE.LGPL3 included in the ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** packaging of this file. Please review the following information to ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** ensure the GNU Lesser General Public License version 3 requirements ** following information to ensure the GNU Lesser General Public License
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** 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 ** As a special exception, The Qt Company gives you certain additional
** Alternatively, this file may be used under the terms of the GNU ** rights. These rights are described in The Qt Company LGPL Exception
** General Public License version 2.0 or (at your option) the GNU General ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
** 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.
** **
** $QT_END_LICENSE$ ** $QT_END_LICENSE$
** **
@@ -141,43 +144,38 @@
/:/**************************************************************************** /:/****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** 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. ** This file is part of the QtQml module of the Qt Toolkit.
** **
** $QT_BEGIN_LICENSE:LGPL$ ** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage ** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in ** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the ** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in ** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms ** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further ** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us. ** information use the contact form at http://www.qt.io/contact-us.
** **
** GNU Lesser General Public License Usage ** GNU Lesser General Public License Usage
** Alternatively, 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 3 as published by the Free Software ** General Public License version 2.1 or version 3 as published by the Free
** Foundation and appearing in the file LICENSE.LGPL3 included in the ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** packaging of this file. Please review the following information to ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** ensure the GNU Lesser General Public License version 3 requirements ** following information to ensure the GNU Lesser General Public License
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** 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 ** As a special exception, The Qt Company gives you certain additional
** Alternatively, this file may be used under the terms of the GNU ** rights. These rights are described in The Qt Company LGPL Exception
** General Public License version 2.0 or (at your option) the GNU General ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
** 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.
** **
** $QT_END_LICENSE$ ** $QT_END_LICENSE$
** **
****************************************************************************/ ****************************************************************************/
// //
// W A R N I N G // W A R N I N G
// ------------- // -------------
@@ -507,7 +505,24 @@ bool Parser::parse(int startToken)
token_buffer[0].token = startToken; token_buffer[0].token = startToken;
first_token = &token_buffer[0]; 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; tos = -1;
program = 0; program = 0;
@@ -1085,6 +1100,31 @@ case $rule_number: {
} break; } 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 ; UiObjectMember: FunctionDeclaration ;
/. /.
case $rule_number: { case $rule_number: {
@@ -3031,9 +3071,9 @@ PropertyAssignmentListOpt: PropertyAssignmentList ;
QString msg; QString msg;
int token = token_buffer[0].token; int token = token_buffer[0].token;
if (token < 0 || token >= TERMINAL_COUNT) if (token < 0 || token >= TERMINAL_COUNT)
msg = qApp->translate("QmlParser", "Syntax error"); msg = QCoreApplication::translate("QmlParser", "Syntax error");
else 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)); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
action = errorState; action = errorState;
@@ -3061,7 +3101,7 @@ PropertyAssignmentListOpt: PropertyAssignmentList ;
for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) {
int a = t_action(errorState, *tk); int a = t_action(errorState, *tk);
if (a > 0 && t_action(a, yytoken)) { 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)); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
yytoken = *tk; yytoken = *tk;
@@ -3085,7 +3125,7 @@ PropertyAssignmentListOpt: PropertyAssignmentList ;
int a = t_action(errorState, tk); int a = t_action(errorState, tk);
if (a > 0 && t_action(a, yytoken)) { 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)); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
yytoken = tk; 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)); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
} }

View File

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

View File

@@ -47,7 +47,7 @@ namespace QmlJS { namespace AST {
class SourceLocation class SourceLocation
{ {
public: 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), : offset(offset), length(length),
startLine(line), startColumn(column) startLine(line), startColumn(column)
{ } { }

View File

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

View File

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

View File

@@ -25,6 +25,17 @@
#pragma once #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> #include <QtCore/qglobal.h>
#ifdef QT_CREATOR #ifdef QT_CREATOR
@@ -46,8 +57,8 @@
// QmlDevTools is a static library // QmlDevTools is a static library
# define QML_PARSER_EXPORT # define QML_PARSER_EXPORT
# elif defined(QT_BUILD_QML_LIB) # elif defined(QT_BUILD_QML_LIB)
# define QML_PARSER_EXPORT Q_AUTOTEST_EXPORT # define QML_PARSER_EXPORT Q_DECL_EXPORT
# else # else
# define QML_PARSER_EXPORT # define QML_PARSER_EXPORT Q_DECL_IMPORT
# endif # endif
#endif // QT_CREATOR #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 = 79,
T_XOR_EQ = 80, T_XOR_EQ = 80,
ACCEPT_STATE = 663, ACCEPT_STATE = 665,
RULE_COUNT = 357, RULE_COUNT = 358,
STATE_COUNT = 664, STATE_COUNT = 666,
TERMINAL_COUNT = 106, TERMINAL_COUNT = 106,
NON_TERMINAL_COUNT = 111, NON_TERMINAL_COUNT = 111,
GOTO_INDEX_OFFSET = 664, GOTO_INDEX_OFFSET = 666,
GOTO_INFO_OFFSET = 3104, GOTO_INFO_OFFSET = 3018,
GOTO_CHECK_OFFSET = 3104 GOTO_CHECK_OFFSET = 3018
}; };
static const char *const spell []; static const char *const spell [];

View File

@@ -341,7 +341,7 @@ static inline bool isIdentifierStart(QChar ch)
// fast path for ascii // fast path for ascii
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') ||
(ch.unicode() >= 'A' && ch.unicode() <= 'Z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') ||
ch == QLatin1Char('$') || ch == QLatin1Char('_')) ch == '$' || ch == '_')
return true; return true;
switch (ch.category()) { switch (ch.category()) {
@@ -364,7 +364,7 @@ static bool isIdentifierPart(QChar ch)
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') ||
(ch.unicode() >= 'A' && ch.unicode() <= 'Z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') ||
(ch.unicode() >= '0' && ch.unicode() <= '9') || (ch.unicode() >= '0' && ch.unicode() <= '9') ||
ch == QLatin1Char('$') || ch == QLatin1Char('_') || ch == '$' || ch == '_' ||
ch.unicode() == 0x200c /* ZWNJ */ || ch.unicode() == 0x200d /* ZWJ */) ch.unicode() == 0x200c /* ZWNJ */ || ch.unicode() == 0x200d /* ZWJ */)
return true; return true;
@@ -691,7 +691,7 @@ again:
_validTokenText = true; _validTokenText = true;
_tokenText.resize(0); _tokenText.resize(0);
startCode--; startCode--;
while (startCode != _codePtr - 1) while (startCode != _codePtr - 1)
_tokenText += *startCode++; _tokenText += *startCode++;
while (_codePtr <= _endPtr) { while (_codePtr <= _endPtr) {
@@ -879,8 +879,7 @@ again:
int Lexer::scanNumber(QChar ch) int Lexer::scanNumber(QChar ch)
{ {
if (ch != QLatin1Char('0')) { if (ch != QLatin1Char('0')) {
QByteArray buf; QVarLengthArray<char, 64> buf;
buf.reserve(64);
buf += ch.toLatin1(); buf += ch.toLatin1();
QChar n = _char; QChar n = _char;
@@ -1217,12 +1216,60 @@ bool Lexer::canInsertAutomaticSemicolon(int token) const
|| _followsClosingBrace; || _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) { const int *current = uriTokens;
// the directives are a Javascript-only extension. while (*current != QmlJSGrammar::EOF_SYMBOL) {
return false; if (*current == token)
return true;
++current;
} }
return false;
}
bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
{
Q_ASSERT(!_qmlMode);
lex(); // fetch the first token lex(); // fetch the first token
@@ -1230,24 +1277,33 @@ bool Lexer::scanDirectives(Directives *directives)
return true; return true;
do { do {
const int lineNumber = tokenStartLine();
const int column = tokenStartColumn();
lex(); // skip T_DOT lex(); // skip T_DOT
const int lineNumber = tokenStartLine();
if (! (_tokenKind == T_IDENTIFIER || _tokenKind == T_RESERVED_WORD)) 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(); const QString directiveName = tokenText();
if (! (directiveName == QLatin1String("pragma") || 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 return false; // not a valid directive name
}
// it must be a pragma or an import directive. // it must be a pragma or an import directive.
if (directiveName == QLatin1String("pragma")) { if (directiveName == QLatin1String("pragma")) {
// .pragma library // .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 return false; // expected `library
}
// we found a .pragma library directive // we found a .pragma library directive
directives->pragmaLibrary(); directives->pragmaLibrary();
@@ -1266,22 +1322,53 @@ bool Lexer::scanDirectives(Directives *directives)
fileImport = true; fileImport = true;
pathOrUri = tokenText(); 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) { } else if (_tokenKind == T_IDENTIFIER) {
// .import T_IDENTIFIER (. T_IDENTIFIER)* T_NUMERIC_LITERAL as T_IDENTIFIER // .import T_IDENTIFIER (. T_IDENTIFIER)* T_NUMERIC_LITERAL as T_IDENTIFIER
pathOrUri = tokenText(); while (true) {
if (!isUriToken(_tokenKind)) {
lex(); // skip the first T_IDENTIFIER error->message = QCoreApplication::translate("QmlParser","Invalid module URI");
for (; _tokenKind == T_DOT; lex()) { error->loc.startLine = tokenStartLine();
if (lex() != T_IDENTIFIER) error->loc.startColumn = tokenStartColumn();
return false; return false;
}
pathOrUri += QLatin1Char('.'); pathOrUri.append(tokenText());
pathOrUri += 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 return false; // expected the module version number
}
version = tokenText(); version = tokenText();
} }
@@ -1289,22 +1376,51 @@ bool Lexer::scanDirectives(Directives *directives)
// //
// recognize the mandatory `as' followed by the module name // 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' 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 return false; // expected module name
}
const QString module = tokenText(); 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) if (fileImport)
directives->importFile(pathOrUri, module); directives->importFile(pathOrUri, module, lineNumber, column);
else 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 return false; // the directives cannot span over multiple lines
}
// fetch the first token after the .pragma/.import directive // fetch the first token after the .pragma/.import directive
lex(); lex();

View File

@@ -46,6 +46,7 @@ QT_QML_BEGIN_NAMESPACE
namespace QmlJS { namespace QmlJS {
class Engine; class Engine;
class DiagnosticMessage;
class QML_PARSER_EXPORT Directives { class QML_PARSER_EXPORT Directives {
public: 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(jsfile);
Q_UNUSED(module); 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(uri);
Q_UNUSED(version); Q_UNUSED(version);
Q_UNUSED(module); Q_UNUSED(module);
Q_UNUSED(line);
Q_UNUSED(column);
} }
}; };
@@ -137,7 +142,7 @@ public:
int lex(); int lex();
bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix); bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix);
bool scanDirectives(Directives *directives); bool scanDirectives(Directives *directives, DiagnosticMessage *error);
int regExpFlags() const { return _patternFlags; } int regExpFlags() const { return _patternFlags; }
QString regExpPattern() const { return _tokenText; } QString regExpPattern() const { return _tokenText; }

View File

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

View File

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