Index: lib/message_generator.dart |
diff --git a/lib/message_generator.dart b/lib/message_generator.dart |
index 1deaa6f2587d37dd9a03cb3268c000502b51a3a5..6dc1b2556c95dac24ad215076c481a5e6289d721 100644 |
--- a/lib/message_generator.dart |
+++ b/lib/message_generator.dart |
@@ -31,27 +31,23 @@ class MessageGenerator extends ProtobufContainer { |
'extensionsAreInitialized', 'mergeFromMessage', 'mergeUnknownFields', |
'==', 'info_', 'GeneratedMessage', 'Object']; |
- // List of names that can't be used in a subclass that implements Map. |
- static final List<String> reservedNamesForMap = |
- ['addAll', 'containsKey', 'containsValue', 'forEach', 'putIfAbsent', |
- 'remove', 'isEmpty', 'isNotEmpty', 'keys', 'length', 'values']; |
- |
- // This should match the extension in dart_options.proto. |
- static const int implementMapOption = 95333044; |
- |
- // Returns true if the implement_map option is turned on for the message. |
- static bool _shouldImplementMap(DescriptorProto desc, bool defaultValue) { |
+ // Returns the mixin for this message, or null if none. |
+ static PbMixin _getMixin(DescriptorProto desc, PbMixin defaultValue) { |
if (!desc.hasOptions()) return defaultValue; |
+ if (!desc.options.hasExtension(Dart_options.mixin)) return defaultValue; |
- var val = desc.options.unknownFields.getField(implementMapOption); |
- if (val == null || val.length != 1) return defaultValue; |
- |
- return val.values[0] == 1; |
+ String name = desc.options.getExtension(Dart_options.mixin); |
+ if (name.isEmpty) return null; // don't use a mixin (override any default) |
+ var mixin = findMixin(name); |
+ if (mixin == null) { |
+ throw("unknown mixin class: ${name}"); |
+ } |
+ return mixin; |
} |
final String classname; |
final String fqname; |
- final bool implementsMap; |
+ final PbMixin mixin; |
final ProtobufContainer _parent; |
final GenerationContext _context; |
@@ -64,7 +60,7 @@ class MessageGenerator extends ProtobufContainer { |
MessageGenerator( |
DescriptorProto descriptor, ProtobufContainer parent, this._context, |
- bool implementMapByDefault) |
+ PbMixin defaultMixin) |
: _descriptor = descriptor, |
_parent = parent, |
classname = (parent.classname == '') ? |
@@ -72,7 +68,7 @@ class MessageGenerator extends ProtobufContainer { |
fqname = (parent == null || parent.fqname == null) ? descriptor.name : |
(parent.fqname == '.' ? |
'.${descriptor.name}' : '${parent.fqname}.${descriptor.name}'), |
- implementsMap = _shouldImplementMap(descriptor, implementMapByDefault) { |
+ mixin = _getMixin(descriptor, defaultMixin) { |
_context.register(this); |
for (EnumDescriptorProto e in _descriptor.enumType) { |
@@ -81,7 +77,7 @@ class MessageGenerator extends ProtobufContainer { |
for (DescriptorProto n in _descriptor.nestedType) { |
_messageGenerators.add( |
- new MessageGenerator(n, this, _context, implementMapByDefault)); |
+ new MessageGenerator(n, this, _context, defaultMixin)); |
} |
for (FieldDescriptorProto x in _descriptor.extension) { |
@@ -91,14 +87,14 @@ class MessageGenerator extends ProtobufContainer { |
String get package => _parent.package; |
- bool get needsMapMixinImport { |
- if (implementsMap) return true; |
- |
+ /// Adds all mixins used in this message and any submessages. |
+ void addMixinsTo(Set<PbMixin> output) { |
+ if (mixin != null) { |
+ output.addAll(mixin.findMixinsToApply()); |
+ } |
for (var m in _messageGenerators) { |
- if (m.implementsMap) return true; |
+ m.addMixinsTo(output); |
} |
- |
- return false; |
} |
void initializeFields() { |
@@ -116,8 +112,8 @@ class MessageGenerator extends ProtobufContainer { |
_methodNames.addAll(reservedWords); |
_methodNames.addAll(reservedNames); |
- if (implementsMap) { |
- _methodNames.addAll(reservedNamesForMap); |
+ if (mixin != null) { |
+ _methodNames.addAll(mixin.findReservedNames()); |
} |
for (EnumGenerator e in _enumGenerators) { |
@@ -128,12 +124,13 @@ class MessageGenerator extends ProtobufContainer { |
m.generate(out); |
} |
- var implClause = ""; |
- if (implementsMap) { |
- implClause = " with MapMixin"; |
+ var mixinClause = ''; |
+ if (mixin != null) { |
+ var mixinNames = mixin.findMixinsToApply().map((m) => m.name); |
+ mixinClause = ' with ${mixinNames.join(", ")}'; |
} |
- out.addBlock('class ${classname} extends GeneratedMessage${implClause} {', |
+ out.addBlock('class ${classname} extends GeneratedMessage${mixinClause} {', |
'}', () |
{ |
out.addBlock( |
@@ -223,76 +220,6 @@ class MessageGenerator extends ProtobufContainer { |
out.println('static PbList<${classname}>${SP}createRepeated()${SP}=>' |
'${SP}new PbList<${classname}>();'); |
- |
- if (implementsMap) { |
- // clear() is inherited from GeneratedMessage. |
- // Other map operations are implemented by MapMixin. |
- out.println(''' |
-@override |
-operator [] (key) { |
- if (key is !String) return null; |
- if (!key.contains(".")) { |
- var tag = getTagNumber(key); |
- if (tag == null) return null; |
- return getField(tag); |
- } |
- |
- var keys = key.split('.'); |
- var item = this; |
- for (var key in keys) { |
- if (item is !GeneratedMessage) return null; |
- var tag = item.getTagNumber(key); |
- if (tag == null) return null; |
- item = item.getField(tag); |
- } |
- |
- return item; |
-} |
- |
-@override |
-operator []= (String key, val) { |
- if (!key.contains(".")) { |
- var tag = _mustGetTagNumber(this, key); |
- setField(tag, val); |
- return; |
- } |
- |
- var keys = key.split('.'); |
- var lastKey = keys.removeLast(); |
- var item = this; |
- for (var key in keys) { |
- var tag = _mustGetTagNumber(item, key); |
- item = item.getField(tag); |
- if (item is !GeneratedMessage) { |
- throw new ArgumentError( |
- "field '\${key}' in \${info._messageName} isn't a GeneratedMessage:"); |
- } |
- } |
- var tag = _mustGetTagNumber(item, lastKey); |
- item.setField(tag, val); |
-} |
- |
-_mustGetTagNumber(GeneratedMessage msg, String key) { |
- var tag = msg.getTagNumber(key); |
- if (tag == null) { |
- throw new ArgumentError( |
- "field '\${key}' not found in \${msg.info_.messageName}"); |
- } |
- return tag; |
-} |
- |
-@override |
-get keys => info_.byName.keys; |
- |
-@override |
-get length => info_.byName.length; |
- |
-remove(key) { |
- throw new UnsupportedError("remove() not supported by \${info_.messageName}"); |
-} |
-'''); |
- } |
- |
generateFieldsAccessorsMutators(out); |
}); |
out.println(); |