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.
This commit is contained in:
parent
80f65d2df8
commit
93362a5aa5
@ -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<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_;
|
||||
vector<string> 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<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);
|
||||
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<string>::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<string>::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<string>::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<string>::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<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
|
||||
|
||||
|
||||
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_);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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_; }
|
||||
|
||||
|
@ -44,9 +44,10 @@
|
||||
|
||||
#include <google/protobuf/stubs/hash.h>
|
||||
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
@ -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<string, string>::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<string>::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<string>::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<string>::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<string>::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<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 objectivec
|
||||
} // namespace compiler
|
||||
|
@ -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<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_;
|
||||
vector<string> other_imports_;
|
||||
};
|
||||
|
||||
} // namespace objectivec
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
Loading…
Reference in New Issue
Block a user