Index: third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc |
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc |
index 5715a43294ba3e4e6b57bde35f60d892141d6cad..4c474a48a692f0fee2cea85f46632d969631de12 100644 |
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc |
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc |
@@ -89,19 +89,20 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor) |
MessageGenerator::~MessageGenerator() {} |
// =================================================================== |
-// 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_) { |
- GOOGLE_CHECK_NE( |
- FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for()); |
+ GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite())) |
+ << "Generator factory error: A non-lite message generator is used to " |
+ "generate lite messages."; |
} |
ImmutableMessageGenerator::~ImmutableMessageGenerator() {} |
-void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) { |
+void ImmutableMessageGenerator::GenerateStaticVariables( |
+ io::Printer* printer, int* bytecode_estimate) { |
// Because descriptor.proto (com.google.protobuf.DescriptorProtos) is |
// used in the construction of descriptors, we have a tricky bootstrapping |
// problem. To help control static initialization order, we make sure all |
@@ -124,23 +125,29 @@ void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) { |
} else { |
vars["private"] = "private "; |
} |
+ if (*bytecode_estimate <= kMaxStaticSize) { |
+ vars["final"] = "final "; |
+ } else { |
+ vars["final"] = ""; |
+ } |
// The descriptor for this type. |
printer->Print(vars, |
// TODO(teboring): final needs to be added back. The way to fix it is to |
// generate methods that can construct the types, and then still declare the |
// types, and then init them in clinit with the new method calls. |
- "$private$static com.google.protobuf.Descriptors.Descriptor\n" |
+ "$private$static $final$com.google.protobuf.Descriptors.Descriptor\n" |
" internal_$identifier$_descriptor;\n"); |
+ *bytecode_estimate += 30; |
// And the FieldAccessorTable. |
- GenerateFieldAccessorTable(printer); |
+ GenerateFieldAccessorTable(printer, bytecode_estimate); |
// Generate static members for all nested types. |
for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
// TODO(kenton): Reuse MessageGenerator objects? |
ImmutableMessageGenerator(descriptor_->nested_type(i), context_) |
- .GenerateStaticVariables(printer); |
+ .GenerateStaticVariables(printer, bytecode_estimate); |
} |
} |
@@ -183,7 +190,7 @@ int ImmutableMessageGenerator::GenerateStaticVariableInitializers( |
} |
void ImmutableMessageGenerator:: |
-GenerateFieldAccessorTable(io::Printer* printer) { |
+GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate) { |
map<string, string> vars; |
vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); |
if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { |
@@ -193,10 +200,19 @@ GenerateFieldAccessorTable(io::Printer* printer) { |
} else { |
vars["private"] = "private "; |
} |
+ if (*bytecode_estimate <= kMaxStaticSize) { |
+ vars["final"] = "final "; |
+ } else { |
+ vars["final"] = ""; |
+ } |
printer->Print(vars, |
- "$private$static\n" |
+ "$private$static $final$\n" |
" com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" |
" internal_$identifier$_fieldAccessorTable;\n"); |
+ |
+ // 6 bytes per field and oneof |
+ *bytecode_estimate += 10 + 6 * descriptor_->field_count() |
+ + 6 * descriptor_->oneof_decl_count(); |
} |
int ImmutableMessageGenerator:: |
@@ -342,7 +358,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { |
printer->Print( |
"}\n"); |
- if (HasGeneratedMethods(descriptor_)) { |
+ if (context_->HasGeneratedMethods(descriptor_)) { |
GenerateParsingConstructor(printer); |
} |
@@ -408,12 +424,20 @@ void ImmutableMessageGenerator::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); |
@@ -426,8 +450,7 @@ void ImmutableMessageGenerator::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" |
"public int getNumber() {\n" |
@@ -440,7 +463,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { |
printer->Print(vars, |
"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"); |
@@ -459,7 +482,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { |
printer->Print("\n"); |
} |
- if (HasGeneratedMethods(descriptor_)) { |
+ if (context_->HasGeneratedMethods(descriptor_)) { |
GenerateIsInitialized(printer); |
GenerateMessageSerializationMethods(printer); |
} |
@@ -664,34 +687,40 @@ GenerateParseFromMethods(io::Printer* printer) { |
"}\n" |
"public static $classname$ parseFrom(java.io.InputStream input)\n" |
" throws java.io.IOException {\n" |
- " return PARSER.parseFrom(input);\n" |
+ " return com.google.protobuf.GeneratedMessage\n" |
+ " .parseWithIOException(PARSER, 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.GeneratedMessage\n" |
+ " .parseWithIOException(PARSER, input, extensionRegistry);\n" |
"}\n" |
"public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n" |
" throws java.io.IOException {\n" |
- " return PARSER.parseDelimitedFrom(input);\n" |
+ " return com.google.protobuf.GeneratedMessage\n" |
+ " .parseDelimitedWithIOException(PARSER, 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 com.google.protobuf.GeneratedMessage\n" |
+ " .parseDelimitedWithIOException(PARSER, 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.GeneratedMessage\n" |
+ " .parseWithIOException(PARSER, 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.GeneratedMessage\n" |
+ " .parseWithIOException(PARSER, input, extensionRegistry);\n" |
"}\n" |
"\n", |
"classname", name_resolver_->GetImmutableClassName(descriptor_)); |
@@ -1049,22 +1078,52 @@ GenerateEqualsAndHashCode(io::Printer* printer) { |
printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n"); |
+ // hashCode non-oneofs. |
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) { |
+ if (field->containing_oneof() == NULL) { |
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); |
+ bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); |
+ if (check_has_bits) { |
+ 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"); |
+ } |
+ } |
+ } |
+ |
+ // hashCode oneofs. |
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
+ printer->Print( |
+ "switch ($oneof_name$Case_) {\n", |
+ "oneof_name", |
+ context_->GetOneofGeneratorInfo( |
+ descriptor_->oneof_decl(i))->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( |
- "if (has$name$()) {\n", |
- "name", info->capitalized_name); |
+ "case $field_number$:\n", |
+ "field_number", |
+ SimpleItoa(field->number())); |
printer->Indent(); |
- } |
- field_generators_.get(field).GenerateHashCode(printer); |
- if (check_has_bits) { |
+ field_generators_.get(field).GenerateHashCode(printer); |
+ printer->Print("break;\n"); |
printer->Outdent(); |
- printer->Print("}\n"); |
} |
+ printer->Print( |
+ "case 0:\n" |
+ "default:\n"); |
+ printer->Outdent(); |
+ printer->Print("}\n"); |
} |
+ |
if (descriptor_->extension_range_count() > 0) { |
printer->Print( |
"hash = hashFields(hash, getExtensionFields());\n"); |
@@ -1105,7 +1164,8 @@ GenerateParsingConstructor(io::Printer* printer) { |
printer->Print( |
"private $classname$(\n" |
" com.google.protobuf.CodedInputStream input,\n" |
- " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n", |
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n", |
"classname", descriptor_->name()); |
printer->Indent(); |
@@ -1165,7 +1225,8 @@ GenerateParsingConstructor(io::Printer* printer) { |
"default: {\n" |
" if (!input.skipField(tag)) {\n" |
" done = true;\n" // it's an endgroup tag |
- " }\n" |
+ " }\n"); |
+ printer->Print( |
" break;\n" |
"}\n"); |
} |
@@ -1215,11 +1276,10 @@ GenerateParsingConstructor(io::Printer* printer) { |
printer->Outdent(); |
printer->Print( |
"} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" |
- " throw new RuntimeException(e.setUnfinishedMessage(this));\n" |
+ " throw e.setUnfinishedMessage(this);\n" |
"} catch (java.io.IOException e) {\n" |
- " throw new RuntimeException(\n" |
- " new com.google.protobuf.InvalidProtocolBufferException(\n" |
- " e.getMessage()).setUnfinishedMessage(this));\n" |
+ " throw new com.google.protobuf.InvalidProtocolBufferException(\n" |
+ " e).setUnfinishedMessage(this);\n" |
"} finally {\n"); |
printer->Indent(); |
@@ -1261,20 +1321,9 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { |
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
" throws com.google.protobuf.InvalidProtocolBufferException {\n", |
"classname", descriptor_->name()); |
- if (HasGeneratedMethods(descriptor_)) { |
- // The parsing constructor throws an InvalidProtocolBufferException via a |
- // RuntimeException to aid in method pruning. We unwrap it here. |
+ if (context_->HasGeneratedMethods(descriptor_)) { |
printer->Print( |
- " try {\n" |
- " return new $classname$(input, extensionRegistry);\n" |
- " } catch (RuntimeException e) {\n" |
- " if (e.getCause() instanceof\n" |
- " com.google.protobuf.InvalidProtocolBufferException) {\n" |
- " throw (com.google.protobuf.InvalidProtocolBufferException)\n" |
- " e.getCause();\n" |
- " }\n" |
- " throw e;\n" |
- " }\n", |
+ " return new $classname$(input, extensionRegistry);\n", |
"classname", descriptor_->name()); |
} else { |
// When parsing constructor isn't generated, use builder to parse |
@@ -1329,14 +1378,39 @@ void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) { |
void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) { |
printer->Print( |
"private static String getTypeUrl(\n" |
+ " java.lang.String typeUrlPrefix,\n" |
" com.google.protobuf.Descriptors.Descriptor descriptor) {\n" |
- " return \"type.googleapis.com/\" + descriptor.getFullName();\n" |
+ " return typeUrlPrefix.endsWith(\"/\")\n" |
+ " ? typeUrlPrefix + descriptor.getFullName()\n" |
+ " : typeUrlPrefix + \"/\" + descriptor.getFullName();\n" |
+ "}\n" |
+ "\n" |
+ "private static String getTypeNameFromTypeUrl(\n" |
+ " java.lang.String typeUrl) {\n" |
+ " int pos = typeUrl.lastIndexOf('/');\n" |
+ " return pos == -1 ? \"\" : typeUrl.substring(pos + 1);\n" |
"}\n" |
"\n" |
"public static <T extends com.google.protobuf.Message> Any pack(\n" |
" T message) {\n" |
" return Any.newBuilder()\n" |
- " .setTypeUrl(getTypeUrl(message.getDescriptorForType()))\n" |
+ " .setTypeUrl(getTypeUrl(\"type.googleapis.com\",\n" |
+ " message.getDescriptorForType()))\n" |
+ " .setValue(message.toByteString())\n" |
+ " .build();\n" |
+ "}\n" |
+ "\n" |
+ "/**\n" |
+ " * Packs a message uisng the given type URL prefix. The type URL will\n" |
+ " * be constructed by concatenating the message type's full name to the\n" |
+ " * prefix with an optional \"/\" separator if the prefix doesn't end\n" |
+ " * with \"/\" already.\n" |
+ " */\n" |
+ "public static <T extends com.google.protobuf.Message> Any pack(\n" |
+ " T message, java.lang.String typeUrlPrefix) {\n" |
+ " return Any.newBuilder()\n" |
+ " .setTypeUrl(getTypeUrl(typeUrlPrefix,\n" |
+ " message.getDescriptorForType()))\n" |
" .setValue(message.toByteString())\n" |
" .build();\n" |
"}\n" |
@@ -1345,8 +1419,8 @@ void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) { |
" java.lang.Class<T> clazz) {\n" |
" T defaultInstance =\n" |
" com.google.protobuf.Internal.getDefaultInstance(clazz);\n" |
- " return getTypeUrl().equals(\n" |
- " getTypeUrl(defaultInstance.getDescriptorForType()));\n" |
+ " return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n" |
+ " defaultInstance.getDescriptorForType().getFullName());\n" |
"}\n" |
"\n" |
"private volatile com.google.protobuf.Message cachedUnpackValue;\n" |