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

import 'dart:convert';
import 'dart:math';

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/precedence.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/fix_reason_target.dart';
import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:nnbd_migration/src/utilities/hint_utils.dart';

Map<int?, List<AtomicEdit>>? _removeCode(
    int offset, int end, _RemovalStyle removalStyle, AtomicEditInfo? info) {
  if (offset < end) {
    // TODO(paulberry): handle preexisting comments?
    switch (removalStyle) {
      case _RemovalStyle.commentSpace:
        return {
          offset: [AtomicEdit.insert('/* ', info: info)],
          end: [AtomicEdit.insert('*/ ', info: info)]
        };
      case _RemovalStyle.delete:
        return {
          offset: [AtomicEdit.delete(end - offset, info: info)]
        };
      case _RemovalStyle.spaceComment:
        return {
          offset: [AtomicEdit.insert(' /*', info: info)],
          end: [AtomicEdit.insert(' */', info: info)]
        };
      case _RemovalStyle.spaceInsideComment:
        return {
          offset: [AtomicEdit.insert('/* ', info: info)],
          end: [AtomicEdit.insert(' */', info: info)]
        };
    }
  } else {
    return null;
  }
}

/// A single atomic change to a source file, decoupled from the location at
/// which the change is made. The [EditPlan] class performs its duties by
/// creating and manipulating [AtomicEdit] objects.
///
/// A list of [AtomicEdit]s may be converted to a [SourceEdit] using the
/// extension [AtomicEditList], and a map of offsets to lists of [AtomicEdit]s
/// may be converted to a list of [SourceEdit] using the extension
/// [AtomicEditMap].
///
/// May be subclassed to allow additional information to be recorded about the
/// edit.
class AtomicEdit {
  /// Additional information about this edit, or `null` if no additional
  /// information is available.
  final AtomicEditInfo? info;

  /// The number of characters that should be deleted by this edit, or `0` if no
  /// characters should be deleted.
  final int length;

  /// The characters that should be inserted by this edit, or the empty string
  /// if no characters should be inserted.
  final String replacement;

  /// If `true`, this edit shouldn't actually be made to the source file; it
  /// exists merely to provide additional information to be shown in the preview
  /// tool.
  final bool isInformative;

  /// Initialize an edit to delete [length] characters.
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  const AtomicEdit.delete(this.length, {this.info, this.isInformative = false})
      : assert(length > 0),
        replacement = '';

  /// Initialize an edit to insert the [replacement] characters.
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  const AtomicEdit.insert(this.replacement,
      {this.info, this.isInformative = false})
      : assert(replacement.length > 0),
        length = 0;

  /// Initialize an edit to replace [length] characters with the [replacement]
  /// characters.
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  const AtomicEdit.replace(this.length, this.replacement, {this.info})
      : assert(length > 0 || replacement.length > 0),
        isInformative = false;

  /// Return `true` if this edit is a deletion (no characters added).
  bool get isDeletion => replacement.isEmpty;

  /// Return `true` if this edit is an insertion (no characters removed).
  bool get isInsertion => length == 0;

  /// Return `true` if this edit is a replacement.
  bool get isReplacement => length > 0 && replacement.isNotEmpty;

  @override
  String toString() {
    if (isInsertion) {
      return 'InsertText(${json.encode(replacement)})';
    } else if (isDeletion) {
      return 'DeleteText($length)';
    } else {
      return 'ReplaceText($length, ${json.encode(replacement)})';
    }
  }
}

/// Information stored along with an atomic edit indicating how it arose.
class AtomicEditInfo {
  /// A description of the change that was made.
  final NullabilityFixDescription description;

  /// The reasons for the edit.
  final Map<FixReasonTarget?, FixReasonInfo?> fixReasons;

  /// If the edit is being made due to a hint, the hint in question; otherwise
  /// `null`.
  final HintComment? hintComment;

  AtomicEditInfo(this.description, this.fixReasons, {this.hintComment});
}

/// An [EditPlan] is a builder capable of accumulating a set of edits to be
/// applied to a given [AstNode].
///
/// Examples of edits include replacing it with a different node, prefixing or
/// suffixing it with additional text, or deleting some of the text it contains.
/// When the text being produced represents an expression, [EditPlan] also keeps
/// track of the precedence of the expression and whether it ends in a
/// casade--this allows automatic insertion of parentheses when necessary, as
/// well as removal of parentheses when they become unnecessary.
///
/// Typical usage will be to produce one or more [EditPlan] objects representing
/// changes to be made to the source code, compose them together, and then call
/// [EditPlan.finalize] to convert into a representation of the concrete edits
/// that need to be made to the source file.
abstract class EditPlan {
  EditPlan._();

  /// Returns the "parent" of the node edited by this [EditPlan].  For edit
  /// plans that replace one AST node with another, this is the parent of the
  /// AST node being replaced.  For edit plans that insert or delete AST nodes,
  /// this is the parent of the AST nodes that will be inserted or deleted.
  AstNode? get parentNode;
}

/// Factory class for creating [EditPlan]s.
class EditPlanner {
  /// Indicates whether code removed by the EditPlanner should be removed by
  /// commenting it out.  A value of `false` means to actually delete the code
  /// that is removed.
  final bool? removeViaComments;

  /// The line info for the source file being edited.  This is used when
  /// removing statements that fill one or more lines, so that we can remove
  /// the indentation as well as the statement, and avoid leaving behind ugly
  /// whitespace.
  final LineInfo? lineInfo;

  /// The text of the source file being edited.  This is used when removing
  /// code, so that we can figure out if it is safe to remove adjoining
  /// whitespace.
  final String? sourceText;

  EditPlanner(this.lineInfo, this.sourceText, {this.removeViaComments = false});

  /// Creates a new edit plan that consists of executing [innerPlan], and then
  /// converting the [hint] (which precedes the node) into text that is not
  /// commented out.
  NodeProducingEditPlan acceptPrefixHint(
      NodeProducingEditPlan innerPlan, HintComment hint,
      {AtomicEditInfo? info}) {
    var affixPlan = innerPlan is _CommentAffixPlan
        ? innerPlan
        : _CommentAffixPlan(innerPlan);
    var changes = hint.changesToAccept(sourceText, info: info);
    assert(affixPlan.offset! >= _endForChanges(changes)!);
    affixPlan.offset = _offsetForChanges(changes);
    affixPlan._prefixChanges = changes + affixPlan._prefixChanges;
    return affixPlan;
  }

  /// Creates a new edit plan that consists of executing [innerPlan], and then
  /// converting the [hint] (which follows the node) into text that is not
  /// commented out.
  NodeProducingEditPlan acceptSuffixHint(
      NodeProducingEditPlan innerPlan, HintComment hint,
      {AtomicEditInfo? info}) {
    var affixPlan = innerPlan is _CommentAffixPlan
        ? innerPlan
        : _CommentAffixPlan(innerPlan);
    var changes = hint.changesToAccept(sourceText);
    assert(affixPlan.end! <= _offsetForChanges(changes)!);
    affixPlan.end = _endForChanges(changes);
    affixPlan._postfixChanges += hint.changesToAccept(sourceText, info: info);
    return affixPlan;
  }

  /// Creates a new edit plan that consists of executing [innerPlan], and then
  /// appending the given [operand], with an intervening binary [operator].
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  NodeProducingEditPlan addBinaryPostfix(
      NodeProducingEditPlan innerPlan, TokenType operator, String operand,
      {AtomicEditInfo? info}) {
    assert(innerPlan.sourceNode is Expression);
    var precedence = Precedence.forTokenType(operator);
    var isAssociative = precedence != Precedence.relational &&
        precedence != Precedence.equality &&
        precedence != Precedence.assignment;
    return surround(innerPlan,
        suffix: [AtomicEdit.insert(' ${operator.lexeme} $operand', info: info)],
        outerPrecedence: precedence,
        innerPrecedence: precedence,
        associative: isAssociative);
  }

