// 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/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:nnbd_migration/src/edit_plan.dart';
import 'package:nnbd_migration/src/hint_action.dart';

/// Data structure used by the nullability migration engine to refer to a
/// specific location in source code.
class CodeReference {
  final String path;

  final int line;

  final int column;

  final int offset;

  /// Name of the enclosing function, or `null` if not known.
  String? function;

  CodeReference(this.path, this.offset, this.line, this.column, this.function);

  /// Creates a [CodeReference] pointing to the given [node].
  factory CodeReference.fromAstNode(AstNode node) {
    var compilationUnit = node.thisOrAncestorOfType<CompilationUnit>()!;
    var source = compilationUnit.declaredElement!.source;
    var location = compilationUnit.lineInfo.getLocation(node.offset);
    return CodeReference(source.fullName, node.offset, location.lineNumber,
        location.columnNumber, _computeEnclosingName(node));
  }

  factory CodeReference.fromElement(Element element) {
    var unitElement = element.thisOrAncestorOfType<CompilationUnitElement>();
    if (unitElement == null) {
      var enclosingElement = element.enclosingElement;
      if (enclosingElement is LibraryElement) {
        unitElement = enclosingElement.definingCompilationUnit;
      } else {
        throw StateError('Unexpected element: $element');
      }
    }

    var path = unitElement.source.fullName;
    var offset = element.nameOffset;

    var location = unitElement.lineInfo.getLocation(offset);
    return CodeReference(path, offset, location.lineNumber,
        location.columnNumber, _computeElementFullName(element));
  }

  /// Gets a short description of this code reference (using the last component
  /// of the path rather than the full path)
  String get shortName => '$shortPath:$line:$column';

  /// Gets the last component of the path part of this code reference.
  String get shortPath {
    var pathAsUri = Uri.file(path);
    return pathAsUri.pathSegments.last;
  }

  @override
  String toString() {
    var pathAsUri = Uri.file(path);
    return '${function ?? 'unknown'} ($pathAsUri:$line:$column)';
  }

  static String? _computeElementFullName(Element? element) {
    List<String> parts = [];
    while (element != null) {
      var elementName = _computeElementName(element);
      if (elementName != null) {
        parts.add(elementName);
      }
      element = element.enclosingElement;
    }
    if (parts.isEmpty) return null;
    return parts.reversed.join('.');
  }

  static String? _computeElementName(Element element) {
    if (element is CompilationUnitElement || element is LibraryElement) {
      return null;
    }
    return element.name;
  }

  static String? _computeEnclosingName(AstNode? node) {
    List<String?> parts = [];
    while (node != null) {
      var nodeName = _computeNodeDeclarationName(node);
      if (nodeName != null) {
        parts.add(nodeName);
      } else if (parts.isEmpty && node is VariableDeclarationList) {
        parts.add(node.variables.first.declaredElement!.name);
      }
      node = node.parent;
    }
    if (parts.isEmpty) return null;
    return parts.reversed.join('.');
  }

  static String? _computeNodeDeclarationName(AstNode node) {
    if (node is ExtensionDeclaration) {
      return node.declaredElement?.name ?? '<unnamed extension>';
    } else if (node is Declaration) {
      var name = node.declaredElement?.name;
      return name == '' ? '<unnamed>' : name;
    } else {
      return null;
    }
  }
}

/// Information exposed to the migration client about the set of nullability
/// nodes decorating a type in the program being migrated.
abstract class DecoratedTypeInfo {
  /// Information about the graph node associated with the decision of whether
  /// or not to make this type into a nullable type.
  NullabilityNodeInfo? get node;

  /// If [type] is a function type, information about the set of nullability
  /// nodes decorating the type's return type.
  DecoratedTypeInfo? get returnType;

  /// The original (pre-migration) type that is being migrated.
  DartType? get type;

  /// If [type] is a function type, looks up information about the set of
  /// nullability nodes decorating one of the type's named parameter types.
  DecoratedTypeInfo? namedParameter(String name);

  /// If [type] is a function type, looks up information about the set of
  /// nullability nodes decorating one of the type's positional parameter types.
  /// (This could be an optional or a required positional parameter).
  DecoratedTypeInfo? positionalParameter(int i);

  /// If [type] is an interface type, looks up information about the set of
  /// nullability nodes decorating one of the type's type arguments.
  DecoratedTypeInfo? typeArgument(int i);
}

/// Information about a propagation step that occurred during downstream
/// propagation.
abstract class DownstreamPropagationStepInfo implements PropagationStepInfo {
  DownstreamPropagationStepInfo? get principalCause;

  /// The node whose nullability was changed.
  ///
  /// Any propagation step that took effect should have a non-null value here.
  /// Propagation steps that are pending but have not taken effect yet, or that
  /// never had an effect (e.g. because an edge was not triggered) will have a
  /// `null` value for this field.
  NullabilityNodeInfo? get targetNode;
}

/// Information exposed to the migration client about an edge in the nullability
/// graph.
///
/// A graph edge represents a dependency relationship between two types being
/// migrated, suggesting that if one type (the source) is made nullable, it may
/// be desirable to make the other type (the destination) nullable as well.
abstract class EdgeInfo implements FixReasonInfo {
  /// User-friendly description of the edge, or `null` if not known.
  String get description;

  /// Information about the graph node that this edge "points to".
  NullabilityNodeInfo get destinationNode;

  /// The set of "guard nodes" for this edge.  Guard nodes are graph nodes whose
  /// nullability determines whether it is important to satisfy a graph edge.
  /// If at least one of an edge's guards is non-nullable, then it is not
  /// important to satisfy the graph edge.  (Typically this is because the code
  /// that led to the graph edge being created is only reachable if the guards
  /// are all nullable).
  Iterable<NullabilityNodeInfo?> get guards;

  /// A boolean indicating whether the graph edge is a "hard" edge.  Hard edges
  /// are associated with unconditional control flow, and thus allow information
  /// about non-nullability to be propagated "upstream" through the nullability
  /// graph.
  bool get isHard;

  /// A boolean indicating whether the graph edge is "satisfied".  At its heart,
  /// the nullability propagation algorithm is an effort to satisfy graph edges
  /// in a way that corresponds to the user's intent.  A graph edge is
  /// considered satisfied if any of the following is true:
  /// - Its [sourceNode] is non-nullable.
  /// - One of its [guards] is non-nullable.
  /// - Its [destinationNode] is nullable.
  bool get isSatisfied;

  /// Indicates whether all the upstream nodes of this edge are nullable (and
  /// thus downstream nullability propagation should try to make the destination
  /// node nullable, if possible).
  bool get isTriggered;

  /// A boolean indicating whether the graph edge is a "union" edge.  Union
  /// edges are edges for which the nullability propagation algorithm tries to
  /// ensure that both the [sourceNode] and the [destinationNode] have the
  /// same nullability.  Typically these are associated with situations where
  /// Dart language semantics require two types to be the same type (e.g. a type
  /// formal bound on a generic function type in a base class, and the
  /// corresponding type formal bound on a generic function type in an
  /// overriding class).
  ///
  /// The [isHard] property is always true for union edges.
  bool get isUnion;

  /// Indicates whether the downstream node of this edge is non-nullable and the
  /// edge is hard (and thus upstream nullability propagation should try to make
  /// the source node non-nullable, if possible).
  bool get isUpstreamTriggered;

  /// Information about the graph node that this edge "points away from".
  NullabilityNodeInfo? get sourceNode;
}

/// Information exposed to the migration client about the location in source
/// code that led an edge to be introduced into the nullability graph.
abstract class EdgeOriginInfo {
  /// If the proximate cause of the edge being introduced into the graph
  /// corresponds to the type of an element in an already migrated-library, the
  /// corresponding element; otherwise `null`.
  ///
  /// Note that either [node] or [element] will always be non-null.
  Element? get element;

  /// The kind of origin represented by this info.
  EdgeOriginKind? get kind;

  /// If the proximate cause of the edge being introduced into the graph
  /// corresponds to an AST node in a source file that is being migrated, the
  /// corresponding AST node; otherwise `null`.
  ///
  /// Note that either [node] or [element] will always be non-null.
  AstNode? get node;

  /// If [node] is non-null, the source file that it appears in.  Otherwise
  /// `null`.
  Source? get source;
}

/// An enumeration of the various kinds of edge origins created by the migration
/// engine.
enum EdgeOriginKind {
  alreadyMigratedType,
  alwaysNullableType,
  angularAnnotation,
  argumentErrorCheckNotNull,
  builtValueNullableAnnotation,
  callTearOff,
  compoundAssignment,
  // See [DummyOrigin].
  dummy,
  dynamicAssignment,
  enumValue,
  expressionChecks,
  externalDynamic,
  fieldFormalParameter,
  fieldNotInitialized,
  forEachVariable,
  getterSetterCorrespondence,
  greatestLowerBound,
  ifNull,
  implicitMixinSuperCall,
  implicitNullInitializer,
  implicitNullReturn,
  implicitThis,
  inferredTypeParameterInstantiation,
  instanceCreation,
  instantiateToBounds,
  isCheckComponentType,
  isCheckMainType,
  iteratorMethodReturn,
  listLengthConstructor,
  literal,
  namedParameterNotSupplied,
  nonNullableBoolType,
  nonNullableObjectSuperclass,
  nonNullableUsage,
  nonNullAssertion,
  nullabilityComment,
  optionalFormalParameter,
  parameterInheritance,
  quiverCheckNotNull,
  returnTypeInheritance,
  stackTraceTypeOrigin,
  thisOrSuper,
  throw_,
  typedefReference,
  typeParameterInstantiation,
  uninitializedRead,
}

/// Interface used by the migration engine to expose information to its client
/// about a reason for a modification to the source file.
abstract class FixReasonInfo {}

/// Abstract interface for assigning ids numbers to nodes, and performing
/// lookups afterwards.
abstract class NodeMapper extends NodeToIdMapper {
  /// Gets the node corresponding to the given [id].
  NullabilityNodeInfo? nodeForId(int? id);
}

/// Abstract interface for assigning ids numbers to nodes.
abstract class NodeToIdMapper {
  /// Gets the id corresponding to the given [node].
  int idForNode(NullabilityNodeInfo node);
}

/// Interface used by the migration engine to expose information to its client
/// about the decisions made during migration, and how those decisions relate to
/// the input source code.
abstract class NullabilityMigrationInstrumentation {
  /// Called whenever changes are decided upon for a given [source] file.
  ///
  /// The format of the changes is a map from source file offset to a list of
  /// changes to be applied at that offset.
  void changes(Source source, Map<int?, List<AtomicEdit>> changes);

  /// Called whenever an explicit [typeAnnotation] is found in the source code,
  /// to report the nullability [node] that was associated with this type.  If
  /// the migration engine determines that the [node] should be nullable, a `?`
  /// will be inserted after the type annotation.
  void explicitTypeNullability(
      Source? source, TypeAnnotation typeAnnotation, NullabilityNodeInfo? node);

  /// Called whenever reference is made to an [element] outside of the code
  /// being migrated, to report the nullability nodes associated with the type
  /// of the element.
  void externalDecoratedType(Element element, DecoratedTypeInfo decoratedType);

  /// Called whenever reference is made to an [typeParameter] outside of the
  /// code being migrated, to report the nullability nodes associated with the
  /// bound of the type parameter.
  void externalDecoratedTypeParameterBound(
      TypeParameterElement typeParameter, DecoratedTypeInfo decoratedType);

  /// Called when the migration process is finished.
  void finished();

  /// Called whenever the migration engine creates a graph edge between
  /// nullability nodes, to report information about the edge that was created,
  /// and why it was created.
  void graphEdge(EdgeInfo edge, EdgeOriginInfo originInfo);

  /// Called when the migration engine starts up, to report information about
  /// the immutable migration nodes [never] and [always] that are used as the
  /// starting point for nullability propagation.
  void immutableNodes(NullabilityNodeInfo never, NullabilityNodeInfo always);

  /// Called whenever the migration engine encounters an implicit return type
  /// associated with an AST node, to report the nullability nodes associated
  /// with the implicit return type of the AST node.
  ///
  /// [node] is the AST node having an implicit return type; it may be an
  /// executable declaration, function-typed formal parameter declaration,
  /// function type alias declaration, GenericFunctionType, or a function
  /// expression.
  void implicitReturnType(
      Source? source, AstNode node, DecoratedTypeInfo? decoratedReturnType);

  /// Called whenever the migration engine encounters an implicit type
  /// associated with an AST node, to report the nullability nodes associated
  /// with the implicit type of the AST node.
  ///
  /// [node] is the AST node having an implicit type; it may be a formal
  /// parameter, a declared identifier, or a variable in a variable declaration
  /// list.
  void implicitType(
      Source? source, AstNode? node, DecoratedTypeInfo decoratedType);

  /// Called whenever the migration engine encounters an AST node with implicit
  /// type arguments, to report the nullability nodes associated with the
  /// implicit type arguments of the AST node.
  ///
  /// [node] is the AST node having implicit type arguments; it may be a
  /// constructor redirection, function expression invocation, method
  /// invocation, instance creation expression, list/map/set literal, or type
  /// annotation.
  void implicitTypeArguments(
      Source? source, AstNode node, Iterable<DecoratedTypeInfo> types);

