// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include #include #include "common/qqmljssourcelocation_p.h" #include "qqmljsast_p.h" #include "qqmljsastvisitor_p.h" #include #include #include QT_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; } ClassExpression *asAnonymousClassDefinition(Node *n) { if (!n) return nullptr; ClassExpression *c = n->asClassDefinition(); if (!c || !c->name.isNull()) return nullptr; return c; } ExpressionNode *Node::expressionCast() { return nullptr; } BinaryExpression *Node::binaryExpressionCast() { return nullptr; } Statement *Node::statementCast() { return nullptr; } UiObjectMember *Node::uiObjectMemberCast() { return nullptr; } LeftHandSideExpression *Node::leftHandSideExpressionCast() { return nullptr; } Pattern *Node::patternCast() { return nullptr; } FunctionExpression *Node::asFunctionDefinition() { return nullptr; } ClassExpression *Node::asClassDefinition() { return nullptr; } bool Node::ignoreRecursionDepth() const { static const bool doIgnore = qEnvironmentVariableIsSet("QV4_CRASH_ON_STACKOVERFLOW"); return doIgnore; } ExpressionNode *ExpressionNode::expressionCast() { return this; } bool ExpressionNode::containsOptionalChain() const { for (const Node *node = this;;) { switch (node->kind) { case Kind_FieldMemberExpression: { const auto *fme = AST::cast(node); if (fme->isOptional) return true; node = fme->base; break; } case Kind_ArrayMemberExpression: { const auto *ame = AST::cast(node); if (ame->isOptional) return true; node = ame->base; break; } case Kind_CallExpression: { const auto *ce = AST::cast(node); if (ce->isOptional) return true; node = ce->base; break; } case Kind_NestedExpression: { const auto *ne = AST::cast(node); node = ne->expression; break; } default: // These unhandled nodes lead to invalid lvalues anyway, so they do not need to be handled here. return false; } } return false; } FormalParameterList *ExpressionNode::reparseAsFormalParameterList(MemoryPool *pool) { AST::ExpressionNode *expr = this; AST::FormalParameterList *f = nullptr; if (AST::Expression *commaExpr = AST::cast(expr)) { f = commaExpr->left->reparseAsFormalParameterList(pool); if (!f) return nullptr; expr = commaExpr->right; } AST::ExpressionNode *rhs = nullptr; if (AST::BinaryExpression *assign = AST::cast(expr)) { if (assign->op != QSOperator::Assign) return nullptr; expr = assign->left; rhs = assign->right; } AST::PatternElement *binding = nullptr; if (AST::IdentifierExpression *idExpr = AST::cast(expr)) { binding = new (pool) AST::PatternElement(idExpr->name, /*type annotation*/nullptr, 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; } void TypeExpression::accept0(BaseVisitor *visitor) { visitor->visit(this); visitor->endVisit(this); } Statement *Statement::statementCast() { return this; } UiObjectMember *UiObjectMember::uiObjectMemberCast() { return this; } void NestedExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } FunctionExpression *NestedExpression::asFunctionDefinition() { return expression->asFunctionDefinition(); } ClassExpression *NestedExpression::asClassDefinition() { return expression->asClassDefinition(); } void ThisExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void IdentifierExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void NullExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void TrueLiteral::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void FalseLiteral::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void SuperLiteral::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void StringLiteral::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void TemplateLiteral::accept0(BaseVisitor *visitor) { bool accepted = true; for (TemplateLiteral *it = this; it && accepted; it = it->next) { accepted = visitor->visit(it); visitor->endVisit(it); } } void NumericLiteral::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void RegExpLiteral::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void ArrayPattern::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) accept(elements, visitor); visitor->endVisit(this); } bool ArrayPattern::isValidArrayLiteral(SourceLocation *errorLocation) const { for (PatternElementList *it = elements; it != nullptr; it = it->next) { PatternElement *e = it->element; if (e && e->bindingTarget != nullptr) { if (errorLocation) *errorLocation = e->firstSourceLocation(); return false; } } return true; } void ObjectPattern::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(properties, visitor); } visitor->endVisit(this); } /* This is the grammar for AssignmentPattern that we need to convert the literal to: AssignmentPattern: ObjectAssignmentPattern ArrayAssignmentPattern ArrayAssignmentPattern: [ ElisionOpt AssignmentRestElementOpt ] [ AssignmentElementList ] [ AssignmentElementList , ElisionOpt AssignmentRestElementOpt ] AssignmentElementList: AssignmentElisionElement AssignmentElementList , AssignmentElisionElement AssignmentElisionElement: ElisionOpt AssignmentElement AssignmentRestElement: ... DestructuringAssignmentTarget ObjectAssignmentPattern: {} { AssignmentPropertyList } { AssignmentPropertyList, } AssignmentPropertyList: AssignmentProperty AssignmentPropertyList , AssignmentProperty AssignmentProperty: IdentifierReference InitializerOpt_In PropertyName: AssignmentElement AssignmentElement: DestructuringAssignmentTarget InitializerOpt_In DestructuringAssignmentTarget: LeftHandSideExpression It was originally parsed with the following grammar: ArrayLiteral: [ ElisionOpt ] [ ElementList ] [ ElementList , ElisionOpt ] ElementList: ElisionOpt AssignmentExpression_In ElisionOpt SpreadElement ElementList , ElisionOpt AssignmentExpression_In ElementList , Elisionopt SpreadElement SpreadElement: ... AssignmentExpression_In ObjectLiteral: {} { PropertyDefinitionList } { PropertyDefinitionList , } PropertyDefinitionList: PropertyDefinition PropertyDefinitionList , PropertyDefinition PropertyDefinition: IdentifierReference CoverInitializedName PropertyName : AssignmentExpression_In MethodDefinition PropertyName: LiteralPropertyName ComputedPropertyName */ 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) continue; if (it->element->type == PatternElement::SpreadElement && it->next) { *errorLocation = it->element->firstSourceLocation(); *errorMessage = QString::fromLatin1("'...' can only appear as last element in a destructuring list."); return false; } 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; } bool PatternElement::convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage) { Q_ASSERT(type == Literal || type == SpreadElement); Q_ASSERT(bindingIdentifier.isNull()); Q_ASSERT(bindingTarget == nullptr); Q_ASSERT(bindingTarget == nullptr); Q_ASSERT(initializer); ExpressionNode *init = initializer; initializer = nullptr; LeftHandSideExpression *lhs = init->leftHandSideExpressionCast(); if (type == SpreadElement) { if (!lhs) { *errorLocation = init->firstSourceLocation(); *errorMessage = QString::fromLatin1("Invalid lhs expression after '...' in destructuring expression."); return false; } } else { type = PatternElement::Binding; if (BinaryExpression *b = init->binaryExpressionCast()) { if (b->op != QSOperator::Assign) { *errorLocation = b->operatorToken; *errorMessage = QString::fromLatin1("Invalid assignment operation in destructuring expression"); return false; } lhs = b->left->leftHandSideExpressionCast(); initializer = b->right; Q_ASSERT(lhs); } else { lhs = init->leftHandSideExpressionCast(); } if (!lhs) { *errorLocation = init->firstSourceLocation(); *errorMessage = QString::fromLatin1("Destructuring target is not a left hand side expression."); return false; } } if (auto *i = cast(lhs)) { bindingIdentifier = i->name; identifierToken = i->identifierToken; return true; } bindingTarget = lhs; if (auto *p = lhs->patternCast()) { if (!p->convertLiteralToAssignmentPattern(pool, errorLocation, errorMessage)) return false; } return true; } bool PatternProperty::convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage) { Q_ASSERT(type != SpreadElement); if (type == Binding) return true; if (type == Getter || type == Setter) { *errorLocation = firstSourceLocation(); *errorMessage = QString::fromLatin1("Invalid getter/setter in destructuring expression."); return false; } if (type == Method) type = Literal; Q_ASSERT(type == Literal); return PatternElement::convertLiteralToAssignmentPattern(pool, errorLocation, errorMessage); } void Elision::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { // ### } visitor->endVisit(this); } void IdentifierPropertyName::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void StringLiteralPropertyName::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void NumericLiteralPropertyName::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } namespace { struct LocaleWithoutZeroPadding : public QLocale { LocaleWithoutZeroPadding() : QLocale(QLocale::C) { setNumberOptions(QLocale::OmitLeadingZeroInExponent | QLocale::OmitGroupSeparator); } }; } QString NumericLiteralPropertyName::asString()const { // Can't use QString::number here anymore as it does zero padding by default now. // In C++11 this initialization is thread-safe (6.7 [stmt.dcl] p4) static LocaleWithoutZeroPadding locale; // Because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83562 we can't use thread_local // for the locale variable and therefore rely on toString(double) to be thread-safe. return locale.toString(id, 'g', 16); } void ArrayMemberExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); accept(expression, visitor); } visitor->endVisit(this); } void FieldMemberExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); } visitor->endVisit(this); } void NewMemberExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); accept(arguments, visitor); } visitor->endVisit(this); } void NewExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void CallExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); accept(arguments, visitor); } visitor->endVisit(this); } void ArgumentList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (ArgumentList *it = this; it; it = it->next) { accept(it->expression, visitor); } } visitor->endVisit(this); } void PostIncrementExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); } visitor->endVisit(this); } void PostDecrementExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); } visitor->endVisit(this); } void DeleteExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void VoidExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void TypeOfExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void PreIncrementExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void PreDecrementExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void UnaryPlusExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void UnaryMinusExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void TildeExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void NotExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void BinaryExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(left, visitor); accept(right, visitor); } visitor->endVisit(this); } void ConditionalExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(ok, visitor); accept(ko, visitor); } visitor->endVisit(this); } void Expression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(left, visitor); accept(right, visitor); } visitor->endVisit(this); } void Block::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(statements, visitor); } visitor->endVisit(this); } void StatementList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (StatementList *it = this; it; it = it->next) { accept(it->statement, visitor); } } visitor->endVisit(this); } void VariableStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(declarations, visitor); } visitor->endVisit(this); } void VariableDeclarationList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (VariableDeclarationList *it = this; it; it = it->next) { accept(it->declaration, visitor); } } visitor->endVisit(this); } void EmptyStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void ExpressionStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void IfStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(ok, visitor); accept(ko, visitor); } visitor->endVisit(this); } void DoWhileStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); accept(expression, visitor); } visitor->endVisit(this); } void WhileStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void ForStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(initialiser, visitor); accept(declarations, visitor); accept(condition, visitor); accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void ForEachStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(lhs, visitor); accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void ContinueStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void BreakStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void ReturnStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void YieldExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void WithStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void SwitchStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(block, visitor); } visitor->endVisit(this); } void CaseBlock::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(clauses, visitor); accept(defaultClause, visitor); accept(moreClauses, visitor); } visitor->endVisit(this); } void CaseClauses::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (CaseClauses *it = this; it; it = it->next) { accept(it->clause, visitor); } } visitor->endVisit(this); } void CaseClause::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(statements, visitor); } visitor->endVisit(this); } void DefaultClause::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(statements, visitor); } visitor->endVisit(this); } void LabelledStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); } visitor->endVisit(this); } void ThrowStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void TryStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); accept(catchExpression, visitor); accept(finallyExpression, visitor); } visitor->endVisit(this); } void Catch::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(patternElement, visitor); accept(statement, visitor); } visitor->endVisit(this); } void Finally::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); } visitor->endVisit(this); } void FunctionDeclaration::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(formals, visitor); accept(typeAnnotation, visitor); accept(body, visitor); } visitor->endVisit(this); } void FunctionExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(formals, visitor); accept(typeAnnotation, visitor); accept(body, visitor); } visitor->endVisit(this); } FunctionExpression *FunctionExpression::asFunctionDefinition() { return this; } BoundNames FormalParameterList::formals() const { BoundNames formals; int i = 0; for (const FormalParameterList *it = this; it; it = it->next) { if (it->element) { QString name = it->element->bindingIdentifier.toString(); int duplicateIndex = formals.indexOf(name); if (duplicateIndex >= 0) { // change the name of the earlier argument to enforce the lookup semantics from the spec formals[duplicateIndex].id += QLatin1String("#") + QString::number(i); } formals += { name, it->element->firstSourceLocation(), it->element->typeAnnotation, it->element->isInjectedSignalParameter ? BoundName::Injected : BoundName::Declared }; } ++i; } return formals; } BoundNames FormalParameterList::boundNames() const { BoundNames names; for (const FormalParameterList *it = this; it; it = it->next) { if (it->element) it->element->boundNames(&names); } return names; } void FormalParameterList::accept0(BaseVisitor *visitor) { bool accepted = true; for (FormalParameterList *it = this; it && accepted; it = it->next) { accepted = visitor->visit(it); if (accepted) accept(it->element, visitor); visitor->endVisit(it); } } FormalParameterList *FormalParameterList::finish(QQmlJS::MemoryPool *) { FormalParameterList *front = next; next = nullptr; return front; } void Program::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(statements, visitor); } visitor->endVisit(this); } void ImportSpecifier::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void ImportsList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (ImportsList *it = this; it; it = it->next) { accept(it->importSpecifier, visitor); } } visitor->endVisit(this); } void NamedImports::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(importsList, visitor); } visitor->endVisit(this); } void FromClause::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void NameSpaceImport::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void ImportClause::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(nameSpaceImport, visitor); accept(namedImports, visitor); } visitor->endVisit(this); } void ImportDeclaration::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(importClause, visitor); accept(fromClause, visitor); } visitor->endVisit(this); } void ExportSpecifier::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void ExportsList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (ExportsList *it = this; it; it = it->next) { accept(it->exportSpecifier, visitor); } } visitor->endVisit(this); } void ExportClause::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(exportsList, visitor); } visitor->endVisit(this); } void ExportDeclaration::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(exportClause, visitor); accept(fromClause, visitor); accept(variableStatementOrDeclaration, visitor); } visitor->endVisit(this); } void ESModule::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(body, visitor); } visitor->endVisit(this); } void DebuggerStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void UiProgram::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(headers, visitor); accept(members, visitor); } visitor->endVisit(this); } void UiPublicMember::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { // accept(annotations, visitor); // accept manually in visit if interested // accept(memberType, visitor); // accept manually in visit if interested accept(statement, visitor); accept(binding, visitor); // accept(parameters, visitor); // accept manually in visit if interested } visitor->endVisit(this); } void UiObjectDefinition::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { // accept(annotations, visitor); // accept manually in visit if interested accept(qualifiedTypeNameId, visitor); accept(initializer, visitor); } visitor->endVisit(this); } void UiObjectInitializer::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(members, visitor); } visitor->endVisit(this); } void UiParameterList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { // accept(type, visitor); // accept manually in visit if interested } visitor->endVisit(this); } void UiObjectBinding::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { // accept(annotations, visitor); // accept manually in visit if interested accept(qualifiedId, visitor); accept(qualifiedTypeNameId, visitor); accept(initializer, visitor); } visitor->endVisit(this); } void UiScriptBinding::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { // accept(annotations, visitor); // accept manually in visit if interested accept(qualifiedId, visitor); accept(statement, visitor); } visitor->endVisit(this); } void UiArrayBinding::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { // accept(annotations, visitor); // accept manually in visit if interested accept(qualifiedId, visitor); accept(members, visitor); } visitor->endVisit(this); } void UiObjectMemberList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (UiObjectMemberList *it = this; it; it = it->next) accept(it->member, visitor); } visitor->endVisit(this); } void UiArrayMemberList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (UiArrayMemberList *it = this; it; it = it->next) accept(it->member, visitor); } visitor->endVisit(this); } void UiQualifiedId::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { // accept(next, visitor) // accept manually in visit if interested } visitor->endVisit(this); } void Type::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(typeId, visitor); accept(typeArgument, visitor); } visitor->endVisit(this); } void TypeAnnotation::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(type, visitor); } visitor->endVisit(this); } void UiImport::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(importUri, visitor); // accept(version, visitor); // accept manually in visit if interested } visitor->endVisit(this); } void UiPragmaValueList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void UiPragma::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void UiHeaderItemList::accept0(BaseVisitor *visitor) { bool accepted = true; for (UiHeaderItemList *it = this; it && accepted; it = it->next) { accepted = visitor->visit(it); if (accepted) accept(it->headerItem, visitor); visitor->endVisit(it); } } void UiSourceElement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { // accept(annotations, visitor); // accept manually in visit if interested accept(sourceElement, visitor); } visitor->endVisit(this); } void UiEnumDeclaration::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { // accept(annotations, visitor); // accept manually in visit if interested accept(members, visitor); } visitor->endVisit(this); } void UiEnumMemberList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void TaggedTemplate::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); accept(templateLiteral, visitor); } visitor->endVisit(this); } void InitializerExpression::accept0(BaseVisitor *visitor) { expression->accept0(visitor); } void PatternElement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(bindingTarget, visitor); accept(typeAnnotation, visitor); accept(initializer, visitor); } visitor->endVisit(this); } void PatternElement::boundNames(BoundNames *names) { if (bindingTarget) { if (PatternElementList *e = elementList()) e->boundNames(names); else if (PatternPropertyList *p = propertyList()) p->boundNames(names); } else { names->append({ bindingIdentifier.toString(), firstSourceLocation(), typeAnnotation, isInjectedSignalParameter ? BoundName::Injected : BoundName::Declared }); } } void PatternElementList::accept0(BaseVisitor *visitor) { bool accepted = true; for (PatternElementList *it = this; it && accepted; it = it->next) { accepted = visitor->visit(it); if (accepted) { accept(it->elision, visitor); accept(it->element, visitor); } visitor->endVisit(it); } } void PatternElementList::boundNames(BoundNames *names) { for (PatternElementList *it = this; it; it = it->next) { if (it->element) it->element->boundNames(names); } } void PatternProperty::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(name, visitor); accept(bindingTarget, visitor); accept(typeAnnotation, visitor); accept(initializer, visitor); } visitor->endVisit(this); } void PatternProperty::boundNames(BoundNames *names) { PatternElement::boundNames(names); } void PatternPropertyList::accept0(BaseVisitor *visitor) { bool accepted = true; for (PatternPropertyList *it = this; it && accepted; it = it->next) { accepted = visitor->visit(it); if (accepted) accept(it->property, visitor); visitor->endVisit(it); } } void PatternPropertyList::boundNames(BoundNames *names) { for (PatternPropertyList *it = this; it; it = it->next) it->property->boundNames(names); } void ComputedPropertyName::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void ClassExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(heritage, visitor); accept(elements, visitor); } visitor->endVisit(this); } ClassExpression *ClassExpression::asClassDefinition() { return this; } void ClassDeclaration::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(heritage, visitor); accept(elements, visitor); } visitor->endVisit(this); } void ClassElementList::accept0(BaseVisitor *visitor) { bool accepted = true; for (ClassElementList *it = this; it && accepted; it = it->next) { accepted = visitor->visit(it); if (accepted) accept(it->property, visitor); visitor->endVisit(it); } } ClassElementList *ClassElementList::finish() { ClassElementList *front = next; next = nullptr; return front; } Pattern *Pattern::patternCast() { return this; } LeftHandSideExpression *LeftHandSideExpression::leftHandSideExpressionCast() { return this; } void UiVersionSpecifier::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } QString Type::toString() const { QString result; toString(&result); return result; } void Type::toString(QString *out) const { typeId->toString(out); if (typeArgument) { out->append(QLatin1Char('<')); typeArgument->toString(out); out->append(QLatin1Char('>')); }; } void UiInlineComponent::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { // accept(annotations, visitor); // accept manually in visit if interested accept(component, visitor); } visitor->endVisit(this); } void UiRequired::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void UiAnnotationList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (UiAnnotationList *it = this; it; it = it->next) accept(it->annotation, visitor); } visitor->endVisit(this); } void UiAnnotation::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(qualifiedTypeNameId, visitor); accept(initializer, visitor); } visitor->endVisit(this); } SourceLocation UiPropertyAttributes::firstSourceLocation() const { std::array tokens {&m_propertyToken, &m_defaultToken, &m_readonlyToken, &m_requiredToken}; const auto it = std::min_element(tokens.begin(), tokens.end(), compareLocationsByBegin); return **it; } SourceLocation UiPropertyAttributes::lastSourceLocation() const { std::array tokens {&m_propertyToken, &m_defaultToken, &m_readonlyToken, &m_requiredToken}; const auto it = std::max_element(tokens.begin(), tokens.end(), compareLocationsByBegin); return **it; } } } // namespace QQmlJS::AST QT_END_NAMESPACE