Make grpc-go proto plugin better: i) support external imports; ii) do not generate *_grpc.pb.go file if there is no service defined; ii) add more comment to gen.sh

This commit is contained in:
iamqizhao
2015-01-29 18:07:54 -08:00
parent 363fb13a4a
commit 796d00c003
3 changed files with 95 additions and 17 deletions

View File

@ -1,8 +1,14 @@
#!/bin/bash
# Please run this under the same directory where the input proto stays. The
# output will stay in the same directory. If this is not the behavior you want,
# feel free to make your own scripts.
# This script serves as an example to demonstrate how to generate the gRPC-Go
# interface and the related messages.
#
# We suggest the importing paths in proto file are relative to $GOPATH/src and
# this script should be run at $GOPATH/src.
#
# If this is not what you need, feel free to make your own scripts. Again, this
# script is for demonstration purpose.
#
locProtocGenGo=$1
locGoPlugIn=$2
proto=$3

View File

@ -79,12 +79,34 @@ string LowerCaseService(const string& service) {
return ret;
}
std::string BadToUnderscore(std::string str) {
for (unsigned i = 0; i < str.size(); ++i) {
if (!std::isalnum(str[i])) {
str[i] = '_';
}
}
return str;
}
const string GetFullName(const string& selfPkg,
const string& msgPkg,
const string& msgName) {
if (selfPkg == msgPkg) {
return msgName;
}
return BadToUnderscore(msgPkg) + "." + msgName;
}
void PrintClientMethodDef(google::protobuf::io::Printer* printer,
const google::protobuf::MethodDescriptor* method,
map<string, string>* vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type()->name();
(*vars)["Response"] = method->output_type()->name();
(*vars)["Request"] = GetFullName((*vars)["PackageName"],
method->input_type()->file()->package(),
method->input_type()->name());
(*vars)["Response"] = GetFullName((*vars)["PackageName"],
method->output_type()->file()->package(),
method->output_type()->name());
if (NoStreaming(method)) {
printer->Print(*vars,
"\t$Method$(ctx context.Context, in *$Request$, opts "
@ -110,9 +132,12 @@ void PrintClientMethodImpl(google::protobuf::io::Printer* printer,
const google::protobuf::MethodDescriptor* method,
map<string, string>* vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type()->name();
(*vars)["Response"] = method->output_type()->name();
(*vars)["Request"] = GetFullName((*vars)["PackageName"],
method->input_type()->file()->package(),
method->input_type()->name());
(*vars)["Response"] = GetFullName((*vars)["PackageName"],
method->output_type()->file()->package(),
method->output_type()->name());
if (NoStreaming(method)) {
printer->Print(
*vars,
@ -281,8 +306,12 @@ void PrintServerMethodDef(google::protobuf::io::Printer* printer,
const google::protobuf::MethodDescriptor* method,
map<string, string>* vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type()->name();
(*vars)["Response"] = method->output_type()->name();
(*vars)["Request"] = GetFullName((*vars)["PackageName"],
method->input_type()->file()->package(),
method->input_type()->name());
(*vars)["Response"] = GetFullName((*vars)["PackageName"],
method->output_type()->file()->package(),
method->output_type()->name());
if (NoStreaming(method)) {
printer->Print(
*vars,
@ -301,8 +330,12 @@ void PrintServerHandler(google::protobuf::io::Printer* printer,
const google::protobuf::MethodDescriptor* method,
map<string, string>* vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type()->name();
(*vars)["Response"] = method->output_type()->name();
(*vars)["Request"] = GetFullName((*vars)["PackageName"],
method->input_type()->file()->package(),
method->input_type()->name());
(*vars)["Response"] = GetFullName((*vars)["PackageName"],
method->output_type()->file()->package(),
method->output_type()->name());
if (NoStreaming(method)) {
printer->Print(
*vars,
@ -480,13 +513,46 @@ void PrintServer(google::protobuf::io::Printer* printer,
"}\n\n");
}
std::string BadToUnderscore(std::string str) {
for (unsigned i = 0; i < str.size(); ++i) {
if (!std::isalnum(str[i])) {
str[i] = '_';
void PrintMessageImports(
google::protobuf::io::Printer* printer,
const google::protobuf::FileDescriptor* file,
map<string, string>* vars) {
set<const google::protobuf::FileDescriptor*> descs;
set<string> importedPkgs;
for (int i = 0; i < file->service_count(); ++i) {
const google::protobuf::ServiceDescriptor* service = file->service(i);
for (int j = 0; j < service->method_count(); ++j) {
const google::protobuf::MethodDescriptor* method = service->method(i);
// Remove duplicated imports.
if (importedPkgs.find(
method->input_type()->file()->package()) == importedPkgs.end()) {
descs.insert(method->input_type()->file());
importedPkgs.insert(method->input_type()->file()->package());
}
if (importedPkgs.find(
method->output_type()->file()->package()) == importedPkgs.end()) {
descs.insert(method->output_type()->file());
importedPkgs.insert(method->output_type()->file()->package());
}
}
}
return str;
for (auto fd : descs) {
if (fd->package() == (*vars)["PackageName"]) {
continue;
}
string name = fd->name();
string import_path = "import \"";
if (name.find('/') == string::npos) {
// Assume all the proto in the same directory belong to the same package.
continue;
} else {
import_path += name.substr(0, name.find_last_of('/')) + "\"";
}
printer->Print(import_path.c_str());
printer->Print("\n");
}
printer->Print("\n");
}
string GetServices(const google::protobuf::FileDescriptor* file) {
@ -512,6 +578,8 @@ string GetServices(const google::protobuf::FileDescriptor* file) {
"\tproto \"github.com/golang/protobuf/proto\"\n"
")\n\n");
PrintMessageImports(&printer, file, &vars);
// $Package$ is used to fully qualify method names.
vars["Package"] = file->package();
if (!file->package().empty()) {

View File

@ -58,6 +58,10 @@ class GoGrpcGenerator : public google::protobuf::compiler::CodeGenerator {
const string& parameter,
google::protobuf::compiler::GeneratorContext* context,
string* error) const {
if (file->service_count() <= 0) {
// Do not generate anything if there is no rpc service defined.
return true;
}
// Get output file name.
string file_name;
if (file->name().size() > 6 &&