qmljs: update parser

Update the qtcreator qmljs parser to the
one of Qt 5.12. It supports EcmaScript 7.

Task-number: QTCREATORBUG-20341
Change-Id: I0d1cff71402ba17e22cde6b46c65614e162280de
Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
This commit is contained in:
Marco Benelli
2018-10-16 15:32:58 +02:00
parent fe8a372773
commit 4646acad0d
46 changed files with 10604 additions and 5872 deletions

View File

@@ -84,7 +84,7 @@ void JsonCheck::postVisit(Node *)
analysis()->m_ranking += previous.m_ranking;
}
bool JsonCheck::visit(ObjectLiteral *ast)
bool JsonCheck::visit(ObjectPattern *ast)
{
if (!proceedCheck(JsonValue::Object, ast->lbraceToken))
return false;
@@ -96,8 +96,8 @@ bool JsonCheck::visit(ObjectLiteral *ast)
return false;
QSet<QString> propertiesFound;
for (PropertyAssignmentList *it = ast->properties; it; it = it->next) {
PropertyNameAndValue *assignment = AST::cast<AST::PropertyNameAndValue *>(it->assignment);
for (PatternPropertyList *it = ast->properties; it; it = it->next) {
PatternProperty *assignment = AST::cast<AST::PatternProperty *>(it->property);
StringLiteralPropertyName *literalName = cast<StringLiteralPropertyName *>(assignment->name);
if (literalName) {
const QString &propertyName = literalName->id.toString();
@@ -106,7 +106,7 @@ bool JsonCheck::visit(ObjectLiteral *ast)
propertiesFound.insert(propertyName);
// Sec. 5.2: "... each property definition's value MUST be a schema..."
m_schema->enterNestedPropertySchema(propertyName);
processSchema(assignment->value);
processSchema(assignment->initializer);
m_schema->leaveNestedSchema();
} else {
analysis()->m_messages.append(Message(ErrInvalidPropertyName,
@@ -144,7 +144,7 @@ bool JsonCheck::visit(ObjectLiteral *ast)
return false;
}
bool JsonCheck::visit(ArrayLiteral *ast)
bool JsonCheck::visit(ArrayPattern *ast)
{
if (!proceedCheck(JsonValue::Array, ast->firstSourceLocation()))
return false;
@@ -155,21 +155,21 @@ bool JsonCheck::visit(ArrayLiteral *ast)
// Sec. 5.5: "When this attribute value is a schema... all the items in the array MUST
// be valid according to the schema."
m_schema->enterNestedItemSchema();
for (ElementList *element = ast->elements; element; element = element->next)
processSchema(element->expression);
for (PatternElementList *element = ast->elements; element; element = element->next)
processSchema(element->element->initializer);
m_schema->leaveNestedSchema();
} else if (m_schema->hasItemArraySchema()) {
// Sec. 5.5: "When this attribute value is an array of schemas... each position in the
// instance array MUST conform to the schema in the corresponding position for this array."
int current = 0;
const int arraySize = m_schema->itemArraySchemaSize();
for (ElementList *element = ast->elements; element; element = element->next, ++current) {
for (PatternElementList *element = ast->elements; element; element = element->next, ++current) {
if (current < arraySize) {
if (m_schema->maybeEnterNestedArraySchema(current)) {
processSchema(element->expression);
processSchema(element->element->initializer);
m_schema->leaveNestedSchema();
} else {
Node::accept(element->expression, this);
Node::accept(element->element->initializer, this);
}
} else {
// TODO: Handle additionalItems.

View File

@@ -51,8 +51,8 @@ private:
bool preVisit(AST::Node *) override;
void postVisit(AST::Node *) override;
bool visit(AST::ObjectLiteral *ast) override;
bool visit(AST::ArrayLiteral *ast) override;
bool visit(AST::ObjectPattern *ast) override;
bool visit(AST::ArrayPattern *ast) override;
bool visit(AST::NullExpression *ast) override;
bool visit(AST::TrueLiteral *ast) override;
bool visit(AST::FalseLiteral *ast) override;

View File

@@ -10,7 +10,7 @@ HEADERS += \
$$PWD/qmljsglobal_p.h \
$$PWD/qmldirparser_p.h \
$$PWD/qmlerror.h \
$$PWD/qmljskeywords_p.h \
$$PWD/qmljskeywords_p.h
SOURCES += \
$$PWD/qmljsast.cpp \
@@ -20,7 +20,13 @@ SOURCES += \
$$PWD/qmljslexer.cpp \
$$PWD/qmljsparser.cpp \
$$PWD/qmldirparser.cpp \
$$PWD/qmlerror.cpp \
$$PWD/qmlerror.cpp
DISTFILES += \
$$PWD/qmljs.g
#CONFIG += qlalr
QLALRSOURCES = $$PWD/qmljs.g
#QMAKE_QLALRFLAGS = --no-debug --qt
DISTFILES += $$QLALRSOURCES
# make sure we install the headers generated by qlalr
#private_headers.CONFIG += no_check_exist

View File

@@ -93,6 +93,7 @@ bool QmlDirParser::parse(const QString &source)
_components.clear();
_scripts.clear();
_designerSupported = false;
_className.clear();
quint16 lineNumber = 0;
bool firstLine = true;
@@ -182,7 +183,8 @@ bool QmlDirParser::parse(const QString &source)
continue;
}
// Ignore these. qmlimportscanner uses them.
_className = sections[1];
} else if (sections[0] == QLatin1String("internal")) {
if (sectionCount != 3) {
reportError(lineNumber, 0,
@@ -256,7 +258,7 @@ bool QmlDirParser::parse(const QString &source)
if (parseVersion(sections[1], &major, &minor)) {
const QString &fileName = sections[2];
if (fileName.endsWith(QLatin1String(".js"))) {
if (fileName.endsWith(QLatin1String(".js")) || fileName.endsWith(QLatin1String(".mjs"))) {
// A 'js' extension indicates a namespaced script import
const Script entry(sections[0], fileName, major, minor);
_scripts.append(entry);
@@ -363,6 +365,11 @@ bool QmlDirParser::designerSupported() const
return _designerSupported;
}
QString QmlDirParser::className() const
{
return _className;
}
QDebug &operator<< (QDebug &debug, const QmlDirParser::Component &component)
{
const QString output = QStringLiteral("{%1 %2.%3}").

View File

@@ -39,8 +39,8 @@
#include <QtCore/QUrl>
#include <QtCore/QHash>
#include <QtCore/QDebug>
#include "qmljsengine_p.h"
#include "qmljsglobal_p.h"
QT_BEGIN_NAMESPACE
@@ -48,8 +48,6 @@ class QmlError;
class QmlEngine;
class QML_PARSER_EXPORT QmlDirParser
{
Q_DISABLE_COPY(QmlDirParser)
public:
QmlDirParser();
~QmlDirParser();
@@ -76,8 +74,7 @@ public:
struct Component
{
Component()
: majorVersion(0), minorVersion(0), internal(false), singleton(false) {}
Component() {}
Component(const QString &typeName, const QString &fileName, int majorVersion, int minorVersion)
: typeName(typeName), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion),
@@ -85,24 +82,23 @@ public:
QString typeName;
QString fileName;
int majorVersion;
int minorVersion;
bool internal;
bool singleton;
int majorVersion = 0;
int minorVersion = 0;
bool internal = false;
bool singleton = false;
};
struct Script
{
Script()
: majorVersion(0), minorVersion(0) {}
Script() {}
Script(const QString &nameSpace, const QString &fileName, int majorVersion, int minorVersion)
: nameSpace(nameSpace), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion) {}
QString nameSpace;
QString fileName;
int majorVersion;
int minorVersion;
int majorVersion = 0;
int minorVersion = 0;
};
QHash<QString,Component> components() const;
@@ -124,6 +120,8 @@ public:
QList<TypeInfo> typeInfos() const;
#endif
QString className() const;
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);
@@ -139,6 +137,7 @@ private:
#ifdef QT_CREATOR
QList<TypeInfo> _typeInfos;
#endif
QString _className;
};
typedef QHash<QString,QmlDirParser::Component> QmlDirComponents;

View File

@@ -91,7 +91,7 @@ QmlErrorPrivate::QmlErrorPrivate()
Creates an empty error object.
*/
QmlError::QmlError()
: d(0)
: d(nullptr)
{
}
@@ -99,7 +99,7 @@ QmlError::QmlError()
Creates a copy of \a other.
*/
QmlError::QmlError(const QmlError &other)
: d(0)
: d(nullptr)
{
*this = other;
}
@@ -111,7 +111,7 @@ QmlError &QmlError::operator=(const QmlError &other)
{
if (!other.d) {
delete d;
d = 0;
d = nullptr;
} else {
if (!d)
d = new QmlErrorPrivate;
@@ -130,7 +130,7 @@ QmlError &QmlError::operator=(const QmlError &other)
*/
QmlError::~QmlError()
{
delete d; d = 0;
delete d; d = nullptr;
}
/*!
@@ -138,7 +138,7 @@ QmlError::~QmlError()
*/
bool QmlError::isValid() const
{
return d != 0;
return d != nullptr;
}
/*!
@@ -231,7 +231,7 @@ QObject *QmlError::object() const
{
if (d)
return d->object;
return 0;
return nullptr;
}
/*!
@@ -260,7 +260,7 @@ QtMsgType QmlError::messageType() const
\since 5.9
Sets the \a messageType for this message. The message type determines which
QDebug handlers are responsible for recieving the message.
QDebug handlers are responsible for receiving the message.
*/
void QmlError::setMessageType(QtMsgType messageType)
{

File diff suppressed because it is too large Load Diff

View File

@@ -31,6 +31,27 @@ QT_QML_BEGIN_NAMESPACE
namespace QmlJS { namespace AST {
FunctionExpression *asAnonymousFunctionDefinition(Node *n)
{
if (!n)
return nullptr;
FunctionExpression *f = n->asFunctionDefinition();
if (!f || !f->name.isNull())
return nullptr;
return f;
}
ClassExpression *asAnonymousClassDefinition(Node *n)
{
if (!n)
return nullptr;
ClassExpression *c = n->asClassDefinition();
if (!c || !c->name.isNull())
return nullptr;
return c;
}
void Node::accept(Visitor *visitor)
{
if (visitor->preVisit(this)) {
@@ -47,22 +68,42 @@ void Node::accept(Node *node, Visitor *visitor)
ExpressionNode *Node::expressionCast()
{
return 0;
return nullptr;
}
BinaryExpression *Node::binaryExpressionCast()
{
return 0;
return nullptr;
}
Statement *Node::statementCast()
{
return 0;
return nullptr;
}
UiObjectMember *Node::uiObjectMemberCast()
{
return 0;
return nullptr;
}
LeftHandSideExpression *Node::leftHandSideExpressionCast()
{
return nullptr;
}
Pattern *Node::patternCast()
{
return nullptr;
}
FunctionExpression *Node::asFunctionDefinition()
{
return nullptr;
}
ClassExpression *Node::asClassDefinition()
{
return nullptr;
}
ExpressionNode *ExpressionNode::expressionCast()
@@ -70,6 +111,42 @@ ExpressionNode *ExpressionNode::expressionCast()
return this;
}
FormalParameterList *ExpressionNode::reparseAsFormalParameterList(MemoryPool *pool)
{
AST::ExpressionNode *expr = this;
AST::FormalParameterList *f = nullptr;
if (AST::Expression *commaExpr = AST::cast<AST::Expression *>(expr)) {
f = commaExpr->left->reparseAsFormalParameterList(pool);
if (!f)
return nullptr;
expr = commaExpr->right;
}
AST::ExpressionNode *rhs = nullptr;
if (AST::BinaryExpression *assign = AST::cast<AST::BinaryExpression *>(expr)) {
if (assign->op != QSOperator::Assign)
return nullptr;
expr = assign->left;
rhs = assign->right;
}
AST::PatternElement *binding = nullptr;
if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(expr)) {
binding = new (pool) AST::PatternElement(idExpr->name, rhs);
binding->identifierToken = idExpr->identifierToken;
} else if (AST::Pattern *p = expr->patternCast()) {
SourceLocation loc;
QString s;
if (!p->convertLiteralToAssignmentPattern(pool, &loc, &s))
return nullptr;
binding = new (pool) AST::PatternElement(p, rhs);
binding->identifierToken = p->firstSourceLocation();
}
if (!binding)
return nullptr;
return new (pool) AST::FormalParameterList(f, binding);
}
BinaryExpression *BinaryExpression::binaryExpressionCast()
{
return this;
@@ -93,6 +170,16 @@ void NestedExpression::accept0(Visitor *visitor)
visitor->endVisit(this);
}
FunctionExpression *NestedExpression::asFunctionDefinition()
{
return expression->asFunctionDefinition();
}
ClassExpression *NestedExpression::asClassDefinition()
{
return expression->asClassDefinition();
}
void ThisExpression::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
@@ -133,6 +220,15 @@ void FalseLiteral::accept0(Visitor *visitor)
visitor->endVisit(this);
}
void SuperLiteral::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
}
visitor->endVisit(this);
}
void StringLiteral::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
@@ -141,6 +237,16 @@ void StringLiteral::accept0(Visitor *visitor)
visitor->endVisit(this);
}
void TemplateLiteral::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
if (next)
accept(next, visitor);
}
visitor->endVisit(this);
}
void NumericLiteral::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
@@ -157,17 +263,27 @@ void RegExpLiteral::accept0(Visitor *visitor)
visitor->endVisit(this);
}
void ArrayLiteral::accept0(Visitor *visitor)
void ArrayPattern::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
if (visitor->visit(this))
accept(elements, visitor);
accept(elision, visitor);
}
visitor->endVisit(this);
}
void ObjectLiteral::accept0(Visitor *visitor)
bool ArrayPattern::isValidArrayLiteral(SourceLocation *errorLocation) const {
for (PatternElementList *it = elements; it != nullptr; it = it->next) {
PatternElement *e = it->element;
if (e && e->bindingTarget != nullptr) {
if (errorLocation)
*errorLocation = e->firstSourceLocation();
return false;
}
}
return true;
}
void ObjectPattern::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(properties, visitor);
@@ -176,18 +292,170 @@ void ObjectLiteral::accept0(Visitor *visitor)
visitor->endVisit(this);
}
void ElementList::accept0(Visitor *visitor)
/*
This is the grammar for AssignmentPattern that we need to convert the literal to:
AssignmentPattern:
ObjectAssignmentPattern
ArrayAssignmentPattern
ArrayAssignmentPattern:
[ ElisionOpt AssignmentRestElementOpt ]
[ AssignmentElementList ]
[ AssignmentElementList , ElisionOpt AssignmentRestElementOpt ]
AssignmentElementList:
AssignmentElisionElement
AssignmentElementList , AssignmentElisionElement
AssignmentElisionElement:
ElisionOpt AssignmentElement
AssignmentRestElement:
... DestructuringAssignmentTarget
ObjectAssignmentPattern:
{}
{ AssignmentPropertyList }
{ AssignmentPropertyList, }
AssignmentPropertyList:
AssignmentProperty
AssignmentPropertyList , AssignmentProperty
AssignmentProperty:
IdentifierReference InitializerOpt_In
PropertyName:
AssignmentElement
AssignmentElement:
DestructuringAssignmentTarget InitializerOpt_In
DestructuringAssignmentTarget:
LeftHandSideExpression
It was originally parsed with the following grammar:
ArrayLiteral:
[ ElisionOpt ]
[ ElementList ]
[ ElementList , ElisionOpt ]
ElementList:
ElisionOpt AssignmentExpression_In
ElisionOpt SpreadElement
ElementList , ElisionOpt AssignmentExpression_In
ElementList , Elisionopt SpreadElement
SpreadElement:
... AssignmentExpression_In
ObjectLiteral:
{}
{ PropertyDefinitionList }
{ PropertyDefinitionList , }
PropertyDefinitionList:
PropertyDefinition
PropertyDefinitionList , PropertyDefinition
PropertyDefinition:
IdentifierReference
CoverInitializedName
PropertyName : AssignmentExpression_In
MethodDefinition
PropertyName:
LiteralPropertyName
ComputedPropertyName
*/
bool ArrayPattern::convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage)
{
if (visitor->visit(this)) {
for (ElementList *it = this; it; it = it->next) {
accept(it->elision, visitor);
accept(it->expression, visitor);
if (parseMode == Binding)
return true;
for (auto *it = elements; it; it = it->next) {
if (!it->element)
continue;
if (it->element->type == PatternElement::SpreadElement && it->next) {
*errorLocation = it->element->firstSourceLocation();
*errorMessage = QString::fromLatin1("'...' can only appear as last element in a destructuring list.");
return false;
}
if (!it->element->convertLiteralToAssignmentPattern(pool, errorLocation, errorMessage))
return false;
}
parseMode = Binding;
return true;
}
bool ObjectPattern::convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage)
{
if (parseMode == Binding)
return true;
for (auto *it = properties; it; it = it->next) {
if (!it->property->convertLiteralToAssignmentPattern(pool, errorLocation, errorMessage))
return false;
}
parseMode = Binding;
return true;
}
bool PatternElement::convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage)
{
Q_ASSERT(type == Literal || type == SpreadElement);
Q_ASSERT(bindingIdentifier.isNull());
Q_ASSERT(bindingTarget == nullptr);
Q_ASSERT(bindingTarget == nullptr);
Q_ASSERT(initializer);
ExpressionNode *init = initializer;
initializer = nullptr;
LeftHandSideExpression *lhs = init->leftHandSideExpressionCast();
if (type == SpreadElement) {
if (!lhs) {
*errorLocation = init->firstSourceLocation();
*errorMessage = QString::fromLatin1("Invalid lhs expression after '...' in destructuring expression.");
return false;
}
} else {
type = PatternElement::Binding;
if (BinaryExpression *b = init->binaryExpressionCast()) {
if (b->op != QSOperator::Assign) {
*errorLocation = b->operatorToken;
*errorMessage = QString::fromLatin1("Invalid assignment operation in destructuring expression");
return false;
}
lhs = b->left->leftHandSideExpressionCast();
initializer = b->right;
Q_ASSERT(lhs);
} else {
lhs = init->leftHandSideExpressionCast();
}
if (!lhs) {
*errorLocation = init->firstSourceLocation();
*errorMessage = QString::fromLatin1("Destructuring target is not a left hand side expression.");
return false;
}
}
visitor->endVisit(this);
if (auto *i = cast<IdentifierExpression *>(lhs)) {
bindingIdentifier = i->name;
identifierToken = i->identifierToken;
return true;
}
bindingTarget = lhs;
if (auto *p = lhs->patternCast()) {
if (!p->convertLiteralToAssignmentPattern(pool, errorLocation, errorMessage))
return false;
}
return true;
}
bool PatternProperty::convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage)
{
Q_ASSERT(type != SpreadElement);
if (type == Binding)
return true;
if (type == Getter || type == Setter) {
*errorLocation = firstSourceLocation();
*errorMessage = QString::fromLatin1("Invalid getter/setter in destructuring expression.");
return false;
}
Q_ASSERT(type == Literal);
return PatternElement::convertLiteralToAssignmentPattern(pool, errorLocation, errorMessage);
}
void Elision::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
@@ -197,38 +465,6 @@ void Elision::accept0(Visitor *visitor)
visitor->endVisit(this);
}
void PropertyNameAndValue::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(name, visitor);
accept(value, visitor);
}
visitor->endVisit(this);
}
void PropertyGetterSetter::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(name, visitor);
accept(formals, visitor);
accept(functionBody, visitor);
}
visitor->endVisit(this);
}
void PropertyAssignmentList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
for (PropertyAssignmentList *it = this; it; it = it->next) {
accept(it->assignment, visitor);
}
}
visitor->endVisit(this);
}
void IdentifierPropertyName::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
@@ -253,6 +489,28 @@ void NumericLiteralPropertyName::accept0(Visitor *visitor)
visitor->endVisit(this);
}
namespace {
struct LocaleWithoutZeroPadding : public QLocale
{
LocaleWithoutZeroPadding()
: QLocale(QLocale::C)
{
setNumberOptions(QLocale::OmitLeadingZeroInExponent | QLocale::OmitGroupSeparator);
}
};
}
QString NumericLiteralPropertyName::asString()const
{
// Can't use QString::number here anymore as it does zero padding by default now.
// In C++11 this initialization is thread-safe (6.7 [stmt.dcl] p4)
static LocaleWithoutZeroPadding locale;
// Because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83562 we can't use thread_local
// for the locale variable and therefore rely on toString(double) to be thread-safe.
return locale.toString(id, 'g', 16);
}
void ArrayMemberExpression::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
@@ -482,15 +740,6 @@ void VariableDeclarationList::accept0(Visitor *visitor)
visitor->endVisit(this);
}
void VariableDeclaration::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(expression, visitor);
}
visitor->endVisit(this);
}
void EmptyStatement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
@@ -543,17 +792,6 @@ void ForStatement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(initialiser, visitor);
accept(condition, visitor);
accept(expression, visitor);
accept(statement, visitor);
}
visitor->endVisit(this);
}
void LocalForStatement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(declarations, visitor);
accept(condition, visitor);
accept(expression, visitor);
@@ -566,18 +804,7 @@ void LocalForStatement::accept0(Visitor *visitor)
void ForEachStatement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(initialiser, visitor);
accept(expression, visitor);
accept(statement, visitor);
}
visitor->endVisit(this);
}
void LocalForEachStatement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(declaration, visitor);
accept(lhs, visitor);
accept(expression, visitor);
accept(statement, visitor);
}
@@ -610,6 +837,16 @@ void ReturnStatement::accept0(Visitor *visitor)
visitor->endVisit(this);
}
void YieldExpression::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(expression, visitor);
}
visitor->endVisit(this);
}
void WithStatement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
@@ -703,6 +940,7 @@ void TryStatement::accept0(Visitor *visitor)
void Catch::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(patternElement, visitor);
accept(statement, visitor);
}
@@ -738,57 +976,182 @@ void FunctionExpression::accept0(Visitor *visitor)
visitor->endVisit(this);
}
FunctionExpression *FunctionExpression::asFunctionDefinition()
{
return this;
}
QStringList FormalParameterList::formals() const
{
QStringList formals;
int i = 0;
for (const FormalParameterList *it = this; it; it = it->next) {
if (it->element) {
QString name = it->element->bindingIdentifier.toString();
int duplicateIndex = formals.indexOf(name);
if (duplicateIndex >= 0) {
// change the name of the earlier argument to enforce the lookup semantics from the spec
formals[duplicateIndex] += QLatin1String("#") + QString::number(i);
}
formals += name;
}
++i;
}
return formals;
}
QStringList FormalParameterList::boundNames() const
{
QStringList names;
for (const FormalParameterList *it = this; it; it = it->next) {
if (it->element)
it->element->boundNames(&names);
}
return names;
}
void FormalParameterList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
// ###
accept(element, visitor);
if (next)
accept(next, visitor);
}
visitor->endVisit(this);
}
void FunctionBody::accept0(Visitor *visitor)
FormalParameterList *FormalParameterList::finish(QmlJS::MemoryPool *pool)
{
if (visitor->visit(this)) {
accept(elements, visitor);
}
FormalParameterList *front = next;
next = nullptr;
visitor->endVisit(this);
int i = 0;
for (const FormalParameterList *it = this; it; it = it->next) {
if (it->element && it->element->bindingIdentifier.isEmpty())
it->element->bindingIdentifier = pool->newString(QLatin1String("arg#") + QString::number(i));
++i;
}
return front;
}
void Program::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(elements, visitor);
accept(statements, visitor);
}
visitor->endVisit(this);
}
void SourceElements::accept0(Visitor *visitor)
void ImportSpecifier::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
for (SourceElements *it = this; it; it = it->next) {
accept(it->element, visitor);
}
visitor->endVisit(this);
}
void ImportsList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
for (ImportsList *it = this; it; it = it->next) {
accept(it->importSpecifier, visitor);
}
}
visitor->endVisit(this);
}
void FunctionSourceElement::accept0(Visitor *visitor)
void NamedImports::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(declaration, visitor);
accept(importsList, visitor);
}
visitor->endVisit(this);
}
void StatementSourceElement::accept0(Visitor *visitor)
void FromClause::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(statement, visitor);
}
visitor->endVisit(this);
}
void NameSpaceImport::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
}
visitor->endVisit(this);
}
void ImportClause::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(nameSpaceImport, visitor);
accept(namedImports, visitor);
}
visitor->endVisit(this);
}
void ImportDeclaration::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(importClause, visitor);
accept(fromClause, visitor);
}
visitor->endVisit(this);
}
void ExportSpecifier::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
}
visitor->endVisit(this);
}
void ExportsList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
for (ExportsList *it = this; it; it = it->next) {
accept(it->exportSpecifier, visitor);
}
}
visitor->endVisit(this);
}
void ExportClause::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(exportsList, visitor);
}
visitor->endVisit(this);
}
void ExportDeclaration::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(fromClause, visitor);
accept(exportClause, visitor);
accept(variableStatementOrDeclaration, visitor);
}
visitor->endVisit(this);
}
void ESModule::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(body, visitor);
}
visitor->endVisit(this);
@@ -916,18 +1279,9 @@ void UiImport::accept0(Visitor *visitor)
visitor->endVisit(this);
}
void UiQualifiedPragmaId::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
}
visitor->endVisit(this);
}
void UiPragma::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(pragmaType, visitor);
}
visitor->endVisit(this);
@@ -970,6 +1324,153 @@ void UiEnumMemberList::accept0(Visitor *visitor)
visitor->endVisit(this);
}
void TaggedTemplate::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(base, visitor);
accept(templateLiteral, visitor);
}
visitor->endVisit(this);
}
void PatternElement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(bindingTarget, visitor);
accept(initializer, visitor);
}
visitor->endVisit(this);
}
void PatternElement::boundNames(QStringList *names)
{
if (bindingTarget) {
if (PatternElementList *e = elementList())
e->boundNames(names);
else if (PatternPropertyList *p = propertyList())
p->boundNames(names);
} else {
names->append(bindingIdentifier.toString());
}
}
void PatternElementList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(elision, visitor);
accept(element, visitor);
if (next)
accept(next, visitor);
}
visitor->endVisit(this);
}
void PatternElementList::boundNames(QStringList *names)
{
for (PatternElementList *it = this; it; it = it->next) {
if (it->element)
it->element->boundNames(names);
}
}
void PatternProperty::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(name, visitor);
accept(bindingTarget, visitor);
accept(initializer, visitor);
}
visitor->endVisit(this);
}
void PatternProperty::boundNames(QStringList *names)
{
PatternElement::boundNames(names);
}
void PatternPropertyList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(property, visitor);
if (next)
accept(next, visitor);
}
visitor->endVisit(this);
}
void PatternPropertyList::boundNames(QStringList *names)
{
for (PatternPropertyList *it = this; it; it = it->next)
it->property->boundNames(names);
}
void ComputedPropertyName::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(expression, visitor);
}
visitor->endVisit(this);
}
void ClassExpression::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(heritage, visitor);
accept(elements, visitor);
}
visitor->endVisit(this);
}
ClassExpression *ClassExpression::asClassDefinition()
{
return this;
}
void ClassDeclaration::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(heritage, visitor);
accept(elements, visitor);
}
visitor->endVisit(this);
}
void ClassElementList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(property, visitor);
if (next)
accept(next, visitor);
}
visitor->endVisit(this);
}
ClassElementList *ClassElementList::finish()
{
ClassElementList *front = next;
next = nullptr;
return front;
}
Pattern *Pattern::patternCast()
{
return this;
}
LeftHandSideExpression *LeftHandSideExpression::leftHandSideExpressionCast()
{
return this;
}
} } // namespace QmlJS::AST
QT_QML_END_NAMESPACE

