// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:kernel/ast.dart';
import 'package:kernel/src/printer.dart';

import '../base/problems.dart' show unsupported;

import '../type_inference/type_schema.dart';

import 'collections.dart'
    show
        ForElement,
        ForInElement,
        ForInMapEntry,
        ForMapEntry,
        IfCaseElement,
        IfCaseMapEntry,
        IfElement,
        IfMapEntry,
        NullAwareElement,
        NullAwareMapEntry,
        PatternForElement,
        PatternForMapEntry,
        SpreadElement;

import 'internal_ast.dart';

/// A shadow tree factory.
class Forest {
  const Forest();

  ArgumentsImpl createArguments(int fileOffset, List<Expression> positional,
      {List<DartType>? types,
      List<NamedExpression>? named,
      bool hasExplicitTypeArguments = true,
      List<Object?>? argumentsOriginalOrder}) {
    if (!hasExplicitTypeArguments) {
      ArgumentsImpl arguments = new ArgumentsImpl(positional,
          types: <DartType>[],
          named: named,
          argumentsOriginalOrder: argumentsOriginalOrder);
      arguments.types.addAll(types!);
      return arguments;
    } else {
      return new ArgumentsImpl(positional,
          types: types,
          named: named,
          argumentsOriginalOrder: argumentsOriginalOrder)
        ..fileOffset = fileOffset;
    }
  }

  Arguments createArgumentsForExtensionMethod(
      int fileOffset,
      int extensionTypeParameterCount,
      int typeParameterCount,
      Expression receiver,
      {List<DartType> extensionTypeArguments = const <DartType>[],
      int? extensionTypeArgumentOffset,
      List<DartType> typeArguments = const <DartType>[],
      List<Expression> positionalArguments = const <Expression>[],
      List<NamedExpression> namedArguments = const <NamedExpression>[],
      List<Object?>? argumentsOriginalOrder}) {
    return new ArgumentsImpl.forExtensionMethod(
        extensionTypeParameterCount, typeParameterCount, receiver,
        extensionTypeArguments: extensionTypeArguments,
        extensionTypeArgumentOffset: extensionTypeArgumentOffset,
        typeArguments: typeArguments,
        positionalArguments: positionalArguments,
        namedArguments: namedArguments,
        argumentsOriginalOrder: argumentsOriginalOrder)
      ..fileOffset = fileOffset;
  }

  ArgumentsImpl createArgumentsEmpty(int fileOffset) {
    return createArguments(fileOffset, <Expression>[]);
  }

  List<NamedExpression> argumentsNamed(Arguments arguments) {
    return arguments.named;
  }

  List<Expression> argumentsPositional(Arguments arguments) {
    return arguments.positional;
  }

  List<DartType> argumentsTypeArguments(Arguments arguments) {
    return arguments.types;
  }

  void argumentsSetTypeArguments(Arguments arguments, List<DartType> types) {
    ArgumentsImpl.setNonInferrableArgumentTypes(
        arguments as ArgumentsImpl, types);
  }

  /// Return a representation of a boolean literal at the given [fileOffset].
  /// The literal has the given [value].
  BoolLiteral createBoolLiteral(int fileOffset, bool value) {
    return new BoolLiteral(value)..fileOffset = fileOffset;
  }

  /// Return a representation of a double literal at the given [fileOffset]. The
  /// literal has the given [value].
  DoubleLiteral createDoubleLiteral(int fileOffset, double value) {
    return new DoubleLiteral(value)..fileOffset = fileOffset;
  }

  /// Return a representation of an integer literal at the given [fileOffset].
  /// The literal has the given [value].
  IntLiteral createIntLiteral(int fileOffset, int value, [String? literal]) {
    return new IntJudgment(value, literal)..fileOffset = fileOffset;
  }

  IntLiteral createIntLiteralLarge(
      int fileOffset, String strippedLiteral, String literal) {
    return new ShadowLargeIntLiteral(strippedLiteral, literal, fileOffset);
  }

