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