// Copyright (c) 2016, 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.

library kernel.clone;

import 'ast.dart';
import 'type_algebra.dart';

/// Visitor that return a clone of a tree, maintaining references to cloned
/// objects.
///
/// This class does not clone members. For that, use the
/// [CloneVisitorWithMembers] and setup references properly.
class CloneVisitorNotMembers implements TreeVisitor<TreeNode> {
  final Map<VariableDeclaration, VariableDeclaration> _variables =
      <VariableDeclaration, VariableDeclaration>{};
  final Map<LabeledStatement, LabeledStatement> labels =
      <LabeledStatement, LabeledStatement>{};
  final Map<SwitchCase, SwitchCase> switchCases = <SwitchCase, SwitchCase>{};
  final Map<TypeParameter, DartType> typeSubstitution;
  final Map<TypeParameter, TypeParameter> typeParams;
  bool cloneAnnotations;

  /// Creates an instance of the cloning visitor for Kernel ASTs.
  ///
  /// The boolean value of [cloneAnnotations] tells if the annotations on the
  /// outline elements in the source AST should be cloned to the target AST. The
  /// annotations in procedure bodies are cloned unconditionally.
  CloneVisitorNotMembers(
      {Map<TypeParameter, DartType>? typeSubstitution,
      Map<TypeParameter, TypeParameter>? typeParams,
      this.cloneAnnotations = true})
      : this.typeSubstitution = ensureMutable(typeSubstitution),
        this.typeParams = typeParams ?? <TypeParameter, TypeParameter>{};

  static Map<TypeParameter, DartType> ensureMutable(
      Map<TypeParameter, DartType>? map) {
    // We need to mutate this map, so make sure we don't use a constant map.
    if (map == null || map.isEmpty) {
      return <TypeParameter, DartType>{};
    }
    return map;
  }

  /// Returns the clone of [variable] or `null` if no clone has been created
  /// for variable.
  VariableDeclaration? getVariableClone(VariableDeclaration variable) {
    return _variables[variable];
  }

  /// Registers [clone] as the clone for [variable].
  ///
  /// Returns the [clone].
  VariableDeclaration setVariableClone(
      VariableDeclaration variable, VariableDeclaration clone) {
    return _variables[variable] = clone;
  }

  @override
  TreeNode visitLibrary(Library node) {
    throw 'Cloning of libraries is not implemented';
  }

  @override
  TreeNode visitClass(Class node) {
    throw 'Cloning of classes is not implemented';
  }

  @override
  TreeNode visitExtension(Extension node) {
    throw 'Cloning of extensions is not implemented';
  }

  @override
  TreeNode visitConstructor(Constructor node) {
    throw 'Cloning of constructors is not implemented here';
  }

  @override
  TreeNode visitProcedure(Procedure node) {
    throw 'Cloning of procedures is not implemented here';
  }

  @override
  TreeNode visitField(Field node) {
    throw 'Cloning of fields is not implemented here';
  }

  @override
  TreeNode visitRedirectingFactory(RedirectingFactory node) {
    throw 'Cloning of redirecting factory constructors is not implemented here';
  }

  // The currently active file uri where we are cloning [TreeNode]s from.  If
  // this is set to `null` we cannot clone file offsets to newly created nodes.
  // The [_cloneFileOffset] helper function will ensure this.
  Uri? _activeFileUri;

  // If we don't know the file uri we are cloning elements from, it's not safe
  // to clone file offsets either.
  int _cloneFileOffset(int fileOffset) {
    return _activeFileUri == null ? TreeNode.noOffset : fileOffset;
  }

  T clone<T extends TreeNode>(T node) {
    final Uri? activeFileUriSaved = _activeFileUri;
    if (node is FileUriNode) {
      _activeFileUri = node.fileUri;
    }
    final TreeNode result = node.accept(this)
      ..fileOffset = _cloneFileOffset(node.fileOffset);
    _activeFileUri = activeFileUriSaved;
    return result as T;
  }

  T? cloneOptional<T extends TreeNode>(T? node) {
    if (node == null) return null;
    final Uri? activeFileUriSaved = _activeFileUri;
    if (node is FileUriNode) {
      _activeFileUri = node.fileUri;
    }
    TreeNode? result = node.accept(this);
    if (result != null) result.fileOffset = _cloneFileOffset(node.fileOffset);
    _activeFileUri = activeFileUriSaved;
    return result as T?;
  }

