diff options
author | Thomas Van Lenten <thomasvl@google.com> | 2016-06-17 10:31:05 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-06-17 10:31:05 -0400 |
commit | 8c20e55c57c90a1a84ac7cf4de96e65911c8212b (patch) | |
tree | 0682f0331cefbe005f0d4e215e487d3179494516 /src/google/protobuf/compiler/objectivec/objectivec_file.cc | |
parent | 98bd6d753a2b15774c56ecd49763ceb2820d7075 (diff) |
Add new generation option for using proto sources from other frameworks.
- Better docs in the generator for the different options that can be passed
during an invoke of protoc.
- Add named_framework_to_proto_path_mappings_path to pass the path to a file
containing mappings of frameworks for different proto files.
- Update the generation to use the mapping to change the #import directives
it creates.
Note: the changes in helpers is mostly moving code within the fine, and then
a small change to expose the parsing so a passed on class can consume the line.
Fixes https://github.com/google/protobuf/issues/1457
Diffstat (limited to 'src/google/protobuf/compiler/objectivec/objectivec_file.cc')
-rw-r--r-- | src/google/protobuf/compiler/objectivec/objectivec_file.cc | 114 |
1 files changed, 109 insertions, 5 deletions
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index 73e6d8d7..cf8c34e1 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -37,8 +37,12 @@ #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/stubs/stl_util.h> #include <google/protobuf/stubs/strutil.h> +#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 { @@ -54,13 +58,31 @@ namespace { class ImportWriter { public: - ImportWriter(const Options& options) : options_(options) {} + 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<string, string>* inout_proto_file_to_framework_name) + : map_(inout_proto_file_to_framework_name) {} + + virtual bool ConsumeLine(const StringPiece& line, string* out_error); + + private: + map<string, string>* map_; + }; + + void ParseFrameworkMappings(); + const Options options_; + map<string, string> proto_file_to_framework_name_; + bool need_to_parse_mapping_file_; + vector<string> protobuf_framework_imports_; vector<string> protobuf_non_framework_imports_; vector<string> other_framework_imports_; @@ -70,20 +92,39 @@ class ImportWriter { 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); - } else if (!options_.generate_for_named_framework.empty()) { + return; + } + + // Lazy parse any mappings. + if (need_to_parse_mapping_file_) { + ParseFrameworkMappings(); + } + + map<string, string>::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); - } else { - other_imports_.push_back(file->Path() + extension); + return; } + + other_imports_.push_back(file->Path() + extension); } -void ImportWriter::Print(io::Printer *printer) const { +void ImportWriter::Print(io::Printer* printer) const { assert(protobuf_non_framework_imports_.size() == protobuf_framework_imports_.size()); @@ -146,6 +187,69 @@ void ImportWriter::Print(io::Printer *printer) const { } } +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); + StringPieceTrimWhitespace(&proto_file); + if (proto_file.size() != 0) { + map<string, string>::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 |