• 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   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