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 {