Add MetadataAnnotation class and metadata fields to relevant objects

Bug: https://github.com/dart-lang/language/issues/1930
Change-Id: I3ba6facd4c0487b0af18108c8d1db21ee6d5a498
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/313640
Auto-Submit: Jake Macdonald <jakemac@google.com>
Reviewed-by: Bob Nystrom <rnystrom@google.com>
Commit-Queue: Jake Macdonald <jakemac@google.com>
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
index c30d1a5..fed1e65 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
@@ -9,6 +9,11 @@
 /// Could be a [Declaration] or [Library].
 abstract interface class MacroTarget {}
 
+/// The interface for things that can be annotated with [MetadataAnnotation]s.
+abstract interface class Annotatable {
+  Iterable<MetadataAnnotation> get metadata;
+}
+
 /// A concrete reference to a named declaration, which may or may not yet be
 /// resolved.
 ///
@@ -100,7 +105,7 @@
 abstract interface class NamedStaticType implements StaticType {}
 
 /// The interface for all declarations.
-abstract interface class Declaration implements MacroTarget {
+abstract interface class Declaration implements Annotatable, MacroTarget {
   /// The library in which this declaration is defined.
   Library get library;
 
@@ -297,7 +302,7 @@
 
 /// General parameter introspection information, see the subtypes
 /// [FunctionTypeParameter] and [ParameterDeclaration].
-abstract interface class Parameter {
+abstract interface class Parameter implements Annotatable {
   /// The type of this parameter.
   TypeAnnotation get type;
 
@@ -356,7 +361,7 @@
 }
 
 /// Introspection information for a Library.
-abstract interface class Library implements MacroTarget {
+abstract interface class Library implements Annotatable, MacroTarget {
   /// The language version of this library.
   LanguageVersion get languageVersion;
 
@@ -371,3 +376,26 @@
 
   int get minor;
 }
+
+/// A metadata annotation on a declaration or library directive.
+abstract interface class MetadataAnnotation {}
+
+/// A [MetadataAnnotation] which is a reference to a const value.
+abstract interface class IdentifierMetadataAnnotation
+    implements MetadataAnnotation {
+  /// The [Identifier] for the const reference.
+  Identifier get identifier;
+}
+
+/// A [Metadata] annotation which is a constructor call.
+abstract interface class ConstructorMetadataAnnotation
+    implements MetadataAnnotation {
+  /// And [Identifier] referring to the type that is being constructed.
+  Identifier get type;
+
+  /// An [Identifier] referring to the specific constructor being called.
+  ///
+  /// For unnamed constructors, the name of this identifier will be the empty
+  /// String.
+  Identifier get constructor;
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/introspection_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/introspection_impls.dart
index 4b57086..2f2b3f4 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/introspection_impls.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/introspection_impls.dart
@@ -158,6 +158,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     required this.name,
     required this.type,
   });
@@ -253,6 +254,56 @@
   RemoteInstanceKind get kind => RemoteInstanceKind.omittedTypeAnnotation;
 }
 
+abstract class MetadataAnnotationImpl extends RemoteInstance
+    implements MetadataAnnotation {
+  MetadataAnnotationImpl(super.id);
+}
+
+class IdentifierMetadataAnnotationImpl extends MetadataAnnotationImpl
+    implements IdentifierMetadataAnnotation {
+  @override
+  final IdentifierImpl identifier;
+
+  @override
+  RemoteInstanceKind get kind =>
+      RemoteInstanceKind.identifierMetadataAnnotation;
+
+  IdentifierMetadataAnnotationImpl({required int id, required this.identifier})
+      : super(id);
+
+  @override
+  void serializeUncached(Serializer serializer) {
+    super.serializeUncached(serializer);
+
+    identifier.serialize(serializer);
+  }
+}
+
+class ConstructorMetadataAnnotationImpl extends MetadataAnnotationImpl
+    implements ConstructorMetadataAnnotation {
+  @override
+  final IdentifierImpl constructor;
+
+  @override
+  final IdentifierImpl type;
+
+  @override
+  RemoteInstanceKind get kind =>
+      RemoteInstanceKind.constructorMetadataAnnotation;
+
+  ConstructorMetadataAnnotationImpl(
+      {required int id, required this.constructor, required this.type})
+      : super(id);
+
+  @override
+  void serializeUncached(Serializer serializer) {
+    super.serializeUncached(serializer);
+
+    constructor.serialize(serializer);
+    type.serialize(serializer);
+  }
+}
+
 abstract class DeclarationImpl extends RemoteInstance implements Declaration {
   @override
   final IdentifierImpl identifier;
@@ -260,10 +311,14 @@
   @override
   final LibraryImpl library;
 
+  @override
+  final List<MetadataAnnotationImpl> metadata;
+
   DeclarationImpl({
     required int id,
     required this.identifier,
     required this.library,
+    required this.metadata,
   }) : super(id);
 
   @override
@@ -272,6 +327,11 @@
 
     identifier.serialize(serializer);
     library.serialize(serializer);
+    serializer.startList();
+    for (MetadataAnnotationImpl annotation in metadata) {
+      annotation.serialize(serializer);
+    }
+    serializer.endList();
   }
 }
 
@@ -293,6 +353,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     required this.isNamed,
     required this.isRequired,
     required this.type,
@@ -323,6 +384,9 @@
   final bool isRequired;
 
   @override
+  final List<MetadataAnnotationImpl> metadata;
+
+  @override
   final String? name;
 
   @override
@@ -335,6 +399,7 @@
     required int id,
     required this.isNamed,
     required this.isRequired,
+    required this.metadata,
     required this.name,
     required this.type,
   }) : super(id);
