Use bit-field int values in buildPartial to skip work on unset groups of fields.

Changes to make this improvement:
1) All non-repeated builder fields (including maps) now have a presence bit regardless of syntax.
2) The buildPartial method is split into one method per 32-field block (aligned with bit-mask ints)
3) If a presence bit-mask int is set to 0, no fields are present, so we can skip the logic for all of those fields in the buildPartial step.

For messages with a lot of fields (> 100) that are sparsely populated this can result in a significant improvement. Not only does it potentially skip a lot of field copying logic, but also breaks the buildPartial method into chunks that should be more easily digested by the JIT compiler as discussed in this issue: https://github.com/protocolbuffers/protobuf/issues/10247.

PiperOrigin-RevId: 485952448
pull/10960/head
Protobuf Team Bot 2 years ago committed by Jerry Berg
parent accd49b95a
commit b0f7bff40c
  1. 181
      src/google/protobuf/compiler/java/enum_field.cc
  2. 32
      src/google/protobuf/compiler/java/enum_field.h
  3. 2
      src/google/protobuf/compiler/java/field.h
  4. 327
      src/google/protobuf/compiler/java/map_field.cc
  5. 7
      src/google/protobuf/compiler/java/map_field.h
  6. 257
      src/google/protobuf/compiler/java/message_builder.cc
  7. 5
      src/google/protobuf/compiler/java/message_builder.h
  8. 315
      src/google/protobuf/compiler/java/message_field.cc
  9. 57
      src/google/protobuf/compiler/java/message_field.h
  10. 199
      src/google/protobuf/compiler/java/primitive_field.cc
  11. 33
      src/google/protobuf/compiler/java/primitive_field.h
  12. 145
      src/google/protobuf/compiler/java/string_field.cc
  13. 32
      src/google/protobuf/compiler/java/string_field.h

