void MessageGenerator::Generate()

in cdk/extra/protobuf/protobuf-3.19.6/src/google/protobuf/compiler/csharp/csharp_message.cc [114:359]


void MessageGenerator::Generate(io::Printer* printer) {
  std::map<std::string, std::string> vars;
  vars["class_name"] = class_name();
  vars["access_level"] = class_access_level();

  WriteMessageDocComment(printer, descriptor_);
  AddDeprecatedFlag(printer);
  AddSerializableAttribute(printer);

  printer->Print(
    vars,
    "$access_level$ sealed partial class $class_name$ : ");

  if (has_extension_ranges_) {
    printer->Print(vars, "pb::IExtendableMessage<$class_name$>\n");
  }
  else {
    printer->Print(vars, "pb::IMessage<$class_name$>\n");
  }
  printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
  printer->Print("    , pb::IBufferMessage\n");
  printer->Print("#endif\n");
  printer->Print("{\n");
  printer->Indent();

  // All static fields and properties
  printer->Print(
      vars,
      "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n");

  printer->Print(
      "private pb::UnknownFieldSet _unknownFields;\n");

  if (has_extension_ranges_) {
    if (IsDescriptorProto(descriptor_->file())) {
      printer->Print(vars, "internal pb::ExtensionSet<$class_name$> _extensions;\n"); // CustomOptions compatibility
    } else {
      printer->Print(vars, "private pb::ExtensionSet<$class_name$> _extensions;\n");
    }

    // a read-only property for fast
    // retrieval of the set in IsInitialized
    printer->Print(vars,
                   "private pb::ExtensionSet<$class_name$> _Extensions { get { "
                   "return _extensions; } }\n");
  }

  for (int i = 0; i < has_bit_field_count_; i++) {
    // don't use arrays since all arrays are heap allocated, saving allocations
    // use ints instead of bytes since bytes lack bitwise operators, saving casts
    printer->Print("private int _hasBits$i$;\n", "i", StrCat(i));
  }

  WriteGeneratedCodeAttributes(printer);

  printer->Print(
      vars,
      "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");

  // Access the message descriptor via the relevant file descriptor or containing message descriptor.
  if (!descriptor_->containing_type()) {
    vars["descriptor_accessor"] = GetReflectionClassName(descriptor_->file())
        + ".Descriptor.MessageTypes[" + StrCat(descriptor_->index()) + "]";
  } else {
    vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
        + ".Descriptor.NestedTypes[" + StrCat(descriptor_->index()) + "]";
  }

  WriteGeneratedCodeAttributes(printer);
  printer->Print(
    vars,
    "public static pbr::MessageDescriptor Descriptor {\n"
    "  get { return $descriptor_accessor$; }\n"
    "}\n"
    "\n");
  WriteGeneratedCodeAttributes(printer);
  printer->Print(
    vars,
    "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
    "  get { return Descriptor; }\n"
    "}\n"
    "\n");

  // Parameterless constructor and partial OnConstruction method.
  WriteGeneratedCodeAttributes(printer);
  printer->Print(
    vars,
    "public $class_name$() {\n"
    "  OnConstruction();\n"
    "}\n\n"
    "partial void OnConstruction();\n\n");

  GenerateCloningCode(printer);
  GenerateFreezingCode(printer);

  // Fields/properties
  for (int i = 0; i < descriptor_->field_count(); i++) {
    const FieldDescriptor* fieldDescriptor = descriptor_->field(i);

    // Rats: we lose the debug comment here :(
    printer->Print(
      "/// <summary>Field number for the \"$field_name$\" field.</summary>\n"
      "public const int $field_constant_name$ = $index$;\n",
      "field_name", fieldDescriptor->name(),
      "field_constant_name", GetFieldConstantName(fieldDescriptor),
      "index", StrCat(fieldDescriptor->number()));
    std::unique_ptr<FieldGeneratorBase> generator(
        CreateFieldGeneratorInternal(fieldDescriptor));
    generator->GenerateMembers(printer);
    printer->Print("\n");
  }

  // oneof properties (for real oneofs, which come before synthetic ones)
  for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
    const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
    vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
    vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
    vars["original_name"] = oneof->name();
    printer->Print(
      vars,
      "private object $name$_;\n"
      "/// <summary>Enum of possible cases for the \"$original_name$\" oneof.</summary>\n"
      "public enum $property_name$OneofCase {\n");
    printer->Indent();
    printer->Print("None = 0,\n");
    for (int j = 0; j < oneof->field_count(); j++) {
      const FieldDescriptor* field = oneof->field(j);
      printer->Print("$field_property_name$ = $index$,\n",
                     "field_property_name", GetPropertyName(field),
                     "index", StrCat(field->number()));
    }
    printer->Outdent();
    printer->Print("}\n");
    // TODO: Should we put the oneof .proto comments here?
    // It's unclear exactly where they should go.
    printer->Print(
      vars,
      "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n");
    WriteGeneratedCodeAttributes(printer);
    printer->Print(
      vars,
      "public $property_name$OneofCase $property_name$Case {\n"
      "  get { return $name$Case_; }\n"
      "}\n\n");
    WriteGeneratedCodeAttributes(printer);
    printer->Print(
      vars,
      "public void Clear$property_name$() {\n"
      "  $name$Case_ = $property_name$OneofCase.None;\n"
      "  $name$_ = null;\n"
      "}\n\n");
  }

  // Standard methods
  GenerateFrameworkMethods(printer);
  GenerateMessageSerializationMethods(printer);
  GenerateMergingMethods(printer);

  if (has_extension_ranges_) {
    printer->Print(
        vars,
        "public TValue GetExtension<TValue>(pb::Extension<$class_name$, "
        "TValue> extension) {\n"
        "  return pb::ExtensionSet.Get(ref _extensions, extension);\n"
        "}\n"
        "public pbc::RepeatedField<TValue> "
        "GetExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> "
        "extension) {\n"
        "  return pb::ExtensionSet.Get(ref _extensions, extension);\n"
        "}\n"
        "public pbc::RepeatedField<TValue> "
        "GetOrInitializeExtension<TValue>(pb::RepeatedExtension<$class_name$, "
        "TValue> extension) {\n"
        "  return pb::ExtensionSet.GetOrInitialize(ref _extensions, "
        "extension);\n"
        "}\n"
        "public void SetExtension<TValue>(pb::Extension<$class_name$, TValue> "
        "extension, TValue value) {\n"
        "  pb::ExtensionSet.Set(ref _extensions, extension, value);\n"
        "}\n"
        "public bool HasExtension<TValue>(pb::Extension<$class_name$, TValue> "
        "extension) {\n"
        "  return pb::ExtensionSet.Has(ref _extensions, extension);\n"
        "}\n"
        "public void ClearExtension<TValue>(pb::Extension<$class_name$, "
        "TValue> extension) {\n"
        "  pb::ExtensionSet.Clear(ref _extensions, extension);\n"
        "}\n"
        "public void "
        "ClearExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> "
        "extension) {\n"
        "  pb::ExtensionSet.Clear(ref _extensions, extension);\n"
        "}\n\n");
  }

  // Nested messages and enums
  if (HasNestedGeneratedTypes()) {
    printer->Print(
      vars,
      "#region Nested types\n"
      "/// <summary>Container for nested types declared in the $class_name$ message type.</summary>\n");
    WriteGeneratedCodeAttributes(printer);
    printer->Print("public static partial class Types {\n");
    printer->Indent();
    for (int i = 0; i < descriptor_->enum_type_count(); i++) {
      EnumGenerator enumGenerator(descriptor_->enum_type(i), this->options());
      enumGenerator.Generate(printer);
    }
    for (int i = 0; i < descriptor_->nested_type_count(); i++) {
      // Don't generate nested types for maps...
      if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
        MessageGenerator messageGenerator(
            descriptor_->nested_type(i), this->options());
        messageGenerator.Generate(printer);
      }
    }
    printer->Outdent();
    printer->Print("}\n"
                   "#endregion\n"
                   "\n");
  }

  if (descriptor_->extension_count() > 0) {
    printer->Print(
      vars,
      "#region Extensions\n"
      "/// <summary>Container for extensions for other messages declared in the $class_name$ message type.</summary>\n");
    WriteGeneratedCodeAttributes(printer);
    printer->Print("public static partial class Extensions {\n");
    printer->Indent();
    for (int i = 0; i < descriptor_->extension_count(); i++) {
      std::unique_ptr<FieldGeneratorBase> generator(
        CreateFieldGeneratorInternal(descriptor_->extension(i)));
      generator->GenerateExtensionCode(printer);
    }
    printer->Outdent();
    printer->Print(
      "}\n"
      "#endregion\n"
      "\n");
  }

  printer->Outdent();
  printer->Print("}\n");
  printer->Print("\n");
}