Line data Source code
1 : // Protocol Buffers - Google's data interchange format
2 : // Copyright 2008 Google Inc. All rights reserved.
3 : // https://developers.google.com/protocol-buffers/
4 : //
5 : // Redistribution and use in source and binary forms, with or without
6 : // modification, are permitted provided that the following conditions are
7 : // met:
8 : //
9 : // * Redistributions of source code must retain the above copyright
10 : // notice, this list of conditions and the following disclaimer.
11 : // * Redistributions in binary form must reproduce the above
12 : // copyright notice, this list of conditions and the following disclaimer
13 : // in the documentation and/or other materials provided with the
14 : // distribution.
15 : // * Neither the name of Google Inc. nor the names of its
16 : // contributors may be used to endorse or promote products derived from
17 : // this software without specific prior written permission.
18 : //
19 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 :
31 : #include <sstream>
32 : #include <algorithm>
33 : #include <map>
34 :
35 : #include <google/protobuf/compiler/code_generator.h>
36 : #include <google/protobuf/compiler/plugin.h>
37 : #include <google/protobuf/descriptor.h>
38 : #include <google/protobuf/descriptor.pb.h>
39 : #include <google/protobuf/io/printer.h>
40 : #include <google/protobuf/io/zero_copy_stream.h>
41 : #include <google/protobuf/stubs/strutil.h>
42 : #include <google/protobuf/wire_format.h>
43 : #include <google/protobuf/wire_format_lite.h>
44 :
45 : #include <google/protobuf/compiler/csharp/csharp_enum.h>
46 : #include <google/protobuf/compiler/csharp/csharp_field_base.h>
47 : #include <google/protobuf/compiler/csharp/csharp_helpers.h>
48 : #include <google/protobuf/compiler/csharp/csharp_message.h>
49 : #include <google/protobuf/compiler/csharp/csharp_names.h>
50 :
51 : using google::protobuf::internal::scoped_ptr;
52 :
53 : namespace google {
54 : namespace protobuf {
55 : namespace compiler {
56 : namespace csharp {
57 :
58 0 : bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
59 0 : return d1->number() < d2->number();
60 : }
61 :
62 0 : MessageGenerator::MessageGenerator(const Descriptor* descriptor)
63 : : SourceGeneratorBase(descriptor->file()),
64 0 : descriptor_(descriptor) {
65 :
66 : // sorted field names
67 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
68 0 : field_names_.push_back(descriptor_->field(i)->name());
69 : }
70 0 : std::sort(field_names_.begin(), field_names_.end());
71 :
72 : // fields by number
73 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
74 0 : fields_by_number_.push_back(descriptor_->field(i));
75 : }
76 : std::sort(fields_by_number_.begin(), fields_by_number_.end(),
77 0 : CompareFieldNumbers);
78 0 : }
79 :
80 0 : MessageGenerator::~MessageGenerator() {
81 0 : }
82 :
83 0 : std::string MessageGenerator::class_name() {
84 0 : return descriptor_->name();
85 : }
86 :
87 0 : std::string MessageGenerator::full_class_name() {
88 0 : return GetClassName(descriptor_);
89 : }
90 :
91 0 : const std::vector<std::string>& MessageGenerator::field_names() {
92 0 : return field_names_;
93 : }
94 :
95 0 : const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() {
96 0 : return fields_by_number_;
97 : }
98 :
99 0 : void MessageGenerator::Generate(io::Printer* printer) {
100 : map<string, string> vars;
101 0 : vars["class_name"] = class_name();
102 0 : vars["access_level"] = class_access_level();
103 :
104 : printer->Print(
105 0 : "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
106 0 : WriteGeneratedCodeAttributes(printer);
107 : printer->Print(
108 : vars,
109 0 : "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n");
110 0 : printer->Indent();
111 :
112 : // All static fields and properties
113 : printer->Print(
114 : vars,
115 : "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n"
116 0 : "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
117 :
118 : // Access the message descriptor via the relevant file descriptor or containing message descriptor.
119 0 : if (!descriptor_->containing_type()) {
120 0 : vars["descriptor_accessor"] = GetUmbrellaClassName(descriptor_->file())
121 0 : + ".Descriptor.MessageTypes[" + SimpleItoa(descriptor_->index()) + "]";
122 : } else {
123 0 : vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
124 0 : + ".Descriptor.NestedTypes[" + SimpleItoa(descriptor_->index()) + "]";
125 : }
126 :
127 : printer->Print(
128 : vars,
129 : "public static pbr::MessageDescriptor Descriptor {\n"
130 : " get { return $descriptor_accessor$; }\n"
131 : "}\n"
132 : "\n"
133 : "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
134 : " get { return Descriptor; }\n"
135 : "}\n"
136 0 : "\n");
137 :
138 : // Parameterless constructor and partial OnConstruction method.
139 : printer->Print(
140 : vars,
141 : "public $class_name$() {\n"
142 : " OnConstruction();\n"
143 : "}\n\n"
144 0 : "partial void OnConstruction();\n\n");
145 :
146 0 : GenerateCloningCode(printer);
147 0 : GenerateFreezingCode(printer);
148 :
149 : // Fields/properties
150 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
151 0 : const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
152 :
153 : // Rats: we lose the debug comment here :(
154 : printer->Print(
155 : "public const int $field_constant_name$ = $index$;\n",
156 : "field_constant_name", GetFieldConstantName(fieldDescriptor),
157 0 : "index", SimpleItoa(fieldDescriptor->number()));
158 : scoped_ptr<FieldGeneratorBase> generator(
159 0 : CreateFieldGeneratorInternal(fieldDescriptor));
160 0 : generator->GenerateMembers(printer);
161 0 : printer->Print("\n");
162 : }
163 :
164 : // oneof properties
165 0 : for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
166 0 : vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
167 0 : vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
168 0 : vars["original_name"] = descriptor_->oneof_decl(i)->name();
169 : printer->Print(
170 : vars,
171 : "private object $name$_;\n"
172 0 : "public enum $property_name$OneofCase {\n");
173 0 : printer->Indent();
174 0 : printer->Print("None = 0,\n");
175 0 : for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
176 0 : const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
177 : printer->Print("$field_property_name$ = $index$,\n",
178 : "field_property_name", GetPropertyName(field),
179 0 : "index", SimpleItoa(field->number()));
180 : }
181 0 : printer->Outdent();
182 0 : printer->Print("}\n");
183 : printer->Print(
184 : vars,
185 : "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n"
186 : "public $property_name$OneofCase $property_name$Case {\n"
187 : " get { return $name$Case_; }\n"
188 : "}\n\n"
189 : "public void Clear$property_name$() {\n"
190 : " $name$Case_ = $property_name$OneofCase.None;\n"
191 : " $name$_ = null;\n"
192 0 : "}\n\n");
193 : }
194 :
195 : // Standard methods
196 0 : GenerateFrameworkMethods(printer);
197 0 : GenerateMessageSerializationMethods(printer);
198 0 : GenerateMergingMethods(printer);
199 :
200 : // Nested messages and enums
201 0 : if (HasNestedGeneratedTypes()) {
202 : printer->Print("#region Nested types\n"
203 0 : "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
204 0 : WriteGeneratedCodeAttributes(printer);
205 0 : printer->Print("public static partial class Types {\n");
206 0 : printer->Indent();
207 0 : for (int i = 0; i < descriptor_->enum_type_count(); i++) {
208 0 : EnumGenerator enumGenerator(descriptor_->enum_type(i));
209 0 : enumGenerator.Generate(printer);
210 0 : }
211 0 : for (int i = 0; i < descriptor_->nested_type_count(); i++) {
212 : // Don't generate nested types for maps...
213 0 : if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
214 0 : MessageGenerator messageGenerator(descriptor_->nested_type(i));
215 0 : messageGenerator.Generate(printer);
216 : }
217 : }
218 0 : printer->Outdent();
219 : printer->Print("}\n"
220 : "#endregion\n"
221 0 : "\n");
222 : }
223 :
224 0 : printer->Outdent();
225 0 : printer->Print("}\n");
226 0 : printer->Print("\n");
227 0 : }
228 :
229 : // Helper to work out whether we need to generate a class to hold nested types/enums.
230 : // Only tricky because we don't want to generate map entry types.
231 0 : bool MessageGenerator::HasNestedGeneratedTypes()
232 : {
233 0 : if (descriptor_->enum_type_count() > 0) {
234 : return true;
235 : }
236 0 : for (int i = 0; i < descriptor_->nested_type_count(); i++) {
237 0 : if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
238 : return true;
239 : }
240 : }
241 : return false;
242 : }
243 :
244 0 : void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
245 : map<string, string> vars;
246 0 : vars["class_name"] = class_name();
247 : printer->Print(
248 : vars,
249 0 : "public $class_name$($class_name$ other) : this() {\n");
250 0 : printer->Indent();
251 : // Clone non-oneof fields first
252 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
253 0 : if (!descriptor_->field(i)->containing_oneof()) {
254 : scoped_ptr<FieldGeneratorBase> generator(
255 0 : CreateFieldGeneratorInternal(descriptor_->field(i)));
256 0 : generator->GenerateCloningCode(printer);
257 : }
258 : }
259 : // Clone just the right field for each oneof
260 0 : for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
261 0 : vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
262 0 : vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
263 0 : printer->Print(vars, "switch (other.$property_name$Case) {\n");
264 0 : printer->Indent();
265 0 : for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
266 0 : const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
267 0 : scoped_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
268 0 : vars["field_property_name"] = GetPropertyName(field);
269 : printer->Print(
270 : vars,
271 0 : "case $property_name$OneofCase.$field_property_name$:\n");
272 0 : printer->Indent();
273 0 : generator->GenerateCloningCode(printer);
274 0 : printer->Print("break;\n");
275 0 : printer->Outdent();
276 : }
277 0 : printer->Outdent();
278 0 : printer->Print("}\n\n");
279 : }
280 :
281 0 : printer->Outdent();
282 0 : printer->Print("}\n\n");
283 :
284 : printer->Print(
285 : vars,
286 : "public $class_name$ Clone() {\n"
287 : " return new $class_name$(this);\n"
288 0 : "}\n\n");
289 0 : }
290 :
291 0 : void MessageGenerator::GenerateFreezingCode(io::Printer* printer) {
292 0 : }
293 :
294 0 : void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
295 : map<string, string> vars;
296 0 : vars["class_name"] = class_name();
297 :
298 : // Equality
299 : printer->Print(
300 : vars,
301 : "public override bool Equals(object other) {\n"
302 : " return Equals(other as $class_name$);\n"
303 : "}\n\n"
304 : "public bool Equals($class_name$ other) {\n"
305 : " if (ReferenceEquals(other, null)) {\n"
306 : " return false;\n"
307 : " }\n"
308 : " if (ReferenceEquals(other, this)) {\n"
309 : " return true;\n"
310 0 : " }\n");
311 0 : printer->Indent();
312 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
313 : scoped_ptr<FieldGeneratorBase> generator(
314 0 : CreateFieldGeneratorInternal(descriptor_->field(i)));
315 0 : generator->WriteEquals(printer);
316 : }
317 0 : printer->Outdent();
318 : printer->Print(
319 : " return true;\n"
320 0 : "}\n\n");
321 :
322 : // GetHashCode
323 : // Start with a non-zero value to easily distinguish between null and "empty" messages.
324 : printer->Print(
325 : "public override int GetHashCode() {\n"
326 0 : " int hash = 1;\n");
327 0 : printer->Indent();
328 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
329 : scoped_ptr<FieldGeneratorBase> generator(
330 0 : CreateFieldGeneratorInternal(descriptor_->field(i)));
331 0 : generator->WriteHash(printer);
332 : }
333 0 : printer->Print("return hash;\n");
334 0 : printer->Outdent();
335 0 : printer->Print("}\n\n");
336 :
337 : printer->Print(
338 : "public override string ToString() {\n"
339 : " return pb::JsonFormatter.Default.Format(this);\n"
340 0 : "}\n\n");
341 0 : }
342 :
343 0 : void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) {
344 : printer->Print(
345 0 : "public void WriteTo(pb::CodedOutputStream output) {\n");
346 0 : printer->Indent();
347 :
348 : // Serialize all the fields
349 0 : for (int i = 0; i < fields_by_number().size(); i++) {
350 : scoped_ptr<FieldGeneratorBase> generator(
351 0 : CreateFieldGeneratorInternal(fields_by_number()[i]));
352 0 : generator->GenerateSerializationCode(printer);
353 : }
354 :
355 : // TODO(jonskeet): Memoize size of frozen messages?
356 0 : printer->Outdent();
357 : printer->Print(
358 : "}\n"
359 : "\n"
360 0 : "public int CalculateSize() {\n");
361 0 : printer->Indent();
362 0 : printer->Print("int size = 0;\n");
363 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
364 : scoped_ptr<FieldGeneratorBase> generator(
365 0 : CreateFieldGeneratorInternal(descriptor_->field(i)));
366 0 : generator->GenerateSerializedSizeCode(printer);
367 : }
368 0 : printer->Print("return size;\n");
369 0 : printer->Outdent();
370 0 : printer->Print("}\n\n");
371 0 : }
372 :
373 0 : void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
374 : // Note: These are separate from GenerateMessageSerializationMethods()
375 : // because they need to be generated even for messages that are optimized
376 : // for code size.
377 : map<string, string> vars;
378 0 : vars["class_name"] = class_name();
379 :
380 : printer->Print(
381 : vars,
382 0 : "public void MergeFrom($class_name$ other) {\n");
383 0 : printer->Indent();
384 : printer->Print(
385 : "if (other == null) {\n"
386 : " return;\n"
387 0 : "}\n");
388 : // Merge non-oneof fields
389 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
390 0 : if (!descriptor_->field(i)->containing_oneof()) {
391 : scoped_ptr<FieldGeneratorBase> generator(
392 0 : CreateFieldGeneratorInternal(descriptor_->field(i)));
393 0 : generator->GenerateMergingCode(printer);
394 : }
395 : }
396 : // Merge oneof fields
397 0 : for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
398 0 : vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
399 0 : vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
400 0 : printer->Print(vars, "switch (other.$property_name$Case) {\n");
401 0 : printer->Indent();
402 0 : for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
403 0 : const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
404 0 : vars["field_property_name"] = GetPropertyName(field);
405 : printer->Print(
406 : vars,
407 : "case $property_name$OneofCase.$field_property_name$:\n"
408 : " $field_property_name$ = other.$field_property_name$;\n"
409 0 : " break;\n");
410 : }
411 0 : printer->Outdent();
412 0 : printer->Print("}\n\n");
413 : }
414 0 : printer->Outdent();
415 0 : printer->Print("}\n\n");
416 0 : printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
417 0 : printer->Indent();
418 : printer->Print(
419 : "uint tag;\n"
420 : "while ((tag = input.ReadTag()) != 0) {\n"
421 0 : " switch(tag) {\n");
422 0 : printer->Indent();
423 0 : printer->Indent();
424 : printer->Print(
425 : "default:\n"
426 : " input.SkipLastField();\n" // We're not storing the data, but we still need to consume it.
427 0 : " break;\n");
428 0 : for (int i = 0; i < fields_by_number().size(); i++) {
429 0 : const FieldDescriptor* field = fields_by_number()[i];
430 : internal::WireFormatLite::WireType wt =
431 0 : internal::WireFormat::WireTypeForFieldType(field->type());
432 0 : uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt);
433 : // Handle both packed and unpacked repeated fields with the same Read*Array call;
434 : // the two generated cases are the packed and unpacked tags.
435 : // TODO(jonskeet): Check that is_packable is equivalent to is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
436 : // It looks like it is...
437 0 : if (field->is_packable()) {
438 : printer->Print(
439 : "case $packed_tag$:\n",
440 : "packed_tag",
441 : SimpleItoa(
442 : internal::WireFormatLite::MakeTag(
443 : field->number(),
444 0 : internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED)));
445 : }
446 :
447 0 : printer->Print("case $tag$: {\n", "tag", SimpleItoa(tag));
448 0 : printer->Indent();
449 : scoped_ptr<FieldGeneratorBase> generator(
450 0 : CreateFieldGeneratorInternal(field));
451 0 : generator->GenerateParsingCode(printer);
452 0 : printer->Print("break;\n");
453 0 : printer->Outdent();
454 0 : printer->Print("}\n");
455 : }
456 0 : printer->Outdent();
457 0 : printer->Print("}\n"); // switch
458 0 : printer->Outdent();
459 0 : printer->Print("}\n"); // while
460 0 : printer->Outdent();
461 0 : printer->Print("}\n\n"); // method
462 0 : }
463 :
464 0 : int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) {
465 0 : for (int i = 0; i < field_names().size(); i++) {
466 0 : if (field_names()[i] == descriptor->name()) {
467 : return i;
468 : }
469 : }
470 0 : GOOGLE_LOG(DFATAL)<< "Could not find ordinal for field " << descriptor->name();
471 0 : return -1;
472 : }
473 :
474 0 : FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
475 : const FieldDescriptor* descriptor) {
476 0 : return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor));
477 : }
478 :
479 : } // namespace csharp
480 : } // namespace compiler
481 : } // namespace protobuf
482 : } // namespace google
|