Index: third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc |
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc |
index b9ee00ff421eb851356b34dff4bd49e2cc1063b4..947b80e4147d36521f019e3304f0f147ea072ed9 100644 |
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc |
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc |
@@ -49,6 +49,17 @@ namespace protobuf { |
namespace compiler { |
namespace java { |
+namespace { |
+bool EnumHasCustomOptions(const EnumDescriptor* descriptor) { |
+ if (descriptor->options().unknown_fields().field_count() > 0) return true; |
+ for (int i = 0; i < descriptor->value_count(); ++i) { |
+ const EnumValueDescriptor* value = descriptor->value(i); |
+ if (value->options().unknown_fields().field_count() > 0) return true; |
+ } |
+ return false; |
+} |
+} // namespace |
+ |
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, |
bool immutable_api, |
Context* context) |
@@ -75,12 +86,10 @@ EnumGenerator::~EnumGenerator() {} |
void EnumGenerator::Generate(io::Printer* printer) { |
WriteEnumDocComment(printer, descriptor_); |
- MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_); |
printer->Print( |
- "public enum $classname$\n" |
- " implements com.google.protobuf.ProtocolMessageEnum {\n", |
- "classname", descriptor_->name()); |
- printer->Annotate("classname", descriptor_); |
+ "public enum $classname$\n" |
+ " implements com.google.protobuf.ProtocolMessageEnum {\n", |
+ "classname", descriptor_->name()); |
printer->Indent(); |
bool ordinal_is_index = true; |
@@ -94,7 +103,7 @@ void EnumGenerator::Generate(io::Printer* printer) { |
} |
for (int i = 0; i < canonical_values_.size(); i++) { |
- std::map<string, string> vars; |
+ map<string, string> vars; |
vars["name"] = canonical_values_[i]->name(); |
vars["index"] = SimpleItoa(canonical_values_[i]->index()); |
vars["number"] = SimpleItoa(canonical_values_[i]->number()); |
@@ -126,7 +135,7 @@ void EnumGenerator::Generate(io::Printer* printer) { |
// ----------------------------------------------------------------- |
for (int i = 0; i < aliases_.size(); i++) { |
- std::map<string, string> vars; |
+ map<string, string> vars; |
vars["classname"] = descriptor_->name(); |
vars["name"] = aliases_[i].value->name(); |
vars["canonical_name"] = aliases_[i].canonical_value->name(); |
@@ -136,7 +145,7 @@ void EnumGenerator::Generate(io::Printer* printer) { |
} |
for (int i = 0; i < descriptor_->value_count(); i++) { |
- std::map<string, string> vars; |
+ map<string, string> vars; |
vars["name"] = descriptor_->value(i)->name(); |
vars["number"] = SimpleItoa(descriptor_->value(i)->number()); |
WriteEnumValueDocComment(printer, descriptor_->value(i)); |
@@ -232,14 +241,49 @@ void EnumGenerator::Generate(io::Printer* printer) { |
// at module init time because it wouldn't work with descriptor.proto, but |
// we can cache the value the first time getDescriptor() is called. |
if (descriptor_->containing_type() == NULL) { |
- // The class generated for the File fully populates the descriptor with |
- // extensions in both the mutable and immutable cases. (In the mutable api |
- // this is accomplished by attempting to load the immutable outer class). |
- printer->Print( |
- " return $file$.getDescriptor().getEnumTypes().get($index$);\n", |
- "file", name_resolver_->GetClassName(descriptor_->file(), |
- immutable_api_), |
- "index", SimpleItoa(descriptor_->index())); |
+ if (!MultipleJavaFiles(descriptor_->file(), immutable_api_)) { |
+ printer->Print( |
+ " return $file$.getDescriptor().getEnumTypes().get($index$);\n", |
+ "file", name_resolver_->GetClassName(descriptor_->file(), |
+ immutable_api_), |
+ "index", SimpleItoa(descriptor_->index())); |
+ } else { |
+ printer->Indent(); |
+ if (EnumHasCustomOptions(descriptor_)) { |
+ // We need to load the immutable classes in order to parse custom |
+ // options. However, since file level enums (no outer class) are |
+ // shared by immutable code and mutable code, the immutable classes |
+ // may not exist. So we try to use Java reflection to retrieve the |
+ // descriptor from immutable classes. |
+ printer->Print( |
+ "try {\n" |
+ " java.lang.Class immutableFileClass =\n" |
+ " java.lang.Class.forName(\"$immutable_file_class_name$\");\n" |
+ " @java.lang.SuppressWarnings(\"unchecked\")\n" |
+ " java.lang.reflect.Method m =\n" |
+ " immutableFileClass.getMethod(\"getDescriptor\");\n" |
+ " com.google.protobuf.Descriptors.FileDescriptor file =\n" |
+ " (com.google.protobuf.Descriptors.FileDescriptor)\n" |
+ " m.invoke(immutableFileClass);\n" |
+ " return file.getEnumTypes().get($index$);\n" |
+ "} catch (java.lang.Exception e) {\n" |
+ // Immutable classes cannot be found. Proceed as if custom options |
+ // don't exist. |
+ "}\n", |
+ "immutable_file_class_name", |
+ name_resolver_->GetImmutableClassName(descriptor_->file()), |
+ "index", SimpleItoa(descriptor_->index())); |
+ } |
+ printer->Print( |
+ "return $immutable_package$.$descriptor_class$.$descriptor$\n" |
+ " .getEnumTypes().get($index$);\n", |
+ "immutable_package", FileJavaPackage(descriptor_->file(), true), |
+ "descriptor_class", |
+ name_resolver_->GetDescriptorClassName(descriptor_->file()), |
+ "descriptor", "getDescriptor()", |
+ "index", SimpleItoa(descriptor_->index())); |
+ printer->Outdent(); |
+ } |
} else { |
printer->Print( |
" return $parent$.$descriptor$.getEnumTypes().get($index$);\n", |