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