[pigeon] Add documentation comment support for Enum members (#2924)

* [pigeon] Add documentation comment support for Enum members

* [pigeon] Bump version
diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md
index b6e036a..ce7e6f6 100644
--- a/packages/pigeon/CHANGELOG.md
+++ b/packages/pigeon/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 4.2.13
+
+* Add documentation comment support for Enum members.
+
 ## 4.2.12
 
 * Updates serialization to use lists instead of maps to improve performance.
diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart
index 6db4a5e..8da2b74 100644
--- a/packages/pigeon/lib/ast.dart
+++ b/packages/pigeon/lib/ast.dart
@@ -242,7 +242,7 @@
   String name;
 
   /// All of the members of the enum.
-  List<String> members;
+  List<EnumMember> members;
 
   /// List of documentation comments, seperated by line.
   ///
@@ -257,6 +257,30 @@
   }
 }
 
+/// Represents a Enum member.
+class EnumMember extends Node {
+  /// Parametric constructor for [EnumMember].
+  EnumMember({
+    required this.name,
+    this.documentationComments = const <String>[],
+  });
+
+  /// The name of the enum member.
+  final String name;
+
+  /// List of documentation comments, seperated by line.
+  ///
+  /// Lines should not include the comment marker itself, but should include any
+  /// leading whitespace, so that any indentation in the original comment is preserved.
+  /// For example: [" List of documentation comments, separated by line.", ...]
+  final List<String> documentationComments;
+
+  @override
+  String toString() {
+    return '(EnumMember name:$name documentationComments:$documentationComments)';
+  }
+}
+
 /// Top-level node for the AST.
 class Root extends Node {
   /// Parametric constructor for [Root].
diff --git a/packages/pigeon/lib/cpp_generator.dart b/packages/pigeon/lib/cpp_generator.dart
index 565c0ba..e06d5d1 100644
--- a/packages/pigeon/lib/cpp_generator.dart
+++ b/packages/pigeon/lib/cpp_generator.dart
@@ -1059,9 +1059,11 @@
         indent, anEnum.documentationComments, _docCommentSpec);
     indent.write('enum class ${anEnum.name} ');
     indent.scoped('{', '};', () {
-      enumerate(anEnum.members, (int index, final String member) {
+      enumerate(anEnum.members, (int index, final EnumMember member) {
+        addDocumentationComments(
+            indent, member.documentationComments, _docCommentSpec);
         indent.writeln(
-            '$member = $index${index == anEnum.members.length - 1 ? '' : ','}');
+            '${member.name} = $index${index == anEnum.members.length - 1 ? '' : ','}');
       });
     });
   }
diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart
index 3edbe68..85956ce 100644
--- a/packages/pigeon/lib/dart_generator.dart
+++ b/packages/pigeon/lib/dart_generator.dart
@@ -482,8 +482,10 @@
           indent, anEnum.documentationComments, _docCommentSpec);
       indent.write('enum ${anEnum.name} ');
       indent.scoped('{', '}', () {
-        for (final String member in anEnum.members) {
-          indent.writeln('$member,');
+        for (final EnumMember member in anEnum.members) {
+          addDocumentationComments(
+              indent, member.documentationComments, _docCommentSpec);
+          indent.writeln('${member.name},');
         }
       });
     }
diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart
index 9ef102a..8140cbb 100644
--- a/packages/pigeon/lib/generator_tools.dart
+++ b/packages/pigeon/lib/generator_tools.dart
@@ -9,7 +9,7 @@
 import 'ast.dart';
 
 /// The current version of pigeon. This must match the version in pubspec.yaml.
