• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ExtensionGenerator(const string & root_class_name,const FieldDescriptor * descriptor)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     std::cerr << "error: Extension is a map<>!"
53          << " That used to be blocked by the compiler." << std::endl;
54     std::cerr.flush();
55     abort();
56   }
57 }
58 
~ExtensionGenerator()59 ExtensionGenerator::~ExtensionGenerator() {}
60 
GenerateMembersHeader(io::Printer * printer)61 void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) {
62   std::map<string, string> vars;
63   vars["method_name"] = method_name_;
64   if (IsRetainedName(method_name_)) {
65     vars["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
66   } else {
67     vars["storage_attribute"] = "";
68   }
69   SourceLocation location;
70   if (descriptor_->GetSourceLocation(&location)) {
71     vars["comments"] = BuildCommentsString(location, true);
72   } else {
73     vars["comments"] = "";
74   }
75   // Unlike normal message fields, check if the file for the extension was
76   // deprecated.
77   vars["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file());
78   printer->Print(vars,
79                  "$comments$"
80                  "+ (GPBExtensionDescriptor *)$method_name$$storage_attribute$$deprecated_attribute$;\n");
81 }
82 
GenerateStaticVariablesInitialization(io::Printer * printer)83 void ExtensionGenerator::GenerateStaticVariablesInitialization(
84     io::Printer* printer) {
85   std::map<string, string> vars;
86   vars["root_class_and_method_name"] = root_class_and_method_name_;
87   vars["extended_type"] = ClassName(descriptor_->containing_type());
88   vars["number"] = StrCat(descriptor_->number());
89 
90   std::vector<string> options;
91   if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated");
92   if (descriptor_->is_packed()) options.push_back("GPBExtensionPacked");
93   if (descriptor_->containing_type()->options().message_set_wire_format())
94     options.push_back("GPBExtensionSetWireFormat");
95 
96   vars["options"] = BuildFlagsString(FLAGTYPE_EXTENSION, options);
97 
98   ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
99   string singular_type;
100   if (objc_type == OBJECTIVECTYPE_MESSAGE) {
101     vars["type"] = string("GPBStringifySymbol(") +
102                    ClassName(descriptor_->message_type()) + ")";
103   } else {
104     vars["type"] = "NULL";
105   }
106 
107   vars["default_name"] = GPBGenericValueFieldName(descriptor_);
108   if (descriptor_->is_repeated()) {
109     vars["default"] = "nil";
110   } else {
111     vars["default"] = DefaultValue(descriptor_);
112   }
113   string type = GetCapitalizedType(descriptor_);
114   vars["extension_type"] = string("GPBDataType") + type;
115 
116   if (objc_type == OBJECTIVECTYPE_ENUM) {
117     vars["enum_desc_func_name"] =
118          EnumName(descriptor_->enum_type()) + "_EnumDescriptor";
119   } else {
120     vars["enum_desc_func_name"] = "NULL";
121   }
122 
123   printer->Print(vars,
124                  "{\n"
125                  "  .defaultValue.$default_name$ = $default$,\n"
126                  "  .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
127                  "  .extendedClass = GPBStringifySymbol($extended_type$),\n"
128                  "  .messageOrGroupClassName = $type$,\n"
129                  "  .enumDescriptorFunc = $enum_desc_func_name$,\n"
130                  "  .fieldNumber = $number$,\n"
131                  "  .dataType = $extension_type$,\n"
132                  "  .options = $options$,\n"
133                  "},\n");
134 }
135 
GenerateRegistrationSource(io::Printer * printer)136 void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) {
137   printer->Print(
138       "[registry addExtension:$root_class_and_method_name$];\n",
139       "root_class_and_method_name", root_class_and_method_name_);
140 }
141 }  // namespace objectivec
142 }  // namespace compiler
143 }  // namespace protobuf
144 }  // namespace google
145