diff options
Diffstat (limited to 'src/google/protobuf/compiler/java/java_message.cc')
-rw-r--r-- | src/google/protobuf/compiler/java/java_message.cc | 763 |
1 files changed, 497 insertions, 266 deletions
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index 9322e242..1cd08f7d 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -37,12 +37,16 @@ #include <algorithm> #include <google/protobuf/stubs/hash.h> #include <map> +#include <memory> #include <vector> +#include <google/protobuf/compiler/java/java_context.h> #include <google/protobuf/compiler/java/java_doc_comment.h> #include <google/protobuf/compiler/java/java_enum.h> #include <google/protobuf/compiler/java/java_extension.h> +#include <google/protobuf/compiler/java/java_generator_factory.h> #include <google/protobuf/compiler/java/java_helpers.h> +#include <google/protobuf/compiler/java/java_name_resolver.h> #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/descriptor.pb.h> @@ -59,107 +63,31 @@ using internal::WireFormat; using internal::WireFormatLite; namespace { - -void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) { - // Print the field's proto-syntax definition as a comment. We don't want to - // print group bodies so we cut off after the first line. - string def = field->DebugString(); - printer->Print("// $def$\n", - "def", def.substr(0, def.find_first_of('\n'))); +bool GenerateHasBits(const Descriptor* descriptor) { + return SupportFieldPresence(descriptor->file()) || + HasRepeatedFields(descriptor); } - -struct FieldOrderingByNumber { - inline bool operator()(const FieldDescriptor* a, - const FieldDescriptor* b) const { - return a->number() < b->number(); - } -}; - -struct ExtensionRangeOrdering { - bool operator()(const Descriptor::ExtensionRange* a, - const Descriptor::ExtensionRange* b) const { - return a->start < b->start; - } -}; - -// Sort the fields of the given Descriptor by number into a new[]'d array -// and return it. -const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { - const FieldDescriptor** fields = - new const FieldDescriptor*[descriptor->field_count()]; - for (int i = 0; i < descriptor->field_count(); i++) { - fields[i] = descriptor->field(i); - } - sort(fields, fields + descriptor->field_count(), - FieldOrderingByNumber()); - return fields; -} - -// Get an identifier that uniquely identifies this type within the file. -// This is used to declare static variables related to this type at the -// outermost file scope. -string UniqueFileScopeIdentifier(const Descriptor* descriptor) { - return "static_" + StringReplace(descriptor->full_name(), ".", "_", true); -} - -// Returns true if the message type has any required fields. If it doesn't, -// we can optimize out calls to its isInitialized() method. -// -// already_seen is used to avoid checking the same type multiple times -// (and also to protect against recursion). -static bool HasRequiredFields( - const Descriptor* type, - hash_set<const Descriptor*>* already_seen) { - if (already_seen->count(type) > 0) { - // The type is already in cache. This means that either: - // a. The type has no required fields. - // b. We are in the midst of checking if the type has required fields, - // somewhere up the stack. In this case, we know that if the type - // has any required fields, they'll be found when we return to it, - // and the whole call to HasRequiredFields() will return true. - // Therefore, we don't have to check if this type has required fields - // here. - return false; - } - already_seen->insert(type); - - // If the type has extensions, an extension with message type could contain - // required fields, so we have to be conservative and assume such an - // extension exists. - if (type->extension_range_count() > 0) return true; - - for (int i = 0; i < type->field_count(); i++) { - const FieldDescriptor* field = type->field(i); - if (field->is_required()) { - return true; - } - if (GetJavaType(field) == JAVATYPE_MESSAGE) { - if (HasRequiredFields(field->message_type(), already_seen)) { - return true; - } - } - } - - return false; -} - -static bool HasRequiredFields(const Descriptor* type) { - hash_set<const Descriptor*> already_seen; - return HasRequiredFields(type, &already_seen); -} - } // namespace // =================================================================== MessageGenerator::MessageGenerator(const Descriptor* descriptor) - : descriptor_(descriptor), - field_generators_(descriptor) { -} + : descriptor_(descriptor) {} MessageGenerator::~MessageGenerator() {} -void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { +// =================================================================== +// TODO(api): Move this class to a separate immutable_message.cc file. +ImmutableMessageGenerator::ImmutableMessageGenerator( + const Descriptor* descriptor, Context* context) + : MessageGenerator(descriptor), context_(context), + name_resolver_(context->GetNameResolver()), + field_generators_(descriptor, context_) { +} + +ImmutableMessageGenerator::~ImmutableMessageGenerator() {} + +void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) { if (HasDescriptorMethods(descriptor_)) { // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is // used in the construction of descriptors, we have a tricky bootstrapping @@ -171,12 +99,12 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { map<string, string> vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); vars["index"] = SimpleItoa(descriptor_->index()); - vars["classname"] = ClassName(descriptor_); + vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); if (descriptor_->containing_type() != NULL) { vars["parent"] = UniqueFileScopeIdentifier( descriptor_->containing_type()); } - if (descriptor_->file()->options().java_multiple_files()) { + if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { // We can only make these package-private since the classes that use them // are in separate files. vars["private"] = ""; @@ -186,31 +114,28 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { // The descriptor for this type. printer->Print(vars, - "$private$static com.google.protobuf.Descriptors.Descriptor\n" + "$private$static final com.google.protobuf.Descriptors.Descriptor\n" " internal_$identifier$_descriptor;\n"); // And the FieldAccessorTable. - printer->Print(vars, - "$private$static\n" - " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" - " internal_$identifier$_fieldAccessorTable;\n"); + GenerateFieldAccessorTable(printer); } // Generate static members for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? - MessageGenerator(descriptor_->nested_type(i)) + ImmutableMessageGenerator(descriptor_->nested_type(i), context_) .GenerateStaticVariables(printer); } } -void MessageGenerator::GenerateStaticVariableInitializers( +void ImmutableMessageGenerator::GenerateStaticVariableInitializers( io::Printer* printer) { if (HasDescriptorMethods(descriptor_)) { map<string, string> vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); vars["index"] = SimpleItoa(descriptor_->index()); - vars["classname"] = ClassName(descriptor_); + vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); if (descriptor_->containing_type() != NULL) { vars["parent"] = UniqueFileScopeIdentifier( descriptor_->containing_type()); @@ -228,56 +153,95 @@ void MessageGenerator::GenerateStaticVariableInitializers( } // And the FieldAccessorTable. - printer->Print(vars, - "internal_$identifier$_fieldAccessorTable = new\n" - " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" - " internal_$identifier$_descriptor,\n" - " new java.lang.String[] { "); - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print( - "\"$field_name$\", ", - "field_name", - UnderscoresToCapitalizedCamelCase(descriptor_->field(i))); - } - printer->Print( - "});\n"); + GenerateFieldAccessorTableInitializer(printer); } // Generate static member initializers for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? - MessageGenerator(descriptor_->nested_type(i)) + ImmutableMessageGenerator(descriptor_->nested_type(i), context_) .GenerateStaticVariableInitializers(printer); } } +void ImmutableMessageGenerator:: +GenerateFieldAccessorTable(io::Printer* printer) { + map<string, string> vars; + vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); + if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { + // We can only make these package-private since the classes that use them + // are in separate files. + vars["private"] = ""; + } else { + vars["private"] = "private "; + } + printer->Print(vars, + "$private$static\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internal_$identifier$_fieldAccessorTable;\n"); +} + +void ImmutableMessageGenerator:: +GenerateFieldAccessorTableInitializer(io::Printer* printer) { + printer->Print( + "internal_$identifier$_fieldAccessorTable = new\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" + " internal_$identifier$_descriptor,\n" + " new java.lang.String[] { ", + "identifier", + UniqueFileScopeIdentifier(descriptor_)); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + printer->Print( + "\"$field_name$\", ", + "field_name", info->capitalized_name); + } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof); + printer->Print( + "\"$oneof_name$\", ", + "oneof_name", info->capitalized_name); + } + printer->Print("});\n"); +} + // =================================================================== -void MessageGenerator::GenerateInterface(io::Printer* printer) { +void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { if (HasDescriptorMethods(descriptor_)) { printer->Print( "public interface $classname$OrBuilder extends\n" + " $extra_interfaces$\n" " com.google.protobuf.GeneratedMessage.\n" " ExtendableMessageOrBuilder<$classname$> {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } else { printer->Print( "public interface $classname$OrBuilder extends \n" + " $extra_interfaces$\n" " com.google.protobuf.GeneratedMessageLite.\n" " ExtendableMessageOrBuilder<$classname$> {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } } else { if (HasDescriptorMethods(descriptor_)) { printer->Print( - "public interface $classname$OrBuilder\n" - " extends com.google.protobuf.MessageOrBuilder {\n", + "public interface $classname$OrBuilder extends\n" + " $extra_interfaces$\n" + " com.google.protobuf.MessageOrBuilder {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } else { printer->Print( - "public interface $classname$OrBuilder\n" - " extends com.google.protobuf.MessageLiteOrBuilder {\n", + "public interface $classname$OrBuilder extends\n" + " $extra_interfaces$\n" + " com.google.protobuf.MessageLiteOrBuilder {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } } @@ -285,7 +249,6 @@ void MessageGenerator::GenerateInterface(io::Printer* printer) { 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); } @@ -296,10 +259,10 @@ void MessageGenerator::GenerateInterface(io::Printer* printer) { // =================================================================== -void MessageGenerator::Generate(io::Printer* printer) { +void ImmutableMessageGenerator::Generate(io::Printer* printer) { bool is_own_file = descriptor_->containing_type() == NULL && - descriptor_->file()->options().java_multiple_files(); + MultipleJavaFiles(descriptor_->file(), /* immutable = */ true); WriteMessageDocComment(printer, descriptor_); @@ -308,41 +271,51 @@ void MessageGenerator::Generate(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { if (HasDescriptorMethods(descriptor_)) { printer->Print( - "public $static$ final class $classname$ extends\n" + "public$static$final class $classname$ extends\n" " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" - " $classname$> implements $classname$OrBuilder {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + " $classname$> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "static", is_own_file ? " " : " static ", + "classname", descriptor_->name(), + "extra_interfaces", ExtraMessageInterfaces(descriptor_)); builder_type = strings::Substitute( "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>", - ClassName(descriptor_)); + name_resolver_->GetImmutableClassName(descriptor_)); } else { printer->Print( - "public $static$ final class $classname$ extends\n" + "public$static$final class $classname$ extends\n" " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" - " $classname$> implements $classname$OrBuilder {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + " $classname$> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "static", is_own_file ? " " : " static ", + "classname", descriptor_->name(), + "extra_interfaces", ExtraMessageInterfaces(descriptor_)); builder_type = strings::Substitute( "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>", - ClassName(descriptor_)); + name_resolver_->GetImmutableClassName(descriptor_)); } } else { if (HasDescriptorMethods(descriptor_)) { printer->Print( - "public $static$ final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage\n" - " implements $classname$OrBuilder {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + "public$static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "static", is_own_file ? " " : " static ", + "classname", descriptor_->name(), + "extra_interfaces", ExtraMessageInterfaces(descriptor_)); builder_type = "com.google.protobuf.GeneratedMessage.Builder<?>"; } else { printer->Print( - "public $static$ final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessageLite\n" - " implements $classname$OrBuilder {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + "public$static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "static", is_own_file ? " " : " static ", + "classname", descriptor_->name(), + "extra_interfaces", ExtraMessageInterfaces(descriptor_)); builder_type = "com.google.protobuf.GeneratedMessageLite.Builder"; } } @@ -359,8 +332,8 @@ void MessageGenerator::Generate(io::Printer* printer) { "}\n", "classname", descriptor_->name(), "buildertype", builder_type, - "set_unknown_fields", HasUnknownFields(descriptor_) - ? " this.unknownFields = builder.getUnknownFields();" : ""); + "set_unknown_fields", + " this.unknownFields = builder.getUnknownFields();"); printer->Print( // Used when constructing the default instance, which cannot be initialized // immediately because it may cyclically refer to other default instances. @@ -376,11 +349,12 @@ void MessageGenerator::Generate(io::Printer* printer) { "}\n" "\n", "classname", descriptor_->name(), - "set_default_unknown_fields", HasUnknownFields(descriptor_) + "set_default_unknown_fields", UseUnknownFieldSet(descriptor_) ? " this.unknownFields =" - " com.google.protobuf.UnknownFieldSet.getDefaultInstance(); " : ""); + " com.google.protobuf.UnknownFieldSet.getDefaultInstance(); " + : " this.unknownFields = com.google.protobuf.ByteString.EMPTY;"); - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { printer->Print( "private final com.google.protobuf.UnknownFieldSet unknownFields;\n" "" @@ -389,6 +363,9 @@ void MessageGenerator::Generate(io::Printer* printer) { " getUnknownFields() {\n" " return this.unknownFields;\n" "}\n"); + } else { + printer->Print( + "private final com.google.protobuf.ByteString unknownFields;\n"); } if (HasGeneratedMethods(descriptor_)) { @@ -400,30 +377,102 @@ void MessageGenerator::Generate(io::Printer* printer) { // Nested types for (int i = 0; i < descriptor_->enum_type_count(); i++) { - EnumGenerator(descriptor_->enum_type(i)).Generate(printer); + EnumGenerator(descriptor_->enum_type(i), true, context_) + .Generate(printer); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator messageGenerator(descriptor_->nested_type(i)); + ImmutableMessageGenerator messageGenerator( + descriptor_->nested_type(i), context_); messageGenerator.GenerateInterface(printer); messageGenerator.Generate(printer); } - // Integers for bit fields. - int totalBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - totalBits += field_generators_.get(descriptor_->field(i)) - .GetNumBitsForMessage(); + if (GenerateHasBits(descriptor_)) { + // 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)); + } } - int totalInts = (totalBits + 31) / 32; - for (int i = 0; i < totalInts; i++) { - printer->Print("private int $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); + + // oneof + map<string, string> vars; + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + vars["oneof_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name; + vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name; + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + // oneofCase_ and oneof_ + printer->Print(vars, + "private int $oneof_name$Case_ = 0;\n" + "private java.lang.Object $oneof_name$_;\n"); + // OneofCase enum + printer->Print(vars, + "public enum $oneof_capitalized_name$Case\n" + " implements com.google.protobuf.Internal.EnumLite {\n"); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "$field_name$($field_number$),\n", + "field_name", + ToUpper(field->name()), + "field_number", + SimpleItoa(field->number())); + } + printer->Print( + "$cap_oneof_name$_NOT_SET(0);\n", + "cap_oneof_name", + ToUpper(vars["oneof_name"])); + printer->Print(vars, + "private int value = 0;\n" + "private $oneof_capitalized_name$Case(int value) {\n" + " this.value = value;\n" + "}\n"); + printer->Print(vars, + "public static $oneof_capitalized_name$Case valueOf(int value) {\n" + " switch (value) {\n"); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + " case $field_number$: return $field_name$;\n", + "field_number", + SimpleItoa(field->number()), + "field_name", + ToUpper(field->name())); + } + printer->Print( + " case 0: return $cap_oneof_name$_NOT_SET;\n" + " default: throw new java.lang.IllegalArgumentException(\n" + " \"Value is undefined for this oneof enum.\");\n" + " }\n" + "}\n" + "public int getNumber() {\n" + " return this.value;\n" + "}\n", + "cap_oneof_name", ToUpper(vars["oneof_name"])); + printer->Outdent(); + printer->Print("};\n\n"); + // oneofCase() + printer->Print(vars, + "public $oneof_capitalized_name$Case\n" + "get$oneof_capitalized_name$Case() {\n" + " return $oneof_capitalized_name$Case.valueOf(\n" + " $oneof_name$Case_);\n" + "}\n" + "\n"); } // Fields for (int i = 0; i < descriptor_->field_count(); i++) { - PrintFieldComment(printer, descriptor_->field(i)); printer->Print("public static final int $constant_name$ = $number$;\n", "constant_name", FieldConstantName(descriptor_->field(i)), "number", SimpleItoa(descriptor_->field(i)->number())); @@ -436,9 +485,12 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print("private void initFields() {\n"); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateInitializationCode(printer); + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateInitializationCode(printer); + } } + printer->Outdent(); printer->Print("}\n"); @@ -451,6 +503,7 @@ void MessageGenerator::Generate(io::Printer* printer) { GenerateEqualsAndHashCode(printer); } + GenerateParseFromMethods(printer); GenerateBuilder(printer); @@ -471,7 +524,8 @@ void MessageGenerator::Generate(io::Printer* printer) { // 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); + ImmutableExtensionGenerator(descriptor_->extension(i), context_) + .Generate(printer); } printer->Outdent(); @@ -481,10 +535,10 @@ void MessageGenerator::Generate(io::Printer* printer) { // =================================================================== -void MessageGenerator:: +void ImmutableMessageGenerator:: GenerateMessageSerializationMethods(io::Printer* printer) { scoped_array<const FieldDescriptor*> sorted_fields( - SortFieldsByNumber(descriptor_)); + SortFieldsByNumber(descriptor_)); vector<const Descriptor::ExtensionRange*> sorted_extensions; for (int i = 0; i < descriptor_->extension_range_count(); ++i) { @@ -513,14 +567,14 @@ GenerateMessageSerializationMethods(io::Printer* printer) { " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" " newMessageSetExtensionWriter();\n", "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } else { printer->Print( "com.google.protobuf.GeneratedMessage$lite$\n" " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" " newExtensionWriter();\n", "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } } @@ -539,7 +593,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } } - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { if (descriptor_->options().message_set_wire_format()) { printer->Print( "getUnknownFields().writeAsMessageSetTo(output);\n"); @@ -547,6 +601,9 @@ GenerateMessageSerializationMethods(io::Printer* printer) { printer->Print( "getUnknownFields().writeTo(output);\n"); } + } else { + printer->Print( + "output.writeRawBytes(unknownFields);\n"); } printer->Outdent(); @@ -575,7 +632,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } } - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { if (descriptor_->options().message_set_wire_format()) { printer->Print( "size += getUnknownFields().getSerializedSizeAsMessageSet();\n"); @@ -583,6 +640,9 @@ GenerateMessageSerializationMethods(io::Printer* printer) { printer->Print( "size += getUnknownFields().getSerializedSize();\n"); } + } else { + printer->Print( + "size += unknownFields.size();\n"); } printer->Outdent(); @@ -602,7 +662,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) { "\n"); } -void MessageGenerator:: +void ImmutableMessageGenerator:: GenerateParseFromMethods(io::Printer* printer) { // Note: These are separate from GenerateMessageSerializationMethods() // because they need to be generated even for messages that are optimized @@ -661,15 +721,15 @@ GenerateParseFromMethods(io::Printer* printer) { " return PARSER.parseFrom(input, extensionRegistry);\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } -void MessageGenerator::GenerateSerializeOneField( +void ImmutableMessageGenerator::GenerateSerializeOneField( io::Printer* printer, const FieldDescriptor* field) { field_generators_.get(field).GenerateSerializationCode(printer); } -void MessageGenerator::GenerateSerializeOneExtensionRange( +void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( io::Printer* printer, const Descriptor::ExtensionRange* range) { printer->Print( "extensionWriter.writeUntil($end$, output);\n", @@ -678,7 +738,7 @@ void MessageGenerator::GenerateSerializeOneExtensionRange( // =================================================================== -void MessageGenerator::GenerateBuilder(io::Printer* printer) { +void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print( "public static Builder newBuilder() { return Builder.create(); }\n" "public Builder newBuilderForType() { return newBuilder(); }\n" @@ -687,7 +747,7 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { "}\n" "public Builder toBuilder() { return newBuilder(this); }\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); if (HasNestedBuilders(descriptor_)) { printer->Print( @@ -706,29 +766,40 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" - " $classname$, Builder> implements $classname$OrBuilder {\n", - "classname", ClassName(descriptor_)); + " $classname$, Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); } else { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n" - " $classname$, Builder> implements $classname$OrBuilder {\n", - "classname", ClassName(descriptor_)); + " $classname$, Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); } } else { if (HasDescriptorMethods(descriptor_)) { printer->Print( "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage.Builder<Builder>\n" - " implements $classname$OrBuilder {\n", - "classname", ClassName(descriptor_)); + " com.google.protobuf.GeneratedMessage.Builder<Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); } else { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessageLite.Builder<\n" " $classname$, Builder>\n" - " implements $classname$OrBuilder {\n", - "classname", ClassName(descriptor_)); + " implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); } } printer->Indent(); @@ -741,21 +812,54 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { 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(); + // oneof + map<string, string> vars; + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + vars["oneof_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name; + vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name; + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + // oneofCase_ and oneof_ + printer->Print(vars, + "private int $oneof_name$Case_ = 0;\n" + "private java.lang.Object $oneof_name$_;\n"); + // oneofCase() and clearOneof() + printer->Print(vars, + "public $oneof_capitalized_name$Case\n" + " get$oneof_capitalized_name$Case() {\n" + " return $oneof_capitalized_name$Case.valueOf(\n" + " $oneof_name$Case_);\n" + "}\n" + "\n" + "public Builder clear$oneof_capitalized_name$() {\n" + " $oneof_name$Case_ = 0;\n" + " $oneof_name$_ = null;\n"); + if (HasDescriptorMethods(descriptor_)) { + printer->Print(" onChanged();\n"); + } + printer->Print( + " return this;\n" + "}\n" + "\n"); } - 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)); + + if (GenerateHasBits(descriptor_)) { + // 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)); field_generators_.get(descriptor_->field(i)) .GenerateBuilderMembers(printer); } @@ -769,7 +873,8 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print("}\n"); } -void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) { +void ImmutableMessageGenerator:: +GenerateDescriptorMethods(io::Printer* printer) { if (HasDescriptorMethods(descriptor_)) { if (!descriptor_->options().no_standard_descriptor_accessor()) { printer->Print( @@ -778,7 +883,7 @@ void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) { " return $fileclass$.internal_$identifier$_descriptor;\n" "}\n" "\n", - "fileclass", ClassName(descriptor_->file()), + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), "identifier", UniqueFileScopeIdentifier(descriptor_)); } printer->Print( @@ -789,22 +894,23 @@ void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) { " $classname$.class, $classname$.Builder.class);\n" "}\n" "\n", - "classname", ClassName(descriptor_), - "fileclass", ClassName(descriptor_->file()), + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), "identifier", UniqueFileScopeIdentifier(descriptor_)); } } // =================================================================== -void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { +void ImmutableMessageGenerator:: +GenerateCommonBuilderMethods(io::Printer* printer) { printer->Print( "// Construct using $classname$.newBuilder()\n" "private Builder() {\n" " maybeForceBuilderInitialization();\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); if (HasDescriptorMethods(descriptor_)) { printer->Print( @@ -813,7 +919,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " super(parent);\n" " maybeForceBuilderInitialization();\n" "}\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } @@ -825,8 +931,10 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { printer->Indent(); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateFieldBuilderInitializationCode(printer); + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateFieldBuilderInitializationCode(printer); + } } printer->Outdent(); printer->Outdent(); @@ -847,13 +955,23 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { "\n" "public Builder clear() {\n" " super.clear();\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateBuilderClearCode(printer); + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateBuilderClearCode(printer); + } + } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "$oneof_name$Case_ = 0;\n" + "$oneof_name$_ = null;\n", + "oneof_name", context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name); } printer->Outdent(); @@ -866,7 +984,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " return create().mergeFrom(buildPartial());\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); if (HasDescriptorMethods(descriptor_)) { printer->Print( "public com.google.protobuf.Descriptors.Descriptor\n" @@ -874,7 +992,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " return $fileclass$.internal_$identifier$_descriptor;\n" "}\n" "\n", - "fileclass", ClassName(descriptor_->file()), + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), "identifier", UniqueFileScopeIdentifier(descriptor_)); } printer->Print( @@ -882,7 +1000,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " return $classname$.getDefaultInstance();\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); // ----------------------------------------------------------------- @@ -897,30 +1015,34 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { "\n" "public $classname$ buildPartial() {\n" " $classname$ result = new $classname$(this);\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(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)); + 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; - 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)); + + if (GenerateHasBits(descriptor_)) { + // 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. @@ -928,10 +1050,18 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { 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)); + if (GenerateHasBits(descriptor_)) { + // 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 (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n", + "oneof_name", context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name); } printer->Outdent(); @@ -945,7 +1075,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " return result;\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); // ----------------------------------------------------------------- @@ -963,7 +1093,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " }\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } printer->Print( @@ -971,11 +1101,48 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { // Optimization: If other is the default instance, we know none of its // fields are set so we can skip the merge. " if (other == $classname$.getDefaultInstance()) return this;\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)).GenerateMergingCode(printer); + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get( + descriptor_->field(i)).GenerateMergingCode(printer); + } + } + + // Merge oneof fields. + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + printer->Print( + "switch (other.get$oneof_capitalized_name$Case()) {\n", + "oneof_capitalized_name", + context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "case $field_name$: {\n", + "field_name", + ToUpper(field->name())); + printer->Indent(); + field_generators_.get(field).GenerateMergingCode(printer); + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } + printer->Print( + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name)); + printer->Outdent(); + printer->Print( + "}\n"); } printer->Outdent(); @@ -986,9 +1153,13 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " this.mergeExtensionFields(other);\n"); } - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { printer->Print( " this.mergeUnknownFields(other.getUnknownFields());\n"); + } else { + printer->Print( + " setUnknownFields(\n" + " getUnknownFields().concat(other.unknownFields));\n"); } printer->Print( @@ -1000,7 +1171,8 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { // =================================================================== -void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { +void ImmutableMessageGenerator:: +GenerateBuilderParsingMethods(io::Printer* printer) { printer->Print( "public Builder mergeFrom(\n" " com.google.protobuf.CodedInputStream input,\n" @@ -1019,12 +1191,12 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { " }\n" " return this;\n" "}\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } // =================================================================== -void MessageGenerator::GenerateIsInitialized( +void ImmutableMessageGenerator::GenerateIsInitialized( io::Printer* printer, UseMemoization useMemoization) { bool memoization = useMemoization == MEMOIZE; if (memoization) { @@ -1039,9 +1211,11 @@ void MessageGenerator::GenerateIsInitialized( printer->Indent(); if (memoization) { + // Don't directly compare to -1 to avoid an Android x86 JIT bug. printer->Print( "byte isInitialized = memoizedIsInitialized;\n" - "if (isInitialized != -1) return isInitialized == 1;\n" + "if (isInitialized == 1) return true;\n" + "if (isInitialized == 0) return false;\n" "\n"); } @@ -1050,6 +1224,7 @@ void MessageGenerator::GenerateIsInitialized( // "has" fields into a single bitfield. for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); if (field->is_required()) { printer->Print( @@ -1057,7 +1232,7 @@ void MessageGenerator::GenerateIsInitialized( " $memoize$\n" " return false;\n" "}\n", - "name", UnderscoresToCapitalizedCamelCase(field), + "name", info->capitalized_name, "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); } } @@ -1065,6 +1240,7 @@ void MessageGenerator::GenerateIsInitialized( // Now check that all embedded messages are initialized. for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); if (GetJavaType(field) == JAVATYPE_MESSAGE && HasRequiredFields(field->message_type())) { switch (field->label()) { @@ -1074,8 +1250,9 @@ void MessageGenerator::GenerateIsInitialized( " $memoize$\n" " return false;\n" "}\n", - "type", ClassName(field->message_type()), - "name", UnderscoresToCapitalizedCamelCase(field), + "type", name_resolver_->GetImmutableClassName( + field->message_type()), + "name", info->capitalized_name, "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); break; case FieldDescriptor::LABEL_OPTIONAL: @@ -1086,8 +1263,9 @@ void MessageGenerator::GenerateIsInitialized( " return false;\n" " }\n" "}\n", - "type", ClassName(field->message_type()), - "name", UnderscoresToCapitalizedCamelCase(field), + "type", name_resolver_->GetImmutableClassName( + field->message_type()), + "name", info->capitalized_name, "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); break; case FieldDescriptor::LABEL_REPEATED: @@ -1098,8 +1276,9 @@ void MessageGenerator::GenerateIsInitialized( " return false;\n" " }\n" "}\n", - "type", ClassName(field->message_type()), - "name", UnderscoresToCapitalizedCamelCase(field), + "type", name_resolver_->GetImmutableClassName( + field->message_type()), + "name", info->capitalized_name, "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); break; } @@ -1130,7 +1309,21 @@ void MessageGenerator::GenerateIsInitialized( // =================================================================== -void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) { +namespace { +bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) { + if (field->is_repeated()) { + return false; + } + if (SupportFieldPresence(field->file())) { + return true; + } + return GetJavaType(field) == JAVATYPE_MESSAGE && + field->containing_oneof() == NULL; +} +} // namespace + +void ImmutableMessageGenerator:: +GenerateEqualsAndHashCode(io::Printer* printer) { printer->Print( "@java.lang.Override\n" "public boolean equals(final java.lang.Object obj) {\n"); @@ -1144,20 +1337,22 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) { "}\n" "$classname$ other = ($classname$) obj;\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(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()) { + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); + if (check_has_bits) { printer->Print( "result = result && (has$name$() == other.has$name$());\n" "if (has$name$()) {\n", - "name", UnderscoresToCapitalizedCamelCase(field)); + "name", info->capitalized_name); printer->Indent(); } field_generators_.get(field).GenerateEqualsCode(printer); - if (!field->is_repeated()) { + if (check_has_bits) { printer->Outdent(); printer->Print( "}\n"); @@ -1181,8 +1376,6 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) { "\n"); printer->Print( - "private int memoizedHashCode = 0;\n"); - printer->Print( "@java.lang.Override\n" "public int hashCode() {\n"); printer->Indent(); @@ -1194,18 +1387,29 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) { printer->Outdent(); printer->Print( "}\n" - "int hash = 41;\n" - "hash = (19 * hash) + getDescriptorForType().hashCode();\n"); + "int hash = 41;\n"); + + if (HasDescriptorMethods(descriptor_)) { + printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n"); + } else { + // Include the hash of the class so that two objects with different types + // but the same field values will probably have different hashes. + printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } + for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (!field->is_repeated()) { + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); + if (check_has_bits) { printer->Print( "if (has$name$()) {\n", - "name", UnderscoresToCapitalizedCamelCase(field)); + "name", info->capitalized_name); printer->Indent(); } field_generators_.get(field).GenerateHashCode(printer); - if (!field->is_repeated()) { + if (check_has_bits) { printer->Outdent(); printer->Print("}\n"); } @@ -1216,8 +1420,15 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) { "hash = hashFields(hash, getExtensionFields());\n"); } } + + if (UseUnknownFieldSet(descriptor_)) { + printer->Print( + "hash = (29 * hash) + getUnknownFields().hashCode();\n"); + } else { + printer->Print( + "hash = (29 * hash) + unknownFields.hashCode();\n"); + } printer->Print( - "hash = (29 * hash) + getUnknownFields().hashCode();\n" "memoizedHashCode = hash;\n" "return hash;\n"); printer->Outdent(); @@ -1228,20 +1439,22 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) { // =================================================================== -void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { +void ImmutableMessageGenerator:: +GenerateExtensionRegistrationCode(io::Printer* printer) { for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator(descriptor_->extension(i)) + ImmutableExtensionGenerator(descriptor_->extension(i), context_) .GenerateRegistrationCode(printer); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator(descriptor_->nested_type(i)) + ImmutableMessageGenerator(descriptor_->nested_type(i), context_) .GenerateExtensionRegistrationCode(printer); } } // =================================================================== -void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) { +void ImmutableMessageGenerator:: +GenerateParsingConstructor(io::Printer* printer) { scoped_array<const FieldDescriptor*> sorted_fields( SortFieldsByNumber(descriptor_)); @@ -1260,7 +1473,8 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) { // Use builder bits to track mutable repeated fields. int totalBuilderBits = 0; for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldGenerator& field = field_generators_.get(descriptor_->field(i)); + const ImmutableFieldGenerator& field = + field_generators_.get(descriptor_->field(i)); totalBuilderBits += field.GetNumBitsForBuilder(); } int totalBuilderInts = (totalBuilderBits + 31) / 32; @@ -1269,10 +1483,17 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) { "bit_field_name", GetBitFieldName(i)); } - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { printer->Print( "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" " com.google.protobuf.UnknownFieldSet.newBuilder();\n"); + } else { + printer->Print( + "com.google.protobuf.ByteString.Output unknownFieldsOutput =\n" + " com.google.protobuf.ByteString.newOutput();\n" + "com.google.protobuf.CodedOutputStream unknownFieldsCodedOutput =\n" + " com.google.protobuf.CodedOutputStream.newInstance(\n" + " unknownFieldsOutput);\n"); } printer->Print( @@ -1300,8 +1521,8 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) { " }\n" " break;\n" "}\n", - "unknown_fields", HasUnknownFields(descriptor_) - ? " unknownFields," : ""); + "unknown_fields", UseUnknownFieldSet(descriptor_) + ? " unknownFields," : " unknownFieldsCodedOutput,"); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = sorted_fields[i]; @@ -1362,9 +1583,18 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) { } // Make unknown fields immutable. - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { printer->Print( "this.unknownFields = unknownFields.build();\n"); + } else { + printer->Print( + "try {\n" + " unknownFieldsCodedOutput.flush();\n" + "} catch (java.io.IOException e) {\n" + "// Should not happen\n" + "} finally {\n" + " unknownFields = unknownFieldsOutput.toByteString();\n" + "}\n"); } // Make extensions immutable. @@ -1379,7 +1609,7 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) { } // =================================================================== -void MessageGenerator::GenerateParser(io::Printer* printer) { +void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { printer->Print( "public static com.google.protobuf.Parser<$classname$> PARSER =\n" " new com.google.protobuf.AbstractParser<$classname$>() {\n", @@ -1429,6 +1659,7 @@ void MessageGenerator::GenerateParser(io::Printer* printer) { "classname", descriptor_->name()); } + } // namespace java } // namespace compiler } // namespace protobuf |