@@ -345,6 +410,12 @@
 
     serializer.addBool(isNamed);
     serializer.addBool(isRequired);
+
+    serializer.startList();
+    for (MetadataAnnotationImpl annotation in metadata) {
+      annotation.serialize(serializer);
+    }
+    serializer.endList();
     serializer.addNullableString(name);
     type.serialize(serializer);
   }
@@ -368,6 +439,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     required this.bound,
   });
 
@@ -424,6 +496,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     required this.isAbstract,
     required this.isExternal,
     required this.isGetter,
@@ -481,6 +554,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     // Function fields.
     required super.isAbstract,
     required super.isExternal,
@@ -518,6 +592,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     // Function fields.
     required super.isAbstract,
     required super.isExternal,
@@ -565,6 +640,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     required this.isExternal,
     required this.isFinal,
     required this.isLate,
@@ -596,6 +672,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     // Variable fields.
     required super.isExternal,
     required super.isFinal,
@@ -630,6 +707,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     required this.typeParameters,
   });
 
@@ -695,6 +773,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     // TypeDeclaration fields.
     required super.typeParameters,
     // ClassDeclaration fields.
@@ -762,6 +841,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     // TypeDeclaration fields.
     required super.typeParameters,
     // EnumDeclaration fields.
@@ -799,6 +879,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     required this.definingEnum,
   });
 
@@ -836,6 +917,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     // TypeDeclaration fields.
     required super.typeParameters,
     // MixinDeclaration fields.
@@ -878,6 +960,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     // TypeDeclaration fields.
     required super.typeParameters,
     // TypeAlias fields.
@@ -900,10 +983,16 @@
   final LanguageVersionImpl languageVersion;
 
   @override
+  final List<MetadataAnnotationImpl> metadata;
+
+  @override
   final Uri uri;
 
   LibraryImpl(
-      {required int id, required this.languageVersion, required this.uri})
+      {required int id,
+      required this.languageVersion,
+      required this.metadata,
+      required this.uri})
       : super(id);
 
   @override
@@ -911,6 +1000,11 @@
     super.serializeUncached(serializer);
 
     languageVersion.serialize(serializer);
+    serializer.startList();
+    for (MetadataAnnotationImpl annotation in metadata) {
+      annotation.serialize(serializer);
+    }
+    serializer.endList();
     serializer.addUri(uri);
   }
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/remote_instance.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/remote_instance.dart
index fb2e565..871b211 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/remote_instance.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/remote_instance.dart
@@ -101,6 +101,7 @@
 enum RemoteInstanceKind {
   classDeclaration,
   constructorDeclaration,
+  constructorMetadataAnnotation,
   enumDeclaration,
   enumValueDeclaration,
   fieldDeclaration,
@@ -108,6 +109,7 @@
   functionTypeAnnotation,
   functionTypeParameter,
   identifier,
+  identifierMetadataAnnotation,
   identifierResolver,
   introspectableClassDeclaration,
   introspectableEnumDeclaration,
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/serialization_extensions.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/serialization_extensions.dart
index c9e5347..6f500dc 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/serialization_extensions.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/serialization_extensions.dart
@@ -29,6 +29,8 @@
         new RemoteInstanceImpl(id: id, kind: kind),
       RemoteInstanceKind.classDeclaration =>
         (this..moveNext())._expectClassDeclaration(id),
+      RemoteInstanceKind.constructorMetadataAnnotation =>
+        (this..moveNext())._expectConstructorMetadataAnnotation(id),
       RemoteInstanceKind.enumDeclaration =>
         (this..moveNext())._expectEnumDeclaration(id),
       RemoteInstanceKind.enumValueDeclaration =>
@@ -46,6 +48,8 @@
       RemoteInstanceKind.functionTypeParameter =>
         (this..moveNext())._expectFunctionTypeParameter(id),
       RemoteInstanceKind.identifier => (this..moveNext())._expectIdentifier(id),
+      RemoteInstanceKind.identifierMetadataAnnotation =>
+        (this..moveNext())._expectIdentifierMetadataAnnotation(id),
       RemoteInstanceKind.introspectableClassDeclaration =>
         (this..moveNext())._expectIntrospectableClassDeclaration(id),
       RemoteInstanceKind.introspectableEnumDeclaration =>
@@ -117,6 +121,7 @@
         id: id,
         isNamed: expectBool(),
         isRequired: (this..moveNext()).expectBool(),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         name: (this..moveNext()).expectNullableString(),
         type: RemoteInstance.deserialize(this),
       );
@@ -131,6 +136,7 @@
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         isNamed: (this..moveNext()).expectBool(),
         isRequired: (this..moveNext()).expectBool(),
         type: RemoteInstance.deserialize(this),
@@ -141,6 +147,7 @@
           id: id,
           identifier: expectRemoteInstance(),
           library: RemoteInstance.deserialize(this),
+          metadata: (this..moveNext())._expectRemoteInstanceList(),
           name: (this..moveNext()).expectNullableString(),
           type: (this..moveNext()).expectRemoteInstance());
 
@@ -157,6 +164,7 @@
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         bound: (this..moveNext()).checkNull() ? null : expectRemoteInstance(),
       );
 
@@ -165,6 +173,7 @@
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         isAbstract: (this..moveNext()).expectBool(),
         isExternal: (this..moveNext()).expectBool(),
         isGetter: (this..moveNext()).expectBool(),
@@ -181,6 +190,7 @@
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         isAbstract: (this..moveNext()).expectBool(),
         isExternal: (this..moveNext()).expectBool(),
         isGetter: (this..moveNext()).expectBool(),
@@ -199,6 +209,7 @@
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         isAbstract: (this..moveNext()).expectBool(),
         isExternal: (this..moveNext()).expectBool(),
         isGetter: (this..moveNext()).expectBool(),
@@ -223,6 +234,7 @@
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         isExternal: (this..moveNext()).expectBool(),
         isFinal: (this..moveNext()).expectBool(),
         isLate: (this..moveNext()).expectBool(),
@@ -234,6 +246,7 @@
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         isExternal: (this..moveNext()).expectBool(),
         isFinal: (this..moveNext()).expectBool(),
         isLate: (this..moveNext()).expectBool(),
@@ -247,6 +260,7 @@
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         typeParameters: (this..moveNext())._expectRemoteInstanceList(),
         interfaces: (this..moveNext())._expectRemoteInstanceList(),
         hasAbstract: (this..moveNext()).expectBool(),
@@ -261,12 +275,27 @@
             (this..moveNext()).checkNull() ? null : expectRemoteInstance(),
       );
 
+  ConstructorMetadataAnnotationImpl _expectConstructorMetadataAnnotation(
+          int id) =>
+      new ConstructorMetadataAnnotationImpl(
+          id: id,
+          constructor: expectRemoteInstance(),
+          type: RemoteInstance.deserialize(this));
+
+  IdentifierMetadataAnnotationImpl _expectIdentifierMetadataAnnotation(
+          int id) =>
+      new IdentifierMetadataAnnotationImpl(
+        id: id,
+        identifier: expectRemoteInstance(),
+      );
+
   IntrospectableClassDeclarationImpl _expectIntrospectableClassDeclaration(
           int id) =>
       new IntrospectableClassDeclarationImpl(
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         typeParameters: (this..moveNext())._expectRemoteInstanceList(),
         interfaces: (this..moveNext())._expectRemoteInstanceList(),
         hasAbstract: (this..moveNext()).expectBool(),
@@ -285,6 +314,7 @@
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         typeParameters: (this..moveNext())._expectRemoteInstanceList(),
         interfaces: (this..moveNext())._expectRemoteInstanceList(),
         mixins: (this..moveNext())._expectRemoteInstanceList(),
@@ -296,6 +326,7 @@
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         typeParameters: (this..moveNext())._expectRemoteInstanceList(),
         interfaces: (this..moveNext())._expectRemoteInstanceList(),
         mixins: (this..moveNext())._expectRemoteInstanceList(),
@@ -306,6 +337,7 @@
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         typeParameters: (this..moveNext())._expectRemoteInstanceList(),
         hasBase: (this..moveNext()).expectBool(),
         interfaces: (this..moveNext())._expectRemoteInstanceList(),
@@ -318,6 +350,7 @@
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         typeParameters: (this..moveNext())._expectRemoteInstanceList(),
         hasBase: (this..moveNext()).expectBool(),
         interfaces: (this..moveNext())._expectRemoteInstanceList(),
@@ -329,6 +362,7 @@
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         definingEnum: RemoteInstance.deserialize(this),
       );
 
@@ -337,6 +371,7 @@
         id: id,
         identifier: expectRemoteInstance(),
         library: RemoteInstance.deserialize(this),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         typeParameters: (this..moveNext())._expectRemoteInstanceList(),
         aliasedType: RemoteInstance.deserialize(this),
       );
@@ -345,6 +380,7 @@
         id: id,
         languageVersion: new LanguageVersionImpl(
             this.expectInt(), (this..moveNext()).expectInt()),
+        metadata: (this..moveNext())._expectRemoteInstanceList(),
         uri: (this..moveNext()).expectUri(),
       );
 
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart
index 1bde42d..b08a640 100644
--- a/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart
@@ -33,6 +33,7 @@
               id: RemoteInstance.uniqueId,
               identifier: identifier,
               library: Fixtures.library,
+              metadata: [],
               typeParameters: [],
               interfaces: [],
               hasAbstract: false,
@@ -331,6 +332,7 @@
             uri: Uri.parse('a.dart'),
             staticScope: null),
         library: Fixtures.library,
+        metadata: [],
         typeParameters: [],
         interfaces: [],
         mixins: [],
@@ -344,6 +346,7 @@
               uri: Uri.parse('a.dart'),
               staticScope: null),
           library: Fixtures.library,
+          metadata: [],
           definingType: myEnum.identifier,
           isExternal: false,
           isFinal: true,
@@ -395,6 +398,7 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'MyClass'),
             library: Fixtures.library,
+            metadata: [],
             typeParameters: [],
             interfaces: [],
             hasAbstract: hasKeywords,
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor/serialization_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor/serialization_test.dart
index 7836a1b..65c6863 100644
--- a/pkg/_fe_analyzer_shared/test/macros/executor/serialization_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/executor/serialization_test.dart
@@ -161,11 +161,13 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'foo'),
             library: Fixtures.library,
+            metadata: [],
             type: fooType);
         final fooNamedFunctionTypeParam = FunctionTypeParameterImpl(
             id: RemoteInstance.uniqueId,
             isNamed: true,
             isRequired: true,
+            metadata: [],
             name: 'foo',
             type: fooType);
 
@@ -176,11 +178,13 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
             library: Fixtures.library,
+            metadata: [],
             type: barType);
         final barPositionalFunctionTypeParam = FunctionTypeParameterImpl(
             id: RemoteInstance.uniqueId,
             isNamed: true,
             isRequired: true,
+            metadata: [],
             name: 'bar',
             type: fooType);
 
@@ -188,6 +192,7 @@
             id: RemoteInstance.uniqueId,
             isNamed: true,
             isRequired: true,
+            metadata: [],
             name: null,
             type: fooType);
 
@@ -196,6 +201,7 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Zap'),
             library: Fixtures.library,
+            metadata: [],
             bound: barType);
 
         // Transitively tests `TypeParameterDeclaration` and
@@ -222,6 +228,7 @@
               identifier:
                   IdentifierImpl(id: RemoteInstance.uniqueId, name: 'name'),
               library: Fixtures.library,
+              metadata: [],
               isAbstract: true,
               isExternal: false,
               isGetter: true,
@@ -241,6 +248,7 @@
               identifier:
                   IdentifierImpl(id: RemoteInstance.uniqueId, name: 'zorp'),
               library: Fixtures.library,
+              metadata: [],
               isAbstract: false,
               isExternal: false,
               isGetter: false,
@@ -262,6 +270,7 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'new'),
             library: Fixtures.library,
+            metadata: [],
             isAbstract: false,
             isExternal: false,
             isGetter: false,
@@ -284,6 +293,7 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
             library: Fixtures.library,
+            metadata: [],
             isExternal: true,
             isFinal: false,
             isLate: true,
