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.
pull/1997/head
Thomas Van Lenten 8 years ago
parent 80f65d2df8
commit 93362a5aa5
  1. 205
      src/google/protobuf/compiler/objectivec/objectivec_file.cc
  2. 2
      src/google/protobuf/compiler/objectivec/objectivec_file.h
  3. 164
      src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
  4. 36
      src/google/protobuf/compiler/objectivec/objectivec_helpers.h

@ -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/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/descriptor.pb.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…
Cancel
Save