From dcbdb306f4442199384a71d532a3610a84d13fd5 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 30 Jun 2018 21:04:51 +0200 Subject: Fix naming of classes in class expressions As with function expressions, class expressions also get an implicitly defined name if they are directly assigned to a named variable. Change-Id: I5fda9d74c1c299107f15b82245333b54ca6d8917 Reviewed-by: Simon Hausmann --- src/qml/parser/qqmljs.g | 16 ++++++++++++++++ src/qml/parser/qqmljsast.cpp | 25 +++++++++++++++++++++++++ src/qml/parser/qqmljsast_p.h | 6 +++++- 3 files changed, 46 insertions(+), 1 deletion(-) (limited to 'src/qml/parser') diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index 9231001f17..cd40a77299 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -1779,6 +1779,8 @@ CoverInitializedName: IdentifierReference Initializer_In; // 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); + if (auto *c = asAnonymousClassDefinition(sym(2).Expression)) + c->name = stringRef(1); AST::BinaryExpression *assignment = new (pool) AST::BinaryExpression(left, QSOperator::Assign, sym(2).Expression); AST::PatternProperty *node = new (pool) AST::PatternProperty(name, assignment); node->colonToken = loc(1); @@ -1797,6 +1799,10 @@ PropertyDefinition: PropertyName T_COLON AssignmentExpression_In; if (!AST::cast(sym(1).PropertyName)) f->name = driver->newStringRef(sym(1).PropertyName->asString()); } + if (auto *c = asAnonymousClassDefinition(sym(3).Expression)) { + if (!AST::cast(sym(1).PropertyName)) + c->name = driver->newStringRef(sym(1).PropertyName->asString()); + } node->colonToken = loc(2); sym(1).Node = node; } break; @@ -2520,6 +2526,10 @@ AssignmentExpression_In: LeftHandSideExpression T_EQ AssignmentExpression_In; if (auto *id = AST::cast(sym(1).Expression)) f->name = id->name; } + if (auto *c = asAnonymousClassDefinition(sym(3).Expression)) { + if (auto *id = AST::cast(sym(1).Expression)) + c->name = id->name; + } AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Assign, sym(3).Expression); node->operatorToken = loc(2); @@ -2832,6 +2842,8 @@ VariableDeclaration_In: BindingIdentifier InitializerOpt_In; // 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); + if (auto *c = asAnonymousClassDefinition(sym(2).Expression)) + c->name = stringRef(1); } break; ./ @@ -2958,6 +2970,8 @@ BindingProperty: BindingIdentifier InitializerOpt_In; // 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); + if (auto *c = asAnonymousClassDefinition(sym(2).Expression)) + c->name = stringRef(1); sym(1).Node = new (pool) AST::PatternProperty(name, stringRef(1), sym(2).Expression); } break; ./ @@ -2986,6 +3000,8 @@ BindingElement: BindingIdentifier InitializerOpt_In; // 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); + if (auto *c = asAnonymousClassDefinition(sym(2).Expression)) + c->name = stringRef(1); sym(1).Node = node; } break; ./ diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp index 89ef861c85..b8c4a58a13 100644 --- a/src/qml/parser/qqmljsast.cpp +++ b/src/qml/parser/qqmljsast.cpp @@ -55,6 +55,16 @@ FunctionExpression *asAnonymousFunctionDefinition(Node *n) return f; } +ClassExpression *asAnonymousClassDefinition(Node *n) +{ + if (!n) + return nullptr; + ClassExpression *c = n->asClassDefinition(); + if (!c || !c->name.isNull()) + return nullptr; + return c; +} + void Node::accept(Visitor *visitor) { @@ -105,6 +115,11 @@ FunctionExpression *Node::asFunctionDefinition() return nullptr; } +ClassExpression *Node::asClassDefinition() +{ + return nullptr; +} + ExpressionNode *ExpressionNode::expressionCast() { return this; @@ -174,6 +189,11 @@ FunctionExpression *NestedExpression::asFunctionDefinition() return expression->asFunctionDefinition(); } +ClassExpression *NestedExpression::asClassDefinition() +{ + return expression->asClassDefinition(); +} + void ThisExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { @@ -1296,6 +1316,11 @@ void ClassExpression::accept0(Visitor *visitor) visitor->endVisit(this); } +ClassExpression *ClassExpression::asClassDefinition() +{ + return this; +} + void ClassDeclaration::accept0(Visitor *visitor) { if (visitor->visit(this)) { diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h index 6a4e1e6ea1..2cf2bcb736 100644 --- a/src/qml/parser/qqmljsast_p.h +++ b/src/qml/parser/qqmljsast_p.h @@ -129,6 +129,7 @@ T1 cast(T2 *ast) } FunctionExpression *asAnonymousFunctionDefinition(AST::Node *n); +ClassExpression *asAnonymousClassDefinition(AST::Node *n); class QML_PARSER_EXPORT Node: public Managed { @@ -257,6 +258,7 @@ public: virtual Pattern *patternCast(); // implements the IsFunctionDefinition rules in the spec virtual FunctionExpression *asFunctionDefinition(); + virtual ClassExpression *asClassDefinition(); void accept(Visitor *visitor); static void accept(Node *node, Visitor *visitor); @@ -314,6 +316,7 @@ public: { return rparenToken; } FunctionExpression *asFunctionDefinition() override; + ClassExpression *asClassDefinition() override; // attributes @@ -2110,7 +2113,6 @@ public: FunctionExpression *asFunctionDefinition() override; - // attributes QStringRef name; bool isArrowFunction = false; @@ -2237,6 +2239,8 @@ public: SourceLocation lastSourceLocation() const override { return rbraceToken; } + ClassExpression *asClassDefinition() override; + // attributes QStringRef name; ExpressionNode *heritage; -- cgit v1.2.3