  /// Root entry point for cloning a subtree within the same context where the
  /// file offsets are valid.
  T cloneInContext<T extends TreeNode>(T node) {
    assert(_activeFileUri == null);
    _activeFileUri = _activeFileUriFromContext(node);
    final TreeNode result = clone<T>(node);
    _activeFileUri = null;
    return result as T;
  }

  Uri? _activeFileUriFromContext(TreeNode? node) {
    while (node != null) {
      if (node is FileUriNode) {
        return node.fileUri;
      }
      node = node.parent;
    }
    return null;
  }

  DartType visitType(DartType type) {
    return substitute(type, typeSubstitution);
  }

  Constant visitConstant(Constant constant) {
    return constant;
  }

  DartType? visitOptionalType(DartType? type) {
    return type == null ? null : substitute(type, typeSubstitution);
  }

  @override
  TreeNode visitInvalidExpression(InvalidExpression node) {
    return new InvalidExpression(
        node.message, node.expression != null ? clone(node.expression!) : null);
  }

  @override
  TreeNode visitVariableGet(VariableGet node) {
    return new VariableGet(
        getVariableClone(node.variable)!, visitOptionalType(node.promotedType));
  }

  @override
  TreeNode visitVariableSet(VariableSet node) {
    return new VariableSet(getVariableClone(node.variable)!, clone(node.value));
  }

  @override
  TreeNode visitAbstractSuperPropertyGet(AbstractSuperPropertyGet node) {
    return new AbstractSuperPropertyGet.byReference(
        node.name, node.interfaceTargetReference);
  }

  @override
  TreeNode visitAbstractSuperPropertySet(AbstractSuperPropertySet node) {
    return new AbstractSuperPropertySet.byReference(
        node.name, clone(node.value), node.interfaceTargetReference);
  }

  @override
  TreeNode visitSuperPropertyGet(SuperPropertyGet node) {
    return new SuperPropertyGet.byReference(
        node.name, node.interfaceTargetReference);
  }

  @override
  TreeNode visitSuperPropertySet(SuperPropertySet node) {
    return new SuperPropertySet.byReference(
        node.name, clone(node.value), node.interfaceTargetReference);
  }

  @override
  TreeNode visitStaticGet(StaticGet node) {
    return new StaticGet.byReference(node.targetReference);
  }

  @override
  TreeNode visitStaticSet(StaticSet node) {
    return new StaticSet.byReference(node.targetReference, clone(node.value));
  }

  @override
  TreeNode visitAbstractSuperMethodInvocation(
      AbstractSuperMethodInvocation node) {
    return new AbstractSuperMethodInvocation.byReference(
        node.name, clone(node.arguments), node.interfaceTargetReference);
  }

  @override
  TreeNode visitSuperMethodInvocation(SuperMethodInvocation node) {
    return new SuperMethodInvocation.byReference(
        node.name, clone(node.arguments), node.interfaceTargetReference);
  }

  @override
  TreeNode visitStaticInvocation(StaticInvocation node) {
    return new StaticInvocation.byReference(
        node.targetReference, clone(node.arguments),
        isConst: node.isConst);
  }

  @override
  TreeNode visitConstructorInvocation(ConstructorInvocation node) {
    return new ConstructorInvocation.byReference(
        node.targetReference, clone(node.arguments),
        isConst: node.isConst);
  }

  @override
  TreeNode visitNot(Not node) {
    return new Not(clone(node.operand));
  }

  @override
  TreeNode visitNullCheck(NullCheck node) {
    return new NullCheck(clone(node.operand));
  }

  @override
  TreeNode visitLogicalExpression(LogicalExpression node) {
    return new LogicalExpression(
        clone(node.left), node.operatorEnum, clone(node.right));
  }

  @override
  TreeNode visitConditionalExpression(ConditionalExpression node) {
    return new ConditionalExpression(clone(node.condition), clone(node.then),
        clone(node.otherwise), visitType(node.staticType));
  }

  @override
  TreeNode visitStringConcatenation(StringConcatenation node) {
    return new StringConcatenation(node.expressions.map(clone).toList());
  }

  @override
  TreeNode visitListConcatenation(ListConcatenation node) {
    return new ListConcatenation(node.lists.map(clone).toList(),
        typeArgument: visitType(node.typeArgument));
  }

  @override
  TreeNode visitSetConcatenation(SetConcatenation node) {
    return new SetConcatenation(node.sets.map(clone).toList(),
        typeArgument: visitType(node.typeArgument));
  }

