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

/// Defines the type model. The type model is part of the
/// [element model](../dart_element_element/dart_element_element-library.html)
/// in that most types are defined by Dart code (the types `dynamic` and `void`
/// being the notable exceptions). All types are represented by an instance of a
/// subclass of [DartType].
///
/// Other than `dynamic` and `void`, all of the types define either the
/// interface defined by a class (an instance of [InterfaceType]) or the type of
/// a function (an instance of [FunctionType]).
///
/// We make a distinction between the declaration of a class (a [ClassElement])
/// and the type defined by that class (an [InterfaceType]). The biggest reason
/// for the distinction is to allow us to more cleanly represent the distinction
/// between type parameters and type arguments. For example, if we define a
/// class as `class Pair<K, V> {}`, the declarations of `K` and `V` represent
/// type parameters. But if we declare a variable as `Pair<String, int> pair;`
/// the references to `String` and `int` are type arguments.
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/src/dart/element/type.dart' show InterfaceTypeImpl;

/// The type associated with elements in the element model.
///
/// Clients may not extend, implement or mix-in this class.
abstract class DartType {
  /// Return the name of this type as it should appear when presented to users
  /// in contexts such as error messages.
  ///
  /// Clients should not depend on the content of the returned value as it will
  /// be changed if doing so would improve the UX.
  @Deprecated('Use getDisplayString instead')
  String get displayName;

  /// Return the element representing the declaration of this type, or `null` if
  /// the type has not, or cannot, be associated with an element. The former
  /// case will occur if the element model is not yet complete; the latter case
  /// will occur if this object represents an undefined type.
  Element get element;

  /// Return `true` if this type represents the bottom type.
  bool get isBottom;

  /// Return `true` if this type represents the type 'Future' defined in the
  /// dart:async library.
  bool get isDartAsyncFuture;

  /// Return `true` if this type represents the type 'FutureOr<T>' defined in
  /// the dart:async library.
  bool get isDartAsyncFutureOr;

  /// Return `true` if this type represents the type 'bool' defined in the
  /// dart:core library.
  bool get isDartCoreBool;

  /// Return `true` if this type represents the type 'double' defined in the
  /// dart:core library.
  bool get isDartCoreDouble;

  /// Return `true` if this type represents the type 'Function' defined in the
  /// dart:core library.
  bool get isDartCoreFunction;

  /// Return `true` if this type represents the type 'int' defined in the
  /// dart:core library.
  bool get isDartCoreInt;

  /// Returns `true` if this type represents the type 'Iterable' defined in the
  /// dart:core library.
  bool get isDartCoreIterable;

  /// Returns `true` if this type represents the type 'List' defined in the
  /// dart:core library.
  bool get isDartCoreList;

  /// Returns `true` if this type represents the type 'Map' defined in the
  /// dart:core library.
  bool get isDartCoreMap;

  /// Return `true` if this type represents the type 'Null' defined in the
  /// dart:core library.
  bool get isDartCoreNull;

  /// Return `true` if this type represents the type 'num' defined in the
  /// dart:core library.
  bool get isDartCoreNum;

  /// Return `true` if this type represents the type `Object` defined in the
  /// dart:core library.
  bool get isDartCoreObject;

  /// Returns `true` if this type represents the type 'Set' defined in the
  /// dart:core library.
  bool get isDartCoreSet;

  /// Return `true` if this type represents the type 'String' defined in the
  /// dart:core library.
  bool get isDartCoreString;

  /// Returns `true` if this type represents the type 'Symbol' defined in the
  /// dart:core library.
  bool get isDartCoreSymbol;

  /// Return `true` if this type represents the type 'dynamic'.
  bool get isDynamic;

  /// Return `true` if this type represents the type 'Object'.
  @Deprecated('Use isDartCoreObject')
  bool get isObject;

  /// Return `true` if this type represents the type 'void'.
  bool get isVoid;

  /// Return the name of this type, or `null` if the type does not have a name,
  /// such as when the type represents the type of an unnamed function.
  @Deprecated('Check element, or use getDisplayString()')
  String get name;

