diff options
author | Alexandru Croitor <alexandru.croitor@qt.io> | 2019-10-14 18:46:38 +0200 |
---|---|---|
committer | Alexandru Croitor <alexandru.croitor@qt.io> | 2019-10-14 19:02:37 +0200 |
commit | c2f8b9535d34da6948ccf45b7d5fd90de2f1bc9e (patch) | |
tree | c6f7e058a985d7c18b51cadc76283caf555071c9 /src/qml/parser | |
parent | 9e633bbda7608ac0231809e2a6a97ae8f2d849d6 (diff) | |
parent | 803f18f02e5609a1ca00a5b78ea6d3613d44e1a0 (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.g | 204 | ||||
-rw-r--r-- | src/qml/parser/qqmljsast.cpp | 6 | ||||
-rw-r--r-- | src/qml/parser/qqmljsast_p.h | 75 | ||||
-rw-r--r-- | src/qml/parser/qqmljskeywords_p.h | 12 | ||||
-rw-r--r-- | src/qml/parser/qqmljslexer.cpp | 82 |
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, |