// 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 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.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/decorated_type.dart';
import 'package:nnbd_migration/src/edit_plan.dart';
import 'package:nnbd_migration/src/fix_builder.dart';
import 'package:nnbd_migration/src/utilities/hint_utils.dart';

/// Base class representing a change that might need to be made to an
/// expression.
abstract class ExpressionChange {
  /// The type of the expression after the change is applied.
  final DartType resultType;

  ExpressionChange(this.resultType);

  /// Description of the change.
  NullabilityFixDescription get description;

  /// Creates a [NodeProducingEditPlan] that applies the change to [innerPlan].
  NodeProducingEditPlan applyExpression(FixAggregator aggregator,
      NodeProducingEditPlan innerPlan, AtomicEditInfo? info);

  /// Creates a string that applies the change to the [inner] text string.
  String applyText(FixAggregator aggregator, String inner);

  /// Describes the change, for use in debugging.
  String describe();
}

/// Visitor that combines together the changes produced by [FixBuilder] into a
/// concrete set of source code edits using the infrastructure of [EditPlan].
class FixAggregator extends UnifyingAstVisitor<void> {
  /// Map from the [AstNode]s that need to have changes made, to the changes
  /// that need to be applied to them.
  final Map<AstNode?, NodeChange> _changes;

  /// The set of [EditPlan]s being accumulated.
  List<EditPlan> _plans = [];

  final EditPlanner planner;

  /// Map from library to the prefix we should use when inserting code that
  /// refers to it.
  final Map<LibraryElement?, String?> _importPrefixes = {};

  final bool? _warnOnWeakCode;

  FixAggregator._(this.planner, this._changes, this._warnOnWeakCode,
      CompilationUnitElement compilationUnitElement) {
    for (var importElement in compilationUnitElement.library.imports2) {
      // TODO(paulberry): the `??=` should ensure that if there are two imports,
      // one prefixed and one not, we prefer the prefix.  Test this.
      _importPrefixes[importElement.importedLibrary] ??=
          importElement.prefix?.element.name;
    }
  }

  /// Creates the necessary Dart code to refer to the given element, using an
  /// import prefix if necessary.
  ///
  /// TODO(paulberry): if the element is not currently imported, we should
  /// update or add an import statement as necessary.
  String? elementToCode(Element element) {
    var name = element.name;
    var library = element.library;
    var prefix = _importPrefixes[library];
    if (prefix != null) {
      return '$prefix.$name';
    } else {
      return name;
    }
  }

  /// Gathers all the changes to nodes descended from [node] into a single
  /// [EditPlan].
  NodeProducingEditPlan innerPlanForNode(AstNode node) {
    var innerPlans = innerPlansForNode(node);
    return planner.passThrough(node, innerPlans: innerPlans);
  }

  /// Gathers all the changes to nodes descended from [node] into a list of
  /// [EditPlan]s, one for each change.
  List<EditPlan> innerPlansForNode(AstNode node) {
    var previousPlans = _plans;
    try {
      _plans = [];
      node.visitChildren(this);
      return _plans;
    } finally {
      _plans = previousPlans;
    }
  }

  /// Gathers all the changes to [node] and its descendants into a single
  /// [EditPlan].
  EditPlan planForNode(AstNode? node) {
    var change = _changes[node];
    if (change != null) {
      return change._apply(node!, this);
    } else {
      return planner.passThrough(node, innerPlans: innerPlansForNode(node!));
    }
  }

  /// Creates a string representation of the given type parameter element,
  /// suitable for inserting into the user's source code.
  String typeFormalToCode(TypeParameterElement formal) {
    var bound = formal.bound;
    if (bound == null ||
        bound.isDynamic ||
        (bound.isDartCoreObject &&
            bound.nullabilitySuffix != NullabilitySuffix.none)) {
      return formal.name;
    }
    return '${formal.name} extends ${typeToCode(bound)}';
  }

  String typeToCode(DartType type) {
    // TODO(paulberry): is it possible to share code with DartType.toString()
    // somehow?
    String suffix =
        type.nullabilitySuffix == NullabilitySuffix.question ? '?' : '';
    if (type is InterfaceType) {
      var name = elementToCode(type.element);
      var typeArguments = type.typeArguments;
      if (typeArguments.isEmpty) {
        return '$name$suffix';
      } else {
        var args = [for (var arg in typeArguments) typeToCode(arg)].join(', ');
        return '$name<$args>$suffix';
      }
    } else if (type is FunctionType) {
      var buffer = StringBuffer();
      buffer.write(typeToCode(type.returnType));
      buffer.write(' Function');
      var typeFormals = type.typeFormals;
      if (typeFormals.isNotEmpty) {
        var formals = [for (var formal in typeFormals) typeFormalToCode(formal)]
            .join(', ');
        buffer.write('<$formals>');
      }
      buffer.write('(');
      String optionalOrNamedCloser = '';
      bool commaNeeded = false;
      for (var parameter in type.parameters) {
        if (commaNeeded) {
          buffer.write(', ');
        } else {
          commaNeeded = true;
        }
        if (optionalOrNamedCloser.isEmpty && !parameter.isRequiredPositional) {
          if (parameter.isPositional) {
            buffer.write('[');
            optionalOrNamedCloser = ']';
          } else {
            buffer.write('{');
            optionalOrNamedCloser = '}';
          }
        }
        buffer.write(typeToCode(parameter.type));
        if (parameter.isNamed) {
          buffer.write(' ${parameter.name}');
        }
      }
      buffer.write(optionalOrNamedCloser);
      buffer.write(')');
      buffer.write(suffix);
      return buffer.toString();
    } else {
      return type.toString();
    }
  }

  @override
  void visitNode(AstNode node) {
    var change = _changes[node];
    if (change != null) {
      var innerPlan = change._apply(node, this);
      _plans.add(innerPlan);
    } else {
      node.visitChildren(this);
    }
  }

  /// Runs the [FixAggregator] on a [unit] and returns the resulting edits.
  static Map<int?, List<AtomicEdit>>? run(CompilationUnit unit,
      String? sourceText, Map<AstNode?, NodeChange> changes,
      {bool? removeViaComments = false, bool? warnOnWeakCode = false}) {
    var planner = EditPlanner(unit.lineInfo, sourceText,
        removeViaComments: removeViaComments);
    var aggregator = FixAggregator._(
        planner, changes, warnOnWeakCode, unit.declaredElement!);
    unit.accept(aggregator);
    if (aggregator._plans.isEmpty) return {};
    EditPlan plan;
    if (aggregator._plans.length == 1) {
      plan = aggregator._plans[0];
    } else {
      plan = planner.passThrough(unit, innerPlans: aggregator._plans);
    }
    return planner.finalize(plan);
  }
}

/// [ExpressionChange] describing the addition of an `as` cast to an expression.
class IntroduceAsChange extends ExpressionChange {
  /// The type being cast to.
  final DartType type;

