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);
+ });
+}