Fix dummy fields (#270)

* Fix dummy fields

* Remove boring test line
diff --git a/protobuf/CHANGELOG.md b/protobuf/CHANGELOG.md
index 06ed05d..d446021 100644
--- a/protobuf/CHANGELOG.md
+++ b/protobuf/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.13.16
+
+* Better handling of dummy calls to `BuilderInfo.add` with a tag number of 0.
+  These would trigger assertions before.
+
 ## 0.13.15
 
 * Add new getter `GeneratedMessage.isFrozen` to query if the message has been frozen. 
diff --git a/protobuf/lib/src/protobuf/builder_info.dart b/protobuf/lib/src/protobuf/builder_info.dart
index f850d35..f8801b1 100644
--- a/protobuf/lib/src/protobuf/builder_info.dart
+++ b/protobuf/lib/src/protobuf/builder_info.dart
@@ -30,8 +30,11 @@
       ValueOfFunc valueOf,
       List<ProtobufEnum> enumValues) {
     var index = byIndex.length;
-    _addField(FieldInfo<T>(name, tagNumber, index, fieldType, defaultOrMaker,
-        subBuilder, valueOf, enumValues));
+    final fieldInfo = (tagNumber == 0)
+        ? FieldInfo.dummy(index)
+        : FieldInfo<T>(name, tagNumber, index, fieldType, defaultOrMaker,
+            subBuilder, valueOf, enumValues);
+    _addField(fieldInfo);
   }
 
   void addMapField<K, V>(int tagNumber, String name, int keyFieldType,
@@ -60,7 +63,7 @@
     // Fields with tag number 0 are considered dummy fields added to avoid
     // index calculations add up. They should not be reflected in the following
     // maps.
-    if (fi.tagNumber != 0) {
+    if (!fi.isDummy) {
       fieldInfo[fi.tagNumber] = fi;
       byTagAsString["${fi.tagNumber}"] = fi;
       byName[fi.name] = fi;
diff --git a/protobuf/lib/src/protobuf/field_info.dart b/protobuf/lib/src/protobuf/field_info.dart
index 4a22e75..a446777 100644
--- a/protobuf/lib/src/protobuf/field_info.dart
+++ b/protobuf/lib/src/protobuf/field_info.dart
@@ -8,8 +8,7 @@
 class FieldInfo<T> {
   FrozenPbList<T> _emptyList;
 
-  // BuilderInfo used when creating a field set for a map field.
-  final BuilderInfo _mapEntryBuilderInfo;
+
 
   final String name;
   final int tagNumber;
@@ -49,6 +48,18 @@
     assert(!_isEnum(type) || valueOf != null);
   }
 
+  // Represents a field that has been removed by a program transformation.
+  FieldInfo.dummy(this.index)
+      : name = '<removed field>',
+        tagNumber = 0,
+        type = 0,
+        makeDefault = null,
+        valueOf = null,
+        check = null,
+        enumValues = null,
+        subBuilder = null,
+        _mapEntryBuilderInfo = null;
+
   FieldInfo.repeated(this.name, this.tagNumber, this.index, int type,
       this.check, this.subBuilder,
       [this.valueOf, this.enumValues])
@@ -82,6 +93,10 @@
     return () => defaultOrMaker;
   }
 
+  /// Returns `true` if this represents a dummy field standing in for a field
+  /// that has been removed by a program transformation.
+  bool get isDummy => tagNumber == 0;
+
   bool get isRequired => _isRequired(type);
   bool get isRepeated => _isRepeated(type);
   bool get isGroupOrMessage => _isGroupOrMessage(type);
@@ -176,10 +191,12 @@
   int keyFieldType;
   int valueFieldType;
   CreateBuilderFunc valueCreator;
+  // BuilderInfo used when creating a field set for a map field.
+  final BuilderInfo _mapEntryBuilderInfo;
 
-  MapFieldInfo.map(String name, int tagNumber, int index, int type,
+  MapFieldInfo(String name, int tagNumber, int index, int type,
       this.keyFieldType, this.valueFieldType, BuilderInfo mapEntryBuilderInfo)
-      : super._map(
+      : super._(
             name,
             tagNumber,
             index,
@@ -189,8 +206,8 @@
             null,
             null,
             null,
-            null,
-            mapEntryBuilderInfo) {
+            null
+            ) {
     assert(name != null);
     assert(tagNumber != null);
     assert(_isMapField(type));
diff --git a/protobuf/pubspec.yaml b/protobuf/pubspec.yaml
index 4e2a03f..0b384bc 100644
--- a/protobuf/pubspec.yaml
+++ b/protobuf/pubspec.yaml
@@ -1,5 +1,5 @@
 name: protobuf
-version: 0.13.15
+version: 0.13.16
 author: Dart Team <misc@dartlang.org>
 description: >
   Runtime library for protocol buffers support.
diff --git a/protobuf/test/dummy_field_test.dart b/protobuf/test/dummy_field_test.dart
new file mode 100644
index 0000000..cc142fa
--- /dev/null
+++ b/protobuf/test/dummy_field_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:protobuf/protobuf.dart';
+import 'package:test/test.dart';
+
+class Message extends GeneratedMessage {
+  get info_ => _i;
+  static final _i = BuilderInfo("Message")
+    ..add(0, null, null, null, null, null, null);
+  Message createEmptyInstance() => Message();
+
+  @override
+  GeneratedMessage clone() => throw UnimplementedError();
+}
+
+main() {
+  test('Has no known fields', () {
+    expect(Message().info_.fieldInfo, isEmpty);
+  });
+}