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

Side by Side Diff: lib/protobuf/plugin/MessageGenerator.dart

Issue 10595002: Protocol Buffer runtime library and 'protoc' plugin (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Work around http://code.google.com/p/dart/issues/detail?id=3806 Created 8 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 | Annotate | Revision Log
« no previous file with comments | « lib/protobuf/plugin/IndentingWriter.dart ('k') | lib/protobuf/plugin/ProtoGenDartConfig.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
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.
4
5 class MessageGenerator implements ProtobufContainer {
6
7 // Variables controlling output prettiness
8 static final String sp = " ";
9 static final bool _blankLines = true;
10 static final bool _fieldComments = true;
11
12 String _builderClassname;
13 String _classname;
14 GenerationContext _context;
15 final GoogleProtobuf_DescriptorProto _descriptor;
16 List<EnumGenerator> _enumGenerators;
17 List<ProtobufField> _fieldList;
18 String _fqname;
19 List<MessageGenerator> _messageGenerators;
20 List<ExtensionGenerator> _extensionGenerators;
21 GoogleProtobuf_FileOptions_OptimizeMode _optimizeFor;
22 ProtobufContainer _parent;
23
24 String get classname() => _classname;
25 String get fqname() => _fqname;
26 GoogleProtobuf_FileOptions_OptimizeMode get optimizeFor() => _optimizeFor;
27
28 MessageGenerator(GoogleProtobuf_DescriptorProto this._descriptor,
29 ProtobufContainer this._parent, GenerationContext this._context) {
30 String name = _descriptor.name;
31 _classname = (_parent === null || _parent.classname == "") ?
32 name :
33 "${_parent.classname}_${name}";
34
35 _builderClassname = "${_classname}_Builder";
36 _fqname = (_parent === null || _parent.fqname === null) ? _descriptor.name :
37 ( _parent.fqname == "." ?
38 ".${_descriptor.name}" :
39 "${_parent.fqname}.${_descriptor.name}" );
40 _optimizeFor = _parent != null ? _parent.optimizeFor : null;
41 _context.register(this);
42
43 _fieldList = [];
44
45 _enumGenerators = new List<EnumGenerator>();
46 for (GoogleProtobuf_EnumDescriptorProto e in _descriptor.enumType) {
47 _enumGenerators.add(new EnumGenerator(e, this, _context));
48 }
49
50 _messageGenerators = new List<MessageGenerator>();
51 for (GoogleProtobuf_DescriptorProto n in _descriptor.nestedType) {
52 _messageGenerators.add(new MessageGenerator(n, this, _context));
53 }
54
55 _extensionGenerators = new List<ExtensionGenerator>();
56 for (GoogleProtobuf_FieldDescriptorProto x in _descriptor.extension) {
57 _extensionGenerators.add(new ExtensionGenerator(x, this, _context));
58 }
59 }
60
61 void initializeFields() {
62 _fieldList = [];
63 ProtobufField._resetIndices();
64 for (GoogleProtobuf_FieldDescriptorProto field in _descriptor.field) {
65 _fieldList.add(new ProtobufField(field, _context));
66 }
67 for (MessageGenerator m in _messageGenerators) {
68 m.initializeFields();
69 }
70 }
71
72 void generate(IndentingWriter out,
73 [List<ExtensionGenerator> allExtensions = null]) {
74 for (EnumGenerator e in _enumGenerators) {
75 e.generate(out);
76 }
77
78 for (MessageGenerator m in _messageGenerators) {
79 m.generate(out, allExtensions);
80 }
81
82 out.addBlock("class ${_classname} extends GeneratedMessage${sp}{", "}", (){
83 for (ExtensionGenerator x in _extensionGenerators) {
84 if (allExtensions != null) {
85 allExtensions.add(x);
86 }
87 x.generate(out);
88 }
89
90 out.println("static ${_classname} _d;");
91 out.println("static ${_builderClassname} newBuilder()${sp}=>"
92 "${sp}new ${_builderClassname}();");
93 out.println("static ${_classname} get defaultInstance()${sp}=>"
94 "${sp}null${sp}==${sp}_d${sp}?${sp}(_d${sp}=${sp}newBuilder()."
95 "buildPartial())${sp}:${sp}_d;");
96 out.println("static ${_classname} parseFromBuffer(List<int> i,"
97 "${sp}[ExtensionRegistry r])"
98 "${sp}=>${sp}GeneratedMessage.parseBuffer(newBuilder(),"
99 "${sp}i,${sp}r);");
100 out.println("static Future<${_classname}> parseFromStream("
101 "InputStream i,${sp}[ExtensionRegistry r])${sp}=>${sp}"
102 "GeneratedMessage.parseStream(newBuilder(),${sp}i,${sp}r);");
103 out.println("static ${_classname} parseFromJson("
104 "String i,"
105 "${sp}[ExtensionRegistry r])"
106 "${sp}=>${sp}GeneratedMessage.parseJson(newBuilder(),${sp}i,${sp}r);");
107 out.println("${_classname}._fromBuilder(${_builderClassname} b)"
108 "${sp}:${sp}super(b);");
109 out.println("${_builderClassname} toBuilder()"
110 "${sp}=>${sp}newBuilder().mergeFromMessage(this);");
111
112 generateFields(out);
113 });
114
115 // -------------------------- BUILDER --------------------------
116 out.blankLine();
117 out.addBlock("class ${_builderClassname} extends Builder${sp}{",
118 "}", ()
119 {
120 out.println("static BuilderInfo _i;");
121
122 if (_blankLines) {
123 out.blankLine();
124 }
125 out.addBlock("void initialize_()${sp}{","}",(){
126 out.addBlock("if${sp}(null${sp}==${sp}_i)${sp}{", "}", () {
127 out.println("_i${sp}=${sp}new BuilderInfo(this,${sp}"
128 "\"${_classname}\");");
129
130 for (ProtobufField field in _fieldList) {
131 String type = field.shortTypeName;
132
133 String makeDefault = null;
134 if (field.hasInitialization) {
135 makeDefault = "${field.initialization}";
136 }
137 String subBuilder = null;
138 if (field.message || field.group) {
139 subBuilder = "()${sp}=>${sp}new ${field.baseType}_Builder()";
140 }
141 String valueOf = null;
142 if (field.enum) {
143 valueOf = "(var v)${sp}=>${sp}${field.baseType}.valueOf(v)";
144 }
145 if ("PM" == type) {
146 // Repeated message: default is an empty list
147 out.println("_i.m(${field.number},${sp}'"
148 "${field.externalFieldName}',${sp}$subBuilder,"
149 "${sp}()${sp}=>${sp}new PbList<${field.baseType}>(this));");
150 } else if (type[0] == "P" && type != "PG" && type != "PE") {
151 // Repeated, not a message or enum: default is an empty list,
152 // subBuilder is null, valueOf is null
153 out.println("_i.p(${field.number},${sp}"
154 "'${field.externalFieldName}',${sp}Builder.$type);");
155 } else if (type == "OE" || type == "QE") {
156 out.println("_i.e(${field.number},${sp}"
157 "'${field.externalFieldName}',${sp}Builder.$type,"
158 "${sp}$makeDefault,${sp}$valueOf);");
159 } else {
160 if (makeDefault == null && subBuilder == null && valueOf == null) {
161 out.println("_i.a(${field.number},${sp}"
162 "'${field.externalFieldName}',${sp}Builder.$type);");
163 } else if (subBuilder == null && valueOf == null) {
164 out.println("_i.a(${field.number},${sp}"
165 "'${field.externalFieldName}',${sp}Builder.$type,"
166 "${sp}$makeDefault);");
167 } else if (valueOf == null) {
168 out.println("_i.a(${field.number},${sp}"
169 "'${field.externalFieldName}',${sp}Builder.$type,"
170 "${sp}$makeDefault,${sp}$subBuilder);");
171 } else {
172 out.println("_i.a(${field.number},${sp}"
173 "'${field.externalFieldName}',${sp}Builder.$type,"
174 "${sp}$makeDefault,${sp}$subBuilder,${sp}$valueOf);");
175 }
176 }
177 }
178
179 if (_descriptor.extensionRange.length > 0) {
180 out.println("_i.hasExtensions${sp}=${sp}true;");
181 }
182 if (!_hasRequiredFields(this, new Set())) {
183 out.println("_i.hasRequiredFields${sp}=${sp}false;");
184 }
185 });
186 });
187
188 if (_blankLines) {
189 out.blankLine();
190 }
191 out.println("$_classname build()${sp}=>${sp}super.build();");
192 out.println("$_classname buildPartial()${sp}=>${sp}"
193 "partial(new ${_classname}._fromBuilder(this));");
194 out.println("BuilderInfo get info_()${sp}=>${sp}_i;");
195
196 generateFieldsAccessorsMutators(out);
197 });
198 out.blankLine();
199 }
200
201 void generateFields(IndentingWriter out) {
202
203 //
204 // Disable 'noSuchMethod' dependency for now until dart2js code generation
205 // improves
206 //
207
208 // if (optimizeFor == GoogleProtobuf_FileOptions_OptimizeMode.SPEED) {
209 for (ProtobufField field in _fieldList) {
210 if (_blankLines) {
211 out.blankLine();
212 }
213
214 String label = field.label.name.substring(6).toLowerCase();
215 String type = field.type.name.substring(5).toLowerCase();
216 if ("message" == type || "group" == type) {
217 type = field.typeName.substring(1);
218 }
219 String options = "";
220 if ((field.options != null) && field.options.packed) {
221 if (options.length == 0) {
222 options = " [";
223 }
224 options = "${options}packed=true";
225 }
226 if (options.length > 0) {
227 options = "${options}]";
228 }
229 if (_fieldComments) {
230 out.println("// $label $type ${field.name}${sp}=${sp}"
231 "${field.number}${options};");
232 }
233 out.println(
234 "${field.typeString} get ${field.externalFieldName}()${sp}=>"
235 "${sp}g_(${field.number});");
236 if (field.single) {
237 out.println("bool has${field.titlecaseFieldName}()${sp}=>"
238 "${sp}h_(${field.number});");
239 }
240 // }
241 }
242 }
243
244 // Returns true if the message type has any required fields. If it doesn't,
245 // we can optimize out calls to its isInitialized()/_findInvalidFields()
246 // methods.
247 //
248 // already_seen is used to avoid checking the same type multiple times
249 // (and also to protect against unbounded recursion).
250 bool _hasRequiredFields(MessageGenerator type, Set alreadySeen) {
251 if (alreadySeen.contains(type._fqname)) {
252 // The type is already in cache. This means that either:
253 // a. The type has no required fields.
254 // b. We are in the midst of checking if the type has required fields,
255 // somewhere up the stack. In this case, we know that if the type
256 // has any required fields, they'll be found when we return to it,
257 // and the whole call to HasRequiredFields() will return true.
258 // Therefore, we don't have to check if this type has required fields
259 // here.
260 return false;
261 }
262 alreadySeen.add(type._fqname);
263 // If the type has extensions, an extension with message type could contain
264 // required fields, so we have to be conservative and assume such an
265 // extension exists.
266 if (type._descriptor.extensionRange.length > 0) {
267 return true;
268 }
269
270 for (ProtobufField field in type._fieldList) {
271 if (field.required) {
272 return true;
273 }
274 if (field.message) {
275 ProtobufContainer messageType = _context[field.typeName];
276 if (messageType != null && messageType is MessageGenerator) {
277 if (_hasRequiredFields(messageType, alreadySeen)) {
278 return true;
279 }
280 }
281 }
282 }
283 return false;
284 }
285
286 void generateFieldsAccessorsMutators(IndentingWriter out) {
287 for (ProtobufField field in _fieldList) {
288 //
289 // Disable code size optimization for now until dart2js code generation
290 // is better able to handle 'noSuchMethod'
291 //
292
293 // if (optimizeFor == GoogleProtobuf_FileOptions_OptimizeMode.SPEED) {
294 if (_blankLines) {
295 out.blankLine();
296 }
297 out.println("${field.typeString} get ${field.externalFieldName}()"
298 "${sp}=>${sp}g_(${field.number});");
299 if (field.single) {
300 out.println("void set ${field.externalFieldName}"
301 "(${field.typeString} v)${sp}"
302 "{${sp}s_(${field.number},${sp}v);${sp}}");
303 out.println("bool has${field.titlecaseFieldName}()${sp}=>"
304 "${sp}h_(${field.number});");
305 out.println("void clear${field.titlecaseFieldName}()${sp}=>"
306 "${sp}c_(${field.number});");
307 }
308 // }
309 }
310 }
311 }
OLDNEW
« no previous file with comments | « lib/protobuf/plugin/IndentingWriter.dart ('k') | lib/protobuf/plugin/ProtoGenDartConfig.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698