-const String pigeonVersion = '4.2.12';
+const String pigeonVersion = '4.2.13';
 
 /// Read all the content from [stdin] to a String.
 String readStdin() {
diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart
index 4292e9c..c52d976 100644
--- a/packages/pigeon/lib/java_generator.dart
+++ b/packages/pigeon/lib/java_generator.dart
@@ -569,9 +569,11 @@
 
     indent.write('public enum ${anEnum.name} ');
     indent.scoped('{', '}', () {
-      enumerate(anEnum.members, (int index, final String member) {
+      enumerate(anEnum.members, (int index, final EnumMember member) {
+        addDocumentationComments(
+            indent, member.documentationComments, _docCommentSpec);
         indent.writeln(
-            '${camelToSnake(member)}($index)${index == anEnum.members.length - 1 ? ';' : ','}');
+            '${camelToSnake(member.name)}($index)${index == anEnum.members.length - 1 ? ';' : ','}');
       });
       indent.writeln('');
       indent.writeln('private final int index;');
diff --git a/packages/pigeon/lib/kotlin_generator.dart b/packages/pigeon/lib/kotlin_generator.dart
index c32cb04..1f52d3d 100644
--- a/packages/pigeon/lib/kotlin_generator.dart
+++ b/packages/pigeon/lib/kotlin_generator.dart
@@ -471,8 +471,10 @@
         indent, anEnum.documentationComments, _docCommentSpec);
     indent.write('enum class ${anEnum.name}(val raw: Int) ');
     indent.scoped('{', '}', () {
-      enumerate(anEnum.members, (int index, final String member) {
-        indent.write('${member.toUpperCase()}($index)');
+      enumerate(anEnum.members, (int index, final EnumMember member) {
+        addDocumentationComments(
+            indent, member.documentationComments, _docCommentSpec);
+        indent.write('${member.name.toUpperCase()}($index)');
         if (index != anEnum.members.length - 1) {
           indent.addln(',');
         } else {
diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart
index 90c41c0..e8de7c1 100644
--- a/packages/pigeon/lib/objc_generator.dart
+++ b/packages/pigeon/lib/objc_generator.dart
@@ -561,10 +561,12 @@
 
     indent.write('typedef NS_ENUM(NSUInteger, $enumName) ');
     indent.scoped('{', '};', () {
-      enumerate(anEnum.members, (int index, final String member) {
+      enumerate(anEnum.members, (int index, final EnumMember member) {
+        addDocumentationComments(
+            indent, member.documentationComments, _docCommentSpec);
         // Capitalized first letter to ensure Swift compatibility
         indent.writeln(
-            '$enumName${member[0].toUpperCase()}${member.substring(1)} = $index,');
+            '$enumName${member.name[0].toUpperCase()}${member.name.substring(1)} = $index,');
       });
     });
   }
diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart
index 46203f6..5da91c4 100644
--- a/packages/pigeon/lib/pigeon_lib.dart
+++ b/packages/pigeon/lib/pigeon_lib.dart
@@ -1049,7 +1049,11 @@
     _enums.add(Enum(
       name: node.name2.lexeme,
       members: node.constants
-          .map((dart_ast.EnumConstantDeclaration e) => e.name2.lexeme)
+          .map((dart_ast.EnumConstantDeclaration e) => EnumMember(
+                name: e.name2.lexeme,
+                documentationComments: _documentationCommentsParser(
+                    e.documentationComment?.tokens),
+              ))
           .toList(),
       documentationComments:
           _documentationCommentsParser(node.documentationComment?.tokens),
diff --git a/packages/pigeon/lib/swift_generator.dart b/packages/pigeon/lib/swift_generator.dart
index 6ee58f5..3736506 100644
--- a/packages/pigeon/lib/swift_generator.dart
+++ b/packages/pigeon/lib/swift_generator.dart
@@ -470,8 +470,10 @@
 
     indent.write('enum ${anEnum.name}: Int ');
     indent.scoped('{', '}', () {
-      enumerate(anEnum.members, (int index, final String member) {
-        indent.writeln('case ${_camelCase(member)} = $index');
+      enumerate(anEnum.members, (int index, final EnumMember member) {
+        addDocumentationComments(
+            indent, member.documentationComments, _docCommentSpec);
+        indent.writeln('case ${_camelCase(member.name)} = $index');
       });
     });
   }
diff --git a/packages/pigeon/pigeons/enum.dart b/packages/pigeon/pigeons/enum.dart
index 7552ac1..d15bb56 100644
--- a/packages/pigeon/pigeons/enum.dart
+++ b/packages/pigeon/pigeons/enum.dart
@@ -6,8 +6,13 @@
 
 /// This comment is to test enum documentation comments.
 enum EnumState {
+  /// This comment is to test enum member (Pending) documentation comments.
   Pending,
+
+  /// This comment is to test enum member (Success) documentation comments.
   Success,
+
+  /// This comment is to test enum member (Error) documentation comments.
   Error,
 }
 
diff --git a/packages/pigeon/pubspec.yaml b/packages/pigeon/pubspec.yaml
index cb8f5f4..a68cd75 100644
--- a/packages/pigeon/pubspec.yaml
+++ b/packages/pigeon/pubspec.yaml
@@ -2,7 +2,7 @@
 description: Code generator tool to make communication between Flutter and the host platform type-safe and easier.
 repository: https://github.com/flutter/packages/tree/main/packages/pigeon
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3Apigeon
-version: 4.2.12 # This must match the version in lib/generator_tools.dart
+version: 4.2.13 # This must match the version in lib/generator_tools.dart
 
 environment:
   sdk: ">=2.12.0 <3.0.0"
diff --git a/packages/pigeon/test/cpp_generator_test.dart b/packages/pigeon/test/cpp_generator_test.dart
index 4d7c218..4021d56 100644
--- a/packages/pigeon/test/cpp_generator_test.dart
+++ b/packages/pigeon/test/cpp_generator_test.dart
@@ -1038,7 +1038,10 @@
       ],
       classes: <Class>[],
       enums: <Enum>[
-        Enum(name: 'Foo', members: <String>['one', 'two'])
+        Enum(name: 'Foo', members: <EnumMember>[
+          EnumMember(name: 'one'),
+          EnumMember(name: 'two'),
+        ])
       ],
     );
     final List<Error> errors = validateCpp(const CppOptions(), root);
@@ -1052,6 +1055,7 @@
       ' class comment',
       ' class field comment',
       ' enum comment',
+      ' enum member comment',
     ];
     int count = 0;
 
@@ -1107,9 +1111,12 @@
             comments[count++],
             unspacedComments[unspacedCount++]
           ],
-          members: <String>[
-            'one',
-            'two',
+          members: <EnumMember>[
+            EnumMember(
+              name: 'one',
+              documentationComments: <String>[comments[count++]],
+            ),
+            EnumMember(name: 'two'),
           ],
         ),
       ],
diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart
index f56fe0a..bf359dd 100644
--- a/packages/pigeon/test/dart_generator_test.dart
+++ b/packages/pigeon/test/dart_generator_test.dart
@@ -38,9 +38,9 @@
   test('gen one enum', () {
     final Enum anEnum = Enum(
       name: 'Foobar',
-      members: <String>[
-        'one',
-        'two',
+      members: <EnumMember>[
+        EnumMember(name: 'one'),
+        EnumMember(name: 'two'),
       ],
     );
     final Root root = Root(
@@ -408,9 +408,9 @@
     ], enums: <Enum>[
       Enum(
         name: 'Enum',
-        members: <String>[
-          'one',
-          'two',
+        members: <EnumMember>[
+          EnumMember(name: 'one'),
+          EnumMember(name: 'two'),
         ],
       )
     ]);
@@ -436,7 +436,10 @@
             ])
       ])
     ], classes: <Class>[], enums: <Enum>[
-      Enum(name: 'Foo', members: <String>['one', 'two'])
+      Enum(name: 'Foo', members: <EnumMember>[
+        EnumMember(name: 'one'),
+        EnumMember(name: 'two'),
+      ])
     ]);
     final StringBuffer sink = StringBuffer();
     generateDart(const DartOptions(), root, sink);
@@ -475,9 +478,9 @@
     ], enums: <Enum>[
       Enum(
         name: 'Enum',
-        members: <String>[
-          'one',
-          'two',
+        members: <EnumMember>[
+          EnumMember(name: 'one'),
+          EnumMember(name: 'two'),
         ],
       )
     ]);
@@ -1168,6 +1171,7 @@
       ' class comment',
       ' class field comment',
       ' enum comment',
+      ' enum member comment',
     ];
     int count = 0;
 
@@ -1223,9 +1227,12 @@
             comments[count++],
             unspacedComments[unspacedCount++]
           ],
-          members: <String>[
-            'one',
-            'two',
+          members: <EnumMember>[
+            EnumMember(
+              name: 'one',
+              documentationComments: <String>[comments[count++]],
+            ),
+            EnumMember(name: 'two'),
           ],
         ),
       ],
@@ -1339,9 +1346,9 @@
       enums: <Enum>[
         Enum(
           name: 'Enum',
-          members: <String>[
-            'one',
-            'two',
+          members: <EnumMember>[
+            EnumMember(name: 'one'),
+            EnumMember(name: 'two'),
           ],
         )
       ],
diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart
index b9b5214..bfcea98 100644
--- a/packages/pigeon/test/java_generator_test.dart
+++ b/packages/pigeon/test/java_generator_test.dart
@@ -42,10 +42,10 @@
   test('gen one enum', () {
     final Enum anEnum = Enum(
       name: 'Foobar',
-      members: <String>[
-        'one',
-        'twoThreeFour',
-        'remoteDB',
+      members: <EnumMember>[
+        EnumMember(name: 'one'),
+        EnumMember(name: 'twoThreeFour'),
+        EnumMember(name: 'remoteDB'),
       ],
     );
     final Root root = Root(
@@ -558,10 +558,10 @@
   test('gen one enum class', () {
     final Enum anEnum = Enum(
       name: 'Enum1',
-      members: <String>[
-        'one',
-        'twoThreeFour',
-        'remoteDB',
+      members: <EnumMember>[
+        EnumMember(name: 'one'),
+        EnumMember(name: 'twoThreeFour'),
+        EnumMember(name: 'remoteDB'),
       ],
     );
     final Class klass = Class(
@@ -614,7 +614,10 @@
             ])
       ])
     ], classes: <Class>[], enums: <Enum>[
-      Enum(name: 'Foo', members: <String>['one', 'two'])
+      Enum(name: 'Foo', members: <EnumMember>[
+        EnumMember(name: 'one'),
+        EnumMember(name: 'two'),
+      ])
     ]);
     final StringBuffer sink = StringBuffer();
     const JavaOptions javaOptions = JavaOptions(className: 'Messages');
@@ -1135,6 +1138,7 @@
       ' class comment',
       ' class field comment',
       ' enum comment',
+      ' enum member comment',
     ];
     int count = 0;
 
@@ -1191,9 +1195,12 @@
             comments[count++],
             unspacedComments[unspacedCount++]
           ],
-          members: <String>[
-            'one',
-            'two',
+          members: <EnumMember>[
+            EnumMember(
+              name: 'one',
+              documentationComments: <String>[comments[count++]],
+            ),
+            EnumMember(name: 'two'),
           ],
         ),
       ],
diff --git a/packages/pigeon/test/kotlin_generator_test.dart b/packages/pigeon/test/kotlin_generator_test.dart
index 4ed3a6c..4653410 100644
--- a/packages/pigeon/test/kotlin_generator_test.dart
+++ b/packages/pigeon/test/kotlin_generator_test.dart
@@ -38,9 +38,9 @@
   test('gen one enum', () {
     final Enum anEnum = Enum(
       name: 'Foobar',
-      members: <String>[
-        'one',
-        'two',
+      members: <EnumMember>[
+        EnumMember(name: 'one'),
+        EnumMember(name: 'two'),
       ],
     );
     final Root root = Root(
@@ -71,7 +71,10 @@
             ])
       ])
     ], classes: <Class>[], enums: <Enum>[
-      Enum(name: 'Foo', members: <String>['one', 'two'])
+      Enum(name: 'Foo', members: <EnumMember>[
+        EnumMember(name: 'one'),
+        EnumMember(name: 'two'),
+      ])
     ]);
     final StringBuffer sink = StringBuffer();
     const KotlinOptions kotlinOptions = KotlinOptions();
