Support for TypeParameter metadata.

R=brianwilkerson@google.com

Change-Id: Id0d0b9018538986787832c8001c6aa43c6bec380
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99733
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/summary2/lazy_ast.dart b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
index 17723b5..b423a53 100644
--- a/pkg/analyzer/lib/src/summary2/lazy_ast.dart
+++ b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
@@ -1178,6 +1178,7 @@
   final LinkedNode data;
 
   bool _hasBound = false;
+  bool _hasMetadata = false;
 
   LazyTypeParameter(this.data);
 
@@ -1193,6 +1194,21 @@
     }
   }
 
+  static void readMetadata(
+    AstBinaryReader reader,
+    TypeParameter node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasMetadata) {
+      var dataList = lazy.data.annotatedNode_metadata;
+      for (var i = 0; i < dataList.length; ++i) {
+        var data = dataList[i];
+        node.metadata[i] = reader.readNode(data);
+      }
+      lazy._hasMetadata = true;
+    }
+  }
+
   static void setData(TypeParameter node, LinkedNode data) {
     node.setProperty(_key, LazyTypeParameter(data));
   }
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 36c9d9d..63ad562 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -367,6 +367,9 @@
     } else if (node is MixinDeclaration) {
       LazyMixinDeclaration.readMetadata(_astReader, node);
       return node.metadata;
+    } else if (node is TypeParameter) {
+      LazyTypeParameter.readMetadata(_astReader, node);
+      return node.metadata;
     } else if (node is VariableDeclaration) {
       var parent2 = node.parent.parent;
       if (parent2 is FieldDeclaration) {
diff --git a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
index b84fef0..562af3dd 100644
--- a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
@@ -173,8 +173,12 @@
   }
 
   @override
+  void visitTypeParameter(TypeParameter node) {
+    node.metadata.accept(this);
+  }
+
+  @override
   void visitTypeParameterList(TypeParameterList node) {
-    // TODO: implement visitTypeParameterList
-//    super.visitTypeParameterList(node);
+    node.typeParameters.accept(this);
   }
 }
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 61c752d..c383abb 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -915,6 +915,7 @@
   }
 
   void writeTypeParameterElement(TypeParameterElement e) {
+    writeMetadata(e, '', '\n');
     writeName(e);
     writeCodeRange(e);
     if (e.bound != null && !e.bound.isObject) {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 274cb6a..d87436d 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -7997,7 +7997,9 @@
   test_metadata_typeParameter_ofClass() async {
     var library = await checkLibrary('const a = null; class C<@a T> {}');
     checkElementText(library, r'''
-class C<T> {
+class C<@
+        a/*location: test.dart;a?*/
+T> {
 }
 const dynamic a = null;
 ''');
@@ -8010,7 +8012,9 @@
 class D {}
 class E {}''');
     checkElementText(library, r'''
-class alias C<T> extends D with E {
+class alias C<@
+        a/*location: test.dart;a?*/
+T> extends D with E {
   synthetic C() = D;
 }
 class D {
@@ -8025,14 +8029,18 @@
     var library = await checkLibrary('const a = null; f<@a T>() {}');
     checkElementText(library, r'''
 const dynamic a = null;
-dynamic f<T>() {}
+dynamic f<@
+        a/*location: test.dart;a?*/
+T>() {}
 ''');
   }
 
   test_metadata_typeParameter_ofTypedef() async {
     var library = await checkLibrary('const a = null; typedef F<@a T>();');
     checkElementText(library, r'''
-typedef F<T> = dynamic Function();
+typedef F<@
+        a/*location: test.dart;a?*/
+T> = dynamic Function();
 const dynamic a = null;
 ''');
   }