void MessageGenerator::GenerateSource()

in cdk/extra/protobuf/protobuf-3.19.6/src/google/protobuf/compiler/objectivec/objectivec_message.cc [386:631]


void MessageGenerator::GenerateSource(io::Printer* printer) {
  if (!IsMapEntryMessage(descriptor_)) {
    printer->Print(
        "#pragma mark - $classname$\n"
        "\n",
        "classname", class_name_);

    if (!deprecated_attribute_.empty()) {
      // No warnings when compiling the impl of this deprecated class.
      printer->Print(
          "#pragma clang diagnostic push\n"
          "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n"
          "\n");
    }

    printer->Print("@implementation $classname$\n\n",
                   "classname", class_name_);

    for (const auto& generator : oneof_generators_) {
      generator->GeneratePropertyImplementation(printer);
    }

    for (int i = 0; i < descriptor_->field_count(); i++) {
      field_generators_.get(descriptor_->field(i))
          .GeneratePropertyImplementation(printer);
    }

    std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
        SortFieldsByNumber(descriptor_));
    std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
        SortFieldsByStorageSize(descriptor_));

    std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
    sorted_extensions.reserve(descriptor_->extension_range_count());
    for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
      sorted_extensions.push_back(descriptor_->extension_range(i));
    }

    std::sort(sorted_extensions.begin(), sorted_extensions.end(),
         ExtensionRangeOrdering());

    // Assign has bits:
    // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing
    //    who needs has bits and assigning them.
    // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
    //    index that groups all the elements in the oneof.
    size_t num_has_bits = field_generators_.CalculateHasBits();
    size_t sizeof_has_storage = (num_has_bits + 31) / 32;
    if (sizeof_has_storage == 0) {
      // In the case where no field needs has bits, don't let the _has_storage_
      // end up as zero length (zero length arrays are sort of a grey area
      // since it has to be at the start of the struct). This also ensures a
      // field with only oneofs keeps the required negative indices they need.
      sizeof_has_storage = 1;
    }
    // Tell all the fields the oneof base.
    for (const auto& generator : oneof_generators_) {
      generator->SetOneofIndexBase(sizeof_has_storage);
    }
    field_generators_.SetOneofIndexBase(sizeof_has_storage);
    // sizeof_has_storage needs enough bits for the single fields that aren't in
    // any oneof, and then one int32 for each oneof (to store the field number).
    sizeof_has_storage += oneof_generators_.size();

    printer->Print(
        "\n"
        "typedef struct $classname$__storage_ {\n"
        "  uint32_t _has_storage_[$sizeof_has_storage$];\n",
        "classname", class_name_,
        "sizeof_has_storage", StrCat(sizeof_has_storage));
    printer->Indent();

    for (int i = 0; i < descriptor_->field_count(); i++) {
      field_generators_.get(size_order_fields[i])
          .GenerateFieldStorageDeclaration(printer);
    }
    printer->Outdent();

    printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);


    printer->Print(
        "// This method is threadsafe because it is initially called\n"
        "// in +initialize for each subclass.\n"
        "+ (GPBDescriptor *)descriptor {\n"
        "  static GPBDescriptor *descriptor = nil;\n"
        "  if (!descriptor) {\n");

    TextFormatDecodeData text_format_decode_data;
    bool has_fields = descriptor_->field_count() > 0;
    bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
    std::string field_description_type;
    if (need_defaults) {
      field_description_type = "GPBMessageFieldDescriptionWithDefault";
    } else {
      field_description_type = "GPBMessageFieldDescription";
    }
    if (has_fields) {
      printer->Indent();
      printer->Indent();
      printer->Print(
          "static $field_description_type$ fields[] = {\n",
          "field_description_type", field_description_type);
      printer->Indent();
      for (int i = 0; i < descriptor_->field_count(); ++i) {
        const FieldGenerator& field_generator =
            field_generators_.get(sorted_fields[i]);
        field_generator.GenerateFieldDescription(printer, need_defaults);
        if (field_generator.needs_textformat_name_support()) {
          text_format_decode_data.AddString(sorted_fields[i]->number(),
                                            field_generator.generated_objc_name(),
                                            field_generator.raw_field_name());
        }
      }
      printer->Outdent();
      printer->Print(
          "};\n");
      printer->Outdent();
      printer->Outdent();
    }

    std::map<std::string, std::string> vars;
    vars["classname"] = class_name_;
    vars["rootclassname"] = root_classname_;
    vars["fields"] = has_fields ? "fields" : "NULL";
    if (has_fields) {
      vars["fields_count"] =
          "(uint32_t)(sizeof(fields) / sizeof(" + field_description_type + "))";
    } else {
      vars["fields_count"] = "0";
    }

    std::vector<std::string> init_flags;
    init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs");
    init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown");
    if (need_defaults) {
      init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault");
    }
    if (descriptor_->options().message_set_wire_format()) {
      init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
    }
    vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION,
                                          init_flags);

    printer->Print(
        vars,
        "    GPBDescriptor *localDescriptor =\n"
        "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
        "                                     rootClass:[$rootclassname$ class]\n"
        "                                          file:$rootclassname$_FileDescriptor()\n"
        "                                        fields:$fields$\n"
        "                                    fieldCount:$fields_count$\n"
        "                                   storageSize:sizeof($classname$__storage_)\n"
        "                                         flags:$init_flags$];\n");
    if (!oneof_generators_.empty()) {
      printer->Print(
          "    static const char *oneofs[] = {\n");
      for (const auto& generator : oneof_generators_) {
        printer->Print("      \"$name$\",\n", "name",
                       generator->DescriptorName());
      }
      printer->Print(
          "    };\n"
          "    [localDescriptor setupOneofs:oneofs\n"
          "                           count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n"
          "                   firstHasIndex:$first_has_index$];\n",
          "first_has_index", oneof_generators_[0]->HasIndexAsString());
    }
    if (text_format_decode_data.num_entries() != 0) {
      const std::string text_format_data_str(text_format_decode_data.Data());
      printer->Print(
          "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
          "    static const char *extraTextFormatInfo =");
      static const int kBytesPerLine = 40;  // allow for escaping
      for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) {
        printer->Print(
            "\n        \"$data$\"",
            "data", EscapeTrigraphs(
                CEscape(text_format_data_str.substr(i, kBytesPerLine))));
      }
      printer->Print(
          ";\n"
          "    [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
          "#endif  // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
    }
    if (!sorted_extensions.empty()) {
      printer->Print(
          "    static const GPBExtensionRange ranges[] = {\n");
      for (int i = 0; i < sorted_extensions.size(); i++) {
        printer->Print("      { .start = $start$, .end = $end$ },\n",
                       "start", StrCat(sorted_extensions[i]->start),
                       "end", StrCat(sorted_extensions[i]->end));
      }
      printer->Print(
          "    };\n"
          "    [localDescriptor setupExtensionRanges:ranges\n"
          "                                    count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
    }
    if (descriptor_->containing_type() != NULL) {
      std::string containing_class = ClassName(descriptor_->containing_type());
      std::string parent_class_ref = ObjCClass(containing_class);
      printer->Print(
          "    [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n",
          "parent_class_ref", parent_class_ref);
    }
    std::string suffix_added;
    ClassName(descriptor_, &suffix_added);
    if (!suffix_added.empty()) {
      printer->Print(
          "    [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n",
          "suffix", suffix_added);
    }
    printer->Print(
        "    #if defined(DEBUG) && DEBUG\n"
        "      NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
        "    #endif  // DEBUG\n"
        "    descriptor = localDescriptor;\n"
        "  }\n"
        "  return descriptor;\n"
        "}\n\n"
        "@end\n\n");

    if (!deprecated_attribute_.empty()) {
      printer->Print(
          "#pragma clang diagnostic pop\n"
          "\n");
    }

    for (int i = 0; i < descriptor_->field_count(); i++) {
      field_generators_.get(descriptor_->field(i))
          .GenerateCFunctionImplementations(printer);
    }

    for (const auto& generator : oneof_generators_) {
      generator->GenerateClearFunctionImplementation(printer);
    }
  }

  for (const auto& generator : enum_generators_) {
    generator->GenerateSource(printer);
  }

  for (const auto& generator : nested_message_generators_) {
    generator->GenerateSource(printer);
  }
}