diff options
author | murgatroid99 <mlumish@google.com> | 2016-04-19 10:56:01 -0700 |
---|---|---|
committer | murgatroid99 <mlumish@google.com> | 2016-04-19 10:56:01 -0700 |
commit | e264e3984f6a5d8b730760d59930191a3a7c31e8 (patch) | |
tree | 7c3de6d924ae0e57cfcdab3bfee167e23ea8a546 /src/compiler | |
parent | 7d69ea63c8af9c7be43434993c82f93033343dce (diff) | |
parent | 279681311f61b079a720b7aef424cbe9000d08e8 (diff) |
Merged from master
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/cpp_generator.cc | 440 | ||||
-rw-r--r-- | src/compiler/cpp_generator.h | 97 | ||||
-rw-r--r-- | src/compiler/cpp_plugin.cc | 129 | ||||
-rw-r--r-- | src/compiler/csharp_generator.cc | 159 | ||||
-rw-r--r-- | src/compiler/python_generator.cc | 9 | ||||
-rw-r--r-- | src/compiler/python_generator.h | 2 | ||||
-rw-r--r-- | src/compiler/python_plugin.cc | 2 | ||||
-rw-r--r-- | src/compiler/ruby_generator.cc | 4 | ||||
-rw-r--r-- | src/compiler/ruby_generator_string-inl.h | 1 |
9 files changed, 528 insertions, 315 deletions
diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc index 97295bed45..b133699306 100644 --- a/src/compiler/cpp_generator.cc +++ b/src/compiler/cpp_generator.cc @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,9 +34,6 @@ #include <map> #include "src/compiler/cpp_generator.h" -#include "src/compiler/cpp_generator_helpers.h" - -#include "src/compiler/config.h" #include <sstream> @@ -50,22 +47,6 @@ grpc::string as_string(T x) { return out.str(); } -bool NoStreaming(const grpc::protobuf::MethodDescriptor *method) { - return !method->client_streaming() && !method->server_streaming(); -} - -bool ClientOnlyStreaming(const grpc::protobuf::MethodDescriptor *method) { - return method->client_streaming() && !method->server_streaming(); -} - -bool ServerOnlyStreaming(const grpc::protobuf::MethodDescriptor *method) { - return !method->client_streaming() && method->server_streaming(); -} - -bool BidiStreaming(const grpc::protobuf::MethodDescriptor *method) { - return method->client_streaming() && method->server_streaming(); -} - grpc::string FilenameIdentifier(const grpc::string &filename) { grpc::string result; for (unsigned i = 0; i < filename.size(); i++) { @@ -83,78 +64,103 @@ grpc::string FilenameIdentifier(const grpc::string &filename) { } } // namespace -grpc::string GetHeaderPrologue(const grpc::protobuf::FileDescriptor *file, - const Parameters ¶ms) { +template<class T, size_t N> +T *array_end(T (&array)[N]) { return array + N; } + +void PrintIncludes(Printer *printer, const std::vector<grpc::string>& headers, const Parameters ¶ms) { + std::map<grpc::string, grpc::string> vars; + + vars["l"] = params.use_system_headers ? '<' : '"'; + vars["r"] = params.use_system_headers ? '>' : '"'; + + if (!params.grpc_search_path.empty()) { + vars["l"] += params.grpc_search_path; + if (params.grpc_search_path.back() != '/') { + vars["l"] += '/'; + } + } + + for (auto i = headers.begin(); i != headers.end(); i++) { + vars["h"] = *i; + printer->Print(vars, "#include $l$$h$$r$\n"); + } +} + +grpc::string GetHeaderPrologue(File *file, const Parameters ¶ms) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. - grpc::protobuf::io::StringOutputStream output_stream(&output); - grpc::protobuf::io::Printer printer(&output_stream, '$'); + auto printer = file->CreatePrinter(&output); std::map<grpc::string, grpc::string> vars; - vars["filename"] = file->name(); - vars["filename_identifier"] = FilenameIdentifier(file->name()); - vars["filename_base"] = grpc_generator::StripProto(file->name()); + vars["filename"] = file->filename(); + vars["filename_identifier"] = FilenameIdentifier(file->filename()); + vars["filename_base"] = file->filename_without_ext(); - printer.Print(vars, "// Generated by the gRPC protobuf plugin.\n"); - printer.Print(vars, + printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n"); + printer->Print(vars, "// If you make any local change, they will be lost.\n"); - printer.Print(vars, "// source: $filename$\n"); - printer.Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n"); - printer.Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n"); - printer.Print(vars, "\n"); - printer.Print(vars, "#include \"$filename_base$.pb.h\"\n"); - printer.Print(vars, "\n"); + printer->Print(vars, "// source: $filename$\n"); + printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n"); + printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n"); + printer->Print(vars, "\n"); + printer->Print(vars, "#include \"$filename_base$.pb.h\"\n"); + printer->Print(vars, "\n"); } return output; } -grpc::string GetHeaderIncludes(const grpc::protobuf::FileDescriptor *file, +grpc::string GetHeaderIncludes(File *file, const Parameters ¶ms) { - grpc::string temp = - "#include <grpc++/impl/codegen/async_stream.h>\n" - "#include <grpc++/impl/codegen/async_unary_call.h>\n" - "#include <grpc++/impl/codegen/proto_utils.h>\n" - "#include <grpc++/impl/codegen/rpc_method.h>\n" - "#include <grpc++/impl/codegen/service_type.h>\n" - "#include <grpc++/impl/codegen/status.h>\n" - "#include <grpc++/impl/codegen/stub_options.h>\n" - "#include <grpc++/impl/codegen/sync_stream.h>\n" - "\n" - "namespace grpc {\n" - "class CompletionQueue;\n" - "class RpcService;\n" - "class ServerCompletionQueue;\n" - "class ServerContext;\n" - "} // namespace grpc\n\n"; + grpc::string output; + { + // Scope the output stream so it closes and finalizes output to the string. + auto printer = file->CreatePrinter(&output); + std::map<grpc::string, grpc::string> vars; - if (!file->package().empty()) { - std::vector<grpc::string> parts = - grpc_generator::tokenize(file->package(), "."); + static const char *headers_strs[] = { + "grpc++/impl/codegen/async_stream.h", + "grpc++/impl/codegen/async_unary_call.h", + "grpc++/impl/codegen/proto_utils.h", + "grpc++/impl/codegen/rpc_method.h", + "grpc++/impl/codegen/service_type.h", + "grpc++/impl/codegen/status.h", + "grpc++/impl/codegen/stub_options.h", + "grpc++/impl/codegen/sync_stream.h" + }; + std::vector<grpc::string> headers(headers_strs, array_end(headers_strs)); + PrintIncludes(printer.get(), headers, params); + printer->Print(vars, "\n"); + printer->Print(vars, "namespace grpc {\n"); + printer->Print(vars, "class CompletionQueue;\n"); + printer->Print(vars, "class Channel;\n"); + printer->Print(vars, "class RpcService;\n"); + printer->Print(vars, "class ServerCompletionQueue;\n"); + printer->Print(vars, "class ServerContext;\n"); + printer->Print(vars, "} // namespace grpc\n\n"); - for (auto part = parts.begin(); part != parts.end(); part++) { - temp.append("namespace "); - temp.append(*part); - temp.append(" {\n"); + if (!file->package().empty()) { + std::vector<grpc::string> parts = file->package_parts(); + + for (auto part = parts.begin(); part != parts.end(); part++) { + vars["part"] = *part; + printer->Print(vars, "namespace $part$ {\n"); + } + printer->Print(vars, "\n"); } - temp.append("\n"); } - - return temp; + return output; } void PrintHeaderClientMethodInterfaces( - grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, + Printer *printer, const Method *method, std::map<grpc::string, grpc::string> *vars, bool is_public) { (*vars)["Method"] = method->name(); - (*vars)["Request"] = - grpc_cpp_generator::ClassName(method->input_type(), true); - (*vars)["Response"] = - grpc_cpp_generator::ClassName(method->output_type(), true); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); if (is_public) { - if (NoStreaming(method)) { + if (method->NoStreaming()) { printer->Print( *vars, "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, " @@ -172,7 +178,7 @@ void PrintHeaderClientMethodInterfaces( "Async$Method$Raw(context, request, cq));\n"); printer->Outdent(); printer->Print("}\n"); - } else if (ClientOnlyStreaming(method)) { + } else if (method->ClientOnlyStreaming()) { printer->Print( *vars, "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>" @@ -198,7 +204,7 @@ void PrintHeaderClientMethodInterfaces( "Async$Method$Raw(context, response, cq, tag));\n"); printer->Outdent(); printer->Print("}\n"); - } else if (ServerOnlyStreaming(method)) { + } else if (method->ServerOnlyStreaming()) { printer->Print( *vars, "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>" @@ -224,7 +230,7 @@ void PrintHeaderClientMethodInterfaces( "Async$Method$Raw(context, request, cq, tag));\n"); printer->Outdent(); printer->Print("}\n"); - } else if (BidiStreaming(method)) { + } else if (method->BidiStreaming()) { printer->Print(*vars, "std::unique_ptr< ::grpc::ClientReaderWriterInterface< " "$Request$, $Response$>> " @@ -253,14 +259,14 @@ void PrintHeaderClientMethodInterfaces( printer->Print("}\n"); } } else { - if (NoStreaming(method)) { + if (method->NoStreaming()) { printer->Print( *vars, "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* " "Async$Method$Raw(::grpc::ClientContext* context, " "const $Request$& request, " "::grpc::CompletionQueue* cq) = 0;\n"); - } else if (ClientOnlyStreaming(method)) { + } else if (method->ClientOnlyStreaming()) { printer->Print( *vars, "virtual ::grpc::ClientWriterInterface< $Request$>*" @@ -271,7 +277,7 @@ void PrintHeaderClientMethodInterfaces( " Async$Method$Raw(::grpc::ClientContext* context, " "$Response$* response, " "::grpc::CompletionQueue* cq, void* tag) = 0;\n"); - } else if (ServerOnlyStreaming(method)) { + } else if (method->ServerOnlyStreaming()) { printer->Print( *vars, "virtual ::grpc::ClientReaderInterface< $Response$>* $Method$Raw(" @@ -282,7 +288,7 @@ void PrintHeaderClientMethodInterfaces( "Async$Method$Raw(" "::grpc::ClientContext* context, const $Request$& request, " "::grpc::CompletionQueue* cq, void* tag) = 0;\n"); - } else if (BidiStreaming(method)) { + } else if (method->BidiStreaming()) { printer->Print(*vars, "virtual ::grpc::ClientReaderWriterInterface< $Request$, " "$Response$>* " @@ -296,17 +302,15 @@ void PrintHeaderClientMethodInterfaces( } } -void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, +void PrintHeaderClientMethod(Printer *printer, + const Method *method, std::map<grpc::string, grpc::string> *vars, bool is_public) { (*vars)["Method"] = method->name(); - (*vars)["Request"] = - grpc_cpp_generator::ClassName(method->input_type(), true); - (*vars)["Response"] = - grpc_cpp_generator::ClassName(method->output_type(), true); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); if (is_public) { - if (NoStreaming(method)) { + if (method->NoStreaming()) { printer->Print( *vars, "::grpc::Status $Method$(::grpc::ClientContext* context, " @@ -324,7 +328,7 @@ void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer, "Async$Method$Raw(context, request, cq));\n"); printer->Outdent(); printer->Print("}\n"); - } else if (ClientOnlyStreaming(method)) { + } else if (method->ClientOnlyStreaming()) { printer->Print( *vars, "std::unique_ptr< ::grpc::ClientWriter< $Request$>>" @@ -348,7 +352,7 @@ void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer, "Async$Method$Raw(context, response, cq, tag));\n"); printer->Outdent(); printer->Print("}\n"); - } else if (ServerOnlyStreaming(method)) { + } else if (method->ServerOnlyStreaming()) { printer->Print( *vars, "std::unique_ptr< ::grpc::ClientReader< $Response$>>" @@ -374,7 +378,7 @@ void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer, "Async$Method$Raw(context, request, cq, tag));\n"); printer->Outdent(); printer->Print("}\n"); - } else if (BidiStreaming(method)) { + } else if (method->BidiStreaming()) { printer->Print( *vars, "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>" @@ -400,13 +404,13 @@ void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer, printer->Print("}\n"); } } else { - if (NoStreaming(method)) { + if (method->NoStreaming()) { printer->Print(*vars, "::grpc::ClientAsyncResponseReader< $Response$>* " "Async$Method$Raw(::grpc::ClientContext* context, " "const $Request$& request, " "::grpc::CompletionQueue* cq) GRPC_OVERRIDE;\n"); - } else if (ClientOnlyStreaming(method)) { + } else if (method->ClientOnlyStreaming()) { printer->Print(*vars, "::grpc::ClientWriter< $Request$>* $Method$Raw(" "::grpc::ClientContext* context, $Response$* response) " @@ -416,7 +420,7 @@ void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer, "::grpc::ClientAsyncWriter< $Request$>* Async$Method$Raw(" "::grpc::ClientContext* context, $Response$* response, " "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n"); - } else if (ServerOnlyStreaming(method)) { + } else if (method->ServerOnlyStreaming()) { printer->Print(*vars, "::grpc::ClientReader< $Response$>* $Method$Raw(" "::grpc::ClientContext* context, const $Request$& request)" @@ -426,7 +430,7 @@ void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer, "::grpc::ClientAsyncReader< $Response$>* Async$Method$Raw(" "::grpc::ClientContext* context, const $Request$& request, " "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n"); - } else if (BidiStreaming(method)) { + } else if (method->BidiStreaming()) { printer->Print( *vars, "::grpc::ClientReaderWriter< $Request$, $Response$>* " @@ -440,38 +444,34 @@ void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer, } } -void PrintHeaderClientMethodData(grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, +void PrintHeaderClientMethodData(Printer *printer, const Method *method, std::map<grpc::string, grpc::string> *vars) { (*vars)["Method"] = method->name(); printer->Print(*vars, "const ::grpc::RpcMethod rpcmethod_$Method$_;\n"); } -void PrintHeaderServerMethodSync(grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, +void PrintHeaderServerMethodSync(Printer *printer, const Method *method, std::map<grpc::string, grpc::string> *vars) { (*vars)["Method"] = method->name(); - (*vars)["Request"] = - grpc_cpp_generator::ClassName(method->input_type(), true); - (*vars)["Response"] = - grpc_cpp_generator::ClassName(method->output_type(), true); - if (NoStreaming(method)) { + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + if (method->NoStreaming()) { printer->Print(*vars, "virtual ::grpc::Status $Method$(" "::grpc::ServerContext* context, const $Request$* request, " "$Response$* response);\n"); - } else if (ClientOnlyStreaming(method)) { + } else if (method->ClientOnlyStreaming()) { printer->Print(*vars, "virtual ::grpc::Status $Method$(" "::grpc::ServerContext* context, " "::grpc::ServerReader< $Request$>* reader, " "$Response$* response);\n"); - } else if (ServerOnlyStreaming(method)) { + } else if (method->ServerOnlyStreaming()) { printer->Print(*vars, "virtual ::grpc::Status $Method$(" "::grpc::ServerContext* context, const $Request$* request, " "::grpc::ServerWriter< $Response$>* writer);\n"); - } else if (BidiStreaming(method)) { + } else if (method->BidiStreaming()) { printer->Print( *vars, "virtual ::grpc::Status $Method$(" @@ -482,20 +482,18 @@ void PrintHeaderServerMethodSync(grpc::protobuf::io::Printer *printer, } void PrintHeaderServerMethodAsync( - grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, + Printer *printer, + const Method *method, std::map<grpc::string, grpc::string> *vars) { (*vars)["Method"] = method->name(); - (*vars)["Request"] = - grpc_cpp_generator::ClassName(method->input_type(), true); - (*vars)["Response"] = - grpc_cpp_generator::ClassName(method->output_type(), true); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); printer->Print(*vars, "template <class BaseClass>\n"); printer->Print(*vars, "class WithAsyncMethod_$Method$ : public BaseClass {\n"); printer->Print( " private:\n" - " void BaseClassMustBeDerivedFromService(Service *service) {}\n"); + " void BaseClassMustBeDerivedFromService(const Service *service) {}\n"); printer->Print(" public:\n"); printer->Indent(); printer->Print(*vars, @@ -506,7 +504,7 @@ void PrintHeaderServerMethodAsync( "~WithAsyncMethod_$Method$() GRPC_OVERRIDE {\n" " BaseClassMustBeDerivedFromService(this);\n" "}\n"); - if (NoStreaming(method)) { + if (method->NoStreaming()) { printer->Print( *vars, "// disable synchronous version of this method\n" @@ -527,7 +525,7 @@ void PrintHeaderServerMethodAsync( " ::grpc::Service::RequestAsyncUnary($Idx$, context, " "request, response, new_call_cq, notification_cq, tag);\n"); printer->Print("}\n"); - } else if (ClientOnlyStreaming(method)) { + } else if (method->ClientOnlyStreaming()) { printer->Print( *vars, "// disable synchronous version of this method\n" @@ -549,7 +547,7 @@ void PrintHeaderServerMethodAsync( " ::grpc::Service::RequestAsyncClientStreaming($Idx$, " "context, reader, new_call_cq, notification_cq, tag);\n"); printer->Print("}\n"); - } else if (ServerOnlyStreaming(method)) { + } else if (method->ServerOnlyStreaming()) { printer->Print( *vars, "// disable synchronous version of this method\n" @@ -572,7 +570,7 @@ void PrintHeaderServerMethodAsync( " ::grpc::Service::RequestAsyncServerStreaming($Idx$, " "context, request, writer, new_call_cq, notification_cq, tag);\n"); printer->Print("}\n"); - } else if (BidiStreaming(method)) { + } else if (method->BidiStreaming()) { printer->Print( *vars, "// disable synchronous version of this method\n" @@ -600,20 +598,18 @@ void PrintHeaderServerMethodAsync( } void PrintHeaderServerMethodGeneric( - grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, + Printer *printer, + const Method *method, std::map<grpc::string, grpc::string> *vars) { (*vars)["Method"] = method->name(); - (*vars)["Request"] = - grpc_cpp_generator::ClassName(method->input_type(), true); - (*vars)["Response"] = - grpc_cpp_generator::ClassName(method->output_type(), true); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); printer->Print(*vars, "template <class BaseClass>\n"); printer->Print(*vars, "class WithGenericMethod_$Method$ : public BaseClass {\n"); printer->Print( " private:\n" - " void BaseClassMustBeDerivedFromService(Service *service) {}\n"); + " void BaseClassMustBeDerivedFromService(const Service *service) {}\n"); printer->Print(" public:\n"); printer->Indent(); printer->Print(*vars, @@ -624,7 +620,7 @@ void PrintHeaderServerMethodGeneric( "~WithGenericMethod_$Method$() GRPC_OVERRIDE {\n" " BaseClassMustBeDerivedFromService(this);\n" "}\n"); - if (NoStreaming(method)) { + if (method->NoStreaming()) { printer->Print( *vars, "// disable synchronous version of this method\n" @@ -634,7 +630,7 @@ void PrintHeaderServerMethodGeneric( " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); - } else if (ClientOnlyStreaming(method)) { + } else if (method->ClientOnlyStreaming()) { printer->Print( *vars, "// disable synchronous version of this method\n" @@ -645,7 +641,7 @@ void PrintHeaderServerMethodGeneric( " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); - } else if (ServerOnlyStreaming(method)) { + } else if (method->ServerOnlyStreaming()) { printer->Print( *vars, "// disable synchronous version of this method\n" @@ -656,7 +652,7 @@ void PrintHeaderServerMethodGeneric( " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); - } else if (BidiStreaming(method)) { + } else if (method->BidiStreaming()) { printer->Print( *vars, "// disable synchronous version of this method\n" @@ -672,8 +668,8 @@ void PrintHeaderServerMethodGeneric( printer->Print(*vars, "};\n"); } -void PrintHeaderService(grpc::protobuf::io::Printer *printer, - const grpc::protobuf::ServiceDescriptor *service, +void PrintHeaderService(Printer *printer, + const Service *service, std::map<grpc::string, grpc::string> *vars) { (*vars)["Service"] = service->name(); @@ -689,13 +685,13 @@ void PrintHeaderService(grpc::protobuf::io::Printer *printer, printer->Indent(); printer->Print("virtual ~StubInterface() {}\n"); for (int i = 0; i < service->method_count(); ++i) { - PrintHeaderClientMethodInterfaces(printer, service->method(i), vars, true); + PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, true); } printer->Outdent(); printer->Print("private:\n"); printer->Indent(); for (int i = 0; i < service->method_count(); ++i) { - PrintHeaderClientMethodInterfaces(printer, service->method(i), vars, false); + PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, false); } printer->Outdent(); printer->Print("};\n"); @@ -705,17 +701,17 @@ void PrintHeaderService(grpc::protobuf::io::Printer *printer, printer->Indent(); printer->Print("Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);\n"); for (int i = 0; i < service->method_count(); ++i) { - PrintHeaderClientMethod(printer, service->method(i), vars, true); + PrintHeaderClientMethod(printer, service->method(i).get(), vars, true); } printer->Outdent(); printer->Print("\n private:\n"); printer->Indent(); printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n"); for (int i = 0; i < service->method_count(); ++i) { - PrintHeaderClientMethod(printer, service->method(i), vars, false); + PrintHeaderClientMethod(printer, service->method(i).get(), vars, false); } for (int i = 0; i < service->method_count(); ++i) { - PrintHeaderClientMethodData(printer, service->method(i), vars); + PrintHeaderClientMethodData(printer, service->method(i).get(), vars); } printer->Outdent(); printer->Print("};\n"); @@ -734,7 +730,7 @@ void PrintHeaderService(grpc::protobuf::io::Printer *printer, printer->Print("Service();\n"); printer->Print("virtual ~Service();\n"); for (int i = 0; i < service->method_count(); ++i) { - PrintHeaderServerMethodSync(printer, service->method(i), vars); + PrintHeaderServerMethodSync(printer, service->method(i).get(), vars); } printer->Outdent(); printer->Print("};\n"); @@ -742,13 +738,13 @@ void PrintHeaderService(grpc::protobuf::io::Printer *printer, // Server side - Asynchronous for (int i = 0; i < service->method_count(); ++i) { (*vars)["Idx"] = as_string(i); - PrintHeaderServerMethodAsync(printer, service->method(i), vars); + PrintHeaderServerMethodAsync(printer, service->method(i).get(), vars); } printer->Print("typedef "); for (int i = 0; i < service->method_count(); ++i) { - (*vars)["method_name"] = service->method(i)->name(); + (*vars)["method_name"] = service->method(i).get()->name(); printer->Print(*vars, "WithAsyncMethod_$method_name$<"); } printer->Print("Service"); @@ -760,20 +756,19 @@ void PrintHeaderService(grpc::protobuf::io::Printer *printer, // Server side - Generic for (int i = 0; i < service->method_count(); ++i) { (*vars)["Idx"] = as_string(i); - PrintHeaderServerMethodGeneric(printer, service->method(i), vars); + PrintHeaderServerMethodGeneric(printer, service->method(i).get(), vars); } printer->Outdent(); printer->Print("};\n"); } -grpc::string GetHeaderServices(const grpc::protobuf::FileDescriptor *file, +grpc::string GetHeaderServices(File *file, const Parameters ¶ms) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. - grpc::protobuf::io::StringOutputStream output_stream(&output); - grpc::protobuf::io::Printer printer(&output_stream, '$'); + auto printer = file->CreatePrinter(&output); std::map<grpc::string, grpc::string> vars; // Package string is empty or ends with a dot. It is used to fully qualify // method names. @@ -784,117 +779,112 @@ grpc::string GetHeaderServices(const grpc::protobuf::FileDescriptor *file, if (!params.services_namespace.empty()) { vars["services_namespace"] = params.services_namespace; - printer.Print(vars, "\nnamespace $services_namespace$ {\n\n"); + printer->Print(vars, "\nnamespace $services_namespace$ {\n\n"); } for (int i = 0; i < file->service_count(); ++i) { - PrintHeaderService(&printer, file->service(i), &vars); - printer.Print("\n"); + PrintHeaderService(printer.get(), file->service(i).get(), &vars); + printer->Print("\n"); } if (!params.services_namespace.empty()) { - printer.Print(vars, "} // namespace $services_namespace$\n\n"); + printer->Print(vars, "} // namespace $services_namespace$\n\n"); } } return output; } -grpc::string GetHeaderEpilogue(const grpc::protobuf::FileDescriptor *file, +grpc::string GetHeaderEpilogue(File *file, const Parameters ¶ms) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. - grpc::protobuf::io::StringOutputStream output_stream(&output); - grpc::protobuf::io::Printer printer(&output_stream, '$'); + auto printer = file->CreatePrinter(&output); std::map<grpc::string, grpc::string> vars; - vars["filename"] = file->name(); - vars["filename_identifier"] = FilenameIdentifier(file->name()); + vars["filename"] = file->filename(); + vars["filename_identifier"] = FilenameIdentifier(file->filename()); if (!file->package().empty()) { - std::vector<grpc::string> parts = - grpc_generator::tokenize(file->package(), "."); + std::vector<grpc::string> parts = file->package_parts(); for (auto part = parts.rbegin(); part != parts.rend(); part++) { vars["part"] = *part; - printer.Print(vars, "} // namespace $part$\n"); + printer->Print(vars, "} // namespace $part$\n"); } - printer.Print(vars, "\n"); + printer->Print(vars, "\n"); } - printer.Print(vars, "\n"); - printer.Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n"); + printer->Print(vars, "\n"); + printer->Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n"); } return output; } -grpc::string GetSourcePrologue(const grpc::protobuf::FileDescriptor *file, +grpc::string GetSourcePrologue(File *file, const Parameters ¶ms) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. - grpc::protobuf::io::StringOutputStream output_stream(&output); - grpc::protobuf::io::Printer printer(&output_stream, '$'); + auto printer = file->CreatePrinter(&output); std::map<grpc::string, grpc::string> vars; - vars["filename"] = file->name(); - vars["filename_base"] = grpc_generator::StripProto(file->name()); + vars["filename"] = file->filename(); + vars["filename_base"] = file->filename_without_ext(); - printer.Print(vars, "// Generated by the gRPC protobuf plugin.\n"); - printer.Print(vars, + printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n"); + printer->Print(vars, "// If you make any local change, they will be lost.\n"); - printer.Print(vars, "// source: $filename$\n\n"); - printer.Print(vars, "#include \"$filename_base$.pb.h\"\n"); - printer.Print(vars, "#include \"$filename_base$.grpc.pb.h\"\n"); - printer.Print(vars, "\n"); + printer->Print(vars, "// source: $filename$\n\n"); + printer->Print(vars, "#include \"$filename_base$.pb.h\"\n"); + printer->Print(vars, "#include \"$filename_base$.grpc.pb.h\"\n"); + printer->Print(vars, "\n"); } return output; } -grpc::string GetSourceIncludes(const grpc::protobuf::FileDescriptor *file, - const Parameters ¶m) { +grpc::string GetSourceIncludes(File *file, + const Parameters ¶ms) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. - grpc::protobuf::io::StringOutputStream output_stream(&output); - grpc::protobuf::io::Printer printer(&output_stream, '$'); + auto printer = file->CreatePrinter(&output); std::map<grpc::string, grpc::string> vars; - printer.Print(vars, "#include <grpc++/impl/codegen/async_stream.h>\n"); - printer.Print(vars, "#include <grpc++/impl/codegen/async_unary_call.h>\n"); - printer.Print(vars, "#include <grpc++/impl/codegen/channel_interface.h>\n"); - printer.Print(vars, "#include <grpc++/impl/codegen/client_unary_call.h>\n"); - printer.Print(vars, - "#include <grpc++/impl/codegen/method_handler_impl.h>\n"); - printer.Print(vars, - "#include <grpc++/impl/codegen/rpc_service_method.h>\n"); - printer.Print(vars, "#include <grpc++/impl/codegen/service_type.h>\n"); - printer.Print(vars, "#include <grpc++/impl/codegen/sync_stream.h>\n"); + static const char *headers_strs[] = { + "grpc++/impl/codegen/async_stream.h", + "grpc++/impl/codegen/async_unary_call.h", + "grpc++/impl/codegen/channel_interface.h", + "grpc++/impl/codegen/client_unary_call.h", + "grpc++/impl/codegen/method_handler_impl.h", + "grpc++/impl/codegen/rpc_service_method.h", + "grpc++/impl/codegen/service_type.h", + "grpc++/impl/codegen/sync_stream.h" + }; + std::vector<grpc::string> headers(headers_strs, array_end(headers_strs)); + PrintIncludes(printer.get(), headers, params); if (!file->package().empty()) { - std::vector<grpc::string> parts = - grpc_generator::tokenize(file->package(), "."); + std::vector<grpc::string> parts = file->package_parts(); for (auto part = parts.begin(); part != parts.end(); part++) { vars["part"] = *part; - printer.Print(vars, "namespace $part$ {\n"); + printer->Print(vars, "namespace $part$ {\n"); } } - printer.Print(vars, "\n"); + printer->Print(vars, "\n"); } return output; } -void PrintSourceClientMethod(grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, +void PrintSourceClientMethod(Printer *printer, + const Method *method, std::map<grpc::string, grpc::string> *vars) { (*vars)["Method"] = method->name(); - (*vars)["Request"] = - grpc_cpp_generator::ClassName(method->input_type(), true); - (*vars)["Response"] = - grpc_cpp_generator::ClassName(method->output_type(), true); - if (NoStreaming(method)) { + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + if (method->NoStreaming()) { printer->Print(*vars, "::grpc::Status $ns$$Service$::Stub::$Method$(" "::grpc::ClientContext* context, " @@ -917,7 +907,7 @@ void PrintSourceClientMethod(grpc::protobuf::io::Printer *printer, "rpcmethod_$Method$_, " "context, request);\n" "}\n\n"); - } else if (ClientOnlyStreaming(method)) { + } else if (method->ClientOnlyStreaming()) { printer->Print(*vars, "::grpc::ClientWriter< $Request$>* " "$ns$$Service$::Stub::$Method$Raw(" @@ -939,7 +929,7 @@ void PrintSourceClientMethod(grpc::protobuf::io::Printer *printer, "rpcmethod_$Method$_, " "context, response, tag);\n" "}\n\n"); - } else if (ServerOnlyStreaming(method)) { + } else if (method->ServerOnlyStreaming()) { printer->Print( *vars, "::grpc::ClientReader< $Response$>* " @@ -962,7 +952,7 @@ void PrintSourceClientMethod(grpc::protobuf::io::Printer *printer, "rpcmethod_$Method$_, " "context, request, tag);\n" "}\n\n"); - } else if (BidiStreaming(method)) { + } else if (method->BidiStreaming()) { printer->Print( *vars, "::grpc::ClientReaderWriter< $Request$, $Response$>* " @@ -989,15 +979,13 @@ void PrintSourceClientMethod(grpc::protobuf::io::Printer *printer, } } -void PrintSourceServerMethod(grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, +void PrintSourceServerMethod(Printer *printer, + const Method *method, std::map<grpc::string, grpc::string> *vars) { (*vars)["Method"] = method->name(); - (*vars)["Request"] = - grpc_cpp_generator::ClassName(method->input_type(), true); - (*vars)["Response"] = - grpc_cpp_generator::ClassName(method->output_type(), true); - if (NoStreaming(method)) { + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + if (method->NoStreaming()) { printer->Print(*vars, "::grpc::Status $ns$$Service$::Service::$Method$(" "::grpc::ServerContext* context, " @@ -1009,7 +997,7 @@ void PrintSourceServerMethod(grpc::protobuf::io::Printer *printer, " return ::grpc::Status(" "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"); printer->Print("}\n\n"); - } else if (ClientOnlyStreaming(method)) { + } else if (method->ClientOnlyStreaming()) { printer->Print(*vars, "::grpc::Status $ns$$Service$::Service::$Method$(" "::grpc::ServerContext* context, " @@ -1022,7 +1010,7 @@ void PrintSourceServerMethod(grpc::protobuf::io::Printer *printer, " return ::grpc::Status(" "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"); printer->Print("}\n\n"); - } else if (ServerOnlyStreaming(method)) { + } else if (method->ServerOnlyStreaming()) { printer->Print(*vars, "::grpc::Status $ns$$Service$::Service::$Method$(" "::grpc::ServerContext* context, " @@ -1035,7 +1023,7 @@ void PrintSourceServerMethod(grpc::protobuf::io::Printer *printer, " return ::grpc::Status(" "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"); printer->Print("}\n\n"); - } else if (BidiStreaming(method)) { + } else if (method->BidiStreaming()) { printer->Print(*vars, "::grpc::Status $ns$$Service$::Service::$Method$(" "::grpc::ServerContext* context, " @@ -1050,15 +1038,15 @@ void PrintSourceServerMethod(grpc::protobuf::io::Printer *printer, } } -void PrintSourceService(grpc::protobuf::io::Printer *printer, - const grpc::protobuf::ServiceDescriptor *service, +void PrintSourceService(Printer *printer, + const Service *service, std::map<grpc::string, grpc::string> *vars) { (*vars)["Service"] = service->name(); printer->Print(*vars, "static const char* $prefix$$Service$_method_names[] = {\n"); for (int i = 0; i < service->method_count(); ++i) { - (*vars)["Method"] = service->method(i)->name(); + (*vars)["Method"] = service->method(i).get()->name(); printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n"); } printer->Print(*vars, "};\n\n"); @@ -1077,14 +1065,14 @@ void PrintSourceService(grpc::protobuf::io::Printer *printer, printer->Indent(); printer->Print(": channel_(channel)"); for (int i = 0; i < service->method_count(); ++i) { - const grpc::protobuf::MethodDescriptor *method = service->method(i); + auto method = service->method(i); (*vars)["Method"] = method->name(); (*vars)["Idx"] = as_string(i); - if (NoStreaming(method)) { + if (method->NoStreaming()) { (*vars)["StreamingType"] = "NORMAL_RPC"; - } else if (ClientOnlyStreaming(method)) { + } else if (method->ClientOnlyStreaming()) { (*vars)["StreamingType"] = "CLIENT_STREAMING"; - } else if (ServerOnlyStreaming(method)) { + } else if (method->ServerOnlyStreaming()) { (*vars)["StreamingType"] = "SERVER_STREAMING"; } else { (*vars)["StreamingType"] = "BIDI_STREAMING"; @@ -1101,21 +1089,19 @@ void PrintSourceService(grpc::protobuf::io::Printer *printer, for (int i = 0; i < service->method_count(); ++i) { (*vars)["Idx"] = as_string(i); - PrintSourceClientMethod(printer, service->method(i), vars); + PrintSourceClientMethod(printer, service->method(i).get(), vars); } printer->Print(*vars, "$ns$$Service$::Service::Service() {\n"); printer->Indent(); printer->Print(*vars, "(void)$prefix$$Service$_method_names;\n"); for (int i = 0; i < service->method_count(); ++i) { - const grpc::protobuf::MethodDescriptor *method = service->method(i); + auto method = service->method(i); (*vars)["Idx"] = as_string(i); (*vars)["Method"] = method->name(); - (*vars)["Request"] = - grpc_cpp_generator::ClassName(method->input_type(), true); - (*vars)["Response"] = - grpc_cpp_generator::ClassName(method->output_type(), true); - if (NoStreaming(method)) { + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + if (method->NoStreaming()) { printer->Print( *vars, "AddMethod(new ::grpc::RpcServiceMethod(\n" @@ -1125,7 +1111,7 @@ void PrintSourceService(grpc::protobuf::io::Printer *printer, "$Request$, " "$Response$>(\n" " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n"); - } else if (ClientOnlyStreaming(method)) { + } else if (method->ClientOnlyStreaming()) { printer->Print( *vars, "AddMethod(new ::grpc::RpcServiceMethod(\n" @@ -1134,7 +1120,7 @@ void PrintSourceService(grpc::protobuf::io::Printer *printer, " new ::grpc::ClientStreamingHandler< " "$ns$$Service$::Service, $Request$, $Response$>(\n" " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n"); - } else if (ServerOnlyStreaming(method)) { + } else if (method->ServerOnlyStreaming()) { printer->Print( *vars, "AddMethod(new ::grpc::RpcServiceMethod(\n" @@ -1143,7 +1129,7 @@ void PrintSourceService(grpc::protobuf::io::Printer *printer, " new ::grpc::ServerStreamingHandler< " "$ns$$Service$::Service, $Request$, $Response$>(\n" " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n"); - } else if (BidiStreaming(method)) { + } else if (method->BidiStreaming()) { printer->Print( *vars, "AddMethod(new ::grpc::RpcServiceMethod(\n" @@ -1161,17 +1147,16 @@ void PrintSourceService(grpc::protobuf::io::Printer *printer, "}\n\n"); for (int i = 0; i < service->method_count(); ++i) { (*vars)["Idx"] = as_string(i); - PrintSourceServerMethod(printer, service->method(i), vars); + PrintSourceServerMethod(printer, service->method(i).get(), vars); } } -grpc::string GetSourceServices(const grpc::protobuf::FileDescriptor *file, +grpc::string GetSourceServices(File *file, const Parameters ¶ms) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. - grpc::protobuf::io::StringOutputStream output_stream(&output); - grpc::protobuf::io::Printer printer(&output_stream, '$'); + auto printer = file->CreatePrinter(&output); std::map<grpc::string, grpc::string> vars; // Package string is empty or ends with a dot. It is used to fully qualify // method names. @@ -1188,20 +1173,19 @@ grpc::string GetSourceServices(const grpc::protobuf::FileDescriptor *file, } for (int i = 0; i < file->service_count(); ++i) { - PrintSourceService(&printer, file->service(i), &vars); - printer.Print("\n"); + PrintSourceService(printer.get(), file->service(i).get(), &vars); + printer->Print("\n"); } } return output; } -grpc::string GetSourceEpilogue(const grpc::protobuf::FileDescriptor *file, +grpc::string GetSourceEpilogue(File *file, const Parameters ¶ms) { grpc::string temp; if (!file->package().empty()) { - std::vector<grpc::string> parts = - grpc_generator::tokenize(file->package(), "."); + std::vector<grpc::string> parts = file->package_parts(); for (auto part = parts.begin(); part != parts.end(); part++) { temp.append("} // namespace "); diff --git a/src/compiler/cpp_generator.h b/src/compiler/cpp_generator.h index 70c2e985f6..99a60a2eae 100644 --- a/src/compiler/cpp_generator.h +++ b/src/compiler/cpp_generator.h @@ -34,7 +34,23 @@ #ifndef GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H #define GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H -#include "src/compiler/config.h" +// cpp_generator.h/.cc do not directly depend on GRPC/ProtoBuf, such that they +// can be used to generate code for other serialization systems, such as +// FlatBuffers. + +#include <memory> +#include <vector> + +#ifndef GRPC_CUSTOM_STRING +#include <string> +#define GRPC_CUSTOM_STRING std::string +#endif + +namespace grpc { + +typedef GRPC_CUSTOM_STRING string; + +} // namespace grpc namespace grpc_cpp_generator { @@ -42,39 +58,86 @@ namespace grpc_cpp_generator { struct Parameters { // Puts the service into a namespace grpc::string services_namespace; + // Use system includes (<>) or local includes ("") + bool use_system_headers; + // Prefix to any grpc include + grpc::string grpc_search_path; +}; + +// An abstract interface representing a method. +struct Method { + virtual ~Method() {} + + virtual grpc::string name() const = 0; + + virtual grpc::string input_type_name() const = 0; + virtual grpc::string output_type_name() const = 0; + + virtual bool NoStreaming() const = 0; + virtual bool ClientOnlyStreaming() const = 0; + virtual bool ServerOnlyStreaming() const = 0; + virtual bool BidiStreaming() const = 0; +}; + +// An abstract interface representing a service. +struct Service { + virtual ~Service() {} + + virtual grpc::string name() const = 0; + + virtual int method_count() const = 0; + virtual std::unique_ptr<const Method> method(int i) const = 0; +}; + +struct Printer { + virtual ~Printer() {} + + virtual void Print(const std::map<grpc::string, grpc::string> &vars, + const char *template_string) = 0; + virtual void Print(const char *string) = 0; + virtual void Indent() = 0; + virtual void Outdent() = 0; +}; + +// An interface that allows the source generated to be output using various +// libraries/idls/serializers. +struct File { + virtual ~File() {} + + virtual grpc::string filename() const = 0; + virtual grpc::string filename_without_ext() const = 0; + virtual grpc::string package() const = 0; + virtual std::vector<grpc::string> package_parts() const = 0; + + virtual int service_count() const = 0; + virtual std::unique_ptr<const Service> service(int i) const = 0; + + virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0; }; // Return the prologue of the generated header file. -grpc::string GetHeaderPrologue(const grpc::protobuf::FileDescriptor *file, - const Parameters ¶ms); +grpc::string GetHeaderPrologue(File *file, const Parameters ¶ms); // Return the includes needed for generated header file. -grpc::string GetHeaderIncludes(const grpc::protobuf::FileDescriptor *file, - const Parameters ¶ms); +grpc::string GetHeaderIncludes(File *file, const Parameters ¶ms); // Return the includes needed for generated source file. -grpc::string GetSourceIncludes(const grpc::protobuf::FileDescriptor *file, - const Parameters ¶ms); +grpc::string GetSourceIncludes(File *file, const Parameters ¶ms); // Return the epilogue of the generated header file. -grpc::string GetHeaderEpilogue(const grpc::protobuf::FileDescriptor *file, - const Parameters ¶ms); +grpc::string GetHeaderEpilogue(File *file, const Parameters ¶ms); // Return the prologue of the generated source file. -grpc::string GetSourcePrologue(const grpc::protobuf::FileDescriptor *file, - const Parameters ¶ms); +grpc::string GetSourcePrologue(File *file, const Parameters ¶ms); // Return the services for generated header file. -grpc::string GetHeaderServices(const grpc::protobuf::FileDescriptor *file, - const Parameters ¶ms); +grpc::string GetHeaderServices(File *file, const Parameters ¶ms); // Return the services for generated source file. -grpc::string GetSourceServices(const grpc::protobuf::FileDescriptor *file, - const Parameters ¶ms); +grpc::string GetSourceServices(File *file, const Parameters ¶ms); // Return the epilogue of the generated source file. -grpc::string GetSourceEpilogue(const grpc::protobuf::FileDescriptor *file, - const Parameters ¶ms); +grpc::string GetSourceEpilogue(File *file, const Parameters ¶ms); } // namespace grpc_cpp_generator diff --git a/src/compiler/cpp_plugin.cc b/src/compiler/cpp_plugin.cc index 88c704948e..f703c6453d 100644 --- a/src/compiler/cpp_plugin.cc +++ b/src/compiler/cpp_plugin.cc @@ -41,6 +41,105 @@ #include "src/compiler/cpp_generator.h" #include "src/compiler/cpp_generator_helpers.h" +class ProtoBufMethod : public grpc_cpp_generator::Method { + public: + ProtoBufMethod(const grpc::protobuf::MethodDescriptor *method) + : method_(method) {} + + grpc::string name() const { return method_->name(); } + + grpc::string input_type_name() const { + return grpc_cpp_generator::ClassName(method_->input_type(), true); + } + grpc::string output_type_name() const { + return grpc_cpp_generator::ClassName(method_->output_type(), true); + } + + bool NoStreaming() const { + return !method_->client_streaming() && !method_->server_streaming(); + } + + bool ClientOnlyStreaming() const { + return method_->client_streaming() && !method_->server_streaming(); + } + + bool ServerOnlyStreaming() const { + return !method_->client_streaming() && method_->server_streaming(); + } + + bool BidiStreaming() const { + return method_->client_streaming() && method_->server_streaming(); + } + + private: + const grpc::protobuf::MethodDescriptor *method_; +}; + +class ProtoBufService : public grpc_cpp_generator::Service { + public: + ProtoBufService(const grpc::protobuf::ServiceDescriptor *service) + : service_(service) {} + + grpc::string name() const { return service_->name(); } + + int method_count() const { return service_->method_count(); }; + std::unique_ptr<const grpc_cpp_generator::Method> method(int i) const { + return std::unique_ptr<const grpc_cpp_generator::Method>( + new ProtoBufMethod(service_->method(i))); + }; + + private: + const grpc::protobuf::ServiceDescriptor *service_; +}; + +class ProtoBufPrinter : public grpc_cpp_generator::Printer { + public: + ProtoBufPrinter(grpc::string *str) + : output_stream_(str), printer_(&output_stream_, '$') {} + + void Print(const std::map<grpc::string, grpc::string> &vars, + const char *string_template) { + printer_.Print(vars, string_template); + } + + void Print(const char *string) { printer_.Print(string); } + void Indent() { printer_.Indent(); } + void Outdent() { printer_.Outdent(); } + + private: + grpc::protobuf::io::StringOutputStream output_stream_; + grpc::protobuf::io::Printer printer_; +}; + +class ProtoBufFile : public grpc_cpp_generator::File { + public: + ProtoBufFile(const grpc::protobuf::FileDescriptor *file) : file_(file) {} + + grpc::string filename() const { return file_->name(); } + grpc::string filename_without_ext() const { + return grpc_generator::StripProto(filename()); + } + + grpc::string package() const { return file_->package(); } + std::vector<grpc::string> package_parts() const { + return grpc_generator::tokenize(package(), "."); + } + + int service_count() const { return file_->service_count(); }; + std::unique_ptr<const grpc_cpp_generator::Service> service(int i) const { + return std::unique_ptr<const grpc_cpp_generator::Service> ( + new ProtoBufService(file_->service(i))); + } + + std::unique_ptr<grpc_cpp_generator::Printer> CreatePrinter(grpc::string *str) const { + return std::unique_ptr<grpc_cpp_generator::Printer>( + new ProtoBufPrinter(str)); + } + + private: + const grpc::protobuf::FileDescriptor *file_; +}; + class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { public: CppGrpcGenerator() {} @@ -59,6 +158,9 @@ class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { } grpc_cpp_generator::Parameters generator_parameters; + generator_parameters.use_system_headers = true; + + ProtoBufFile pbfile(file); if (!parameter.empty()) { std::vector<grpc::string> parameters_list = @@ -70,6 +172,17 @@ class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { grpc_generator::tokenize(*parameter_string, "="); if (param[0] == "services_namespace") { generator_parameters.services_namespace = param[1]; + } else if (param[0] == "use_system_headers") { + if (param[1] == "true") { + generator_parameters.use_system_headers = true; + } else if (param[1] == "false") { + generator_parameters.use_system_headers = false; + } else { + *error = grpc::string("Invalid parameter: ") + *parameter_string; + return false; + } + } else if (param[0] == "grpc_search_path") { + generator_parameters.grpc_search_path = param[1]; } else { *error = grpc::string("Unknown parameter: ") + *parameter_string; return false; @@ -80,10 +193,10 @@ class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { grpc::string file_name = grpc_generator::StripProto(file->name()); grpc::string header_code = - grpc_cpp_generator::GetHeaderPrologue(file, generator_parameters) + - grpc_cpp_generator::GetHeaderIncludes(file, generator_parameters) + - grpc_cpp_generator::GetHeaderServices(file, generator_parameters) + - grpc_cpp_generator::GetHeaderEpilogue(file, generator_parameters); + grpc_cpp_generator::GetHeaderPrologue(&pbfile, generator_parameters) + + grpc_cpp_generator::GetHeaderIncludes(&pbfile, generator_parameters) + + grpc_cpp_generator::GetHeaderServices(&pbfile, generator_parameters) + + grpc_cpp_generator::GetHeaderEpilogue(&pbfile, generator_parameters); std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> header_output( context->Open(file_name + ".grpc.pb.h")); grpc::protobuf::io::CodedOutputStream header_coded_out( @@ -91,10 +204,10 @@ class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { header_coded_out.WriteRaw(header_code.data(), header_code.size()); grpc::string source_code = - grpc_cpp_generator::GetSourcePrologue(file, generator_parameters) + - grpc_cpp_generator::GetSourceIncludes(file, generator_parameters) + - grpc_cpp_generator::GetSourceServices(file, generator_parameters) + - grpc_cpp_generator::GetSourceEpilogue(file, generator_parameters); + grpc_cpp_generator::GetSourcePrologue(&pbfile, generator_parameters) + + grpc_cpp_generator::GetSourceIncludes(&pbfile, generator_parameters) + + grpc_cpp_generator::GetSourceServices(&pbfile, generator_parameters) + + grpc_cpp_generator::GetSourceEpilogue(&pbfile, generator_parameters); std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> source_output( context->Open(file_name + ".grpc.pb.cc")); grpc::protobuf::io::CodedOutputStream source_coded_out( diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index f6079bdc05..69e2738d53 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -81,6 +81,10 @@ std::string GetServerInterfaceName(const ServiceDescriptor* service) { return "I" + service->name(); } +std::string GetServerClassName(const ServiceDescriptor* service) { + return service->name() + "Base"; +} + std::string GetCSharpMethodType(MethodType method_type) { switch (method_type) { case METHODTYPE_NO_STREAMING: @@ -108,10 +112,14 @@ std::string GetMethodFieldName(const MethodDescriptor *method) { return "__Method_" + method->name(); } -std::string GetMethodRequestParamMaybe(const MethodDescriptor *method) { +std::string GetMethodRequestParamMaybe(const MethodDescriptor *method, + bool invocation_param=false) { if (method->client_streaming()) { return ""; } + if (invocation_param) { + return "request, "; + } return GetClassName(method->input_type()) + " request, "; } @@ -242,6 +250,8 @@ void GenerateServiceDescriptorProperty(Printer* out, const ServiceDescriptor *se void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) { out->Print("// client interface\n"); + out->Print("[System.Obsolete(\"Client side interfaced will be removed " + "in the next release. Use client class directly.\")]\n"); out->Print("public interface $name$\n", "name", GetClientInterfaceName(service)); out->Print("{\n"); @@ -290,6 +300,8 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) { void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) { out->Print("// server-side interface\n"); + out->Print("[System.Obsolete(\"Service implementations should inherit" + " from the generated abstract base class instead.\")]\n"); out->Print("public interface $name$\n", "name", GetServerInterfaceName(service)); out->Print("{\n"); @@ -309,21 +321,64 @@ void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) { out->Print("\n"); } +void GenerateServerClass(Printer* out, const ServiceDescriptor *service) { + out->Print("// server-side abstract class\n"); + out->Print("public abstract class $name$\n", "name", + GetServerClassName(service)); + out->Print("{\n"); + out->Indent(); + for (int i = 0; i < service->method_count(); i++) { + const MethodDescriptor *method = service->method(i); + out->Print( + "public virtual $returntype$ $methodname$($request$$response_stream_maybe$, " + "ServerCallContext context)\n", + "methodname", method->name(), "returntype", + GetMethodReturnTypeServer(method), "request", + GetMethodRequestParamServer(method), "response_stream_maybe", + GetMethodResponseStreamMaybe(method)); + out->Print("{\n"); + out->Indent(); + out->Print("throw new RpcException(" + "new Status(StatusCode.Unimplemented, \"\"));\n"); + out->Outdent(); + out->Print("}\n\n"); + } + out->Outdent(); + out->Print("}\n"); + out->Print("\n"); +} + void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { out->Print("// client stub\n"); out->Print( - "public class $name$ : ClientBase, $interface$\n", - "name", GetClientClassName(service), "interface", - GetClientInterfaceName(service)); + "public class $name$ : ClientBase<$name$>, $interface$\n", + "name", GetClientClassName(service), + "interface", GetClientInterfaceName(service)); out->Print("{\n"); out->Indent(); // constructors - out->Print( - "public $name$(Channel channel) : base(channel)\n", - "name", GetClientClassName(service)); + out->Print("public $name$(Channel channel) : base(channel)\n", + "name", GetClientClassName(service)); + out->Print("{\n"); + out->Print("}\n"); + out->Print("public $name$(CallInvoker callInvoker) : base(callInvoker)\n", + "name", GetClientClassName(service)); out->Print("{\n"); out->Print("}\n"); + out->Print("///<summary>Protected parameterless constructor to allow creation" + " of test doubles.</summary>\n"); + out->Print("protected $name$() : base()\n", + "name", GetClientClassName(service)); + out->Print("{\n"); + out->Print("}\n"); + out->Print("///<summary>Protected constructor to allow creation of configured" + " clients.</summary>\n"); + out->Print("protected $name$(ClientBaseConfiguration configuration)" + " : base(configuration)\n", + "name", GetClientClassName(service)); + out->Print("{\n"); + out->Print("}\n\n"); for (int i = 0; i < service->method_count(); i++) { const MethodDescriptor *method = service->method(i); @@ -331,30 +386,26 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { if (method_type == METHODTYPE_NO_STREAMING) { // unary calls have an extra synchronous stub method - out->Print( - "public $response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n", + out->Print("public virtual $response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n", "methodname", method->name(), "request", GetClassName(method->input_type()), "response", GetClassName(method->output_type())); out->Print("{\n"); out->Indent(); - out->Print("var call = CreateCall($methodfield$, new CallOptions(headers, deadline, cancellationToken));\n", - "methodfield", GetMethodFieldName(method)); - out->Print("return Calls.BlockingUnaryCall(call, request);\n"); + out->Print("return $methodname$(request, new CallOptions(headers, deadline, cancellationToken));\n", + "methodname", method->name()); out->Outdent(); out->Print("}\n"); // overload taking CallOptions as a param - out->Print( - "public $response$ $methodname$($request$ request, CallOptions options)\n", - "methodname", method->name(), "request", - GetClassName(method->input_type()), "response", - GetClassName(method->output_type())); + out->Print("public virtual $response$ $methodname$($request$ request, CallOptions options)\n", + "methodname", method->name(), "request", + GetClassName(method->input_type()), "response", + GetClassName(method->output_type())); out->Print("{\n"); out->Indent(); - out->Print("var call = CreateCall($methodfield$, options);\n", + out->Print("return CallInvoker.BlockingUnaryCall($methodfield$, null, options, request);\n", "methodfield", GetMethodFieldName(method)); - out->Print("return Calls.BlockingUnaryCall(call, request);\n"); out->Outdent(); out->Print("}\n"); } @@ -364,57 +415,44 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { method_name += "Async"; // prevent name clash with synchronous method. } out->Print( - "public $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n", - "methodname", method_name, "request_maybe", - GetMethodRequestParamMaybe(method), "returntype", - GetMethodReturnTypeClient(method)); + "public virtual $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n", + "methodname", method_name, "request_maybe", + GetMethodRequestParamMaybe(method), "returntype", + GetMethodReturnTypeClient(method)); out->Print("{\n"); out->Indent(); - out->Print("var call = CreateCall($methodfield$, new CallOptions(headers, deadline, cancellationToken));\n", - "methodfield", GetMethodFieldName(method)); - switch (GetMethodType(method)) { - case METHODTYPE_NO_STREAMING: - out->Print("return Calls.AsyncUnaryCall(call, request);\n"); - break; - case METHODTYPE_CLIENT_STREAMING: - out->Print("return Calls.AsyncClientStreamingCall(call);\n"); - break; - case METHODTYPE_SERVER_STREAMING: - out->Print( - "return Calls.AsyncServerStreamingCall(call, request);\n"); - break; - case METHODTYPE_BIDI_STREAMING: - out->Print("return Calls.AsyncDuplexStreamingCall(call);\n"); - break; - default: - GOOGLE_LOG(FATAL)<< "Can't get here."; - } + + out->Print("return $methodname$($request_maybe$new CallOptions(headers, deadline, cancellationToken));\n", + "methodname", method_name, + "request_maybe", GetMethodRequestParamMaybe(method, true)); out->Outdent(); out->Print("}\n"); // overload taking CallOptions as a param out->Print( - "public $returntype$ $methodname$($request_maybe$CallOptions options)\n", + "public virtual $returntype$ $methodname$($request_maybe$CallOptions options)\n", "methodname", method_name, "request_maybe", GetMethodRequestParamMaybe(method), "returntype", GetMethodReturnTypeClient(method)); out->Print("{\n"); out->Indent(); - out->Print("var call = CreateCall($methodfield$, options);\n", - "methodfield", GetMethodFieldName(method)); switch (GetMethodType(method)) { case METHODTYPE_NO_STREAMING: - out->Print("return Calls.AsyncUnaryCall(call, request);\n"); + out->Print("return CallInvoker.AsyncUnaryCall($methodfield$, null, options, request);\n", + "methodfield", GetMethodFieldName(method)); break; case METHODTYPE_CLIENT_STREAMING: - out->Print("return Calls.AsyncClientStreamingCall(call);\n"); + out->Print("return CallInvoker.AsyncClientStreamingCall($methodfield$, null, options);\n", + "methodfield", GetMethodFieldName(method)); break; case METHODTYPE_SERVER_STREAMING: out->Print( - "return Calls.AsyncServerStreamingCall(call, request);\n"); + "return CallInvoker.AsyncServerStreamingCall($methodfield$, null, options, request);\n", + "methodfield", GetMethodFieldName(method)); break; case METHODTYPE_BIDI_STREAMING: - out->Print("return Calls.AsyncDuplexStreamingCall(call);\n"); + out->Print("return CallInvoker.AsyncDuplexStreamingCall($methodfield$, null, options);\n", + "methodfield", GetMethodFieldName(method)); break; default: GOOGLE_LOG(FATAL)<< "Can't get here."; @@ -422,17 +460,30 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { out->Outdent(); out->Print("}\n"); } + + // override NewInstance method + out->Print("protected override $name$ NewInstance(ClientBaseConfiguration configuration)\n", + "name", GetClientClassName(service)); + out->Print("{\n"); + out->Indent(); + out->Print("return new $name$(configuration);\n", + "name", GetClientClassName(service)); + out->Outdent(); + out->Print("}\n"); + out->Outdent(); out->Print("}\n"); out->Print("\n"); } -void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service) { +void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service, + bool use_server_class) { out->Print( "// creates service definition that can be registered with a server\n"); out->Print( "public static ServerServiceDefinition BindService($interface$ serviceImpl)\n", - "interface", GetServerInterfaceName(service)); + "interface", use_server_class ? GetServerClassName(service) : + GetServerInterfaceName(service)); out->Print("{\n"); out->Indent(); @@ -489,8 +540,10 @@ void GenerateService(Printer* out, const ServiceDescriptor *service) { GenerateServiceDescriptorProperty(out, service); GenerateClientInterface(out, service); GenerateServerInterface(out, service); + GenerateServerClass(out, service); GenerateClientStub(out, service); - GenerateBindServiceMethod(out, service); + GenerateBindServiceMethod(out, service, false); + GenerateBindServiceMethod(out, service, true); GenerateNewStubMethods(out, service); out->Outdent(); diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc index 4fd5dfbecb..02c032800b 100644 --- a/src/compiler/python_generator.cc +++ b/src/compiler/python_generator.cc @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -190,11 +190,10 @@ bool PrintBetaServicer(const ServiceDescriptor* service, "Documentation", doc, }); out->Print("\n"); - out->Print(dict, "class Beta$Service$Servicer(object):\n"); + out->Print(dict, "class Beta$Service$Servicer(six.with_metaclass(abc.ABCMeta, object)):\n"); { IndentScope raii_class_indent(out); out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); - out->Print("__metaclass__ = abc.ABCMeta\n"); for (int i = 0; i < service->method_count(); ++i) { auto meth = service->method(i); grpc::string arg_name = meth->client_streaming() ? @@ -219,11 +218,10 @@ bool PrintBetaStub(const ServiceDescriptor* service, "Documentation", doc, }); out->Print("\n"); - out->Print(dict, "class Beta$Service$Stub(object):\n"); + out->Print(dict, "class Beta$Service$Stub(six.with_metaclass(abc.ABCMeta, object)):\n"); { IndentScope raii_class_indent(out); out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); - out->Print("__metaclass__ = abc.ABCMeta\n"); for (int i = 0; i < service->method_count(); ++i) { const MethodDescriptor* meth = service->method(i); grpc::string arg_name = meth->client_streaming() ? @@ -449,6 +447,7 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name, bool PrintPreamble(const FileDescriptor* file, const GeneratorConfiguration& config, Printer* out) { out->Print("import abc\n"); + out->Print("import six\n"); out->Print("from $Package$ import implementations as beta_implementations\n", "Package", config.beta_package_root); out->Print("from grpc.framework.common import cardinality\n"); diff --git a/src/compiler/python_generator.h b/src/compiler/python_generator.h index 68da18f9ba..e56b6790ef 100644 --- a/src/compiler/python_generator.h +++ b/src/compiler/python_generator.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/compiler/python_plugin.cc b/src/compiler/python_plugin.cc index d781ddbee5..92a07b2f80 100644 --- a/src/compiler/python_plugin.cc +++ b/src/compiler/python_plugin.cc @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/compiler/ruby_generator.cc b/src/compiler/ruby_generator.cc index 299137519f..5ac56ad289 100644 --- a/src/compiler/ruby_generator.cc +++ b/src/compiler/ruby_generator.cc @@ -55,11 +55,11 @@ namespace { // Prints out the method using the ruby gRPC DSL. void PrintMethod(const MethodDescriptor *method, const grpc::string &package, Printer *out) { - grpc::string input_type = RubyTypeOf(method->input_type()->name(), package); + grpc::string input_type = RubyTypeOf(method->input_type()->full_name(), package); if (method->client_streaming()) { input_type = "stream(" + input_type + ")"; } - grpc::string output_type = RubyTypeOf(method->output_type()->name(), package); + grpc::string output_type = RubyTypeOf(method->output_type()->full_name(), package); if (method->server_streaming()) { output_type = "stream(" + output_type + ")"; } diff --git a/src/compiler/ruby_generator_string-inl.h b/src/compiler/ruby_generator_string-inl.h index 8da3a88da2..d1ad871c1a 100644 --- a/src/compiler/ruby_generator_string-inl.h +++ b/src/compiler/ruby_generator_string-inl.h @@ -115,6 +115,7 @@ inline grpc::string RubyTypeOf(const grpc::string &a_type, return res; } else { std::vector<grpc::string> prefixes_and_type = Split(res, '.'); + res.clear(); for (unsigned int i = 0; i < prefixes_and_type.size(); ++i) { if (i != 0) { res += "::"; // switch '.' to the ruby module delim |