@@ -299,6 +309,7 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
             library: Fixtures.library,
+            metadata: [],
             isExternal: false,
             isFinal: true,
             isLate: false,
@@ -332,6 +343,7 @@
               identifier:
                   IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
               library: Fixtures.library,
+              metadata: [],
               interfaces: [barType],
               hasAbstract: boolValue,
               hasBase: boolValue,
@@ -355,6 +367,7 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'MyEnum'),
             library: Fixtures.library,
+            metadata: [],
             interfaces: [barType],
             mixins: [serializableType],
             typeParameters: [zapTypeParam],
@@ -368,6 +381,7 @@
             id: RemoteInstance.uniqueId,
             identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'a'),
             library: Fixtures.library,
+            metadata: [],
             definingEnum:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'MyEnum'),
           );
@@ -382,6 +396,7 @@
               identifier:
                   IdentifierImpl(id: RemoteInstance.uniqueId, name: 'MyMixin'),
               library: Fixtures.library,
+              metadata: [],
               hasBase: base,
               interfaces: [barType],
               superclassConstraints: [serializableType],
@@ -398,6 +413,7 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'FooOfBar'),
             library: Fixtures.library,
+            metadata: [],
             typeParameters: [zapTypeParam],
             aliasedType: NamedTypeAnnotationImpl(
                 id: RemoteInstance.uniqueId,
@@ -421,6 +437,7 @@
                 identifier:
                     IdentifierImpl(id: RemoteInstance.uniqueId, name: r'hello'),
                 library: Fixtures.library,
+                metadata: [],
                 name: 'hello',
                 type: barType,
               ),
@@ -431,6 +448,7 @@
                 identifier:
                     IdentifierImpl(id: RemoteInstance.uniqueId, name: r'$1'),
                 library: Fixtures.library,
+                metadata: [],
                 name: null,
                 type: fooType,
               ),
@@ -572,6 +590,34 @@
       }
     });
   });
+
+  group('metadata annotations can be serialized and deserialized', () {
+    for (var mode in [SerializationMode.byteData, SerializationMode.json]) {
+      group('with mode $mode', () {
+        test('identifiers', () {
+          final identifierMetadata = IdentifierMetadataAnnotationImpl(
+              id: RemoteInstance.uniqueId,
+              identifier: IdentifierImpl(
+                  id: RemoteInstance.uniqueId, name: 'singleton'));
+
+          expectSerializationEquality<IdentifierMetadataAnnotationImpl>(
+              identifierMetadata, mode, RemoteInstance.deserialize);
+        });
+
+        test('constructor invocations', () {
+          final constructorMetadata = ConstructorMetadataAnnotationImpl(
+              id: RemoteInstance.uniqueId,
+              type: IdentifierImpl(
+                  id: RemoteInstance.uniqueId, name: 'Singleton'),
+              constructor: IdentifierImpl(
+                  id: RemoteInstance.uniqueId, name: 'someName'));
+
+          expectSerializationEquality<ConstructorMetadataAnnotationImpl>(
+              constructorMetadata, mode, RemoteInstance.deserialize);
+        });
+      });
+    }
+  });
 }
 
 /// Serializes [serializable] in server mode, then deserializes it in client
@@ -600,6 +646,8 @@
             TypeAnnotation() =>
               deepEqualsTypeAnnotation(deserialized as TypeAnnotation),
             Arguments() => deepEqualsArguments(deserialized),
+            MetadataAnnotation() =>
+              deepEqualsMetadataAnnotation(deserialized as MetadataAnnotation),
             _ => throw new UnsupportedError(
                 'Unsupported object type $deserialized'),
           });
diff --git a/pkg/_fe_analyzer_shared/test/macros/util.dart b/pkg/_fe_analyzer_shared/test/macros/util.dart
index fc559ec..ea9b249 100644
--- a/pkg/_fe_analyzer_shared/test/macros/util.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/util.dart
@@ -196,6 +196,10 @@
 Matcher deepEqualsArguments(Arguments arguments) =>
     _DeepEqualityMatcher(arguments);
 
