// 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:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:analyzer/dart/analysis/features.dart';
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/dart/element/type_provider.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/error/best_practices_verifier.dart';
import 'package:analyzer/src/generated/element_type_provider.dart';
import 'package:analyzer/src/generated/migration.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:collection/collection.dart' show IterableExtension;
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_class_hierarchy.dart';
import 'package:nnbd_migration/src/decorated_type.dart';
import 'package:nnbd_migration/src/edit_plan.dart';
import 'package:nnbd_migration/src/fix_aggregator.dart';
import 'package:nnbd_migration/src/nullability_node.dart';
import 'package:nnbd_migration/src/utilities/permissive_mode.dart';
import 'package:nnbd_migration/src/utilities/resolution_utils.dart';
import 'package:nnbd_migration/src/utilities/where_or_null_transformer.dart';
import 'package:nnbd_migration/src/variables.dart';
import 'package:pub_semver/pub_semver.dart';

bool _isIncrementOrDecrementOperator(TokenType tokenType) {
  switch (tokenType) {
    case TokenType.PLUS_PLUS:
    case TokenType.MINUS_MINUS:
      return true;
    default:
      return false;
  }
}

/// Problem reported by [FixBuilder] when encountering a compound assignment
/// for which the combination result is nullable.  This occurs if the compound
/// assignment resolves to a user-defined operator that returns a nullable type,
/// but the target of the assignment expects a non-nullable type.  We need to
/// add a null check but it's nontrivial to do so because we would have to
/// rewrite the assignment as an ordinary assignment (e.g. change `x += y` to
/// `x = (x + y)!`), but that might change semantics by causing subexpressions
/// of the target to be evaluated twice.
///
/// TODO(paulberry): consider alternatives.
/// See https://github.com/dart-lang/sdk/issues/38675.
class CompoundAssignmentCombinedNullable implements Problem {
  const CompoundAssignmentCombinedNullable();
}

/// Problem reported by [FixBuilder] when encountering a compound assignment
/// for which the value read from the target of the assignment has a nullable
/// type.  We need to add a null check but it's nontrivial to do so because we
/// would have to rewrite the assignment as an ordinary assignment (e.g. change
/// `x += y` to `x = x! + y`), but that might change semantics by causing
/// subexpressions of the target to be evaluated twice.
///
/// TODO(paulberry): consider alternatives.
/// See https://github.com/dart-lang/sdk/issues/38676.
class CompoundAssignmentReadNullable implements Problem {
  const CompoundAssignmentReadNullable();
}

/// This class runs the analyzer's resolver over the code being migrated, after
/// graph propagation, to figure out what changes need to be made.  It doesn't
/// actually make the changes; it simply reports what changes are necessary
/// through abstract methods.
class FixBuilder {
  final DecoratedClassHierarchy? _decoratedClassHierarchy;

  /// The type provider providing non-nullable types.
  final TypeProvider typeProvider;

  final Map<AstNode, NodeChange> changes = {};

  final Map<AstNode, Set<Problem>> problems = {};

  /// The NNBD type system.
  final TypeSystemImpl _typeSystem;

  /// Variables for this migration run.
  final Variables? _variables;

  /// The file being analyzed.
  final Source? source;

  late ResolverVisitor _resolver;

  /// The listener to which exceptions should be reported.
  final NullabilityMigrationListener? listener;

  /// The compilation unit for which fixes are being built.
  final CompilationUnit? unit;

  final MigrationResolutionHooksImpl migrationResolutionHooks;

  /// Parameter elements for which an explicit type should be added, and what
  /// that type should be.
  final Map<ParameterElement, DartType> _addedParameterTypes = {};

  final bool? warnOnWeakCode;

  final NullabilityGraph _graph;

  /// Helper that assists us in transforming Iterable methods to their "OrNull"
  /// equivalents.
  final WhereOrNullTransformer _whereOrNullTransformer;

  /// Indicates whether an import of package:collection's `IterableExtension`
  /// will need to be added.
  @visibleForTesting
  bool needsIterableExtension = false;

  /// Map of additional package dependencies that will be required by the
  /// migrated code.  Keys are package names; values indicate the minimum
  /// required version of each package.
  final Map<String, Version> _neededPackages;

  factory FixBuilder(
      Source? source,
      DecoratedClassHierarchy? decoratedClassHierarchy,
      TypeProvider typeProvider,
      TypeSystemImpl typeSystem,
      Variables? variables,
      LibraryElementImpl definingLibrary,
      NullabilityMigrationListener? listener,
      CompilationUnit? unit,
      bool? warnOnWeakCode,
      NullabilityGraph graph,
      Map<String, Version> neededPackages) {
    var migrationResolutionHooks = MigrationResolutionHooksImpl();
    return FixBuilder._(
        decoratedClassHierarchy,
        _makeNnbdTypeSystem(
            (typeProvider as TypeProviderImpl).asNonNullableByDefault,
            typeSystem,
            migrationResolutionHooks),
        variables,
        source,
        definingLibrary,
        listener,
        unit,
        migrationResolutionHooks,
        warnOnWeakCode,
        graph,
        neededPackages);
  }

  FixBuilder._(
      this._decoratedClassHierarchy,
      this._typeSystem,
      this._variables,
      this.source,
      LibraryElementImpl definingLibrary,
      this.listener,
      this.unit,
      this.migrationResolutionHooks,
      this.warnOnWeakCode,
      this._graph,
      this._neededPackages)
      : typeProvider = _typeSystem.typeProvider,
        _whereOrNullTransformer =
            WhereOrNullTransformer(_typeSystem.typeProvider, _typeSystem) {
    migrationResolutionHooks._fixBuilder = this;
    assert(_typeSystem.isNonNullableByDefault);
    assert((typeProvider as TypeProviderImpl).isNonNullableByDefault);
    var inheritanceManager = InheritanceManager3();
    // TODO(paulberry): is it a bad idea to throw away errors?
    var errorListener = AnalysisErrorListener.NULL_LISTENER;
    _resolver = ResolverVisitorForMigration(
        inheritanceManager,
        definingLibrary,
        source!,
        typeProvider,
        errorListener,
        _typeSystem,
        FeatureSet.fromEnableFlags2(
          sdkLanguageVersion: Feature.non_nullable.releaseVersion!,
          flags: [],
        ),
        migrationResolutionHooks);
  }