  /// Return a representation of a list literal at the given [fileOffset]. The
  /// [isConst] is `true` if the literal is either explicitly or implicitly a
  /// constant. The [typeArgument] is the representation of the single valid
  /// type argument preceding the list literal, or `null` if there is no type
  /// argument, there is more than one type argument, or if the type argument
  /// cannot be resolved. The list of [expressions] is a list of the
  /// representations of the list elements.
  ListLiteral createListLiteral(
      int fileOffset, DartType typeArgument, List<Expression> expressions,
      {required bool isConst}) {
    return new ListLiteral(expressions,
        typeArgument: typeArgument, isConst: isConst)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of a set literal at the given [fileOffset]. The
  /// [isConst] is `true` if the literal is either explicitly or implicitly a
  /// constant. The [typeArgument] is the representation of the single valid
  /// type argument preceding the set literal, or `null` if there is no type
  /// argument, there is more than one type argument, or if the type argument
  /// cannot be resolved. The list of [expressions] is a list of the
  /// representations of the set elements.
  SetLiteral createSetLiteral(
      int fileOffset, DartType typeArgument, List<Expression> expressions,
      {required bool isConst}) {
    return new SetLiteral(expressions,
        typeArgument: typeArgument, isConst: isConst)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of a map literal at the given [fileOffset]. The
  /// [isConst] is `true` if the literal is either explicitly or implicitly a
  /// constant. The [keyType] is the representation of the first type argument
  /// preceding the map literal, or `null` if there are not exactly two type
  /// arguments or if the first type argument cannot be resolved. The
  /// [valueType] is the representation of the second type argument preceding
  /// the map literal, or `null` if there are not exactly two type arguments or
  /// if the second type argument cannot be resolved. The list of [entries] is a
  /// list of the representations of the map entries.
  MapLiteral createMapLiteral(int fileOffset, DartType keyType,
      DartType valueType, List<MapLiteralEntry> entries,
      {required bool isConst}) {
    return new MapLiteral(entries,
        keyType: keyType, valueType: valueType, isConst: isConst)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of a null literal at the given [fileOffset].
  NullLiteral createNullLiteral(int fileOffset) {
    return new NullLiteral()..fileOffset = fileOffset;
  }

  /// Return a representation of a simple string literal at the given
  /// [fileOffset]. The literal has the given [value]. This does not include
  /// either adjacent strings or interpolated strings.
  StringLiteral createStringLiteral(int fileOffset, String value) {
    return new StringLiteral(value)..fileOffset = fileOffset;
  }

  /// Return a representation of a symbol literal defined by [value] at the
  /// given [fileOffset].
  SymbolLiteral createSymbolLiteral(int fileOffset, String value) {
    return new SymbolLiteral(value)..fileOffset = fileOffset;
  }

  TypeLiteral createTypeLiteral(int fileOffset, DartType type) {
    return new TypeLiteral(type)..fileOffset = fileOffset;
  }

  /// Return a representation of a key/value pair in a literal map at the given
  /// [fileOffset]. The [key] is the representation of the expression used to
  /// compute the key. The [value] is the representation of the expression used
  /// to compute the value.
  MapLiteralEntry createMapEntry(
      int fileOffset, Expression key, Expression value) {
    return new MapLiteralEntry(key, value)..fileOffset = fileOffset;
  }

  /// Return a representation of a null-aware key/value pair, were either the
  /// key or the value might be `null`, in a literal map at the given
  /// [fileOffset]. The [key] is the representation of the expression used to
  /// compute the key. The [value] is the representation of the expression used
  /// to compute the value.
  NullAwareMapEntry createNullAwareMapEntry(int fileOffset,
      {required bool isKeyNullAware,
      required Expression key,
      required bool isValueNullAware,
      required Expression value}) {
    return new NullAwareMapEntry(
        isKeyNullAware: isKeyNullAware,
        key: key,
        isValueNullAware: isValueNullAware,
        value: value)
      ..fileOffset = fileOffset;
  }

  LoadLibrary createLoadLibrary(
      int fileOffset, LibraryDependency dependency, Arguments? arguments) {
    return new LoadLibraryImpl(dependency, arguments)..fileOffset = fileOffset;
  }

  Expression checkLibraryIsLoaded(
      int fileOffset, LibraryDependency dependency) {
    return new CheckLibraryIsLoaded(dependency)..fileOffset = fileOffset;
  }

  Expression createAsExpression(
      int fileOffset, Expression expression, DartType type,
      {bool forDynamic = false}) {
    return new AsExpression(expression, type)
      ..fileOffset = fileOffset
      ..isForDynamic = forDynamic;
  }

  Expression createSpreadElement(int fileOffset, Expression expression,
      {required bool isNullAware}) {
    return new SpreadElement(expression, isNullAware: isNullAware)
      ..fileOffset = fileOffset;
  }

  Expression createNullAwareElement(int fileOffset, Expression expression) {
    return new NullAwareElement(expression)..fileOffset = fileOffset;
  }

  Expression createIfElement(
      int fileOffset, Expression condition, Expression then,
      [Expression? otherwise]) {
    return new IfElement(condition, then, otherwise)..fileOffset = fileOffset;
  }

  Expression createIfCaseElement(int fileOffset,
      {required List<Statement> prelude,
      required Expression expression,
      required PatternGuard patternGuard,
      required Expression then,
      Expression? otherwise}) {
    return new IfCaseElement(
        prelude: prelude,
        expression: expression,
        patternGuard: patternGuard,
        then: then,
        otherwise: otherwise)
      ..fileOffset = fileOffset;
  }

  MapLiteralEntry createIfMapEntry(
      int fileOffset, Expression condition, MapLiteralEntry then,
      [MapLiteralEntry? otherwise]) {
    return new IfMapEntry(condition, then, otherwise)..fileOffset = fileOffset;
  }

  MapLiteralEntry createIfCaseMapEntry(int fileOffset,
      {required List<Statement> prelude,
      required Expression expression,
      required PatternGuard patternGuard,
      required MapLiteralEntry then,
      MapLiteralEntry? otherwise}) {
    return new IfCaseMapEntry(
        prelude: prelude,
        expression: expression,
        patternGuard: patternGuard,
        then: then,
        otherwise: otherwise)
      ..fileOffset = fileOffset;
  }

  ForElement createForElement(
      int fileOffset,
      List<VariableDeclaration> variables,
      Expression? condition,
      List<Expression> updates,
      Expression body) {
    return new ForElement(variables, condition, updates, body)
      ..fileOffset = fileOffset;
  }

  PatternForElement createPatternForElement(int fileOffset,
      {required PatternVariableDeclaration patternVariableDeclaration,
      required List<VariableDeclaration> intermediateVariables,
      required List<VariableDeclaration> variables,
      required Expression? condition,
      required List<Expression> updates,
      required Expression body}) {
    return new PatternForElement(
        patternVariableDeclaration: patternVariableDeclaration,
        intermediateVariables: intermediateVariables,
        variables: variables,
        condition: condition,
        updates: updates,
        body: body)
      ..fileOffset = fileOffset;
  }

  ForMapEntry createForMapEntry(
      int fileOffset,
      List<VariableDeclaration> variables,
      Expression? condition,
      List<Expression> updates,
      MapLiteralEntry body) {
    return new ForMapEntry(variables, condition, updates, body)
      ..fileOffset = fileOffset;
  }

  PatternForMapEntry createPatternForMapEntry(int fileOffset,
      {required PatternVariableDeclaration patternVariableDeclaration,
      required List<VariableDeclaration> intermediateVariables,
      required List<VariableDeclaration> variables,
      required Expression? condition,
      required List<Expression> updates,
      required MapLiteralEntry body}) {
    return new PatternForMapEntry(
        patternVariableDeclaration: patternVariableDeclaration,
        intermediateVariables: intermediateVariables,
        variables: variables,
        condition: condition,
        updates: updates,
        body: body)
      ..fileOffset = fileOffset;
  }

  ForInElement createForInElement(
      int fileOffset,
      VariableDeclaration variable,
      Expression iterable,
      Expression? synthesizedAssignment,
      Statement? expressionEffects,
      Expression body,
      Expression? problem,
      {bool isAsync = false}) {
    return new ForInElement(variable, iterable, synthesizedAssignment,
        expressionEffects, body, problem,
        isAsync: isAsync)
      ..fileOffset = fileOffset;
  }

  ForInMapEntry createForInMapEntry(
      int fileOffset,
      VariableDeclaration variable,
      Expression iterable,
      Expression? synthesizedAssignment,
      Statement? expressionEffects,
      MapLiteralEntry body,
      Expression? problem,
      {bool isAsync = false}) {
    return new ForInMapEntry(variable, iterable, synthesizedAssignment,
        expressionEffects, body, problem,
        isAsync: isAsync)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of an assert that appears in a constructor's
  /// initializer list.
  AssertInitializer createAssertInitializer(
      int fileOffset, AssertStatement assertStatement) {
    return new AssertInitializer(assertStatement)..fileOffset = fileOffset;
  }

  /// Return a representation of an assert that appears as a statement.
  AssertStatement createAssertStatement(int fileOffset, Expression condition,
      Expression? message, int conditionStartOffset, int conditionEndOffset) {
    return new AssertStatement(condition,
        conditionStartOffset: conditionStartOffset,
        conditionEndOffset: conditionEndOffset,
        message: message)
      ..fileOffset = fileOffset;
  }

  Expression createAwaitExpression(int fileOffset, Expression operand) {
    return new AwaitExpression(operand)..fileOffset = fileOffset;
  }

  /// Return a representation of a block of [statements] at the given
  /// [fileOffset].
  Block createBlock(
      int fileOffset, int fileEndOffset, List<Statement> statements) {
    List<Statement>? copy;
    for (int i = 0; i < statements.length; i++) {
      Statement statement = statements[i];
      if (statement is _VariablesDeclaration) {
        copy ??= new List<Statement>.of(statements.getRange(0, i));
        copy.addAll(statement.declarations);
      } else if (copy != null) {
        copy.add(statement);
      }
    }
    return new Block(copy ?? statements)
      ..fileOffset = fileOffset
      ..fileEndOffset = fileEndOffset;
  }

  /// Return a representation of a break statement.
  Statement createBreakStatement(int fileOffset, Object? label) {
    // TODO(johnniwinther): Use [label]?
    return new BreakStatementImpl(isContinue: false)
      ..fileOffset = fileOffset
      ..target = label is LabeledStatement ? label : dummyLabeledStatement;
  }

  /// Return a representation of a catch clause.
  Catch createCatch(
      int fileOffset,
      DartType exceptionType,
      VariableDeclaration? exceptionParameter,
      VariableDeclaration? stackTraceParameter,
      DartType stackTraceType,
      Statement body) {
    return new Catch(exceptionParameter, body,
        guard: exceptionType, stackTrace: stackTraceParameter)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of a conditional expression at the given
  /// [fileOffset]. The [condition] is the expression preceding the question
  /// mark. The [thenExpression] is the expression following the question mark.
  /// The [elseExpression] is the expression following the colon.
  ConditionalExpression createConditionalExpression(
      int fileOffset,
      Expression condition,
      Expression thenExpression,
      Expression elseExpression) {
    return new ConditionalExpression(
        condition, thenExpression, elseExpression, const UnknownType())
      ..fileOffset = fileOffset;
  }

  /// Return a representation of a continue statement.
  Statement createContinueStatement(int fileOffset, Object? label) {
    // TODO(johnniwinther): Use [label]?
    return new BreakStatementImpl(isContinue: true)..fileOffset = fileOffset;
  }

  /// Return a representation of a do statement.
  Statement createDoStatement(
      int fileOffset, Statement body, Expression condition) {
    return new DoStatement(body, condition)..fileOffset = fileOffset;
  }

  /// Return a representation of an expression statement at the given
  /// [fileOffset] containing the [expression].
  Statement createExpressionStatement(int fileOffset, Expression expression) {
    return new ExpressionStatement(expression)..fileOffset = fileOffset;
  }

  /// Return a representation of an empty statement  at the given [fileOffset].
  Statement createEmptyStatement(int fileOffset) {
    return new EmptyStatement()..fileOffset = fileOffset;
  }

  /// Return a representation of a for statement.
  Statement createForStatement(
      int fileOffset,
      List<VariableDeclaration>? variables,
      Expression? condition,
      List<Expression> updaters,
      Statement body) {
    return new ForStatement(
        variables ?? // Coverage-ignore(suite): Not run.
            [],
        condition,
        updaters,
        body)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of an `if` statement.
  Statement createIfStatement(int fileOffset, Expression condition,
      Statement thenStatement, Statement? elseStatement) {
    return new IfStatement(condition, thenStatement, elseStatement)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of an `is` expression at the given [fileOffset].
  /// The [operand] is the representation of the left operand. The [type] is a
  /// representation of the type that is the right operand. If [notFileOffset]
  /// is non-null the test is negated the that file offset.
  Expression createIsExpression(
      int fileOffset, Expression operand, DartType type,
      {int? notFileOffset}) {
    Expression result = new IsExpression(operand, type)
      ..fileOffset = fileOffset;
    if (notFileOffset != null) {
      result = createNot(notFileOffset, result);
    }
    return result;
  }

  /// Return a representation of a logical expression at the given [fileOffset]
  /// having the [leftOperand], [rightOperand] and the [operatorString]
  /// (either `&&` or `||`).
  Expression createLogicalExpression(int fileOffset, Expression leftOperand,
      String operatorString, Expression rightOperand) {
    LogicalExpressionOperator operator;
    if (operatorString == '&&') {
      operator = LogicalExpressionOperator.AND;
    } else if (operatorString == '||') {
      operator = LogicalExpressionOperator.OR;
    } else {
      throw new UnsupportedError(
          "Unhandled logical operator '$operatorString'");
    }

    return new LogicalExpression(leftOperand, operator, rightOperand)
      ..fileOffset = fileOffset;
  }

  Expression createNot(int fileOffset, Expression operand) {
    return new Not(operand)..fileOffset = fileOffset;
  }

  /// Return a representation of a rethrow statement consisting of the
  /// rethrow at [rethrowFileOffset] and the statement at [statementFileOffset].
  Statement createRethrowStatement(
      int rethrowFileOffset, int statementFileOffset) {
    return new ExpressionStatement(
        new Rethrow()..fileOffset = rethrowFileOffset)
      ..fileOffset = statementFileOffset;
  }

  /// Return a representation of a return statement.
  Statement createReturnStatement(int fileOffset, Expression? expression,
      {bool isArrow = true}) {
    return new ReturnStatementImpl(isArrow, expression)
      ..fileOffset = fileOffset;
  }

  Expression createStringConcatenation(
      int fileOffset, List<Expression> expressions) {
    assert(fileOffset != TreeNode.noOffset);
    return new StringConcatenation(expressions)..fileOffset = fileOffset;
  }

  /// The given [statement] is being used as the target of either a break or
  /// continue statement. Return the statement that should be used as the actual
  /// target.
  LabeledStatement createLabeledStatement(Statement statement) {
    return new LabeledStatement(statement)..fileOffset = statement.fileOffset;
  }

  Expression createThisExpression(int fileOffset) {
    return new ThisExpression()..fileOffset = fileOffset;
  }

  /// Return a representation of a throw expression at the given [fileOffset].
  Expression createThrow(int fileOffset, Expression expression) {
    return new Throw(expression)..fileOffset = fileOffset;
  }

  bool isThrow(Object? o) => o is Throw;

  Statement createTryStatement(int fileOffset, Statement tryBlock,
      List<Catch>? catchBlocks, Statement? finallyBlock) {
    return new TryStatement(tryBlock, catchBlocks ?? <Catch>[], finallyBlock)
      ..fileOffset = fileOffset;
  }

  _VariablesDeclaration variablesDeclaration(
      List<VariableDeclaration> declarations, Uri uri) {
    return new _VariablesDeclaration(declarations, uri);
  }

  List<VariableDeclaration> variablesDeclarationExtractDeclarations(
      Object? variablesDeclaration) {
    return (variablesDeclaration as _VariablesDeclaration).declarations;
  }

  Statement wrapVariables(Statement statement) {
    if (statement is _VariablesDeclaration) {
      return new Block(
          new List<Statement>.of(statement.declarations, growable: true))
        ..fileOffset = statement.fileOffset;
    } else if (statement is VariableDeclaration) {
      return new Block(<Statement>[statement])
        ..fileOffset = statement.fileOffset;
    } else {
      return statement;
    }
  }

  /// Return a representation of a while statement at the given [fileOffset]
  /// consisting of the given [condition] and [body].
  Statement createWhileStatement(
      int fileOffset, Expression condition, Statement body) {
    return new WhileStatement(condition, body)..fileOffset = fileOffset;
  }

  /// Return a representation of a yield statement at the given [fileOffset]
  /// of the given [expression]. If [isYieldStar] is `true` the created
  /// statement is a yield* statement.
  Statement createYieldStatement(int fileOffset, Expression expression,
      {required bool isYieldStar}) {
    return new YieldStatement(expression, isYieldStar: isYieldStar)
      ..fileOffset = fileOffset;
  }

  bool isErroneousNode(Object? node) {
    if (node is ExpressionStatement) {
      // Coverage-ignore-block(suite): Not run.
      ExpressionStatement statement = node;
      node = statement.expression;
    }
    if (node is VariableDeclaration) {
      // Coverage-ignore-block(suite): Not run.
      VariableDeclaration variable = node;
      node = variable.initializer;
    }
    if (node is Let) {
      // Coverage-ignore-block(suite): Not run.
      Let let = node;
      node = let.variable.initializer;
    }
    return node is InvalidExpression;
  }

  bool isThisExpression(Object node) => node is ThisExpression;

  bool isVariablesDeclaration(Object? node) => node is _VariablesDeclaration;

  /// Creates [VariableDeclaration] for a variable named [name] at the given
  /// [functionNestingLevel].
  VariableDeclaration createVariableDeclaration(int fileOffset, String? name,
      {Expression? initializer,
      DartType? type,
      bool isFinal = false,
      bool isConst = false,
      bool isInitializingFormal = false,
      bool isSuperInitializingFormal = false,
      bool isCovariantByDeclaration = false,
      bool isLocalFunction = false,
      bool isSynthesized = false}) {
    return new VariableDeclarationImpl(name,
        type: type,
        initializer: initializer,
        isFinal: isFinal,
        isConst: isConst,
        isInitializingFormal: isInitializingFormal,
        isSuperInitializingFormal: isSuperInitializingFormal,
        isCovariantByDeclaration: isCovariantByDeclaration,
        isLocalFunction: isLocalFunction,
        isSynthesized: isSynthesized,
        hasDeclaredInitializer: initializer != null)
      ..fileOffset = fileOffset;
  }

  VariableDeclarationImpl createVariableDeclarationForValue(
      Expression initializer,
      {DartType type = const DynamicType()}) {
    return new VariableDeclarationImpl.forValue(initializer)
      ..type = type
      ..fileOffset = initializer.fileOffset;
  }

  TypeParameterType createTypeParameterTypeWithDefaultNullabilityForLibrary(
      TypeParameter typeParameter, Library library) {
    return new TypeParameterType.withDefaultNullability(typeParameter);
  }

  Expression createExpressionInvocation(
      int fileOffset, Expression expression, Arguments arguments) {
    return new ExpressionInvocation(expression, arguments)
      ..fileOffset = fileOffset;
  }

  Expression createMethodInvocation(
      int fileOffset, Expression expression, Name name, Arguments arguments,
      {required bool isNullAware}) {
    return new MethodInvocation(expression, name, arguments,
        isNullAware: isNullAware)
      ..fileOffset = fileOffset;
  }

  SuperMethodInvocation createSuperMethodInvocation(
      int fileOffset, Name name, Procedure procedure, Arguments arguments) {
    return new SuperMethodInvocation(name, arguments, procedure)
      ..fileOffset = fileOffset;
  }

  NullCheck createNullCheck(int fileOffset, Expression expression) {
    return new NullCheck(expression)..fileOffset = fileOffset;
  }

  Expression createPropertyGet(int fileOffset, Expression receiver, Name name,
      {required bool isNullAware}) {
    return new PropertyGet(receiver, name, isNullAware: isNullAware)
      ..fileOffset = fileOffset;
  }

  Expression createPropertySet(
      int fileOffset, Expression receiver, Name name, Expression value,
      {required bool forEffect,
      bool readOnlyReceiver = false,
      required bool isNullAware}) {
    return new PropertySet(receiver, name, value,
        forEffect: forEffect,
        readOnlyReceiver: readOnlyReceiver,
        isNullAware: isNullAware)
      ..fileOffset = fileOffset;
  }

  IndexGet createIndexGet(int fileOffset, Expression receiver, Expression index,
      {required bool isNullAware}) {
    return new IndexGet(receiver, index, isNullAware: isNullAware)
      ..fileOffset = fileOffset;
  }

  IndexSet createIndexSet(
      int fileOffset, Expression receiver, Expression index, Expression value,
      {required bool forEffect, required bool isNullAware}) {
    return new IndexSet(receiver, index, value,
        forEffect: forEffect, isNullAware: isNullAware)
      ..fileOffset = fileOffset;
  }

  VariableGet createVariableGet(int fileOffset, VariableDeclaration variable) {
    return new VariableGetImpl(variable, forNullGuardedAccess: false)
      ..fileOffset = fileOffset;
  }

  EqualsExpression createEquals(
      int fileOffset, Expression left, Expression right,
      {required bool isNot}) {
    return new EqualsExpression(left, right, isNot: isNot)
      ..fileOffset = fileOffset;
  }

  BinaryExpression createBinary(
      int fileOffset, Expression left, Name binaryName, Expression right) {
    return new BinaryExpression(left, binaryName, right)
      ..fileOffset = fileOffset;
  }

  UnaryExpression createUnary(
      int fileOffset, Name unaryName, Expression expression) {
    return new UnaryExpression(unaryName, expression)..fileOffset = fileOffset;
  }

  ParenthesizedExpression createParenthesized(
      int fileOffset, Expression expression) {
    return new ParenthesizedExpression(expression)..fileOffset = fileOffset;
  }

  ConstructorTearOff createConstructorTearOff(int fileOffset, Member target) {
    assert(target is Constructor || (target is Procedure && target.isFactory),
        "Unexpected constructor tear off target: $target");
    return new ConstructorTearOff(target)..fileOffset = fileOffset;
  }

  StaticTearOff createStaticTearOff(int fileOffset, Procedure procedure) {
    assert(procedure.kind == ProcedureKind.Method,
        "Unexpected static tear off target: $procedure");
    assert(!procedure.isRedirectingFactory,
        "Unexpected static tear off target: $procedure");
    return new StaticTearOff(procedure)..fileOffset = fileOffset;
  }

  StaticGet createStaticGet(int fileOffset, Member target) {
    assert(target is Field || (target is Procedure && target.isGetter));
    return new StaticGet(target)..fileOffset = fileOffset;
  }

  RedirectingFactoryTearOff createRedirectingFactoryTearOff(
      int fileOffset, Procedure procedure) {
    assert(procedure.isRedirectingFactory);
    return new RedirectingFactoryTearOff(procedure)..fileOffset = fileOffset;
  }

  Instantiation createInstantiation(
      int fileOffset, Expression expression, List<DartType> typeArguments) {
    return new Instantiation(expression, typeArguments)
      ..fileOffset = fileOffset;
  }

  TypedefTearOff createTypedefTearOff(
      int fileOffset,
      List<StructuralParameter> typeParameters,
      Expression expression,
      List<DartType> typeArguments) {
    return new TypedefTearOff(typeParameters, expression, typeArguments)
      ..fileOffset = fileOffset;
  }

  AndPattern createAndPattern(int fileOffset, Pattern left, Pattern right) {
    return new AndPattern(left, right)..fileOffset = fileOffset;
  }

  AssignedVariablePattern createAssignedVariablePattern(
      int fileOffset, VariableDeclaration variable) {
    return new AssignedVariablePattern(variable)..fileOffset = fileOffset;
  }

  CastPattern createCastPattern(
      int fileOffset, Pattern pattern, DartType type) {
    return new CastPattern(pattern, type)..fileOffset = fileOffset;
  }

  ConstantPattern createConstantPattern(Expression expression) {
    return new ConstantPattern(expression)..fileOffset = expression.fileOffset;
  }

  InvalidPattern createInvalidPattern(Expression expression,
      {required List<VariableDeclaration> declaredVariables}) {
    return new InvalidPattern(expression, declaredVariables: declaredVariables)
      ..fileOffset = expression.fileOffset;
  }

  ListPattern createListPattern(
      int fileOffset, DartType? typeArgument, List<Pattern> patterns) {
    return new ListPattern(typeArgument, patterns)..fileOffset = fileOffset;
  }

  MapPattern createMapPattern(int fileOffset, DartType? keyType,
      DartType? valueType, List<MapPatternEntry> entries) {
    return new MapPattern(keyType, valueType, entries)..fileOffset = fileOffset;
  }

  MapPatternEntry createMapPatternEntry(
      int fileOffset, Expression key, Pattern value) {
    return new MapPatternEntry(key, value)..fileOffset = fileOffset;
  }

  MapPatternRestEntry createMapPatternRestEntry(int fileOffset) {
    return new MapPatternRestEntry()..fileOffset = fileOffset;
  }

  NamedPattern createNamedPattern(
      int fileOffset, String name, Pattern pattern) {
    return new NamedPattern(name, pattern)..fileOffset = fileOffset;
  }

  NullAssertPattern createNullAssertPattern(int fileOffset, Pattern pattern) {
    return new NullAssertPattern(pattern)..fileOffset = fileOffset;
  }

  NullCheckPattern createNullCheckPattern(int fileOffset, Pattern pattern) {
    return new NullCheckPattern(pattern)..fileOffset = fileOffset;
  }

  OrPattern createOrPattern(int fileOffset, Pattern left, Pattern right,
      {required List<VariableDeclaration> orPatternJointVariables}) {
    return new OrPattern(left, right,
        orPatternJointVariables: orPatternJointVariables)
      ..fileOffset = fileOffset;
  }

  RecordPattern createRecordPattern(int fileOffset, List<Pattern> patterns) {
    return new RecordPattern(patterns)..fileOffset = fileOffset;
  }

  RelationalPattern createRelationalPattern(
      int fileOffset, RelationalPatternKind kind, Expression expression) {
    return new RelationalPattern(kind, expression)..fileOffset = fileOffset;
  }

  RestPattern createRestPattern(int fileOffset, Pattern? subPattern) {
    return new RestPattern(subPattern)..fileOffset = fileOffset;
  }

  VariablePattern createVariablePattern(
      int fileOffset, DartType? type, VariableDeclaration variable) {
    return new VariablePattern(type, variable)..fileOffset = fileOffset;
  }

  WildcardPattern createWildcardPattern(int fileOffset, DartType? type) {
    return new WildcardPattern(type)..fileOffset = fileOffset;
  }

  PatternGuard createPatternGuard(int fileOffset, Pattern pattern,
      [Expression? guard]) {
    return new PatternGuard(pattern, guard)..fileOffset = fileOffset;
  }

  PatternSwitchCase createPatternSwitchCase(int fileOffset,
      List<int> caseOffsets, List<PatternGuard> patternGuards, Statement body,
      {required bool isDefault,
      required bool hasLabel,
      required List<VariableDeclaration> jointVariables,
      required List<int>? jointVariableFirstUseOffsets}) {
    return new PatternSwitchCase(caseOffsets, patternGuards, body,
        isDefault: isDefault,
        hasLabel: hasLabel,
        jointVariables: jointVariables,
        jointVariableFirstUseOffsets: jointVariableFirstUseOffsets)
      ..fileOffset = fileOffset;
  }

  PatternSwitchStatement createPatternSwitchStatement(
      int fileOffset, Expression expression, List<PatternSwitchCase> cases) {
    return new PatternSwitchStatement(expression, cases)
      ..fileOffset = fileOffset;
  }

  SwitchExpressionCase createSwitchExpressionCase(
      int fileOffset, PatternGuard patternGuard, Expression expression) {
    return new SwitchExpressionCase(patternGuard, expression)
      ..fileOffset = fileOffset;
  }

  SwitchExpression createSwitchExpression(
      int fileOffset, Expression expression, List<SwitchExpressionCase> cases) {
    return new SwitchExpression(expression, cases)..fileOffset = fileOffset;
  }

  PatternVariableDeclaration createPatternVariableDeclaration(
      int fileOffset, Pattern pattern, Expression initializer,
      {required bool isFinal}) {
    return new PatternVariableDeclaration(pattern, initializer,
        isFinal: isFinal)
      ..fileOffset = fileOffset;
  }

  PatternAssignment createPatternAssignment(
      int fileOffset, Pattern pattern, Expression expression) {
    return new PatternAssignment(pattern, expression)..fileOffset = fileOffset;
  }

  IfCaseStatement createIfCaseStatement(int fileOffset, Expression expression,
      PatternGuard patternGuard, Statement then, Statement? otherwise) {
    return new IfCaseStatement(expression, patternGuard, then, otherwise)
      ..fileOffset = fileOffset;
  }

  DotShorthand createDotShorthandContext(
      int fileOffset, Expression innerExpression) {
    return new DotShorthand(innerExpression)..fileOffset = fileOffset;
  }

  DotShorthandInvocation createDotShorthandInvocation(
      int fileOffset, Name name, Arguments arguments,
      {required int nameOffset, required bool isConst}) {
    return new DotShorthandInvocation(
      name,
      arguments,
      nameOffset: nameOffset,
      isConst: isConst,
    )..fileOffset = fileOffset;
  }

  DotShorthandPropertyGet createDotShorthandPropertyGet(
      int fileOffset, Name name,
      {required int nameOffset}) {
    return new DotShorthandPropertyGet(name, nameOffset: nameOffset)
      ..fileOffset = fileOffset;
  }
}

class _VariablesDeclaration extends AuxiliaryStatement {
  final List<VariableDeclaration> declarations;
  final Uri uri;

  _VariablesDeclaration(this.declarations, this.uri) {
    setParents(declarations, this);
  }

  @override
  // Coverage-ignore(suite): Not run.
  R accept<R>(v) {
    throw unsupported("accept", fileOffset, uri);
  }

  @override
  // Coverage-ignore(suite): Not run.
  R accept1<R, A>(v, arg) {
    throw unsupported("accept1", fileOffset, uri);
  }

  @override
  // Coverage-ignore(suite): Not run.
  Never visitChildren(v) {
    throw unsupported("visitChildren", fileOffset, uri);
  }

  @override
  // Coverage-ignore(suite): Not run.
  Never transformChildren(v) {
    throw unsupported("transformChildren", fileOffset, uri);
  }

  @override
  // Coverage-ignore(suite): Not run.
  Never transformOrRemoveChildren(v) {
    throw unsupported("transformOrRemoveChildren", fileOffset, uri);
  }

  @override
  String toString() {
    return "_VariablesDeclaration(${toStringInternal()})";
  }

  @override
  // Coverage-ignore(suite): Not run.
  void toTextInternal(AstPrinter printer) {
    for (int index = 0; index < declarations.length; index++) {
      if (index > 0) {
        printer.write(', ');
      }
      printer.writeVariableDeclaration(declarations[index],
          includeModifiersAndType: index == 0);
    }
    printer.write(';');
  }
}
