aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/parser
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-03-25 19:14:23 +0200
committerLars Knoll <lars.knoll@qt.io>2018-05-02 14:17:03 +0000
commit1e974dd01c074ae9f32a5a1210f2fc55dba8dd3c (patch)
tree08d93f9278cfcab33d7ad4c1309737d45f1270ad /src/qml/parser
parent3f82c8131fed248c24ed8c8be7449b4732afcd0b (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.g19
-rw-r--r--src/qml/parser/qqmljsast.cpp26
-rw-r--r--src/qml/parser/qqmljsast_p.h10
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;