  /// Indicates whether this is a downcast.
  final bool isDowncast;

  IntroduceAsChange(this.type, {required this.isDowncast}) : super(type);

  @override
  NullabilityFixDescription get description => isDowncast
      ? NullabilityFixDescription.downcastExpression
      : NullabilityFixDescription.otherCastExpression;

  @override
  NodeProducingEditPlan applyExpression(FixAggregator aggregator,
          NodeProducingEditPlan innerPlan, AtomicEditInfo? info) =>
      aggregator.planner.addBinaryPostfix(
          innerPlan, TokenType.AS, aggregator.typeToCode(type),
          info: info);

  @override
  String applyText(FixAggregator aggregator, String inner) =>
      '$inner as ${aggregator.typeToCode(type)}';

  @override
  String describe() => 'IntroduceAsChange($type)';
}

/// [ExpressionChange] describing the addition of an `as` cast to an expression
/// having a Future type.
class IntroduceThenChange extends ExpressionChange {
  /// The change that should be made to the value the future completes with.
  final ExpressionChange innerChange;

  IntroduceThenChange(DartType resultType, this.innerChange)
      : super(resultType);

  @override
  NullabilityFixDescription get description =>
      NullabilityFixDescription.addThen;

  @override
  NodeProducingEditPlan applyExpression(FixAggregator aggregator,
          NodeProducingEditPlan innerPlan, AtomicEditInfo? info) =>
      aggregator.planner.addPostfix(innerPlan,
          '.then((value) => ${innerChange.applyText(aggregator, 'value')})',
          info: info);

  @override
  String applyText(FixAggregator aggregator, String inner) =>
      '$inner.then((value) => ${innerChange.applyText(aggregator, 'value')})';

  @override
  String describe() => 'IntroduceThenChange($innerChange)';
}

/// Reasons that a variable declaration is to be made late.
enum LateAdditionReason {
  /// It was inferred that the associated variable declaration is to be made
  /// late through the late-inferring algorithm.
  inference,

  /// It was inferred that the associated variable declaration is to be made
  /// late, because it is a test variable which is assigned during setup.
  testVariableInference,
}

/// Base class representing a kind of change that [FixAggregator] might make to
/// a particular AST node.
abstract class NodeChange<N extends AstNode> {
  NodeChange._();

  /// Indicates whether this node exists solely to provide informative
  /// information.
  bool get isInformative => false;

  Iterable<String> get _toStringParts => const [];

  @override
  String toString() => '$runtimeType(${_toStringParts.join(', ')})';

  /// Applies this change to the given [node], producing an [EditPlan].  The
  /// [aggregator] may be used to gather up any edits to the node's descendants
  /// into their own [EditPlan]s.
  ///
  /// Note: the reason the caller can't just gather up the edits and pass them
  /// in is that some changes don't preserve all of the structure of the nodes
  /// below them (e.g. dropping an unnecessary cast), so those changes need to
  /// be able to call the appropriate [aggregator] methods just on the nodes
  /// they need.
  ///
  /// May return `null` if no changes need to be made.
  EditPlan _apply(N node, FixAggregator aggregator);

  /// Creates the appropriate specialized kind of [NodeChange] appropriate for
  /// the given [node].
  static NodeChange<AstNode>? create(AstNode node) =>
      node.accept(_NodeChangeVisitor._instance);
}

/// Implementation of [NodeChange] specialized for operating on [Annotation]
/// nodes.
class NodeChangeForAnnotation extends NodeChange<Annotation> {
  /// Indicates whether the node should be changed into a `required` keyword.
  bool changeToRequiredKeyword = false;

  /// If [changeToRequiredKeyword] is `true`, the information that should be
  /// contained in the edit.
  AtomicEditInfo? changeToRequiredKeywordInfo;

  NodeChangeForAnnotation() : super._();

  @override
  Iterable<String> get _toStringParts =>
      [if (changeToRequiredKeyword) 'changeToRequiredKeyword'];

  @override
  EditPlan _apply(Annotation node, FixAggregator aggregator) {
    if (!changeToRequiredKeyword) {
      return aggregator.innerPlanForNode(node);
    }
    var name = node.name;
    if (name is PrefixedIdentifier) {
      name = name.identifier;
    }
    if (aggregator.planner.sourceText!.substring(name.offset, name.end) ==
        'required') {
      // The text `required` already exists in the annotation; we can just
      // extract it.
      return aggregator.planner.extract(
          node, aggregator.planForNode(name) as NodeProducingEditPlan,
          infoBefore: changeToRequiredKeywordInfo, alwaysDelete: true);
    } else {
      return aggregator.planner.replace(node,
          [AtomicEdit.insert('required', info: changeToRequiredKeywordInfo)]);
    }
  }
}

/// Implementation of [NodeChange] specialized for operating on [ArgumentList]
/// nodes.
class NodeChangeForArgumentList extends NodeChange<ArgumentList> {
  /// Map whose keys are the arguments that should be dropped from this argument
  /// list, if any.  Values are info about why the arguments are being dropped.
  final Map<Expression, AtomicEditInfo?> _argumentsToDrop = {};

  NodeChangeForArgumentList() : super._();

  /// Queries the map whose keys are the arguments that should be dropped from
  /// this argument list, if any.  Values are info about why the arguments are
  /// being dropped.
  @visibleForTesting
  Map<Expression, AtomicEditInfo?> get argumentsToDrop => _argumentsToDrop;

  @override
  Iterable<String> get _toStringParts =>
      [if (_argumentsToDrop.isNotEmpty) 'argumentsToDrop: $_argumentsToDrop'];

  /// Updates `this` so that the given [argument] will be dropped, using [info]
  /// to annotate the reason why it is being dropped.
  void dropArgument(Expression argument, AtomicEditInfo? info) {
    assert(!_argumentsToDrop.containsKey(argument));
    _argumentsToDrop[argument] = info;
  }

  @override
  EditPlan _apply(ArgumentList node, FixAggregator aggregator) {
    assert(_argumentsToDrop.keys.every((e) => identical(e.parent, node)));
    List<EditPlan> innerPlans = [];
    for (var argument in node.arguments) {
      if (_argumentsToDrop.containsKey(argument)) {
        innerPlans.add(aggregator.planner
            .removeNode(argument, info: _argumentsToDrop[argument]));
      } else {
        innerPlans.add(aggregator.planForNode(argument));
      }
    }
    return aggregator.planner.passThrough(node, innerPlans: innerPlans);
  }
}

/// Implementation of [NodeChange] specialized for operating on [AsExpression]
/// nodes.
class NodeChangeForAsExpression extends NodeChangeForExpression<AsExpression> {
  /// Indicates whether the cast should be removed.
  bool removeAs = false;