  /// Clear any data from the propagation step in preparation for that step
  /// being re-run.
  void prepareForUpdate();
}

/// Information exposed to the migration client about a single node in the
/// nullability graph.
abstract class NullabilityNodeInfo implements FixReasonInfo {
  /// List of compound nodes wrapping this node.
  final List<NullabilityNodeInfo> outerCompoundNodes = <NullabilityNodeInfo>[];

  /// Source code location corresponding to this nullability node, or `null` if
  /// not known.
  CodeReference? get codeReference;

  /// Some nodes get nullability from downstream, so the downstream edges are
  /// available to query as well.
  Iterable<EdgeInfo> get downstreamEdges;

  /// The hint actions users can perform on this node, indexed by the type of
  /// hint.
  ///
  /// Each edit is represented as a [Map<int, List<AtomicEdit>>] as is typical
  /// of [AtomicEdit]s since they do not have an offset. See extensions
  /// [AtomicEditMap] and [AtomicEditList] for usage.
  Map<HintActionKind, Map<int?, List<AtomicEdit>>> get hintActions;

  /// After migration is complete, this getter can be used to query whether
  /// the type associated with this node was determined to be "exact nullable."
  bool get isExactNullable;

  /// Indicates whether the node is immutable.  The only immutable nodes in the
  /// nullability graph are the nodes `never` and `always` that are used as the
  /// starting points for nullability propagation.
  bool get isImmutable;

  /// After migration is complete, this getter can be used to query whether
  /// the type associated with this node was determined to be nullable.
  bool get isNullable;

  /// The edges that caused this node to have the nullability that it has.
  Iterable<EdgeInfo> get upstreamEdges;

  /// If [isNullable] is false, the propagation step that caused this node to
  /// become non-nullable (if any).
  UpstreamPropagationStepInfo? get whyNotNullable;

  /// If [isNullable] is true, the propagation step that caused this node to
  /// become nullable.
  DownstreamPropagationStepInfo? get whyNullable;
}

abstract class PropagationStepInfo {
  CodeReference? get codeReference;

  /// The nullability edge associated with this propagation step, if any.
  /// Otherwise `null`.
  EdgeInfo? get edge;
}

/// Reason information for a simple fix that isn't associated with any edges or
/// nodes.
abstract class SimpleFixReasonInfo implements FixReasonInfo {
  /// Code location of the fix.
  CodeReference get codeReference;

  /// Description of the fix.
  String get description;
}

/// A simple implementation of [NodeMapper] that assigns ids to nodes as they
/// are requested, backed by a map.
///
/// Be careful not to leak references to nodes by holding on to this beyond the
/// lifetime of the nodes it maps.
class SimpleNodeMapper extends NodeMapper {
  final _nodeToId = <NullabilityNodeInfo, int>{};
  final _idToNode = <int, NullabilityNodeInfo>{};

  @override
  int idForNode(NullabilityNodeInfo node) {
    final id = _nodeToId.putIfAbsent(node, () => _nodeToId.length);
    _idToNode.putIfAbsent(id, () => node);
    return id;
  }

  @override
  NullabilityNodeInfo? nodeForId(int? id) => _idToNode[id!];
}

/// Information exposed to the migration client about a node in the nullability
/// graph resulting from a type substitution.
abstract class SubstitutionNodeInfo extends NullabilityNodeInfo {
  /// Nullability node representing the inner type of the substitution.
  ///
  /// For example, if this NullabilityNode arose from substituting `int*` for
  /// `T` in the type `T*`, [innerNode] is the nullability corresponding to the
  /// `*` in `int*`.
  NullabilityNodeInfo get innerNode;

  /// Nullability node representing the outer type of the substitution.
  ///
  /// For example, if this NullabilityNode arose from substituting `int*` for
  /// `T` in the type `T*`, [innerNode] is the nullability corresponding to the
  /// `*` in `T*`.
  NullabilityNodeInfo get outerNode;
}

/// Information about a propagation step that occurred during upstream
/// propagation.
abstract class UpstreamPropagationStepInfo implements PropagationStepInfo {
  bool get isStartingPoint;

  /// The node whose nullability was changed.
  ///
  /// Any propagation step that took effect should have a non-null value here.
  /// Propagation steps that are pending but have not taken effect yet, or that
  /// never had an effect (e.g. because an edge was not triggered) will have a
  /// `null` value for this field.
  NullabilityNodeInfo get node;

  UpstreamPropagationStepInfo? get principalCause;
}
