Print default types of type parameters of type defining elements.

R=brianwilkerson@google.com

Change-Id: I62e2d7b050e0d81169b0d780ebce8858bee9dec0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164700
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 88ea0b6..d4fd128 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -12,6 +12,7 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:meta/meta.dart';
 import 'package:test/test.dart';
 
 import 'resolved_ast_printer.dart';
@@ -204,7 +205,7 @@
 
     writeName(e);
     writeCodeRange(e);
-    writeTypeParameterElements(e.typeParameters);
+    writeTypeParameterElements(e.typeParameters, withDefault: true);
 
     if (e.supertype != null && e.supertype.element.name != 'Object' ||
         e.mixins.isNotEmpty) {
@@ -369,7 +370,7 @@
     buffer.write('extension ');
     writeName(e);
     writeCodeRange(e);
-    writeTypeParameterElements(e.typeParameters);
+    writeTypeParameterElements(e.typeParameters, withDefault: false);
     if (e.extendedType != null) {
       buffer.write(' on ');
       writeType(e.extendedType);
@@ -404,7 +405,7 @@
     writeName(e);
     writeCodeRange(e);
 
-    writeTypeParameterElements(e.typeParameters);
+    writeTypeParameterElements(e.typeParameters, withDefault: false);
     writeParameterElements(e.parameters);
 
     writeBodyModifiers(e);
@@ -421,7 +422,7 @@
       buffer.write('typedef ');
       writeName(e);
       writeCodeRange(e);
-      writeTypeParameterElements(e.typeParameters);
+      writeTypeParameterElements(e.typeParameters, withDefault: true);
 
       buffer.write(' = ');
 
@@ -429,7 +430,7 @@
       if (function != null) {
         writeType(function.returnType);
         buffer.write(' Function');
-        writeTypeParameterElements(function.typeParameters);
+        writeTypeParameterElements(function.typeParameters, withDefault: false);
         writeParameterElements(function.parameters);
       } else {
         buffer.write('<null>');
@@ -539,7 +540,7 @@
     writeCodeRange(e);
     writeTypeInferenceError(e);
 
-    writeTypeParameterElements(e.typeParameters);
+    writeTypeParameterElements(e.typeParameters, withDefault: false);
     writeParameterElements(e.parameters);
 
     writeBodyModifiers(e);
@@ -1046,13 +1047,17 @@
     }
   }
 
-  void writeTypeParameterElement(TypeParameterElement e) {
+  void writeTypeParameterElement(
+    TypeParameterElement e, {
+    @required bool withDefault,
+  }) {
+    var impl = e as TypeParameterElementImpl;
+
     writeMetadata(e, '', '\n');
 
     // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
     // variance is added to the interface.
     if (withTypeParameterVariance) {
-      var impl = e as TypeParameterElementImpl;
       var variance = impl.variance;
       buffer.write(variance.toString() + ' ');
     }
@@ -1063,16 +1068,24 @@
       buffer.write(' extends ');
       writeType(e.bound);
     }
-    // TODO(scheglov) print the default type
-//    if (e is TypeParameterElementImpl && e.defaultType != null) {
-//      buffer.write(' = ');
-//      writeType(e.defaultType);
-//    }
+
+    if (withDefault) {
+      var defaultType = impl.defaultType;
+      if (defaultType is! DynamicTypeImpl) {
+        buffer.write(' = ');
+        writeType(defaultType);
+      }
+    }
   }
 
-  void writeTypeParameterElements(List<TypeParameterElement> elements) {
+  void writeTypeParameterElements(
+    List<TypeParameterElement> elements, {
+    @required bool withDefault,
+  }) {
     if (!withFullyResolvedAst) {
-      writeList('<', '>', elements, ', ', writeTypeParameterElement);
+      writeList('<', '>', elements, ', ', (e) {
+        writeTypeParameterElement(e, withDefault: withDefault);
+      });
     }
   }
 
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 210f03a..77e7e0e 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -1289,7 +1289,7 @@
 ''');
     checkElementText(library, r'''
 notSimplyBounded typedef F = dynamic Function(C<dynamic> value);
-notSimplyBounded class C<T extends dynamic Function(C<dynamic>)> {
+notSimplyBounded class C<T extends dynamic Function(C<dynamic>) = dynamic Function(C<dynamic>)> {
 }
 ''');
   }
@@ -1301,7 +1301,7 @@
 class C<T extends C<dynamic>> {}
 ''');
     checkElementText(library, r'''
-class C<T extends C<dynamic>> {
+class C<T extends C<dynamic> = C<dynamic>> {
 }
 ''');
   }
@@ -1325,7 +1325,7 @@
 class D<T extends D> {}
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends D<dynamic>> {
+notSimplyBounded class C<T extends D<dynamic> = D<dynamic>> {
 }
 notSimplyBounded class D<T extends D<dynamic>> {
 }
@@ -1338,7 +1338,7 @@
 class D<T> {}
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends D<T>> {
+notSimplyBounded class C<T extends D<T> = D<dynamic>> {
 }
 class D<T> {
 }
@@ -1353,9 +1353,9 @@
 class D<T extends D<T>> {}
 ''');
     checkElementText(library, r'''
-class C<T extends D<dynamic>> {
+class C<T extends D<dynamic> = D<dynamic>> {
 }
-notSimplyBounded class D<T extends D<T>> {
+notSimplyBounded class D<T extends D<T> = D<dynamic>> {
 }
 ''');
   }
@@ -1365,7 +1365,7 @@
 class C<T extends void Function(T)> {}
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends void Function(T)> {
+notSimplyBounded class C<T extends void Function(T) = void Function(Null)> {
 }
 ''');
   }
@@ -1375,7 +1375,7 @@
 class C<T extends T Function()> {}
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends T Function()> {
+notSimplyBounded class C<T extends T Function() = dynamic Function()> {
 }
 ''');
   }
@@ -1385,7 +1385,7 @@
 class C<T extends void Function()> {}
 ''');
     checkElementText(library, r'''
-class C<T extends void Function()> {
+class C<T extends void Function() = void Function()> {
 }
 ''');
   }
@@ -1402,7 +1402,7 @@
     checkElementText(library, r'''
 notSimplyBounded typedef F = dynamic Function(dynamic Function(dynamic) value);
 notSimplyBounded typedef G = dynamic Function(dynamic value);
-notSimplyBounded class C<T extends dynamic Function(dynamic Function(dynamic))> {
+notSimplyBounded class C<T extends dynamic Function(dynamic Function(dynamic)) = dynamic Function(dynamic Function(dynamic))> {
 }
 ''');
   }
@@ -1435,7 +1435,7 @@
 class D<T> {}
 ''');
     checkElementText(library, r'''
-class C<T extends D<dynamic>> {
+class C<T extends D<dynamic> = D<dynamic>> {
 }
 class D<T> {
 }
@@ -1675,7 +1675,7 @@
 class D {}
 ''');
     checkElementText(library, r'''
-class C<T, U extends D> {
+class C<T = Object, U extends D = D> {
 }
 class D {
 }
@@ -1709,7 +1709,7 @@
   test_class_type_parameters_f_bound_complex() async {
     var library = await checkLibrary('class C<T extends List<U>, U> {}');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends List<U>, U> {
+notSimplyBounded class C<T extends List<U> = List<dynamic>, U> {
 }
 ''');
   }
@@ -7468,7 +7468,7 @@
 }
 class B extends A {
 }
-class S<T extends A> {
+class S<T extends A = A> {
   S(T _);
 }
 S<B> s;
@@ -8140,7 +8140,7 @@
 C c;
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<S extends num, T extends C<S, T>> {
+notSimplyBounded class C<S extends num = num, T extends C<S, T> = C<num, dynamic>> {
 }
 C<num, C<num, dynamic>> c;
 ''');
@@ -8156,7 +8156,7 @@
 }
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends C<T>> {
+notSimplyBounded class C<T extends C<T> = C<dynamic>> {
 }
 class B {
   C<C<dynamic>> c3;
@@ -8172,7 +8172,7 @@
 C c;
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends C<T, U>, U extends num> {
+notSimplyBounded class C<T extends C<T, U> = C<dynamic, num>, U extends num = num> {
 }
 C<C<dynamic, num>, num> c;
 ''');
@@ -8206,7 +8206,7 @@
 F f;
 ''');
     checkElementText(library, r'''
-typedef F<T extends num> = dynamic Function(T p);
+typedef F<T extends num = num> = dynamic Function(T p);
 dynamic Function(num) f;
 ''');
   }
@@ -8220,7 +8220,7 @@
     checkElementText(library, r'''
 class A<T> {
 }
-notSimplyBounded class B<T extends int Function(), U extends A<T>> {
+notSimplyBounded class B<T extends int Function() = int Function(), U extends A<T> = A<int Function()>> {
 }
 B<int Function(), A<int Function()>> b;
 ''');
@@ -8232,7 +8232,7 @@
 F f;
 ''');
     checkElementText(library, r'''
-typedef F<T extends num> = S Function<S>(T p);
+typedef F<T extends num = num> = S Function<S>(T p);
 S Function<S>(num) f;
 ''');
   }
@@ -8245,10 +8245,10 @@
 class B<T extends num> {}
 ''');
     checkElementText(library, r'''
-class A<R extends B<num>> {
+class A<R extends B<num> = B<num>> {
   final List<B<num>> values;
 }
-class B<T extends num> {
+class B<T extends num = num> {
 }
 ''');
   }
@@ -8259,7 +8259,7 @@
 C c;
 ''');
     checkElementText(library, r'''
-class C<T extends num> {
+class C<T extends num = num> {
 }
 C<num> c;
 ''');
@@ -9625,7 +9625,7 @@
 }
 class D {
 }
-mixin M<T extends num, U> on A, B implements C, D {
+mixin M<T extends num = num, U> on A, B implements C, D {
   T f;
   U get g {}
   void set s(int v) {}
@@ -10780,7 +10780,7 @@
 }
 class B extends A {
 }
-class C<T extends A> {
+class C<T extends A = A> {
   final T f;
   const C(T this.f);
 }
@@ -11289,7 +11289,7 @@
 ''');
     checkElementText(library, r'''
 notSimplyBounded typedef F = void Function(C<C<dynamic>> c);
-notSimplyBounded class C<T extends C<T>> {
+notSimplyBounded class C<T extends C<T> = C<dynamic>> {
 }
 ''');
   }
@@ -11303,7 +11303,7 @@
 ''');
     checkElementText(library, r'''
 notSimplyBounded typedef F = void Function(C<C<dynamic>> );
-notSimplyBounded class C<T extends C<T>> {
+notSimplyBounded class C<T extends C<T> = C<dynamic>> {
 }
 ''');
   }
@@ -11317,7 +11317,7 @@
 ''');
     checkElementText(library, r'''
 notSimplyBounded typedef F = void Function(C<C<dynamic>> c);
-notSimplyBounded class C<T extends C<T>> {
+notSimplyBounded class C<T extends C<T> = C<dynamic>> {
 }
 ''');
   }
