// 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
    with
        TreeVisitorExperimentExclusionMixin<TreeNode>,
        ExpressionVisitorExperimentExclusionMixin<TreeNode>,
        StatementVisitorExperimentExclusionMixin<TreeNode>
    implements TreeVisitor<TreeNode> {
  final Map<VariableBase, VariableBase> _variables =
      <VariableBase, VariableBase>{};
  final Map<VariableContext, VariableContext> _variableContexts =
      <VariableContext, VariableContext>{};
  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;
  bool inScope = false;

  /// 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.
  new({
    Map<TypeParameter, DartType>? typeSubstitution,
    Map<TypeParameter, TypeParameter>? typeParams,
    Map<StructuralParameter, StructuralParameter>? structuralParameters,
    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.
  Variable? getVariableClone(Variable variable) {
    return _variables[variable] as Variable?;
  }

  /// Registers [clone] as the clone for [variable].
  ///
  /// Returns the [clone].
  V setVariableClone<V extends VariableBase>(V variable, V 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 visitExtensionTypeDeclaration(ExtensionTypeDeclaration node) {
    throw 'Cloning of extension type declarations 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';
  }

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

  bool _assertFileUriTarget(TreeNode node, TreeNode clone) {
    if (node is FileUriNode && clone is FileUriNode) {
      if (node.fileUri != clone.fileUri) {
        assert(
          false,
          "Original and clone disagrees on file uri: "
          "${node.fileUri} vs ${clone.fileUri}",
        );
        return false;
      }
      return true;
    } else if (node is! FileUriNode && clone is! FileUriNode) {
      return true;
    }
    assert(false, "Original and clone disagrees on being a file uri node.");
    return false;
  }

  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);

    assert(_assertFileUriTarget(node, result));

    _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);
      assert(_assertFileUriTarget(node, result));
    }
    _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) {
    Variable? variable = getVariableClone(node.variable);
    assert(variable != null, "Missing clone for variable ${node.variable}.");
    return new VariableGet(variable!, visitOptionalType(node.promotedType));
  }

  @override
  TreeNode visitVariableSet(VariableSet node) {
    Variable? variable = getVariableClone(node.variable);
    assert(variable != null, "Missing clone for variable ${node.variable}.");
    return new VariableSet(variable!, clone(node.value));
  }

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

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

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

  @override
  TreeNode visitSuperPropertySet(SuperPropertySet node) {
    return new SuperPropertySet.byReference(
      clone(node.receiver),
      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(
      clone(node.receiver),
      node.name,
      clone(node.arguments),
      node.interfaceTargetReference,
    );
  }

  @override
  TreeNode visitSuperMethodInvocation(SuperMethodInvocation node) {
    return new SuperMethodInvocation.byReference(
      clone(node.receiver),
      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 visitRedirectingFactoryInvocation(
    RedirectingFactoryInvocation node,
  ) {
    return new RedirectingFactoryInvocation.byReference(
      node.redirectingFactoryTargetReference,
      clone(node.expression),
    );
  }

  @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));
  }

  @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))..flags = node.flags;
  }

  @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 visitRecordLiteral(RecordLiteral node) {
    return new RecordLiteral(
      node.positional.map(clone).toList(),
      node.named.map(clone).toList(),
      visitType(node.recordType) as RecordType,
      isConst: node.isConst,
    );
  }

  @override
  TreeNode visitAwaitExpression(AwaitExpression node) {
    return new AwaitExpression(clone(node.operand))
      ..runtimeCheckType = node.runtimeCheckType != null
          ? visitType(node.runtimeCheckType!)
          : null;
  }

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

  @override
  TreeNode visitConstantExpression(ConstantExpression node) {
    if (node is FileUriConstantExpression) {
      return new FileUriConstantExpression(
        visitConstant(node.constant),
        type: visitType(node.type),
        fileUri: node.fileUri,
      );
    }
    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) {
    SyntheticVariable newVariable = clone(node.variable);
    return new Let(newVariable, clone(node.body));
  }

  @override
  TreeNode visitBlockExpression(BlockExpression node) {
    // The scope should be cloned before the rest of the node, since the
    // variables declared in the scope can appear in the node.
    Scope? clonedScope = _cloneScope(node.scope);
    return new BlockExpression(clone(node.body), clone(node.value))
      ..scope = clonedScope;
  }

  @override
  TreeNode visitRecordIndexGet(RecordIndexGet node) {
    return new RecordIndexGet(
      clone(node.receiver),
      visitType(node.receiverType) as RecordType,
      node.index,
    );
  }

  @override
  TreeNode visitRecordNameGet(RecordNameGet node) {
    return new RecordNameGet(
      clone(node.receiver),
      visitType(node.receiverType) as RecordType,
      node.name,
    );
  }

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

  Scope? _cloneScope(Scope? scope) {
    bool savedInScope = inScope;
    inScope = true;

    Scope? result;
    if (scope != null) {
      List<VariableContext> clonedContexts = [];
      for (VariableContext context in scope.contexts) {
        VariableContext clonedContext = new VariableContext(
          captureKind: context.captureKind,
          variables: [],
        );
        for (VariableBase variable in context.variables) {
          // TODO(cstefantsova): Support [TypeVariable]s.
          variable as Variable;
          // If a variable appears in a context, it must be the point of
          // declaration of that variable, and it shouldn't be previously
          // cloned.
          assert(getVariableClone(variable) == null);
          Variable clonedVariable = clone(variable);
          clonedContext.addVariable(clonedVariable);
        }
        clonedContexts.add(clonedContext);
        _variableContexts[context] = clonedContext;
      }
      result = new Scope(contexts: clonedContexts);
    }

    inScope = savedInScope;
    return result;
  }

  List<VariableContext>? _cloneCapturedContexts(
    List<VariableContext>? capturedContexts,
  ) {
    return capturedContexts == null
        ? null
        : [
            for (VariableContext context in capturedContexts)
              _variableContexts[context]!,
          ];
  }

  @override
  TreeNode visitBlock(Block node) {
    // The scope should be cloned before the rest of the node, since the
    // variables declared in the scope can appear in the node.
    Scope? clonedScope = _cloneScope(node.scope);
    return new Block(node.statements.map(clone).toList())
      ..scope = clonedScope
      ..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) {
    // The scope should be cloned before the rest of the node, since the
    // variables declared in the scope can appear in the node.
    Scope? clonedScope = _cloneScope(node.scope);
    return new WhileStatement(clone(node.condition), clone(node.body))
      ..scope = clonedScope;
  }

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

  @override
  TreeNode visitForStatement(ForStatement node) {
    // The scope should be cloned before the rest of the node, since the
    // variables declared in the scope can appear in the node.
    Scope? clonedScope = _cloneScope(node.scope);
    List<VariableDeclaration> variables = node.variables.map(clone).toList();
    return new ForStatement(
      variables,
      cloneOptional(node.condition),
      node.updates.map(clone).toList(),
      clone(node.body),
    )..scope = clonedScope;
  }

  @override
  TreeNode visitForInStatement(ForInStatement node) {
    // The scope should be cloned before the rest of the node, since the
    // variables declared in the scope can appear in the node.
    Scope? clonedScope = _cloneScope(node.scope);
    DeclaredVariable newVariable = clone(node.variable);
    return new ForInStatement(
        newVariable,
        clone(node.iterable),
        clone(node.body),
        isAsync: node.isAsync,
      )
      ..scope = clonedScope
      ..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,
    )..expressionTypeInternal = visitOptionalType(node.expressionTypeInternal);
  }

  @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) {
    // The scope should be cloned before the rest of the node, since the
    // variables declared in the scope can appear in the node.
    Scope? clonedScope = _cloneScope(node.scope);
    CatchVariable? newException = cloneOptional(node.exception);
    CatchVariable? newStackTrace = cloneOptional(node.stackTrace);
    return new Catch(
      newException,
      clone(node.body),
      stackTrace: newStackTrace,
      guard: visitType(node.guard),
    )..scope = clonedScope;
  }

  @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 visitVariable(Variable node) {
    throw new UnimplementedError(
      "${this.runtimeType}.visitVariableDeclaration",
    );
  }

  @override
  TreeNode visitPositionalParameter(PositionalParameter node) {
    return _variables[node] ??
        setVariableClone(
          node,
          new PositionalParameter(
              cosmeticName: node.cosmeticName,
              type: visitType(node.type),
              defaultValue: cloneOptional(node.defaultValue),
            )
            ..flags = node.flags
            ..annotations = _cloneAnnotations(node)
            ..fileEqualsOffset = _cloneFileOffset(node.fileEqualsOffset),
        );
  }

  @override
  TreeNode visitNamedParameter(NamedParameter node) {
    return _variables[node] ??
        setVariableClone(
          node,
          new NamedParameter(
              parameterName: node.parameterName,
              type: visitType(node.type),
              defaultValue: cloneOptional(node.defaultValue),
            )
            ..flags = node.flags
            ..annotations = _cloneAnnotations(node)
            ..fileEqualsOffset = _cloneFileOffset(node.fileEqualsOffset),
        );
  }

  @override
  TreeNode visitCatchVariable(CatchVariable node) {
    return _variables[node] ??
        setVariableClone(
          node,
          new CatchVariable(
              name: node.catchVariableName,
              type: visitOptionalType(node.type),
            )
            ..flags = node.flags
            ..annotations = _cloneAnnotations(node)
            ..fileEqualsOffset = _cloneFileOffset(node.fileEqualsOffset),
        );
  }

  TreeNode _cloneVariable<V extends Variable>(
    V node,
    TreeNode Function(V, {Expression? initializer}) clone,
  ) {
    V? clonedVariable = _variables[node] as V?;
    if (clonedVariable == null) {
      return clone(
        node,
        // Don't clone initializers of variables during scope cloning. The
        // variables in the scope may refer to each other through their
        // initializers, and the current layout of variable contexts within
        // scopes doesn't allow for easy following of the variable
        // declaration order. Therefore, cloning of initializers is
        // postponed until the points of variable declarations further in
        // the code.
        initializer: inScope ? null : cloneOptional(node.initializer),
      );
    } else {
      // The variables cloned in [_cloneScope] don't have initializers until
      // the point of the variable declaration, where this visit method is
      // called the second time. At that point, the initializer should be
      // cloned.
      assert(!inScope && clonedVariable.initializer == null);
      clonedVariable.initializer = cloneOptional(node.initializer)
        ?..parent = clonedVariable;
      return clonedVariable;
    }
  }

  @override
  TreeNode visitLocalVariable(LocalVariable node) {
    return _cloneVariable(node, (
      LocalVariable node, {
      Expression? initializer,
    }) {
      return setVariableClone(
        node,
        new LocalVariable(
            name: node.cosmeticName!,
            type: visitOptionalType(node.type),
            initializer: initializer,
          )
          ..flags = node.flags
          ..annotations = _cloneAnnotations(node)
          ..fileEqualsOffset = _cloneFileOffset(node.fileEqualsOffset),
      );
    });
  }

  @override
  TreeNode visitLocalFunctionVariable(LocalFunctionVariable node) {
    return _variables[node] ??
        setVariableClone(
          node,
          new LocalFunctionVariable(
              name: node.cosmeticName!,
              type: visitOptionalType(node.type),
            )
            ..flags = node.flags
            ..annotations = _cloneAnnotations(node)
            ..fileEqualsOffset = _cloneFileOffset(node.fileEqualsOffset),
        );
  }

  @override
  TreeNode visitConstVariable(ConstVariable node) {
    return _variables[node] ??
        setVariableClone(
          node,
          new ConstVariable(
              name: node.cosmeticName!,
              type: visitOptionalType(node.type),
              value: cloneOptional(node.value),
            )
            ..flags = node.flags
            ..annotations = _cloneAnnotations(node)
            ..fileEqualsOffset = _cloneFileOffset(node.fileEqualsOffset),
        );
  }

  @override
  TreeNode visitLateVariable(LateVariable node) {
    return _cloneVariable(node, (LateVariable node, {Expression? initializer}) {
      return setVariableClone(
        node,
        new LateVariable(
            name: node.cosmeticName!,
            type: visitOptionalType(node.type),
            initialValue: initializer,
          )
          ..flags = node.flags
          ..annotations = _cloneAnnotations(node)
          ..fileEqualsOffset = _cloneFileOffset(node.fileEqualsOffset),
      );
    });
  }

  @override
  TreeNode visitSyntheticVariable(SyntheticVariable node) {
    return _cloneVariable(node, (
      SyntheticVariable node, {
      Expression? initializer,
    }) {
      return setVariableClone(
        node,
        SyntheticVariable(
            cosmeticName: node.cosmeticName,
            type: visitType(node.type),
            initializer: initializer,
          )
          ..flags = node.flags
          ..annotations = _cloneAnnotations(node)
          ..fileEqualsOffset = _cloneFileOffset(node.fileEqualsOffset),
      );
    });
  }

  @override
  TreeNode visitThisVariable(ThisVariable node) {
    return _variables[node] ??
        setVariableClone(
          node,
          new ThisVariable(type: visitType(node.type))
            ..flags = node.flags
            ..annotations = _cloneAnnotations(node)
            ..fileEqualsOffset = _cloneFileOffset(node.fileEqualsOffset),
        );
  }

  @override
  TreeNode visitVariableStatement(VariableStatement node) {
    return new VariableStatement(clone(node.declaration))
      ..fileOffset = _cloneFileOffset(node.fileOffset);
  }

  @override
  TreeNode visitVariableDeclaration(VariableDeclaration node) {
    return new VariableDeclaration(clone(node.variable))
      ..capturedContexts = _cloneCapturedContexts(node.capturedContexts)
      ..fileOffset = _cloneFileOffset(node.fileOffset);
  }

  List<Expression> _cloneAnnotations(Annotatable node) {
    return cloneAnnotations && !node.annotations.isEmpty
        ? node.annotations.map(clone).toList()
        : const <Expression>[];
  }

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

  void prepareTypeParameters(List<TypeParameter> typeParameters) {
    for (int i = 0; i < typeParameters.length; i++) {
      TypeParameter node = typeParameters[i];
      TypeParameter? newNode = typeParams[node];
      if (newNode == null) {
        newNode = new TypeParameter(node.name);
        typeParams[node] = newNode;
        typeSubstitution[node] = new TypeParameterType(
          newNode,
          node.computeNullabilityFromBound(),
        );
      }
    }
  }

  @override
  TypeParameter visitTypeParameter(TypeParameter node) {
    TypeParameter newNode = typeParams[node]!;
    newNode.bound = visitType(node.bound);
    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);
    // The scope should be cloned before the rest of the node, since the
    // variables declared in the scope can appear in the node.
    Scope? clonedScope = _cloneScope(node.scope);
    List<TypeParameter> typeParameters = node.typeParameters
        .map(clone)
        .toList();
    List<PositionalParameter> positional = node.positionalParameters
        .map(clone)
        .toList();
    List<NamedParameter> named = node.namedParameters.map(clone).toList();
    ThisVariable? thisVariable = cloneOptional(node.thisVariable);
    final DartType? futureValueType = node.emittedValueType != null
        ? visitType(node.emittedValueType!)
        : null;
    return new FunctionNode(
        cloneFunctionNodeBody(node),
        typeParameters: typeParameters,
        positionalParameters: positional,
        namedParameters: named,
        thisVariable: thisVariable,
        requiredParameterCount: node.requiredParameterCount,
        returnType: visitType(node.returnType),
        asyncMarker: node.asyncMarker,
        dartAsyncMarker: node.dartAsyncMarker,
        emittedValueType: futureValueType,
      )
      ..scope = clonedScope
      ..capturedContexts = _cloneCapturedContexts(node.capturedContexts)
      ..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));
  }

  TreeNode _unsupportedNode(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 _unsupportedNode(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(node.message)..flags = node.flags;
  }

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

  @override
  TreeNode visitLibraryPart(LibraryPart node) {
    return _unsupportedNode(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 _unsupportedNode(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 _unsupportedNode(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),
    )..flags = node.flags;
  }

  @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) as LocalFunctionVariable,
      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) {
    return new TypedefTearOff(
      node.structuralParameters,
      clone(node.expression),
      node.typeArguments.map(visitType).toList(),
    );
  }

  @override
  TreeNode visitAndPattern(AndPattern node) {
    return new AndPattern(clone(node.left), clone(node.right));
  }

  @override
  TreeNode visitAssignedVariablePattern(AssignedVariablePattern node) {
    return new AssignedVariablePattern(getVariableClone(node.variable)!)
      ..matchedValueType = visitOptionalType(node.matchedValueType)
      ..needsCast = node.needsCast;
  }

  @override
  TreeNode visitCastPattern(CastPattern node) {
    return new CastPattern(clone(node.pattern), visitType(node.type));
  }

  @override
  TreeNode visitConstantPattern(ConstantPattern node) {
    return new ConstantPattern(clone(node.expression));
  }

  @override
  TreeNode visitInvalidPattern(InvalidPattern node) {
    return new InvalidPattern(
      clone(node.invalidExpression),
      declaredVariables: node.declaredVariables
          .map((e) => getVariableClone(e) as DeclaredVariable)
          .toList(),
    );
  }

  @override
  TreeNode visitListPattern(ListPattern node) {
    return new ListPattern(
      visitOptionalType(node.typeArgument),
      node.patterns.map(clone).toList(),
    );
  }

  @override
  TreeNode visitMapPattern(MapPattern node) {
    return new MapPattern(
      visitOptionalType(node.keyType),
      visitOptionalType(node.valueType),
      node.entries.map(clone).toList(),
    );
  }

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

  @override
  TreeNode visitMapPatternRestEntry(MapPatternRestEntry node) {
    return new MapPatternRestEntry();
  }

  @override
  TreeNode visitNamedPattern(NamedPattern node) {
    return new NamedPattern(node.name, clone(node.pattern));
  }

  @override
  TreeNode visitNullAssertPattern(NullAssertPattern node) {
    return new NullAssertPattern(clone(node.pattern));
  }

  @override
  TreeNode visitNullCheckPattern(NullCheckPattern node) {
    return new NullCheckPattern(clone(node.pattern));
  }

  @override
  TreeNode visitObjectPattern(ObjectPattern node) {
    return new ObjectPattern(
      visitType(node.requiredType),
      node.fields.map(clone).toList(),
    );
  }

  @override
  TreeNode visitOrPattern(OrPattern node) {
    return new OrPattern(
      clone(node.left),
      clone(node.right),
      orPatternJointVariables: node.orPatternJointVariables
          .map((e) => getVariableClone(e) as DeclaredVariable)
          .toList(),
    );
  }

  @override
  TreeNode visitRecordPattern(RecordPattern node) {
    return new RecordPattern(node.patterns.map(clone).toList());
  }

  @override
  TreeNode visitRelationalPattern(RelationalPattern node) {
    return new RelationalPattern(node.kind, clone(node.expression))
      ..expressionType = visitOptionalType(node.expressionType);
  }

  @override
  TreeNode visitRestPattern(RestPattern node) {
    return new RestPattern(cloneOptional(node.subPattern));
  }

  @override
  TreeNode visitVariablePattern(VariablePattern node) {
    return new VariablePattern(
      visitOptionalType(node.type),
      clone(node.variable),
    );
  }

  @override
  TreeNode visitWildcardPattern(WildcardPattern node) {
    return new WildcardPattern(visitOptionalType(node.type));
  }

  @override
  TreeNode visitPatternGuard(PatternGuard node) {
    return new PatternGuard(node.pattern, node.guard);
  }

  @override
  TreeNode visitPatternSwitchCase(PatternSwitchCase node) {
    return new PatternSwitchCase(
      new List<int>.of(node.caseOffsets),
      node.patternGuards.map(clone).toList(),
      clone(node.body),
      isDefault: node.isDefault,
      hasLabel: node.hasLabel,
      jointVariables: node.jointVariables
          .map((e) => getVariableClone(e) as DeclaredVariable)
          .toList(),
      jointVariableFirstUseOffsets: node.jointVariableFirstUseOffsets == null
          ? null
          : new List<int>.of(node.jointVariableFirstUseOffsets!),
    );
  }

  @override
  TreeNode visitPatternSwitchStatement(PatternSwitchStatement node) {
    return new PatternSwitchStatement(
      clone(node.expression),
      node.cases.map(clone).toList(),
    )..expressionTypeInternal = visitOptionalType(node.expressionTypeInternal);
  }

  @override
  TreeNode visitSwitchExpression(SwitchExpression node) {
    return new SwitchExpression(
        clone(node.expression),
        node.cases.map(clone).toList(),
      )
      ..expressionType = visitOptionalType(node.expressionType)
      ..staticType = visitOptionalType(node.staticType);
  }

  @override
  TreeNode visitSwitchExpressionCase(SwitchExpressionCase node) {
    return new SwitchExpressionCase(
      clone(node.patternGuard),
      clone(node.expression),
    );
  }

  @override
  TreeNode visitPatternVariableDeclaration(PatternVariableDeclaration node) {
    return new PatternVariableDeclaration(
      clone(node.pattern),
      clone(node.initializer),
      isFinal: node.isFinal,
    );
  }

  @override
  TreeNode visitPatternAssignment(PatternAssignment node) {
    return new PatternAssignment(clone(node.pattern), clone(node.expression));
  }

  @override
  TreeNode visitIfCaseStatement(IfCaseStatement node) {
    return new IfCaseStatement(
      clone(node.expression),
      clone(node.patternGuard),
      clone(node.then),
      cloneOptional(node.otherwise),
    );
  }

  @override
  TreeNode visitAuxiliaryExpression(AuxiliaryExpression node) {
    throw new UnsupportedError(
      "Unsupported auxiliary expression ${node} (${node.runtimeType}).",
    );
  }

  @override
  TreeNode visitAuxiliaryStatement(AuxiliaryStatement node) {
    throw new UnsupportedError(
      "Unsupported auxiliary statement ${node} (${node.runtimeType}).",
    );
  }

  @override
  TreeNode visitAuxiliaryInitializer(AuxiliaryInitializer node) {
    throw new UnsupportedError(
      "Unsupported auxiliary initializer ${node} (${node.runtimeType}).",
    );
  }

  @override
  TreeNode visitAuxiliaryPattern(AuxiliaryPattern node) {
    throw new UnsupportedError(
      "Unsupported auxiliary pattern ${node} (${node.runtimeType}).",
    );
  }
}

