Home | History | Annotate | Download | only in objectivec
      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 #include <iostream>
     32 
     33 #include <google/protobuf/compiler/objectivec/objectivec_extension.h>
     34 #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
     35 #include <google/protobuf/descriptor.pb.h>
     36 #include <google/protobuf/stubs/strutil.h>
     37 #include <google/protobuf/io/printer.h>
     38 
     39 namespace google {
     40 namespace protobuf {
     41 namespace compiler {
     42 namespace objectivec {
     43 
     44 ExtensionGenerator::ExtensionGenerator(const string& root_class_name,
     45                                        const FieldDescriptor* descriptor)
     46     : method_name_(ExtensionMethodName(descriptor)),
     47       root_class_and_method_name_(root_class_name + "_" + method_name_),
     48       descriptor_(descriptor) {
     49   if (descriptor->is_map()) {
     50     // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
     51     // error cases, so it seems to be ok to use as a back door for errors.
     52     cerr << "error: Extension is a map<>!"
     53          << " That used to be blocked by the compiler." << endl;
     54     cerr.flush();
     55     abort();
     56   }
     57 }
     58 
     59 ExtensionGenerator::~ExtensionGenerator() {}
     60 
     61 void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) {
     62   map<string, string> vars;
     63   vars["method_name"] = method_name_;
     64   SourceLocation location;
     65   if (descriptor_->GetSourceLocation(&location)) {
     66     vars["comments"] = BuildCommentsString(location);
     67   } else {
     68     vars["comments"] = "";
     69   }
     70   printer->Print(vars,
     71                  "$comments$"
     72                  "+ (GPBExtensionDescriptor *)$method_name$;\n");
     73 }
     74 
     75 void ExtensionGenerator::GenerateStaticVariablesInitialization(
     76     io::Printer* printer) {
     77   map<string, string> vars;
     78   vars["root_class_and_method_name"] = root_class_and_method_name_;
     79   vars["extended_type"] = ClassName(descriptor_->containing_type());
     80   vars["number"] = SimpleItoa(descriptor_->number());
     81 
     82   std::vector<string> options;
     83   if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated");
     84   if (descriptor_->is_packed()) options.push_back("GPBExtensionPacked");
     85   if (descriptor_->containing_type()->options().message_set_wire_format())
     86     options.push_back("GPBExtensionSetWireFormat");
     87 
     88   vars["options"] = BuildFlagsString(options);
     89 
     90   ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
     91   string singular_type;
     92   if (objc_type == OBJECTIVECTYPE_MESSAGE) {
     93     vars["type"] = string("GPBStringifySymbol(") +
     94                    ClassName(descriptor_->message_type()) + ")";
     95   } else {
     96     vars["type"] = "NULL";
     97   }
     98 
     99   vars["default_name"] = GPBGenericValueFieldName(descriptor_);
    100   if (descriptor_->is_repeated()) {
    101     vars["default"] = "nil";
    102   } else {
    103     vars["default"] = DefaultValue(descriptor_);
    104   }
    105   string type = GetCapitalizedType(descriptor_);
    106   vars["extension_type"] = string("GPBDataType") + type;
    107 
    108   if (objc_type == OBJECTIVECTYPE_ENUM) {
    109     vars["enum_desc_func_name"] =
    110          EnumName(descriptor_->enum_type()) + "_EnumDescriptor";
    111   } else {
    112     vars["enum_desc_func_name"] = "NULL";
    113   }
    114 
    115   printer->Print(vars,
    116                  "{\n"
    117                  "  .defaultValue.$default_name$ = $default$,\n"
    118                  "  .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
    119                  "  .extendedClass = GPBStringifySymbol($extended_type$),\n"
    120                  "  .messageOrGroupClassName = $type$,\n"
    121                  "  .enumDescriptorFunc = $enum_desc_func_name$,\n"
    122                  "  .fieldNumber = $number$,\n"
    123                  "  .dataType = $extension_type$,\n"
    124                  "  .options = $options$,\n"
    125                  "},\n");
    126 }
    127 
    128 void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) {
    129   printer->Print(
    130       "[registry addExtension:$root_class_and_method_name$];\n",
    131       "root_class_and_method_name", root_class_and_method_name_);
    132 }
    133 }  // namespace objectivec
    134 }  // namespace compiler
    135 }  // namespace protobuf
    136 }  // namespace google
    137