File diff suppressed because it is too large Load Diff

View File

@@ -74,22 +74,27 @@ class IdentifierExpression;
class NullExpression;
class TrueLiteral;
class FalseLiteral;
class SuperLiteral;
class NumericLiteral;
class StringLiteral;
class TemplateLiteral;
class RegExpLiteral;
class ArrayLiteral;
class ObjectLiteral;
class ElementList;
class Pattern;
class ArrayPattern;
class ObjectPattern;
class PatternElement;
class PatternElementList;
class PatternProperty;
class PatternPropertyList;
class Elision;
class PropertyAssignmentList;
class PropertyGetterSetter;
class PropertyNameAndValue;
class PropertyName;
class IdentifierPropertyName;
class StringLiteralPropertyName;
class NumericLiteralPropertyName;
class ComputedPropertyName;
class ArrayMemberExpression;
class FieldMemberExpression;
class TaggedTemplate;
class NewMemberExpression;
class NewExpression;
class CallExpression;
@@ -108,20 +113,19 @@ class NotExpression;
class BinaryExpression;
class ConditionalExpression;
class Expression; // ### rename
class YieldExpression;
class Block;
class LeftHandSideExpression;
class StatementList;
class VariableStatement;
class VariableDeclarationList;
class VariableDeclaration;
class EmptyStatement;
class ExpressionStatement;
class IfStatement;
class DoWhileStatement;
class WhileStatement;
class ForStatement;
class LocalForStatement;
class ForEachStatement;
class LocalForEachStatement;
class ContinueStatement;
class BreakStatement;
class ReturnStatement;
@@ -139,14 +143,26 @@ class Finally;
class FunctionDeclaration;
class FunctionExpression;
class FormalParameterList;
class FunctionBody;
class ExportSpecifier;
class ExportsList;
class ExportClause;
class ExportDeclaration;
class Program;
class SourceElements;
class SourceElement;
class FunctionSourceElement;
class StatementSourceElement;
class ImportSpecifier;
class ImportsList;
class NamedImports;
class NameSpaceImport;
class NamedImport;
class ImportClause;
class FromClause;
class ImportDeclaration;
class ModuleItem;
class ESModule;
class DebuggerStatement;
class NestedExpression;
class ClassExpression;
class ClassDeclaration;
class ClassElementList;
// ui elements
class UiProgram;
@@ -164,7 +180,6 @@ class UiObjectMember;
class UiObjectMemberList;
class UiArrayMemberList;
class UiQualifiedId;
class UiQualifiedPragmaId;
class UiHeaderItemList;
class UiEnumDeclaration;
class UiEnumMemberList;

View File

@@ -68,7 +68,6 @@ public:
virtual bool visit(UiObjectMemberList *) { return true; }
virtual bool visit(UiArrayMemberList *) { return true; }
virtual bool visit(UiQualifiedId *) { return true; }
virtual bool visit(UiQualifiedPragmaId *) { return true; }
virtual bool visit(UiEnumDeclaration *) { return true; }
virtual bool visit(UiEnumMemberList *) { return true; }
@@ -87,7 +86,6 @@ public:
virtual void endVisit(UiObjectMemberList *) {}
virtual void endVisit(UiArrayMemberList *) {}
virtual void endVisit(UiQualifiedId *) {}
virtual void endVisit(UiQualifiedPragmaId *) {}
virtual void endVisit(UiEnumDeclaration *) {}
virtual void endVisit(UiEnumMemberList *) { }
@@ -107,36 +105,42 @@ public:
virtual bool visit(FalseLiteral *) { return true; }
virtual void endVisit(FalseLiteral *) {}
virtual bool visit(SuperLiteral *) { return true; }
virtual void endVisit(SuperLiteral *) {}
virtual bool visit(StringLiteral *) { return true; }
virtual void endVisit(StringLiteral *) {}
virtual bool visit(TemplateLiteral *) { return true; }
virtual void endVisit(TemplateLiteral *) {}
virtual bool visit(NumericLiteral *) { return true; }
virtual void endVisit(NumericLiteral *) {}
virtual bool visit(RegExpLiteral *) { return true; }
virtual void endVisit(RegExpLiteral *) {}
virtual bool visit(ArrayLiteral *) { return true; }
virtual void endVisit(ArrayLiteral *) {}
virtual bool visit(ArrayPattern *) { return true; }
virtual void endVisit(ArrayPattern *) {}
virtual bool visit(ObjectLiteral *) { return true; }
virtual void endVisit(ObjectLiteral *) {}
virtual bool visit(ObjectPattern *) { return true; }
virtual void endVisit(ObjectPattern *) {}
virtual bool visit(ElementList *) { return true; }
virtual void endVisit(ElementList *) {}
virtual bool visit(PatternElementList *) { return true; }
virtual void endVisit(PatternElementList *) {}
virtual bool visit(PatternPropertyList *) { return true; }
virtual void endVisit(PatternPropertyList *) {}
virtual bool visit(PatternElement *) { return true; }
virtual void endVisit(PatternElement *) {}
virtual bool visit(PatternProperty *) { return true; }
virtual void endVisit(PatternProperty *) {}
virtual bool visit(Elision *) { return true; }
virtual void endVisit(Elision *) {}
virtual bool visit(PropertyAssignmentList *) { return true; }
virtual void endVisit(PropertyAssignmentList *) {}
virtual bool visit(PropertyNameAndValue *) { return true; }
virtual void endVisit(PropertyNameAndValue *) {}
virtual bool visit(PropertyGetterSetter *) { return true; }
virtual void endVisit(PropertyGetterSetter *) {}
virtual bool visit(NestedExpression *) { return true; }
virtual void endVisit(NestedExpression *) {}
@@ -149,12 +153,18 @@ public:
virtual bool visit(NumericLiteralPropertyName *) { return true; }
virtual void endVisit(NumericLiteralPropertyName *) {}
virtual bool visit(ComputedPropertyName *) { return true; }
virtual void endVisit(ComputedPropertyName *) {}
virtual bool visit(ArrayMemberExpression *) { return true; }
virtual void endVisit(ArrayMemberExpression *) {}
virtual bool visit(FieldMemberExpression *) { return true; }
virtual void endVisit(FieldMemberExpression *) {}
virtual bool visit(TaggedTemplate *) { return true; }
virtual void endVisit(TaggedTemplate *) {}
virtual bool visit(NewMemberExpression *) { return true; }
virtual void endVisit(NewMemberExpression *) {}
@@ -221,9 +231,6 @@ public:
virtual bool visit(VariableDeclarationList *) { return true; }
virtual void endVisit(VariableDeclarationList *) {}
virtual bool visit(VariableDeclaration *) { return true; }
virtual void endVisit(VariableDeclaration *) {}
virtual bool visit(EmptyStatement *) { return true; }
virtual void endVisit(EmptyStatement *) {}
@@ -242,15 +249,9 @@ public:
virtual bool visit(ForStatement *) { return true; }
virtual void endVisit(ForStatement *) {}
virtual bool visit(LocalForStatement *) { return true; }
virtual void endVisit(LocalForStatement *) {}
virtual bool visit(ForEachStatement *) { return true; }
virtual void endVisit(ForEachStatement *) {}
virtual bool visit(LocalForEachStatement *) { return true; }
virtual void endVisit(LocalForEachStatement *) {}
virtual bool visit(ContinueStatement *) { return true; }
virtual void endVisit(ContinueStatement *) {}
@@ -260,6 +261,9 @@ public:
virtual bool visit(ReturnStatement *) { return true; }
virtual void endVisit(ReturnStatement *) {}
virtual bool visit(YieldExpression *) { return true; }
virtual void endVisit(YieldExpression *) {}
virtual bool visit(WithStatement *) { return true; }
virtual void endVisit(WithStatement *) {}
@@ -302,20 +306,56 @@ public:
virtual bool visit(FormalParameterList *) { return true; }
virtual void endVisit(FormalParameterList *) {}
virtual bool visit(FunctionBody *) { return true; }
virtual void endVisit(FunctionBody *) {}
virtual bool visit(ClassExpression *) { return true; }
virtual void endVisit(ClassExpression *) {}
virtual bool visit(ClassDeclaration *) { return true; }
virtual void endVisit(ClassDeclaration *) {}
virtual bool visit(ClassElementList *) { return true; }
virtual void endVisit(ClassElementList *) {}
virtual bool visit(Program *) { return true; }
virtual void endVisit(Program *) {}
virtual bool visit(SourceElements *) { return true; }
virtual void endVisit(SourceElements *) {}
virtual bool visit(NameSpaceImport *) { return true; }
virtual void endVisit(NameSpaceImport *) {}
virtual bool visit(FunctionSourceElement *) { return true; }
virtual void endVisit(FunctionSourceElement *) {}
virtual bool visit(ImportSpecifier *) { return true; }
virtual void endVisit(ImportSpecifier *) {}
virtual bool visit(StatementSourceElement *) { return true; }
virtual void endVisit(StatementSourceElement *) {}
virtual bool visit(ImportsList *) { return true; }
virtual void endVisit(ImportsList *) {}
virtual bool visit(NamedImports *) { return true; }
virtual void endVisit(NamedImports *) {}
virtual bool visit(FromClause *) { return true; }
virtual void endVisit(FromClause *) {}
virtual bool visit(ImportClause *) { return true; }
virtual void endVisit(ImportClause *) {}
virtual bool visit(ImportDeclaration *) { return true; }
virtual void endVisit(ImportDeclaration *) {}
virtual bool visit(ExportSpecifier *) { return true; }
virtual void endVisit(ExportSpecifier *) {}
virtual bool visit(ExportsList *) { return true; }
virtual void endVisit(ExportsList *) {}
virtual bool visit(ExportClause *) { return true; }
virtual void endVisit(ExportClause *) {}
virtual bool visit(ExportDeclaration *) { return true; }
virtual void endVisit(ExportDeclaration *) {}
virtual bool visit(ModuleItem *) { return true; }
virtual void endVisit(ModuleItem *) {}
virtual bool visit(ESModule *) { return true; }
virtual void endVisit(ESModule *) {}
virtual bool visit(DebuggerStatement *) { return true; }
virtual void endVisit(DebuggerStatement *) {}

