LCOV - code coverage report
Current view: top level - third_party/protobuf/src/google/protobuf/compiler/java - java_enum.cc (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 0 95 0.0 %
Date: 2015-10-10 Functions: 0 5 0.0 %

          Line data    Source code
       1             : // Protocol Buffers - Google's data interchange format
       2             : // Copyright 2008 Google Inc.  All rights reserved.
       3             : // https://developers.google.com/protocol-buffers/
       4             : //
       5             : // Redistribution and use in source and binary forms, with or without
       6             : // modification, are permitted provided that the following conditions are
       7             : // met:
       8             : //
       9             : //     * Redistributions of source code must retain the above copyright
      10             : // notice, this list of conditions and the following disclaimer.
      11             : //     * Redistributions in binary form must reproduce the above
      12             : // copyright notice, this list of conditions and the following disclaimer
      13             : // in the documentation and/or other materials provided with the
      14             : // distribution.
      15             : //     * Neither the name of Google Inc. nor the names of its
      16             : // contributors may be used to endorse or promote products derived from
      17             : // this software without specific prior written permission.
      18             : //
      19             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      20             : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      21             : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      22             : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      23             : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      24             : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      25             : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      26             : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      27             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      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.
      30             : 
      31             : // Author: kenton@google.com (Kenton Varda)
      32             : //  Based on original Protocol Buffers design by
      33             : //  Sanjay Ghemawat, Jeff Dean, and others.
      34             : 
      35             : #include <map>
      36             : #include <string>
      37             : 
      38             : #include <google/protobuf/compiler/java/java_context.h>
      39             : #include <google/protobuf/compiler/java/java_enum.h>
      40             : #include <google/protobuf/compiler/java/java_doc_comment.h>
      41             : #include <google/protobuf/compiler/java/java_helpers.h>
      42             : #include <google/protobuf/compiler/java/java_name_resolver.h>
      43             : #include <google/protobuf/io/printer.h>
      44             : #include <google/protobuf/descriptor.pb.h>
      45             : #include <google/protobuf/stubs/strutil.h>
      46             : 
      47             : namespace google {
      48             : namespace protobuf {
      49             : namespace compiler {
      50             : namespace java {
      51             : 
      52             : namespace {
      53           0 : bool EnumHasCustomOptions(const EnumDescriptor* descriptor) {
      54           0 :   if (descriptor->options().unknown_fields().field_count() > 0) return true;
      55           0 :   for (int i = 0; i < descriptor->value_count(); ++i) {
      56           0 :     const EnumValueDescriptor* value = descriptor->value(i);
      57           0 :     if (value->options().unknown_fields().field_count() > 0) return true;
      58             :   }
      59             :   return false;
      60             : }
      61             : }  // namespace
      62             : 
      63           0 : EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
      64             :                              bool immutable_api,
      65             :                              Context* context)
      66             :   : descriptor_(descriptor), immutable_api_(immutable_api),
      67           0 :     name_resolver_(context->GetNameResolver())  {
      68           0 :   for (int i = 0; i < descriptor_->value_count(); i++) {
      69           0 :     const EnumValueDescriptor* value = descriptor_->value(i);
      70             :     const EnumValueDescriptor* canonical_value =
      71           0 :       descriptor_->FindValueByNumber(value->number());
      72             : 
      73           0 :     if (value == canonical_value) {
      74           0 :       canonical_values_.push_back(value);
      75             :     } else {
      76             :       Alias alias;
      77           0 :       alias.value = value;
      78           0 :       alias.canonical_value = canonical_value;
      79           0 :       aliases_.push_back(alias);
      80             :     }
      81             :   }
      82           0 : }
      83             : 
      84           0 : EnumGenerator::~EnumGenerator() {}
      85             : 
      86           0 : void EnumGenerator::Generate(io::Printer* printer) {
      87           0 :   WriteEnumDocComment(printer, descriptor_);
      88           0 :   if (HasDescriptorMethods(descriptor_)) {
      89             :     printer->Print(
      90             :       "public enum $classname$\n"
      91             :       "    implements com.google.protobuf.ProtocolMessageEnum {\n",
      92           0 :       "classname", descriptor_->name());
      93             :   } else {
      94             :     printer->Print(
      95             :       "public enum $classname$\n"
      96             :       "    implements com.google.protobuf.Internal.EnumLite {\n",
      97           0 :       "classname", descriptor_->name());
      98             :   }
      99           0 :   printer->Indent();
     100             : 
     101           0 :   for (int i = 0; i < canonical_values_.size(); i++) {
     102             :     map<string, string> vars;
     103           0 :     vars["name"] = canonical_values_[i]->name();
     104           0 :     vars["index"] = SimpleItoa(canonical_values_[i]->index());
     105           0 :     vars["number"] = SimpleItoa(canonical_values_[i]->number());
     106           0 :     WriteEnumValueDocComment(printer, canonical_values_[i]);
     107           0 :     if (canonical_values_[i]->options().deprecated()) {
     108           0 :       printer->Print("@java.lang.Deprecated\n");
     109             :     }
     110             :     printer->Print(vars,
     111           0 :       "$name$($index$, $number$),\n");
     112             :   }
     113             : 
     114           0 :   if (SupportUnknownEnumValue(descriptor_->file())) {
     115           0 :     printer->Print("UNRECOGNIZED(-1, -1),\n");
     116             :   }
     117             : 
     118             :   printer->Print(
     119             :     ";\n"
     120           0 :     "\n");
     121             : 
     122             :   // -----------------------------------------------------------------
     123             : 
     124           0 :   for (int i = 0; i < aliases_.size(); i++) {
     125             :     map<string, string> vars;
     126           0 :     vars["classname"] = descriptor_->name();
     127           0 :     vars["name"] = aliases_[i].value->name();
     128           0 :     vars["canonical_name"] = aliases_[i].canonical_value->name();
     129           0 :     WriteEnumValueDocComment(printer, aliases_[i].value);
     130             :     printer->Print(vars,
     131           0 :       "public static final $classname$ $name$ = $canonical_name$;\n");
     132             :   }
     133             : 
     134           0 :   for (int i = 0; i < descriptor_->value_count(); i++) {
     135             :     map<string, string> vars;
     136           0 :     vars["name"] = descriptor_->value(i)->name();
     137           0 :     vars["number"] = SimpleItoa(descriptor_->value(i)->number());
     138           0 :     WriteEnumValueDocComment(printer, descriptor_->value(i));
     139             :     printer->Print(vars,
     140           0 :       "public static final int $name$_VALUE = $number$;\n");
     141             :   }
     142           0 :   printer->Print("\n");
     143             : 
     144             :   // -----------------------------------------------------------------
     145             : 
     146             :   printer->Print(
     147             :     "\n"
     148           0 :     "public final int getNumber() {\n");
     149           0 :   if (SupportUnknownEnumValue(descriptor_->file())) {
     150             :     printer->Print(
     151             :       "  if (index == -1) {\n"
     152             :       "    throw new java.lang.IllegalArgumentException(\n"
     153             :       "        \"Can't get the number of an unknown enum value.\");\n"
     154           0 :       "  }\n");
     155             :   }
     156             :   printer->Print(
     157             :     "  return value;\n"
     158             :     "}\n"
     159             :     "\n"
     160             :     "public static $classname$ valueOf(int value) {\n"
     161             :     "  switch (value) {\n",
     162           0 :     "classname", descriptor_->name());
     163           0 :   printer->Indent();
     164           0 :   printer->Indent();
     165             : 
     166           0 :   for (int i = 0; i < canonical_values_.size(); i++) {
     167             :     printer->Print(
     168             :       "case $number$: return $name$;\n",
     169           0 :       "name", canonical_values_[i]->name(),
     170           0 :       "number", SimpleItoa(canonical_values_[i]->number()));
     171             :   }
     172             : 
     173           0 :   printer->Outdent();
     174           0 :   printer->Outdent();
     175             :   printer->Print(
     176             :     "    default: return null;\n"
     177             :     "  }\n"
     178             :     "}\n"
     179             :     "\n"
     180             :     "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n"
     181             :     "    internalGetValueMap() {\n"
     182             :     "  return internalValueMap;\n"
     183             :     "}\n"
     184             :     "private static final com.google.protobuf.Internal.EnumLiteMap<\n"
     185             :     "    $classname$> internalValueMap =\n"
     186             :     "      new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
     187             :     "        public $classname$ findValueByNumber(int number) {\n"
     188             :     "          return $classname$.valueOf(number);\n"
     189             :     "        }\n"
     190             :     "      };\n"
     191             :     "\n",
     192           0 :     "classname", descriptor_->name());
     193             : 
     194             :   // -----------------------------------------------------------------
     195             :   // Reflection
     196             : 
     197           0 :   if (HasDescriptorMethods(descriptor_)) {
     198             :     printer->Print(
     199             :       "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n"
     200             :       "    getValueDescriptor() {\n"
     201             :       "  return getDescriptor().getValues().get(index);\n"
     202             :       "}\n"
     203             :       "public final com.google.protobuf.Descriptors.EnumDescriptor\n"
     204             :       "    getDescriptorForType() {\n"
     205             :       "  return getDescriptor();\n"
     206             :       "}\n"
     207             :       "public static final com.google.protobuf.Descriptors.EnumDescriptor\n"
     208           0 :       "    getDescriptor() {\n");
     209             : 
     210             :     // TODO(kenton):  Cache statically?  Note that we can't access descriptors
     211             :     //   at module init time because it wouldn't work with descriptor.proto, but
     212             :     //   we can cache the value the first time getDescriptor() is called.
     213           0 :     if (descriptor_->containing_type() == NULL) {
     214           0 :       if (!MultipleJavaFiles(descriptor_->file(), immutable_api_)) {
     215             :         printer->Print(
     216             :           "  return $file$.getDescriptor().getEnumTypes().get($index$);\n",
     217             :           "file", name_resolver_->GetClassName(descriptor_->file(),
     218             :                                                immutable_api_),
     219           0 :           "index", SimpleItoa(descriptor_->index()));
     220             :       } else {
     221           0 :         printer->Indent();
     222           0 :         if (EnumHasCustomOptions(descriptor_)) {
     223             :           // We need to load the immutable classes in order to parse custom
     224             :           // options. However, since file level enums (no outer class) are
     225             :           // shared by immutable code and mutable code, the immutable classes
     226             :           // may not exist. So we try to use Java reflection to retrieve the
     227             :           // descriptor from immutable classes.
     228             :           printer->Print(
     229             :             "try {\n"
     230             :             "  java.lang.Class immutableFileClass =\n"
     231             :             "      java.lang.Class.forName(\"$immutable_file_class_name$\");\n"
     232             :             "  @java.lang.SuppressWarnings(\"unchecked\")\n"
     233             :             "  java.lang.reflect.Method m =\n"
     234             :             "      immutableFileClass.getMethod(\"getDescriptor\");\n"
     235             :             "  com.google.protobuf.Descriptors.FileDescriptor file =\n"
     236             :             "      (com.google.protobuf.Descriptors.FileDescriptor)\n"
     237             :             "          m.invoke(immutableFileClass);\n"
     238             :             "  return file.getEnumTypes().get($index$);\n"
     239             :             "} catch (Exception e) {\n"
     240             :             // Immutable classes cannot be found. Proceed as if custom options
     241             :             // don't exist.
     242             :             "}\n",
     243             :             "immutable_file_class_name",
     244             :             name_resolver_->GetImmutableClassName(descriptor_->file()),
     245           0 :             "index", SimpleItoa(descriptor_->index()));
     246             :         }
     247             :         printer->Print(
     248             :           "return $immutable_package$.$descriptor_class$.$descriptor$\n"
     249             :           "    .getEnumTypes().get($index$);\n",
     250             :           "immutable_package", FileJavaPackage(descriptor_->file(), true),
     251             :           "descriptor_class",
     252             :           name_resolver_->GetDescriptorClassName(descriptor_->file()),
     253             :           "descriptor", "getDescriptor()",
     254           0 :           "index", SimpleItoa(descriptor_->index()));
     255           0 :         printer->Outdent();
     256             :       }
     257             :     } else {
     258             :       printer->Print(
     259             :           "  return $parent$.$descriptor$.getEnumTypes().get($index$);\n",
     260             :           "parent", name_resolver_->GetClassName(descriptor_->containing_type(),
     261             :                                                  immutable_api_),
     262           0 :           "descriptor", descriptor_->containing_type()->options()
     263           0 :                         .no_standard_descriptor_accessor()
     264             :                         ? "getDefaultInstance().getDescriptorForType()"
     265             :                         : "getDescriptor()",
     266           0 :           "index", SimpleItoa(descriptor_->index()));
     267             :     }
     268             : 
     269             :     printer->Print(
     270             :       "}\n"
     271             :       "\n"
     272             :       "private static final $classname$[] VALUES = ",
     273           0 :       "classname", descriptor_->name());
     274             : 
     275           0 :     if (CanUseEnumValues()) {
     276             :       // If the constants we are going to output are exactly the ones we
     277             :       // have declared in the Java enum in the same order, then we can use
     278             :       // the values() method that the Java compiler automatically generates
     279             :       // for every enum.
     280           0 :       printer->Print("values();\n");
     281             :     } else {
     282             :       printer->Print(
     283             :         "{\n"
     284           0 :         "  ");
     285           0 :       for (int i = 0; i < descriptor_->value_count(); i++) {
     286             :         printer->Print("$name$, ",
     287           0 :           "name", descriptor_->value(i)->name());
     288             :       }
     289             :       printer->Print(
     290             :           "\n"
     291           0 :           "};\n");
     292             :     }
     293             : 
     294             :     printer->Print(
     295             :       "\n"
     296             :       "public static $classname$ valueOf(\n"
     297             :       "    com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n"
     298             :       "  if (desc.getType() != getDescriptor()) {\n"
     299             :       "    throw new java.lang.IllegalArgumentException(\n"
     300             :       "      \"EnumValueDescriptor is not for this type.\");\n"
     301             :       "  }\n",
     302           0 :       "classname", descriptor_->name());
     303           0 :     if (SupportUnknownEnumValue(descriptor_->file())) {
     304             :       printer->Print(
     305             :         "  if (desc.getIndex() == -1) {\n"
     306             :         "    return UNRECOGNIZED;\n"
     307           0 :         "  }\n");
     308             :     }
     309             :     printer->Print(
     310             :       "  return VALUES[desc.getIndex()];\n"
     311             :       "}\n"
     312           0 :       "\n");
     313             : 
     314             :     // index is only used for reflection; lite implementation does not need it
     315           0 :     printer->Print("private final int index;\n");
     316             :   }
     317             : 
     318             :   // -----------------------------------------------------------------
     319             : 
     320             :   printer->Print(
     321             :     "private final int value;\n\n"
     322             :     "private $classname$(int index, int value) {\n",
     323           0 :     "classname", descriptor_->name());
     324           0 :   if (HasDescriptorMethods(descriptor_)) {
     325           0 :     printer->Print("  this.index = index;\n");
     326             :   }
     327             :   printer->Print(
     328             :     "  this.value = value;\n"
     329           0 :     "}\n");
     330             : 
     331             :   printer->Print(
     332             :     "\n"
     333             :     "// @@protoc_insertion_point(enum_scope:$full_name$)\n",
     334           0 :     "full_name", descriptor_->full_name());
     335             : 
     336           0 :   printer->Outdent();
     337           0 :   printer->Print("}\n\n");
     338           0 : }
     339             : 
     340           0 : bool EnumGenerator::CanUseEnumValues() {
     341           0 :   if (canonical_values_.size() != descriptor_->value_count()) {
     342             :     return false;
     343             :   }
     344           0 :   for (int i = 0; i < descriptor_->value_count(); i++) {
     345           0 :     if (descriptor_->value(i)->name() != canonical_values_[i]->name()) {
     346             :       return false;
     347             :     }
     348             :   }
     349             :   return true;
     350             : }
     351             : 
     352             : }  // namespace java
     353             : }  // namespace compiler
     354             : }  // namespace protobuf
     355             : }  // namespace google

Generated by: LCOV version 1.10