Fine. Record and match metadata for top-level and members.

Change-Id: I5462888530294394383462b17c3039a54a16a2ae
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/420461
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 716992e..e26eada 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3028,7 +3028,7 @@
     _metadata = metadata;
   }
 
-  Metadata get metadata2 => MetadataImpl(_getMetadataFlags(), metadata);
+  MetadataImpl get metadata2 => MetadataImpl(_getMetadataFlags(), metadata);
 
   @override
   String? get name => _name;
@@ -3613,6 +3613,9 @@
   List<FormalParameterElementMixin> get formalParameters;
 
   @override
+  MetadataImpl get metadata2;
+
+  @override
   TypeImpl get returnType;
 
   @override
@@ -5787,7 +5790,7 @@
   LibraryElementImpl get library2 => firstFragment.library;
 
   @override
-  Metadata get metadata2 => firstFragment.metadata2;
+  MetadataImpl get metadata2 => firstFragment.metadata2;
 
   @override
   List<MethodElementImpl2> get methods2 {
@@ -7799,7 +7802,7 @@
   bool get isStatic => _wrappedElement.isStatic;
 
   @override
-  Metadata get metadata2 => _wrappedElement.metadata2;
+  MetadataImpl get metadata2 => _wrappedElement.metadata2;
 
   @override
   TypeImpl get returnType => _wrappedElement.returnType;
@@ -10341,6 +10344,9 @@
   GetterElement2OrMember? get getter2;
 
   @override
+  MetadataImpl get metadata2;
+
+  @override
   SetterElement2OrMember? get setter2;
 }
 
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 6821861..0b17580 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -942,7 +942,7 @@
   @override
   List<ElementAnnotation> get metadata => _declaration.metadata;
 
-  Metadata get metadata2 => declaration.metadata2;
+  MetadataImpl get metadata2 => declaration.metadata2;
 
   @override
   String? get name => _declaration.name;
diff --git a/pkg/analyzer/lib/src/fine/library_manifest.dart b/pkg/analyzer/lib/src/fine/library_manifest.dart
index 33e5c92..438245a 100644
--- a/pkg/analyzer/lib/src/fine/library_manifest.dart
+++ b/pkg/analyzer/lib/src/fine/library_manifest.dart
@@ -309,6 +309,9 @@
         }
         manifest.items[name] = ExportItem(
           id: id,
+          // TODO(scheglov): Exports should not be items at all.
+          // We should have a separate map of names to IDs.
+          metadata: ManifestMetadata(annotations: []),
         );
       }
     }
diff --git a/pkg/analyzer/lib/src/fine/manifest_item.dart b/pkg/analyzer/lib/src/fine/manifest_item.dart
index 153a7d8..a20041e 100644
--- a/pkg/analyzer/lib/src/fine/manifest_item.dart
+++ b/pkg/analyzer/lib/src/fine/manifest_item.dart
@@ -13,9 +13,26 @@
 import 'package:analyzer/src/summary2/data_writer.dart';
 import 'package:analyzer/src/utilities/extensions/collection.dart';
 
