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

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: made mixins more general 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 PbMixin _getMixin(DescriptorProto desc, PbMixin 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 var mixin = findMixin(name);
42 // Returns true if the implement_map option is turned on for the message. 42 if (mixin == null) {
43 static bool _shouldImplementMap(DescriptorProto desc, bool defaultValue) { 43 throw("unknown mixin class: ${name}");
44 if (!desc.hasOptions()) return defaultValue; 44 }
45 45 return mixin;
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 } 46 }
51 47
52 final String classname; 48 final String classname;
53 final String fqname; 49 final String fqname;
54 final bool implementsMap; 50 final PbMixin mixin;
55 51
56 final ProtobufContainer _parent; 52 final ProtobufContainer _parent;
57 final GenerationContext _context; 53 final GenerationContext _context;
58 final DescriptorProto _descriptor; 54 final DescriptorProto _descriptor;
59 final List<EnumGenerator> _enumGenerators = <EnumGenerator>[]; 55 final List<EnumGenerator> _enumGenerators = <EnumGenerator>[];
60 final List<ProtobufField> _fieldList = <ProtobufField>[]; 56 final List<ProtobufField> _fieldList = <ProtobufField>[];
61 final List<MessageGenerator> _messageGenerators = <MessageGenerator>[]; 57 final List<MessageGenerator> _messageGenerators = <MessageGenerator>[];
62 final List<ExtensionGenerator> _extensionGenerators = <ExtensionGenerator>[]; 58 final List<ExtensionGenerator> _extensionGenerators = <ExtensionGenerator>[];
63 final Set<String> _methodNames = new Set<String>(); 59 final Set<String> _methodNames = new Set<String>();
64 60
65 MessageGenerator( 61 MessageGenerator(
66 DescriptorProto descriptor, ProtobufContainer parent, this._context, 62 DescriptorProto descriptor, ProtobufContainer parent, this._context,
67 bool implementMapByDefault) 63 PbMixin defaultMixin)
68 : _descriptor = descriptor, 64 : _descriptor = descriptor,
69 _parent = parent, 65 _parent = parent,
70 classname = (parent.classname == '') ? 66 classname = (parent.classname == '') ?
71 descriptor.name : '${parent.classname}_${descriptor.name}', 67 descriptor.name : '${parent.classname}_${descriptor.name}',
72 fqname = (parent == null || parent.fqname == null) ? descriptor.name : 68 fqname = (parent == null || parent.fqname == null) ? descriptor.name :
73 (parent.fqname == '.' ? 69 (parent.fqname == '.' ?
74 '.${descriptor.name}' : '${parent.fqname}.${descriptor.name}'), 70 '.${descriptor.name}' : '${parent.fqname}.${descriptor.name}'),
75 implementsMap = _shouldImplementMap(descriptor, implementMapByDefault) { 71 mixin = _getMixin(descriptor, defaultMixin) {
76 _context.register(this); 72 _context.register(this);
77 73
78 for (EnumDescriptorProto e in _descriptor.enumType) { 74 for (EnumDescriptorProto e in _descriptor.enumType) {
79 _enumGenerators.add(new EnumGenerator(e, this, _context)); 75 _enumGenerators.add(new EnumGenerator(e, this, _context));
80 } 76 }
81 77
82 for (DescriptorProto n in _descriptor.nestedType) { 78 for (DescriptorProto n in _descriptor.nestedType) {
83 _messageGenerators.add( 79 _messageGenerators.add(
84 new MessageGenerator(n, this, _context, implementMapByDefault)); 80 new MessageGenerator(n, this, _context, defaultMixin));
85 } 81 }
86 82
87 for (FieldDescriptorProto x in _descriptor.extension) { 83 for (FieldDescriptorProto x in _descriptor.extension) {
88 _extensionGenerators.add(new ExtensionGenerator(x, this, _context)); 84 _extensionGenerators.add(new ExtensionGenerator(x, this, _context));
89 } 85 }
90 } 86 }
91 87
92 String get package => _parent.package; 88 String get package => _parent.package;
93 89
94 bool get needsMapMixinImport { 90 /// Adds all mixins used in this message and any submessages.
95 if (implementsMap) return true; 91 void addMixinsTo(Set<PbMixin> output) {
96 92 if (mixin != null) {
93 output.addAll(mixin.findMixinsToApply());
94 }
97 for (var m in _messageGenerators) { 95 for (var m in _messageGenerators) {
98 if (m.implementsMap) return true; 96 m.addMixinsTo(output);
99 } 97 }
100
101 return false;
102 } 98 }
103 99
104 void initializeFields() { 100 void initializeFields() {
105 _fieldList.clear(); 101 _fieldList.clear();
106 for (FieldDescriptorProto field in _descriptor.field) { 102 for (FieldDescriptorProto field in _descriptor.field) {
107 _fieldList.add(new ProtobufField(field, this, _context)); 103 _fieldList.add(new ProtobufField(field, this, _context));
108 } 104 }
109 for (MessageGenerator m in _messageGenerators) { 105 for (MessageGenerator m in _messageGenerators) {
110 m.initializeFields(); 106 m.initializeFields();
111 } 107 }
112 } 108 }
113 109
114 void generate(IndentingWriter out) { 110 void generate(IndentingWriter out) {
115 _methodNames.clear(); 111 _methodNames.clear();
116 _methodNames.addAll(reservedWords); 112 _methodNames.addAll(reservedWords);
117 _methodNames.addAll(reservedNames); 113 _methodNames.addAll(reservedNames);
118 114
119 if (implementsMap) { 115 if (mixin != null) {
120 _methodNames.addAll(reservedNamesForMap); 116 _methodNames.addAll(mixin.findReservedNames());
121 } 117 }
122 118
123 for (EnumGenerator e in _enumGenerators) { 119 for (EnumGenerator e in _enumGenerators) {
124 e.generate(out); 120 e.generate(out);
125 } 121 }
126 122
127 for (MessageGenerator m in _messageGenerators) { 123 for (MessageGenerator m in _messageGenerators) {
128 m.generate(out); 124 m.generate(out);
129 } 125 }
130 126
131 var implClause = ""; 127 var mixinClause = '';
132 if (implementsMap) { 128 if (mixin != null) {
133 implClause = " with MapMixin"; 129 var mixinNames = mixin.findMixinsToApply().map((m) => m.name);
130 mixinClause = ' with ${mixinNames.join(", ")}';
134 } 131 }
135 132
136 out.addBlock('class ${classname} extends GeneratedMessage${implClause} {', 133 out.addBlock('class ${classname} extends GeneratedMessage${mixinClause} {',
137 '}', () 134 '}', ()
138 { 135 {
139 out.addBlock( 136 out.addBlock(
140 'static final BuilderInfo _i = new BuilderInfo(\'${classname}\')', 137 'static final BuilderInfo _i = new BuilderInfo(\'${classname}\')',
141 ';', () { 138 ';', () {
142 for (ProtobufField field in _fieldList) { 139 for (ProtobufField field in _fieldList) {
143 String type = field.shortTypeName; 140 String type = field.shortTypeName;
144 String fieldType = field.baseTypeForPackage(package); 141 String fieldType = field.baseTypeForPackage(package);
145 142
146 String makeDefault = null; 143 String makeDefault = null;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 '${SP}new ${classname}()..mergeFromMessage(this);'); 213 '${SP}new ${classname}()..mergeFromMessage(this);');
217 214
218 out.println('BuilderInfo get info_${SP}=>${SP}_i;'); 215 out.println('BuilderInfo get info_${SP}=>${SP}_i;');
219 216
220 // Factory functions which can be used as default value closures. 217 // Factory functions which can be used as default value closures.
221 out.println('static ${classname}${SP}create()${SP}=>' 218 out.println('static ${classname}${SP}create()${SP}=>'
222 '${SP}new ${classname}();'); 219 '${SP}new ${classname}();');
223 out.println('static PbList<${classname}>${SP}createRepeated()${SP}=>' 220 out.println('static PbList<${classname}>${SP}createRepeated()${SP}=>'
224 '${SP}new PbList<${classname}>();'); 221 '${SP}new PbList<${classname}>();');
225 222
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); 223 generateFieldsAccessorsMutators(out);
297 }); 224 });
298 out.println(); 225 out.println();
299 } 226 }
300 227
301 // Returns true if the message type has any required fields. If it doesn't, 228 // Returns true if the message type has any required fields. If it doesn't,
302 // we can optimize out calls to its isInitialized()/_findInvalidFields() 229 // we can optimize out calls to its isInitialized()/_findInvalidFields()
303 // methods. 230 // methods.
304 // 231 //
305 // already_seen is used to avoid checking the same type multiple times 232 // 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}' 298 '(${fieldTypeString} v)${SP}'
372 '{${SP}setField(${field.number},${SP}v);${SP}}'); 299 '{${SP}setField(${field.number},${SP}v);${SP}}');
373 out.println('bool $hasIdentifier()${SP}=>' 300 out.println('bool $hasIdentifier()${SP}=>'
374 '${SP}hasField(${field.number});'); 301 '${SP}hasField(${field.number});');
375 out.println('void $clearIdentifier()${SP}=>' 302 out.println('void $clearIdentifier()${SP}=>'
376 '${SP}clearField(${field.number});'); 303 '${SP}clearField(${field.number});');
377 } 304 }
378 } 305 }
379 } 306 }
380 } 307 }
OLDNEW
« lib/file_generator.dart ('K') | « lib/file_generator.dart ('k') | lib/protoc.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698