  @override
  Iterable<String> get _toStringParts =>
      [...super._toStringParts, if (removeAs) 'removeAs'];

  @override
  EditPlan _apply(AsExpression node, FixAggregator aggregator) {
    if (removeAs) {
      return aggregator.planner.extract(node,
          aggregator.planForNode(node.expression) as NodeProducingEditPlan,
          infoAfter:
              AtomicEditInfo(NullabilityFixDescription.removeAs, const {}));
    } else {
      return super._apply(node, aggregator);
    }
  }
}

/// Implementation of [NodeChange] specialized for operating on
/// [AssignmentExpression] nodes.
class NodeChangeForAssignment
    extends NodeChangeForExpression<AssignmentExpression>
    with NodeChangeForAssignmentLike {
  /// Indicates whether the user should be warned that the assignment is a
  /// null-aware assignment that will have no effect when strong checking is
  /// enabled.
  bool isWeakNullAware = false;

  @override
  Iterable<String> get _toStringParts =>
      [...super._toStringParts, if (isWeakNullAware) 'isWeakNullAware'];

  @override
  NodeProducingEditPlan _apply(
      AssignmentExpression node, FixAggregator aggregator) {
    var lhsPlan = aggregator.planForNode(node.leftHandSide);
    if (isWeakNullAware && !aggregator._warnOnWeakCode!) {
      // Just keep the LHS
      return aggregator.planner.extract(node, lhsPlan as NodeProducingEditPlan,
          infoAfter: AtomicEditInfo(
              NullabilityFixDescription.removeNullAwareAssignment, const {}));
    }
    var operatorPlan = _makeOperatorPlan(aggregator, node, node.operator);
    var rhsPlan = aggregator.planForNode(node.rightHandSide);
    var innerPlans = <EditPlan>[
      lhsPlan,
      if (operatorPlan != null) operatorPlan,
      rhsPlan
    ];
    return _applyExpression(aggregator,
        aggregator.planner.passThrough(node, innerPlans: innerPlans));
  }

  EditPlan? _makeOperatorPlan(
      FixAggregator aggregator, AssignmentExpression node, Token operator) {
    var operatorPlan = super._makeOperatorPlan(aggregator, node, operator);
    if (operatorPlan != null) return operatorPlan;
    if (isWeakNullAware) {
      assert(aggregator._warnOnWeakCode!);
      return aggregator.planner.informativeMessageForToken(node, operator,
          info: AtomicEditInfo(
              NullabilityFixDescription
                  .nullAwareAssignmentUnnecessaryInStrongMode,
              const {}));
    } else {
      return null;
    }
  }
}

/// Common behaviors for expressions that can represent an assignment (possibly
/// through desugaring).
mixin NodeChangeForAssignmentLike<N extends Expression>
    on NodeChangeForExpression<N> {
  /// Indicates whether the user should be warned that the assignment has a
  /// bad combined type (the return type of the combiner isn't assignable to the
  /// write type of the target).
  bool hasBadCombinedType = false;

  /// Indicates whether the user should be warned that the assignment has a
  /// nullable source type.
  bool hasNullableSource = false;

  @override
  Iterable<String> get _toStringParts => [
        ...super._toStringParts,
        if (hasBadCombinedType) 'hasBadCombinedType',
        if (hasNullableSource) 'hasNullableSource'
      ];

  EditPlan? _makeOperatorPlan(
      FixAggregator aggregator, N node, Token operator) {
    if (hasNullableSource) {
      return aggregator.planner.informativeMessageForToken(node, operator,
          info: AtomicEditInfo(
              NullabilityFixDescription.compoundAssignmentHasNullableSource,
              const {}));
    } else if (hasBadCombinedType) {
      return aggregator.planner.informativeMessageForToken(node, operator,
          info: AtomicEditInfo(
              NullabilityFixDescription.compoundAssignmentHasBadCombinedType,
              const {}));
    } else {
      return null;
    }
  }
}

/// Implementation of [NodeChange] specialized for operating on
/// [CompilationUnit] nodes.
class NodeChangeForCompilationUnit extends NodeChange<CompilationUnit> {
  /// A map of the imports that should be added, or the empty map if no imports
  /// should be added.
  ///
  /// Each import is expressed as a map entry whose key is the URI to import and
  /// whose value is the set of symbols to show.
  final Map<String, Set<String>> _addImports = {};

  bool removeLanguageVersionComment = false;

  NodeChangeForCompilationUnit() : super._();

  /// Queries a map of the imports that should be added, or the empty map if no
  /// imports should be added.
  ///
  /// Each import is expressed as a map entry whose key is the URI to import and
  /// whose value is the set of symbols to show.
  @visibleForTesting
  Map<String, Set<String>> get addImports => _addImports;

  @override
  Iterable<String> get _toStringParts => [
        if (_addImports.isNotEmpty) 'addImports: $_addImports',
        if (removeLanguageVersionComment) 'removeLanguageVersionComment'
      ];

  /// Updates `this` so that an import of [uri] will be added, showing [name].
  void addImport(String uri, String name) {
    (_addImports[uri] ??= {}).add(name);
  }

  @override
  EditPlan _apply(CompilationUnit node, FixAggregator aggregator) {
    List<EditPlan> innerPlans = [];
    if (removeLanguageVersionComment) {
      final comment = (node as CompilationUnitImpl).languageVersionToken!;
      innerPlans.add(aggregator.planner.replaceToken(node, comment, '',
          info: AtomicEditInfo(
              NullabilityFixDescription.removeLanguageVersionComment,
              const {})));
    }
    _processDirectives(node, aggregator, innerPlans);
    for (var declaration in node.declarations) {
      innerPlans.add(aggregator.planForNode(declaration));
    }
    return aggregator.planner.passThrough(node, innerPlans: innerPlans);
  }

  /// Adds the necessary inner plans to [innerPlans] for the directives part of
  /// [node].  This solely involves adding imports.
  void _processDirectives(CompilationUnit node, FixAggregator aggregator,
      List<EditPlan> innerPlans) {
    List<MapEntry<String, Set<String>>> importsToAdd =
        _addImports.entries.toList();
    importsToAdd.sort((x, y) => x.key.compareTo(y.key));

    void insertImport(int offset, MapEntry<String, Set<String>> importToAdd,
        {String prefix = '', String suffix = '\n'}) {
      var shownNames = importToAdd.value.toList();
      shownNames.sort();
      innerPlans.add(aggregator.planner.insertText(node, offset, [
        if (prefix.isNotEmpty) AtomicEdit.insert(prefix),
        AtomicEdit.insert(
            "import '${importToAdd.key}' show ${shownNames.join(', ')};",
            info: AtomicEditInfo(NullabilityFixDescription.addImport, {})),
        if (suffix.isNotEmpty) AtomicEdit.insert(suffix)
      ]));
    }

    if (node.directives.every((d) => d is LibraryDirective)) {
      while (importsToAdd.isNotEmpty) {
        insertImport(
            node.declarations.beginToken!.offset, importsToAdd.removeAt(0),
            suffix: importsToAdd.isEmpty ? '\n\n' : '\n');
      }
    } else {
      for (var directive in node.directives) {
        while (importsToAdd.isNotEmpty &&
            _shouldImportGoBefore(importsToAdd.first.key, directive)) {
          insertImport(directive.offset, importsToAdd.removeAt(0));
        }
        innerPlans.add(aggregator.planForNode(directive));
      }
      while (importsToAdd.isNotEmpty) {
        insertImport(node.directives.last.end, importsToAdd.removeAt(0),
            prefix: '\n', suffix: '');
      }
    }
  }