  /// Creates a new edit plan that consists of executing [innerPlan], and then
  /// prepending the given [operand], with an intervening binary [operator].
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  ///
  /// If the expression represented by [operand] is known not to end in a
  /// cascade expression, caller may optionally set [allowCascade] to `true` to
  /// prevent a rare corner case where parentheses would be added unnecessarily.
  /// Note that it is always safe to leave [allowCascade] at its default value
  /// of `false`.
  NodeProducingEditPlan addBinaryPrefix(
      String operand, TokenType operator, NodeProducingEditPlan innerPlan,
      {AtomicEditInfo? info, bool allowCascade = false}) {
    assert(innerPlan.sourceNode is Expression);
    var precedence = Precedence.forTokenType(operator);
    var isAssociative = precedence == Precedence.assignment;
    return surround(innerPlan,
        prefix: [AtomicEdit.insert('$operand ${operator.lexeme} ', info: info)],
        outerPrecedence: precedence,
        innerPrecedence: precedence,
        associative: isAssociative,
        allowCascade: allowCascade);
  }

  /// Creates a new edit plan that consists of executing [innerPlan], and then
  /// appending the given [comment]].
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  ///
  /// Optional argument [isInformative] indicates whether the comment is simply
  /// informative, or should actually be applied to the final output (the
  /// default).
  NodeProducingEditPlan addCommentPostfix(
      NodeProducingEditPlan innerPlan, String comment,
      {AtomicEditInfo? info, bool isInformative = false}) {
    var end = innerPlan.end!;
    return surround(innerPlan, suffix: [
      AtomicEdit.insert(' ', isInformative: isInformative),
      AtomicEdit.insert(comment, info: info, isInformative: isInformative),
      if (!_isJustBefore(end, const [')', ']', '}', ';']) &&
          !_isJustBeforeWhitespace(end))
        AtomicEdit.insert(' ', isInformative: isInformative)
    ]);
  }

  /// Creates a new edit plan that consists of executing [innerPlan], and then
  /// appending the given text with postfix precedence.  This could be used, for
  /// example, to append a property access or method call.
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  NodeProducingEditPlan addPostfix(NodeProducingEditPlan innerPlan, String text,
      {AtomicEditInfo? info}) {
    assert(innerPlan.sourceNode is Expression);
    return surround(innerPlan,
        suffix: [AtomicEdit.insert(text, info: info)],
        outerPrecedence: Precedence.postfix,
        innerPrecedence: Precedence.postfix,
        associative: true);
  }

  /// Creates a new edit plan that consists of executing [innerPlan], and then
  /// appending the given postfix [operator].  This could be used, for example,
  /// to add a null check.
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  NodeProducingEditPlan addUnaryPostfix(
          NodeProducingEditPlan innerPlan, TokenType operator,
          {AtomicEditInfo? info}) =>
      addPostfix(innerPlan, operator.lexeme, info: info);

  /// Creates a new edit plan that consists of executing [innerPlan], and then
  /// prepending the given prefix [operator].
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  NodeProducingEditPlan addUnaryPrefix(
      TokenType operator, NodeProducingEditPlan innerPlan,
      {AtomicEditInfo? info}) {
    assert(innerPlan.sourceNode is Expression);
    return surround(innerPlan,
        prefix: [AtomicEdit.insert(operator.lexeme, info: info)],
        outerPrecedence: Precedence.prefix,
        innerPrecedence: Precedence.prefix,
        associative: true);
  }

  /// Creates a [_PassThroughBuilder] object based around [node].
  ///
  /// Exposed so that we can substitute a mock class in unit tests.
  @visibleForTesting
  PassThroughBuilder createPassThroughBuilder(AstNode? node) =>
      _PassThroughBuilderImpl(node);

  /// Creates a new edit plan that consists of executing [innerPlan], and then
  /// dropping the given nullability [hint].
  NodeProducingEditPlan dropNullabilityHint(
      NodeProducingEditPlan innerPlan, HintComment hint,
      {AtomicEditInfo? info}) {
    var affixPlan = innerPlan is _CommentAffixPlan
        ? innerPlan
        : _CommentAffixPlan(innerPlan);
    var changes = hint.changesToRemove(sourceText, info: info);
    assert(affixPlan.end! <= _offsetForChanges(changes)!);
    affixPlan.end = _endForChanges(changes);
    affixPlan._postfixChanges += changes;
    return affixPlan;
  }

  /// Creates a new edit plan that consists of executing [innerPlan], and then
  /// appending an informative ` `, to illustrate that the type is non-nullable.
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  NodeProducingEditPlan explainNonNullable(NodeProducingEditPlan innerPlan,
      {AtomicEditInfo? info}) {
    assert(innerPlan.sourceNode is TypeAnnotation);
    return surround(innerPlan,
        suffix: [AtomicEdit.insert(' ', info: info, isInformative: true)]);
  }

  /// Creates a new edit plan that consists of executing [innerPlan], and then
  /// removing from the source code any code that is in [sourceNode] but not in
  /// [innerPlan.sourceNode].  This is intended to be used to drop unnecessary
  /// syntax (for example, to drop an unnecessary cast).
  ///
  /// If no changes are required to the AST node that is being extracted, the
  /// caller may create innerPlan using [EditPlan.passThrough].
  ///
  /// Optional parameters [infoBefore] and [infoAfter] contain information about
  /// why the change was made.  The reason there are two of these parameters is
  /// because in general, two chunks of source code will be removed: the code
  /// coming before [innerPlan.sourceNode] and the code coming after it.
  ///
  /// [innerPlan] will be finalized as a side effect (either immediately or when
  /// the newly created plan is finalized), so it should not be re-used by the
  /// caller.
  NodeProducingEditPlan extract(
      AstNode? sourceNode, NodeProducingEditPlan innerPlan,
      {AtomicEditInfo? infoBefore,
      AtomicEditInfo? infoAfter,
      bool alwaysDelete = false}) {
    var parent = innerPlan.sourceNode!.parent;
    if (!identical(parent, sourceNode) && parent is ParenthesizedExpression) {
      innerPlan = _ProvisionalParenEditPlan(parent, innerPlan);
    }
    return _ExtractEditPlan(
        sourceNode, innerPlan, this, infoBefore, infoAfter, alwaysDelete);
  }

  /// Converts [plan] to a representation of the concrete edits that need
  /// to be made to the source file.  These edits may be converted into
  /// [SourceEdit]s using the extensions [AtomicEditList] and [AtomicEditMap].
  ///
  /// Finalizing an [EditPlan] is a destructive operation; it should not be used
  /// again after it is finalized.
  Map<int?, List<AtomicEdit>>? finalize(EditPlan plan) {
    // Convert to a plan for the top level CompilationUnit.
    var parent = plan.parentNode;
    if (parent != null) {
      var unit = parent.thisOrAncestorOfType<CompilationUnit>();
      plan = passThrough(unit, innerPlans: [plan]);
    }
    // The plan for a compilation unit should always be a NodeProducingEditPlan.
    // So we can just ask it for its changes.
    return (plan as NodeProducingEditPlan)._getChanges(false);
  }

  /// Creates a new edit plan that adds an informative message to the given
  /// [token].
  ///
  /// The created edit plan should be inserted into the list of inner plans for
  /// a pass-through plan targeted at the [containingNode].  See [passThrough].
  EditPlan informativeMessageForToken(AstNode containingNode, Token token,
      {AtomicEditInfo? info}) {
    return _TokenChangePlan(containingNode, {
      token.offset: [
        AtomicEdit.delete(token.lexeme.length, info: info, isInformative: true)
      ]
    });
  }

  /// Creates a new edit plan that inserts the text indicated by [edits] at the
  /// given [offset].
  ///
  /// The created edit will have the given [parentNode].  In general this should
  /// be the innermost AST node containing the given [offset].
  EditPlan insertText(AstNode parentNode, int offset, List<AtomicEdit> edits) {
    assert(!edits.any((edit) => !edit.isInsertion),
        'All edits should be insertions');
    return _TokenChangePlan(parentNode, {offset: edits});
  }

  /// Creates a new edit plan that consists of executing [innerPlan], and then
  /// appending a `?`, to make a type nullable.
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  NodeProducingEditPlan makeNullable(NodeProducingEditPlan innerPlan,
      {AtomicEditInfo? info}) {
    var sourceNode = innerPlan.sourceNode;
    assert(sourceNode is TypeAnnotation ||
        sourceNode is FunctionTypedFormalParameter ||
        (sourceNode is FieldFormalParameter && sourceNode.parameters != null));
    return surround(innerPlan, suffix: [AtomicEdit.insert('?', info: info)]);
  }