  @override
  TreeNode visitMapConcatenation(MapConcatenation node) {
    return new MapConcatenation(node.maps.map(clone).toList(),
        keyType: visitType(node.keyType), valueType: visitType(node.valueType));
  }

  @override
  TreeNode visitInstanceCreation(InstanceCreation node) {
    final Map<Reference, Expression> fieldValues = <Reference, Expression>{};
    node.fieldValues.forEach((Reference fieldRef, Expression value) {
      fieldValues[fieldRef] = clone(value);
    });
    return new InstanceCreation(
        node.classReference,
        node.typeArguments.map(visitType).toList(),
        fieldValues,
        node.asserts.map(clone).toList(),
        node.unusedArguments.map(clone).toList());
  }

  @override
  TreeNode visitFileUriExpression(FileUriExpression node) {
    return new FileUriExpression(clone(node.expression), _activeFileUri!);
  }

  @override
  TreeNode visitIsExpression(IsExpression node) {
    return new IsExpression(clone(node.operand), visitType(node.type))
      ..flags = node.flags;
  }

  @override
  TreeNode visitAsExpression(AsExpression node) {
    return new AsExpression(clone(node.operand), visitType(node.type))
      ..flags = node.flags;
  }

  @override
  TreeNode visitSymbolLiteral(SymbolLiteral node) {
    return new SymbolLiteral(node.value);
  }

  @override
  TreeNode visitTypeLiteral(TypeLiteral node) {
    return new TypeLiteral(visitType(node.type));
  }

  @override
  TreeNode visitThisExpression(ThisExpression node) {
    return new ThisExpression();
  }

  @override
  TreeNode visitRethrow(Rethrow node) {
    return new Rethrow();
  }

  @override
  TreeNode visitThrow(Throw node) {
    return new Throw(clone(node.expression));
  }

  @override
  TreeNode visitListLiteral(ListLiteral node) {
    return new ListLiteral(node.expressions.map(clone).toList(),
        typeArgument: visitType(node.typeArgument), isConst: node.isConst);
  }

  @override
  TreeNode visitSetLiteral(SetLiteral node) {
    return new SetLiteral(node.expressions.map(clone).toList(),
        typeArgument: visitType(node.typeArgument), isConst: node.isConst);
  }

  @override
  TreeNode visitMapLiteral(MapLiteral node) {
    return new MapLiteral(node.entries.map(clone).toList(),
        keyType: visitType(node.keyType),
        valueType: visitType(node.valueType),
        isConst: node.isConst);
  }

  @override
  TreeNode visitMapLiteralEntry(MapLiteralEntry node) {
    return new MapLiteralEntry(clone(node.key), clone(node.value));
  }

  @override
  TreeNode visitAwaitExpression(AwaitExpression node) {
    return new AwaitExpression(clone(node.operand));
  }

  @override
  TreeNode visitFunctionExpression(FunctionExpression node) {
    return new FunctionExpression(clone(node.function));
  }

  @override
  TreeNode visitConstantExpression(ConstantExpression node) {
    return new ConstantExpression(
        visitConstant(node.constant), visitType(node.type));
  }

  @override
  TreeNode visitStringLiteral(StringLiteral node) {
    return new StringLiteral(node.value);
  }

  @override
  TreeNode visitIntLiteral(IntLiteral node) {
    return new IntLiteral(node.value);
  }

  @override
  TreeNode visitDoubleLiteral(DoubleLiteral node) {
    return new DoubleLiteral(node.value);
  }

  @override
  TreeNode visitBoolLiteral(BoolLiteral node) {
    return new BoolLiteral(node.value);
  }

  @override
  TreeNode visitNullLiteral(NullLiteral node) {
    return new NullLiteral();
  }

  @override
  TreeNode visitLet(Let node) {
    VariableDeclaration newVariable = clone(node.variable);
    return new Let(newVariable, clone(node.body));
  }

  @override
  TreeNode visitBlockExpression(BlockExpression node) {
    return new BlockExpression(clone(node.body), clone(node.value));
  }

  @override
  TreeNode visitExpressionStatement(ExpressionStatement node) {
    return new ExpressionStatement(clone(node.expression));
  }

  @override
  TreeNode visitBlock(Block node) {
    return new Block(node.statements.map(clone).toList())
      ..fileEndOffset = _cloneFileOffset(node.fileEndOffset);
  }

  @override
  TreeNode visitAssertBlock(AssertBlock node) {
    return new AssertBlock(node.statements.map(clone).toList());
  }