View File

@@ -98,15 +98,8 @@ double integerFromString(const char *buf, int size, int radix)
return result;
}
double integerFromString(const QString &str, int radix)
{
QByteArray ba = QStringRef(&str).trimmed().toLatin1();
return integerFromString(ba.constData(), ba.size(), radix);
}
Engine::Engine()
: _lexer(0), _directives(0)
: _lexer(nullptr), _directives(nullptr)
{ }
Engine::~Engine()

View File

@@ -49,14 +49,40 @@ QT_QML_BEGIN_NAMESPACE
namespace QmlJS {
class Lexer;
class Directives;
class MemoryPool;
class QML_PARSER_EXPORT Directives {
public:
virtual ~Directives() {}
virtual void pragmaLibrary()
{
}
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, int line, int column)
{
Q_UNUSED(uri);
Q_UNUSED(version);
Q_UNUSED(module);
Q_UNUSED(line);
Q_UNUSED(column);
}
};
class QML_PARSER_EXPORT DiagnosticMessage
{
public:
DiagnosticMessage()
: kind(Severity::Error) {}
DiagnosticMessage() {}
DiagnosticMessage(Severity::Enum kind, const AST::SourceLocation &loc, const QString &message)
: kind(kind), loc(loc), message(message) {}
@@ -67,7 +93,7 @@ public:
bool isError() const
{ return kind == Severity::Error; }
Severity::Enum kind;
Severity::Enum kind = Severity::Error;
AST::SourceLocation loc;
QString message;
};

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,9 @@
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -21,6 +22,8 @@
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
@@ -39,7 +42,6 @@
#define QMLJSGRAMMAR_P_H
#include "qmljsglobal_p.h"
#include <QtCore/qglobal.h>
QT_BEGIN_NAMESPACE
@@ -48,47 +50,55 @@ class QML_PARSER_EXPORT QmlJSGrammar
public:
enum VariousConstants {
EOF_SYMBOL = 0,
REDUCE_HERE = 107,
SHIFT_THERE = 106,
REDUCE_HERE = 125,
T_AND = 1,
T_AND_AND = 2,
T_AND_EQ = 3,
T_AS = 95,
T_ARROW = 93,
T_AS = 110,
T_AUTOMATIC_SEMICOLON = 62,
T_BREAK = 4,
T_CASE = 5,
T_CATCH = 6,
T_CLASS = 98,
T_COLON = 7,
T_COMMA = 8,
T_COMMENT = 89,
T_COMPATIBILITY_SEMICOLON = 90,
T_CONST = 84,
T_COMMENT = 91,
T_COMPATIBILITY_SEMICOLON = 92,
T_CONST = 86,
T_CONTINUE = 9,
T_DEBUGGER = 86,
T_DEBUGGER = 88,
T_DEFAULT = 10,
T_DELETE = 11,
T_DIVIDE_ = 12,
T_DIVIDE_EQ = 13,
T_DO = 14,
T_DOT = 15,
T_ELLIPSIS = 95,
T_ELSE = 16,
T_ENUM = 91,
T_ENUM = 94,
T_EQ = 17,
T_EQ_EQ = 18,
T_EQ_EQ_EQ = 19,
T_ERROR = 99,
T_FALSE = 83,
T_FEED_JS_EXPRESSION = 103,
T_FEED_JS_PROGRAM = 105,
T_FEED_JS_SOURCE_ELEMENT = 104,
T_FEED_JS_STATEMENT = 102,
T_FEED_UI_OBJECT_MEMBER = 101,
T_FEED_UI_PROGRAM = 100,
T_ERROR = 114,
T_EXPORT = 101,
T_EXTENDS = 99,
T_FALSE = 85,
T_FEED_JS_EXPRESSION = 118,
T_FEED_JS_MODULE = 120,
T_FEED_JS_SCRIPT = 119,
T_FEED_JS_STATEMENT = 117,
T_FEED_UI_OBJECT_MEMBER = 116,
T_FEED_UI_PROGRAM = 115,
T_FINALLY = 20,
T_FOR = 21,
T_FORCE_BLOCK = 122,
T_FORCE_DECLARATION = 121,
T_FOR_LOOKAHEAD_OK = 123,
T_FROM = 102,
T_FUNCTION = 22,
T_GE = 23,
T_GET = 97,
T_GET = 112,
T_GT = 24,
T_GT_GT = 25,
T_GT_GT_EQ = 26,
@@ -96,13 +106,13 @@ public:
T_GT_GT_GT_EQ = 28,
T_IDENTIFIER = 29,
T_IF = 30,
T_IMPORT = 93,
T_IMPORT = 108,
T_IN = 31,
T_INSTANCEOF = 32,
T_LBRACE = 33,
T_LBRACKET = 34,
T_LE = 35,
T_LET = 85,
T_LET = 87,
T_LPAREN = 36,
T_LT = 37,
T_LT_LT = 38,
@@ -110,66 +120,82 @@ public:
T_MINUS = 40,
T_MINUS_EQ = 41,
T_MINUS_MINUS = 42,
T_MULTILINE_STRING_LITERAL = 88,
T_MULTILINE_STRING_LITERAL = 90,
T_NEW = 43,
T_NOT = 44,
T_NOT_EQ = 45,
T_NOT_EQ_EQ = 46,
T_NULL = 81,
T_NO_SUBSTITUTION_TEMPLATE = 103,
T_NULL = 83,
T_NUMERIC_LITERAL = 47,
T_ON = 96,
T_OF = 111,
T_ON = 124,
T_OR = 48,
T_OR_EQ = 49,
T_OR_OR = 50,
T_PLUS = 51,
T_PLUS_EQ = 52,
T_PLUS_PLUS = 53,
T_PRAGMA = 94,
T_PROPERTY = 66,
T_PUBLIC = 92,
T_PRAGMA = 109,
T_PROPERTY = 68,
T_PUBLIC = 107,
T_QUESTION = 54,
T_RBRACE = 55,
T_RBRACKET = 56,
T_READONLY = 68,
T_READONLY = 70,
T_REMAINDER = 57,
T_REMAINDER_EQ = 58,
T_RESERVED_WORD = 87,
T_RESERVED_WORD = 89,
T_RETURN = 59,
T_RPAREN = 60,
T_SEMICOLON = 61,
T_SET = 98,
T_SIGNAL = 67,
T_SET = 113,
T_SIGNAL = 69,
T_STAR = 63,
T_STAR_EQ = 64,
T_STRING_LITERAL = 65,
T_SWITCH = 69,
T_THIS = 70,
T_THROW = 71,
T_TILDE = 72,
T_TRUE = 82,
T_TRY = 73,
T_TYPEOF = 74,
T_VAR = 75,
T_VOID = 76,
T_WHILE = 77,
T_WITH = 78,
T_XOR = 79,
T_XOR_EQ = 80,
T_STAR_EQ = 66,
T_STAR_STAR = 64,
T_STAR_STAR_EQ = 65,
T_STATIC = 100,
T_STRING_LITERAL = 67,
T_SUPER = 97,
T_SWITCH = 71,
T_TEMPLATE_HEAD = 104,
T_TEMPLATE_MIDDLE = 105,
T_TEMPLATE_TAIL = 106,
T_THIS = 72,
T_THROW = 73,
T_TILDE = 74,
T_TRUE = 84,
T_TRY = 75,
T_TYPEOF = 76,
T_VAR = 77,
T_VOID = 78,
T_WHILE = 79,
T_WITH = 80,
T_XOR = 81,
T_XOR_EQ = 82,
T_YIELD = 96,
ACCEPT_STATE = 691,
RULE_COUNT = 369,
STATE_COUNT = 692,
TERMINAL_COUNT = 108,
NON_TERMINAL_COUNT = 112,
ACCEPT_STATE = 1008,
RULE_COUNT = 586,
STATE_COUNT = 1009,
TERMINAL_COUNT = 126,
NON_TERMINAL_COUNT = 213,
GOTO_INDEX_OFFSET = 692,
GOTO_INFO_OFFSET = 3357,
GOTO_CHECK_OFFSET = 3357
GOTO_INDEX_OFFSET = 1009,
GOTO_INFO_OFFSET = 5937,
GOTO_CHECK_OFFSET = 5937
};
static const char *const spell[];
static const short lhs[];
static const short rhs[];
#ifndef QLALR_NO_QMLJSGRAMMAR_DEBUG_INFO
static const int rule_index[];
static const int rule_info[];
#endif // QLALR_NO_QMLJSGRAMMAR_DEBUG_INFO
static const short goto_default[];
static const short action_default[];
static const short action_index[];

View File

