// Copyright (c) 2020, 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.

/// Data structure representing a part of a type.  When a fix has multiple
/// reasons (due to a complex type having different nullabilities at different
/// locations), this data structure allows us to tell which part of the type
/// is associated with each reason.
abstract class FixReasonTarget {
  /// Fix reason target representing the full type, rather than a part of it.
  static const FixReasonTarget root = _FixReasonTarget_Root();

  const FixReasonTarget._();

  /// Gets a fix reason target representing the type's return type.
  FixReasonTarget get returnType => _FixReasonTarget_ReturnType(this);

  /// Returns a description of the fix reason target that's suitable for
  /// appending to a description of a nullability trace.
  ///
  /// For example, `root.returnType.suffix` returns ` for return type`.  This
  /// can be attached to a string like `nullability reason` to form
  /// `nullability reason for return type`.
  String get suffix => _describe('for');

  /// Gets a fix reason target representing the type's yielded type.  This
  /// represents the type argument of `Future` or `FutureOr`, or in the case
  /// where `await` is applied to a non-future type, the type itself.
  FixReasonTarget get yieldedType => _FixReasonTarget_YieldedType(this);

  /// Gets a fix reason target representing one of the type's named parameters.
  FixReasonTarget namedParameter(String name) =>
      _FixReasonTarget_NamedParameter(this, name);

  /// Gets a fix reason target representing one of the type's positional
  /// parameters.
  FixReasonTarget positionalParameter(int i) =>
      _FixReasonTarget_PositionalParameter(this, i);

  /// Gets a fix reason target representing one of the type's type arguments.
  FixReasonTarget typeArgument(int i) => _FixReasonTarget_TypeArgument(this, i);

  String _describe(String preposition);
}

/// Fix reason target representing a named parameter of a function type.
class _FixReasonTarget_NamedParameter extends _FixReasonTarget_Part {
  final String name;

  _FixReasonTarget_NamedParameter(FixReasonTarget inner, this.name)
      : super(inner);

  @override
  int get hashCode => Object.hash(2, inner, name);

  @override
  bool operator ==(Object other) =>
      other is _FixReasonTarget_NamedParameter &&
      inner == other.inner &&
      name == other.name;

  @override
  String _describe(String preposition) =>
      ' $preposition parameter $name${inner._describe('of')}';
}

/// Fix reason target representing a type that forms part of a larger type (e.g.
/// the `int` part of `List<int>`).
abstract class _FixReasonTarget_Part extends FixReasonTarget {
  final FixReasonTarget inner;

  _FixReasonTarget_Part(this.inner) : super._();
}

/// Fix reason target representing a positional parameter of a function type.
class _FixReasonTarget_PositionalParameter extends _FixReasonTarget_Part {
  final int index;

  _FixReasonTarget_PositionalParameter(FixReasonTarget inner, this.index)
      : super(inner);

  @override
  int get hashCode => Object.hash(1, inner, index);

  @override
  bool operator ==(Object other) =>
      other is _FixReasonTarget_PositionalParameter &&
      inner == other.inner &&
      index == other.index;

  @override
  String _describe(String preposition) =>
      ' $preposition parameter $index${inner._describe('of')}';
}

/// Fix reason target representing the return type of a function type.
class _FixReasonTarget_ReturnType extends _FixReasonTarget_Part {
  _FixReasonTarget_ReturnType(FixReasonTarget inner) : super(inner);

  @override
  int get hashCode => Object.hash(3, inner);

  @override
  bool operator ==(Object other) =>
      other is _FixReasonTarget_ReturnType && inner == other.inner;

  @override
  String _describe(String preposition) =>
      ' $preposition return type${inner._describe('of')}';
}

/// Fix reason target representing the root of the type in question.
class _FixReasonTarget_Root extends FixReasonTarget {
  const _FixReasonTarget_Root() : super._();

  @override
  int get hashCode => 0;

  @override
  bool operator ==(Object other) => other is _FixReasonTarget_Root;

  @override
  String _describe(String preposition) => '';
}

/// Fix reason target representing a type argument of an interface type.
class _FixReasonTarget_TypeArgument extends _FixReasonTarget_Part {
  final int index;

  _FixReasonTarget_TypeArgument(FixReasonTarget inner, this.index)
      : super(inner);

  @override
  int get hashCode => Object.hash(5, inner, index);

  @override
  bool operator ==(Object other) =>
      other is _FixReasonTarget_TypeArgument &&
      inner == other.inner &&
      index == other.index;

  @override
  String _describe(String preposition) =>
      ' $preposition type argument $index${inner._describe('of')}';
}

/// Fix reason target representing the type argument of `Future` or `FutureOr`,
/// or in the case where `await` is applied to a non-future type, the type
/// itself.
///
/// This allows the migration tool to describe a type correspondence that exists
/// in a subtype check involving `FutureOr`, for example if the user tries to
/// assign `List<int?>` to `FutureOr<List<int*>>`, then the migration tool
/// determines that it needs to change `*` into `?`.  To make this determination
/// it has to form a correspondence between the type argument of the source type
/// and the type argument of the type argument of the destination type.  To
/// explain to the user which part of the two types is involved in the
/// correspondence, we need an ambiguous way of referring to either "type
/// argument of type argument of" or simply "type argument".  The solution is to
/// describe the fix reason target as "type argument of yielded type".
class _FixReasonTarget_YieldedType extends _FixReasonTarget_Part {
  _FixReasonTarget_YieldedType(FixReasonTarget inner) : super(inner);

  @override
  int get hashCode => Object.hash(4, inner);

  @override
  bool operator ==(Object other) =>
      other is _FixReasonTarget_YieldedType && inner == other.inner;

  @override
  String _describe(String preposition) =>
      ' $preposition yielded type${inner._describe('from')}';
}