  @override
  TreeNode visitEmptyStatement(EmptyStatement node) {
    return new EmptyStatement();
  }

  @override
  TreeNode visitAssertStatement(AssertStatement node) {
    return new AssertStatement(clone(node.condition),
        conditionStartOffset: node.conditionStartOffset,
        conditionEndOffset: node.conditionEndOffset,
        message: cloneOptional(node.message));
  }

  @override
  TreeNode visitLabeledStatement(LabeledStatement node) {
    LabeledStatement newNode = new LabeledStatement(null);
    labels[node] = newNode;
    newNode.body = clone(node.body)..parent = newNode;
    return newNode;
  }

  @override
  TreeNode visitBreakStatement(BreakStatement node) {
    return new BreakStatement(labels[node.target]!);
  }

  @override
  TreeNode visitWhileStatement(WhileStatement node) {
    return new WhileStatement(clone(node.condition), clone(node.body));
  }

  @override
  TreeNode visitDoStatement(DoStatement node) {
    return new DoStatement(clone(node.body), clone(node.condition));
  }

  @override
  TreeNode visitForStatement(ForStatement node) {
    List<VariableDeclaration> variables = node.variables.map(clone).toList();
    return new ForStatement(variables, cloneOptional(node.condition),
        node.updates.map(clone).toList(), clone(node.body));
  }

  @override
  TreeNode visitForInStatement(ForInStatement node) {
    VariableDeclaration newVariable = clone(node.variable);
    return new ForInStatement(
        newVariable, clone(node.iterable), clone(node.body),
        isAsync: node.isAsync)
      ..bodyOffset = node.bodyOffset;
  }

  @override
  TreeNode visitSwitchStatement(SwitchStatement node) {
    for (SwitchCase switchCase in node.cases) {
      switchCases[switchCase] = new SwitchCase(
          switchCase.expressions.map(clone).toList(),
          new List<int>.of(switchCase.expressionOffsets),
          dummyStatement,
          isDefault: switchCase.isDefault);
    }
    return new SwitchStatement(
        clone(node.expression), node.cases.map(clone).toList(),
        isExplicitlyExhaustive: node.isExplicitlyExhaustive);
  }

  @override
  TreeNode visitSwitchCase(SwitchCase node) {
    SwitchCase switchCase = switchCases[node]!;
    switchCase.body = clone(node.body)..parent = switchCase;
    return switchCase;
  }

  @override
  TreeNode visitContinueSwitchStatement(ContinueSwitchStatement node) {
    return new ContinueSwitchStatement(switchCases[node.target]!);
  }

  @override
  TreeNode visitIfStatement(IfStatement node) {
    return new IfStatement(
        clone(node.condition), clone(node.then), cloneOptional(node.otherwise));
  }

  @override
  TreeNode visitReturnStatement(ReturnStatement node) {
    return new ReturnStatement(cloneOptional(node.expression));
  }

  @override
  TreeNode visitTryCatch(TryCatch node) {
    return new TryCatch(clone(node.body), node.catches.map(clone).toList(),
        isSynthetic: node.isSynthetic);
  }

  @override
  TreeNode visitCatch(Catch node) {
    VariableDeclaration? newException = cloneOptional(node.exception);
    VariableDeclaration? newStackTrace = cloneOptional(node.stackTrace);
    return new Catch(newException, clone(node.body),
        stackTrace: newStackTrace, guard: visitType(node.guard));
  }

  @override
  TreeNode visitTryFinally(TryFinally node) {
    return new TryFinally(clone(node.body), clone(node.finalizer));
  }

  @override
  TreeNode visitYieldStatement(YieldStatement node) {
    return new YieldStatement(clone(node.expression))..flags = node.flags;
  }

  @override
  TreeNode visitVariableDeclaration(VariableDeclaration node) {
    return setVariableClone(
        node,
        new VariableDeclaration(node.name,
            initializer: cloneOptional(node.initializer),
            type: visitType(node.type))
          ..annotations = cloneAnnotations && !node.annotations.isEmpty
              ? node.annotations.map(clone).toList()
              : const <Expression>[]
          ..flags = node.flags
          ..fileEqualsOffset = _cloneFileOffset(node.fileEqualsOffset));
  }