  /// Visits the entire compilation [unit] using the analyzer's resolver and
  /// makes note of changes that need to be made.
  void visitAll() {
    try {
      ElementTypeProvider.current = migrationResolutionHooks;
      unit!.accept(_FixBuilderPreVisitor(this));
      unit!.accept(_resolver);
      unit!.accept(_FixBuilderPostVisitor(this));
    } catch (exception, stackTrace) {
      if (listener != null) {
        listener!.reportException(source, unit, exception, stackTrace);
      } else {
        rethrow;
      }
    } finally {
      ElementTypeProvider.current = const ElementTypeProvider();
    }
  }

  /// Called whenever an AST node is found that can't be automatically fixed.
  void _addProblem(AstNode node, Problem problem) {
    var newlyAdded = (problems[node] ??= {}).add(problem);
    assert(newlyAdded);
  }

  /// Computes the type that [element] will have after migration.
  ///
  /// If [targetType] is present, and [element] is a class member, it is the
  /// type of the class within which [element] is being accessed; this is used
  /// to perform the correct substitutions.
  DartType _computeMigratedType(Element element) {
    element = element.declaration!;
    if (element is ClassElement || element is TypeParameterElement) {
      return typeProvider.typeType;
    } else if (element is PropertyAccessorElement &&
        element.isSynthetic &&
        !element.variable.isSynthetic) {
      var variableType = _variables!
          .toFinalType(_variables!.decoratedElementType(element.variable));
      if (element.isSetter) {
        return FunctionTypeImpl(
            returnType: typeProvider.voidType,
            typeFormals: [],
            parameters: [
              ParameterElementImpl.synthetic(
                  'value', variableType, ParameterKind.REQUIRED)
            ],
            nullabilitySuffix: NullabilitySuffix.none);
      } else {
        return FunctionTypeImpl(
            returnType: variableType,
            typeFormals: [],
            parameters: [],
            nullabilitySuffix: NullabilitySuffix.none);
      }
    } else {
      return _variables!.toFinalType(_variables!.decoratedElementType(element));
    }
  }

  /// Returns the [NodeChange] object accumulating changes for the given [node],
  /// creating it if necessary.
  NodeChange _getChange(AstNode node) =>
      changes[node] ??= NodeChange.create(node)!;

  /// Determines whether the given [node], which is a null-aware method
  /// invocation, property access, or index expression, should remain null-aware
  /// after migration.
  bool _shouldStayNullAware(Expression node) {
    Expression? target;
    if (node is PropertyAccess) {
      target = node.target;
    } else if (node is MethodInvocation) {
      target = node.target;
    } else {
      throw StateError('Unexpected expression type: ${node.runtimeType}');
    }
    if (!_typeSystem.isPotentiallyNullable(target!.staticType!)) {
      (_getChange(node) as NodeChangeForNullAware).removeNullAwareness = true;
      return false;
    }
    return true;
  }

  static TypeSystemImpl _makeNnbdTypeSystem(
      TypeProvider nnbdTypeProvider,
      TypeSystemImpl typeSystem,
      MigrationResolutionHooksImpl migrationResolutionHooks) {
    // TODO(paulberry): do we need to test both possible values of
    // strictInference?
    return TypeSystemImpl(
        implicitCasts: typeSystem.implicitCasts,
        isNonNullableByDefault: true,
        strictCasts: typeSystem.strictCasts,
        strictInference: typeSystem.strictInference,
        typeProvider: nnbdTypeProvider);
  }
}

/// Fix reason object when adding a null check because of an explicit hint.
class FixReason_NullCheckHint implements SimpleFixReasonInfo {
  @override
  final CodeReference codeReference;

  FixReason_NullCheckHint(this.codeReference);

  @override
  String get description => 'Null check hint';
}

/// Implementation of [MigrationResolutionHooks] that interfaces with
/// [FixBuilder].
class MigrationResolutionHooksImpl
    with ResolutionUtils
    implements MigrationResolutionHooks {
  FixBuilder? _fixBuilder;

  final Expando<List<CollectionElement>> _collectionElements = Expando();

  final Expando<bool> _shouldStayNullAware = Expando();

  final Map<Expression, _AssignmentLikeExpressionHandler>
      _assignmentLikeExpressionHandlers = {};

  FlowAnalysis<AstNode, Statement, Expression, PromotableElement, DartType>?
      _flowAnalysis;

  /// Deferred processing that should be performed once we have finished
  /// evaluating the type of a method invocation.
  final Map<MethodInvocation, DartType Function(DartType)>
      _deferredMethodInvocationProcessing = {};

  TypeProvider get typeProvider => _fixBuilder!.typeProvider;

  @override
  void freshTypeParameterCreated(TypeParameterElement newTypeParameter,
      TypeParameterElement oldTypeParameter) {
    DecoratedTypeParameterBounds.current!.put(newTypeParameter,
        DecoratedTypeParameterBounds.current!.get(oldTypeParameter));
  }

  @override
  List<InterfaceType> getClassInterfaces(ClassElementImpl element) {
    return _wrapExceptions(
        _fixBuilder!.unit,
        () => element.interfacesInternal,
        () => [
              for (var interface in element.interfacesInternal)
                _getClassInterface(element, interface.element)
            ]);
  }

  @override
  bool? getConditionalKnownValue(AstNode node) =>
      _wrapExceptions(node, () => null, () {
        // TODO(paulberry): handle conditional expressions.
        var conditionalDiscard = _fixBuilder!._variables!
            .getConditionalDiscard(_fixBuilder!.source, node);
        if (conditionalDiscard == null) {
          return null;
        } else {
          if (conditionalDiscard.keepTrue && conditionalDiscard.keepFalse) {
            return null;
          }
          var conditionValue = conditionalDiscard.keepTrue;
          (_fixBuilder!._getChange(node) as NodeChangeForConditional)
            ..conditionValue = conditionValue
            ..conditionReason = conditionalDiscard.reason;
          // If we're just issuing warnings, instruct the resolver to go ahead
          // and visit both branches of the conditional.
          return _fixBuilder!.warnOnWeakCode! ? null : conditionValue;
        }
      });

  @override
  List<ParameterElement> getExecutableParameters(
      ExecutableElementImpl element) {
    if (_fixBuilder!._graph.isBeingMigrated(element.library.source)) {
      // The element is part of a library that's being migrated, so its
      // parameters all have been visited (and thus have their own final
      // types).  So we don't need to do anything.
      return const ElementTypeProvider().getExecutableParameters(element);
    } else {
      // The element is not part of a library that's being migrated, so its
      // parameters probably haven't been visited; we need to get the parameters
      // from the final function type.
      return getExecutableType(element).parameters;
    }
  }

  @override
  DartType getExecutableReturnType(Element element) =>
      getExecutableType(element as ElementImplWithFunctionType).returnType;

  @override
  FunctionType getExecutableType(ElementImplWithFunctionType element) =>
      _wrapExceptions(_fixBuilder!.unit, () => element.typeInternal, () {
        var type = _fixBuilder!._computeMigratedType(element);
        Element baseElement = element;
        if (baseElement is Member) {
          type = baseElement.substitution.substituteType(type);
        }
        return type as FunctionType;
      });

  @override
  DartType getExtendedType(ExtensionElementImpl element) {
    return _wrapExceptions(
        _fixBuilder!.unit,
        () => element.extendedTypeInternal,
        () => _fixBuilder!._variables!.toFinalType(
            _fixBuilder!._variables!.decoratedElementType(element)));
  }

  @override
  DartType getFieldType(PropertyInducingElementImpl element) =>
      _wrapExceptions(_fixBuilder!.unit, () => element.typeInternal, () {
        assert(!element.isSynthetic);
        return _fixBuilder!._computeMigratedType(element);
      });

  @override
  List<CollectionElement> getListElements(ListLiteral node) => _wrapExceptions(
      node,
      () => node.elements,
      () => _collectionElements[node] ??=
          _transformCollectionElements(node.elements));

  @override
  List<CollectionElement> getSetOrMapElements(SetOrMapLiteral node) =>
      _wrapExceptions(
          node,
          () => node.elements,
          () => _collectionElements[node] ??=
              _transformCollectionElements(node.elements));

  @override
  DartType? getTypeParameterBound(TypeParameterElementImpl element) {
    var decoratedBound = _fixBuilder!._variables!
        .decoratedTypeParameterBound(element, allowNullUnparentedBounds: true);
    if (decoratedBound == null) return element.boundInternal;
    var bound = _fixBuilder!._variables!.toFinalType(decoratedBound);
    if (bound.isDynamic) {
      return null;
    } else if (bound.isDartCoreObject &&
        bound.nullabilitySuffix == NullabilitySuffix.question) {
      return null;
    } else {
      return bound;
    }
  }

  @override
  DartType getVariableType(VariableElementImpl variable) =>
      _wrapExceptions(_fixBuilder!.unit, () => variable.typeInternal, () {
        if (variable.library == null) {
          // This is a synthetic variable created during resolution (e.g. a
          // parameter of a function type), so the type it currently has is the
          // correct post-migration type.
          return variable.typeInternal;
        }
        if (variable is ParameterElement) {
          var enclosingElement = variable.enclosingElement;
          if (enclosingElement is PropertyAccessorElement &&
              enclosingElement.isSynthetic) {
            // This is the parameter of a synthetic getter, so it has the same
            // type as the corresponding variable.
            return _fixBuilder!._computeMigratedType(enclosingElement.variable);
          }
        }
        return _fixBuilder!._computeMigratedType(variable);
      });

  @override
  bool isIndexExpressionNullAware(IndexExpression node) {
    // Null-aware index expressions weren't supported prior to NNBD.
    assert(!node.isNullAware);
    return false;
  }

  @override
  bool isLibraryNonNullableByDefault(LibraryElementImpl element) {
    return _fixBuilder!._graph.isBeingMigrated(element.source) ||
        element.isNonNullableByDefaultInternal;
  }

  @override
  bool isMethodInvocationNullAware(MethodInvocation node) {
    return node.isNullAware &&
        (_shouldStayNullAware[node] ??=
            _fixBuilder!._shouldStayNullAware(node));
  }

  /// Indicates whether the given [element] is a member of an extension on a
  /// potentially nullable type (and hence the extension member can be invoked
  /// on a nullable type without introducing a null check).
  bool isNullableExtensionMember(Element? element) {
    if (element != null) {
      var enclosingElement = element.enclosingElement;
      if (enclosingElement is ExtensionElement) {
        return _fixBuilder!._typeSystem
            .isPotentiallyNullable(enclosingElement.extendedType);
      }
    }
    return false;
  }

  @override
  bool isPropertyAccessNullAware(PropertyAccess node) {
    return node.isNullAware &&
        (_shouldStayNullAware[node] ??=
            _fixBuilder!._shouldStayNullAware(node));
  }

  @override
  DartType modifyExpressionType(Expression node, DartType type) =>
      _wrapExceptions(node, () => type, () {
        if (node is NamedExpression) {
          // Do not attempt to modify named expressions.  We should already have
          // been called for [node.expression], and we should have made the
          // necessary modifications then.
          return type;
        }
        var parent = node.parent;
        if (parent is AssignmentExpression) {
          if (parent.leftHandSide == node) {
            return type;
          }
          return _assignmentLikeExpressionHandlers[parent]!
              .modifyAssignmentRhs(this, node, type);
        } else if (parent is PrefixExpression) {
          if (_isIncrementOrDecrementOperator(parent.operator.type)) {
            return type;
          }
        } else if (parent is PostfixExpression) {
          if (_isIncrementOrDecrementOperator(parent.operator.type)) {
            return type;
          }
        }
        return _modifyRValueType(node, type);
      });

  @override
  DartType modifyInferredParameterType(
      ParameterElement parameter, DartType type) {
    var postMigrationType = parameter.type;
    if (postMigrationType != type) {
      // TODO(paulberry): test field formal parameters.
      _fixBuilder!._addedParameterTypes[parameter] = postMigrationType;
      return postMigrationType;
    }
    return type;
  }

  @override
  void setCompoundAssignmentExpressionTypes(CompoundAssignmentExpression node) {
    assert(_assignmentLikeExpressionHandlers[node] == null);
    if (node is AssignmentExpression) {
      var handler = _AssignmentExpressionHandler(node);
      _assignmentLikeExpressionHandlers[node] = handler;
      handler.handleLValueType(this, node.readType, node.writeType!);
    } else if (node is PrefixExpression) {
      assert(_isIncrementOrDecrementOperator(node.operator.type));
      var handler = _PrefixExpressionHandler(node);
      _assignmentLikeExpressionHandlers[node] = handler;
      handler.handleLValueType(this, node.readType, node.writeType!);
      handler.handleAssignmentRhs(this, _fixBuilder!.typeProvider.intType);
    } else if (node is PostfixExpression) {
      assert(_isIncrementOrDecrementOperator(node.operator.type));
      var handler = _PostfixExpressionHandler(node);
      _assignmentLikeExpressionHandlers[node] = handler;
      handler.handleLValueType(this, node.readType, node.writeType!);
      handler.handleAssignmentRhs(this, _fixBuilder!.typeProvider.intType);
    } else {
      throw StateError('(${node.runtimeType}) $node');
    }
  }

  @override
  void setFlowAnalysis(
      FlowAnalysis<AstNode, Statement, Expression, PromotableElement, DartType>?
          flowAnalysis) {
    _flowAnalysis = flowAnalysis;
  }

  DartType _addCastOrNullCheck(
      Expression node, DartType expressionType, DartType contextType) {
    var checks =
        _fixBuilder!._variables!.expressionChecks(_fixBuilder!.source, node);
    var change = _createExpressionChange(node, expressionType, contextType);
    var info = AtomicEditInfo(change.description, checks?.edges ?? {});
    (_fixBuilder!._getChange(node) as NodeChangeForExpression)
        .addExpressionChange(change, info);
    return change.resultType;
  }

  DartType _addNullCheck(Expression node, DartType type,
      {AtomicEditInfo? info, HintComment? hint}) {
    var change = _createNullCheckChange(node, type, hint: hint);
    var checks =
        _fixBuilder!._variables!.expressionChecks(_fixBuilder!.source, node);
    info ??= AtomicEditInfo(change.description, checks?.edges ?? {});
    var nodeChangeForExpression =
        _fixBuilder!._getChange(node) as NodeChangeForExpression;
    nodeChangeForExpression.addExpressionChange(change, info);
    return change.resultType;
  }

  ExpressionChange _createExpressionChange(
      Expression node, DartType expressionType, DartType contextType) {
    var expressionFutureTypeArgument = _getFutureTypeArgument(expressionType);
    var contextFutureTypeArgument = _getFutureTypeArgument(contextType);
    if (expressionFutureTypeArgument != null &&
        contextFutureTypeArgument != null) {
      return IntroduceThenChange(
          contextType,
          _createExpressionChange(
              node, expressionFutureTypeArgument, contextFutureTypeArgument));
    }
    // Either a cast or a null check is needed.  We prefer to do a null
    // check if we can.
    var nonNullType = _fixBuilder!._typeSystem.promoteToNonNull(expressionType);
    if (_fixBuilder!._typeSystem.isSubtypeOf(nonNullType, contextType)) {
      return _createNullCheckChange(node, expressionType);
    } else {
      _flowAnalysis!.asExpression_end(node, contextType);
      return IntroduceAsChange(contextType,
          isDowncast: _fixBuilder!._typeSystem
              .isSubtypeOf(contextType, expressionType));
    }
  }

  ExpressionChange _createNullCheckChange(Expression node, DartType type,
      {HintComment? hint}) {
    var resultType =
        _fixBuilder!._typeSystem.promoteToNonNull(type as TypeImpl);
    _flowAnalysis!.nonNullAssert_end(node);
    return type.isDartCoreNull && hint == null
        ? NoValidMigrationChange(resultType)
        : NullCheckChange(resultType, hint: hint);
  }

  Expression _findNullabilityContextAncestor(Expression node) {
    while (true) {
      var parent = node.parent;
      if (parent is BinaryExpression &&
          parent.operator.type == TokenType.QUESTION_QUESTION &&
          identical(node, parent.rightOperand)) {
        node = parent;
        continue;
      }
      return node;
    }
  }

  InterfaceType _getClassInterface(
      ClassElement class_, ClassElement superclass) {
    var decoratedSupertype = _fixBuilder!._decoratedClassHierarchy!
        .getDecoratedSupertype(class_, superclass);
    var finalType = _fixBuilder!._variables!.toFinalType(decoratedSupertype);
    return finalType as InterfaceType;
  }

  DartType? _getFutureTypeArgument(DartType type) {
    if (type is InterfaceType && type.isDartAsyncFuture) {
      var typeArguments = type.typeArguments;
      if (typeArguments.isNotEmpty) {
        return typeArguments.first;
      }
    }
    return null;
  }

  DartType _modifyRValueType(Expression node, DartType type,
      {DartType? context}) {
    if (node is MethodInvocation) {
      var deferredProcessing = _deferredMethodInvocationProcessing.remove(node);
      if (deferredProcessing != null) {
        type = deferredProcessing(type);
      }
    }
    var hint =
        _fixBuilder!._variables!.getNullCheckHint(_fixBuilder!.source, node);
    if (hint != null) {
      type = _addNullCheck(node, type,
          info: AtomicEditInfo(
              NullabilityFixDescription.checkExpressionDueToHint,
              {
                FixReasonTarget.root:
                    FixReason_NullCheckHint(CodeReference.fromAstNode(node))
              },
              hintComment: hint),
          hint: hint);
    }
    if (type.isDynamic) return type;
    var ancestor = _findNullabilityContextAncestor(node);
    context ??=
        InferenceContext.getContext(ancestor) ?? DynamicTypeImpl.instance;
    if (!_fixBuilder!._typeSystem.isSubtypeOf(type, context)) {
      var transformationInfo =
          _fixBuilder!._whereOrNullTransformer.tryTransformOrElseArgument(node);
      if (transformationInfo != null) {
        // We can fix this by dropping the node and changing the method call.
        _fixBuilder!.needsIterableExtension = true;
        _fixBuilder!._neededPackages['collection'] =
            Version.parse('1.15.0-nullsafety.4');
        var info = AtomicEditInfo(
            NullabilityFixDescription.changeMethodName(
                transformationInfo.originalName,
                transformationInfo.replacementName),
            {});
        (_fixBuilder!._getChange(transformationInfo.methodInvocation.methodName)
                as NodeChangeForMethodName)
            .replaceWith(transformationInfo.replacementName, info);
        (_fixBuilder!._getChange(
                    transformationInfo.methodInvocation.argumentList)
                as NodeChangeForArgumentList)
            .dropArgument(transformationInfo.orElseArgument, info);
        _deferredMethodInvocationProcessing[
                transformationInfo.methodInvocation] =
            (methodInvocationType) => _fixBuilder!._typeSystem
                .makeNullable(methodInvocationType as TypeImpl);
        return type;
      }
      return _addCastOrNullCheck(node, type, context);
    }
    if (!_fixBuilder!._typeSystem.isNullable(type)) return type;
    if (_needsNullCheckDueToStructure(ancestor)) {
      return _addNullCheck(node, type);
    }
    return type;
  }

  bool _needsNullCheckDueToStructure(Expression node) {
    var parent = node.parent;

    if (parent is BinaryExpression) {
      if (identical(node, parent.leftOperand)) {
        var operatorType = parent.operator.type;
        if (operatorType == TokenType.QUESTION_QUESTION ||
            operatorType == TokenType.EQ_EQ ||
            operatorType == TokenType.BANG_EQ) {
          return false;
        } else {
          return !isNullableExtensionMember(parent.staticElement);
        }
      }
    } else if (parent is PrefixedIdentifier) {
      if (isDeclaredOnObject(parent.identifier.name) ||
          isNullableExtensionMember(parent.identifier.staticElement)) {
        return false;
      }
      return identical(node, parent.prefix);
    } else if (parent is PropertyAccess) {
      if (isDeclaredOnObject(parent.propertyName.name) ||
          isNullableExtensionMember(parent.propertyName.staticElement)) {
        return false;
      }
      // TODO(paulberry): what about cascaded?
      return parent.operator.type == TokenType.PERIOD &&
          identical(node, parent.target);
    } else if (parent is MethodInvocation) {
      if (isDeclaredOnObject(parent.methodName.name) ||
          isNullableExtensionMember(parent.methodName.staticElement)) {
        return false;
      }
      // TODO(paulberry): what about cascaded?
      return parent.operator!.type == TokenType.PERIOD &&
          identical(node, parent.target);
    } else if (parent is IndexExpression) {
      if (identical(node, parent.target)) {
        return !isNullableExtensionMember(parent.staticElement);
      } else {
        return false;
      }
    } else if (parent is ConditionalExpression) {
      return identical(node, parent.condition);
    } else if (parent is FunctionExpressionInvocation) {
      if (identical(node, parent.function)) {
        return !isNullableExtensionMember(parent.staticElement);
      } else {
        return false;
      }
    } else if (parent is PrefixExpression) {
      // TODO(paulberry): for prefix increment/decrement, inserting a null check
      // isn't sufficient.
      return !isNullableExtensionMember(parent.staticElement);
    } else if (parent is ThrowExpression) {
      return true;
    }
    return false;
  }

  CollectionElement? _transformCollectionElement(CollectionElement? node) {
    while (node is IfElement) {
      var conditionalDiscard = _fixBuilder!._variables!
          .getConditionalDiscard(_fixBuilder!.source, node);
      if (conditionalDiscard == null ||
          conditionalDiscard.keepTrue && conditionalDiscard.keepFalse) {
        return node;
      }
      var conditionValue = conditionalDiscard.keepTrue;
      var ifElement = node;
      node = conditionValue ? ifElement.thenElement : ifElement.elseElement;
    }
    return node;
  }

  List<CollectionElement> _transformCollectionElements(
      NodeList<CollectionElement> elements) {
    return elements
        .map(_transformCollectionElement)
        .whereType<CollectionElement>()
        .toList();
  }

  /// Runs the computation in [compute].  If an exception occurs and
  /// [_fixBuilder.listener] is non-null, the exception is reported to the
  /// listener and [fallback] is called to produce a result.  Otherwise the
  /// exception is propagated normally.
  T _wrapExceptions<T>(
      AstNode? node, T Function() fallback, T Function() compute) {
    if (_fixBuilder!.listener == null) return compute();
    try {
      return compute();
    } catch (exception, stackTrace) {
      _fixBuilder!.listener!
          .reportException(_fixBuilder!.source, node, exception, stackTrace);
      return fallback();
    }
  }
}

/// Problem reported by [FixBuilder] when encountering a non-nullable unnamed
/// optional parameter that lacks a default value.
class NonNullableUnnamedOptionalParameter implements Problem {
  const NonNullableUnnamedOptionalParameter();
}

/// Common supertype for problems reported by [FixBuilder._addProblem].
abstract class Problem {}

/// Specialization of [_AssignmentLikeExpressionHandler] for
/// [AssignmentExpression].
class _AssignmentExpressionHandler extends _AssignmentLikeExpressionHandler {
  @override
  final AssignmentExpression node;

  _AssignmentExpressionHandler(this.node);

  @override
  MethodElement? get combiner => node.staticElement;

  @override
  TokenType get combinerType => node.operator.type;

  @override
  Expression get target => node.leftHandSide;
}

/// Data structure keeping track of intermediate results when the fix builder
/// is handling an assignment expression, or an expression that desugars to an
/// assignment.
abstract class _AssignmentLikeExpressionHandler {
  /// For compound and null-aware assignments, the type read from the LHS.
  late final DartType? readType;

  /// The type that may be written to the LHS.
  late final DartType writeType;

  /// The type that should be used as a context type when inferring the RHS.
  DartType? rhsContextType;

  /// Gets the static element representing the combiner.
  MethodElement? get combiner;

  /// Gets the operator type representing the combiner.
  TokenType get combinerType;

  /// Gets the expression in question.
  Expression get node;

  /// Gets the target of the assignment.
  Expression get target;

  /// Called after visiting the RHS of the assignment, to verify that for
  /// compound assignments, the return value of the assignment is assignable to
  /// [writeType].
  void handleAssignmentRhs(
      MigrationResolutionHooksImpl hooks, DartType rhsType) {
    MethodElement? combiner = this.combiner;
    if (combiner != null) {
      var fixBuilder = hooks._fixBuilder!;
      var combinerReturnType =
          fixBuilder._typeSystem.refineBinaryExpressionType(
        readType!,
        combinerType,
        rhsType,
        combiner.returnType,
        combiner,
      );
      if (!fixBuilder._typeSystem.isSubtypeOf(combinerReturnType, writeType)) {
        (fixBuilder._getChange(node) as NodeChangeForAssignmentLike)
            .hasBadCombinedType = true;
      }
    }
  }

  /// Called after visiting the LHS of the assignment.  Records the [readType],
  /// [writeType], and [rhsContextType].  Also verifies that for compound
  /// assignments, the [readType] is non-nullable, and that for null-aware
  /// assignments, the [readType] is nullable.
  void handleLValueType(MigrationResolutionHooksImpl hooks,
      DartType? readTypeToSet, DartType writeTypeToSet) {
    assert(writeTypeToSet.nullabilitySuffix != NullabilitySuffix.star);
    writeType = writeTypeToSet;
    // TODO(scheglov) Remove this after the analyzer breaking change that
    // will top setting types for LHS.
    (target as ExpressionImpl).staticType = writeTypeToSet;
    var fixBuilder = hooks._fixBuilder;
    if (combinerType == TokenType.EQ) {
      rhsContextType = writeTypeToSet;
    } else {
      readType = readTypeToSet;
      assert(readType!.nullabilitySuffix != NullabilitySuffix.star);
      if (combinerType == TokenType.QUESTION_QUESTION_EQ) {
        rhsContextType = writeTypeToSet;
        if (fixBuilder!._typeSystem.isNonNullable(readType!)) {
          (fixBuilder._getChange(node) as NodeChangeForAssignment)
              .isWeakNullAware = true;
        }
      } else {
        if (!readType!.isDynamic &&
            fixBuilder!._typeSystem.isPotentiallyNullable(readType!)) {
          (fixBuilder._getChange(node) as NodeChangeForAssignmentLike)
              .hasNullableSource = true;
        }
      }
    }
  }

  /// Called after visiting the RHS of the assignment.
  DartType modifyAssignmentRhs(MigrationResolutionHooksImpl hooks,
      Expression subexpression, DartType type) {
    type =
        hooks._modifyRValueType(subexpression, type, context: rhsContextType);
    handleAssignmentRhs(hooks, type);
    return type;
  }
}

/// Visitor that computes additional migrations on behalf of [FixBuilder] that
/// should be run after resolution
class _FixBuilderPostVisitor extends GeneralizingAstVisitor<void>
    with PermissiveModeVisitor<void> {
  final FixBuilder _fixBuilder;

  _FixBuilderPostVisitor(this._fixBuilder);

  @override
  NullabilityMigrationListener? get listener => _fixBuilder.listener;

  @override
  Source? get source => _fixBuilder.source;

  @override
  void visitAsExpression(AsExpression node) {
    if (!_fixBuilder._variables!.wasUnnecessaryCast(_fixBuilder.source, node) &&
        BestPracticesVerifier.isUnnecessaryCast(
            node, _fixBuilder._typeSystem)) {
      (_fixBuilder._getChange(node) as NodeChangeForAsExpression).removeAs =
          true;
    }
  }

  @override
  void visitCompilationUnit(CompilationUnit node) {
    if ((node as CompilationUnitImpl).languageVersionToken != null) {
      (_fixBuilder._getChange(node) as NodeChangeForCompilationUnit)
          .removeLanguageVersionComment = true;
    }
    if (_fixBuilder.needsIterableExtension) {
      var packageCollectionImport =
          _findImportDirective(node, 'package:collection/collection.dart');
      if (packageCollectionImport != null) {
        for (var combinator in packageCollectionImport.combinators) {
          if (combinator is ShowCombinator) {
            _ensureShows(combinator, 'IterableExtension');
          }
        }
      } else {
        (_fixBuilder._getChange(node) as NodeChangeForCompilationUnit)
            .addImport(
                'package:collection/collection.dart', 'IterableExtension');
      }
    }
    super.visitCompilationUnit(node);
  }

  @override
  void visitSimpleFormalParameter(SimpleFormalParameter node) {
    if (node.type == null) {
      var typeToAdd = _fixBuilder._addedParameterTypes[node.declaredElement!];
      if (typeToAdd != null) {
        (_fixBuilder._getChange(node) as NodeChangeForSimpleFormalParameter)
            .addExplicitType = typeToAdd;
      }
    }
  }

  @override
  void visitVariableDeclarationList(VariableDeclarationList node) {
    if (node.type == null) {
      // TODO(paulberry): for fields, handle inference via override as well.
      List<DartType> neededTypes = [];
      List<DartType> inferredTypes = [];
      bool explicitTypeNeeded = false;
      for (var variableDeclaration in node.variables) {
        var neededType = _fixBuilder
            ._computeMigratedType(variableDeclaration.declaredElement!);
        neededTypes.add(neededType);
        var inferredType = variableDeclaration.initializer?.staticType ??
            _fixBuilder.typeProvider.dynamicType;
        inferredTypes.add(inferredType);
        if (neededType != inferredType) {
          explicitTypeNeeded = true;
        }
      }
      if (explicitTypeNeeded) {
        var firstNeededType = neededTypes[0];
        if (neededTypes.any((t) => t != firstNeededType)) {
          throw UnimplementedError(
              'Different explicit types needed in multi-variable declaration');
        } else {
          (_fixBuilder._getChange(node) as NodeChangeForVariableDeclarationList)
              .addExplicitType = firstNeededType;
        }
      }
    }

    // Check if the nullability node for a single variable declaration has been
    // declared to be late.
    if (node.variables.length == 1) {
      var variableElement = node.variables.single.declaredElement!;
      var lateCondition = _fixBuilder._variables!
          .decoratedElementType(variableElement)
          .node!
          .lateCondition;
      switch (lateCondition) {
        case LateCondition.possiblyLate:
          (_fixBuilder._getChange(node) as NodeChangeForVariableDeclarationList)
              .lateAdditionReason = LateAdditionReason.inference;
          break;
        case LateCondition.possiblyLateDueToTestSetup:
          (_fixBuilder._getChange(node) as NodeChangeForVariableDeclarationList)
              .lateAdditionReason = LateAdditionReason.testVariableInference;
          break;
        case LateCondition.lateDueToHint:
        // Handled below.
        case LateCondition.notLate:
        // Nothing to do.
      }
    }

    var lateHint = _fixBuilder._variables!.getLateHint(source, node);
    if (lateHint != null) {
      (_fixBuilder._getChange(node) as NodeChangeForVariableDeclarationList)
          .lateHint = lateHint;
    }
    super.visitVariableDeclarationList(node);
  }

  /// Creates the necessary changes to ensure that [combinator] shows [name].
  void _ensureShows(ShowCombinator combinator, String name) {
    if (combinator.shownNames.any((shownName) => shownName.name == name)) {
      return;
    }
    (_fixBuilder._getChange(combinator) as NodeChangeForShowCombinator)
        .addName(name);
  }

  /// Searches [unit] for an unprefixed import directive whose URI matches
  /// [uri], returning it if found, or `null` if not found.
  ImportDirective? _findImportDirective(CompilationUnit unit, String uri) {
    for (var directive in unit.directives) {
      if (directive is ImportDirective &&
          directive.prefix == null &&
          directive.uriContent == uri) {
        return directive;
      }
    }
    return null;
  }
}

/// Visitor that computes additional migrations on behalf of [FixBuilder] that
/// don't need to be integrated into the resolver itself, and should be run
/// prior to resolution
class _FixBuilderPreVisitor extends GeneralizingAstVisitor<void>
    with PermissiveModeVisitor<void> {
  final FixBuilder _fixBuilder;

  _FixBuilderPreVisitor(this._fixBuilder);

  @override
  NullabilityMigrationListener? get listener => _fixBuilder.listener;

  @override
  Source? get source => _fixBuilder.source;

  @override
  void visitDefaultFormalParameter(DefaultFormalParameter node) {
    var element = node.declaredElement;
    if (node.defaultValue == null) {
      var requiredHint =
          _fixBuilder._variables!.getRequiredHint(_fixBuilder.source, node);
      var nullabilityNode =
          _fixBuilder._variables!.decoratedElementType(element!).node!;
      if (!nullabilityNode.isNullable) {
        var enclosingElement = element.enclosingElement;
        if (enclosingElement is ConstructorElement &&
            enclosingElement.isFactory &&
            enclosingElement.redirectedConstructor != null) {
          // Redirecting factory constructors inherit their parameters' default
          // values from the constructors they redirect to, so the lack of a
          // default value doesn't mean the parameter has to be nullable.
        } else if (element.isNamed) {
          _addRequiredKeyword(node, nullabilityNode, requiredHint);
        } else {
          _fixBuilder._addProblem(
              node, const NonNullableUnnamedOptionalParameter());
        }
      } else if (requiredHint != null ||
          element.metadata.any((m) => m.isRequired)) {
        _addRequiredKeyword(node, nullabilityNode, requiredHint);
      }
    }
    super.visitDefaultFormalParameter(node);
  }

  @override
  void visitFieldFormalParameter(FieldFormalParameter node) {
    if (node.type == null) {
      // Potentially add an explicit type to a field formal parameter.
      var decl = node.declaredElement as FieldFormalParameterElement;
      var decoratedType = _fixBuilder._variables!.decoratedElementType(decl);
      var field = decl.field;
      if (field != null) {
        var decoratedFieldType =
            _fixBuilder._variables!.decoratedElementType(field);
        var typeToAdd = _fixBuilder._variables!.toFinalType(decoratedType);
        var fieldFinalType =
            _fixBuilder._variables!.toFinalType(decoratedFieldType);
        if (typeToAdd is InterfaceType &&
            !_fixBuilder._typeSystem.isSubtypeOf(fieldFinalType, typeToAdd)) {
          (_fixBuilder._getChange(node) as NodeChangeForFieldFormalParameter)
              .addExplicitType = typeToAdd;
        }
      }
    } else if (node.parameters != null) {
      // Handle function-typed field formal parameters.
      var decoratedType =
          _fixBuilder._variables!.decoratedElementType(node.declaredElement!);
      if (decoratedType.node!.isNullable) {
        (_fixBuilder._getChange(node) as NodeChangeForFieldFormalParameter)
            .recordNullability(decoratedType, decoratedType.node!.isNullable,
                nullabilityHint:
                    _fixBuilder._variables!.getNullabilityHint(source, node));
      }
    }
    super.visitFieldFormalParameter(node);
  }

  @override
  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
    var decoratedType =
        _fixBuilder._variables!.decoratedElementType(node.declaredElement!);
    if (decoratedType.node!.isNullable) {
      (_fixBuilder._getChange(node)
              as NodeChangeForFunctionTypedFormalParameter)
          .recordNullability(decoratedType, decoratedType.node!.isNullable,
              nullabilityHint:
                  _fixBuilder._variables!.getNullabilityHint(source, node));
    }
    super.visitFunctionTypedFormalParameter(node);
  }

  @override
  void visitGenericFunctionType(GenericFunctionType node) {
    var decoratedType = _fixBuilder._variables!
        .decoratedTypeAnnotation(_fixBuilder.source, node);
    if (!typeIsNonNullableByContext(node)) {
      _makeTypeNameNullable(node, decoratedType);
    }
    (node as GenericFunctionTypeImpl).type =
        _fixBuilder._variables!.toFinalType(decoratedType);
    super.visitGenericFunctionType(node);
  }

  @override
  void visitMethodDeclaration(MethodDeclaration node) {
    if (node.isGetter && node.isAbstract) {
      for (var annotation in node.metadata) {
        if (annotation.arguments == null) {
          var element = annotation.element;
          if (element is PropertyAccessorElement &&
              element.name == 'nullable') {
            if (element.enclosingElement is CompilationUnitElement) {
              if (element.library.source.uri.toString() ==
                  'package:built_value/built_value.dart') {
                var info = AtomicEditInfo(
                    NullabilityFixDescription.removeNullableAnnotation, {});
                (_fixBuilder._getChange(node) as NodeChangeForMethodDeclaration)
                  ..annotationToRemove = annotation
                  ..removeAnnotationInfo = info;
              }
            }
          }
        }
      }
    }
    super.visitMethodDeclaration(node);
  }

  @override
  void visitNamedType(NamedType node) {
    var decoratedType = _fixBuilder._variables!
        .decoratedTypeAnnotation(_fixBuilder.source, node);
    if (!typeIsNonNullableByContext(node)) {
      if (!_typeIsNaturallyNullable(decoratedType.type!)) {
        _makeTypeNameNullable(node, decoratedType);
      }
    }
    (node as NamedTypeImpl).type =
        _fixBuilder._variables!.toFinalType(decoratedType);
    super.visitNamedType(node);
  }

  void _addRequiredKeyword(DefaultFormalParameter parameter,
      NullabilityNode node, HintComment? requiredHint) {
    // Change an existing `@required` annotation into a `required` keyword if
    // possible.
    final element = parameter.declaredElement!;
    final method = element.enclosingElement!;
    final cls = method.enclosingElement!;
    var info = AtomicEditInfo(
        NullabilityFixDescription.addRequired(
            cls.name, method.name, element.name),
        {FixReasonTarget.root: node});
    var metadata = parameter.metadata;
    if (metadata.isNotEmpty) {
      // Only the last annotation can be changed into a `required` keyword;
      // changing an earlier annotation into a keyword would be illegal.
      var lastAnnotation = metadata.last;
      if (lastAnnotation.elementAnnotation!.isRequired) {
        (_fixBuilder._getChange(lastAnnotation) as NodeChangeForAnnotation)
          ..changeToRequiredKeyword = true
          ..changeToRequiredKeywordInfo = info;
        return;
      }
    }
    // Otherwise create a new `required` keyword.
    var nodeChange = (_fixBuilder._getChange(parameter)
        as NodeChangeForDefaultFormalParameter)
      ..addRequiredKeyword = true
      ..addRequiredKeywordInfo = info
      ..requiredHint = requiredHint;
    var requiredAnnotation = metadata.firstWhereOrNull(
        (annotation) => annotation.elementAnnotation!.isRequired);
    if (requiredAnnotation != null) {
      // If the parameter was annotated with `@required`, but it was not the
      // last annotation, we remove the annotation in addition to adding the
      // `required` keyword.
      nodeChange
        ..annotationToRemove = requiredAnnotation
        ..removeAnnotationInfo = info;
    }
  }

  void _makeTypeNameNullable(TypeAnnotation node, DecoratedType decoratedType) {
    bool makeNullable = decoratedType.node!.isNullable;
    if (decoratedType.type!.isDartAsyncFutureOr) {
      var typeArguments = decoratedType.typeArguments;
      if (typeArguments.length == 1) {
        var typeArgument = typeArguments[0]!;
        if ((_typeIsNaturallyNullable(typeArgument.type!) ||
            typeArgument.node!.isNullable)) {
          // FutureOr<T?>? is equivalent to FutureOr<T?>, so there is no need to
          // make this type nullable.
          makeNullable = false;
        }
      }
    }
    (_fixBuilder._getChange(node) as NodeChangeForTypeAnnotation)
        .recordNullability(
            decoratedType, makeNullable,
            nullabilityHint:
                _fixBuilder._variables!.getNullabilityHint(source, node));
  }

  bool _typeIsNaturallyNullable(DartType type) =>
      type.isDynamic || type.isVoid || type.isDartCoreNull;
}

/// Specialization of [_AssignmentLikeExpressionHandler] for
/// [PostfixExpression].
class _PostfixExpressionHandler extends _AssignmentLikeExpressionHandler {
  @override
  final PostfixExpression node;

  _PostfixExpressionHandler(this.node)
      : assert(_isIncrementOrDecrementOperator(node.operator.type));

  @override
  MethodElement? get combiner => node.staticElement;

  @override
  TokenType get combinerType => node.operator.type;

  @override
  Expression get target => node.operand;
}

/// Specialization of [_AssignmentLikeExpressionHandler] for
/// [PrefixExpression].
class _PrefixExpressionHandler extends _AssignmentLikeExpressionHandler {
  @override
  final PrefixExpression node;

  _PrefixExpressionHandler(this.node)
      : assert(_isIncrementOrDecrementOperator(node.operator.type));

  @override
  MethodElement? get combiner => node.staticElement;

  @override
  TokenType get combinerType => node.operator.type;

  @override
  Expression get target => node.operand;
}
