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 |
52 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, | 63 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, |
53 bool immutable_api, | 64 bool immutable_api, |
54 Context* context) | 65 Context* context) |
55 : descriptor_(descriptor), immutable_api_(immutable_api), | 66 : descriptor_(descriptor), immutable_api_(immutable_api), |
56 context_(context), | 67 context_(context), |
57 name_resolver_(context->GetNameResolver()) { | 68 name_resolver_(context->GetNameResolver()) { |
58 for (int i = 0; i < descriptor_->value_count(); i++) { | 69 for (int i = 0; i < descriptor_->value_count(); i++) { |
59 const EnumValueDescriptor* value = descriptor_->value(i); | 70 const EnumValueDescriptor* value = descriptor_->value(i); |
60 const EnumValueDescriptor* canonical_value = | 71 const EnumValueDescriptor* canonical_value = |
61 descriptor_->FindValueByNumber(value->number()); | 72 descriptor_->FindValueByNumber(value->number()); |
62 | 73 |
63 if (value == canonical_value) { | 74 if (value == canonical_value) { |
64 canonical_values_.push_back(value); | 75 canonical_values_.push_back(value); |
65 } else { | 76 } else { |
66 Alias alias; | 77 Alias alias; |
67 alias.value = value; | 78 alias.value = value; |
68 alias.canonical_value = canonical_value; | 79 alias.canonical_value = canonical_value; |
69 aliases_.push_back(alias); | 80 aliases_.push_back(alias); |
70 } | 81 } |
71 } | 82 } |
72 } | 83 } |
73 | 84 |
74 EnumGenerator::~EnumGenerator() {} | 85 EnumGenerator::~EnumGenerator() {} |
75 | 86 |
76 void EnumGenerator::Generate(io::Printer* printer) { | 87 void EnumGenerator::Generate(io::Printer* printer) { |
77 WriteEnumDocComment(printer, descriptor_); | 88 WriteEnumDocComment(printer, descriptor_); |
78 MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_); | |
79 printer->Print( | 89 printer->Print( |
80 "public enum $classname$\n" | 90 "public enum $classname$\n" |
81 " implements com.google.protobuf.ProtocolMessageEnum {\n", | 91 " implements com.google.protobuf.ProtocolMessageEnum {\n", |
82 "classname", descriptor_->name()); | 92 "classname", descriptor_->name()); |
83 printer->Annotate("classname", descriptor_); | |
84 printer->Indent(); | 93 printer->Indent(); |
85 | 94 |
86 bool ordinal_is_index = true; | 95 bool ordinal_is_index = true; |
87 string index_text = "ordinal()"; | 96 string index_text = "ordinal()"; |
88 for (int i = 0; i < canonical_values_.size(); i++) { | 97 for (int i = 0; i < canonical_values_.size(); i++) { |
89 if (canonical_values_[i]->index() != i) { | 98 if (canonical_values_[i]->index() != i) { |
90 ordinal_is_index = false; | 99 ordinal_is_index = false; |
91 index_text = "index"; | 100 index_text = "index"; |
92 break; | 101 break; |
93 } | 102 } |
94 } | 103 } |
95 | 104 |
96 for (int i = 0; i < canonical_values_.size(); i++) { | 105 for (int i = 0; i < canonical_values_.size(); i++) { |
97 std::map<string, string> vars; | 106 map<string, string> vars; |
98 vars["name"] = canonical_values_[i]->name(); | 107 vars["name"] = canonical_values_[i]->name(); |
99 vars["index"] = SimpleItoa(canonical_values_[i]->index()); | 108 vars["index"] = SimpleItoa(canonical_values_[i]->index()); |
100 vars["number"] = SimpleItoa(canonical_values_[i]->number()); | 109 vars["number"] = SimpleItoa(canonical_values_[i]->number()); |
101 WriteEnumValueDocComment(printer, canonical_values_[i]); | 110 WriteEnumValueDocComment(printer, canonical_values_[i]); |
102 if (canonical_values_[i]->options().deprecated()) { | 111 if (canonical_values_[i]->options().deprecated()) { |
103 printer->Print("@java.lang.Deprecated\n"); | 112 printer->Print("@java.lang.Deprecated\n"); |
104 } | 113 } |
105 if (ordinal_is_index) { | 114 if (ordinal_is_index) { |
106 printer->Print(vars, | 115 printer->Print(vars, |
107 "$name$($number$),\n"); | 116 "$name$($number$),\n"); |
(...skipping 11 matching lines...) Expand all Loading... |
119 } | 128 } |
120 } | 129 } |
121 | 130 |
122 printer->Print( | 131 printer->Print( |
123 ";\n" | 132 ";\n" |
124 "\n"); | 133 "\n"); |
125 | 134 |
126 // ----------------------------------------------------------------- | 135 // ----------------------------------------------------------------- |
127 | 136 |
128 for (int i = 0; i < aliases_.size(); i++) { | 137 for (int i = 0; i < aliases_.size(); i++) { |
129 std::map<string, string> vars; | 138 map<string, string> vars; |
130 vars["classname"] = descriptor_->name(); | 139 vars["classname"] = descriptor_->name(); |
131 vars["name"] = aliases_[i].value->name(); | 140 vars["name"] = aliases_[i].value->name(); |
132 vars["canonical_name"] = aliases_[i].canonical_value->name(); | 141 vars["canonical_name"] = aliases_[i].canonical_value->name(); |
133 WriteEnumValueDocComment(printer, aliases_[i].value); | 142 WriteEnumValueDocComment(printer, aliases_[i].value); |
134 printer->Print(vars, | 143 printer->Print(vars, |
135 "public static final $classname$ $name$ = $canonical_name$;\n"); | 144 "public static final $classname$ $name$ = $canonical_name$;\n"); |
136 } | 145 } |
137 | 146 |
138 for (int i = 0; i < descriptor_->value_count(); i++) { | 147 for (int i = 0; i < descriptor_->value_count(); i++) { |
139 std::map<string, string> vars; | 148 map<string, string> vars; |
140 vars["name"] = descriptor_->value(i)->name(); | 149 vars["name"] = descriptor_->value(i)->name(); |
141 vars["number"] = SimpleItoa(descriptor_->value(i)->number()); | 150 vars["number"] = SimpleItoa(descriptor_->value(i)->number()); |
142 WriteEnumValueDocComment(printer, descriptor_->value(i)); | 151 WriteEnumValueDocComment(printer, descriptor_->value(i)); |
143 printer->Print(vars, | 152 printer->Print(vars, |
144 "public static final int $name$_VALUE = $number$;\n"); | 153 "public static final int $name$_VALUE = $number$;\n"); |
145 } | 154 } |
146 printer->Print("\n"); | 155 printer->Print("\n"); |
147 | 156 |
148 // ----------------------------------------------------------------- | 157 // ----------------------------------------------------------------- |
149 | 158 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 " return getDescriptor();\n" | 234 " return getDescriptor();\n" |
226 "}\n" | 235 "}\n" |
227 "public static final com.google.protobuf.Descriptors.EnumDescriptor\n" | 236 "public static final com.google.protobuf.Descriptors.EnumDescriptor\n" |
228 " getDescriptor() {\n", | 237 " getDescriptor() {\n", |
229 "index_text", index_text); | 238 "index_text", index_text); |
230 | 239 |
231 // TODO(kenton): Cache statically? Note that we can't access descriptors | 240 // TODO(kenton): Cache statically? Note that we can't access descriptors |
232 // at module init time because it wouldn't work with descriptor.proto, but | 241 // at module init time because it wouldn't work with descriptor.proto, but |
233 // we can cache the value the first time getDescriptor() is called. | 242 // we can cache the value the first time getDescriptor() is called. |
234 if (descriptor_->containing_type() == NULL) { | 243 if (descriptor_->containing_type() == NULL) { |
235 // The class generated for the File fully populates the descriptor with | 244 if (!MultipleJavaFiles(descriptor_->file(), immutable_api_)) { |
236 // extensions in both the mutable and immutable cases. (In the mutable api | 245 printer->Print( |
237 // this is accomplished by attempting to load the immutable outer class). | 246 " return $file$.getDescriptor().getEnumTypes().get($index$);\n", |
238 printer->Print( | 247 "file", name_resolver_->GetClassName(descriptor_->file(), |
239 " return $file$.getDescriptor().getEnumTypes().get($index$);\n", | 248 immutable_api_), |
240 "file", name_resolver_->GetClassName(descriptor_->file(), | 249 "index", SimpleItoa(descriptor_->index())); |
241 immutable_api_), | 250 } else { |
242 "index", SimpleItoa(descriptor_->index())); | 251 printer->Indent(); |
| 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 } |
243 } else { | 287 } else { |
244 printer->Print( | 288 printer->Print( |
245 " return $parent$.$descriptor$.getEnumTypes().get($index$);\n", | 289 " return $parent$.$descriptor$.getEnumTypes().get($index$);\n", |
246 "parent", name_resolver_->GetClassName(descriptor_->containing_type(), | 290 "parent", name_resolver_->GetClassName(descriptor_->containing_type(), |
247 immutable_api_), | 291 immutable_api_), |
248 "descriptor", descriptor_->containing_type()->options() | 292 "descriptor", descriptor_->containing_type()->options() |
249 .no_standard_descriptor_accessor() | 293 .no_standard_descriptor_accessor() |
250 ? "getDefaultInstance().getDescriptorForType()" | 294 ? "getDefaultInstance().getDescriptorForType()" |
251 : "getDescriptor()", | 295 : "getDescriptor()", |
252 "index", SimpleItoa(descriptor_->index())); | 296 "index", SimpleItoa(descriptor_->index())); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 return false; | 386 return false; |
343 } | 387 } |
344 } | 388 } |
345 return true; | 389 return true; |
346 } | 390 } |
347 | 391 |
348 } // namespace java | 392 } // namespace java |
349 } // namespace compiler | 393 } // namespace compiler |
350 } // namespace protobuf | 394 } // namespace protobuf |
351 } // namespace google | 395 } // namespace google |
OLD | NEW |