| Index: third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc
|
| index 8b91193fcbea3d0730bb50c8efd6f1612d5870d0..47ee84cfdb0d8ee5b2a42d6aab1a75bc92e21545 100644
|
| --- a/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc
|
| +++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc
|
| @@ -245,14 +245,54 @@ void MessageGenerator::GenerateStaticVariableInitializers(
|
| MessageGenerator(descriptor_->nested_type(i))
|
| .GenerateStaticVariableInitializers(printer);
|
| }
|
| +}
|
|
|
| - for (int i = 0; i < descriptor_->extension_count(); i++) {
|
| - // TODO(kenton): Reuse ExtensionGenerator objects?
|
| - ExtensionGenerator(descriptor_->extension(i))
|
| - .GenerateInitializationCode(printer);
|
| +// ===================================================================
|
| +
|
| +void MessageGenerator::GenerateInterface(io::Printer* printer) {
|
| +
|
| + if (descriptor_->extension_range_count() > 0) {
|
| + if (HasDescriptorMethods(descriptor_)) {
|
| + printer->Print(
|
| + "public interface $classname$OrBuilder extends\n"
|
| + " com.google.protobuf.GeneratedMessage.\n"
|
| + " ExtendableMessageOrBuilder<$classname$> {\n",
|
| + "classname", descriptor_->name());
|
| + } else {
|
| + printer->Print(
|
| + "public interface $classname$OrBuilder extends \n"
|
| + " com.google.protobuf.GeneratedMessageLite.\n"
|
| + " ExtendableMessageOrBuilder<$classname$> {\n",
|
| + "classname", descriptor_->name());
|
| + }
|
| + } else {
|
| + if (HasDescriptorMethods(descriptor_)) {
|
| + printer->Print(
|
| + "public interface $classname$OrBuilder\n"
|
| + " extends com.google.protobuf.MessageOrBuilder {\n",
|
| + "classname", descriptor_->name());
|
| + } else {
|
| + printer->Print(
|
| + "public interface $classname$OrBuilder\n"
|
| + " extends com.google.protobuf.MessageLiteOrBuilder {\n",
|
| + "classname", descriptor_->name());
|
| + }
|
| }
|
| +
|
| + printer->Indent();
|
| + for (int i = 0; i < descriptor_->field_count(); i++) {
|
| + printer->Print("\n");
|
| + PrintFieldComment(printer, descriptor_->field(i));
|
| + field_generators_.get(descriptor_->field(i))
|
| + .GenerateInterfaceMembers(printer);
|
| + }
|
| + printer->Outdent();
|
| +
|
| + printer->Print("}\n");
|
| }
|
|
|
| +// ===================================================================
|
| +
|
| void MessageGenerator::Generate(io::Printer* printer) {
|
| bool is_own_file =
|
| descriptor_->containing_type() == NULL &&
|
| @@ -263,14 +303,14 @@ void MessageGenerator::Generate(io::Printer* printer) {
|
| printer->Print(
|
| "public $static$ final class $classname$ extends\n"
|
| " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
|
| - " $classname$> {\n",
|
| + " $classname$> implements $classname$OrBuilder {\n",
|
| "static", is_own_file ? "" : "static",
|
| "classname", descriptor_->name());
|
| } else {
|
| printer->Print(
|
| "public $static$ final class $classname$ extends\n"
|
| " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
|
| - " $classname$> {\n",
|
| + " $classname$> implements $classname$OrBuilder {\n",
|
| "static", is_own_file ? "" : "static",
|
| "classname", descriptor_->name());
|
| }
|
| @@ -278,13 +318,15 @@ void MessageGenerator::Generate(io::Printer* printer) {
|
| if (HasDescriptorMethods(descriptor_)) {
|
| printer->Print(
|
| "public $static$ final class $classname$ extends\n"
|
| - " com.google.protobuf.GeneratedMessage {\n",
|
| + " com.google.protobuf.GeneratedMessage\n"
|
| + " implements $classname$OrBuilder {\n",
|
| "static", is_own_file ? "" : "static",
|
| "classname", descriptor_->name());
|
| } else {
|
| printer->Print(
|
| "public $static$ final class $classname$ extends\n"
|
| - " com.google.protobuf.GeneratedMessageLite {\n",
|
| + " com.google.protobuf.GeneratedMessageLite\n"
|
| + " implements $classname$OrBuilder {\n",
|
| "static", is_own_file ? "" : "static",
|
| "classname", descriptor_->name());
|
| }
|
| @@ -292,8 +334,8 @@ void MessageGenerator::Generate(io::Printer* printer) {
|
| printer->Indent();
|
| printer->Print(
|
| "// Use $classname$.newBuilder() to construct.\n"
|
| - "private $classname$() {\n"
|
| - " initFields();\n"
|
| + "private $classname$(Builder builder) {\n"
|
| + " super(builder);\n"
|
| "}\n"
|
| // Used when constructing the default instance, which cannot be initialized
|
| // immediately because it may cyclically refer to other default instances.
|
| @@ -310,33 +352,29 @@ void MessageGenerator::Generate(io::Printer* printer) {
|
| "\n",
|
| "classname", descriptor_->name());
|
|
|
| - if (HasDescriptorMethods(descriptor_)) {
|
| - printer->Print(
|
| - "public static final com.google.protobuf.Descriptors.Descriptor\n"
|
| - " getDescriptor() {\n"
|
| - " return $fileclass$.internal_$identifier$_descriptor;\n"
|
| - "}\n"
|
| - "\n"
|
| - "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
|
| - " internalGetFieldAccessorTable() {\n"
|
| - " return $fileclass$.internal_$identifier$_fieldAccessorTable;\n"
|
| - "}\n"
|
| - "\n",
|
| - "fileclass", ClassName(descriptor_->file()),
|
| - "identifier", UniqueFileScopeIdentifier(descriptor_));
|
| - }
|
| + GenerateDescriptorMethods(printer);
|
|
|
| - // Nested types and extensions
|
| + // Nested types
|
| for (int i = 0; i < descriptor_->enum_type_count(); i++) {
|
| EnumGenerator(descriptor_->enum_type(i)).Generate(printer);
|
| }
|
|
|
| for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
| - MessageGenerator(descriptor_->nested_type(i)).Generate(printer);
|
| + MessageGenerator messageGenerator(descriptor_->nested_type(i));
|
| + messageGenerator.GenerateInterface(printer);
|
| + messageGenerator.Generate(printer);
|
| }
|
|
|
| - for (int i = 0; i < descriptor_->extension_count(); i++) {
|
| - ExtensionGenerator(descriptor_->extension(i)).Generate(printer);
|
| + // Integers for bit fields.
|
| + int totalBits = 0;
|
| + for (int i = 0; i < descriptor_->field_count(); i++) {
|
| + totalBits += field_generators_.get(descriptor_->field(i))
|
| + .GetNumBitsForMessage();
|
| + }
|
| + int totalInts = (totalBits + 31) / 32;
|
| + for (int i = 0; i < totalInts; i++) {
|
| + printer->Print("private int $bit_field_name$;\n",
|
| + "bit_field_name", GetBitFieldName(i));
|
| }
|
|
|
| // Fields
|
| @@ -361,35 +399,42 @@ void MessageGenerator::Generate(io::Printer* printer) {
|
| printer->Print("}\n");
|
|
|
| if (HasGeneratedMethods(descriptor_)) {
|
| - GenerateIsInitialized(printer);
|
| + GenerateIsInitialized(printer, MEMOIZE);
|
| GenerateMessageSerializationMethods(printer);
|
| }
|
|
|
| + if (HasEqualsAndHashCode(descriptor_)) {
|
| + GenerateEqualsAndHashCode(printer);
|
| + }
|
| +
|
| GenerateParseFromMethods(printer);
|
| GenerateBuilder(printer);
|
|
|
| - // Force initialization of outer class. Otherwise, nested extensions may
|
| - // not be initialized. Also carefully initialize the default instance in
|
| - // such a way that it doesn't conflict with other initialization.
|
| + // Carefully initialize the default instance in such a way that it doesn't
|
| + // conflict with other initialization.
|
| printer->Print(
|
| "\n"
|
| "static {\n"
|
| " defaultInstance = new $classname$(true);\n"
|
| - " $file$.internalForceInit();\n"
|
| " defaultInstance.initFields();\n"
|
| - "}\n",
|
| - "file", ClassName(descriptor_->file()),
|
| - "classname", descriptor_->name());
|
| -
|
| - printer->Print(
|
| + "}\n"
|
| "\n"
|
| "// @@protoc_insertion_point(class_scope:$full_name$)\n",
|
| + "classname", descriptor_->name(),
|
| "full_name", descriptor_->full_name());
|
|
|
| + // Extensions must be declared after the defaultInstance is initialized
|
| + // because the defaultInstance is used by the extension to lazily retrieve
|
| + // the outer class's FileDescriptor.
|
| + for (int i = 0; i < descriptor_->extension_count(); i++) {
|
| + ExtensionGenerator(descriptor_->extension(i)).Generate(printer);
|
| + }
|
| +
|
| printer->Outdent();
|
| printer->Print("}\n\n");
|
| }
|
|
|
| +
|
| // ===================================================================
|
|
|
| void MessageGenerator::
|
| @@ -502,6 +547,13 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
|
| " return size;\n"
|
| "}\n"
|
| "\n");
|
| +
|
| + printer->Print(
|
| + "@java.lang.Override\n"
|
| + "protected Object writeReplace() throws java.io.ObjectStreamException {\n"
|
| + " return super.writeReplace();\n"
|
| + "}\n"
|
| + "\n");
|
| }
|
|
|
| void MessageGenerator::
|
| @@ -605,42 +657,68 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) {
|
| "\n",
|
| "classname", ClassName(descriptor_));
|
|
|
| + if (HasNestedBuilders(descriptor_)) {
|
| + printer->Print(
|
| + "@java.lang.Override\n"
|
| + "protected Builder newBuilderForType(\n"
|
| + " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
|
| + " Builder builder = new Builder(parent);\n"
|
| + " return builder;\n"
|
| + "}\n");
|
| + }
|
| +
|
| if (descriptor_->extension_range_count() > 0) {
|
| if (HasDescriptorMethods(descriptor_)) {
|
| printer->Print(
|
| "public static final class Builder extends\n"
|
| " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
|
| - " $classname$, Builder> {\n",
|
| + " $classname$, Builder> implements $classname$OrBuilder {\n",
|
| "classname", ClassName(descriptor_));
|
| } else {
|
| printer->Print(
|
| "public static final class Builder extends\n"
|
| " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n"
|
| - " $classname$, Builder> {\n",
|
| + " $classname$, Builder> implements $classname$OrBuilder {\n",
|
| "classname", ClassName(descriptor_));
|
| }
|
| } else {
|
| if (HasDescriptorMethods(descriptor_)) {
|
| printer->Print(
|
| "public static final class Builder extends\n"
|
| - " com.google.protobuf.GeneratedMessage.Builder<Builder> {\n",
|
| + " com.google.protobuf.GeneratedMessage.Builder<Builder>\n"
|
| + " implements $classname$OrBuilder {\n",
|
| "classname", ClassName(descriptor_));
|
| } else {
|
| printer->Print(
|
| "public static final class Builder extends\n"
|
| " com.google.protobuf.GeneratedMessageLite.Builder<\n"
|
| - " $classname$, Builder> {\n",
|
| + " $classname$, Builder>\n"
|
| + " implements $classname$OrBuilder {\n",
|
| "classname", ClassName(descriptor_));
|
| }
|
| }
|
| printer->Indent();
|
|
|
| + GenerateDescriptorMethods(printer);
|
| GenerateCommonBuilderMethods(printer);
|
|
|
| if (HasGeneratedMethods(descriptor_)) {
|
| + GenerateIsInitialized(printer, DONT_MEMOIZE);
|
| GenerateBuilderParsingMethods(printer);
|
| }
|
|
|
| + // Integers for bit fields.
|
| + int totalBits = 0;
|
| + for (int i = 0; i < descriptor_->field_count(); i++) {
|
| + totalBits += field_generators_.get(descriptor_->field(i))
|
| + .GetNumBitsForBuilder();
|
| + }
|
| + int totalInts = (totalBits + 31) / 32;
|
| + for (int i = 0; i < totalInts; i++) {
|
| + printer->Print("private int $bit_field_name$;\n",
|
| + "bit_field_name", GetBitFieldName(i));
|
| + }
|
| +
|
| for (int i = 0; i < descriptor_->field_count(); i++) {
|
| printer->Print("\n");
|
| PrintFieldComment(printer, descriptor_->field(i));
|
| @@ -657,36 +735,92 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) {
|
| printer->Print("}\n");
|
| }
|
|
|
| +void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) {
|
| + if (HasDescriptorMethods(descriptor_)) {
|
| + printer->Print(
|
| + "public static final com.google.protobuf.Descriptors.Descriptor\n"
|
| + " getDescriptor() {\n"
|
| + " return $fileclass$.internal_$identifier$_descriptor;\n"
|
| + "}\n"
|
| + "\n"
|
| + "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
|
| + " internalGetFieldAccessorTable() {\n"
|
| + " return $fileclass$.internal_$identifier$_fieldAccessorTable;\n"
|
| + "}\n"
|
| + "\n",
|
| + "fileclass", ClassName(descriptor_->file()),
|
| + "identifier", UniqueFileScopeIdentifier(descriptor_));
|
| + }
|
| +}
|
| +
|
| // ===================================================================
|
|
|
| void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
|
| printer->Print(
|
| - "private $classname$ result;\n"
|
| - "\n"
|
| "// Construct using $classname$.newBuilder()\n"
|
| - "private Builder() {}\n"
|
| - "\n"
|
| - "private static Builder create() {\n"
|
| - " Builder builder = new Builder();\n"
|
| - " builder.result = new $classname$();\n"
|
| - " return builder;\n"
|
| + "private Builder() {\n"
|
| + " maybeForceBuilderInitialization();\n"
|
| "}\n"
|
| - "\n"
|
| - "protected $classname$ internalGetResult() {\n"
|
| - " return result;\n"
|
| + "\n",
|
| + "classname", ClassName(descriptor_));
|
| +
|
| + if (HasDescriptorMethods(descriptor_)) {
|
| + printer->Print(
|
| + "private Builder(BuilderParent parent) {\n"
|
| + " super(parent);\n"
|
| + " maybeForceBuilderInitialization();\n"
|
| + "}\n",
|
| + "classname", ClassName(descriptor_));
|
| + }
|
| +
|
| +
|
| + if (HasNestedBuilders(descriptor_)) {
|
| + printer->Print(
|
| + "private void maybeForceBuilderInitialization() {\n"
|
| + " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n");
|
| +
|
| + printer->Indent();
|
| + printer->Indent();
|
| + for (int i = 0; i < descriptor_->field_count(); i++) {
|
| + field_generators_.get(descriptor_->field(i))
|
| + .GenerateFieldBuilderInitializationCode(printer);
|
| + }
|
| + printer->Outdent();
|
| + printer->Outdent();
|
| +
|
| + printer->Print(
|
| + " }\n"
|
| + "}\n");
|
| + } else {
|
| + printer->Print(
|
| + "private void maybeForceBuilderInitialization() {\n"
|
| + "}\n");
|
| + }
|
| +
|
| + printer->Print(
|
| + "private static Builder create() {\n"
|
| + " return new Builder();\n"
|
| "}\n"
|
| "\n"
|
| "public Builder clear() {\n"
|
| - " if (result == null) {\n"
|
| - " throw new IllegalStateException(\n"
|
| - " \"Cannot call clear() after build().\");\n"
|
| - " }\n"
|
| - " result = new $classname$();\n"
|
| + " super.clear();\n",
|
| + "classname", ClassName(descriptor_));
|
| +
|
| + printer->Indent();
|
| +
|
| + for (int i = 0; i < descriptor_->field_count(); i++) {
|
| + field_generators_.get(descriptor_->field(i))
|
| + .GenerateBuilderClearCode(printer);
|
| + }
|
| +
|
| + printer->Outdent();
|
| +
|
| + printer->Print(
|
| " return this;\n"
|
| "}\n"
|
| "\n"
|
| "public Builder clone() {\n"
|
| - " return create().mergeFrom(result);\n"
|
| + " return create().mergeFrom(buildPartial());\n"
|
| "}\n"
|
| "\n",
|
| "classname", ClassName(descriptor_));
|
| @@ -703,49 +837,78 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
|
| "public $classname$ getDefaultInstanceForType() {\n"
|
| " return $classname$.getDefaultInstance();\n"
|
| "}\n"
|
| - "\n"
|
| - "public boolean isInitialized() {\n"
|
| - " return result.isInitialized();\n"
|
| - "}\n",
|
| + "\n",
|
| "classname", ClassName(descriptor_));
|
|
|
| // -----------------------------------------------------------------
|
|
|
| printer->Print(
|
| "public $classname$ build() {\n"
|
| - // If result == null, we'll throw an appropriate exception later.
|
| - " if (result != null && !isInitialized()) {\n"
|
| + " $classname$ result = buildPartial();\n"
|
| + " if (!result.isInitialized()) {\n"
|
| " throw newUninitializedMessageException(result);\n"
|
| " }\n"
|
| - " return buildPartial();\n"
|
| + " return result;\n"
|
| "}\n"
|
| "\n"
|
| "private $classname$ buildParsed()\n"
|
| " throws com.google.protobuf.InvalidProtocolBufferException {\n"
|
| - " if (!isInitialized()) {\n"
|
| + " $classname$ result = buildPartial();\n"
|
| + " if (!result.isInitialized()) {\n"
|
| " throw newUninitializedMessageException(\n"
|
| " result).asInvalidProtocolBufferException();\n"
|
| " }\n"
|
| - " return buildPartial();\n"
|
| + " return result;\n"
|
| "}\n"
|
| "\n"
|
| "public $classname$ buildPartial() {\n"
|
| - " if (result == null) {\n"
|
| - " throw new IllegalStateException(\n"
|
| - " \"build() has already been called on this Builder.\");\n"
|
| - " }\n",
|
| + " $classname$ result = new $classname$(this);\n",
|
| "classname", ClassName(descriptor_));
|
| +
|
| printer->Indent();
|
|
|
| + // 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.
|
| + int totalBuilderBits = 0;
|
| + int totalMessageBits = 0;
|
| + for (int i = 0; i < descriptor_->field_count(); i++) {
|
| + const FieldGenerator& field = field_generators_.get(descriptor_->field(i));
|
| + totalBuilderBits += field.GetNumBitsForBuilder();
|
| + totalMessageBits += field.GetNumBitsForMessage();
|
| + }
|
| + int totalBuilderInts = (totalBuilderBits + 31) / 32;
|
| + int totalMessageInts = (totalMessageBits + 31) / 32;
|
| + 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));
|
| + }
|
| +
|
| printer->Outdent();
|
| +
|
| + if (HasDescriptorMethods(descriptor_)) {
|
| + printer->Print(
|
| + " onBuilt();\n");
|
| + }
|
| +
|
| printer->Print(
|
| - " $classname$ returnMe = result;\n"
|
| - " result = null;\n"
|
| - " return returnMe;\n"
|
| + " return result;\n"
|
| "}\n"
|
| "\n",
|
| "classname", ClassName(descriptor_));
|
| @@ -834,25 +997,31 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
|
| printer->Print(
|
| "case 0:\n" // zero signals EOF / limit reached
|
| " this.setUnknownFields(unknownFields.build());\n"
|
| + " $on_changed$\n"
|
| " return this;\n"
|
| "default: {\n"
|
| " if (!parseUnknownField(input, unknownFields,\n"
|
| " extensionRegistry, tag)) {\n"
|
| " this.setUnknownFields(unknownFields.build());\n"
|
| + " $on_changed$\n"
|
| " return this;\n" // it's an endgroup tag
|
| " }\n"
|
| " break;\n"
|
| - "}\n");
|
| + "}\n",
|
| + "on_changed", HasDescriptorMethods(descriptor_) ? "onChanged();" : "");
|
| } else {
|
| printer->Print(
|
| "case 0:\n" // zero signals EOF / limit reached
|
| + " $on_changed$\n"
|
| " return this;\n"
|
| "default: {\n"
|
| " if (!parseUnknownField(input, extensionRegistry, tag)) {\n"
|
| + " $on_changed$\n"
|
| " return this;\n" // it's an endgroup tag
|
| " }\n"
|
| " break;\n"
|
| - "}\n");
|
| + "}\n",
|
| + "on_changed", HasDescriptorMethods(descriptor_) ? "onChanged();" : "");
|
| }
|
|
|
| for (int i = 0; i < descriptor_->field_count(); i++) {
|
| @@ -898,16 +1067,33 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
|
| " }\n" // switch (tag)
|
| " }\n" // while (true)
|
| "}\n"
|
| +
|
| "\n");
|
| }
|
|
|
| // ===================================================================
|
|
|
| -void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
|
| +void MessageGenerator::GenerateIsInitialized(
|
| + io::Printer* printer, UseMemoization useMemoization) {
|
| + bool memoization = useMemoization == MEMOIZE;
|
| + if (memoization) {
|
| + // Memoizes whether the protocol buffer is fully initialized (has all
|
| + // required fields). -1 means not yet computed. 0 means false and 1 means
|
| + // true.
|
| + printer->Print(
|
| + "private byte memoizedIsInitialized = -1;\n");
|
| + }
|
| printer->Print(
|
| "public final boolean isInitialized() {\n");
|
| printer->Indent();
|
|
|
| + if (memoization) {
|
| + printer->Print(
|
| + "byte isInitialized = memoizedIsInitialized;\n"
|
| + "if (isInitialized != -1) return isInitialized == 1;\n"
|
| + "\n");
|
| + }
|
| +
|
| // Check that all required fields in this message are set.
|
| // TODO(kenton): We can optimize this when we switch to putting all the
|
| // "has" fields into a single bitfield.
|
| @@ -916,8 +1102,12 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
|
|
|
| if (field->is_required()) {
|
| printer->Print(
|
| - "if (!has$name$) return false;\n",
|
| - "name", UnderscoresToCapitalizedCamelCase(field));
|
| + "if (!has$name$()) {\n"
|
| + " $memoize$\n"
|
| + " return false;\n"
|
| + "}\n",
|
| + "name", UnderscoresToCapitalizedCamelCase(field),
|
| + "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
|
| }
|
| }
|
|
|
| @@ -929,25 +1119,37 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
|
| switch (field->label()) {
|
| case FieldDescriptor::LABEL_REQUIRED:
|
| printer->Print(
|
| - "if (!get$name$().isInitialized()) return false;\n",
|
| + "if (!get$name$().isInitialized()) {\n"
|
| + " $memoize$\n"
|
| + " return false;\n"
|
| + "}\n",
|
| "type", ClassName(field->message_type()),
|
| - "name", UnderscoresToCapitalizedCamelCase(field));
|
| + "name", UnderscoresToCapitalizedCamelCase(field),
|
| + "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
|
| break;
|
| case FieldDescriptor::LABEL_OPTIONAL:
|
| printer->Print(
|
| "if (has$name$()) {\n"
|
| - " if (!get$name$().isInitialized()) return false;\n"
|
| + " if (!get$name$().isInitialized()) {\n"
|
| + " $memoize$\n"
|
| + " return false;\n"
|
| + " }\n"
|
| "}\n",
|
| "type", ClassName(field->message_type()),
|
| - "name", UnderscoresToCapitalizedCamelCase(field));
|
| + "name", UnderscoresToCapitalizedCamelCase(field),
|
| + "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
|
| break;
|
| case FieldDescriptor::LABEL_REPEATED:
|
| printer->Print(
|
| - "for ($type$ element : get$name$List()) {\n"
|
| - " if (!element.isInitialized()) return false;\n"
|
| + "for (int i = 0; i < get$name$Count(); i++) {\n"
|
| + " if (!get$name$(i).isInitialized()) {\n"
|
| + " $memoize$\n"
|
| + " return false;\n"
|
| + " }\n"
|
| "}\n",
|
| "type", ClassName(field->message_type()),
|
| - "name", UnderscoresToCapitalizedCamelCase(field));
|
| + "name", UnderscoresToCapitalizedCamelCase(field),
|
| + "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
|
| break;
|
| }
|
| }
|
| @@ -955,10 +1157,20 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
|
|
|
| if (descriptor_->extension_range_count() > 0) {
|
| printer->Print(
|
| - "if (!extensionsAreInitialized()) return false;\n");
|
| + "if (!extensionsAreInitialized()) {\n"
|
| + " $memoize$\n"
|
| + " return false;\n"
|
| + "}\n",
|
| + "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
|
| }
|
|
|
| printer->Outdent();
|
| +
|
| + if (memoization) {
|
| + printer->Print(
|
| + " memoizedIsInitialized = 1;\n");
|
| + }
|
| +
|
| printer->Print(
|
| " return true;\n"
|
| "}\n"
|
| @@ -967,6 +1179,94 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
|
|
|
| // ===================================================================
|
|
|
| +void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) {
|
| + printer->Print(
|
| + "@java.lang.Override\n"
|
| + "public boolean equals(final Object obj) {\n");
|
| + printer->Indent();
|
| + printer->Print(
|
| + "if (obj == this) {\n"
|
| + " return true;\n"
|
| + "}\n"
|
| + "if (!(obj instanceof $classname$)) {\n"
|
| + " return super.equals(obj);\n"
|
| + "}\n"
|
| + "$classname$ other = ($classname$) obj;\n"
|
| + "\n",
|
| + "classname", ClassName(descriptor_));
|
| +
|
| + printer->Print("boolean result = true;\n");
|
| + for (int i = 0; i < descriptor_->field_count(); i++) {
|
| + const FieldDescriptor* field = descriptor_->field(i);
|
| + if (!field->is_repeated()) {
|
| + printer->Print(
|
| + "result = result && (has$name$() == other.has$name$());\n"
|
| + "if (has$name$()) {\n",
|
| + "name", UnderscoresToCapitalizedCamelCase(field));
|
| + printer->Indent();
|
| + }
|
| + field_generators_.get(field).GenerateEqualsCode(printer);
|
| + if (!field->is_repeated()) {
|
| + printer->Outdent();
|
| + printer->Print(
|
| + "}\n");
|
| + }
|
| + }
|
| + if (HasDescriptorMethods(descriptor_)) {
|
| + printer->Print(
|
| + "result = result &&\n"
|
| + " getUnknownFields().equals(other.getUnknownFields());\n");
|
| + if (descriptor_->extension_range_count() > 0) {
|
| + printer->Print(
|
| + "result = result &&\n"
|
| + " getExtensionFields().equals(other.getExtensionFields());\n");
|
| + }
|
| + }
|
| + printer->Print(
|
| + "return result;\n");
|
| + printer->Outdent();
|
| + printer->Print(
|
| + "}\n"
|
| + "\n");
|
| +
|
| + printer->Print(
|
| + "@java.lang.Override\n"
|
| + "public int hashCode() {\n");
|
| + printer->Indent();
|
| + printer->Print(
|
| + "int hash = 41;\n"
|
| + "hash = (19 * hash) + getDescriptorForType().hashCode();\n");
|
| + for (int i = 0; i < descriptor_->field_count(); i++) {
|
| + const FieldDescriptor* field = descriptor_->field(i);
|
| + if (!field->is_repeated()) {
|
| + printer->Print(
|
| + "if (has$name$()) {\n",
|
| + "name", UnderscoresToCapitalizedCamelCase(field));
|
| + printer->Indent();
|
| + }
|
| + field_generators_.get(field).GenerateHashCode(printer);
|
| + if (!field->is_repeated()) {
|
| + printer->Outdent();
|
| + printer->Print("}\n");
|
| + }
|
| + }
|
| + if (HasDescriptorMethods(descriptor_)) {
|
| + if (descriptor_->extension_range_count() > 0) {
|
| + printer->Print(
|
| + "hash = hashFields(hash, getExtensionFields());\n");
|
| + }
|
| + }
|
| + printer->Print(
|
| + "hash = (29 * hash) + getUnknownFields().hashCode();\n"
|
| + "return hash;\n");
|
| + printer->Outdent();
|
| + printer->Print(
|
| + "}\n"
|
| + "\n");
|
| +}
|
| +
|
| +// ===================================================================
|
| +
|
| void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) {
|
| for (int i = 0; i < descriptor_->extension_count(); i++) {
|
| ExtensionGenerator(descriptor_->extension(i))
|
|
|