  /// Return the nullability suffix of this type.
  NullabilitySuffix get nullabilitySuffix;

  /// Return the presentation of this type as it should appear when presented
  /// to users in contexts such as error messages.
  ///
  /// If [withNullability] is `true`, then [NullabilitySuffix.question] and
  /// [NullabilitySuffix.star] will be be represented as `?` and `*`.
  /// [NullabilitySuffix.none] does not have any explicit presentation.
  ///
  /// If [withNullability] is `false`, nullability suffixes will not be
  /// included into the presentation.
  ///
  /// Clients should not depend on the content of the returned value as it will
  /// be changed if doing so would improve the UX.
  String getDisplayString({bool withNullability = false});

  /// If this type is a [TypeParameterType], returns its bound if it has one, or
  /// [objectType] otherwise.
  ///
  /// For any other type, returns `this`. Applies recursively -- if the bound is
  /// itself a type parameter, that is resolved too.
  DartType resolveToBound(DartType objectType);

  /// Return the type resulting from substituting the given [argumentTypes] for
  /// the given [parameterTypes] in this type. The specification defines this
  /// operation in section 2:
  /// <blockquote>
  /// The notation <i>[x<sub>1</sub>, ..., x<sub>n</sub>/y<sub>1</sub>, ...,
  /// y<sub>n</sub>]E</i> denotes a copy of <i>E</i> in which all occurrences of
  /// <i>y<sub>i</sub>, 1 <= i <= n</i> have been replaced with
  /// <i>x<sub>i</sub></i>.
  /// </blockquote>
  /// Note that, contrary to the specification, this method will not create a
  /// copy of this type if no substitutions were required, but will return this
  /// type directly.
  ///
  /// Note too that the current implementation of this method is only guaranteed
  /// to work when the parameter types are type variables.
  @Deprecated("""
Use ClassElement.instantiate() or FunctionTypeAliasElement.instantiate()
""")
  DartType substitute2(
      List<DartType> argumentTypes, List<DartType> parameterTypes);
}

/// The type of a function, method, constructor, getter, or setter. Function
/// types come in three variations:
///
/// * The types of functions that only have required parameters. These have the
///   general form <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>) &rarr; T</i>.
/// * The types of functions with optional positional parameters. These have the
///   general form <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>, [T<sub>n+1</sub>
///   &hellip;, T<sub>n+k</sub>]) &rarr; T</i>.
/// * The types of functions with named parameters. These have the general form
///   <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>, {T<sub>x1</sub> x1, &hellip;,
///   T<sub>xk</sub> xk}) &rarr; T</i>.
///
/// Clients may not extend, implement or mix-in this class.
abstract class FunctionType implements ParameterizedType {
  /// Deprecated: use [typeFormals].
  @deprecated
  List<TypeParameterElement> get boundTypeParameters;

  /// Return a map from the names of named parameters to the types of the named
  /// parameters of this type of function. The entries in the map will be
  /// iterated in the same order as the order in which the named parameters were
  /// defined. If there were no named parameters declared then the map will be
  /// empty.
  Map<String, DartType> get namedParameterTypes;

  /// The names of the required positional parameters of this type of function,
  /// in the order that the parameters appear.
  List<String> get normalParameterNames;

  /// Return a list containing the types of the normal parameters of this type
  /// of function. The parameter types are in the same order as they appear in
  /// the declaration of the function.
  List<DartType> get normalParameterTypes;

  /// The names of the optional positional parameters of this type of function,
  /// in the order that the parameters appear.
  List<String> get optionalParameterNames;

  /// Return a map from the names of optional (positional) parameters to the
  /// types of the optional parameters of this type of function. The entries in
  /// the map will be iterated in the same order as the order in which the
  /// optional parameters were defined. If there were no optional parameters
  /// declared then the map will be empty.
  List<DartType> get optionalParameterTypes;

  /// Return a list containing the parameters elements of this type of function.
  /// The parameter types are in the same order as they appear in the
  /// declaration of the function.
  List<ParameterElement> get parameters;

  /// Return the type of object returned by this type of function.
  DartType get returnType;

