| 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 |