Chromium Code Reviews| 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..8a39bfbf8bfd27cb5897e10d94724875c6a34360 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,50 @@ 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 Constructor) { |
|
karlklose
2017/03/15 15:20:22
If you stored `node.parent` in a local variable, t
Dmitry Stefantsov
2017/03/16 09:30:42
Yes, I agree with a small remark. The if-else oper
|
| + return (node.parent as Member).enclosingClass.typeParameters.length < |
| + node.typeParameters.length; |
| + } |
| + if (node.parent is Procedure && |
| + (node.parent as Procedure).kind == ProcedureKind.Factory) { |
| + return (node.parent as Member).enclosingClass.typeParameters.length < |
| + node.typeParameters.length; |
| + } |
| + if (node.typeParameters.length > 0) { |
| + return true; |
| + } |
| + return false; |
| + } |
| + |
| + 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); |
| + } |
| + } |
| } |