|
|
|
@ -31,6 +31,15 @@ |
|
|
|
|
#include <unordered_set> |
|
|
|
|
#include <vector> |
|
|
|
|
|
|
|
|
|
using ::google::protobuf::FileDescriptor; |
|
|
|
|
using ::google::protobuf::compiler::CodeGenerator; |
|
|
|
|
using ::google::protobuf::compiler::DiskSourceTree; |
|
|
|
|
using ::google::protobuf::compiler::GeneratorContext; |
|
|
|
|
using ::google::protobuf::compiler::Importer; |
|
|
|
|
using ::google::protobuf::compiler::MultiFileErrorCollector; |
|
|
|
|
using ::google::protobuf::io::StringOutputStream; |
|
|
|
|
using ::google::protobuf::io::ZeroCopyOutputStream; |
|
|
|
|
|
|
|
|
|
namespace grpc_tools { |
|
|
|
|
int protoc_main(int argc, char* argv[]) { |
|
|
|
|
google::protobuf::compiler::CommandLineInterface cli; |
|
|
|
@ -52,31 +61,26 @@ int protoc_main(int argc, char* argv[]) { |
|
|
|
|
|
|
|
|
|
namespace internal { |
|
|
|
|
|
|
|
|
|
class GeneratorContextImpl |
|
|
|
|
: public ::google::protobuf::compiler::GeneratorContext { |
|
|
|
|
class GeneratorContextImpl : public GeneratorContext { |
|
|
|
|
public: |
|
|
|
|
GeneratorContextImpl( |
|
|
|
|
const std::vector<const ::google::protobuf::FileDescriptor*>& |
|
|
|
|
parsed_files, |
|
|
|
|
const std::vector<const FileDescriptor*>& parsed_files, |
|
|
|
|
std::vector<std::pair<std::string, std::string>>* files_out) |
|
|
|
|
: files_(files_out), parsed_files_(parsed_files) {} |
|
|
|
|
|
|
|
|
|
::google::protobuf::io::ZeroCopyOutputStream* Open( |
|
|
|
|
const std::string& filename) { |
|
|
|
|
ZeroCopyOutputStream* Open(const std::string& filename) { |
|
|
|
|
files_->emplace_back(filename, ""); |
|
|
|
|
return new ::google::protobuf::io::StringOutputStream( |
|
|
|
|
&(files_->back().second)); |
|
|
|
|
return new StringOutputStream(&(files_->back().second)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// NOTE(rbellevi): Equivalent to Open, since all files start out empty.
|
|
|
|
|
::google::protobuf::io::ZeroCopyOutputStream* OpenForAppend( |
|
|
|
|
const std::string& filename) { |
|
|
|
|
ZeroCopyOutputStream* OpenForAppend(const std::string& filename) { |
|
|
|
|
return Open(filename); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// NOTE(rbellevi): Equivalent to Open, since all files start out empty.
|
|
|
|
|
::google::protobuf::io::ZeroCopyOutputStream* OpenForInsert( |
|
|
|
|
const std::string& filename, const std::string& insertion_point) { |
|
|
|
|
ZeroCopyOutputStream* OpenForInsert(const std::string& filename, |
|
|
|
|
const std::string& insertion_point) { |
|
|
|
|
return Open(filename); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -87,11 +91,10 @@ class GeneratorContextImpl |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
std::vector<std::pair<std::string, std::string>>* files_; |
|
|
|
|
const std::vector<const ::google::protobuf::FileDescriptor*>& parsed_files_; |
|
|
|
|
const std::vector<const FileDescriptor*>& parsed_files_; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class ErrorCollectorImpl |
|
|
|
|
: public ::google::protobuf::compiler::MultiFileErrorCollector { |
|
|
|
|
class ErrorCollectorImpl : public MultiFileErrorCollector { |
|
|
|
|
public: |
|
|
|
|
ErrorCollectorImpl(std::vector<::grpc_tools::ProtocError>* errors, |
|
|
|
|
std::vector<::grpc_tools::ProtocWarning>* warnings) |
|
|
|
@ -113,12 +116,11 @@ class ErrorCollectorImpl |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static void calculate_transitive_closure( |
|
|
|
|
const ::google::protobuf::FileDescriptor* descriptor, |
|
|
|
|
std::vector<const ::google::protobuf::FileDescriptor*>* transitive_closure, |
|
|
|
|
const FileDescriptor* descriptor, |
|
|
|
|
std::vector<const FileDescriptor*>* transitive_closure, |
|
|
|
|
std::unordered_set<const ::google::protobuf::FileDescriptor*>* visited) { |
|
|
|
|
for (int i = 0; i < descriptor->dependency_count(); ++i) { |
|
|
|
|
const ::google::protobuf::FileDescriptor* dependency = |
|
|
|
|
descriptor->dependency(i); |
|
|
|
|
const FileDescriptor* dependency = descriptor->dependency(i); |
|
|
|
|
if (visited->find(dependency) == visited->end()) { |
|
|
|
|
calculate_transitive_closure(dependency, transitive_closure, visited); |
|
|
|
|
} |
|
|
|
@ -130,27 +132,24 @@ static void calculate_transitive_closure( |
|
|
|
|
} // end namespace internal
|
|
|
|
|
|
|
|
|
|
static int generate_code( |
|
|
|
|
::google::protobuf::compiler::CodeGenerator* code_generator, |
|
|
|
|
char* protobuf_path, const std::vector<std::string>* include_paths, |
|
|
|
|
CodeGenerator* code_generator, char* protobuf_path, |
|
|
|
|
const std::vector<std::string>* include_paths, |
|
|
|
|
std::vector<std::pair<std::string, std::string>>* files_out, |
|
|
|
|
std::vector<::grpc_tools::ProtocError>* errors, |
|
|
|
|
std::vector<::grpc_tools::ProtocWarning>* warnings) { |
|
|
|
|
std::unique_ptr<internal::ErrorCollectorImpl> error_collector( |
|
|
|
|
new internal::ErrorCollectorImpl(errors, warnings)); |
|
|
|
|
std::unique_ptr<::google::protobuf::compiler::DiskSourceTree> source_tree( |
|
|
|
|
new ::google::protobuf::compiler::DiskSourceTree()); |
|
|
|
|
std::unique_ptr<DiskSourceTree> source_tree(new DiskSourceTree()); |
|
|
|
|
for (const auto& include_path : *include_paths) { |
|
|
|
|
source_tree->MapPath("", include_path); |
|
|
|
|
} |
|
|
|
|
::google::protobuf::compiler::Importer importer(source_tree.get(), |
|
|
|
|
error_collector.get()); |
|
|
|
|
const ::google::protobuf::FileDescriptor* parsed_file = |
|
|
|
|
importer.Import(protobuf_path); |
|
|
|
|
Importer importer(source_tree.get(), error_collector.get()); |
|
|
|
|
const FileDescriptor* parsed_file = importer.Import(protobuf_path); |
|
|
|
|
if (parsed_file == nullptr) { |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
std::vector<const ::google::protobuf::FileDescriptor*> transitive_closure; |
|
|
|
|
std::unordered_set<const ::google::protobuf::FileDescriptor*> visited; |
|
|
|
|
std::vector<const FileDescriptor*> transitive_closure; |
|
|
|
|
std::unordered_set<const FileDescriptor*> visited; |
|
|
|
|
internal::calculate_transitive_closure(parsed_file, &transitive_closure, |
|
|
|
|
&visited); |
|
|
|
|
internal::GeneratorContextImpl generator_context(transitive_closure, |
|
|
|
|