Serialize typedef parameters (including function typed ones) to Kernel and use it to resynthesize typedefs from Kernel.

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

Review-Url: https://codereview.chromium.org/2990783002 .
This commit is contained in:
Konstantin Shcheglov 2017-07-27 11:53:12 -07:00
parent 7d8d0b51c4
commit afc392b66d
10 changed files with 140 additions and 88 deletions

View file

@ -1683,6 +1683,11 @@ class CompilationUnitElementImpl extends UriReferencedElementImpl
@override
List<FunctionTypeAliasElement> get functionTypeAliases {
if (_kernelContext != null) {
_typeAliases ??= _kernelContext.library.typedefs
.map((k) => new FunctionTypeAliasElementImpl.forKernel(this, k))
.toList(growable: false);
}
if (_unlinkedUnit != null) {
_typeAliases ??= _unlinkedUnit.typedefs.map((t) {
if (t.style == TypedefStyle.functionType) {
@ -4920,6 +4925,11 @@ class FunctionTypeAliasElementImpl extends ElementImpl
*/
final UnlinkedTypedef _unlinkedTypedef;
/**
* The kernel of the element.
*/
final kernel.Typedef _kernel;
/**
* A list containing all of the parameters defined by this type alias.
*/
@ -4944,13 +4954,23 @@ class FunctionTypeAliasElementImpl extends ElementImpl
*/
FunctionTypeAliasElementImpl(String name, int nameOffset)
: _unlinkedTypedef = null,
_kernel = null,
super(name, nameOffset);
/**
* Initialize using the given kernel.
*/
FunctionTypeAliasElementImpl.forKernel(
CompilationUnitElementImpl enclosingUnit, this._kernel)
: _unlinkedTypedef = null,
super.forSerialized(enclosingUnit);
/**
* Initialize a newly created type alias element to have the given [name].
*/
FunctionTypeAliasElementImpl.forNode(Identifier name)
: _unlinkedTypedef = null,
_kernel = null,
super.forNode(name);
/**
@ -4958,7 +4978,8 @@ class FunctionTypeAliasElementImpl extends ElementImpl
*/
FunctionTypeAliasElementImpl.forSerialized(
this._unlinkedTypedef, CompilationUnitElementImpl enclosingUnit)
: super.forSerialized(enclosingUnit);
: _kernel = null,
super.forSerialized(enclosingUnit);
@override
int get codeLength {
@ -4999,7 +5020,7 @@ class FunctionTypeAliasElementImpl extends ElementImpl
_enclosingElement as CompilationUnitElementImpl;
@override
List<kernel.TypeParameter> get kernelTypeParams => null;
List<kernel.TypeParameter> get kernelTypeParams => _kernel?.typeParameters;
@override
ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS;
@ -5015,6 +5036,9 @@ class FunctionTypeAliasElementImpl extends ElementImpl
@override
String get name {
if (_kernel != null) {
return _kernel.name;
}
if (_unlinkedTypedef != null) {
return _unlinkedTypedef.name;
}
@ -5032,6 +5056,13 @@ class FunctionTypeAliasElementImpl extends ElementImpl
@override
List<ParameterElement> get parameters {
if (_kernel != null) {
_parameters ??= ParameterElementImpl.forKernelParameters(
this,
_kernel.requiredParameterCount,
_kernel.positionalParameters,
_kernel.namedParameters);
}
if (_unlinkedTypedef != null) {
_parameters ??= ParameterElementImpl.resynthesizeList(
_unlinkedTypedef.parameters, this);
@ -5054,10 +5085,17 @@ class FunctionTypeAliasElementImpl extends ElementImpl
@override
DartType get returnType {
if (_unlinkedTypedef != null && _returnType == null) {
_returnType = enclosingUnit.resynthesizerContext.resolveTypeRef(
this, _unlinkedTypedef.returnType,
declaredType: true);
if (_returnType == null) {
if (_kernel != null) {
var type = _kernel.type as kernel.FunctionType;
_returnType =
enclosingUnit._kernelContext.getType(this, type.returnType);
}
if (_unlinkedTypedef != null) {
_returnType = enclosingUnit.resynthesizerContext.resolveTypeRef(
this, _unlinkedTypedef.returnType,
declaredType: true);
}
}
return _returnType;
}
@ -5069,8 +5107,10 @@ class FunctionTypeAliasElementImpl extends ElementImpl
@override
FunctionType get type {
if (_unlinkedTypedef != null && _type == null) {
_type = new FunctionTypeImpl.forTypedef(this);
if (_type == null) {
if (_kernel != null || _unlinkedTypedef != null) {
_type = new FunctionTypeImpl.forTypedef(this);
}
}
return _type;
}

View file

@ -9435,6 +9435,13 @@ typedef dynamic F(dynamic x, dynamic y);
''');
}
test_typedef_parameters_named() async {
var library = await checkLibrary('typedef F({y, z, x});');
checkElementText(library, r'''
typedef dynamic F({dynamic y}, {dynamic z}, {dynamic x});
''');
}
test_typedef_return_type() async {
var library = await checkLibrary('typedef int F();');
checkElementText(library, r'''

View file

@ -723,11 +723,6 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_library_documented_stars();
}
@failingTest
test_main_typedef() async {
await super.test_main_typedef();
}
@failingTest
test_metadata_classTypeAlias() async {
await super.test_metadata_classTypeAlias();
@ -800,11 +795,6 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_metadata_simpleFormalParameter_withDefault();
}
@failingTest
test_metadata_typeParameter_ofTypedef() async {
await super.test_metadata_typeParameter_ofTypedef();
}
@failingTest
test_method_documented() async {
await super.test_method_documented();
@ -995,61 +985,6 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_typedef_generic_asFieldType();
}
@failingTest
test_typedef_parameter_parameters() async {
await super.test_typedef_parameter_parameters();
}
@failingTest
test_typedef_parameter_parameters_in_generic_class() async {
await super.test_typedef_parameter_parameters_in_generic_class();
}
@failingTest
test_typedef_parameter_return_type() async {
await super.test_typedef_parameter_return_type();
}
@failingTest
test_typedef_parameter_type() async {
await super.test_typedef_parameter_type();
}
@failingTest
test_typedef_parameter_type_generic() async {
await super.test_typedef_parameter_type_generic();
}
@failingTest
test_typedef_parameters() async {
await super.test_typedef_parameters();
}
@failingTest
test_typedef_return_type() async {
await super.test_typedef_return_type();
}
@failingTest
test_typedef_return_type_generic() async {
await super.test_typedef_return_type_generic();
}
@failingTest
test_typedef_return_type_implicit() async {
await super.test_typedef_return_type_implicit();
}
@failingTest
test_typedef_return_type_void() async {
await super.test_typedef_return_type_void();
}
@failingTest
test_typedef_type_parameters() async {
await super.test_typedef_type_parameters();
}
@failingTest
test_typedef_type_parameters_bound() async {
await super.test_typedef_type_parameters_bound();
@ -1065,16 +1000,6 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_typedef_type_parameters_bound_recursive2();
}
@failingTest
test_typedef_type_parameters_f_bound_complex() async {
await super.test_typedef_type_parameters_f_bound_complex();
}
@failingTest
test_typedef_type_parameters_f_bound_simple() async {
await super.test_typedef_type_parameters_f_bound_simple();
}
@failingTest
@fastaProblem
test_unresolved_annotation_instanceCreation_argument_super() async {

View file

@ -4,6 +4,8 @@
library fasta.kernel_function_type_alias_builder;
import 'package:front_end/src/fasta/kernel/kernel_function_type_builder.dart';
import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart';
import 'package:kernel/ast.dart'
show
DartType,
@ -11,15 +13,15 @@ import 'package:kernel/ast.dart'
FunctionType,
InvalidType,
TypeParameter,
Typedef;
Typedef,
VariableDeclaration;
import 'package:kernel/type_algebra.dart' show substitute;
import '../fasta_codes.dart' show templateCyclicTypedef;
import 'kernel_builder.dart'
show
FunctionTypeAliasBuilder,
KernelFormalParameterBuilder,
KernelFunctionTypeBuilder,
KernelTypeBuilder,
KernelTypeVariableBuilder,
@ -61,6 +63,7 @@ class KernelFunctionTypeAliasBuilder
return thisType;
}
thisType = const InvalidType();
DartType builtType = type?.build(library) ?? const DynamicType();
if (typeVariables != null) {
for (KernelTypeVariableBuilder tv in typeVariables) {
@ -68,6 +71,9 @@ class KernelFunctionTypeAliasBuilder
target.typeParameters.add(tv.parameter..parent = target);
}
}
_buildParameters(library);
return thisType = builtType;
}
@ -103,4 +109,23 @@ class KernelFunctionTypeAliasBuilder
}
return buildTypesWithBuiltArguments(library, builtArguments);
}
/// Build and set formal parameters of this typedef.
void _buildParameters(LibraryBuilder library) {
int requiredCount = 0;
final positional = <VariableDeclaration>[];
final named = <VariableDeclaration>[];
if (type.formals != null) {
for (KernelFormalParameterBuilder formal in type.formals) {
KernelVariableDeclaration parameter = formal.build(library);
if (formal.isPositional) {
positional.add(parameter);
if (formal.isRequired) requiredCount++;
} else if (formal.isNamed) {
named.add(parameter);
}
}
target.setParameters(requiredCount, positional, named);
}
}
}

View file

@ -14,7 +14,6 @@ import 'package:kernel/ast.dart'
TypeParameter;
import '../fasta_codes.dart' show messageSupertypeIsFunction;
import 'kernel_builder.dart'
show
FormalParameterBuilder,

View file

@ -493,6 +493,16 @@ class Typedef extends NamedNode {
List<Expression> annotations = const <Expression>[];
String name;
final List<TypeParameter> typeParameters;
@informative
int requiredParameterCount = 0;
@informative
List<VariableDeclaration> positionalParameters = <VariableDeclaration>[];
@informative
List<VariableDeclaration> namedParameters = <VariableDeclaration>[];
DartType type;
Typedef(this.name, this.type,
@ -508,9 +518,22 @@ class Typedef extends NamedNode {
return v.visitTypedef(this);
}
void setParameters(
int requiredParameterCount,
List<VariableDeclaration> positionalParameters,
List<VariableDeclaration> namedParameters) {
this.requiredParameterCount = requiredParameterCount;
this.positionalParameters = positionalParameters;
this.namedParameters = namedParameters;
setParents(this.positionalParameters, this);
setParents(this.namedParameters, this);
}
transformChildren(Transformer v) {
transformList(annotations, v, this);
transformList(typeParameters, v, this);
transformList(positionalParameters, v, this);
transformList(namedParameters, v, this);
if (type != null) {
type = v.visitDartType(type);
}
@ -519,6 +542,9 @@ class Typedef extends NamedNode {
visitChildren(Visitor v) {
visitList(annotations, v);
visitList(typeParameters, v);
visitList(typeParameters, v);
visitList(positionalParameters, v);
visitList(namedParameters, v);
type?.accept(v);
}

View file

@ -438,6 +438,13 @@ class BinaryBuilder {
String name = readStringReference();
String fileUri = readUriReference();
readAndPushTypeParameterList(node.typeParameters, node);
int requiredParameterCount = readUInt();
var positionalParameters = readVariableDeclarationList();
var namedParameters = readVariableDeclarationList();
node.setParameters(
requiredParameterCount, positionalParameters, namedParameters);
var type = readDartType();
typeParameterStack.length = 0;
if (shouldWriteData) {
@ -1221,6 +1228,11 @@ class BinaryBuilder {
return new NamedExpression(readStringReference(), readExpression());
}
List<VariableDeclaration> readVariableDeclarationList() {
return new List<VariableDeclaration>.generate(
readUInt(), (i) => readVariableDeclaration());
}
List<VariableDeclaration> readAndPushVariableDeclarationList() {
return new List<VariableDeclaration>.generate(
readUInt(), (i) => readAndPushVariableDeclaration());

View file

@ -344,14 +344,19 @@ class BinaryPrinter extends Visitor {
}
void visitTypedef(Typedef node) {
_variableIndexer = new VariableIndexer();
writeCanonicalNameReference(getCanonicalNameOfTypedef(node));
writeOffset(node.fileOffset);
writeStringReference(node.name);
writeUriReference(node.fileUri ?? '');
_typeParameterIndexer.enter(node.typeParameters);
writeNodeList(node.typeParameters);
writeUInt30(node.requiredParameterCount);
writeVariableDeclarationList(node.positionalParameters);
writeVariableDeclarationList(node.namedParameters);
writeNode(node.type);
_typeParameterIndexer.exit(node.typeParameters);
_variableIndexer = null;
}
void writeAnnotation(Expression annotation) {

View file

@ -337,7 +337,8 @@ class VerifyingVisitor extends RecursiveVisitor {
!(parent is ForStatement && parent.body != node) &&
!(parent is ForInStatement && parent.body != node) &&
parent is! Let &&
parent is! LocalInitializer) {
parent is! LocalInitializer &&
parent is! Typedef) {
problem(
node,
"VariableDeclaration must be a direct child of a Block, "

View file

@ -4225,6 +4225,18 @@ void StreamingFlowGraphBuilder::SkipLibraryTypedef() {
SkipStringReference(); // read name index.
ReadUInt(); // read source_uri_index.
SkipTypeParametersList(); // read type parameters.
ReadUInt(); // read required parameter count
intptr_t positional_count = ReadListLength();
for (intptr_t i = 0; i < positional_count; i++) {
SkipVariableDeclaration();
}
intptr_t named_count = ReadListLength();
for (intptr_t i = 0; i < named_count; i++) {
SkipVariableDeclaration();
}
SkipDartType(); // read type.
}