  /// The formal type parameters of this generic function.
  /// For example `<T> T -> T`.
  ///
  /// TODO(scheglov) Remove the mention for "typeParameters".
  /// These are distinct from the `typeParameters` list, which contains type
  /// parameters from surrounding contexts, and thus are free type variables
  /// from the perspective of this function type.
  List<TypeParameterElement> get typeFormals;

  @override
  FunctionType instantiate(List<DartType> argumentTypes);

  @Deprecated("Use FunctionTypeAliasElement.instantiate()")
  @override
  FunctionType substitute2(
      List<DartType> argumentTypes, List<DartType> parameterTypes);

  /// Return the type resulting from substituting the given [argumentTypes] for
  /// this type's parameters. This is fully equivalent to
  /// `substitute(argumentTypes, getTypeArguments())`.
  @deprecated // use instantiate
  FunctionType substitute3(List<DartType> argumentTypes);
}

/// The type introduced by either a class or an interface, or a reference to
/// such a type.
///
/// Clients may not extend, implement or mix-in this class.
abstract class InterfaceType implements ParameterizedType {
  /// Return a list containing all of the accessors (getters and setters)
  /// declared in this type.
  List<PropertyAccessorElement> get accessors;

  /// Return a list containing all of the constructors declared in this type.
  List<ConstructorElement> get constructors;

  @override
  ClassElement get element;

  /// Return a list containing all of the interfaces that are implemented by
  /// this interface. Note that this is <b>not</b>, in general, equivalent to
  /// getting the interfaces from this type's element because the types returned
  /// by this method will have had their type parameters replaced.
  List<InterfaceType> get interfaces;

  /// Return a list containing all of the methods declared in this type.
  List<MethodElement> get methods;

  /// Return a list containing all of the mixins that are applied to the class
  /// being extended in order to derive the superclass of this class. Note that
  /// this is <b>not</b>, in general, equivalent to getting the mixins from this
  /// type's element because the types returned by this method will have had
  /// their type parameters replaced.
  List<InterfaceType> get mixins;

  /// Return the type representing the superclass of this type, or null if this
  /// type represents the class 'Object'. Note that this is <b>not</b>, in
  /// general, equivalent to getting the superclass from this type's element
  /// because the type returned by this method will have had it's type
  /// parameters replaced.
  InterfaceType get superclass;

  /// Return a list containing all of the super-class constraints that this
  /// mixin declaration declares. The list will be empty if this class does not
  /// represent a mixin declaration.
  List<InterfaceType> get superclassConstraints;

  /// Return the element representing the getter with the given [name] that is
  /// declared in this class, or `null` if this class does not declare a getter
  /// with the given name.
  PropertyAccessorElement getGetter(String name);

  /// Return the element representing the method with the given [name] that is
  /// declared in this class, or `null` if this class does not declare a method
  /// with the given name.
  MethodElement getMethod(String name);

  /// Return the element representing the setter with the given [name] that is
  /// declared in this class, or `null` if this class does not declare a setter
  /// with the given name.
  PropertyAccessorElement getSetter(String name);

  @Deprecated("Use ClassElement.instantiate()")
  @override
  InterfaceType instantiate(List<DartType> argumentTypes);

  /// Return the element representing the constructor that results from looking
  /// up the constructor with the given [name] in this class with respect to the
  /// given [library], or `null` if the look up fails. The behavior of this
  /// method is defined by the Dart Language Specification in section 12.11.1:
  /// <blockquote>
  /// If <i>e</i> is of the form <b>new</b> <i>T.id()</i> then let <i>q<i> be
  /// the constructor <i>T.id</i>, otherwise let <i>q<i> be the constructor
  /// <i>T<i>. Otherwise, if <i>q</i> is not defined or not accessible, a
  /// NoSuchMethodException is thrown.
  /// </blockquote>
  ConstructorElement lookUpConstructor(String name, LibraryElement library);