  @override
  TreeNode visitFunctionDeclaration(FunctionDeclaration node) {
    VariableDeclaration newVariable = clone(node.variable);
    // Create the declaration before cloning the body to support recursive
    // [LocalFunctionInvocation] nodes.
    FunctionDeclaration declaration =
        new FunctionDeclaration(newVariable, dummyFunctionNode);
    FunctionNode functionNode = clone(node.function);
    declaration.function = functionNode..parent = declaration;
    return declaration;
  }

  void prepareTypeParameters(List<TypeParameter> typeParameters) {
    for (TypeParameter node in typeParameters) {
      TypeParameter? newNode = typeParams[node];
      if (newNode == null) {
        newNode = new TypeParameter(node.name);
        typeParams[node] = newNode;
        typeSubstitution[node] =
            new TypeParameterType.forAlphaRenaming(node, newNode);
      }
    }
  }

  @override
  TypeParameter visitTypeParameter(TypeParameter node) {
    TypeParameter newNode = typeParams[node]!;
    newNode.bound = visitType(node.bound);
    // ignore: unnecessary_null_comparison
    if (node.defaultType != null) {
      newNode.defaultType = visitType(node.defaultType);
    }
    return newNode
      ..annotations = cloneAnnotations && !node.annotations.isEmpty
          ? node.annotations.map(clone).toList()
          : const <Expression>[]
      ..flags = node.flags;
  }

  Statement? cloneFunctionNodeBody(FunctionNode node) {
    bool savedCloneAnnotations = this.cloneAnnotations;
    try {
      this.cloneAnnotations = true;
      return cloneOptional(node.body);
    } finally {
      this.cloneAnnotations = savedCloneAnnotations;
    }
  }

  @override
  TreeNode visitFunctionNode(FunctionNode node) {
    prepareTypeParameters(node.typeParameters);
    List<TypeParameter> typeParameters =
        node.typeParameters.map(clone).toList();
    List<VariableDeclaration> positional =
        node.positionalParameters.map(clone).toList();
    List<VariableDeclaration> named = node.namedParameters.map(clone).toList();
    final DartType? futureValueType =
        node.futureValueType != null ? visitType(node.futureValueType!) : null;
    return new FunctionNode(cloneFunctionNodeBody(node),
        typeParameters: typeParameters,
        positionalParameters: positional,
        namedParameters: named,
        requiredParameterCount: node.requiredParameterCount,
        returnType: visitType(node.returnType),
        asyncMarker: node.asyncMarker,
        dartAsyncMarker: node.dartAsyncMarker,
        futureValueType: futureValueType)
      ..fileEndOffset = _cloneFileOffset(node.fileEndOffset);
  }

  @override
  TreeNode visitArguments(Arguments node) {
    return new Arguments(node.positional.map(clone).toList(),
        types: node.types.map(visitType).toList(),
        named: node.named.map(clone).toList());
  }

  @override
  TreeNode visitNamedExpression(NamedExpression node) {
    return new NamedExpression(node.name, clone(node.value));
  }

  @override
  TreeNode defaultBasicLiteral(BasicLiteral node) {
    return defaultExpression(node);
  }

  @override
  TreeNode defaultExpression(Expression node) {
    throw 'Unimplemented clone for Kernel expression: $node';
  }

  @override
  TreeNode defaultInitializer(Initializer node) {
    throw 'Unimplemented clone for Kernel initializer: $node';
  }

  @override
  TreeNode defaultMember(Member node) {
    throw 'Unimplemented clone for Kernel member: $node';
  }

  @override
  TreeNode defaultStatement(Statement node) {
    throw 'Unimplemented clone for Kernel statement: $node';
  }

  @override
  TreeNode defaultTreeNode(TreeNode node) {
    throw 'Cloning Kernel non-members is not supported.  '
        'Tried cloning $node';
  }

  @override
  TreeNode visitAssertInitializer(AssertInitializer node) {
    return new AssertInitializer(clone(node.statement));
  }

