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_field.h>
     34 #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
     35 #include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
     36 #include <google/protobuf/compiler/objectivec/objectivec_map_field.h>
     37 #include <google/protobuf/compiler/objectivec/objectivec_message_field.h>
     38 #include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h>
     39 #include <google/protobuf/io/printer.h>
     40 #include <google/protobuf/wire_format.h>
     41 #include <google/protobuf/stubs/common.h>
     42 #include <google/protobuf/stubs/strutil.h>
     43 
     44 namespace google {
     45 namespace protobuf {
     46 namespace compiler {
     47 namespace objectivec {
     48 
     49 namespace {
     50 
     51 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
     52                              map<string, string>* variables) {
     53   string camel_case_name = FieldName(descriptor);
     54   string raw_field_name;
     55   if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
     56     raw_field_name = descriptor->message_type()->name();
     57   } else {
     58     raw_field_name = descriptor->name();
     59   }
     60   // The logic here has to match -[GGPBFieldDescriptor textFormatName].
     61   const string un_camel_case_name(
     62       UnCamelCaseFieldName(camel_case_name, descriptor));
     63   const bool needs_custom_name = (raw_field_name != un_camel_case_name);
     64 
     65   SourceLocation location;
     66   if (descriptor->GetSourceLocation(&location)) {
     67     (*variables)["comments"] = BuildCommentsString(location);
     68   } else {
     69     (*variables)["comments"] = "\n";
     70   }
     71   const string& classname = ClassName(descriptor->containing_type());
     72   (*variables)["classname"] = classname;
     73   (*variables)["name"] = camel_case_name;
     74   const string& capitalized_name = FieldNameCapitalized(descriptor);
     75   (*variables)["capitalized_name"] = capitalized_name;
     76   (*variables)["raw_field_name"] = raw_field_name;
     77   (*variables)["field_number_name"] =
     78       classname + "_FieldNumber_" + capitalized_name;
     79   (*variables)["field_number"] = SimpleItoa(descriptor->number());
     80   (*variables)["field_type"] = GetCapitalizedType(descriptor);
     81   (*variables)["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor);
     82   std::vector<string> field_flags;
     83   if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
     84   if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired");
     85   if (descriptor->is_optional()) field_flags.push_back("GPBFieldOptional");
     86   if (descriptor->is_packed()) field_flags.push_back("GPBFieldPacked");
     87 
     88   // ObjC custom flags.
     89   if (descriptor->has_default_value())
     90     field_flags.push_back("GPBFieldHasDefaultValue");
     91   if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom");
     92   if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
     93     field_flags.push_back("GPBFieldHasEnumDescriptor");
     94   }
     95 
     96   (*variables)["fieldflags"] = BuildFlagsString(field_flags);
     97 
     98   (*variables)["default"] = DefaultValue(descriptor);
     99   (*variables)["default_name"] = GPBGenericValueFieldName(descriptor);
    100 
    101   (*variables)["dataTypeSpecific_name"] = "className";
    102   (*variables)["dataTypeSpecific_value"] = "NULL";
    103 
    104   (*variables)["storage_offset_value"] =
    105       "(uint32_t)offsetof(" + classname + "__storage_, " + camel_case_name + ")";
    106   (*variables)["storage_offset_comment"] = "";
    107 
    108   // Clear some common things so they can be set just when needed.
    109   (*variables)["storage_attribute"] = "";
    110 }
    111 
    112 }  // namespace
    113 
    114 FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
    115                                      const Options& options) {
    116   FieldGenerator* result = NULL;
    117   if (field->is_repeated()) {
    118     switch (GetObjectiveCType(field)) {
    119       case OBJECTIVECTYPE_MESSAGE: {
    120         if (field->is_map()) {
    121           result = new MapFieldGenerator(field, options);
    122         } else {
    123           result = new RepeatedMessageFieldGenerator(field, options);
    124         }
    125         break;
    126       }
    127       case OBJECTIVECTYPE_ENUM:
    128         result = new RepeatedEnumFieldGenerator(field, options);
    129         break;
    130       default:
    131         result = new RepeatedPrimitiveFieldGenerator(field, options);
    132         break;
    133     }
    134   } else {
    135     switch (GetObjectiveCType(field)) {
    136       case OBJECTIVECTYPE_MESSAGE: {
    137         result = new MessageFieldGenerator(field, options);
    138         break;
    139       }
    140       case OBJECTIVECTYPE_ENUM:
    141         result = new EnumFieldGenerator(field, options);
    142         break;
    143       default:
    144         if (IsReferenceType(field)) {
    145           result = new PrimitiveObjFieldGenerator(field, options);
    146         } else {
    147           result = new PrimitiveFieldGenerator(field, options);
    148         }
    149         break;
    150     }
    151   }
    152   result->FinishInitialization();
    153   return result;
    154 }
    155 
    156 FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor,
    157                                const Options& options)
    158     : descriptor_(descriptor) {
    159   SetCommonFieldVariables(descriptor, &variables_);
    160 }
    161 
    162 FieldGenerator::~FieldGenerator() {}
    163 
    164 void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const {
    165   printer->Print(
    166       variables_,
    167       "$field_number_name$ = $field_number$,\n");
    168 }
    169 
    170 void FieldGenerator::GenerateCFunctionDeclarations(
    171     io::Printer* printer) const {
    172   // Nothing
    173 }
    174 
    175 void FieldGenerator::GenerateCFunctionImplementations(
    176     io::Printer* printer) const {
    177   // Nothing
    178 }
    179 
    180 void FieldGenerator::DetermineForwardDeclarations(
    181     set<string>* fwd_decls) const {
    182   // Nothing
    183 }
    184 
    185 void FieldGenerator::GenerateFieldDescription(
    186     io::Printer* printer, bool include_default) const {
    187   // Printed in the same order as the structure decl.
    188   if (include_default) {
    189     printer->Print(
    190         variables_,
    191         "{\n"
    192         "  .defaultValue.$default_name$ = $default$,\n"
    193         "  .core.name = \"$name$\",\n"
    194         "  .core.dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
    195         "  .core.number = $field_number_name$,\n"
    196         "  .core.hasIndex = $has_index$,\n"
    197         "  .core.offset = $storage_offset_value$,$storage_offset_comment$\n"
    198         "  .core.flags = $fieldflags$,\n"
    199         "  .core.dataType = GPBDataType$field_type$,\n"
    200         "},\n");
    201   } else {
    202     printer->Print(
    203         variables_,
    204         "{\n"
    205         "  .name = \"$name$\",\n"
    206         "  .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
    207         "  .number = $field_number_name$,\n"
    208         "  .hasIndex = $has_index$,\n"
    209         "  .offset = $storage_offset_value$,$storage_offset_comment$\n"
    210         "  .flags = $fieldflags$,\n"
    211         "  .dataType = GPBDataType$field_type$,\n"
    212         "},\n");
    213   }
    214 }
    215 
    216 void FieldGenerator::SetRuntimeHasBit(int has_index) {
    217   variables_["has_index"] = SimpleItoa(has_index);
    218 }
    219 
    220 void FieldGenerator::SetNoHasBit(void) {
    221   variables_["has_index"] = "GPBNoHasBit";
    222 }
    223 
    224 int FieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
    225   return 0;
    226 }
    227 
    228 void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) {
    229   // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
    230   // error cases, so it seems to be ok to use as a back door for errors.
    231   cerr << "Error: should have overriden SetExtraRuntimeHasBitsBase()." << endl;
    232   cerr.flush();
    233   abort();
    234 }
    235 
    236 void FieldGenerator::SetOneofIndexBase(int index_base) {
    237   if (descriptor_->containing_oneof() != NULL) {
    238     int index = descriptor_->containing_oneof()->index() + index_base;
    239     // Flip the sign to mark it as a oneof.
    240     variables_["has_index"] = SimpleItoa(-index);
    241   }
    242 }
    243 
    244 void FieldGenerator::FinishInitialization(void) {
    245   // If "property_type" wasn't set, make it "storage_type".
    246   if ((variables_.find("property_type") == variables_.end()) &&
    247       (variables_.find("storage_type") != variables_.end())) {
    248     variables_["property_type"] = variable("storage_type");
    249   }
    250 }
    251 
    252 SingleFieldGenerator::SingleFieldGenerator(const FieldDescriptor* descriptor,
    253                                            const Options& options)
    254     : FieldGenerator(descriptor, options) {
    255   // Nothing
    256 }
    257 
    258 SingleFieldGenerator::~SingleFieldGenerator() {}
    259 
    260 void SingleFieldGenerator::GenerateFieldStorageDeclaration(
    261     io::Printer* printer) const {
    262   printer->Print(variables_, "$storage_type$ $name$;\n");
    263 }
    264 
    265 void SingleFieldGenerator::GeneratePropertyDeclaration(
    266     io::Printer* printer) const {
    267   printer->Print(variables_, "$comments$");
    268   printer->Print(
    269       variables_,
    270       "@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n"
    271       "\n");
    272   if (WantsHasProperty()) {
    273     printer->Print(
    274         variables_,
    275         "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
    276   }
    277 }
    278 
    279 void SingleFieldGenerator::GeneratePropertyImplementation(
    280     io::Printer* printer) const {
    281   if (WantsHasProperty()) {
    282     printer->Print(variables_, "@dynamic has$capitalized_name$, $name$;\n");
    283   } else {
    284     printer->Print(variables_, "@dynamic $name$;\n");
    285   }
    286 }
    287 
    288 bool SingleFieldGenerator::WantsHasProperty(void) const {
    289   if (descriptor_->containing_oneof() != NULL) {
    290     // If in a oneof, it uses the oneofcase instead of a has bit.
    291     return false;
    292   }
    293   if (HasFieldPresence(descriptor_->file())) {
    294     // In proto1/proto2, every field has a has_$name$() method.
    295     return true;
    296   }
    297   return false;
    298 }
    299 
    300 bool SingleFieldGenerator::RuntimeUsesHasBit(void) const {
    301   if (descriptor_->containing_oneof() != NULL) {
    302     // The oneof tracks what is set instead.
    303     return false;
    304   }
    305   return true;
    306 }
    307 
    308 ObjCObjFieldGenerator::ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
    309                                              const Options& options)
    310     : SingleFieldGenerator(descriptor, options) {
    311   variables_["property_storage_attribute"] = "strong";
    312   if (IsRetainedName(variables_["name"])) {
    313     variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
    314   }
    315 }
    316 
    317 ObjCObjFieldGenerator::~ObjCObjFieldGenerator() {}
    318 
    319 void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration(
    320     io::Printer* printer) const {
    321   printer->Print(variables_, "$storage_type$ *$name$;\n");
    322 }
    323 
    324 void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
    325     io::Printer* printer) const {
    326 
    327   // Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that
    328   // it uses pointers and deals with Objective C's rules around storage name
    329   // conventions (init*, new*, etc.)
    330 
    331   printer->Print(variables_, "$comments$");
    332   printer->Print(
    333       variables_,
    334       "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n");
    335   if (WantsHasProperty()) {
    336     printer->Print(
    337         variables_,
    338         "/// Test to see if @c $name$ has been set.\n"
    339         "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
    340   }
    341   if (IsInitName(variables_.find("name")->second)) {
    342     // If property name starts with init we need to annotate it to get past ARC.
    343     // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
    344     printer->Print(variables_,
    345                    "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
    346   }
    347   printer->Print("\n");
    348 }
    349 
    350 RepeatedFieldGenerator::RepeatedFieldGenerator(
    351     const FieldDescriptor* descriptor, const Options& options)
    352     : ObjCObjFieldGenerator(descriptor, options) {
    353   // Default to no comment and let the cases needing it fill it in.
    354   variables_["array_comment"] = "";
    355 }
    356 
    357 RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
    358 
    359 void RepeatedFieldGenerator::FinishInitialization(void) {
    360   FieldGenerator::FinishInitialization();
    361   if (variables_.find("array_property_type") == variables_.end()) {
    362     variables_["array_property_type"] = variable("array_storage_type");
    363   }
    364 }
    365 
    366 void RepeatedFieldGenerator::GenerateFieldStorageDeclaration(
    367     io::Printer* printer) const {
    368   printer->Print(variables_, "$array_storage_type$ *$name$;\n");
    369 }
    370 
    371 void RepeatedFieldGenerator::GeneratePropertyImplementation(
    372     io::Printer* printer) const {
    373   printer->Print(variables_, "@dynamic $name$, $name$_Count;\n");
    374 }
    375 
    376 void RepeatedFieldGenerator::GeneratePropertyDeclaration(
    377     io::Printer* printer) const {
    378 
    379   // Repeated fields don't need the has* properties, but they do expose a
    380   // *Count (to check without autocreation).  So for the field property we need
    381   // the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for
    382   // dealing with needing Objective C's rules around storage name conventions
    383   // (init*, new*, etc.)
    384 
    385   printer->Print(
    386       variables_,
    387       "$comments$"
    388       "$array_comment$"
    389       "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n"
    390       "/// The number of items in @c $name$ without causing the array to be created.\n"
    391       "@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\n");
    392   if (IsInitName(variables_.find("name")->second)) {
    393     // If property name starts with init we need to annotate it to get past ARC.
    394     // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
    395     printer->Print(variables_,
    396                    "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
    397   }
    398   printer->Print("\n");
    399 }
    400 
    401 bool RepeatedFieldGenerator::WantsHasProperty(void) const {
    402   // Consumer check the array size/existance rather than a has bit.
    403   return false;
    404 }
    405 
    406 bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const {
    407   return false;  // The array having anything is what is used.
    408 }
    409 
    410 FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
    411                                      const Options& options)
    412     : descriptor_(descriptor),
    413       field_generators_(
    414           new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
    415       extension_generators_(
    416           new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
    417   // Construct all the FieldGenerators.
    418   for (int i = 0; i < descriptor->field_count(); i++) {
    419     field_generators_[i].reset(
    420         FieldGenerator::Make(descriptor->field(i), options));
    421   }
    422   for (int i = 0; i < descriptor->extension_count(); i++) {
    423     extension_generators_[i].reset(
    424         FieldGenerator::Make(descriptor->extension(i), options));
    425   }
    426 }
    427 
    428 FieldGeneratorMap::~FieldGeneratorMap() {}
    429 
    430 const FieldGenerator& FieldGeneratorMap::get(
    431     const FieldDescriptor* field) const {
    432   GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
    433   return *field_generators_[field->index()];
    434 }
    435 
    436 const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
    437   return *extension_generators_[index];
    438 }
    439 
    440 int FieldGeneratorMap::CalculateHasBits(void) {
    441   int total_bits = 0;
    442   for (int i = 0; i < descriptor_->field_count(); i++) {
    443     if (field_generators_[i]->RuntimeUsesHasBit()) {
    444       field_generators_[i]->SetRuntimeHasBit(total_bits);
    445       ++total_bits;
    446     } else {
    447       field_generators_[i]->SetNoHasBit();
    448     }
    449     int extra_bits = field_generators_[i]->ExtraRuntimeHasBitsNeeded();
    450     if (extra_bits) {
    451       field_generators_[i]->SetExtraRuntimeHasBitsBase(total_bits);
    452       total_bits += extra_bits;
    453     }
    454   }
    455   return total_bits;
    456 }
    457 
    458 void FieldGeneratorMap::SetOneofIndexBase(int index_base) {
    459   for (int i = 0; i < descriptor_->field_count(); i++) {
    460     field_generators_[i]->SetOneofIndexBase(index_base);
    461   }
    462 }
    463 
    464 bool FieldGeneratorMap::DoesAnyFieldHaveNonZeroDefault(void) const {
    465   for (int i = 0; i < descriptor_->field_count(); i++) {
    466     if (HasNonZeroDefaultValue(descriptor_->field(i))) {
    467       return true;
    468     }
    469   }
    470 
    471   return false;
    472 }
    473 
    474 }  // namespace objectivec
    475 }  // namespace compiler
    476 }  // namespace protobuf
    477 }  // namespace google
    478