aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/parser
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2019-10-14 18:46:38 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2019-10-14 19:02:37 +0200
commitc2f8b9535d34da6948ccf45b7d5fd90de2f1bc9e (patch)
treec6f7e058a985d7c18b51cadc76283caf555071c9 /src/qml/parser
parent9e633bbda7608ac0231809e2a6a97ae8f2d849d6 (diff)
parent803f18f02e5609a1ca00a5b78ea6d3613d44e1a0 (diff)
Merge remote-tracking branch 'origin/dev' into wip/cmake
Removed dependencies.yaml because we don't use it yet in wip/cmake. Fixed conflict in qmlcachegen.cpp. Change-Id: Ie1060c737bee1daa85779903598e5b6d5020d922
Diffstat (limited to 'src/qml/parser')
-rw-r--r--src/qml/parser/qqmljs.g204
-rw-r--r--src/qml/parser/qqmljsast.cpp6
-rw-r--r--src/qml/parser/qqmljsast_p.h75
-rw-r--r--src/qml/parser/qqmljskeywords_p.h12
-rw-r--r--src/qml/parser/qqmljslexer.cpp82
5 files changed, 213 insertions, 166 deletions
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index 8ac7633ae0..e28899883f 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -49,6 +49,7 @@
%token T_DIVIDE_EQ "/=" T_DO "do" T_DOT "."
%token T_ELSE "else" T_EQ "=" T_EQ_EQ "=="
%token T_EQ_EQ_EQ "===" T_FINALLY "finally" T_FOR "for"
+%token T_FUNCTION_STAR "function *"
%token T_FUNCTION "function" T_GE ">=" T_GT ">"
%token T_GT_GT ">>" T_GT_GT_EQ ">>=" T_GT_GT_GT ">>>"
%token T_GT_GT_GT_EQ ">>>=" T_IDENTIFIER "identifier" T_IF "if"
@@ -88,6 +89,7 @@
%token T_STATIC "static"
%token T_EXPORT "export"
%token T_FROM "from"
+%token T_REQUIRED "required"
--- template strings
%token T_NO_SUBSTITUTION_TEMPLATE"(no subst template)"
@@ -120,8 +122,9 @@
%token T_FOR_LOOKAHEAD_OK "(for lookahead ok)"
--%left T_PLUS T_MINUS
-%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY T_ON T_SET T_GET T_OF T_STATIC T_FROM T_AS
+%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY T_ON T_SET T_GET T_OF T_STATIC T_FROM T_AS T_REQUIRED
%nonassoc REDUCE_HERE
+%right T_THEN T_ELSE
%start TopLevel
@@ -848,13 +851,7 @@ UiVersionSpecifier: T_VERSION_NUMBER;
UiImport: UiImportHead UiVersionSpecifier Semicolon;
/.
case $rule_number: {
- auto versionToken = loc(2);
- auto version = sym(2).UiVersionSpecifier;
- sym(1).UiImport->version = version;
- if (version->minorToken.isValid()) {
- versionToken.length += version->minorToken.length + (version->minorToken.offset - versionToken.offset - versionToken.length);
- }
- sym(1).UiImport->versionToken = versionToken;
+ sym(1).UiImport->version = sym(2).UiVersionSpecifier;
sym(1).UiImport->semicolonToken = loc(3);
} break;
./
@@ -862,7 +859,6 @@ UiImport: UiImportHead UiVersionSpecifier Semicolon;
UiImport: UiImportHead UiVersionSpecifier T_AS QmlIdentifier Semicolon;
/.
case $rule_number: {
- sym(1).UiImport->versionToken = loc(2);
sym(1).UiImport->version = sym(2).UiVersionSpecifier;
sym(1).UiImport->asToken = loc(3);
sym(1).UiImport->importIdToken = loc(4);
@@ -1175,7 +1171,7 @@ UiObjectMember: T_SIGNAL T_IDENTIFIER Semicolon;
} break;
./
-UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier Semicolon;
+UiObjectMemberListPropertyNoInitialiser: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier Semicolon;
/.
case $rule_number: {
AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6));
@@ -1189,23 +1185,19 @@ UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier S
} break;
./
-UiObjectMember: T_READONLY T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier Semicolon;
+UiObjectMember: UiObjectMemberListPropertyNoInitialiser;
+
+UiObjectMember: T_READONLY UiObjectMemberListPropertyNoInitialiser;
/.
case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7));
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isReadonlyMember = true;
node->readonlyToken = loc(1);
- node->typeModifier = stringRef(3);
- node->propertyToken = loc(2);
- node->typeModifierToken = loc(3);
- node->typeToken = loc(5);
- node->identifierToken = loc(7);
- node->semicolonToken = loc(8);
sym(1).Node = node;
} break;
./
-UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier Semicolon;
+UiObjectMemberPropertyNoInitialiser: T_PROPERTY UiPropertyType QmlIdentifier Semicolon;
/.
case $rule_number: {
AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3));
@@ -1217,42 +1209,47 @@ UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier Semicolon;
} break;
./
-UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType QmlIdentifier Semicolon;
+
+UiObjectMember: UiObjectMemberPropertyNoInitialiser;
+
+UiObjectMember: T_DEFAULT UiObjectMemberPropertyNoInitialiser;
/.
case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4));
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isDefaultMember = true;
node->defaultToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->semicolonToken = loc(5);
sym(1).Node = node;
} break;
./
-UiObjectMember: T_DEFAULT T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier Semicolon;
+UiObjectMember: T_DEFAULT UiObjectMemberListPropertyNoInitialiser;
/.
case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7));
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isDefaultMember = true;
node->defaultToken = loc(1);
- node->typeModifier = stringRef(3);
- node->propertyToken = loc(2);
- node->typeModifierToken = loc(2);
- node->typeToken = loc(4);
- node->identifierToken = loc(7);
- node->semicolonToken = loc(8);
sym(1).Node = node;
} break;
./
+
OptionalSemicolon: | Semicolon;
/.
/* we need OptionalSemicolon because UiScriptStatement might already parse the last semicolon
and then we would miss a semicolon (see tests/auto/quick/qquickvisualdatamodel/data/objectlist.qml)*/
./
-UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement OptionalSemicolon;
+UiObjectMember: T_REQUIRED UiObjectMemberPropertyNoInitialiser;
+/.
+ case $rule_number: {
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
+ node->requiredToken = loc(1);
+ node->isRequired = true;
+ sym(1).Node = node;
+ } break;
+./
+
+
+UiObjectMemberWithScriptStatement: T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement OptionalSemicolon;
/.
case $rule_number: {
AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3), sym(5).Statement);
@@ -1264,35 +1261,29 @@ UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatemen
} break;
./
-UiObjectMember: T_READONLY T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement OptionalSemicolon;
+UiObjectMember: UiObjectMemberWithScriptStatement;
+
+UiObjectMember: T_READONLY UiObjectMemberWithScriptStatement;
/.
case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4), sym(6).Statement);
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isReadonlyMember = true;
node->readonlyToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->colonToken = loc(5);
sym(1).Node = node;
} break;
./
-UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement OptionalSemicolon;
+UiObjectMember: T_DEFAULT UiObjectMemberWithScriptStatement;
/.
case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4), sym(6).Statement);
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isDefaultMember = true;
node->defaultToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->colonToken = loc(5);
sym(1).Node = node;
} break;
./
-UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET Semicolon;
+UiObjectMemberWithArray: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET Semicolon;
/.
case $rule_number: {
AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6));
@@ -1318,35 +1309,19 @@ UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T
} break;
./
-UiObjectMember: T_READONLY T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET Semicolon;
+UiObjectMember: UiObjectMemberWithArray;
+
+UiObjectMember: T_READONLY UiObjectMemberWithArray;
/.
case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7));
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isReadonlyMember = true;
node->readonlyToken = loc(1);
- node->typeModifier = stringRef(3);
- node->propertyToken = loc(2);
- node->typeModifierToken = loc(3);
- node->typeToken = loc(5);
- node->identifierToken = loc(7);
- node->semicolonToken = loc(8); // insert a fake ';' before ':'
-
- AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(7));
- propertyName->identifierToken = loc(7);
- propertyName->next = 0;
-
- AST::UiArrayBinding *binding = new (pool) AST::UiArrayBinding(propertyName, sym(10).UiArrayMemberList->finish());
- binding->colonToken = loc(8);
- binding->lbracketToken = loc(9);
- binding->rbracketToken = loc(11);
-
- node->binding = binding;
-
sym(1).Node = node;
} break;
./
-UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_COLON ExpressionStatementLookahead UiQualifiedId UiObjectInitializer Semicolon;
+UiObjectMemberExpressionStatementLookahead: T_PROPERTY UiPropertyType QmlIdentifier T_COLON ExpressionStatementLookahead UiQualifiedId UiObjectInitializer Semicolon;
/.
case $rule_number: {
AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3));
@@ -1369,43 +1344,30 @@ UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_COLON ExpressionStatem
} break;
./
-UiObjectMember: T_READONLY T_PROPERTY UiPropertyType QmlIdentifier T_COLON ExpressionStatementLookahead UiQualifiedId UiObjectInitializer Semicolon;
+UiObjectMember: UiObjectMemberExpressionStatementLookahead;
+
+UiObjectMember: T_READONLY UiObjectMemberExpressionStatementLookahead;
/.
case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4));
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isReadonlyMember = true;
node->readonlyToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->semicolonToken = loc(5); // insert a fake ';' before ':'
-
- AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(4));
- propertyName->identifierToken = loc(4);
- propertyName->next = 0;
-
- AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding(
- propertyName, sym(7).UiQualifiedId, sym(8).UiObjectInitializer);
- binding->colonToken = loc(5);
-
- node->binding = binding;
-
sym(1).Node = node;
} break;
./
-UiObjectMember: FunctionDeclarationWithTypes;
+UiObjectMember: GeneratorDeclaration;
/.
case $rule_number: {
- sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
+ auto node = new (pool) AST::UiSourceElement(sym(1).Node);
+ sym(1).Node = node;
} break;
./
-UiObjectMember: GeneratorExpression;
+UiObjectMember: FunctionDeclarationWithTypes;
/.
case $rule_number: {
- auto node = new (pool) AST::UiSourceElement(sym(1).Node);
- sym(1).Node = node;
+ sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
} break;
./
@@ -1501,6 +1463,7 @@ QmlIdentifier: T_GET;
QmlIdentifier: T_SET;
QmlIdentifier: T_FROM;
QmlIdentifier: T_OF;
+QmlIdentifier: T_REQUIRED;
JsIdentifier: T_IDENTIFIER;
JsIdentifier: T_PROPERTY;
@@ -1513,6 +1476,7 @@ JsIdentifier: T_FROM;
JsIdentifier: T_STATIC;
JsIdentifier: T_OF;
JsIdentifier: T_AS;
+JsIdentifier: T_REQUIRED;
IdentifierReference: JsIdentifier;
BindingIdentifier: IdentifierReference;
@@ -3232,7 +3196,7 @@ ExpressionStatementLookahead: ;
int token = lookaheadToken(lexer);
if (token == T_LBRACE)
pushToken(T_FORCE_BLOCK);
- else if (token == T_FUNCTION || token == T_CLASS || token == T_LET || token == T_CONST)
+ else if (token == T_FUNCTION || token == T_FUNCTION_STAR || token == T_CLASS || token == T_LET || token == T_CONST)
pushToken(T_FORCE_DECLARATION);
} break;
./
@@ -3980,27 +3944,14 @@ GeneratorRBrace: T_RBRACE;
} break;
./
-GeneratorDeclaration: Function T_STAR BindingIdentifier GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
-/.
- case $rule_number: {
- AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(3), sym(5).FormalParameterList, sym(8).StatementList);
- node->functionToken = loc(1);
- node->identifierToken = loc(3);
- node->lparenToken = loc(4);
- node->rparenToken = loc(6);
- node->lbraceToken = loc(7);
- node->rbraceToken = loc(9);
- node->isGenerator = true;
- sym(1).Node = node;
- } break;
-./
+FunctionStar: T_FUNCTION_STAR %prec REDUCE_HERE;
-GeneratorDeclaration_Default: GeneratorDeclaration;
-GeneratorDeclaration_Default: Function T_STAR GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
+GeneratorDeclaration: FunctionStar BindingIdentifier GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
/.
case $rule_number: {
- AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(QStringRef(), sym(4).FormalParameterList, sym(7).StatementList);
+ AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
node->functionToken = loc(1);
+ node->identifierToken = loc(2);
node->lparenToken = loc(3);
node->rparenToken = loc(5);
node->lbraceToken = loc(6);
@@ -4010,27 +3961,28 @@ GeneratorDeclaration_Default: Function T_STAR GeneratorLParen FormalParameters T
} break;
./
-GeneratorExpression: T_FUNCTION T_STAR BindingIdentifier GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
+GeneratorDeclaration_Default: GeneratorDeclaration;
+GeneratorDeclaration_Default: FunctionStar GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
/.
case $rule_number: {
- AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(3), sym(5).FormalParameterList, sym(8).StatementList);
+ AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(QStringRef(), sym(3).FormalParameterList, sym(6).StatementList);
node->functionToken = loc(1);
- if (!stringRef(3).isNull())
- node->identifierToken = loc(3);
- node->lparenToken = loc(4);
- node->rparenToken = loc(6);
- node->lbraceToken = loc(7);
- node->rbraceToken = loc(9);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->lbraceToken = loc(5);
+ node->rbraceToken = loc(7);
node->isGenerator = true;
sym(1).Node = node;
} break;
./
-GeneratorExpression: T_FUNCTION T_STAR GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
+GeneratorExpression: T_FUNCTION_STAR BindingIdentifier GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
/.
case $rule_number: {
- AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(4).FormalParameterList, sym(7).StatementList);
+ AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
node->functionToken = loc(1);
+ if (!stringRef(2).isNull())
+ node->identifierToken = loc(2);
node->lparenToken = loc(3);
node->rparenToken = loc(5);
node->lbraceToken = loc(6);
@@ -4040,6 +3992,20 @@ GeneratorExpression: T_FUNCTION T_STAR GeneratorLParen FormalParameters T_RPAREN
} break;
./
+GeneratorExpression: T_FUNCTION_STAR GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
+/.
+ case $rule_number: {
+ AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(3).FormalParameterList, sym(6).StatementList);
+ node->functionToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->lbraceToken = loc(5);
+ node->rbraceToken = loc(7);
+ node->isGenerator = true;
+ sym(1).Node = node;
+ } break;
+./
+
GeneratorBody: FunctionBody;
YieldExpression: T_YIELD;
@@ -4419,7 +4385,7 @@ ExportDeclarationLookahead: ;
/.
case $rule_number: {
int token = lookaheadToken(lexer);
- if (token == T_FUNCTION || token == T_CLASS)
+ if (token == T_FUNCTION || token == T_FUNCTION_STAR || token == T_CLASS)
pushToken(T_FORCE_DECLARATION);
} break;
./
diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp
index b63b2191b9..03355b3e38 100644
--- a/src/qml/parser/qqmljsast.cpp
+++ b/src/qml/parser/qqmljsast.cpp
@@ -105,6 +105,12 @@ ClassExpression *Node::asClassDefinition()
return nullptr;
}
+bool Node::ignoreRecursionDepth() const
+{
+ static const bool doIgnore = qEnvironmentVariableIsSet("QV4_CRASH_ON_STACKOVERFLOW");
+ return doIgnore;
+}
+
ExpressionNode *ExpressionNode::expressionCast()
{
return this;
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index 39194068bf..e436c4673d 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -275,10 +275,16 @@ public:
virtual FunctionExpression *asFunctionDefinition();
virtual ClassExpression *asClassDefinition();
+ bool ignoreRecursionDepth() const;
+
inline void accept(Visitor *visitor)
{
Visitor::RecursionDepthCheck recursionCheck(visitor);
- if (recursionCheck()) {
+
+ // Stack overflow is uncommon, ignoreRecursionDepth() only returns true if
+ // QV4_CRASH_ON_STACKOVERFLOW is set, and ignoreRecursionDepth() needs to be out of line.
+ // Therefore, check for ignoreRecursionDepth() _after_ calling the inline recursionCheck().
+ if (recursionCheck() || ignoreRecursionDepth()) {
if (visitor->preVisit(this))
accept0(visitor);
visitor->postVisit(this);
@@ -307,6 +313,14 @@ public:
int kind = Kind_Undefined;
};
+template<typename T>
+T lastListElement(T head)
+{
+ auto current = head;
+ while (current->next)
+ current = current->next;
+ return current;
+}
class QML_PARSER_EXPORT UiQualifiedId: public Node
{
@@ -338,7 +352,7 @@ public:
{ return identifierToken; }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : identifierToken; }
+ { return lastListElement(this)->identifierToken; }
// attributes
UiQualifiedId *next;
@@ -397,7 +411,7 @@ public:
{ return typeId->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : typeId->lastSourceLocation(); }
+ { return lastListElement(this)->typeId->lastSourceLocation(); }
inline TypeArgumentList *finish()
{
@@ -678,7 +692,10 @@ public:
{ return literalToken; }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : (expression ? expression->lastSourceLocation() : literalToken); }
+ {
+ auto last = lastListElement(this);
+ return (last->expression ? last->expression->lastSourceLocation() : last->literalToken);
+ }
void accept0(Visitor *visitor) override;
@@ -800,7 +817,7 @@ public:
{ return commaToken; }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : commaToken; }
+ { return lastListElement(this)->commaToken; }
inline Elision *finish ()
{
@@ -961,7 +978,10 @@ public:
{ return elision ? elision->firstSourceLocation() : element->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : (element ? element->lastSourceLocation() : elision->lastSourceLocation()); }
+ {
+ auto last = lastListElement(this);
+ return last->element ? last->element->lastSourceLocation() : last->elision->lastSourceLocation();
+ }
Elision *elision = nullptr;
PatternElement *element = nullptr;
@@ -1036,7 +1056,7 @@ public:
{ return property->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : property->lastSourceLocation(); }
+ { return lastListElement(this)->property->lastSourceLocation(); }
PatternProperty *property;
PatternPropertyList *next;
@@ -1645,7 +1665,9 @@ public:
{ return statement->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : statement->lastSourceLocation(); }
+ {
+ return lastListElement(this)->statement->lastSourceLocation();
+ }
inline StatementList *finish ()
{
@@ -2138,7 +2160,9 @@ public:
{ return clause->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : clause->lastSourceLocation(); }
+ {
+ return lastListElement(this)->clause->lastSourceLocation();
+ }
inline CaseClauses *finish ()
{
@@ -2429,7 +2453,9 @@ public:
{ return element->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : element->lastSourceLocation(); }
+ {
+ return lastListElement(this)->element->lastSourceLocation();
+ }
FormalParameterList *finish(MemoryPool *pool);
@@ -2606,7 +2632,9 @@ public:
{ return importSpecifierToken; }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : importSpecifierToken; }
+ {
+ return lastListElement(this)->importSpecifierToken;
+ }
// attributes
SourceLocation importSpecifierToken;
@@ -2843,7 +2871,7 @@ public:
SourceLocation firstSourceLocation() const override
{ return exportSpecifier->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : exportSpecifier->lastSourceLocation(); }
+ { return lastListElement(this)->exportSpecifier->lastSourceLocation(); }
// attributes
ExportSpecifier *exportSpecifier;
@@ -2997,7 +3025,6 @@ public:
QStringRef importId;
SourceLocation importToken;
SourceLocation fileNameToken;
- SourceLocation versionToken;
SourceLocation asToken;
SourceLocation importIdToken;
SourceLocation semicolonToken;
@@ -3036,7 +3063,7 @@ public:
{ return member->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : member->lastSourceLocation(); }
+ { return lastListElement(this)->member->lastSourceLocation(); }
UiObjectMemberList *finish()
{
@@ -3115,7 +3142,7 @@ public:
{ return headerItem->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : headerItem->lastSourceLocation(); }
+ { return lastListElement(this)->headerItem->lastSourceLocation(); }
// attributes
Node *headerItem;
@@ -3179,7 +3206,7 @@ public:
{ return member->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : member->lastSourceLocation(); }
+ { return lastListElement(this)->member->lastSourceLocation(); }
UiArrayMemberList *finish()
{
@@ -3240,7 +3267,10 @@ public:
{ return colonToken.isValid() ? identifierToken : propertyTypeToken; }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : (colonToken.isValid() ? propertyTypeToken : identifierToken); }
+ {
+ auto last = lastListElement(this);
+ return (last->colonToken.isValid() ? last->propertyTypeToken : last->identifierToken);
+ }
inline UiParameterList *finish ()
{
@@ -3283,6 +3313,8 @@ public:
return defaultToken;
else if (readonlyToken.isValid())
return readonlyToken;
+ else if (requiredToken.isValid())
+ return requiredToken;
return propertyToken;
}
@@ -3306,10 +3338,13 @@ public:
UiObjectMember *binding; // initialized with a QML object or array.
bool isDefaultMember;
bool isReadonlyMember;
+ bool isRequired = false;
UiParameterList *parameters;
+ // TODO: merge source locations
SourceLocation defaultToken;
SourceLocation readonlyToken;
SourceLocation propertyToken;
+ SourceLocation requiredToken;
SourceLocation typeModifierToken;
SourceLocation typeToken;
SourceLocation identifierToken;
@@ -3493,8 +3528,10 @@ public:
{ return memberToken; }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() :
- valueToken.isValid() ? valueToken : memberToken; }
+ {
+ auto last = lastListElement(this);
+ return last->valueToken.isValid() ? last->valueToken : last->memberToken;
+ }
void accept0(Visitor *visitor) override;
diff --git a/src/qml/parser/qqmljskeywords_p.h b/src/qml/parser/qqmljskeywords_p.h
index 96b3709162..3eb054341f 100644
--- a/src/qml/parser/qqmljskeywords_p.h
+++ b/src/qml/parser/qqmljskeywords_p.h
@@ -743,6 +743,18 @@ static inline int classify8(const QChar *s, int parseModeFlags) {
}
}
}
+ } else if (s[2].unicode() == 'q') {
+ if (s[3].unicode() == 'u') {
+ if (s[4].unicode() == 'i') {
+ if (s[5].unicode() == 'r') {
+ if (s[6].unicode() == 'e') {
+ if (s[7].unicode() == 'd') {
+ return Lexer::T_REQUIRED;
+ }
+ }
+ }
+ }
+ }
}
}
}
diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp
index 1e0ac72bd1..443e1a7476 100644
--- a/src/qml/parser/qqmljslexer.cpp
+++ b/src/qml/parser/qqmljslexer.cpp
@@ -492,6 +492,42 @@ int Lexer::scanToken()
again:
_validTokenText = false;
+ // handle comment can be called after a '/' has been read
+ // and returns true if it actually encountered a comment
+ auto handleComment = [this](){
+ if (_char == QLatin1Char('*')) {
+ scanChar();
+ while (_codePtr <= _endPtr) {
+ if (_char == QLatin1Char('*')) {
+ scanChar();
+ if (_char == QLatin1Char('/')) {
+ scanChar();
+
+ if (_engine) {
+ _engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 4,
+ tokenStartLine(), tokenStartColumn() + 2);
+ }
+
+ return true;
+ }
+ } else {
+ scanChar();
+ }
+ }
+ } else if (_char == QLatin1Char('/')) {
+ while (_codePtr <= _endPtr && !isLineTerminator()) {
+ scanChar();
+ }
+ if (_engine) {
+ _engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 2,
+ tokenStartLine(), tokenStartColumn() + 2);
+ }
+ return true;
+ }
+ return false;
+ };
+
+
while (_char.isSpace()) {
if (isLineTerminator()) {
if (_restrictedKeyword) {
@@ -599,35 +635,9 @@ again:
case ':': return T_COLON;
case '/':
- if (_char == QLatin1Char('*')) {
- scanChar();
- while (_codePtr <= _endPtr) {
- if (_char == QLatin1Char('*')) {
- scanChar();
- if (_char == QLatin1Char('/')) {
- scanChar();
-
- if (_engine) {
- _engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 4,
- tokenStartLine(), tokenStartColumn() + 2);
- }
-
- goto again;
- }
- } else {
- scanChar();
- }
- }
- } else if (_char == QLatin1Char('/')) {
- while (_codePtr <= _endPtr && !isLineTerminator()) {
- scanChar();
- }
- if (_engine) {
- _engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 2,
- tokenStartLine(), tokenStartColumn() + 2);
- }
+ if (handleComment())
goto again;
- } if (_char == QLatin1Char('=')) {
+ else if (_char == QLatin1Char('=')) {
scanChar();
return T_DIVIDE_EQ;
}
@@ -829,6 +839,21 @@ again:
if (!identifierWithEscapeChars)
kind = classify(_tokenStartPtr, _tokenLength, parseModeFlags());
+ if (kind == T_FUNCTION) {
+ continue_skipping:
+ while (_codePtr < _endPtr && _char.isSpace())
+ scanChar();
+ if (_char == QLatin1Char('*')) {
+ _tokenLength = _codePtr - _tokenStartPtr - 1;
+ kind = T_FUNCTION_STAR;
+ scanChar();
+ } else if (_char == QLatin1Char('/')) {
+ scanChar();
+ if (handleComment())
+ goto continue_skipping;
+ }
+ }
+
if (_engine) {
if (kind == T_IDENTIFIER && identifierWithEscapeChars)
_tokenSpell = _engine->newStringRef(_tokenText);
@@ -1407,6 +1432,7 @@ static const int uriTokens[] = {
QQmlJSGrammar::T_FINALLY,
QQmlJSGrammar::T_FOR,
QQmlJSGrammar::T_FUNCTION,
+ QQmlJSGrammar::T_FUNCTION_STAR,
QQmlJSGrammar::T_IF,
QQmlJSGrammar::T_IN,
QQmlJSGrammar::T_OF,