3131#include " google/protobuf/compiler/objectivec/file.h"
3232
3333#include < algorithm>
34+ #include < cstddef>
35+ #include < cstdint>
3436#include < functional>
3537#include < iterator>
3638#include < memory>
4446#include " absl/strings/str_join.h"
4547#include " google/protobuf/compiler/objectivec/enum.h"
4648#include " google/protobuf/compiler/objectivec/extension.h"
49+ #include " google/protobuf/compiler/objectivec/helpers.h"
4750#include " google/protobuf/compiler/objectivec/import_writer.h"
4851#include " google/protobuf/compiler/objectivec/message.h"
4952#include " google/protobuf/compiler/objectivec/names.h"
53+ #include " google/protobuf/compiler/objectivec/options.h"
5054#include " google/protobuf/descriptor.h"
5155#include " google/protobuf/descriptor.pb.h"
5256#include " google/protobuf/descriptor_legacy.h"
@@ -64,28 +68,48 @@ const int32_t GOOGLE_PROTOBUF_OBJC_VERSION = 30007;
6468
6569const char * kHeaderExtension = " .pbobjc.h" ;
6670
67- // Checks if a message contains any extension definitions (on the message or
68- // a nested message under it).
69- bool MessageContainsExtensions (const Descriptor* message) {
71+ // Checks if a message contains extension definitions (on the message or
72+ // a nested message under it). `include_custom_options` decides if custom
73+ // options count as extensions.
74+ bool MessageContainsExtensions (const Descriptor* message,
75+ bool include_custom_options) {
7076 if (message->extension_count () > 0 ) {
71- return true ;
77+ if (include_custom_options) {
78+ return true ;
79+ }
80+ for (int i = 0 ; i < message->extension_count (); i++) {
81+ if (!ExtensionIsCustomOption (message->extension (i))) {
82+ return true ;
83+ }
84+ }
7285 }
7386 for (int i = 0 ; i < message->nested_type_count (); i++) {
74- if (MessageContainsExtensions (message->nested_type (i))) {
87+ if (MessageContainsExtensions (message->nested_type (i),
88+ include_custom_options)) {
7589 return true ;
7690 }
7791 }
7892 return false ;
7993}
8094
81- // Checks if the file contains any extensions definitions (at the root or
82- // nested under a message).
83- bool FileContainsExtensions (const FileDescriptor* file) {
95+ // Checks if the file contains extensions definitions (at the root or
96+ // nested under a message). `include_custom_options` decides if custom
97+ // options count as extensions.
98+ bool FileContainsExtensions (const FileDescriptor* file,
99+ bool include_custom_options) {
84100 if (file->extension_count () > 0 ) {
85- return true ;
101+ if (include_custom_options) {
102+ return true ;
103+ }
104+ for (int i = 0 ; i < file->extension_count (); i++) {
105+ if (!ExtensionIsCustomOption (file->extension (i))) {
106+ return true ;
107+ }
108+ }
86109 }
87110 for (int i = 0 ; i < file->message_type_count (); i++) {
88- if (MessageContainsExtensions (file->message_type (i))) {
111+ if (MessageContainsExtensions (file->message_type (i),
112+ include_custom_options)) {
89113 return true ;
90114 }
91115 }
@@ -112,17 +136,20 @@ void MakeDescriptors(
112136 const Descriptor* descriptor, const std::string& file_description_name,
113137 std::vector<std::unique_ptr<EnumGenerator>>* enum_generators,
114138 std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators,
115- std::vector<std::unique_ptr<MessageGenerator>>* message_generators) {
139+ std::vector<std::unique_ptr<MessageGenerator>>* message_generators,
140+ bool strip_custom_options) {
116141 for (int i = 0 ; i < descriptor->enum_type_count (); i++) {
117142 enum_generators->emplace_back (
118143 std::make_unique<EnumGenerator>(descriptor->enum_type (i)));
119144 }
120145 for (int i = 0 ; i < descriptor->nested_type_count (); i++) {
121146 message_generators->emplace_back (std::make_unique<MessageGenerator>(
122147 file_description_name, descriptor->nested_type (i)));
123- message_generators->back ()->AddExtensionGenerators (extension_generators);
148+ message_generators->back ()->AddExtensionGenerators (extension_generators,
149+ strip_custom_options);
124150 MakeDescriptors (descriptor->nested_type (i), file_description_name,
125- enum_generators, extension_generators, message_generators);
151+ enum_generators, extension_generators, message_generators,
152+ strip_custom_options);
126153 }
127154}
128155
@@ -184,7 +211,8 @@ FileGenerator::CommonState::CollectMinimalFileDepsContainingExtensionsInternal(
184211 }
185212 }
186213
187- const bool file_has_exts = FileContainsExtensions (file);
214+ const bool file_has_exts =
215+ FileContainsExtensions (file, include_custom_options);
188216
189217 // Fast path: if nothing to prune or there was only one dep, the prune work is
190218 // a waste, skip it.
@@ -241,16 +269,23 @@ FileGenerator::FileGenerator(const FileDescriptor* file,
241269 std::make_unique<EnumGenerator>(file_->enum_type (i)));
242270 }
243271 for (int i = 0 ; i < file_->extension_count (); i++) {
244- extension_generators_.push_back (std::make_unique<ExtensionGenerator>(
245- root_class_name_, file_->extension (i)));
272+ const FieldDescriptor* extension = file_->extension (i);
273+ if (!generation_options.strip_custom_options ||
274+ !ExtensionIsCustomOption (extension)) {
275+ extension_generators_.push_back (
276+ std::make_unique<ExtensionGenerator>(root_class_name_, extension));
277+ }
246278 }
279+ file_scoped_extension_count_ = extension_generators_.size ();
247280 for (int i = 0 ; i < file_->message_type_count (); i++) {
248281 message_generators_.emplace_back (std::make_unique<MessageGenerator>(
249282 file_description_name_, file_->message_type (i)));
250- message_generators_.back ()->AddExtensionGenerators (&extension_generators_);
283+ message_generators_.back ()->AddExtensionGenerators (
284+ &extension_generators_, generation_options.strip_custom_options );
251285 MakeDescriptors (file_->message_type (i), file_description_name_,
252286 &enum_generators_, &extension_generators_,
253- &message_generators_);
287+ &message_generators_,
288+ generation_options.strip_custom_options );
254289 }
255290}
256291
@@ -298,17 +333,17 @@ void FileGenerator::GenerateHeader(io::Printer* p) const {
298333
299334 // The dynamic methods block is only needed if there are extensions that are
300335 // file level scoped (not message scoped). The first
301- // file_->extension_count() of extension_generators_ are the file scoped
336+ // file_scoped_extension_count_ of extension_generators_ are the file scoped
302337 // ones.
303- if (file_-> extension_count () ) {
338+ if (file_scoped_extension_count_ ) {
304339 p->Emit (" @interface $root_class_name$ (DynamicMethods)\n " );
305340
306- for (int i = 0 ; i < file_-> extension_count () ; i++) {
341+ for (size_t i = 0 ; i < file_scoped_extension_count_ ; i++) {
307342 extension_generators_[i]->GenerateMembersHeader (p);
308343 }
309344
310345 p->Emit (" @end\n\n " );
311- } // file_->extension_count()
346+ }
312347
313348 for (const auto & generator : message_generators_) {
314349 generator->GenerateMessageHeader (p);
0 commit comments