50 namespace objectivec {
57 const char* kHeaderExtension =
".pbobjc.h";
62 if (
message->enum_type_count() > 0) {
65 for (
int i = 0;
i <
message->nested_type_count();
i++) {
66 if (MessageContainsEnums(
message->nested_type(
i))) {
76 if (
message->extension_count() > 0) {
79 for (
int i = 0;
i <
message->nested_type_count();
i++) {
80 if (MessageContainsExtensions(
message->nested_type(
i))) {
90 if (file->enum_type_count() > 0) {
93 for (
int i = 0;
i < file->message_type_count();
i++) {
94 if (MessageContainsEnums(file->message_type(
i))) {
104 if (file->extension_count() > 0) {
107 for (
int i = 0;
i < file->message_type_count();
i++) {
108 if (MessageContainsExtensions(file->message_type(
i))) {
117 void PruneFileAndDepsMarkingAsVisited(
119 std::vector<const FileDescriptor*>* files,
120 std::set<const FileDescriptor*>* files_visited) {
121 std::vector<const FileDescriptor*>::iterator iter =
122 std::find(files->begin(), files->end(), file);
123 if (iter != files->end()) {
126 files_visited->insert(file);
127 for (
int i = 0;
i < file->dependency_count();
i++) {
128 PruneFileAndDepsMarkingAsVisited(file->dependency(
i), files, files_visited);
133 void CollectMinimalFileDepsContainingExtensionsWorker(
135 std::vector<const FileDescriptor*>* files,
136 std::set<const FileDescriptor*>* files_visited) {
137 if (files_visited->find(file) != files_visited->end()) {
140 files_visited->insert(file);
142 if (FileContainsExtensions(file)) {
143 files->push_back(file);
144 for (
int i = 0;
i < file->dependency_count();
i++) {
146 PruneFileAndDepsMarkingAsVisited(dep, files, files_visited);
149 for (
int i = 0;
i < file->dependency_count();
i++) {
151 CollectMinimalFileDepsContainingExtensionsWorker(dep, files,
166 void CollectMinimalFileDepsContainingExtensions(
168 std::vector<const FileDescriptor*>* files) {
169 std::set<const FileDescriptor*> files_visited;
170 for (
int i = 0;
i < file->dependency_count();
i++) {
172 CollectMinimalFileDepsContainingExtensionsWorker(dep, files,
178 for (
int i = 0;
i < file->dependency_count();
i++) {
179 if (dep == file->dependency(
i)) {
212 std::set<string> headers;
216 headers.insert(
"GPBRootObject.h");
217 headers.insert(
"GPBMessage.h");
218 headers.insert(
"GPBDescriptor.h");
220 headers.insert(
"GPBProtocolBuffers.h");
231 "#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$\n"
232 "#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.\n"
234 "#if $google_protobuf_objc_version$ < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION\n"
235 "#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.\n"
246 const string header_extension(kHeaderExtension);
250 import_writer.
Print(printer);
258 "// @@protoc_insertion_point(imports)\n"
260 "#pragma clang diagnostic push\n"
261 "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"
263 "CF_EXTERN_C_BEGIN\n"
266 std::set<string> fwd_decls;
268 generator->DetermineForwardDeclarations(&fwd_decls);
270 for (std::set<string>::const_iterator
i(fwd_decls.begin());
271 i != fwd_decls.end(); ++
i) {
272 printer->
Print(
"$value$;\n",
"value", *
i);
274 if (fwd_decls.begin() != fwd_decls.end()) {
275 printer->
Print(
"\n");
279 "NS_ASSUME_NONNULL_BEGIN\n"
284 generator->GenerateHeader(printer);
288 generator->GenerateEnumHeader(printer);
294 "#pragma mark - $root_class_name$\n"
297 " * Exposes the extension registry for this file.\n"
299 " * The base class provides:\n"
301 " * + (GPBExtensionRegistry *)extensionRegistry;\n"
303 " * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n"
304 " * this file and all files that it depends on.\n"
306 "@interface $root_class_name$ : GPBRootObject\n"
314 "@interface $root_class_name$ (DynamicMethods)\n",
318 generator->GenerateMembersHeader(printer);
321 printer->
Print(
"@end\n\n");
325 generator->GenerateMessageHeader(printer);
329 "NS_ASSUME_NONNULL_END\n"
333 "#pragma clang diagnostic pop\n"
335 "// @@protoc_insertion_point(global_scope)\n");
340 std::set<string> headers;
341 headers.insert(
"GPBProtocolBuffers_RuntimeSupport.h");
345 if (FileContainsEnums(
file_)) {
347 "#import <stdatomic.h>\n"
351 std::vector<const FileDescriptor*> deps_with_extensions;
352 CollectMinimalFileDepsContainingExtensions(
file_, &deps_with_extensions);
359 const string header_extension(kHeaderExtension);
366 std::set<string> public_import_names;
372 bool public_import = (public_import_names.count(dep->
name()) != 0);
373 if (!public_import) {
374 import_writer.
AddFile(dep, header_extension);
382 for (std::vector<const FileDescriptor *>::iterator iter =
383 deps_with_extensions.begin();
384 iter != deps_with_extensions.end(); ++iter) {
385 if (!IsDirectDependency(*iter,
file_)) {
386 import_writer.
AddFile(*iter, header_extension);
390 import_writer.
Print(printer);
393 bool includes_oneof =
false;
395 if (generator->IncludesOneOfDefinition()) {
396 includes_oneof =
true;
406 "// @@protoc_insertion_point(imports)\n"
408 "#pragma clang diagnostic push\n"
409 "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n");
410 if (includes_oneof) {
415 "#pragma clang diagnostic ignored \"-Wdirect-ivar-access\"\n");
420 "#pragma mark - $root_class_name$\n"
422 "@implementation $root_class_name$\n\n",
425 const bool file_contains_extensions = FileContainsExtensions(
file_);
429 if (file_contains_extensions || !deps_with_extensions.empty()) {
431 "+ (GPBExtensionRegistry*)extensionRegistry {\n"
432 " // This is called by +initialize so there is no need to worry\n"
433 " // about thread safety and initialization of registry.\n"
434 " static GPBExtensionRegistry* registry = nil;\n"
435 " if (!registry) {\n"
436 " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"
437 " registry = [[GPBExtensionRegistry alloc] init];\n");
442 if (file_contains_extensions) {
444 "static GPBExtensionDescription descriptions[] = {\n");
447 generator->GenerateStaticVariablesInitialization(printer);
450 generator->GenerateStaticVariablesInitialization(printer);
455 "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n"
456 " GPBExtensionDescriptor *extension =\n"
457 " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]];\n"
458 " [registry addExtension:extension];\n"
459 " [self globallyRegisterExtension:extension];\n"
460 " [extension release];\n"
464 if (deps_with_extensions.empty()) {
466 "// None of the imports (direct or indirect) defined extensions, so no need to add\n"
467 "// them to this registry.\n");
470 "// Merge in the imports (direct or indirect) that defined extensions.\n");
471 for (std::vector<const FileDescriptor *>::iterator iter =
472 deps_with_extensions.begin();
473 iter != deps_with_extensions.end(); ++iter) {
476 "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
477 "dependency", root_class_name);
486 " return registry;\n"
491 "// No extensions in the file and none of the imports (direct or indirect)\n"
492 "// defined extensions, so no need to generate +extensionRegistry.\n");
495 "// No extensions in the file and no imports, so no need to generate\n"
496 "// +extensionRegistry.\n");
500 printer->
Print(
"\n@end\n\n");
504 std::map<string, string> vars;
510 vars[
"syntax"] =
"GPBFileSyntaxUnknown";
513 vars[
"syntax"] =
"GPBFileSyntaxProto2";
516 vars[
"syntax"] =
"GPBFileSyntaxProto3";
520 "#pragma mark - $root_class_name$_FileDescriptor\n"
522 "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
523 " // This is called by +initialize so there is no need to worry\n"
524 " // about thread safety of the singleton.\n"
525 " static GPBFileDescriptor *descriptor = NULL;\n"
526 " if (!descriptor) {\n"
527 " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n");
528 if (vars[
"objc_prefix"].
size() > 0) {
531 " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
532 " objcPrefix:@\"$objc_prefix$\"\n"
533 " syntax:$syntax$];\n");
537 " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
538 " syntax:$syntax$];\n");
542 " return descriptor;\n"
548 generator->GenerateSource(printer);
551 generator->GenerateSource(printer);
556 "#pragma clang diagnostic pop\n"
558 "// @@protoc_insertion_point(global_scope)\n");
565 io::Printer* printer,
const std::set<string>& headers_to_import)
const {
567 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
568 "// source: $filename$\n"
576 "// This CPP symbol can be defined to use imports that match up to the framework\n"
577 "// imports needed when using CocoaPods.\n"
578 "#if !defined($cpp_symbol$)\n"
579 " #define $cpp_symbol$ 0\n"
582 "#if $cpp_symbol$\n",
583 "cpp_symbol", cpp_symbol);
586 for (std::set<string>::const_iterator iter = headers_to_import.begin();
587 iter != headers_to_import.end(); ++iter) {
589 " #import <$framework_name$/$header$>\n",
591 "framework_name", framework_name);
597 for (std::set<string>::const_iterator iter = headers_to_import.begin();
598 iter != headers_to_import.end(); ++iter) {
600 " #import \"$header$\"\n",