  @override
  TreeNode visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) {
    return new CheckLibraryIsLoaded(node.import);
  }

  @override
  TreeNode visitCombinator(Combinator node) {
    return defaultTreeNode(node);
  }

  @override
  TreeNode visitFieldInitializer(FieldInitializer node) {
    return new FieldInitializer.byReference(
        node.fieldReference, clone(node.value));
  }

  @override
  TreeNode visitInstantiation(Instantiation node) {
    return new Instantiation(
        clone(node.expression), node.typeArguments.map(visitType).toList());
  }

  @override
  TreeNode visitInvalidInitializer(InvalidInitializer node) {
    return new InvalidInitializer();
  }

  @override
  TreeNode visitLibraryDependency(LibraryDependency node) {
    return defaultTreeNode(node);
  }

  @override
  TreeNode visitLibraryPart(LibraryPart node) {
    return defaultTreeNode(node);
  }

  @override
  TreeNode visitLoadLibrary(LoadLibrary node) {
    return new LoadLibrary(node.import);
  }

  @override
  TreeNode visitLocalInitializer(LocalInitializer node) {
    return new LocalInitializer(clone(node.variable));
  }

  @override
  TreeNode visitComponent(Component node) {
    return defaultTreeNode(node);
  }

  @override
  TreeNode visitRedirectingInitializer(RedirectingInitializer node) {
    return new RedirectingInitializer.byReference(
        node.targetReference, clone(node.arguments));
  }

  @override
  TreeNode visitSuperInitializer(SuperInitializer node) {
    return new SuperInitializer.byReference(
        node.targetReference, clone(node.arguments));
  }

  @override
  TreeNode visitTypedef(Typedef node) {
    return defaultTreeNode(node);
  }

  @override
  TreeNode visitDynamicGet(DynamicGet node) {
    return new DynamicGet(node.kind, clone(node.receiver), node.name);
  }

  @override
  TreeNode visitDynamicInvocation(DynamicInvocation node) {
    return new DynamicInvocation(
        node.kind, clone(node.receiver), node.name, clone(node.arguments));
  }

  @override
  TreeNode visitDynamicSet(DynamicSet node) {
    return new DynamicSet(
        node.kind, clone(node.receiver), node.name, clone(node.value));
  }

  @override
  TreeNode visitEqualsCall(EqualsCall node) {
    return new EqualsCall.byReference(clone(node.left), clone(node.right),
        functionType: visitType(node.functionType) as FunctionType,
        interfaceTargetReference: node.interfaceTargetReference);
  }

  @override
  TreeNode visitEqualsNull(EqualsNull node) {
    return new EqualsNull(clone(node.expression));
  }

  @override
  TreeNode visitFunctionInvocation(FunctionInvocation node) {
    return new FunctionInvocation(
        node.kind, clone(node.receiver), clone(node.arguments),
        functionType: visitOptionalType(node.functionType) as FunctionType?);
  }

  @override
  TreeNode visitInstanceGet(InstanceGet node) {
    return new InstanceGet.byReference(
        node.kind, clone(node.receiver), node.name,
        resultType: visitType(node.resultType),
        interfaceTargetReference: node.interfaceTargetReference);
  }

  @override
  TreeNode visitInstanceInvocation(InstanceInvocation node) {
    return new InstanceInvocation.byReference(
        node.kind, clone(node.receiver), node.name, clone(node.arguments),
        functionType: visitType(node.functionType) as FunctionType,
        interfaceTargetReference: node.interfaceTargetReference)
      ..flags = node.flags;
  }

  @override
  TreeNode visitInstanceGetterInvocation(InstanceGetterInvocation node) {
    return new InstanceGetterInvocation.byReference(
        node.kind, clone(node.receiver), node.name, clone(node.arguments),
        functionType: visitOptionalType(node.functionType) as FunctionType,
        interfaceTargetReference: node.interfaceTargetReference);
  }

  @override
  TreeNode visitInstanceSet(InstanceSet node) {
    return new InstanceSet.byReference(
        node.kind, clone(node.receiver), node.name, clone(node.value),
        interfaceTargetReference: node.interfaceTargetReference);
  }

  @override
  TreeNode visitInstanceTearOff(InstanceTearOff node) {
    return new InstanceTearOff.byReference(
        node.kind, clone(node.receiver), node.name,
        resultType: visitType(node.resultType),
        interfaceTargetReference: node.interfaceTargetReference);
  }

  @override
  TreeNode visitLocalFunctionInvocation(LocalFunctionInvocation node) {
    return new LocalFunctionInvocation(
        getVariableClone(node.variable)!, clone(node.arguments),
        functionType: visitType(node.functionType) as FunctionType);
  }

  @override
  TreeNode visitStaticTearOff(StaticTearOff node) {
    return new StaticTearOff.byReference(node.targetReference);
  }

  @override
  TreeNode visitFunctionTearOff(FunctionTearOff node) {
    return new FunctionTearOff(clone(node.receiver));
  }

  @override
  TreeNode visitConstructorTearOff(ConstructorTearOff node) {
    return new ConstructorTearOff.byReference(node.targetReference);
  }

  @override
  TreeNode visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
    return new RedirectingFactoryTearOff.byReference(node.targetReference);
  }

  @override
  TreeNode visitTypedefTearOff(TypedefTearOff node) {
    prepareTypeParameters(node.typeParameters);
    return new TypedefTearOff(
        node.typeParameters.map(visitTypeParameter).toList(),
        clone(node.expression),
        node.typeArguments.map(visitType).toList());
  }
}

