Add DartType.alias{Element,Arguments} and class TypeAliasElement

First step in implementing non-function type aliases in the analyzer:
Just add the new back-references in types, such that they can refer to
a type alias which was used to obtain the type, if any.

Next step: Preserve the aliasElement and aliasArguments in summaries,
next again: Create `TypeAliasElementImpl` and ensure that the parser
can create them.

Change-Id: I1bfbc2c3893e32c5b1826552361a0238aa2b4058
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/169380
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Erik Ernst <eernst@google.com>
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 2656b09..4e47272 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1155,24 +1155,20 @@
 
 /// A function type alias (`typedef`).
 ///
+/// This class models a type alias whose body specifies a function type, as
+/// is the only possible kind of type alias before the generalization that
+/// allows the body to be an arbitrary type.
+///
+/// This class will be deprecated and [TypeAliasElement] will replace it
+/// when non-function type aliases are enabled by default.
+///
 /// Clients may not extend, implement or mix-in this class.
-abstract class FunctionTypeAliasElement
-    implements TypeParameterizedElement, TypeDefiningElement {
-  @override
-  CompilationUnitElement get enclosingElement;
-
+abstract class FunctionTypeAliasElement implements TypeAliasElement {
   /// Return the generic function type element representing the generic function
   /// type on the right side of the equals.
   GenericFunctionTypeElement get function;
 
-  /// Produces the function type resulting from instantiating this typedef with
-  /// the given [typeArguments] and [nullabilitySuffix].
-  ///
-  /// Note that this always instantiates the typedef itself, so for a
-  /// [FunctionTypeAliasElement] the returned [FunctionType] might still be a
-  /// generic function, with type formals. For example, if the typedef is:
-  ///     typedef F<T> = void Function<U>(T, U);
-  /// then `F<int>` will produce `void Function<U>(int, U)`.
+  @override
   FunctionType instantiate({
     @required List<DartType> typeArguments,
     @required NullabilitySuffix nullabilitySuffix,
@@ -1664,6 +1660,28 @@
   bool get isExternal;
 }
 
+/// A type alias (`typedef`).
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class TypeAliasElement
+    implements TypeParameterizedElement, TypeDefiningElement {
+  @override
+  CompilationUnitElement get enclosingElement;
+
+  /// Produces the type resulting from instantiating this typedef with the given
+  /// [typeArguments] and [nullabilitySuffix].
+  ///
+  /// Note that this always instantiates the typedef itself, so for a
+  /// [TypeAliasElement] the returned [DartType] might still be a generic
+  /// type, with type formals. For example, if the typedef is:
+  ///     typedef F<T> = void Function<U>(T, U);
+  /// then `F<int>` will produce `void Function<U>(int, U)`.
+  DartType instantiate({
+    @required List<DartType> typeArguments,
+    @required NullabilitySuffix nullabilitySuffix,
+  });
+}
+
 /// An element that defines a type.
 ///
 /// Clients may not extend, implement or mix-in this class.
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index 326b7a8..e7c04af 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -29,6 +29,14 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class DartType {
+  /// If this type is an instantiation of a type alias, return the type
+  /// arguments used for the instantiation. Otherwise return `null`.
+  List<DartType> get aliasArguments;
+
+  /// If this type is an instantiation of a type alias, return it.
+  /// Otherwise return `null`.
+  TypeAliasElement get aliasElement;
+
   /// Return the name of this type as it should appear when presented to users
   /// in contexts such as error messages.
   ///
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index f0be482..20211b6 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -1602,12 +1602,18 @@
 /// The abstract class `TypeImpl` implements the behavior common to objects
 /// representing the declared type of elements in the element model.
 abstract class TypeImpl implements DartType {
+  @override
+  final List<DartType> aliasArguments;
+
+  @override
+  final TypeAliasElement aliasElement;
+
   /// The element representing the declaration of this type, or `null` if the
   /// type has not, or cannot, be associated with an element.
   final Element _element;
 
   /// Initialize a newly created type to be declared by the given [element].
-  TypeImpl(this._element);
+  TypeImpl(this._element, {this.aliasElement, this.aliasArguments});
 
   @deprecated
   @override