  /// Determines whether a new import of [newImportUri] should be sorted before
  /// an existing [directive].
  bool _shouldImportGoBefore(String newImportUri, Directive directive) {
    if (directive is ImportDirective) {
      return newImportUri.compareTo(directive.uriContent!) < 0;
    } else if (directive is LibraryDirective) {
      // Library directives must come before imports.
      return false;
    } else {
      // Everything else tends to come after imports.
      return true;
    }
  }
}

/// Common infrastructure used by [NodeChange] objects that operate on AST nodes
/// with conditional behavior (if statements, if elements, and conditional
/// expressions).
mixin NodeChangeForConditional<N extends AstNode> on NodeChange<N> {
  /// If not `null`, indicates that the condition expression is known to
  /// evaluate to either `true` or `false`, so the other branch of the
  /// conditional is dead code and should be eliminated.
  bool? conditionValue;

  /// If [conditionValue] is not `null`, the reason that should be included in
  /// the [AtomicEditInfo] for the edit that removes the dead code.
  FixReasonInfo? conditionReason;

  @override
  Iterable<String> get _toStringParts =>
      [...super._toStringParts, if (conditionValue != null) 'conditionValue'];

  /// If dead code removal is warranted for [node], returns an [EditPlan] that
  /// removes the dead code (and performs appropriate updates within any
  /// descendant AST nodes that remain).  Otherwise returns `null`.
  EditPlan? _applyConditional(N node, FixAggregator aggregator,
      AstNode conditionNode, AstNode thenNode, AstNode? elseNode) {
    if (conditionValue == null) return null;
    if (aggregator._warnOnWeakCode!) {
      var conditionPlan = aggregator.innerPlanForNode(conditionNode);
      var info = AtomicEditInfo(
          conditionValue!
              ? NullabilityFixDescription.conditionTrueInStrongMode
              : NullabilityFixDescription.conditionFalseInStrongMode,
          {FixReasonTarget.root: conditionReason});
      var commentedConditionPlan = aggregator.planner.addCommentPostfix(
          conditionPlan, '/* == $conditionValue */',
          info: info, isInformative: true);
      return aggregator.planner.passThrough(node, innerPlans: [
        commentedConditionPlan,
        aggregator.planForNode(thenNode),
        if (elseNode != null) aggregator.planForNode(elseNode)
      ]);
    }
    AstNode? nodeToKeep;
    NullabilityFixDescription descriptionBefore, descriptionAfter;
    if (conditionValue!) {
      nodeToKeep = thenNode;
      descriptionBefore = NullabilityFixDescription.discardCondition;
      if (elseNode == null) {
        descriptionAfter = descriptionBefore;
      } else {
        descriptionAfter = NullabilityFixDescription.discardElse;
      }
    } else {
      nodeToKeep = elseNode;
      descriptionBefore =
          descriptionAfter = NullabilityFixDescription.discardThen;
    }
    if (nodeToKeep == null ||
        nodeToKeep is Block && nodeToKeep.statements.isEmpty) {
      // The conditional node collapses to a no-op, so try to remove it
      // entirely.
      var info = AtomicEditInfo(NullabilityFixDescription.discardIf,
          {FixReasonTarget.root: conditionReason});
      var removeNode = aggregator.planner.tryRemoveNode(node, info: info);
      if (removeNode != null) {
        return removeNode;
      } else {
        // We can't remove the node because it's not inside a sequence, so we
        // have to create a suitable replacement.
        if (node is IfStatement) {
          return aggregator.planner
              .replace(node, [AtomicEdit.insert('{}', info: info)], info: info);
        } else if (node is IfElement) {
          return aggregator.planner.replace(
              node, [AtomicEdit.insert('...{}', info: info)],
              info: info);
        } else {
          // We should never get here; the only types of conditional nodes that
          // can wind up collapsing to a no-op are if statements and if
          // elements.
          throw StateError(
              'Unexpected node type collapses to no-op: ${node.runtimeType}');
        }
      }
    }
    var infoBefore = AtomicEditInfo(
        descriptionBefore, {FixReasonTarget.root: conditionReason});
    var infoAfter = AtomicEditInfo(
        descriptionAfter, {FixReasonTarget.root: conditionReason});
    if (nodeToKeep is Block && nodeToKeep.statements.length == 1) {
      var singleStatement = nodeToKeep.statements[0];
      if (singleStatement is VariableDeclarationStatement) {
        // It's not safe to eliminate the {} because it increases the scope of
        // the variable declarations
      } else {
        nodeToKeep = singleStatement;
      }
    }
    return aggregator.planner.extract(
        node, aggregator.planForNode(nodeToKeep) as NodeProducingEditPlan,
        infoBefore: infoBefore, infoAfter: infoAfter);
  }
}

/// Implementation of [NodeChange] specialized for operating on
/// [ConditionalExpression] nodes.
class NodeChangeForConditionalExpression
    extends NodeChangeForExpression<ConditionalExpression>
    with NodeChangeForConditional {
  @override
  EditPlan _apply(ConditionalExpression node, FixAggregator aggregator) {
    return _applyConditional(node, aggregator, node.condition,
            node.thenExpression, node.elseExpression) ??
        super._apply(node, aggregator);
  }
}

