Store Typedef(s) in kernel when parsing with Fasta, deserilize in DillLibraryBuilder.

R=ahe@google.com, paulberry@google.com, sigmund@google.com
BUG=

Review-Url: https://codereview.chromium.org/2882893002 .
diff --git a/pkg/analyzer/lib/src/fasta/element_store.dart b/pkg/analyzer/lib/src/fasta/element_store.dart
index c6a1049..537bc90 100644
--- a/pkg/analyzer/lib/src/fasta/element_store.dart
+++ b/pkg/analyzer/lib/src/fasta/element_store.dart
@@ -79,6 +79,8 @@
         do {
           if (builder is ClassBuilder) {
             elements[builder] = new KernelClassElement(builder);
+          } else if (builder is KernelFunctionTypeAliasBuilder) {
+            elements[builder] = new KernelFunctionTypeAliasElement(builder);
           } else if (builder is DillMemberBuilder) {
             Member member = builder.member;
             if (member is Field) {} else if (member is Procedure) {
@@ -289,6 +291,27 @@
   }
 }
 
+class KernelFunctionTypeAliasElement extends MockFunctionTypeAliasElement {
+  final KernelFunctionTypeAliasBuilder builder;
+
+  KernelFunctionTypeAliasElement(this.builder);
+
+  @override
+  analyzer.DartType get returnType {
+    return internalError("not supported.");
+  }
+
+  @override
+  analyzer.FunctionType get type {
+    return internalError("not supported.");
+  }
+
+  @override
+  List<TypeParameterElement> get typeParameters {
+    return internalError("not supported.");
+  }
+}
+
 class KernelInterfaceType extends MockInterfaceType {
   final KernelClassElement element;
 
diff --git a/pkg/analyzer/lib/src/fasta/mock_element.dart b/pkg/analyzer/lib/src/fasta/mock_element.dart
index f4404ae..c55c627 100644
--- a/pkg/analyzer/lib/src/fasta/mock_element.dart
+++ b/pkg/analyzer/lib/src/fasta/mock_element.dart
@@ -347,6 +347,17 @@
   FunctionDeclaration computeNode() => internalError("not supported.");
 }
 
+abstract class MockFunctionTypeAliasElement extends MockElement
+    implements FunctionTypeAliasElement {
+  MockFunctionTypeAliasElement() : super(ElementKind.FUNCTION_TYPE_ALIAS);
+
+  CompilationUnitElement get enclosingElement {
+    return internalError("not supported.");
+  }
+
+  TypeAlias computeNode() => internalError("not supported.");
+}
+
 abstract class MockParameterElement extends MockElement
     implements ParameterElement {
   MockParameterElement() : super(ElementKind.PARAMETER);
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
index 5854e6f..76be7d3 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
@@ -4,6 +4,7 @@
 
 library fasta.dill_library_builder;
 
+import 'package:front_end/src/fasta/dill/dill_typedef_builder.dart';
 import 'package:kernel/ast.dart'
     show
         Class,
@@ -15,7 +16,8 @@
         ListLiteral,
         Member,
         Procedure,
-        StaticGet;
+        StaticGet,
+        Typedef;
 
 import '../errors.dart' show internalError;
 
@@ -104,6 +106,11 @@
     return builder;
   }
 
+  void addTypedef(Typedef typedef) {
+    var typedefBuilder = new DillFunctionTypeAliasBuilder(typedef, this);
+    addBuilder(typedef.name, typedefBuilder, typedef.fileOffset);
+  }
+
   bool addToExportScope(String name, Builder member) {
     return internalError("Not implemented yet.");
   }
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
index 0206c29..d61cecb 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
@@ -36,6 +36,7 @@
   Future<Null> buildOutline(DillLibraryBuilder builder) async {
     builder.library.classes.forEach(builder.addClass);
     builder.library.procedures.forEach(builder.addMember);
+    builder.library.typedefs.forEach(builder.addTypedef);
     builder.library.fields.forEach(builder.addMember);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_typedef_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_typedef_builder.dart
new file mode 100644
index 0000000..07c66c9
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/dill/dill_typedef_builder.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2017, 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.
+
+library fasta.dill_typedef_builder;
+
+import 'package:front_end/src/fasta/builder/library_builder.dart';
+import 'package:front_end/src/fasta/errors.dart';
+import 'package:kernel/ast.dart' show DartType, Typedef;
+
+import '../kernel/kernel_builder.dart'
+    show
+        FormalParameterBuilder,
+        KernelFunctionTypeAliasBuilder,
+        KernelTypeBuilder,
+        MetadataBuilder,
+        TypeVariableBuilder;
+import 'dill_library_builder.dart' show DillLibraryBuilder;
+
+class DillFunctionTypeAliasBuilder extends KernelFunctionTypeAliasBuilder {
+  final Typedef typedef;
+
+  DillFunctionTypeAliasBuilder(this.typedef, DillLibraryBuilder parent)
+      : super(null, null, typedef.name, null, null, parent, typedef.fileOffset);
+
+  @override
+  List<FormalParameterBuilder> get formals {
+    return internalError('Not implemented.');
+  }
+
+  List<MetadataBuilder> get metadata {
+    return internalError('Not implemented.');
+  }
+
+  @override
+  KernelTypeBuilder get returnType {
+    return internalError('Not implemented.');
+  }
+
+  @override
+  List<TypeVariableBuilder> get typeVariables {
+    return internalError('Not implemented.');
+  }
+
+  @override
+  DartType buildThisType(LibraryBuilder library) => typedef.type;
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart
index 4b083dc..f69cf34 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart
@@ -4,6 +4,7 @@
 
 library fasta.kernel_function_type_alias_builder;
 
+import 'package:front_end/src/fasta/util/relativize.dart';
 import 'package:kernel/ast.dart'
     show
         DartType,
@@ -11,17 +12,17 @@
         FunctionType,
         InvalidType,
         NamedType,
-        TypeParameter;
-
+        TypeParameter,
+        Typedef;
 import 'package:kernel/type_algebra.dart' show substitute;
 
 import '../messages.dart' show warning;
-
 import 'kernel_builder.dart'
     show
         FormalParameterBuilder,
         FunctionTypeAliasBuilder,
         KernelFormalParameterBuilder,
+        KernelLibraryBuilder,
         KernelTypeBuilder,
         KernelTypeVariableBuilder,
         LibraryBuilder,
@@ -46,6 +47,14 @@
       : super(metadata, returnType, name, typeVariables, formals, parent,
             charOffset);
 
+  Typedef build(KernelLibraryBuilder libraryBuilder) {
+    DartType type = buildThisType(libraryBuilder);
+    var typedef_ = new Typedef(name, type);
+    typedef_.fileUri = relativizeUri(parent.fileUri);
+    typedef_.fileOffset = charOffset;
+    return typedef_;
+  }
+
   DartType buildThisType(LibraryBuilder library) {
     if (thisType != null) {
       if (thisType == const InvalidType()) {
@@ -90,22 +99,6 @@
         requiredParameterCount: requiredParameterCount);
   }
 
-  /// [arguments] have already been built.
-  DartType buildTypesWithBuiltArguments(
-      LibraryBuilder library, List<DartType> arguments) {
-    var thisType = buildThisType(library);
-    if (thisType is DynamicType) return thisType;
-    FunctionType result = thisType;
-    if (result.typeParameters.isEmpty && arguments == null) return result;
-    arguments =
-        computeDefaultTypeArguments(library, result.typeParameters, arguments);
-    Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
-    for (int i = 0; i < result.typeParameters.length; i++) {
-      substitution[result.typeParameters[i]] = arguments[i];
-    }
-    return substitute(result.withoutTypeParameters, substitution);
-  }
-
   DartType buildType(
       LibraryBuilder library, List<KernelTypeBuilder> arguments) {
     var thisType = buildThisType(library);
@@ -121,4 +114,20 @@
     }
     return buildTypesWithBuiltArguments(library, builtArguments);
   }
+
+  /// [arguments] have already been built.
+  DartType buildTypesWithBuiltArguments(
+      LibraryBuilder library, List<DartType> arguments) {
+    var thisType = buildThisType(library);
+    if (thisType is DynamicType) return thisType;
+    FunctionType result = thisType;
+    if (result.typeParameters.isEmpty && arguments == null) return result;
+    arguments =
+        computeDefaultTypeArguments(library, result.typeParameters, arguments);
+    Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
+    for (int i = 0; i < result.typeParameters.length; i++) {
+      substitution[result.typeParameters[i]] = arguments[i];
+    }
+    return substitute(result.withoutTypeParameters, substitution);
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index 64739bd..6da0448 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -652,9 +652,8 @@
       library.addMember(builder.build(this)..isStatic = true);
     } else if (builder is KernelProcedureBuilder) {
       library.addMember(builder.build(this)..isStatic = true);
-    } else if (builder is FunctionTypeAliasBuilder) {
-      // Kernel discard typedefs and use their corresponding function types
-      // directly.
+    } else if (builder is KernelFunctionTypeAliasBuilder) {
+      library.addTypedef(builder.build(this));
     } else if (builder is KernelEnumBuilder) {
       library.addClass(builder.build(this, coreLibrary));
     } else if (builder is PrefixBuilder) {
diff --git a/pkg/front_end/test/incremental_kernel_generator_test.dart b/pkg/front_end/test/incremental_kernel_generator_test.dart
index 658bc2a..ca97c3e 100644
--- a/pkg/front_end/test/incremental_kernel_generator_test.dart
+++ b/pkg/front_end/test/incremental_kernel_generator_test.dart
@@ -184,6 +184,31 @@
     }
   }
 
+  test_compile_typedef() async {
+    writeFile('/test/.packages', 'test:lib/');
+    String aPath = '/test/lib/a.dart';
+    String bPath = '/test/lib/b.dart';
+    writeFile(aPath, 'typedef int F<T>(T x);');
+    Uri bUri = writeFile(
+        bPath,
+        r'''
+import 'a.dart';
+F<String> f;
+''');
+
+    Program program = await getInitialState(bUri);
+    Library library = _getLibrary(program, bUri);
+    expect(
+        _getLibraryText(library),
+        r'''
+library;
+import self as self;
+import "dart:core" as core;
+
+static field (core::String) → core::int f;
+''');
+  }
+
   test_updatePart() async {
     writeFile('/test/.packages', 'test:lib/');
     String libPath = '/test/lib/test.dart';
diff --git a/pkg/front_end/test/subpackage_relationships_test.dart b/pkg/front_end/test/subpackage_relationships_test.dart
index 97c7504..b0592bb 100644
--- a/pkg/front_end/test/subpackage_relationships_test.dart
+++ b/pkg/front_end/test/subpackage_relationships_test.dart
@@ -64,6 +64,7 @@
   ]),
   'lib/src/fasta/dill': new SubpackageRules(allowedDependencies: [
     'lib/src/fasta',
+    'lib/src/fasta/builder',
     'lib/src/fasta/kernel',
   ]),
   'lib/src/fasta/kernel': new SubpackageRules(allowedDependencies: [
diff --git a/pkg/front_end/testcases/covariant_generic.dart.outline.expect b/pkg/front_end/testcases/covariant_generic.dart.outline.expect
index d618506..86f10e0 100644
--- a/pkg/front_end/testcases/covariant_generic.dart.outline.expect
+++ b/pkg/front_end/testcases/covariant_generic.dart.outline.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+typedef Callback = <T extends core::Object>(T) → void;
 class Foo<T extends core::Object> extends core::Object {
   final field self::Foo::T finalField;
   final field (self::Foo::T) → void callbackField;
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.strong.expect
index 3ac87d5..bb7b086 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.strong.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+typedef F = <V extends core::Object>(V) → void;
 class C<T extends core::Object> extends self::D<self::C::T> {
   constructor •() → void
     : super self::D::•()
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.expect
index 5e0a79e..d994b73 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+typedef G = <V extends core::Object>() → core::List<V>;
 class C<T extends core::Object> extends self::D<self::C::T> {
   constructor •() → void
     : super self::D::•()
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_return_type.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_return_type.dart.strong.expect
index 2cdb834..a5ca65f 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_return_type.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_return_type.dart.strong.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+typedef F = <V extends core::Object>() → V;
 class C<T extends core::Object> extends self::D<self::C::T> {
   constructor •() → void
     : super self::D::•()
diff --git a/pkg/front_end/testcases/inference/lambda_return_type.dart.direct.expect b/pkg/front_end/testcases/inference/lambda_return_type.dart.direct.expect
index 84db6c0..576d334 100644
--- a/pkg/front_end/testcases/inference/lambda_return_type.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/lambda_return_type.dart.direct.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+typedef FunctionReturningNum = () → core::num;
 static method main() → dynamic {
   core::int i = 1;
   core::Object o = 1;
diff --git a/pkg/front_end/testcases/inference/lambda_return_type.dart.outline.expect b/pkg/front_end/testcases/inference/lambda_return_type.dart.outline.expect
index 09dc88c..7b76fd8 100644
--- a/pkg/front_end/testcases/inference/lambda_return_type.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/lambda_return_type.dart.outline.expect
@@ -1,5 +1,7 @@
 library test;
 import self as self;
+import "dart:core" as core;
 
+typedef FunctionReturningNum = () → core::num;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/inference/lambda_return_type.dart.strong.expect b/pkg/front_end/testcases/inference/lambda_return_type.dart.strong.expect
index 61410a5..e977946 100644
--- a/pkg/front_end/testcases/inference/lambda_return_type.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/lambda_return_type.dart.strong.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+typedef FunctionReturningNum = () → core::num;
 static method main() → dynamic {
   core::int i = 1;
   core::Object o = 1;
diff --git a/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.direct.expect b/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.direct.expect
index 571a2a1..ed2a536 100644
--- a/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.direct.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+typedef FunctionReturningInt = () → core::int;
 static method main() → dynamic {
   function f() → core::num
     return 0;
diff --git a/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.outline.expect b/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.outline.expect
index 09dc88c..d055413 100644
--- a/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.outline.expect
@@ -1,5 +1,7 @@
 library test;
 import self as self;
+import "dart:core" as core;
 
+typedef FunctionReturningInt = () → core::int;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.strong.expect b/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.strong.expect
index 571a2a1..ed2a536 100644
--- a/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.strong.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+typedef FunctionReturningInt = () → core::int;
 static method main() → dynamic {
   function f() → core::num
     return 0;
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.strong.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.strong.expect
index 486e1f3..20689bc 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.strong.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+typedef F = () → core::int;
 static method main() → dynamic {
   core::List<() → core::int> v = <() → core::int>[() → core::int {
     return 1;
diff --git a/pkg/front_end/testcases/rasta/malformed_function_type.dart.outline.expect b/pkg/front_end/testcases/rasta/malformed_function_type.dart.outline.expect
index 6a28c0d..3951999 100644
--- a/pkg/front_end/testcases/rasta/malformed_function_type.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/malformed_function_type.dart.outline.expect
@@ -1,5 +1,7 @@
 library;
 import self as self;
+import "dart:core" as core;
 
+typedef Handle = (core::String) → dynamic;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/rasta/type_literals.dart.outline.expect b/pkg/front_end/testcases/rasta/type_literals.dart.outline.expect
index 6b1bbaf..f3f456b 100644
--- a/pkg/front_end/testcases/rasta/type_literals.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/type_literals.dart.outline.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+typedef Func = () → void;
 class C<T extends core::Object> extends core::Object {
   constructor •() → void
     ;
diff --git a/pkg/front_end/testcases/rasta/typedef.dart.outline.expect b/pkg/front_end/testcases/rasta/typedef.dart.outline.expect
index 6a28c0d..f4b16f1 100644
--- a/pkg/front_end/testcases/rasta/typedef.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/typedef.dart.outline.expect
@@ -1,5 +1,6 @@
 library;
 import self as self;
 
+typedef Foo = () → void;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.outline.expect b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.outline.expect
index b27584e..eff4b82 100644
--- a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.outline.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+typedef VoidFunction = () → void;
 class Fisk extends core::Object {
   constructor •() → void
     ;
diff --git a/pkg/front_end/testcases/typedef.dart.direct.expect b/pkg/front_end/testcases/typedef.dart.direct.expect
index b53d1e4..03c71df 100644
--- a/pkg/front_end/testcases/typedef.dart.direct.expect
+++ b/pkg/front_end/testcases/typedef.dart.direct.expect
@@ -2,6 +2,9 @@
 import self as self;
 import "dart:core" as core;
 
+typedef _NullaryFunction = () → dynamic;
+typedef _UnaryFunction = (dynamic) → dynamic;
+typedef _BinaryFunction = (dynamic, dynamic) → dynamic;
 static method main() → dynamic {
   core::print(self::main is () → dynamic);
   core::print(self::main is (dynamic) → dynamic);
diff --git a/pkg/front_end/testcases/typedef.dart.outline.expect b/pkg/front_end/testcases/typedef.dart.outline.expect
index 6a28c0d..fa3c15d 100644
--- a/pkg/front_end/testcases/typedef.dart.outline.expect
+++ b/pkg/front_end/testcases/typedef.dart.outline.expect
@@ -1,5 +1,8 @@
 library;
 import self as self;
 
+typedef _NullaryFunction = () → dynamic;
+typedef _UnaryFunction = (dynamic) → dynamic;
+typedef _BinaryFunction = (dynamic, dynamic) → dynamic;
 static method main() → dynamic
   ;