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

import 'dart:convert';

import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/src/nullability_migration_impl.dart';
import 'package:pub_semver/pub_semver.dart';

export 'package:nnbd_migration/src/utilities/hint_utils.dart' show HintComment;

/// Description of fixes that might be performed by nullability migration.
class NullabilityFixDescription {
  /// A `.then((value) => ...)` suffix was added to an expression.
  static const addThen = NullabilityFixDescription._(
      appliedMessage: 'Added `.then` to adjust type of Future expression',
      kind: NullabilityFixKind.addThen);

  /// An import was added to the library.
  static const addImport = NullabilityFixDescription._(
      appliedMessage: 'Added import for use in migrated code',
      kind: NullabilityFixKind.addImport);

  /// A variable declaration needs to be marked as "late".
  static const addLate = NullabilityFixDescription._(
      appliedMessage: 'Added a late keyword', kind: NullabilityFixKind.addLate);

  /// A variable declaration needs to be marked as "late" due to the presence of
  /// a `/*late*/` hint.
  static const addLateDueToHint = NullabilityFixDescription._(
      appliedMessage: 'Added a late keyword, due to a hint',
      kind: NullabilityFixKind.addLateDueToHint);

  /// A variable declaration needs to be marked as "late" due to being certainly
  /// assigned in test setup.
  static const addLateDueToTestSetup = NullabilityFixDescription._(
      appliedMessage: 'Added a late keyword, due to assignment in `setUp`',
      kind: NullabilityFixKind.addLateDueToTestSetup);

  /// A variable declaration needs to be marked as "late" and "final" due to the
  /// presence of a `/*late final*/` hint.
  static const addLateFinalDueToHint = NullabilityFixDescription._(
      appliedMessage: 'Added late and final keywords, due to a hint',
      kind: NullabilityFixKind.addLateFinalDueToHint);

  /// An expression's value needs to be null-checked.
  static const checkExpression = NullabilityFixDescription._(
    appliedMessage: 'Added a non-null assertion to nullable expression',
    kind: NullabilityFixKind.checkExpression,
  );

  /// An expression's value will be null-checked due to a hint.
  static const checkExpressionDueToHint = NullabilityFixDescription._(
    appliedMessage: 'Accepted a null check hint',
    kind: NullabilityFixKind.checkExpressionDueToHint,
  );

  /// A compound assignment's combiner operator returns a type that isn't
  /// assignable to the LHS of the assignment.
  static const compoundAssignmentHasBadCombinedType =
      NullabilityFixDescription._(
    appliedMessage: 'Compound assignment has bad combined type',
    kind: NullabilityFixKind.compoundAssignmentHasBadCombinedType,
  );

  /// A compound assignment's LHS has a nullable type.
  static const compoundAssignmentHasNullableSource =
      NullabilityFixDescription._(
    appliedMessage: 'Compound assignment has nullable source',
    kind: NullabilityFixKind.compoundAssignmentHasNullableSource,
  );

  /// Informative message: a condition of an if-test or conditional expression
  /// will always evaluate to `false` in strong checking mode.
  static const conditionFalseInStrongMode = NullabilityFixDescription._(
      appliedMessage: 'Condition will always be false in strong checking mode',
      kind: NullabilityFixKind.conditionFalseInStrongMode);

  /// Informative message: a condition of an if-test or conditional expression
  /// will always evaluate to `true` in strong checking mode.
  static const conditionTrueInStrongMode = NullabilityFixDescription._(
      appliedMessage: 'Condition will always be true in strong checking mode',
      kind: NullabilityFixKind.conditionTrueInStrongMode);

  /// An if-test or conditional expression needs to have its condition
  /// discarded.
  static const discardCondition = NullabilityFixDescription._(
    appliedMessage: 'Discarded a condition which is always true',
    kind: NullabilityFixKind.removeDeadCode,
  );

  /// An if-test or conditional expression needs to have its condition and
  /// "else" branch discarded.
  static const discardElse = NullabilityFixDescription._(
    appliedMessage: 'Discarded an unreachable conditional else branch',
    kind: NullabilityFixKind.removeDeadCode,
  );

  /// An if-test or conditional expression needs to have its condition and
  /// "then" branch discarded.
  static const discardThen = NullabilityFixDescription._(
    appliedMessage:
        'Discarded a condition which is always false, and the "then" branch '
        'that follows',
    kind: NullabilityFixKind.removeDeadCode,
  );

  /// An if-test needs to be discarded completely.
  static const discardIf = NullabilityFixDescription._(
    appliedMessage: 'Discarded an if-test with no effect',
    kind: NullabilityFixKind.removeDeadCode,
  );