  /// Return the element representing the getter that results from looking up
  /// the getter with the given [name] in this class with respect to the given
  /// [library], or `null` if the look up fails. The behavior of this method is
  /// defined by the Dart Language Specification in section 12.15.1:
  /// <blockquote>
  /// The result of looking up getter (respectively setter) <i>m</i> in class
  /// <i>C</i> with respect to library <i>L</i> is:
  /// * If <i>C</i> declares an instance getter (respectively setter) named
  ///   <i>m</i> that is accessible to <i>L</i>, then that getter (respectively
  ///   setter) is the result of the lookup. Otherwise, if <i>C</i> has a
  ///   superclass <i>S</i>, then the result of the lookup is the result of
  ///   looking up getter (respectively setter) <i>m</i> in <i>S</i> with
  ///   respect to <i>L</i>. Otherwise, we say that the lookup has failed.
  /// </blockquote>
  @Deprecated('Use lookupGetter2 instead')
  PropertyAccessorElement lookUpGetter(String name, LibraryElement library);

  /// Return the getter with the given [name].
  ///
  /// If [concrete] is `true`, then the concrete implementation is returned,
  /// from this type, or its superclass.
  ///
  /// If [inherited] is `true`, then only getters from the superclass are
  /// considered.
  ///
  /// If [recoveryStatic] is `true`, then static getters of the class,
  /// and its superclasses are considered. Clients should not use it.
  PropertyAccessorElement lookUpGetter2(
    String name,
    LibraryElement library, {
    bool concrete = false,
    bool inherited = false,
    bool recoveryStatic = false,
  });

  /// Return the element representing the getter that results from looking up
  /// the getter with the given [name] in the superclass of this class with
  /// respect to the given [library], or `null` if the look up fails. The
  /// behavior of this method is defined by the Dart Language Specification in
  /// section 12.15.1:
  /// <blockquote>
  /// The result of looking up getter (respectively setter) <i>m</i> in class
  /// <i>C</i> with respect to library <i>L</i> is:
  /// * If <i>C</i> declares an instance getter (respectively setter) named
  ///   <i>m</i> that is accessible to <i>L</i>, then that getter (respectively
  ///   setter) is the result of the lookup. Otherwise, if <i>C</i> has a
  ///   superclass <i>S</i>, then the result of the lookup is the result of
  ///   looking up getter (respectively setter) <i>m</i> in <i>S</i> with
  ///   respect to <i>L</i>. Otherwise, we say that the lookup has failed.
  /// </blockquote>
  @Deprecated('Use lookupGetter2 instead')
  PropertyAccessorElement lookUpGetterInSuperclass(
      String name, LibraryElement library);

  /// Look up the member with the given [name] in this type and all extended
  /// and mixed in classes, and by default including [thisType]. If the search
  /// fails, this will then search interfaces.
  ///
  /// Return the element representing the member that was found, or `null` if
  /// there is no getter with the given name.
  ///
  /// The [library] determines if a private member name is visible, and does not
  /// need to be supplied for public names.
  @Deprecated('Use lookupGetter2 instead')
  PropertyAccessorElement lookUpInheritedGetter(String name,
      {LibraryElement library, bool thisType = true});

  /// Look up the member with the given [name] in this type and all extended
  /// and mixed in classes, starting from this type. If the search fails,
  /// search interfaces.
  ///
  /// Return the element representing the member that was found, or `null` if
  /// there is no getter with the given name.
  ///
  /// The [library] determines if a private member name is visible, and does not
  /// need to be supplied for public names.
  @Deprecated('Use lookupGetter2 and/or lookupMethod2 instead')
  ExecutableElement lookUpInheritedGetterOrMethod(String name,
      {LibraryElement library});

  /// Look up the member with the given [name] in this type and all extended
  /// and mixed in classes, and by default including [thisType]. If the search
  /// fails, this will then search interfaces.
  ///
  /// Return the element representing the member that was found, or `null` if
  /// there is no getter with the given name.
  ///
  /// The [library] determines if a private member name is visible, and does not
  /// need to be supplied for public names.
  @Deprecated('Use lookupMethod2 instead')
  MethodElement lookUpInheritedMethod(String name,
      {LibraryElement library, bool thisType = true});

