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 |