+/// Checks if two [MetadataAnnotation]s are identical
+Matcher deepEqualsMetadataAnnotation(MetadataAnnotation metadata) =>
+    _DeepEqualityMatcher(metadata);
+
 /// Checks if two [Declaration]s, [TypeAnnotation]s, or [Code] objects are of
 /// the same type and all their fields are equal.
 class _DeepEqualityMatcher extends Matcher {
@@ -213,7 +217,9 @@
     if (!equals(item.runtimeType).matches(instance.runtimeType, matchState)) {
       return false;
     }
-    if (instance is Declaration || instance is TypeAnnotation) {
+    if (instance is Declaration ||
+        instance is TypeAnnotation ||
+        instance is MetadataAnnotation) {
       var instanceReflector = reflect(instance);
       var itemReflector = reflect(item);
 
@@ -285,6 +291,7 @@
   static final library = LibraryImpl(
       id: RemoteInstance.uniqueId,
       languageVersion: LanguageVersionImpl(3, 0),
+      metadata: [],
       uri: Uri.parse('package:foo/bar.dart'));
   static final nullableBoolType = NamedTypeAnnotationImpl(
       id: RemoteInstance.uniqueId,
@@ -311,6 +318,7 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'world'),
             library: Fixtures.library,
+            metadata: [],
             name: 'world',
             type: stringType),
       ],
@@ -320,6 +328,7 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: r'$1'),
             library: Fixtures.library,
+            metadata: [],
             name: null,
             type: stringType),
         RecordFieldDeclarationImpl(
@@ -327,6 +336,7 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: r'$2'),
             library: Fixtures.library,
+            metadata: [],
             name: 'hello',
             type: nullableBoolType),
       ]);
@@ -337,6 +347,7 @@
       identifier:
           IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myFunction'),
       library: Fixtures.library,
+      metadata: [],
       isAbstract: false,
       isExternal: false,
       isGetter: false,
@@ -351,6 +362,7 @@
       identifier:
           IdentifierImpl(id: RemoteInstance.uniqueId, name: '_myVariable'),
       library: Fixtures.library,
+      metadata: [],
       isExternal: false,
       isFinal: true,
       isLate: false,
@@ -360,6 +372,7 @@
       identifier:
           IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myVariable'),
       library: Fixtures.library,
+      metadata: [],
       isAbstract: false,
       isExternal: false,
       isGetter: true,
@@ -374,6 +387,7 @@
       identifier:
           IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myVariable'),
       library: Fixtures.library,
+      metadata: [],
       isAbstract: false,
       isExternal: false,
       isGetter: false,
@@ -386,6 +400,7 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'value'),
             library: Fixtures.library,
+            metadata: [],
             isNamed: false,
             isRequired: true,
             type: stringType)
@@ -397,6 +412,7 @@
       id: RemoteInstance.uniqueId,
       identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'library'),
       library: Fixtures.library,
+      metadata: [],
       isExternal: false,
       isFinal: true,
       isLate: false,
@@ -434,6 +450,7 @@
       id: RemoteInstance.uniqueId,
       identifier: myClassType.identifier,
       library: Fixtures.library,
+      metadata: [],
       typeParameters: [],
       interfaces: [myInterfaceType],
       hasAbstract: false,
@@ -450,6 +467,7 @@
       identifier:
           IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myConstructor'),
       library: Fixtures.library,
+      metadata: [],
       isAbstract: false,
       isExternal: false,
       isGetter: false,
@@ -462,6 +480,7 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myField'),
             library: Fixtures.library,
+            metadata: [],
             isNamed: false,
             isRequired: true,
             type: TestOmittedTypeAnnotation(myField.type))
@@ -474,6 +493,7 @@
       id: RemoteInstance.uniqueId,
       identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myField'),
       library: Fixtures.library,
+      metadata: [],
       isExternal: false,
       isFinal: false,
       isLate: false,
@@ -484,6 +504,7 @@
       id: RemoteInstance.uniqueId,
       identifier: myInterfaceType.identifier,
       library: Fixtures.library,
+      metadata: [],
       typeParameters: [],
       interfaces: [],
       hasAbstract: false,
@@ -499,6 +520,7 @@
       id: RemoteInstance.uniqueId,
       identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myMethod'),
       library: Fixtures.library,
+      metadata: [],
       isAbstract: false,
       isExternal: false,
       isGetter: false,
@@ -514,6 +536,7 @@
       id: RemoteInstance.uniqueId,
       identifier: mySuperclassType.identifier,
       library: Fixtures.library,
+      metadata: [],
       typeParameters: [],
       interfaces: [],
       hasAbstract: false,
@@ -538,6 +561,7 @@
       id: RemoteInstance.uniqueId,
       identifier: myEnumType.identifier,
       library: Fixtures.library,
+      metadata: [],
       typeParameters: [],
       interfaces: [],
       mixins: []);
