• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #include "google/protobuf/compiler/objectivec/extension.h"
9 
10 #include <string>
11 #include <vector>
12 
13 #include "absl/container/btree_set.h"
14 #include "absl/container/flat_hash_set.h"
15 #include "absl/log/absl_check.h"
16 #include "absl/strings/str_cat.h"
17 #include "absl/strings/string_view.h"
18 #include "google/protobuf/compiler/objectivec/helpers.h"
19 #include "google/protobuf/compiler/objectivec/names.h"
20 #include "google/protobuf/compiler/objectivec/options.h"
21 #include "google/protobuf/descriptor.h"
22 #include "google/protobuf/descriptor.pb.h"
23 #include "google/protobuf/io/printer.h"
24 
25 namespace google {
26 namespace protobuf {
27 namespace compiler {
28 namespace objectivec {
29 
ExtensionGenerator(absl::string_view root_or_message_class_name,const FieldDescriptor * descriptor,const GenerationOptions & generation_options)30 ExtensionGenerator::ExtensionGenerator(
31     absl::string_view root_or_message_class_name,
32     const FieldDescriptor* descriptor,
33     const GenerationOptions& generation_options)
34     : root_or_message_class_name_(root_or_message_class_name),
35       method_name_(ExtensionMethodName(descriptor)),
36       descriptor_(descriptor),
37       generation_options_(generation_options) {
38   ABSL_CHECK(!descriptor->is_map())
39       << "error: Extension is a map<>!"
40       << " That used to be blocked by the compiler.";
41   if (descriptor->containing_type()->options().message_set_wire_format()) {
42     ABSL_CHECK(descriptor->type() == FieldDescriptor::TYPE_MESSAGE)
43         << "error: Extension to a message_set_wire_format message and the type "
44            "wasn't a message!";
45     ABSL_CHECK(!descriptor->is_repeated())
46         << "error: Extension to a message_set_wire_format message should not "
47            "be repeated!";
48   }
49 }
50 
GenerateMembersHeader(io::Printer * printer) const51 void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) const {
52   printer->Emit(
53       {{"method_name", method_name_},
54        {"comments",
55         [&] { EmitCommentsString(printer, generation_options_, descriptor_); }},
56        {"storage_attribute",
57         IsRetainedName(method_name_) ? "NS_RETURNS_NOT_RETAINED" : ""},
58        {"deprecated_attribute",
59         // Unlike normal message fields, check if the file for the extension was
60         // deprecated.
61         GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file())}},
62       R"objc(
63         $comments$
64         + (GPBExtensionDescriptor *)$method_name$$ storage_attribute$$ deprecated_attribute$;
65       )objc");
66 }
67 
GenerateStaticVariablesInitialization(io::Printer * printer) const68 void ExtensionGenerator::GenerateStaticVariablesInitialization(
69     io::Printer* printer) const {
70   const std::string containing_type = ClassName(descriptor_->containing_type());
71   ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
72 
73   std::vector<std::string> options;
74   if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated");
75   if (descriptor_->is_packed()) options.push_back("GPBExtensionPacked");
76   if (descriptor_->containing_type()->options().message_set_wire_format()) {
77     options.push_back("GPBExtensionSetWireFormat");
78   }
79 
80   printer->Emit(
81       {{"default",
82         descriptor_->is_repeated() ? "nil" : DefaultValue(descriptor_)},
83        {"default_name", GPBGenericValueFieldName(descriptor_)},
84        {"enum_desc_func_name",
85         objc_type == OBJECTIVECTYPE_ENUM
86             ? absl::StrCat(EnumName(descriptor_->enum_type()),
87                            "_EnumDescriptor")
88             : "NULL"},
89        {"extended_type", ObjCClass(containing_type)},
90        {"extension_type",
91         absl::StrCat("GPBDataType", GetCapitalizedType(descriptor_))},
92        {"method_name", method_name_},
93        {"number", descriptor_->number()},
94        {"options", BuildFlagsString(FLAGTYPE_EXTENSION, options)},
95        {"root_or_message_class_name", root_or_message_class_name_},
96        {"type", objc_type == OBJECTIVECTYPE_MESSAGE
97                     ? ObjCClass(ClassName(descriptor_->message_type()))
98                     : "Nil"}},
99       R"objc(
100         {
101           .defaultValue.$default_name$ = $default$,
102           .singletonName = GPBStringifySymbol($root_or_message_class_name$) "_$method_name$",
103           .extendedClass.clazz = $extended_type$,
104           .messageOrGroupClass.clazz = $type$,
105           .enumDescriptorFunc = $enum_desc_func_name$,
106           .fieldNumber = $number$,
107           .dataType = $extension_type$,
108           .options = $options$,
109         },
110       )objc");
111 }
112 
DetermineObjectiveCClassDefinitions(absl::btree_set<std::string> * fwd_decls) const113 void ExtensionGenerator::DetermineObjectiveCClassDefinitions(
114     absl::btree_set<std::string>* fwd_decls) const {
115   std::string extended_type = ClassName(descriptor_->containing_type());
116   fwd_decls->insert(ObjCClassDeclaration(extended_type));
117   ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
118   if (objc_type == OBJECTIVECTYPE_MESSAGE) {
119     std::string message_type = ClassName(descriptor_->message_type());
120     fwd_decls->insert(ObjCClassDeclaration(message_type));
121   }
122 }
123 
DetermineNeededFiles(absl::flat_hash_set<const FileDescriptor * > * deps) const124 void ExtensionGenerator::DetermineNeededFiles(
125     absl::flat_hash_set<const FileDescriptor*>* deps) const {
126   const Descriptor* extended_type = descriptor_->containing_type();
127   if (descriptor_->file() != extended_type->file()) {
128     deps->insert(extended_type->file());
129   }
130 
131   const ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
132   if (objc_type == OBJECTIVECTYPE_MESSAGE) {
133     const Descriptor* value_msg_descriptor = descriptor_->message_type();
134     if (descriptor_->file() != value_msg_descriptor->file()) {
135       deps->insert(value_msg_descriptor->file());
136     }
137   } else if (objc_type == OBJECTIVECTYPE_ENUM) {
138     const EnumDescriptor* value_enum_descriptor = descriptor_->enum_type();
139     if (descriptor_->file() != value_enum_descriptor->file()) {
140       deps->insert(value_enum_descriptor->file());
141     }
142   }
143 }
144 
145 }  // namespace objectivec
146 }  // namespace compiler
147 }  // namespace protobuf
148 }  // namespace google
149