/// Implementation of [NodeChange] specialized for operating on
/// [DefaultFormalParameter] nodes.
class NodeChangeForDefaultFormalParameter
    extends NodeChange<DefaultFormalParameter> {
  /// Indicates whether a `required` keyword should be added to this node.
  bool addRequiredKeyword = false;

  /// If [addRequiredKeyword] is `true`, the information that should be
  /// contained in the edit.
  AtomicEditInfo? addRequiredKeywordInfo;

  /// If [addRequiredKeyword] is `true`, and there is a `/*required*/` hint,
  /// the hint comment that should be converted into a simple `required` string.
  HintComment? requiredHint;

  /// If non-null, indicates a `@required` annotation which should be removed
  /// from this node.
  Annotation? annotationToRemove;

  /// If [annotationToRemove] is non-null, the information that should be
  /// contained in the edit.
  AtomicEditInfo? removeAnnotationInfo;

  NodeChangeForDefaultFormalParameter() : super._();

  @override
  Iterable<String> get _toStringParts =>
      [if (addRequiredKeyword) 'addRequiredKeyword'];

  @override
  EditPlan _apply(DefaultFormalParameter node, FixAggregator aggregator) {
    if (!addRequiredKeyword) return aggregator.innerPlanForNode(node);

    if (requiredHint != null) {
      var innerPlan = aggregator.innerPlanForNode(node);
      return aggregator.planner.acceptPrefixHint(innerPlan, requiredHint!,
          info: addRequiredKeywordInfo);
    }

    var offset = node.firstTokenAfterCommentAndMetadata!.offset;
    return aggregator.planner.passThrough(node, innerPlans: [
      aggregator.planner.insertText(node, offset, [
        AtomicEdit.insert('required ', info: addRequiredKeywordInfo),
      ]),
      if (annotationToRemove != null)
        aggregator.planner
            .removeNode(annotationToRemove!, info: removeAnnotationInfo),
      ...aggregator.innerPlansForNode(node),
    ]);
  }
}

/// Implementation of [NodeChange] specialized for operating on [Expression]
/// nodes.
class NodeChangeForExpression<N extends Expression> extends NodeChange<N> {
  /// The list of [ExpressionChange] objects that should be applied to the
  /// expression, in the order they should be applied.
  final List<ExpressionChange> expressionChanges = [];

  /// The list of [AtomicEditInfo] objects corresponding to each change in
  /// [expressionChanges].
  final List<AtomicEditInfo?> expressionChangeInfos = [];

  NodeChangeForExpression() : super._();

  @override
  Iterable<String> get _toStringParts => [
        for (var expressionChange in expressionChanges)
          expressionChange.describe()
      ];

  void addExpressionChange(ExpressionChange change, AtomicEditInfo? info) {
    expressionChanges.add(change);
    expressionChangeInfos.add(info);
  }

  @override
  EditPlan _apply(N node, FixAggregator aggregator) {
    var innerPlan = aggregator.innerPlanForNode(node);
    return _applyExpression(aggregator, innerPlan);
  }

  /// If the expression needs to be wrapped in another expression (e.g. a null
  /// check), wraps the given [innerPlan] to produce appropriate result.
  /// Otherwise returns [innerPlan] unchanged.
  NodeProducingEditPlan _applyExpression(
      FixAggregator aggregator, NodeProducingEditPlan innerPlan) {
    var plan = innerPlan;
    for (int i = 0; i < expressionChanges.length; i++) {
      plan = expressionChanges[i]
          .applyExpression(aggregator, plan, expressionChangeInfos[i]);
    }
    return plan;
  }
}

/// Implementation of [NodeChange] specialized for operating on
/// [FieldFormalParameter] nodes.
class NodeChangeForFieldFormalParameter
    extends NodeChangeForType<FieldFormalParameter> {
  /// If not `null`, an explicit type annotation that should be added to the
  /// parameter.
  DartType? addExplicitType;

  NodeChangeForFieldFormalParameter() : super._();

  @override
  Iterable<String> get _toStringParts =>
      [if (addExplicitType != null) 'addExplicitType'];

  @override
  EditPlan _apply(FieldFormalParameter node, FixAggregator aggregator) {
    if (addExplicitType != null) {
      var typeText = aggregator.typeToCode(addExplicitType!);
      // Even a field formal parameter can use `var`, `final`.
      if (node.keyword?.keyword == Keyword.VAR) {
        // TODO(srawlins): Test instrumentation info.
        var info =
            AtomicEditInfo(NullabilityFixDescription.replaceVar(typeText), {});
        return aggregator.planner.passThrough(node, innerPlans: [
          aggregator.planner
              .replaceToken(node, node.keyword!, typeText, info: info),
          ...aggregator.innerPlansForNode(node),
        ]);
      } else {
        // TODO(srawlins): Test instrumentation info.
        var info =
            AtomicEditInfo(NullabilityFixDescription.addType(typeText), {});
        var offset = node.thisKeyword.offset;
        return aggregator.planner.passThrough(node, innerPlans: [
          aggregator.planner.insertText(node, offset, [
            AtomicEdit.insert(typeText, info: info),
            AtomicEdit.insert(' ')
          ]),
          ...aggregator.innerPlansForNode(node),
        ]);
      }
    } else {
      return super._apply(node, aggregator);
    }
  }
}

/// Implementation of [NodeChange] specialized for operating on
/// [FunctionTypedFormalParameter] nodes.
class NodeChangeForFunctionTypedFormalParameter
    extends NodeChangeForType<FunctionTypedFormalParameter> {
  NodeChangeForFunctionTypedFormalParameter() : super._();
}

/// Implementation of [NodeChange] specialized for operating on [IfElement]
/// nodes.
class NodeChangeForIfElement extends NodeChange<IfElement>
    with NodeChangeForConditional {
  NodeChangeForIfElement() : super._();

  @override
  EditPlan _apply(IfElement node, FixAggregator aggregator) {
    return _applyConditional(node, aggregator, node.condition, node.thenElement,
            node.elseElement) ??
        aggregator.innerPlanForNode(node);
  }
}

/// Implementation of [NodeChange] specialized for operating on [IfStatement]
/// nodes.
class NodeChangeForIfStatement extends NodeChange<IfStatement>
    with NodeChangeForConditional {
  NodeChangeForIfStatement() : super._();

  @override
  EditPlan _apply(IfStatement node, FixAggregator aggregator) {
    return _applyConditional(node, aggregator, node.condition,
            node.thenStatement, node.elseStatement) ??
        aggregator.innerPlanForNode(node);
  }
}

/// Implementation of [NodeChange] specialized for operating on
/// [MethodDeclaration] nodes.
class NodeChangeForMethodDeclaration extends NodeChange<MethodDeclaration> {
  /// If non-null, indicates a `@nullable` annotation which should be removed
  /// from this node.
  Annotation? annotationToRemove;

  /// If [annotationToRemove] is non-null, the information that should be
  /// contained in the edit.
  AtomicEditInfo? removeAnnotationInfo;

  NodeChangeForMethodDeclaration() : super._();

  @override
  Iterable<String> get _toStringParts =>
      [if (annotationToRemove != null) 'annotationToRemove'];

  @override
  EditPlan _apply(MethodDeclaration node, FixAggregator aggregator) {
    return aggregator.planner.passThrough(node, innerPlans: [
      if (annotationToRemove != null)
        aggregator.planner
            .removeNode(annotationToRemove!, info: removeAnnotationInfo),
      ...aggregator.innerPlansForNode(node),
    ]);
  }
}

