Index: third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_file.cc |
diff --git a/third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_file.cc |
index 7ad127bb3b621f1a1a9d1aa8bb1237165b5532d7..ed4fc6a3a25c23d9adefe78364cf23e62a80ff73 100644 |
--- a/third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_file.cc |
+++ b/third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_file.cc |
@@ -37,129 +37,23 @@ |
#include <google/protobuf/io/zero_copy_stream_impl.h> |
#include <google/protobuf/stubs/stl_util.h> |
#include <google/protobuf/stubs/strutil.h> |
-#include <algorithm> // std::find() |
-#include <iostream> |
#include <sstream> |
-// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some |
-// error cases, so it seems to be ok to use as a back door for errors. |
- |
namespace google { |
namespace protobuf { |
-namespace compiler { |
-namespace objectivec { |
- |
-namespace { |
- |
-// This is also found in GPBBootstrap.h, and needs to be kept in sync. |
-const int32 GOOGLE_PROTOBUF_OBJC_VERSION = 30002; |
- |
-const char* kHeaderExtension = ".pbobjc.h"; |
- |
-// Checks if a message contains any extension definitions (on the message or |
-// a nested message under it). |
-bool MessageContainsExtensions(const Descriptor* message) { |
- if (message->extension_count() > 0) { |
- return true; |
- } |
- for (int i = 0; i < message->nested_type_count(); i++) { |
- if (MessageContainsExtensions(message->nested_type(i))) { |
- return true; |
- } |
- } |
- return false; |
-} |
- |
-// Checks if the file contains any extensions definitions (at the root or |
-// nested under a message). |
-bool FileContainsExtensions(const FileDescriptor* file) { |
- if (file->extension_count() > 0) { |
- return true; |
- } |
- for (int i = 0; i < file->message_type_count(); i++) { |
- if (MessageContainsExtensions(file->message_type(i))) { |
- return true; |
- } |
- } |
- return false; |
-} |
- |
-// Helper for CollectMinimalFileDepsContainingExtensionsWorker that marks all |
-// deps as visited and prunes them from the needed files list. |
-void PruneFileAndDepsMarkingAsVisited( |
- const FileDescriptor* file, |
- vector<const FileDescriptor*>* files, |
- set<const FileDescriptor*>* files_visited) { |
- vector<const FileDescriptor*>::iterator iter = |
- std::find(files->begin(), files->end(), file); |
- if (iter != files->end()) { |
- files->erase(iter); |
- } |
- files_visited->insert(file); |
- for (int i = 0; i < file->dependency_count(); i++) { |
- PruneFileAndDepsMarkingAsVisited(file->dependency(i), files, files_visited); |
- } |
-} |
- |
-// Helper for CollectMinimalFileDepsContainingExtensions. |
-void CollectMinimalFileDepsContainingExtensionsWorker( |
- const FileDescriptor* file, |
- vector<const FileDescriptor*>* files, |
- set<const FileDescriptor*>* files_visited) { |
- if (files_visited->find(file) != files_visited->end()) { |
- return; |
- } |
- files_visited->insert(file); |
- if (FileContainsExtensions(file)) { |
- files->push_back(file); |
- for (int i = 0; i < file->dependency_count(); i++) { |
- const FileDescriptor* dep = file->dependency(i); |
- PruneFileAndDepsMarkingAsVisited(dep, files, files_visited); |
- } |
- } else { |
- for (int i = 0; i < file->dependency_count(); i++) { |
- const FileDescriptor* dep = file->dependency(i); |
- CollectMinimalFileDepsContainingExtensionsWorker(dep, files, |
- files_visited); |
- } |
- } |
-} |
+// This is also found in GPBBootstrap.h, and needs to be kept in sync. It |
+// is the version check done to ensure generated code works with the current |
+// runtime being used. |
+const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30001; |
-// Collect the deps of the given file that contain extensions. This can be used to |
-// create the chain of roots that need to be wired together. |
-// |
-// NOTE: If any changes are made to this and the supporting functions, you will |
-// need to manually validate what the generated code is for the test files: |
-// objectivec/Tests/unittest_extension_chain_*.proto |
-// There are comments about what the expected code should be line and limited |
-// testing objectivec/Tests/GPBUnittestProtos2.m around compilation (#imports |
-// specifically). |
-void CollectMinimalFileDepsContainingExtensions( |
- const FileDescriptor* file, |
- vector<const FileDescriptor*>* files) { |
- set<const FileDescriptor*> files_visited; |
- for (int i = 0; i < file->dependency_count(); i++) { |
- const FileDescriptor* dep = file->dependency(i); |
- CollectMinimalFileDepsContainingExtensionsWorker(dep, files, |
- &files_visited); |
- } |
-} |
- |
-bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) { |
- for (int i = 0; i < file->dependency_count(); i++) { |
- if (dep == file->dependency(i)) { |
- return true; |
- } |
- } |
- return false; |
-} |
- |
-} // namespace |
+namespace compiler { |
+namespace objectivec { |
FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options) |
: file_(file), |
root_class_name_(FileClassName(file)), |
+ is_public_dep_(false), |
options_(options) { |
for (int i = 0; i < file_->enum_type_count(); i++) { |
EnumGenerator *generator = new EnumGenerator(file_->enum_type(i)); |
@@ -178,6 +72,8 @@ FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options) |
} |
FileGenerator::~FileGenerator() { |
+ STLDeleteContainerPointers(dependency_generators_.begin(), |
+ dependency_generators_.end()); |
STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end()); |
STLDeleteContainerPointers(message_generators_.begin(), |
message_generators_.end()); |
@@ -186,40 +82,36 @@ FileGenerator::~FileGenerator() { |
} |
void FileGenerator::GenerateHeader(io::Printer *printer) { |
- PrintFileRuntimePreamble(printer, "GPBProtocolBuffers.h"); |
+ printer->Print( |
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" |
+ "// source: $filename$\n" |
+ "\n", |
+ "filename", file_->name()); |
+ |
+ printer->Print( |
+ "#import \"GPBProtocolBuffers.h\"\n" |
+ "\n"); |
// Add some verification that the generated code matches the source the |
// code is being compiled with. |
- // NOTE: This captures the raw numeric values at the time the generator was |
- // compiled, since that will be the versions for the ObjC runtime at that |
- // time. The constants in the generated code will then get their values at |
- // at compile time (so checking against the headers being used to compile). |
printer->Print( |
- "#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$\n" |
- "#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.\n" |
- "#endif\n" |
- "#if $google_protobuf_objc_version$ < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION\n" |
- "#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.\n" |
+ "#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != $protoc_gen_objc_version$\n" |
+ "#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.\n" |
"#endif\n" |
"\n", |
- "google_protobuf_objc_version", SimpleItoa(GOOGLE_PROTOBUF_OBJC_VERSION)); |
- |
- // #import any headers for "public imports" in the proto file. |
- { |
- ImportWriter import_writer( |
- options_.generate_for_named_framework, |
- options_.named_framework_to_proto_path_mappings_path); |
- const string header_extension(kHeaderExtension); |
- for (int i = 0; i < file_->public_dependency_count(); i++) { |
- import_writer.AddFile(file_->public_dependency(i), header_extension); |
+ "protoc_gen_objc_version", |
+ SimpleItoa(GOOGLE_PROTOBUF_OBJC_GEN_VERSION)); |
+ |
+ const vector<FileGenerator *> &dependency_generators = DependencyGenerators(); |
+ for (vector<FileGenerator *>::const_iterator iter = |
+ dependency_generators.begin(); |
+ iter != dependency_generators.end(); ++iter) { |
+ if ((*iter)->IsPublicDependency()) { |
+ printer->Print("#import \"$header$.pbobjc.h\"\n", |
+ "header", (*iter)->Path()); |
} |
- import_writer.Print(printer); |
} |
- // Note: |
- // deprecated-declarations suppression is only needed if some place in this |
- // proto file is something deprecated or if it references something from |
- // another file that is deprecated. |
printer->Print( |
"// @@protoc_insertion_point(imports)\n" |
"\n" |
@@ -262,16 +154,14 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { |
printer->Print( |
"#pragma mark - $root_class_name$\n" |
"\n" |
- "/**\n" |
- " * Exposes the extension registry for this file.\n" |
- " *\n" |
- " * The base class provides:\n" |
- " * @code\n" |
- " * + (GPBExtensionRegistry *)extensionRegistry;\n" |
- " * @endcode\n" |
- " * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n" |
- " * this file and all files that it depends on.\n" |
- " **/\n" |
+ "/// Exposes the extension registry for this file.\n" |
+ "///\n" |
+ "/// The base class provides:\n" |
+ "/// @code\n" |
+ "/// + (GPBExtensionRegistry *)extensionRegistry;\n" |
+ "/// @endcode\n" |
+ "/// which is a @c GPBExtensionRegistry that includes all the extensions defined by\n" |
+ "/// this file and all files that it depends on.\n" |
"@interface $root_class_name$ : GPBRootObject\n" |
"@end\n" |
"\n", |
@@ -308,114 +198,80 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { |
} |
void FileGenerator::GenerateSource(io::Printer *printer) { |
- // #import the runtime support. |
- PrintFileRuntimePreamble(printer, "GPBProtocolBuffers_RuntimeSupport.h"); |
- |
- vector<const FileDescriptor*> deps_with_extensions; |
- CollectMinimalFileDepsContainingExtensions(file_, &deps_with_extensions); |
- |
- { |
- ImportWriter import_writer( |
- options_.generate_for_named_framework, |
- options_.named_framework_to_proto_path_mappings_path); |
- const string header_extension(kHeaderExtension); |
- |
- // #import the header for this proto file. |
- import_writer.AddFile(file_, header_extension); |
- |
- // #import the headers for anything that a plain dependency of this proto |
- // file (that means they were just an include, not a "public" include). |
- set<string> public_import_names; |
- for (int i = 0; i < file_->public_dependency_count(); i++) { |
- public_import_names.insert(file_->public_dependency(i)->name()); |
- } |
- for (int i = 0; i < file_->dependency_count(); i++) { |
- const FileDescriptor *dep = file_->dependency(i); |
- bool public_import = (public_import_names.count(dep->name()) != 0); |
- if (!public_import) { |
- import_writer.AddFile(dep, header_extension); |
- } |
- } |
- |
- // If any indirect dependency provided extensions, it needs to be directly |
- // imported so it can get merged into the root's extensions registry. |
- // See the Note by CollectMinimalFileDepsContainingExtensions before |
- // changing this. |
- for (vector<const FileDescriptor *>::iterator iter = |
- deps_with_extensions.begin(); |
- iter != deps_with_extensions.end(); ++iter) { |
- if (!IsDirectDependency(*iter, file_)) { |
- import_writer.AddFile(*iter, header_extension); |
- } |
- } |
- |
- import_writer.Print(printer); |
- } |
+ printer->Print( |
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" |
+ "// source: $filename$\n" |
+ "\n", |
+ "filename", file_->name()); |
- bool includes_oneof = false; |
- for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); |
- iter != message_generators_.end(); ++iter) { |
- if ((*iter)->IncludesOneOfDefinition()) { |
- includes_oneof = true; |
- break; |
+ string header_file = Path() + ".pbobjc.h"; |
+ printer->Print( |
+ "#import \"GPBProtocolBuffers_RuntimeSupport.h\"\n" |
+ "#import \"$header_file$\"\n", |
+ "header_file", header_file); |
+ const vector<FileGenerator *> &dependency_generators = |
+ DependencyGenerators(); |
+ for (vector<FileGenerator *>::const_iterator iter = |
+ dependency_generators.begin(); |
+ iter != dependency_generators.end(); ++iter) { |
+ if (!(*iter)->IsPublicDependency()) { |
+ printer->Print("#import \"$header$.pbobjc.h\"\n", |
+ "header", (*iter)->Path()); |
} |
} |
- |
- // Note: |
- // deprecated-declarations suppression is only needed if some place in this |
- // proto file is something deprecated or if it references something from |
- // another file that is deprecated. |
printer->Print( |
"// @@protoc_insertion_point(imports)\n" |
"\n" |
"#pragma clang diagnostic push\n" |
- "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"); |
- if (includes_oneof) { |
- // The generated code for oneof's uses direct ivar access, suppress the |
- // warning incase developer turn that on in the context they compile the |
- // generated code. |
- printer->Print( |
- "#pragma clang diagnostic ignored \"-Wdirect-ivar-access\"\n"); |
- } |
+ "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n" |
+ "\n"); |
printer->Print( |
- "\n" |
"#pragma mark - $root_class_name$\n" |
"\n" |
"@implementation $root_class_name$\n\n", |
"root_class_name", root_class_name_); |
- const bool file_contains_extensions = FileContainsExtensions(file_); |
+ // Generate the extension initialization structures for the top level and |
+ // any nested messages. |
+ ostringstream extensions_stringstream; |
+ if (file_->extension_count() + file_->message_type_count() > 0) { |
+ io::OstreamOutputStream extensions_outputstream(&extensions_stringstream); |
+ io::Printer extensions_printer(&extensions_outputstream, '$'); |
+ for (vector<ExtensionGenerator *>::iterator iter = |
+ extension_generators_.begin(); |
+ iter != extension_generators_.end(); ++iter) { |
+ (*iter)->GenerateStaticVariablesInitialization(&extensions_printer); |
+ } |
+ for (vector<MessageGenerator *>::iterator iter = |
+ message_generators_.begin(); |
+ iter != message_generators_.end(); ++iter) { |
+ (*iter)->GenerateStaticVariablesInitialization(&extensions_printer); |
+ } |
+ extensions_stringstream.flush(); |
+ } |
// If there were any extensions or this file has any dependencies, output |
// a registry to override to create the file specific registry. |
- if (file_contains_extensions || !deps_with_extensions.empty()) { |
+ const string& extensions_str = extensions_stringstream.str(); |
+ if (extensions_str.length() > 0 || file_->dependency_count() > 0) { |
printer->Print( |
"+ (GPBExtensionRegistry*)extensionRegistry {\n" |
" // This is called by +initialize so there is no need to worry\n" |
" // about thread safety and initialization of registry.\n" |
" static GPBExtensionRegistry* registry = nil;\n" |
" if (!registry) {\n" |
- " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n" |
+ " GPBDebugCheckRuntimeVersion();\n" |
" registry = [[GPBExtensionRegistry alloc] init];\n"); |
printer->Indent(); |
printer->Indent(); |
- if (file_contains_extensions) { |
+ if (extensions_str.length() > 0) { |
printer->Print( |
"static GPBExtensionDescription descriptions[] = {\n"); |
printer->Indent(); |
- for (vector<ExtensionGenerator *>::iterator iter = |
- extension_generators_.begin(); |
- iter != extension_generators_.end(); ++iter) { |
- (*iter)->GenerateStaticVariablesInitialization(printer); |
- } |
- for (vector<MessageGenerator *>::iterator iter = |
- message_generators_.begin(); |
- iter != message_generators_.end(); ++iter) { |
- (*iter)->GenerateStaticVariablesInitialization(printer); |
- } |
+ printer->Print(extensions_str.c_str()); |
printer->Outdent(); |
printer->Print( |
"};\n" |
@@ -428,21 +284,14 @@ void FileGenerator::GenerateSource(io::Printer *printer) { |
"}\n"); |
} |
- if (deps_with_extensions.empty()) { |
- printer->Print( |
- "// None of the imports (direct or indirect) defined extensions, so no need to add\n" |
- "// them to this registry.\n"); |
- } else { |
+ const vector<FileGenerator *> &dependency_generators = |
+ DependencyGenerators(); |
+ for (vector<FileGenerator *>::const_iterator iter = |
+ dependency_generators.begin(); |
+ iter != dependency_generators.end(); ++iter) { |
printer->Print( |
- "// Merge in the imports (direct or indirect) that defined extensions.\n"); |
- for (vector<const FileDescriptor *>::iterator iter = |
- deps_with_extensions.begin(); |
- iter != deps_with_extensions.end(); ++iter) { |
- const string root_class_name(FileClassName((*iter))); |
- printer->Print( |
- "[registry addExtensions:[$dependency$ extensionRegistry]];\n", |
- "dependency", root_class_name); |
- } |
+ "[registry addExtensions:[$dependency$ extensionRegistry]];\n", |
+ "dependency", (*iter)->RootClassName()); |
} |
printer->Outdent(); |
@@ -451,39 +300,27 @@ void FileGenerator::GenerateSource(io::Printer *printer) { |
printer->Print( |
" }\n" |
" return registry;\n" |
- "}\n"); |
- } else { |
- if (file_->dependency_count() > 0) { |
- printer->Print( |
- "// No extensions in the file and none of the imports (direct or indirect)\n" |
- "// defined extensions, so no need to generate +extensionRegistry.\n"); |
- } else { |
- printer->Print( |
- "// No extensions in the file and no imports, so no need to generate\n" |
- "// +extensionRegistry.\n"); |
- } |
+ "}\n" |
+ "\n"); |
} |
- printer->Print("\n@end\n\n"); |
+ printer->Print("@end\n\n"); |
// File descriptor only needed if there are messages to use it. |
if (message_generators_.size() > 0) { |
- map<string, string> vars; |
- vars["root_class_name"] = root_class_name_; |
- vars["package"] = file_->package(); |
- vars["objc_prefix"] = FileClassPrefix(file_); |
+ string syntax; |
switch (file_->syntax()) { |
case FileDescriptor::SYNTAX_UNKNOWN: |
- vars["syntax"] = "GPBFileSyntaxUnknown"; |
+ syntax = "GPBFileSyntaxUnknown"; |
break; |
case FileDescriptor::SYNTAX_PROTO2: |
- vars["syntax"] = "GPBFileSyntaxProto2"; |
+ syntax = "GPBFileSyntaxProto2"; |
break; |
case FileDescriptor::SYNTAX_PROTO3: |
- vars["syntax"] = "GPBFileSyntaxProto3"; |
+ syntax = "GPBFileSyntaxProto3"; |
break; |
} |
- printer->Print(vars, |
+ printer->Print( |
"#pragma mark - $root_class_name$_FileDescriptor\n" |
"\n" |
"static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n" |
@@ -491,24 +328,16 @@ void FileGenerator::GenerateSource(io::Printer *printer) { |
" // about thread safety of the singleton.\n" |
" static GPBFileDescriptor *descriptor = NULL;\n" |
" if (!descriptor) {\n" |
- " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"); |
- if (vars["objc_prefix"].size() > 0) { |
- printer->Print( |
- vars, |
- " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" |
- " objcPrefix:@\"$objc_prefix$\"\n" |
- " syntax:$syntax$];\n"); |
- } else { |
- printer->Print( |
- vars, |
- " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" |
- " syntax:$syntax$];\n"); |
- } |
- printer->Print( |
+ " GPBDebugCheckRuntimeVersion();\n" |
+ " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" |
+ " syntax:$syntax$];\n" |
" }\n" |
" return descriptor;\n" |
"}\n" |
- "\n"); |
+ "\n", |
+ "root_class_name", root_class_name_, |
+ "package", file_->package(), |
+ "syntax", syntax); |
} |
for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin(); |
@@ -527,35 +356,24 @@ void FileGenerator::GenerateSource(io::Printer *printer) { |
"// @@protoc_insertion_point(global_scope)\n"); |
} |
-// Helper to print the import of the runtime support at the top of generated |
-// files. This currently only supports the runtime coming from a framework |
-// as defined by the official CocoaPod. |
-void FileGenerator::PrintFileRuntimePreamble( |
- io::Printer* printer, const string& header_to_import) const { |
- printer->Print( |
- "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" |
- "// source: $filename$\n" |
- "\n", |
- "filename", file_->name()); |
+const string FileGenerator::Path() const { return FilePath(file_); } |
- const string framework_name(ProtobufLibraryFrameworkName); |
- const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name)); |
- printer->Print( |
- "// This CPP symbol can be defined to use imports that match up to the framework\n" |
- "// imports needed when using CocoaPods.\n" |
- "#if !defined($cpp_symbol$)\n" |
- " #define $cpp_symbol$ 0\n" |
- "#endif\n" |
- "\n" |
- "#if $cpp_symbol$\n" |
- " #import <$framework_name$/$header$>\n" |
- "#else\n" |
- " #import \"$header$\"\n" |
- "#endif\n" |
- "\n", |
- "cpp_symbol", cpp_symbol, |
- "header", header_to_import, |
- "framework_name", framework_name); |
+const vector<FileGenerator *> &FileGenerator::DependencyGenerators() { |
+ if (file_->dependency_count() != dependency_generators_.size()) { |
+ set<string> public_import_names; |
+ for (int i = 0; i < file_->public_dependency_count(); i++) { |
+ public_import_names.insert(file_->public_dependency(i)->name()); |
+ } |
+ for (int i = 0; i < file_->dependency_count(); i++) { |
+ FileGenerator *generator = |
+ new FileGenerator(file_->dependency(i), options_); |
+ const string& name = file_->dependency(i)->name(); |
+ bool public_import = (public_import_names.count(name) != 0); |
+ generator->SetIsPublicDependency(public_import); |
+ dependency_generators_.push_back(generator); |
+ } |
+ } |
+ return dependency_generators_; |
} |
} // namespace objectivec |