diff options
Diffstat (limited to 'src/google/protobuf/compiler/java/java_message_lite.cc')
-rw-r--r-- | src/google/protobuf/compiler/java/java_message_lite.cc | 823 |
1 files changed, 410 insertions, 413 deletions
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc index 94ed2c39..3a512e8d 100644 --- a/src/google/protobuf/compiler/java/java_message_lite.cc +++ b/src/google/protobuf/compiler/java/java_message_lite.cc @@ -38,26 +38,24 @@ #include <google/protobuf/stubs/hash.h> #include <map> #include <memory> -#ifndef _SHARED_PTR_H -#include <google/protobuf/stubs/shared_ptr.h> -#endif #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_lite.h> -#include <google/protobuf/compiler/java/java_extension.h> +#include <google/protobuf/compiler/java/java_extension_lite.h> #include <google/protobuf/compiler/java/java_generator_factory.h> #include <google/protobuf/compiler/java/java_helpers.h> #include <google/protobuf/compiler/java/java_message_builder.h> #include <google/protobuf/compiler/java/java_message_builder_lite.h> #include <google/protobuf/compiler/java/java_name_resolver.h> +#include <google/protobuf/descriptor.pb.h> #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/printer.h> -#include <google/protobuf/descriptor.pb.h> #include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/substitute.h> +#include <google/protobuf/stubs/strutil.h> + namespace google { namespace protobuf { @@ -68,6 +66,14 @@ using internal::WireFormat; using internal::WireFormatLite; namespace { +bool EnableExperimentalRuntimeForLite() { +#ifdef PROTOBUF_EXPERIMENT + return PROTOBUF_EXPERIMENT; +#else // PROTOBUF_EXPERIMENT + return false; +#endif // !PROTOBUF_EXPERIMENT +} + bool GenerateHasBits(const Descriptor* descriptor) { return SupportFieldPresence(descriptor->file()) || HasRepeatedFields(descriptor); @@ -87,19 +93,20 @@ ImmutableMessageLiteGenerator::ImmutableMessageLiteGenerator( : MessageGenerator(descriptor), context_(context), name_resolver_(context->GetNameResolver()), field_generators_(descriptor, context_) { - GOOGLE_CHECK_EQ( - FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for()); + GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite())) + << "Generator factory error: A lite message generator is used to " + "generate non-lite messages."; } ImmutableMessageLiteGenerator::~ImmutableMessageLiteGenerator() {} void ImmutableMessageLiteGenerator::GenerateStaticVariables( - io::Printer* printer) { + io::Printer* printer, int* bytecode_estimate) { // Generate static members for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_) - .GenerateStaticVariables(printer); + .GenerateStaticVariables(printer, bytecode_estimate); } } @@ -119,23 +126,32 @@ int ImmutableMessageLiteGenerator::GenerateStaticVariableInitializers( // =================================================================== void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) { + MaybePrintGeneratedAnnotation(context_, printer, descriptor_, + /* immutable = */ true, "OrBuilder"); if (descriptor_->extension_range_count() > 0) { printer->Print( - "public interface $classname$OrBuilder extends \n" - " $extra_interfaces$\n" - " com.google.protobuf.GeneratedMessageLite.\n" - " ExtendableMessageOrBuilder<\n" - " $classname$, $classname$.Builder> {\n", - "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name()); + "$deprecation$public interface ${$$classname$OrBuilder$}$ extends \n" + " $extra_interfaces$\n" + " com.google.protobuf.GeneratedMessageLite.\n" + " ExtendableMessageOrBuilder<\n" + " $classname$, $classname$.Builder> {\n", + "deprecation", descriptor_->options().deprecated() ? + "@java.lang.Deprecated " : "", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), + "classname", descriptor_->name(), + "{", "", "}", ""); } else { printer->Print( - "public interface $classname$OrBuilder extends\n" - " $extra_interfaces$\n" - " com.google.protobuf.MessageLiteOrBuilder {\n", - "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name()); + "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n" + " $extra_interfaces$\n" + " com.google.protobuf.MessageLiteOrBuilder {\n", + "deprecation", descriptor_->options().deprecated() ? + "@java.lang.Deprecated " : "", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), + "classname", descriptor_->name(), + "{", "", "}", ""); } + printer->Annotate("{", "}", descriptor_); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { @@ -162,22 +178,25 @@ void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) { // =================================================================== void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { - bool is_own_file = - descriptor_->containing_type() == NULL && - MultipleJavaFiles(descriptor_->file(), /* immutable = */ true); + bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true); - map<string, string> variables; + std::map<string, string> variables; variables["static"] = is_own_file ? " " : " static "; variables["classname"] = descriptor_->name(); variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_); + variables["deprecation"] = descriptor_->options().deprecated() + ? "@java.lang.Deprecated " : ""; WriteMessageDocComment(printer, descriptor_); + MaybePrintGeneratedAnnotation(context_, printer, descriptor_, + /* immutable = */ true); + // The builder_type stores the super type name of the nested Builder class. string builder_type; if (descriptor_->extension_range_count() > 0) { printer->Print(variables, - "public $static$final class $classname$ extends\n" + "$deprecation$public $static$final class $classname$ extends\n" " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" " $classname$, $classname$.Builder> implements\n" " $extra_interfaces$\n" @@ -187,7 +206,7 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { name_resolver_->GetImmutableClassName(descriptor_)); } else { printer->Print(variables, - "public $static$final class $classname$ extends\n" + "$deprecation$public $static$final class $classname$ extends\n" " com.google.protobuf.GeneratedMessageLite<\n" " $classname$, $classname$.Builder> implements\n" " $extra_interfaces$\n" @@ -197,7 +216,7 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { } printer->Indent(); - GenerateParsingConstructor(printer); + GenerateConstructor(printer); // Nested types for (int i = 0; i < descriptor_->enum_type_count(); i++) { @@ -229,13 +248,13 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { } // oneof - map<string, string> vars; + std::map<string, string> vars; for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - vars["oneof_name"] = context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name; + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name; vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name; - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + oneof)->capitalized_name; + vars["oneof_index"] = SimpleItoa(oneof->index()); // oneofCase_ and oneof_ printer->Print(vars, "private int $oneof_name$Case_ = 0;\n" @@ -245,8 +264,8 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { "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); + for (int j = 0; j < oneof->field_count(); j++) { + const FieldDescriptor* field = oneof->field(j); printer->Print( "$field_name$($field_number$),\n", "field_name", @@ -259,15 +278,23 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { "cap_oneof_name", ToUpper(vars["oneof_name"])); printer->Print(vars, - "private int value = 0;\n" + "private final int value;\n" "private $oneof_capitalized_name$Case(int value) {\n" " this.value = value;\n" "}\n"); printer->Print(vars, + "/**\n" + " * @deprecated Use {@link #forNumber(int)} instead.\n" + " */\n" + "@java.lang.Deprecated\n" "public static $oneof_capitalized_name$Case valueOf(int value) {\n" + " return forNumber(value);\n" + "}\n" + "\n" + "public static $oneof_capitalized_name$Case forNumber(int value) {\n" " switch (value) {\n"); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + for (int j = 0; j < oneof->field_count(); j++) { + const FieldDescriptor* field = oneof->field(j); printer->Print( " case $field_number$: return $field_name$;\n", "field_number", @@ -277,10 +304,10 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { } 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" + " default: return null;\n" " }\n" "}\n" + "@java.lang.Override\n" "public int getNumber() {\n" " return this.value;\n" "}\n", @@ -289,9 +316,10 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Print("};\n\n"); // oneofCase() printer->Print(vars, + "@java.lang.Override\n" "public $oneof_capitalized_name$Case\n" "get$oneof_capitalized_name$Case() {\n" - " return $oneof_capitalized_name$Case.valueOf(\n" + " return $oneof_capitalized_name$Case.forNumber(\n" " $oneof_name$Case_);\n" "}\n" "\n" @@ -311,77 +339,81 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Print("\n"); } - GenerateMessageSerializationMethods(printer); - - if (HasEqualsAndHashCode(descriptor_)) { - GenerateEqualsAndHashCode(printer); + if (!EnableExperimentalRuntime(context_)) { + GenerateMessageSerializationMethods(printer); } - GenerateParseFromMethods(printer); GenerateBuilder(printer); if (HasRequiredFields(descriptor_)) { // Memoizes whether the protocol buffer is fully initialized (has all - // required fields). -1 means not yet computed. 0 means false and 1 means - // true. + // required fields). 0 means false, 1 means true, and all other values + // mean not yet computed. printer->Print( - "private byte memoizedIsInitialized = -1;\n"); + "private byte memoizedIsInitialized = 2;\n"); } printer->Print( - "protected final Object dynamicMethod(\n" - " com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n" - " Object arg0, Object arg1) {\n" - " switch (method) {\n" - " case PARSE_PARTIAL_FROM: {\n" - " return new $classname$(" - " (com.google.protobuf.CodedInputStream) arg0,\n" - " (com.google.protobuf.ExtensionRegistryLite) arg1);\n" - " }\n" - " case NEW_INSTANCE: {\n" - " return new $classname$(\n" - " com.google.protobuf.Internal.EMPTY_CODED_INPUT_STREAM,\n" - " com.google.protobuf.ExtensionRegistryLite\n" - " .getEmptyRegistry());\n" - " }\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "@java.lang.Override\n" + "@java.lang.SuppressWarnings({\"unchecked\", \"fallthrough\"})\n" + "protected final java.lang.Object dynamicMethod(\n" + " com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n" + " java.lang.Object arg0, java.lang.Object arg1) {\n" + " switch (method) {\n" + " case NEW_MUTABLE_INSTANCE: {\n" + " return new $classname$();\n" + " }\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Indent(); printer->Indent(); printer->Print( - "case IS_INITIALIZED: {\n"); + "case NEW_BUILDER: {\n"); + printer->Indent(); - GenerateDynamicMethodIsInitialized(printer); + GenerateDynamicMethodNewBuilder(printer); printer->Outdent(); - printer->Print( - "}\n" - "case MAKE_IMMUTABLE: {\n"); + if (!EnableExperimentalRuntimeForLite()) { + printer->Print( + "}\n" + "case IS_INITIALIZED: {\n"); + printer->Indent(); + GenerateDynamicMethodIsInitialized(printer); + printer->Outdent(); - printer->Indent(); - GenerateDynamicMethodMakeImmutable(printer); - printer->Outdent(); + printer->Print("}\n"); - printer->Print( - "}\n" - "case NEW_BUILDER: {\n"); + printer->Print( + "case MAKE_IMMUTABLE: {\n"); - printer->Indent(); - GenerateDynamicMethodNewBuilder(printer); - printer->Outdent(); + printer->Indent(); + GenerateDynamicMethodMakeImmutable(printer); + printer->Outdent(); - printer->Print( - "}\n" - "case MERGE_FROM: {\n"); + printer->Print( + "}\n" + "case VISIT: {\n"); + + printer->Indent(); + GenerateDynamicMethodVisit(printer); + printer->Outdent(); + + printer->Print( + "}\n" + "case MERGE_FROM_STREAM: {\n"); + + printer->Indent(); + GenerateDynamicMethodMergeFromStream(printer); + printer->Outdent(); + } - printer->Indent(); - GenerateDynamicMethodMergeFrom(printer); - printer->Outdent(); printer->Print( "}\n" + "// fall through\n" "case GET_DEFAULT_INSTANCE: {\n" " return DEFAULT_INSTANCE;\n" "}\n" @@ -390,20 +422,46 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { // manipulating static fields but that has exceptional cost on Android as // it will generate an extra class for every message. Instead, use the // double-check locking pattern which works just as well. - " if (PARSER == null) {" + // + // The "parser" temporary mirrors the "PARSER" field to eliminate a read + // at the final return statement. + " com.google.protobuf.Parser<$classname$> parser = PARSER;\n" + " if (parser == null) {\n" " synchronized ($classname$.class) {\n" - " if (PARSER == null) {\n" - " PARSER = new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n" + " parser = PARSER;\n" + " if (parser == null) {\n" + " parser = new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n" + " PARSER = parser;\n" " }\n" " }\n" " }\n" - " return PARSER;\n" - "}\n", + " return parser;\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Outdent(); - printer->Outdent(); + if (HasRequiredFields(descriptor_)) { + printer->Print( + "}\n" + "case GET_MEMOIZED_IS_INITIALIZED: {\n" + " return memoizedIsInitialized;\n" + "}\n" + "case SET_MEMOIZED_IS_INITIALIZED: {\n" + " memoizedIsInitialized = (byte) (arg0 == null ? 0 : 1);\n" + " return null;\n" + "}\n"); + } else { + printer->Print( + "}\n" + "case GET_MEMOIZED_IS_INITIALIZED: {\n" + " return (byte) 1;\n" + "}\n" + "case SET_MEMOIZED_IS_INITIALIZED: {\n" + " return null;\n" + "}\n"); + } + + printer->Outdent(); printer->Print( " }\n" " throw new UnsupportedOperationException();\n" @@ -425,14 +483,24 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Print( "static {\n" - " DEFAULT_INSTANCE = new $classname$(\n" - " com.google.protobuf.Internal\n" - " .EMPTY_CODED_INPUT_STREAM,\n" - " com.google.protobuf.ExtensionRegistryLite\n" - " .getEmptyRegistry());\n" + " // New instances are implicitly immutable so no need to make\n" + " // immutable.\n" + " DEFAULT_INSTANCE = new $classname$();\n" "}\n" "\n", "classname", descriptor_->name()); + if (EnableExperimentalRuntimeForLite()) { + // Register the default instance in a map. This map will be used by + // experimental runtime to lookup default instance given a class instance + // without using Java reflection. + printer->Print( + "static {\n" + " com.google.protobuf.GeneratedMessageLite.registerDefaultInstance(\n" + " $classname$.class, DEFAULT_INSTANCE);\n" + "}\n", + "classname", descriptor_->name()); + } + printer->Print( "public static $classname$ getDefaultInstance() {\n" " return DEFAULT_INSTANCE;\n" @@ -440,28 +508,45 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); + // 'of' method for Wrappers + if (IsWrappersProtoFile(descriptor_->file())) { + printer->Print( + "public static $classname$ of($field_type$ value) {\n" + " return newBuilder().setValue(value).build();\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "field_type", PrimitiveTypeName(GetJavaType(descriptor_->field(0)))); + } + GenerateParser(printer); // Extensions must be declared after the DEFAULT_INSTANCE is initialized // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve // the outer class's FileDescriptor. for (int i = 0; i < descriptor_->extension_count(); i++) { - ImmutableExtensionGenerator(descriptor_->extension(i), context_) + ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_) .Generate(printer); } + printer->Outdent(); printer->Print("}\n\n"); } + // =================================================================== void ImmutableMessageLiteGenerator:: GenerateMessageSerializationMethods(io::Printer* printer) { - google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields( + if (EnableExperimentalRuntimeForLite()) { + return; + } + + std::unique_ptr<const FieldDescriptor * []> sorted_fields( SortFieldsByNumber(descriptor_)); - vector<const Descriptor::ExtensionRange*> sorted_extensions; + std::vector<const Descriptor::ExtensionRange*> sorted_extensions; for (int i = 0; i < descriptor_->extension_range_count(); ++i) { sorted_extensions.push_back(descriptor_->extension_range(i)); } @@ -469,42 +554,41 @@ GenerateMessageSerializationMethods(io::Printer* printer) { ExtensionRangeOrdering()); printer->Print( + "@java.lang.Override\n" "public void writeTo(com.google.protobuf.CodedOutputStream output)\n" " throws java.io.IOException {\n"); printer->Indent(); if (HasPackedFields(descriptor_)) { // writeTo(CodedOutputStream output) might be invoked without // getSerializedSize() ever being called, but we need the memoized - // sizes in case this message has packed fields. Rather than emit checks for - // each packed field, just call getSerializedSize() up front. - // In most cases, getSerializedSize() will have already been called anyway - // by one of the wrapper writeTo() methods, making this call cheap. - printer->Print( - "getSerializedSize();\n"); + // sizes in case this message has packed fields. Rather than emit checks + // for each packed field, just call getSerializedSize() up front. In most + // cases, getSerializedSize() will have already been called anyway by one + // of the wrapper writeTo() methods, making this call cheap. + printer->Print("getSerializedSize();\n"); } if (descriptor_->extension_range_count() > 0) { if (descriptor_->options().message_set_wire_format()) { printer->Print( - "com.google.protobuf.GeneratedMessageLite\n" - " .ExtendableMessage<$classname$, $classname$.Builder>\n" - " .ExtensionWriter extensionWriter =\n" - " newMessageSetExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "com.google.protobuf.GeneratedMessageLite\n" + " .ExtendableMessage<$classname$, $classname$.Builder>\n" + " .ExtensionWriter extensionWriter =\n" + " newMessageSetExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } else { printer->Print( - "com.google.protobuf.GeneratedMessageLite\n" - " .ExtendableMessage<$classname$, $classname$.Builder>\n" - " .ExtensionWriter extensionWriter =\n" - " newExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "com.google.protobuf.GeneratedMessageLite\n" + " .ExtendableMessage<$classname$, $classname$.Builder>\n" + " .ExtensionWriter extensionWriter =\n" + " newExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } } // Merge the fields and the extension ranges, both sorted by field number. for (int i = 0, j = 0; - i < descriptor_->field_count() || j < sorted_extensions.size(); - ) { + i < descriptor_->field_count() || j < sorted_extensions.size();) { if (i == descriptor_->field_count()) { GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]); } else if (j == sorted_extensions.size()) { @@ -516,21 +600,24 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } } - if (PreserveUnknownFields(descriptor_)) { - printer->Print( - "unknownFields.writeTo(output);\n"); + if (descriptor_->options().message_set_wire_format()) { + printer->Print("unknownFields.writeAsMessageSetTo(output);\n"); + } else { + printer->Print("unknownFields.writeTo(output);\n"); } printer->Outdent(); printer->Print( - "}\n" - "\n" - "public int getSerializedSize() {\n" - " int size = memoizedSerializedSize;\n" - " if (size != -1) return size;\n" - "\n" - " size = 0;\n"); + "}\n" + "\n" + "@java.lang.Override\n" + "public int getSerializedSize() {\n" + " int size = memoizedSerializedSize;\n" + " if (size != -1) return size;\n" + "\n"); printer->Indent(); + printer->Print( + "size = 0;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer); @@ -538,28 +625,26 @@ GenerateMessageSerializationMethods(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "size += extensionsSerializedSizeAsMessageSet();\n"); + printer->Print("size += extensionsSerializedSizeAsMessageSet();\n"); } else { - printer->Print( - "size += extensionsSerializedSize();\n"); + printer->Print("size += extensionsSerializedSize();\n"); } } - if (PreserveUnknownFields(descriptor_)) { - printer->Print( - "size += unknownFields.getSerializedSize();\n"); + if (descriptor_->options().message_set_wire_format()) { + printer->Print("size += unknownFields.getSerializedSizeAsMessageSet();\n"); + } else { + printer->Print("size += unknownFields.getSerializedSize();\n"); } + printer->Print( + "memoizedSerializedSize = size;\n" + "return size;\n"); + printer->Outdent(); printer->Print( - " memoizedSerializedSize = size;\n" - " return size;\n" "}\n" "\n"); - - printer->Print( - "private static final long serialVersionUID = 0L;\n"); } void ImmutableMessageLiteGenerator:: @@ -569,56 +654,77 @@ GenerateParseFromMethods(io::Printer* printer) { // for code size. printer->Print( "public static $classname$ parseFrom(\n" + " java.nio.ByteBuffer data)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, data);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " java.nio.ByteBuffer data,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, data, extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(\n" " com.google.protobuf.ByteString data)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return parser().parseFrom(data);\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, data);\n" "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.ByteString data,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return parser().parseFrom(data, extensionRegistry);\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, data, extensionRegistry);\n" "}\n" "public static $classname$ parseFrom(byte[] data)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return parser().parseFrom(data);\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, data);\n" "}\n" "public static $classname$ parseFrom(\n" " byte[] data,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return parser().parseFrom(data, extensionRegistry);\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, data, extensionRegistry);\n" "}\n" "public static $classname$ parseFrom(java.io.InputStream input)\n" " throws java.io.IOException {\n" - " return parser().parseFrom(input);\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, input);\n" "}\n" "public static $classname$ parseFrom(\n" " java.io.InputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" - " return parser().parseFrom(input, extensionRegistry);\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, input, extensionRegistry);\n" "}\n" "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n" " throws java.io.IOException {\n" - " return parser().parseDelimitedFrom(input);\n" + " return parseDelimitedFrom(DEFAULT_INSTANCE, input);\n" "}\n" "public static $classname$ parseDelimitedFrom(\n" " java.io.InputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" - " return parser().parseDelimitedFrom(input, extensionRegistry);\n" + " return parseDelimitedFrom(DEFAULT_INSTANCE, input, extensionRegistry);\n" "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.CodedInputStream input)\n" " throws java.io.IOException {\n" - " return parser().parseFrom(input);\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, input);\n" "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.CodedInputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" - " return parser().parseFrom(input, extensionRegistry);\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, input, extensionRegistry);\n" "}\n" "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); @@ -641,10 +747,10 @@ void ImmutableMessageLiteGenerator::GenerateSerializeOneExtensionRange( void ImmutableMessageLiteGenerator::GenerateBuilder(io::Printer* printer) { printer->Print( "public static Builder newBuilder() {\n" - " return DEFAULT_INSTANCE.toBuilder();\n" + " return (Builder) DEFAULT_INSTANCE.createBuilder();\n" "}\n" "public static Builder newBuilder($classname$ prototype) {\n" - " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n" + " return (Builder) DEFAULT_INSTANCE.createBuilder(prototype);\n" "}\n" "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); @@ -663,7 +769,10 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized( return; } - // Don't directly compare to -1 to avoid an Android x86 JIT bug. + // TODO(xiaofeng): Remove this when b/64445758 is fixed. We don't need to + // check memoizedIsInitialized here because the caller does that already, + // but right now proguard proto shrinker asserts on the bytecode layout of + // this code so it can't be removed until proguard is updated. printer->Print( "byte isInitialized = memoizedIsInitialized;\n" "if (isInitialized == 1) return DEFAULT_INSTANCE;\n" @@ -681,9 +790,6 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized( if (field->is_required()) { printer->Print( "if (!has$name$()) {\n" - " if (shouldMemoize) {\n" - " memoizedIsInitialized = 0;\n" - " }\n" " return null;\n" "}\n", "name", info->capitalized_name); @@ -700,9 +806,6 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized( case FieldDescriptor::LABEL_REQUIRED: printer->Print( "if (!get$name$().isInitialized()) {\n" - " if (shouldMemoize) {\n" - " memoizedIsInitialized = 0;\n" - " }\n" " return null;\n" "}\n", "type", name_resolver_->GetImmutableClassName( @@ -726,9 +829,6 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized( } printer->Print( " if (!get$name$().isInitialized()) {\n" - " if (shouldMemoize) {\n" - " memoizedIsInitialized = 0;\n" - " }\n" " return null;\n" " }\n" "}\n", @@ -737,11 +837,8 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized( case FieldDescriptor::LABEL_REPEATED: if (IsMapEntry(field->message_type())) { printer->Print( - "for ($type$ item : get$name$().values()) {\n" + "for ($type$ item : get$name$Map().values()) {\n" " if (!item.isInitialized()) {\n" - " if (shouldMemoize) {\n" - " memoizedIsInitialized = 0;\n" - " }\n" " return null;\n" " }\n" "}\n", @@ -752,9 +849,6 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized( printer->Print( "for (int i = 0; i < get$name$Count(); i++) {\n" " if (!get$name$(i).isInitialized()) {\n" - " if (shouldMemoize) {\n" - " memoizedIsInitialized = 0;\n" - " }\n" " return null;\n" " }\n" "}\n", @@ -770,17 +864,11 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized( if (descriptor_->extension_range_count() > 0) { printer->Print( "if (!extensionsAreInitialized()) {\n" - " if (shouldMemoize) {\n" - " memoizedIsInitialized = 0;\n" - " }\n" " return null;\n" "}\n"); } printer->Print( - "if (shouldMemoize) memoizedIsInitialized = 1;\n"); - - printer->Print( "return DEFAULT_INSTANCE;\n" "\n"); } @@ -789,11 +877,13 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized( void ImmutableMessageLiteGenerator::GenerateDynamicMethodMakeImmutable( io::Printer* printer) { + // Output generation code for each field. for (int i = 0; i < descriptor_->field_count(); i++) { field_generators_.get(descriptor_->field(i)) .GenerateDynamicMethodMakeImmutableCode(printer); } + printer->Print( "return null;\n"); } @@ -808,19 +898,17 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuilder( // =================================================================== -void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom( +void ImmutableMessageLiteGenerator::GenerateDynamicMethodVisit( io::Printer* printer) { printer->Print( - // Optimization: If other is the default instance, we know none of its - // fields are set so we can skip the merge. - "if (arg0 == $classname$.getDefaultInstance()) return this;\n" - "$classname$ other = ($classname$) arg0;\n", + "Visitor visitor = (Visitor) arg0;\n" + "$classname$ other = ($classname$) arg1;\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); for (int i = 0; i < descriptor_->field_count(); i++) { if (!descriptor_->field(i)->containing_oneof()) { field_generators_.get( - descriptor_->field(i)).GenerateMergingCode(printer); + descriptor_->field(i)).GenerateVisitCode(printer); } } @@ -839,7 +927,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom( "field_name", ToUpper(field->name())); printer->Indent(); - field_generators_.get(field).GenerateMergingCode(printer); + field_generators_.get(field).GenerateVisitCode(printer); printer->Print( "break;\n"); printer->Outdent(); @@ -848,276 +936,166 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom( } printer->Print( "case $cap_oneof_name$_NOT_SET: {\n" + " visitor.visitOneofNotSet($oneof_name$Case_ != 0);\n" " break;\n" "}\n", "cap_oneof_name", ToUpper(context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name)); + descriptor_->oneof_decl(i))->name), + "oneof_name", + context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name); printer->Outdent(); printer->Print( "}\n"); } - // if message type has extensions - if (descriptor_->extension_range_count() > 0) { - printer->Print( - "this.mergeExtensionFields(other);\n"); - } - - if (PreserveUnknownFields(descriptor_)) { - printer->Print( - "this.mergeUnknownFields(other.unknownFields);\n"); - } - printer->Print( - "return this;\n"); -} - -// =================================================================== - -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 ImmutableMessageLiteGenerator:: -GenerateEqualsAndHashCode(io::Printer* printer) { - printer->Print( - "@java.lang.Override\n" - "public boolean equals(final java.lang.Object obj) {\n"); + "if (visitor == com.google.protobuf.GeneratedMessageLite.MergeFromVisitor\n" + " .INSTANCE) {\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", 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); - 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", info->capitalized_name); - printer->Indent(); - } - field_generators_.get(field).GenerateEqualsCode(printer); - if (check_has_bits) { - printer->Outdent(); - printer->Print( - "}\n"); - } - } - if (PreserveUnknownFields(descriptor_)) { - // Always consider unknown fields for equality. This will sometimes return - // false for non-canonical ordering when running in LITE_RUNTIME but it's - // the best we can do. + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + const OneofDescriptor* field = descriptor_->oneof_decl(i); printer->Print( - "result = result && unknownFields.equals(other.unknownFields);\n"); + "if (other.$oneof_name$Case_ != 0) {\n" + " $oneof_name$Case_ = other.$oneof_name$Case_;\n" + "}\n", + "oneof_name", context_->GetOneofGeneratorInfo(field)->name); } - 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( - "if (memoizedHashCode != 0) {\n"); - printer->Indent(); - printer->Print( - "return memoizedHashCode;\n"); - printer->Outdent(); - printer->Print( - "}\n" - "int hash = 41;\n"); - // 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_)); + 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 < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); - bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); - if (check_has_bits) { + for (int i = 0; i < totalInts; i++) { printer->Print( - "if (has$name$()) {\n", - "name", info->capitalized_name); - printer->Indent(); - } - field_generators_.get(field).GenerateHashCode(printer); - if (check_has_bits) { - printer->Outdent(); - printer->Print("}\n"); + "$bit_field_name$ |= other.$bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); } } - - printer->Print( - "hash = (29 * hash) + unknownFields.hashCode();\n"); - printer->Print( - "memoizedHashCode = hash;\n" - "return hash;\n"); printer->Outdent(); printer->Print( - "}\n" - "\n"); -} + "}\n"); -// =================================================================== -void ImmutableMessageLiteGenerator:: -GenerateExtensionRegistrationCode(io::Printer* printer) { - for (int i = 0; i < descriptor_->extension_count(); i++) { - ImmutableExtensionGenerator(descriptor_->extension(i), context_) - .GenerateRegistrationCode(printer); - } - - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_) - .GenerateExtensionRegistrationCode(printer); - } + printer->Print( + "return this;\n"); } // =================================================================== -void ImmutableMessageLiteGenerator:: -GenerateParsingConstructor(io::Printer* printer) { - google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields( - SortFieldsByNumber(descriptor_)); +void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFromStream( + io::Printer* printer) { printer->Print( - "private $classname$(\n" - " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n", - "classname", descriptor_->name()); - printer->Indent(); - - // Initialize all fields to default. - GenerateInitializers(printer); - - // Use builder bits to track mutable repeated fields. - int totalBuilderBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - const ImmutableFieldLiteGenerator& field = - field_generators_.get(descriptor_->field(i)); - totalBuilderBits += field.GetNumBitsForBuilder(); - } - int totalBuilderInts = (totalBuilderBits + 31) / 32; - for (int i = 0; i < totalBuilderInts; i++) { - printer->Print("int mutable_$bit_field_name$ = 0;\n", - "bit_field_name", GetBitFieldName(i)); - } - + "com.google.protobuf.CodedInputStream input =\n" + " (com.google.protobuf.CodedInputStream) arg0;\n" + "com.google.protobuf.ExtensionRegistryLite extensionRegistry =\n" + " (com.google.protobuf.ExtensionRegistryLite) arg1;\n" + "if (extensionRegistry == null) {\n" + " throw new java.lang.NullPointerException();\n" + "}\n"); printer->Print( "try {\n"); printer->Indent(); - - printer->Print( - "boolean done = false;\n" - "while (!done) {\n"); - printer->Indent(); - - printer->Print( - "int tag = input.readTag();\n" - "switch (tag) {\n"); - printer->Indent(); - - printer->Print( - "case 0:\n" // zero signals EOF / limit reached - " done = true;\n" - " break;\n"); - - if (PreserveUnknownFields(descriptor_)) { - if (descriptor_->extension_range_count() > 0) { - printer->Print( - "default: {\n" - " if (!parseUnknownField(getDefaultInstanceForType(),\n" - " input, extensionRegistry, tag)) {\n" - " done = true;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); - } else { - printer->Print( - "default: {\n" - " if (!parseUnknownField(tag, input)) {\n" - " done = true;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); - } + if (EnableExperimentalRuntime(context_)) { + printer->Print( + "mergeFromInternal(input, extensionRegistry);\n" + "return DEFAULT_INSTANCE;\n"); } else { printer->Print( - "default: {\n" - " if (!input.skipField(tag)) {\n" - " done = true;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); - } - - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = sorted_fields[i]; - uint32 tag = WireFormatLite::MakeTag(field->number(), - WireFormat::WireTypeForFieldType(field->type())); + "boolean done = false;\n" + "while (!done) {\n"); + printer->Indent(); printer->Print( - "case $tag$: {\n", - "tag", SimpleItoa(tag)); + "int tag = input.readTag();\n" + "switch (tag) {\n"); printer->Indent(); - field_generators_.get(field).GenerateParsingCode(printer); - - printer->Outdent(); printer->Print( - " break;\n" - "}\n"); + "case 0:\n" // zero signals EOF / limit reached + " done = true;\n" + " break;\n"); - if (field->is_packable()) { - // To make packed = true wire compatible, we generate parsing code from a - // packed version of this field regardless of field->options().packed(). - uint32 packed_tag = WireFormatLite::MakeTag(field->number(), - WireFormatLite::WIRETYPE_LENGTH_DELIMITED); - printer->Print( - "case $tag$: {\n", - "tag", SimpleItoa(packed_tag)); + std::unique_ptr<const FieldDescriptor* []> sorted_fields( + SortFieldsByNumber(descriptor_)); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = sorted_fields[i]; + uint32 tag = WireFormatLite::MakeTag( + field->number(), WireFormat::WireTypeForFieldType(field->type())); + + printer->Print("case $tag$: {\n", "tag", + SimpleItoa(static_cast<int32>(tag))); printer->Indent(); - field_generators_.get(field).GenerateParsingCodeFromPacked(printer); + field_generators_.get(field).GenerateParsingCode(printer); printer->Outdent(); printer->Print( " break;\n" "}\n"); + + if (field->is_packable()) { + // To make packed = true wire compatible, we generate parsing code from + // a packed version of this field regardless of + // field->options().packed(). + uint32 packed_tag = WireFormatLite::MakeTag( + field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + printer->Print("case $tag$: {\n", "tag", + SimpleItoa(static_cast<int32>(packed_tag))); + printer->Indent(); + + field_generators_.get(field).GenerateParsingCodeFromPacked(printer); + + printer->Outdent(); + printer->Print( + " break;\n" + "}\n"); + } } - } - printer->Outdent(); - printer->Outdent(); - printer->Print( - " }\n" // switch (tag) - "}\n"); // while (!done) + if (descriptor_->extension_range_count() > 0) { + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "default: {\n" + " if (!parseUnknownFieldAsMessageSet(\n" + " getDefaultInstanceForType(), input, extensionRegistry,\n" + " tag)) {\n" + " done = true;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); + } else { + printer->Print( + "default: {\n" + " if (!parseUnknownField(getDefaultInstanceForType(),\n" + " input, extensionRegistry, tag)) {\n" + " done = true;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); + } + } else { + printer->Print( + "default: {\n" + " if (!parseUnknownField(tag, input)) {\n" + " done = true;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); + } + + printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" // switch (tag) + "}\n"); // while (!done) + } printer->Outdent(); printer->Print( @@ -1130,19 +1108,39 @@ GenerateParsingConstructor(io::Printer* printer) { "} finally {\n"); printer->Indent(); - // Make repeated field list immutable. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = sorted_fields[i]; - field_generators_.get(field).GenerateParsingDoneCode(printer); + printer->Outdent(); + printer->Print( + "}\n"); // finally +} + +// =================================================================== + +void ImmutableMessageLiteGenerator:: +GenerateExtensionRegistrationCode(io::Printer* printer) { + for (int i = 0; i < descriptor_->extension_count(); i++) { + ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_) + .GenerateRegistrationCode(printer); } + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_) + .GenerateExtensionRegistrationCode(printer); + } +} + +// =================================================================== +void ImmutableMessageLiteGenerator:: +GenerateConstructor(io::Printer* printer) { printer->Print( - "doneParsing();\n"); + "private $classname$() {\n", + "classname", descriptor_->name()); + printer->Indent(); + + // Initialize all fields to default. + GenerateInitializers(printer); - printer->Outdent(); printer->Outdent(); printer->Print( - " }\n" // finally "}\n"); } @@ -1167,7 +1165,6 @@ void ImmutableMessageLiteGenerator::GenerateInitializers(io::Printer* printer) { } } - } // namespace java } // namespace compiler } // namespace protobuf |