  /// Creates a new edit plan that makes no changes to [node], but may make
  /// changes to some of its descendants (specified via [innerPlans]).
  ///
  /// Note that the [innerPlans] must be specified in document order.
  ///
  /// All plans in [innerPlans] will be finalized as a side effect (either
  /// immediately or when the newly created plan is finalized), so they should
  /// not be re-used by the caller.
  NodeProducingEditPlan passThrough(AstNode? node,
      {Iterable<EditPlan> innerPlans = const []}) {
    // It's possible that some of the inner plans are nested more deeply within
    // [node] than others.  We want to group these inner plans together into
    // pass through plans at each level in the AST until we bubble up to [node].
    // To do so, we form a stack of [_PassThroughBuilder] objects to handle each
    // level of AST depth, where the first entry in the stack corresponds to
    // [node], and each subsequent entry will correspond to a child of the
    // previous.
    var builderStack = [createPassThroughBuilder(node)];
    var ancestryPath = <AstNode?>[];
    for (var plan in innerPlans) {
      // Compute the ancestryPath (the path from `plan.parentNode` up to
      // `node`).  Note that whereas builderStack walks stepwise down the AST,
      // ancestryStack will walk stepwise up the AST, with the last entry of
      // ancestryStack corresponding to the first entry of builderStack.  We
      // re-use the same list for each loop iteration to reduce GC load.
      ancestryPath.clear();
      for (var parent = plan.parentNode;
          !identical(parent, node);
          parent = parent!.parent) {
        ancestryPath.add(parent);
      }
      ancestryPath.add(node);
      // Find the deepest entry in builderStack that's on the ancestryPath.
      var builderIndex = _findMatchingBuilder(builderStack, ancestryPath);
      // We're finished with all builders beyond that entry.
      while (builderStack.length > builderIndex + 1) {
        var passThrough = builderStack.removeLast().finish(this);
        builderStack.last.add(passThrough);
      }
      // And we may need to add new builders to make our way down to
      // `plan.parentNode`.
      while (builderStack.length < ancestryPath.length) {
        // Since builderStack and ancestryPath walk in different directions
        // through the AST, when building entry builderIndex, we need to count
        // backwards from the end of ancestryPath to figure out which node to
        // associate the builder with.
        builderStack.add(createPassThroughBuilder(
            ancestryPath[ancestryPath.length - builderStack.length - 1]));
      }
      // Now the deepest entry in the builderStack corresponds to
      // `plan.parentNode`, so we can add the plan to it.
      builderStack.last.add(plan);
    }
    // We're now finished with all builders.
    while (true) {
      var passThrough = builderStack.removeLast().finish(this);
      if (builderStack.isEmpty) return passThrough;
      builderStack.last.add(passThrough);
    }
  }

  /// Creates a new edit plan that removes [sourceNode] from the AST.
  ///
  /// [sourceNode] must be one element of a variable length sequence maintained
  /// by [sourceNode]'s parent (for example, a statement in a block, an element
  /// in a list, a declaration in a class, etc.).  If it is not, an exception is
  /// thrown.
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  EditPlan removeNode(AstNode sourceNode, {AtomicEditInfo? info}) {
    var result = tryRemoveNode(sourceNode, info: info);
    if (result == null) {
      var parent = sourceNode.parent;
      throw StateError(
          'Cannot remove node whose parent is of type ${parent.runtimeType}');
    }
    return result;
  }

  /// Creates a new edit plan that removes a sequence of adjacent nodes from
  /// the AST, starting with [firstSourceNode] and ending with [lastSourceNode].
  ///
  /// [firstSourceNode] and [lastSourceNode] must be elements of a variable
  /// length sequence maintained by their (common) parent (for example,
  /// statements in a block, elements in a list, declarations in a class, etc.)
  /// [lastSourceNode] must come after [firstSourceNode].
  ///
  /// If [firstSourceNode] and [lastSourceNode] are the same node, then the
  /// behavior is identical to [removeNode] (i.e. just the one node is removed).
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  EditPlan removeNodes(AstNode firstSourceNode, AstNode lastSourceNode,
      {AtomicEditInfo? info}) {
    var parent = firstSourceNode.parent;
    assert(identical(lastSourceNode.parent, parent));
    var sequenceNodes = _computeSequenceNodes(parent);
    if (sequenceNodes == null) {
      throw StateError(
          'Cannot remove node whose parent is of type ${parent.runtimeType}');
    }
    var firstIndex = sequenceNodes.indexOf(firstSourceNode);
    assert(firstIndex != -1);
    var lastIndex = sequenceNodes.indexOf(lastSourceNode, firstIndex);
    assert(lastIndex >= firstIndex);
    return _RemoveEditPlan(parent, firstIndex, lastIndex, info);
  }

  /// Creates a new edit plan that removes null awareness from [sourceNode].
  ///
  /// The created edit plan should be inserted into the list of inner plans for
  /// a pass-through plan targeted at the source node.  See [passThrough].
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  ///
  /// Optional argument [isInformative] indicates whether the comment is simply
  /// informative, or should actually be applied to the final output (the
  /// default).
  EditPlan removeNullAwareness(Expression sourceNode,
      {AtomicEditInfo? info, bool isInformative = false}) {
    Token? operator;
    if (sourceNode is MethodInvocation) {
      operator = sourceNode.operator;
    } else if (sourceNode is PropertyAccess) {
      operator = sourceNode.operator;
    } else {
      throw StateError(
          'Tried to remove null awareness from an unexpected node type: '
          '${sourceNode.runtimeType}');
    }
    assert(operator!.type == TokenType.QUESTION_PERIOD);
    return _TokenChangePlan(sourceNode, {
      operator!.offset: [
        AtomicEdit.delete(1, info: info, isInformative: isInformative)
      ]
    });
  }

  /// Creates a new edit plan that replaces the contents of [sourceNode] with
  /// the given [replacement] text.
  ///
  /// If the edit plan is going to be used in a context where an expression is
  /// expected, additional arguments should be provided to control the behavior
  /// of parentheses insertion and deletion: [precedence] indicates the
  /// precedence of the resulting expression.  [endsInCascade] indicates whether
  /// the resulting plan will end in a cascade.
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  NodeProducingEditPlan replace(
      AstNode sourceNode, List<AtomicEdit> replacement,
      {Precedence precedence = Precedence.primary,
      bool endsInCascade = false,
      AtomicEditInfo? info}) {
    assert(!replacement.any((edit) => !edit.isInsertion),
        'All edits should be insertions');
    return _SimpleEditPlan(sourceNode, precedence, endsInCascade, {
      sourceNode.offset: [
        AtomicEdit.delete(sourceNode.length, info: info),
        ...replacement
      ]
    });
  }

  /// Creates a new edit plan that replaces [token] with the given [replacement]
  /// text.
  ///
  /// [parentNode] should be the innermost AST node containing [token].
  EditPlan replaceToken(AstNode parentNode, Token token, String replacement,
      {AtomicEditInfo? info}) {
    return _TokenChangePlan(parentNode, {
      token.offset: [AtomicEdit.replace(token.length, replacement, info: info)]
    });
  }

