Fix generation of invalid Dart code for oneof enums. (#231)

Fix generation of invalid Dart code for oneof enums.
diff --git a/protoc_plugin/CHANGELOG.md b/protoc_plugin/CHANGELOG.md
index 59687d7..cc8adb2 100644
--- a/protoc_plugin/CHANGELOG.md
+++ b/protoc_plugin/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 16.0.5
+
+* Fix generation of invalid Dart code for oneof enums
+  by adding list of reserved enum names.
+
 ## 16.0.4
 
 * Generate '@Deprecated' annotations on fields that have been deprecated in the
diff --git a/protoc_plugin/lib/message_generator.dart b/protoc_plugin/lib/message_generator.dart
index bda0a55..41746a3 100644
--- a/protoc_plugin/lib/message_generator.dart
+++ b/protoc_plugin/lib/message_generator.dart
@@ -13,7 +13,7 @@
       IndentingWriter out, String classname, List<ProtobufField> fields) {
     out.addBlock('enum ${classname} {', '}\n', () {
       for (ProtobufField field in fields) {
-        final name = field.memberNames.fieldName;
+        final name = oneofEnumMemberName(field.memberNames.fieldName);
         out.println('$name, ');
       }
       out.println('notSet');
@@ -321,8 +321,10 @@
             'static const $_coreImportPrefix.Map<$_coreImportPrefix.int, ${oneof.oneofEnumName}> ${oneof.byTagMapName} = {',
             '};', () {
           for (ProtobufField field in _oneofFields[oneof.index]) {
+            final oneofMemberName =
+                oneofEnumMemberName(field.memberNames.fieldName);
             out.println(
-                '${field.number} : ${oneof.oneofEnumName}.${field.memberNames.fieldName},');
+                '${field.number} : ${oneof.oneofEnumName}.${oneofMemberName},');
           }
           out.println('0 : ${oneof.oneofEnumName}.notSet');
         });
diff --git a/protoc_plugin/lib/names.dart b/protoc_plugin/lib/names.dart
index 9f51677..cac4e54 100644
--- a/protoc_plugin/lib/names.dart
+++ b/protoc_plugin/lib/names.dart
@@ -175,6 +175,9 @@
       avoidInitialUnderscore(descriptorName), usedNames, defaultSuffixes());
 }
 
+String oneofEnumMemberName(String fieldName) => disambiguateName(
+    fieldName, Set<String>.from(_oneofEnumMemberNames), defaultSuffixes());
+
 /// Chooses the name of the Dart class to generate for a proto message or enum.
 ///
 /// For a nested message or enum, [parent] should be provided
@@ -509,3 +512,6 @@
   'valueOf',
   'values',
 ];
+
+// List of names used in Dart enums, which can't be used as enum member names.
+const _oneofEnumMemberNames = const <String>['index', 'values'];
diff --git a/protoc_plugin/pubspec.yaml b/protoc_plugin/pubspec.yaml
index 9adcaf4..44fec3d 100644
--- a/protoc_plugin/pubspec.yaml
+++ b/protoc_plugin/pubspec.yaml
@@ -1,5 +1,5 @@
 name: protoc_plugin
-version: 16.0.4-dev-1
+version: 16.0.5
 author: Dart Team <misc@dartlang.org>
 description: Protoc compiler plugin to generate Dart code
 homepage: https://github.com/dart-lang/protobuf
diff --git a/protoc_plugin/test/oneof_test.dart b/protoc_plugin/test/oneof_test.dart
index acd48fc..42a3041 100644
--- a/protoc_plugin/test/oneof_test.dart
+++ b/protoc_plugin/test/oneof_test.dart
@@ -32,10 +32,10 @@
     expect(foo.third, true);
     expect(foo.hasFourth(), false);
     expect(foo.fourth, []);
-    expect(foo.hasFifth(), false);
-    expect(foo.fifth, Bar());
-    expect(foo.hasSixth(), false);
-    expect(foo.sixth, enum_type.A);
+    expect(foo.hasIndex(), false);
+    expect(foo.index, Bar());
+    expect(foo.hasValues(), false);
+    expect(foo.values, EnumType.DEFAULT);
 
     foo.fourth = [1, 2];
     expect(foo.whichOneofField(), Foo_OneofField.fourth);
@@ -47,13 +47,13 @@
     expect(foo.third, false);
     expect(foo.hasFourth(), true);
     expect(foo.fourth, [1, 2]);
-    expect(foo.hasFifth(), false);
-    expect(foo.fifth, Bar());
-    expect(foo.hasSixth(), false);
-    expect(foo.sixth, enum_type.A);
+    expect(foo.hasIndex(), false);
+    expect(foo.index, Bar());
+    expect(foo.hasValues(), false);
+    expect(foo.values, EnumType.DEFAULT);
 
