| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739 | 
							- /*
 
-  *
 
-  * Copyright 2015 gRPC authors.
 
-  *
 
-  * Licensed under the Apache License, Version 2.0 (the "License");
 
-  * you may not use this file except in compliance with the License.
 
-  * You may obtain a copy of the License at
 
-  *
 
-  *     http://www.apache.org/licenses/LICENSE-2.0
 
-  *
 
-  * Unless required by applicable law or agreed to in writing, software
 
-  * distributed under the License is distributed on an "AS IS" BASIS,
 
-  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
-  * See the License for the specific language governing permissions and
 
-  * limitations under the License.
 
-  *
 
-  */
 
- #include <cctype>
 
- #include <map>
 
- #include <sstream>
 
- #include <vector>
 
- #include "src/compiler/config.h"
 
- #include "src/compiler/csharp_generator.h"
 
- #include "src/compiler/csharp_generator_helpers.h"
 
- using google::protobuf::compiler::csharp::GetClassName;
 
- using google::protobuf::compiler::csharp::GetFileNamespace;
 
- using google::protobuf::compiler::csharp::GetReflectionClassName;
 
- using grpc::protobuf::Descriptor;
 
- using grpc::protobuf::FileDescriptor;
 
- using grpc::protobuf::MethodDescriptor;
 
- using grpc::protobuf::ServiceDescriptor;
 
- using grpc::protobuf::io::Printer;
 
- using grpc::protobuf::io::StringOutputStream;
 
- using grpc_generator::GetMethodType;
 
- using grpc_generator::METHODTYPE_BIDI_STREAMING;
 
- using grpc_generator::METHODTYPE_CLIENT_STREAMING;
 
- using grpc_generator::METHODTYPE_NO_STREAMING;
 
- using grpc_generator::METHODTYPE_SERVER_STREAMING;
 
- using grpc_generator::MethodType;
 
- using grpc_generator::StringReplace;
 
- using std::map;
 
- using std::vector;
 
