| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 #include <google/protobuf/compiler/java/java_name_resolver.h> | 42 #include <google/protobuf/compiler/java/java_name_resolver.h> |
| 43 #include <google/protobuf/io/printer.h> | 43 #include <google/protobuf/io/printer.h> |
| 44 #include <google/protobuf/descriptor.pb.h> | 44 #include <google/protobuf/descriptor.pb.h> |
| 45 #include <google/protobuf/stubs/strutil.h> | 45 #include <google/protobuf/stubs/strutil.h> |
| 46 | 46 |
| 47 namespace google { | 47 namespace google { |
| 48 namespace protobuf { | 48 namespace protobuf { |
| 49 namespace compiler { | 49 namespace compiler { |
| 50 namespace java { | 50 namespace java { |
| 51 | 51 |
| 52 namespace { | |
| 53 bool EnumHasCustomOptions(const EnumDescriptor* descriptor) { | |
| 54 if (descriptor->options().unknown_fields().field_count() > 0) return true; | |
| 55 for (int i = 0; i < descriptor->value_count(); ++i) { | |
| 56 const EnumValueDescriptor* value = descriptor->value(i); | |
| 57 if (value->options().unknown_fields().field_count() > 0) return true; | |
| 58 } | |
| 59 return false; | |
| 60 } | |
| 61 } // namespace | |
| 62 | |
| 63 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, | 52 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, |
| 64 bool immutable_api, | 53 bool immutable_api, |
| 65 Context* context) | 54 Context* context) |
| 66 : descriptor_(descriptor), immutable_api_(immutable_api), | 55 : descriptor_(descriptor), immutable_api_(immutable_api), |
| 67 context_(context), | 56 context_(context), |
| 68 name_resolver_(context->GetNameResolver()) { | 57 name_resolver_(context->GetNameResolver()) { |
| 69 for (int i = 0; i < descriptor_->value_count(); i++) { | 58 for (int i = 0; i < descriptor_->value_count(); i++) { |
| 70 const EnumValueDescriptor* value = descriptor_->value(i); | 59 const EnumValueDescriptor* value = descriptor_->value(i); |
| 71 const EnumValueDescriptor* canonical_value = | 60 const EnumValueDescriptor* canonical_value = |
| 72 descriptor_->FindValueByNumber(value->number()); | 61 descriptor_->FindValueByNumber(value->number()); |
| 73 | 62 |
| 74 if (value == canonical_value) { | 63 if (value == canonical_value) { |
| 75 canonical_values_.push_back(value); | 64 canonical_values_.push_back(value); |
| 76 } else { | 65 } else { |
| 77 Alias alias; | 66 Alias alias; |
| 78 alias.value = value; | 67 alias.value = value; |
| 79 alias.canonical_value = canonical_value; | 68 alias.canonical_value = canonical_value; |
| 80 aliases_.push_back(alias); | 69 aliases_.push_back(alias); |
| 81 } | 70 } |
| 82 } | 71 } |
| 83 } | 72 } |
| 84 | 73 |
| 85 EnumGenerator::~EnumGenerator() {} | 74 EnumGenerator::~EnumGenerator() {} |
| 86 | 75 |
| 87 void EnumGenerator::Generate(io::Printer* printer) { | 76 void EnumGenerator::Generate(io::Printer* printer) { |
| 88 WriteEnumDocComment(printer, descriptor_); | 77 WriteEnumDocComment(printer, descriptor_); |
| 78 MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_); |
| 89 printer->Print( | 79 printer->Print( |
| 90 "public enum $classname$\n" | 80 "public enum $classname$\n" |
| 91 " implements com.google.protobuf.ProtocolMessageEnum {\n", | 81 " implements com.google.protobuf.ProtocolMessageEnum {\n", |
| 92 "classname", descriptor_->name()); | 82 "classname", descriptor_->name()); |
| 83 printer->Annotate("classname", descriptor_); |
| 93 printer->Indent(); | 84 printer->Indent(); |
| 94 | 85 |
| 95 bool ordinal_is_index = true; | 86 bool ordinal_is_index = true; |
| 96 string index_text = "ordinal()"; | 87 string index_text = "ordinal()"; |
| 97 for (int i = 0; i < canonical_values_.size(); i++) { | 88 for (int i = 0; i < canonical_values_.size(); i++) { |
| 98 if (canonical_values_[i]->index() != i) { | 89 if (canonical_values_[i]->index() != i) { |
| 99 ordinal_is_index = false; | 90 ordinal_is_index = false; |
| 100 index_text = "index"; | 91 index_text = "index"; |
| 101 break; | 92 break; |
| 102 } | 93 } |
| 103 } | 94 } |
| 104 | 95 |
| 105 for (int i = 0; i < canonical_values_.size(); i++) { | 96 for (int i = 0; i < canonical_values_.size(); i++) { |
| 106 map<string, string> vars; | 97 std::map<string, string> vars; |
| 107 vars["name"] = canonical_values_[i]->name(); | 98 vars["name"] = canonical_values_[i]->name(); |
| 108 vars["index"] = SimpleItoa(canonical_values_[i]->index()); | 99 vars["index"] = SimpleItoa(canonical_values_[i]->index()); |
| 109 vars["number"] = SimpleItoa(canonical_values_[i]->number()); | 100 vars["number"] = SimpleItoa(canonical_values_[i]->number()); |
| 110 WriteEnumValueDocComment(printer, canonical_values_[i]); | 101 WriteEnumValueDocComment(printer, canonical_values_[i]); |
| 111 if (canonical_values_[i]->options().deprecated()) { | 102 if (canonical_values_[i]->options().deprecated()) { |
| 112 printer->Print("@java.lang.Deprecated\n"); | 103 printer->Print("@java.lang.Deprecated\n"); |
| 113 } | 104 } |
| 114 if (ordinal_is_index) { | 105 if (ordinal_is_index) { |
| 115 printer->Print(vars, | 106 printer->Print(vars, |
| 116 "$name$($number$),\n"); | 107 "$name$($number$),\n"); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 128 } | 119 } |
| 129 } | 120 } |
| 130 | 121 |
| 131 printer->Print( | 122 printer->Print( |
| 132 ";\n" | 123 ";\n" |
| 133 "\n"); | 124 "\n"); |
| 134 | 125 |
| 135 // ----------------------------------------------------------------- | 126 // ----------------------------------------------------------------- |
| 136 | 127 |
| 137 for (int i = 0; i < aliases_.size(); i++) { | 128 for (int i = 0; i < aliases_.size(); i++) { |
| 138 map<string, string> vars; | 129 std::map<string, string> vars; |
| 139 vars["classname"] = descriptor_->name(); | 130 vars["classname"] = descriptor_->name(); |
| 140 vars["name"] = aliases_[i].value->name(); | 131 vars["name"] = aliases_[i].value->name(); |
| 141 vars["canonical_name"] = aliases_[i].canonical_value->name(); | 132 vars["canonical_name"] = aliases_[i].canonical_value->name(); |
| 142 WriteEnumValueDocComment(printer, aliases_[i].value); | 133 WriteEnumValueDocComment(printer, aliases_[i].value); |
| 143 printer->Print(vars, | 134 printer->Print(vars, |
| 144 "public static final $classname$ $name$ = $canonical_name$;\n"); | 135 "public static final $classname$ $name$ = $canonical_name$;\n"); |
| 145 } | 136 } |
| 146 | 137 |
| 147 for (int i = 0; i < descriptor_->value_count(); i++) { | 138 for (int i = 0; i < descriptor_->value_count(); i++) { |
| 148 map<string, string> vars; | 139 std::map<string, string> vars; |
| 149 vars["name"] = descriptor_->value(i)->name(); | 140 vars["name"] = descriptor_->value(i)->name(); |
| 150 vars["number"] = SimpleItoa(descriptor_->value(i)->number()); | 141 vars["number"] = SimpleItoa(descriptor_->value(i)->number()); |
| 151 WriteEnumValueDocComment(printer, descriptor_->value(i)); | 142 WriteEnumValueDocComment(printer, descriptor_->value(i)); |
| 152 printer->Print(vars, | 143 printer->Print(vars, |
| 153 "public static final int $name$_VALUE = $number$;\n"); | 144 "public static final int $name$_VALUE = $number$;\n"); |
| 154 } | 145 } |
| 155 printer->Print("\n"); | 146 printer->Print("\n"); |
| 156 | 147 |
| 157 // ----------------------------------------------------------------- | 148 // ----------------------------------------------------------------- |
| 158 | 149 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 " return getDescriptor();\n" | 225 " return getDescriptor();\n" |
| 235 "}\n" | 226 "}\n" |
| 236 "public static final com.google.protobuf.Descriptors.EnumDescriptor\n" | 227 "public static final com.google.protobuf.Descriptors.EnumDescriptor\n" |
| 237 " getDescriptor() {\n", | 228 " getDescriptor() {\n", |
| 238 "index_text", index_text); | 229 "index_text", index_text); |
| 239 | 230 |
| 240 // TODO(kenton): Cache statically? Note that we can't access descriptors | 231 // TODO(kenton): Cache statically? Note that we can't access descriptors |
| 241 // at module init time because it wouldn't work with descriptor.proto, but | 232 // at module init time because it wouldn't work with descriptor.proto, but |
| 242 // we can cache the value the first time getDescriptor() is called. | 233 // we can cache the value the first time getDescriptor() is called. |
| 243 if (descriptor_->containing_type() == NULL) { | 234 if (descriptor_->containing_type() == NULL) { |
| 244 if (!MultipleJavaFiles(descriptor_->file(), immutable_api_)) { | 235 // The class generated for the File fully populates the descriptor with |
| 245 printer->Print( | 236 // extensions in both the mutable and immutable cases. (In the mutable api |
| 246 " return $file$.getDescriptor().getEnumTypes().get($index$);\n", | 237 // this is accomplished by attempting to load the immutable outer class). |
| 247 "file", name_resolver_->GetClassName(descriptor_->file(), | 238 printer->Print( |
| 248 immutable_api_), | 239 " return $file$.getDescriptor().getEnumTypes().get($index$);\n", |
| 249 "index", SimpleItoa(descriptor_->index())); | 240 "file", name_resolver_->GetClassName(descriptor_->file(), |
| 250 } else { | 241 immutable_api_), |
| 251 printer->Indent(); | 242 "index", SimpleItoa(descriptor_->index())); |
| 252 if (EnumHasCustomOptions(descriptor_)) { | |
| 253 // We need to load the immutable classes in order to parse custom | |
| 254 // options. However, since file level enums (no outer class) are | |
| 255 // shared by immutable code and mutable code, the immutable classes | |
| 256 // may not exist. So we try to use Java reflection to retrieve the | |
| 257 // descriptor from immutable classes. | |
| 258 printer->Print( | |
| 259 "try {\n" | |
| 260 " java.lang.Class immutableFileClass =\n" | |
| 261 " java.lang.Class.forName(\"$immutable_file_class_name$\");\n" | |
| 262 " @java.lang.SuppressWarnings(\"unchecked\")\n" | |
| 263 " java.lang.reflect.Method m =\n" | |
| 264 " immutableFileClass.getMethod(\"getDescriptor\");\n" | |
| 265 " com.google.protobuf.Descriptors.FileDescriptor file =\n" | |
| 266 " (com.google.protobuf.Descriptors.FileDescriptor)\n" | |
| 267 " m.invoke(immutableFileClass);\n" | |
| 268 " return file.getEnumTypes().get($index$);\n" | |
| 269 "} catch (java.lang.Exception e) {\n" | |
| 270 // Immutable classes cannot be found. Proceed as if custom options | |
| 271 // don't exist. | |
| 272 "}\n", | |
| 273 "immutable_file_class_name", | |
| 274 name_resolver_->GetImmutableClassName(descriptor_->file()), | |
| 275 "index", SimpleItoa(descriptor_->index())); | |
| 276 } | |
| 277 printer->Print( | |
| 278 "return $immutable_package$.$descriptor_class$.$descriptor$\n" | |
| 279 " .getEnumTypes().get($index$);\n", | |
| 280 "immutable_package", FileJavaPackage(descriptor_->file(), true), | |
| 281 "descriptor_class", | |
| 282 name_resolver_->GetDescriptorClassName(descriptor_->file()), | |
| 283 "descriptor", "getDescriptor()", | |
| 284 "index", SimpleItoa(descriptor_->index())); | |
| 285 printer->Outdent(); | |
| 286 } | |
| 287 } else { | 243 } else { |
| 288 printer->Print( | 244 printer->Print( |
| 289 " return $parent$.$descriptor$.getEnumTypes().get($index$);\n", | 245 " return $parent$.$descriptor$.getEnumTypes().get($index$);\n", |
| 290 "parent", name_resolver_->GetClassName(descriptor_->containing_type(), | 246 "parent", name_resolver_->GetClassName(descriptor_->containing_type(), |
| 291 immutable_api_), | 247 immutable_api_), |
| 292 "descriptor", descriptor_->containing_type()->options() | 248 "descriptor", descriptor_->containing_type()->options() |
| 293 .no_standard_descriptor_accessor() | 249 .no_standard_descriptor_accessor() |
| 294 ? "getDefaultInstance().getDescriptorForType()" | 250 ? "getDefaultInstance().getDescriptorForType()" |
| 295 : "getDescriptor()", | 251 : "getDescriptor()", |
| 296 "index", SimpleItoa(descriptor_->index())); | 252 "index", SimpleItoa(descriptor_->index())); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 return false; | 342 return false; |
| 387 } | 343 } |
| 388 } | 344 } |
| 389 return true; | 345 return true; |
| 390 } | 346 } |
| 391 | 347 |
| 392 } // namespace java | 348 } // namespace java |
| 393 } // namespace compiler | 349 } // namespace compiler |
| 394 } // namespace protobuf | 350 } // namespace protobuf |
| 395 } // namespace google | 351 } // namespace google |
| OLD | NEW |