  /// Creates a new edit plan that consists of executing [innerPlan], and then
  /// surrounding it with [prefix] and [suffix] text.  This could be used, for
  /// example, to add a cast.
  ///
  /// Note that it's tricky to get precedence correct.  When possible, use one
  /// of the other methods in this class, such as [addBinaryPostfix],
  /// [addBinaryPrefix], [addUnaryPostfix], or [addUnaryPrefix].
  ///
  /// If the edit plan is going to be used in a context where an expression is
  /// expected, additional arguments should be provided to control the behavior
  /// of parentheses insertion and deletion: [outerPrecedence] indicates the
  /// precedence of the resulting expression.  [innerPrecedence] indicates the
  /// precedence that is required for [innerPlan].  [associative] indicates
  /// whether it is allowed for [innerPlan]'s precedence to match
  /// [innerPrecedence].  [allowCascade] indicates whether [innerPlan] can end
  /// in a cascade section without requiring parentheses.  [endsInCascade]
  /// indicates whether the resulting plan will end in a cascade.
  ///
  /// So, for example, if it is desired to append the suffix ` + foo` to an
  /// expression, specify `Precedence.additive` for [outerPrecedence] and
  /// [innerPrecedence], and `true` for [associative] (since addition associates
  /// to the left).
  ///
  /// Note that [endsInCascade] is ignored if there is no [suffix] (since in
  /// this situation, whether the final plan ends in a cascade section will be
  /// determined by [innerPlan]).
  NodeProducingEditPlan surround(NodeProducingEditPlan innerPlan,
      {List<AtomicEdit>? prefix,
      List<AtomicEdit>? suffix,
      Precedence outerPrecedence = Precedence.primary,
      Precedence innerPrecedence = Precedence.none,
      bool associative = false,
      bool allowCascade = false,
      bool endsInCascade = false}) {
    var parensNeeded = innerPlan._parensNeeded(
        threshold: innerPrecedence,
        associative: associative,
        allowCascade: allowCascade);
    var innerChanges =
        innerPlan._getChanges(parensNeeded) ?? <int, List<AtomicEdit>>{};
    if (prefix != null) {
      (innerChanges[innerPlan.offset] ??= []).insertAll(0, prefix);
    }
    if (suffix != null) {
      (innerChanges[innerPlan.end] ??= []).addAll(suffix);
    }
    return _SimpleEditPlan(
        innerPlan.sourceNode,
        outerPrecedence,
        suffix == null
            ? innerPlan.endsInCascade && !parensNeeded
            : endsInCascade,
        innerChanges);
  }

  /// Tries to create a new edit plan that removes [node] from the AST.
  ///
  /// [node] must be one element of a variable length sequence maintained by
  /// [node]'s parent (for example, a statement in a block, an element in a
  /// list, a declaration in a class, etc.).  If it is not, `null` is returned.
  ///
  /// Optional argument [info] contains information about why the change was
  /// made.
  EditPlan? tryRemoveNode(AstNode sourceNode,
      {List<AstNode>? sequenceNodes, AtomicEditInfo? info}) {
    var parent = sourceNode.parent;
    sequenceNodes ??= _computeSequenceNodes(parent);
    if (sequenceNodes == null) {
      return null;
    }
    var index = sequenceNodes.indexOf(sourceNode);
    assert(index != -1);
    return _RemoveEditPlan(parent, index, index, info);
  }

  /// Walks backward through the source text, starting at [offset] and stopping
  /// before passing any non-whitespace character.
  ///
  /// Does not walk further than [limit] (which should be less than or equal to
  /// [offset]).
  int _backAcrossWhitespace(int offset, int limit) {
    assert(limit <= offset);
    return limit + sourceText!.substring(limit, offset).trimRight().length;
  }

  /// Walks backward through the source text, starting at [offset] and stopping
  /// when the beginning of the line is reached.
  ///
  /// If [offset] is at the beginning of the line, it is returned unchanged.
  int _backToLineStart(int offset) {
    var lineNumber = lineInfo!.getLocation(offset).lineNumber;
    // lineNumber is one-based, but lineInfo.lineStarts expects a zero-based
    // index, so we need `lineInfo.lineStarts[lineNumber - 1]`.
    return lineInfo!.lineStarts[lineNumber - 1];
  }

  int? _endForChanges(Map<int?, List<AtomicEdit>> changes) {
    int? result;
    for (var entry in changes.entries) {
      var end = entry.key;
      for (var edit in entry.value) {
        end = end! + edit.length;
      }
      if (result == null || end! > result) result = end;
    }
    return result;
  }

  /// Finds the deepest entry in [builderStack] that matches an entry in
  /// [ancestryStack], taking advantage of the fact that [builderStack] walks
  /// stepwise down the AST, and [ancestryStack] walks stepwise up the AST, with
  /// the last entry of [ancestryStack] corresponding to the first entry of
  /// [builderStack].
  int _findMatchingBuilder(
      List<PassThroughBuilder> builderStack, List<AstNode?> ancestryStack) {
    var builderIndex = builderStack.length - 1;
    while (builderIndex > 0) {
      var ancestryIndex = ancestryStack.length - builderIndex - 1;
      if (ancestryIndex >= 0 &&
          identical(
              builderStack[builderIndex].node, ancestryStack[ancestryIndex])) {
        break;
      }
      --builderIndex;
    }
    return builderIndex;
  }

  /// Walks forward through the source text, starting at [offset] and stopping
  /// before passing any non-whitespace character.
  ///
  /// Does not walk further than [limit] (which should be greater than or equal
  /// to [offset]).
  int _forwardAcrossWhitespace(int offset, int limit) {
    return limit - sourceText!.substring(offset, limit).trimLeft().length;
  }

  /// Walks forward through the source text, starting at [offset] and stopping
  /// at the beginning of the next line (or at the end of the document, if this
  /// line is the last line).
  int _forwardToLineEnd(int offset) {
    int lineNumber = lineInfo!.getLocation(offset).lineNumber;
    // lineNumber is one-based, so if it is equal to
    // `lineInfo.lineStarts.length`, then we are on the last line.
    if (lineNumber >= lineInfo!.lineStarts.length) {
      return sourceText!.length;
    }
    // lineInfo.lineStarts expects a zero-based index, so
    // `lineInfo.lineStarts[lineNumber]` gives us the beginning of the next
    // line.
    return lineInfo!.lineStarts[lineNumber];
  }

  /// Determines whether the given source [offset] comes just after one of the
  /// characters in [characters].
  bool _isJustAfter(int offset, List<String> characters) =>
      offset > 0 && characters.contains(sourceText![offset - 1]);

  /// Determines whether the given source [end] comes just before one of the
  /// characters in [characters].
  bool _isJustBefore(int end, List<String> characters) =>
      end < sourceText!.length && characters.contains(sourceText![end]);

  /// Determines whether the given source [end] comes just before whitespace.
  /// For the purpose of this check, the end of the file is considered
  /// whitespace.
  bool _isJustBeforeWhitespace(int end) =>
      end >= sourceText!.length || _isWhitespaceRange(end, end + 1);

  /// Determines if the characters between [offset] and [end] in the source text
  /// are all whitespace characters.
  bool _isWhitespaceRange(int offset, int end) {
    return sourceText!.substring(offset, end).trimRight().isEmpty;
  }

  int? _offsetForChanges(Map<int?, List<AtomicEdit>> changes) {
    int? result;
    for (var key in changes.keys) {
      if (result == null || key! < result) result = key;
    }
    return result;
  }

  /// If the given [node] maintains a variable-length sequence of child nodes,
  /// returns a list containing those child nodes, otherwise returns `null`.
  ///
  /// The returned list may or may not be the exact list used by the node to
  /// maintain its child nodes.  For example, [CompilationUnit] maintains its
  /// directives and declarations in separate lists, so the returned list is
  /// a new list containing both directives and declarations.
  static List<AstNode>? _computeSequenceNodes(AstNode? node) {
    if (node is Block) {
      return node.statements;
    } else if (node is ListLiteral) {
      return node.elements;
    } else if (node is SetOrMapLiteral) {
      return node.elements;
    } else if (node is ArgumentList) {
      return node.arguments;
    } else if (node is FormalParameter) {
      return node.metadata;
    } else if (node is FormalParameterList) {
      return node.parameters;
    } else if (node is VariableDeclarationList) {
      return node.variables;
    } else if (node is TypeArgumentList) {
      return node.arguments;
    } else if (node is TypeParameterList) {
      return node.typeParameters;
    } else if (node is EnumDeclaration) {
      return node.constants;
    } else if (node is ClassDeclaration) {
      return node.members;
    } else if (node is CompilationUnit) {
      return [...node.directives, ...node.declarations];
    } else if (node is MethodDeclaration) {
      return node.metadata;
    } else {
      return null;
    }
  }
}

/// Specialization of [EditPlan] for the situation where the text being produced
/// represents a single expression (i.e. an expression, statement, class
/// declaration, etc.)
abstract class NodeProducingEditPlan extends EditPlan {
  /// The AST node to which the edit plan applies.
  final AstNode? sourceNode;

