void ImmutableMessageGenerator::Generate()

in cdk/extra/protobuf/protobuf-3.19.6/src/google/protobuf/compiler/java/java_message.cc [306:571]


void ImmutableMessageGenerator::Generate(io::Printer* printer) {
  bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true);

  std::map<std::string, std::string> variables;
  variables["static"] = is_own_file ? "" : "static ";
  variables["classname"] = descriptor_->name();
  variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
  variables["ver"] = GeneratedCodeVersionSuffix();
  variables["deprecation"] =
      descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "";

  WriteMessageDocComment(printer, descriptor_);
  MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
                                /* immutable = */ true);
  // The builder_type stores the super type name of the nested Builder class.
  std::string builder_type;
  if (descriptor_->extension_range_count() > 0) {
    printer->Print(
        variables,
        "$deprecation$public $static$final class $classname$ extends\n");
    printer->Annotate("classname", descriptor_);
    printer->Print(
        variables,
        "    com.google.protobuf.GeneratedMessage$ver$.ExtendableMessage<\n"
        "      $classname$> implements\n"
        "    $extra_interfaces$\n"
        "    $classname$OrBuilder {\n");
    builder_type = strings::Substitute(
        "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
        name_resolver_->GetImmutableClassName(descriptor_),
        GeneratedCodeVersionSuffix());
  } else {
    printer->Print(
        variables,
        "$deprecation$public $static$final class $classname$ extends\n");
    printer->Annotate("classname", descriptor_);
    printer->Print(variables,
                   "    com.google.protobuf.GeneratedMessage$ver$ implements\n"
                   "    $extra_interfaces$\n"
                   "    $classname$OrBuilder {\n");
    builder_type =
        strings::Substitute("com.google.protobuf.GeneratedMessage$0.Builder<?>",
                         GeneratedCodeVersionSuffix());
  }
  printer->Print("private static final long serialVersionUID = 0L;\n");

  printer->Indent();
  // Using builder_type, instead of Builder, prevents the Builder class from
  // being loaded into PermGen space when the default instance is created.
  // This optimizes the PermGen space usage for clients that do not modify
  // messages.
  printer->Print(
      "// Use $classname$.newBuilder() to construct.\n"
      "private $classname$($buildertype$ builder) {\n"
      "  super(builder);\n"
      "}\n",
      "classname", descriptor_->name(), "buildertype", builder_type);
  printer->Print("private $classname$() {\n", "classname", descriptor_->name());
  printer->Indent();
  GenerateInitializers(printer);
  printer->Outdent();
  printer->Print(
      "}\n"
      "\n");

  printer->Print(variables,
                 "@java.lang.Override\n"
                 "@SuppressWarnings({\"unused\"})\n"
                 "protected java.lang.Object newInstance(\n"
                 "    UnusedPrivateParameter unused) {\n"
                 "  return new $classname$();\n"
                 "}\n"
                 "\n");

  // TODO(b/248149118): Remove this superfluous override.
  printer->Print(
      "@java.lang.Override\n"
      "public final com.google.protobuf.UnknownFieldSet\n"
      "getUnknownFields() {\n"
      "  return this.unknownFields;\n"
      "}\n");

  GenerateDescriptorMethods(printer);

  // Nested types
  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
    EnumGenerator(descriptor_->enum_type(i), true, context_).Generate(printer);
  }

  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
    // Don't generate Java classes for map entry messages.
    if (IsMapEntry(descriptor_->nested_type(i))) continue;
    ImmutableMessageGenerator messageGenerator(descriptor_->nested_type(i),
                                               context_);
    messageGenerator.GenerateInterface(printer);
    messageGenerator.Generate(printer);
  }

  // Integers for bit fields.
  int totalBits = 0;
  for (int i = 0; i < descriptor_->field_count(); i++) {
    totalBits +=
        field_generators_.get(descriptor_->field(i)).GetNumBitsForMessage();
  }
  int totalInts = (totalBits + 31) / 32;
  for (int i = 0; i < totalInts; i++) {
    printer->Print("private int $bit_field_name$;\n", "bit_field_name",
                   GetBitFieldName(i));
  }

  // oneof
  std::map<std::string, std::string> vars;
  for (auto oneof : oneofs_) {
    vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name;
    vars["oneof_capitalized_name"] =
        context_->GetOneofGeneratorInfo(oneof)->capitalized_name;
    vars["oneof_index"] = StrCat((oneof)->index());
    // oneofCase_ and oneof_
    printer->Print(vars,
                   "private int $oneof_name$Case_ = 0;\n"
                   "private java.lang.Object $oneof_name$_;\n");
    // OneofCase enum
    printer->Print(
        vars,
        "public enum $oneof_capitalized_name$Case\n"
        // TODO(dweis): Remove EnumLite when we want to break compatibility with
        // 3.x users
        "    implements com.google.protobuf.Internal.EnumLite,\n"
        "        com.google.protobuf.AbstractMessage.InternalOneOfEnum {\n");
    printer->Indent();
    for (int j = 0; j < (oneof)->field_count(); j++) {
      const FieldDescriptor* field = (oneof)->field(j);
      printer->Print(
          "$deprecation$$field_name$($field_number$),\n", "deprecation",
          field->options().deprecated() ? "@java.lang.Deprecated " : "",
          "field_name", ToUpper(field->name()), "field_number",
          StrCat(field->number()));
    }
    printer->Print("$cap_oneof_name$_NOT_SET(0);\n", "cap_oneof_name",
                   ToUpper(vars["oneof_name"]));
    printer->Print(vars,
                   "private final int value;\n"
                   "private $oneof_capitalized_name$Case(int value) {\n"
                   "  this.value = value;\n"
                   "}\n");
    printer->Print(
        vars,
        "/**\n"
        " * @param value The number of the enum to look for.\n"
        " * @return The enum associated with the given number.\n"
        " * @deprecated Use {@link #forNumber(int)} instead.\n"
        " */\n"
        "@java.lang.Deprecated\n"
        "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
        "  return forNumber(value);\n"
        "}\n"
        "\n"
        "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
        "  switch (value) {\n");
    for (int j = 0; j < (oneof)->field_count(); j++) {
      const FieldDescriptor* field = (oneof)->field(j);
      printer->Print("    case $field_number$: return $field_name$;\n",
                     "field_number", StrCat(field->number()),
                     "field_name", ToUpper(field->name()));
    }
    printer->Print(
        "    case 0: return $cap_oneof_name$_NOT_SET;\n"
        "    default: return null;\n"
        "  }\n"
        "}\n"
        "public int getNumber() {\n"
        "  return this.value;\n"
        "}\n",
        "cap_oneof_name", ToUpper(vars["oneof_name"]));
    printer->Outdent();
    printer->Print("};\n\n");
    // oneofCase()
    printer->Print(vars,
                   "public $oneof_capitalized_name$Case\n"
                   "get$oneof_capitalized_name$Case() {\n"
                   "  return $oneof_capitalized_name$Case.forNumber(\n"
                   "      $oneof_name$Case_);\n"
                   "}\n"
                   "\n");
  }

  if (IsAnyMessage(descriptor_)) {
    GenerateAnyMethods(printer);
  }

  // Fields
  for (int i = 0; i < descriptor_->field_count(); i++) {
    printer->Print("public static final int $constant_name$ = $number$;\n",
                   "constant_name", FieldConstantName(descriptor_->field(i)),
                   "number", StrCat(descriptor_->field(i)->number()));
    printer->Annotate("constant_name", descriptor_->field(i));
    field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
    printer->Print("\n");
  }

  if (context_->HasGeneratedMethods(descriptor_)) {
    GenerateIsInitialized(printer);
    GenerateMessageSerializationMethods(printer);
    GenerateEqualsAndHashCode(printer);
  }


  GenerateParseFromMethods(printer);
  GenerateBuilder(printer);

  printer->Print(
      "\n"
      "// @@protoc_insertion_point(class_scope:$full_name$)\n",
      "full_name", descriptor_->full_name());

  // Carefully initialize the default instance in such a way that it doesn't
  // conflict with other initialization.
  printer->Print("private static final $classname$ DEFAULT_INSTANCE;\n",
                 "classname",
                 name_resolver_->GetImmutableClassName(descriptor_));
  printer->Print(
      "static {\n"
      "  DEFAULT_INSTANCE = new $classname$();\n"
      "}\n"
      "\n",
      "classname", name_resolver_->GetImmutableClassName(descriptor_));

  printer->Print(
      "public static $classname$ getDefaultInstance() {\n"
      "  return DEFAULT_INSTANCE;\n"
      "}\n"
      "\n",
      "classname", name_resolver_->GetImmutableClassName(descriptor_));

  // 'of' method for Wrappers
  if (IsWrappersProtoFile(descriptor_->file())) {
    printer->Print(
        "public static $classname$ of($field_type$ value) {\n"
        "  return newBuilder().setValue(value).build();\n"
        "}\n"
        "\n",
        "classname", name_resolver_->GetImmutableClassName(descriptor_),
        "field_type", PrimitiveTypeName(GetJavaType(descriptor_->field(0))));
  }

  GenerateParser(printer);

  printer->Print(
      "@java.lang.Override\n"
      "public $classname$ getDefaultInstanceForType() {\n"
      "  return DEFAULT_INSTANCE;\n"
      "}\n"
      "\n",
      "classname", name_resolver_->GetImmutableClassName(descriptor_));

  // Extensions must be declared after the DEFAULT_INSTANCE is initialized
  // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
  // the outer class's FileDescriptor.
  for (int i = 0; i < descriptor_->extension_count(); i++) {
    ImmutableExtensionGenerator(descriptor_->extension(i), context_)
        .Generate(printer);
  }

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