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 // http://code.google.com/p/protobuf/ | 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. |
11 // * Redistributions in binary form must reproduce the above | 11 // * Redistributions in binary form must reproduce the above |
12 // copyright notice, this list of conditions and the following disclaimer | 12 // copyright notice, this list of conditions and the following disclaimer |
13 // in the documentation and/or other materials provided with the | 13 // in the documentation and/or other materials provided with the |
(...skipping 14 matching lines...) Expand all Loading... |
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | 30 |
31 // Author: kenton@google.com (Kenton Varda) | 31 // Author: kenton@google.com (Kenton Varda) |
32 // Based on original Protocol Buffers design by | 32 // Based on original Protocol Buffers design by |
33 // Sanjay Ghemawat, Jeff Dean, and others. | 33 // Sanjay Ghemawat, Jeff Dean, and others. |
34 | 34 |
35 #include <map> | 35 #include <map> |
36 #include <string> | 36 #include <string> |
37 | 37 |
38 #include <google/protobuf/compiler/java/java_enum.h> | 38 #include <google/protobuf/compiler/java/java_context.h> |
| 39 #include <google/protobuf/compiler/java/java_enum_lite.h> |
39 #include <google/protobuf/compiler/java/java_doc_comment.h> | 40 #include <google/protobuf/compiler/java/java_doc_comment.h> |
40 #include <google/protobuf/compiler/java/java_helpers.h> | 41 #include <google/protobuf/compiler/java/java_helpers.h> |
| 42 #include <google/protobuf/compiler/java/java_name_resolver.h> |
41 #include <google/protobuf/io/printer.h> | 43 #include <google/protobuf/io/printer.h> |
42 #include <google/protobuf/descriptor.pb.h> | 44 #include <google/protobuf/descriptor.pb.h> |
43 #include <google/protobuf/stubs/strutil.h> | 45 #include <google/protobuf/stubs/strutil.h> |
44 | 46 |
45 namespace google { | 47 namespace google { |
46 namespace protobuf { | 48 namespace protobuf { |
47 namespace compiler { | 49 namespace compiler { |
48 namespace java { | 50 namespace java { |
49 | 51 |
50 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) | 52 namespace { |
51 : descriptor_(descriptor) { | 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 EnumLiteGenerator::EnumLiteGenerator(const EnumDescriptor* descriptor, |
| 64 bool immutable_api, |
| 65 Context* context) |
| 66 : descriptor_(descriptor), immutable_api_(immutable_api), |
| 67 name_resolver_(context->GetNameResolver()) { |
52 for (int i = 0; i < descriptor_->value_count(); i++) { | 68 for (int i = 0; i < descriptor_->value_count(); i++) { |
53 const EnumValueDescriptor* value = descriptor_->value(i); | 69 const EnumValueDescriptor* value = descriptor_->value(i); |
54 const EnumValueDescriptor* canonical_value = | 70 const EnumValueDescriptor* canonical_value = |
55 descriptor_->FindValueByNumber(value->number()); | 71 descriptor_->FindValueByNumber(value->number()); |
56 | 72 |
57 if (value == canonical_value) { | 73 if (value == canonical_value) { |
58 canonical_values_.push_back(value); | 74 canonical_values_.push_back(value); |
59 } else { | 75 } else { |
60 Alias alias; | 76 Alias alias; |
61 alias.value = value; | 77 alias.value = value; |
62 alias.canonical_value = canonical_value; | 78 alias.canonical_value = canonical_value; |
63 aliases_.push_back(alias); | 79 aliases_.push_back(alias); |
64 } | 80 } |
65 } | 81 } |
66 } | 82 } |
67 | 83 |
68 EnumGenerator::~EnumGenerator() {} | 84 EnumLiteGenerator::~EnumLiteGenerator() {} |
69 | 85 |
70 void EnumGenerator::Generate(io::Printer* printer) { | 86 void EnumLiteGenerator::Generate(io::Printer* printer) { |
71 WriteEnumDocComment(printer, descriptor_); | 87 WriteEnumDocComment(printer, descriptor_); |
72 if (HasDescriptorMethods(descriptor_)) { | 88 printer->Print( |
73 printer->Print( | 89 "public enum $classname$\n" |
74 "public enum $classname$\n" | 90 " implements com.google.protobuf.Internal.EnumLite {\n", |
75 " implements com.google.protobuf.ProtocolMessageEnum {\n", | 91 "classname", descriptor_->name()); |
76 "classname", descriptor_->name()); | |
77 } else { | |
78 printer->Print( | |
79 "public enum $classname$\n" | |
80 " implements com.google.protobuf.Internal.EnumLite {\n", | |
81 "classname", descriptor_->name()); | |
82 } | |
83 printer->Indent(); | 92 printer->Indent(); |
84 | 93 |
85 for (int i = 0; i < canonical_values_.size(); i++) { | 94 for (int i = 0; i < canonical_values_.size(); i++) { |
86 map<string, string> vars; | 95 map<string, string> vars; |
87 vars["name"] = canonical_values_[i]->name(); | 96 vars["name"] = canonical_values_[i]->name(); |
88 vars["index"] = SimpleItoa(canonical_values_[i]->index()); | |
89 vars["number"] = SimpleItoa(canonical_values_[i]->number()); | 97 vars["number"] = SimpleItoa(canonical_values_[i]->number()); |
90 WriteEnumValueDocComment(printer, canonical_values_[i]); | 98 WriteEnumValueDocComment(printer, canonical_values_[i]); |
| 99 if (canonical_values_[i]->options().deprecated()) { |
| 100 printer->Print("@java.lang.Deprecated\n"); |
| 101 } |
91 printer->Print(vars, | 102 printer->Print(vars, |
92 "$name$($index$, $number$),\n"); | 103 "$name$($number$),\n"); |
| 104 } |
| 105 |
| 106 if (SupportUnknownEnumValue(descriptor_->file())) { |
| 107 printer->Print("UNRECOGNIZED(-1),\n"); |
93 } | 108 } |
94 | 109 |
95 printer->Print( | 110 printer->Print( |
96 ";\n" | 111 ";\n" |
97 "\n"); | 112 "\n"); |
98 | 113 |
99 // ----------------------------------------------------------------- | 114 // ----------------------------------------------------------------- |
100 | 115 |
101 for (int i = 0; i < aliases_.size(); i++) { | 116 for (int i = 0; i < aliases_.size(); i++) { |
102 map<string, string> vars; | 117 map<string, string> vars; |
(...skipping 12 matching lines...) Expand all Loading... |
115 WriteEnumValueDocComment(printer, descriptor_->value(i)); | 130 WriteEnumValueDocComment(printer, descriptor_->value(i)); |
116 printer->Print(vars, | 131 printer->Print(vars, |
117 "public static final int $name$_VALUE = $number$;\n"); | 132 "public static final int $name$_VALUE = $number$;\n"); |
118 } | 133 } |
119 printer->Print("\n"); | 134 printer->Print("\n"); |
120 | 135 |
121 // ----------------------------------------------------------------- | 136 // ----------------------------------------------------------------- |
122 | 137 |
123 printer->Print( | 138 printer->Print( |
124 "\n" | 139 "\n" |
125 "public final int getNumber() { return value; }\n" | 140 "public final int getNumber() {\n" |
| 141 " return value;\n" |
| 142 "}\n" |
126 "\n" | 143 "\n" |
127 "public static $classname$ valueOf(int value) {\n" | 144 "public static $classname$ valueOf(int value) {\n" |
128 " switch (value) {\n", | 145 " switch (value) {\n", |
129 "classname", descriptor_->name()); | 146 "classname", descriptor_->name()); |
130 printer->Indent(); | 147 printer->Indent(); |
131 printer->Indent(); | 148 printer->Indent(); |
132 | 149 |
133 for (int i = 0; i < canonical_values_.size(); i++) { | 150 for (int i = 0; i < canonical_values_.size(); i++) { |
134 printer->Print( | 151 printer->Print( |
135 "case $number$: return $name$;\n", | 152 "case $number$: return $name$;\n", |
136 "name", canonical_values_[i]->name(), | 153 "name", canonical_values_[i]->name(), |
137 "number", SimpleItoa(canonical_values_[i]->number())); | 154 "number", SimpleItoa(canonical_values_[i]->number())); |
138 } | 155 } |
139 | 156 |
140 printer->Outdent(); | 157 printer->Outdent(); |
141 printer->Outdent(); | 158 printer->Outdent(); |
142 printer->Print( | 159 printer->Print( |
143 " default: return null;\n" | 160 " default: return null;\n" |
144 " }\n" | 161 " }\n" |
145 "}\n" | 162 "}\n" |
146 "\n" | 163 "\n" |
147 "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" | 164 "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" |
148 " internalGetValueMap() {\n" | 165 " internalGetValueMap() {\n" |
149 " return internalValueMap;\n" | 166 " return internalValueMap;\n" |
150 "}\n" | 167 "}\n" |
151 "private static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" | 168 "private static final com.google.protobuf.Internal.EnumLiteMap<\n" |
152 " internalValueMap =\n" | 169 " $classname$> internalValueMap =\n" |
153 " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" | 170 " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" |
154 " public $classname$ findValueByNumber(int number) {\n" | 171 " public $classname$ findValueByNumber(int number) {\n" |
155 " return $classname$.valueOf(number);\n" | 172 " return $classname$.valueOf(number);\n" |
156 " }\n" | 173 " }\n" |
157 " };\n" | 174 " };\n" |
158 "\n", | 175 "\n", |
159 "classname", descriptor_->name()); | 176 "classname", descriptor_->name()); |
160 | 177 |
161 // ----------------------------------------------------------------- | |
162 // Reflection | |
163 | |
164 if (HasDescriptorMethods(descriptor_)) { | |
165 printer->Print( | |
166 "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n" | |
167 " getValueDescriptor() {\n" | |
168 " return getDescriptor().getValues().get(index);\n" | |
169 "}\n" | |
170 "public final com.google.protobuf.Descriptors.EnumDescriptor\n" | |
171 " getDescriptorForType() {\n" | |
172 " return getDescriptor();\n" | |
173 "}\n" | |
174 "public static final com.google.protobuf.Descriptors.EnumDescriptor\n" | |
175 " getDescriptor() {\n"); | |
176 | |
177 // TODO(kenton): Cache statically? Note that we can't access descriptors | |
178 // at module init time because it wouldn't work with descriptor.proto, but | |
179 // we can cache the value the first time getDescriptor() is called. | |
180 if (descriptor_->containing_type() == NULL) { | |
181 printer->Print( | |
182 " return $file$.getDescriptor().getEnumTypes().get($index$);\n", | |
183 "file", ClassName(descriptor_->file()), | |
184 "index", SimpleItoa(descriptor_->index())); | |
185 } else { | |
186 printer->Print( | |
187 " return $parent$.getDescriptor().getEnumTypes().get($index$);\n", | |
188 "parent", ClassName(descriptor_->containing_type()), | |
189 "index", SimpleItoa(descriptor_->index())); | |
190 } | |
191 | |
192 printer->Print( | |
193 "}\n" | |
194 "\n" | |
195 "private static final $classname$[] VALUES = ", | |
196 "classname", descriptor_->name()); | |
197 | |
198 if (CanUseEnumValues()) { | |
199 // If the constants we are going to output are exactly the ones we | |
200 // have declared in the Java enum in the same order, then we can use | |
201 // the values() method that the Java compiler automatically generates | |
202 // for every enum. | |
203 printer->Print("values();\n"); | |
204 } else { | |
205 printer->Print( | |
206 "{\n" | |
207 " "); | |
208 for (int i = 0; i < descriptor_->value_count(); i++) { | |
209 printer->Print("$name$, ", | |
210 "name", descriptor_->value(i)->name()); | |
211 } | |
212 printer->Print( | |
213 "\n" | |
214 "};\n"); | |
215 } | |
216 | |
217 printer->Print( | |
218 "\n" | |
219 "public static $classname$ valueOf(\n" | |
220 " com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n" | |
221 " if (desc.getType() != getDescriptor()) {\n" | |
222 " throw new java.lang.IllegalArgumentException(\n" | |
223 " \"EnumValueDescriptor is not for this type.\");\n" | |
224 " }\n" | |
225 " return VALUES[desc.getIndex()];\n" | |
226 "}\n" | |
227 "\n", | |
228 "classname", descriptor_->name()); | |
229 | |
230 // index is only used for reflection; lite implementation does not need it | |
231 printer->Print("private final int index;\n"); | |
232 } | |
233 | |
234 // ----------------------------------------------------------------- | |
235 | |
236 printer->Print( | 178 printer->Print( |
237 "private final int value;\n\n" | 179 "private final int value;\n\n" |
238 "private $classname$(int index, int value) {\n", | 180 "private $classname$(int value) {\n", |
239 "classname", descriptor_->name()); | 181 "classname", descriptor_->name()); |
240 if (HasDescriptorMethods(descriptor_)) { | |
241 printer->Print(" this.index = index;\n"); | |
242 } | |
243 printer->Print( | 182 printer->Print( |
244 " this.value = value;\n" | 183 " this.value = value;\n" |
245 "}\n"); | 184 "}\n"); |
246 | 185 |
247 printer->Print( | 186 printer->Print( |
248 "\n" | 187 "\n" |
249 "// @@protoc_insertion_point(enum_scope:$full_name$)\n", | 188 "// @@protoc_insertion_point(enum_scope:$full_name$)\n", |
250 "full_name", descriptor_->full_name()); | 189 "full_name", descriptor_->full_name()); |
251 | 190 |
252 printer->Outdent(); | 191 printer->Outdent(); |
253 printer->Print("}\n\n"); | 192 printer->Print("}\n\n"); |
254 } | 193 } |
255 | 194 |
256 bool EnumGenerator::CanUseEnumValues() { | 195 bool EnumLiteGenerator::CanUseEnumValues() { |
257 if (canonical_values_.size() != descriptor_->value_count()) { | 196 if (canonical_values_.size() != descriptor_->value_count()) { |
258 return false; | 197 return false; |
259 } | 198 } |
260 for (int i = 0; i < descriptor_->value_count(); i++) { | 199 for (int i = 0; i < descriptor_->value_count(); i++) { |
261 if (descriptor_->value(i)->name() != canonical_values_[i]->name()) { | 200 if (descriptor_->value(i)->name() != canonical_values_[i]->name()) { |
262 return false; | 201 return false; |
263 } | 202 } |
264 } | 203 } |
265 return true; | 204 return true; |
266 } | 205 } |
267 | 206 |
268 } // namespace java | 207 } // namespace java |
269 } // namespace compiler | 208 } // namespace compiler |
270 } // namespace protobuf | 209 } // namespace protobuf |
271 } // namespace google | 210 } // namespace google |
OLD | NEW |