  NodeProducingEditPlan._(this.sourceNode) : super._();

  /// Offset just past the end of the source text affected by this plan.
  int? get end => sourceNode!.end;

  /// If the result of executing this [EditPlan] will be an expression,
  /// indicates whether the expression will end in an unparenthesized cascade.
  @visibleForTesting
  bool get endsInCascade;

  /// Offset of the start of the source text affected by this plan.
  int? get offset => sourceNode!.offset;

  @override
  AstNode? get parentNode => sourceNode!.parent;

  /// Determines whether the text produced by this [EditPlan] would need
  /// parentheses if it were to be used as a replacement for its [sourceNode].
  ///
  /// If this [EditPlan] would produce an expression that ends in a cascade, it
  /// will be necessary to search the [sourceNode]'s ancestors to see if any of
  /// them represents a cascade section (and hence, parentheses are required).
  /// If a non-null value is provided for [cascadeSearchLimit], it is the most
  /// distant ancestor that will be searched.
  @visibleForTesting
  bool? parensNeededFromContext(AstNode? cascadeSearchLimit) {
    if (sourceNode is! Expression) return false;
    var parent = sourceNode!.parent;
    return parent == null
        ? false
        : parent
            .accept(_ParensNeededFromContextVisitor(this, cascadeSearchLimit));
  }

  /// Modifies [changes] to insert parentheses enclosing the [sourceNode].  This
  /// works even if [changes] already includes modifications at the beginning or
  /// end of [sourceNode]--the parentheses are inserted outside of any
  /// pre-existing changes.
  Map<int?, List<AtomicEdit>>? _createAddParenChanges(
      Map<int?, List<AtomicEdit>>? changes) {
    changes ??= {};
    (changes[offset] ??= []).insert(0, const AtomicEdit.insert('('));
    (changes[end] ??= []).add(const AtomicEdit.insert(')'));
    return changes;
  }

  /// Computes the necessary set of [changes] for this [EditPlan], either
  /// including or not including parentheses depending on the value of [parens].
  ///
  /// An [EditPlan] for which [_getChanges] has been called is considered to be
  /// finalized.
  Map<int?, List<AtomicEdit>>? _getChanges(bool parens);

  /// Determines if the text that would be produced by [EditPlan] needs to be
  /// surrounded by parens, based on the context in which it will be used.
  bool _parensNeeded(
      {required Precedence threshold,
      bool associative = false,
      bool allowCascade = false});
}

/// Data structure that accumulates together a set of [EditPlans] sharing a
/// common parent node, and groups them together into an [EditPlan] with a
/// parent node one level up the AST.
@visibleForTesting
abstract class PassThroughBuilder {
  /// The AST node that is the parent of all the [EditPlan]s being accumulated.
  AstNode? get node;

  /// Accumulate another edit plan.
  void add(EditPlan innerPlan);

  /// Called when no more edit plans need to be added.  Returns the final
  /// [EditPlan].
  NodeProducingEditPlan finish(EditPlanner planner);
}

/// [EditPlan] that wraps an inner plan with optional prefix and suffix changes.
class _CommentAffixPlan extends _NestedEditPlan {
  Map<int?, List<AtomicEdit>>? _prefixChanges;

  Map<int?, List<AtomicEdit>>? _postfixChanges;

  @override
  int? offset;

  @override
  int? end;

  _CommentAffixPlan(NodeProducingEditPlan innerPlan)
      : offset = innerPlan.offset,
        end = innerPlan.end,
        super(innerPlan.sourceNode, innerPlan);

  @override
  Map<int?, List<AtomicEdit>>? _getChanges(bool parens) =>
      _prefixChanges + innerPlan._getChanges(parens) + _postfixChanges;
}

/// Visitor that determines whether a given [AstNode] ends in a cascade.
class _EndsInCascadeVisitor extends UnifyingAstVisitor<void> {
  bool endsInCascade = false;

  final int end;

  _EndsInCascadeVisitor(this.end);

  @override
  void visitCascadeExpression(CascadeExpression node) {
    if (node.end != end) return;
    endsInCascade = true;
  }

  @override
  void visitNode(AstNode node) {
    if (node.end != end) return;
    node.visitChildren(this);
  }
}

/// [EditPlan] representing an "extraction" of an inner AST node, e.g. replacing
/// `a + b * c` with `b + c`.
///
/// Defers computation of whether parentheses are needed to the inner plan.
class _ExtractEditPlan extends _NestedEditPlan {
  final EditPlanner _planner;

  final AtomicEditInfo? _infoBefore;

  final AtomicEditInfo? _infoAfter;

  /// Whether text-to-be-removed should be removed (as opposed to commented out)
  /// even when [EditPlan.removeViaComments] is true.
  final bool _alwaysDelete;

  _ExtractEditPlan(AstNode? sourceNode, NodeProducingEditPlan innerPlan,
      this._planner, this._infoBefore, this._infoAfter, this._alwaysDelete)
      : super(sourceNode, innerPlan);

  @override
  Map<int?, List<AtomicEdit>>? _getChanges(bool parens) {
    // Get the inner changes.  If they already have provisional parens and we
    // need them, use them.
    var useInnerParens = parens && innerPlan is _ProvisionalParenEditPlan;
    var changes = innerPlan._getChanges(useInnerParens);
    // TODO(paulberry): don't remove comments
    _RemovalStyle leadingChangeRemovalStyle;
    _RemovalStyle trailingChangeRemovalStyle;
    if (_alwaysDelete || !_planner.removeViaComments!) {
      leadingChangeRemovalStyle = _RemovalStyle.delete;
      trailingChangeRemovalStyle = _RemovalStyle.delete;
    } else {
      leadingChangeRemovalStyle = _RemovalStyle.commentSpace;
      trailingChangeRemovalStyle = _RemovalStyle.spaceComment;
    }
    // Extract the inner expression.
    changes = _removeCode(offset!, innerPlan.offset!, leadingChangeRemovalStyle,
            _infoBefore) +
        changes +
        _removeCode(
            innerPlan.end!, end!, trailingChangeRemovalStyle, _infoAfter);
    // Apply parens if needed.
    if (parens && !useInnerParens) {
      changes = _createAddParenChanges(changes);
    }
    return changes;
  }
}

/// [EditPlan] representing additional edits performed on the result of a
/// previous [innerPlan].
///
/// By default, defers computation of whether parentheses are needed to the
/// inner plan.
abstract class _NestedEditPlan extends NodeProducingEditPlan {
  final NodeProducingEditPlan innerPlan;

  _NestedEditPlan(AstNode? sourceNode, this.innerPlan) : super._(sourceNode);

  @override
  bool get endsInCascade => innerPlan.endsInCascade;

  @override
  bool _parensNeeded(
          {required Precedence threshold,
          bool associative = false,
          bool allowCascade = false}) =>
      innerPlan._parensNeeded(
          threshold: threshold,
          associative: associative,
          allowCascade: allowCascade);
}

/// Visitor that determines whether an [_editPlan] needs to be parenthesized
/// based on the context surrounding its source node.  To use this class, visit
/// the source node's parent.
class _ParensNeededFromContextVisitor extends GeneralizingAstVisitor<bool> {
  final NodeProducingEditPlan _editPlan;

  /// If [_editPlan] would produce an expression that ends in a cascade, it
  /// will be necessary to search the [_target]'s ancestors to see if any of
  /// them represents a cascade section (and hence, parentheses are required).
  /// If a non-null value is provided for [_cascadeSearchLimit], it is the most
  /// distant ancestor that will be searched.
  final AstNode? _cascadeSearchLimit;

  _ParensNeededFromContextVisitor(this._editPlan, this._cascadeSearchLimit) {
    assert(_target is Expression);
  }

  AstNode? get _target => _editPlan.sourceNode;

  @override
  bool visitAsExpression(AsExpression node) {
    if (identical(_target, node.expression)) {
      return _editPlan._parensNeeded(threshold: Precedence.relational);
    } else {
      return false;
    }
  }