/// Implementation of [NodeChange] specialized for operating on
/// [MethodInvocation] nodes.
class NodeChangeForMethodInvocation
    extends NodeChangeForExpression<MethodInvocation>
    with NodeChangeForNullAware {
  @override
  NodeProducingEditPlan _apply(
      MethodInvocation node, FixAggregator aggregator) {
    var target = node.target;
    var targetPlan = target == null ? null : aggregator.planForNode(target);
    var nullAwarePlan = _applyNullAware(node, aggregator);
    var methodNamePlan = aggregator.planForNode(node.methodName);
    var typeArguments = node.typeArguments;
    var typeArgumentsPlan =
        typeArguments == null ? null : aggregator.planForNode(typeArguments);
    var argumentListPlan = aggregator.planForNode(node.argumentList);
    var innerPlans = [
      if (targetPlan != null) targetPlan,
      if (nullAwarePlan != null) nullAwarePlan,
      methodNamePlan,
      if (typeArgumentsPlan != null) typeArgumentsPlan,
      argumentListPlan
    ];
    return _applyExpression(aggregator,
        aggregator.planner.passThrough(node, innerPlans: innerPlans));
  }
}

/// Implementation of [NodeChange] specialized for operating on
/// [SimpleIdentifier] nodes that represent a method name.
class NodeChangeForMethodName extends NodeChange<SimpleIdentifier> {
  /// The name the method name should be changed to, or `null` if no change
  /// should be made.
  String? _replacement;

  /// Info object associated with the replacement.
  AtomicEditInfo? _replacementInfo;

  NodeChangeForMethodName() : super._();

  /// Queries the name the method name should be changed to, or `null` if no
  /// change should be made.
  @visibleForTesting
  String? get replacement => _replacement;

  /// Queries the info object associated with the replacement.
  @visibleForTesting
  AtomicEditInfo? get replacementInfo => _replacementInfo;

  @override
  Iterable<String> get _toStringParts =>
      [if (replacement != null) 'replacement: $replacement'];

  /// Updates `this` so that the method name will be changed to [replacement],
  /// using [info] to annotate the reason for the change.
  void replaceWith(String replacement, AtomicEditInfo? info) {
    assert(_replacement == null);
    _replacement = replacement;
    _replacementInfo = info;
  }

  @override
  EditPlan _apply(SimpleIdentifier node, FixAggregator aggregator) {
    if (replacement != null) {
      return aggregator.planner.replace(
          node, [AtomicEdit.insert(replacement!, info: replacementInfo)],
          info: replacementInfo);
    } else {
      return aggregator.innerPlanForNode(node);
    }
  }
}

/// Common infrastructure used by [NodeChange] objects that operate on AST nodes
/// with that can be null-aware (method invocations and propety accesses).
mixin NodeChangeForNullAware<N extends Expression> on NodeChange<N> {
  /// Indicates whether null-awareness should be removed.
  bool removeNullAwareness = false;

  @override
  Iterable<String> get _toStringParts =>
      [...super._toStringParts, if (removeNullAwareness) 'removeNullAwareness'];

  /// Returns an [EditPlan] that removes null awareness, if appropriate.
  /// Otherwise returns `null`.
  EditPlan? _applyNullAware(N node, FixAggregator aggregator) {
    if (!removeNullAwareness) return null;
    var description = aggregator._warnOnWeakCode!
        ? NullabilityFixDescription.nullAwarenessUnnecessaryInStrongMode
        : NullabilityFixDescription.removeNullAwareness;
    return aggregator.planner.removeNullAwareness(node,
        info: AtomicEditInfo(description, const {}),
        isInformative: aggregator._warnOnWeakCode!);
  }
}

/// Implementation of [NodeChange] specialized for operating on
/// [PostfixExpression] nodes.
class NodeChangeForPostfixExpression
    extends NodeChangeForExpression<PostfixExpression>
    with NodeChangeForAssignmentLike {
  @override
  NodeProducingEditPlan _apply(
      PostfixExpression node, FixAggregator aggregator) {
    var operandPlan = aggregator.planForNode(node.operand);
    var operatorPlan = _makeOperatorPlan(aggregator, node, node.operator);
    var innerPlans = <EditPlan>[
      operandPlan,
      if (operatorPlan != null) operatorPlan
    ];
    return _applyExpression(aggregator,
        aggregator.planner.passThrough(node, innerPlans: innerPlans));
  }
}

/// Implementation of [NodeChange] specialized for operating on
/// [PrefixExpression] nodes.
class NodeChangeForPrefixExpression
    extends NodeChangeForExpression<PrefixExpression>
    with NodeChangeForAssignmentLike {
  @override
  NodeProducingEditPlan _apply(
      PrefixExpression node, FixAggregator aggregator) {
    var operatorPlan = _makeOperatorPlan(aggregator, node, node.operator);
    var operandPlan = aggregator.planForNode(node.operand);
    var innerPlans = <EditPlan>[
      if (operatorPlan != null) operatorPlan,
      operandPlan
    ];
    return _applyExpression(aggregator,
        aggregator.planner.passThrough(node, innerPlans: innerPlans));
  }
}

/// Implementation of [NodeChange] specialized for operating on [PropertyAccess]
/// nodes.
class NodeChangeForPropertyAccess
    extends NodeChangeForExpression<PropertyAccess>
    with NodeChangeForNullAware {
  @override
  NodeProducingEditPlan _apply(PropertyAccess node, FixAggregator aggregator) {
    var targetPlan =
        node.target == null ? null : aggregator.planForNode(node.target);
    var nullAwarePlan = _applyNullAware(node, aggregator);
    var propertyNamePlan = aggregator.planForNode(node.propertyName);
    var innerPlans = [
      if (targetPlan != null) targetPlan,
      if (nullAwarePlan != null) nullAwarePlan,
      propertyNamePlan
    ];
    return _applyExpression(aggregator,
        aggregator.planner.passThrough(node, innerPlans: innerPlans));
  }
}

/// Implementation of [NodeChange] specialized for operating on [ShowCombinator]
/// nodes.
class NodeChangeForShowCombinator extends NodeChange<ShowCombinator> {
  /// A set of the names that should be added, or the empty set if no names
  /// should be added.
  final Set<String> _addNames = {};

  NodeChangeForShowCombinator() : super._();

  /// Queries the set of names that should be added, or the empty set if no
  /// names should be added.
  @visibleForTesting
  Iterable<String> get addNames => _addNames;

  @override
  Iterable<String> get _toStringParts => [
        if (_addNames.isNotEmpty) 'addNames: $_addNames',
      ];

  /// Updates `this` so that [name] will be added.
  void addName(String name) {
    _addNames.add(name);
  }

