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
;