diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-03-25 19:14:23 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-05-02 14:17:03 +0000 |
commit | 1e974dd01c074ae9f32a5a1210f2fc55dba8dd3c (patch) | |
tree | 08d93f9278cfcab33d7ad4c1309737d45f1270ad /src/qml/parser | |
parent | 3f82c8131fed248c24ed8c8be7449b4732afcd0b (diff) |
Properly set names of most anonymous functions
In ES6, anonymous functions assigned to a variable/property with
a known name, inherit the name of that variable/property.
Change-Id: I79479b9358b24d610e3e696eb19fe0ec4aee15d1
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/parser')
-rw-r--r-- | src/qml/parser/qqmljs.g | 19 | ||||
-rw-r--r-- | src/qml/parser/qqmljsast.cpp | 26 | ||||
-rw-r--r-- | src/qml/parser/qqmljsast_p.h | 10 |
3 files changed, 54 insertions, 1 deletions
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index 389938e053..ce641accd8 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -1791,6 +1791,10 @@ CoverInitializedName: IdentifierReference Initializer_In; AST::PatternProperty *node = new (pool) AST::PatternProperty(name, stringRef(1), sym(2).Expression); node->colonToken = loc(2); 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)) + f->name = stringRef(1); + } break; ./ @@ -1800,6 +1804,10 @@ PropertyDefinition: PropertyName T_COLON AssignmentExpression_In; /. case $rule_number: { AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(1).PropertyName, sym(3).Expression); + if (auto *f = asAnonymousFunctionDefinition(sym(3).Expression)) { + if (!AST::cast<AST::ComputedPropertyName *>(sym(1).PropertyName)) + f->name = driver->newStringRef(sym(1).PropertyName->asString()); + } node->colonToken = loc(2); sym(1).Node = node; } break; @@ -2518,6 +2526,12 @@ AssignmentExpression_In: LeftHandSideExpression T_EQ AssignmentExpression_In; return false; } } + // if lhs is an identifier expression and rhs is an anonymous function expression, we need to assign the name of lhs to the function + if (auto *f = asAnonymousFunctionDefinition(sym(3).Expression)) { + if (auto *id = AST::cast<AST::IdentifierExpression *>(sym(1).Expression)) + f->name = id->name; + } + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Assign, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2826,6 +2840,9 @@ VariableDeclaration_In: BindingIdentifier InitializerOpt_In; auto *node = new (pool) AST::PatternElement(stringRef(1), sym(2).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)) + f->name = stringRef(1); } break; ./ @@ -3478,7 +3495,7 @@ FunctionExpression: T_FUNCTION BindingIdentifier T_LPAREN FormalParameters T_RPA FunctionExpression: T_FUNCTION T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace; /. case $rule_number: { - AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(1), sym(3).FormalParameterList, sym(6).StatementList); + 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); diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp index 762eb9536a..eef7a33f26 100644 --- a/src/qml/parser/qqmljsast.cpp +++ b/src/qml/parser/qqmljsast.cpp @@ -45,6 +45,17 @@ QT_QML_BEGIN_NAMESPACE namespace QQmlJS { namespace AST { +FunctionExpression *asAnonymousFunctionDefinition(Node *n) +{ + if (!n) + return nullptr; + FunctionExpression *f = n->asFunctionDefinition(); + if (!f || !f->name.isNull()) + return nullptr; + return f; +} + + void Node::accept(Visitor *visitor) { if (visitor->preVisit(this)) { @@ -89,6 +100,11 @@ Pattern *Node::patternCast() return nullptr; } +FunctionExpression *Node::asFunctionDefinition() +{ + return nullptr; +} + ExpressionNode *ExpressionNode::expressionCast() { return this; @@ -117,6 +133,11 @@ void NestedExpression::accept0(Visitor *visitor) visitor->endVisit(this); } +FunctionExpression *NestedExpression::asFunctionDefinition() +{ + return expression->asFunctionDefinition(); +} + void ThisExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { @@ -909,6 +930,11 @@ void FunctionExpression::accept0(Visitor *visitor) visitor->endVisit(this); } +FunctionExpression *FunctionExpression::asFunctionDefinition() +{ + return this; +} + QStringList FormalParameterList::formals() const { QStringList formals; diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h index 10fe2e9e72..e14e058e83 100644 --- a/src/qml/parser/qqmljsast_p.h +++ b/src/qml/parser/qqmljsast_p.h @@ -128,6 +128,8 @@ T1 cast(T2 *ast) return 0; } +FunctionExpression *asAnonymousFunctionDefinition(AST::Node *n); + class QML_PARSER_EXPORT Node: public Managed { public: @@ -254,6 +256,8 @@ public: virtual UiObjectMember *uiObjectMemberCast(); virtual LeftHandSideExpression *leftHandSideExpressionCast(); virtual Pattern *patternCast(); + // implements the IsFunctionDefinition rules in the spec + virtual FunctionExpression *asFunctionDefinition(); void accept(Visitor *visitor); static void accept(Node *node, Visitor *visitor); @@ -307,6 +311,9 @@ public: SourceLocation lastSourceLocation() const override { return rparenToken; } + FunctionExpression *asFunctionDefinition() override; + + // attributes ExpressionNode *expression; SourceLocation lparenToken; @@ -2140,6 +2147,9 @@ public: SourceLocation lastSourceLocation() const override { return rbraceToken; } + FunctionExpression *asFunctionDefinition() override; + + // attributes QStringRef name; bool isArrowFunction = false; |