/// Visitor that return a clone of a tree, maintaining references to cloned
/// objects.
///
/// It is safe to clone members, but cloning a class or library is not
/// supported.
class CloneVisitorWithMembers extends CloneVisitorNotMembers {
  CloneVisitorWithMembers(
      {Map<TypeParameter, DartType>? typeSubstitution,
      Map<TypeParameter, TypeParameter>? typeParams,
      bool cloneAnnotations = true})
      : super(
            typeSubstitution: typeSubstitution,
            typeParams: typeParams,
            cloneAnnotations: cloneAnnotations);

  @override
  @Deprecated("When cloning with members one should use the specific cloneX")
  T clone<T extends TreeNode>(T node) {
    return super.clone(node);
  }

  Constructor cloneConstructor(Constructor node, Reference? reference) {
    final Uri? activeFileUriSaved = _activeFileUri;
    _activeFileUri = node.fileUri;

    Constructor result = new Constructor(
      super.clone(node.function),
      name: node.name,
      isConst: node.isConst,
      isExternal: node.isExternal,
      isSynthetic: node.isSynthetic,
      initializers: node.initializers.map(super.clone).toList(),
      transformerFlags: node.transformerFlags,
      fileUri: node.fileUri,
      reference: reference,
    )
      ..annotations = cloneAnnotations && !node.annotations.isEmpty
          ? node.annotations.map(super.clone).toList()
          : const <Expression>[]
      ..fileOffset = _cloneFileOffset(node.fileOffset)
      ..fileEndOffset = _cloneFileOffset(node.fileEndOffset);

    _activeFileUri = activeFileUriSaved;
    return result;
  }

  Procedure cloneProcedure(Procedure node, Reference? reference) {
    final Uri? activeFileUriSaved = _activeFileUri;
    _activeFileUri = node.fileUri;
    Procedure result = new Procedure(
        node.name, node.kind, super.clone(node.function),
        reference: reference,
        transformerFlags: node.transformerFlags,
        fileUri: node.fileUri,
        stubKind: node.stubKind,
        stubTarget: node.stubTarget)
      ..annotations = cloneAnnotations && !node.annotations.isEmpty
          ? node.annotations.map(super.clone).toList()
          : const <Expression>[]
      ..fileStartOffset = _cloneFileOffset(node.fileStartOffset)
      ..fileOffset = _cloneFileOffset(node.fileOffset)
      ..fileEndOffset = _cloneFileOffset(node.fileEndOffset)
      ..flags = node.flags;

    _activeFileUri = activeFileUriSaved;
    return result;
  }

  Field cloneField(Field node, Reference? fieldReference,
      Reference? getterReference, Reference? setterReference) {
    final Uri? activeFileUriSaved = _activeFileUri;
    _activeFileUri = node.fileUri;

    Field result;
    if (node.hasSetter) {
      result = new Field.mutable(node.name,
          type: visitType(node.type),
          initializer: cloneOptional(node.initializer),
          transformerFlags: node.transformerFlags,
          fileUri: node.fileUri,
          fieldReference: fieldReference,
          getterReference: getterReference,
          setterReference: setterReference);
    } else {
      assert(
          setterReference == null,
          "Cannot use setter reference $setterReference "
          "for clone of an immutable field.");
      result = new Field.immutable(node.name,
          type: visitType(node.type),
          initializer: cloneOptional(node.initializer),
          transformerFlags: node.transformerFlags,
          fileUri: node.fileUri,
          fieldReference: fieldReference,
          getterReference: getterReference);
    }
    result
      ..annotations = cloneAnnotations && !node.annotations.isEmpty
          ? node.annotations.map(super.clone).toList()
          : const <Expression>[]
      ..fileOffset = _cloneFileOffset(node.fileOffset)
      ..fileEndOffset = _cloneFileOffset(node.fileEndOffset)
      ..flags = node.flags;

    _activeFileUri = activeFileUriSaved;
    return result;
  }

