aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/parser
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2019-01-08 16:27:56 +0100
committerSimon Hausmann <simon.hausmann@qt.io>2019-07-09 16:52:01 +0200
commita06736cab722c2a4283cdcbda8d003d8e91d7f54 (patch)
treef083fe5bca85a06254e63729802d6c081c88cf87 /src/qml/parser
parentd9f115327cd36cef370172bc87706cca6e57f912 (diff)
Add basic type annotation support for QML functions to the grammar
Inspired by TypeScript syntax, allow optional type annotations in the style of ": <name of type>" in for the parameters of functions and their return type. These annotations are not used at the moment, so by default we produce an error message when encountering them in the AST. In addition their usage is limited to functions declared in the QML scope. All other uses attempt to produce readable syntax errors. So for example this is okay: Item { function blah(param: string) string { ... } } And this is not okay: // some file.js function blah(param: string) : string { ... } Change-Id: I12d20b4e2ce92e01108132975a06cfd13ba4a254 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/parser')
-rw-r--r--src/qml/parser/qqmljs.g213
-rw-r--r--src/qml/parser/qqmljsast.cpp35
-rw-r--r--src/qml/parser/qqmljsast_p.h181
-rw-r--r--src/qml/parser/qqmljsastfwd_p.h3
-rw-r--r--src/qml/parser/qqmljsastvisitor_p.h9
5 files changed, 345 insertions, 96 deletions
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index daaa402ef1..28566e21ea 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -299,6 +299,9 @@ public:
AST::ExportsList *ExportsList;
AST::ExportClause *ExportClause;
AST::ExportDeclaration *ExportDeclaration;
+ AST::TypeAnnotation *TypeAnnotation;
+ AST::TypeArgumentList *TypeArgumentList;
+ AST::Type *Type;
AST::UiProgram *UiProgram;
AST::UiHeaderItemList *UiHeaderItemList;
@@ -424,6 +427,8 @@ protected:
diagnostic_messages.append(compileError(location, message));
}
+ bool ensureNoFunctionTypeAnnotations(AST::TypeAnnotation *returnTypeAnnotation, AST::FormalParameterList *formals);
+
protected:
Engine *driver;
MemoryPool *pool;
@@ -594,6 +599,21 @@ int Parser::lookaheadToken(Lexer *lexer)
return yytoken;
}
+bool Parser::ensureNoFunctionTypeAnnotations(AST::TypeAnnotation *returnValueAnnotation, AST::FormalParameterList *formals)
+{
+ for (auto formal = formals; formal; formal = formal->next) {
+ if (formal->element && formal->element->typeAnnotation) {
+ syntaxError(formal->element->typeAnnotation->firstSourceLocation(), "Type annotations are not permitted in function parameters in JavaScript functions");
+ return false;
+ }
+ }
+ if (returnValueAnnotation) {
+ syntaxError(returnValueAnnotation->firstSourceLocation(), "Type annotations are not permitted for the return value of JavaScript functions");
+ return false;
+ }
+ return true;
+}
+
//#define PARSER_DEBUG
bool Parser::parse(int startToken)
@@ -1355,7 +1375,7 @@ UiObjectMember: T_READONLY T_PROPERTY UiPropertyType QmlIdentifier T_COLON Expre
} break;
./
-UiObjectMember: FunctionDeclaration;
+UiObjectMember: FunctionDeclarationWithTypes;
/.
case $rule_number: {
sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
@@ -1471,6 +1491,54 @@ IdentifierReference: JsIdentifier;
BindingIdentifier: IdentifierReference;
--------------------------------------------------------------------------------------------------------
+-- Types
+--------------------------------------------------------------------------------------------------------
+
+TypeArguments: Type;
+/.
+ case $rule_number: {
+ sym(1).TypeArgumentList = new (pool) AST::TypeArgumentList(sym(1).Type);
+ } break;
+./
+
+TypeArguments: TypeArguments T_COMMA Type;
+/.
+ case $rule_number: {
+ sym(1).TypeArgumentList = new (pool) AST::TypeArgumentList(sym(1).TypeArgumentList, sym(3).Type);
+ } break;
+./
+
+Type: UiQualifiedId T_LT TypeArguments T_GT;
+/.
+ case $rule_number: {
+ sym(1).Type = new (pool) AST::Type(sym(1).UiQualifiedId, sym(3).TypeArgumentList->finish());
+ } break;
+./
+
+Type: UiQualifiedId;
+/.
+ case $rule_number: {
+ sym(1).Type = new (pool) AST::Type(sym(1).UiQualifiedId);
+ } break;
+./
+
+TypeAnnotation: T_COLON Type;
+/.
+ case $rule_number: {
+ sym(1).TypeAnnotation = new (pool) AST::TypeAnnotation(sym(2).Type);
+ sym(1).TypeAnnotation->colonToken = loc(1);
+ } break;
+./
+
+TypeAnnotationOpt: TypeAnnotation;
+TypeAnnotationOpt: ;
+/.
+ case $rule_number: {
+ sym(1).TypeAnnotation = nullptr;
+ } break;
+./
+
+--------------------------------------------------------------------------------------------------------
-- Expressions
--------------------------------------------------------------------------------------------------------
@@ -2851,7 +2919,14 @@ VarDeclaration: Var VariableDeclarationList;
VarDeclaration_In: Var VariableDeclarationList_In;
/.
case $rule_number: {
- AST::VariableStatement *node = new (pool) AST::VariableStatement(sym(2).VariableDeclarationList->finish(sym(1).scope));
+ AST::VariableDeclarationList *declarations = sym(2).VariableDeclarationList->finish(sym(1).scope);
+ for (auto it = declarations; it; it = it->next) {
+ if (it->declaration && it->declaration->typeAnnotation) {
+ syntaxError(it->declaration->typeAnnotation->firstSourceLocation(), "Type annotations are not permitted in variable declarations");
+ return false;
+ }
+ }
+ AST::VariableStatement *node = new (pool) AST::VariableStatement(declarations);
node->declarationKindToken = loc(1);
sym(1).Node = node;
} break;
@@ -2888,22 +2963,22 @@ VariableDeclarationList_In: VariableDeclarationList_In T_COMMA VariableDeclarati
} break;
./
-LexicalBinding: BindingIdentifier InitializerOpt;
+LexicalBinding: BindingIdentifier TypeAnnotationOpt InitializerOpt;
/. case $rule_number: Q_FALLTHROUGH(); ./
-LexicalBinding_In: BindingIdentifier InitializerOpt_In;
+LexicalBinding_In: BindingIdentifier TypeAnnotationOpt InitializerOpt_In;
/. case $rule_number: Q_FALLTHROUGH(); ./
-VariableDeclaration: BindingIdentifier InitializerOpt;
+VariableDeclaration: BindingIdentifier TypeAnnotationOpt InitializerOpt;
/. case $rule_number: Q_FALLTHROUGH(); ./
-VariableDeclaration_In: BindingIdentifier InitializerOpt_In;
+VariableDeclaration_In: BindingIdentifier TypeAnnotationOpt InitializerOpt_In;
/.
case $rule_number: {
- auto *node = new (pool) AST::PatternElement(stringRef(1), sym(2).Expression);
+ auto *node = new (pool) AST::PatternElement(stringRef(1), sym(2).TypeAnnotation, sym(3).Expression);
node->identifierToken = loc(1);
sym(1).Node = node;
// if initializer is an anonymous function expression, we need to assign identifierref as it's name
- if (auto *f = asAnonymousFunctionDefinition(sym(2).Expression))
+ if (auto *f = asAnonymousFunctionDefinition(sym(3).Expression))
f->name = stringRef(1);
- if (auto *c = asAnonymousClassDefinition(sym(2).Expression))
+ if (auto *c = asAnonymousClassDefinition(sym(3).Expression))
c->name = stringRef(1);
} break;
./
@@ -3053,15 +3128,15 @@ BindingProperty: PropertyName T_COLON BindingPattern InitializerOpt_In;
} break;
./
-BindingElement: BindingIdentifier InitializerOpt_In;
+BindingElement: BindingIdentifier TypeAnnotationOpt InitializerOpt_In;
/.
case $rule_number: {
- AST::PatternElement *node = new (pool) AST::PatternElement(stringRef(1), sym(2).Expression);
+ AST::PatternElement *node = new (pool) AST::PatternElement(stringRef(1), sym(2).TypeAnnotation, sym(3).Expression);
node->identifierToken = loc(1);
// if initializer is an anonymous function expression, we need to assign identifierref as it's name
- if (auto *f = asAnonymousFunctionDefinition(sym(2).Expression))
+ if (auto *f = asAnonymousFunctionDefinition(sym(3).Expression))
f->name = stringRef(1);
- if (auto *c = asAnonymousClassDefinition(sym(2).Expression))
+ if (auto *c = asAnonymousClassDefinition(sym(3).Expression))
c->name = stringRef(1);
sym(1).Node = node;
} break;
@@ -3078,7 +3153,7 @@ BindingElement: BindingPattern InitializerOpt_In;
BindingRestElement: T_ELLIPSIS BindingIdentifier;
/.
case $rule_number: {
- AST::PatternElement *node = new (pool) AST::PatternElement(stringRef(2), nullptr, AST::PatternElement::RestElement);
+ AST::PatternElement *node = new (pool) AST::PatternElement(stringRef(2), /*type annotation*/nullptr, nullptr, AST::PatternElement::RestElement);
node->identifierToken = loc(2);
sym(1).Node = node;
} break;
@@ -3268,12 +3343,16 @@ IterationStatement: T_FOR T_LPAREN ForDeclaration InOrOf Expression_In T_RPAREN
} break;
./
-ForDeclaration: LetOrConst BindingIdentifier;
+ForDeclaration: LetOrConst BindingIdentifier TypeAnnotationOpt;
/. case $rule_number: Q_FALLTHROUGH(); ./
-ForDeclaration: Var BindingIdentifier;
+ForDeclaration: Var BindingIdentifier TypeAnnotationOpt;
/.
case $rule_number: {
- auto *node = new (pool) AST::PatternElement(stringRef(2), nullptr);
+ if (auto typeAnnotation = sym(3).TypeAnnotation) {
+ syntaxError(typeAnnotation->firstSourceLocation(), "Type annotations are not permitted in variable declarations");
+ return false;
+ }
+ auto *node = new (pool) AST::PatternElement(stringRef(2), sym(3).TypeAnnotation, nullptr);
node->identifierToken = loc(2);
node->scope = sym(1).scope;
node->isForDeclaration = true;
@@ -3560,59 +3639,85 @@ DebuggerStatement: T_DEBUGGER T_SEMICOLON;
-- otherwise conflict.
Function: T_FUNCTION %prec REDUCE_HERE;
-FunctionDeclaration: Function BindingIdentifier T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
+FunctionDeclaration: Function BindingIdentifier T_LPAREN FormalParameters T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
- AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
+ if (!ensureNoFunctionTypeAnnotations(sym(6).TypeAnnotation, sym(4).FormalParameterList))
+ return false;
+ AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(8).StatementList,
+ /*type annotation*/nullptr);
node->functionToken = loc(1);
node->identifierToken = loc(2);
node->lparenToken = loc(3);
node->rparenToken = loc(5);
- node->lbraceToken = loc(6);
- node->rbraceToken = loc(8);
+ node->lbraceToken = loc(7);
+ node->rbraceToken = loc(9);
sym(1).Node = node;
} break;
./
+FunctionDeclarationWithTypes: Function BindingIdentifier T_LPAREN FormalParameters T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
+/.
+ case $rule_number: {
+ AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(8).StatementList,
+ sym(6).TypeAnnotation);
+ node->functionToken = loc(1);
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(7);
+ node->rbraceToken = loc(9);
+ sym(1).Node = node;
+ } break;
+./
FunctionDeclaration_Default: FunctionDeclaration;
-FunctionDeclaration_Default: Function T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
+FunctionDeclaration_Default: Function T_LPAREN FormalParameters T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
- AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(QStringRef(), sym(3).FormalParameterList, sym(6).StatementList);
+ if (!ensureNoFunctionTypeAnnotations(sym(5).TypeAnnotation, sym(3).FormalParameterList))
+ return false;
+ AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(QStringRef(), sym(3).FormalParameterList, sym(7).StatementList,
+ /*type annotation*/nullptr);
node->functionToken = loc(1);
node->lparenToken = loc(2);
node->rparenToken = loc(4);
- node->lbraceToken = loc(5);
- node->rbraceToken = loc(7);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
sym(1).Node = node;
} break;
./
-FunctionExpression: T_FUNCTION BindingIdentifier T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
+FunctionExpression: T_FUNCTION BindingIdentifier T_LPAREN FormalParameters T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
- AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
+ if (!ensureNoFunctionTypeAnnotations(sym(6).TypeAnnotation, sym(4).FormalParameterList))
+ return false;
+ AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(8).StatementList,
+ /*type annotation*/nullptr);
node->functionToken = loc(1);
if (! stringRef(2).isNull())
node->identifierToken = loc(2);
node->lparenToken = loc(3);
node->rparenToken = loc(5);
- node->lbraceToken = loc(6);
- node->rbraceToken = loc(8);
+ node->lbraceToken = loc(7);
+ node->rbraceToken = loc(9);
sym(1).Node = node;
} break;
./
-FunctionExpression: T_FUNCTION T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
+FunctionExpression: T_FUNCTION T_LPAREN FormalParameters T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
- AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(3).FormalParameterList, sym(6).StatementList);
+ if (!ensureNoFunctionTypeAnnotations(sym(5).TypeAnnotation, sym(3).FormalParameterList))
+ return false;
+ AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(3).FormalParameterList, sym(7).StatementList,
+ /*type annotation*/nullptr);
node->functionToken = loc(1);
node->lparenToken = loc(2);
node->rparenToken = loc(4);
- node->lbraceToken = loc(5);
- node->rbraceToken = loc(7);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
sym(1).Node = node;
} break;
./
@@ -3722,7 +3827,7 @@ ArrowFunction_In: ArrowParameters T_ARROW ConciseBodyLookahead T_FORCE_BLOCK Fun
ArrowParameters: BindingIdentifier;
/.
case $rule_number: {
- AST::PatternElement *e = new (pool) AST::PatternElement(stringRef(1), nullptr, AST::PatternElement::Binding);
+ AST::PatternElement *e = new (pool) AST::PatternElement(stringRef(1), /*type annotation*/nullptr, nullptr, AST::PatternElement::Binding);
e->identifierToken = loc(1);
sym(1).FormalParameterList = (new (pool) AST::FormalParameterList(nullptr, e))->finish(pool);
} break;
@@ -3756,30 +3861,34 @@ ConciseBodyLookahead: ;
} break;
./
-MethodDefinition: PropertyName T_LPAREN StrictFormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
+MethodDefinition: PropertyName T_LPAREN StrictFormalParameters T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
- AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(1), sym(3).FormalParameterList, sym(6).StatementList);
+ if (!ensureNoFunctionTypeAnnotations(sym(5).TypeAnnotation, sym(3).FormalParameterList))
+ return false;
+ AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(1), sym(3).FormalParameterList, sym(7).StatementList);
f->functionToken = sym(1).PropertyName->firstSourceLocation();
f->lparenToken = loc(2);
f->rparenToken = loc(4);
- f->lbraceToken = loc(5);
- f->rbraceToken = loc(7);
+ f->lbraceToken = loc(6);
+ f->rbraceToken = loc(8);
AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(1).PropertyName, f, AST::PatternProperty::Method);
node->colonToken = loc(2);
sym(1).Node = node;
} break;
./
-MethodDefinition: T_STAR PropertyName GeneratorLParen StrictFormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
+MethodDefinition: T_STAR PropertyName GeneratorLParen StrictFormalParameters T_RPAREN TypeAnnotationOpt FunctionLBrace GeneratorBody GeneratorRBrace;
/.
case $rule_number: {
- AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
+ if (!ensureNoFunctionTypeAnnotations(sym(6).TypeAnnotation, sym(4).FormalParameterList))
+ return false;
+ AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(8).StatementList);
f->functionToken = sym(2).PropertyName->firstSourceLocation();
f->lparenToken = loc(3);
f->rparenToken = loc(5);
- f->lbraceToken = loc(6);
- f->rbraceToken = loc(8);
+ f->lbraceToken = loc(7);
+ f->rbraceToken = loc(9);
f->isGenerator = true;
AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(2).PropertyName, f, AST::PatternProperty::Method);
node->colonToken = loc(2);
@@ -3788,30 +3897,34 @@ MethodDefinition: T_STAR PropertyName GeneratorLParen StrictFormalParameters T_R
./
-MethodDefinition: T_GET PropertyName T_LPAREN T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
+MethodDefinition: T_GET PropertyName T_LPAREN T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
- AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), nullptr, sym(6).StatementList);
+ if (!ensureNoFunctionTypeAnnotations(sym(5).TypeAnnotation, /*formals*/nullptr))
+ return false;
+ AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), nullptr, sym(7).StatementList);
f->functionToken = sym(2).PropertyName->firstSourceLocation();
f->lparenToken = loc(3);
f->rparenToken = loc(4);
- f->lbraceToken = loc(5);
- f->rbraceToken = loc(7);
+ f->lbraceToken = loc(6);
+ f->rbraceToken = loc(8);
AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(2).PropertyName, f, AST::PatternProperty::Getter);
node->colonToken = loc(2);
sym(1).Node = node;
} break;
./
-MethodDefinition: T_SET PropertyName T_LPAREN PropertySetParameterList T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
+MethodDefinition: T_SET PropertyName T_LPAREN PropertySetParameterList T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
- AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
+ if (!ensureNoFunctionTypeAnnotations(sym(6).TypeAnnotation, sym(4).FormalParameterList))
+ return false;
+ AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(8).StatementList);
f->functionToken = sym(2).PropertyName->firstSourceLocation();
f->lparenToken = loc(3);
f->rparenToken = loc(5);
- f->lbraceToken = loc(6);
- f->rbraceToken = loc(8);
+ f->lbraceToken = loc(7);
+ f->rbraceToken = loc(9);
AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(2).PropertyName, f, AST::PatternProperty::Setter);
node->colonToken = loc(2);
sym(1).Node = node;
diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp
index 1bc0e6e364..de5db73d3f 100644
--- a/src/qml/parser/qqmljsast.cpp
+++ b/src/qml/parser/qqmljsast.cpp
@@ -131,7 +131,7 @@ FormalParameterList *ExpressionNode::reparseAsFormalParameterList(MemoryPool *po
}
AST::PatternElement *binding = nullptr;
if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(expr)) {
- binding = new (pool) AST::PatternElement(idExpr->name, rhs);
+ binding = new (pool) AST::PatternElement(idExpr->name, /*type annotation*/nullptr, rhs);
binding->identifierToken = idExpr->identifierToken;
} else if (AST::Pattern *p = expr->patternCast()) {
SourceLocation loc;
@@ -961,6 +961,7 @@ void FunctionDeclaration::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(formals, visitor);
+ accept(typeAnnotation, visitor);
accept(body, visitor);
}
@@ -971,6 +972,7 @@ void FunctionExpression::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(formals, visitor);
+ accept(typeAnnotation, visitor);
accept(body, visitor);
}
@@ -1271,6 +1273,35 @@ void UiQualifiedId::accept0(Visitor *visitor)
visitor->endVisit(this);
}
+void Type::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(typeId, visitor);
+ accept(typeArguments, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TypeArgumentList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (TypeArgumentList *it = this; it; it = it->next)
+ accept(it->typeId, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TypeAnnotation::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(type, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
void UiImport::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
@@ -1339,6 +1370,7 @@ void PatternElement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(bindingTarget, visitor);
+ accept(typeAnnotation, visitor);
accept(initializer, visitor);
}
@@ -1382,6 +1414,7 @@ void PatternProperty::accept0(Visitor *visitor)
if (visitor->visit(this)) {
accept(name, visitor);
accept(bindingTarget, visitor);
+ accept(typeAnnotation, visitor);
accept(initializer, visitor);
}
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index c62c11885f..21d143edf1 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -234,6 +234,9 @@ public:
Kind_PatternElementList,
Kind_PatternProperty,
Kind_PatternPropertyList,
+ Kind_Type,
+ Kind_TypeArgumentList,
+ Kind_TypeAnnotation,
Kind_UiArrayBinding,
Kind_UiImport,
@@ -304,6 +307,128 @@ public:
int kind = Kind_Undefined;
};
+
+class QML_PARSER_EXPORT UiQualifiedId: public Node
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(UiQualifiedId)
+
+ UiQualifiedId(const QStringRef &name)
+ : next(this), name(name)
+ { kind = K; }
+
+ UiQualifiedId(UiQualifiedId *previous, const QStringRef &name)
+ : name(name)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ UiQualifiedId *finish()
+ {
+ UiQualifiedId *head = next;
+ next = nullptr;
+ return head;
+ }
+
+ void accept0(Visitor *visitor) override;
+
+ SourceLocation firstSourceLocation() const override
+ { return identifierToken; }
+
+ SourceLocation lastSourceLocation() const override
+ { return next ? next->lastSourceLocation() : identifierToken; }
+
+// attributes
+ UiQualifiedId *next;
+ QStringRef name;
+ SourceLocation identifierToken;
+};
+
+class QML_PARSER_EXPORT Type: public Node
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(Type)
+
+ Type(UiQualifiedId *typeId, Node *typeArguments = nullptr)
+ : typeId(typeId)
+ , typeArguments(typeArguments)
+ { kind = K; }
+
+ void accept0(Visitor *visitor) override;
+
+ SourceLocation firstSourceLocation() const override
+ { return typeId->firstSourceLocation(); }
+
+ SourceLocation lastSourceLocation() const override
+ { return typeArguments ? typeArguments->lastSourceLocation() : typeId->lastSourceLocation(); }
+
+// attributes
+ UiQualifiedId *typeId;
+ Node *typeArguments; // TypeArgumentList
+};
+
+
+class QML_PARSER_EXPORT TypeArgumentList: public Node
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(TypeArgumentList)
+
+ TypeArgumentList(Type *typeId)
+ : typeId(typeId)
+ , next(nullptr)
+ { kind = K; }
+
+ TypeArgumentList(TypeArgumentList *previous, Type *typeId)
+ : typeId(typeId)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ void accept0(Visitor *visitor) override;
+
+ SourceLocation firstSourceLocation() const override
+ { return typeId->firstSourceLocation(); }
+
+ SourceLocation lastSourceLocation() const override
+ { return next ? next->lastSourceLocation() : typeId->lastSourceLocation(); }
+
+ inline TypeArgumentList *finish()
+ {
+ TypeArgumentList *front = next;
+ next = nullptr;
+ return front;
+ }
+
+// attributes
+ Type *typeId;
+ TypeArgumentList *next;
+};
+
+class QML_PARSER_EXPORT TypeAnnotation: public Node
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(TypeAnnotation)
+
+ TypeAnnotation(Type *type)
+ : type(type)
+ { kind = K; }
+
+ void accept0(Visitor *visitor) override;
+
+ SourceLocation firstSourceLocation() const override
+ { return colonToken; }
+
+ SourceLocation lastSourceLocation() const override
+ { return type->lastSourceLocation(); }
+
+// attributes
+ Type *type;
+ SourceLocation colonToken;
+};
class QML_PARSER_EXPORT ExpressionNode: public Node
{
public:
@@ -729,8 +854,9 @@ public:
: initializer(i), type(t)
{ kind = K; }
- PatternElement(const QStringRef &n, ExpressionNode *i = nullptr, Type t = Binding)
+ PatternElement(const QStringRef &n, TypeAnnotation *typeAnnotation = nullptr, ExpressionNode *i = nullptr, Type t = Binding)
: bindingIdentifier(n), initializer(i), type(t)
+ , typeAnnotation(typeAnnotation)
{
Q_ASSERT(t >= RestElement);
kind = K;
@@ -750,7 +876,7 @@ public:
{ return identifierToken.isValid() ? identifierToken : (bindingTarget ? bindingTarget->firstSourceLocation() : initializer->firstSourceLocation()); }
SourceLocation lastSourceLocation() const override
- { return initializer ? initializer->lastSourceLocation() : (bindingTarget ? bindingTarget->lastSourceLocation() : identifierToken); }
+ { return initializer ? initializer->lastSourceLocation() : (bindingTarget ? bindingTarget->lastSourceLocation() : (typeAnnotation ? typeAnnotation->lastSourceLocation() : identifierToken)); }
ExpressionNode *destructuringTarget() const { return bindingTarget; }
Pattern *destructuringPattern() const { return bindingTarget ? bindingTarget->patternCast() : nullptr; }
@@ -768,6 +894,7 @@ public:
ExpressionNode *bindingTarget = nullptr;
ExpressionNode *initializer = nullptr;
Type type = Literal;
+ TypeAnnotation *typeAnnotation = nullptr;
// when used in a VariableDeclarationList
VariableScope scope = VariableScope::NoScope;
bool isForDeclaration = false;
@@ -820,7 +947,7 @@ public:
{ kind = K; }
PatternProperty(PropertyName *name, const QStringRef &n, ExpressionNode *i = nullptr)
- : PatternElement(n, i), name(name)
+ : PatternElement(n, /*type annotation*/nullptr, i), name(name)
{ kind = K; }
PatternProperty(PropertyName *name, Pattern *pattern, ExpressionNode *i = nullptr)
@@ -2155,8 +2282,9 @@ class QML_PARSER_EXPORT FunctionExpression: public ExpressionNode
public:
QQMLJS_DECLARE_AST_NODE(FunctionExpression)
- FunctionExpression(const QStringRef &n, FormalParameterList *f, StatementList *b):
- name (n), formals (f), body (b)
+ FunctionExpression(const QStringRef &n, FormalParameterList *f, StatementList *b, TypeAnnotation *typeAnnotation = nullptr):
+ name (n), formals (f), body (b),
+ typeAnnotation(typeAnnotation)
{ kind = K; }
void accept0(Visitor *visitor) override;
@@ -2175,6 +2303,7 @@ public:
bool isGenerator = false;
FormalParameterList *formals;
StatementList *body;
+ TypeAnnotation *typeAnnotation;
SourceLocation functionToken;
SourceLocation identifierToken;
SourceLocation lparenToken;
@@ -2188,8 +2317,8 @@ class QML_PARSER_EXPORT FunctionDeclaration: public FunctionExpression
public:
QQMLJS_DECLARE_AST_NODE(FunctionDeclaration)
- FunctionDeclaration(const QStringRef &n, FormalParameterList *f, StatementList *b):
- FunctionExpression(n, f, b)
+ FunctionDeclaration(const QStringRef &n, FormalParameterList *f, StatementList *b, TypeAnnotation *typeAnnotation = nullptr):
+ FunctionExpression(n, f, b, typeAnnotation)
{ kind = K; }
void accept0(Visitor *visitor) override;
@@ -2810,44 +2939,6 @@ public:
SourceLocation semicolonToken;
};
-class QML_PARSER_EXPORT UiQualifiedId: public Node
-{
-public:
- QQMLJS_DECLARE_AST_NODE(UiQualifiedId)
-
- UiQualifiedId(const QStringRef &name)
- : next(this), name(name)
- { kind = K; }
-
- UiQualifiedId(UiQualifiedId *previous, const QStringRef &name)
- : name(name)
- {
- kind = K;
- next = previous->next;
- previous->next = this;
- }
-
- UiQualifiedId *finish()
- {
- UiQualifiedId *head = next;
- next = nullptr;
- return head;
- }
-
- void accept0(Visitor *visitor) override;
-
- SourceLocation firstSourceLocation() const override
- { return identifierToken; }
-
- SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : identifierToken; }
-
-// attributes
- UiQualifiedId *next;
- QStringRef name;
- SourceLocation identifierToken;
-};
-
class QML_PARSER_EXPORT UiImport: public Node
{
public:
diff --git a/src/qml/parser/qqmljsastfwd_p.h b/src/qml/parser/qqmljsastfwd_p.h
index 6fe108e425..05226fd043 100644
--- a/src/qml/parser/qqmljsastfwd_p.h
+++ b/src/qml/parser/qqmljsastfwd_p.h
@@ -158,6 +158,9 @@ class NestedExpression;
class ClassExpression;
class ClassDeclaration;
class ClassElementList;
+class TypeArgumentList;
+class Type;
+class TypeAnnotation;
// ui elements
class UiProgram;
diff --git a/src/qml/parser/qqmljsastvisitor_p.h b/src/qml/parser/qqmljsastvisitor_p.h
index f3732cbba8..7146cd00ac 100644
--- a/src/qml/parser/qqmljsastvisitor_p.h
+++ b/src/qml/parser/qqmljsastvisitor_p.h
@@ -403,6 +403,15 @@ public:
virtual bool visit(DebuggerStatement *) { return true; }
virtual void endVisit(DebuggerStatement *) {}
+ virtual bool visit(Type *) { return true; }
+ virtual void endVisit(Type *) {}
+
+ virtual bool visit(TypeArgumentList *) { return true; }
+ virtual void endVisit(TypeArgumentList *) {}
+
+ virtual bool visit(TypeAnnotation *) { return true; }
+ virtual void endVisit(TypeAnnotation *) {}
+
virtual void throwRecursionDepthError() = 0;
quint16 recursionDepth() const { return m_recursionDepth; }