Migration: Created decorated types for synthetic default constructors of generic classes.
Fixes #37347.
Change-Id: I8eb7ca910f62aa7f10efbad3048096118cfcb4c8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107185
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index ec43afa..6e83905 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -86,20 +86,13 @@
var constructorElement = constructors[0];
if (constructorElement.isSynthetic) {
// Need to create a decorated type for the default constructor.
- if (classElement.typeParameters.isNotEmpty) {
- // TODO(paulberry): handle the default constructor for a generic
- // class.
- } else {
- var decoratedReturnType =
- _createDecoratedTypeForClass(classElement, node);
- var functionType = DecoratedType(
- constructorElement.type, _graph.never,
- returnType: decoratedReturnType,
- positionalParameters: [],
- namedParameters: {});
- _variables.recordDecoratedElementType(
- constructorElement, functionType);
- }
+ var decoratedReturnType =
+ _createDecoratedTypeForClass(classElement, node);
+ var functionType = DecoratedType(constructorElement.type, _graph.never,
+ returnType: decoratedReturnType,
+ positionalParameters: [],
+ namedParameters: {});
+ _variables.recordDecoratedElementType(constructorElement, functionType);
}
}
return null;
@@ -355,13 +348,11 @@
DecoratedType _createDecoratedTypeForClass(
ClassElement classElement, AstNode node) {
- if (classElement.typeParameters.isNotEmpty) {
- // Need to decorate the type parameters appropriately.
- // TODO(paulberry,brianwilkerson)
- _unimplemented(node, 'Declaration of a constructor with type parameters');
- }
- var decoratedType = new DecoratedType(classElement.type, _graph.never);
- return decoratedType;
+ var typeArguments = classElement.typeParameters
+ .map((t) => DecoratedType(t.type, _graph.never))
+ .toList();
+ return DecoratedType(classElement.type, _graph.never,
+ typeArguments: typeArguments);
}
/// Creates a DecoratedType corresponding to [type], with fresh nullability
diff --git a/pkg/nnbd_migration/test/node_builder_test.dart b/pkg/nnbd_migration/test/node_builder_test.dart
index 36b0ce8..5e2c014 100644
--- a/pkg/nnbd_migration/test/node_builder_test.dart
+++ b/pkg/nnbd_migration/test/node_builder_test.dart
@@ -44,6 +44,26 @@
expect(decoratedConstructorType.returnType.node, same(never));
}
+ test_class_with_default_constructor_generic() async {
+ await analyze('''
+class C<T, U> {}
+''');
+ var defaultConstructor = findElement.class_('C').constructors.single;
+ var decoratedConstructorType =
+ variables.decoratedElementType(defaultConstructor);
+ expect(decoratedConstructorType.type.toString(), 'C<T, U> Function()');
+ expect(decoratedConstructorType.node, same(never));
+ expect(decoratedConstructorType.typeArguments, isEmpty);
+ var returnType = decoratedConstructorType.returnType;
+ expect(returnType.type.toString(), 'C<T, U>');
+ expect(returnType.node, same(never));
+ expect(returnType.typeArguments, hasLength(2));
+ expect(returnType.typeArguments[0].type.toString(), 'T');
+ expect(returnType.typeArguments[0].node, same(never));
+ expect(returnType.typeArguments[1].type.toString(), 'U');
+ expect(returnType.typeArguments[1].node, same(never));
+ }
+
test_constructor_returnType_implicit_dynamic() async {
await analyze('''
class C {