From 93362a5aa552a7797a54efd05ccc678348ff9ef7 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Tue, 23 Aug 2016 10:19:03 -0400 Subject: [PATCH] Move the ImportWriter into the ObjC Helpers. grpc likely needs to provide the same sorta handling, so expose the class so the logic can be reused. --- .../compiler/objectivec/objectivec_file.cc | 205 +----------------- .../compiler/objectivec/objectivec_file.h | 2 - .../compiler/objectivec/objectivec_helpers.cc | 164 +++++++++++++- .../compiler/objectivec/objectivec_helpers.h | 36 +++ 4 files changed, 202 insertions(+), 205 deletions(-) diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index 438f411324..26babad51f 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -54,205 +54,6 @@ const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30001; namespace compiler { namespace objectivec { -namespace { - -class ImportWriter { - public: - ImportWriter(const Options& options) - : options_(options), - need_to_parse_mapping_file_(true) {} - - void AddFile(const FileGenerator* file); - void Print(io::Printer *printer) const; - - private: - class ProtoFrameworkCollector : public LineConsumer { - public: - ProtoFrameworkCollector(map* inout_proto_file_to_framework_name) - : map_(inout_proto_file_to_framework_name) {} - - virtual bool ConsumeLine(const StringPiece& line, string* out_error); - - private: - map* map_; - }; - - void ParseFrameworkMappings(); - - const Options options_; - map proto_file_to_framework_name_; - bool need_to_parse_mapping_file_; - - vector protobuf_framework_imports_; - vector protobuf_non_framework_imports_; - vector other_framework_imports_; - vector other_imports_; -}; - -void ImportWriter::AddFile(const FileGenerator* file) { - const FileDescriptor* file_descriptor = file->Descriptor(); - const string extension(".pbobjc.h"); - - if (IsProtobufLibraryBundledProtoFile(file_descriptor)) { - protobuf_framework_imports_.push_back( - FilePathBasename(file_descriptor) + extension); - protobuf_non_framework_imports_.push_back(file->Path() + extension); - return; - } - - // Lazy parse any mappings. - if (need_to_parse_mapping_file_) { - ParseFrameworkMappings(); - } - - map::iterator proto_lookup = - proto_file_to_framework_name_.find(file_descriptor->name()); - if (proto_lookup != proto_file_to_framework_name_.end()) { - other_framework_imports_.push_back( - proto_lookup->second + "/" + - FilePathBasename(file_descriptor) + extension); - return; - } - - if (!options_.generate_for_named_framework.empty()) { - other_framework_imports_.push_back( - options_.generate_for_named_framework + "/" + - FilePathBasename(file_descriptor) + extension); - return; - } - - other_imports_.push_back(file->Path() + extension); -} - -void ImportWriter::Print(io::Printer* printer) const { - assert(protobuf_non_framework_imports_.size() == - protobuf_framework_imports_.size()); - - bool add_blank_line = false; - - if (protobuf_framework_imports_.size() > 0) { - const string framework_name(ProtobufLibraryFrameworkName); - const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name)); - - printer->Print( - "#if $cpp_symbol$\n", - "cpp_symbol", cpp_symbol); - for (vector::const_iterator iter = protobuf_framework_imports_.begin(); - iter != protobuf_framework_imports_.end(); ++iter) { - printer->Print( - " #import <$framework_name$/$header$>\n", - "framework_name", framework_name, - "header", *iter); - } - printer->Print( - "#else\n"); - for (vector::const_iterator iter = protobuf_non_framework_imports_.begin(); - iter != protobuf_non_framework_imports_.end(); ++iter) { - printer->Print( - " #import \"$header$\"\n", - "header", *iter); - } - printer->Print( - "#endif\n"); - - add_blank_line = true; - } - - if (other_framework_imports_.size() > 0) { - if (add_blank_line) { - printer->Print("\n"); - } - - for (vector::const_iterator iter = other_framework_imports_.begin(); - iter != other_framework_imports_.end(); ++iter) { - printer->Print( - " #import <$header$>\n", - "header", *iter); - } - - add_blank_line = true; - } - - if (other_imports_.size() > 0) { - if (add_blank_line) { - printer->Print("\n"); - } - - for (vector::const_iterator iter = other_imports_.begin(); - iter != other_imports_.end(); ++iter) { - printer->Print( - " #import \"$header$\"\n", - "header", *iter); - } - } -} - -void ImportWriter::ParseFrameworkMappings() { - need_to_parse_mapping_file_ = false; - if (options_.named_framework_to_proto_path_mappings_path.empty()) { - return; // Nothing to do. - } - - ProtoFrameworkCollector collector(&proto_file_to_framework_name_); - string parse_error; - if (!ParseSimpleFile(options_.named_framework_to_proto_path_mappings_path, - &collector, &parse_error)) { - cerr << "error parsing " << options_.named_framework_to_proto_path_mappings_path - << " : " << parse_error << endl; - cerr.flush(); - } -} - -bool ImportWriter::ProtoFrameworkCollector::ConsumeLine( - const StringPiece& line, string* out_error) { - int offset = line.find(':'); - if (offset == StringPiece::npos) { - *out_error = - string("Framework/proto file mapping line without colon sign: '") + - line.ToString() + "'."; - return false; - } - StringPiece framework_name(line, 0, offset); - StringPiece proto_file_list(line, offset + 1, line.length() - offset - 1); - StringPieceTrimWhitespace(&framework_name); - - int start = 0; - while (start < proto_file_list.length()) { - offset = proto_file_list.find(',', start); - if (offset == StringPiece::npos) { - offset = proto_file_list.length(); - } - - StringPiece proto_file(proto_file_list, start, offset - start); - StringPieceTrimWhitespace(&proto_file); - if (proto_file.size() != 0) { - map::iterator existing_entry = - map_->find(proto_file.ToString()); - if (existing_entry != map_->end()) { - cerr << "warning: duplicate proto file reference, replacing framework entry for '" - << proto_file.ToString() << "' with '" << framework_name.ToString() - << "' (was '" << existing_entry->second << "')." << endl; - cerr.flush(); - } - - if (proto_file.find(' ') != StringPiece::npos) { - cerr << "note: framework mapping file had a proto file with a space in, hopefully that isn't a missing comma: '" - << proto_file.ToString() << "'" << endl; - cerr.flush(); - } - - (*map_)[proto_file.ToString()] = framework_name.ToString(); - } - - start = offset + 1; - } - - return true; -} - -} // namespace - - FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options) : file_(file), root_class_name_(FileClassName(file)), @@ -305,7 +106,7 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { dependency_generators.begin(); iter != dependency_generators.end(); ++iter) { if ((*iter)->IsPublicDependency()) { - import_writer.AddFile(*iter); + import_writer.AddFile((*iter)->file_); } } import_writer.Print(printer); @@ -410,7 +211,7 @@ void FileGenerator::GenerateSource(io::Printer *printer) { ImportWriter import_writer(options_); // #import the header for this proto file. - import_writer.AddFile(this); + import_writer.AddFile(file_); // #import the headers for anything that a plain dependency of this proto // file (that means they were just an include, not a "public" include). @@ -420,7 +221,7 @@ void FileGenerator::GenerateSource(io::Printer *printer) { dependency_generators.begin(); iter != dependency_generators.end(); ++iter) { if (!(*iter)->IsPublicDependency()) { - import_writer.AddFile(*iter); + import_writer.AddFile((*iter)->file_); } } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h index 8e4388d8d2..60b19f1933 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h @@ -62,8 +62,6 @@ class FileGenerator { void GenerateHeader(io::Printer* printer); const string& RootClassName() const { return root_class_name_; } - const string Path() const { return FilePath(file_); } - const FileDescriptor* Descriptor() const { return file_; } bool IsPublicDependency() const { return is_public_dep_; } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index 8222dfdb9b..a1de635e48 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -44,9 +44,10 @@ #include #include +#include #include +#include #include -#include #include #include @@ -1433,6 +1434,167 @@ bool ParseSimpleFile( return parser.Finish(); } +void ImportWriter::AddFile(const FileDescriptor* file) { + const string extension(".pbobjc.h"); + const string file_path(FilePath(file)); + + if (IsProtobufLibraryBundledProtoFile(file)) { + protobuf_framework_imports_.push_back( + FilePathBasename(file) + extension); + protobuf_non_framework_imports_.push_back(file_path + extension); + return; + } + + // Lazy parse any mappings. + if (need_to_parse_mapping_file_) { + ParseFrameworkMappings(); + } + + map::iterator proto_lookup = + proto_file_to_framework_name_.find(file->name()); + if (proto_lookup != proto_file_to_framework_name_.end()) { + other_framework_imports_.push_back( + proto_lookup->second + "/" + + FilePathBasename(file) + extension); + return; + } + + if (!options_.generate_for_named_framework.empty()) { + other_framework_imports_.push_back( + options_.generate_for_named_framework + "/" + + FilePathBasename(file) + extension); + return; + } + + other_imports_.push_back(file_path + extension); +} + +void ImportWriter::Print(io::Printer* printer) const { + assert(protobuf_non_framework_imports_.size() == + protobuf_framework_imports_.size()); + + bool add_blank_line = false; + + if (protobuf_framework_imports_.size() > 0) { + const string framework_name(ProtobufLibraryFrameworkName); + const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name)); + + printer->Print( + "#if $cpp_symbol$\n", + "cpp_symbol", cpp_symbol); + for (vector::const_iterator iter = protobuf_framework_imports_.begin(); + iter != protobuf_framework_imports_.end(); ++iter) { + printer->Print( + " #import <$framework_name$/$header$>\n", + "framework_name", framework_name, + "header", *iter); + } + printer->Print( + "#else\n"); + for (vector::const_iterator iter = protobuf_non_framework_imports_.begin(); + iter != protobuf_non_framework_imports_.end(); ++iter) { + printer->Print( + " #import \"$header$\"\n", + "header", *iter); + } + printer->Print( + "#endif\n"); + + add_blank_line = true; + } + + if (other_framework_imports_.size() > 0) { + if (add_blank_line) { + printer->Print("\n"); + } + + for (vector::const_iterator iter = other_framework_imports_.begin(); + iter != other_framework_imports_.end(); ++iter) { + printer->Print( + " #import <$header$>\n", + "header", *iter); + } + + add_blank_line = true; + } + + if (other_imports_.size() > 0) { + if (add_blank_line) { + printer->Print("\n"); + } + + for (vector::const_iterator iter = other_imports_.begin(); + iter != other_imports_.end(); ++iter) { + printer->Print( + " #import \"$header$\"\n", + "header", *iter); + } + } +} + +void ImportWriter::ParseFrameworkMappings() { + need_to_parse_mapping_file_ = false; + if (options_.named_framework_to_proto_path_mappings_path.empty()) { + return; // Nothing to do. + } + + ProtoFrameworkCollector collector(&proto_file_to_framework_name_); + string parse_error; + if (!ParseSimpleFile(options_.named_framework_to_proto_path_mappings_path, + &collector, &parse_error)) { + cerr << "error parsing " << options_.named_framework_to_proto_path_mappings_path + << " : " << parse_error << endl; + cerr.flush(); + } +} + +bool ImportWriter::ProtoFrameworkCollector::ConsumeLine( + const StringPiece& line, string* out_error) { + int offset = line.find(':'); + if (offset == StringPiece::npos) { + *out_error = + string("Framework/proto file mapping line without colon sign: '") + + line.ToString() + "'."; + return false; + } + StringPiece framework_name(line, 0, offset); + StringPiece proto_file_list(line, offset + 1, line.length() - offset - 1); + StringPieceTrimWhitespace(&framework_name); + + int start = 0; + while (start < proto_file_list.length()) { + offset = proto_file_list.find(',', start); + if (offset == StringPiece::npos) { + offset = proto_file_list.length(); + } + + StringPiece proto_file(proto_file_list, start, offset - start); + StringPieceTrimWhitespace(&proto_file); + if (proto_file.size() != 0) { + map::iterator existing_entry = + map_->find(proto_file.ToString()); + if (existing_entry != map_->end()) { + cerr << "warning: duplicate proto file reference, replacing framework entry for '" + << proto_file.ToString() << "' with '" << framework_name.ToString() + << "' (was '" << existing_entry->second << "')." << endl; + cerr.flush(); + } + + if (proto_file.find(' ') != StringPiece::npos) { + cerr << "note: framework mapping file had a proto file with a space in, hopefully that isn't a missing comma: '" + << proto_file.ToString() << "'" << endl; + cerr.flush(); + } + + (*map_)[proto_file.ToString()] = framework_name.ToString(); + } + + start = offset + 1; + } + + return true; +} + } // namespace objectivec } // namespace compiler diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index 998c6281c1..db3031541e 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -225,6 +225,42 @@ class LIBPROTOC_EXPORT LineConsumer { bool ParseSimpleFile( const string& path, LineConsumer* line_consumer, string* out_error); + +// Helper class for parsing framework import mappings and generating +// import statements. +class LIBPROTOC_EXPORT ImportWriter { + public: + ImportWriter(const Options& options) + : options_(options), + need_to_parse_mapping_file_(true) {} + + void AddFile(const FileDescriptor* file); + void Print(io::Printer *printer) const; + + private: + class ProtoFrameworkCollector : public LineConsumer { + public: + ProtoFrameworkCollector(map* inout_proto_file_to_framework_name) + : map_(inout_proto_file_to_framework_name) {} + + virtual bool ConsumeLine(const StringPiece& line, string* out_error); + + private: + map* map_; + }; + + void ParseFrameworkMappings(); + + const Options options_; + map proto_file_to_framework_name_; + bool need_to_parse_mapping_file_; + + vector protobuf_framework_imports_; + vector protobuf_non_framework_imports_; + vector other_framework_imports_; + vector other_imports_; +}; + } // namespace objectivec } // namespace compiler } // namespace protobuf