Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(383)

Side by Side Diff: lib/message_generator.dart

Issue 1192943003: changes for 0.3.9 (Closed) Base URL: https://github.com/dart-lang/dart-protoc-plugin.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of protoc; 5 part of protoc;
6 6
7 const String SP = ' '; 7 const String SP = ' ';
8 8
9 class MessageGenerator extends ProtobufContainer { 9 class MessageGenerator extends ProtobufContainer {
10 // List of Dart language reserved words in names which cannot be used in a 10 // List of Dart language reserved words in names which cannot be used in a
(...skipping 13 matching lines...) Expand all
24 'writeToBuffer', 'writeToCodedBufferWriter', 24 'writeToBuffer', 'writeToCodedBufferWriter',
25 'mergeFromCodedBufferReader', 'mergeFromBuffer', 25 'mergeFromCodedBufferReader', 'mergeFromBuffer',
26 'writeToJson', 'mergeFromJson', 26 'writeToJson', 'mergeFromJson',
27 'writeToJsonMap', 'mergeFromJsonMap', 27 'writeToJsonMap', 'mergeFromJsonMap',
28 'addExtension', 'getExtension', 'setExtension', 28 'addExtension', 'getExtension', 'setExtension',
29 'hasExtension', 'clearExtension', 29 'hasExtension', 'clearExtension',
30 'getField', 'setField', 'hasField', 'clearField', 30 'getField', 'setField', 'hasField', 'clearField',
31 'extensionsAreInitialized', 'mergeFromMessage', 'mergeUnknownFields', 31 'extensionsAreInitialized', 'mergeFromMessage', 'mergeUnknownFields',
32 '==', 'info_', 'GeneratedMessage', 'Object']; 32 '==', 'info_', 'GeneratedMessage', 'Object'];
33 33
34 // List of names that can't be used in a subclass that implements Map. 34 // Returns the mixin for this message, or null if none.
35 static final List<String> reservedNamesForMap = 35 static String _getMixin(DescriptorProto desc, String defaultValue) {
36 ['addAll', 'containsKey', 'containsValue', 'forEach', 'putIfAbsent', 36 if (!desc.hasOptions()) return defaultValue;
37 'remove', 'isEmpty', 'isNotEmpty', 'keys', 'length', 'values']; 37 if (!desc.options.hasExtension(Dart_options.mixin)) return defaultValue;
38 38
39 // This should match the extension in dart_options.proto. 39 String name = desc.options.getExtension(Dart_options.mixin);
40 static const int implementMapOption = 95333044; 40 if (name.isEmpty) return null; // don't use a mixin (override any default)
41 41 if (!reservedNamesForMixins.containsKey(name)) {
42 // Returns true if the implement_map option is turned on for the message. 42 throw("unknown mixin class: ${name}");
43 static bool _shouldImplementMap(DescriptorProto desc, bool defaultValue) { 43 }
44 if (!desc.hasOptions()) return defaultValue; 44 return name;
45
46 var val = desc.options.unknownFields.getField(implementMapOption);
47 if (val == null || val.length != 1) return defaultValue;
48
49 return val.values[0] == 1;
50 } 45 }
51 46
52 final String classname; 47 final String classname;
53 final String fqname; 48 final String fqname;
54 final bool implementsMap; 49 final String mixin;
55 50
56 final ProtobufContainer _parent; 51 final ProtobufContainer _parent;
57 final GenerationContext _context; 52 final GenerationContext _context;
58 final DescriptorProto _descriptor; 53 final DescriptorProto _descriptor;
59 final List<EnumGenerator> _enumGenerators = <EnumGenerator>[]; 54 final List<EnumGenerator> _enumGenerators = <EnumGenerator>[];
60 final List<ProtobufField> _fieldList = <ProtobufField>[]; 55 final List<ProtobufField> _fieldList = <ProtobufField>[];
61 final List<MessageGenerator> _messageGenerators = <MessageGenerator>[]; 56 final List<MessageGenerator> _messageGenerators = <MessageGenerator>[];
62 final List<ExtensionGenerator> _extensionGenerators = <ExtensionGenerator>[]; 57 final List<ExtensionGenerator> _extensionGenerators = <ExtensionGenerator>[];
63 final Set<String> _methodNames = new Set<String>(); 58 final Set<String> _methodNames = new Set<String>();
64 59
65 MessageGenerator( 60 MessageGenerator(
66 DescriptorProto descriptor, ProtobufContainer parent, this._context, 61 DescriptorProto descriptor, ProtobufContainer parent, this._context,
67 bool implementMapByDefault) 62 String defaultMixin)
68 : _descriptor = descriptor, 63 : _descriptor = descriptor,
69 _parent = parent, 64 _parent = parent,
70 classname = (parent.classname == '') ? 65 classname = (parent.classname == '') ?
71 descriptor.name : '${parent.classname}_${descriptor.name}', 66 descriptor.name : '${parent.classname}_${descriptor.name}',
72 fqname = (parent == null || parent.fqname == null) ? descriptor.name : 67 fqname = (parent == null || parent.fqname == null) ? descriptor.name :
73 (parent.fqname == '.' ? 68 (parent.fqname == '.' ?
74 '.${descriptor.name}' : '${parent.fqname}.${descriptor.name}'), 69 '.${descriptor.name}' : '${parent.fqname}.${descriptor.name}'),
75 implementsMap = _shouldImplementMap(descriptor, implementMapByDefault) { 70 mixin = _getMixin(descriptor, defaultMixin) {
76 _context.register(this); 71 _context.register(this);
77 72
78 for (EnumDescriptorProto e in _descriptor.enumType) { 73 for (EnumDescriptorProto e in _descriptor.enumType) {
79 _enumGenerators.add(new EnumGenerator(e, this, _context)); 74 _enumGenerators.add(new EnumGenerator(e, this, _context));
80 } 75 }
81 76
82 for (DescriptorProto n in _descriptor.nestedType) { 77 for (DescriptorProto n in _descriptor.nestedType) {
83 _messageGenerators.add( 78 _messageGenerators.add(
84 new MessageGenerator(n, this, _context, implementMapByDefault)); 79 new MessageGenerator(n, this, _context, defaultMixin));
85 } 80 }
86 81
87 for (FieldDescriptorProto x in _descriptor.extension) { 82 for (FieldDescriptorProto x in _descriptor.extension) {
88 _extensionGenerators.add(new ExtensionGenerator(x, this, _context)); 83 _extensionGenerators.add(new ExtensionGenerator(x, this, _context));
89 } 84 }
90 } 85 }
91 86
92 String get package => _parent.package; 87 String get package => _parent.package;
93 88
94 bool get needsMapMixinImport {
95 if (implementsMap) return true;
96
97 for (var m in _messageGenerators) {
98 if (m.implementsMap) return true;
99 }
100
101 return false;
102 }
103
104 void initializeFields() { 89 void initializeFields() {
105 _fieldList.clear(); 90 _fieldList.clear();
106 for (FieldDescriptorProto field in _descriptor.field) { 91 for (FieldDescriptorProto field in _descriptor.field) {
107 _fieldList.add(new ProtobufField(field, this, _context)); 92 _fieldList.add(new ProtobufField(field, this, _context));
108 } 93 }
109 for (MessageGenerator m in _messageGenerators) { 94 for (MessageGenerator m in _messageGenerators) {
110 m.initializeFields(); 95 m.initializeFields();
111 } 96 }
112 } 97 }
113 98
114 void generate(IndentingWriter out) { 99 void generate(IndentingWriter out) {
115 _methodNames.clear(); 100 _methodNames.clear();
116 _methodNames.addAll(reservedWords); 101 _methodNames.addAll(reservedWords);
117 _methodNames.addAll(reservedNames); 102 _methodNames.addAll(reservedNames);
118 103
119 if (implementsMap) { 104 if (mixin != null) {
120 _methodNames.addAll(reservedNamesForMap); 105 _methodNames.addAll(reservedNamesForMixins[mixin]);
121 } 106 }
122 107
123 for (EnumGenerator e in _enumGenerators) { 108 for (EnumGenerator e in _enumGenerators) {
124 e.generate(out); 109 e.generate(out);
125 } 110 }
126 111
127 for (MessageGenerator m in _messageGenerators) { 112 for (MessageGenerator m in _messageGenerators) {
128 m.generate(out); 113 m.generate(out);
129 } 114 }
130 115
131 var implClause = ""; 116 var mixinClause = "";
132 if (implementsMap) { 117 if (mixin != null) {
133 implClause = " with MapMixin"; 118 mixinClause = " with ${mixin}";
Søren Gjesse 2015/06/22 18:29:38 The new approach currently does not require/suppor
skybrian 2015/06/23 02:21:25 It didn't because the PbMapMixin was in the protob
134 } 119 }
135 120
136 out.addBlock('class ${classname} extends GeneratedMessage${implClause} {', 121 out.addBlock('class ${classname} extends GeneratedMessage${mixinClause} {',
137 '}', () 122 '}', ()
138 { 123 {
139 out.addBlock( 124 out.addBlock(
140 'static final BuilderInfo _i = new BuilderInfo(\'${classname}\')', 125 'static final BuilderInfo _i = new BuilderInfo(\'${classname}\')',
141 ';', () { 126 ';', () {
142 for (ProtobufField field in _fieldList) { 127 for (ProtobufField field in _fieldList) {
143 String type = field.shortTypeName; 128 String type = field.shortTypeName;
144 String fieldType = field.baseTypeForPackage(package); 129 String fieldType = field.baseTypeForPackage(package);
145 130
146 String makeDefault = null; 131 String makeDefault = null;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 '${SP}new ${classname}()..mergeFromMessage(this);'); 201 '${SP}new ${classname}()..mergeFromMessage(this);');
217 202
218 out.println('BuilderInfo get info_${SP}=>${SP}_i;'); 203 out.println('BuilderInfo get info_${SP}=>${SP}_i;');
219 204
220 // Factory functions which can be used as default value closures. 205 // Factory functions which can be used as default value closures.
221 out.println('static ${classname}${SP}create()${SP}=>' 206 out.println('static ${classname}${SP}create()${SP}=>'
222 '${SP}new ${classname}();'); 207 '${SP}new ${classname}();');
223 out.println('static PbList<${classname}>${SP}createRepeated()${SP}=>' 208 out.println('static PbList<${classname}>${SP}createRepeated()${SP}=>'
224 '${SP}new PbList<${classname}>();'); 209 '${SP}new PbList<${classname}>();');
225 210
226
227 if (implementsMap) {
228 // clear() is inherited from GeneratedMessage.
229 // Other map operations are implemented by MapMixin.
230 out.println('''
231 @override
232 operator [] (key) {
233 if (key is !String) return null;
234 if (!key.contains(".")) {
235 var tag = getTagNumber(key);
236 if (tag == null) return null;
237 return getField(tag);
238 }
239
240 var keys = key.split('.');
241 var item = this;
242 for (var key in keys) {
243 if (item is !GeneratedMessage) return null;
244 var tag = item.getTagNumber(key);
245 if (tag == null) return null;
246 item = item.getField(tag);
247 }
248
249 return item;
250 }
251
252 @override
253 operator []= (String key, val) {
254 if (!key.contains(".")) {
255 var tag = _mustGetTagNumber(this, key);
256 setField(tag, val);
257 return;
258 }
259
260 var keys = key.split('.');
261 var lastKey = keys.removeLast();
262 var item = this;
263 for (var key in keys) {
264 var tag = _mustGetTagNumber(item, key);
265 item = item.getField(tag);
266 if (item is !GeneratedMessage) {
267 throw new ArgumentError(
268 "field '\${key}' in \${info._messageName} isn't a GeneratedMessage:");
269 }
270 }
271 var tag = _mustGetTagNumber(item, lastKey);
272 item.setField(tag, val);
273 }
274
275 _mustGetTagNumber(GeneratedMessage msg, String key) {
276 var tag = msg.getTagNumber(key);
277 if (tag == null) {
278 throw new ArgumentError(
279 "field '\${key}' not found in \${msg.info_.messageName}");
280 }
281 return tag;
282 }
283
284 @override
285 get keys => info_.byName.keys;
286
287 @override
288 get length => info_.byName.length;
289
290 remove(key) {
291 throw new UnsupportedError("remove() not supported by \${info_.messageName}");
292 }
293 ''');
294 }
295
296 generateFieldsAccessorsMutators(out); 211 generateFieldsAccessorsMutators(out);
297 }); 212 });
298 out.println(); 213 out.println();
299 } 214 }
300 215
301 // Returns true if the message type has any required fields. If it doesn't, 216 // Returns true if the message type has any required fields. If it doesn't,
302 // we can optimize out calls to its isInitialized()/_findInvalidFields() 217 // we can optimize out calls to its isInitialized()/_findInvalidFields()
303 // methods. 218 // methods.
304 // 219 //
305 // already_seen is used to avoid checking the same type multiple times 220 // already_seen is used to avoid checking the same type multiple times
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 '(${fieldTypeString} v)${SP}' 286 '(${fieldTypeString} v)${SP}'
372 '{${SP}setField(${field.number},${SP}v);${SP}}'); 287 '{${SP}setField(${field.number},${SP}v);${SP}}');
373 out.println('bool $hasIdentifier()${SP}=>' 288 out.println('bool $hasIdentifier()${SP}=>'
374 '${SP}hasField(${field.number});'); 289 '${SP}hasField(${field.number});');
375 out.println('void $clearIdentifier()${SP}=>' 290 out.println('void $clearIdentifier()${SP}=>'
376 '${SP}clearField(${field.number});'); 291 '${SP}clearField(${field.number});');
377 } 292 }
378 } 293 }
379 } 294 }
380 } 295 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698