@@ -546,6 +570,7 @@
       id: RemoteInstance.uniqueId,
       identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'a'),
       library: Fixtures.library,
+      metadata: [],
       definingEnum: myEnum.identifier,
     ),
   ];
@@ -554,6 +579,7 @@
       identifier: IdentifierImpl(
           id: RemoteInstance.uniqueId, name: 'myEnumConstructor'),
       library: Fixtures.library,
+      metadata: [],
       isAbstract: false,
       isExternal: false,
       isGetter: false,
@@ -566,6 +592,7 @@
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myField'),
             library: Fixtures.library,
+            metadata: [],
             isNamed: false,
             isRequired: true,
             type: stringType)
@@ -579,6 +606,7 @@
     id: RemoteInstance.uniqueId,
     identifier: myMixinType.identifier,
     library: Fixtures.library,
+    metadata: [],
     typeParameters: [],
     hasBase: false,
     interfaces: [],
@@ -589,6 +617,7 @@
       identifier:
           IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myMixinMethod'),
       library: Fixtures.library,
+      metadata: [],
       isAbstract: false,
       isExternal: false,
       isGetter: false,
diff --git a/pkg/analyzer/lib/src/summary2/macro_declarations.dart b/pkg/analyzer/lib/src/summary2/macro_declarations.dart
index 2c6ec24..cd11c2b 100644
--- a/pkg/analyzer/lib/src/summary2/macro_declarations.dart
+++ b/pkg/analyzer/lib/src/summary2/macro_declarations.dart
@@ -19,6 +19,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     required super.typeParameters,
     required super.interfaces,
     required super.hasAbstract,
@@ -102,6 +103,8 @@
           id: macro.RemoteInstance.uniqueId,
           languageVersion:
               macro.LanguageVersionImpl(version.major, version.minor),
+          // TODO: Provide metadata annotations.
+          metadata: const [],
           uri: element.library!.source.uri,
           element: element);
       _libraryMap[element.library!] = library;
@@ -143,6 +146,8 @@
       id: macro.RemoteInstance.uniqueId,
       identifier: identifier(element),
       library: library(element),
+      // TODO: Provide metadata annotations.
+      metadata: const [],
       isExternal: element.isExternal,
       isFinal: element.isFinal,
       isLate: element.isLate,
@@ -159,6 +164,8 @@
       id: macro.RemoteInstance.uniqueId,
       identifier: identifier(element),
       library: library(element),
+      // TODO: Provide metadata annotations.
+      metadata: const [],
       typeParameters: element.typeParameters.map(_typeParameter).toList(),
       interfaces: element.interfaces
           .map(_dartType)
@@ -187,6 +194,8 @@
       id: macro.RemoteInstance.uniqueId,
       identifier: identifier(element),
       library: library(element),
+      // TODO: Provide metadata annotations.
+      metadata: const [],
       bound: element.bound.mapOrNull(_dartType),
     );
   }
@@ -215,6 +224,8 @@
           id: macro.RemoteInstance.uniqueId,
           languageVersion:
               macro.LanguageVersionImpl(version.major, version.minor),
+          // TODO: Provide metadata annotations.
+          metadata: const [],
           uri: element.library!.source.uri,
           element: element);
       _libraryMap[element.library!] = library;
@@ -249,6 +260,8 @@
       isNamed: node.isNamed,
       isRequired: node.isRequired,
       name: node.name?.lexeme,
+      // TODO: Provide metadata annotations.
+      metadata: const [],
       type: typeAnnotation,
     );
   }
@@ -261,6 +274,8 @@
       id: macro.RemoteInstance.uniqueId,
       identifier: _declaredIdentifier(node.name, node.declaredElement!),
       library: library(node.declaredElement!),
+      // TODO: Provide metadata annotations.
+      metadata: const [],
       typeParameters: _typeParameters(node.typeParameters),
       interfaces: _typeAnnotations(node.implementsClause?.interfaces),
       hasAbstract: node.abstractKeyword != null,
@@ -336,6 +351,8 @@
       id: macro.RemoteInstance.uniqueId,
       identifier: _declaredIdentifier(node.name, node.declaredElement!),
       library: library(node.declaredElement!),
+      // TODO: Provide metadata annotations.
+      metadata: const [],
       bound: node.bound.mapOrNull(_typeAnnotation),
     );
   }
@@ -356,6 +373,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     required super.isExternal,
     required super.isFinal,
     required super.isLate,
@@ -393,6 +411,7 @@
     required super.id,
     required super.identifier,
     required super.library,
