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

/// 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, LineInfo Function(String) getLineInfo) {
    var path = element.source.fullName;
    var offset = element.nameOffset;
    var location = getLineInfo(path).getLocation(offset);
    return CodeReference(path, offset, location.lineNumber,
        location.columnNumber, _computeElementFullName(element));
  }

  CodeReference.fromJson(dynamic json)
      : path = json['path'] as String,
        offset = json['offset'] as int,
        line = json['line'] as int,
        column = json['col'] as int,
        function = json['function'] as String;

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

  Map<String, Object> toJson() {
    return {
      'path': path,
      'offset': offset,
      'line': line,
      'col': column,
      if (function != null) 'function': function
    };
  }

  @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,
  argumentErrorCheckNotNull,
  compoundAssignment,
  // See [DummyOrigin].
  dummy,
  dynamicAssignment,
  enumValue,
  expressionChecks,
  fieldFormalParameter,
  fieldNotInitialized,
  forEachVariable,
  getterSetterCorrespondence,
  greatestLowerBound,
  ifNull,
  implicitMixinSuperCall,
  implicitNullInitializer,
  implicitNullReturn,
  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 {}

/// Enum describing the possible hints that can be performed on an edge or a
/// node.
///
/// Which actions are available can be built by other visitors, and the hint can
/// be applied by visitors such as EditPlanner when the user requests it from
/// the front end.
enum HintActionKind {
  /// Add a `/*?*/` hint to a type.
  addNullableHint,

  /// Add a `/*!*/` hint to a type.
  addNonNullableHint,

  /// Change a `/*!*/` hint to a `/*?*/` hint.
  changeToNullableHint,

  /// Change a `/*?*/` hint to a `/*!*/` hint.
  changeToNonNullableHint,

  /// Remove a `/*?*/` hint.
  removeNullableHint,

  /// Remove a `/*!*/` hint.
  removeNonNullableHint,
}

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

/// Extension methods to make [HintActionKind] act as a smart enum.
extension HintActionKindBehaviors on HintActionKind {
  /// Get the text description of a [HintActionKind], for display to users.
  String get description {
    switch (this) {
      case HintActionKind.addNullableHint:
        return 'Add /*?*/ hint';
      case HintActionKind.addNonNullableHint:
        return 'Add /*!*/ hint';
      case HintActionKind.removeNullableHint:
        return 'Remove /*?*/ hint';
      case HintActionKind.removeNonNullableHint:
        return 'Remove /*!*/ hint';
      case HintActionKind.changeToNullableHint:
        return 'Change to /*?*/ hint';
      case HintActionKind.changeToNonNullableHint:
        return 'Change to /*!*/ hint';
    }

    assert(false);
    return null;
  }
}