  @override
  bool visitAssignmentExpression(AssignmentExpression node) {
    if (identical(_target, node.rightHandSide)) {
      return _editPlan._parensNeeded(
          threshold: Precedence.none,
          allowCascade: !_isRightmostDescendantOfCascadeSection(node));
    } else {
      return false;
    }
  }

  @override
  bool visitAwaitExpression(AwaitExpression node) {
    assert(identical(_target, node.expression));
    return _editPlan._parensNeeded(
        threshold: Precedence.prefix, associative: true);
  }

  @override
  bool visitBinaryExpression(BinaryExpression node) {
    var precedence = node.precedence;
    return _editPlan._parensNeeded(
        threshold: precedence,
        associative: identical(_target, node.leftOperand) &&
            precedence != Precedence.relational &&
            precedence != Precedence.equality);
  }

  @override
  bool visitCascadeExpression(CascadeExpression node) {
    if (identical(_target, node.target)) {
      return _editPlan._parensNeeded(
          threshold: Precedence.cascade, associative: true, allowCascade: true);
    } else {
      return false;
    }
  }

  @override
  bool visitConditionalExpression(ConditionalExpression node) {
    if (identical(_target, node.condition)) {
      return _editPlan._parensNeeded(threshold: Precedence.conditional);
    } else {
      return _editPlan._parensNeeded(threshold: Precedence.none);
    }
  }

  @override
  bool visitExtensionOverride(ExtensionOverride node) {
    assert(identical(_target, node.extensionName));
    return _editPlan._parensNeeded(
        threshold: Precedence.postfix, associative: true);
  }

  @override
  bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
    assert(identical(_target, node.function));
    return _editPlan._parensNeeded(
        threshold: Precedence.postfix, associative: true);
  }

  @override
  bool visitIndexExpression(IndexExpression node) {
    if (identical(_target, node.target)) {
      return _editPlan._parensNeeded(
          threshold: Precedence.postfix, associative: true);
    } else {
      return false;
    }
  }

  @override
  bool visitIsExpression(IsExpression node) {
    if (identical(_target, node.expression)) {
      return _editPlan._parensNeeded(threshold: Precedence.relational);
    } else {
      return false;
    }
  }

  @override
  bool visitMethodInvocation(MethodInvocation node) {
    // Note: it's tempting to assert identical(_target, node.target) here,
    // because in a method invocation like `x.m(...)`, the only AST node that's
    // a child of the method invocation and semantically represents an
    // expression is the target (`x` in this example).  Unfortunately, that
    // doesn't work, because even though `m` isn't semantically an expression,
    // it's represented in the analyzer AST as an identifier and Identifier
    // implements Expression.  So we have to handle both `x` and `m`.
    //
    // Fortunately we don't have to do any extra work to handle `m`, because it
    // will always be an identifier, hence it will always be high precedence and
    // it will never require parentheses.  So we just do the correct logic for
    // the target, without asserting.
    return _editPlan._parensNeeded(
        threshold: Precedence.postfix, associative: true);
  }

  @override
  bool visitNode(AstNode node) {
    return false;
  }

  @override
  bool visitParenthesizedExpression(ParenthesizedExpression node) {
    assert(identical(_target, node.expression));
    return false;
  }

  @override
  bool visitPostfixExpression(PostfixExpression node) {
    assert(identical(_target, node.operand));
    return _editPlan._parensNeeded(
        threshold: Precedence.postfix, associative: true);
  }

  @override
  bool visitPrefixedIdentifier(PrefixedIdentifier node) {
    if (identical(_target, node.prefix)) {
      return _editPlan._parensNeeded(
          threshold: Precedence.postfix, associative: true);
    } else {
      assert(identical(_target, node.identifier));
      return _editPlan._parensNeeded(
          threshold: Precedence.primary, associative: true);
    }
  }

  @override
  bool visitPrefixExpression(PrefixExpression node) {
    assert(identical(_target, node.operand));
    return _editPlan._parensNeeded(
        threshold: Precedence.prefix, associative: true);
  }

  @override
  bool visitPropertyAccess(PropertyAccess node) {
    if (identical(_target, node.target)) {
      return _editPlan._parensNeeded(
          threshold: Precedence.postfix, associative: true);
    } else {
      assert(identical(_target, node.propertyName));
      return _editPlan._parensNeeded(
          threshold: Precedence.primary, associative: true);
    }
  }

  @override
  bool visitThrowExpression(ThrowExpression node) {
    assert(identical(_target, node.expression));
    return _editPlan._parensNeeded(
        threshold: Precedence.assignment,
        associative: true,
        allowCascade: !_isRightmostDescendantOfCascadeSection(node));
  }

  /// Searches the ancestors of [node] to determine if it is the rightmost
  /// descendant of a cascade section.  (If this is the case, parentheses may be
  /// required).  The search is limited by [_cascadeSearchLimit].
  bool _isRightmostDescendantOfCascadeSection(AstNode node) {
    while (true) {
      var parent = node.parent;
      if (parent == null) {
        // No more ancestors, so we can stop.
        return false;
      }
      if (parent is CascadeExpression && !identical(parent.target, node)) {
        // Node is a cascade section.
        return true;
      }
      if (parent.end != node.end) {
        // Node is not the rightmost descendant of parent, so we can stop.
        return false;
      }
      if (identical(node, _cascadeSearchLimit)) {
        // We reached the cascade search limit so we don't have to look any
        // further.
        return false;
      }
      node = parent;
    }
  }
}

class _PassThroughBuilderImpl implements PassThroughBuilder {
  @override
  final AstNode? node;

  /// The [EditPlan]s accumulated so far.
  final List<EditPlan> innerPlans = [];

  /// The [EditPlanner] currently being used to create this
  /// [_PassThroughEditPlan].
  late EditPlanner planner;

  /// Determination of whether the resulting [EditPlan] will end in a cascade,
  /// or `null` if it is not yet known.
  bool? endsInCascade;

  /// The set of changes aggregated together so far.
  Map<int?, List<AtomicEdit>>? changes;

  /// If [node] is a sequence, the list of its child nodes.  Otherwise `null`.
  List<AstNode>? sequenceNodes;

  /// If [node] is a sequence that uses separators (e.g. a list literal, which
  /// uses comma separators), a list of its separators.  Otherwise `null`.
  List<Token>? separators;

  /// If [separators] is non-null, and nodes are being removed from the
  /// sequence, this boolean indicates whether each node should be removed along
  /// with the separator that *precedes* it.
  ///
  /// `false` indicates that each node should be removed along with the
  /// separator that *follows* it.
  bool removeLeadingSeparators = false;

  _PassThroughBuilderImpl(this.node);

  @override
  void add(EditPlan innerPlan) {
    assert(identical(innerPlan.parentNode, node));
    innerPlans.add(innerPlan);
  }

  @override
  NodeProducingEditPlan finish(EditPlanner planner) {
    this.planner = planner;
    var node = this.node;
    if (node is ParenthesizedExpression) {
      assert(innerPlans.length <= 1);
      var innerPlan = innerPlans.isEmpty
          ? planner.passThrough(node.expression)
          : innerPlans[0];
      if (innerPlan is NodeProducingEditPlan) {
        return _ProvisionalParenEditPlan(node, innerPlan);
      }
    }

    // Make a provisional determination of whether the result will end in a
    // cascade.
    // TODO(paulberry): can we make some of these computations lazy?
    endsInCascade = node is CascadeExpression ? true : null;
    sequenceNodes = EditPlanner._computeSequenceNodes(node);
    separators =
        sequenceNodes == null ? null : _computeSeparators(node, sequenceNodes);
    _processPlans();
    Precedence precedence;
    if (node is FunctionExpression && node.body is ExpressionFunctionBody) {
      // To avoid ambiguities when adding `as Type` after a function expression,
      // assume assignment precedence.
      // TODO(paulberry): this is a hack - see
      // https://github.com/dart-lang/sdk/issues/40536
      precedence = Precedence.assignment;
    } else if (node is Expression) {
      precedence = node.precedence;
    } else {
      precedence = Precedence.primary;
    }
    return _PassThroughEditPlan._(
        node, precedence, endsInCascade ?? node!.endsInCascade, changes);
  }