+    required super.metadata,
     required super.typeParameters,
     required super.interfaces,
     required super.hasAbstract,
@@ -411,6 +430,7 @@
   LibraryImpl({
     required super.id,
     required super.languageVersion,
+    required super.metadata,
     required super.uri,
   });
 
@@ -424,6 +444,7 @@
   LibraryImplFromElement({
     required super.id,
     required super.languageVersion,
+    required super.metadata,
     required super.uri,
     required this.element,
   });
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro/macro.dart
index 22870cb..91143f0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro/macro.dart
@@ -803,7 +803,9 @@
           id: macro.RemoteInstance.uniqueId,
           uri: builder.importUri,
           languageVersion:
-              new macro.LanguageVersionImpl(version.major, version.minor));
+              new macro.LanguageVersionImpl(version.major, version.minor),
+          // TODO: Provide metadata annotations.
+          metadata: const []);
     }();
   }
 
@@ -849,6 +851,8 @@
                 id: macro.RemoteInstance.uniqueId,
                 identifier: identifier,
                 library: library,
+                // TODO: Provide metadata annotations.
+                metadata: const [],
                 typeParameters: typeParameters,
                 hasBase: builder.isBase,
                 interfaces: interfaces,
@@ -861,6 +865,8 @@
             id: macro.RemoteInstance.uniqueId,
             identifier: identifier,
             library: library,
+            // TODO: Provide metadata annotations.
+            metadata: const [],
             typeParameters: typeParameters,
             interfaces: interfaces,
             hasAbstract: builder.isAbstract,
@@ -891,6 +897,8 @@
             id: macro.RemoteInstance.uniqueId,
             name: builder.name),
         library: library,
+        // TODO: Provide metadata annotations.
+        metadata: const [],
         // TODO(johnniwinther): Support typeParameters
         typeParameters: [],
         aliasedType:
@@ -921,6 +929,8 @@
             id: macro.RemoteInstance.uniqueId,
             identifier: identifier,
             library: library,
+            // TODO: Provide metadata annotations.
+            metadata: const [],
             isRequired: formal.isRequiredNamed,
             isNamed: true,
             type: type,
@@ -930,6 +940,8 @@
             id: macro.RemoteInstance.uniqueId,
             identifier: identifier,
             library: library,
+            // TODO: Provide metadata annotations.
+            metadata: const [],
             isRequired: formal.isRequiredPositional,
             isNamed: false,
             type: type,
@@ -958,6 +970,8 @@
           id: macro.RemoteInstance.uniqueId,
           name: builder.name),
       library: _libraryFor(builder.libraryBuilder),
+      // TODO: Provide metadata annotations.
+      metadata: const [],
       definingType: definingClass.identifier as macro.IdentifierImpl,
       isFactory: builder.isFactory,
       isAbstract: builder.isAbstract,
@@ -988,6 +1002,8 @@
           id: macro.RemoteInstance.uniqueId,
           name: builder.name),
       library: _libraryFor(builder.libraryBuilder),
+      // TODO: Provide metadata annotations.
+      metadata: const [],
       definingType: definingClass.identifier as macro.IdentifierImpl,
       isFactory: builder.isFactory,
       isAbstract: builder.isAbstract,
@@ -1025,6 +1041,8 @@
               id: macro.RemoteInstance.uniqueId,
               name: builder.name),
           library: library,
+          // TODO: Provide metadata annotations.
+          metadata: const [],
           definingType: definingClass.identifier as macro.IdentifierImpl,
           isAbstract: builder.isAbstract,
           isExternal: builder.isExternal,
@@ -1046,6 +1064,8 @@
               id: macro.RemoteInstance.uniqueId,
               name: builder.name),
           library: library,
+          // TODO: Provide metadata annotations.
+          metadata: const [],
           isAbstract: builder.isAbstract,
           isExternal: builder.isExternal,
           isGetter: builder.isGetter,
@@ -1078,6 +1098,8 @@
               id: macro.RemoteInstance.uniqueId,
               name: builder.name),
           library: library,
+          // TODO: Provide metadata annotations.
+          metadata: const [],
           definingType: definingClass.identifier as macro.IdentifierImpl,
           isExternal: builder.isExternal,
           isFinal: builder.isFinal,
@@ -1092,6 +1114,8 @@
               id: macro.RemoteInstance.uniqueId,
               name: builder.name),
           library: library,
+          // TODO: Provide metadata annotations.
+          metadata: const [],
           isExternal: builder.isExternal,
           isFinal: builder.isFinal,
           isLate: builder.isLate,