@@ -11331,7 +11331,7 @@
 ''');
     checkElementText(library, r'''
 notSimplyBounded typedef F = C<C<dynamic>> Function();
-notSimplyBounded class C<T extends C<T>> {
+notSimplyBounded class C<T extends C<T> = C<dynamic>> {
 }
 ''');
   }
@@ -11345,7 +11345,7 @@
 ''');
     checkElementText(library, r'''
 notSimplyBounded typedef F = C<C<dynamic>> Function();
-notSimplyBounded class C<T extends C<T>> {
+notSimplyBounded class C<T extends C<T> = C<dynamic>> {
 }
 ''');
   }
@@ -11438,7 +11438,7 @@
     var library = await checkLibrary(
         'typedef U F<T extends Object, U extends D>(T t); class D {}');
     checkElementText(library, r'''
-typedef F<T, U extends D> = U Function(T t);
+typedef F<T = Object, U extends D = D> = U Function(T t);
 class D {
 }
 ''');
@@ -11463,7 +11463,7 @@
   test_typedef_type_parameters_f_bound_complex() async {
     var library = await checkLibrary('typedef U F<T extends List<U>, U>(T t);');
     checkElementText(library, r'''
-notSimplyBounded typedef F<T extends List<U>, U> = U Function(T t);
+notSimplyBounded typedef F<T extends List<U> = List<dynamic>, U> = U Function(T t);
 ''');
   }