  /// Look up the member with the given [name] in this type and all extended
  /// and mixed in classes, and by default including [thisType]. If the search
  /// fails, this will then search interfaces.
  ///
  /// Return the element representing the member that was found, or `null` if
  /// there is no getter with the given name.
  ///
  /// The [library] determines if a private member name is visible, and does not
  /// need to be supplied for public names.
  @Deprecated('Use lookupSetter2 instead')
  PropertyAccessorElement lookUpInheritedSetter(String name,
      {LibraryElement library, bool thisType = true});

  /// Return the element representing the method that results from looking up
  /// the method with the given [name] in this class with respect to the given
  /// [library], or `null` if the look up fails. The behavior of this method is
  /// defined by the Dart Language Specification in section 12.15.1:
  /// <blockquote>
  /// The result of looking up method <i>m</i> in class <i>C</i> with respect to
  /// library <i>L</i> is:
  /// * If <i>C</i> declares an instance method named <i>m</i> that is
  ///   accessible to <i>L</i>, then that method is the result of the lookup.
  ///   Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the
  ///   lookup is the result of looking up method <i>m</i> in <i>S</i> with
  ///   respect to <i>L</i> Otherwise, we say that the lookup has failed.
  /// </blockquote>
  @Deprecated('Use lookupMethod2 instead')
  MethodElement lookUpMethod(String name, LibraryElement library);

  /// Return the method with the given [name].
  ///
  /// If [concrete] is `true`, then the concrete implementation is returned,
  /// from this type, or its superclass.
  ///
  /// If [inherited] is `true`, then only methods from the superclass are
  /// considered.
  ///
  /// If [recoveryStatic] is `true`, then static methods of the class,
  /// and its superclasses are considered. Clients should not use it.
  MethodElement lookUpMethod2(
    String name,
    LibraryElement library, {
    bool concrete = false,
    bool inherited = false,
    bool recoveryStatic = false,
  });

  /// Return the element representing the method that results from looking up
  /// the method with the given [name] in the superclass of this class with
  /// respect to the given [library], or `null` if the look up fails. The
  /// behavior of this method is defined by the Dart Language Specification in
  /// section 12.15.1:
  /// <blockquote>
  /// The result of looking up method <i>m</i> in class <i>C</i> with respect to
  /// library <i>L</i> is:
  /// * If <i>C</i> declares an instance method named <i>m</i> that is
  ///   accessible to <i>L</i>, then that method is the result of the lookup.
  ///   Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the
  /// * lookup is the result of looking up method <i>m</i> in <i>S</i> with
  ///   respect to <i>L</i>.
  /// * Otherwise, we say that the lookup has failed.
  /// </blockquote>
  @Deprecated('Use lookupMethod2 instead')
  MethodElement lookUpMethodInSuperclass(String name, LibraryElement library);

  /// Return the element representing the setter that results from looking up
  /// the setter with the given [name] in this class with respect to the given
  /// [library], or `null` if the look up fails. The behavior of this method is
  /// defined by the Dart Language Specification in section 12.16:
  /// <blockquote>
  /// The result of looking up getter (respectively setter) <i>m</i> in class
  /// <i>C</i> with respect to library <i>L</i> is:
  /// * If <i>C</i> declares an instance getter (respectively setter) named
  ///   <i>m</i> that is accessible to <i>L</i>, then that getter (respectively
  ///   setter) is the result of the lookup. Otherwise, if <i>C</i> has a
  ///   superclass <i>S</i>, then the result of the lookup is the result of
  ///   looking up getter (respectively setter) <i>m</i> in <i>S</i> with
  ///   respect to <i>L</i>. Otherwise, we say that the lookup has failed.
  /// </blockquote>
  @Deprecated('Use lookupSetter2 instead')
  PropertyAccessorElement lookUpSetter(String name, LibraryElement library);

  /// Return the setter with the given [name].
  ///
  /// If [concrete] is `true`, then the concrete implementation is returned,
  /// from this type, or its superclass.
  ///
  /// If [inherited] is `true`, then only setters from the superclass are
  /// considered.
  ///
  /// If [recoveryStatic] is `true`, then static setters of the class,
  /// and its superclasses are considered. Clients should not use it.
  PropertyAccessorElement lookUpSetter2(
    String name,
    LibraryElement library, {
    bool concrete = false,
    bool inherited = false,
    bool recoveryStatic = false,
  });