+// TODO(scheglov): inline into ManifestItem when remove ExportItem
+sealed class AnnotatedItem extends ManifestItem {
+  final ManifestMetadata metadata;
+
+  AnnotatedItem({
+    required super.id,
+    required this.metadata,
+  });
+
+  @override
+  void write(BufferedSink sink) {
+    super.write(sink);
+    metadata.write(sink);
+  }
+}
+
 class ClassItem extends InterfaceItem {
   ClassItem({
     required super.id,
+    required super.metadata,
     required super.typeParameters,
     required super.supertype,
     required super.interfaces,
@@ -33,6 +50,7 @@
       (typeParameters) {
         return ClassItem(
           id: id,
+          metadata: ManifestMetadata.encode(context, element.metadata2),
           typeParameters: typeParameters,
           supertype: element.supertype?.encode(context),
           mixins: element.mixins.encode(context),
@@ -46,6 +64,7 @@
   factory ClassItem.read(SummaryDataReader reader) {
     return ClassItem(
       id: ManifestItemId.read(reader),
+      metadata: ManifestMetadata.read(reader),
       typeParameters: ManifestTypeParameter.readList(reader),
       members: InstanceItem._readMembers(reader),
       supertype: ManifestType.readOptional(reader),
@@ -68,11 +87,13 @@
 class ExportItem extends TopLevelItem {
   ExportItem({
     required super.id,
+    required super.metadata,
   });
 
   factory ExportItem.read(SummaryDataReader reader) {
     return ExportItem(
       id: ManifestItemId.read(reader),
+      metadata: ManifestMetadata.read(reader),
     );
   }
 
@@ -90,6 +111,7 @@
 
   InstanceItem({
     required super.id,
+    required super.metadata,
     required this.typeParameters,
     required this.members,
   });
@@ -120,6 +142,7 @@
 
   InstanceItemGetterItem({
     required super.id,
+    required super.metadata,
     required super.isStatic,
     required this.returnType,
   });
@@ -131,6 +154,7 @@
   }) {
     return InstanceItemGetterItem(
       id: id,
+      metadata: ManifestMetadata.encode(context, element.metadata2),
       isStatic: element.isStatic,
       returnType: element.returnType.encode(context),
     );
@@ -139,6 +163,7 @@
   factory InstanceItemGetterItem.read(SummaryDataReader reader) {
     return InstanceItemGetterItem(
       id: ManifestItemId.read(reader),
+      metadata: ManifestMetadata.read(reader),
       isStatic: reader.readBool(),
       returnType: ManifestType.read(reader),
     );
@@ -149,6 +174,9 @@
     GetterElement2OrMember element,
   ) {
     var context = MatchContext(parent: instanceContext);
+    if (!metadata.match(context, element.metadata2)) {
+      return null;
+    }
     if (element.isStatic != isStatic) {
       return null;
     }
@@ -166,11 +194,12 @@
   }
 }
 
-sealed class InstanceItemMemberItem extends ManifestItem {
+sealed class InstanceItemMemberItem extends AnnotatedItem {
   final bool isStatic;
 
   InstanceItemMemberItem({
     required super.id,
+    required super.metadata,
     required this.isStatic,
   });
 
@@ -198,6 +227,7 @@
 
   InstanceItemMethodItem({
     required super.id,
+    required super.metadata,
     required super.isStatic,
     required this.functionType,
   });
@@ -209,6 +239,7 @@
   }) {
     return InstanceItemMethodItem(
       id: id,
+      metadata: ManifestMetadata.encode(context, element.metadata2),
       isStatic: element.isStatic,
       functionType: element.type.encode(context),
     );
@@ -217,6 +248,7 @@
   factory InstanceItemMethodItem.read(SummaryDataReader reader) {
     return InstanceItemMethodItem(
       id: ManifestItemId.read(reader),
+      metadata: ManifestMetadata.read(reader),
       isStatic: reader.readBool(),
       functionType: ManifestFunctionType.read(reader),
     );
@@ -227,6 +259,9 @@
     MethodElement2OrMember element,
   ) {
     var context = MatchContext(parent: instanceContext);
+    if (!metadata.match(context, element.metadata2)) {
+      return null;
+    }
     if (element.isStatic != isStatic) {
       return null;
     }
@@ -252,6 +287,7 @@
 
   InterfaceItem({
     required super.id,
+    required super.metadata,
     required super.typeParameters,
     required super.members,
     required this.supertype,
@@ -269,6 +305,11 @@
 
   MatchContext? _matchInterfaceElement(InterfaceElementImpl2 element) {
     var context = MatchContext(parent: null);
+
+    if (!metadata.match(context, element.metadata2)) {
+      return null;
+    }
+
     context.addTypeParameters(element.typeParameters2);
     if (supertype.match(context, element.supertype) &&
         interfaces.match(context, element.interfaces) &&
@@ -286,6 +327,7 @@
 
   InterfaceItemConstructorItem({
     required super.id,
+    required super.metadata,
     required super.isStatic,
     required this.isConst,
     required this.isFactory,
@@ -300,6 +342,7 @@
     // TODO(scheglov): initializers
     return InterfaceItemConstructorItem(
       id: id,
+      metadata: ManifestMetadata.encode(context, element.metadata2),
       isStatic: false,
       isConst: element.isConst,
       isFactory: element.isFactory,
@@ -310,6 +353,7 @@
   factory InterfaceItemConstructorItem.read(SummaryDataReader reader) {
     return InterfaceItemConstructorItem(
       id: ManifestItemId.read(reader),
+      metadata: ManifestMetadata.read(reader),
       isStatic: reader.readBool(),
       isConst: reader.readBool(),
       isFactory: reader.readBool(),
@@ -322,6 +366,9 @@
     ConstructorElementImpl2 element,
   ) {
     var context = MatchContext(parent: instanceContext);
+    if (!metadata.match(context, element.metadata2)) {
+      return null;
+    }
     if (isConst != element.isConst) {
       return null;
     }
@@ -443,6 +490,7 @@
 
   TopLevelFunctionItem({
     required super.id,
+    required super.metadata,
     required this.functionType,
   });
 
@@ -453,6 +501,7 @@
   }) {
     return TopLevelFunctionItem(
       id: id,
+      metadata: ManifestMetadata.encode(context, element.metadata2),
       functionType: element.type.encode(context),
     );
   }
@@ -460,6 +509,7 @@
   factory TopLevelFunctionItem.read(SummaryDataReader reader) {
     return TopLevelFunctionItem(
       id: ManifestItemId.read(reader),
+      metadata: ManifestMetadata.read(reader),
       functionType: ManifestFunctionType.read(reader),
     );
   }
@@ -468,6 +518,11 @@
     TopLevelFunctionElementImpl element,
   ) {
     var context = MatchContext(parent: null);
+
+    if (!metadata.match(context, element.metadata2)) {
+      return null;
+    }
+
     if (!functionType.match(context, element.type)) {
       return null;
     }
@@ -484,13 +539,12 @@
 }
 
 class TopLevelGetterItem extends TopLevelItem {
-  final ManifestMetadata metadata;
   final ManifestType returnType;
   final ManifestNode? constInitializer;
 
   TopLevelGetterItem({
     required super.id,
-    required this.metadata,
+    required super.metadata,
     required this.returnType,
     required this.constInitializer,
   });
@@ -502,7 +556,10 @@
   }) {
     return TopLevelGetterItem(
       id: id,
-      metadata: ManifestMetadata.encode(context, element.metadata2),
+      metadata: ManifestMetadata.encode(
+        context,
+        element.thisOrVariableMetadata,
+      ),
       returnType: element.returnType.encode(context),
       constInitializer: element.constInitializer?.encode(context),
     );
@@ -520,7 +577,7 @@
   MatchContext? match(GetterElementImpl element) {
     var context = MatchContext(parent: null);
 
-    if (!metadata.match(context, element.metadata2)) {
+    if (!metadata.match(context, element.thisOrVariableMetadata)) {
       return null;
     }
 
@@ -539,15 +596,15 @@
   void write(BufferedSink sink) {
     sink.writeEnum(_ManifestItemKind.topLevelGetter);
     super.write(sink);
-    metadata.write(sink);
     returnType.write(sink);
     constInitializer.writeOptional(sink);
   }
 }
 
-sealed class TopLevelItem extends ManifestItem {
+sealed class TopLevelItem extends AnnotatedItem {
   TopLevelItem({
     required super.id,
+    required super.metadata,
   });
 
   factory TopLevelItem.read(SummaryDataReader reader) {
@@ -568,12 +625,11 @@
 }
 
 class TopLevelSetterItem extends TopLevelItem {
-  final ManifestMetadata metadata;
   final ManifestType valueType;
 
   TopLevelSetterItem({
     required super.id,
-    required this.metadata,
+    required super.metadata,
     required this.valueType,
   });
 
@@ -584,7 +640,10 @@
   }) {
     return TopLevelSetterItem(
       id: id,
-      metadata: ManifestMetadata.encode(context, element.metadata2),
+      metadata: ManifestMetadata.encode(
+        context,
+        element.thisOrVariableMetadata,
+      ),
       valueType: element.formalParameters[0].type.encode(context),
     );
   }
@@ -600,7 +659,7 @@
   MatchContext? match(SetterElementImpl element) {
     var context = MatchContext(parent: null);
 
-    if (!metadata.match(context, element.metadata2)) {
+    if (!metadata.match(context, element.thisOrVariableMetadata)) {
       return null;
     }
 
@@ -615,7 +674,6 @@
   void write(BufferedSink sink) {
     sink.writeEnum(_ManifestItemKind.topLevelSetter);
     super.write(sink);
-    metadata.write(sink);
     valueType.write(sink);
   }
 }
@@ -651,3 +709,13 @@
     return null;
   }
 }
+
+extension _PropertyAccessExtension on PropertyAccessorElement2OrMember {
+  MetadataImpl get thisOrVariableMetadata {
+    if (isSynthetic) {
+      return variable3!.metadata2;
+    } else {
+      return metadata2;
+    }
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 01ca5b4..42c93fc 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -8236,6 +8236,44 @@
     );
   }
 
+  test_manifest_class_constructor_metadata() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  @Deprected('0')
+  A.foo();
+  @Deprected('0')
+  A.bar();
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        bar: #M1
+        foo: #M2
+''',
+      updatedCode: r'''
+class A {
+  @Deprected('1')
+  A.foo();
+  @Deprected('0')
+  A.bar();
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        bar: #M1
+        foo: #M3
+''',
+    );
+  }
+
   test_manifest_class_constructor_private() async {
     await _runLibraryManifestScenario(
       initialCode: r'''
@@ -8474,6 +8512,44 @@
     );
   }
 
+  test_manifest_class_getter_metadata() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  @Deprecated('0')
+  int get foo => 0;
+  @Deprecated('0')
+  int get bar => 0;
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        bar: #M1
+        foo: #M2
+''',
+      updatedCode: r'''
+class A {
+  @Deprecated('1')
+  int get foo => 0;
+  @Deprecated('0')
+  int get bar => 0;
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        bar: #M1
+        foo: #M3
+''',
+    );
+  }
+
   test_manifest_class_getter_private_instance() async {
     await _runLibraryManifestScenario(
       initialCode: r'''
@@ -8783,6 +8859,38 @@
     );
   }
 
+  test_manifest_class_metadata() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+@Deprecated('0')
+class A {}
+@Deprecated('0')
+class B {}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+      B: #M1
+''',
+      updatedCode: r'''
+@Deprecated('0')
+class A {}
+@Deprecated('1')
+class B {}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+      B: #M2
+''',
+    );
+  }
+
   test_manifest_class_method_add() async {
     await _runLibraryManifestScenario(
       initialCode: r'''
@@ -9156,6 +9264,44 @@
     );
   }
 
+  test_manifest_class_method_metadata() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  @Deprecated('0')
+  void foo() {}
+  @Deprecated('0')
+  void bar() {}
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        bar: #M1
+        foo: #M2
+''',
+      updatedCode: r'''
+class A {
+  @Deprecated('1')
+  void foo() {}
+  @Deprecated('0')
+  void bar() {}
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        bar: #M1
+        foo: #M3
+''',
+    );
+  }
+
   test_manifest_class_method_private_instance() async {
     await _runLibraryManifestScenario(
       initialCode: r'''
@@ -10979,6 +11125,38 @@
     );
   }
 
+  test_manifest_topLevelFunction_metadata() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+@Deprected('0')
+void a() {}
+@Deprected('0')
+void b() {}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      a: #M0
+      b: #M1
+''',
+      updatedCode: r'''
+@Deprected('0')
+void a() {}
+@Deprected('1')
+void b() {}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      a: #M0
+      b: #M2
+''',
+    );
+  }
+
   test_manifest_topLevelFunction_private() async {
     await _runLibraryManifestScenario(
       initialCode: r'''
@@ -11175,6 +11353,38 @@
     );
   }
 
+  test_manifest_topLevelGetter_metadata() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+@Deprecated('0')
+int get a => 0;
+@Deprecated('0')
+int get b => 0;
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      a: #M0
+      b: #M1
+''',
+      updatedCode: r'''
+@Deprecated('0')
+int get a => 0;
+@Deprecated('1')
+int get b => 0;
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      a: #M0
+      b: #M2
+''',
+    );
+  }
+
   test_manifest_topLevelGetter_private() async {
     await _runLibraryManifestScenario(
       initialCode: r'''
@@ -11273,6 +11483,38 @@
     );
   }
 
+  test_manifest_topLevelSetter_metadata() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+@Deprecated('0')
+set a(int _) {}
+@Deprecated('0')
+set b(int _) {}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      a=: #M0
+      b=: #M1
+''',
+      updatedCode: r'''
+@Deprecated('0')
+set a(int _) {}
+@Deprecated('1')
+set b(int _) {}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      a=: #M0
+      b=: #M2
+''',
+    );
+  }
+
   test_manifest_topLevelSetter_valueType() async {
     configuration.withElementManifests = true;
     await _runLibraryManifestScenario(
@@ -11398,6 +11640,42 @@
     );
   }
 
+  test_manifest_topLevelVariable_metadata() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+@Deprecated('0')
+var a = 0;
+@Deprecated('0')
+var b = 0;
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      a: #M0
+      a=: #M1
+      b: #M2
+      b=: #M3
+''',
+      updatedCode: r'''
+@Deprecated('0')
+var a = 0;
+@Deprecated('1')
+var b = 0;
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      a: #M0
+      a=: #M1
+      b: #M4
+      b=: #M5
+''',
+    );
+  }
+
   test_manifest_topLevelVariable_private_const() async {
     await _runLibraryManifestScenario(
       initialCode: r'''
diff --git a/pkg/analyzer/test/src/dart/analysis/result_printer.dart b/pkg/analyzer/test/src/dart/analysis/result_printer.dart
index 6e3118ae..edcd9bd 100644
--- a/pkg/analyzer/test/src/dart/analysis/result_printer.dart
+++ b/pkg/analyzer/test/src/dart/analysis/result_printer.dart
@@ -753,6 +753,7 @@
   void _writeClassItem(ClassItem item) {
     if (configuration.withElementManifests) {
       sink.withIndent(() {
+        _writeMetadata(item);
         _writeTypeParameters(item.typeParameters);
         _writeNamedType('supertype', item.supertype);
       });
@@ -779,10 +780,13 @@
       sink.withIndent(() {
         switch (item) {
           case InstanceItemGetterItem():
+            _writeMetadata(item);
             _writeNamedType('returnType', item.returnType);
           case InstanceItemMethodItem():
+            _writeMetadata(item);
             _writeNamedType('functionType', item.functionType);
           case InterfaceItemConstructorItem():
+            _writeMetadata(item);
             _writeNamedType('functionType', item.functionType);
         }
       });
@@ -799,6 +803,18 @@
     sink.writeln('(${parts.join(', ')}) $idStr');
   }
 
+  void _writeMetadata(AnnotatedItem item) {
+    if (configuration.withElementManifests) {
+      sink.writeElements(
+        'metadata',
+        item.metadata.annotations.indexed.toList(),
+        (indexed) {
+          _writeNode('[${indexed.$1}]', indexed.$2.ast);
+        },
+      );
+    }
+  }
+
   void _writeNamedId(LookupName name, ManifestItemId id) {
     var idStr = idProvider.manifestId(id);
     sink.writelnWithIndent('$name: $idStr');
@@ -840,6 +856,7 @@
   void _writeTopLevelFunctionItem(TopLevelFunctionItem item) {
     if (configuration.withElementManifests) {
       sink.withIndent(() {
+        _writeMetadata(item);
         _writeNamedType('functionType', item.functionType);
       });
     }
@@ -848,6 +865,7 @@
   void _writeTopLevelGetterItem(TopLevelGetterItem item) {
     if (configuration.withElementManifests) {
       sink.withIndent(() {
+        _writeMetadata(item);
         _writeNamedType('returnType', item.returnType);
         _writeNode('constInitializer', item.constInitializer);
       });
@@ -857,6 +875,7 @@
   void _writeTopLevelSetterItem(TopLevelSetterItem item) {
     if (configuration.withElementManifests) {
       sink.withIndent(() {
+        _writeMetadata(item);
         _writeNamedType('valueType', item.valueType);
       });
     }