@@ -583,9 +586,9 @@
   test('gen one enum class', () {
     final Enum anEnum = Enum(
       name: 'Enum1',
-      members: <String>[
-        'one',
-        'two',
+      members: <EnumMember>[
+        EnumMember(name: 'one'),
+        EnumMember(name: 'two'),
       ],
     );
     final Class klass = Class(
@@ -1014,6 +1017,7 @@
       ' class comment',
       ' class field comment',
       ' enum comment',
+      ' enum member comment',
     ];
     int count = 0;
 
@@ -1070,9 +1074,12 @@
             comments[count++],
             unspacedComments[unspacedCount++]
           ],
-          members: <String>[
-            'one',
-            'two',
+          members: <EnumMember>[
+            EnumMember(
+              name: 'one',
+              documentationComments: <String>[comments[count++]],
+            ),
+            EnumMember(name: 'two'),
           ],
         ),
       ],
diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart
index fef4641..cf83029 100644
--- a/packages/pigeon/test/objc_generator_test.dart
+++ b/packages/pigeon/test/objc_generator_test.dart
@@ -42,9 +42,9 @@
     final Root root = Root(apis: <Api>[], classes: <Class>[], enums: <Enum>[
       Enum(
         name: 'Enum1',
-        members: <String>[
-          'one',
-          'two',
+        members: <EnumMember>[
+          EnumMember(name: 'one'),
+          EnumMember(name: 'two'),
         ],
       )
     ]);
@@ -60,9 +60,9 @@
     final Root root = Root(apis: <Api>[], classes: <Class>[], enums: <Enum>[
       Enum(
         name: 'Enum1',
-        members: <String>[
-          'one',
-          'two',
+        members: <EnumMember>[
+          EnumMember(name: 'one'),
+          EnumMember(name: 'two'),
         ],
       )
     ]);
@@ -95,9 +95,9 @@
       enums: <Enum>[
         Enum(
           name: 'Enum1',
-          members: <String>[
-            'one',
-            'two',
+          members: <EnumMember>[
+            EnumMember(name: 'one'),
+            EnumMember(name: 'two'),
           ],
         )
       ],
@@ -127,7 +127,10 @@
             ])
       ])
     ], classes: <Class>[], enums: <Enum>[
-      Enum(name: 'Foo', members: <String>['one', 'two'])
+      Enum(name: 'Foo', members: <EnumMember>[
+        EnumMember(name: 'one'),
+        EnumMember(name: 'two'),
+      ])
     ]);
     final StringBuffer sink = StringBuffer();
     const ObjcOptions options = ObjcOptions(header: 'foo.h', prefix: 'AC');
