Serialize metadata for enum constants.

R=brianwilkerson@google.com, paulberry@google.com

Change-Id: Iee11718d5c8ea6256a2a54772b12acc5bf8b5214
Reviewed-on: https://dart-review.googlesource.com/59361
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 1bde05f..542ee6a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -95,7 +95,7 @@
   /**
    * The version of data format, should be incremented on every format change.
    */
-  static const int DATA_VERSION = 60;
+  static const int DATA_VERSION = 61;
 
   /**
    * The number of exception contexts allowed to write. Once this field is
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index fdf5e48..8916caf 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -7238,11 +7238,23 @@
 class UnlinkedEnumValueBuilder extends Object
     with _UnlinkedEnumValueMixin
     implements idl.UnlinkedEnumValue {
+  List<UnlinkedExprBuilder> _annotations;
   UnlinkedDocumentationCommentBuilder _documentationComment;
   String _name;
   int _nameOffset;
 
   @override
+  List<UnlinkedExprBuilder> get annotations =>
+      _annotations ??= <UnlinkedExprBuilder>[];
+
+  /**
+   * Annotations for this value.
+   */
+  void set annotations(List<UnlinkedExprBuilder> value) {
+    this._annotations = value;
+  }
+
+  @override
   UnlinkedDocumentationCommentBuilder get documentationComment =>
       _documentationComment;
 
@@ -7276,10 +7288,12 @@
   }
 
   UnlinkedEnumValueBuilder(
-      {UnlinkedDocumentationCommentBuilder documentationComment,
+      {List<UnlinkedExprBuilder> annotations,
+      UnlinkedDocumentationCommentBuilder documentationComment,
       String name,
       int nameOffset})
-      : _documentationComment = documentationComment,
+      : _annotations = annotations,
+        _documentationComment = documentationComment,
         _name = name,
         _nameOffset = nameOffset;
 
@@ -7287,6 +7301,7 @@
    * Flush [informative] data recursively.
    */
   void flushInformative() {
+    _annotations?.forEach((b) => b.flushInformative());
     _documentationComment = null;
     _nameOffset = null;
   }
@@ -7296,11 +7311,24 @@
    */
   void collectApiSignature(api_sig.ApiSignature signature) {
     signature.addString(this._name ?? '');
+    if (this._annotations == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._annotations.length);
+      for (var x in this._annotations) {
+        x?.collectApiSignature(signature);
+      }
+    }
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_annotations;
     fb.Offset offset_documentationComment;
     fb.Offset offset_name;
+    if (!(_annotations == null || _annotations.isEmpty)) {
+      offset_annotations = fbBuilder
+          .writeList(_annotations.map((b) => b.finish(fbBuilder)).toList());
+    }
     if (_documentationComment != null) {
       offset_documentationComment = _documentationComment.finish(fbBuilder);
     }
@@ -7308,6 +7336,9 @@
       offset_name = fbBuilder.writeString(_name);
     }
     fbBuilder.startTable();
+    if (offset_annotations != null) {
+      fbBuilder.addOffset(3, offset_annotations);
+    }
     if (offset_documentationComment != null) {
       fbBuilder.addOffset(2, offset_documentationComment);
     }
@@ -7337,11 +7368,20 @@
 
   _UnlinkedEnumValueImpl(this._bc, this._bcOffset);
 
+  List<idl.UnlinkedExpr> _annotations;
   idl.UnlinkedDocumentationComment _documentationComment;
   String _name;
   int _nameOffset;
 
   @override
+  List<idl.UnlinkedExpr> get annotations {
+    _annotations ??=
+        const fb.ListReader<idl.UnlinkedExpr>(const _UnlinkedExprReader())
+            .vTableGet(_bc, _bcOffset, 3, const <idl.UnlinkedExpr>[]);
+    return _annotations;
+  }
+
+  @override
   idl.UnlinkedDocumentationComment get documentationComment {
     _documentationComment ??= const _UnlinkedDocumentationCommentReader()
         .vTableGet(_bc, _bcOffset, 2, null);
@@ -7365,6 +7405,9 @@
   @override
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
+    if (annotations.isNotEmpty)
+      _result["annotations"] =
+          annotations.map((_value) => _value.toJson()).toList();
     if (documentationComment != null)
       _result["documentationComment"] = documentationComment.toJson();
     if (name != '') _result["name"] = name;
@@ -7374,6 +7417,7 @@
 
   @override
   Map<String, Object> toMap() => {
+        "annotations": annotations,
         "documentationComment": documentationComment,
         "name": name,
         "nameOffset": nameOffset,
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 2b752f0..54b21e9 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -2042,6 +2042,11 @@
  */
 table UnlinkedEnumValue {
   /**
+   * Annotations for this value.
+   */
+  annotations:[UnlinkedExpr] (id: 3);
+
+  /**
    * Documentation comment for the enum value, or `null` if there is no
    * documentation comment.
    */
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 49b3d3e..343740b 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -1660,6 +1660,12 @@
  */
 abstract class UnlinkedEnumValue extends base.SummaryClass {
   /**
+   * Annotations for this value.
+   */
+  @Id(3)
+  List<UnlinkedExpr> get annotations;
+
+  /**
    * Documentation comment for the enum value, or `null` if there is no
    * documentation comment.
    */
diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
index ea0c328..156b98df 100644
--- a/pkg/analyzer/lib/src/summary/summarize_ast.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
@@ -580,6 +580,18 @@
   }
 
   /**
+   * Serialize an [EnumConstantDeclaration] into an [UnlinkedEnumValue].
+   */
+  UnlinkedEnumValueBuilder serializeEnumConstantDeclaration(
+      EnumConstantDeclaration node) {
+    return new UnlinkedEnumValueBuilder(
+        annotations: serializeAnnotations(node.metadata),
+        documentationComment: serializeDocumentation(node.documentationComment),
+        name: node.name.name,
+        nameOffset: node.name.offset);
+  }
+
+  /**
    * Serialize a [FunctionDeclaration] or [MethodDeclaration] into an
    * [UnlinkedExecutable].
    *
@@ -1134,13 +1146,7 @@
     UnlinkedEnumBuilder b = new UnlinkedEnumBuilder();
     b.name = node.name.name;
     b.nameOffset = node.name.offset;
-    b.values = node.constants
-        .map((EnumConstantDeclaration value) => new UnlinkedEnumValueBuilder(
-            documentationComment:
-                serializeDocumentation(value.documentationComment),
-            name: value.name.name,
-            nameOffset: value.name.offset))
-        .toList();
+    b.values = node.constants.map(serializeEnumConstantDeclaration).toList();
     b.documentationComment = serializeDocumentation(node.documentationComment);
     b.annotations = serializeAnnotations(node.metadata);
     b.codeRange = serializeCodeRange(node);
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index 37b5eca..0f78b0f 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -8674,6 +8674,12 @@
         .annotations);
   }
 
+  test_metadata_enumConstantDeclaration() {
+    checkAnnotationA(serializeEnumText('const a = null; enum E { @a v }')
+        .values[0]
+        .annotations);
+  }
+
   test_metadata_enumDeclaration() {
     checkAnnotationA(
         serializeEnumText('const a = null; @a enum E { v }').annotations);