  @override
  EditPlan _apply(ShowCombinator node, FixAggregator aggregator) {
    List<EditPlan> innerPlans = [];
    List<String> namesToAdd = _addNames.toList();
    namesToAdd.sort();

    void insertName(int offset, String nameToAdd,
        {String prefix = '', String suffix = ', '}) {
      innerPlans.add(aggregator.planner.insertText(node, offset, [
        if (prefix.isNotEmpty) AtomicEdit.insert(prefix),
        AtomicEdit.insert(nameToAdd),
        if (suffix.isNotEmpty) AtomicEdit.insert(suffix)
      ]));
    }

    for (var shownName in node.shownNames) {
      while (namesToAdd.isNotEmpty &&
          namesToAdd.first.compareTo(shownName.name) < 0) {
        insertName(shownName.offset, namesToAdd.removeAt(0));
      }
      innerPlans.add(aggregator.planForNode(shownName));
    }
    while (namesToAdd.isNotEmpty) {
      insertName(node.shownNames.last.end, namesToAdd.removeAt(0),
          prefix: ', ', suffix: '');
    }
    return aggregator.planner.passThrough(node, innerPlans: innerPlans);
  }
}

/// Implementation of [NodeChange] specialized for operating on
/// [SimpleFormalParameter] nodes.
class NodeChangeForSimpleFormalParameter
    extends NodeChange<SimpleFormalParameter> {
  /// If not `null`, an explicit type annotation that should be added to the
  /// parameter.
  DartType? addExplicitType;

  NodeChangeForSimpleFormalParameter() : super._();

  @override
  Iterable<String> get _toStringParts =>
      [if (addExplicitType != null) 'addExplicitType'];

  @override
  EditPlan _apply(SimpleFormalParameter node, FixAggregator aggregator) {
    var innerPlan = aggregator.innerPlanForNode(node);
    if (addExplicitType == null) return innerPlan;
    var typeText = aggregator.typeToCode(addExplicitType!);
    if (node.keyword?.keyword == Keyword.VAR) {
      // TODO(srawlins): Test instrumentation info.
      var info =
          AtomicEditInfo(NullabilityFixDescription.replaceVar(typeText), {});
      return aggregator.planner.passThrough(node, innerPlans: [
        aggregator.planner
            .replaceToken(node, node.keyword!, typeText, info: info),
        ...aggregator.innerPlansForNode(node),
      ]);
    } else {
      // TODO(srawlins): Test instrumentation info.
      var info =
          AtomicEditInfo(NullabilityFixDescription.addType(typeText), {});
      // Skip past the offset of any metadata, a potential `final` keyword, and
      // a potential `covariant` keyword.
      var offset = node.type?.offset ?? node.identifier!.offset;
      return aggregator.planner.passThrough(node, innerPlans: [
        aggregator.planner.insertText(node, offset,
            [AtomicEdit.insert(typeText, info: info), AtomicEdit.insert(' ')]),
        ...aggregator.innerPlansForNode(node),
      ]);
    }
  }
}

/// Implementation of [NodeChange] specialized for operating on nodes which
/// represent a type, and can be made and hinted nullable and non-nullable.
abstract class NodeChangeForType<N extends AstNode> extends NodeChange<N> {
  bool _makeNullable = false;

  HintComment? _nullabilityHint;

  /// The decorated type of the type annotation, or `null` if there is no
  /// decorated type info of interest.  If [makeNullable] is `true`, the node
  /// from this type will be attached to the edit that adds the `?`. If
  /// [_makeNullable] is `false`, the node from this type will be attached to
  /// the information about why the node wasn't made nullable.
  DecoratedType? _decoratedType;

  NodeChangeForType._() : super._();

  @override
  bool get isInformative => !_makeNullable;

  /// Indicates whether the type should be made nullable by adding a `?`.
  bool get makeNullable => _makeNullable;

  /// If we are making the type nullable due to a hint, the comment that caused
  /// it.
  HintComment? get nullabilityHint => _nullabilityHint;

  @override
  Iterable<String> get _toStringParts => [
        if (_makeNullable) 'makeNullable',
        if (_nullabilityHint != null) 'nullabilityHint'
      ];

  void recordNullability(DecoratedType decoratedType, bool makeNullable,
      {HintComment? nullabilityHint}) {
    _decoratedType = decoratedType;
    _makeNullable = makeNullable;
    _nullabilityHint = nullabilityHint;
  }

  @override
  EditPlan _apply(N node, FixAggregator aggregator) {
    var innerPlan = aggregator.innerPlanForNode(node);
    if (_decoratedType == null) return innerPlan;
    var typeName =
        _decoratedType!.type!.getDisplayString(withNullability: false);
    var fixReasons = {FixReasonTarget.root: _decoratedType!.node};
    if (_makeNullable) {
      var hint = _nullabilityHint;
      if (hint != null) {
        return aggregator.planner.acceptSuffixHint(innerPlan, hint,
            info: AtomicEditInfo(
                NullabilityFixDescription.makeTypeNullableDueToHint(typeName),
                fixReasons,
                hintComment: hint));
      } else {
        return aggregator.planner.makeNullable(innerPlan,
            info: AtomicEditInfo(
                NullabilityFixDescription.makeTypeNullable(typeName),
                fixReasons));
      }
    } else {
      var hint = _nullabilityHint;
      if (hint != null) {
        return aggregator.planner.dropNullabilityHint(innerPlan, hint,
            info: AtomicEditInfo(
                NullabilityFixDescription.typeNotMadeNullableDueToHint(
                    typeName),
                fixReasons,
                hintComment: hint));
      } else {
        return aggregator.planner.explainNonNullable(innerPlan,
            info: AtomicEditInfo(
                NullabilityFixDescription.typeNotMadeNullable(typeName),
                fixReasons));
      }
    }
  }
}

/// Implementation of [NodeChange] specialized for operating on [TypeAnnotation]
/// nodes.
class NodeChangeForTypeAnnotation extends NodeChangeForType<TypeAnnotation> {
  NodeChangeForTypeAnnotation() : super._();
}

