aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-03-25 20:16:27 +0200
committerLars Knoll <lars.knoll@qt.io>2018-05-02 14:17:08 +0000
commit17f72f2d07352940b67a60c2ff6f7ef848793488 (patch)
tree4a2cf7429acaaf8c8c9d8620f989ad07ccd120b7 /src
parent1e974dd01c074ae9f32a5a1210f2fc55dba8dd3c (diff)
Fix destructuring of arrow function parameters
Change-Id: I64b49ae77ecd81eafb320cda04a1a7bf4b2dc90c Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/parser/qqmljs.g35
-rw-r--r--src/qml/parser/qqmljsast.cpp42
-rw-r--r--src/qml/parser/qqmljsast_p.h8
3 files changed, 54 insertions, 31 deletions
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index ce641accd8..bb0f53f4ab 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -387,7 +387,6 @@ protected:
AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr);
AST::UiQualifiedPragmaId *reparseAsQualifiedPragmaId(AST::ExpressionNode *expr);
- AST::FormalParameterList *reparseAsFormalParameterList(AST::ExpressionNode *expr);
void pushToken(int token);
int lookaheadToken(Lexer *lexer);
@@ -553,34 +552,6 @@ AST::UiQualifiedPragmaId *Parser::reparseAsQualifiedPragmaId(AST::ExpressionNode
return 0;
}
-AST::FormalParameterList *Parser::reparseAsFormalParameterList(AST::ExpressionNode *expr)
-{
- AST::FormalParameterList *f = nullptr;
- if (AST::Expression *commaExpr = AST::cast<AST::Expression *>(expr)) {
- f = reparseAsFormalParameterList(commaExpr->left);
- 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;
- }
- if (!binding)
- return nullptr;
- return new (pool) AST::FormalParameterList(f, binding);
-}
-
void Parser::pushToken(int token)
{
last_token->token = yytoken;
@@ -1506,7 +1477,7 @@ CoverParenthesizedExpressionAndArrowParameterList: T_LPAREN BindingRestElement T
CoverParenthesizedExpressionAndArrowParameterList: T_LPAREN Expression_In T_COMMA BindingRestElementOpt T_RPAREN;
/.
case $rule_number: {
- AST::FormalParameterList *list = reparseAsFormalParameterList(sym(2).Expression);
+ AST::FormalParameterList *list = sym(2).Expression->reparseAsFormalParameterList(pool);
if (!list) {
syntaxError(loc(1), "Invalid Arrow parameter list.");
return false;
@@ -2867,6 +2838,7 @@ BindingPattern: T_LBRACE ObjectBindingPattern T_RBRACE;
auto *node = new (pool) AST::ObjectPattern(sym(2).PatternPropertyList);
node->lbraceToken = loc(1);
node->rbraceToken = loc(3);
+ node->parseMode = AST::Pattern::Binding;
sym(1).Node = node;
} break;
./
@@ -2877,6 +2849,7 @@ BindingPattern: T_LBRACKET ArrayBindingPattern T_RBRACKET;
auto *node = new (pool) AST::ArrayPattern(sym(2).PatternElementList);
node->lbracketToken = loc(1);
node->rbracketToken = loc(3);
+ node->parseMode = AST::Pattern::Binding;
sym(1).Node = node;
} break;
./
@@ -3612,7 +3585,7 @@ ArrowParameters: CoverParenthesizedExpressionAndArrowParameterList;
case $rule_number: {
if (coverExpressionType != CE_FormalParameterList) {
AST::NestedExpression *ne = static_cast<AST::NestedExpression *>(sym(1).Node);
- AST::FormalParameterList *list = reparseAsFormalParameterList(ne->expression);
+ AST::FormalParameterList *list = ne->expression->reparseAsFormalParameterList(pool);
if (!list) {
syntaxError(loc(1), "Invalid Arrow parameter list.");
return false;
diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp
index eef7a33f26..c86fb24e82 100644
--- a/src/qml/parser/qqmljsast.cpp
+++ b/src/qml/parser/qqmljsast.cpp
@@ -110,6 +110,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;
@@ -319,6 +355,8 @@ PropertyName:
*/
bool ArrayPattern::convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage)
{
+ if (parseMode == Binding)
+ return true;
for (auto *it = elements; it; it = it->next) {
if (it->element->type == PatternElement::SpreadElement && it->next) {
*errorLocation = it->element->firstSourceLocation();
@@ -328,15 +366,19 @@ bool ArrayPattern::convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLoc
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;
}
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index e14e058e83..c83a459506 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -279,6 +279,9 @@ public:
ExpressionNode() {}
ExpressionNode *expressionCast() override;
+
+ AST::FormalParameterList *reparseAsFormalParameterList(MemoryPool *pool);
+
};
class QML_PARSER_EXPORT LeftHandSideExpression : public ExpressionNode
@@ -527,8 +530,13 @@ public:
class QML_PARSER_EXPORT Pattern : public LeftHandSideExpression
{
public:
+ enum ParseMode {
+ Literal,
+ Binding
+ };
Pattern *patternCast() override;
virtual bool convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage) = 0;
+ ParseMode parseMode = Literal;
};
class QML_PARSER_EXPORT ArrayPattern : public Pattern