  static const downcastExpression = NullabilityFixDescription._(
    appliedMessage: 'Added a downcast to an expression',
    kind: NullabilityFixKind.downcastExpression,
  );

  /// Informative message: there is no valid migration for `null` in a
  /// non-nullable context.
  static const noValidMigrationForNull = NullabilityFixDescription._(
      appliedMessage: 'No valid migration for `null` in a non-nullable context',
      kind: NullabilityFixKind.noValidMigrationForNull);

  /// Informative message: a null-aware access won't be necessary in strong
  /// checking mode.
  static const nullAwarenessUnnecessaryInStrongMode =
      NullabilityFixDescription._(
          appliedMessage:
              'Null-aware access will be unnecessary in strong checking mode',
          kind: NullabilityFixKind.nullAwarenessUnnecessaryInStrongMode);

  /// Informative message: a null-aware assignment won't be necessary in strong
  /// checking mode.
  static const nullAwareAssignmentUnnecessaryInStrongMode =
      NullabilityFixDescription._(
          appliedMessage:
              'Null-aware assignment will be unnecessary in strong checking mode',
          kind: NullabilityFixKind.nullAwareAssignmentUnnecessaryInStrongMode);

  static const otherCastExpression = NullabilityFixDescription._(
    appliedMessage: 'Added a cast to an expression (non-downcast)',
    kind: NullabilityFixKind.otherCastExpression,
  );

  /// An unnecessary downcast has been discarded.
  static const removeLanguageVersionComment = NullabilityFixDescription._(
    appliedMessage: 'Removed language version comment so that NNBD features '
        'will be allowed in this file',
    kind: NullabilityFixKind.removeLanguageVersionComment,
  );

  /// An unnecessary downcast has been discarded.
  static const removeAs = NullabilityFixDescription._(
    appliedMessage: 'Discarded a downcast that is now unnecessary',
    kind: NullabilityFixKind.removeAs,
  );

  /// A null-aware operator needs to be changed into its non-null-aware
  /// equivalent.
  static const removeNullAwareness = NullabilityFixDescription._(
      appliedMessage:
          'Changed a null-aware access into an ordinary access, because the target cannot be null',
      kind: NullabilityFixKind.removeDeadCode);

  /// A null-aware assignment was removed because its LHS is non-nullable.
  static const removeNullAwareAssignment = NullabilityFixDescription._(
      appliedMessage:
          'Removed a null-aware assignment, because the target cannot be null',
      kind: NullabilityFixKind.removeDeadCode);

  /// A message used to indicate a fix has been applied.
  final String appliedMessage;

  /// The kind of fix described.
  final NullabilityFixKind kind;

  /// A formal parameter needs to have a required keyword added.
  factory NullabilityFixDescription.addRequired(
          String className, String functionName, String paramName) =>
      NullabilityFixDescription._(
        appliedMessage: "Add 'required' keyword to parameter '$paramName' in " +
            (className == null ? functionName : "'$className.$functionName'"),
        kind: NullabilityFixKind.addRequired,
      );

  /// An explicit type needs to be added.
  factory NullabilityFixDescription.addType(String typeText) =>
      NullabilityFixDescription._(
        appliedMessage: "Add the explicit type '$typeText'",
        kind: NullabilityFixKind.replaceVar,
      );

  /// A method call was changed from calling one method to another.
  factory NullabilityFixDescription.changeMethodName(
          String oldName, String newName) =>
      NullabilityFixDescription._(
          appliedMessage: "Changed method '$oldName' to '$newName'",
          kind: NullabilityFixKind.changeMethodName);

  /// An explicit type mentioned in the source program needs to be made
  /// nullable.
  factory NullabilityFixDescription.makeTypeNullable(String type) =>
      NullabilityFixDescription._(
        appliedMessage: "Changed type '$type' to be nullable",
        kind: NullabilityFixKind.makeTypeNullable,
      );

  /// An explicit type mentioned in the source program will be made
  /// nullable due to a nullability hint.
  factory NullabilityFixDescription.makeTypeNullableDueToHint(String type) =>
      NullabilityFixDescription._(
        appliedMessage:
            "Changed type '$type' to be nullable, due to a nullability hint",
        kind: NullabilityFixKind.makeTypeNullableDueToHint,
      );

  /// A 'var' declaration needs to be replaced with an explicit type.
  factory NullabilityFixDescription.replaceVar(String typeText) =>
      NullabilityFixDescription._(
        appliedMessage: "Replace 'var' with '$typeText'",
        kind: NullabilityFixKind.replaceVar,
      );

