Index: pkg/kernel/lib/transformations/reify/transformation/transformer.dart |
diff --git a/pkg/kernel/lib/transformations/reify/transformation/transformer.dart b/pkg/kernel/lib/transformations/reify/transformation/transformer.dart |
index 867248510fc833bc62779501b704cf075f34d517..a057443a62209700b78a8f2a3183195be2ea12d7 100644 |
--- a/pkg/kernel/lib/transformations/reify/transformation/transformer.dart |
+++ b/pkg/kernel/lib/transformations/reify/transformation/transformer.dart |
@@ -103,6 +103,8 @@ class ReifyVisitor extends Transformer with DebugTrace { |
// TODO(karlklose): find a way to get rid of this state in the visitor. |
TransformationContext context; |
+ static const String genericMethodTypeParametersName = r"$typeParameters"; |
+ |
bool libraryShouldBeTransformed(Library library) { |
return libraryToTransform == null || libraryToTransform == library; |
} |
@@ -180,6 +182,9 @@ class ReifyVisitor extends Transformer with DebugTrace { |
// Intercept calls to factories of classes we do not transform |
return interceptInstantiation(invocation, target); |
} |
+ |
+ addTypeArgumentToGenericInvocation(invocation); |
+ |
return invocation; |
} |
@@ -419,6 +424,8 @@ class ReifyVisitor extends Transformer with DebugTrace { |
FunctionNode visitFunctionNode(FunctionNode node) { |
trace(node); |
+ addTypeArgumentToGenericDeclaration(node); |
+ |
// If we have a [TransformationContext] with a runtime type field and we |
// translate a constructor or factory, we need a parameter that the code of |
// initializers or the factory body can use to access type arguments. |
@@ -572,4 +579,46 @@ class ReifyVisitor extends Transformer with DebugTrace { |
new InterfaceType(builder.coreTypes.mapClass, |
<DartType>[node.keyType, node.valueType])); |
} |
+ |
+ Expression visitMethodInvocation(MethodInvocation node) { |
+ node.transformChildren(this); |
+ addTypeArgumentToGenericInvocation(node); |
+ return node; |
+ } |
+ |
+ bool isGenericMethod(FunctionNode node) { |
+ if (node.parent is Member) { |
+ Member member = node.parent; |
+ if (member is Constructor || |
+ member is Procedure && member.kind == ProcedureKind.Factory) { |
+ return member.enclosingClass.typeParameters.length < |
+ node.typeParameters.length; |
+ } |
+ } |
+ return node.typeParameters.isNotEmpty; |
+ } |
+ |
+ void addTypeArgumentToGenericInvocation(InvocationExpression expression) { |
+ if (expression.arguments.types.length > 0) { |
+ ListLiteral genericMethodTypeParameters = new ListLiteral( |
+ expression.arguments.types |
+ .map(createRuntimeType) |
+ .toList(growable: false), |
+ typeArgument: rtiLibrary.typeType); |
+ expression.arguments.named.add(new NamedExpression( |
+ genericMethodTypeParametersName, genericMethodTypeParameters) |
+ ..parent = expression.arguments); |
+ } |
+ } |
+ |
+ void addTypeArgumentToGenericDeclaration(FunctionNode node) { |
+ if (isGenericMethod(node)) { |
+ VariableDeclaration genericMethodTypeParameters = new VariableDeclaration( |
+ genericMethodTypeParametersName, |
+ type: new InterfaceType( |
+ builder.coreTypes.listClass, <DartType>[rtiLibrary.typeType])); |
+ genericMethodTypeParameters.parent = node; |
+ node.namedParameters.insert(0, genericMethodTypeParameters); |
+ } |
+ } |
} |