Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(142)

Unified Diff: third_party/grpc/src/compiler/csharp_generator.cc

Issue 1932353002: Initial checkin of gRPC to third_party/ Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/grpc/src/compiler/csharp_generator.cc
diff --git a/third_party/grpc/src/compiler/csharp_generator.cc b/third_party/grpc/src/compiler/csharp_generator.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f6079bdc05abfd6af67faf117598b451324f46ab
--- /dev/null
+++ b/third_party/grpc/src/compiler/csharp_generator.cc
@@ -0,0 +1,539 @@
+/*
+ *
+ * Copyright 2015-2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <cctype>
+#include <map>
+#include <sstream>
+#include <vector>
+
+#include "src/compiler/csharp_generator.h"
+#include "src/compiler/config.h"
+#include "src/compiler/csharp_generator_helpers.h"
+#include "src/compiler/csharp_generator.h"
+
+
+using google::protobuf::compiler::csharp::GetFileNamespace;
+using google::protobuf::compiler::csharp::GetClassName;
+using google::protobuf::compiler::csharp::GetReflectionClassName;
+using grpc::protobuf::FileDescriptor;
+using grpc::protobuf::Descriptor;
+using grpc::protobuf::ServiceDescriptor;
+using grpc::protobuf::MethodDescriptor;
+using grpc::protobuf::io::Printer;
+using grpc::protobuf::io::StringOutputStream;
+using grpc_generator::MethodType;
+using grpc_generator::GetMethodType;
+using grpc_generator::METHODTYPE_NO_STREAMING;
+using grpc_generator::METHODTYPE_CLIENT_STREAMING;
+using grpc_generator::METHODTYPE_SERVER_STREAMING;
+using grpc_generator::METHODTYPE_BIDI_STREAMING;
+using grpc_generator::StringReplace;
+using std::map;
+using std::vector;
+
+
+namespace grpc_csharp_generator {
+namespace {
+
+std::string GetServiceClassName(const ServiceDescriptor* service) {
+ return service->name();
+}
+
+std::string GetClientInterfaceName(const ServiceDescriptor* service) {
+ return "I" + service->name() + "Client";
+}
+
+std::string GetClientClassName(const ServiceDescriptor* service) {
+ return service->name() + "Client";
+}
+
+std::string GetServerInterfaceName(const ServiceDescriptor* service) {
+ return "I" + service->name();
+}
+
+std::string GetCSharpMethodType(MethodType method_type) {
+ switch (method_type) {
+ case METHODTYPE_NO_STREAMING:
+ return "MethodType.Unary";
+ case METHODTYPE_CLIENT_STREAMING:
+ return "MethodType.ClientStreaming";
+ case METHODTYPE_SERVER_STREAMING:
+ return "MethodType.ServerStreaming";
+ case METHODTYPE_BIDI_STREAMING:
+ return "MethodType.DuplexStreaming";
+ }
+ GOOGLE_LOG(FATAL)<< "Can't get here.";
+ return "";
+}
+
+std::string GetServiceNameFieldName() {
+ return "__ServiceName";
+}
+
+std::string GetMarshallerFieldName(const Descriptor *message) {
+ return "__Marshaller_" + message->name();
+}
+
+std::string GetMethodFieldName(const MethodDescriptor *method) {
+ return "__Method_" + method->name();
+}
+
+std::string GetMethodRequestParamMaybe(const MethodDescriptor *method) {
+ if (method->client_streaming()) {
+ return "";
+ }
+ return GetClassName(method->input_type()) + " request, ";
+}
+
+std::string GetMethodReturnTypeClient(const MethodDescriptor *method) {
+ switch (GetMethodType(method)) {
+ case METHODTYPE_NO_STREAMING:
+ return "AsyncUnaryCall<" + GetClassName(method->output_type()) + ">";
+ case METHODTYPE_CLIENT_STREAMING:
+ return "AsyncClientStreamingCall<" + GetClassName(method->input_type())
+ + ", " + GetClassName(method->output_type()) + ">";
+ case METHODTYPE_SERVER_STREAMING:
+ return "AsyncServerStreamingCall<" + GetClassName(method->output_type())
+ + ">";
+ case METHODTYPE_BIDI_STREAMING:
+ return "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 "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 "Task<" + GetClassName(method->output_type()) + ">";
+ case METHODTYPE_SERVER_STREAMING:
+ case METHODTYPE_BIDI_STREAMING:
+ return "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 ", 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 Marshaller<$type$> $fieldname$ = 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 Method<$request$, $response$> $fieldname$ = new 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("// service descriptor\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 GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
+ out->Print("// client interface\n");
+ out->Print("public interface $name$\n", "name",
+ GetClientInterfaceName(service));
+ out->Print("{\n");
+ out->Indent();
+ 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
+ out->Print(
+ "$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()));
+
+ // overload taking CallOptions as a param
+ out->Print(
+ "$response$ $methodname$($request$ request, CallOptions options);\n",
+ "methodname", method->name(), "request",
+ GetClassName(method->input_type()), "response",
+ GetClassName(method->output_type()));
+ }
+
+ std::string method_name = method->name();
+ if (method_type == METHODTYPE_NO_STREAMING) {
+ method_name += "Async"; // prevent name clash with synchronous method.
+ }
+ out->Print(
+ "$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));
+
+ // overload taking CallOptions as a param
+ out->Print(
+ "$returntype$ $methodname$($request_maybe$CallOptions options);\n",
+ "methodname", method_name, "request_maybe",
+ GetMethodRequestParamMaybe(method), "returntype",
+ GetMethodReturnTypeClient(method));
+ }
+ out->Outdent();
+ out->Print("}\n");
+ out->Print("\n");
+}
+
+void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) {
+ out->Print("// server-side interface\n");
+ out->Print("public interface $name$\n", "name",
+ GetServerInterfaceName(service));
+ out->Print("{\n");
+ out->Indent();
+ for (int i = 0; i < service->method_count(); i++) {
+ const MethodDescriptor *method = service->method(i);
+ out->Print(
+ "$returntype$ $methodname$($request$$response_stream_maybe$, "
+ "ServerCallContext context);\n",
+ "methodname", method->name(), "returntype",
+ GetMethodReturnTypeServer(method), "request",
+ GetMethodRequestParamServer(method), "response_stream_maybe",
+ GetMethodResponseStreamMaybe(method));
+ }
+ 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));
+ out->Print("{\n");
+ out->Indent();
+
+ // constructors
+ out->Print(
+ "public $name$(Channel channel) : base(channel)\n",
+ "name", GetClientClassName(service));
+ out->Print("{\n");
+ out->Print("}\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
+ out->Print(
+ "public $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->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("{\n");
+ out->Indent();
+ out->Print("var call = CreateCall($methodfield$, options);\n",
+ "methodfield", GetMethodFieldName(method));
+ out->Print("return Calls.BlockingUnaryCall(call, request);\n");
+ 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.
+ }
+ 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));
+ 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->Outdent();
+ out->Print("}\n");
+
+ // overload taking CallOptions as a param
+ out->Print(
+ "public $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");
+ 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->Outdent();
+ out->Print("}\n");
+ }
+ out->Outdent();
+ out->Print("}\n");
+ out->Print("\n");
+}
+
+void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service) {
+ 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));
+ out->Print("{\n");
+ out->Indent();
+
+ out->Print(
+ "return ServerServiceDefinition.CreateBuilder($servicenamefield$)\n",
+ "servicenamefield", GetServiceNameFieldName());
+ out->Indent();
+ out->Indent();
+ for (int i = 0; i < service->method_count(); i++) {
+ const MethodDescriptor *method = service->method(i);
+ out->Print(".AddMethod($methodfield$, serviceImpl.$methodname$)",
+ "methodfield", GetMethodFieldName(method), "methodname",
+ method->name());
+ if (i == service->method_count() - 1) {
+ out->Print(".Build();");
+ }
+ out->Print("\n");
+ }
+ out->Outdent();
+ out->Outdent();
+
+ out->Outdent();
+ out->Print("}\n");
+ out->Print("\n");
+}
+
+void GenerateNewStubMethods(Printer* out, const ServiceDescriptor *service) {
+ out->Print("// creates a new client\n");
+ out->Print("public static $classname$ NewClient(Channel channel)\n",
+ "classname", GetClientClassName(service));
+ out->Print("{\n");
+ out->Indent();
+ out->Print("return new $classname$(channel);\n", "classname",
+ GetClientClassName(service));
+ out->Outdent();
+ out->Print("}\n");
+ out->Print("\n");
+}
+
+void GenerateService(Printer* out, const ServiceDescriptor *service) {
+ out->Print("public static class $classname$\n", "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);
+ GenerateClientInterface(out, service);
+ GenerateServerInterface(out, service);
+ GenerateClientStub(out, service);
+ GenerateBindServiceMethod(out, service);
+ GenerateNewStubMethods(out, service);
+
+ out->Outdent();
+ out->Print("}\n");
+}
+
+} // anonymous namespace
+
+grpc::string GetServices(const FileDescriptor *file) {
+ 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("// Generated by the protocol buffer compiler. DO NOT EDIT!\n");
+ out.Print("// source: $filename$\n", "filename", file->name());
+ out.Print("#region Designer generated code\n");
+ out.Print("\n");
+ out.Print("using System;\n");
+ out.Print("using System.Threading;\n");
+ out.Print("using System.Threading.Tasks;\n");
+ out.Print("using Grpc.Core;\n");
+ out.Print("\n");
+
+ out.Print("namespace $namespace$ {\n", "namespace", GetFileNamespace(file));
+ out.Indent();
+ for (int i = 0; i < file->service_count(); i++) {
+ GenerateService(&out, file->service(i));
+ }
+ out.Outdent();
+ out.Print("}\n");
+ out.Print("#endregion\n");
+ }
+ return output;
+}
+
+} // namespace grpc_csharp_generator
« no previous file with comments | « third_party/grpc/src/compiler/csharp_generator.h ('k') | third_party/grpc/src/compiler/csharp_generator_helpers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698