  RedirectingFactory cloneRedirectingFactory(
      RedirectingFactory node, Reference? reference) {
    final Uri? activeFileUriSaved = _activeFileUri;
    _activeFileUri = node.fileUri;

    RedirectingFactory result = new RedirectingFactory(node.targetReference,
        name: node.name,
        isConst: node.isConst,
        isExternal: node.isExternal,
        transformerFlags: node.transformerFlags,
        typeArguments: node.typeArguments.map(visitType).toList(),
        function: super.clone(node.function),
        fileUri: node.fileUri,
        reference: reference)
      ..fileOffset = _cloneFileOffset(node.fileOffset)
      ..annotations = cloneAnnotations && !node.annotations.isEmpty
          ? node.annotations.map(super.clone).toList()
          : const <Expression>[];

    _activeFileUri = activeFileUriSaved;
    return result;
  }
}

/// Cloner that resolves super calls in mixin declarations.
class MixinApplicationCloner extends CloneVisitorWithMembers {
  final Class mixinApplicationClass;
  Map<Name, Member>? _getterMap;
  Map<Name, Member>? _setterMap;

  MixinApplicationCloner(this.mixinApplicationClass,
      {Map<TypeParameter, DartType>? typeSubstitution,
      Map<TypeParameter, TypeParameter>? typeParams,
      bool cloneAnnotations = true})
      : super(
            typeSubstitution: typeSubstitution,
            typeParams: typeParams,
            cloneAnnotations: cloneAnnotations);

  Member? _findSuperMember(Name name, {required bool isSetter}) {
    // ignore: unnecessary_null_comparison
    assert(isSetter != null);
    Map<Name, Member> cache;
    if (isSetter) {
      cache = _setterMap ??= {};
    } else {
      cache = _getterMap ??= {};
    }
    Member? member = cache[name];
    if (member != null) {
      return member;
    }
    Class? superClass = mixinApplicationClass.superclass;
    while (superClass != null) {
      for (Procedure procedure in superClass.procedures) {
        if (procedure.name == name) {
          if (isSetter) {
            if (procedure.kind == ProcedureKind.Setter &&
                !procedure.isAbstract) {
              return cache[name] = procedure;
            }
          } else {
            if (procedure.kind != ProcedureKind.Setter &&
                !procedure.isAbstract) {
              return cache[name] = procedure;
            }
          }
        }
      }
      for (Field field in superClass.fields) {
        if (field.name == name) {
          if (isSetter) {
            if (field.hasSetter) {
              return cache[name] = field;
            }
          } else {
            return cache[name] = field;
          }
        }
      }

      superClass = superClass.superclass;
    }
    // TODO(johnniwinther): Throw instead when the CFE reports missing concrete
    // super members.
    // throw new StateError(
    //     'No super member found for $name in $mixinApplicationClass');
    return null;
  }

  @override
  SuperMethodInvocation visitSuperMethodInvocation(SuperMethodInvocation node) {
    SuperMethodInvocation cloned =
        super.visitSuperMethodInvocation(node) as SuperMethodInvocation;
    cloned.interfaceTarget = _findSuperMember(node.name, isSetter: false)
            as Procedure? ??
        // TODO(johnniwinther): Remove this when an error is reported instead.
        cloned.interfaceTarget;
    return cloned;
  }

  @override
  SuperPropertyGet visitSuperPropertyGet(SuperPropertyGet node) {
    SuperPropertyGet cloned =
        super.visitSuperPropertyGet(node) as SuperPropertyGet;
    cloned.interfaceTarget = _findSuperMember(node.name, isSetter: false) ??
        // TODO(johnniwinther): Remove this when an error is reported instead.
        cloned.interfaceTarget;
    return cloned;
  }

  @override
  SuperPropertySet visitSuperPropertySet(SuperPropertySet node) {
    SuperPropertySet cloned =
        super.visitSuperPropertySet(node) as SuperPropertySet;
    cloned.interfaceTarget = _findSuperMember(node.name, isSetter: true) ??
        // TODO(johnniwinther): Remove this when an error is reported instead.
        cloned.interfaceTarget;
    return cloned;
  }
}

class CloneProcedureWithoutBody extends CloneVisitorWithMembers {
  CloneProcedureWithoutBody(
      {Map<TypeParameter, DartType>? typeSubstitution,
      bool cloneAnnotations = true})
      : super(
            typeSubstitution: typeSubstitution,
            cloneAnnotations: cloneAnnotations);

  @override
  Statement? cloneFunctionNodeBody(FunctionNode node) => null;
}
