// 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 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 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());
  }

  @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>[]
      ..startFileOffset = _cloneFileOffset(node.startFileOffset)
      ..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?;
    return cloned;
  }

  @override
  SuperPropertyGet visitSuperPropertyGet(SuperPropertyGet node) {
    SuperPropertyGet cloned =
        super.visitSuperPropertyGet(node) as SuperPropertyGet;
    cloned.interfaceTarget = _findSuperMember(node.name, isSetter: false);
    return cloned;
  }

  @override
  SuperPropertySet visitSuperPropertySet(SuperPropertySet node) {
    SuperPropertySet cloned =
        super.visitSuperPropertySet(node) as SuperPropertySet;
    cloned.interfaceTarget = _findSuperMember(node.name, isSetter: true);
    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;
}
