OLD | NEW |
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 /// A Dart function called on each item added to a repeated list | |
8 /// to check its type and range. | |
9 const checkItem = '\$checkItem'; | |
10 | |
11 class MessageGenerator extends ProtobufContainer { | 7 class MessageGenerator extends ProtobufContainer { |
12 // List of Dart language reserved words in names which cannot be used in a | |
13 // subclass of GeneratedMessage. | |
14 static final List<String> reservedWords = [ | |
15 'assert', | |
16 'break', | |
17 'case', | |
18 'catch', | |
19 'class', | |
20 'const', | |
21 'continue', | |
22 'default', | |
23 'do', | |
24 'else', | |
25 'enum', | |
26 'extends', | |
27 'false', | |
28 'final', | |
29 'finally', | |
30 'for', | |
31 'if', | |
32 'in', | |
33 'is', | |
34 'new', | |
35 'null', | |
36 'rethrow', | |
37 'return', | |
38 'super', | |
39 'switch', | |
40 'this', | |
41 'throw', | |
42 'true', | |
43 'try', | |
44 'var', | |
45 'void', | |
46 'while', | |
47 'with' | |
48 ]; | |
49 | |
50 // List of names used in the generated class itself | |
51 static final List<String> generatedNames = [ | |
52 'create', | |
53 'createRepeated', | |
54 'getDefault', | |
55 checkItem | |
56 ]; | |
57 | |
58 // Returns the mixin for this message, or null if none. | 8 // Returns the mixin for this message, or null if none. |
59 static PbMixin _getMixin(DescriptorProto desc, PbMixin defaultValue) { | 9 static PbMixin _getMixin(DescriptorProto desc, PbMixin defaultValue) { |
60 if (!desc.hasOptions()) return defaultValue; | 10 if (!desc.hasOptions()) return defaultValue; |
61 if (!desc.options.hasExtension(Dart_options.mixin)) return defaultValue; | 11 if (!desc.options.hasExtension(Dart_options.mixin)) return defaultValue; |
62 | 12 |
63 String name = desc.options.getExtension(Dart_options.mixin); | 13 String name = desc.options.getExtension(Dart_options.mixin); |
64 if (name.isEmpty) return null; // don't use a mixin (override any default) | 14 if (name.isEmpty) return null; // don't use a mixin (override any default) |
65 var mixin = findMixin(name); | 15 var mixin = findMixin(name); |
66 if (mixin == null) { | 16 if (mixin == null) { |
67 throw ("unknown mixin class: ${name}"); | 17 throw ("unknown mixin class: ${name}"); |
68 } | 18 } |
69 return mixin; | 19 return mixin; |
70 } | 20 } |
71 | 21 |
72 final String classname; | 22 final String classname; |
73 final String fqname; | 23 final String fqname; |
74 final PbMixin mixin; | 24 final PbMixin mixin; |
75 | 25 |
76 final ProtobufContainer _parent; | 26 final ProtobufContainer _parent; |
77 final DescriptorProto _descriptor; | 27 final DescriptorProto _descriptor; |
78 final List<EnumGenerator> _enumGenerators = <EnumGenerator>[]; | 28 final List<EnumGenerator> _enumGenerators = <EnumGenerator>[]; |
79 final List<MessageGenerator> _messageGenerators = <MessageGenerator>[]; | 29 final List<MessageGenerator> _messageGenerators = <MessageGenerator>[]; |
80 final List<ExtensionGenerator> _extensionGenerators = <ExtensionGenerator>[]; | 30 final List<ExtensionGenerator> _extensionGenerators = <ExtensionGenerator>[]; |
81 | 31 |
82 // populated by resolve() | 32 // populated by resolve() |
83 List<ProtobufField> _fieldList; | 33 List<ProtobufField> _fieldList; |
84 | 34 |
85 // Used during generation. | |
86 final Set<String> _methodNames = new Set<String>(); | |
87 | |
88 MessageGenerator(DescriptorProto descriptor, ProtobufContainer parent, | 35 MessageGenerator(DescriptorProto descriptor, ProtobufContainer parent, |
89 PbMixin defaultMixin) | 36 PbMixin defaultMixin) |
90 : _descriptor = descriptor, | 37 : _descriptor = descriptor, |
91 _parent = parent, | 38 _parent = parent, |
92 classname = (parent.classname == '') | 39 classname = (parent.classname == '') |
93 ? descriptor.name | 40 ? descriptor.name |
94 : '${parent.classname}_${descriptor.name}', | 41 : '${parent.classname}_${descriptor.name}', |
95 fqname = (parent == null || parent.fqname == null) | 42 fqname = (parent == null || parent.fqname == null) |
96 ? descriptor.name | 43 ? descriptor.name |
97 : (parent.fqname == '.' | 44 : (parent.fqname == '.' |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 } | 98 } |
152 for (var e in _enumGenerators) { | 99 for (var e in _enumGenerators) { |
153 e.register(ctx); | 100 e.register(ctx); |
154 } | 101 } |
155 } | 102 } |
156 | 103 |
157 // Creates fields and resolves extension targets. | 104 // Creates fields and resolves extension targets. |
158 void resolve(GenerationContext ctx) { | 105 void resolve(GenerationContext ctx) { |
159 if (_fieldList != null) throw new StateError("message already resolved"); | 106 if (_fieldList != null) throw new StateError("message already resolved"); |
160 | 107 |
161 var sorted = new List<FieldDescriptorProto>.from(_descriptor.field) | 108 var reserved = mixin?.findReservedNames() ?? const <String>[]; |
162 ..sort((FieldDescriptorProto a, FieldDescriptorProto b) { | 109 var fields = messageFieldNames(_descriptor, reserved: reserved); |
163 if (a.number < b.number) return -1; | |
164 if (a.number > b.number) return 1; | |
165 throw "multiple fields defined for tag ${a.number} in $fqname"; | |
166 }); | |
167 | 110 |
168 _fieldList = <ProtobufField>[]; | 111 _fieldList = <ProtobufField>[]; |
169 for (FieldDescriptorProto field in sorted) { | 112 for (MemberNames names in fields.values) { |
170 int index = _fieldList.length; | 113 _fieldList.add(new ProtobufField.message(names, this, ctx)); |
171 _fieldList.add(new ProtobufField(field, index, this, ctx)); | |
172 } | 114 } |
173 | 115 |
174 for (var m in _messageGenerators) { | 116 for (var m in _messageGenerators) { |
175 m.resolve(ctx); | 117 m.resolve(ctx); |
176 } | 118 } |
177 for (var x in _extensionGenerators) { | 119 for (var x in _extensionGenerators) { |
178 x.resolve(ctx); | 120 x.resolve(ctx); |
179 } | 121 } |
180 } | 122 } |
181 | 123 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 m.addConstantImportsTo(imports); | 177 m.addConstantImportsTo(imports); |
236 } | 178 } |
237 for (var x in _extensionGenerators) { | 179 for (var x in _extensionGenerators) { |
238 x.addConstantImportsTo(imports); | 180 x.addConstantImportsTo(imports); |
239 } | 181 } |
240 } | 182 } |
241 | 183 |
242 void generate(IndentingWriter out) { | 184 void generate(IndentingWriter out) { |
243 checkResolved(); | 185 checkResolved(); |
244 | 186 |
245 _methodNames.clear(); | |
246 _methodNames.addAll(reservedWords); | |
247 _methodNames.addAll(GeneratedMessage_reservedNames); | |
248 _methodNames.addAll(generatedNames); | |
249 | |
250 if (mixin != null) { | |
251 _methodNames.addAll(mixin.findReservedNames()); | |
252 } | |
253 | |
254 for (MessageGenerator m in _messageGenerators) { | 187 for (MessageGenerator m in _messageGenerators) { |
255 m.generate(out); | 188 m.generate(out); |
256 } | 189 } |
257 | 190 |
258 var mixinClause = ''; | 191 var mixinClause = ''; |
259 if (mixin != null) { | 192 if (mixin != null) { |
260 var mixinNames = mixin.findMixinsToApply().map((m) => m.name); | 193 var mixinNames = mixin.findMixinsToApply().map((m) => m.name); |
261 mixinClause = ' with ${mixinNames.join(", ")}'; | 194 mixinClause = ' with ${mixinNames.join(", ")}'; |
262 } | 195 } |
263 | 196 |
264 out.addBlock( | 197 out.addBlock( |
265 'class ${classname} extends GeneratedMessage${mixinClause} {', '}', () { | 198 'class ${classname} extends GeneratedMessage${mixinClause} {', '}', () { |
266 out.addBlock( | 199 out.addBlock( |
267 'static final BuilderInfo _i = new BuilderInfo(\'${classname}\')', | 200 'static final BuilderInfo _i = new BuilderInfo(\'${classname}\')', |
268 ';', () { | 201 ';', () { |
269 for (ProtobufField field in _fieldList) { | 202 for (ProtobufField field in _fieldList) { |
270 out.println(field.generateBuilderInfoCall(package)); | 203 var dartFieldName = field.memberNames.fieldName; |
| 204 out.println(field.generateBuilderInfoCall(package, dartFieldName)); |
271 } | 205 } |
272 | 206 |
273 if (_descriptor.extensionRange.length > 0) { | 207 if (_descriptor.extensionRange.length > 0) { |
274 out.println('..hasExtensions = true'); | 208 out.println('..hasExtensions = true'); |
275 } | 209 } |
276 if (!_hasRequiredFields(this, new Set())) { | 210 if (!_hasRequiredFields(this, new Set())) { |
277 out.println('..hasRequiredFields = false'); | 211 out.println('..hasRequiredFields = false'); |
278 } | 212 } |
279 }); | 213 }); |
280 | 214 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 } | 293 } |
360 } | 294 } |
361 } | 295 } |
362 return false; | 296 return false; |
363 } | 297 } |
364 | 298 |
365 void generateFieldsAccessorsMutators(IndentingWriter out) { | 299 void generateFieldsAccessorsMutators(IndentingWriter out) { |
366 for (ProtobufField field in _fieldList) { | 300 for (ProtobufField field in _fieldList) { |
367 out.println(); | 301 out.println(); |
368 | 302 |
369 // Choose non-conflicting names. | |
370 String identifier = field.dartFieldName; | |
371 String hasIdentifier = field.hasMethodName; | |
372 String clearIdentifier = field.clearMethodName; | |
373 if (!field.isRepeated) { | |
374 while (_methodNames.contains(identifier) || | |
375 _methodNames.contains(hasIdentifier) || | |
376 _methodNames.contains(clearIdentifier)) { | |
377 identifier += '_' + field.number.toString(); | |
378 hasIdentifier += '_' + field.number.toString(); | |
379 clearIdentifier += '_' + field.number.toString(); | |
380 } | |
381 _methodNames.add(identifier); | |
382 _methodNames.add(hasIdentifier); | |
383 _methodNames.add(clearIdentifier); | |
384 } else { | |
385 while (_methodNames.contains(identifier)) { | |
386 identifier += '_' + field.number.toString(); | |
387 } | |
388 _methodNames.add(identifier); | |
389 } | |
390 | |
391 var fieldTypeString = field.getDartType(package); | 303 var fieldTypeString = field.getDartType(package); |
392 var defaultExpr = field.getDefaultExpr(); | 304 var defaultExpr = field.getDefaultExpr(); |
393 out.println('${fieldTypeString} get ${identifier}' | 305 var names = field.memberNames; |
| 306 |
| 307 out.println('${fieldTypeString} get ${names.fieldName}' |
394 ' => \$_get(' | 308 ' => \$_get(' |
395 '${field.index}, ${field.number}, $defaultExpr);'); | 309 '${field.index}, ${field.number}, $defaultExpr);'); |
396 if (!field.isRepeated) { | 310 if (!field.isRepeated) { |
397 var fastSetter = field.baseType.setter; | 311 var fastSetter = field.baseType.setter; |
398 if (fastSetter != null) { | 312 if (fastSetter != null) { |
399 out.println('void set $identifier' | 313 out.println('void set ${names.fieldName}' |
400 '($fieldTypeString v) { ' | 314 '($fieldTypeString v) { ' |
401 '$fastSetter(${field.index}, ${field.number}, v);' | 315 '$fastSetter(${field.index}, ${field.number}, v);' |
402 ' }'); | 316 ' }'); |
403 } else { | 317 } else { |
404 out.println('void set $identifier' | 318 out.println('void set ${names.fieldName}' |
405 '($fieldTypeString v) { ' | 319 '($fieldTypeString v) { ' |
406 'setField(${field.number}, v);' | 320 'setField(${field.number}, v);' |
407 ' }'); | 321 ' }'); |
408 } | 322 } |
409 out.println('bool $hasIdentifier() =>' | 323 out.println('bool ${names.hasMethodName}() =>' |
410 ' \$_has(${field.index}, ${field.number});'); | 324 ' \$_has(${field.index}, ${field.number});'); |
411 out.println('void $clearIdentifier() =>' | 325 out.println('void ${names.clearMethodName}() =>' |
412 ' clearField(${field.number});'); | 326 ' clearField(${field.number});'); |
413 } | 327 } |
414 } | 328 } |
415 } | 329 } |
416 | 330 |
417 void generateEnums(IndentingWriter out) { | 331 void generateEnums(IndentingWriter out) { |
418 for (EnumGenerator e in _enumGenerators) { | 332 for (EnumGenerator e in _enumGenerators) { |
419 e.generate(out); | 333 e.generate(out); |
420 } | 334 } |
421 | 335 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 | 374 |
461 for (var m in _messageGenerators) { | 375 for (var m in _messageGenerators) { |
462 m.generateConstants(out); | 376 m.generateConstants(out); |
463 } | 377 } |
464 | 378 |
465 for (var e in _enumGenerators) { | 379 for (var e in _enumGenerators) { |
466 e.generateConstants(out); | 380 e.generateConstants(out); |
467 } | 381 } |
468 } | 382 } |
469 } | 383 } |
OLD | NEW |