@@ -42,10 +42,10 @@ QT_QML_BEGIN_NAMESPACE
namespace QmlJS {
static inline int classify2(const QChar *s, bool qmlMode) {
static inline int classify2(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'a') {
if (s[1].unicode() == 's') {
return qmlMode ? Lexer::T_AS : Lexer::T_IDENTIFIER;
return Lexer::T_AS;
}
}
else if (s[0].unicode() == 'd') {
@@ -61,15 +61,18 @@ static inline int classify2(const QChar *s, bool qmlMode) {
return Lexer::T_IN;
}
}
else if (qmlMode && s[0].unicode() == 'o') {
else if (s[0].unicode() == 'o') {
if (s[1].unicode() == 'n') {
return qmlMode ? Lexer::T_ON : Lexer::T_IDENTIFIER;
return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_ON : Lexer::T_IDENTIFIER;
}
else if (s[1].unicode() == 'f') {
return Lexer::T_OF;
}
}
return Lexer::T_IDENTIFIER;
}
static inline int classify3(const QChar *s, bool qmlMode) {
static inline int classify3(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'f') {
if (s[1].unicode() == 'o') {
if (s[2].unicode() == 'r') {
@@ -87,7 +90,7 @@ static inline int classify3(const QChar *s, bool qmlMode) {
else if (s[0].unicode() == 'i') {
if (s[1].unicode() == 'n') {
if (s[2].unicode() == 't') {
return qmlMode ? int(Lexer::T_INT) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_INT) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -129,12 +132,12 @@ static inline int classify3(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
static inline int classify4(const QChar *s, bool qmlMode) {
static inline int classify4(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'b') {
if (s[1].unicode() == 'y') {
if (s[2].unicode() == 't') {
if (s[3].unicode() == 'e') {
return qmlMode ? int(Lexer::T_BYTE) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_BYTE) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -150,7 +153,7 @@ static inline int classify4(const QChar *s, bool qmlMode) {
else if (s[1].unicode() == 'h') {
if (s[2].unicode() == 'a') {
if (s[3].unicode() == 'r') {
return qmlMode ? int(Lexer::T_CHAR) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_CHAR) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -166,7 +169,16 @@ static inline int classify4(const QChar *s, bool qmlMode) {
else if (s[1].unicode() == 'n') {
if (s[2].unicode() == 'u') {
if (s[3].unicode() == 'm') {
return qmlMode ? int(Lexer::T_ENUM) : int(Lexer::T_RESERVED_WORD);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_ENUM) : int(Lexer::T_RESERVED_WORD);
}
}
}
}
else if (s[0].unicode() == 'f') {
if (s[1].unicode() == 'r') {
if (s[2].unicode() == 'o') {
if (s[3].unicode() == 'm') {
return int(Lexer::T_FROM);
}
}
}
@@ -175,7 +187,7 @@ static inline int classify4(const QChar *s, bool qmlMode) {
if (s[1].unicode() == 'o') {
if (s[2].unicode() == 't') {
if (s[3].unicode() == 'o') {
return qmlMode ? int(Lexer::T_GOTO) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_GOTO) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -184,7 +196,7 @@ static inline int classify4(const QChar *s, bool qmlMode) {
if (s[1].unicode() == 'o') {
if (s[2].unicode() == 'n') {
if (s[3].unicode() == 'g') {
return qmlMode ? int(Lexer::T_LONG) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_LONG) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -235,7 +247,7 @@ static inline int classify4(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
static inline int classify5(const QChar *s, bool qmlMode) {
static inline int classify5(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'b') {
if (s[1].unicode() == 'r') {
if (s[2].unicode() == 'e') {
@@ -290,7 +302,7 @@ static inline int classify5(const QChar *s, bool qmlMode) {
if (s[2].unicode() == 'n') {
if (s[3].unicode() == 'a') {
if (s[4].unicode() == 'l') {
return qmlMode ? int(Lexer::T_FINAL) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_FINAL) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -299,7 +311,7 @@ static inline int classify5(const QChar *s, bool qmlMode) {
if (s[2].unicode() == 'o') {
if (s[3].unicode() == 'a') {
if (s[4].unicode() == 't') {
return qmlMode ? int(Lexer::T_FLOAT) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_FLOAT) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -310,7 +322,7 @@ static inline int classify5(const QChar *s, bool qmlMode) {
if (s[2].unicode() == 'o') {
if (s[3].unicode() == 'r') {
if (s[4].unicode() == 't') {
return qmlMode ? int(Lexer::T_SHORT) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_SHORT) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -319,7 +331,7 @@ static inline int classify5(const QChar *s, bool qmlMode) {
if (s[2].unicode() == 'p') {
if (s[3].unicode() == 'e') {
if (s[4].unicode() == 'r') {
return qmlMode ? int(Lexer::T_SUPER) : int(Lexer::T_RESERVED_WORD);
return int(Lexer::T_SUPER);
}
}
}
@@ -347,10 +359,21 @@ static inline int classify5(const QChar *s, bool qmlMode) {
}
}
}
else if (s[0].unicode() == 'y') {
if (s[1].unicode() == 'i') {
if (s[2].unicode() == 'e') {
if (s[3].unicode() == 'l') {
if (s[4].unicode() == 'd') {
return (parseModeFlags & Lexer::YieldIsKeyword) ? Lexer::T_YIELD : Lexer::T_IDENTIFIER;
}
}
}
}
}
return Lexer::T_IDENTIFIER;
}
static inline int classify6(const QChar *s, bool qmlMode) {
static inline int classify6(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'd') {
if (s[1].unicode() == 'e') {
if (s[2].unicode() == 'l') {
@@ -368,7 +391,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'b') {
if (s[4].unicode() == 'l') {
if (s[5].unicode() == 'e') {
return qmlMode ? int(Lexer::T_DOUBLE) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_DOUBLE) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -394,7 +417,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'o') {
if (s[4].unicode() == 'r') {
if (s[5].unicode() == 't') {
return qmlMode ? int(Lexer::T_IMPORT) : int(Lexer::T_RESERVED_WORD);
return Lexer::T_IMPORT;
}
}
}
@@ -407,7 +430,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'i') {
if (s[4].unicode() == 'v') {
if (s[5].unicode() == 'e') {
return qmlMode ? int(Lexer::T_NATIVE) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_NATIVE) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -420,7 +443,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'l') {
if (s[4].unicode() == 'i') {
if (s[5].unicode() == 'c') {
return qmlMode ? Lexer::T_PUBLIC : Lexer::T_IDENTIFIER;
return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_PUBLIC : Lexer::T_IDENTIFIER;
}
}
}
@@ -431,7 +454,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'g') {
if (s[4].unicode() == 'm') {
if (s[5].unicode() == 'a') {
return qmlMode ? Lexer::T_PRAGMA : Lexer::T_IDENTIFIER;
return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_PRAGMA : Lexer::T_IDENTIFIER;
}
}
}
@@ -452,7 +475,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
}
}
else if (s[0].unicode() == 's') {
if (qmlMode && s[1].unicode() == 'i') {
if ((parseModeFlags & Lexer::QmlMode) && s[1].unicode() == 'i') {
if (s[2].unicode() == 'g') {
if (s[3].unicode() == 'n') {
if (s[4].unicode() == 'a') {
@@ -468,7 +491,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 't') {
if (s[4].unicode() == 'i') {
if (s[5].unicode() == 'c') {
return qmlMode ? int(Lexer::T_STATIC) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::StaticIsKeyword) ? int(Lexer::T_STATIC) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -492,7 +515,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'o') {
if (s[4].unicode() == 'w') {
if (s[5].unicode() == 's') {
return qmlMode ? int(Lexer::T_THROWS) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_THROWS) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -513,7 +536,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
static inline int classify7(const QChar *s, bool qmlMode) {
static inline int classify7(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'b') {
if (s[1].unicode() == 'o') {
if (s[2].unicode() == 'o') {
@@ -521,7 +544,7 @@ static inline int classify7(const QChar *s, bool qmlMode) {
if (s[4].unicode() == 'e') {
if (s[5].unicode() == 'a') {
if (s[6].unicode() == 'n') {
return qmlMode ? int(Lexer::T_BOOLEAN) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_BOOLEAN) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -581,7 +604,7 @@ static inline int classify7(const QChar *s, bool qmlMode) {
if (s[4].unicode() == 'a') {
if (s[5].unicode() == 'g') {
if (s[6].unicode() == 'e') {
return qmlMode ? int(Lexer::T_PACKAGE) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_PACKAGE) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -594,7 +617,7 @@ static inline int classify7(const QChar *s, bool qmlMode) {
if (s[4].unicode() == 'a') {
if (s[5].unicode() == 't') {
if (s[6].unicode() == 'e') {
return qmlMode ? int(Lexer::T_PRIVATE) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_PRIVATE) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -605,7 +628,7 @@ static inline int classify7(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
static inline int classify8(const QChar *s, bool qmlMode) {
static inline int classify8(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'a') {
if (s[1].unicode() == 'b') {
if (s[2].unicode() == 's') {
@@ -614,7 +637,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
if (s[5].unicode() == 'a') {
if (s[6].unicode() == 'c') {
if (s[7].unicode() == 't') {
return qmlMode ? int(Lexer::T_ABSTRACT) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_ABSTRACT) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -674,7 +697,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
}
}
}
else if (qmlMode && s[0].unicode() == 'p') {
else if ((parseModeFlags & Lexer::QmlMode) && s[0].unicode() == 'p') {
if (s[1].unicode() == 'r') {
if (s[2].unicode() == 'o') {
if (s[3].unicode() == 'p') {
@@ -691,7 +714,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
}
}
}
else if (qmlMode && s[0].unicode() == 'r') {
else if ((parseModeFlags & Lexer::QmlMode) && s[0].unicode() == 'r') {
if (s[1].unicode() == 'e') {
if (s[2].unicode() == 'a') {
if (s[3].unicode() == 'd') {
@@ -716,7 +739,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
if (s[5].unicode() == 'i') {
if (s[6].unicode() == 'l') {
if (s[7].unicode() == 'e') {
return qmlMode ? int(Lexer::T_VOLATILE) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_VOLATILE) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -728,7 +751,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
static inline int classify9(const QChar *s, bool qmlMode) {
static inline int classify9(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'i') {
if (s[1].unicode() == 'n') {
if (s[2].unicode() == 't') {
@@ -738,7 +761,7 @@ static inline int classify9(const QChar *s, bool qmlMode) {
if (s[6].unicode() == 'a') {
if (s[7].unicode() == 'c') {
if (s[8].unicode() == 'e') {
return qmlMode ? int(Lexer::T_INTERFACE) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_INTERFACE) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -757,7 +780,7 @@ static inline int classify9(const QChar *s, bool qmlMode) {
if (s[6].unicode() == 't') {
if (s[7].unicode() == 'e') {
if (s[8].unicode() == 'd') {
return qmlMode ? int(Lexer::T_PROTECTED) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_PROTECTED) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -776,7 +799,7 @@ static inline int classify9(const QChar *s, bool qmlMode) {
if (s[6].unicode() == 'e') {
if (s[7].unicode() == 'n') {
if (s[8].unicode() == 't') {
return qmlMode ? int(Lexer::T_TRANSIENT) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_TRANSIENT) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -789,7 +812,7 @@ static inline int classify9(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
static inline int classify10(const QChar *s, bool qmlMode) {
static inline int classify10(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'i') {
if (s[1].unicode() == 'm') {
if (s[2].unicode() == 'p') {
@@ -800,7 +823,7 @@ static inline int classify10(const QChar *s, bool qmlMode) {
if (s[7].unicode() == 'n') {
if (s[8].unicode() == 't') {
if (s[9].unicode() == 's') {
return qmlMode ? int(Lexer::T_IMPLEMENTS) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_IMPLEMENTS) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -833,7 +856,7 @@ static inline int classify10(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
static inline int classify12(const QChar *s, bool qmlMode) {
static inline int classify12(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 's') {
if (s[1].unicode() == 'y') {
if (s[2].unicode() == 'n') {
@@ -846,7 +869,7 @@ static inline int classify12(const QChar *s, bool qmlMode) {
if (s[9].unicode() == 'z') {
if (s[10].unicode() == 'e') {
if (s[11].unicode() == 'd') {
return qmlMode ? int(Lexer::T_SYNCHRONIZED) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_SYNCHRONIZED) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -862,18 +885,18 @@ static inline int classify12(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
int Lexer::classify(const QChar *s, int n, bool qmlMode) {
int Lexer::classify(const QChar *s, int n, int parseModeFlags) {
switch (n) {
case 2: return classify2(s, qmlMode);
case 3: return classify3(s, qmlMode);
case 4: return classify4(s, qmlMode);
case 5: return classify5(s, qmlMode);
case 6: return classify6(s, qmlMode);
case 7: return classify7(s, qmlMode);
case 8: return classify8(s, qmlMode);
case 9: return classify9(s, qmlMode);
case 10: return classify10(s, qmlMode);
case 12: return classify12(s, qmlMode);
case 2: return classify2(s, parseModeFlags);
case 3: return classify3(s, parseModeFlags);
case 4: return classify4(s, parseModeFlags);
case 5: return classify5(s, parseModeFlags);
case 6: return classify6(s, parseModeFlags);
case 7: return classify7(s, parseModeFlags);
case 8: return classify8(s, parseModeFlags);
case 9: return classify9(s, parseModeFlags);
case 10: return classify10(s, parseModeFlags);
case 12: return classify12(s, parseModeFlags);
default: return Lexer::T_IDENTIFIER;
} // switch
}

View File

@@ -44,6 +44,8 @@ static inline int regExpFlagFromChar(const QChar &ch)
case 'g': return Lexer::RegExp_Global;
case 'i': return Lexer::RegExp_IgnoreCase;
case 'm': return Lexer::RegExp_Multiline;
case 'u': return Lexer::RegExp_Unicode;
case 'y': return Lexer::RegExp_Sticky;
}
return 0;
}
@@ -63,22 +65,15 @@ static inline QChar convertHex(QChar c1, QChar c2)
return QChar((convertHex(c1.unicode()) << 4) + convertHex(c2.unicode()));
}
static inline QChar convertUnicode(QChar c1, QChar c2, QChar c3, QChar c4)
{
return QChar((convertHex(c3.unicode()) << 4) + convertHex(c4.unicode()),
(convertHex(c1.unicode()) << 4) + convertHex(c2.unicode()));
}
Lexer::Lexer(Engine *engine)
: _engine(engine)
, _codePtr(0)
, _endPtr(0)
, _lastLinePtr(0)
, _tokenLinePtr(0)
, _tokenStartPtr(0)
, _codePtr(nullptr)
, _endPtr(nullptr)
, _tokenStartPtr(nullptr)
, _char(QLatin1Char('\n'))
, _errorCode(NoError)
, _currentLineNumber(0)
, _currentColumnNumber(0)
, _tokenValue(0)
, _parenthesesState(IgnoreParentheses)
, _parenthesesCount(0)
@@ -87,6 +82,7 @@ Lexer::Lexer(Engine *engine)
, _tokenKind(0)
, _tokenLength(0)
, _tokenLine(0)
, _tokenColumn(0)
, _validTokenText(false)
, _prohibitAutomaticSemicolon(false)
, _restrictedKeyword(false)
@@ -123,14 +119,13 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode)
_codePtr = code.unicode();
_endPtr = _codePtr + code.length();
_lastLinePtr = _codePtr;
_tokenLinePtr = _codePtr;
_tokenStartPtr = _codePtr;
_char = QLatin1Char('\n');
_errorCode = NoError;
_currentLineNumber = lineno;
_currentColumnNumber = 0;
_tokenValue = 0;
// parentheses state
@@ -142,6 +137,7 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode)
_patternFlags = 0;
_tokenLength = 0;
_tokenLine = lineno;
_tokenColumn = 0;
_validTokenText = false;
_prohibitAutomaticSemicolon = false;
@@ -158,9 +154,10 @@ void Lexer::scanChar()
if (sequenceLength == 2)
_char = *_codePtr++;
if (unsigned sequenceLength = isLineTerminatorSequence()) {
_lastLinePtr = _codePtr + sequenceLength - 1; // points to the first character after the newline
++_currentColumnNumber;
if (isLineTerminator()) {
++_currentLineNumber;
_currentColumnNumber = 0;
}
}
@@ -208,12 +205,32 @@ inline bool isBinop(int tok)
return false;
}
}
int hexDigit(QChar c)
{
if (c >= QLatin1Char('0') && c <= QLatin1Char('9'))
return c.unicode() - '0';
if (c >= QLatin1Char('a') && c <= QLatin1Char('f'))
return c.unicode() - 'a' + 10;
if (c >= QLatin1Char('A') && c <= QLatin1Char('F'))
return c.unicode() - 'A' + 10;
return -1;
}
int octalDigit(QChar c)
{
if (c >= QLatin1Char('0') && c <= QLatin1Char('7'))
return c.unicode() - '0';
return -1;
}
} // anonymous namespace
int Lexer::lex()
{
const int previousTokenKind = _tokenKind;
again:
_tokenSpell = QStringRef();
_tokenKind = scanToken();
_tokenLength = _codePtr - _tokenStartPtr - 1;
@@ -225,6 +242,9 @@ int Lexer::lex()
// update the flags
switch (_tokenKind) {
case T_LBRACE:
if (_bracesCount > 0)
++_bracesCount;
Q_FALLTHROUGH();
case T_SEMICOLON:
case T_QUESTION:
case T_COLON:
@@ -252,9 +272,15 @@ int Lexer::lex()
case T_CONTINUE:
case T_BREAK:
case T_RETURN:
case T_YIELD:
case T_THROW:
_restrictedKeyword = true;
break;
case T_RBRACE:
if (_bracesCount > 0)
--_bracesCount;
if (_bracesCount == 0)
goto again;
} // switch
// update the parentheses state
@@ -281,39 +307,57 @@ int Lexer::lex()
return _tokenKind;
}
bool Lexer::isUnicodeEscapeSequence(const QChar *chars)
uint Lexer::decodeUnicodeEscapeCharacter(bool *ok)
{
if (isHexDigit(chars[0]) && isHexDigit(chars[1]) && isHexDigit(chars[2]) && isHexDigit(chars[3]))
return true;
return false;
}
QChar Lexer::decodeUnicodeEscapeCharacter(bool *ok)
{
if (_char == QLatin1Char('u') && isUnicodeEscapeSequence(&_codePtr[0])) {
Q_ASSERT(_char == QLatin1Char('u'));
scanChar(); // skip u
const QChar c1 = _char;
if (_codePtr + 4 <= _endPtr && isHexDigit(_char)) {
uint codePoint = 0;
for (int i = 0; i < 4; ++i) {
int digit = hexDigit(_char);
if (digit < 0)
goto error;
codePoint *= 16;
codePoint += digit;
scanChar();
const QChar c2 = _char;
scanChar();
const QChar c3 = _char;
scanChar();
const QChar c4 = _char;
scanChar();
if (ok)
*ok = true;
return convertUnicode(c1, c2, c3, c4);
}
*ok = true;
return codePoint;
} else if (_codePtr < _endPtr && _char == QLatin1Char('{')) {
scanChar(); // skip '{'
uint codePoint = 0;
if (!isHexDigit(_char))
// need at least one hex digit
goto error;
while (_codePtr <= _endPtr) {
int digit = hexDigit(_char);
if (digit < 0)
break;
codePoint *= 16;
codePoint += digit;
if (codePoint > 0x10ffff)
goto error;
scanChar();
}
if (_char != QLatin1Char('}'))
goto error;
scanChar(); // skip '}'
*ok = true;
return codePoint;
}
error:
_errorCode = IllegalUnicodeEscapeSequence;
_errorMessage = QCoreApplication::translate("QmlParser", "Illegal unicode escape sequence");
*ok = false;
return QChar();
return 0;
}
QChar Lexer::decodeHexEscapeCharacter(bool *ok)
@@ -337,15 +381,15 @@ QChar Lexer::decodeHexEscapeCharacter(bool *ok)
return QChar();
}
static inline bool isIdentifierStart(QChar ch)
static inline bool isIdentifierStart(uint ch)
{
// fast path for ascii
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') ||
(ch.unicode() >= 'A' && ch.unicode() <= 'Z') ||
if ((ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
ch == '$' || ch == '_')
return true;
switch (ch.category()) {
switch (QChar::category(ch)) {
case QChar::Number_Letter:
case QChar::Letter_Uppercase:
case QChar::Letter_Lowercase:
@@ -359,17 +403,17 @@ static inline bool isIdentifierStart(QChar ch)
return false;
}
static bool isIdentifierPart(QChar ch)
static bool isIdentifierPart(uint ch)
{
// fast path for ascii
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') ||
(ch.unicode() >= 'A' && ch.unicode() <= 'Z') ||
(ch.unicode() >= '0' && ch.unicode() <= '9') ||
if ((ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9') ||
ch == '$' || ch == '_' ||
ch.unicode() == 0x200c /* ZWNJ */ || ch.unicode() == 0x200d /* ZWJ */)
ch == 0x200c /* ZWNJ */ || ch == 0x200d /* ZWJ */)
return true;
switch (ch.category()) {
switch (QChar::category(ch)) {
case QChar::Mark_NonSpacing:
case QChar::Mark_SpacingCombining:
@@ -398,19 +442,23 @@ int Lexer::scanToken()
return tk;
}
if (_bracesCount == 0) {
// we're inside a Template string
return scanString(TemplateContinuation);
}
_terminator = false;
again:
_validTokenText = false;
_tokenLinePtr = _lastLinePtr;
while (_char.isSpace()) {
if (unsigned sequenceLength = isLineTerminatorSequence()) {
_tokenLinePtr = _codePtr + sequenceLength - 1;
if (isLineTerminator()) {
if (_restrictedKeyword) {
// automatic semicolon insertion
_tokenLine = _currentLineNumber;
_tokenColumn = _currentColumnNumber;
_tokenStartPtr = _codePtr - 1;
return T_SEMICOLON;
} else {
@@ -424,6 +472,7 @@ again:
_tokenStartPtr = _codePtr - 1;
_tokenLine = _currentLineNumber;
_tokenColumn = _currentColumnNumber;
if (_codePtr > _endPtr)
return EOF_SYMBOL;
@@ -487,6 +536,9 @@ again:
return T_EQ_EQ_EQ;
}
return T_EQ_EQ;
} else if (_char == QLatin1Char('>')) {
scanChar();
return T_ARROW;
}
return T_EQ;
@@ -543,50 +595,18 @@ again:
return T_DIVIDE_;
case '.':
if (_char.isDigit()) {
QVarLengthArray<char,32> chars;
chars.append(ch.unicode()); // append the `.'
while (_char.isDigit()) {
chars.append(_char.unicode());
if (isDecimalDigit(_char.unicode()))
return scanNumber(ch);
if (_char == QLatin1Char('.')) {
scanChar();
}
if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) {
if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) &&
_codePtr[1].isDigit())) {
chars.append(_char.unicode());
scanChar(); // consume `e'
if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) {
chars.append(_char.unicode());
scanChar(); // consume the sign
}
while (_char.isDigit()) {
chars.append(_char.unicode());
if (_char == QLatin1Char('.')) {
scanChar();
}
}
}
chars.append('\0');
const char *begin = chars.constData();
const char *end = 0;
bool ok = false;
_tokenValue = qstrtod(begin, &end, &ok);
if (end - begin != chars.size() - 1) {
_errorCode = IllegalExponentIndicator;
_errorMessage = QCoreApplication::translate("QmlParser", "Illegal syntax for exponential number");
return T_ELLIPSIS;
} else {
_errorCode = IllegalCharacter;
_errorMessage = QCoreApplication::translate("QmlParser", "Unexpected token '.'");
return T_ERROR;
}
return T_NUMERIC_LITERAL;
}
return T_DOT;
@@ -597,7 +617,7 @@ again:
} else if (_char == QLatin1Char('-')) {
scanChar();
if (_terminator && !_delimited && !_prohibitAutomaticSemicolon) {
if (_terminator && !_delimited && !_prohibitAutomaticSemicolon && _tokenKind != T_LPAREN) {
_stackToken = T_MINUS_MINUS;
return T_SEMICOLON;
}
@@ -615,7 +635,7 @@ again:
} else if (_char == QLatin1Char('+')) {
scanChar();
if (_terminator && !_delimited && !_prohibitAutomaticSemicolon) {
if (_terminator && !_delimited && !_prohibitAutomaticSemicolon && _tokenKind != T_LPAREN) {
_stackToken = T_PLUS_PLUS;
return T_SEMICOLON;
}
@@ -628,6 +648,13 @@ again:
if (_char == QLatin1Char('=')) {
scanChar();
return T_STAR_EQ;
} else if (_char == QLatin1Char('*')) {
scanChar();
if (_char == QLatin1Char('=')) {
scanChar();
return T_STAR_STAR_EQ;
}
return T_STAR_STAR;
}
return T_STAR;
@@ -662,16 +689,129 @@ again:
}
return T_NOT;
case '`':
_outerTemplateBraceCount.push(_bracesCount);
Q_FALLTHROUGH();
case '\'':
case '"': {
const QChar quote = ch;
case '"':
return scanString(ScanStringMode(ch.unicode()));
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return scanNumber(ch);
default: {
uint c = ch.unicode();
bool identifierWithEscapeChars = false;
if (QChar::isHighSurrogate(c) && QChar::isLowSurrogate(_char.unicode())) {
c = QChar::surrogateToUcs4(ushort(c), _char.unicode());
scanChar();
} else if (c == '\\' && _char == QLatin1Char('u')) {
identifierWithEscapeChars = true;
bool ok = false;
c = decodeUnicodeEscapeCharacter(&ok);
if (!ok)
return T_ERROR;
}
if (isIdentifierStart(c)) {
if (identifierWithEscapeChars) {
_tokenText.resize(0);
if (QChar::requiresSurrogates(c)) {
_tokenText += QChar(QChar::highSurrogate(c));
_tokenText += QChar(QChar::lowSurrogate(c));
} else {
_tokenText += QChar(c);
}
_validTokenText = true;
}
while (_codePtr <= _endPtr) {
c = _char.unicode();
if (QChar::isHighSurrogate(c) && QChar::isLowSurrogate(_codePtr->unicode())) {
scanChar();
c = QChar::surrogateToUcs4(ushort(c), _char.unicode());
} else if (_char == QLatin1Char('\\') && _codePtr[0] == QLatin1Char('u')) {
if (!identifierWithEscapeChars) {
identifierWithEscapeChars = true;
_tokenText.resize(0);
_tokenText.insert(0, _tokenStartPtr, _codePtr - _tokenStartPtr - 1);
_validTokenText = true;
}
scanChar(); // skip '\\'
bool ok = false;
c = decodeUnicodeEscapeCharacter(&ok);
if (!ok)
return T_ERROR;
if (!isIdentifierPart(c))
break;
if (identifierWithEscapeChars) {
if (QChar::requiresSurrogates(c)) {
_tokenText += QChar(QChar::highSurrogate(c));
_tokenText += QChar(QChar::lowSurrogate(c));
} else {
_tokenText += QChar(c);
}
}
continue;
}
if (!isIdentifierPart(c))
break;
if (identifierWithEscapeChars) {
if (QChar::requiresSurrogates(c)) {
_tokenText += QChar(QChar::highSurrogate(c));
_tokenText += QChar(QChar::lowSurrogate(c));
} else {
_tokenText += QChar(c);
}
}
scanChar();
}
_tokenLength = _codePtr - _tokenStartPtr - 1;
int kind = T_IDENTIFIER;
if (!identifierWithEscapeChars)
kind = classify(_tokenStartPtr, _tokenLength, parseModeFlags());
if (_engine) {
if (kind == T_IDENTIFIER && identifierWithEscapeChars)
_tokenSpell = _engine->newStringRef(_tokenText);
else
_tokenSpell = _engine->midRef(_tokenStartPtr - _code.unicode(), _tokenLength);
}
return kind;
}
}
break;
}
return T_ERROR;
}
int Lexer::scanString(ScanStringMode mode)
{
QChar quote = (mode == TemplateContinuation) ? QChar(TemplateHead) : QChar(mode);
bool multilineStringLiteral = false;
const QChar *startCode = _codePtr;
if (_engine) {
while (_codePtr <= _endPtr) {
if (isLineTerminator()) {
if (isLineTerminator() && quote != QLatin1Char('`')) {
if (qmlMode())
break;
_errorCode = IllegalCharacter;
@@ -679,10 +819,20 @@ again:
return T_ERROR;
} else if (_char == QLatin1Char('\\')) {
break;
} else if (_char == '$' && quote == QLatin1Char('`')) {
break;
} else if (_char == quote) {
_tokenSpell = _engine->midRef(startCode - _code.unicode() - 1, _codePtr - startCode);
scanChar();
if (quote == QLatin1Char('`'))
_bracesCount = _outerTemplateBraceCount.pop();
if (mode == TemplateHead)
return T_NO_SUBSTITUTION_TEMPLATE;
else if (mode == TemplateContinuation)
return T_TEMPLATE_TAIL;
else
return T_STRING_LITERAL;
}
scanChar();
@@ -702,13 +852,29 @@ again:
if (sequenceLength == 2)
_tokenText += *_codePtr;
scanChar();
} else if (_char == quote) {
} else if (_char == mode) {
scanChar();
if (_engine)
_tokenSpell = _engine->newStringRef(_tokenText);
if (quote == QLatin1Char('`'))
_bracesCount = _outerTemplateBraceCount.pop();
if (mode == TemplateContinuation)
return T_TEMPLATE_TAIL;
else if (mode == TemplateHead)
return T_NO_SUBSTITUTION_TEMPLATE;
return multilineStringLiteral ? T_MULTILINE_STRING_LITERAL : T_STRING_LITERAL;
} else if (quote == QLatin1Char('`') && _char == QLatin1Char('$') && *_codePtr == '{') {
scanChar();
scanChar();
_bracesCount = 1;
if (_engine)
_tokenSpell = _engine->newStringRef(_tokenText);
return (mode == TemplateHead ? T_TEMPLATE_HEAD : T_TEMPLATE_MIDDLE);
} else if (_char == QLatin1Char('\\')) {
scanChar();
if (_codePtr > _endPtr) {
@@ -723,11 +889,15 @@ again:
// unicode escape sequence
case 'u': {
bool ok = false;
u = decodeUnicodeEscapeCharacter(&ok);
if (! ok) {
_errorCode = IllegalUnicodeEscapeSequence;
_errorMessage = QCoreApplication::translate("QmlParser", "Illegal unicode escape sequence");
uint codePoint = decodeUnicodeEscapeCharacter(&ok);
if (!ok)
return T_ERROR;
if (QChar::requiresSurrogates(codePoint)) {
// need to use a surrogate pair
_tokenText += QChar(QChar::highSurrogate(codePoint));
u = QChar::lowSurrogate(codePoint);
} else {
u = codePoint;
}
} break;
@@ -759,7 +929,7 @@ again:
u = QLatin1Char('\0');
break;
}
// fall through
Q_FALLTHROUGH();
case '1':
case '2':
case '3':
@@ -797,145 +967,96 @@ again:
_errorMessage = QCoreApplication::translate("QmlParser", "Unclosed string at end of line");
return T_ERROR;
}
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return scanNumber(ch);
default: {
QChar c = ch;
bool identifierWithEscapeChars = false;
if (c == QLatin1Char('\\') && _char == QLatin1Char('u')) {
identifierWithEscapeChars = true;
bool ok = false;
c = decodeUnicodeEscapeCharacter(&ok);
if (! ok) {
_errorCode = IllegalUnicodeEscapeSequence;
_errorMessage = QCoreApplication::translate("QmlParser", "Illegal unicode escape sequence");
return T_ERROR;
}
}
if (isIdentifierStart(c)) {
if (identifierWithEscapeChars) {
_tokenText.resize(0);
_tokenText += c;
_validTokenText = true;
}
while (true) {
c = _char;
if (_char == QLatin1Char('\\') && _codePtr[0] == QLatin1Char('u')) {
if (! identifierWithEscapeChars) {
identifierWithEscapeChars = true;
_tokenText.resize(0);
_tokenText.insert(0, _tokenStartPtr, _codePtr - _tokenStartPtr - 1);
_validTokenText = true;
}
scanChar(); // skip '\\'
bool ok = false;
c = decodeUnicodeEscapeCharacter(&ok);
if (! ok) {
_errorCode = IllegalUnicodeEscapeSequence;
_errorMessage = QCoreApplication::translate("QmlParser", "Illegal unicode escape sequence");
return T_ERROR;
}
if (isIdentifierPart(c))
_tokenText += c;
continue;
} else if (isIdentifierPart(c)) {
if (identifierWithEscapeChars)
_tokenText += c;
scanChar();
continue;
}
_tokenLength = _codePtr - _tokenStartPtr - 1;
int kind = T_IDENTIFIER;
if (! identifierWithEscapeChars)
kind = classify(_tokenStartPtr, _tokenLength, _qmlMode);
if (_engine) {
if (kind == T_IDENTIFIER && identifierWithEscapeChars)
_tokenSpell = _engine->newStringRef(_tokenText);
else
_tokenSpell = _engine->midRef(_tokenStartPtr - _code.unicode(), _tokenLength);
}
return kind;
}
}
}
break;
}
return T_ERROR;
}
int Lexer::scanNumber(QChar ch)
{
if (ch != QLatin1Char('0')) {
QVarLengthArray<char, 64> buf;
buf += ch.toLatin1();
if (ch == QLatin1Char('0')) {
if (_char == QLatin1Char('x') || _char == QLatin1Char('X')) {
ch = _char; // remember the x or X to use it in the error message below.
QChar n = _char;
const QChar *code = _codePtr;
while (n.isDigit()) {
buf += n.toLatin1();
n = *code++;
// parse hex integer literal
scanChar(); // consume 'x'
if (!isHexDigit(_char)) {
_errorCode = IllegalNumber;
_errorMessage = QCoreApplication::translate("QmlParser", "At least one hexadecimal digit is required after '0%1'").arg(ch);
return T_ERROR;
}
if (n != QLatin1Char('.') && n != QLatin1Char('e') && n != QLatin1Char('E')) {
if (code != _codePtr) {
_codePtr = code - 1;
double d = 0.;
while (1) {
int digit = ::hexDigit(_char);
if (digit < 0)
break;
d *= 16;
d += digit;
scanChar();
}
buf.append('\0');
_tokenValue = strtod(buf.constData(), 0);
_tokenValue = d;
return T_NUMERIC_LITERAL;
} else if (_char == QLatin1Char('o') || _char == QLatin1Char('O')) {
ch = _char; // remember the o or O to use it in the error message below.
// parse octal integer literal
scanChar(); // consume 'o'
if (!isOctalDigit(_char.unicode())) {
_errorCode = IllegalNumber;
_errorMessage = QCoreApplication::translate("QmlParser", "At least one octal digit is required after '0%1'").arg(ch);
return T_ERROR;
}
double d = 0.;
while (1) {
int digit = ::octalDigit(_char);
if (digit < 0)
break;
d *= 8;
d += digit;
scanChar();
}
_tokenValue = d;
return T_NUMERIC_LITERAL;
} else if (_char == QLatin1Char('b') || _char == QLatin1Char('B')) {
ch = _char; // remember the b or B to use it in the error message below.
// parse binary integer literal
scanChar(); // consume 'b'
if (_char.unicode() != '0' && _char.unicode() != '1') {
_errorCode = IllegalNumber;
_errorMessage = QCoreApplication::translate("QmlParser", "At least one binary digit is required after '0%1'").arg(ch);
return T_ERROR;
}
double d = 0.;
while (1) {
int digit = 0;
if (_char.unicode() == '1')
digit = 1;
else if (_char.unicode() != '0')
break;
d *= 2;
d += digit;
scanChar();
}
_tokenValue = d;
return T_NUMERIC_LITERAL;
} else if (_char.isDigit() && !qmlMode()) {
_errorCode = IllegalCharacter;
_errorMessage = QCoreApplication::translate("QmlParser", "Decimal numbers can't start with '0'");
return T_ERROR;
}
QVarLengthArray<char,32> chars;
chars.append(ch.unicode());
if (ch == QLatin1Char('0') && (_char == QLatin1Char('x') || _char == QLatin1Char('X'))) {
ch = _char; // remember the x or X to use it in the error message below.
// parse hex integer literal
chars.append(_char.unicode());
scanChar(); // consume `x'
while (isHexDigit(_char)) {
chars.append(_char.unicode());
scanChar();
}
if (chars.size() < 3) {
_errorCode = IllegalHexNumber;
_errorMessage = QCoreApplication::translate("QmlParser", "At least one hexadecimal digit is required after '0%1'").arg(ch);
return T_ERROR;
}
_tokenValue = integerFromString(chars.constData(), chars.size(), 16);
return T_NUMERIC_LITERAL;
}
// decimal integer literal
QVarLengthArray<char,32> chars;
chars.append(ch.unicode());
if (ch != QLatin1Char('.')) {
while (_char.isDigit()) {
chars.append(_char.unicode());
scanChar(); // consume the digit
@@ -944,6 +1065,8 @@ int Lexer::scanNumber(QChar ch)
if (_char == QLatin1Char('.')) {
chars.append(_char.unicode());
scanChar(); // consume `.'
}
}
while (_char.isDigit()) {
chars.append(_char.unicode());
@@ -968,35 +1091,11 @@ int Lexer::scanNumber(QChar ch)
}
}
}
} else if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) {
if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) &&
_codePtr[1].isDigit())) {
chars.append(_char.unicode());
scanChar(); // consume `e'
if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) {
chars.append(_char.unicode());
scanChar(); // consume the sign
}
while (_char.isDigit()) {
chars.append(_char.unicode());
scanChar();
}
}
}
if (chars.size() == 1) {
// if we ended up with a single digit, then it was a '0'
_tokenValue = 0;
return T_NUMERIC_LITERAL;
}
chars.append('\0');
const char *begin = chars.constData();
const char *end = 0;
const char *end = nullptr;
bool ok = false;
_tokenValue = qstrtod(begin, &end, &ok);
@@ -1160,16 +1259,6 @@ bool Lexer::isOctalDigit(ushort c)
return (c >= '0' && c <= '7');
}
int Lexer::tokenEndLine() const
{
return _currentLineNumber;
}
int Lexer::tokenEndColumn() const
{
return _codePtr - _lastLinePtr;
}
QString Lexer::tokenText() const
{
if (_validTokenText)
@@ -1242,6 +1331,7 @@ static const int uriTokens[] = {
QmlJSGrammar::T_FUNCTION,
QmlJSGrammar::T_IF,
QmlJSGrammar::T_IN,
QmlJSGrammar::T_OF,
QmlJSGrammar::T_INSTANCEOF,
QmlJSGrammar::T_NEW,
QmlJSGrammar::T_NULL,
@@ -1288,7 +1378,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
lex(); // skip T_DOT
if (! (_tokenKind == T_IDENTIFIER || _tokenKind == T_RESERVED_WORD))
if (! (_tokenKind == T_IDENTIFIER || _tokenKind == T_IMPORT))
return true; // expected a valid QML/JS directive
const QString directiveName = tokenText();
@@ -1312,7 +1402,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
}
// we found a .pragma library directive
directives->pragmaLibrary(lineNumber, column);
directives->pragmaLibrary();
} else {
Q_ASSERT(directiveName == QLatin1String("import"));
@@ -1382,7 +1472,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
//
// recognize the mandatory `as' followed by the module name
//
if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("as") && tokenStartLine() == lineNumber)) {
if (! (lex() == T_AS && tokenStartLine() == lineNumber)) {
if (fileImport)
error->message = QCoreApplication::translate("QmlParser", "File import requires a qualifier");
else

View File

@@ -40,6 +40,7 @@
#include "qmljsgrammar_p.h"
#include <QtCore/qstring.h>
#include <QtCore/qstack.h>
QT_QML_BEGIN_NAMESPACE
@@ -47,35 +48,7 @@ namespace QmlJS {
class Engine;
class DiagnosticMessage;
class QML_PARSER_EXPORT Directives {
public:
virtual ~Directives() {}
virtual void pragmaLibrary(int line, int column)
{
Q_UNUSED(line);
Q_UNUSED(column);
}
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, int line, int column)
{
Q_UNUSED(uri);
Q_UNUSED(version);
Q_UNUSED(module);
Q_UNUSED(line);
Q_UNUSED(column);
}
};
class Directives;
class QML_PARSER_EXPORT Lexer: public QmlJSGrammar
{
@@ -85,10 +58,7 @@ public:
T_BOOLEAN = T_RESERVED_WORD,
T_BYTE = T_RESERVED_WORD,
T_CHAR = T_RESERVED_WORD,
T_CLASS = T_RESERVED_WORD,
T_DOUBLE = T_RESERVED_WORD,
T_EXPORT = T_RESERVED_WORD,
T_EXTENDS = T_RESERVED_WORD,
T_FINAL = T_RESERVED_WORD,
T_FLOAT = T_RESERVED_WORD,
T_GOTO = T_RESERVED_WORD,
@@ -101,8 +71,6 @@ public:
T_PRIVATE = T_RESERVED_WORD,
T_PROTECTED = T_RESERVED_WORD,
T_SHORT = T_RESERVED_WORD,
T_STATIC = T_RESERVED_WORD,
T_SUPER = T_RESERVED_WORD,
T_SYNCHRONIZED = T_RESERVED_WORD,
T_THROWS = T_RESERVED_WORD,
T_TRANSIENT = T_RESERVED_WORD,
@@ -112,7 +80,7 @@ public:
enum Error {
NoError,
IllegalCharacter,
IllegalHexNumber,
IllegalNumber,
UnclosedStringLiteral,
IllegalEscapeSequence,
IllegalUnicodeEscapeSequence,
@@ -130,13 +98,34 @@ public:
enum RegExpFlag {
RegExp_Global = 0x01,
RegExp_IgnoreCase = 0x02,
RegExp_Multiline = 0x04
RegExp_Multiline = 0x04,
RegExp_Unicode = 0x08,
RegExp_Sticky = 0x10
};
enum ParseModeFlags {
QmlMode = 0x1,
YieldIsKeyword = 0x2,
StaticIsKeyword = 0x4
};
public:
Lexer(Engine *engine);
int parseModeFlags() const {
int flags = 0;
if (qmlMode())
flags |= QmlMode|StaticIsKeyword;
if (yieldIsKeyWord())
flags |= YieldIsKeyword;
if (_staticIsKeyword)
flags |= StaticIsKeyword;
return flags;
}
bool qmlMode() const;
bool yieldIsKeyWord() const { return _generatorLevel != 0; }
void setStaticIsKeyword(bool b) { _staticIsKeyword = b; }
QString code() const;
void setCode(const QString &code, int lineno, bool qmlMode = true);
@@ -154,10 +143,7 @@ public:
int tokenLength() const { return _tokenLength; }
int tokenStartLine() const { return _tokenLine; }
int tokenStartColumn() const { return _tokenStartPtr - _tokenLinePtr + 1; }
int tokenEndLine() const;
int tokenEndColumn() const;
int tokenStartColumn() const { return _tokenColumn; }
inline QStringRef tokenSpell() const { return _tokenSpell; }
double tokenValue() const { return _tokenValue; }
@@ -176,13 +162,23 @@ public:
BalancedParentheses
};
void enterGeneratorBody() { ++_generatorLevel; }
void leaveGeneratorBody() { --_generatorLevel; }
protected:
int classify(const QChar *s, int n, bool qmlMode);
static int classify(const QChar *s, int n, int parseModeFlags);
private:
inline void scanChar();
int scanToken();
int scanNumber(QChar ch);
enum ScanStringMode {
SingleQuote = '\'',
DoubleQuote = '"',
TemplateHead = '`',
TemplateContinuation = 0
};
int scanString(ScanStringMode mode);
bool isLineTerminator() const;
unsigned isLineTerminatorSequence() const;
@@ -190,10 +186,9 @@ private:
static bool isDecimalDigit(ushort c);
static bool isHexDigit(QChar c);
static bool isOctalDigit(ushort c);
static bool isUnicodeEscapeSequence(const QChar *chars);
void syncProhibitAutomaticSemicolon();
QChar decodeUnicodeEscapeCharacter(bool *ok);
uint decodeUnicodeEscapeCharacter(bool *ok);
QChar decodeHexEscapeCharacter(bool *ok);
private:
@@ -206,26 +201,30 @@ private:
const QChar *_codePtr;
const QChar *_endPtr;
const QChar *_lastLinePtr;
const QChar *_tokenLinePtr;
const QChar *_tokenStartPtr;
QChar _char;
Error _errorCode;
int _currentLineNumber;
int _currentColumnNumber;
double _tokenValue;
// parentheses state
ParenthesesState _parenthesesState;
int _parenthesesCount;
// template string stack
QStack<int> _outerTemplateBraceCount;
int _bracesCount = -1;
int _stackToken;
int _patternFlags;
int _tokenKind;
int _tokenLength;
int _tokenLine;
int _tokenColumn;
bool _validTokenText;
bool _prohibitAutomaticSemicolon;
@@ -234,6 +233,8 @@ private:
bool _followsClosingBrace;
bool _delimited;
bool _qmlMode;
int _generatorLevel = 0;
bool _staticIsKeyword = false;
};
} // end of namespace QmlJS

View File

@@ -56,13 +56,7 @@ class QML_PARSER_EXPORT MemoryPool : public QSharedData
void operator =(const MemoryPool &other);
public:
MemoryPool()
: _blocks(0),
_allocatedBlocks(0),
_blockCount(-1),
_ptr(0),
_end(0)
{ }
MemoryPool() {}
~MemoryPool()
{
@@ -74,6 +68,7 @@ public:
free(_blocks);
}
qDeleteAll(strings);
}
inline void *allocate(size_t size)
@@ -90,11 +85,16 @@ public:
void reset()
{
_blockCount = -1;
_ptr = _end = 0;
_ptr = _end = nullptr;
}
template <typename Tp> Tp *New() { return new (this->allocate(sizeof(Tp))) Tp(); }
QStringRef newString(const QString &string) {
strings.append(new QString(string));
return QStringRef(strings.last());
}
private:
Q_NEVER_INLINE void *allocate_helper(size_t size)
{
@@ -110,7 +110,7 @@ private:
Q_CHECK_PTR(_blocks);
for (int index = _blockCount; index < _allocatedBlocks; ++index)
_blocks[index] = 0;
_blocks[index] = nullptr;
}
char *&block = _blocks[_blockCount];
@@ -129,11 +129,12 @@ private:
}
private:
char **_blocks;
int _allocatedBlocks;
int _blockCount;
char *_ptr;
char *_end;
char **_blocks = nullptr;
int _allocatedBlocks = 0;
int _blockCount = -1;
char *_ptr = nullptr;
char *_end = nullptr;
QVector<QString*> strings;
enum
{
@@ -144,12 +145,10 @@ private:
class QML_PARSER_EXPORT Managed
{
Managed(const Managed &other);
void operator = (const Managed &other);
Q_DISABLE_COPY(Managed)
public:
Managed() {}
~Managed() {}
Managed() = default;
~Managed() = default;
void *operator new(size_t size, MemoryPool *pool) { return pool->allocate(size); }
void operator delete(void *) {}

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,13 @@
#line 178 "qmljs.g"
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -13,13 +16,26 @@
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** 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-3.0.html.
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -70,30 +86,42 @@ public:
union Value {
int ival;
double dval;
AST::VariableScope scope;
AST::ForEachType forEachType;
AST::ArgumentList *ArgumentList;
AST::CaseBlock *CaseBlock;
AST::CaseClause *CaseClause;
AST::CaseClauses *CaseClauses;
AST::Catch *Catch;
AST::DefaultClause *DefaultClause;
AST::ElementList *ElementList;
AST::Elision *Elision;
AST::ExpressionNode *Expression;
AST::TemplateLiteral *Template;
AST::Finally *Finally;
AST::FormalParameterList *FormalParameterList;
AST::FunctionBody *FunctionBody;
AST::FunctionDeclaration *FunctionDeclaration;
AST::Node *Node;
AST::PropertyName *PropertyName;
AST::PropertyAssignment *PropertyAssignment;
AST::PropertyAssignmentList *PropertyAssignmentList;
AST::SourceElement *SourceElement;
AST::SourceElements *SourceElements;
AST::Statement *Statement;
AST::StatementList *StatementList;
AST::Block *Block;
AST::VariableDeclaration *VariableDeclaration;
AST::VariableDeclarationList *VariableDeclarationList;
AST::Pattern *Pattern;
AST::PatternElement *PatternElement;
AST::PatternElementList *PatternElementList;
AST::PatternProperty *PatternProperty;
AST::PatternPropertyList *PatternPropertyList;
AST::ClassElementList *ClassElementList;
AST::ImportClause *ImportClause;
AST::FromClause *FromClause;
AST::NameSpaceImport *NameSpaceImport;
AST::ImportsList *ImportsList;
AST::NamedImports *NamedImports;
AST::ImportSpecifier *ImportSpecifier;
AST::ExportSpecifier *ExportSpecifier;
AST::ExportsList *ExportsList;
AST::ExportClause *ExportClause;
AST::ExportDeclaration *ExportDeclaration;
AST::UiProgram *UiProgram;
AST::UiHeaderItemList *UiHeaderItemList;
@@ -110,7 +138,6 @@ public:
AST::UiObjectMemberList *UiObjectMemberList;
AST::UiArrayMemberList *UiArrayMemberList;
AST::UiQualifiedId *UiQualifiedId;
AST::UiQualifiedPragmaId *UiQualifiedPragmaId;
AST::UiEnumMemberList *UiEnumMemberList;
};
@@ -119,12 +146,13 @@ public:
~Parser();
// parse a UI program
bool parse() { return parse(T_FEED_UI_PROGRAM); }
bool parse() { ++functionNestingLevel; bool r = parse(T_FEED_UI_PROGRAM); --functionNestingLevel; return r; }
bool parseStatement() { return parse(T_FEED_JS_STATEMENT); }
bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); }
bool parseSourceElement() { return parse(T_FEED_JS_SOURCE_ELEMENT); }
bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); }
bool parseProgram() { return parse(T_FEED_JS_PROGRAM); }
bool parseUiObjectMember() { ++functionNestingLevel; bool r = parse(T_FEED_UI_OBJECT_MEMBER); --functionNestingLevel; return r; }
bool parseProgram() { return parse(T_FEED_JS_SCRIPT); }
bool parseScript() { return parse(T_FEED_JS_SCRIPT); }
bool parseModule() { return parse(T_FEED_JS_MODULE); }
AST::UiProgram *ast() const
{ return AST::cast<AST::UiProgram *>(program); }
@@ -193,22 +221,31 @@ protected:
{ return location_stack [tos + index - 1]; }
AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr);
AST::UiQualifiedPragmaId *reparseAsQualifiedPragmaId(AST::ExpressionNode *expr);
void pushToken(int token);
int lookaheadToken(Lexer *lexer);
void syntaxError(const AST::SourceLocation &location, const char *message) {
diagnostic_messages.append(DiagnosticMessage(Severity::Error, location, QLatin1String(message)));
}
void syntaxError(const AST::SourceLocation &location, const QString &message) {
diagnostic_messages.append(DiagnosticMessage(Severity::Error, location, message));
}
protected:
Engine *driver;
MemoryPool *pool;
int tos;
int stack_size;
Value *sym_stack;
int *state_stack;
AST::SourceLocation *location_stack;
QStringRef *string_stack;
int tos = 0;
int stack_size = 0;
Value *sym_stack = nullptr;
int *state_stack = nullptr;
AST::SourceLocation *location_stack = nullptr;
QVector<QStringRef> string_stack;
AST::Node *program;
AST::Node *program = nullptr;
// error recovery
enum { TOKEN_BUFFER_SIZE = 3 };
// error recovery and lookahead handling
enum { TOKEN_BUFFER_SIZE = 5 };
struct SavedToken {
int token;
@@ -217,14 +254,25 @@ protected:
QStringRef spell;
};
double yylval;
int yytoken = -1;
double yylval = 0.;
QStringRef yytokenspell;
AST::SourceLocation yylloc;
AST::SourceLocation yyprevlloc;
SavedToken token_buffer[TOKEN_BUFFER_SIZE];
SavedToken *first_token;
SavedToken *last_token;
SavedToken *first_token = nullptr;
SavedToken *last_token = nullptr;
int functionNestingLevel = 0;
enum CoverExpressionType {
CE_Invalid,
CE_ParenthesizedExpression,
CE_FormalParameterList
};
AST::SourceLocation coverExpressionErrorLocation;
CoverExpressionType coverExpressionType = CE_Invalid;
QList<DiagnosticMessage> diagnostic_messages;
};
@@ -233,9 +281,27 @@ protected:
#define J_SCRIPT_REGEXPLITERAL_RULE1 96
#line 1511 "qmljs.g"
#define J_SCRIPT_REGEXPLITERAL_RULE2 97
#define J_SCRIPT_REGEXPLITERAL_RULE1 128
#line 1523 "qmljs.g"
#define J_SCRIPT_REGEXPLITERAL_RULE2 129
#line 3022 "qmljs.g"
#define J_SCRIPT_EXPRESSIONSTATEMENTLOOKAHEAD_RULE 421
#line 3653 "qmljs.g"
#define J_SCRIPT_CONCISEBODYLOOKAHEAD_RULE 499
#line 4181 "qmljs.g"
#define J_SCRIPT_EXPORTDECLARATIONLOOKAHEAD_RULE 569
#line 4469 "qmljs.g"
QT_QML_END_NAMESPACE

View File

@@ -306,14 +306,14 @@ bool Bind::visit(UiArrayBinding *)
return true;
}
bool Bind::visit(VariableDeclaration *ast)
bool Bind::visit(PatternElement *ast)
{
if (ast->name.isEmpty())
if (ast->bindingIdentifier.isEmpty() || !ast->isVariableDeclaration())
return false;
ASTVariableReference *ref = new ASTVariableReference(ast, _doc, &_valueOwner);
if (_currentObjectValue)
_currentObjectValue->setMember(ast->name.toString(), ref);
_currentObjectValue->setMember(ast->bindingIdentifier, ref);
return true;
}
@@ -337,8 +337,8 @@ bool Bind::visit(FunctionExpression *ast)
// 1. Function formal arguments
for (FormalParameterList *it = ast->formals; it; it = it->next) {
if (!it->name.isEmpty())
functionScope->setMember(it->name.toString(), _valueOwner.unknownValue());
if (!it->element->bindingIdentifier.isEmpty())
functionScope->setMember(it->element->bindingIdentifier, _valueOwner.unknownValue());
}
// 2. Functions defined inside the function body

View File

@@ -79,7 +79,7 @@ protected:
// QML/JS
bool visit(AST::FunctionDeclaration *ast) override;
bool visit(AST::FunctionExpression *ast) override;
bool visit(AST::VariableDeclaration *ast) override;
bool visit(AST::PatternElement *ast) override;
ObjectValue *switchObjectValue(ObjectValue *newObjectValue);
ObjectValue *bindObject(AST::UiQualifiedId *qualifiedTypeNameId, AST::UiObjectInitializer *initializer);

View File

@@ -197,10 +197,6 @@ protected:
return true;
if (Statement *stmt = ast->statementCast())
onUnreachable(stmt);
if (FunctionSourceElement *fun = cast<FunctionSourceElement *>(ast))
onUnreachable(fun->declaration);
if (StatementSourceElement *stmt = cast<StatementSourceElement *>(ast))
onUnreachable(stmt->statement);
return false;
}
@@ -306,8 +302,6 @@ protected:
bool visit(WhileStatement *ast) override { return preconditionLoopStatement(ast, ast->statement); }
bool visit(ForStatement *ast) override { return preconditionLoopStatement(ast, ast->statement); }
bool visit(ForEachStatement *ast) override { return preconditionLoopStatement(ast, ast->statement); }
bool visit(LocalForStatement *ast) override { return preconditionLoopStatement(ast, ast->statement); }
bool visit(LocalForEachStatement *ast) override { return preconditionLoopStatement(ast, ast->statement); }
bool visit(DoWhileStatement *ast) override
{
@@ -367,8 +361,8 @@ public:
{
clear();
for (FormalParameterList *plist = function->formals; plist; plist = plist->next) {
if (!plist->name.isEmpty())
_formalParameterNames += plist->name.toString();
if (!plist->element->bindingIdentifier.isEmpty())
_formalParameterNames += plist->element->bindingIdentifier.toString();
}
Node::accept(function->body, this);
@@ -418,11 +412,11 @@ protected:
return true;
}
bool visit(VariableDeclaration *ast)
bool visit(PatternElement *ast)
{
if (ast->name.isEmpty())
if (ast->bindingIdentifier.isEmpty() || !ast->isVariableDeclaration())
return true;
const QString &name = ast->name.toString();
const QString &name = ast->bindingIdentifier.toString();
if (_formalParameterNames.contains(name))
addMessage(WarnAlreadyFormalParameter, ast->identifierToken, name);
@@ -484,7 +478,7 @@ private:
QList<Message> _messages;
QStringList _formalParameterNames;
QHash<QString, VariableDeclaration *> _declaredVariables;
QHash<QString, PatternElement *> _declaredVariables;
QHash<QString, FunctionDeclaration *> _declaredFunctions;
QHash<QString, QList<SourceLocation> > _possiblyUndeclaredUses;
bool _seenNonDeclarationStatement;
@@ -1039,8 +1033,8 @@ bool Check::visit(UiArrayBinding *ast)
bool Check::visit(UiPublicMember *ast)
{
if (ast->type == UiPublicMember::Property) {
if (ast->isValid()) {
const QStringRef typeName = ast->memberTypeName();
if (ast->defaultToken.isValid() || ast->readonlyToken.isValid()) {
const QStringRef typeName = ast->memberType->name;
if (!typeName.isEmpty() && typeName.at(0).isLower()) {
const QString typeNameS = typeName.toString();
if (!isValidBuiltinPropertyType(typeNameS))
@@ -1277,8 +1271,6 @@ bool Check::visit(Block *ast)
&& !cast<Finally *>(p)
&& !cast<ForStatement *>(p)
&& !cast<ForEachStatement *>(p)
&& !cast<LocalForStatement *>(p)
&& !cast<LocalForEachStatement *>(p)
&& !cast<DoWhileStatement *>(p)
&& !cast<WhileStatement *>(p)
&& !cast<IfStatement *>(p)
@@ -1311,8 +1303,7 @@ bool Check::visit(Expression *ast)
{
if (ast->left && ast->right) {
Node *p = parent();
if (!cast<ForStatement *>(p)
&& !cast<LocalForStatement *>(p)) {
if (!cast<ForStatement *>(p)) {
addMessage(WarnComma, ast->commaToken);
}
}
@@ -1372,13 +1363,6 @@ bool Check::visit(ForStatement *ast)
return true;
}
bool Check::visit(LocalForStatement *ast)
{
if (ast->condition)
checkAssignInCondition(ast->condition);
return true;
}
bool Check::visit(WhileStatement *ast)
{
if (ast->expression)

View File

@@ -84,7 +84,6 @@ protected:
bool visit(AST::ExpressionStatement *ast) override;
bool visit(AST::IfStatement *ast) override;
bool visit(AST::ForStatement *ast) override;
bool visit(AST::LocalForStatement *ast) override;
bool visit(AST::WhileStatement *ast) override;
bool visit(AST::DoWhileStatement *ast) override;
bool visit(AST::CaseBlock *ast) override;

View File

@@ -366,11 +366,11 @@ void DescribeValueVisitor::visit(const Reference *value)
}
} else if (const ASTVariableReference *v = value->asAstVariableReference()) {
basicDump("ASTVariableReference", v, printDetail);
const AST::VariableDeclaration *var = v->ast();
if (printDetail && var) {
const AST::PatternElement *var = v->ast();
if (printDetail && var && var->isVariableDeclaration()) {
dumpNewline();
dump("variable:");
dump(var->name.toString());
dump(var->bindingIdentifier.toString());
}
} else if (const QmlPrototypeReference *v = value->asQmlPrototypeReference()) {
basicDump("QmlPrototypeReference", v, printDetail);

View File

@@ -248,7 +248,7 @@ public:
{}
void pragmaLibrary(int line, int column) override
void pragmaLibrary(int line, int column)
{
isLibrary = true;
addLocation(line, column);
@@ -305,12 +305,14 @@ bool Document::parse_helper(int startToken)
case QmlJSGrammar::T_FEED_UI_PROGRAM:
_parsedCorrectly = parser.parse();
break;
case QmlJSGrammar::T_FEED_JS_PROGRAM:
case QmlJSGrammar::T_FEED_JS_SCRIPT:
case QmlJSGrammar::T_FEED_JS_MODULE:
_parsedCorrectly = parser.parseProgram();
for (const auto &d: directives.locations()) {
_jsdirectives << d;
}
break;
case QmlJSGrammar::T_FEED_JS_EXPRESSION:
_parsedCorrectly = parser.parseExpression();
break;
@@ -341,7 +343,7 @@ bool Document::parseQml()
bool Document::parseJavaScript()
{
return parse_helper(QmlJSGrammar::T_FEED_JS_PROGRAM);
return parse_helper(QmlJSGrammar::T_FEED_JS_SCRIPT);
}
bool Document::parseExpression()

View File

@@ -126,11 +126,6 @@ bool Evaluate::visit(AST::UiHeaderItemList *)
return false;
}
bool Evaluate::visit(AST::UiQualifiedPragmaId *)
{
return false;
}
bool Evaluate::visit(AST::UiPragma *)
{
return false;
@@ -264,20 +259,20 @@ bool Evaluate::visit(AST::RegExpLiteral *)
return false;
}
bool Evaluate::visit(AST::ArrayLiteral *)
bool Evaluate::visit(AST::ArrayPattern *)
{
_result = _valueOwner->arrayCtor()->returnValue();
return false;
}
bool Evaluate::visit(AST::ObjectLiteral *)
bool Evaluate::visit(AST::ObjectPattern *)
{
// ### properties
_result = _valueOwner->newObject();
return false;
}
bool Evaluate::visit(AST::ElementList *)
bool Evaluate::visit(AST::PatternElementList *)
{
return false;
}
@@ -287,17 +282,12 @@ bool Evaluate::visit(AST::Elision *)
return false;
}
bool Evaluate::visit(AST::PropertyAssignmentList *)
bool Evaluate::visit(AST::PatternPropertyList *)
{
return false;
}
bool Evaluate::visit(AST::PropertyGetterSetter *)
{
return false;
}
bool Evaluate::visit(AST::PropertyNameAndValue *)
bool Evaluate::visit(AST::PatternProperty *)
{
return false;
}
@@ -529,11 +519,6 @@ bool Evaluate::visit(AST::Block *)
return false;
}
bool Evaluate::visit(AST::StatementList *)
{
return false;
}
bool Evaluate::visit(AST::VariableStatement *)
{
return false;
@@ -544,7 +529,7 @@ bool Evaluate::visit(AST::VariableDeclarationList *)
return false;
}
bool Evaluate::visit(AST::VariableDeclaration *)
bool Evaluate::visit(AST::PatternElement *)
{
return false;
}
@@ -579,21 +564,11 @@ bool Evaluate::visit(AST::ForStatement *)
return false;
}
bool Evaluate::visit(AST::LocalForStatement *)
{
return false;
}
bool Evaluate::visit(AST::ForEachStatement *)
{
return false;
}
bool Evaluate::visit(AST::LocalForEachStatement *)
{
return false;
}
bool Evaluate::visit(AST::ContinueStatement *)
{
return false;
@@ -679,27 +654,12 @@ bool Evaluate::visit(AST::FormalParameterList *)
return false;
}
bool Evaluate::visit(AST::FunctionBody *)
{
return false;
}
bool Evaluate::visit(AST::Program *)
{
return false;
}
bool Evaluate::visit(AST::SourceElements *)
{
return false;
}
bool Evaluate::visit(AST::FunctionSourceElement *)
{
return false;
}
bool Evaluate::visit(AST::StatementSourceElement *)
bool Evaluate::visit(AST::StatementList *)
{
return false;
}

View File

@@ -61,7 +61,6 @@ protected:
// Ui
bool visit(AST::UiProgram *ast) override;
bool visit(AST::UiHeaderItemList *ast) override;
bool visit(AST::UiQualifiedPragmaId *ast) override;
bool visit(AST::UiPragma *ast) override;
bool visit(AST::UiImport *ast) override;
bool visit(AST::UiPublicMember *ast) override;
@@ -84,13 +83,12 @@ protected:
bool visit(AST::StringLiteral *ast) override;
bool visit(AST::NumericLiteral *ast) override;
bool visit(AST::RegExpLiteral *ast) override;
bool visit(AST::ArrayLiteral *ast) override;
bool visit(AST::ObjectLiteral *ast) override;
bool visit(AST::ElementList *ast) override;
bool visit(AST::ArrayPattern *ast) override;
bool visit(AST::ObjectPattern *ast) override;
bool visit(AST::Elision *ast) override;
bool visit(AST::PropertyAssignmentList *ast) override;
bool visit(AST::PropertyGetterSetter *ast) override;
bool visit(AST::PropertyNameAndValue *ast) override;
bool visit(AST::PatternElementList *ast) override;
bool visit(AST::PatternPropertyList *ast) override;
bool visit(AST::PatternProperty *ast) override;
bool visit(AST::NestedExpression *ast) override;
bool visit(AST::IdentifierPropertyName *ast) override;
bool visit(AST::StringLiteralPropertyName *ast) override;
@@ -116,19 +114,16 @@ protected:
bool visit(AST::ConditionalExpression *ast) override;
bool visit(AST::Expression *ast) override;
bool visit(AST::Block *ast) override;
bool visit(AST::StatementList *ast) override;
bool visit(AST::VariableStatement *ast) override;
bool visit(AST::VariableDeclarationList *ast) override;
bool visit(AST::VariableDeclaration *ast) override;
bool visit(AST::PatternElement *ast) override;
bool visit(AST::EmptyStatement *ast) override;
bool visit(AST::ExpressionStatement *ast) override;
bool visit(AST::IfStatement *ast) override;
bool visit(AST::DoWhileStatement *ast) override;
bool visit(AST::WhileStatement *ast) override;
bool visit(AST::ForStatement *ast) override;
bool visit(AST::LocalForStatement *ast) override;
bool visit(AST::ForEachStatement *ast) override;
bool visit(AST::LocalForEachStatement *ast) override;
bool visit(AST::ContinueStatement *ast) override;
bool visit(AST::BreakStatement *ast) override;
bool visit(AST::ReturnStatement *ast) override;
@@ -146,11 +141,8 @@ protected:
bool visit(AST::FunctionDeclaration *ast) override;
bool visit(AST::FunctionExpression *ast) override;
bool visit(AST::FormalParameterList *ast) override;
bool visit(AST::FunctionBody *ast) override;
bool visit(AST::Program *ast) override;
bool visit(AST::SourceElements *ast) override;
bool visit(AST::FunctionSourceElement *ast) override;
bool visit(AST::StatementSourceElement *ast) override;
bool visit(AST::StatementList *ast) override;
bool visit(AST::DebuggerStatement *ast) override;
private:

View File

@@ -1052,6 +1052,11 @@ void ObjectValue::setMember(const QString &name, const Value *value)
m_members[name].value = value;
}
void ObjectValue::setMember(const QStringRef &name, const Value *value)
{
m_members[name.toString()].value = value;
}
void ObjectValue::setPropertyInfo(const QString &name, const PropertyInfo &propertyInfo)
{
m_members[name].propertyInfo = propertyInfo;
@@ -1856,7 +1861,7 @@ ASTObjectValue::ASTObjectValue(UiQualifiedId *typeName,
for (UiObjectMemberList *it = m_initializer->members; it; it = it->next) {
UiObjectMember *member = it->member;
if (UiPublicMember *def = cast<UiPublicMember *>(member)) {
if (def->type == UiPublicMember::Property && !def->name.isEmpty() && def->isValid()) {
if (def->type == UiPublicMember::Property && !def->name.isEmpty()) {
ASTPropertyReference *ref = new ASTPropertyReference(def, m_doc, valueOwner);
m_properties.append(ref);
if (def->defaultToken.isValid())
@@ -1931,7 +1936,7 @@ const Document *ASTObjectValue::document() const
return m_doc;
}
ASTVariableReference::ASTVariableReference(VariableDeclaration *ast, const Document *doc, ValueOwner *valueOwner)
ASTVariableReference::ASTVariableReference(PatternElement *ast, const Document *doc, ValueOwner *valueOwner)
: Reference(valueOwner)
, m_ast(ast)
, m_doc(doc)
@@ -1947,7 +1952,7 @@ const ASTVariableReference *ASTVariableReference::asAstVariableReference() const
return this;
}
const VariableDeclaration *ASTVariableReference::ast() const
const PatternElement *ASTVariableReference::ast() const
{
return m_ast;
}
@@ -1955,16 +1960,16 @@ const VariableDeclaration *ASTVariableReference::ast() const
const Value *ASTVariableReference::value(ReferenceContext *referenceContext) const
{
// may be assigned to later
if (!m_ast->expression)
if (!m_ast->expressionCast())
return valueOwner()->unknownValue();
Document::Ptr doc = m_doc->ptr();
ScopeChain scopeChain(doc, referenceContext->context());
ScopeBuilder builder(&scopeChain);
builder.push(ScopeAstPath(doc)(m_ast->expression->firstSourceLocation().begin()));
builder.push(ScopeAstPath(doc)(m_ast->expressionCast()->firstSourceLocation().begin()));
Evaluate evaluator(&scopeChain, referenceContext);
return evaluator(m_ast->expression);
return evaluator(m_ast->expressionCast());
}
bool ASTVariableReference::getSourceLocation(QString *fileName, int *line, int *column) const
@@ -1981,12 +1986,12 @@ class UsesArgumentsArray : protected Visitor
bool m_usesArgumentsArray;
public:
bool operator()(FunctionBody *ast)
bool operator()(StatementList *ast)
{
if (!ast || !ast->elements)
if (!ast)
return false;
m_usesArgumentsArray = false;
Node::accept(ast->elements, this);
Node::accept(ast, this);
return m_usesArgumentsArray;
}
@@ -2001,7 +2006,8 @@ protected:
}
// don't go into nested functions
bool visit(FunctionBody *) { return false; }
bool visit(Program *) { return false; }
bool visit(StatementList *) { return false; }
};
} // anonymous namespace
@@ -2013,7 +2019,7 @@ ASTFunctionValue::ASTFunctionValue(FunctionExpression *ast, const Document *doc,
setPrototype(valueOwner->functionPrototype());
for (FormalParameterList *it = ast->formals; it; it = it->next)
m_argumentNames.append(it->name.toString());
m_argumentNames.append(it->element->bindingIdentifier.toString());
m_isVariadic = UsesArgumentsArray()(ast->body);
}
@@ -2121,10 +2127,9 @@ bool ASTPropertyReference::getSourceLocation(QString *fileName, int *line, int *
const Value *ASTPropertyReference::value(ReferenceContext *referenceContext) const
{
if (m_ast->statement
&& (!m_ast->isValid()
|| m_ast->memberTypeName() == QLatin1String("variant")
|| m_ast->memberTypeName() == QLatin1String("var")
|| m_ast->memberTypeName() == QLatin1String("alias"))) {
&& (m_ast->memberType->name == QLatin1String("variant")
|| m_ast->memberType->name == QLatin1String("var")
|| m_ast->memberType->name == QLatin1String("alias"))) {
// Adjust the context for the current location - expensive!
// ### Improve efficiency by caching the 'use chain' constructed in ScopeBuilder.
@@ -2140,7 +2145,7 @@ const Value *ASTPropertyReference::value(ReferenceContext *referenceContext) con
return evaluator(m_ast->statement);
}
const QString memberType = m_ast->memberTypeName().toString();
const QString memberType = m_ast->memberType->name.toString();
const Value *builtin = valueOwner()->defaultValueForBuiltinType(memberType);
if (!builtin->asUndefinedValue())

View File

@@ -508,6 +508,7 @@ public:
virtual void processMembers(MemberProcessor *processor) const;
virtual void setMember(const QString &name, const Value *value);
virtual void setMember(const QStringRef &name, const Value *value);
virtual void setPropertyInfo(const QString &name, const PropertyInfo &propertyInfo);
virtual void removeMember(const QString &name);
@@ -884,14 +885,14 @@ private:
class QMLJS_EXPORT ASTVariableReference: public Reference
{
AST::VariableDeclaration *m_ast;
AST::PatternElement *m_ast;
const Document *m_doc;
public:
ASTVariableReference(AST::VariableDeclaration *ast, const Document *doc, ValueOwner *valueOwner);
ASTVariableReference(AST::PatternElement *ast, const Document *doc, ValueOwner *valueOwner);
~ASTVariableReference();
const ASTVariableReference *asAstVariableReference() const override;
const AST::VariableDeclaration *ast() const;
const AST::PatternElement *ast() const;
private:
const Value *value(ReferenceContext *referenceContext) const override;
bool getSourceLocation(QString *fileName, int *line, int *column) const override;

View File

@@ -531,7 +531,6 @@ protected:
bool visit(UiPragma *ast) override
{
out("pragma ", ast->pragmaToken);
accept(ast->pragmaType);
return false;
}
@@ -666,20 +665,16 @@ protected:
bool visit(NumericLiteral *ast) override { out(ast->literalToken); return true; }
bool visit(RegExpLiteral *ast) override { out(ast->literalToken); return true; }
bool visit(ArrayLiteral *ast) override
bool visit(ArrayPattern *ast) override
{
out(ast->lbracketToken);
if (ast->elements)
accept(ast->elements);
if (ast->elements && ast->elision)
out(", ", ast->commaToken);
if (ast->elision)
accept(ast->elision);
out(ast->rbracketToken);
return false;
}
bool visit(ObjectLiteral *ast) override
bool visit(ObjectPattern *ast) override
{
out(ast->lbraceToken);
lnAcceptIndented(ast->properties);
@@ -688,55 +683,57 @@ protected:
return false;
}
bool visit(ElementList *ast) override
bool visit(PatternElementList *ast) override
{
for (ElementList *it = ast; it; it = it->next) {
for (PatternElementList *it = ast; it; it = it->next) {
if (it->elision)
accept(it->elision);
if (it->elision && it->expression)
if (it->elision && it->element)
out(", ");
if (it->expression)
accept(it->expression);
if (it->element)
accept(it->element);
if (it->next)
out(", ", ast->commaToken);
out(", ");
}
return false;
}
bool visit(PropertyAssignmentList *ast) override
bool visit(PatternPropertyList *ast) override
{
for (PropertyAssignmentList *it = ast; it; it = it->next) {
PropertyNameAndValue *assignment = AST::cast<PropertyNameAndValue *>(it->assignment);
for (PatternPropertyList *it = ast; it; it = it->next) {
PatternProperty *assignment = AST::cast<PatternProperty *>(it->property);
if (assignment) {
out("\"");
accept(assignment->name);
out("\"");
out(": ", assignment->colonToken);
accept(assignment->value);
accept(assignment->initializer);
if (it->next) {
out(",", ast->commaToken); // always invalid?
out(","); // always invalid?
newLine();
}
continue;
}
PropertyGetterSetter *getterSetter = AST::cast<PropertyGetterSetter *>(it->assignment);
if (getterSetter) {
switch (getterSetter->type) {
case PropertyGetterSetter::Getter:
PatternPropertyList *getterSetter = AST::cast<PatternPropertyList *>(it->next);
if (getterSetter->property) {
switch (getterSetter->property->type) {
case PatternElement::Getter:
out("get");
break;
case PropertyGetterSetter::Setter:
case PatternElement::Setter:
out("set");
break;
default:
break;
}
accept(getterSetter->name);
out("(", getterSetter->lparenToken);
accept(getterSetter->formals);
out("(", getterSetter->rparenToken);
out(" {", getterSetter->lbraceToken);
accept(getterSetter->functionBody);
out(" }", getterSetter->rbraceToken);
accept(getterSetter->property->name);
out("(");
//accept(getterSetter->formals); // TODO
out(")");
out(" {");
//accept(getterSetter->functionBody); // TODO
out(" }");
}
}
return false;
@@ -922,12 +919,15 @@ protected:
return false;
}
bool visit(VariableDeclaration *ast) override
bool visit(PatternElement *ast) override
{
if (!ast->isVariableDeclaration())
return false;
out(ast->identifierToken);
if (ast->expression) {
if (ast->initializer) {
out(" = ");
accept(ast->expression);
accept(ast->initializer);
}
return false;
}
@@ -996,45 +996,13 @@ protected:
return false;
}
bool visit(LocalForStatement *ast) override
{
out(ast->forToken);
out(" ");
out(ast->lparenToken);
out(ast->varToken);
out(" ");
accept(ast->declarations);
out("; ", ast->firstSemicolonToken);
accept(ast->condition);
out("; ", ast->secondSemicolonToken);
accept(ast->expression);
out(")", ast->rparenToken);
acceptBlockOrIndented(ast->statement);
return false;
}
bool visit(ForEachStatement *ast) override
{
out(ast->forToken);
out(" ");
out(ast->lparenToken);
accept(ast->initialiser);
out(" in ", ast->inToken);
accept(ast->expression);
out(ast->rparenToken);
acceptBlockOrIndented(ast->statement);
return false;
}
bool visit(LocalForEachStatement *ast) override
{
out(ast->forToken);
out(" ");
out(ast->lparenToken);
out(ast->varToken);
out(" ");
accept(ast->declaration);
out(" in ", ast->inToken);
accept(ast->lhs);
out(" in ");
accept(ast->expression);
out(ast->rparenToken);
acceptBlockOrIndented(ast->statement);
@@ -1245,12 +1213,6 @@ protected:
return false;
}
bool visit(UiQualifiedPragmaId *ast) override
{
out(ast->identifierToken);
return false;
}
bool visit(Elision *ast) override
{
for (Elision *it = ast; it; it = it->next) {
@@ -1288,16 +1250,6 @@ protected:
return false;
}
bool visit(SourceElements *ast) override
{
for (SourceElements *it = ast; it; it = it->next) {
accept(it->element);
if (it->next)
newLine();
}
return false;
}
bool visit(VariableDeclarationList *ast) override
{
for (VariableDeclarationList *it = ast; it; it = it->next) {
@@ -1321,9 +1273,7 @@ protected:
bool visit(FormalParameterList *ast) override
{
for (FormalParameterList *it = ast; it; it = it->next) {
if (it->commaToken.isValid())
out(", ", it->commaToken);
out(it->identifierToken);
out(it->element->bindingIdentifier.toString()); // TODO
}
return false;
}

View File

@@ -250,12 +250,12 @@ QVariant SimpleAbstractStreamReader::parsePropertyExpression(AST::ExpressionNode
{
Q_ASSERT(expressionNode);
AST::ArrayLiteral *arrayLiteral = AST::cast<AST::ArrayLiteral *>(expressionNode);
AST::ArrayPattern *arrayLiteral = AST::cast<AST::ArrayPattern *>(expressionNode);
if (arrayLiteral) {
QList<QVariant> variantList;
for (AST::ElementList *it = arrayLiteral->elements; it; it = it->next)
variantList << parsePropertyExpression(it->expression);
for (AST::PatternElementList *it = arrayLiteral->elements; it; it = it->next)
variantList << parsePropertyExpression(it->element->initializer);
return variantList;
}

View File

@@ -189,13 +189,14 @@ void TypeDescriptionReader::readDependencies(UiScriptBinding *ast)
addError(ast->statement->firstSourceLocation(), tr("Expected dependency definitions"));
return;
}
ArrayLiteral *exp = AST::cast<ArrayLiteral *>(stmt->expression);
ArrayPattern *exp = AST::cast<ArrayPattern *>(stmt->expression);
if (!exp) {
addError(stmt->expression->firstSourceLocation(), tr("Expected dependency definitions"));
return;
}
for (ElementList *l = exp->elements; l; l = l->next) {
StringLiteral *str = AST::cast<StringLiteral *>(l->expression);
for (PatternElementList *l = exp->elements; l; l = l->next) {
//StringLiteral *str = AST::cast<StringLiteral *>(l->element->initializer);
StringLiteral *str = AST::cast<StringLiteral *>(l->element->initializer);
*_dependencies << str->value.toString();
}
}
@@ -231,7 +232,7 @@ void TypeDescriptionReader::readComponent(UiObjectDefinition *ast)
} else if (name == QLatin1String("exports")) {
readExports(script, fmo);
} else if (name == QLatin1String("exportMetaObjectRevisions")) {
readMetaObjectRevisions(script, fmo);
//readMetaObjectRevisions(script, fmo);
} else if (name == QLatin1String("attachedType")) {
fmo->setAttachedTypeName(readStringBinding(script));
} else if (name == QLatin1String("isSingleton")) {
@@ -562,14 +563,14 @@ void TypeDescriptionReader::readExports(UiScriptBinding *ast, FakeMetaObject::Pt
return;
}
ArrayLiteral *arrayLit = AST::cast<ArrayLiteral *>(expStmt->expression);
ArrayPattern *arrayLit = AST::cast<ArrayPattern *>(expStmt->expression);
if (!arrayLit) {
addError(expStmt->firstSourceLocation(), tr("Expected array of strings after colon."));
return;
}
for (ElementList *it = arrayLit->elements; it; it = it->next) {
StringLiteral *stringLit = AST::cast<StringLiteral *>(it->expression);
for (PatternElementList *it = arrayLit->elements; it; it = it->next) {
StringLiteral *stringLit = AST::cast<StringLiteral *>(it->element->initializer);
if (!stringLit) {
addError(arrayLit->firstSourceLocation(), tr("Expected array literal with only string literal members."));
return;
@@ -608,7 +609,7 @@ void TypeDescriptionReader::readMetaObjectRevisions(UiScriptBinding *ast, FakeMe
return;
}
ArrayLiteral *arrayLit = AST::cast<ArrayLiteral *>(expStmt->expression);
ArrayPattern *arrayLit = AST::cast<ArrayPattern *>(expStmt->expression);
if (!arrayLit) {
addError(expStmt->firstSourceLocation(), tr("Expected array of numbers after colon."));
return;
@@ -616,8 +617,8 @@ void TypeDescriptionReader::readMetaObjectRevisions(UiScriptBinding *ast, FakeMe
int exportIndex = 0;
const int exportCount = fmo->exports().size();
for (ElementList *it = arrayLit->elements; it; it = it->next, ++exportIndex) {
NumericLiteral *numberLit = cast<NumericLiteral *>(it->expression);
for (PatternElementList *it = arrayLit->elements; it; it = it->next, ++exportIndex) {
NumericLiteral *numberLit = cast<NumericLiteral *>(it->element->initializer);
if (!numberLit) {
addError(arrayLit->firstSourceLocation(), tr("Expected array literal with only number literal members."));
return;
@@ -654,18 +655,18 @@ void TypeDescriptionReader::readEnumValues(AST::UiScriptBinding *ast, LanguageUt
return;
}
ObjectLiteral *objectLit = AST::cast<ObjectLiteral *>(expStmt->expression);
ObjectPattern *objectLit = AST::cast<ObjectPattern *>(expStmt->expression);
if (!objectLit) {
addError(expStmt->firstSourceLocation(), tr("Expected object literal after colon."));
return;
}
for (PropertyAssignmentList *it = objectLit->properties; it; it = it->next) {
PropertyNameAndValue *assignement = AST::cast<PropertyNameAndValue *>(it->assignment);
for (PatternPropertyList *it = objectLit->properties; it; it = it->next) {
PatternProperty *assignement = AST::cast<PatternProperty *>(it->property);
if (assignement) {
StringLiteralPropertyName *propName = AST::cast<StringLiteralPropertyName *>(assignement->name);
NumericLiteral *value = AST::cast<NumericLiteral *>(assignement->value);
UnaryMinusExpression *minus = AST::cast<UnaryMinusExpression *>(assignement->value);
NumericLiteral *value = AST::cast<NumericLiteral *>(assignement->initializer);
UnaryMinusExpression *minus = AST::cast<UnaryMinusExpression *>(assignement->initializer);
if (minus)
value = AST::cast<NumericLiteral *>(minus->expression);
if (!propName || !value) {
@@ -679,7 +680,7 @@ void TypeDescriptionReader::readEnumValues(AST::UiScriptBinding *ast, LanguageUt
fme->addKey(propName->id.toString(), v);
continue;
}
PropertyGetterSetter *getterSetter = AST::cast<PropertyGetterSetter *>(it->assignment);
PatternPropertyList *getterSetter = AST::cast<PatternPropertyList *>(it->next);
if (getterSetter)
addError(objectLit->firstSourceLocation(), tr("Enum should not contain getter and setters, but only 'string: number' elements."));
}

View File

@@ -35,7 +35,8 @@ bool InteractiveInterpreter::canEvaluate()
int yytos = -1;
setCode(m_code, 1);
m_tokens.append(T_FEED_JS_PROGRAM);
m_tokens.append(T_FEED_JS_SCRIPT);
m_tokens.append(T_FEED_JS_MODULE);
do {
if (++yytos == m_stateStack.size())

View File

@@ -160,15 +160,12 @@ public:
bool visit(VariableStatement *ast) override { test(ast); return true; }
bool visit(VariableDeclarationList *ast) override { test(ast); return true; }
bool visit(VariableDeclaration *ast) override { test(ast); return true; }
bool visit(ExpressionStatement *ast) override { test(ast); return true; }
bool visit(IfStatement *ast) override { test(ast); return true; }
bool visit(DoWhileStatement *ast) override { test(ast); return true; }
bool visit(WhileStatement *ast) override { test(ast); return true; }
bool visit(ForStatement *ast) override { test(ast); return true; }
bool visit(LocalForStatement *ast) override { test(ast); return true; }
bool visit(ForEachStatement *ast) override { test(ast); return true; }
bool visit(LocalForEachStatement *ast) override { test(ast); return true; }
bool visit(ContinueStatement *ast) override { test(ast); return true; }
bool visit(BreakStatement *ast) override { test(ast); return true; }
bool visit(ReturnStatement *ast) override { test(ast); return true; }

View File

@@ -84,7 +84,7 @@ protected:
bool visit(AST::UiPublicMember *node) override
{
if (node->memberTypeName() == m_typeName){
if (node->memberType->name == m_typeName){
const ObjectValue * objectValue = m_context->lookupType(m_document.data(), QStringList(m_typeName));
if (objectValue == m_typeValue)
m_implemenations.append(node->typeToken);
@@ -187,9 +187,10 @@ protected:
return false;
}
bool visit(AST::VariableDeclaration *node) override
bool visit(AST::PatternElement *node) override
{
AST::Node::accept(node->expression, this);
if (node->isVariableDeclaration())
AST::Node::accept(node->initializer, this);
return false;
}

View File

@@ -81,6 +81,7 @@ void AddPropertyVisitor::addInMembers(QmlJS::AST::UiObjectInitializer *initializ
QmlJS::AST::UiObjectMemberList *insertAfter = searchMemberToInsertAfter(initializer->members, m_name, m_propertyOrder);
QmlJS::AST::SourceLocation endOfPreviousMember;
QmlJS::AST::SourceLocation startOfNextMember;
bool previousMemberSemicolon = false;
unsigned depth;
if (insertAfter == nullptr || insertAfter->member == nullptr) {
@@ -96,6 +97,16 @@ void AddPropertyVisitor::addInMembers(QmlJS::AST::UiObjectInitializer *initializ
} else {
endOfPreviousMember = insertAfter->member->lastSourceLocation();
// Find out if the previous members ends with semicolon.
if (auto member = QmlJS::AST::cast<QmlJS::AST::UiScriptBinding*>(insertAfter->member)) {
if (auto stmt = QmlJS::AST::cast<QmlJS::AST::ExpressionStatement*>(member->statement))
previousMemberSemicolon = stmt->semicolonToken.isValid();
else
previousMemberSemicolon = endOfPreviousMember.isValid();
} else {
previousMemberSemicolon = endOfPreviousMember.isValid();
}
if (insertAfter->next && insertAfter->next->member)
startOfNextMember = insertAfter->next->member->firstSourceLocation();
else
@@ -113,7 +124,7 @@ void AddPropertyVisitor::addInMembers(QmlJS::AST::UiObjectInitializer *initializ
needsTrailingSemicolon = m_propertyType == QmlRefactoring::ScriptBinding;
}
} else { // we're inserting after a member, not after the lbrace
if (endOfPreviousMember.isValid()) { // there already is a semicolon after the previous member
if (previousMemberSemicolon) {
if (insertAfter->next && insertAfter->next->member) { // and the after us there is a member, not an rbrace, so:
needsTrailingSemicolon = m_propertyType == QmlRefactoring::ScriptBinding;
}

View File

@@ -85,8 +85,8 @@ static TypeName resolveTypeName(const ASTPropertyReference *ref, const ContextPt
{
TypeName type = "unknown";
if (ref->ast()->isValid()) {
type = ref->ast()->memberTypeName().toUtf8();
if (ref->ast()->defaultToken.isValid()) {
type = ref->ast()->memberType->name.toUtf8();
if (type == "alias") {
const Value *value = context->lookupReference(ref);

View File

@@ -1178,9 +1178,6 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
if (property->type == AST::UiPublicMember::Signal)
continue; // QML designer doesn't support this yet.
if (property->name.isEmpty() || !property->isValid())
continue; // better safe than sorry.
const QStringRef astName = property->name;
QString astValue;
if (property->statement)
@@ -1193,7 +1190,7 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
astValue = astValue.left(astValue.length() - 1);
astValue = astValue.trimmed();
const TypeName &astType = property->memberTypeName().toUtf8();
const TypeName &astType = property->memberType->name.toUtf8();
AbstractProperty modelProperty = modelNode.property(astName.toUtf8());
if (property->binding) {
@@ -1250,12 +1247,12 @@ static QVariant parsePropertyExpression(AST::ExpressionNode *expressionNode)
{
Q_ASSERT(expressionNode);
auto arrayLiteral = AST::cast<AST::ArrayLiteral *>(expressionNode);
auto arrayLiteral = AST::cast<AST::ArrayPattern *>(expressionNode);
if (arrayLiteral) {
QList<QVariant> variantList;
for (AST::ElementList *it = arrayLiteral->elements; it; it = it->next)
variantList << parsePropertyExpression(it->expression);
for (AST::PatternElementList *it = arrayLiteral->elements; it; it = it->next)
variantList << parsePropertyExpression(it->element->initializer);
return variantList;
}

View File

@@ -295,8 +295,8 @@ protected:
decl.text += QLatin1Char('(');
for (FormalParameterList *it = ast->formals; it; it = it->next) {
if (!it->name.isEmpty())
decl.text += it->name;
if (!it->element->bindingIdentifier.isEmpty())
decl.text += it->element->bindingIdentifier;
if (it->next)
decl.text += QLatin1String(", ");
@@ -309,14 +309,14 @@ protected:
return false;
}
bool visit(AST::VariableDeclaration *ast) override
bool visit(AST::PatternElement *ast) override
{
if (ast->name.isEmpty())
if (!ast->isVariableDeclaration() || ast->bindingIdentifier.isEmpty())
return false;
Declaration decl;
decl.text.fill(QLatin1Char(' '), _depth);
decl.text += ast->name;
decl.text += ast->bindingIdentifier;
const SourceLocation first = ast->identifierToken;
decl.startLine = first.startLine;
@@ -343,8 +343,8 @@ protected:
decl.text += QLatin1Char('(');
for (FormalParameterList *it = funcExpr->formals; it; it = it->next) {
if (!it->name.isEmpty())
decl.text += it->name;
if (!it->element->bindingIdentifier.isEmpty())
decl.text += it->element->bindingIdentifier;
if (it->next)
decl.text += QLatin1String(", ");

View File

@@ -227,9 +227,9 @@ protected:
return false;
}
bool visit(AST::VariableDeclaration *node) override
bool visit(AST::PatternElement *node) override
{
if (node->name == _name) {
if (node->isVariableDeclaration() && node->bindingIdentifier == _name) {
if (checkLookup())
_usages.append(node->identifierToken);
}
@@ -322,7 +322,7 @@ protected:
bool visit(AST::UiPublicMember *node) override
{
if (node->memberTypeName() == _name){
if (node->memberType->name == _name){
const ObjectValue * tVal = _context->lookupType(_doc.data(), QStringList(_name));
if (tVal == _typeValue)
_usages.append(node->typeToken);
@@ -406,9 +406,10 @@ protected:
return false;
}
bool visit(AST::VariableDeclaration *node) override
bool visit(AST::PatternElement *node) override
{
Node::accept(node->expression, this);
if (node->isVariableDeclaration())
Node::accept(node->initializer, this);
return false;
}
@@ -583,8 +584,8 @@ protected:
bool visit(UiPublicMember *node) override
{
if (containsOffset(node->typeToken)){
if (node->isValid()) {
_name = node->memberTypeName().toString();
if (node->defaultToken.isValid()) {
_name = node->memberType->name.toString();
_targetValue = _scopeChain->context()->lookupType(_doc.data(), QStringList(_name));
_scope = 0;
_typeKind = TypeKind;
@@ -612,10 +613,10 @@ protected:
return true;
}
bool visit(VariableDeclaration *node) override
bool visit(PatternElement *node) override
{
if (containsOffset(node->identifierToken)) {
_name = node->name.toString();
if (node->isVariableDeclaration() && containsOffset(node->identifierToken)) {
_name = node->bindingIdentifier.toString();
return false;
}
return true;

View File

@@ -323,8 +323,8 @@ protected:
bool visit(UiPublicMember *ast)
{
if (ast->typeToken.isValid() && ast->isValid()) {
if (m_scopeChain.context()->lookupType(m_scopeChain.document().data(), QStringList(ast->memberTypeName().toString())))
if (ast->typeToken.isValid()) { // TODO: ast->isValid() ?
if (m_scopeChain.context()->lookupType(m_scopeChain.document().data(), QStringList(ast->memberType->name.toString())))
addUse(ast->typeToken, SemanticHighlighter::QmlTypeType);
}
if (ast->identifierToken.isValid())
@@ -350,9 +350,10 @@ protected:
return visit(static_cast<FunctionExpression *>(ast));
}
bool visit(VariableDeclaration *ast)
bool visit(PatternElement *ast)
{
processName(ast->name, ast->identifierToken);
if (ast->isVariableDeclaration())
processName(ast->bindingIdentifier, ast->identifierToken);
return true;
}

View File

@@ -263,14 +263,14 @@ private:
bool visit(AST::BinaryExpression *binExp)
{
AST::IdentifierExpression *lhsIdent = AST::cast<AST::IdentifierExpression *>(binExp->left);
AST::ObjectLiteral *rhsObjLit = AST::cast<AST::ObjectLiteral *>(binExp->right);
AST::ObjectPattern *rhsObjLit = AST::cast<AST::ObjectPattern *>(binExp->right);
if (lhsIdent && rhsObjLit && (lhsIdent->name == QLatin1String("testcase"))
&& (binExp->op == QSOperator::Assign)) {
QModelIndex index = m_model->enterTestCase(rhsObjLit);
m_nodeToIndex.insert(rhsObjLit, index);
if (AST::PropertyAssignmentList *properties = rhsObjLit->properties)
if (AST::PatternPropertyList *properties = rhsObjLit->properties)
visitProperties(properties);
m_model->leaveTestCase();
@@ -290,13 +290,13 @@ private:
return true;
}
void visitProperties(AST::PropertyAssignmentList *properties)
void visitProperties(AST::PatternPropertyList *properties)
{
while (properties) {
QModelIndex index = m_model->enterTestCaseProperties(properties);
m_nodeToIndex.insert(properties, index);
if (AST::PropertyNameAndValue *assignment = AST::cast<AST::PropertyNameAndValue *>(properties->assignment))
if (AST::ObjectLiteral *objLiteral = AST::cast<AST::ObjectLiteral *>(assignment->value))
if (AST::PatternProperty *assignment = AST::cast<AST::PatternProperty *>(properties->property))
if (AST::ObjectPattern *objLiteral = AST::cast<AST::ObjectPattern *>(assignment->initializer))
visitProperties(objLiteral->properties);
m_model->leaveTestCaseProperties();
@@ -592,7 +592,7 @@ static QString functionDisplayName(QStringRef name, AST::FormalParameterList *fo
if (!name.isEmpty())
display += name.toString() + QLatin1Char('(');
for (AST::FormalParameterList *param = formals; param; param = param->next) {
display += param->name.toString();
display += param->element->bindingIdentifier.toString();
if (param->next)
display += QLatin1String(", ");
}
@@ -650,7 +650,7 @@ void QmlOutlineModel::leaveFieldMemberExpression()
leaveNode();
}
QModelIndex QmlOutlineModel::enterTestCase(AST::ObjectLiteral *objectLiteral)
QModelIndex QmlOutlineModel::enterTestCase(AST::ObjectPattern *objectLiteral)
{
QMap<int, QVariant> objectData;
@@ -667,18 +667,18 @@ void QmlOutlineModel::leaveTestCase()
leaveNode();
}
QModelIndex QmlOutlineModel::enterTestCaseProperties(AST::PropertyAssignmentList *propertyAssignmentList)
QModelIndex QmlOutlineModel::enterTestCaseProperties(AST::PatternPropertyList *propertyAssignmentList)
{
QMap<int, QVariant> objectData;
if (AST::PropertyNameAndValue *assignment = AST::cast<AST::PropertyNameAndValue *>(
propertyAssignmentList->assignment)) {
if (AST::PatternProperty *assignment = AST::cast<AST::PatternProperty *>(
propertyAssignmentList->property)) {
if (AST::IdentifierPropertyName *propertyName = AST::cast<AST::IdentifierPropertyName *>(assignment->name)) {
objectData.insert(Qt::DisplayRole, propertyName->id.toString());
objectData.insert(ItemTypeRole, ElementBindingType);
QmlOutlineItem *item;
if (assignment->value->kind == AST::Node::Kind_FunctionExpression)
if (assignment->initializer->kind == AST::Node::Kind_FunctionExpression)
item = enterNode(objectData, assignment, 0, Icons::functionDeclarationIcon());
else if (assignment->value->kind == AST::Node::Kind_ObjectLiteral)
else if (assignment->initializer->kind == AST::Node::Kind_ObjectPattern)
item = enterNode(objectData, assignment, 0, Icons::objectDefinitionIcon());
else
item = enterNode(objectData, assignment, 0, Icons::scriptBindingIcon());
@@ -686,8 +686,8 @@ QModelIndex QmlOutlineModel::enterTestCaseProperties(AST::PropertyAssignmentList
return item->index();
}
}
if (AST::PropertyGetterSetter *getterSetter = AST::cast<AST::PropertyGetterSetter *>(
propertyAssignmentList->assignment)) {
if (AST::PatternProperty *getterSetter = AST::cast<AST::PatternProperty *>(
propertyAssignmentList->property)) {
if (AST::IdentifierPropertyName *propertyName = AST::cast<AST::IdentifierPropertyName *>(getterSetter->name)) {
objectData.insert(Qt::DisplayRole, propertyName->id.toString());
objectData.insert(ItemTypeRole, ElementBindingType);
@@ -728,7 +728,7 @@ AST::SourceLocation QmlOutlineModel::sourceLocation(const QModelIndex &index) co
location = getLocation(member);
else if (AST::ExpressionNode *expression = node->expressionCast())
location = getLocation(expression);
else if (AST::PropertyAssignmentList *propertyAssignmentList = AST::cast<AST::PropertyAssignmentList *>(node))
else if (AST::PatternPropertyList *propertyAssignmentList = AST::cast<AST::PatternPropertyList *>(node))
location = getLocation(propertyAssignmentList);
}
return location;
@@ -999,26 +999,16 @@ AST::SourceLocation QmlOutlineModel::getLocation(AST::ExpressionNode *exprNode)
return location;
}
AST::SourceLocation QmlOutlineModel::getLocation(AST::PropertyAssignmentList *propertyNode) {
if (AST::PropertyNameAndValue *assignment = AST::cast<AST::PropertyNameAndValue *>(propertyNode->assignment))
AST::SourceLocation QmlOutlineModel::getLocation(AST::PatternPropertyList *propertyNode) {
if (AST::PatternProperty *assignment = AST::cast<AST::PatternProperty *>(propertyNode->property))
return getLocation(assignment);
if (AST::PropertyGetterSetter *getterSetter = AST::cast<AST::PropertyGetterSetter *>(propertyNode->assignment))
return getLocation(getterSetter);
return propertyNode->commaToken; // should never happen
return propertyNode->firstSourceLocation(); // should never happen
}
AST::SourceLocation QmlOutlineModel::getLocation(AST::PropertyNameAndValue *propertyNode) {
AST::SourceLocation QmlOutlineModel::getLocation(AST::PatternProperty *propertyNode) {
AST::SourceLocation location;
location = propertyNode->name->propertyNameToken;
location.length = propertyNode->value->lastSourceLocation().end() - location.offset;
return location;
}
AST::SourceLocation QmlOutlineModel::getLocation(AST::PropertyGetterSetter *propertyNode) {
AST::SourceLocation location;
location = propertyNode->name->propertyNameToken;
location.length = propertyNode->rbraceToken.end() - location.offset;
location.length = propertyNode->initializer->lastSourceLocation().end() - location.offset;
return location;
}

View File

@@ -120,10 +120,10 @@ private:
QmlJS::AST::FunctionExpression *functionExpression);
void leaveFieldMemberExpression();
QModelIndex enterTestCase(QmlJS::AST::ObjectLiteral *objectLiteral);
QModelIndex enterTestCase(QmlJS::AST::ObjectPattern *objectLiteral);
void leaveTestCase();
QModelIndex enterTestCaseProperties(QmlJS::AST::PropertyAssignmentList *propertyAssignmentList);
QModelIndex enterTestCaseProperties(QmlJS::AST::PatternPropertyList *propertyAssignmentList);
void leaveTestCaseProperties();
private:
@@ -140,9 +140,8 @@ private:
static QString asString(QmlJS::AST::UiQualifiedId *id);
static QmlJS::AST::SourceLocation getLocation(QmlJS::AST::UiObjectMember *objMember);
static QmlJS::AST::SourceLocation getLocation(QmlJS::AST::ExpressionNode *exprNode);
static QmlJS::AST::SourceLocation getLocation(QmlJS::AST::PropertyAssignmentList *propertyNode);
static QmlJS::AST::SourceLocation getLocation(QmlJS::AST::PropertyNameAndValue *propertyNode);
static QmlJS::AST::SourceLocation getLocation(QmlJS::AST::PropertyGetterSetter *propertyNode);
static QmlJS::AST::SourceLocation getLocation(QmlJS::AST::PatternProperty *propertyNode);
static QmlJS::AST::SourceLocation getLocation(QmlJS::AST::PatternPropertyList *propertyNode);
QIcon getIcon(QmlJS::AST::UiQualifiedId *objDef);
QString getAnnotation(QmlJS::AST::UiObjectInitializer *objInitializer);

View File

@@ -134,8 +134,8 @@ protected:
for (FormalParameterList *it = ast->formals; it; it = it->next) {
if (it != ast->formals)
entry.displayName += QLatin1String(", ");
if (!it->name.isEmpty())
entry.displayName += it->name.toString();
if (!it->element->bindingIdentifier.isEmpty())
entry.displayName += it->element->bindingIdentifier.toString();
}
entry.displayName += QLatin1Char(')');
entry.symbolName = entry.displayName;
@@ -214,8 +214,8 @@ protected:
for (FormalParameterList *it = funcExpr->formals; it; it = it->next) {
if (it != funcExpr->formals)
entry.displayName += QLatin1String(", ");
if (!it->name.isEmpty())
entry.displayName += it->name.toString();
if (!it->element->bindingIdentifier.isEmpty())
entry.displayName += it->element->bindingIdentifier.toString();
}
entry.displayName += QLatin1Char(')');
entry.symbolName = entry.displayName;