void MessageBuilderGenerator::GenerateCommonBuilderMethods()

in cdk/extra/protobuf/protobuf-3.19.6/src/google/protobuf/compiler/java/java_message_builder.cc [289:608]


void MessageBuilderGenerator::GenerateCommonBuilderMethods(
    io::Printer* printer) {
  // Decide if we really need to have the "maybeForceBuilderInitialization()"
  // method.
  // TODO(b/249158148): Remove the need for this entirely
  bool need_maybe_force_builder_init = false;
  for (int i = 0; i < descriptor_->field_count(); i++) {
    if (descriptor_->field(i)->message_type() != nullptr &&
        !IsRealOneof(descriptor_->field(i)) &&
        HasHasbit(descriptor_->field(i))) {
      need_maybe_force_builder_init = true;
      break;
    }
  }

  const char* force_builder_init = need_maybe_force_builder_init
                                       ? "  maybeForceBuilderInitialization();"
                                       : "";

  printer->Print(
      "// Construct using $classname$.newBuilder()\n"
      "private Builder() {\n"
      "$force_builder_init$\n"
      "}\n"
      "\n",
      "classname", name_resolver_->GetImmutableClassName(descriptor_),
      "force_builder_init", force_builder_init);

  printer->Print(
      "private Builder(\n"
      "    com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n"
      "  super(parent);\n"
      "$force_builder_init$\n"
      "}\n",
      "classname", name_resolver_->GetImmutableClassName(descriptor_), "ver",
      GeneratedCodeVersionSuffix(), "force_builder_init", force_builder_init);

  if (need_maybe_force_builder_init) {
    printer->Print(
        "private void maybeForceBuilderInitialization() {\n"
        "  if (com.google.protobuf.GeneratedMessage$ver$\n"
        "          .alwaysUseFieldBuilders) {\n",
        "ver", GeneratedCodeVersionSuffix());

    printer->Indent();
    printer->Indent();
    for (int i = 0; i < descriptor_->field_count(); i++) {
      if (!IsRealOneof(descriptor_->field(i))) {
        field_generators_.get(descriptor_->field(i))
            .GenerateFieldBuilderInitializationCode(printer);
      }
    }
    printer->Outdent();
    printer->Outdent();

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

  printer->Print(
      "@java.lang.Override\n"
      "public Builder clear() {\n"
      "  super.clear();\n");

  printer->Indent();

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

  for (auto oneof : oneofs_) {
    printer->Print(
        "$oneof_name$Case_ = 0;\n"
        "$oneof_name$_ = null;\n",
        "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name);
  }

  printer->Outdent();

  printer->Print(
      "  return this;\n"
      "}\n"
      "\n");

  printer->Print(
      "@java.lang.Override\n"
      "public com.google.protobuf.Descriptors.Descriptor\n"
      "    getDescriptorForType() {\n"
      "  return $fileclass$.internal_$identifier$_descriptor;\n"
      "}\n"
      "\n",
      "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
      "identifier", UniqueFileScopeIdentifier(descriptor_));

  // LITE runtime implements this in GeneratedMessageLite.
  printer->Print(
      "@java.lang.Override\n"
      "public $classname$ getDefaultInstanceForType() {\n"
      "  return $classname$.getDefaultInstance();\n"
      "}\n"
      "\n",
      "classname", name_resolver_->GetImmutableClassName(descriptor_));

  printer->Print(
      "@java.lang.Override\n"
      "public $classname$ build() {\n"
      "  $classname$ result = buildPartial();\n"
      "  if (!result.isInitialized()) {\n"
      "    throw newUninitializedMessageException(result);\n"
      "  }\n"
      "  return result;\n"
      "}\n"
      "\n",
      "classname", name_resolver_->GetImmutableClassName(descriptor_));

  printer->Print(
      "@java.lang.Override\n"
      "public $classname$ buildPartial() {\n"
      "  $classname$ result = new $classname$(this);\n",
      "classname", name_resolver_->GetImmutableClassName(descriptor_));

  printer->Indent();

  int totalBuilderBits = 0;
  int totalMessageBits = 0;
  for (int i = 0; i < descriptor_->field_count(); i++) {
    const ImmutableFieldGenerator& field =
        field_generators_.get(descriptor_->field(i));
    totalBuilderBits += field.GetNumBitsForBuilder();
    totalMessageBits += field.GetNumBitsForMessage();
  }
  int totalBuilderInts = (totalBuilderBits + 31) / 32;
  int totalMessageInts = (totalMessageBits + 31) / 32;

  // Local vars for from and to bit fields to avoid accessing the builder and
  // message over and over for these fields. Seems to provide a slight
  // perforamance improvement in micro benchmark and this is also what proto1
  // code does.
  for (int i = 0; i < totalBuilderInts; i++) {
    printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n",
                   "bit_field_name", GetBitFieldName(i));
  }
  for (int i = 0; i < totalMessageInts; i++) {
    printer->Print("int to_$bit_field_name$ = 0;\n", "bit_field_name",
                   GetBitFieldName(i));
  }

  // Output generation code for each field.
  for (int i = 0; i < descriptor_->field_count(); i++) {
    field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer);
  }

  // Copy the bit field results to the generated message
  for (int i = 0; i < totalMessageInts; i++) {
    printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n",
                   "bit_field_name", GetBitFieldName(i));
  }

  for (auto oneof : oneofs_) {
    printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n",
                   "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name);
  }

  printer->Outdent();

  printer->Print("  onBuilt();\n");

  printer->Print(
      "  return result;\n"
      "}\n"
      "\n",
      "classname", name_resolver_->GetImmutableClassName(descriptor_));

  // Override methods declared in GeneratedMessage to return the concrete
  // generated type so callsites won't depend on GeneratedMessage. This
  // is needed to keep binary compatibility when we change generated code
  // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release
  // we changed all generated code to subclass GeneratedMessageV3).
  printer->Print(
      "@java.lang.Override\n"
      "public Builder clone() {\n"
      "  return super.clone();\n"
      "}\n"
      "@java.lang.Override\n"
      "public Builder setField(\n"
      "    com.google.protobuf.Descriptors.FieldDescriptor field,\n"
      "    java.lang.Object value) {\n"
      "  return super.setField(field, value);\n"
      "}\n"
      "@java.lang.Override\n"
      "public Builder clearField(\n"
      "    com.google.protobuf.Descriptors.FieldDescriptor field) {\n"
      "  return super.clearField(field);\n"
      "}\n"
      "@java.lang.Override\n"
      "public Builder clearOneof(\n"
      "    com.google.protobuf.Descriptors.OneofDescriptor oneof) {\n"
      "  return super.clearOneof(oneof);\n"
      "}\n"
      "@java.lang.Override\n"
      "public Builder setRepeatedField(\n"
      "    com.google.protobuf.Descriptors.FieldDescriptor field,\n"
      "    int index, java.lang.Object value) {\n"
      "  return super.setRepeatedField(field, index, value);\n"
      "}\n"
      "@java.lang.Override\n"
      "public Builder addRepeatedField(\n"
      "    com.google.protobuf.Descriptors.FieldDescriptor field,\n"
      "    java.lang.Object value) {\n"
      "  return super.addRepeatedField(field, value);\n"
      "}\n");

  if (descriptor_->extension_range_count() > 0) {
    printer->Print(
        "@java.lang.Override\n"
        "public <Type> Builder setExtension(\n"
        "    com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
        "        $classname$, Type> extension,\n"
        "    Type value) {\n"
        "  return super.setExtension(extension, value);\n"
        "}\n"
        "@java.lang.Override\n"
        "public <Type> Builder setExtension(\n"
        "    com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
        "        $classname$, java.util.List<Type>> extension,\n"
        "    int index, Type value) {\n"
        "  return super.setExtension(extension, index, value);\n"
        "}\n"
        "@java.lang.Override\n"
        "public <Type> Builder addExtension(\n"
        "    com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
        "        $classname$, java.util.List<Type>> extension,\n"
        "    Type value) {\n"
        "  return super.addExtension(extension, value);\n"
        "}\n"
        "@java.lang.Override\n"
        "public <Type> Builder clearExtension(\n"
        "    com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
        "        $classname$, ?> extension) {\n"
        "  return super.clearExtension(extension);\n"
        "}\n",
        "classname", name_resolver_->GetImmutableClassName(descriptor_));
  }

  // -----------------------------------------------------------------

  if (context_->HasGeneratedMethods(descriptor_)) {
    printer->Print(
        "@java.lang.Override\n"
        "public Builder mergeFrom(com.google.protobuf.Message other) {\n"
        "  if (other instanceof $classname$) {\n"
        "    return mergeFrom(($classname$)other);\n"
        "  } else {\n"
        "    super.mergeFrom(other);\n"
        "    return this;\n"
        "  }\n"
        "}\n"
        "\n",
        "classname", name_resolver_->GetImmutableClassName(descriptor_));

    printer->Print(
        "public Builder mergeFrom($classname$ other) {\n"
        // Optimization:  If other is the default instance, we know none of its
        //   fields are set so we can skip the merge.
        "  if (other == $classname$.getDefaultInstance()) return this;\n",
        "classname", name_resolver_->GetImmutableClassName(descriptor_));
    printer->Indent();

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

    // Merge oneof fields.
    for (auto oneof : oneofs_) {
      printer->Print("switch (other.get$oneof_capitalized_name$Case()) {\n",
                     "oneof_capitalized_name",
                     context_->GetOneofGeneratorInfo(oneof)->capitalized_name);
      printer->Indent();
      for (int j = 0; j < oneof->field_count(); j++) {
        const FieldDescriptor* field = oneof->field(j);
        printer->Print("case $field_name$: {\n", "field_name",
                       ToUpper(field->name()));
        printer->Indent();
        field_generators_.get(field).GenerateMergingCode(printer);
        printer->Print("break;\n");
        printer->Outdent();
        printer->Print("}\n");
      }
      printer->Print(
          "case $cap_oneof_name$_NOT_SET: {\n"
          "  break;\n"
          "}\n",
          "cap_oneof_name",
          ToUpper(context_->GetOneofGeneratorInfo(oneof)->name));
      printer->Outdent();
      printer->Print("}\n");
    }

    printer->Outdent();

    // if message type has extensions
    if (descriptor_->extension_range_count() > 0) {
      printer->Print("  this.mergeExtensionFields(other);\n");
    }

    printer->Print("  this.mergeUnknownFields(other.getUnknownFields());\n");

    printer->Print("  onChanged();\n");

    printer->Print(
        "  return this;\n"
        "}\n"
        "\n");
  }
}