-    foo.fifth = Bar()..i = 1;
-    expect(foo.whichOneofField(), Foo_OneofField.fifth);
+    foo.index = Bar()..i = 1;
+    expect(foo.whichOneofField(), Foo_OneofField.index_);
     expect(foo.hasFirst(), false);
     expect(foo.first, '');
     expect(foo.hasSecond(), false);
@@ -62,13 +62,13 @@
     expect(foo.third, false);
     expect(foo.hasFourth(), false);
     expect(foo.fourth, []);
-    expect(foo.hasFifth(), true);
-    expect(foo.fifth, Bar()..i = 1);
-    expect(foo.hasSixth(), false);
-    expect(foo.sixth, enum_type.A);
+    expect(foo.hasIndex(), true);
+    expect(foo.index, Bar()..i = 1);
+    expect(foo.hasValues(), false);
+    expect(foo.values, EnumType.DEFAULT);
 
-    foo.sixth = enum_type.B;
-    expect(foo.whichOneofField(), Foo_OneofField.sixth);
+    foo.values = EnumType.A;
+    expect(foo.whichOneofField(), Foo_OneofField.values_);
     expect(foo.hasFirst(), false);
     expect(foo.first, '');
     expect(foo.hasSecond(), false);
@@ -77,10 +77,10 @@
     expect(foo.third, false);
     expect(foo.hasFourth(), false);
     expect(foo.fourth, []);
-    expect(foo.hasFifth(), false);
-    expect(foo.fifth, Bar());
-    expect(foo.hasSixth(), true);
-    expect(foo.sixth, enum_type.B);
+    expect(foo.hasIndex(), false);
+    expect(foo.index, Bar());
+    expect(foo.hasValues(), true);
+    expect(foo.values, EnumType.A);
   });
 
   test('set and clear oneof', () {
@@ -172,10 +172,10 @@
   expect(foo.third, false);
   expect(foo.hasFourth(), false);
   expect(foo.fourth, []);
-  expect(foo.hasFifth(), false);
-  expect(foo.fifth, Bar());
-  expect(foo.hasSixth(), false);
-  expect(foo.sixth, enum_type.A);
+  expect(foo.hasIndex(), false);
+  expect(foo.index, Bar());
+  expect(foo.hasValues(), false);
+  expect(foo.values, EnumType.DEFAULT);
 }
 
 void expectFirstSet(Foo foo) {
@@ -188,10 +188,10 @@
   expect(foo.third, false);
   expect(foo.hasFourth(), false);
   expect(foo.fourth, []);
-  expect(foo.hasFifth(), false);
-  expect(foo.fifth, Bar());
-  expect(foo.hasSixth(), false);
-  expect(foo.sixth, enum_type.A);
+  expect(foo.hasIndex(), false);
+  expect(foo.index, Bar());
+  expect(foo.hasValues(), false);
+  expect(foo.values, EnumType.DEFAULT);
 }
 
 void expectOneofNotSet(Foo foo) {
@@ -204,10 +204,10 @@
   expect(foo.third, false);
   expect(foo.hasFourth(), false);
   expect(foo.fourth, []);
-  expect(foo.hasFifth(), false);
-  expect(foo.fifth, Bar());
-  expect(foo.hasSixth(), false);
-  expect(foo.sixth, enum_type.A);
+  expect(foo.hasIndex(), false);
+  expect(foo.index, Bar());
+  expect(foo.hasValues(), false);
+  expect(foo.values, EnumType.DEFAULT);
 
   expect(foo.whichColors(), Foo_Colors.notSet);
   expect(foo.hasRed(), false);
diff --git a/protoc_plugin/test/protos/oneof.proto b/protoc_plugin/test/protos/oneof.proto
index c78bd56..e790a68 100644
--- a/protoc_plugin/test/protos/oneof.proto
+++ b/protoc_plugin/test/protos/oneof.proto
@@ -7,26 +7,26 @@
 package protobuf_unittest;
 
 message Bar {
-    int32 i = 1;
+  int32 i = 1;
 }
 
-enum enum_type {
-    A = 0;
-    B = 1;
+enum EnumType {
+  DEFAULT = 0;
+  A = 1;
 }
 
 message Foo {
-    oneof oneof_field {
-        string first = 1;
-        int32 second = 5;
-        bool third = 3;
-        bytes fourth = 7;
-        Bar fifth = 8;
-        enum_type sixth = 6;
-    }
+  oneof oneof_field {
+    string first = 1;
+    int32 second = 5;
+    bool third = 3;
+    bytes fourth = 7;
+    Bar index = 8;
+    EnumType values = 6;
+  }
 
-    oneof colors {
-        string red = 2;
-        string green = 4;
-    }
+  oneof colors {
+    string red = 2;
+    string green = 4;
+  }
 }