  /// An explicit type mentioned in the source program does not need to be made
  /// nullable.
  factory NullabilityFixDescription.typeNotMadeNullable(String type) =>
      NullabilityFixDescription._(
        appliedMessage: "Type '$type' was not made nullable",
        kind: NullabilityFixKind.typeNotMadeNullable,
      );

  /// An explicit type mentioned in the source program does not need to be made
  /// nullable.
  factory NullabilityFixDescription.typeNotMadeNullableDueToHint(String type) =>
      NullabilityFixDescription._(
        appliedMessage: "Type '$type' was not made nullable due to a hint",
        kind: NullabilityFixKind.typeNotMadeNullableDueToHint,
      );

  const NullabilityFixDescription._(
      {@required this.appliedMessage, @required this.kind})
      : assert(appliedMessage != null),
        assert(kind != null);

  @override
  int get hashCode {
    int hash = 0;
    hash = JenkinsSmiHash.combine(hash, appliedMessage.hashCode);
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  bool operator ==(Object other) =>
      other is NullabilityFixDescription &&
      appliedMessage == other.appliedMessage &&
      kind == other.kind;

  @override
  String toString() =>
      'NullabilityFixDescription(${json.encode(appliedMessage)}, $kind)';
}

/// An enumeration of the various kinds of nullability fixes.
enum NullabilityFixKind {
  addThen,
  addImport,
  addLate,
  addLateDueToHint,
  addLateDueToTestSetup,
  addLateFinalDueToHint,
  addRequired,
  addType,
  changeMethodName,
  checkExpression,
  checkExpressionDueToHint,
  compoundAssignmentHasNullableSource,
  compoundAssignmentHasBadCombinedType,
  conditionFalseInStrongMode,
  conditionTrueInStrongMode,
  downcastExpression,
  makeTypeNullable,
  makeTypeNullableDueToHint,
  noValidMigrationForNull,
  nullAwarenessUnnecessaryInStrongMode,
  nullAwareAssignmentUnnecessaryInStrongMode,
  otherCastExpression,
  removeAs,
  removeDeadCode,
  removeLanguageVersionComment,
  replaceVar,
  typeNotMadeNullable,
  typeNotMadeNullableDueToHint,
}

/// Provisional API for DartFix to perform nullability migration.
///
/// Usage: pass each input source file to [prepareInput].  Then pass each input
/// source file to [processInput].  Then pass each input source file to
/// [finalizeInput].  Then call [finish] to obtain the modifications that need
/// to be made to each source file.
abstract class NullabilityMigration {
  /// Prepares to perform nullability migration.
  ///
  /// If [permissive] is `true`, exception handling logic will try to proceed
  /// as far as possible even though the migration algorithm is not yet
  /// complete.  TODO(paulberry): remove this mode once the migration algorithm
  /// is fully implemented.
  ///
  /// Optional parameter [removeViaComments] indicates whether code that the
  /// migration tool wishes to remove should instead be commenting it out.
  ///
  /// Optional parameter [warnOnWeakCode] indicates whether weak-only code
  /// should be warned about or removed (in the way specified by
  /// [removeViaComments]).
  factory NullabilityMigration(NullabilityMigrationListener listener,
      LineInfo Function(String) getLineInfo,
      {bool permissive,
      NullabilityMigrationInstrumentation instrumentation,
      bool removeViaComments,
      bool warnOnWeakCode}) = NullabilityMigrationImpl;

  /// Check if this migration is being run permissively.
  bool get isPermissive;

  /// Use this getter after any calls to [prepareInput] to obtain a list of URIs
  /// of unmigrated dependencies.  Ideally, this list should be empty before the
  /// user tries to migrate their package.
  List<String> get unmigratedDependencies;

  void finalizeInput(ResolvedUnitResult result);

  /// Finishes the migration.  Returns a map indicating packages that have been
  /// newly imported by the migration; the caller should ensure that these
  /// packages are properly imported by the package's pubspec.
  ///
  /// Keys of the returned map are package names; values indicate the minimum
  /// required version of each package.
  Map<String, Version> finish();

  void prepareInput(ResolvedUnitResult result);

  void processInput(ResolvedUnitResult result);

  /// Update the migration after an edge has been added or removed.
  void update();
}

/// [NullabilityMigrationListener] is used by [NullabilityMigration]
/// to communicate source changes or "fixes" to the client.
abstract class NullabilityMigrationListener {
  /// [addEdit] is called once for each source edit, in the order in which they
  /// appear in the source file.
  void addEdit(Source source, SourceEdit edit);

  void addSuggestion(String descriptions, Location location);

  /// [reportException] is called once for each exception that occurs in
  /// "permissive mode", reporting the location of the exception and the
  /// exception details.
  void reportException(
      Source source, AstNode node, Object exception, StackTrace stackTrace);
}
