Skip to content

Commit

Permalink
Introduce protoName on fields (google#273)
Browse files Browse the repository at this point in the history
  • Loading branch information
sigurdm authored Aug 23, 2019
1 parent 1d7b49a commit dbd8cb3
Show file tree
Hide file tree
Showing 19 changed files with 433 additions and 383 deletions.
8 changes: 8 additions & 0 deletions protobuf/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 0.14.0

* `FieldInfo` objects have a new getter `.protoName` that gives the non-camel-case name of the field
as in the `.proto`-file.
* **Breaking**: The field-adder methods on `BuilderInfo` now takes only named optional arguments.
To migrate, update `protoc_plugin` to version 18.0.0 or higher.
* The field-adder methods on `BuilderInfo` all take a new argument `protoName`.

## 0.13.16

* Better handling of dummy calls to `BuilderInfo.add` with a tag number of 0.
Expand Down
81 changes: 44 additions & 37 deletions protobuf/lib/src/protobuf/builder_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,27 @@ class BuilderInfo {
dynamic defaultOrMaker,
CreateBuilderFunc subBuilder,
ValueOfFunc valueOf,
List<ProtobufEnum> enumValues) {
List<ProtobufEnum> enumValues,
{String protoName}) {
var index = byIndex.length;
final fieldInfo = (tagNumber == 0)
? FieldInfo.dummy(index)
: FieldInfo<T>(name, tagNumber, index, fieldType, defaultOrMaker,
subBuilder, valueOf, enumValues);
: FieldInfo<T>(name, tagNumber, index, fieldType,
defaultOrMaker: defaultOrMaker,
subBuilder: subBuilder,
valueOf: valueOf,
enumValues: enumValues,
protoName: protoName);
_addField(fieldInfo);
}

void addMapField<K, V>(int tagNumber, String name, int keyFieldType,
int valueFieldType, BuilderInfo mapEntryBuilderInfo) {
int valueFieldType, BuilderInfo mapEntryBuilderInfo,
{String protoName}) {
var index = byIndex.length;
_addField(MapFieldInfo<K, V>.map(name, tagNumber, index, PbFieldType.M,
keyFieldType, valueFieldType, mapEntryBuilderInfo));
_addField(MapFieldInfo<K, V>(name, tagNumber, index, PbFieldType.M,
keyFieldType, valueFieldType, mapEntryBuilderInfo,
protoName: protoName));
}

void addRepeated<T>(
Expand All @@ -51,10 +58,12 @@ class BuilderInfo {
CheckFunc<T> check,
CreateBuilderFunc subBuilder,
ValueOfFunc valueOf,
List<ProtobufEnum> enumValues) {
List<ProtobufEnum> enumValues,
{String protoName}) {
var index = byIndex.length;
_addField(FieldInfo<T>.repeated(name, tagNumber, index, fieldType, check,
subBuilder, valueOf, enumValues));
_addField(FieldInfo<T>.repeated(
name, tagNumber, index, fieldType, check, subBuilder,
valueOf: valueOf, enumValues: enumValues, protoName: protoName));
}

void _addField(FieldInfo fi) {
Expand All @@ -71,71 +80,65 @@ class BuilderInfo {
}

void a<T>(int tagNumber, String name, int fieldType,
[dynamic defaultOrMaker,
{dynamic defaultOrMaker,
CreateBuilderFunc subBuilder,
ValueOfFunc valueOf,
List<ProtobufEnum> enumValues]) {
List<ProtobufEnum> enumValues,
String protoName}) {
add<T>(tagNumber, name, fieldType, defaultOrMaker, subBuilder, valueOf,
enumValues);
}

/// Adds PbFieldType.OS String with no default value to reduce generated
/// code size.
void aOS(int tagNumber, String name) {
void aOS(int tagNumber, String name, {String protoName}) {
add<String>(tagNumber, name, PbFieldType.OS, null, null, null, null);
}

/// Adds PbFieldType.PS String with no default value.
void pPS(int tagNumber, String name) {
void pPS(int tagNumber, String name, {String protoName}) {
addRepeated<String>(tagNumber, name, PbFieldType.PS,
getCheckFunction(PbFieldType.PS), null, null, null);
}

/// Adds PbFieldType.QS String with no default value.
void aQS(int tagNumber, String name) {
void aQS(int tagNumber, String name, {String protoName}) {
add<String>(tagNumber, name, PbFieldType.QS, null, null, null, null);
}

/// Adds Int64 field with Int64.ZERO default.
void aInt64(int tagNumber, String name) {
void aInt64(int tagNumber, String name, {String protoName}) {
add<Int64>(tagNumber, name, PbFieldType.O6, Int64.ZERO, null, null, null);
}

/// Adds a boolean with no default value.
void aOB(int tagNumber, String name) {
void aOB(int tagNumber, String name, {String protoName}) {
add<bool>(tagNumber, name, PbFieldType.OB, null, null, null, null);
}

// Enum.
void e<T>(int tagNumber, String name, int fieldType, dynamic defaultOrMaker,
ValueOfFunc valueOf, List<ProtobufEnum> enumValues) {
void e<T>(int tagNumber, String name, int fieldType,
{dynamic defaultOrMaker,
ValueOfFunc valueOf,
List<ProtobufEnum> enumValues,
String protoName}) {
add<T>(
tagNumber, name, fieldType, defaultOrMaker, null, valueOf, enumValues);
}

// Repeated, not a message, group, or enum.
void p<T>(int tagNumber, String name, int fieldType) {
void p<T>(int tagNumber, String name, int fieldType, {String protoName}) {
assert(!_isGroupOrMessage(fieldType) && !_isEnum(fieldType));
addRepeated<T>(tagNumber, name, fieldType, getCheckFunction(fieldType),
null, null, null);
}

// Repeated message, group, or enum.
void pc<T>(int tagNumber, String name, int fieldType,
[CreateBuilderFunc subBuilder,
ValueOfFunc valueOf,
List<ProtobufEnum> enumValues]) {
assert(_isGroupOrMessage(fieldType) || _isEnum(fieldType));
addRepeated<T>(tagNumber, name, fieldType, _checkNotNull, subBuilder,
valueOf, enumValues);
}

@Deprecated('Use [pc] instead. The given [check] function is ignored.'
'This function will be removed in the next major version.')
void pp<T>(int tagNumber, String name, int fieldType, CheckFunc<T> check,
[CreateBuilderFunc subBuilder,
{CreateBuilderFunc subBuilder,
ValueOfFunc valueOf,
List<ProtobufEnum> enumValues]) {
List<ProtobufEnum> enumValues,
String protoName}) {
assert(_isGroupOrMessage(fieldType) || _isEnum(fieldType));
addRepeated<T>(tagNumber, name, fieldType, _checkNotNull, subBuilder,
valueOf, enumValues);
Expand All @@ -147,20 +150,24 @@ class BuilderInfo {
}

// Map field.
void m<K, V>(int tagNumber, String name, String entryClassName,
int keyFieldType, int valueFieldType,
[CreateBuilderFunc valueCreator,
void m<K, V>(int tagNumber, String name,
{String entryClassName,
int keyFieldType,
int valueFieldType,
CreateBuilderFunc valueCreator,
ValueOfFunc valueOf,
List<ProtobufEnum> enumValues,
PackageName packageName = const PackageName('')]) {
PackageName packageName = const PackageName(''),
String protoName}) {
BuilderInfo mapEntryBuilderInfo = BuilderInfo(entryClassName,
package: packageName)
..add(PbMap._keyFieldNumber, 'key', keyFieldType, null, null, null, null)
..add(PbMap._valueFieldNumber, 'value', valueFieldType, null,
valueCreator, valueOf, enumValues);

addMapField<K, V>(
tagNumber, name, keyFieldType, valueFieldType, mapEntryBuilderInfo);
tagNumber, name, keyFieldType, valueFieldType, mapEntryBuilderInfo,
protoName: protoName);
}

bool containsTagNumber(int tagNumber) => fieldInfo.containsKey(tagNumber);
Expand Down
22 changes: 14 additions & 8 deletions protobuf/lib/src/protobuf/extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,26 @@ class Extension<T> extends FieldInfo<T> {
final String extendee;

Extension(this.extendee, String name, int tagNumber, int fieldType,
[dynamic defaultOrMaker,
{dynamic defaultOrMaker,
CreateBuilderFunc subBuilder,
ValueOfFunc valueOf,
List<ProtobufEnum> enumValues])
: super(name, tagNumber, null, fieldType, defaultOrMaker, subBuilder,
valueOf, enumValues);
List<ProtobufEnum> enumValues,
String protoName})
: super(name, tagNumber, null, fieldType,
defaultOrMaker: defaultOrMaker,
subBuilder: subBuilder,
valueOf: valueOf,
enumValues: enumValues,
protoName: protoName);

Extension.repeated(this.extendee, String name, int tagNumber, int fieldType,
CheckFunc<T> check,
[CreateBuilderFunc subBuilder,
{CheckFunc<T> check,
CreateBuilderFunc subBuilder,
ValueOfFunc valueOf,
List<ProtobufEnum> enumValues])
List<ProtobufEnum> enumValues,
String protoName})
: super.repeated(name, tagNumber, null, fieldType, check, subBuilder,
valueOf, enumValues);
valueOf: valueOf, enumValues: enumValues, protoName: protoName);

int get hashCode => extendee.hashCode * 31 + tagNumber;

Expand Down
91 changes: 43 additions & 48 deletions protobuf/lib/src/protobuf/field_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ part of protobuf;
class FieldInfo<T> {
FrozenPbList<T> _emptyList;

// BuilderInfo used when creating a field set for a map field.
final BuilderInfo _mapEntryBuilderInfo;

final String name;

/// The name of this field as written in the proto-definition.
///
/// This will typically consist of words separated with underscores.
final String protoName;

final int tagNumber;
final int index; // index of the field's value. Null for extensions.
final int type;
Expand All @@ -38,56 +41,45 @@ class FieldInfo<T> {
// (Not used for non-repeated fields.)
final CheckFunc<T> check;

FieldInfo(this.name, this.tagNumber, this.index, int type,
[dynamic defaultOrMaker, this.subBuilder, this.valueOf, this.enumValues])
: this.type = type,
this.makeDefault = findMakeDefault(type, defaultOrMaker),
this.check = null,
_mapEntryBuilderInfo = null {
assert(type != 0);
assert(!_isGroupOrMessage(type) || subBuilder != null);
assert(!_isEnum(type) || valueOf != null);
}
FieldInfo(this.name, this.tagNumber, this.index, this.type,
{dynamic defaultOrMaker,
this.subBuilder,
this.valueOf,
this.enumValues,
String protoName})
: makeDefault = findMakeDefault(type, defaultOrMaker),
check = null,
protoName = protoName ?? _unCamelCase(name),
assert(type != 0),
assert(!_isGroupOrMessage(type) ||
subBuilder != null ||
_isMapField(type)),
assert(!_isEnum(type) || valueOf != null);

// Represents a field that has been removed by a program transformation.
FieldInfo.dummy(this.index)
: name = '<removed field>',
protoName = '<removed field>',
tagNumber = 0,
type = 0,
makeDefault = null,
valueOf = null,
check = null,
enumValues = null,
subBuilder = null,
_mapEntryBuilderInfo = null;
subBuilder = null;

FieldInfo.repeated(this.name, this.tagNumber, this.index, int type,
FieldInfo.repeated(this.name, this.tagNumber, this.index, this.type,
this.check, this.subBuilder,
[this.valueOf, this.enumValues])
: this.type = type,
this.makeDefault = (() => PbList<T>(check: check)),
_mapEntryBuilderInfo = null {
{this.valueOf, this.enumValues, String protoName})
: makeDefault = (() => PbList<T>(check: check)),
protoName = protoName ?? _unCamelCase(name) {
assert(name != null);
assert(tagNumber != null);
assert(_isRepeated(type));
assert(check != null);
assert(!_isEnum(type) || valueOf != null);
}

FieldInfo._map(
this.name, this.tagNumber, this.index, int type, this.makeDefault,
[dynamic defaultOrMaker,
this.subBuilder,
this.valueOf,
this.enumValues,
this._mapEntryBuilderInfo])
: this.type = type,
this.check = null {
assert(name != null);
assert(tagNumber != null);
assert(_isMapField(type));
}

static MakeDefaultFunc findMakeDefault(int type, dynamic defaultOrMaker) {
if (defaultOrMaker == null) return PbFieldType._defaultForType(type);
if (defaultOrMaker is MakeDefaultFunc) return defaultOrMaker;
Expand Down Expand Up @@ -188,25 +180,28 @@ class FieldInfo<T> {
String toString() => name;
}

final RegExp _upperCase = RegExp('[A-Z]');

String _unCamelCase(String name) {
return name.replaceAllMapped(
_upperCase, (match) => '_${match.group(0).toLowerCase()}');
}

class MapFieldInfo<K, V> extends FieldInfo<PbMap<K, V>> {
int keyFieldType;
int valueFieldType;
CreateBuilderFunc valueCreator;

MapFieldInfo.map(String name, int tagNumber, int index, int type,
this.keyFieldType, this.valueFieldType, BuilderInfo mapEntryBuilderInfo)
: super._map(
name,
tagNumber,
index,
type,
() =>
PbMap<K, V>(keyFieldType, valueFieldType, mapEntryBuilderInfo),
null,
null,
null,
null,
mapEntryBuilderInfo) {
// BuilderInfo used when creating a field set for a map field.
final BuilderInfo _mapEntryBuilderInfo;

MapFieldInfo(String name, int tagNumber, int index, int type,
this.keyFieldType, this.valueFieldType, this._mapEntryBuilderInfo,
{String protoName})
: super(name, tagNumber, index, type,
defaultOrMaker: () =>
PbMap<K, V>(keyFieldType, valueFieldType, _mapEntryBuilderInfo),
protoName: protoName) {
assert(name != null);
assert(tagNumber != null);
assert(_isMapField(type));
Expand Down
2 changes: 1 addition & 1 deletion protobuf/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: protobuf
version: 0.13.16
version: 0.14.0
author: Dart Team <[email protected]>
description: >
Runtime library for protocol buffers support.
Expand Down
4 changes: 2 additions & 2 deletions protobuf/test/mock_util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import 'package:protobuf/protobuf.dart'

BuilderInfo mockInfo(String className, CreateBuilderFunc create) {
return BuilderInfo(className)
..a(1, "val", PbFieldType.O3, 42)
..a(1, "val", PbFieldType.O3, defaultOrMaker: 42)
..a(2, "str", PbFieldType.OS)
..a(3, "child", PbFieldType.OM, create, create)
..a(3, "child", PbFieldType.OM, defaultOrMaker: create, subBuilder: create)
..p<int>(4, "int32s", PbFieldType.P3)
..a(5, "int64", PbFieldType.O6);
}
Expand Down
2 changes: 1 addition & 1 deletion protobuf/test/readonly_message_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Rec extends GeneratedMessage {
@override
BuilderInfo info_ = BuilderInfo('rec')
..a(1, 'value', PbFieldType.O3)
..pc<Rec>(2, 'sub', PbFieldType.PM, Rec.create)
..pc<Rec>(2, 'sub', PbFieldType.PM, subBuilder: Rec.create)
..p<int>(10, 'ints', PbFieldType.P3);

int get value => $_get(0, 0);
Expand Down
Loading

0 comments on commit dbd8cb3

Please sign in to comment.