@ -32,24 +32,24 @@
// Based on original Protocol Buffers design by // Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others. // Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/java/enum_field.h> #include "google/protobuf/compiler/java/enum_field.h"
#include <cstdint> #include <cstdint>
#include <map> #include <map>
#include <string> #include <string>
#include <google/protobuf/stubs/logging.h> #include "google/protobuf/stubs/logging.h"
#include <google/protobuf/stubs/common.h> #include "google/protobuf/stubs/common.h"
#include <google/protobuf/io/printer.h> #include "google/protobuf/io/printer.h"
#include <google/protobuf/wire_format.h> #include "google/protobuf/wire_format.h"
#include <google/protobuf/stubs/strutil.h> #include "google/protobuf/stubs/strutil.h"
#include <google/protobuf/compiler/java/context.h> #include "google/protobuf/compiler/java/context.h"
#include <google/protobuf/compiler/java/doc_comment.h> #include "google/protobuf/compiler/java/doc_comment.h"
#include <google/protobuf/compiler/java/helpers.h> #include "google/protobuf/compiler/java/helpers.h"
#include <google/protobuf/compiler/java/name_resolver.h> #include "google/protobuf/compiler/java/name_resolver.h"
// Must be last. // Must be last.
#include <google/protobuf/port_def.inc> #include "google/protobuf/port_def.inc"
namespace google { namespace google {
namespace protobuf { namespace protobuf {
@ -58,10 +58,11 @@ namespace java {
namespace { namespace {
void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex, void SetEnumVariables(
int builderBitIndex, const FieldGeneratorInfo* info, const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
ClassNameResolver* name_resolver, const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
std::map<std::string, std::string>* variables) { std::map<std::string, std::string>* variables,
Context* context) {
SetCommonFieldVariables(descriptor, info, variables); SetCommonFieldVariables(descriptor, info, variables);
(*variables)["type"] = (*variables)["type"] =
@ -80,40 +81,27 @@ void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
// by the proto compiler // by the proto compiler
(*variables)["deprecation"] = (*variables)["deprecation"] =
descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] = variables->insert(
descriptor->options().deprecated() {"kt_deprecation",
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + descriptor->options().deprecated()
" is deprecated\") " ? StrCat("@kotlin.Deprecated(message = \"Field ",
: ""; (*variables)["name"], " is deprecated\") ")
(*variables)["on_changed"] = "onChanged();"; : ""});
// Use deprecated valueOf() method to be compatible with old generated code
// for v2.5.0/v2.6.1.
// TODO(xiaofeng): Use "forNumber" when we no longer support compatibility
// with v2.5.0/v2.6.1, and remove the @SuppressWarnings annotations.
(*variables)["for_number"] = "valueOf";
if (HasHasbit(descriptor)) { if (HasHasbit(descriptor)) {
// For singular messages and builders, one bit is used for the hasField bit. // For singular messages and builders, one bit is used for the hasField bit.
(*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
// Note that these have a trailing ";". // Note that these have a trailing ";".
(*variables)["set_has_field_bit_message"] = (*variables)["set_has_field_bit_message"] =
GenerateSetBit(messageBitIndex) + ";"; GenerateSetBit(messageBitIndex) + ";";
(*variables)["set_has_field_bit_builder"] = (*variables)["set_has_field_bit_to_local"] =
GenerateSetBit(builderBitIndex) + ";"; GenerateSetBitToLocal(messageBitIndex);
(*variables)["clear_has_field_bit_builder"] =
GenerateClearBit(builderBitIndex) + ";";
(*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
} else { } else {
(*variables)["set_has_field_bit_message"] = ""; (*variables)["set_has_field_bit_message"] = "";
(*variables)["set_has_field_bit_builder"] = ""; (*variables)["set_has_field_bit_to_local"] = "";
(*variables)["clear_has_field_bit_builder"] = ""; variables->insert({"is_field_present_message",
StrCat((*variables)["name"], "_ != ",
(*variables)["is_field_present_message"] = (*variables)["default"], ".getNumber()")});
(*variables)["name"] + "_ != " + (*variables)["default"] +
".getNumber()";
} }
// For repeated builders, one bit is used for whether the array is immutable. // For repeated builders, one bit is used for whether the array is immutable.
@ -121,15 +109,21 @@ void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
(*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
(*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
// Note that these have a trailing ";".
(*variables)["set_has_field_bit_builder"] =
GenerateSetBit(builderBitIndex) + ";";
(*variables)["clear_has_field_bit_builder"] =
GenerateClearBit(builderBitIndex) + ";";
(*variables)["get_has_field_bit_from_local"] = (*variables)["get_has_field_bit_from_local"] =
GenerateGetBitFromLocal(builderBitIndex); GenerateGetBitFromLocal(builderBitIndex);
(*variables)["set_has_field_bit_to_local"] =
GenerateSetBitToLocal(messageBitIndex);
if (SupportUnknownEnumValue(descriptor->file())) { if (SupportUnknownEnumValue(descriptor->file())) {
(*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED"; variables->insert(
{"unknown", StrCat((*variables)["type"], ".UNRECOGNIZED")});
} else { } else {
(*variables)["unknown"] = (*variables)["default"]; variables->insert({"unknown", (*variables)["default"]});
} }
} }
@ -140,21 +134,30 @@ void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
ImmutableEnumFieldGenerator::ImmutableEnumFieldGenerator( ImmutableEnumFieldGenerator::ImmutableEnumFieldGenerator(
const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
Context* context) Context* context)
: descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { : descriptor_(descriptor),
message_bit_index_(messageBitIndex),
builder_bit_index_(builderBitIndex),
name_resolver_(context->GetNameResolver()) {
SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
context->GetFieldGeneratorInfo(descriptor), name_resolver_, context->GetFieldGeneratorInfo(descriptor), name_resolver_,
&variables_); &variables_, context);
} }
ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {} ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {}
int ImmutableEnumFieldGenerator::GetMessageBitIndex() const {
return message_bit_index_;
}
int ImmutableEnumFieldGenerator::GetBuilderBitIndex() const {
return builder_bit_index_;
}
int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const { int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
return HasHasbit(descriptor_) ? 1 : 0; return HasHasbit(descriptor_) ? 1 : 0;
} }
int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { return 1; }
return GetNumBitsForMessage();
}
void ImmutableEnumFieldGenerator::GenerateInterfaceMembers( void ImmutableEnumFieldGenerator::GenerateInterfaceMembers(
io::Printer* printer) const { io::Printer* printer) const {
@ -173,7 +176,7 @@ void ImmutableEnumFieldGenerator::GenerateInterfaceMembers(
} }
void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const { void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const {
printer->Print(variables_, "private int $name$_;\n"); printer->Print(variables_, "private int $name$_ = $default_number$;\n");
PrintExtraFieldInfo(variables_, printer); PrintExtraFieldInfo(variables_, printer);
if (HasHazzer(descriptor_)) { if (HasHazzer(descriptor_)) {
WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
@ -197,8 +200,7 @@ void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"@java.lang.Override $deprecation$public $type$ " "@java.lang.Override $deprecation$public $type$ "
"${$get$capitalized_name$$}$() {\n" "${$get$capitalized_name$$}$() {\n"
" @SuppressWarnings(\"deprecation\")\n" " $type$ result = $type$.forNumber($name$_);\n"
" $type$ result = $type$.$for_number$($name$_);\n"
" return result == null ? $unknown$ : result;\n" " return result == null ? $unknown$ : result;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -229,9 +231,9 @@ void ImmutableEnumFieldGenerator::GenerateBuilderMembers(
printer->Print(variables_, printer->Print(variables_,
"$deprecation$public Builder " "$deprecation$public Builder "
"${$set$capitalized_name$Value$}$(int value) {\n" "${$set$capitalized_name$Value$}$(int value) {\n"
" $set_has_field_bit_builder$\n"
" $name$_ = value;\n" " $name$_ = value;\n"
" $on_changed$\n" " $set_has_field_bit_builder$\n"
" onChanged();\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -240,8 +242,7 @@ void ImmutableEnumFieldGenerator::GenerateBuilderMembers(
printer->Print(variables_, printer->Print(variables_,
"@java.lang.Override\n" "@java.lang.Override\n"
"$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
" @SuppressWarnings(\"deprecation\")\n" " $type$ result = $type$.forNumber($name$_);\n"
" $type$ result = $type$.$for_number$($name$_);\n"
" return result == null ? $unknown$ : result;\n" " return result == null ? $unknown$ : result;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -255,7 +256,7 @@ void ImmutableEnumFieldGenerator::GenerateBuilderMembers(
" }\n" " }\n"
" $set_has_field_bit_builder$\n" " $set_has_field_bit_builder$\n"
" $name$_ = value.getNumber();\n" " $name$_ = value.getNumber();\n"
" $on_changed$\n" " onChanged();\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -266,7 +267,7 @@ void ImmutableEnumFieldGenerator::GenerateBuilderMembers(
"$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
" $clear_has_field_bit_builder$\n" " $clear_has_field_bit_builder$\n"
" $name$_ = $default_number$;\n" " $name$_ = $default_number$;\n"
" $on_changed$\n" " onChanged();\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -313,9 +314,7 @@ void ImmutableEnumFieldGenerator::GenerateInitializationCode(
void ImmutableEnumFieldGenerator::GenerateBuilderClearCode( void ImmutableEnumFieldGenerator::GenerateBuilderClearCode(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_, "$name$_ = $default_number$;\n");
"$name$_ = $default_number$;\n"
"$clear_has_field_bit_builder$\n");
} }
void ImmutableEnumFieldGenerator::GenerateMergingCode( void ImmutableEnumFieldGenerator::GenerateMergingCode(
@ -338,13 +337,13 @@ void ImmutableEnumFieldGenerator::GenerateMergingCode(
void ImmutableEnumFieldGenerator::GenerateBuildingCode( void ImmutableEnumFieldGenerator::GenerateBuildingCode(
io::Printer* printer) const { io::Printer* printer) const {
if (HasHazzer(descriptor_)) { printer->Print(variables_,
printer->Print(variables_, "if ($get_has_field_bit_from_local$) {\n"
"if ($get_has_field_bit_from_local$) {\n" " result.$name$_ = $name$_;\n");
" $set_has_field_bit_to_local$;\n" if (GetNumBitsForMessage() > 0) {
"}\n"); printer->Print(variables_, " $set_has_field_bit_to_local$;\n");
} }
printer->Print(variables_, "result.$name$_ = $name$_;\n"); printer->Print("}\n");
} }
void ImmutableEnumFieldGenerator::GenerateBuilderParsingCode( void ImmutableEnumFieldGenerator::GenerateBuilderParsingCode(
@ -440,8 +439,7 @@ void ImmutableEnumOneofFieldGenerator::GenerateMembers(
printer->Print(variables_, printer->Print(variables_,
"$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
" if ($has_oneof_case_message$) {\n" " if ($has_oneof_case_message$) {\n"
" @SuppressWarnings(\"deprecation\")\n" " $type$ result = $type$.forNumber(\n"
" $type$ result = $type$.$for_number$(\n"
" (java.lang.Integer) $oneof_name$_);\n" " (java.lang.Integer) $oneof_name$_);\n"
" return result == null ? $unknown$ : result;\n" " return result == null ? $unknown$ : result;\n"
" }\n" " }\n"
@ -480,7 +478,7 @@ void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers(
"${$set$capitalized_name$Value$}$(int value) {\n" "${$set$capitalized_name$Value$}$(int value) {\n"
" $set_oneof_case_message$;\n" " $set_oneof_case_message$;\n"
" $oneof_name$_ = value;\n" " $oneof_name$_ = value;\n"
" $on_changed$\n" " onChanged();\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -490,14 +488,14 @@ void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers(
"@java.lang.Override\n" "@java.lang.Override\n"
"$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
" if ($has_oneof_case_message$) {\n" " if ($has_oneof_case_message$) {\n"
" @SuppressWarnings(\"deprecation\")\n" " $type$ result = $type$.forNumber(\n"
" $type$ result = $type$.$for_number$(\n"
" (java.lang.Integer) $oneof_name$_);\n" " (java.lang.Integer) $oneof_name$_);\n"
" return result == null ? $unknown$ : result;\n" " return result == null ? $unknown$ : result;\n"
" }\n" " }\n"
" return $default$;\n" " return $default$;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldAccessorDocComment(printer, descriptor_, SETTER, WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
/* builder */ true); /* builder */ true);
printer->Print(variables_, printer->Print(variables_,
@ -508,10 +506,11 @@ void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers(
" }\n" " }\n"
" $set_oneof_case_message$;\n" " $set_oneof_case_message$;\n"
" $oneof_name$_ = value.getNumber();\n" " $oneof_name$_ = value.getNumber();\n"
" $on_changed$\n" " onChanged();\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ true); /* builder */ true);
printer->Print( printer->Print(
@ -520,7 +519,7 @@ void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers(
" if ($has_oneof_case_message$) {\n" " if ($has_oneof_case_message$) {\n"
" $clear_oneof_case_message$;\n" " $clear_oneof_case_message$;\n"
" $oneof_name$_ = null;\n" " $oneof_name$_ = null;\n"
" $on_changed$\n" " onChanged();\n"
" }\n" " }\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
@ -534,10 +533,7 @@ void ImmutableEnumOneofFieldGenerator::GenerateBuilderClearCode(
void ImmutableEnumOneofFieldGenerator::GenerateBuildingCode( void ImmutableEnumOneofFieldGenerator::GenerateBuildingCode(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, // No-Op: Handled by single statement for the oneof
"if ($has_oneof_case_message$) {\n"
" result.$oneof_name$_ = $oneof_name$_;\n"
"}\n");
} }
void ImmutableEnumOneofFieldGenerator::GenerateMergingCode( void ImmutableEnumOneofFieldGenerator::GenerateMergingCode(
@ -626,11 +622,8 @@ void ImmutableEnumOneofFieldGenerator::GenerateHashCode(
RepeatedImmutableEnumFieldGenerator::RepeatedImmutableEnumFieldGenerator( RepeatedImmutableEnumFieldGenerator::RepeatedImmutableEnumFieldGenerator(
const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
Context* context) Context* context)
: descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { : ImmutableEnumFieldGenerator(descriptor, messageBitIndex, builderBitIndex,
SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, context) {}
context->GetFieldGeneratorInfo(descriptor), name_resolver_,
&variables_);
}
RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {} RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {}
@ -670,6 +663,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateMembers(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print( printer->Print(
variables_, variables_,
"@SuppressWarnings(\"serial\")\n"
"private java.util.List<java.lang.Integer> $name$_;\n" "private java.util.List<java.lang.Integer> $name$_;\n"
"private static final " "private static final "
"com.google.protobuf.Internal.ListAdapter.Converter<\n" "com.google.protobuf.Internal.ListAdapter.Converter<\n"
@ -677,8 +671,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateMembers(
" new com.google.protobuf.Internal.ListAdapter.Converter<\n" " new com.google.protobuf.Internal.ListAdapter.Converter<\n"
" java.lang.Integer, $type$>() {\n" " java.lang.Integer, $type$>() {\n"
" public $type$ convert(java.lang.Integer from) {\n" " public $type$ convert(java.lang.Integer from) {\n"
" @SuppressWarnings(\"deprecation\")\n" " $type$ result = $type$.forNumber(from);\n"
" $type$ result = $type$.$for_number$(from);\n"
" return result == null ? $unknown$ : result;\n" " return result == null ? $unknown$ : result;\n"
" }\n" " }\n"
" };\n"); " };\n");
@ -794,7 +787,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers(
" }\n" " }\n"
" ensure$capitalized_name$IsMutable();\n" " ensure$capitalized_name$IsMutable();\n"
" $name$_.set(index, value.getNumber());\n" " $name$_.set(index, value.getNumber());\n"
" $on_changed$\n" " onChanged();\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -808,7 +801,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers(
" }\n" " }\n"
" ensure$capitalized_name$IsMutable();\n" " ensure$capitalized_name$IsMutable();\n"
" $name$_.add(value.getNumber());\n" " $name$_.add(value.getNumber());\n"
" $on_changed$\n" " onChanged();\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -821,7 +814,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers(
" for ($type$ value : values) {\n" " for ($type$ value : values) {\n"
" $name$_.add(value.getNumber());\n" " $name$_.add(value.getNumber());\n"
" }\n" " }\n"
" $on_changed$\n" " onChanged();\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -832,7 +825,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers(
"$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
" $name$_ = java.util.Collections.emptyList();\n" " $name$_ = java.util.Collections.emptyList();\n"
" $clear_mutable_bit_builder$;\n" " $clear_mutable_bit_builder$;\n"
" $on_changed$\n" " onChanged();\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -862,7 +855,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers(
" int index, int value) {\n" " int index, int value) {\n"
" ensure$capitalized_name$IsMutable();\n" " ensure$capitalized_name$IsMutable();\n"
" $name$_.set(index, value);\n" " $name$_.set(index, value);\n"
" $on_changed$\n" " onChanged();\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -873,7 +866,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers(
"${$add$capitalized_name$Value$}$(int value) {\n" "${$add$capitalized_name$Value$}$(int value) {\n"
" ensure$capitalized_name$IsMutable();\n" " ensure$capitalized_name$IsMutable();\n"
" $name$_.add(value);\n" " $name$_.add(value);\n"
" $on_changed$\n" " onChanged();\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -887,7 +880,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers(
" for (int value : values) {\n" " for (int value : values) {\n"
" $name$_.add(value);\n" " $name$_.add(value);\n"
" }\n" " }\n"
" $on_changed$\n" " onChanged();\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -927,7 +920,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateMergingCode(
" ensure$capitalized_name$IsMutable();\n" " ensure$capitalized_name$IsMutable();\n"
" $name$_.addAll(other.$name$_);\n" " $name$_.addAll(other.$name$_);\n"
" }\n" " }\n"
" $on_changed$\n" " onChanged();\n"
"}\n"); "}\n");
} }
@ -1154,4 +1147,4 @@ std::string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const {
} // namespace protobuf } // namespace protobuf
} // namespace google } // namespace google
#include <google/protobuf/port_undef.inc> #include "google/protobuf/port_undef.inc"

@ -38,7 +38,7 @@
#include <map> #include <map>
#include <string> #include <string>
#include <google/protobuf/compiler/java/field.h> #include "google/protobuf/compiler/java/field.h"
namespace google { namespace google {
namespace protobuf { namespace protobuf {
@ -61,10 +61,15 @@ class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator {
explicit ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor, explicit ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor,
int messageBitIndex, int builderBitIndex, int messageBitIndex, int builderBitIndex,
Context* context); Context* context);
ImmutableEnumFieldGenerator(const ImmutableEnumFieldGenerator&) = delete;
ImmutableEnumFieldGenerator& operator=(const ImmutableEnumFieldGenerator&) =
delete;
~ImmutableEnumFieldGenerator() override; ~ImmutableEnumFieldGenerator() override;
// implements ImmutableFieldGenerator // implements ImmutableFieldGenerator
// --------------------------------------- // ---------------------------------------
int GetMessageBitIndex() const override;
int GetBuilderBitIndex() const override;
int GetNumBitsForMessage() const override; int GetNumBitsForMessage() const override;
int GetNumBitsForBuilder() const override; int GetNumBitsForBuilder() const override;
void GenerateInterfaceMembers(io::Printer* printer) const override; void GenerateInterfaceMembers(io::Printer* printer) const override;
@ -87,11 +92,10 @@ class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator {
protected: protected:
const FieldDescriptor* descriptor_; const FieldDescriptor* descriptor_;
int message_bit_index_;
int builder_bit_index_;
std::map<std::string, std::string> variables_; std::map<std::string, std::string> variables_;
ClassNameResolver* name_resolver_; ClassNameResolver* name_resolver_;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldGenerator);
}; };
class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator { class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator {
@ -99,6 +103,10 @@ class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator {
ImmutableEnumOneofFieldGenerator(const FieldDescriptor* descriptor, ImmutableEnumOneofFieldGenerator(const FieldDescriptor* descriptor,
int messageBitIndex, int builderBitIndex, int messageBitIndex, int builderBitIndex,
Context* context); Context* context);
ImmutableEnumOneofFieldGenerator(const ImmutableEnumOneofFieldGenerator&) =
delete;
ImmutableEnumOneofFieldGenerator& operator=(
const ImmutableEnumOneofFieldGenerator&) = delete;
~ImmutableEnumOneofFieldGenerator() override; ~ImmutableEnumOneofFieldGenerator() override;
void GenerateMembers(io::Printer* printer) const override; void GenerateMembers(io::Printer* printer) const override;
@ -111,16 +119,17 @@ class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator {
void GenerateSerializedSizeCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override;
void GenerateEqualsCode(io::Printer* printer) const override; void GenerateEqualsCode(io::Printer* printer) const override;
void GenerateHashCode(io::Printer* printer) const override; void GenerateHashCode(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldGenerator);
}; };
class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator { class RepeatedImmutableEnumFieldGenerator : public ImmutableEnumFieldGenerator {
public: public:
explicit RepeatedImmutableEnumFieldGenerator( explicit RepeatedImmutableEnumFieldGenerator(
const FieldDescriptor* descriptor, int messageBitIndex, const FieldDescriptor* descriptor, int messageBitIndex,
int builderBitIndex, Context* context); int builderBitIndex, Context* context);
RepeatedImmutableEnumFieldGenerator(
const RepeatedImmutableEnumFieldGenerator&) = delete;
RepeatedImmutableEnumFieldGenerator& operator=(
const RepeatedImmutableEnumFieldGenerator&) = delete;
~RepeatedImmutableEnumFieldGenerator() override; ~RepeatedImmutableEnumFieldGenerator() override;
// implements ImmutableFieldGenerator --------------------------------------- // implements ImmutableFieldGenerator ---------------------------------------
@ -145,13 +154,6 @@ class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator {
void GenerateKotlinDslMembers(io::Printer* printer) const override; void GenerateKotlinDslMembers(io::Printer* printer) const override;
std::string GetBoxedType() const override; std::string GetBoxedType() const override;
private:
const FieldDescriptor* descriptor_;
std::map<std::string, std::string> variables_;
ClassNameResolver* name_resolver_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldGenerator);
}; };
} // namespace java } // namespace java

@ -68,6 +68,8 @@ class ImmutableFieldGenerator {
ImmutableFieldGenerator() {} ImmutableFieldGenerator() {}
virtual ~ImmutableFieldGenerator(); virtual ~ImmutableFieldGenerator();
virtual int GetMessageBitIndex() const = 0;
virtual int GetBuilderBitIndex() const = 0;
virtual int GetNumBitsForMessage() const = 0; virtual int GetNumBitsForMessage() const = 0;
virtual int GetNumBitsForBuilder() const = 0; virtual int GetNumBitsForBuilder() const = 0;
virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0; virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0;

@ -28,16 +28,16 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <google/protobuf/compiler/java/map_field.h> #include "google/protobuf/compiler/java/map_field.h"
#include <google/protobuf/io/printer.h> #include "google/protobuf/io/printer.h"
#include <google/protobuf/compiler/java/context.h> #include "google/protobuf/compiler/java/context.h"
#include <google/protobuf/compiler/java/doc_comment.h> #include "google/protobuf/compiler/java/doc_comment.h"
#include <google/protobuf/compiler/java/helpers.h> #include "google/protobuf/compiler/java/helpers.h"
#include <google/protobuf/compiler/java/name_resolver.h> #include "google/protobuf/compiler/java/name_resolver.h"
// Must be last. // Must be last.
#include <google/protobuf/port_def.inc> #include "google/protobuf/port_def.inc"
namespace google { namespace google {
namespace protobuf { namespace protobuf {
@ -88,10 +88,10 @@ std::string WireType(const FieldDescriptor* field) {
std::string(FieldTypeName(field->type())); std::string(FieldTypeName(field->type()));
} }
void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, void SetMessageVariables(
int builderBitIndex, const FieldGeneratorInfo* info, const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
Context* context, const FieldGeneratorInfo* info, Context* context,
std::map<std::string, std::string>* variables) { std::map<std::string, std::string>* variables) {
SetCommonFieldVariables(descriptor, info, variables); SetCommonFieldVariables(descriptor, info, variables);
ClassNameResolver* name_resolver = context->GetNameResolver(); ClassNameResolver* name_resolver = context->GetNameResolver();
@ -120,13 +120,14 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
: ""; : "";
(*variables)["value_null_check"] = (*variables)["value_null_check"] =
valueJavaType != JAVATYPE_ENUM && IsReferenceType(valueJavaType) valueJavaType != JAVATYPE_ENUM && IsReferenceType(valueJavaType)
? "if (value == null) {\n" ? "if (value == null) { "
" throw new NullPointerException(\"map value\");\n" "throw new NullPointerException(\"map value\"); }"
"}\n"
: ""; : "";
if (valueJavaType == JAVATYPE_ENUM) { if (valueJavaType == JAVATYPE_ENUM) {
// We store enums as Integers internally. // We store enums as Integers internally.
(*variables)["value_type"] = "int"; (*variables)["value_type"] = "int";
variables->insert(
{"value_type_pass_through_nullness", (*variables)["value_type"]});
(*variables)["boxed_value_type"] = "java.lang.Integer"; (*variables)["boxed_value_type"] = "java.lang.Integer";
(*variables)["value_wire_type"] = WireType(value); (*variables)["value_wire_type"] = WireType(value);
(*variables)["value_default_value"] = (*variables)["value_default_value"] =
@ -134,13 +135,15 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
(*variables)["value_enum_type"] = TypeName(value, name_resolver, false); (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
(*variables)["value_enum_type_pass_through_nullness"] = variables->insert(
pass_through_nullness + (*variables)["value_enum_type"]; {"value_enum_type_pass_through_nullness",
StrCat(pass_through_nullness, (*variables)["value_enum_type"])});
if (SupportUnknownEnumValue(descriptor->file())) { if (SupportUnknownEnumValue(descriptor->file())) {
// Map unknown values to a special UNRECOGNIZED value if supported. // Map unknown values to a special UNRECOGNIZED value if supported.
(*variables)["unrecognized_value"] = variables->insert(
(*variables)["value_enum_type"] + ".UNRECOGNIZED"; {"unrecognized_value",
StrCat((*variables)["value_enum_type"], ".UNRECOGNIZED")});
} else { } else {
// Map unknown values to the default value if we don't have UNRECOGNIZED. // Map unknown values to the default value if we don't have UNRECOGNIZED.
(*variables)["unrecognized_value"] = (*variables)["unrecognized_value"] =
@ -149,35 +152,48 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
} else { } else {
(*variables)["value_type"] = TypeName(value, name_resolver, false); (*variables)["value_type"] = TypeName(value, name_resolver, false);
(*variables)["value_type_pass_through_nullness"] = variables->insert(
(IsReferenceType(valueJavaType) ? pass_through_nullness : "") + {"value_type_pass_through_nullness",
(*variables)["value_type"]; StrCat(
(IsReferenceType(valueJavaType) ? pass_through_nullness : ""),
(*variables)["value_type"])});
(*variables)["boxed_value_type"] = TypeName(value, name_resolver, true); (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
(*variables)["value_wire_type"] = WireType(value); (*variables)["value_wire_type"] = WireType(value);
(*variables)["value_default_value"] = (*variables)["value_default_value"] =
DefaultValue(value, true, name_resolver); DefaultValue(value, true, name_resolver);
} }
(*variables)["type_parameters"] = variables->insert(
(*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"]; {"type_parameters", StrCat((*variables)["boxed_key_type"], ", ",
(*variables)["boxed_value_type"])});
// TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
// by the proto compiler // by the proto compiler
(*variables)["deprecation"] = (*variables)["deprecation"] =
descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] = variables->insert(
descriptor->options().deprecated() {"kt_deprecation",
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + descriptor->options().deprecated()
" is deprecated\") " ? StrCat("@kotlin.Deprecated(message = \"Field ",
: ""; (*variables)["name"], " is deprecated\") ")
: ""});
(*variables)["on_changed"] = "onChanged();"; (*variables)["on_changed"] = "onChanged();";
(*variables)["default_entry"] = variables->insert(
(*variables)["capitalized_name"] + "DefaultEntryHolder.defaultEntry"; {"default_entry", StrCat((*variables)["capitalized_name"],
(*variables)["map_field_parameter"] = (*variables)["default_entry"]; "DefaultEntryHolder.defaultEntry")});
variables->insert({"map_field_parameter", (*variables)["default_entry"]});
(*variables)["descriptor"] = (*variables)["descriptor"] =
name_resolver->GetImmutableClassName(descriptor->file()) + ".internal_" + name_resolver->GetImmutableClassName(descriptor->file()) + ".internal_" +
UniqueFileScopeIdentifier(descriptor->message_type()) + "_descriptor, "; UniqueFileScopeIdentifier(descriptor->message_type()) + "_descriptor, ";
(*variables)["ver"] = GeneratedCodeVersionSuffix(); (*variables)["ver"] = GeneratedCodeVersionSuffix();
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
(*variables)["get_has_field_bit_from_local"] =
GenerateGetBitFromLocal(builderBitIndex);
(*variables)["set_has_field_bit_builder"] =
GenerateSetBit(builderBitIndex) + ";";
(*variables)["clear_has_field_bit_builder"] =
GenerateClearBit(builderBitIndex) + ";";
} }
} // namespace } // namespace
@ -185,7 +201,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
ImmutableMapFieldGenerator::ImmutableMapFieldGenerator( ImmutableMapFieldGenerator::ImmutableMapFieldGenerator(
const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
Context* context) Context* context)
: descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { : descriptor_(descriptor),
message_bit_index_(messageBitIndex),
builder_bit_index_(builderBitIndex),
name_resolver_(context->GetNameResolver()),
context_(context) {
SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
context->GetFieldGeneratorInfo(descriptor), context, context->GetFieldGeneratorInfo(descriptor), context,
&variables_); &variables_);
@ -193,6 +213,14 @@ ImmutableMapFieldGenerator::ImmutableMapFieldGenerator(
ImmutableMapFieldGenerator::~ImmutableMapFieldGenerator() {} ImmutableMapFieldGenerator::~ImmutableMapFieldGenerator() {}
int ImmutableMapFieldGenerator::GetMessageBitIndex() const {
return message_bit_index_;
}
int ImmutableMapFieldGenerator::GetBuilderBitIndex() const {
return builder_bit_index_;
}
int ImmutableMapFieldGenerator::GetNumBitsForMessage() const { return 0; } int ImmutableMapFieldGenerator::GetNumBitsForMessage() const { return 0; }
int ImmutableMapFieldGenerator::GetNumBitsForBuilder() const { return 1; } int ImmutableMapFieldGenerator::GetNumBitsForBuilder() const { return 1; }
@ -254,16 +282,16 @@ void ImmutableMapFieldGenerator::GenerateInterfaceMembers(
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(variables_,
"$deprecation$\n" "$deprecation$$value_type_pass_through_nullness$ "
"$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n" "${$get$capitalized_name$ValueOrDefault$}$(\n"
" $key_type$ key,\n" " $key_type$ key,\n"
" $value_type$ defaultValue);\n"); " $value_type_pass_through_nullness$ defaultValue);\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(
"$deprecation$\n" variables_,
"$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n" "$deprecation$$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
" $key_type$ key);\n"); " $key_type$ key);\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
} }
} else { } else {
@ -282,17 +310,16 @@ void ImmutableMapFieldGenerator::GenerateInterfaceMembers(
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(variables_,
"$deprecation$\n" "$deprecation$$value_type_pass_through_nullness$ "
"$value_type_pass_through_nullness$ "
"${$get$capitalized_name$OrDefault$}$(\n" "${$get$capitalized_name$OrDefault$}$(\n"
" $key_type$ key,\n" " $key_type$ key,\n"
" $value_type_pass_through_nullness$ defaultValue);\n"); " $value_type_pass_through_nullness$ defaultValue);\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(
"$deprecation$\n" variables_,
"$value_type$ ${$get$capitalized_name$OrThrow$}$(\n" "$deprecation$$value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
" $key_type$ key);\n"); " $key_type$ key);\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
} }
} }
@ -312,6 +339,7 @@ void ImmutableMapFieldGenerator::GenerateMembers(io::Printer* printer) const {
" $value_default_value$);\n" " $value_default_value$);\n"
"}\n"); "}\n");
printer->Print(variables_, printer->Print(variables_,
"@SuppressWarnings(\"serial\")\n"
"private com.google.protobuf.MapField<\n" "private com.google.protobuf.MapField<\n"
" $type_parameters$> $name$_;\n" " $type_parameters$> $name$_;\n"
"private com.google.protobuf.MapField<$type_parameters$>\n" "private com.google.protobuf.MapField<$type_parameters$>\n"
@ -347,42 +375,45 @@ void ImmutableMapFieldGenerator::GenerateMembers(io::Printer* printer) const {
void ImmutableMapFieldGenerator::GenerateBuilderMembers( void ImmutableMapFieldGenerator::GenerateBuilderMembers(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, printer->Print(
"private com.google.protobuf.MapField<\n" variables_,
" $type_parameters$> $name$_;\n" "private com.google.protobuf.MapField<\n"
"private com.google.protobuf.MapField<$type_parameters$>\n" " $type_parameters$> $name$_;\n"
"internalGet$capitalized_name$() {\n" "$deprecation$private com.google.protobuf.MapField<$type_parameters$>\n"
" if ($name$_ == null) {\n" " internalGet$capitalized_name$() {\n"
" return com.google.protobuf.MapField.emptyMapField(\n" " if ($name$_ == null) {\n"
" $map_field_parameter$);\n" " return com.google.protobuf.MapField.emptyMapField(\n"
" }\n" " $map_field_parameter$);\n"
" return $name$_;\n" " }\n"
"}\n" " return $name$_;\n"
"private com.google.protobuf.MapField<$type_parameters$>\n" "}\n"
"internalGetMutable$capitalized_name$() {\n" "$deprecation$private com.google.protobuf.MapField<$type_parameters$>\n"
" $on_changed$;\n" " internalGetMutable$capitalized_name$() {\n"
" if ($name$_ == null) {\n" " if ($name$_ == null) {\n"
" $name$_ = com.google.protobuf.MapField.newMapField(\n" " $name$_ = com.google.protobuf.MapField.newMapField(\n"
" $map_field_parameter$);\n" " $map_field_parameter$);\n"
" }\n" " }\n"
" if (!$name$_.isMutable()) {\n" " if (!$name$_.isMutable()) {\n"
" $name$_ = $name$_.copy();\n" " $name$_ = $name$_.copy();\n"
" }\n" " }\n"
" return $name$_;\n" " $set_has_field_bit_builder$\n"
"}\n"); " $on_changed$\n"
" return $name$_;\n"
"}\n");
GenerateMapGetters(printer); GenerateMapGetters(printer);
printer->Print(variables_, printer->Print(
"$deprecation$\n" variables_,
"public Builder ${$clear$capitalized_name$$}$() {\n" "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
" internalGetMutable$capitalized_name$().getMutableMap()\n" " $clear_has_field_bit_builder$\n"
" .clear();\n" " internalGetMutable$capitalized_name$().getMutableMap()\n"
" return this;\n" " .clear();\n"
"}\n"); " return this;\n"
"}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(variables_,
"$deprecation$\n" "$deprecation$public Builder ${$remove$capitalized_name$$}$(\n"
"public Builder ${$remove$capitalized_name$$}$(\n"
" $key_type$ key) {\n" " $key_type$ key) {\n"
" $key_null_check$\n" " $key_null_check$\n"
" internalGetMutable$capitalized_name$().getMutableMap()\n" " internalGetMutable$capitalized_name$().getMutableMap()\n"
@ -390,6 +421,7 @@ void ImmutableMapFieldGenerator::GenerateBuilderMembers(
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
printer->Print( printer->Print(
variables_, variables_,
@ -398,7 +430,8 @@ void ImmutableMapFieldGenerator::GenerateBuilderMembers(
" */\n" " */\n"
"@java.lang.Deprecated\n" "@java.lang.Deprecated\n"
"public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
"${$getMutable$capitalized_name$$}$() {\n" " ${$getMutable$capitalized_name$$}$() {\n"
" $set_has_field_bit_builder$\n"
" return internalGetAdapted$capitalized_name$Map(\n" " return internalGetAdapted$capitalized_name$Map(\n"
" internalGetMutable$capitalized_name$().getMutableMap());\n" " internalGetMutable$capitalized_name$().getMutableMap());\n"
"}\n"); "}\n");
@ -412,9 +445,11 @@ void ImmutableMapFieldGenerator::GenerateBuilderMembers(
" $value_null_check$\n" " $value_null_check$\n"
" internalGetMutable$capitalized_name$().getMutableMap()\n" " internalGetMutable$capitalized_name$().getMutableMap()\n"
" .put(key, $name$ValueConverter.doBackward(value));\n" " .put(key, $name$ValueConverter.doBackward(value));\n"
" $set_has_field_bit_builder$\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(
variables_, variables_,
@ -423,9 +458,11 @@ void ImmutableMapFieldGenerator::GenerateBuilderMembers(
" internalGetAdapted$capitalized_name$Map(\n" " internalGetAdapted$capitalized_name$Map(\n"
" internalGetMutable$capitalized_name$().getMutableMap())\n" " internalGetMutable$capitalized_name$().getMutableMap())\n"
" .putAll(values);\n" " .putAll(values);\n"
" $set_has_field_bit_builder$\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
if (SupportUnknownEnumValue(descriptor_->file())) { if (SupportUnknownEnumValue(descriptor_->file())) {
printer->Print( printer->Print(
variables_, variables_,
@ -435,6 +472,7 @@ void ImmutableMapFieldGenerator::GenerateBuilderMembers(
"@java.lang.Deprecated\n" "@java.lang.Deprecated\n"
"public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
"${$getMutable$capitalized_name$Value$}$() {\n" "${$getMutable$capitalized_name$Value$}$() {\n"
" $set_has_field_bit_builder$\n"
" return internalGetMutable$capitalized_name$().getMutableMap();\n" " return internalGetMutable$capitalized_name$().getMutableMap();\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -448,9 +486,11 @@ void ImmutableMapFieldGenerator::GenerateBuilderMembers(
" $value_null_check$\n" " $value_null_check$\n"
" internalGetMutable$capitalized_name$().getMutableMap()\n" " internalGetMutable$capitalized_name$().getMutableMap()\n"
" .put(key, value);\n" " .put(key, value);\n"
" $set_has_field_bit_builder$\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(
variables_, variables_,
@ -458,6 +498,7 @@ void ImmutableMapFieldGenerator::GenerateBuilderMembers(
" java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n" " java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
" internalGetMutable$capitalized_name$().getMutableMap()\n" " internalGetMutable$capitalized_name$().getMutableMap()\n"
" .putAll(values);\n" " .putAll(values);\n"
" $set_has_field_bit_builder$\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -470,55 +511,59 @@ void ImmutableMapFieldGenerator::GenerateBuilderMembers(
" */\n" " */\n"
"@java.lang.Deprecated\n" "@java.lang.Deprecated\n"
"public java.util.Map<$type_parameters$>\n" "public java.util.Map<$type_parameters$>\n"
"${$getMutable$capitalized_name$$}$() {\n" " ${$getMutable$capitalized_name$$}$() {\n"
" $set_has_field_bit_builder$\n"
" return internalGetMutable$capitalized_name$().getMutableMap();\n" " return internalGetMutable$capitalized_name$().getMutableMap();\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(variables_,
"$deprecation$" "$deprecation$public Builder ${$put$capitalized_name$$}$(\n"
"public Builder ${$put$capitalized_name$$}$(\n"
" $key_type$ key,\n" " $key_type$ key,\n"
" $value_type$ value) {\n" " $value_type$ value) {\n"
" $key_null_check$\n" " $key_null_check$\n"
" $value_null_check$\n" " $value_null_check$\n"
" internalGetMutable$capitalized_name$().getMutableMap()\n" " internalGetMutable$capitalized_name$().getMutableMap()\n"
" .put(key, value);\n" " .put(key, value);\n"
" $set_has_field_bit_builder$\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(
"$deprecation$\n" variables_,
"public Builder ${$putAll$capitalized_name$$}$(\n" "$deprecation$public Builder ${$putAll$capitalized_name$$}$(\n"
" java.util.Map<$type_parameters$> values) {\n" " java.util.Map<$type_parameters$> values) {\n"
" internalGetMutable$capitalized_name$().getMutableMap()\n" " internalGetMutable$capitalized_name$().getMutableMap()\n"
" .putAll(values);\n" " .putAll(values);\n"
" return this;\n" " $set_has_field_bit_builder$\n"
"}\n"); " return this;\n"
"}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
} }
} }
void ImmutableMapFieldGenerator::GenerateMapGetters( void ImmutableMapFieldGenerator::GenerateMapGetters(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, printer->Print(
"$deprecation$\n" variables_,
"public int ${$get$capitalized_name$Count$}$() {\n" "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
" return internalGet$capitalized_name$().getMap().size();\n" " return internalGet$capitalized_name$().getMap().size();\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(
variables_, variables_,
"$deprecation$\n"
"@java.lang.Override\n" "@java.lang.Override\n"
"public boolean ${$contains$capitalized_name$$}$(\n" "$deprecation$public boolean ${$contains$capitalized_name$$}$(\n"
" $key_type$ key) {\n" " $key_type$ key) {\n"
" $key_null_check$\n" " $key_null_check$\n"
" return internalGet$capitalized_name$().getMap().containsKey(key);\n" " return internalGet$capitalized_name$().getMap().containsKey(key);\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
printer->Print(variables_, printer->Print(variables_,
"/**\n" "/**\n"
@ -534,19 +579,19 @@ void ImmutableMapFieldGenerator::GenerateMapGetters(
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(variables_,
"@java.lang.Override\n" "@java.lang.Override\n"
"$deprecation$\n" "$deprecation$public java.util.Map<$boxed_key_type$, "
"public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" "$value_enum_type$>\n"
"${$get$capitalized_name$Map$}$() {\n" "${$get$capitalized_name$Map$}$() {\n"
" return internalGetAdapted$capitalized_name$Map(\n" " return internalGetAdapted$capitalized_name$Map(\n"
" internalGet$capitalized_name$().getMap());" " internalGet$capitalized_name$().getMap());"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(
variables_, variables_,
"@java.lang.Override\n" "@java.lang.Override\n"
"$deprecation$\n" "$deprecation$public $value_enum_type_pass_through_nullness$ "
"public $value_enum_type_pass_through_nullness$ "
"${$get$capitalized_name$OrDefault$}$(\n" "${$get$capitalized_name$OrDefault$}$(\n"
" $key_type$ key,\n" " $key_type$ key,\n"
" $value_enum_type_pass_through_nullness$ defaultValue) {\n" " $value_enum_type_pass_through_nullness$ defaultValue) {\n"
@ -558,12 +603,12 @@ void ImmutableMapFieldGenerator::GenerateMapGetters(
" : defaultValue;\n" " : defaultValue;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(
variables_, variables_,
"@java.lang.Override\n" "@java.lang.Override\n"
"$deprecation$\n" "$deprecation$public $value_enum_type$ get$capitalized_name$OrThrow(\n"
"public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
" $key_type$ key) {\n" " $key_type$ key) {\n"
" $key_null_check$\n" " $key_null_check$\n"
" java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n" " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
@ -574,6 +619,7 @@ void ImmutableMapFieldGenerator::GenerateMapGetters(
" return $name$ValueConverter.doForward(map.get(key));\n" " return $name$ValueConverter.doForward(map.get(key));\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
if (SupportUnknownEnumValue(descriptor_->file())) { if (SupportUnknownEnumValue(descriptor_->file())) {
printer->Print( printer->Print(
variables_, variables_,
@ -588,23 +634,22 @@ void ImmutableMapFieldGenerator::GenerateMapGetters(
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(variables_,
variables_, "@java.lang.Override\n"
"@java.lang.Override\n" "$deprecation$public java.util.Map<$boxed_key_type$, "
"$deprecation$\n" "$boxed_value_type$>\n"
"public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "${$get$capitalized_name$ValueMap$}$() {\n"
"${$get$capitalized_name$ValueMap$}$() {\n" " return internalGet$capitalized_name$().getMap();\n"
" return internalGet$capitalized_name$().getMap();\n" "}\n");
"}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(
variables_, variables_,
"@java.lang.Override\n" "@java.lang.Override\n"
"$deprecation$\n" "$deprecation$public $value_type_pass_through_nullness$ "
"public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n" "${$get$capitalized_name$ValueOrDefault$}$(\n"
" $key_type$ key,\n" " $key_type$ key,\n"
" $value_type$ defaultValue) {\n" " $value_type_pass_through_nullness$ defaultValue) {\n"
" $key_null_check$\n" " $key_null_check$\n"
" java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n" " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
" internalGet$capitalized_name$().getMap();\n" " internalGet$capitalized_name$().getMap();\n"
@ -615,8 +660,8 @@ void ImmutableMapFieldGenerator::GenerateMapGetters(
printer->Print( printer->Print(
variables_, variables_,
"@java.lang.Override\n" "@java.lang.Override\n"
"$deprecation$\n" "$deprecation$public $value_type$ "
"public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n" "${$get$capitalized_name$ValueOrThrow$}$(\n"
" $key_type$ key) {\n" " $key_type$ key) {\n"
" $key_null_check$\n" " $key_null_check$\n"
" java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n" " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
@ -643,8 +688,7 @@ void ImmutableMapFieldGenerator::GenerateMapGetters(
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(variables_,
"@java.lang.Override\n" "@java.lang.Override\n"
"$deprecation$\n" "$deprecation$public java.util.Map<$type_parameters$> "
"public java.util.Map<$type_parameters$> "
"${$get$capitalized_name$Map$}$() {\n" "${$get$capitalized_name$Map$}$() {\n"
" return internalGet$capitalized_name$().getMap();\n" " return internalGet$capitalized_name$().getMap();\n"
"}\n"); "}\n");
@ -653,10 +697,10 @@ void ImmutableMapFieldGenerator::GenerateMapGetters(
printer->Print( printer->Print(
variables_, variables_,
"@java.lang.Override\n" "@java.lang.Override\n"
"$deprecation$\n" "$deprecation$public $value_type_pass_through_nullness$ "
"public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n" "${$get$capitalized_name$OrDefault$}$(\n"
" $key_type$ key,\n" " $key_type$ key,\n"
" $value_type$ defaultValue) {\n" " $value_type_pass_through_nullness$ defaultValue) {\n"
" $key_null_check$\n" " $key_null_check$\n"
" java.util.Map<$type_parameters$> map =\n" " java.util.Map<$type_parameters$> map =\n"
" internalGet$capitalized_name$().getMap();\n" " internalGet$capitalized_name$().getMap();\n"
@ -664,19 +708,19 @@ void ImmutableMapFieldGenerator::GenerateMapGetters(
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(
"@java.lang.Override\n" variables_,
"$deprecation$\n" "@java.lang.Override\n"
"public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n" "$deprecation$public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
" $key_type$ key) {\n" " $key_type$ key) {\n"
" $key_null_check$\n" " $key_null_check$\n"
" java.util.Map<$type_parameters$> map =\n" " java.util.Map<$type_parameters$> map =\n"
" internalGet$capitalized_name$().getMap();\n" " internalGet$capitalized_name$().getMap();\n"
" if (!map.containsKey(key)) {\n" " if (!map.containsKey(key)) {\n"
" throw new java.lang.IllegalArgumentException();\n" " throw new java.lang.IllegalArgumentException();\n"
" }\n" " }\n"
" return map.get(key);\n" " return map.get(key);\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
} }
} }
@ -775,6 +819,7 @@ void ImmutableMapFieldGenerator::GenerateInitializationCode(
void ImmutableMapFieldGenerator::GenerateBuilderClearCode( void ImmutableMapFieldGenerator::GenerateBuilderClearCode(
io::Printer* printer) const { io::Printer* printer) const {
// No need to clear the has-bit since we clear the bitField ints all at once.
printer->Print(variables_, printer->Print(variables_,
"internalGetMutable$capitalized_name$().clear();\n"); "internalGetMutable$capitalized_name$().clear();\n");
} }
@ -783,14 +828,17 @@ void ImmutableMapFieldGenerator::GenerateMergingCode(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"internalGetMutable$capitalized_name$().mergeFrom(\n" "internalGetMutable$capitalized_name$().mergeFrom(\n"
" other.internalGet$capitalized_name$());\n"); " other.internalGet$capitalized_name$());\n"
"$set_has_field_bit_builder$\n");
} }
void ImmutableMapFieldGenerator::GenerateBuildingCode( void ImmutableMapFieldGenerator::GenerateBuildingCode(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"result.$name$_ = internalGet$capitalized_name$();\n" "if ($get_has_field_bit_from_local$) {\n"
"result.$name$_.makeImmutable();\n"); " result.$name$_ = internalGet$capitalized_name$();\n"
" result.$name$_.makeImmutable();\n"
"}\n");
} }
void ImmutableMapFieldGenerator::GenerateBuilderParsingCode( void ImmutableMapFieldGenerator::GenerateBuilderParsingCode(
@ -807,6 +855,7 @@ void ImmutableMapFieldGenerator::GenerateBuilderParsingCode(
"} else {\n" "} else {\n"
" internalGetMutable$capitalized_name$().getMutableMap().put(\n" " internalGetMutable$capitalized_name$().getMutableMap().put(\n"
" $name$__.getKey(), $name$__.getValue());\n" " $name$__.getKey(), $name$__.getValue());\n"
" $set_has_field_bit_builder$\n"
"}\n"); "}\n");
} else { } else {
printer->Print( printer->Print(
@ -815,10 +864,10 @@ void ImmutableMapFieldGenerator::GenerateBuilderParsingCode(
"$name$__ = input.readMessage(\n" "$name$__ = input.readMessage(\n"
" $default_entry$.getParserForType(), extensionRegistry);\n" " $default_entry$.getParserForType(), extensionRegistry);\n"
"internalGetMutable$capitalized_name$().getMutableMap().put(\n" "internalGetMutable$capitalized_name$().getMutableMap().put(\n"
" $name$__.getKey(), $name$__.getValue());\n"); " $name$__.getKey(), $name$__.getValue());\n"
"$set_has_field_bit_builder$\n");
} }
} }
void ImmutableMapFieldGenerator::GenerateSerializationCode( void ImmutableMapFieldGenerator::GenerateSerializationCode(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
@ -871,4 +920,4 @@ std::string ImmutableMapFieldGenerator::GetBoxedType() const {
} // namespace protobuf } // namespace protobuf
} // namespace google } // namespace google
#include <google/protobuf/port_undef.inc> #include "google/protobuf/port_undef.inc"

@ -31,7 +31,7 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
#include <google/protobuf/compiler/java/field.h> #include "google/protobuf/compiler/java/field.h"
namespace google { namespace google {
namespace protobuf { namespace protobuf {
@ -46,6 +46,8 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator {
~ImmutableMapFieldGenerator() override; ~ImmutableMapFieldGenerator() override;
// implements ImmutableFieldGenerator --------------------------------------- // implements ImmutableFieldGenerator ---------------------------------------
int GetMessageBitIndex() const override;
int GetBuilderBitIndex() const override;
int GetNumBitsForMessage() const override; int GetNumBitsForMessage() const override;
int GetNumBitsForBuilder() const override; int GetNumBitsForBuilder() const override;
void GenerateInterfaceMembers(io::Printer* printer) const override; void GenerateInterfaceMembers(io::Printer* printer) const override;
@ -68,8 +70,11 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator {
private: private:
const FieldDescriptor* descriptor_; const FieldDescriptor* descriptor_;
int message_bit_index_;
int builder_bit_index_;
std::map<std::string, std::string> variables_; std::map<std::string, std::string> variables_;
ClassNameResolver* name_resolver_; ClassNameResolver* name_resolver_;
Context* context_;
void GenerateMapGetters(io::Printer* printer) const; void GenerateMapGetters(io::Printer* printer) const;
}; };

@ -32,29 +32,30 @@
// Based on original Protocol Buffers design by // Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others. // Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/java/message_builder.h> #include "google/protobuf/compiler/java/message_builder.h"
#include <algorithm> #include <algorithm>
#include <map> #include <map>
#include <memory> #include <memory>
#include <set>
#include <vector> #include <vector>
#include <google/protobuf/io/coded_stream.h> #include "google/protobuf/io/coded_stream.h"
#include <google/protobuf/io/printer.h> #include "google/protobuf/io/printer.h"
#include <google/protobuf/wire_format.h> #include "google/protobuf/wire_format.h"
#include <google/protobuf/stubs/strutil.h> #include "google/protobuf/stubs/strutil.h"
#include <google/protobuf/stubs/substitute.h> #include "google/protobuf/stubs/substitute.h"
#include <google/protobuf/compiler/java/context.h> #include "google/protobuf/compiler/java/context.h"
#include <google/protobuf/compiler/java/doc_comment.h> #include "google/protobuf/compiler/java/doc_comment.h"
#include <google/protobuf/compiler/java/enum.h> #include "google/protobuf/compiler/java/enum.h"
#include <google/protobuf/compiler/java/extension.h> #include "google/protobuf/compiler/java/extension.h"
#include <google/protobuf/compiler/java/generator_factory.h> #include "google/protobuf/compiler/java/generator_factory.h"
#include <google/protobuf/compiler/java/helpers.h> #include "google/protobuf/compiler/java/helpers.h"
#include <google/protobuf/compiler/java/name_resolver.h> #include "google/protobuf/compiler/java/name_resolver.h"
#include <google/protobuf/descriptor.pb.h> #include "google/protobuf/descriptor.pb.h"
// Must be last. // Must be last.
#include <google/protobuf/port_def.inc> #include "google/protobuf/port_def.inc"
namespace google { namespace google {
namespace protobuf { namespace protobuf {
@ -145,12 +146,11 @@ void MessageBuilderGenerator::Generate(io::Printer* printer) {
"\n" "\n"
"public Builder clear$oneof_capitalized_name$() {\n" "public Builder clear$oneof_capitalized_name$() {\n"
" $oneof_name$Case_ = 0;\n" " $oneof_name$Case_ = 0;\n"
" $oneof_name$_ = null;\n"); " $oneof_name$_ = null;\n"
printer->Print(" onChanged();\n"); " onChanged();\n"
printer->Print( " return this;\n"
" return this;\n" "}\n"
"}\n" "\n");
"\n");
} }
// Integers for bit fields. // Integers for bit fields.
@ -355,6 +355,11 @@ void MessageBuilderGenerator::GenerateCommonBuilderMethods(
" super.clear();\n"); " super.clear();\n");
printer->Indent(); printer->Indent();
int totalBuilderInts = (descriptor_->field_count() + 31) / 32;
for (int i = 0; i < totalBuilderInts; i++) {
printer->Print("$bit_field_name$ = 0;\n", "bit_field_name",
GetBitFieldName(i));
}
for (int i = 0; i < descriptor_->field_count(); i++) { for (int i = 0; i < descriptor_->field_count(); i++) {
field_generators_.get(descriptor_->field(i)) field_generators_.get(descriptor_->field(i))
@ -406,63 +411,7 @@ void MessageBuilderGenerator::GenerateCommonBuilderMethods(
"\n", "\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_)); "classname", name_resolver_->GetImmutableClassName(descriptor_));
printer->Print( GenerateBuildPartial(printer);
"@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 // Override methods declared in GeneratedMessage to return the concrete
// generated type so callsites won't depend on GeneratedMessage. This // generated type so callsites won't depend on GeneratedMessage. This
@ -610,6 +559,156 @@ void MessageBuilderGenerator::GenerateCommonBuilderMethods(
} }
} }
void MessageBuilderGenerator::GenerateBuildPartial(io::Printer* printer) {
printer->Print(
"@java.lang.Override\n"
"public $classname$ buildPartial() {\n"
" $classname$ result = new $classname$(this);\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
printer->Indent();
// Handle the repeated fields first so that the "mutable bits" are cleared.
bool has_repeated_fields = false;
for (int i = 0; i < descriptor_->field_count(); ++i) {
if (descriptor_->field(i)->is_repeated() &&
!IsMapField(descriptor_->field(i))) {
has_repeated_fields = true;
printer->Print("buildPartialRepeatedFields(result);\n");
break;
}
}
// One buildPartial#() per from_bit_field
int totalBuilderInts = (descriptor_->field_count() + 31) / 32;
if (totalBuilderInts > 0) {
for (int i = 0; i < totalBuilderInts; ++i) {
printer->Print(
"if ($bit_field_name$ != 0) { buildPartial$piece$(result); }\n",
"bit_field_name", GetBitFieldName(i), "piece", StrCat(i));
}
}
if (!oneofs_.empty()) {
printer->Print("buildPartialOneofs(result);\n");
}
printer->Outdent();
printer->Print(
" onBuilt();\n"
" return result;\n"
"}\n"
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
// Build Repeated Fields
if (has_repeated_fields) {
printer->Print(
"private void buildPartialRepeatedFields($classname$ result) {\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); ++i) {
if (descriptor_->field(i)->is_repeated() &&
!IsMapField(descriptor_->field(i))) {
const ImmutableFieldGenerator& field =
field_generators_.get(descriptor_->field(i));
field.GenerateBuildingCode(printer);
}
}
printer->Outdent();
printer->Print("}\n\n");
}
// Build non-oneof fields
int start_field = 0;
for (int i = 0; i < totalBuilderInts; i++) {
start_field = GenerateBuildPartialPiece(printer, i, start_field);
}
// Build Oneofs
if (!oneofs_.empty()) {
printer->Print("private void buildPartialOneofs($classname$ result) {\n",
"classname",
name_resolver_->GetImmutableClassName(descriptor_));
printer->Indent();
for (auto oneof : oneofs_) {
printer->Print(
"result.$oneof_name$Case_ = $oneof_name$Case_;\n"
"result.$oneof_name$_ = this.$oneof_name$_;\n",
"oneof_name", context_->GetOneofGeneratorInfo(oneof)->name);
for (int i = 0; i < oneof->field_count(); ++i) {
if (oneof->field(i)->message_type() != nullptr) {
const ImmutableFieldGenerator& field =
field_generators_.get(oneof->field(i));
field.GenerateBuildingCode(printer);
}
}
}
printer->Outdent();
printer->Print("}\n\n");
}
}
int MessageBuilderGenerator::GenerateBuildPartialPiece(io::Printer* printer,
int piece,
int first_field) {
printer->Print(
"private void buildPartial$piece$($classname$ result) {\n"
" int from_$bit_field_name$ = $bit_field_name$;\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_), "piece",
StrCat(piece), "bit_field_name", GetBitFieldName(piece));
printer->Indent();
std::set<int> declared_to_bitfields;
int bit = 0;
int next = first_field;
for (; bit < 32 && next < descriptor_->field_count(); ++next) {
const ImmutableFieldGenerator& field =
field_generators_.get(descriptor_->field(next));
bit += field.GetNumBitsForBuilder();
// Skip oneof fields that are handled separately
if (IsRealOneof(descriptor_->field(next))) {
continue;
}
// Skip repeated fields because they are currently handled
// in separate buildPartial sub-methods.
if (descriptor_->field(next)->is_repeated() &&
!IsMapField(descriptor_->field(next))) {
continue;
}
// Skip fields without presence bits in the builder
if (field.GetNumBitsForBuilder() == 0) {
continue;
}
// Track message bits if necessary
if (field.GetNumBitsForMessage() > 0) {
int to_bitfield = field.GetMessageBitIndex() / 32;
if (declared_to_bitfields.count(to_bitfield) == 0) {
printer->Print("int to_$bit_field_name$ = 0;\n", "bit_field_name",
GetBitFieldName(to_bitfield));
declared_to_bitfields.insert(to_bitfield);
}
}
// Copy the field from the builder to the message
field.GenerateBuildingCode(printer);
}
// Copy the bit field results to the generated message
for (int to_bitfield : declared_to_bitfields) {
printer->Print("result.$bit_field_name$ |= to_$bit_field_name$;\n",
"bit_field_name", GetBitFieldName(to_bitfield));
}
printer->Outdent();
printer->Print("}\n\n");
return next;
}
// =================================================================== // ===================================================================
void MessageBuilderGenerator::GenerateBuilderParsingMethods( void MessageBuilderGenerator::GenerateBuilderParsingMethods(
@ -807,4 +906,4 @@ void MessageBuilderGenerator::GenerateIsInitialized(io::Printer* printer) {
} // namespace protobuf } // namespace protobuf
} // namespace google } // namespace google
#include <google/protobuf/port_undef.inc> #include "google/protobuf/port_undef.inc"

@ -69,6 +69,11 @@ class MessageBuilderGenerator {
private: private:
void GenerateCommonBuilderMethods(io::Printer* printer); void GenerateCommonBuilderMethods(io::Printer* printer);
void GenerateBuildPartial(io::Printer* printer);
int GenerateBuildPartialPiece(io::Printer* printer, int piece,
int first_field);
int GenerateBuildPartialPieceWithoutPresence(io::Printer* printer, int piece,
int first_field);
void GenerateDescriptorMethods(io::Printer* printer); void GenerateDescriptorMethods(io::Printer* printer);
void GenerateBuilderParsingMethods(io::Printer* printer); void GenerateBuilderParsingMethods(io::Printer* printer);
void GenerateBuilderFieldParsingCases(io::Printer* printer); void GenerateBuilderFieldParsingCases(io::Printer* printer);

@ -32,21 +32,21 @@
// Based on original Protocol Buffers design by // Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others. // Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/java/message_field.h> #include "google/protobuf/compiler/java/message_field.h"
#include <map> #include <map>
#include <string> #include <string>
#include <google/protobuf/io/printer.h> #include "google/protobuf/io/printer.h"
#include <google/protobuf/wire_format.h> #include "google/protobuf/wire_format.h"
#include <google/protobuf/stubs/strutil.h> #include "google/protobuf/stubs/strutil.h"
#include <google/protobuf/compiler/java/context.h> #include "google/protobuf/compiler/java/context.h"
#include <google/protobuf/compiler/java/doc_comment.h> #include "google/protobuf/compiler/java/doc_comment.h"
#include <google/protobuf/compiler/java/helpers.h> #include "google/protobuf/compiler/java/helpers.h"
#include <google/protobuf/compiler/java/name_resolver.h> #include "google/protobuf/compiler/java/name_resolver.h"
// Must be last. // Must be last.
#include <google/protobuf/port_def.inc> #include "google/protobuf/port_def.inc"
namespace google { namespace google {
namespace protobuf { namespace protobuf {
@ -56,10 +56,11 @@ namespace java {
namespace { namespace {
void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, void SetMessageVariables(
int builderBitIndex, const FieldGeneratorInfo* info, const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
ClassNameResolver* name_resolver, const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
std::map<std::string, std::string>* variables) { std::map<std::string, std::string>* variables,
Context* context) {
SetCommonFieldVariables(descriptor, info, variables); SetCommonFieldVariables(descriptor, info, variables);
(*variables)["type"] = (*variables)["type"] =
@ -74,11 +75,12 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
// by the proto compiler // by the proto compiler
(*variables)["deprecation"] = (*variables)["deprecation"] =
descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] = variables->insert(
descriptor->options().deprecated() {"kt_deprecation",
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + descriptor->options().deprecated()
" is deprecated\") " ? StrCat("@kotlin.Deprecated(message = \"Field ",
: ""; (*variables)["name"], " is deprecated\") ")
: ""});
(*variables)["on_changed"] = "onChanged();"; (*variables)["on_changed"] = "onChanged();";
(*variables)["ver"] = GeneratedCodeVersionSuffix(); (*variables)["ver"] = GeneratedCodeVersionSuffix();
(*variables)["get_parser"] = (*variables)["get_parser"] =
@ -88,24 +90,16 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
if (HasHasbit(descriptor)) { if (HasHasbit(descriptor)) {
// For singular messages and builders, one bit is used for the hasField bit. // For singular messages and builders, one bit is used for the hasField bit.
(*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
// Note that these have a trailing ";". // Note that these have a trailing ";".
(*variables)["set_has_field_bit_message"] = (*variables)["set_has_field_bit_to_local"] =
GenerateSetBit(messageBitIndex) + ";"; GenerateSetBitToLocal(messageBitIndex);
(*variables)["set_has_field_bit_builder"] =
GenerateSetBit(builderBitIndex) + ";";
(*variables)["clear_has_field_bit_builder"] =
GenerateClearBit(builderBitIndex) + ";";
(*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
} else { } else {
(*variables)["set_has_field_bit_message"] = ""; (*variables)["set_has_field_bit_to_local"] = "";
(*variables)["set_has_field_bit_builder"] = ""; variables->insert({"is_field_present_message",
(*variables)["clear_has_field_bit_builder"] = ""; StrCat((*variables)["name"], "_ != null")});
(*variables)["is_field_present_message"] =
(*variables)["name"] + "_ != null";
} }
// For repeated builders, one bit is used for whether the array is immutable. // For repeated builders, one bit is used for whether the array is immutable.
@ -113,10 +107,13 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
(*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
(*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
(*variables)["set_has_field_bit_builder"] =
GenerateSetBit(builderBitIndex) + ";";
(*variables)["clear_has_field_bit_builder"] =
GenerateClearBit(builderBitIndex) + ";";
(*variables)["get_has_field_bit_from_local"] = (*variables)["get_has_field_bit_from_local"] =
GenerateGetBitFromLocal(builderBitIndex); GenerateGetBitFromLocal(builderBitIndex);
(*variables)["set_has_field_bit_to_local"] =
GenerateSetBitToLocal(messageBitIndex);
} }
} // namespace } // namespace
@ -126,21 +123,31 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
ImmutableMessageFieldGenerator::ImmutableMessageFieldGenerator( ImmutableMessageFieldGenerator::ImmutableMessageFieldGenerator(
const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
Context* context) Context* context)
: descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { : descriptor_(descriptor),
message_bit_index_(messageBitIndex),
builder_bit_index_(builderBitIndex),
name_resolver_(context->GetNameResolver()),
context_(context) {
SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
context->GetFieldGeneratorInfo(descriptor), context->GetFieldGeneratorInfo(descriptor),
name_resolver_, &variables_); name_resolver_, &variables_, context);
} }
ImmutableMessageFieldGenerator::~ImmutableMessageFieldGenerator() {} ImmutableMessageFieldGenerator::~ImmutableMessageFieldGenerator() {}
int ImmutableMessageFieldGenerator::GetMessageBitIndex() const {
return message_bit_index_;
}
int ImmutableMessageFieldGenerator::GetBuilderBitIndex() const {
return builder_bit_index_;
}
int ImmutableMessageFieldGenerator::GetNumBitsForMessage() const { int ImmutableMessageFieldGenerator::GetNumBitsForMessage() const {
return HasHasbit(descriptor_) ? 1 : 0; return HasHasbit(descriptor_) ? 1 : 0;
} }
int ImmutableMessageFieldGenerator::GetNumBitsForBuilder() const { int ImmutableMessageFieldGenerator::GetNumBitsForBuilder() const { return 1; }
return GetNumBitsForMessage();
}
void ImmutableMessageFieldGenerator::GenerateInterfaceMembers( void ImmutableMessageFieldGenerator::GenerateInterfaceMembers(
io::Printer* printer) const { io::Printer* printer) const {
@ -173,24 +180,6 @@ void ImmutableMessageFieldGenerator::GenerateMembers(
" return $get_has_field_bit_message$;\n" " return $get_has_field_bit_message$;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
printer->Print(
variables_,
"@java.lang.Override\n"
"$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
" return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
"}\n");
printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"@java.lang.Override\n"
"$deprecation$public $type$OrBuilder "
"${$get$capitalized_name$OrBuilder$}$() {\n"
" return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
"}\n");
printer->Annotate("{", "}", descriptor_);
} else { } else {
WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
printer->Print( printer->Print(
@ -200,24 +189,25 @@ void ImmutableMessageFieldGenerator::GenerateMembers(
" return $name$_ != null;\n" " return $name$_ != null;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
printer->Print(
variables_,
"@java.lang.Override\n"
"$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
" return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
"}\n");
printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"@java.lang.Override\n"
"$deprecation$public $type$OrBuilder "
"${$get$capitalized_name$OrBuilder$}$() {\n"
" return get$capitalized_name$();\n"
"}\n");
printer->Annotate("{", "}", descriptor_);
} }
WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
printer->Print(
variables_,
"@java.lang.Override\n"
"$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
" return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
"}\n");
printer->Annotate("{", "}", descriptor_);
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"@java.lang.Override\n"
"$deprecation$public $type$OrBuilder "
"${$get$capitalized_name$OrBuilder$}$() {\n"
" return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
"}\n");
printer->Annotate("{", "}", descriptor_);
} }
void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition( void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
@ -255,9 +245,6 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers(
// When using nested-builders, the code initially works just like the // When using nested-builders, the code initially works just like the
// non-nested builder case. It only creates a nested builder lazily on // non-nested builder case. It only creates a nested builder lazily on
// demand and then forever delegates to it after creation. // demand and then forever delegates to it after creation.
bool has_hasbit = HasHasbit(descriptor_);
printer->Print(variables_, "private $type$ $name$_;\n"); printer->Print(variables_, "private $type$ $name$_;\n");
printer->Print(variables_, printer->Print(variables_,
@ -272,21 +259,11 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers(
// boolean hasField() // boolean hasField()
WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
if (has_hasbit) { printer->Print(variables_,
printer->Print( "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
variables_, " return $get_has_field_bit_builder$;\n"
"$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" "}\n");
" return $get_has_field_bit_builder$;\n" printer->Annotate("{", "}", descriptor_);
"}\n");
printer->Annotate("{", "}", descriptor_);
} else {
printer->Print(
variables_,
"$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
" return $name$Builder_ != null || $name$_ != null;\n"
"}\n");
printer->Annotate("{", "}", descriptor_);
}
// Field getField() // Field getField()
WriteFieldAccessorDocComment(printer, descriptor_, GETTER); WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
@ -304,12 +281,12 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers(
"if (value == null) {\n" "if (value == null) {\n"
" throw new NullPointerException();\n" " throw new NullPointerException();\n"
"}\n" "}\n"
"$name$_ = value;\n" "$name$_ = value;\n",
"$on_changed$\n",
"$name$Builder_.setMessage(value);\n", "$name$Builder_.setMessage(value);\n",
"$set_has_field_bit_builder$\n" "$set_has_field_bit_builder$\n"
"$on_changed$\n"
"return this;\n"); "return this;\n");
// Field.Builder setField(Field.Builder builderForValue) // Field.Builder setField(Field.Builder builderForValue)
@ -319,58 +296,48 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers(
"$deprecation$public Builder ${$set$capitalized_name$$}$(\n" "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
" $type$.Builder builderForValue)", " $type$.Builder builderForValue)",
"$name$_ = builderForValue.build();\n" "$name$_ = builderForValue.build();\n",
"$on_changed$\n",
"$name$Builder_.setMessage(builderForValue.build());\n", "$name$Builder_.setMessage(builderForValue.build());\n",
"$set_has_field_bit_builder$\n" "$set_has_field_bit_builder$\n"
"$on_changed$\n"
"return this;\n"); "return this;\n");
// Field.Builder mergeField(Field value) // Message.Builder mergeField(Field value)
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction( PrintNestedBuilderFunction(
printer, printer,
"$deprecation$public Builder ${$merge$capitalized_name$$}$($type$ value)", "$deprecation$public Builder ${$merge$capitalized_name$$}$($type$ value)",
"if ($get_has_field_bit_builder$ &&\n"
has_hasbit " $name$_ != null &&\n"
? "if ($get_has_field_bit_builder$ &&\n" " $name$_ != $type$.getDefaultInstance()) {\n"
" $name$_ != null &&\n" " get$capitalized_name$Builder().mergeFrom(value);\n"
" $name$_ != $type$.getDefaultInstance()) {\n" "} else {\n"
" $name$_ =\n" " $name$_ = value;\n"
" $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" "}\n",
"} else {\n"
" $name$_ = value;\n"
"}\n"
"$on_changed$\n"
: "if ($name$_ != null) {\n"
" $name$_ =\n"
" $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
"} else {\n"
" $name$_ = value;\n"
"}\n"
"$on_changed$\n",
"$name$Builder_.mergeFrom(value);\n", "$name$Builder_.mergeFrom(value);\n",
"$set_has_field_bit_builder$\n" "$set_has_field_bit_builder$\n"
"$on_changed$\n"
"return this;\n"); "return this;\n");
// Field.Builder clearField() // Message.Builder clearField()
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction( printer->Print(variables_,
printer, "$deprecation$public Builder ${$clear$capitalized_name$$}$()", "$deprecation$public Builder clear$capitalized_name$() {\n"
" $clear_has_field_bit_builder$\n"
"$name$_ = null;\n" " $name$_ = null;\n"
"$on_changed$\n", " if ($name$Builder_ != null) {\n"
" $name$Builder_.dispose();\n"
has_hasbit ? "$name$Builder_.clear();\n" " $name$Builder_ = null;\n"
: "$name$_ = null;\n" " }\n"
"$name$Builder_ = null;\n", " $on_changed$\n"
" return this;\n"
"$clear_has_field_bit_builder$\n" "}\n");
"return this;\n");
// Field.Builder getFieldBuilder()
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(variables_,
"$deprecation$public $type$.Builder " "$deprecation$public $type$.Builder "
@ -380,6 +347,8 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers(
" return get$capitalized_name$FieldBuilder().getBuilder();\n" " return get$capitalized_name$FieldBuilder().getBuilder();\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
// FieldOrBuilder getFieldOrBuilder()
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(variables_,
"$deprecation$public $type$OrBuilder " "$deprecation$public $type$OrBuilder "
@ -392,6 +361,8 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers(
" }\n" " }\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
// SingleFieldBuilder getFieldFieldBuilder
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(
variables_, variables_,
@ -449,9 +420,7 @@ void ImmutableMessageFieldGenerator::GenerateKotlinOrNull(io::Printer* printer)
void ImmutableMessageFieldGenerator::GenerateFieldBuilderInitializationCode( void ImmutableMessageFieldGenerator::GenerateFieldBuilderInitializationCode(
io::Printer* printer) const { io::Printer* printer) const {
if (HasHasbit(descriptor_)) { printer->Print(variables_, "get$capitalized_name$FieldBuilder();\n");
printer->Print(variables_, "get$capitalized_name$FieldBuilder();\n");
}
} }
void ImmutableMessageFieldGenerator::GenerateInitializationCode( void ImmutableMessageFieldGenerator::GenerateInitializationCode(
@ -459,17 +428,13 @@ void ImmutableMessageFieldGenerator::GenerateInitializationCode(
void ImmutableMessageFieldGenerator::GenerateBuilderClearCode( void ImmutableMessageFieldGenerator::GenerateBuilderClearCode(
io::Printer* printer) const { io::Printer* printer) const {
if (HasHasbit(descriptor_)) { // No need to clear the has-bit since we clear the bitField ints all at once.
PrintNestedBuilderCondition(printer, "$name$_ = null;\n", printer->Print(variables_,
"$name$_ = null;\n"
"$name$Builder_.clear();\n"); "if ($name$Builder_ != null) {\n"
printer->Print(variables_, "$clear_has_field_bit_builder$\n"); " $name$Builder_.dispose();\n"
} else { " $name$Builder_ = null;\n"
PrintNestedBuilderCondition(printer, "$name$_ = null;\n", "}\n");
"$name$_ = null;\n"
"$name$Builder_ = null;\n");
}
} }
void ImmutableMessageFieldGenerator::GenerateMergingCode( void ImmutableMessageFieldGenerator::GenerateMergingCode(
@ -482,19 +447,15 @@ void ImmutableMessageFieldGenerator::GenerateMergingCode(
void ImmutableMessageFieldGenerator::GenerateBuildingCode( void ImmutableMessageFieldGenerator::GenerateBuildingCode(
io::Printer* printer) const { io::Printer* printer) const {
if (HasHasbit(descriptor_)) { printer->Print(variables_,
printer->Print(variables_, "if ($get_has_field_bit_from_local$) {\n"); "if ($get_has_field_bit_from_local$) {\n"
printer->Indent(); " result.$name$_ = $name$Builder_ == null\n"
PrintNestedBuilderCondition(printer, "result.$name$_ = $name$_;\n", " ? $name$_\n"
"result.$name$_ = $name$Builder_.build();\n"); " : $name$Builder_.build();\n");
printer->Outdent(); if (GetNumBitsForMessage() > 0) {
printer->Print(variables_, printer->Print(variables_, " $set_has_field_bit_to_local$;\n");
" $set_has_field_bit_to_local$;\n"
"}\n");
} else {
PrintNestedBuilderCondition(printer, "result.$name$_ = $name$_;\n",
"result.$name$_ = $name$Builder_.build();\n");
} }
printer->Print("}\n");
} }
void ImmutableMessageFieldGenerator::GenerateBuilderParsingCode( void ImmutableMessageFieldGenerator::GenerateBuilderParsingCode(
@ -575,6 +536,7 @@ void ImmutableMessageOneofFieldGenerator::GenerateMembers(
" return $has_oneof_case_message$;\n" " return $has_oneof_case_message$;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
WriteFieldAccessorDocComment(printer, descriptor_, GETTER); WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
printer->Print(variables_, printer->Print(variables_,
"@java.lang.Override\n" "@java.lang.Override\n"
@ -758,7 +720,7 @@ void ImmutableMessageOneofFieldGenerator::GenerateBuilderMembers(
" $oneof_name$_ = null;\n" " $oneof_name$_ = null;\n"
" }\n" " }\n"
" $set_oneof_case_message$;\n" " $set_oneof_case_message$;\n"
" $on_changed$;\n" " $on_changed$\n"
" return $name$Builder_;\n" " return $name$Builder_;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
@ -775,16 +737,11 @@ void ImmutableMessageOneofFieldGenerator::GenerateBuilderClearCode(
void ImmutableMessageOneofFieldGenerator::GenerateBuildingCode( void ImmutableMessageOneofFieldGenerator::GenerateBuildingCode(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, "if ($has_oneof_case_message$) {\n"); printer->Print(variables_,
printer->Indent(); "if ($has_oneof_case_message$ &&\n"
" $name$Builder_ != null) {\n"
PrintNestedBuilderCondition( " result.$oneof_name$_ = $name$Builder_.build();\n"
printer, "result.$oneof_name$_ = $oneof_name$_;\n", "}\n");
"result.$oneof_name$_ = $name$Builder_.build();\n");
printer->Outdent();
printer->Print("}\n");
} }
void ImmutableMessageOneofFieldGenerator::GenerateMergingCode( void ImmutableMessageOneofFieldGenerator::GenerateMergingCode(
@ -834,11 +791,8 @@ void ImmutableMessageOneofFieldGenerator::GenerateSerializedSizeCode(
RepeatedImmutableMessageFieldGenerator::RepeatedImmutableMessageFieldGenerator( RepeatedImmutableMessageFieldGenerator::RepeatedImmutableMessageFieldGenerator(
const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
Context* context) Context* context)
: descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { : ImmutableMessageFieldGenerator(descriptor, messageBitIndex,
SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, builderBitIndex, context) {}
context->GetFieldGeneratorInfo(descriptor),
name_resolver_, &variables_);
}
RepeatedImmutableMessageFieldGenerator:: RepeatedImmutableMessageFieldGenerator::
~RepeatedImmutableMessageFieldGenerator() {} ~RepeatedImmutableMessageFieldGenerator() {}
@ -881,7 +835,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateInterfaceMembers(
void RepeatedImmutableMessageFieldGenerator::GenerateMembers( void RepeatedImmutableMessageFieldGenerator::GenerateMembers(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, "private java.util.List<$type$> $name$_;\n"); printer->Print(variables_, "@SuppressWarnings(\"serial\")\n"
"private java.util.List<$type$> $name$_;\n");
PrintExtraFieldInfo(variables_, printer); PrintExtraFieldInfo(variables_, printer);
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(variables_,
@ -891,6 +846,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateMembers(
" return $name$_;\n" // note: unmodifiable list " return $name$_;\n" // note: unmodifiable list
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
// List<FieldOrBuilder> getFieldOrBuilderList()
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(
variables_, variables_,
@ -900,6 +857,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateMembers(
" return $name$_;\n" " return $name$_;\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
// int getFieldCount()
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(
variables_, variables_,
@ -908,6 +867,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateMembers(
" return $name$_.size();\n" " return $name$_.size();\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
// Field getField(int index)
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(
variables_, variables_,
@ -916,6 +877,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateMembers(
" return $name$_.get(index);\n" " return $name$_.get(index);\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
// FieldOrBuilder getFieldOrBuilder(int index)
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(variables_,
"@java.lang.Override\n" "@java.lang.Override\n"
@ -1141,7 +1104,7 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers(
"return this;\n"); "return this;\n");
// Builder clearAllRepeatedField() // Builder clearRepeatedField()
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction( PrintNestedBuilderFunction(
printer, "$deprecation$public Builder ${$clear$capitalized_name$$}$()", printer, "$deprecation$public Builder ${$clear$capitalized_name$$}$()",
@ -1168,6 +1131,7 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers(
"return this;\n"); "return this;\n");
// Field.Builder getRepeatedFieldBuilder(int index)
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(
variables_, variables_,
@ -1177,6 +1141,7 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers(
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
// FieldOrBuilder getRepeatedFieldOrBuilder(int index)
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(variables_,
"$deprecation$public $type$OrBuilder " "$deprecation$public $type$OrBuilder "
@ -1190,6 +1155,7 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers(
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
// List<FieldOrBuilder> getRepeatedFieldOrBuilderList()
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(
variables_, variables_,
@ -1203,6 +1169,7 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers(
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
// Field.Builder addRepeatedField()
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_, printer->Print(variables_,
"$deprecation$public $type$.Builder " "$deprecation$public $type$.Builder "
@ -1211,6 +1178,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers(
" $type$.getDefaultInstance());\n" " $type$.getDefaultInstance());\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
// Field.Builder addRepeatedFieldBuilder(int index)
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(
variables_, variables_,
@ -1220,6 +1189,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers(
" index, $type$.getDefaultInstance());\n" " index, $type$.getDefaultInstance());\n"
"}\n"); "}\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
// List<Field.Builder> getRepeatedFieldBuilderList()
WriteFieldDocComment(printer, descriptor_); WriteFieldDocComment(printer, descriptor_);
printer->Print( printer->Print(
variables_, variables_,
@ -1478,4 +1449,4 @@ void RepeatedImmutableMessageFieldGenerator::GenerateKotlinDslMembers(
} // namespace protobuf } // namespace protobuf
} // namespace google } // namespace google
#include <google/protobuf/port_undef.inc> #include "google/protobuf/port_undef.inc"

@ -38,7 +38,7 @@
#include <map> #include <map>
#include <string> #include <string>
#include <google/protobuf/compiler/java/field.h> #include "google/protobuf/compiler/java/field.h"
namespace google { namespace google {
namespace protobuf { namespace protobuf {
@ -62,10 +62,16 @@ class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator {
int messageBitIndex, int messageBitIndex,
int builderBitIndex, int builderBitIndex,
Context* context); Context* context);
ImmutableMessageFieldGenerator(const ImmutableMessageFieldGenerator&) =
delete;
ImmutableMessageFieldGenerator& operator=(
const ImmutableMessageFieldGenerator&) = delete;
~ImmutableMessageFieldGenerator() override; ~ImmutableMessageFieldGenerator() override;
// implements ImmutableFieldGenerator // implements ImmutableFieldGenerator
// --------------------------------------- // ---------------------------------------
int GetMessageBitIndex() const override;
int GetBuilderBitIndex() const override;
int GetNumBitsForMessage() const override; int GetNumBitsForMessage() const override;
int GetNumBitsForBuilder() const override; int GetNumBitsForBuilder() const override;
void GenerateInterfaceMembers(io::Printer* printer) const override; void GenerateInterfaceMembers(io::Printer* printer) const override;
@ -88,20 +94,22 @@ class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator {
protected: protected:
const FieldDescriptor* descriptor_; const FieldDescriptor* descriptor_;
int message_bit_index_;
int builder_bit_index_;
std::map<std::string, std::string> variables_; std::map<std::string, std::string> variables_;
ClassNameResolver* name_resolver_; ClassNameResolver* name_resolver_;
Context* context_;
void PrintNestedBuilderCondition(io::Printer* printer, virtual void PrintNestedBuilderCondition(
const char* regular_case, io::Printer* printer, const char* regular_case,
const char* nested_builder_case) const; const char* nested_builder_case) const;
void PrintNestedBuilderFunction(io::Printer* printer, virtual void PrintNestedBuilderFunction(io::Printer* printer,
const char* method_prototype, const char* method_prototype,
const char* regular_case, const char* regular_case,
const char* nested_builder_case, const char* nested_builder_case,
const char* trailing_code) const; const char* trailing_code) const;
private: private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldGenerator);
void GenerateKotlinOrNull(io::Printer* printer) const; void GenerateKotlinOrNull(io::Printer* printer) const;
}; };
@ -111,6 +119,10 @@ class ImmutableMessageOneofFieldGenerator
ImmutableMessageOneofFieldGenerator(const FieldDescriptor* descriptor, ImmutableMessageOneofFieldGenerator(const FieldDescriptor* descriptor,
int messageBitIndex, int builderBitIndex, int messageBitIndex, int builderBitIndex,
Context* context); Context* context);
ImmutableMessageOneofFieldGenerator(
const ImmutableMessageOneofFieldGenerator&) = delete;
ImmutableMessageOneofFieldGenerator& operator=(
const ImmutableMessageOneofFieldGenerator&) = delete;
~ImmutableMessageOneofFieldGenerator() override; ~ImmutableMessageOneofFieldGenerator() override;
void GenerateMembers(io::Printer* printer) const override; void GenerateMembers(io::Printer* printer) const override;
@ -121,16 +133,18 @@ class ImmutableMessageOneofFieldGenerator
void GenerateBuilderParsingCode(io::Printer* printer) const override; void GenerateBuilderParsingCode(io::Printer* printer) const override;
void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override;
void GenerateSerializedSizeCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldGenerator);
}; };
class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator { class RepeatedImmutableMessageFieldGenerator
: public ImmutableMessageFieldGenerator {
public: public:
explicit RepeatedImmutableMessageFieldGenerator( explicit RepeatedImmutableMessageFieldGenerator(
const FieldDescriptor* descriptor, int messageBitIndex, const FieldDescriptor* descriptor, int messageBitIndex,
int builderBitIndex, Context* context); int builderBitIndex, Context* context);
RepeatedImmutableMessageFieldGenerator(
const RepeatedImmutableMessageFieldGenerator&) = delete;
RepeatedImmutableMessageFieldGenerator& operator=(
const RepeatedImmutableMessageFieldGenerator&) = delete;
~RepeatedImmutableMessageFieldGenerator() override; ~RepeatedImmutableMessageFieldGenerator() override;
// implements ImmutableFieldGenerator --------------------------------------- // implements ImmutableFieldGenerator ---------------------------------------
@ -155,21 +169,14 @@ class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator {
std::string GetBoxedType() const override; std::string GetBoxedType() const override;
protected: protected:
const FieldDescriptor* descriptor_; void PrintNestedBuilderCondition(
std::map<std::string, std::string> variables_; io::Printer* printer, const char* regular_case,
ClassNameResolver* name_resolver_; const char* nested_builder_case) const override;
void PrintNestedBuilderCondition(io::Printer* printer,
const char* regular_case,
const char* nested_builder_case) const;
void PrintNestedBuilderFunction(io::Printer* printer, void PrintNestedBuilderFunction(io::Printer* printer,
const char* method_prototype, const char* method_prototype,
const char* regular_case, const char* regular_case,
const char* nested_builder_case, const char* nested_builder_case,
const char* trailing_code) const; const char* trailing_code) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldGenerator);
}; };
} // namespace java } // namespace java

@ -32,21 +32,21 @@
// Based on original Protocol Buffers design by // Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others. // Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/java/primitive_field.h> #include "google/protobuf/compiler/java/primitive_field.h"
#include <cstdint> #include <cstdint>
#include <map> #include <map>
#include <string> #include <string>
#include <google/protobuf/stubs/logging.h> #include "google/protobuf/stubs/logging.h"
#include <google/protobuf/stubs/common.h> #include "google/protobuf/stubs/common.h"
#include <google/protobuf/io/printer.h> #include "google/protobuf/io/printer.h"
#include <google/protobuf/wire_format.h> #include "google/protobuf/wire_format.h"
#include <google/protobuf/stubs/strutil.h> #include "google/protobuf/stubs/strutil.h"
#include <google/protobuf/compiler/java/context.h> #include "google/protobuf/compiler/java/context.h"
#include <google/protobuf/compiler/java/doc_comment.h> #include "google/protobuf/compiler/java/doc_comment.h"
#include <google/protobuf/compiler/java/helpers.h> #include "google/protobuf/compiler/java/helpers.h"
#include <google/protobuf/compiler/java/name_resolver.h> #include "google/protobuf/compiler/java/name_resolver.h"
namespace google { namespace google {
namespace protobuf { namespace protobuf {
@ -57,53 +57,55 @@ using internal::WireFormat;
namespace { namespace {
void SetPrimitiveVariables(const FieldDescriptor* descriptor, void SetPrimitiveVariables(
int messageBitIndex, int builderBitIndex, const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
const FieldGeneratorInfo* info, const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
ClassNameResolver* name_resolver, std::map<std::string, std::string>* variables,
std::map<std::string, std::string>* variables) { Context* context) {
SetCommonFieldVariables(descriptor, info, variables); SetCommonFieldVariables(descriptor, info, variables);
JavaType javaType = GetJavaType(descriptor); JavaType javaType = GetJavaType(descriptor);
(*variables)["type"] = PrimitiveTypeName(javaType); (*variables)["type"] = PrimitiveTypeName(javaType);
(*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType); (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType);
(*variables)["kt_type"] = KotlinTypeName(javaType); (*variables)["kt_type"] = KotlinTypeName(javaType);
(*variables)["field_type"] = (*variables)["type"]; variables->insert({"field_type", (*variables)["type"]});
std::string name = (*variables)["name"];
if (javaType == JAVATYPE_BOOLEAN || javaType == JAVATYPE_DOUBLE || if (javaType == JAVATYPE_BOOLEAN || javaType == JAVATYPE_DOUBLE ||
javaType == JAVATYPE_FLOAT || javaType == JAVATYPE_INT || javaType == JAVATYPE_FLOAT || javaType == JAVATYPE_INT ||
javaType == JAVATYPE_LONG) { javaType == JAVATYPE_LONG) {
std::string capitalized_type = UnderscoresToCamelCase( std::string capitalized_type = UnderscoresToCamelCase(
PrimitiveTypeName(javaType), /*cap_first_letter=*/true); PrimitiveTypeName(javaType), /*cap_first_letter=*/true);
(*variables)["field_list_type"] = (*variables)["field_list_type"] =
"com.google.protobuf.Internal." + capitalized_type + "List"; StrCat("com.google.protobuf.Internal.", capitalized_type, "List");
(*variables)["empty_list"] = "empty" + capitalized_type + "List()"; (*variables)["empty_list"] =
(*variables)["create_list"] = "new" + capitalized_type + "List()"; StrCat("empty", capitalized_type, "List()");
(*variables)["create_list"] =
StrCat("new", capitalized_type, "List()");
(*variables)["mutable_copy_list"] = (*variables)["mutable_copy_list"] =
"mutableCopy(" + (*variables)["name"] + "_)"; StrCat("mutableCopy(", name, "_)");
(*variables)["name_make_immutable"] = (*variables)["name_make_immutable"] =
(*variables)["name"] + "_.makeImmutable()"; StrCat(name, "_.makeImmutable()");
(*variables)["repeated_get"] = (*variables)["repeated_get"] =
(*variables)["name"] + "_.get" + capitalized_type; StrCat(name, "_.get", capitalized_type);
(*variables)["repeated_add"] = (*variables)["repeated_add"] =
(*variables)["name"] + "_.add" + capitalized_type; StrCat(name, "_.add", capitalized_type);
(*variables)["repeated_set"] = (*variables)["repeated_set"] =
(*variables)["name"] + "_.set" + capitalized_type; StrCat(name, "_.set", capitalized_type);
} else { } else {
std::string boxed_type = (*variables)["boxed_type"];
(*variables)["field_list_type"] = (*variables)["field_list_type"] =
"java.util.List<" + (*variables)["boxed_type"] + ">"; StrCat("java.util.List<", boxed_type, ">");
(*variables)["create_list"] = (*variables)["create_list"] =
"new java.util.ArrayList<" + (*variables)["boxed_type"] + ">()"; StrCat("new java.util.ArrayList<", boxed_type, ">()");
(*variables)["mutable_copy_list"] = "new java.util.ArrayList<" + (*variables)["mutable_copy_list"] =
(*variables)["boxed_type"] + ">(" + StrCat("new java.util.ArrayList<", boxed_type, ">(", name, "_)");
(*variables)["name"] + "_)";
(*variables)["empty_list"] = "java.util.Collections.emptyList()"; (*variables)["empty_list"] = "java.util.Collections.emptyList()";
(*variables)["name_make_immutable"] = (*variables)["name_make_immutable"] = StrCat(
(*variables)["name"] + "_ = java.util.Collections.unmodifiableList(" + name, "_ = java.util.Collections.unmodifiableList(", name, "_)");
(*variables)["name"] + "_)"; (*variables)["repeated_get"] = StrCat(name, "_.get");
(*variables)["repeated_get"] = (*variables)["name"] + "_.get"; (*variables)["repeated_add"] = StrCat(name, "_.add");
(*variables)["repeated_add"] = (*variables)["name"] + "_.add"; (*variables)["repeated_set"] = StrCat(name, "_.set");
(*variables)["repeated_set"] = (*variables)["name"] + "_.set";
} }
(*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
@ -119,9 +121,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
WireFormat::TagSize(descriptor->number(), GetType(descriptor))); WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
if (IsReferenceType(GetJavaType(descriptor))) { if (IsReferenceType(GetJavaType(descriptor))) {
(*variables)["null_check"] = (*variables)["null_check"] =
" if (value == null) {\n" "if (value == null) { throw new NullPointerException(); }";
" throw new NullPointerException();\n"
" }\n";
} else { } else {
(*variables)["null_check"] = ""; (*variables)["null_check"] = "";
} }
@ -131,8 +131,8 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] = (*variables)["kt_deprecation"] =
descriptor->options().deprecated() descriptor->options().deprecated()
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + ? StrCat("@kotlin.Deprecated(message = \"Field ", name,
" is deprecated\") " " is deprecated\") ")
: ""; : "";
int fixed_size = FixedSize(GetType(descriptor)); int fixed_size = FixedSize(GetType(descriptor));
if (fixed_size != -1) { if (fixed_size != -1) {
@ -143,40 +143,29 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
if (HasHasbit(descriptor)) { if (HasHasbit(descriptor)) {
// For singular messages and builders, one bit is used for the hasField bit. // For singular messages and builders, one bit is used for the hasField bit.
(*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
// Note that these have a trailing ";". // Note that these have a trailing ";".
(*variables)["set_has_field_bit_message"] = (*variables)["set_has_field_bit_to_local"] =
GenerateSetBit(messageBitIndex) + ";"; GenerateSetBitToLocal(messageBitIndex) + ";";
(*variables)["set_has_field_bit_builder"] =
GenerateSetBit(builderBitIndex) + ";";
(*variables)["clear_has_field_bit_builder"] =
GenerateClearBit(builderBitIndex) + ";";
(*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
} else { } else {
(*variables)["set_has_field_bit_message"] = ""; (*variables)["set_has_field_bit_to_local"] = "";
(*variables)["set_has_field_bit_builder"] = "";
(*variables)["clear_has_field_bit_builder"] = "";
switch (descriptor->type()) { switch (descriptor->type()) {
case FieldDescriptor::TYPE_BYTES: case FieldDescriptor::TYPE_BYTES:
(*variables)["is_field_present_message"] = (*variables)["is_field_present_message"] =
"!" + (*variables)["name"] + "_.isEmpty()"; StrCat("!", name, "_.isEmpty()");
break; break;
case FieldDescriptor::TYPE_FLOAT: case FieldDescriptor::TYPE_FLOAT:
(*variables)["is_field_present_message"] = (*variables)["is_field_present_message"] =
"java.lang.Float.floatToRawIntBits(" + (*variables)["name"] + StrCat("java.lang.Float.floatToRawIntBits(", name, "_) != 0");
"_) != 0";
break; break;
case FieldDescriptor::TYPE_DOUBLE: case FieldDescriptor::TYPE_DOUBLE:
(*variables)["is_field_present_message"] = (*variables)["is_field_present_message"] = StrCat(
"java.lang.Double.doubleToRawLongBits(" + (*variables)["name"] + "java.lang.Double.doubleToRawLongBits(", name, "_) != 0");
"_) != 0";
break; break;
default: default:
(*variables)["is_field_present_message"] = variables->insert(
(*variables)["name"] + "_ != " + (*variables)["default"]; {"is_field_present_message",
StrCat(name, "_ != ", (*variables)["default"])});
break; break;
} }
} }
@ -186,10 +175,15 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
(*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
// Always track the presence of a field explicitly in the builder, regardless
// of syntax.
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
(*variables)["get_has_field_bit_from_local"] = (*variables)["get_has_field_bit_from_local"] =
GenerateGetBitFromLocal(builderBitIndex); GenerateGetBitFromLocal(builderBitIndex);
(*variables)["set_has_field_bit_to_local"] = (*variables)["set_has_field_bit_builder"] =
GenerateSetBitToLocal(messageBitIndex); GenerateSetBit(builderBitIndex) + ";";
(*variables)["clear_has_field_bit_builder"] =
GenerateClearBit(builderBitIndex) + ";";
} }
} // namespace } // namespace
@ -199,21 +193,30 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
ImmutablePrimitiveFieldGenerator::ImmutablePrimitiveFieldGenerator( ImmutablePrimitiveFieldGenerator::ImmutablePrimitiveFieldGenerator(
const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
Context* context) Context* context)
: descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { : descriptor_(descriptor),
message_bit_index_(messageBitIndex),
builder_bit_index_(builderBitIndex),
name_resolver_(context->GetNameResolver()) {
SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
context->GetFieldGeneratorInfo(descriptor), context->GetFieldGeneratorInfo(descriptor),
name_resolver_, &variables_); name_resolver_, &variables_, context);
} }
ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {} ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {}
int ImmutablePrimitiveFieldGenerator::GetMessageBitIndex() const {
return message_bit_index_;
}
int ImmutablePrimitiveFieldGenerator::GetBuilderBitIndex() const {
return builder_bit_index_;
}
int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const { int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
return HasHasbit(descriptor_) ? 1 : 0; return HasHasbit(descriptor_) ? 1 : 0;
} }
int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { return 1; }
return GetNumBitsForMessage();
}
void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers( void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
io::Printer* printer) const { io::Printer* printer) const {
@ -228,7 +231,7 @@ void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
void ImmutablePrimitiveFieldGenerator::GenerateMembers( void ImmutablePrimitiveFieldGenerator::GenerateMembers(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, "private $field_type$ $name$_;\n"); printer->Print(variables_, "private $field_type$ $name$_ = $default$;\n");
PrintExtraFieldInfo(variables_, printer); PrintExtraFieldInfo(variables_, printer);
if (HasHazzer(descriptor_)) { if (HasHazzer(descriptor_)) {
WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
@ -278,9 +281,9 @@ void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
printer->Print(variables_, printer->Print(variables_,
"$deprecation$public Builder " "$deprecation$public Builder "
"${$set$capitalized_name$$}$($type$ value) {\n" "${$set$capitalized_name$$}$($type$ value) {\n"
"$null_check$" " $null_check$\n"
" $set_has_field_bit_builder$\n"
" $name$_ = value;\n" " $name$_ = value;\n"
" $set_has_field_bit_builder$\n"
" $on_changed$\n" " $on_changed$\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
@ -352,9 +355,8 @@ void ImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode( void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, // No need to clear the has-bit since we clear the bitField ints all at once.
"$name$_ = $default$;\n" printer->Print(variables_, "$name$_ = $default$;\n");
"$clear_has_field_bit_builder$\n");
} }
void ImmutablePrimitiveFieldGenerator::GenerateMergingCode( void ImmutablePrimitiveFieldGenerator::GenerateMergingCode(
@ -374,23 +376,13 @@ void ImmutablePrimitiveFieldGenerator::GenerateMergingCode(
void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode( void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
io::Printer* printer) const { io::Printer* printer) const {
if (HasHazzer(descriptor_)) { printer->Print(variables_,
if (IsDefaultValueJavaDefault(descriptor_)) { "if ($get_has_field_bit_from_local$) {\n"
printer->Print(variables_, " result.$name$_ = $name$_;\n");
"if ($get_has_field_bit_from_local$) {\n" if (GetNumBitsForMessage() > 0) {
" result.$name$_ = $name$_;\n" printer->Print(variables_, " $set_has_field_bit_to_local$\n");
" $set_has_field_bit_to_local$;\n"
"}\n");
} else {
printer->Print(variables_,
"if ($get_has_field_bit_from_local$) {\n"
" $set_has_field_bit_to_local$;\n"
"}\n"
"result.$name$_ = $name$_;\n");
}
} else {
printer->Print(variables_, "result.$name$_ = $name$_;\n");
} }
printer->Print("}\n");
} }
void ImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode( void ImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode(
@ -579,7 +571,7 @@ void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers(
printer->Print(variables_, printer->Print(variables_,
"$deprecation$public Builder " "$deprecation$public Builder "
"${$set$capitalized_name$$}$($type$ value) {\n" "${$set$capitalized_name$$}$($type$ value) {\n"
"$null_check$" " $null_check$\n"
" $set_oneof_case_message$;\n" " $set_oneof_case_message$;\n"
" $oneof_name$_ = value;\n" " $oneof_name$_ = value;\n"
" $on_changed$\n" " $on_changed$\n"
@ -610,10 +602,7 @@ void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderClearCode(
void ImmutablePrimitiveOneofFieldGenerator::GenerateBuildingCode( void ImmutablePrimitiveOneofFieldGenerator::GenerateBuildingCode(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, // no-op
"if ($has_oneof_case_message$) {\n"
" result.$oneof_name$_ = $oneof_name$_;\n"
"}\n");
} }
void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode( void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode(
@ -671,11 +660,8 @@ RepeatedImmutablePrimitiveFieldGenerator::
int messageBitIndex, int messageBitIndex,
int builderBitIndex, int builderBitIndex,
Context* context) Context* context)
: descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { : ImmutablePrimitiveFieldGenerator(descriptor, messageBitIndex,
SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, builderBitIndex, context) {}
context->GetFieldGeneratorInfo(descriptor),
name_resolver_, &variables_);
}
RepeatedImmutablePrimitiveFieldGenerator:: RepeatedImmutablePrimitiveFieldGenerator::
~RepeatedImmutablePrimitiveFieldGenerator() {} ~RepeatedImmutablePrimitiveFieldGenerator() {}
@ -704,7 +690,8 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
void RepeatedImmutablePrimitiveFieldGenerator::GenerateMembers( void RepeatedImmutablePrimitiveFieldGenerator::GenerateMembers(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, "private $field_list_type$ $name$_;\n"); printer->Print(variables_, "@SuppressWarnings(\"serial\")\n"
"private $field_list_type$ $name$_;\n");
PrintExtraFieldInfo(variables_, printer); PrintExtraFieldInfo(variables_, printer);
WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
printer->Print(variables_, printer->Print(variables_,
@ -754,7 +741,7 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
" if (!$get_mutable_bit_builder$) {\n" " if (!$get_mutable_bit_builder$) {\n"
" $name$_ = $mutable_copy_list$;\n" " $name$_ = $mutable_copy_list$;\n"
" $set_mutable_bit_builder$;\n" " $set_mutable_bit_builder$;\n"
" }\n" " }\n"
"}\n"); "}\n");
// Note: We return an unmodifiable list because otherwise the caller // Note: We return an unmodifiable list because otherwise the caller
@ -789,7 +776,7 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
printer->Print(variables_, printer->Print(variables_,
"$deprecation$public Builder ${$set$capitalized_name$$}$(\n" "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
" int index, $type$ value) {\n" " int index, $type$ value) {\n"
"$null_check$" " $null_check$\n"
" ensure$capitalized_name$IsMutable();\n" " ensure$capitalized_name$IsMutable();\n"
" $repeated_set$(index, value);\n" " $repeated_set$(index, value);\n"
" $on_changed$\n" " $on_changed$\n"
@ -801,7 +788,7 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
printer->Print(variables_, printer->Print(variables_,
"$deprecation$public Builder " "$deprecation$public Builder "
"${$add$capitalized_name$$}$($type$ value) {\n" "${$add$capitalized_name$$}$($type$ value) {\n"
"$null_check$" " $null_check$\n"
" ensure$capitalized_name$IsMutable();\n" " ensure$capitalized_name$IsMutable();\n"
" $repeated_add$(value);\n" " $repeated_add$(value);\n"
" $on_changed$\n" " $on_changed$\n"
@ -939,9 +926,7 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode( void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_, "$name$_ = $empty_list$;\n");
"$name$_ = $empty_list$;\n"
"$clear_mutable_bit_builder$;\n");
} }
void RepeatedImmutablePrimitiveFieldGenerator::GenerateMergingCode( void RepeatedImmutablePrimitiveFieldGenerator::GenerateMergingCode(

@ -38,7 +38,7 @@
#include <map> #include <map>
#include <string> #include <string>
#include <google/protobuf/compiler/java/field.h> #include "google/protobuf/compiler/java/field.h"
namespace google { namespace google {
namespace protobuf { namespace protobuf {
@ -62,10 +62,16 @@ class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator {
int messageBitIndex, int messageBitIndex,
int builderBitIndex, int builderBitIndex,
Context* context); Context* context);
ImmutablePrimitiveFieldGenerator(const ImmutablePrimitiveFieldGenerator&) =
delete;
ImmutablePrimitiveFieldGenerator& operator=(
const ImmutablePrimitiveFieldGenerator&) = delete;
~ImmutablePrimitiveFieldGenerator() override; ~ImmutablePrimitiveFieldGenerator() override;
// implements ImmutableFieldGenerator // implements ImmutableFieldGenerator
// --------------------------------------- // ---------------------------------------
int GetMessageBitIndex() const override;
int GetBuilderBitIndex() const override;
int GetNumBitsForMessage() const override; int GetNumBitsForMessage() const override;
int GetNumBitsForBuilder() const override; int GetNumBitsForBuilder() const override;
void GenerateInterfaceMembers(io::Printer* printer) const override; void GenerateInterfaceMembers(io::Printer* printer) const override;
@ -88,11 +94,10 @@ class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator {
protected: protected:
const FieldDescriptor* descriptor_; const FieldDescriptor* descriptor_;
int message_bit_index_;
int builder_bit_index_;
std::map<std::string, std::string> variables_; std::map<std::string, std::string> variables_;
ClassNameResolver* name_resolver_; ClassNameResolver* name_resolver_;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldGenerator);
}; };
class ImmutablePrimitiveOneofFieldGenerator class ImmutablePrimitiveOneofFieldGenerator
@ -101,6 +106,10 @@ class ImmutablePrimitiveOneofFieldGenerator
ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
int messageBitIndex, int messageBitIndex,
int builderBitIndex, Context* context); int builderBitIndex, Context* context);
ImmutablePrimitiveOneofFieldGenerator(
const ImmutablePrimitiveOneofFieldGenerator&) = delete;
ImmutablePrimitiveOneofFieldGenerator& operator=(
const ImmutablePrimitiveOneofFieldGenerator&) = delete;
~ImmutablePrimitiveOneofFieldGenerator() override; ~ImmutablePrimitiveOneofFieldGenerator() override;
void GenerateMembers(io::Printer* printer) const override; void GenerateMembers(io::Printer* printer) const override;
@ -111,17 +120,18 @@ class ImmutablePrimitiveOneofFieldGenerator
void GenerateBuilderParsingCode(io::Printer* printer) const override; void GenerateBuilderParsingCode(io::Printer* printer) const override;
void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override;
void GenerateSerializedSizeCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldGenerator);
}; };
class RepeatedImmutablePrimitiveFieldGenerator class RepeatedImmutablePrimitiveFieldGenerator
: public ImmutableFieldGenerator { : public ImmutablePrimitiveFieldGenerator {
public: public:
explicit RepeatedImmutablePrimitiveFieldGenerator( explicit RepeatedImmutablePrimitiveFieldGenerator(
const FieldDescriptor* descriptor, int messageBitIndex, const FieldDescriptor* descriptor, int messageBitIndex,
int builderBitIndex, Context* context); int builderBitIndex, Context* context);
RepeatedImmutablePrimitiveFieldGenerator(
const RepeatedImmutablePrimitiveFieldGenerator&) = delete;
RepeatedImmutablePrimitiveFieldGenerator& operator=(
const RepeatedImmutablePrimitiveFieldGenerator&) = delete;
~RepeatedImmutablePrimitiveFieldGenerator() override; ~RepeatedImmutablePrimitiveFieldGenerator() override;
// implements ImmutableFieldGenerator --------------------------------------- // implements ImmutableFieldGenerator ---------------------------------------
@ -146,13 +156,6 @@ class RepeatedImmutablePrimitiveFieldGenerator
void GenerateKotlinDslMembers(io::Printer* printer) const override; void GenerateKotlinDslMembers(io::Printer* printer) const override;
std::string GetBoxedType() const override; std::string GetBoxedType() const override;
private:
const FieldDescriptor* descriptor_;
std::map<std::string, std::string> variables_;
ClassNameResolver* name_resolver_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldGenerator);
}; };
} // namespace java } // namespace java

@ -33,21 +33,21 @@
// Based on original Protocol Buffers design by // Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others. // Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/java/string_field.h> #include "google/protobuf/compiler/java/string_field.h"
#include <cstdint> #include <cstdint>
#include <map> #include <map>
#include <string> #include <string>
#include <google/protobuf/stubs/logging.h> #include "google/protobuf/stubs/logging.h"
#include <google/protobuf/stubs/common.h> #include "google/protobuf/stubs/common.h"
#include <google/protobuf/io/printer.h> #include "google/protobuf/io/printer.h"
#include <google/protobuf/wire_format.h> #include "google/protobuf/wire_format.h"
#include <google/protobuf/stubs/strutil.h> #include "google/protobuf/stubs/strutil.h"
#include <google/protobuf/compiler/java/context.h> #include "google/protobuf/compiler/java/context.h"
#include <google/protobuf/compiler/java/doc_comment.h> #include "google/protobuf/compiler/java/doc_comment.h"
#include <google/protobuf/compiler/java/helpers.h> #include "google/protobuf/compiler/java/helpers.h"
#include <google/protobuf/compiler/java/name_resolver.h> #include "google/protobuf/compiler/java/name_resolver.h"
namespace google { namespace google {
namespace protobuf { namespace protobuf {
@ -59,11 +59,11 @@ using internal::WireFormatLite;
namespace { namespace {
void SetPrimitiveVariables(const FieldDescriptor* descriptor, void SetPrimitiveVariables(
int messageBitIndex, int builderBitIndex, const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
const FieldGeneratorInfo* info, const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
ClassNameResolver* name_resolver, std::map<std::string, std::string>* variables,
std::map<std::string, std::string>* variables) { Context* context) {
SetCommonFieldVariables(descriptor, info, variables); SetCommonFieldVariables(descriptor, info, variables);
(*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY"; (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY";
@ -77,9 +77,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["tag_size"] = StrCat( (*variables)["tag_size"] = StrCat(
WireFormat::TagSize(descriptor->number(), GetType(descriptor))); WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
(*variables)["null_check"] = (*variables)["null_check"] =
" if (value == null) {\n" "if (value == null) { throw new NullPointerException(); }";
" throw new NullPointerException();\n"
" }\n";
(*variables)["isStringEmpty"] = "com.google.protobuf.GeneratedMessage" + (*variables)["isStringEmpty"] = "com.google.protobuf.GeneratedMessage" +
GeneratedCodeVersionSuffix() + GeneratedCodeVersionSuffix() +
".isStringEmpty"; ".isStringEmpty";
@ -93,34 +91,33 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
// by the proto compiler // by the proto compiler
(*variables)["deprecation"] = (*variables)["deprecation"] =
descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] = variables->insert(
descriptor->options().deprecated() {"kt_deprecation",
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + descriptor->options().deprecated()
" is deprecated\") " ? StrCat("@kotlin.Deprecated(message = \"Field ",
: ""; (*variables)["name"], " is deprecated\") ")
: ""});
(*variables)["on_changed"] = "onChanged();"; (*variables)["on_changed"] = "onChanged();";
if (HasHasbit(descriptor)) { if (HasHasbit(descriptor)) {
// For singular messages and builders, one bit is used for the hasField bit. // For singular messages and builders, one bit is used for the hasField bit.
(*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); (*variables)["set_has_field_bit_to_local"] =
GenerateSetBitToLocal(messageBitIndex);
// Note that these have a trailing ";". // Note that these have a trailing ";".
(*variables)["set_has_field_bit_message"] = (*variables)["set_has_field_bit_message"] =
GenerateSetBit(messageBitIndex) + ";"; GenerateSetBit(messageBitIndex) + ";";
(*variables)["set_has_field_bit_builder"] =
GenerateSetBit(builderBitIndex) + ";";
(*variables)["clear_has_field_bit_builder"] =
GenerateClearBit(builderBitIndex) + ";";
(*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
} else { } else {
(*variables)["get_has_field_bit_message"] = "";
(*variables)["set_has_field_bit_to_local"] = "";
(*variables)["set_has_field_bit_message"] = ""; (*variables)["set_has_field_bit_message"] = "";
(*variables)["set_has_field_bit_builder"] = "";
(*variables)["clear_has_field_bit_builder"] = "";
(*variables)["is_field_present_message"] = variables->insert({"is_field_present_message",
"!" + (*variables)["isStringEmpty"] + "(" + (*variables)["name"] + "_)"; StrCat("!", (*variables)["isStringEmpty"], "(",
(*variables)["name"], "_)")});
} }
// For repeated builders, one bit is used for whether the array is immutable. // For repeated builders, one bit is used for whether the array is immutable.
@ -128,10 +125,13 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
(*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
(*variables)["get_has_field_bit_from_local"] = (*variables)["get_has_field_bit_from_local"] =
GenerateGetBitFromLocal(builderBitIndex); GenerateGetBitFromLocal(builderBitIndex);
(*variables)["set_has_field_bit_to_local"] = (*variables)["set_has_field_bit_builder"] =
GenerateSetBitToLocal(messageBitIndex); GenerateSetBit(builderBitIndex) + ";";
(*variables)["clear_has_field_bit_builder"] =
GenerateClearBit(builderBitIndex) + ";";
} }
} // namespace } // namespace
@ -141,21 +141,30 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
ImmutableStringFieldGenerator::ImmutableStringFieldGenerator( ImmutableStringFieldGenerator::ImmutableStringFieldGenerator(
const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
Context* context) Context* context)
: descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { : descriptor_(descriptor),
message_bit_index_(messageBitIndex),
builder_bit_index_(builderBitIndex),
name_resolver_(context->GetNameResolver()) {
SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
context->GetFieldGeneratorInfo(descriptor), context->GetFieldGeneratorInfo(descriptor),
name_resolver_, &variables_); name_resolver_, &variables_, context);
} }
ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {} ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {}
int ImmutableStringFieldGenerator::GetMessageBitIndex() const {
return message_bit_index_;
}
int ImmutableStringFieldGenerator::GetBuilderBitIndex() const {
return builder_bit_index_;
}
int ImmutableStringFieldGenerator::GetNumBitsForMessage() const { int ImmutableStringFieldGenerator::GetNumBitsForMessage() const {
return HasHasbit(descriptor_) ? 1 : 0; return HasHasbit(descriptor_) ? 1 : 0;
} }
int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const { int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const { return 1; }
return GetNumBitsForMessage();
}
// A note about how strings are handled. This code used to just store a String // A note about how strings are handled. This code used to just store a String
// in the Message. This had two issues: // in the Message. This had two issues:
@ -207,7 +216,9 @@ void ImmutableStringFieldGenerator::GenerateInterfaceMembers(
void ImmutableStringFieldGenerator::GenerateMembers( void ImmutableStringFieldGenerator::GenerateMembers(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, "private volatile java.lang.Object $name$_;\n"); printer->Print(variables_,
"@SuppressWarnings(\"serial\")\n"
"private volatile java.lang.Object $name$_ = $default$;\n");
PrintExtraFieldInfo(variables_, printer); PrintExtraFieldInfo(variables_, printer);
if (HasHazzer(descriptor_)) { if (HasHazzer(descriptor_)) {
@ -326,9 +337,9 @@ void ImmutableStringFieldGenerator::GenerateBuilderMembers(
printer->Print(variables_, printer->Print(variables_,
"$deprecation$public Builder ${$set$capitalized_name$$}$(\n" "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
" java.lang.String value) {\n" " java.lang.String value) {\n"
"$null_check$" " $null_check$\n"
" $set_has_field_bit_builder$\n"
" $name$_ = value;\n" " $name$_ = value;\n"
" $set_has_field_bit_builder$\n"
" $on_changed$\n" " $on_changed$\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
@ -337,14 +348,14 @@ void ImmutableStringFieldGenerator::GenerateBuilderMembers(
/* builder */ true); /* builder */ true);
printer->Print( printer->Print(
variables_, variables_,
"$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n");
" $clear_has_field_bit_builder$\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
// The default value is not a simple literal so we want to avoid executing // The default value is not a simple literal so we want to avoid executing
// it multiple times. Instead, get the default out of the default instance. // it multiple times. Instead, get the default out of the default instance.
printer->Print(variables_, printer->Print(variables_,
" $name$_ = getDefaultInstance().get$capitalized_name$();\n"); " $name$_ = getDefaultInstance().get$capitalized_name$();\n");
printer->Print(variables_, printer->Print(variables_,
" $clear_has_field_bit_builder$\n"
" $on_changed$\n" " $on_changed$\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
@ -355,14 +366,14 @@ void ImmutableStringFieldGenerator::GenerateBuilderMembers(
variables_, variables_,
"$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n" "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
" com.google.protobuf.ByteString value) {\n" " com.google.protobuf.ByteString value) {\n"
"$null_check$"); " $null_check$\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
if (CheckUtf8(descriptor_)) { if (CheckUtf8(descriptor_)) {
printer->Print(variables_, " checkByteStringIsUtf8(value);\n"); printer->Print(variables_, " checkByteStringIsUtf8(value);\n");
} }
printer->Print(variables_, printer->Print(variables_,
" $set_has_field_bit_builder$\n"
" $name$_ = value;\n" " $name$_ = value;\n"
" $set_has_field_bit_builder$\n"
" $on_changed$\n" " $on_changed$\n"
" return this;\n" " return this;\n"
"}\n"); "}\n");
@ -409,9 +420,7 @@ void ImmutableStringFieldGenerator::GenerateInitializationCode(
void ImmutableStringFieldGenerator::GenerateBuilderClearCode( void ImmutableStringFieldGenerator::GenerateBuilderClearCode(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_, "$name$_ = $default$;\n");
"$name$_ = $default$;\n"
"$clear_has_field_bit_builder$\n");
} }
void ImmutableStringFieldGenerator::GenerateMergingCode( void ImmutableStringFieldGenerator::GenerateMergingCode(
@ -421,14 +430,15 @@ void ImmutableStringFieldGenerator::GenerateMergingCode(
// all string fields to Strings when copying fields from a Message. // all string fields to Strings when copying fields from a Message.
printer->Print(variables_, printer->Print(variables_,
"if (other.has$capitalized_name$()) {\n" "if (other.has$capitalized_name$()) {\n"
" $set_has_field_bit_builder$\n"
" $name$_ = other.$name$_;\n" " $name$_ = other.$name$_;\n"
" $set_has_field_bit_builder$\n"
" $on_changed$\n" " $on_changed$\n"
"}\n"); "}\n");
} else { } else {
printer->Print(variables_, printer->Print(variables_,
"if (!other.get$capitalized_name$().isEmpty()) {\n" "if (!other.get$capitalized_name$().isEmpty()) {\n"
" $name$_ = other.$name$_;\n" " $name$_ = other.$name$_;\n"
" $set_has_field_bit_builder$\n"
" $on_changed$\n" " $on_changed$\n"
"}\n"); "}\n");
} }
@ -436,13 +446,13 @@ void ImmutableStringFieldGenerator::GenerateMergingCode(
void ImmutableStringFieldGenerator::GenerateBuildingCode( void ImmutableStringFieldGenerator::GenerateBuildingCode(
io::Printer* printer) const { io::Printer* printer) const {
if (HasHazzer(descriptor_)) { printer->Print(variables_,
printer->Print(variables_, "if ($get_has_field_bit_from_local$) {\n"
"if ($get_has_field_bit_from_local$) {\n" " result.$name$_ = $name$_;\n");
" $set_has_field_bit_to_local$;\n" if (GetNumBitsForMessage() > 0) {
"}\n"); printer->Print(variables_, " $set_has_field_bit_to_local$;\n");
} }
printer->Print(variables_, "result.$name$_ = $name$_;\n"); printer->Print("}\n");
} }
void ImmutableStringFieldGenerator::GenerateBuilderParsingCode( void ImmutableStringFieldGenerator::GenerateBuilderParsingCode(
@ -641,7 +651,7 @@ void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers(
printer->Print(variables_, printer->Print(variables_,
"$deprecation$public Builder ${$set$capitalized_name$$}$(\n" "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
" java.lang.String value) {\n" " java.lang.String value) {\n"
"$null_check$" " $null_check$\n"
" $set_oneof_case_message$;\n" " $set_oneof_case_message$;\n"
" $oneof_name$_ = value;\n" " $oneof_name$_ = value;\n"
" $on_changed$\n" " $on_changed$\n"
@ -668,7 +678,7 @@ void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers(
variables_, variables_,
"$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n" "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
" com.google.protobuf.ByteString value) {\n" " com.google.protobuf.ByteString value) {\n"
"$null_check$"); " $null_check$\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
if (CheckUtf8(descriptor_)) { if (CheckUtf8(descriptor_)) {
printer->Print(variables_, " checkByteStringIsUtf8(value);\n"); printer->Print(variables_, " checkByteStringIsUtf8(value);\n");
@ -698,10 +708,7 @@ void ImmutableStringOneofFieldGenerator::GenerateMergingCode(
void ImmutableStringOneofFieldGenerator::GenerateBuildingCode( void ImmutableStringOneofFieldGenerator::GenerateBuildingCode(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, // No-Op: oneof fields are built by a single statement
"if ($has_oneof_case_message$) {\n"
" result.$oneof_name$_ = $oneof_name$_;\n"
"}\n");
} }
void ImmutableStringOneofFieldGenerator::GenerateBuilderParsingCode( void ImmutableStringOneofFieldGenerator::GenerateBuilderParsingCode(
@ -740,11 +747,8 @@ void ImmutableStringOneofFieldGenerator::GenerateSerializedSizeCode(
RepeatedImmutableStringFieldGenerator::RepeatedImmutableStringFieldGenerator( RepeatedImmutableStringFieldGenerator::RepeatedImmutableStringFieldGenerator(
const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
Context* context) Context* context)
: descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { : ImmutableStringFieldGenerator(descriptor, messageBitIndex,
SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, builderBitIndex, context) {}
context->GetFieldGeneratorInfo(descriptor),
name_resolver_, &variables_);
}
RepeatedImmutableStringFieldGenerator:: RepeatedImmutableStringFieldGenerator::
~RepeatedImmutableStringFieldGenerator() {} ~RepeatedImmutableStringFieldGenerator() {}
@ -787,6 +791,7 @@ void RepeatedImmutableStringFieldGenerator::GenerateInterfaceMembers(
void RepeatedImmutableStringFieldGenerator::GenerateMembers( void RepeatedImmutableStringFieldGenerator::GenerateMembers(
io::Printer* printer) const { io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"@SuppressWarnings(\"serial\")\n"
"private com.google.protobuf.LazyStringList $name$_;\n"); "private com.google.protobuf.LazyStringList $name$_;\n");
PrintExtraFieldInfo(variables_, printer); PrintExtraFieldInfo(variables_, printer);
WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
@ -882,7 +887,7 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers(
printer->Print(variables_, printer->Print(variables_,
"$deprecation$public Builder ${$set$capitalized_name$$}$(\n" "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
" int index, java.lang.String value) {\n" " int index, java.lang.String value) {\n"
"$null_check$" " $null_check$\n"
" ensure$capitalized_name$IsMutable();\n" " ensure$capitalized_name$IsMutable();\n"
" $name$_.set(index, value);\n" " $name$_.set(index, value);\n"
" $on_changed$\n" " $on_changed$\n"
@ -894,7 +899,7 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers(
printer->Print(variables_, printer->Print(variables_,
"$deprecation$public Builder ${$add$capitalized_name$$}$(\n" "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
" java.lang.String value) {\n" " java.lang.String value) {\n"
"$null_check$" " $null_check$\n"
" ensure$capitalized_name$IsMutable();\n" " ensure$capitalized_name$IsMutable();\n"
" $name$_.add(value);\n" " $name$_.add(value);\n"
" $on_changed$\n" " $on_changed$\n"
@ -931,7 +936,7 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers(
variables_, variables_,
"$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n" "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n"
" com.google.protobuf.ByteString value) {\n" " com.google.protobuf.ByteString value) {\n"
"$null_check$"); " $null_check$\n");
printer->Annotate("{", "}", descriptor_); printer->Annotate("{", "}", descriptor_);
if (CheckUtf8(descriptor_)) { if (CheckUtf8(descriptor_)) {
printer->Print(variables_, " checkByteStringIsUtf8(value);\n"); printer->Print(variables_, " checkByteStringIsUtf8(value);\n");

@ -39,7 +39,7 @@
#include <map> #include <map>
#include <string> #include <string>
#include <google/protobuf/compiler/java/field.h> #include "google/protobuf/compiler/java/field.h"
namespace google { namespace google {
namespace protobuf { namespace protobuf {
@ -62,10 +62,15 @@ class ImmutableStringFieldGenerator : public ImmutableFieldGenerator {
explicit ImmutableStringFieldGenerator(const FieldDescriptor* descriptor, explicit ImmutableStringFieldGenerator(const FieldDescriptor* descriptor,
int messageBitIndex, int messageBitIndex,
int builderBitIndex, Context* context); int builderBitIndex, Context* context);
ImmutableStringFieldGenerator(const ImmutableStringFieldGenerator&) = delete;
ImmutableStringFieldGenerator& operator=(
const ImmutableStringFieldGenerator&) = delete;
~ImmutableStringFieldGenerator() override; ~ImmutableStringFieldGenerator() override;
// implements ImmutableFieldGenerator // implements ImmutableFieldGenerator
// --------------------------------------- // ---------------------------------------
int GetMessageBitIndex() const override;
int GetBuilderBitIndex() const override;
int GetNumBitsForMessage() const override; int GetNumBitsForMessage() const override;
int GetNumBitsForBuilder() const override; int GetNumBitsForBuilder() const override;
void GenerateInterfaceMembers(io::Printer* printer) const override; void GenerateInterfaceMembers(io::Printer* printer) const override;
@ -88,11 +93,10 @@ class ImmutableStringFieldGenerator : public ImmutableFieldGenerator {
protected: protected:
const FieldDescriptor* descriptor_; const FieldDescriptor* descriptor_;
int message_bit_index_;
int builder_bit_index_;
std::map<std::string, std::string> variables_; std::map<std::string, std::string> variables_;
ClassNameResolver* name_resolver_; ClassNameResolver* name_resolver_;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldGenerator);
}; };
class ImmutableStringOneofFieldGenerator class ImmutableStringOneofFieldGenerator
@ -101,6 +105,10 @@ class ImmutableStringOneofFieldGenerator
ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor, ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor,
int messageBitIndex, int builderBitIndex, int messageBitIndex, int builderBitIndex,
Context* context); Context* context);
ImmutableStringOneofFieldGenerator(
const ImmutableStringOneofFieldGenerator&) = delete;
ImmutableStringOneofFieldGenerator& operator=(
const ImmutableStringOneofFieldGenerator&) = delete;
~ImmutableStringOneofFieldGenerator() override; ~ImmutableStringOneofFieldGenerator() override;
private: private:
@ -112,15 +120,18 @@ class ImmutableStringOneofFieldGenerator
void GenerateBuilderParsingCode(io::Printer* printer) const override; void GenerateBuilderParsingCode(io::Printer* printer) const override;
void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override;
void GenerateSerializedSizeCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldGenerator);
}; };
class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator { class RepeatedImmutableStringFieldGenerator
: public ImmutableStringFieldGenerator {
public: public:
explicit RepeatedImmutableStringFieldGenerator( explicit RepeatedImmutableStringFieldGenerator(
const FieldDescriptor* descriptor, int messageBitIndex, const FieldDescriptor* descriptor, int messageBitIndex,
int builderBitIndex, Context* context); int builderBitIndex, Context* context);
RepeatedImmutableStringFieldGenerator(
const RepeatedImmutableStringFieldGenerator&) = delete;
RepeatedImmutableStringFieldGenerator& operator=(
const RepeatedImmutableStringFieldGenerator&) = delete;
~RepeatedImmutableStringFieldGenerator() override; ~RepeatedImmutableStringFieldGenerator() override;
// implements ImmutableFieldGenerator --------------------------------------- // implements ImmutableFieldGenerator ---------------------------------------
@ -143,13 +154,6 @@ class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator {
void GenerateKotlinDslMembers(io::Printer* printer) const override; void GenerateKotlinDslMembers(io::Printer* printer) const override;
std::string GetBoxedType() const override; std::string GetBoxedType() const override;
private:
const FieldDescriptor* descriptor_;
std::map<std::string, std::string> variables_;
ClassNameResolver* name_resolver_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldGenerator);
}; };
} // namespace java } // namespace java

Loading…
Cancel
Save