|
|
@ -36,11 +36,10 @@ |
|
|
|
#include <sstream> |
|
|
|
#include <sstream> |
|
|
|
#include <vector> |
|
|
|
#include <vector> |
|
|
|
|
|
|
|
|
|
|
|
#include "src/compiler/csharp_generator.h" |
|
|
|
|
|
|
|
#include "src/compiler/config.h" |
|
|
|
#include "src/compiler/config.h" |
|
|
|
#include "src/compiler/csharp_generator_helpers.h" |
|
|
|
|
|
|
|
#include "src/compiler/csharp_generator.h" |
|
|
|
#include "src/compiler/csharp_generator.h" |
|
|
|
|
|
|
|
#include "src/compiler/csharp_generator.h" |
|
|
|
|
|
|
|
#include "src/compiler/csharp_generator_helpers.h" |
|
|
|
|
|
|
|
|
|
|
|
using google::protobuf::compiler::csharp::GetFileNamespace; |
|
|
|
using google::protobuf::compiler::csharp::GetFileNamespace; |
|
|
|
using google::protobuf::compiler::csharp::GetClassName; |
|
|
|
using google::protobuf::compiler::csharp::GetClassName; |
|
|
@ -61,7 +60,6 @@ using grpc_generator::StringReplace; |
|
|
|
using std::map; |
|
|
|
using std::map; |
|
|
|
using std::vector; |
|
|
|
using std::vector; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace grpc_csharp_generator { |
|
|
|
namespace grpc_csharp_generator { |
|
|
|
namespace { |
|
|
|
namespace { |
|
|
|
|
|
|
|
|
|
|
@ -70,28 +68,37 @@ namespace { |
|
|
|
// Currently, we cannot easily reuse the functionality as
|
|
|
|
// Currently, we cannot easily reuse the functionality as
|
|
|
|
// google/protobuf/compiler/csharp/csharp_doc_comment.h is not a public header.
|
|
|
|
// google/protobuf/compiler/csharp/csharp_doc_comment.h is not a public header.
|
|
|
|
// TODO(jtattermusch): reuse the functionality from google/protobuf.
|
|
|
|
// TODO(jtattermusch): reuse the functionality from google/protobuf.
|
|
|
|
void GenerateDocCommentBodyImpl(grpc::protobuf::io::Printer* printer, grpc::protobuf::SourceLocation location) { |
|
|
|
void GenerateDocCommentBodyImpl(grpc::protobuf::io::Printer *printer, |
|
|
|
grpc::string comments = location.leading_comments.empty() ? |
|
|
|
grpc::protobuf::SourceLocation location) { |
|
|
|
location.trailing_comments : location.leading_comments; |
|
|
|
grpc::string comments = location.leading_comments.empty() |
|
|
|
|
|
|
|
? location.trailing_comments |
|
|
|
|
|
|
|
: location.leading_comments; |
|
|
|
if (comments.empty()) { |
|
|
|
if (comments.empty()) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
// XML escaping... no need for apostrophes etc as the whole text is going to be a child
|
|
|
|
// XML escaping... no need for apostrophes etc as the whole text is going to
|
|
|
|
|
|
|
|
// be a child
|
|
|
|
// node of a summary element, not part of an attribute.
|
|
|
|
// node of a summary element, not part of an attribute.
|
|
|
|
comments = grpc_generator::StringReplace(comments, "&", "&", true); |
|
|
|
comments = grpc_generator::StringReplace(comments, "&", "&", true); |
|
|
|
comments = grpc_generator::StringReplace(comments, "<", "<", true); |
|
|
|
comments = grpc_generator::StringReplace(comments, "<", "<", true); |
|
|
|
|
|
|
|
|
|
|
|
std::vector<grpc::string> lines; |
|
|
|
std::vector<grpc::string> lines; |
|
|
|
grpc_generator::Split(comments, '\n', &lines); |
|
|
|
grpc_generator::Split(comments, '\n', &lines); |
|
|
|
// TODO: We really should work out which part to put in the summary and which to put in the remarks...
|
|
|
|
// TODO: We really should work out which part to put in the summary and which
|
|
|
|
// but that needs to be part of a bigger effort to understand the markdown better anyway.
|
|
|
|
// to put in the remarks...
|
|
|
|
|
|
|
|
// but that needs to be part of a bigger effort to understand the markdown
|
|
|
|
|
|
|
|
// better anyway.
|
|
|
|
printer->Print("/// <summary>\n"); |
|
|
|
printer->Print("/// <summary>\n"); |
|
|
|
bool last_was_empty = false; |
|
|
|
bool last_was_empty = false; |
|
|
|
// We squash multiple blank lines down to one, and remove any trailing blank lines. We need
|
|
|
|
// We squash multiple blank lines down to one, and remove any trailing blank
|
|
|
|
// to preserve the blank lines themselves, as this is relevant in the markdown.
|
|
|
|
// lines. We need
|
|
|
|
// Note that we can't remove leading or trailing whitespace as *that's* relevant in markdown too.
|
|
|
|
// to preserve the blank lines themselves, as this is relevant in the
|
|
|
|
|
|
|
|
// markdown.
|
|
|
|
|
|
|
|
// Note that we can't remove leading or trailing whitespace as *that's*
|
|
|
|
|
|
|
|
// relevant in markdown too.
|
|
|
|
// (We don't skip "just whitespace" lines, either.)
|
|
|
|
// (We don't skip "just whitespace" lines, either.)
|
|
|
|
for (std::vector<grpc::string>::iterator it = lines.begin(); it != lines.end(); ++it) { |
|
|
|
for (std::vector<grpc::string>::iterator it = lines.begin(); |
|
|
|
|
|
|
|
it != lines.end(); ++it) { |
|
|
|
grpc::string line = *it; |
|
|
|
grpc::string line = *it; |
|
|
|
if (line.empty()) { |
|
|
|
if (line.empty()) { |
|
|
|
last_was_empty = true; |
|
|
|
last_was_empty = true; |
|
|
@ -107,8 +114,8 @@ void GenerateDocCommentBodyImpl(grpc::protobuf::io::Printer* printer, grpc::prot |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename DescriptorType> |
|
|
|
template <typename DescriptorType> |
|
|
|
void GenerateDocCommentBody( |
|
|
|
void GenerateDocCommentBody(grpc::protobuf::io::Printer *printer, |
|
|
|
grpc::protobuf::io::Printer* printer, const DescriptorType* descriptor) { |
|
|
|
const DescriptorType *descriptor) { |
|
|
|
grpc::protobuf::SourceLocation location; |
|
|
|
grpc::protobuf::SourceLocation location; |
|
|
|
if (descriptor->GetSourceLocation(&location)) { |
|
|
|
if (descriptor->GetSourceLocation(&location)) { |
|
|
|
GenerateDocCommentBodyImpl(printer, location); |
|
|
|
GenerateDocCommentBodyImpl(printer, location); |
|
|
@ -142,9 +149,7 @@ std::string GetCSharpMethodType(MethodType method_type) { |
|
|
|
return ""; |
|
|
|
return ""; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::string GetServiceNameFieldName() { |
|
|
|
std::string GetServiceNameFieldName() { return "__ServiceName"; } |
|
|
|
return "__ServiceName"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string GetMarshallerFieldName(const Descriptor *message) { |
|
|
|
std::string GetMarshallerFieldName(const Descriptor *message) { |
|
|
|
return "__Marshaller_" + message->name(); |
|
|
|
return "__Marshaller_" + message->name(); |
|
|
@ -174,14 +179,14 @@ std::string GetMethodReturnTypeClient(const MethodDescriptor *method) { |
|
|
|
case METHODTYPE_NO_STREAMING: |
|
|
|
case METHODTYPE_NO_STREAMING: |
|
|
|
return "AsyncUnaryCall<" + GetClassName(method->output_type()) + ">"; |
|
|
|
return "AsyncUnaryCall<" + GetClassName(method->output_type()) + ">"; |
|
|
|
case METHODTYPE_CLIENT_STREAMING: |
|
|
|
case METHODTYPE_CLIENT_STREAMING: |
|
|
|
return "AsyncClientStreamingCall<" + GetClassName(method->input_type()) |
|
|
|
return "AsyncClientStreamingCall<" + GetClassName(method->input_type()) + |
|
|
|
+ ", " + GetClassName(method->output_type()) + ">"; |
|
|
|
", " + GetClassName(method->output_type()) + ">"; |
|
|
|
case METHODTYPE_SERVER_STREAMING: |
|
|
|
case METHODTYPE_SERVER_STREAMING: |
|
|
|
return "AsyncServerStreamingCall<" + GetClassName(method->output_type()) |
|
|
|
return "AsyncServerStreamingCall<" + GetClassName(method->output_type()) + |
|
|
|
+ ">"; |
|
|
|
">"; |
|
|
|
case METHODTYPE_BIDI_STREAMING: |
|
|
|
case METHODTYPE_BIDI_STREAMING: |
|
|
|
return "AsyncDuplexStreamingCall<" + GetClassName(method->input_type()) |
|
|
|
return "AsyncDuplexStreamingCall<" + GetClassName(method->input_type()) + |
|
|
|
+ ", " + GetClassName(method->output_type()) + ">"; |
|
|
|
", " + GetClassName(method->output_type()) + ">"; |
|
|
|
} |
|
|
|
} |
|
|
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
|
|
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
|
|
|
return ""; |
|
|
|
return ""; |
|
|
@ -194,8 +199,8 @@ std::string GetMethodRequestParamServer(const MethodDescriptor *method) { |
|
|
|
return GetClassName(method->input_type()) + " request"; |
|
|
|
return GetClassName(method->input_type()) + " request"; |
|
|
|
case METHODTYPE_CLIENT_STREAMING: |
|
|
|
case METHODTYPE_CLIENT_STREAMING: |
|
|
|
case METHODTYPE_BIDI_STREAMING: |
|
|
|
case METHODTYPE_BIDI_STREAMING: |
|
|
|
return "IAsyncStreamReader<" + GetClassName(method->input_type()) |
|
|
|
return "IAsyncStreamReader<" + GetClassName(method->input_type()) + |
|
|
|
+ "> requestStream"; |
|
|
|
"> requestStream"; |
|
|
|
} |
|
|
|
} |
|
|
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
|
|
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
|
|
|
return ""; |
|
|
|
return ""; |
|
|
@ -205,7 +210,8 @@ std::string GetMethodReturnTypeServer(const MethodDescriptor *method) { |
|
|
|
switch (GetMethodType(method)) { |
|
|
|
switch (GetMethodType(method)) { |
|
|
|
case METHODTYPE_NO_STREAMING: |
|
|
|
case METHODTYPE_NO_STREAMING: |
|
|
|
case METHODTYPE_CLIENT_STREAMING: |
|
|
|
case METHODTYPE_CLIENT_STREAMING: |
|
|
|
return "global::System.Threading.Tasks.Task<" + GetClassName(method->output_type()) + ">"; |
|
|
|
return "global::System.Threading.Tasks.Task<" + |
|
|
|
|
|
|
|
GetClassName(method->output_type()) + ">"; |
|
|
|
case METHODTYPE_SERVER_STREAMING: |
|
|
|
case METHODTYPE_SERVER_STREAMING: |
|
|
|
case METHODTYPE_BIDI_STREAMING: |
|
|
|
case METHODTYPE_BIDI_STREAMING: |
|
|
|
return "global::System.Threading.Tasks.Task"; |
|
|
|
return "global::System.Threading.Tasks.Task"; |
|
|
@ -221,8 +227,8 @@ std::string GetMethodResponseStreamMaybe(const MethodDescriptor *method) { |
|
|
|
return ""; |
|
|
|
return ""; |
|
|
|
case METHODTYPE_SERVER_STREAMING: |
|
|
|
case METHODTYPE_SERVER_STREAMING: |
|
|
|
case METHODTYPE_BIDI_STREAMING: |
|
|
|
case METHODTYPE_BIDI_STREAMING: |
|
|
|
return ", IServerStreamWriter<" + GetClassName(method->output_type()) |
|
|
|
return ", IServerStreamWriter<" + GetClassName(method->output_type()) + |
|
|
|
+ "> responseStream"; |
|
|
|
"> responseStream"; |
|
|
|
} |
|
|
|
} |
|
|
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
|
|
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
|
|
|
return ""; |
|
|
|
return ""; |
|
|
@ -232,7 +238,8 @@ std::string GetMethodResponseStreamMaybe(const MethodDescriptor *method) { |
|
|
|
std::vector<const Descriptor *> GetUsedMessages( |
|
|
|
std::vector<const Descriptor *> GetUsedMessages( |
|
|
|
const ServiceDescriptor *service) { |
|
|
|
const ServiceDescriptor *service) { |
|
|
|
std::set<const Descriptor *> descriptor_set; |
|
|
|
std::set<const Descriptor *> descriptor_set; |
|
|
|
std::vector<const Descriptor*> result; // vector is to maintain stable ordering
|
|
|
|
std::vector<const Descriptor *> |
|
|
|
|
|
|
|
result; // vector is to maintain stable ordering
|
|
|
|
for (int i = 0; i < service->method_count(); i++) { |
|
|
|
for (int i = 0; i < service->method_count(); i++) { |
|
|
|
const MethodDescriptor *method = service->method(i); |
|
|
|
const MethodDescriptor *method = service->method(i); |
|
|
|
if (descriptor_set.find(method->input_type()) == descriptor_set.end()) { |
|
|
|
if (descriptor_set.find(method->input_type()) == descriptor_set.end()) { |
|
|
@ -252,7 +259,10 @@ void GenerateMarshallerFields(Printer* out, const ServiceDescriptor *service) { |
|
|
|
for (size_t i = 0; i < used_messages.size(); i++) { |
|
|
|
for (size_t i = 0; i < used_messages.size(); i++) { |
|
|
|
const Descriptor *message = used_messages[i]; |
|
|
|
const Descriptor *message = used_messages[i]; |
|
|
|
out->Print( |
|
|
|
out->Print( |
|
|
|
"static readonly Marshaller<$type$> $fieldname$ = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), $type$.Parser.ParseFrom);\n", |
|
|
|
"static readonly Marshaller<$type$> $fieldname$ = " |
|
|
|
|
|
|
|
"Marshallers.Create((arg) => " |
|
|
|
|
|
|
|
"global::Google.Protobuf.MessageExtensions.ToByteArray(arg), " |
|
|
|
|
|
|
|
"$type$.Parser.ParseFrom);\n", |
|
|
|
"fieldname", GetMarshallerFieldName(message), "type", |
|
|
|
"fieldname", GetMarshallerFieldName(message), "type", |
|
|
|
GetClassName(message)); |
|
|
|
GetClassName(message)); |
|
|
|
} |
|
|
|
} |
|
|
@ -261,7 +271,8 @@ void GenerateMarshallerFields(Printer* out, const ServiceDescriptor *service) { |
|
|
|
|
|
|
|
|
|
|
|
void GenerateStaticMethodField(Printer *out, const MethodDescriptor *method) { |
|
|
|
void GenerateStaticMethodField(Printer *out, const MethodDescriptor *method) { |
|
|
|
out->Print( |
|
|
|
out->Print( |
|
|
|
"static readonly Method<$request$, $response$> $fieldname$ = new Method<$request$, $response$>(\n", |
|
|
|
"static readonly Method<$request$, $response$> $fieldname$ = new " |
|
|
|
|
|
|
|
"Method<$request$, $response$>(\n", |
|
|
|
"fieldname", GetMethodFieldName(method), "request", |
|
|
|
"fieldname", GetMethodFieldName(method), "request", |
|
|
|
GetClassName(method->input_type()), "response", |
|
|
|
GetClassName(method->input_type()), "response", |
|
|
|
GetClassName(method->output_type())); |
|
|
|
GetClassName(method->output_type())); |
|
|
@ -281,11 +292,14 @@ void GenerateStaticMethodField(Printer* out, const MethodDescriptor *method) { |
|
|
|
out->Outdent(); |
|
|
|
out->Outdent(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void GenerateServiceDescriptorProperty(Printer* out, const ServiceDescriptor *service) { |
|
|
|
void GenerateServiceDescriptorProperty(Printer *out, |
|
|
|
|
|
|
|
const ServiceDescriptor *service) { |
|
|
|
std::ostringstream index; |
|
|
|
std::ostringstream index; |
|
|
|
index << service->index(); |
|
|
|
index << service->index(); |
|
|
|
out->Print("/// <summary>Service descriptor</summary>\n"); |
|
|
|
out->Print("/// <summary>Service descriptor</summary>\n"); |
|
|
|
out->Print("public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor\n"); |
|
|
|
out->Print( |
|
|
|
|
|
|
|
"public static global::Google.Protobuf.Reflection.ServiceDescriptor " |
|
|
|
|
|
|
|
"Descriptor\n"); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print(" get { return $umbrella$.Descriptor.Services[$index$]; }\n", |
|
|
|
out->Print(" get { return $umbrella$.Descriptor.Services[$index$]; }\n", |
|
|
|
"umbrella", GetReflectionClassName(service->file()), "index", |
|
|
|
"umbrella", GetReflectionClassName(service->file()), "index", |
|
|
@ -295,7 +309,9 @@ void GenerateServiceDescriptorProperty(Printer* out, const ServiceDescriptor *se |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void GenerateServerClass(Printer *out, const ServiceDescriptor *service) { |
|
|
|
void GenerateServerClass(Printer *out, const ServiceDescriptor *service) { |
|
|
|
out->Print("/// <summary>Base class for server-side implementations of $servicename$</summary>\n", |
|
|
|
out->Print( |
|
|
|
|
|
|
|
"/// <summary>Base class for server-side implementations of " |
|
|
|
|
|
|
|
"$servicename$</summary>\n", |
|
|
|
"servicename", GetServiceClassName(service)); |
|
|
|
"servicename", GetServiceClassName(service)); |
|
|
|
out->Print("public abstract class $name$\n", "name", |
|
|
|
out->Print("public abstract class $name$\n", "name", |
|
|
|
GetServerClassName(service)); |
|
|
|
GetServerClassName(service)); |
|
|
@ -305,7 +321,8 @@ void GenerateServerClass(Printer* out, const ServiceDescriptor *service) { |
|
|
|
const MethodDescriptor *method = service->method(i); |
|
|
|
const MethodDescriptor *method = service->method(i); |
|
|
|
GenerateDocCommentBody(out, method); |
|
|
|
GenerateDocCommentBody(out, method); |
|
|
|
out->Print( |
|
|
|
out->Print( |
|
|
|
"public virtual $returntype$ $methodname$($request$$response_stream_maybe$, " |
|
|
|
"public virtual $returntype$ " |
|
|
|
|
|
|
|
"$methodname$($request$$response_stream_maybe$, " |
|
|
|
"ServerCallContext context)\n", |
|
|
|
"ServerCallContext context)\n", |
|
|
|
"methodname", method->name(), "returntype", |
|
|
|
"methodname", method->name(), "returntype", |
|
|
|
GetMethodReturnTypeServer(method), "request", |
|
|
|
GetMethodReturnTypeServer(method), "request", |
|
|
@ -313,7 +330,8 @@ void GenerateServerClass(Printer* out, const ServiceDescriptor *service) { |
|
|
|
GetMethodResponseStreamMaybe(method)); |
|
|
|
GetMethodResponseStreamMaybe(method)); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Indent(); |
|
|
|
out->Indent(); |
|
|
|
out->Print("throw new RpcException(" |
|
|
|
out->Print( |
|
|
|
|
|
|
|
"throw new RpcException(" |
|
|
|
"new Status(StatusCode.Unimplemented, \"\"));\n"); |
|
|
|
"new Status(StatusCode.Unimplemented, \"\"));\n"); |
|
|
|
out->Outdent(); |
|
|
|
out->Outdent(); |
|
|
|
out->Print("}\n\n"); |
|
|
|
out->Print("}\n\n"); |
|
|
@ -324,38 +342,46 @@ void GenerateServerClass(Printer* out, const ServiceDescriptor *service) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void GenerateClientStub(Printer *out, const ServiceDescriptor *service) { |
|
|
|
void GenerateClientStub(Printer *out, const ServiceDescriptor *service) { |
|
|
|
out->Print("/// <summary>Client for $servicename$</summary>\n", |
|
|
|
out->Print("/// <summary>Client for $servicename$</summary>\n", "servicename", |
|
|
|
"servicename", GetServiceClassName(service)); |
|
|
|
GetServiceClassName(service)); |
|
|
|
out->Print( |
|
|
|
out->Print("public class $name$ : ClientBase<$name$>\n", "name", |
|
|
|
"public class $name$ : ClientBase<$name$>\n", |
|
|
|
GetClientClassName(service)); |
|
|
|
"name", GetClientClassName(service)); |
|
|
|
|
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Indent(); |
|
|
|
out->Indent(); |
|
|
|
|
|
|
|
|
|
|
|
// constructors
|
|
|
|
// constructors
|
|
|
|
out->Print("/// <summary>Creates a new client for $servicename$</summary>\n" |
|
|
|
out->Print( |
|
|
|
"/// <param name=\"channel\">The channel to use to make remote calls.</param>\n", |
|
|
|
"/// <summary>Creates a new client for $servicename$</summary>\n" |
|
|
|
|
|
|
|
"/// <param name=\"channel\">The channel to use to make remote " |
|
|
|
|
|
|
|
"calls.</param>\n", |
|
|
|
"servicename", GetServiceClassName(service)); |
|
|
|
"servicename", GetServiceClassName(service)); |
|
|
|
out->Print("public $name$(Channel channel) : base(channel)\n", |
|
|
|
out->Print("public $name$(Channel channel) : base(channel)\n", "name", |
|
|
|
"name", GetClientClassName(service)); |
|
|
|
GetClientClassName(service)); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("}\n"); |
|
|
|
out->Print("}\n"); |
|
|
|
out->Print("/// <summary>Creates a new client for $servicename$ that uses a custom <c>CallInvoker</c>.</summary>\n" |
|
|
|
out->Print( |
|
|
|
"/// <param name=\"callInvoker\">The callInvoker to use to make remote calls.</param>\n", |
|
|
|
"/// <summary>Creates a new client for $servicename$ that uses a custom " |
|
|
|
|
|
|
|
"<c>CallInvoker</c>.</summary>\n" |
|
|
|
|
|
|
|
"/// <param name=\"callInvoker\">The callInvoker to use to make remote " |
|
|
|
|
|
|
|
"calls.</param>\n", |
|
|
|
"servicename", GetServiceClassName(service)); |
|
|
|
"servicename", GetServiceClassName(service)); |
|
|
|
out->Print("public $name$(CallInvoker callInvoker) : base(callInvoker)\n", |
|
|
|
out->Print("public $name$(CallInvoker callInvoker) : base(callInvoker)\n", |
|
|
|
"name", GetClientClassName(service)); |
|
|
|
"name", GetClientClassName(service)); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("}\n"); |
|
|
|
out->Print("}\n"); |
|
|
|
out->Print("/// <summary>Protected parameterless constructor to allow creation" |
|
|
|
out->Print( |
|
|
|
|
|
|
|
"/// <summary>Protected parameterless constructor to allow creation" |
|
|
|
" of test doubles.</summary>\n"); |
|
|
|
" of test doubles.</summary>\n"); |
|
|
|
out->Print("protected $name$() : base()\n", |
|
|
|
out->Print("protected $name$() : base()\n", "name", |
|
|
|
"name", GetClientClassName(service)); |
|
|
|
GetClientClassName(service)); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("}\n"); |
|
|
|
out->Print("}\n"); |
|
|
|
out->Print("/// <summary>Protected constructor to allow creation of configured clients.</summary>\n" |
|
|
|
out->Print( |
|
|
|
|
|
|
|
"/// <summary>Protected constructor to allow creation of configured " |
|
|
|
|
|
|
|
"clients.</summary>\n" |
|
|
|
"/// <param name=\"configuration\">The client configuration.</param>\n"); |
|
|
|
"/// <param name=\"configuration\">The client configuration.</param>\n"); |
|
|
|
out->Print("protected $name$(ClientBaseConfiguration configuration)" |
|
|
|
out->Print( |
|
|
|
|
|
|
|
"protected $name$(ClientBaseConfiguration configuration)" |
|
|
|
" : base(configuration)\n", |
|
|
|
" : base(configuration)\n", |
|
|
|
"name", GetClientClassName(service)); |
|
|
|
"name", GetClientClassName(service)); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("{\n"); |
|
|
@ -368,26 +394,35 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { |
|
|
|
if (method_type == METHODTYPE_NO_STREAMING) { |
|
|
|
if (method_type == METHODTYPE_NO_STREAMING) { |
|
|
|
// unary calls have an extra synchronous stub method
|
|
|
|
// unary calls have an extra synchronous stub method
|
|
|
|
GenerateDocCommentBody(out, method); |
|
|
|
GenerateDocCommentBody(out, method); |
|
|
|
out->Print("public virtual $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", |
|
|
|
"methodname", method->name(), "request", |
|
|
|
GetClassName(method->input_type()), "response", |
|
|
|
GetClassName(method->input_type()), "response", |
|
|
|
GetClassName(method->output_type())); |
|
|
|
GetClassName(method->output_type())); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Indent(); |
|
|
|
out->Indent(); |
|
|
|
out->Print("return $methodname$(request, new CallOptions(headers, deadline, cancellationToken));\n", |
|
|
|
out->Print( |
|
|
|
|
|
|
|
"return $methodname$(request, new CallOptions(headers, deadline, " |
|
|
|
|
|
|
|
"cancellationToken));\n", |
|
|
|
"methodname", method->name()); |
|
|
|
"methodname", method->name()); |
|
|
|
out->Outdent(); |
|
|
|
out->Outdent(); |
|
|
|
out->Print("}\n"); |
|
|
|
out->Print("}\n"); |
|
|
|
|
|
|
|
|
|
|
|
// overload taking CallOptions as a param
|
|
|
|
// overload taking CallOptions as a param
|
|
|
|
GenerateDocCommentBody(out, method); |
|
|
|
GenerateDocCommentBody(out, method); |
|
|
|
out->Print("public virtual $response$ $methodname$($request$ request, CallOptions options)\n", |
|
|
|
out->Print( |
|
|
|
|
|
|
|
"public virtual $response$ $methodname$($request$ request, " |
|
|
|
|
|
|
|
"CallOptions options)\n", |
|
|
|
"methodname", method->name(), "request", |
|
|
|
"methodname", method->name(), "request", |
|
|
|
GetClassName(method->input_type()), "response", |
|
|
|
GetClassName(method->input_type()), "response", |
|
|
|
GetClassName(method->output_type())); |
|
|
|
GetClassName(method->output_type())); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Indent(); |
|
|
|
out->Indent(); |
|
|
|
out->Print("return CallInvoker.BlockingUnaryCall($methodfield$, null, options, request);\n", |
|
|
|
out->Print( |
|
|
|
|
|
|
|
"return CallInvoker.BlockingUnaryCall($methodfield$, null, options, " |
|
|
|
|
|
|
|
"request);\n", |
|
|
|
"methodfield", GetMethodFieldName(method)); |
|
|
|
"methodfield", GetMethodFieldName(method)); |
|
|
|
out->Outdent(); |
|
|
|
out->Outdent(); |
|
|
|
out->Print("}\n"); |
|
|
|
out->Print("}\n"); |
|
|
@ -399,23 +434,28 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { |
|
|
|
} |
|
|
|
} |
|
|
|
GenerateDocCommentBody(out, method); |
|
|
|
GenerateDocCommentBody(out, method); |
|
|
|
out->Print( |
|
|
|
out->Print( |
|
|
|
"public virtual $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n", |
|
|
|
"public virtual $returntype$ $methodname$($request_maybe$Metadata " |
|
|
|
|
|
|
|
"headers = null, DateTime? deadline = null, CancellationToken " |
|
|
|
|
|
|
|
"cancellationToken = default(CancellationToken))\n", |
|
|
|
"methodname", method_name, "request_maybe", |
|
|
|
"methodname", method_name, "request_maybe", |
|
|
|
GetMethodRequestParamMaybe(method), "returntype", |
|
|
|
GetMethodRequestParamMaybe(method), "returntype", |
|
|
|
GetMethodReturnTypeClient(method)); |
|
|
|
GetMethodReturnTypeClient(method)); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Indent(); |
|
|
|
out->Indent(); |
|
|
|
|
|
|
|
|
|
|
|
out->Print("return $methodname$($request_maybe$new CallOptions(headers, deadline, cancellationToken));\n", |
|
|
|
out->Print( |
|
|
|
"methodname", method_name, |
|
|
|
"return $methodname$($request_maybe$new CallOptions(headers, deadline, " |
|
|
|
"request_maybe", GetMethodRequestParamMaybe(method, true)); |
|
|
|
"cancellationToken));\n", |
|
|
|
|
|
|
|
"methodname", method_name, "request_maybe", |
|
|
|
|
|
|
|
GetMethodRequestParamMaybe(method, true)); |
|
|
|
out->Outdent(); |
|
|
|
out->Outdent(); |
|
|
|
out->Print("}\n"); |
|
|
|
out->Print("}\n"); |
|
|
|
|
|
|
|
|
|
|
|
// overload taking CallOptions as a param
|
|
|
|
// overload taking CallOptions as a param
|
|
|
|
GenerateDocCommentBody(out, method); |
|
|
|
GenerateDocCommentBody(out, method); |
|
|
|
out->Print( |
|
|
|
out->Print( |
|
|
|
"public virtual $returntype$ $methodname$($request_maybe$CallOptions options)\n", |
|
|
|
"public virtual $returntype$ $methodname$($request_maybe$CallOptions " |
|
|
|
|
|
|
|
"options)\n", |
|
|
|
"methodname", method_name, "request_maybe", |
|
|
|
"methodname", method_name, "request_maybe", |
|
|
|
GetMethodRequestParamMaybe(method), "returntype", |
|
|
|
GetMethodRequestParamMaybe(method), "returntype", |
|
|
|
GetMethodReturnTypeClient(method)); |
|
|
|
GetMethodReturnTypeClient(method)); |
|
|
@ -423,20 +463,27 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { |
|
|
|
out->Indent(); |
|
|
|
out->Indent(); |
|
|
|
switch (GetMethodType(method)) { |
|
|
|
switch (GetMethodType(method)) { |
|
|
|
case METHODTYPE_NO_STREAMING: |
|
|
|
case METHODTYPE_NO_STREAMING: |
|
|
|
out->Print("return CallInvoker.AsyncUnaryCall($methodfield$, null, options, request);\n", |
|
|
|
out->Print( |
|
|
|
|
|
|
|
"return CallInvoker.AsyncUnaryCall($methodfield$, null, options, " |
|
|
|
|
|
|
|
"request);\n", |
|
|
|
"methodfield", GetMethodFieldName(method)); |
|
|
|
"methodfield", GetMethodFieldName(method)); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case METHODTYPE_CLIENT_STREAMING: |
|
|
|
case METHODTYPE_CLIENT_STREAMING: |
|
|
|
out->Print("return CallInvoker.AsyncClientStreamingCall($methodfield$, null, options);\n", |
|
|
|
out->Print( |
|
|
|
|
|
|
|
"return CallInvoker.AsyncClientStreamingCall($methodfield$, null, " |
|
|
|
|
|
|
|
"options);\n", |
|
|
|
"methodfield", GetMethodFieldName(method)); |
|
|
|
"methodfield", GetMethodFieldName(method)); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case METHODTYPE_SERVER_STREAMING: |
|
|
|
case METHODTYPE_SERVER_STREAMING: |
|
|
|
out->Print( |
|
|
|
out->Print( |
|
|
|
"return CallInvoker.AsyncServerStreamingCall($methodfield$, null, options, request);\n", |
|
|
|
"return CallInvoker.AsyncServerStreamingCall($methodfield$, null, " |
|
|
|
|
|
|
|
"options, request);\n", |
|
|
|
"methodfield", GetMethodFieldName(method)); |
|
|
|
"methodfield", GetMethodFieldName(method)); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case METHODTYPE_BIDI_STREAMING: |
|
|
|
case METHODTYPE_BIDI_STREAMING: |
|
|
|
out->Print("return CallInvoker.AsyncDuplexStreamingCall($methodfield$, null, options);\n", |
|
|
|
out->Print( |
|
|
|
|
|
|
|
"return CallInvoker.AsyncDuplexStreamingCall($methodfield$, null, " |
|
|
|
|
|
|
|
"options);\n", |
|
|
|
"methodfield", GetMethodFieldName(method)); |
|
|
|
"methodfield", GetMethodFieldName(method)); |
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
@ -447,12 +494,14 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// override NewInstance method
|
|
|
|
// override NewInstance method
|
|
|
|
out->Print("protected override $name$ NewInstance(ClientBaseConfiguration configuration)\n", |
|
|
|
out->Print( |
|
|
|
|
|
|
|
"protected override $name$ NewInstance(ClientBaseConfiguration " |
|
|
|
|
|
|
|
"configuration)\n", |
|
|
|
"name", GetClientClassName(service)); |
|
|
|
"name", GetClientClassName(service)); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Indent(); |
|
|
|
out->Indent(); |
|
|
|
out->Print("return new $name$(configuration);\n", |
|
|
|
out->Print("return new $name$(configuration);\n", "name", |
|
|
|
"name", GetClientClassName(service)); |
|
|
|
GetClientClassName(service)); |
|
|
|
out->Outdent(); |
|
|
|
out->Outdent(); |
|
|
|
out->Print("}\n"); |
|
|
|
out->Print("}\n"); |
|
|
|
|
|
|
|
|
|
|
@ -463,9 +512,11 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { |
|
|
|
|
|
|
|
|
|
|
|
void GenerateBindServiceMethod(Printer *out, const ServiceDescriptor *service) { |
|
|
|
void GenerateBindServiceMethod(Printer *out, const ServiceDescriptor *service) { |
|
|
|
out->Print( |
|
|
|
out->Print( |
|
|
|
"/// <summary>Creates service definition that can be registered with a server</summary>\n"); |
|
|
|
"/// <summary>Creates service definition that can be registered with a " |
|
|
|
|
|
|
|
"server</summary>\n"); |
|
|
|
out->Print( |
|
|
|
out->Print( |
|
|
|
"public static ServerServiceDefinition BindService($implclass$ serviceImpl)\n", |
|
|
|
"public static ServerServiceDefinition BindService($implclass$ " |
|
|
|
|
|
|
|
"serviceImpl)\n", |
|
|
|
"implclass", GetServerClassName(service)); |
|
|
|
"implclass", GetServerClassName(service)); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Print("{\n"); |
|
|
|
out->Indent(); |
|
|
|
out->Indent(); |
|
|
|