@@ -161,7 +164,10 @@
             ])
       ])
     ], classes: <Class>[], enums: <Enum>[
-      Enum(name: 'Foo', members: <String>['one', 'two'])
+      Enum(name: 'Foo', members: <EnumMember>[
+        EnumMember(name: 'one'),
+        EnumMember(name: 'two'),
+      ])
     ]);
     const ObjcOptions options = ObjcOptions(header: 'foo.h');
     final List<Error> errors = validateObjc(options, root);
@@ -190,9 +196,9 @@
       enums: <Enum>[
         Enum(
           name: 'Enum1',
-          members: <String>[
-            'one',
-            'two',
+          members: <EnumMember>[
+            EnumMember(name: 'one'),
+            EnumMember(name: 'two'),
           ],
         )
       ],
@@ -1749,6 +1755,7 @@
       ' class comment',
       ' class field comment',
       ' enum comment',
+      ' enum member comment',
     ];
     int count = 0;
 
@@ -1805,9 +1812,12 @@
             comments[count++],
             unspacedComments[unspacedCount++]
           ],
-          members: <String>[
-            'one',
-            'two',
+          members: <EnumMember>[
+            EnumMember(
+              name: 'one',
+              documentationComments: <String>[comments[count++]],
+            ),
+            EnumMember(name: 'two'),
           ],
         ),
       ],