/// Implementation of [NodeChange] specialized for operating on
/// [VariableDeclarationList] nodes.
class NodeChangeForVariableDeclarationList
    extends NodeChange<VariableDeclarationList> {
  /// If an explicit type should be added to this variable declaration, the type
  /// that should be added.  Otherwise `null`.
  DartType? addExplicitType;

  /// Indicates whether a "late" annotation should be added to this variable
  /// declaration, caused by inference.
  LateAdditionReason? lateAdditionReason;

  /// If a "late" annotation should be added to this variable declaration, and
  /// the cause is a "late" hint, the hint that caused it.  Otherwise `null`.
  HintComment? lateHint;

  NodeChangeForVariableDeclarationList() : super._();

  @override
  Iterable<String> get _toStringParts => [
        if (addExplicitType != null) 'addExplicitType',
        if (lateAdditionReason != null) 'lateAdditionReason',
        if (lateHint != null) 'lateHint'
      ];

  @override
  EditPlan _apply(VariableDeclarationList node, FixAggregator aggregator) {
    List<EditPlan> innerPlans = [];
    if (lateAdditionReason != null) {
      var description = lateAdditionReason == LateAdditionReason.inference
          ? NullabilityFixDescription.addLate
          : NullabilityFixDescription.addLateDueToTestSetup;
      var info = AtomicEditInfo(description, {});
      innerPlans.add(aggregator.planner.insertText(
          node,
          node.firstTokenAfterCommentAndMetadata.offset,
          [AtomicEdit.insert('late', info: info), AtomicEdit.insert(' ')]));
    }
    if (addExplicitType != null) {
      var typeText = aggregator.typeToCode(addExplicitType!);
      if (node.keyword?.keyword == Keyword.VAR) {
        var info =
            AtomicEditInfo(NullabilityFixDescription.replaceVar(typeText), {});
        innerPlans.add(aggregator.planner
            .replaceToken(node, node.keyword!, typeText, info: info));
      } else {
        var info =
            AtomicEditInfo(NullabilityFixDescription.addType(typeText), {});
        innerPlans.add(aggregator.planner.insertText(
            node,
            node.variables.first.offset,
            [AtomicEdit.insert(typeText, info: info), AtomicEdit.insert(' ')]));
      }
    }
    innerPlans.addAll(aggregator.innerPlansForNode(node));
    var plan = aggregator.planner.passThrough(node, innerPlans: innerPlans);
    if (lateHint != null) {
      var description = lateHint!.kind == HintCommentKind.late_
          ? NullabilityFixDescription.addLateDueToHint
          : NullabilityFixDescription.addLateFinalDueToHint;
      plan = aggregator.planner.acceptPrefixHint(plan, lateHint!,
          info: AtomicEditInfo(description, {}, hintComment: lateHint));
    }
    return plan;
  }
}

/// [ExpressionChange] describing the addition of a comment explaining that a
/// literal `null` could not be migrated.
class NoValidMigrationChange extends ExpressionChange {
  NoValidMigrationChange(DartType resultType) : super(resultType);

  @override
  NullabilityFixDescription get description =>
      NullabilityFixDescription.noValidMigrationForNull;

  @override
  NodeProducingEditPlan applyExpression(FixAggregator aggregator,
          NodeProducingEditPlan innerPlan, AtomicEditInfo? info) =>
      aggregator.planner.addCommentPostfix(
          innerPlan, '/* no valid migration */',
          info: info, isInformative: true);

  @override
  String applyText(FixAggregator aggregator, String inner) =>
      '$inner /* no valid migration */';

  @override
  String describe() => 'NoValidMigrationChange';
}

/// [ExpressionChange] describing the addition of an `!` after an expression.
class NullCheckChange extends ExpressionChange {
  /// The hint that is causing this `!` to be added, if any.
  final HintComment? hint;

  NullCheckChange(DartType resultType, {this.hint}) : super(resultType);

  @override
  NullabilityFixDescription get description =>
      NullabilityFixDescription.checkExpression;

  @override
  NodeProducingEditPlan applyExpression(FixAggregator aggregator,
      NodeProducingEditPlan innerPlan, AtomicEditInfo? info) {
    if (hint != null) {
      return aggregator.planner.acceptSuffixHint(innerPlan, hint!, info: info);
    } else {
      return aggregator.planner
          .addUnaryPostfix(innerPlan, TokenType.BANG, info: info);
    }
  }

  @override
  String applyText(FixAggregator aggregator, String inner) => '$inner!';

  @override
  String describe() => 'NullCheckChange';
}

/// Visitor that creates an appropriate [NodeChange] object for the node being
/// visited.
class _NodeChangeVisitor extends GeneralizingAstVisitor<NodeChange<AstNode>> {
  static final _instance = _NodeChangeVisitor();

  @override
  NodeChange visitAnnotation(Annotation node) => NodeChangeForAnnotation();

  @override
  NodeChange visitArgumentList(ArgumentList node) =>
      NodeChangeForArgumentList();

  @override
  NodeChange visitAsExpression(AsExpression node) =>
      NodeChangeForAsExpression();

  @override
  NodeChange visitAssignmentExpression(AssignmentExpression node) =>
      NodeChangeForAssignment();

  @override
  NodeChange visitCompilationUnit(CompilationUnit node) =>
      NodeChangeForCompilationUnit();

  @override
  NodeChange visitConditionalExpression(ConditionalExpression node) =>
      NodeChangeForConditionalExpression();

  @override
  NodeChange visitDefaultFormalParameter(DefaultFormalParameter node) =>
      NodeChangeForDefaultFormalParameter();

  @override
  NodeChange visitExpression(Expression node) => NodeChangeForExpression();

  @override
  NodeChange visitFieldFormalParameter(FieldFormalParameter node) =>
      NodeChangeForFieldFormalParameter();

  @override
  NodeChange visitFunctionTypedFormalParameter(
          FunctionTypedFormalParameter node) =>
      NodeChangeForFunctionTypedFormalParameter();

  @override
  NodeChange visitGenericFunctionType(GenericFunctionType node) =>
      NodeChangeForTypeAnnotation();

  @override
  NodeChange visitIfElement(IfElement node) => NodeChangeForIfElement();

  @override
  NodeChange visitIfStatement(IfStatement node) => NodeChangeForIfStatement();

  @override
  NodeChange visitMethodDeclaration(MethodDeclaration node) =>
      NodeChangeForMethodDeclaration();

  @override
  NodeChange visitMethodInvocation(MethodInvocation node) =>
      NodeChangeForMethodInvocation();

  @override
  NodeChange visitNamedType(NamedType node) => NodeChangeForTypeAnnotation();

  @override
  NodeChange visitNode(AstNode node) =>
      throw StateError('Unexpected node type: ${node.runtimeType}');

  @override
  NodeChange visitPostfixExpression(PostfixExpression node) =>
      NodeChangeForPostfixExpression();

  @override
  NodeChange visitPrefixExpression(PrefixExpression node) =>
      NodeChangeForPrefixExpression();

  @override
  NodeChange visitPropertyAccess(PropertyAccess node) =>
      NodeChangeForPropertyAccess();

  @override
  NodeChange visitShowCombinator(ShowCombinator node) =>
      NodeChangeForShowCombinator();

  @override
  NodeChange visitSimpleFormalParameter(SimpleFormalParameter node) =>
      NodeChangeForSimpleFormalParameter();

  @override
  NodeChange? visitSimpleIdentifier(SimpleIdentifier node) {
    var parent = node.parent;
    if (parent is MethodInvocation && identical(node, parent.methodName)) {
      return NodeChangeForMethodName();
    } else {
      return super.visitSimpleIdentifier(node);
    }
  }

  @override
  NodeChange visitVariableDeclarationList(VariableDeclarationList node) =>
      NodeChangeForVariableDeclarationList();
}
