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/descriptor.h>
37 #include <google/protobuf/descriptor.pb.h>
38 #include <google/protobuf/io/printer.h>
39 #include <google/protobuf/io/zero_copy_stream.h>
40 #include <google/protobuf/stubs/strutil.h>
41 #include <google/protobuf/wire_format.h>
42 #include <google/protobuf/wire_format_lite.h>
43
44 #include <google/protobuf/compiler/csharp/csharp_options.h>
45 #include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
46 #include <google/protobuf/compiler/csharp/csharp_enum.h>
47 #include <google/protobuf/compiler/csharp/csharp_field_base.h>
48 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
49 #include <google/protobuf/compiler/csharp/csharp_message.h>
50 #include <google/protobuf/compiler/csharp/csharp_names.h>
51
52 namespace google {
53 namespace protobuf {
54 namespace compiler {
55 namespace csharp {
56
CompareFieldNumbers(const FieldDescriptor * d1,const FieldDescriptor * d2)57 bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
58 return d1->number() < d2->number();
59 }
60
MessageGenerator(const Descriptor * descriptor,const Options * options)61 MessageGenerator::MessageGenerator(const Descriptor* descriptor,
62 const Options* options)
63 : SourceGeneratorBase(descriptor->file(), options),
64 descriptor_(descriptor),
65 has_bit_field_count_(0),
66 end_tag_(GetGroupEndTag(descriptor)),
67 has_extension_ranges_(descriptor->extension_range_count() > 0) {
68 // fields by number
69 for (int i = 0; i < descriptor_->field_count(); i++) {
70 fields_by_number_.push_back(descriptor_->field(i));
71 }
72 std::sort(fields_by_number_.begin(), fields_by_number_.end(),
73 CompareFieldNumbers);
74
75 if (IsProto2(descriptor_->file())) {
76 int primitiveCount = 0;
77 for (int i = 0; i < descriptor_->field_count(); i++) {
78 const FieldDescriptor* field = descriptor_->field(i);
79 if (!IsNullable(field)) {
80 primitiveCount++;
81 if (has_bit_field_count_ == 0 || (primitiveCount % 32) == 0) {
82 has_bit_field_count_++;
83 }
84 }
85 }
86 }
87 }
88
~MessageGenerator()89 MessageGenerator::~MessageGenerator() {
90 }
91
class_name()92 std::string MessageGenerator::class_name() {
93 return descriptor_->name();
94 }
95
full_class_name()96 std::string MessageGenerator::full_class_name() {
97 return GetClassName(descriptor_);
98 }
99
fields_by_number()100 const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() {
101 return fields_by_number_;
102 }
103
AddDeprecatedFlag(io::Printer * printer)104 void MessageGenerator::AddDeprecatedFlag(io::Printer* printer) {
105 if (descriptor_->options().deprecated()) {
106 printer->Print("[global::System.ObsoleteAttribute]\n");
107 }
108 }
109
AddSerializableAttribute(io::Printer * printer)110 void MessageGenerator::AddSerializableAttribute(io::Printer* printer) {
111 if (this->options()->serializable) {
112 printer->Print("[global::System.SerializableAttribute]\n");
113 }
114 }
115
Generate(io::Printer * printer)116 void MessageGenerator::Generate(io::Printer* printer) {
117 std::map<string, string> vars;
118 vars["class_name"] = class_name();
119 vars["access_level"] = class_access_level();
120
121 WriteMessageDocComment(printer, descriptor_);
122 AddDeprecatedFlag(printer);
123 AddSerializableAttribute(printer);
124
125 printer->Print(
126 vars,
127 "$access_level$ sealed partial class $class_name$ : ");
128
129 if (has_extension_ranges_) {
130 printer->Print(vars, "pb::IExtendableMessage<$class_name$>");
131 }
132 else {
133 printer->Print(vars, "pb::IMessage<$class_name$>");
134 }
135 printer->Print(" {\n");
136 printer->Indent();
137
138 // All static fields and properties
139 printer->Print(
140 vars,
141 "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n");
142
143 printer->Print(
144 "private pb::UnknownFieldSet _unknownFields;\n");
145
146 if (has_extension_ranges_) {
147 if (IsDescriptorProto(descriptor_->file())) {
148 printer->Print(vars, "internal pb::ExtensionSet<$class_name$> _extensions;\n"); // CustomOptions compatibility
149 } else {
150 printer->Print(vars, "private pb::ExtensionSet<$class_name$> _extensions;\n");
151 }
152 }
153
154 for (int i = 0; i < has_bit_field_count_; i++) {
155 // don't use arrays since all arrays are heap allocated, saving allocations
156 // use ints instead of bytes since bytes lack bitwise operators, saving casts
157 printer->Print("private int _hasBits$i$;\n", "i", StrCat(i));
158 }
159
160 WriteGeneratedCodeAttributes(printer);
161
162 printer->Print(
163 vars,
164 "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
165
166 // Access the message descriptor via the relevant file descriptor or containing message descriptor.
167 if (!descriptor_->containing_type()) {
168 vars["descriptor_accessor"] = GetReflectionClassName(descriptor_->file())
169 + ".Descriptor.MessageTypes[" + StrCat(descriptor_->index()) + "]";
170 } else {
171 vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
172 + ".Descriptor.NestedTypes[" + StrCat(descriptor_->index()) + "]";
173 }
174
175 WriteGeneratedCodeAttributes(printer);
176 printer->Print(
177 vars,
178 "public static pbr::MessageDescriptor Descriptor {\n"
179 " get { return $descriptor_accessor$; }\n"
180 "}\n"
181 "\n");
182 WriteGeneratedCodeAttributes(printer);
183 printer->Print(
184 vars,
185 "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
186 " get { return Descriptor; }\n"
187 "}\n"
188 "\n");
189
190 // Parameterless constructor and partial OnConstruction method.
191 WriteGeneratedCodeAttributes(printer);
192 printer->Print(
193 vars,
194 "public $class_name$() {\n"
195 " OnConstruction();\n"
196 "}\n\n"
197 "partial void OnConstruction();\n\n");
198
199 GenerateCloningCode(printer);
200 GenerateFreezingCode(printer);
201
202 // Fields/properties
203 for (int i = 0; i < descriptor_->field_count(); i++) {
204 const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
205
206 // Rats: we lose the debug comment here :(
207 printer->Print(
208 "/// <summary>Field number for the \"$field_name$\" field.</summary>\n"
209 "public const int $field_constant_name$ = $index$;\n",
210 "field_name", fieldDescriptor->name(),
211 "field_constant_name", GetFieldConstantName(fieldDescriptor),
212 "index", StrCat(fieldDescriptor->number()));
213 std::unique_ptr<FieldGeneratorBase> generator(
214 CreateFieldGeneratorInternal(fieldDescriptor));
215 generator->GenerateMembers(printer);
216 printer->Print("\n");
217 }
218
219 // oneof properties
220 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
221 vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
222 vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
223 vars["original_name"] = descriptor_->oneof_decl(i)->name();
224 printer->Print(
225 vars,
226 "private object $name$_;\n"
227 "/// <summary>Enum of possible cases for the \"$original_name$\" oneof.</summary>\n"
228 "public enum $property_name$OneofCase {\n");
229 printer->Indent();
230 printer->Print("None = 0,\n");
231 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
232 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
233 printer->Print("$field_property_name$ = $index$,\n",
234 "field_property_name", GetPropertyName(field),
235 "index", StrCat(field->number()));
236 }
237 printer->Outdent();
238 printer->Print("}\n");
239 // TODO: Should we put the oneof .proto comments here?
240 // It's unclear exactly where they should go.
241 printer->Print(
242 vars,
243 "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n");
244 WriteGeneratedCodeAttributes(printer);
245 printer->Print(
246 vars,
247 "public $property_name$OneofCase $property_name$Case {\n"
248 " get { return $name$Case_; }\n"
249 "}\n\n");
250 WriteGeneratedCodeAttributes(printer);
251 printer->Print(
252 vars,
253 "public void Clear$property_name$() {\n"
254 " $name$Case_ = $property_name$OneofCase.None;\n"
255 " $name$_ = null;\n"
256 "}\n\n");
257 }
258
259 // Standard methods
260 GenerateFrameworkMethods(printer);
261 GenerateMessageSerializationMethods(printer);
262 GenerateMergingMethods(printer);
263
264 if (has_extension_ranges_) {
265 printer->Print(
266 vars,
267 "public TValue GetExtension<TValue>(pb::Extension<$class_name$, TValue> extension) {\n"
268 " return pb::ExtensionSet.Get(ref _extensions, extension);\n"
269 "}\n"
270 "public pbc::RepeatedField<TValue> GetExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> extension) {\n"
271 " return pb::ExtensionSet.Get(ref _extensions, extension);\n"
272 "}\n"
273 "public pbc::RepeatedField<TValue> GetOrRegisterExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> extension) {\n"
274 " return pb::ExtensionSet.GetOrRegister(ref _extensions, extension);\n"
275 "}\n"
276 "public void SetExtension<TValue>(pb::Extension<$class_name$, TValue> extension, TValue value) {\n"
277 " pb::ExtensionSet.Set(ref _extensions, extension, value);\n"
278 "}\n"
279 "public bool HasExtension<TValue>(pb::Extension<$class_name$, TValue> extension) {\n"
280 " return pb::ExtensionSet.Has(ref _extensions, extension);\n"
281 "}\n"
282 "public void ClearExtension<TValue>(pb::Extension<$class_name$, TValue> extension) {\n"
283 " pb::ExtensionSet.Clear(ref _extensions, extension);\n"
284 "}\n"
285 "public void ClearExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> extension) {\n"
286 " pb::ExtensionSet.Clear(ref _extensions, extension);\n"
287 "}\n\n");
288 }
289
290 // Nested messages and enums
291 if (HasNestedGeneratedTypes()) {
292 printer->Print(
293 vars,
294 "#region Nested types\n"
295 "/// <summary>Container for nested types declared in the $class_name$ message type.</summary>\n");
296 WriteGeneratedCodeAttributes(printer);
297 printer->Print("public static partial class Types {\n");
298 printer->Indent();
299 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
300 EnumGenerator enumGenerator(descriptor_->enum_type(i), this->options());
301 enumGenerator.Generate(printer);
302 }
303 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
304 // Don't generate nested types for maps...
305 if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
306 MessageGenerator messageGenerator(
307 descriptor_->nested_type(i), this->options());
308 messageGenerator.Generate(printer);
309 }
310 }
311 printer->Outdent();
312 printer->Print("}\n"
313 "#endregion\n"
314 "\n");
315 }
316
317 if (descriptor_->extension_count() > 0) {
318 printer->Print(
319 vars,
320 "#region Extensions\n"
321 "/// <summary>Container for extensions for other messages declared in the $class_name$ message type.</summary>\n");
322 WriteGeneratedCodeAttributes(printer);
323 printer->Print("internal static partial class Extensions {\n");
324 printer->Indent();
325 for (int i = 0; i < descriptor_->extension_count(); i++) {
326 std::unique_ptr<FieldGeneratorBase> generator(
327 CreateFieldGeneratorInternal(descriptor_->extension(i)));
328 generator->GenerateExtensionCode(printer);
329 }
330 printer->Outdent();
331 printer->Print(
332 "}\n"
333 "#endregion\n"
334 "\n");
335 }
336
337 printer->Outdent();
338 printer->Print("}\n");
339 printer->Print("\n");
340 }
341
342 // Helper to work out whether we need to generate a class to hold nested types/enums.
343 // Only tricky because we don't want to generate map entry types.
HasNestedGeneratedTypes()344 bool MessageGenerator::HasNestedGeneratedTypes()
345 {
346 if (descriptor_->enum_type_count() > 0) {
347 return true;
348 }
349 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
350 if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
351 return true;
352 }
353 }
354 return false;
355 }
356
GenerateCloningCode(io::Printer * printer)357 void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
358 std::map<string, string> vars;
359 WriteGeneratedCodeAttributes(printer);
360 vars["class_name"] = class_name();
361 printer->Print(
362 vars,
363 "public $class_name$($class_name$ other) : this() {\n");
364 printer->Indent();
365 for (int i = 0; i < has_bit_field_count_; i++) {
366 printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", StrCat(i));
367 }
368 // Clone non-oneof fields first
369 for (int i = 0; i < descriptor_->field_count(); i++) {
370 if (!descriptor_->field(i)->containing_oneof()) {
371 std::unique_ptr<FieldGeneratorBase> generator(
372 CreateFieldGeneratorInternal(descriptor_->field(i)));
373 generator->GenerateCloningCode(printer);
374 }
375 }
376 // Clone just the right field for each oneof
377 for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
378 vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
379 vars["property_name"] = UnderscoresToCamelCase(
380 descriptor_->oneof_decl(i)->name(), true);
381 printer->Print(vars, "switch (other.$property_name$Case) {\n");
382 printer->Indent();
383 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
384 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
385 std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
386 vars["field_property_name"] = GetPropertyName(field);
387 printer->Print(
388 vars,
389 "case $property_name$OneofCase.$field_property_name$:\n");
390 printer->Indent();
391 generator->GenerateCloningCode(printer);
392 printer->Print("break;\n");
393 printer->Outdent();
394 }
395 printer->Outdent();
396 printer->Print("}\n\n");
397 }
398 // Clone unknown fields
399 printer->Print(
400 "_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);\n");
401 if (has_extension_ranges_) {
402 printer->Print(
403 "_extensions = pb::ExtensionSet.Clone(other._extensions);\n");
404 }
405
406 printer->Outdent();
407 printer->Print("}\n\n");
408
409 WriteGeneratedCodeAttributes(printer);
410 printer->Print(
411 vars,
412 "public $class_name$ Clone() {\n"
413 " return new $class_name$(this);\n"
414 "}\n\n");
415 }
416
GenerateFreezingCode(io::Printer * printer)417 void MessageGenerator::GenerateFreezingCode(io::Printer* printer) {
418 }
419
GenerateFrameworkMethods(io::Printer * printer)420 void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
421 std::map<string, string> vars;
422 vars["class_name"] = class_name();
423
424 // Equality
425 WriteGeneratedCodeAttributes(printer);
426 printer->Print(
427 vars,
428 "public override bool Equals(object other) {\n"
429 " return Equals(other as $class_name$);\n"
430 "}\n\n");
431 WriteGeneratedCodeAttributes(printer);
432 printer->Print(
433 vars,
434 "public bool Equals($class_name$ other) {\n"
435 " if (ReferenceEquals(other, null)) {\n"
436 " return false;\n"
437 " }\n"
438 " if (ReferenceEquals(other, this)) {\n"
439 " return true;\n"
440 " }\n");
441 printer->Indent();
442 for (int i = 0; i < descriptor_->field_count(); i++) {
443 std::unique_ptr<FieldGeneratorBase> generator(
444 CreateFieldGeneratorInternal(descriptor_->field(i)));
445 generator->WriteEquals(printer);
446 }
447 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
448 printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n",
449 "property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
450 }
451 if (has_extension_ranges_) {
452 printer->Print(
453 "if (!Equals(_extensions, other._extensions)) {\n"
454 " return false;\n"
455 "}\n");
456 }
457 printer->Outdent();
458 printer->Print(
459 " return Equals(_unknownFields, other._unknownFields);\n"
460 "}\n\n");
461
462 // GetHashCode
463 // Start with a non-zero value to easily distinguish between null and "empty" messages.
464 WriteGeneratedCodeAttributes(printer);
465 printer->Print(
466 "public override int GetHashCode() {\n"
467 " int hash = 1;\n");
468 printer->Indent();
469 for (int i = 0; i < descriptor_->field_count(); i++) {
470 std::unique_ptr<FieldGeneratorBase> generator(
471 CreateFieldGeneratorInternal(descriptor_->field(i)));
472 generator->WriteHash(printer);
473 }
474 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
475 printer->Print("hash ^= (int) $name$Case_;\n",
476 "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false));
477 }
478 if (has_extension_ranges_) {
479 printer->Print(
480 "if (_extensions != null) {\n"
481 " hash ^= _extensions.GetHashCode();\n"
482 "}\n");
483 }
484 printer->Print(
485 "if (_unknownFields != null) {\n"
486 " hash ^= _unknownFields.GetHashCode();\n"
487 "}\n"
488 "return hash;\n");
489 printer->Outdent();
490 printer->Print("}\n\n");
491
492 WriteGeneratedCodeAttributes(printer);
493 printer->Print(
494 "public override string ToString() {\n"
495 " return pb::JsonFormatter.ToDiagnosticString(this);\n"
496 "}\n\n");
497 }
498
GenerateMessageSerializationMethods(io::Printer * printer)499 void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) {
500 WriteGeneratedCodeAttributes(printer);
501 printer->Print(
502 "public void WriteTo(pb::CodedOutputStream output) {\n");
503 printer->Indent();
504
505 // Serialize all the fields
506 for (int i = 0; i < fields_by_number().size(); i++) {
507 std::unique_ptr<FieldGeneratorBase> generator(
508 CreateFieldGeneratorInternal(fields_by_number()[i]));
509 generator->GenerateSerializationCode(printer);
510 }
511
512 if (has_extension_ranges_) {
513 // Serialize extensions
514 printer->Print(
515 "if (_extensions != null) {\n"
516 " _extensions.WriteTo(output);\n"
517 "}\n");
518 }
519
520 // Serialize unknown fields
521 printer->Print(
522 "if (_unknownFields != null) {\n"
523 " _unknownFields.WriteTo(output);\n"
524 "}\n");
525
526 // TODO(jonskeet): Memoize size of frozen messages?
527 printer->Outdent();
528 printer->Print(
529 "}\n"
530 "\n");
531 WriteGeneratedCodeAttributes(printer);
532 printer->Print(
533 "public int CalculateSize() {\n");
534 printer->Indent();
535 printer->Print("int size = 0;\n");
536 for (int i = 0; i < descriptor_->field_count(); i++) {
537 std::unique_ptr<FieldGeneratorBase> generator(
538 CreateFieldGeneratorInternal(descriptor_->field(i)));
539 generator->GenerateSerializedSizeCode(printer);
540 }
541
542 if (has_extension_ranges_) {
543 printer->Print(
544 "if (_extensions != null) {\n"
545 " size += _extensions.CalculateSize();\n"
546 "}\n");
547 }
548
549 printer->Print(
550 "if (_unknownFields != null) {\n"
551 " size += _unknownFields.CalculateSize();\n"
552 "}\n");
553
554 printer->Print("return size;\n");
555 printer->Outdent();
556 printer->Print("}\n\n");
557 }
558
GenerateMergingMethods(io::Printer * printer)559 void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
560 // Note: These are separate from GenerateMessageSerializationMethods()
561 // because they need to be generated even for messages that are optimized
562 // for code size.
563 std::map<string, string> vars;
564 vars["class_name"] = class_name();
565
566 WriteGeneratedCodeAttributes(printer);
567 printer->Print(
568 vars,
569 "public void MergeFrom($class_name$ other) {\n");
570 printer->Indent();
571 printer->Print(
572 "if (other == null) {\n"
573 " return;\n"
574 "}\n");
575 // Merge non-oneof fields
576 for (int i = 0; i < descriptor_->field_count(); i++) {
577 if (!descriptor_->field(i)->containing_oneof()) {
578 std::unique_ptr<FieldGeneratorBase> generator(
579 CreateFieldGeneratorInternal(descriptor_->field(i)));
580 generator->GenerateMergingCode(printer);
581 }
582 }
583 // Merge oneof fields
584 for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
585 vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
586 vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
587 printer->Print(vars, "switch (other.$property_name$Case) {\n");
588 printer->Indent();
589 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
590 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
591 vars["field_property_name"] = GetPropertyName(field);
592 printer->Print(
593 vars,
594 "case $property_name$OneofCase.$field_property_name$:\n");
595 printer->Indent();
596 std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
597 generator->GenerateMergingCode(printer);
598 printer->Print("break;\n");
599 printer->Outdent();
600 }
601 printer->Outdent();
602 printer->Print("}\n\n");
603 }
604 // Merge extensions
605 if (has_extension_ranges_) {
606 printer->Print("pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions);\n");
607 }
608
609 // Merge unknown fields.
610 printer->Print(
611 "_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);\n");
612
613 printer->Outdent();
614 printer->Print("}\n\n");
615
616
617 WriteGeneratedCodeAttributes(printer);
618 printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
619 printer->Indent();
620 printer->Print(
621 "uint tag;\n"
622 "while ((tag = input.ReadTag()) != 0) {\n"
623 " switch(tag) {\n");
624 printer->Indent();
625 printer->Indent();
626 if (end_tag_ != 0) {
627 printer->Print(
628 "$end_tag$:\n"
629 " return;\n",
630 "end_tag", StrCat(end_tag_));
631 }
632 if (has_extension_ranges_) {
633 printer->Print(
634 "default:\n"
635 " if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) {\n"
636 " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);\n"
637 " }\n"
638 " break;\n");
639 } else {
640 printer->Print(
641 "default:\n"
642 " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);\n"
643 " break;\n");
644 }
645 for (int i = 0; i < fields_by_number().size(); i++) {
646 const FieldDescriptor* field = fields_by_number()[i];
647 internal::WireFormatLite::WireType wt =
648 internal::WireFormat::WireTypeForFieldType(field->type());
649 uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt);
650 // Handle both packed and unpacked repeated fields with the same Read*Array call;
651 // the two generated cases are the packed and unpacked tags.
652 // TODO(jonskeet): Check that is_packable is equivalent to
653 // is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
654 // It looks like it is...
655 if (field->is_packable()) {
656 printer->Print(
657 "case $packed_tag$:\n",
658 "packed_tag",
659 StrCat(
660 internal::WireFormatLite::MakeTag(
661 field->number(),
662 internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED)));
663 }
664
665 printer->Print("case $tag$: {\n", "tag", StrCat(tag));
666 printer->Indent();
667 std::unique_ptr<FieldGeneratorBase> generator(
668 CreateFieldGeneratorInternal(field));
669 generator->GenerateParsingCode(printer);
670 printer->Print("break;\n");
671 printer->Outdent();
672 printer->Print("}\n");
673 }
674 printer->Outdent();
675 printer->Print("}\n"); // switch
676 printer->Outdent();
677 printer->Print("}\n"); // while
678 printer->Outdent();
679 printer->Print("}\n\n"); // method
680 }
681
682 // it's a waste of space to track presence for all values, so we only track them if they're not nullable
GetPresenceIndex(const FieldDescriptor * descriptor)683 int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) {
684 if (IsNullable(descriptor) || !IsProto2(descriptor_->file())) {
685 return -1;
686 }
687
688 int index = 0;
689 for (int i = 0; i < fields_by_number().size(); i++) {
690 const FieldDescriptor* field = fields_by_number()[i];
691 if (field == descriptor) {
692 return index;
693 }
694 if (!IsNullable(field)) {
695 index++;
696 }
697 }
698 GOOGLE_LOG(DFATAL)<< "Could not find presence index for field " << descriptor->name();
699 return -1;
700 }
701
CreateFieldGeneratorInternal(const FieldDescriptor * descriptor)702 FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
703 const FieldDescriptor* descriptor) {
704 return CreateFieldGenerator(descriptor, GetPresenceIndex(descriptor), this->options());
705 }
706
707 } // namespace csharp
708 } // namespace compiler
709 } // namespace protobuf
710 } // namespace google
711