  /// Return the element representing the setter that results from looking up
  /// the setter with the given [name] in the superclass of this class with
  /// respect to the given [library], or `null` if the look up fails. The
  /// behavior of this method is defined by the Dart Language Specification in
  /// section 12.16:
  /// <blockquote>
  /// The result of looking up getter (respectively setter) <i>m</i> in class
  /// <i>C</i> with respect to library <i>L</i> is:
  /// * If <i>C</i> declares an instance getter (respectively setter) named
  ///   <i>m</i> that is accessible to <i>L</i>, then that getter (respectively
  ///   setter) is the result of the lookup. Otherwise, if <i>C</i> has a
  ///   superclass <i>S</i>, then the result of the lookup is the result of
  ///   looking up getter (respectively setter) <i>m</i> in <i>S</i> with
  ///   respect to <i>L</i>. Otherwise, we say that the lookup has failed.
  /// </blockquote>
  @Deprecated('Use lookupSetter2 instead')
  PropertyAccessorElement lookUpSetterInSuperclass(
      String name, LibraryElement library);

  @Deprecated("Use ClassElement.instantiate()")
  @override
  InterfaceType substitute2(
      List<DartType> argumentTypes, List<DartType> parameterTypes);

  /// Return the type resulting from substituting the given arguments for this
  /// type's parameters. This is fully equivalent to `substitute2(argumentTypes,
  /// getTypeArguments())`.
  @deprecated // use instantiate
  InterfaceType substitute4(List<DartType> argumentTypes);

  /// Returns a "smart" version of the "least upper bound" of the given types.
  ///
  /// If these types have the same element and differ only in terms of the type
  /// arguments, attempts to find a compatible set of type arguments.
  ///
  /// Otherwise, returns the same result as [DartType.getLeastUpperBound].
  // TODO(brianwilkerson) This needs to be deprecated and moved to TypeSystem.
  static InterfaceType getSmartLeastUpperBound(
          InterfaceType first, InterfaceType second) =>
      InterfaceTypeImpl.getSmartLeastUpperBound(first, second);
}

/// A type that can track substituted type parameters, either for itself after
/// instantiation, or from a surrounding context.
///
/// For example, given a class `Foo<T>`, after instantiation with S for T, it
/// will track the substitution `{S/T}`.
///
/// This substitution will be propagated to its members. For example, say our
/// `Foo<T>` class has a field `T bar;`. When we look up this field, we will get
/// back a [FieldElement] that tracks the substituted type as `{S/T}T`, so when
/// we ask for the field type we will get `S`.
///
/// Clients may not extend, implement or mix-in this class.
abstract class ParameterizedType implements DartType {
  /// Return the type arguments used to instantiate this type.
  ///
  /// An [InterfaceType] always has type arguments.
  ///
  /// A [FunctionType] has type arguments only if it is a result of a typedef
  /// instantiation, otherwise the result is `null`.
  List<DartType> get typeArguments;

  /// Return a list containing all of the type parameters declared for this
  /// type.
  @Deprecated("Use ClassElement.typeParameters or FunctionType.typeFormals")
  List<TypeParameterElement> get typeParameters;

  /// Return the type resulting from instantiating (replacing) the given
  /// [argumentTypes] for this type's bound type parameters.
  @Deprecated("Use ClassElement.instantiate()")
  ParameterizedType instantiate(List<DartType> argumentTypes);
}

/// The type introduced by a type parameter.
///
/// Clients may not extend, implement or mix-in this class.
abstract class TypeParameterType implements DartType {
  /// Return the type representing the bound associated with this parameter,
  /// or `dynamic` if there was no explicit bound.
  DartType get bound;

  /// An object that can be used to identify this type parameter with `==`.
  ///
  /// Depending on the use, [bound] may also need to be taken into account.
  /// A given type parameter, it may have different bounds in different scopes.
  /// Always consult the bound if that could be relevant.
  ElementLocation get definition;

  @override
  TypeParameterElement get element;
}
