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 cerr << "error: Extension is a map<>!"
53 << " That used to be blocked by the compiler." << endl;
54 cerr.flush();
55 abort();
56 }
57 }
58
~ExtensionGenerator()59 ExtensionGenerator::~ExtensionGenerator() {}
60
GenerateMembersHeader(io::Printer * printer)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
GenerateStaticVariablesInitialization(io::Printer * printer)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
GenerateRegistrationSource(io::Printer * printer)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