diff --git a/packages/pigeon/test/swift_generator_test.dart b/packages/pigeon/test/swift_generator_test.dart
index 1ba2fde..74c8aad 100644
--- a/packages/pigeon/test/swift_generator_test.dart
+++ b/packages/pigeon/test/swift_generator_test.dart
@@ -37,9 +37,9 @@
   test('gen one enum', () {
     final Enum anEnum = Enum(
       name: 'Foobar',
-      members: <String>[
-        'one',
-        'two',
+      members: <EnumMember>[
+        EnumMember(name: 'one'),
+        EnumMember(name: 'two'),
       ],
     );
     final Root root = Root(
@@ -70,7 +70,10 @@
             ])
       ])
     ], classes: <Class>[], enums: <Enum>[
-      Enum(name: 'Foo', members: <String>['one', 'two'])
+      Enum(name: 'Foo', members: <EnumMember>[
+        EnumMember(name: 'one'),
+        EnumMember(name: 'two'),
+      ])
     ]);
     final StringBuffer sink = StringBuffer();
     const SwiftOptions swiftOptions = SwiftOptions();
@@ -532,9 +535,9 @@
   test('gen one enum class', () {
     final Enum anEnum = Enum(
       name: 'Enum1',
-      members: <String>[
-        'one',
-        'two',
+      members: <EnumMember>[
+        EnumMember(name: 'one'),
+        EnumMember(name: 'two'),
       ],
     );
     final Class klass = Class(
@@ -953,6 +956,7 @@
       ' class comment',
       ' class field comment',
       ' enum comment',
+      ' enum member comment',
     ];
     int count = 0;
 
@@ -1009,9 +1013,12 @@
             comments[count++],
             unspacedComments[unspacedCount++]
           ],
-          members: <String>[
-            'one',
-            'two',
+          members: <EnumMember>[
+            EnumMember(
+              name: 'one',
+              documentationComments: <String>[comments[count++]],
+            ),
+            EnumMember(name: 'two'),
           ],
         ),
       ],