Revision control

++ // 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
++ // Qt-Security score:significant
++
++ #include <QString>
++ #include <QLocale>
++ #include "common/qqmljsdiagnosticmessage_p.h"
++ #include "common/qqmljssourcelocation_p.h"
++ #include "qqmljsast_p.h"
++
++ #include "qqmljsastvisitor_p.h"
++ #include <qlocale.h>
++
++ #include <algorithm>
++ #include <array>
++
++ 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<const FieldMemberExpression*>(node);
++ if (fme->isOptional)
++ return true;
++ node = fme->base;
++ break;
++ }
++ case Kind_ArrayMemberExpression: {
++ const auto *ame = AST::cast<const ArrayMemberExpression*>(node);
++ if (ame->isOptional)
++ return true;
++ node = ame->base;
++ break;
++ }
++ case Kind_CallExpression: {
++ const auto *ce = AST::cast<const CallExpression*>(node);
++ if (ce->isOptional)
++ return true;
++ node = ce->base;
++ break;
++ }
++ case Kind_NestedExpression: {
++ const auto *ne = AST::cast<const NestedExpression*>(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::CommaExpression *commaExpr = AST::cast<AST::CommaExpression *>(expr)) {
++ f = commaExpr->left->reparseAsFormalParameterList(pool);
++ if (!f)
++ return nullptr;
++
++ f->commaToken = commaExpr->commaToken;
++ 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, /*type annotation*/nullptr, rhs);
++ binding->identifierToken = idExpr->identifierToken;
++ } else if (AST::Pattern *p = expr->patternCast()) {
++ SourceLocation loc;
++ QString s;
++ if (!p->convertLiteralToAssignmentPattern(&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(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(errorLocation, errorMessage))
++ return false;
++ }
++ parseMode = Binding;
++ return true;
++ }
++
++ QList<DiagnosticMessage> ArrayPattern::warningsForAssignments() const
++ {
++ QList<DiagnosticMessage> result;
++ for (auto *it = elements; it; it = it->next) {
++ if (!it->element)
++ continue;
++ result += it->element->warningsForAssignments();
++ }
++ return result;
++ }
++
++ bool ObjectPattern::convertLiteralToAssignmentPattern(SourceLocation *errorLocation, QString *errorMessage)
++ {
++ if (parseMode == Binding)
++ return true;
++ for (auto *it = properties; it; it = it->next) {
++ if (!it->property->convertLiteralToAssignmentPattern(errorLocation, errorMessage))
++ return false;
++ }
++ parseMode = Binding;
++ return true;
++ }
++
++ QList<DiagnosticMessage> ObjectPattern::warningsForAssignments() const
++ {
++ QList<DiagnosticMessage> result;
++ for (auto *it = properties; it; it = it->next)
++ result += it->property->warningsForAssignments();
++ return result;
++ }
++
++ bool PatternElement::convertLiteralToAssignmentPattern(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<IdentifierExpression *>(lhs)) {
++ bindingIdentifier = i->name;
++ identifierToken = i->identifierToken;
++ return true;
++ }
++
++ bindingTarget = lhs;
++ if (auto *p = lhs->patternCast()) {
++ if (!p->convertLiteralToAssignmentPattern(errorLocation, errorMessage))
++ return false;
++ }
++ return true;
++ }
++
++ QList<DiagnosticMessage> PatternElement::warningsForAssignments() const
++ {
++ LeftHandSideExpression *lhs = nullptr;
++
++ if (bindingTarget) {
++ lhs = bindingTarget->leftHandSideExpressionCast();
++ } else if (initializer) {
++ ExpressionNode *init = initializer;
++ if (BinaryExpression *b = init->binaryExpressionCast()) {
++ if (b->op == QSOperator::Assign)
++ lhs = b->left->leftHandSideExpressionCast();
++ }
++ }
++
++ if (!lhs)
++ return { };
++
++ if (auto *p = lhs->patternCast())
++ return p->warningsForAssignments();
++
++ return { };
++ }
++
++ bool PatternProperty::convertLiteralToAssignmentPattern(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(errorLocation, errorMessage);
++ }
++
++ QList<DiagnosticMessage> PatternProperty::warningsForAssignments() const
++ {
++ QList<DiagnosticMessage> result;
++
++ if (!colonToken.isValid()) {
++ if (const BinaryExpression *b =
++ initializer ? initializer->binaryExpressionCast() : nullptr) {
++ if (b->op == QSOperator::Assign) {
++ result.append(QQmlJS::DiagnosticMessage{
++ QString::fromLatin1("Invalid shorthand property initializer"), QtWarningMsg,
++ b->operatorToken });
++ }
++ }
++ }
++
++ result += PatternElement::warningsForAssignments();
++ return result;
++ }
++
++ 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 CommaExpression::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
++ {
++ return *std::min({ &m_propertyToken, &m_defaultToken, &m_readonlyToken, &m_requiredToken,
++ &m_finalToken, &m_virtualToken, &m_overrideToken },
++ compareLocationsByBegin<true>);
++ }
++
++ SourceLocation UiPropertyAttributes::lastSourceLocation() const
++ {
++ return *std::max({ &m_propertyToken, &m_defaultToken, &m_readonlyToken, &m_requiredToken,
++ &m_finalToken, &m_virtualToken, &m_overrideToken },
++ compareLocationsByBegin<false>);
++ }
++
++ } } // namespace QQmlJS::AST
++
++ QT_END_NAMESPACE
++
++