| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 | 30 |
| 31 #include <google/protobuf/compiler/objectivec/objectivec_file.h> | 31 #include <google/protobuf/compiler/objectivec/objectivec_file.h> |
| 32 #include <google/protobuf/compiler/objectivec/objectivec_enum.h> | 32 #include <google/protobuf/compiler/objectivec/objectivec_enum.h> |
| 33 #include <google/protobuf/compiler/objectivec/objectivec_extension.h> | 33 #include <google/protobuf/compiler/objectivec/objectivec_extension.h> |
| 34 #include <google/protobuf/compiler/objectivec/objectivec_message.h> | 34 #include <google/protobuf/compiler/objectivec/objectivec_message.h> |
| 35 #include <google/protobuf/compiler/code_generator.h> | 35 #include <google/protobuf/compiler/code_generator.h> |
| 36 #include <google/protobuf/io/printer.h> | 36 #include <google/protobuf/io/printer.h> |
| 37 #include <google/protobuf/io/zero_copy_stream_impl.h> | 37 #include <google/protobuf/io/zero_copy_stream_impl.h> |
| 38 #include <google/protobuf/stubs/stl_util.h> | 38 #include <google/protobuf/stubs/stl_util.h> |
| 39 #include <google/protobuf/stubs/strutil.h> | 39 #include <google/protobuf/stubs/strutil.h> |
| 40 #include <algorithm> // std::find() |
| 41 #include <iostream> |
| 40 #include <sstream> | 42 #include <sstream> |
| 41 | 43 |
| 44 // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some |
| 45 // error cases, so it seems to be ok to use as a back door for errors. |
| 46 |
| 42 namespace google { | 47 namespace google { |
| 43 namespace protobuf { | 48 namespace protobuf { |
| 44 | |
| 45 // This is also found in GPBBootstrap.h, and needs to be kept in sync. It | |
| 46 // is the version check done to ensure generated code works with the current | |
| 47 // runtime being used. | |
| 48 const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30001; | |
| 49 | |
| 50 namespace compiler { | 49 namespace compiler { |
| 51 namespace objectivec { | 50 namespace objectivec { |
| 52 | 51 |
| 52 namespace { |
| 53 |
| 54 // This is also found in GPBBootstrap.h, and needs to be kept in sync. |
| 55 const int32 GOOGLE_PROTOBUF_OBJC_VERSION = 30002; |
| 56 |
| 57 const char* kHeaderExtension = ".pbobjc.h"; |
| 58 |
| 59 // Checks if a message contains any extension definitions (on the message or |
| 60 // a nested message under it). |
| 61 bool MessageContainsExtensions(const Descriptor* message) { |
| 62 if (message->extension_count() > 0) { |
| 63 return true; |
| 64 } |
| 65 for (int i = 0; i < message->nested_type_count(); i++) { |
| 66 if (MessageContainsExtensions(message->nested_type(i))) { |
| 67 return true; |
| 68 } |
| 69 } |
| 70 return false; |
| 71 } |
| 72 |
| 73 // Checks if the file contains any extensions definitions (at the root or |
| 74 // nested under a message). |
| 75 bool FileContainsExtensions(const FileDescriptor* file) { |
| 76 if (file->extension_count() > 0) { |
| 77 return true; |
| 78 } |
| 79 for (int i = 0; i < file->message_type_count(); i++) { |
| 80 if (MessageContainsExtensions(file->message_type(i))) { |
| 81 return true; |
| 82 } |
| 83 } |
| 84 return false; |
| 85 } |
| 86 |
| 87 // Helper for CollectMinimalFileDepsContainingExtensionsWorker that marks all |
| 88 // deps as visited and prunes them from the needed files list. |
| 89 void PruneFileAndDepsMarkingAsVisited( |
| 90 const FileDescriptor* file, |
| 91 vector<const FileDescriptor*>* files, |
| 92 set<const FileDescriptor*>* files_visited) { |
| 93 vector<const FileDescriptor*>::iterator iter = |
| 94 std::find(files->begin(), files->end(), file); |
| 95 if (iter != files->end()) { |
| 96 files->erase(iter); |
| 97 } |
| 98 files_visited->insert(file); |
| 99 for (int i = 0; i < file->dependency_count(); i++) { |
| 100 PruneFileAndDepsMarkingAsVisited(file->dependency(i), files, files_visited); |
| 101 } |
| 102 } |
| 103 |
| 104 // Helper for CollectMinimalFileDepsContainingExtensions. |
| 105 void CollectMinimalFileDepsContainingExtensionsWorker( |
| 106 const FileDescriptor* file, |
| 107 vector<const FileDescriptor*>* files, |
| 108 set<const FileDescriptor*>* files_visited) { |
| 109 if (files_visited->find(file) != files_visited->end()) { |
| 110 return; |
| 111 } |
| 112 files_visited->insert(file); |
| 113 |
| 114 if (FileContainsExtensions(file)) { |
| 115 files->push_back(file); |
| 116 for (int i = 0; i < file->dependency_count(); i++) { |
| 117 const FileDescriptor* dep = file->dependency(i); |
| 118 PruneFileAndDepsMarkingAsVisited(dep, files, files_visited); |
| 119 } |
| 120 } else { |
| 121 for (int i = 0; i < file->dependency_count(); i++) { |
| 122 const FileDescriptor* dep = file->dependency(i); |
| 123 CollectMinimalFileDepsContainingExtensionsWorker(dep, files, |
| 124 files_visited); |
| 125 } |
| 126 } |
| 127 } |
| 128 |
| 129 // Collect the deps of the given file that contain extensions. This can be used
to |
| 130 // create the chain of roots that need to be wired together. |
| 131 // |
| 132 // NOTE: If any changes are made to this and the supporting functions, you will |
| 133 // need to manually validate what the generated code is for the test files: |
| 134 // objectivec/Tests/unittest_extension_chain_*.proto |
| 135 // There are comments about what the expected code should be line and limited |
| 136 // testing objectivec/Tests/GPBUnittestProtos2.m around compilation (#imports |
| 137 // specifically). |
| 138 void CollectMinimalFileDepsContainingExtensions( |
| 139 const FileDescriptor* file, |
| 140 vector<const FileDescriptor*>* files) { |
| 141 set<const FileDescriptor*> files_visited; |
| 142 for (int i = 0; i < file->dependency_count(); i++) { |
| 143 const FileDescriptor* dep = file->dependency(i); |
| 144 CollectMinimalFileDepsContainingExtensionsWorker(dep, files, |
| 145 &files_visited); |
| 146 } |
| 147 } |
| 148 |
| 149 bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) { |
| 150 for (int i = 0; i < file->dependency_count(); i++) { |
| 151 if (dep == file->dependency(i)) { |
| 152 return true; |
| 153 } |
| 154 } |
| 155 return false; |
| 156 } |
| 157 |
| 158 } // namespace |
| 159 |
| 53 FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options) | 160 FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options) |
| 54 : file_(file), | 161 : file_(file), |
| 55 root_class_name_(FileClassName(file)), | 162 root_class_name_(FileClassName(file)), |
| 56 is_public_dep_(false), | |
| 57 options_(options) { | 163 options_(options) { |
| 58 for (int i = 0; i < file_->enum_type_count(); i++) { | 164 for (int i = 0; i < file_->enum_type_count(); i++) { |
| 59 EnumGenerator *generator = new EnumGenerator(file_->enum_type(i)); | 165 EnumGenerator *generator = new EnumGenerator(file_->enum_type(i)); |
| 60 enum_generators_.push_back(generator); | 166 enum_generators_.push_back(generator); |
| 61 } | 167 } |
| 62 for (int i = 0; i < file_->message_type_count(); i++) { | 168 for (int i = 0; i < file_->message_type_count(); i++) { |
| 63 MessageGenerator *generator = | 169 MessageGenerator *generator = |
| 64 new MessageGenerator(root_class_name_, file_->message_type(i), options_)
; | 170 new MessageGenerator(root_class_name_, file_->message_type(i), options_)
; |
| 65 message_generators_.push_back(generator); | 171 message_generators_.push_back(generator); |
| 66 } | 172 } |
| 67 for (int i = 0; i < file_->extension_count(); i++) { | 173 for (int i = 0; i < file_->extension_count(); i++) { |
| 68 ExtensionGenerator *generator = | 174 ExtensionGenerator *generator = |
| 69 new ExtensionGenerator(root_class_name_, file_->extension(i)); | 175 new ExtensionGenerator(root_class_name_, file_->extension(i)); |
| 70 extension_generators_.push_back(generator); | 176 extension_generators_.push_back(generator); |
| 71 } | 177 } |
| 72 } | 178 } |
| 73 | 179 |
| 74 FileGenerator::~FileGenerator() { | 180 FileGenerator::~FileGenerator() { |
| 75 STLDeleteContainerPointers(dependency_generators_.begin(), | |
| 76 dependency_generators_.end()); | |
| 77 STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end()); | 181 STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end()); |
| 78 STLDeleteContainerPointers(message_generators_.begin(), | 182 STLDeleteContainerPointers(message_generators_.begin(), |
| 79 message_generators_.end()); | 183 message_generators_.end()); |
| 80 STLDeleteContainerPointers(extension_generators_.begin(), | 184 STLDeleteContainerPointers(extension_generators_.begin(), |
| 81 extension_generators_.end()); | 185 extension_generators_.end()); |
| 82 } | 186 } |
| 83 | 187 |
| 84 void FileGenerator::GenerateHeader(io::Printer *printer) { | 188 void FileGenerator::GenerateHeader(io::Printer *printer) { |
| 85 printer->Print( | 189 PrintFileRuntimePreamble(printer, "GPBProtocolBuffers.h"); |
| 86 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" | |
| 87 "// source: $filename$\n" | |
| 88 "\n", | |
| 89 "filename", file_->name()); | |
| 90 | |
| 91 printer->Print( | |
| 92 "#import \"GPBProtocolBuffers.h\"\n" | |
| 93 "\n"); | |
| 94 | 190 |
| 95 // Add some verification that the generated code matches the source the | 191 // Add some verification that the generated code matches the source the |
| 96 // code is being compiled with. | 192 // code is being compiled with. |
| 193 // NOTE: This captures the raw numeric values at the time the generator was |
| 194 // compiled, since that will be the versions for the ObjC runtime at that |
| 195 // time. The constants in the generated code will then get their values at |
| 196 // at compile time (so checking against the headers being used to compile). |
| 97 printer->Print( | 197 printer->Print( |
| 98 "#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != $protoc_gen_objc_version$\n" | 198 "#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$\n" |
| 99 "#error This file was generated by a different version of protoc which is
incompatible with your Protocol Buffer library sources.\n" | 199 "#error This file was generated by a newer version of protoc which is inco
mpatible with your Protocol Buffer library sources.\n" |
| 200 "#endif\n" |
| 201 "#if $google_protobuf_objc_version$ < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_V
ERSION\n" |
| 202 "#error This file was generated by an older version of protoc which is inc
ompatible with your Protocol Buffer library sources.\n" |
| 100 "#endif\n" | 203 "#endif\n" |
| 101 "\n", | 204 "\n", |
| 102 "protoc_gen_objc_version", | 205 "google_protobuf_objc_version", SimpleItoa(GOOGLE_PROTOBUF_OBJC_VERSION)); |
| 103 SimpleItoa(GOOGLE_PROTOBUF_OBJC_GEN_VERSION)); | |
| 104 | 206 |
| 105 const vector<FileGenerator *> &dependency_generators = DependencyGenerators(); | 207 // #import any headers for "public imports" in the proto file. |
| 106 for (vector<FileGenerator *>::const_iterator iter = | 208 { |
| 107 dependency_generators.begin(); | 209 ImportWriter import_writer( |
| 108 iter != dependency_generators.end(); ++iter) { | 210 options_.generate_for_named_framework, |
| 109 if ((*iter)->IsPublicDependency()) { | 211 options_.named_framework_to_proto_path_mappings_path); |
| 110 printer->Print("#import \"$header$.pbobjc.h\"\n", | 212 const string header_extension(kHeaderExtension); |
| 111 "header", (*iter)->Path()); | 213 for (int i = 0; i < file_->public_dependency_count(); i++) { |
| 214 import_writer.AddFile(file_->public_dependency(i), header_extension); |
| 112 } | 215 } |
| 216 import_writer.Print(printer); |
| 113 } | 217 } |
| 114 | 218 |
| 219 // Note: |
| 220 // deprecated-declarations suppression is only needed if some place in this |
| 221 // proto file is something deprecated or if it references something from |
| 222 // another file that is deprecated. |
| 115 printer->Print( | 223 printer->Print( |
| 116 "// @@protoc_insertion_point(imports)\n" | 224 "// @@protoc_insertion_point(imports)\n" |
| 117 "\n" | 225 "\n" |
| 118 "#pragma clang diagnostic push\n" | 226 "#pragma clang diagnostic push\n" |
| 119 "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n" | 227 "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n" |
| 120 "\n" | 228 "\n" |
| 121 "CF_EXTERN_C_BEGIN\n" | 229 "CF_EXTERN_C_BEGIN\n" |
| 122 "\n"); | 230 "\n"); |
| 123 | 231 |
| 124 set<string> fwd_decls; | 232 set<string> fwd_decls; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 147 for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); | 255 for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); |
| 148 iter != message_generators_.end(); ++iter) { | 256 iter != message_generators_.end(); ++iter) { |
| 149 (*iter)->GenerateEnumHeader(printer); | 257 (*iter)->GenerateEnumHeader(printer); |
| 150 } | 258 } |
| 151 | 259 |
| 152 // For extensions to chain together, the Root gets created even if there | 260 // For extensions to chain together, the Root gets created even if there |
| 153 // are no extensions. | 261 // are no extensions. |
| 154 printer->Print( | 262 printer->Print( |
| 155 "#pragma mark - $root_class_name$\n" | 263 "#pragma mark - $root_class_name$\n" |
| 156 "\n" | 264 "\n" |
| 157 "/// Exposes the extension registry for this file.\n" | 265 "/**\n" |
| 158 "///\n" | 266 " * Exposes the extension registry for this file.\n" |
| 159 "/// The base class provides:\n" | 267 " *\n" |
| 160 "/// @code\n" | 268 " * The base class provides:\n" |
| 161 "/// + (GPBExtensionRegistry *)extensionRegistry;\n" | 269 " * @code\n" |
| 162 "/// @endcode\n" | 270 " * + (GPBExtensionRegistry *)extensionRegistry;\n" |
| 163 "/// which is a @c GPBExtensionRegistry that includes all the extensions d
efined by\n" | 271 " * @endcode\n" |
| 164 "/// this file and all files that it depends on.\n" | 272 " * which is a @c GPBExtensionRegistry that includes all the extensions de
fined by\n" |
| 273 " * this file and all files that it depends on.\n" |
| 274 " **/\n" |
| 165 "@interface $root_class_name$ : GPBRootObject\n" | 275 "@interface $root_class_name$ : GPBRootObject\n" |
| 166 "@end\n" | 276 "@end\n" |
| 167 "\n", | 277 "\n", |
| 168 "root_class_name", root_class_name_); | 278 "root_class_name", root_class_name_); |
| 169 | 279 |
| 170 if (extension_generators_.size() > 0) { | 280 if (extension_generators_.size() > 0) { |
| 171 // The dynamic methods block is only needed if there are extensions. | 281 // The dynamic methods block is only needed if there are extensions. |
| 172 printer->Print( | 282 printer->Print( |
| 173 "@interface $root_class_name$ (DynamicMethods)\n", | 283 "@interface $root_class_name$ (DynamicMethods)\n", |
| 174 "root_class_name", root_class_name_); | 284 "root_class_name", root_class_name_); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 191 "NS_ASSUME_NONNULL_END\n" | 301 "NS_ASSUME_NONNULL_END\n" |
| 192 "\n" | 302 "\n" |
| 193 "CF_EXTERN_C_END\n" | 303 "CF_EXTERN_C_END\n" |
| 194 "\n" | 304 "\n" |
| 195 "#pragma clang diagnostic pop\n" | 305 "#pragma clang diagnostic pop\n" |
| 196 "\n" | 306 "\n" |
| 197 "// @@protoc_insertion_point(global_scope)\n"); | 307 "// @@protoc_insertion_point(global_scope)\n"); |
| 198 } | 308 } |
| 199 | 309 |
| 200 void FileGenerator::GenerateSource(io::Printer *printer) { | 310 void FileGenerator::GenerateSource(io::Printer *printer) { |
| 201 printer->Print( | 311 // #import the runtime support. |
| 202 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" | 312 PrintFileRuntimePreamble(printer, "GPBProtocolBuffers_RuntimeSupport.h"); |
| 203 "// source: $filename$\n" | |
| 204 "\n", | |
| 205 "filename", file_->name()); | |
| 206 | 313 |
| 207 string header_file = Path() + ".pbobjc.h"; | 314 vector<const FileDescriptor*> deps_with_extensions; |
| 208 printer->Print( | 315 CollectMinimalFileDepsContainingExtensions(file_, &deps_with_extensions); |
| 209 "#import \"GPBProtocolBuffers_RuntimeSupport.h\"\n" | 316 |
| 210 "#import \"$header_file$\"\n", | 317 { |
| 211 "header_file", header_file); | 318 ImportWriter import_writer( |
| 212 const vector<FileGenerator *> &dependency_generators = | 319 options_.generate_for_named_framework, |
| 213 DependencyGenerators(); | 320 options_.named_framework_to_proto_path_mappings_path); |
| 214 for (vector<FileGenerator *>::const_iterator iter = | 321 const string header_extension(kHeaderExtension); |
| 215 dependency_generators.begin(); | 322 |
| 216 iter != dependency_generators.end(); ++iter) { | 323 // #import the header for this proto file. |
| 217 if (!(*iter)->IsPublicDependency()) { | 324 import_writer.AddFile(file_, header_extension); |
| 218 printer->Print("#import \"$header$.pbobjc.h\"\n", | 325 |
| 219 "header", (*iter)->Path()); | 326 // #import the headers for anything that a plain dependency of this proto |
| 327 // file (that means they were just an include, not a "public" include). |
| 328 set<string> public_import_names; |
| 329 for (int i = 0; i < file_->public_dependency_count(); i++) { |
| 330 public_import_names.insert(file_->public_dependency(i)->name()); |
| 331 } |
| 332 for (int i = 0; i < file_->dependency_count(); i++) { |
| 333 const FileDescriptor *dep = file_->dependency(i); |
| 334 bool public_import = (public_import_names.count(dep->name()) != 0); |
| 335 if (!public_import) { |
| 336 import_writer.AddFile(dep, header_extension); |
| 337 } |
| 338 } |
| 339 |
| 340 // If any indirect dependency provided extensions, it needs to be directly |
| 341 // imported so it can get merged into the root's extensions registry. |
| 342 // See the Note by CollectMinimalFileDepsContainingExtensions before |
| 343 // changing this. |
| 344 for (vector<const FileDescriptor *>::iterator iter = |
| 345 deps_with_extensions.begin(); |
| 346 iter != deps_with_extensions.end(); ++iter) { |
| 347 if (!IsDirectDependency(*iter, file_)) { |
| 348 import_writer.AddFile(*iter, header_extension); |
| 349 } |
| 350 } |
| 351 |
| 352 import_writer.Print(printer); |
| 353 } |
| 354 |
| 355 bool includes_oneof = false; |
| 356 for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); |
| 357 iter != message_generators_.end(); ++iter) { |
| 358 if ((*iter)->IncludesOneOfDefinition()) { |
| 359 includes_oneof = true; |
| 360 break; |
| 220 } | 361 } |
| 221 } | 362 } |
| 363 |
| 364 // Note: |
| 365 // deprecated-declarations suppression is only needed if some place in this |
| 366 // proto file is something deprecated or if it references something from |
| 367 // another file that is deprecated. |
| 222 printer->Print( | 368 printer->Print( |
| 223 "// @@protoc_insertion_point(imports)\n" | 369 "// @@protoc_insertion_point(imports)\n" |
| 224 "\n" | 370 "\n" |
| 225 "#pragma clang diagnostic push\n" | 371 "#pragma clang diagnostic push\n" |
| 226 "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n" | 372 "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"); |
| 227 "\n"); | 373 if (includes_oneof) { |
| 374 // The generated code for oneof's uses direct ivar access, suppress the |
| 375 // warning incase developer turn that on in the context they compile the |
| 376 // generated code. |
| 377 printer->Print( |
| 378 "#pragma clang diagnostic ignored \"-Wdirect-ivar-access\"\n"); |
| 379 } |
| 228 | 380 |
| 229 printer->Print( | 381 printer->Print( |
| 382 "\n" |
| 230 "#pragma mark - $root_class_name$\n" | 383 "#pragma mark - $root_class_name$\n" |
| 231 "\n" | 384 "\n" |
| 232 "@implementation $root_class_name$\n\n", | 385 "@implementation $root_class_name$\n\n", |
| 233 "root_class_name", root_class_name_); | 386 "root_class_name", root_class_name_); |
| 234 | 387 |
| 235 // Generate the extension initialization structures for the top level and | 388 const bool file_contains_extensions = FileContainsExtensions(file_); |
| 236 // any nested messages. | |
| 237 ostringstream extensions_stringstream; | |
| 238 if (file_->extension_count() + file_->message_type_count() > 0) { | |
| 239 io::OstreamOutputStream extensions_outputstream(&extensions_stringstream); | |
| 240 io::Printer extensions_printer(&extensions_outputstream, '$'); | |
| 241 for (vector<ExtensionGenerator *>::iterator iter = | |
| 242 extension_generators_.begin(); | |
| 243 iter != extension_generators_.end(); ++iter) { | |
| 244 (*iter)->GenerateStaticVariablesInitialization(&extensions_printer); | |
| 245 } | |
| 246 for (vector<MessageGenerator *>::iterator iter = | |
| 247 message_generators_.begin(); | |
| 248 iter != message_generators_.end(); ++iter) { | |
| 249 (*iter)->GenerateStaticVariablesInitialization(&extensions_printer); | |
| 250 } | |
| 251 extensions_stringstream.flush(); | |
| 252 } | |
| 253 | 389 |
| 254 // If there were any extensions or this file has any dependencies, output | 390 // If there were any extensions or this file has any dependencies, output |
| 255 // a registry to override to create the file specific registry. | 391 // a registry to override to create the file specific registry. |
| 256 const string& extensions_str = extensions_stringstream.str(); | 392 if (file_contains_extensions || !deps_with_extensions.empty()) { |
| 257 if (extensions_str.length() > 0 || file_->dependency_count() > 0) { | |
| 258 printer->Print( | 393 printer->Print( |
| 259 "+ (GPBExtensionRegistry*)extensionRegistry {\n" | 394 "+ (GPBExtensionRegistry*)extensionRegistry {\n" |
| 260 " // This is called by +initialize so there is no need to worry\n" | 395 " // This is called by +initialize so there is no need to worry\n" |
| 261 " // about thread safety and initialization of registry.\n" | 396 " // about thread safety and initialization of registry.\n" |
| 262 " static GPBExtensionRegistry* registry = nil;\n" | 397 " static GPBExtensionRegistry* registry = nil;\n" |
| 263 " if (!registry) {\n" | 398 " if (!registry) {\n" |
| 264 " GPBDebugCheckRuntimeVersion();\n" | 399 " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n" |
| 265 " registry = [[GPBExtensionRegistry alloc] init];\n"); | 400 " registry = [[GPBExtensionRegistry alloc] init];\n"); |
| 266 | 401 |
| 267 printer->Indent(); | 402 printer->Indent(); |
| 268 printer->Indent(); | 403 printer->Indent(); |
| 269 | 404 |
| 270 if (extensions_str.length() > 0) { | 405 if (file_contains_extensions) { |
| 271 printer->Print( | 406 printer->Print( |
| 272 "static GPBExtensionDescription descriptions[] = {\n"); | 407 "static GPBExtensionDescription descriptions[] = {\n"); |
| 273 printer->Indent(); | 408 printer->Indent(); |
| 274 printer->Print(extensions_str.c_str()); | 409 for (vector<ExtensionGenerator *>::iterator iter = |
| 410 extension_generators_.begin(); |
| 411 iter != extension_generators_.end(); ++iter) { |
| 412 (*iter)->GenerateStaticVariablesInitialization(printer); |
| 413 } |
| 414 for (vector<MessageGenerator *>::iterator iter = |
| 415 message_generators_.begin(); |
| 416 iter != message_generators_.end(); ++iter) { |
| 417 (*iter)->GenerateStaticVariablesInitialization(printer); |
| 418 } |
| 275 printer->Outdent(); | 419 printer->Outdent(); |
| 276 printer->Print( | 420 printer->Print( |
| 277 "};\n" | 421 "};\n" |
| 278 "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0])
; ++i) {\n" | 422 "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0])
; ++i) {\n" |
| 279 " GPBExtensionDescriptor *extension =\n" | 423 " GPBExtensionDescriptor *extension =\n" |
| 280 " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&d
escriptions[i]];\n" | 424 " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&d
escriptions[i]];\n" |
| 281 " [registry addExtension:extension];\n" | 425 " [registry addExtension:extension];\n" |
| 282 " [self globallyRegisterExtension:extension];\n" | 426 " [self globallyRegisterExtension:extension];\n" |
| 283 " [extension release];\n" | 427 " [extension release];\n" |
| 284 "}\n"); | 428 "}\n"); |
| 285 } | 429 } |
| 286 | 430 |
| 287 const vector<FileGenerator *> &dependency_generators = | 431 if (deps_with_extensions.empty()) { |
| 288 DependencyGenerators(); | |
| 289 for (vector<FileGenerator *>::const_iterator iter = | |
| 290 dependency_generators.begin(); | |
| 291 iter != dependency_generators.end(); ++iter) { | |
| 292 printer->Print( | 432 printer->Print( |
| 293 "[registry addExtensions:[$dependency$ extensionRegistry]];\n", | 433 "// None of the imports (direct or indirect) defined extensions, so no
need to add\n" |
| 294 "dependency", (*iter)->RootClassName()); | 434 "// them to this registry.\n"); |
| 435 } else { |
| 436 printer->Print( |
| 437 "// Merge in the imports (direct or indirect) that defined extensions.
\n"); |
| 438 for (vector<const FileDescriptor *>::iterator iter = |
| 439 deps_with_extensions.begin(); |
| 440 iter != deps_with_extensions.end(); ++iter) { |
| 441 const string root_class_name(FileClassName((*iter))); |
| 442 printer->Print( |
| 443 "[registry addExtensions:[$dependency$ extensionRegistry]];\n", |
| 444 "dependency", root_class_name); |
| 445 } |
| 295 } | 446 } |
| 296 | 447 |
| 297 printer->Outdent(); | 448 printer->Outdent(); |
| 298 printer->Outdent(); | 449 printer->Outdent(); |
| 299 | 450 |
| 300 printer->Print( | 451 printer->Print( |
| 301 " }\n" | 452 " }\n" |
| 302 " return registry;\n" | 453 " return registry;\n" |
| 303 "}\n" | 454 "}\n"); |
| 304 "\n"); | 455 } else { |
| 456 if (file_->dependency_count() > 0) { |
| 457 printer->Print( |
| 458 "// No extensions in the file and none of the imports (direct or indir
ect)\n" |
| 459 "// defined extensions, so no need to generate +extensionRegistry.\n")
; |
| 460 } else { |
| 461 printer->Print( |
| 462 "// No extensions in the file and no imports, so no need to generate\n
" |
| 463 "// +extensionRegistry.\n"); |
| 464 } |
| 305 } | 465 } |
| 306 | 466 |
| 307 printer->Print("@end\n\n"); | 467 printer->Print("\n@end\n\n"); |
| 308 | 468 |
| 309 // File descriptor only needed if there are messages to use it. | 469 // File descriptor only needed if there are messages to use it. |
| 310 if (message_generators_.size() > 0) { | 470 if (message_generators_.size() > 0) { |
| 311 string syntax; | 471 map<string, string> vars; |
| 472 vars["root_class_name"] = root_class_name_; |
| 473 vars["package"] = file_->package(); |
| 474 vars["objc_prefix"] = FileClassPrefix(file_); |
| 312 switch (file_->syntax()) { | 475 switch (file_->syntax()) { |
| 313 case FileDescriptor::SYNTAX_UNKNOWN: | 476 case FileDescriptor::SYNTAX_UNKNOWN: |
| 314 syntax = "GPBFileSyntaxUnknown"; | 477 vars["syntax"] = "GPBFileSyntaxUnknown"; |
| 315 break; | 478 break; |
| 316 case FileDescriptor::SYNTAX_PROTO2: | 479 case FileDescriptor::SYNTAX_PROTO2: |
| 317 syntax = "GPBFileSyntaxProto2"; | 480 vars["syntax"] = "GPBFileSyntaxProto2"; |
| 318 break; | 481 break; |
| 319 case FileDescriptor::SYNTAX_PROTO3: | 482 case FileDescriptor::SYNTAX_PROTO3: |
| 320 syntax = "GPBFileSyntaxProto3"; | 483 vars["syntax"] = "GPBFileSyntaxProto3"; |
| 321 break; | 484 break; |
| 322 } | 485 } |
| 323 printer->Print( | 486 printer->Print(vars, |
| 324 "#pragma mark - $root_class_name$_FileDescriptor\n" | 487 "#pragma mark - $root_class_name$_FileDescriptor\n" |
| 325 "\n" | 488 "\n" |
| 326 "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n" | 489 "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n" |
| 327 " // This is called by +initialize so there is no need to worry\n" | 490 " // This is called by +initialize so there is no need to worry\n" |
| 328 " // about thread safety of the singleton.\n" | 491 " // about thread safety of the singleton.\n" |
| 329 " static GPBFileDescriptor *descriptor = NULL;\n" | 492 " static GPBFileDescriptor *descriptor = NULL;\n" |
| 330 " if (!descriptor) {\n" | 493 " if (!descriptor) {\n" |
| 331 " GPBDebugCheckRuntimeVersion();\n" | 494 " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"); |
| 332 " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package
$\"\n" | 495 if (vars["objc_prefix"].size() > 0) { |
| 333 " syntax:$syntax$];\
n" | 496 printer->Print( |
| 497 vars, |
| 498 " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$packa
ge$\"\n" |
| 499 " objcPrefix:@\"$objc_
prefix$\"\n" |
| 500 " syntax:$syntax$]
;\n"); |
| 501 } else { |
| 502 printer->Print( |
| 503 vars, |
| 504 " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$packa
ge$\"\n" |
| 505 " syntax:$syntax$]
;\n"); |
| 506 } |
| 507 printer->Print( |
| 334 " }\n" | 508 " }\n" |
| 335 " return descriptor;\n" | 509 " return descriptor;\n" |
| 336 "}\n" | 510 "}\n" |
| 337 "\n", | 511 "\n"); |
| 338 "root_class_name", root_class_name_, | |
| 339 "package", file_->package(), | |
| 340 "syntax", syntax); | |
| 341 } | 512 } |
| 342 | 513 |
| 343 for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin(); | 514 for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin(); |
| 344 iter != enum_generators_.end(); ++iter) { | 515 iter != enum_generators_.end(); ++iter) { |
| 345 (*iter)->GenerateSource(printer); | 516 (*iter)->GenerateSource(printer); |
| 346 } | 517 } |
| 347 for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); | 518 for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); |
| 348 iter != message_generators_.end(); ++iter) { | 519 iter != message_generators_.end(); ++iter) { |
| 349 (*iter)->GenerateSource(printer); | 520 (*iter)->GenerateSource(printer); |
| 350 } | 521 } |
| 351 | 522 |
| 352 printer->Print( | 523 printer->Print( |
| 353 "\n" | 524 "\n" |
| 354 "#pragma clang diagnostic pop\n" | 525 "#pragma clang diagnostic pop\n" |
| 355 "\n" | 526 "\n" |
| 356 "// @@protoc_insertion_point(global_scope)\n"); | 527 "// @@protoc_insertion_point(global_scope)\n"); |
| 357 } | 528 } |
| 358 | 529 |
| 359 const string FileGenerator::Path() const { return FilePath(file_); } | 530 // Helper to print the import of the runtime support at the top of generated |
| 531 // files. This currently only supports the runtime coming from a framework |
| 532 // as defined by the official CocoaPod. |
| 533 void FileGenerator::PrintFileRuntimePreamble( |
| 534 io::Printer* printer, const string& header_to_import) const { |
| 535 printer->Print( |
| 536 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" |
| 537 "// source: $filename$\n" |
| 538 "\n", |
| 539 "filename", file_->name()); |
| 360 | 540 |
| 361 const vector<FileGenerator *> &FileGenerator::DependencyGenerators() { | 541 const string framework_name(ProtobufLibraryFrameworkName); |
| 362 if (file_->dependency_count() != dependency_generators_.size()) { | 542 const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name)); |
| 363 set<string> public_import_names; | 543 printer->Print( |
| 364 for (int i = 0; i < file_->public_dependency_count(); i++) { | 544 "// This CPP symbol can be defined to use imports that match up to the fra
mework\n" |
| 365 public_import_names.insert(file_->public_dependency(i)->name()); | 545 "// imports needed when using CocoaPods.\n" |
| 366 } | 546 "#if !defined($cpp_symbol$)\n" |
| 367 for (int i = 0; i < file_->dependency_count(); i++) { | 547 " #define $cpp_symbol$ 0\n" |
| 368 FileGenerator *generator = | 548 "#endif\n" |
| 369 new FileGenerator(file_->dependency(i), options_); | 549 "\n" |
| 370 const string& name = file_->dependency(i)->name(); | 550 "#if $cpp_symbol$\n" |
| 371 bool public_import = (public_import_names.count(name) != 0); | 551 " #import <$framework_name$/$header$>\n" |
| 372 generator->SetIsPublicDependency(public_import); | 552 "#else\n" |
| 373 dependency_generators_.push_back(generator); | 553 " #import \"$header$\"\n" |
| 374 } | 554 "#endif\n" |
| 375 } | 555 "\n", |
| 376 return dependency_generators_; | 556 "cpp_symbol", cpp_symbol, |
| 557 "header", header_to_import, |
| 558 "framework_name", framework_name); |
| 377 } | 559 } |
| 378 | 560 |
| 379 } // namespace objectivec | 561 } // namespace objectivec |
| 380 } // namespace compiler | 562 } // namespace compiler |
| 381 } // namespace protobuf | 563 } // namespace protobuf |
| 382 } // namespace google | 564 } // namespace google |
| OLD | NEW |