  /// Starting at index [planIndex] of [innerPlans] (whose value is [plan]),
  /// scans forward to see if there is a range of inner plans that remove a
  /// contiguous range of AST nodes.
  ///
  /// Returns the index into [innerPlans] of the last such contiguous plan, or
  /// [planIndex] if a contiguous range of removals wasn't found.
  int _findConsecutiveRemovals(int planIndex, _RemoveEditPlan plan) {
    assert(identical(innerPlans[planIndex], plan));
    var lastRemovePlanIndex = planIndex;
    var lastRemoveEditPlan = plan;
    while (lastRemovePlanIndex + 1 < innerPlans.length) {
      var nextPlan = innerPlans[lastRemovePlanIndex + 1];
      if (nextPlan is _RemoveEditPlan) {
        if (nextPlan.firstChildIndex == lastRemoveEditPlan.lastChildIndex + 1) {
          // Removals are consecutive.  Slurp up.
          lastRemovePlanIndex++;
          lastRemoveEditPlan = nextPlan;
          continue;
        }
      }
      break;
    }
    return lastRemovePlanIndex;
  }

  /// Processes an inner plan of type [NodeProducingEditPlan].
  void _handleNodeProducingEditPlan(NodeProducingEditPlan innerPlan) {
    var parensNeeded = innerPlan.parensNeededFromContext(node)!;
    assert(_checkParenLogic(innerPlan, parensNeeded));
    if (!parensNeeded && innerPlan is _ProvisionalParenEditPlan) {
      var innerInnerPlan = innerPlan.innerPlan;
      if (innerInnerPlan is _PassThroughEditPlan) {
        // Input source code had redundant parens, so keep them.
        parensNeeded = true;
      }
    }
    changes += innerPlan._getChanges(parensNeeded);
    // Note: we use innerPlan.sourceNode.end here instead of innerPlan.end,
    // because what we care about is the input grammar, so we don't want to be
    // fooled by any whitespace or comments included in the innerPlan.
    if (endsInCascade == null && innerPlan.sourceNode!.end == node!.end) {
      endsInCascade = !parensNeeded && innerPlan.endsInCascade;
    }
  }

  /// Processes one or more inner plans of type [_RemoveEditPlan], and returns
  /// an updated [planIndex] pointing to the next inner plan to be processed.
  ///
  /// [firstPlan] should be the plan located at index [planIndex].
  int _handleRemoveEditPlans(_RemoveEditPlan firstPlan, int planIndex) {
    assert(identical(innerPlans[planIndex], firstPlan));
    assert(identical(firstPlan.parentNode, node));
    var firstPlanIndex = planIndex;
    var lastPlanIndex = _findConsecutiveRemovals(firstPlanIndex, firstPlan);
    var lastPlan = innerPlans[lastPlanIndex] as _RemoveEditPlan;
    int lastRemovalEnd;
    int nextRemovalOffset;
    removeLeadingSeparators = separators != null &&
        firstPlan.firstChildIndex != 0 &&
        lastPlan.lastChildIndex >= separators!.length;
    if (planner.removeViaComments!) {
      nextRemovalOffset = _removalOffset(firstPlan);
      lastRemovalEnd = _removalEnd(lastPlan);
    } else {
      var firstRemovalOffset = _removalOffset(firstPlan);
      var firstLineStart = planner._backToLineStart(firstRemovalOffset);
      var startsOnLineBoundary =
          planner._isWhitespaceRange(firstLineStart, firstRemovalOffset);
      lastRemovalEnd = _removalEnd(lastPlan);
      var lastLineEnd = planner._forwardToLineEnd(lastRemovalEnd);
      var endsOnLineBoundary =
          planner._isWhitespaceRange(lastRemovalEnd, lastLineEnd);
      if (!endsOnLineBoundary) {
        // E.g. removing B and C, and possibly A, from `A; B; C; D;`.  Want to
        // remove the whitespace after `C;`.
        lastRemovalEnd =
            planner._forwardAcrossWhitespace(lastRemovalEnd, lastLineEnd);
      } else if (!startsOnLineBoundary) {
        // E.g. removing B and C from `A; B; C;`.  Want to remove the whitespace
        // before `B`.
        firstRemovalOffset =
            planner._backAcrossWhitespace(firstRemovalOffset, firstLineStart);
      } else {
        // Removing whole lines.
        firstRemovalOffset = firstLineStart;
        lastRemovalEnd = lastLineEnd;
      }
      if (firstPlanIndex == 0 && lastPlanIndex == sequenceNodes!.length - 1) {
        // We're removing everything.  Try to remove additional whitespace so
        // that we're left with just `()`, `{}`, or `[]`.
        var candidateFirstRemovalOffset = planner._backAcrossWhitespace(
            firstRemovalOffset, min(firstRemovalOffset, node!.offset));
        if (planner
            ._isJustAfter(candidateFirstRemovalOffset, const ['(', '[', '{'])) {
          var candidateLastRemovalEnd =
              planner._forwardAcrossWhitespace(lastRemovalEnd, node!.end);
          if (planner
              ._isJustBefore(candidateLastRemovalEnd, const [')', ']', '}'])) {
            firstRemovalOffset = candidateFirstRemovalOffset;
            lastRemovalEnd = candidateLastRemovalEnd;
          }
        }
      }
      nextRemovalOffset = firstRemovalOffset;
    }

    for (; planIndex <= lastPlanIndex; planIndex++) {
      var innerPlan = innerPlans[planIndex] as _RemoveEditPlan;
      var offset = nextRemovalOffset;
      int end;
      if (planIndex == lastPlanIndex) {
        end = lastRemovalEnd;
      } else {
        var nextInnerPlan = innerPlans[planIndex + 1] as _RemoveEditPlan;
        assert(identical(nextInnerPlan.parentNode, node));
        nextRemovalOffset = _removalOffset(nextInnerPlan);
        if (planner.removeViaComments!) {
          end = _removalEnd(innerPlans[planIndex] as _RemoveEditPlan);
        } else {
          var lineStart = planner._backToLineStart(nextRemovalOffset);
          if (planner._isWhitespaceRange(lineStart, nextRemovalOffset)) {
            // The next node to remove starts at the beginning of a line
            // (possibly with whitespace before it).  Consider the removal of
            // the whitespace to be part of removing the next node.
            nextRemovalOffset = lineStart;
          }
          end = nextRemovalOffset;
        }
      }
      changes += _removeCode(
          offset,
          end,
          planner.removeViaComments!
              ? _RemovalStyle.spaceInsideComment
              : _RemovalStyle.delete,
          innerPlan.info);
    }

    return planIndex;
  }

  /// Walks through the plans in [innerPlans], adjusting them as necessary and
  /// collecting their changes in [changes].
  void _processPlans() {
    int planIndex = 0;
    while (planIndex < innerPlans.length) {
      var innerPlan = innerPlans[planIndex];
      if (innerPlan is NodeProducingEditPlan) {
        _handleNodeProducingEditPlan(innerPlan);
        planIndex++;
      } else if (innerPlan is _RemoveEditPlan) {
        planIndex = _handleRemoveEditPlans(innerPlan, planIndex);
      } else if (innerPlan is _TokenChangePlan) {
        changes += innerPlan.changes;
        planIndex++;
      } else {
        throw UnimplementedError('Unrecognized inner plan type');
      }
    }
  }

  /// Computes the end for the text that should be removed by the given
  /// [innerPlan].
  int _removalEnd(_RemoveEditPlan innerPlan) {
    if (separators != null &&
        !removeLeadingSeparators &&
        innerPlan.lastChildIndex < separators!.length) {
      return separators![innerPlan.lastChildIndex].end;
    } else {
      return sequenceNodes![innerPlan.lastChildIndex].end;
    }
  }

  /// Computes the offset for the text that should be removed by the given
  /// [innerPlan].
  int _removalOffset(_RemoveEditPlan innerPlan) {
    if (separators != null && removeLeadingSeparators) {
      return separators![innerPlan.firstChildIndex - 1].offset;
    } else {
      return sequenceNodes![innerPlan.firstChildIndex].offset;
    }
  }

