Commit 93362a5a authored by Thomas Van Lenten's avatar Thomas Van Lenten

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.
parent 80f65d2d
...@@ -54,205 +54,6 @@ const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30001; ...@@ -54,205 +54,6 @@ const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30001;
namespace compiler { namespace compiler {
namespace objectivec { 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) FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options)
: file_(file), : file_(file),
root_class_name_(FileClassName(file)), root_class_name_(FileClassName(file)),
...@@ -305,7 +106,7 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { ...@@ -305,7 +106,7 @@ void FileGenerator::GenerateHeader(io::Printer *printer) {
dependency_generators.begin(); dependency_generators.begin();
iter != dependency_generators.end(); ++iter) { iter != dependency_generators.end(); ++iter) {
if ((*iter)->IsPublicDependency()) { if ((*iter)->IsPublicDependency()) {
import_writer.AddFile(*iter); import_writer.AddFile((*iter)->file_);
} }
} }
import_writer.Print(printer); import_writer.Print(printer);
...@@ -410,7 +211,7 @@ void FileGenerator::GenerateSource(io::Printer *printer) { ...@@ -410,7 +211,7 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
ImportWriter import_writer(options_); ImportWriter import_writer(options_);
// #import the header for this proto file. // #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 // #import the headers for anything that a plain dependency of this proto
// file (that means they were just an include, not a "public" include). // file (that means they were just an include, not a "public" include).
...@@ -420,7 +221,7 @@ void FileGenerator::GenerateSource(io::Printer *printer) { ...@@ -420,7 +221,7 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
dependency_generators.begin(); dependency_generators.begin();
iter != dependency_generators.end(); ++iter) { iter != dependency_generators.end(); ++iter) {
if (!(*iter)->IsPublicDependency()) { if (!(*iter)->IsPublicDependency()) {
import_writer.AddFile(*iter); import_writer.AddFile((*iter)->file_);
} }
} }
......
...@@ -62,8 +62,6 @@ class FileGenerator { ...@@ -62,8 +62,6 @@ class FileGenerator {
void GenerateHeader(io::Printer* printer); void GenerateHeader(io::Printer* printer);
const string& RootClassName() const { return root_class_name_; } 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_; } bool IsPublicDependency() const { return is_public_dep_; }
......
...@@ -44,9 +44,10 @@ ...@@ -44,9 +44,10 @@
#include <google/protobuf/stubs/hash.h> #include <google/protobuf/stubs/hash.h>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/coded_stream.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/io/zero_copy_stream_impl.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/strutil.h>
...@@ -1433,6 +1434,167 @@ bool ParseSimpleFile( ...@@ -1433,6 +1434,167 @@ bool ParseSimpleFile(
return parser.Finish(); 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 objectivec
} // namespace compiler } // namespace compiler
......
...@@ -225,6 +225,42 @@ class LIBPROTOC_EXPORT LineConsumer { ...@@ -225,6 +225,42 @@ class LIBPROTOC_EXPORT LineConsumer {
bool ParseSimpleFile( bool ParseSimpleFile(
const string& path, LineConsumer* line_consumer, string* out_error); 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 objectivec
} // namespace compiler } // namespace compiler
} // namespace protobuf } // namespace protobuf
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment