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