  static bool _checkParenLogic(EditPlan innerPlan, bool parensNeeded) {
    if (innerPlan is _SimpleEditPlan && innerPlan._innerChanges == null) {
      if (innerPlan.sourceNode is FunctionExpression) {
        // Skip parentheses check for function expressions; it produces false
        // failures when examining an expression like `x ?? (y) => z`, due to
        // https://github.com/dart-lang/sdk/issues/40536.
        // TODO(paulberry): fix this.
      } else {
        assert(
            !parensNeeded,
            "Code prior to fixes didn't need parens here, "
            "shouldn't need parens now.");
      }
    }
    return true;
  }

  /// Compute the set of tokens used by the given [parent] node to separate its
  /// [childNodes].
  static List<Token>? _computeSeparators(
      AstNode? parent, List<AstNode>? childNodes) {
    if (parent is Block ||
        parent is ClassDeclaration ||
        parent is CompilationUnit ||
        parent is FormalParameter ||
        parent is MethodDeclaration) {
      // These parent types don't use separators.
      return null;
    } else {
      var result = <Token>[];
      for (var child in childNodes!) {
        var separator = child.endToken.next;
        if (separator != null && separator.type == TokenType.COMMA) {
          result.add(separator);
        }
      }
      assert(result.length == childNodes.length ||
          result.length == childNodes.length - 1);
      return result;
    }
  }
}

/// [EditPlan] representing an AstNode that is not to be changed, but may have
/// some changes applied to some of its descendants.
class _PassThroughEditPlan extends _SimpleEditPlan {
  _PassThroughEditPlan._(AstNode? node, Precedence precedence,
      bool endsInCascade, Map<int?, List<AtomicEdit>>? innerChanges)
      : super(node, precedence, endsInCascade, innerChanges);
}

/// [EditPlan] applying to a [ParenthesizedExpression].  Unlike the normal
/// behavior of adding parentheses when needed, [_ProvisionalParenEditPlan]
/// preserves existing parens if they are needed, and removes them if they are
/// not.
///
/// Defers computation of whether parentheses are needed to the inner plan.
class _ProvisionalParenEditPlan extends _NestedEditPlan {
  /// Creates a new edit plan that consists of executing [innerPlan], and then
  /// possibly removing surrounding parentheses from the source code.
  ///
  /// Caller should not re-use [innerPlan] after this call--it (and the data
  /// structures it points to) may be incorporated into this edit plan and later
  /// modified.
  _ProvisionalParenEditPlan(
      ParenthesizedExpression node, NodeProducingEditPlan innerPlan)
      : super(node, innerPlan);

  @override
  Map<int?, List<AtomicEdit>>? _getChanges(bool parens) {
    var changes = innerPlan._getChanges(false);
    if (!parens) {
      changes ??= {};
      (changes[offset] ??= []).insert(0, const AtomicEdit.delete(1));
      (changes[end! - 1] ??= []).add(const AtomicEdit.delete(1));
    }
    return changes;
  }
}

/// Enum used by [_ExtractEditPlan._removeCode] to describe how code should be
/// removed.
enum _RemovalStyle {
  /// Code should be removed by commenting it out.  Inserted comment delimiters
  /// should be a comment delimiter followed by a space (i.e. `/* ` and `*/ `).
  commentSpace,

  /// Code should be removed by deleting it.
  delete,

  /// Code should be removed by commenting it out.  Inserted comment delimiters
  /// should be a space followed by a comment delimiter (i.e. ` /*` and ` */`).
  spaceComment,

  /// Code should be removed by commenting it out.  Inserted comment delimiters
  /// should have a space inside the comment.
  spaceInsideComment,
}

/// [EditPlan] representing one or more AstNodes that are to be removed from
/// their (common) parent, which must be an AST node that stores a list of
/// sub-nodes.
///
/// If more than one node is to be removed by this [EditPlan], they must be
/// contiguous.
class _RemoveEditPlan extends EditPlan {
  @override
  final AstNode? parentNode;

  /// Index of the node to be removed within the parent.
  final int firstChildIndex;

  /// Index of the node to be removed within the parent.
  final int lastChildIndex;

  final AtomicEditInfo? info;

  _RemoveEditPlan(
      this.parentNode, this.firstChildIndex, this.lastChildIndex, this.info)
      : super._();
}

/// Implementation of [EditPlan] underlying simple cases where no computation
/// needs to be deferred.
class _SimpleEditPlan extends NodeProducingEditPlan {
  final Precedence _precedence;

  @override
  final bool endsInCascade;

  final Map<int?, List<AtomicEdit>>? _innerChanges;

  bool _finalized = false;

  _SimpleEditPlan(
      AstNode? node, this._precedence, this.endsInCascade, this._innerChanges)
      : super._(node);

  @override
  Map<int?, List<AtomicEdit>>? _getChanges(bool parens) {
    assert(!_finalized);
    _finalized = true;
    return parens ? _createAddParenChanges(_innerChanges) : _innerChanges;
  }

  @override
  bool _parensNeeded(
      {required Precedence threshold,
      bool associative = false,
      bool allowCascade = false}) {
    if (endsInCascade && !allowCascade) return true;
    if (_precedence < threshold) return true;
    if (_precedence == threshold && !associative) return true;
    return false;
  }
}

/// [EditPlan] representing a change (or changes) to be made to a token in the
/// [parentNode].
///
/// This is used, for example, to change the `?.` token of a [MethodInvocation]
/// or [PropertyAccess] to `.`.
class _TokenChangePlan extends EditPlan {
  @override
  final AstNode parentNode;

  /// The changes to be made.
  final Map<int?, List<AtomicEdit>> changes;

  _TokenChangePlan(this.parentNode, this.changes) : super._();
}

/// Extension containing useful operations on a list of [AtomicEdit]s.
extension AtomicEditList on List<AtomicEdit> {
  /// Converts a list of [AtomicEdits] to a single [SourceEdit] by concatenating
  /// them.
  ///
  /// If [includeInformative] is `true`, informative edits are included;
  /// otherwise they are ignored.
  SourceEdit toSourceEdit(int offset, {bool includeInformative = false}) {
    var totalLength = 0;
    var replacement = '';
    for (var edit in this) {
      if (!edit.isInformative || includeInformative) {
        totalLength += edit.length;
        replacement += edit.replacement;
      }
    }
    return SourceEdit(offset, totalLength, replacement);
  }
}

/// Extension containing useful operations on a map from offsets to lists of
/// [AtomicEdit]s.  This data structure is used by [EditPlan]s to accumulate
/// source file changes.
extension AtomicEditMap on Map<int?, List<AtomicEdit>>? {
  /// Applies the changes to source file text.
  ///
  /// If [includeInformative] is `true`, informative edits are included;
  /// otherwise they are ignored.
  String applyTo(String code, {bool includeInformative = false}) {
    return SourceEdit.applySequence(
        code, toSourceEdits(includeInformative: includeInformative));
  }

  /// Converts the changes to a list of [SourceEdit]s.  The list is reverse
  /// sorted by offset so that they can be applied in order.
  ///
  /// If [includeInformative] is `true`, informative edits are included;
  /// otherwise they are ignored.
  List<SourceEdit> toSourceEdits({bool includeInformative = false}) {
    return [
      for (var offset in this!.keys.toList()..sort((a, b) => b!.compareTo(a!)))
        this![offset]!
            .toSourceEdit(offset!, includeInformative: includeInformative)
    ];
  }

  /// Destructively combines two change representations.  If one or the other
  /// input is null, the other input is returned unchanged for efficiency.
  Map<int?, List<AtomicEdit>>? operator +(
      Map<int?, List<AtomicEdit>>? newChanges) {
    if (newChanges == null) return this;
    if (this == null) {
      return newChanges;
    } else {
      for (var entry in newChanges.entries) {
        var currentValue = this![entry.key];
        if (currentValue == null) {
          this![entry.key] = entry.value;
        } else {
          currentValue.addAll(entry.value);
        }
      }
      return this;
    }
  }
}

/// Extension allowing an AstNode to be queried to see if it ends in a casade
/// expression.
extension EndsInCascadeExtension on AstNode {
  @visibleForTesting
  bool get endsInCascade {
    var visitor = _EndsInCascadeVisitor(end);
    accept(visitor);
    return visitor.endsInCascade;
  }
}