- namespace grpc_csharp_generator {
 
- namespace {
 
- // This function is a massaged version of
 
- // https://github.com/google/protobuf/blob/master/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
 
- // Currently, we cannot easily reuse the functionality as
 
- // google/protobuf/compiler/csharp/csharp_doc_comment.h is not a public header.
 
- // TODO(jtattermusch): reuse the functionality from google/protobuf.
 
- bool GenerateDocCommentBodyImpl(grpc::protobuf::io::Printer* printer,
 
-                                 grpc::protobuf::SourceLocation location) {
 
-   grpc::string comments = location.leading_comments.empty()
 
-                               ? location.trailing_comments
 
-                               : location.leading_comments;
 
-   if (comments.empty()) {
 
-     return false;
 
-   }
 
-   // 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.
 
-   comments = grpc_generator::StringReplace(comments, "&", "&", true);
 
-   comments = grpc_generator::StringReplace(comments, "<", "<", true);
 
-   std::vector<grpc::string> 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...
 
-   // but that needs to be part of a bigger effort to understand the markdown
 
-   // better anyway.
 
-   printer->Print("/// <summary>\n");
 
-   bool last_was_empty = false;
 
-   // We squash multiple blank lines down to one, and remove any trailing blank
 
-   // lines. We need
 
-   // 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.)
 
-   for (std::vector<grpc::string>::iterator it = lines.begin();
 
-        it != lines.end(); ++it) {
 
-     grpc::string line = *it;
 
-     if (line.empty()) {
 
-       last_was_empty = true;
 
-     } else {
 
-       if (last_was_empty) {
 
-         printer->Print("///\n");
 
-       }
 
-       last_was_empty = false;
 
-       printer->Print("///$line$\n", "line", *it);
 
-     }
 
-   }
 
-   printer->Print("/// </summary>\n");
 
-   return true;
 
- }
 
- template <typename DescriptorType>
 
- bool GenerateDocCommentBody(grpc::protobuf::io::Printer* printer,
 
-                             const DescriptorType* descriptor) {
 
-   grpc::protobuf::SourceLocation location;
 
-   if (!descriptor->GetSourceLocation(&location)) {
 
-     return false;
 
-   }
 
-   return GenerateDocCommentBodyImpl(printer, location);
 
- }
 
- void GenerateDocCommentServerMethod(grpc::protobuf::io::Printer* printer,
 
-                                     const MethodDescriptor* method) {
 
-   if (GenerateDocCommentBody(printer, method)) {
 
-     if (method->client_streaming()) {
 
-       printer->Print(
 
-           "/// <param name=\"requestStream\">Used for reading requests from "
 
-           "the client.</param>\n");
 
-     } else {
 
-       printer->Print(
 
-           "/// <param name=\"request\">The request received from the "
 
-           "client.</param>\n");
 
-     }
 
-     if (method->server_streaming()) {
 
-       printer->Print(
 
-           "/// <param name=\"responseStream\">Used for sending responses back "
 
-           "to the client.</param>\n");
 
-     }
 
-     printer->Print(
 
-         "/// <param name=\"context\">The context of the server-side call "
 
-         "handler being invoked.</param>\n");
 
-     if (method->server_streaming()) {
 
-       printer->Print(
 
-           "/// <returns>A task indicating completion of the "
 
-           "handler.</returns>\n");
 
-     } else {
 
-       printer->Print(
 
-           "/// <returns>The response to send back to the client (wrapped by a "
 
-           "task).</returns>\n");
 
-     }
 
-   }
 
- }
 
- void GenerateDocCommentClientMethod(grpc::protobuf::io::Printer* printer,
 
-                                     const MethodDescriptor* method,
 
-                                     bool is_sync, bool use_call_options) {
 
-   if (GenerateDocCommentBody(printer, method)) {
 
-     if (!method->client_streaming()) {
 
-       printer->Print(
 
-           "/// <param name=\"request\">The request to send to the "
 
-           "server.</param>\n");
 
-     }
 
-     if (!use_call_options) {
 
-       printer->Print(
 
-           "/// <param name=\"headers\">The initial metadata to send with the "
 
-           "call. This parameter is optional.</param>\n");
 
-       printer->Print(
 
-           "/// <param name=\"deadline\">An optional deadline for the call. The "
 
-           "call will be cancelled if deadline is hit.</param>\n");
 
-       printer->Print(
 
-           "/// <param name=\"cancellationToken\">An optional token for "
 
-           "canceling the call.</param>\n");
 
-     } else {
 
-       printer->Print(
 
-           "/// <param name=\"options\">The options for the call.</param>\n");
 
-     }
 
-     if (is_sync) {
 
-       printer->Print(
 
-           "/// <returns>The response received from the server.</returns>\n");
 
-     } else {
 
-       printer->Print("/// <returns>The call object.</returns>\n");
 
-     }
 
-   }
 
- }
 
- std::string GetServiceClassName(const ServiceDescriptor* service) {
 
-   return service->name();
 
- }
 
- std::string GetClientClassName(const ServiceDescriptor* service) {
 
-   return service->name() + "Client";
 
- }
 
- std::string GetServerClassName(const ServiceDescriptor* service) {
 
-   return service->name() + "Base";
 
- }
 
- std::string GetCSharpMethodType(MethodType method_type) {
 
-   switch (method_type) {
 
-     case METHODTYPE_NO_STREAMING:
 
-       return "grpc::MethodType.Unary";
 
-     case METHODTYPE_CLIENT_STREAMING:
 
-       return "grpc::MethodType.ClientStreaming";
 
-     case METHODTYPE_SERVER_STREAMING:
 
-       return "grpc::MethodType.ServerStreaming";
 
-     case METHODTYPE_BIDI_STREAMING:
 
-       return "grpc::MethodType.DuplexStreaming";
 
-   }
 
-   GOOGLE_LOG(FATAL) << "Can't get here.";
 
-   return "";
 
- }
 
- std::string GetServiceNameFieldName() { return "__ServiceName"; }
 
- std::string GetMarshallerFieldName(const Descriptor* message) {
 
-   return "__Marshaller_" +
 
-          grpc_generator::StringReplace(message->full_name(), ".", "_", true);
 
- }
 
- std::string GetMethodFieldName(const MethodDescriptor* method) {
 
-   return "__Method_" + method->name();
 
- }
 
- 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, ";
 
- }
 
- std::string GetAccessLevel(bool internal_access) {
 
-   return internal_access ? "internal" : "public";
 
- }
 
- std::string GetMethodReturnTypeClient(const MethodDescriptor* method) {
 
-   switch (GetMethodType(method)) {
 
-     case METHODTYPE_NO_STREAMING:
 
-       return "grpc::AsyncUnaryCall<" + GetClassName(method->output_type()) +
 
-              ">";
 
-     case METHODTYPE_CLIENT_STREAMING:
 
-       return "grpc::AsyncClientStreamingCall<" +
 
-              GetClassName(method->input_type()) + ", " +
 
-              GetClassName(method->output_type()) + ">";
 
-     case METHODTYPE_SERVER_STREAMING:
 
-       return "grpc::AsyncServerStreamingCall<" +
 
-              GetClassName(method->output_type()) + ">";
 
-     case METHODTYPE_BIDI_STREAMING:
 
-       return "grpc::AsyncDuplexStreamingCall<" +
 
-              GetClassName(method->input_type()) + ", " +
 
-              GetClassName(method->output_type()) + ">";
 
-   }
 
-   GOOGLE_LOG(FATAL) << "Can't get here.";
 
-   return "";
 
- }
 
- std::string GetMethodRequestParamServer(const MethodDescriptor* method) {
 
-   switch (GetMethodType(method)) {
 
-     case METHODTYPE_NO_STREAMING:
 
-     case METHODTYPE_SERVER_STREAMING:
 
-       return GetClassName(method->input_type()) + " request";
 
-     case METHODTYPE_CLIENT_STREAMING:
 
-     case METHODTYPE_BIDI_STREAMING:
 
-       return "grpc::IAsyncStreamReader<" + GetClassName(method->input_type()) +
 
-              "> requestStream";
 
-   }
 
-   GOOGLE_LOG(FATAL) << "Can't get here.";
 
-   return "";
 
- }
 
- std::string GetMethodReturnTypeServer(const MethodDescriptor* method) {
 
-   switch (GetMethodType(method)) {
 
-     case METHODTYPE_NO_STREAMING:
 
-     case METHODTYPE_CLIENT_STREAMING:
 
-       return "global::System.Threading.Tasks.Task<" +
 
-              GetClassName(method->output_type()) + ">";
 
-     case METHODTYPE_SERVER_STREAMING:
 
-     case METHODTYPE_BIDI_STREAMING:
 
-       return "global::System.Threading.Tasks.Task";
 
-   }
 
-   GOOGLE_LOG(FATAL) << "Can't get here.";
 
-   return "";
 
- }
 
- std::string GetMethodResponseStreamMaybe(const MethodDescriptor* method) {
 
-   switch (GetMethodType(method)) {
 
-     case METHODTYPE_NO_STREAMING:
 
-     case METHODTYPE_CLIENT_STREAMING:
 
-       return "";
 
-     case METHODTYPE_SERVER_STREAMING:
 
-     case METHODTYPE_BIDI_STREAMING:
 
-       return ", grpc::IServerStreamWriter<" +
 
-              GetClassName(method->output_type()) + "> responseStream";
 
-   }
 
-   GOOGLE_LOG(FATAL) << "Can't get here.";
 
-   return "";
 
- }
 
- // Gets vector of all messages used as input or output types.
 
- std::vector<const Descriptor*> GetUsedMessages(
 
-     const ServiceDescriptor* service) {
 
-   std::set<const Descriptor*> descriptor_set;
 
-   std::vector<const Descriptor*>
 
-       result;  // vector is to maintain stable ordering
 
-   for (int i = 0; i < service->method_count(); i++) {
 
-     const MethodDescriptor* method = service->method(i);
 
-     if (descriptor_set.find(method->input_type()) == descriptor_set.end()) {
 
-       descriptor_set.insert(method->input_type());
 
-       result.push_back(method->input_type());
 
-     }
 
-     if (descriptor_set.find(method->output_type()) == descriptor_set.end()) {
 
-       descriptor_set.insert(method->output_type());
 
-       result.push_back(method->output_type());
 
-     }
 
-   }
 
-   return result;
 
- }
 
- void GenerateMarshallerFields(Printer* out, const ServiceDescriptor* service) {
 
-   std::vector<const Descriptor*> used_messages = GetUsedMessages(service);
 
-   for (size_t i = 0; i < used_messages.size(); i++) {
 
-     const Descriptor* message = used_messages[i];
 
-     out->Print(
 
-         "static readonly grpc::Marshaller<$type$> $fieldname$ = "
 
-         "grpc::Marshallers.Create((arg) => "
 
-         "global::Google.Protobuf.MessageExtensions.ToByteArray(arg), "
 
-         "$type$.Parser.ParseFrom);\n",
 
-         "fieldname", GetMarshallerFieldName(message), "type",
 
-         GetClassName(message));
 
-   }
 
-   out->Print("\n");
 
- }
 
- void GenerateStaticMethodField(Printer* out, const MethodDescriptor* method) {
 
-   out->Print(
 
-       "static readonly grpc::Method<$request$, $response$> $fieldname$ = new "
 
-       "grpc::Method<$request$, $response$>(\n",
 
-       "fieldname", GetMethodFieldName(method), "request",
 
-       GetClassName(method->input_type()), "response",
 
-       GetClassName(method->output_type()));
 
-   out->Indent();
 
-   out->Indent();
 
-   out->Print("$methodtype$,\n", "methodtype",
 
-              GetCSharpMethodType(GetMethodType(method)));
 
-   out->Print("$servicenamefield$,\n", "servicenamefield",
 
-              GetServiceNameFieldName());
 
-   out->Print("\"$methodname$\",\n", "methodname", method->name());
 
-   out->Print("$requestmarshaller$,\n", "requestmarshaller",
 
-              GetMarshallerFieldName(method->input_type()));
 
-   out->Print("$responsemarshaller$);\n", "responsemarshaller",
 
-              GetMarshallerFieldName(method->output_type()));
 
-   out->Print("\n");
 
-   out->Outdent();
 
-   out->Outdent();
 
- }
 
- void GenerateServiceDescriptorProperty(Printer* out,
 
-                                        const ServiceDescriptor* service) {
 
-   std::ostringstream index;
 
-   index << service->index();
 
-   out->Print("/// <summary>Service descriptor</summary>\n");
 
-   out->Print(
 
-       "public static global::Google.Protobuf.Reflection.ServiceDescriptor "
 
-       "Descriptor\n");
 
-   out->Print("{\n");
 
-   out->Print("  get { return $umbrella$.Descriptor.Services[$index$]; }\n",
 
-              "umbrella", GetReflectionClassName(service->file()), "index",
 
-              index.str());
 
-   out->Print("}\n");
 
-   out->Print("\n");
 
- }
 
- void GenerateServerClass(Printer* out, const ServiceDescriptor* service) {
 
-   out->Print(
 
-       "/// <summary>Base class for server-side implementations of "
 
-       "$servicename$</summary>\n",
 
-       "servicename", GetServiceClassName(service));
 
-   out->Print("public abstract partial 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);
 
-     GenerateDocCommentServerMethod(out, method);
 
-     out->Print(
 
-         "public virtual $returntype$ "
 
-         "$methodname$($request$$response_stream_maybe$, "
 
-         "grpc::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 grpc::RpcException("
 
-         "new grpc::Status(grpc::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("/// <summary>Client for $servicename$</summary>\n", "servicename",
 
-              GetServiceClassName(service));
 
-   out->Print("public partial class $name$ : grpc::ClientBase<$name$>\n", "name",
 
-              GetClientClassName(service));
 
-   out->Print("{\n");
 
-   out->Indent();
 
-   // constructors
 
-   out->Print(
 
-       "/// <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));
 
-   out->Print("public $name$(grpc::Channel channel) : base(channel)\n", "name",
 
-              GetClientClassName(service));
 
-   out->Print("{\n");
 
-   out->Print("}\n");
 
-   out->Print(
 
-       "/// <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));
 
-   out->Print(
 
-       "public $name$(grpc::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"
 
-       "/// <param name=\"configuration\">The client configuration.</param>\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);
 
-     MethodType method_type = GetMethodType(method);
 
-     if (method_type == METHODTYPE_NO_STREAMING) {
 
-       // unary calls have an extra synchronous stub method
 
-       GenerateDocCommentClientMethod(out, method, true, false);
 
-       out->Print(
 
-           "public virtual $response$ $methodname$($request$ request, "
 
-           "grpc::Metadata "
 
-           "headers = null, global::System.DateTime? deadline = null, "
 
-           "global::System.Threading.CancellationToken "
 
-           "cancellationToken = "
 
-           "default(global::System.Threading.CancellationToken))\n",
 
-           "methodname", method->name(), "request",
 
-           GetClassName(method->input_type()), "response",
 
-           GetClassName(method->output_type()));
 
-       out->Print("{\n");
 
-       out->Indent();
 
-       out->Print(
 
-           "return $methodname$(request, new grpc::CallOptions(headers, "
 
-           "deadline, "
 
-           "cancellationToken));\n",
 
-           "methodname", method->name());
 
-       out->Outdent();
 
-       out->Print("}\n");
 
-       // overload taking CallOptions as a param
 
-       GenerateDocCommentClientMethod(out, method, true, true);
 
-       out->Print(
 
-           "public virtual $response$ $methodname$($request$ request, "
 
-           "grpc::CallOptions options)\n",
 
-           "methodname", method->name(), "request",
 
-           GetClassName(method->input_type()), "response",
 
-           GetClassName(method->output_type()));
 
-       out->Print("{\n");
 
-       out->Indent();
 
-       out->Print(
 
-           "return CallInvoker.BlockingUnaryCall($methodfield$, null, options, "
 
-           "request);\n",
 
-           "methodfield", GetMethodFieldName(method));
 
-       out->Outdent();
 
-       out->Print("}\n");
 
-     }
 
-     std::string method_name = method->name();
 
-     if (method_type == METHODTYPE_NO_STREAMING) {
 
-       method_name += "Async";  // prevent name clash with synchronous method.
 
-     }
 
-     GenerateDocCommentClientMethod(out, method, false, false);
 
-     out->Print(
 
-         "public virtual $returntype$ "
 
-         "$methodname$($request_maybe$grpc::Metadata "
 
-         "headers = null, global::System.DateTime? deadline = null, "
 
-         "global::System.Threading.CancellationToken "
 
-         "cancellationToken = "
 
-         "default(global::System.Threading.CancellationToken))\n",
 
-         "methodname", method_name, "request_maybe",
 
-         GetMethodRequestParamMaybe(method), "returntype",
 
-         GetMethodReturnTypeClient(method));
 
-     out->Print("{\n");
 
-     out->Indent();
 
-     out->Print(
 
-         "return $methodname$($request_maybe$new grpc::CallOptions(headers, "
 
-         "deadline, "
 
-         "cancellationToken));\n",
 
-         "methodname", method_name, "request_maybe",
 
-         GetMethodRequestParamMaybe(method, true));
 
-     out->Outdent();
 
-     out->Print("}\n");
 
-     // overload taking CallOptions as a param
 
-     GenerateDocCommentClientMethod(out, method, false, true);
 
-     out->Print(
 
-         "public virtual $returntype$ "
 
-         "$methodname$($request_maybe$grpc::CallOptions "
 
-         "options)\n",
 
-         "methodname", method_name, "request_maybe",
 
-         GetMethodRequestParamMaybe(method), "returntype",
 
-         GetMethodReturnTypeClient(method));
 
-     out->Print("{\n");
 
-     out->Indent();
 
-     switch (GetMethodType(method)) {
 
-       case METHODTYPE_NO_STREAMING:
 
-         out->Print(
 
-             "return CallInvoker.AsyncUnaryCall($methodfield$, null, options, "
 
-             "request);\n",
 
-             "methodfield", GetMethodFieldName(method));
 
-         break;
 
-       case METHODTYPE_CLIENT_STREAMING:
 
-         out->Print(
 
-             "return CallInvoker.AsyncClientStreamingCall($methodfield$, null, "
 
-             "options);\n",
 
-             "methodfield", GetMethodFieldName(method));
 
-         break;
 
-       case METHODTYPE_SERVER_STREAMING:
 
-         out->Print(
 
-             "return CallInvoker.AsyncServerStreamingCall($methodfield$, null, "
 
-             "options, request);\n",
 
-             "methodfield", GetMethodFieldName(method));
 
-         break;
 
-       case METHODTYPE_BIDI_STREAMING:
 
-         out->Print(
 
-             "return CallInvoker.AsyncDuplexStreamingCall($methodfield$, null, "
 
-             "options);\n",
 
-             "methodfield", GetMethodFieldName(method));
 
-         break;
 
-       default:
 
-         GOOGLE_LOG(FATAL) << "Can't get here.";
 
-     }
 
-     out->Outdent();
 
-     out->Print("}\n");
 
-   }
 
-   // override NewInstance method
 
-   out->Print(
 
-       "/// <summary>Creates a new instance of client from given "
 
-       "<c>ClientBaseConfiguration</c>.</summary>\n");
 
-   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) {
 
-   out->Print(
 
-       "/// <summary>Creates service definition that can be registered with a "
 
-       "server</summary>\n");
 
-   out->Print(
 
-       "/// <param name=\"serviceImpl\">An object implementing the server-side"
 
-       " handling logic.</param>\n");
 
-   out->Print(
 
-       "public static grpc::ServerServiceDefinition BindService($implclass$ "
 
-       "serviceImpl)\n",
 
-       "implclass", GetServerClassName(service));
 
-   out->Print("{\n");
 
-   out->Indent();
 
-   out->Print("return grpc::ServerServiceDefinition.CreateBuilder()");
 
-   out->Indent();
 
-   out->Indent();
 
-   for (int i = 0; i < service->method_count(); i++) {
 
-     const MethodDescriptor* method = service->method(i);
 
-     out->Print("\n.AddMethod($methodfield$, serviceImpl.$methodname$)",
 
-                "methodfield", GetMethodFieldName(method), "methodname",
 
-                method->name());
 
-   }
 
-   out->Print(".Build();\n");
 
-   out->Outdent();
 
-   out->Outdent();
 
-   out->Outdent();
 
-   out->Print("}\n");
 
-   out->Print("\n");
 
- }
 
- void GenerateBindServiceWithBinderMethod(Printer* out,
 
-                                          const ServiceDescriptor* service) {
 
-   out->Print(
 
-       "/// <summary>Register service method implementations with a service "
 
-       "binder. Useful when customizing the service binding logic.\n"
 
-       "/// Note: this method is part of an experimental API that can change or "
 
-       "be "
 
-       "removed without any prior notice.</summary>\n");
 
-   out->Print(
 
-       "/// <param name=\"serviceBinder\">Service methods will be bound by "
 
-       "calling <c>AddMethod</c> on this object."
 
-       "</param>\n");
 
-   out->Print(
 
-       "/// <param name=\"serviceImpl\">An object implementing the server-side"
 
-       " handling logic.</param>\n");
 
-   out->Print(
 
-       "public static void BindService(grpc::ServiceBinderBase serviceBinder, "
 
-       "$implclass$ "
 
-       "serviceImpl)\n",
 
-       "implclass", GetServerClassName(service));
 
-   out->Print("{\n");
 
-   out->Indent();
 
-   for (int i = 0; i < service->method_count(); i++) {
 
-     const MethodDescriptor* method = service->method(i);
 
-     out->Print(
 
-         "serviceBinder.AddMethod($methodfield$, serviceImpl.$methodname$);\n",
 
-         "methodfield", GetMethodFieldName(method), "methodname",
 
-         method->name());
 
-   }
 
-   out->Outdent();
 
-   out->Print("}\n");
 
-   out->Print("\n");
 
- }
 
- void GenerateService(Printer* out, const ServiceDescriptor* service,
 
-                      bool generate_client, bool generate_server,
 
-                      bool internal_access) {
 
-   GenerateDocCommentBody(out, service);
 
-   out->Print("$access_level$ static partial class $classname$\n",
 
-              "access_level", GetAccessLevel(internal_access), "classname",
 
-              GetServiceClassName(service));
 
-   out->Print("{\n");
 
-   out->Indent();
 
-   out->Print("static readonly string $servicenamefield$ = \"$servicename$\";\n",
 
-              "servicenamefield", GetServiceNameFieldName(), "servicename",
 
-              service->full_name());
 
-   out->Print("\n");
 
-   GenerateMarshallerFields(out, service);
 
-   for (int i = 0; i < service->method_count(); i++) {
 
-     GenerateStaticMethodField(out, service->method(i));
 
-   }
 
-   GenerateServiceDescriptorProperty(out, service);
 
-   if (generate_server) {
 
-     GenerateServerClass(out, service);
 
-   }
 
-   if (generate_client) {
 
-     GenerateClientStub(out, service);
 
-   }
 
-   if (generate_server) {
 
-     GenerateBindServiceMethod(out, service);
 
-     GenerateBindServiceWithBinderMethod(out, service);
 
-   }
 
-   out->Outdent();
 
-   out->Print("}\n");
 
- }
 
- }  // anonymous namespace
 
- grpc::string GetServices(const FileDescriptor* file, bool generate_client,
 
-                          bool generate_server, bool internal_access) {
 
-   grpc::string output;
 
-   {
 
-     // Scope the output stream so it closes and finalizes output to the string.
 
-     StringOutputStream output_stream(&output);
 
-     Printer out(&output_stream, '$');
 
-     // Don't write out any output if there no services, to avoid empty service
 
-     // files being generated for proto files that don't declare any.
 
-     if (file->service_count() == 0) {
 
-       return output;
 
-     }
 
-     // Write out a file header.
 
-     out.Print("// <auto-generated>\n");
 
-     out.Print(
 
-         "//     Generated by the protocol buffer compiler.  DO NOT EDIT!\n");
 
-     out.Print("//     source: $filename$\n", "filename", file->name());
 
-     out.Print("// </auto-generated>\n");
 
-     // use C++ style as there are no file-level XML comments in .NET
 
-     grpc::string leading_comments = GetCsharpComments(file, true);
 
-     if (!leading_comments.empty()) {
 
-       out.Print("// Original file comments:\n");
 
-       out.PrintRaw(leading_comments.c_str());
 
-     }
 
-     out.Print("#pragma warning disable 0414, 1591\n");
 
-     out.Print("#region Designer generated code\n");
 
-     out.Print("\n");
 
-     out.Print("using grpc = global::Grpc.Core;\n");
 
-     out.Print("\n");
 
-     grpc::string file_namespace = GetFileNamespace(file);
 
-     if (file_namespace != "") {
 
-       out.Print("namespace $namespace$ {\n", "namespace", file_namespace);
 
-       out.Indent();
 
-     }
 
-     for (int i = 0; i < file->service_count(); i++) {
 
-       GenerateService(&out, file->service(i), generate_client, generate_server,
 
-                       internal_access);
 
-     }
 
-     if (file_namespace != "") {
 
-       out.Outdent();
 
-       out.Print("}\n");
 
-     }
 
-     out.Print("#endregion\n");
 
-   }
 
-   return output;
 
- }
 
- }  // namespace grpc_csharp_generator
 
 
  |