/// 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 {
  new({
    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(),
            containsSuperCalls: node.containsSuperCalls,
            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);
    setParents(result.annotations, result);

    assert(_assertFileUriTarget(node, result));

    _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,
            containsSuperCalls: node.containsSuperCalls,
            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;
    setParents(result.annotations, result);

    assert(_assertFileUriTarget(node, result));

    _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) {
      ThisVariable? clonedThisVariable =
          node.thisVariable?.accept<TreeNode>(this) as ThisVariable?;
      result = new Field.mutable(
        node.name,
        type: visitType(node.type),
        initializer: cloneOptional(node.initializer),
        containsSuperCalls: node.containsSuperCalls,
        fileUri: node.fileUri,
        fieldReference: fieldReference,
        getterReference: getterReference,
        setterReference: setterReference,
      )..thisVariable = clonedThisVariable;
      clonedThisVariable?.parent = result;
    } else {
      assert(
        setterReference == null,
        "Cannot use setter reference $setterReference "
        "for clone of an immutable field.",
      );
      ThisVariable? clonedThisVariable =
          node.thisVariable?.accept<TreeNode>(this) as ThisVariable?;
      result = new Field.immutable(
        node.name,
        type: visitType(node.type),
        initializer: cloneOptional(node.initializer),
        containsSuperCalls: node.containsSuperCalls,
        fileUri: node.fileUri,
        fieldReference: fieldReference,
        getterReference: getterReference,
      )..thisVariable = clonedThisVariable;
      clonedThisVariable?.parent = result;
    }
    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;
    setParents(result.annotations, result);

    assert(_assertFileUriTarget(node, result));

    _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;

  new(
    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}) {
    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 {
  new({
    Map<TypeParameter, DartType>? typeSubstitution,
    bool cloneAnnotations = true,
  }) : super(
         typeSubstitution: typeSubstitution,
         cloneAnnotations: cloneAnnotations,
       );

  /// Clones procedure and replaces its parts with those passed as arguments
  ///
  /// [cloneProcedureWith] is a shortcut that can be helpful, for example, for
  /// transforming external procedures.
  ///
  /// Since this cloner clones procedures without the body, it's safe to replace
  /// the parameters of the cloned procedure, since they aren't referenced
  /// anywhere. If either [positionalParameters] or [namedParameters] are
  /// passed in, they are used in place of the freshly cloned
  /// [FunctionNode.positionalParameters] and [FunctionNode.namedParameters].
  Procedure cloneProcedureWith(
    Procedure node,
    Reference? reference, {
    List<PositionalParameter>? positionalParameters,
    List<NamedParameter>? namedParameters,
  }) {
    Procedure cloned = cloneProcedure(node, reference);
    if (positionalParameters != null) {
      cloned.function.positionalParameters = positionalParameters;
      setParents(positionalParameters, cloned.function);
    }
    if (namedParameters != null) {
      cloned.function.namedParameters = namedParameters;
      setParents(namedParameters, cloned.function);
    }
    return cloned;
  }

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