Skip to content

Commit

Permalink
Add support for map fields. (flutter#137)
Browse files Browse the repository at this point in the history
  • Loading branch information
szakarias authored Nov 27, 2018
1 parent d29fec2 commit aede207
Show file tree
Hide file tree
Showing 18 changed files with 385 additions and 20 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
## 0.11.0

* Breaking change: Support for [map fields](https://developers.google.com/protocol-buffers/docs/proto3#maps)
Generated files require package:protobuf version 0.10.5 or newer.
Protobuf map fields such as:

message Foo {
map<int32, string> map_field = 1;
}
are now no longer represented as List<Foo_MapFieldEntry> but as Map<int, String>.

All code handling these fields needs to be updated.

## 0.10.5

* Generated files now import `dart:async` with a prefix to prevent name
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ TEST_PROTO_LIST = \
import_clash \
map_api \
map_api2 \
map_field \
mixins \
multiple_files_test \
nested_extension \
Expand Down
2 changes: 1 addition & 1 deletion lib/file_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ class FileGenerator extends ProtobufContainer {
// Make sure any other symbols in dart:core don't cause name conflicts with
// protobuf classes that have the same name.
out.println("// ignore: UNUSED_SHOWN_NAME\n"
"import 'dart:core' show int, bool, double, String, List, override;\n");
"import 'dart:core' show int, bool, double, String, List, Map, override;\n");

if (_needsFixnumImport) {
out.println("import 'package:fixnum/fixnum.dart';");
Expand Down
14 changes: 10 additions & 4 deletions lib/message_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ class MessageGenerator extends ProtobufContainer {
checkResolved();

for (MessageGenerator m in _messageGenerators) {
// Don't output the generated map entry type. Instead, the `PbMap` type
// from the protobuf library is used to hold the keys and values.
if (m._descriptor.options.hasMapEntry()) continue;
m.generate(out);
}

Expand Down Expand Up @@ -381,8 +384,8 @@ class MessageGenerator extends ProtobufContainer {
var names = field.memberNames;

_emitOverrideIf(field.overridesGetter, out);
var getterExpr = _getterExpression(
fieldTypeString, field.index, defaultExpr, field.isRepeated);
final getterExpr = _getterExpression(fieldTypeString, field.index,
defaultExpr, field.isRepeated, field.isMapField);
out.println('${fieldTypeString} get ${names.fieldName} => ${getterExpr};');

if (field.isRepeated) {
Expand Down Expand Up @@ -421,8 +424,11 @@ class MessageGenerator extends ProtobufContainer {
}
}

String _getterExpression(
String fieldType, int index, String defaultExpr, bool isRepeated) {
String _getterExpression(String fieldType, int index, String defaultExpr,
bool isRepeated, bool isMapField) {
if (isMapField) {
return '\$_getMap($index)';
}
if (fieldType == 'String') {
return '\$_getS($index, $defaultExpr)';
}
Expand Down
44 changes: 40 additions & 4 deletions lib/protobuf_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,24 @@ class ProtobufField {
/// True if this field uses the Int64 from the fixnum package.
bool get needsFixnumImport => baseType.unprefixed == "Int64";

/// True if this field is a map field definition: `map<key_type, value_type> map_field = N`.
bool get isMapField {
if (!isRepeated || !baseType.isMessage) return false;
MessageGenerator generator = baseType.generator;
return generator._descriptor.options.hasMapEntry();
}

/// Returns the expression to use for the Dart type.
///
/// This will be a List for repeated types.
/// [fileGen] represents the .proto file where we are generating code.
String getDartType(FileGenerator fileGen) {
if (isMapField) {
MessageGenerator d = baseType.generator;
String keyType = d._fieldList[0].baseType.getDartType(fileGen);
String valueType = d._fieldList[1].baseType.getDartType(fileGen);
return 'Map<$keyType, $valueType>';
}
if (isRepeated) return baseType.getRepeatedDartType(fileGen);
return baseType.getDartType(fileGen);
}
Expand Down Expand Up @@ -106,18 +119,41 @@ class ProtobufField {
String quotedName = "'$dartFieldName'";
String type = baseType.getDartType(fileGen);

if (isMapField) {
MessageGenerator generator = baseType.generator;
ProtobufField key = generator._fieldList[0];
ProtobufField value = generator._fieldList[1];
String keyType = key.baseType.getDartType(fileGen);
String valueType = value.baseType.getDartType(fileGen);
String keyTypeConstant = key.typeConstant;
String valTypeConstant = value.typeConstant;

if (value.baseType.isMessage || value.baseType.isGroup) {
return '..m<$keyType, $valueType>($number, $quotedName, '
'$keyTypeConstant, $valTypeConstant, $valueType.create)';
}
if (value.baseType.isEnum) {
return '..m<$keyType, $valueType>($number, $quotedName, '
'$keyTypeConstant, $valTypeConstant, null, $valueType.valueOf, '
'$valueType.values)';
}
return '..m<$keyType, $valueType>($number, $quotedName, '
'$keyTypeConstant, $valTypeConstant)';
}

if (isRepeated) {
if (baseType.isMessage || baseType.isGroup) {
return '..pp<$type>($number, $quotedName, $typeConstant,'
' $type.$checkItem, $type.create)';
} else if (baseType.isEnum) {
}
if (baseType.isEnum) {
return '..pp<$type>($number, $quotedName, $typeConstant,'
' $type.$checkItem, null, $type.valueOf, $type.values)';
} else if (typeConstant == '$_protobufImportPrefix.PbFieldType.PS') {
}
if (typeConstant == '$_protobufImportPrefix.PbFieldType.PS') {
return '..pPS($number, $quotedName)';
} else {
return '..p<$type>($number, $quotedName, $typeConstant)';
}
return '..p<$type>($number, $quotedName, $typeConstant)';
}

String makeDefault = generateDefaultFunction(fileGen);
Expand Down
2 changes: 1 addition & 1 deletion lib/src/dart_options.pb.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import

// ignore: UNUSED_SHOWN_NAME
import 'dart:core' show int, bool, double, String, List, override;
import 'dart:core' show int, bool, double, String, List, Map, override;

import 'package:protobuf/protobuf.dart' as $pb;

Expand Down
2 changes: 1 addition & 1 deletion lib/src/descriptor.pb.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import

// ignore: UNUSED_SHOWN_NAME
import 'dart:core' show int, bool, double, String, List, override;
import 'dart:core' show int, bool, double, String, List, Map, override;

import 'package:fixnum/fixnum.dart';
import 'package:protobuf/protobuf.dart' as $pb;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/plugin.pb.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import

// ignore: UNUSED_SHOWN_NAME
import 'dart:core' show int, bool, double, String, List, override;
import 'dart:core' show int, bool, double, String, List, Map, override;

import 'package:protobuf/protobuf.dart' as $pb;

Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ environment:
dependencies:
fixnum: ^0.10.5
path: ^1.0.0
protobuf: ^0.10.4
protobuf: ^0.10.5
dart_style: ^1.0.6

dev_dependencies:
Expand Down
2 changes: 1 addition & 1 deletion test/goldens/grpc_service.pb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import

// ignore: UNUSED_SHOWN_NAME
import 'dart:core' show int, bool, double, String, List, override;
import 'dart:core' show int, bool, double, String, List, Map, override;

import 'package:protobuf/protobuf.dart' as $pb;

Expand Down
2 changes: 1 addition & 1 deletion test/goldens/header_in_package.pb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import

// ignore: UNUSED_SHOWN_NAME
import 'dart:core' show int, bool, double, String, List, override;
import 'dart:core' show int, bool, double, String, List, Map, override;

import 'package:protobuf/protobuf.dart' as $pb;

2 changes: 1 addition & 1 deletion test/goldens/header_with_fixnum.pb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import

// ignore: UNUSED_SHOWN_NAME
import 'dart:core' show int, bool, double, String, List, override;
import 'dart:core' show int, bool, double, String, List, Map, override;

import 'package:fixnum/fixnum.dart';
import 'package:protobuf/protobuf.dart' as $pb;
Expand Down
2 changes: 1 addition & 1 deletion test/goldens/imports.pb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import

// ignore: UNUSED_SHOWN_NAME
import 'dart:core' show int, bool, double, String, List, override;
import 'dart:core' show int, bool, double, String, List, Map, override;

import 'package:protobuf/protobuf.dart' as $pb;

Expand Down
2 changes: 1 addition & 1 deletion test/goldens/oneMessage.pb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import

// ignore: UNUSED_SHOWN_NAME
import 'dart:core' show int, bool, double, String, List, override;
import 'dart:core' show int, bool, double, String, List, Map, override;

import 'package:protobuf/protobuf.dart' as $pb;

Expand Down
2 changes: 1 addition & 1 deletion test/goldens/service.pb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import 'dart:async' as $async;
// ignore: UNUSED_SHOWN_NAME
import 'dart:core' show int, bool, double, String, List, override;
import 'dart:core' show int, bool, double, String, List, Map, override;

import 'package:protobuf/protobuf.dart' as $pb;

Expand Down
2 changes: 1 addition & 1 deletion test/goldens/topLevelEnum.pb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import

// ignore: UNUSED_SHOWN_NAME
import 'dart:core' show int, bool, double, String, List, override;
import 'dart:core' show int, bool, double, String, List, Map, override;

export 'test.pbenum.dart';

Loading

0 comments on commit aede207

Please sign in to comment.