diff options
author | David Garcia Quintas <dgq@google.com> | 2016-05-02 10:56:54 -0700 |
---|---|---|
committer | David Garcia Quintas <dgq@google.com> | 2016-05-02 10:56:54 -0700 |
commit | 80721b20ca574df78e7e884a023425274e964a17 (patch) | |
tree | 3f18a170c1cdc49af7c48a787170a818eb2efa0f /src/compiler | |
parent | 1b2db6333d4783e18b8d72db7893a758c4fcd2b9 (diff) | |
parent | 1dd74dd3783daa3ac427add91b3b81deb7758200 (diff) |
Merge branch 'master' of github.com:grpc/grpc into codegen_remove_proto
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/config.h | 14 | ||||
-rw-r--r-- | src/compiler/cpp_generator.cc | 14 | ||||
-rw-r--r-- | src/compiler/cpp_generator.h | 14 | ||||
-rw-r--r-- | src/compiler/cpp_plugin.cc | 28 | ||||
-rw-r--r-- | src/compiler/csharp_generator.cc | 129 | ||||
-rw-r--r-- | src/compiler/csharp_generator.h | 4 | ||||
-rw-r--r-- | src/compiler/csharp_plugin.cc | 24 | ||||
-rw-r--r-- | src/compiler/generator_helpers.h | 109 | ||||
-rw-r--r-- | src/compiler/objective_c_generator.cc | 6 | ||||
-rw-r--r-- | src/compiler/objective_c_plugin.cc | 6 | ||||
-rw-r--r-- | src/compiler/python_generator.cc | 10 |
11 files changed, 326 insertions, 32 deletions
diff --git a/src/compiler/config.h b/src/compiler/config.h index fea976c318..d8b95818db 100644 --- a/src/compiler/config.h +++ b/src/compiler/config.h @@ -42,8 +42,10 @@ #include <google/protobuf/descriptor.pb.h> #define GRPC_CUSTOM_DESCRIPTOR ::google::protobuf::Descriptor #define GRPC_CUSTOM_FILEDESCRIPTOR ::google::protobuf::FileDescriptor +#define GRPC_CUSTOM_FILEDESCRIPTORPROTO ::google::protobuf::FileDescriptorProto #define GRPC_CUSTOM_METHODDESCRIPTOR ::google::protobuf::MethodDescriptor #define GRPC_CUSTOM_SERVICEDESCRIPTOR ::google::protobuf::ServiceDescriptor +#define GRPC_CUSTOM_SOURCELOCATION ::google::protobuf::SourceLocation #endif #ifndef GRPC_CUSTOM_CODEGENERATOR @@ -68,12 +70,19 @@ #define GRPC_CUSTOM_PLUGINMAIN ::google::protobuf::compiler::PluginMain #endif +#ifndef GRPC_CUSTOM_PARSEGENERATORPARAMETER +#include <google/protobuf/compiler/code_generator.h> +#define GRPC_CUSTOM_PARSEGENERATORPARAMETER ::google::protobuf::compiler::ParseGeneratorParameter +#endif + namespace grpc { namespace protobuf { typedef GRPC_CUSTOM_DESCRIPTOR Descriptor; typedef GRPC_CUSTOM_FILEDESCRIPTOR FileDescriptor; +typedef GRPC_CUSTOM_FILEDESCRIPTORPROTO FileDescriptorProto; typedef GRPC_CUSTOM_METHODDESCRIPTOR MethodDescriptor; typedef GRPC_CUSTOM_SERVICEDESCRIPTOR ServiceDescriptor; +typedef GRPC_CUSTOM_SOURCELOCATION SourceLocation; namespace compiler { typedef GRPC_CUSTOM_CODEGENERATOR CodeGenerator; typedef GRPC_CUSTOM_GENERATORCONTEXT GeneratorContext; @@ -81,6 +90,11 @@ static inline int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { return GRPC_CUSTOM_PLUGINMAIN(argc, argv, generator); } +static inline void ParseGeneratorParameter(const string& parameter, + std::vector<std::pair<string, string> >* options) { + GRPC_CUSTOM_PARSEGENERATORPARAMETER(parameter, options); +} + } // namespace compiler namespace io { typedef GRPC_CUSTOM_PRINTER Printer; diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc index 9319c41934..e2f127094a 100644 --- a/src/compiler/cpp_generator.cc +++ b/src/compiler/cpp_generator.cc @@ -102,6 +102,11 @@ grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) { printer->Print(vars, "// If you make any local change, they will be lost.\n"); printer->Print(vars, "// source: $filename$\n"); + grpc::string leading_comments = file->GetLeadingComments(); + if (!leading_comments.empty()) { + printer->Print(vars, "// Original file comments:\n"); + printer->Print(leading_comments.c_str()); + } printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n"); printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n"); printer->Print(vars, "\n"); @@ -456,6 +461,7 @@ void PrintHeaderServerMethodSync(Printer *printer, const Method *method, (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); + printer->Print(method->GetLeadingComments().c_str()); if (method->NoStreaming()) { printer->Print(*vars, "virtual ::grpc::Status $Method$(" @@ -480,6 +486,7 @@ void PrintHeaderServerMethodSync(Printer *printer, const Method *method, "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);" "\n"); } + printer->Print(method->GetTrailingComments().c_str()); } void PrintHeaderServerMethodAsync( @@ -674,6 +681,7 @@ void PrintHeaderService(Printer *printer, std::map<grpc::string, grpc::string> *vars) { (*vars)["Service"] = service->name(); + printer->Print(service->GetLeadingComments().c_str()); printer->Print(*vars, "class $Service$ GRPC_FINAL {\n" " public:\n"); @@ -686,7 +694,9 @@ void PrintHeaderService(Printer *printer, printer->Indent(); printer->Print("virtual ~StubInterface() {}\n"); for (int i = 0; i < service->method_count(); ++i) { + printer->Print(service->method(i)->GetLeadingComments().c_str()); PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, true); + printer->Print(service->method(i)->GetTrailingComments().c_str()); } printer->Outdent(); printer->Print("private:\n"); @@ -762,6 +772,7 @@ void PrintHeaderService(Printer *printer, printer->Outdent(); printer->Print("};\n"); + printer->Print(service->GetTrailingComments().c_str()); } grpc::string GetHeaderServices(File *file, @@ -817,6 +828,8 @@ grpc::string GetHeaderEpilogue(File *file, const Parameters & /*params*/) { printer->Print(vars, "\n"); printer->Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n"); + + printer->Print(file->GetTrailingComments().c_str()); } return output; } @@ -837,6 +850,7 @@ grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) { 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$$message_header_ext$\"\n"); printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n"); printer->Print(vars, file->additional_headers().c_str()); diff --git a/src/compiler/cpp_generator.h b/src/compiler/cpp_generator.h index 953ddfd569..2a003b1069 100644 --- a/src/compiler/cpp_generator.h +++ b/src/compiler/cpp_generator.h @@ -64,8 +64,16 @@ struct Parameters { grpc::string grpc_search_path; }; +// A common interface for objects having comments in the source. +// Return formatted comments to be inserted in generated code. +struct CommentHolder { + virtual ~CommentHolder() {} + virtual grpc::string GetLeadingComments() const = 0; + virtual grpc::string GetTrailingComments() const = 0; +}; + // An abstract interface representing a method. -struct Method { +struct Method : public CommentHolder { virtual ~Method() {} virtual grpc::string name() const = 0; @@ -80,7 +88,7 @@ struct Method { }; // An abstract interface representing a service. -struct Service { +struct Service : public CommentHolder { virtual ~Service() {} virtual grpc::string name() const = 0; @@ -101,7 +109,7 @@ struct Printer { // An interface that allows the source generated to be output using various // libraries/idls/serializers. -struct File { +struct File : public CommentHolder { virtual ~File() {} virtual grpc::string filename() const = 0; diff --git a/src/compiler/cpp_plugin.cc b/src/compiler/cpp_plugin.cc index e321c64639..0ec183e474 100644 --- a/src/compiler/cpp_plugin.cc +++ b/src/compiler/cpp_plugin.cc @@ -35,11 +35,15 @@ // #include <memory> +#include <sstream> #include "src/compiler/config.h" #include "src/compiler/cpp_generator.h" #include "src/compiler/cpp_generator_helpers.h" +#include "src/compiler/generator_helpers.h" + +using grpc_generator::GetCppComments; class ProtoBufMethod : public grpc_cpp_generator::Method { public: @@ -71,6 +75,14 @@ class ProtoBufMethod : public grpc_cpp_generator::Method { return method_->client_streaming() && method_->server_streaming(); } + grpc::string GetLeadingComments() const { + return GetCppComments(method_, true); + } + + grpc::string GetTrailingComments() const { + return GetCppComments(method_, false); + } + private: const grpc::protobuf::MethodDescriptor *method_; }; @@ -88,6 +100,14 @@ class ProtoBufService : public grpc_cpp_generator::Service { new ProtoBufMethod(service_->method(i))); }; + grpc::string GetLeadingComments() const { + return GetCppComments(service_, true); + } + + grpc::string GetTrailingComments() const { + return GetCppComments(service_, false); + } + private: const grpc::protobuf::ServiceDescriptor *service_; }; @@ -141,6 +161,14 @@ class ProtoBufFile : public grpc_cpp_generator::File { new ProtoBufPrinter(str)); } + grpc::string GetLeadingComments() const { + return GetCppComments(file_, true); + } + + grpc::string GetTrailingComments() const { + return GetCppComments(file_, false); + } + private: const grpc::protobuf::FileDescriptor *file_; }; diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index 4def6c5e31..ac0fee1ec4 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -52,6 +52,7 @@ using grpc::protobuf::MethodDescriptor; using grpc::protobuf::io::Printer; using grpc::protobuf::io::StringOutputStream; using grpc_generator::MethodType; +using grpc_generator::GetCppComments; using grpc_generator::GetMethodType; using grpc_generator::METHODTYPE_NO_STREAMING; using grpc_generator::METHODTYPE_CLIENT_STREAMING; @@ -65,6 +66,56 @@ 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. +void 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; + } + // 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"); +} + +template <typename DescriptorType> +void GenerateDocCommentBody( + grpc::protobuf::io::Printer* printer, const DescriptorType* descriptor) { + grpc::protobuf::SourceLocation location; + if (descriptor->GetSourceLocation(&location)) { + GenerateDocCommentBodyImpl(printer, location); + } +} + std::string GetServiceClassName(const ServiceDescriptor* service) { return service->name(); } @@ -123,6 +174,10 @@ std::string GetMethodRequestParamMaybe(const MethodDescriptor *method, 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: @@ -238,7 +293,7 @@ void GenerateStaticMethodField(Printer* out, const MethodDescriptor *method) { void GenerateServiceDescriptorProperty(Printer* out, const ServiceDescriptor *service) { std::ostringstream index; index << service->index(); - out->Print("// service descriptor\n"); + 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", @@ -249,7 +304,8 @@ void GenerateServiceDescriptorProperty(Printer* out, const ServiceDescriptor *se } void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) { - out->Print("// client interface\n"); + out->Print("/// <summary>Client for $servicename$</summary>\n", + "servicename", GetServiceClassName(service)); 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", @@ -262,6 +318,7 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) { if (method_type == METHODTYPE_NO_STREAMING) { // unary calls have an extra synchronous stub method + GenerateDocCommentBody(out, method); out->Print( "$response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));\n", "methodname", method->name(), "request", @@ -269,6 +326,7 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) { GetClassName(method->output_type())); // overload taking CallOptions as a param + GenerateDocCommentBody(out, method); out->Print( "$response$ $methodname$($request$ request, CallOptions options);\n", "methodname", method->name(), "request", @@ -280,6 +338,7 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) { if (method_type == METHODTYPE_NO_STREAMING) { method_name += "Async"; // prevent name clash with synchronous method. } + GenerateDocCommentBody(out, method); out->Print( "$returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));\n", "methodname", method_name, "request_maybe", @@ -287,6 +346,7 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) { GetMethodReturnTypeClient(method)); // overload taking CallOptions as a param + GenerateDocCommentBody(out, method); out->Print( "$returntype$ $methodname$($request_maybe$CallOptions options);\n", "methodname", method_name, "request_maybe", @@ -299,7 +359,8 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) { } void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) { - out->Print("// server-side interface\n"); + out->Print("/// <summary>Interface of server-side implementations of $servicename$</summary>\n", + "servicename", GetServiceClassName(service)); out->Print("[System.Obsolete(\"Service implementations should inherit" " from the generated abstract base class instead.\")]\n"); out->Print("public interface $name$\n", "name", @@ -308,6 +369,7 @@ void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) { out->Indent(); for (int i = 0; i < service->method_count(); i++) { const MethodDescriptor *method = service->method(i); + GenerateDocCommentBody(out, method); out->Print( "$returntype$ $methodname$($request$$response_stream_maybe$, " "ServerCallContext context);\n", @@ -322,13 +384,15 @@ void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) { } void GenerateServerClass(Printer* out, const ServiceDescriptor *service) { - out->Print("// server-side abstract class\n"); + out->Print("/// <summary>Base class for server-side implementations of $servicename$</summary>\n", + "servicename", GetServiceClassName(service)); 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); + GenerateDocCommentBody(out, method); out->Print( "public virtual $returntype$ $methodname$($request$$response_stream_maybe$, " "ServerCallContext context)\n", @@ -349,7 +413,8 @@ void GenerateServerClass(Printer* out, const ServiceDescriptor *service) { } void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { - out->Print("// client stub\n"); + out->Print("/// <summary>Client for $servicename$</summary>\n", + "servicename", GetServiceClassName(service)); out->Print("#pragma warning disable 0618\n"); out->Print( "public class $name$ : ClientBase<$name$>, $interface$\n", @@ -388,6 +453,7 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { if (method_type == METHODTYPE_NO_STREAMING) { // unary calls have an extra synchronous stub method + GenerateDocCommentBody(out, method); 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", @@ -400,6 +466,7 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { out->Print("}\n"); // overload taking CallOptions as a param + GenerateDocCommentBody(out, method); out->Print("public virtual $response$ $methodname$($request$ request, CallOptions options)\n", "methodname", method->name(), "request", GetClassName(method->input_type()), "response", @@ -416,6 +483,7 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { if (method_type == METHODTYPE_NO_STREAMING) { method_name += "Async"; // prevent name clash with synchronous method. } + GenerateDocCommentBody(out, method); out->Print( "public virtual $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n", "methodname", method_name, "request_maybe", @@ -431,6 +499,7 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { out->Print("}\n"); // overload taking CallOptions as a param + GenerateDocCommentBody(out, method); out->Print( "public virtual $returntype$ $methodname$($request_maybe$CallOptions options)\n", "methodname", method_name, "request_maybe", @@ -481,7 +550,7 @@ void GenerateClientStub(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"); + "/// <summary>Creates service definition that can be registered with a server</summary>\n"); out->Print("#pragma warning disable 0618\n"); out->Print( "public static ServerServiceDefinition BindService($interface$ serviceImpl)\n", @@ -515,7 +584,8 @@ void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service, } void GenerateNewStubMethods(Printer* out, const ServiceDescriptor *service) { - out->Print("// creates a new client\n"); + out->Print("/// <summary>Creates a new client for $servicename$</summary>\n", + "servicename", GetServiceClassName(service)); out->Print("public static $classname$ NewClient(Channel channel)\n", "classname", GetClientClassName(service)); out->Print("{\n"); @@ -527,8 +597,12 @@ void GenerateNewStubMethods(Printer* out, const ServiceDescriptor *service) { out->Print("\n"); } -void GenerateService(Printer* out, const ServiceDescriptor *service) { - out->Print("public static class $classname$\n", "classname", +void GenerateService(Printer* out, const ServiceDescriptor *service, + bool generate_client, bool generate_server, + bool internal_access) { + GenerateDocCommentBody(out, service); + out->Print("$access_level$ static class $classname$\n", "access_level", + GetAccessLevel(internal_access), "classname", GetServiceClassName(service)); out->Print("{\n"); out->Indent(); @@ -542,13 +616,22 @@ void GenerateService(Printer* out, const ServiceDescriptor *service) { GenerateStaticMethodField(out, service->method(i)); } GenerateServiceDescriptorProperty(out, service); - GenerateClientInterface(out, service); - GenerateServerInterface(out, service); - GenerateServerClass(out, service); - GenerateClientStub(out, service); - GenerateBindServiceMethod(out, service, false); - GenerateBindServiceMethod(out, service, true); - GenerateNewStubMethods(out, service); + + if (generate_client) { + GenerateClientInterface(out, service); + } + if (generate_server) { + GenerateServerInterface(out, service); + GenerateServerClass(out, service); + } + if (generate_client) { + GenerateClientStub(out, service); + GenerateNewStubMethods(out, service); + } + if (generate_server) { + GenerateBindServiceMethod(out, service, false); + GenerateBindServiceMethod(out, service, true); + } out->Outdent(); out->Print("}\n"); @@ -556,7 +639,8 @@ void GenerateService(Printer* out, const ServiceDescriptor *service) { } // anonymous namespace -grpc::string GetServices(const FileDescriptor *file) { +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. @@ -573,6 +657,14 @@ grpc::string GetServices(const FileDescriptor *file) { // 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()); + + // use C++ style as there are no file-level XML comments in .NET + grpc::string leading_comments = GetCppComments(file, true); + if (!leading_comments.empty()) { + out.Print("// Original file comments:\n"); + out.Print(leading_comments.c_str()); + } + out.Print("#region Designer generated code\n"); out.Print("\n"); out.Print("using System;\n"); @@ -584,7 +676,8 @@ grpc::string GetServices(const FileDescriptor *file) { out.Print("namespace $namespace$ {\n", "namespace", GetFileNamespace(file)); out.Indent(); for (int i = 0; i < file->service_count(); i++) { - GenerateService(&out, file->service(i)); + GenerateService(&out, file->service(i), generate_client, generate_server, + internal_access); } out.Outdent(); out.Print("}\n"); diff --git a/src/compiler/csharp_generator.h b/src/compiler/csharp_generator.h index 90eb7e2984..f0585af4fd 100644 --- a/src/compiler/csharp_generator.h +++ b/src/compiler/csharp_generator.h @@ -40,7 +40,9 @@ namespace grpc_csharp_generator { -grpc::string GetServices(const grpc::protobuf::FileDescriptor *file); +grpc::string GetServices(const grpc::protobuf::FileDescriptor *file, + bool generate_client, bool generate_server, + bool internal_access); } // namespace grpc_csharp_generator diff --git a/src/compiler/csharp_plugin.cc b/src/compiler/csharp_plugin.cc index 8b9395f9e2..5350e73f10 100644 --- a/src/compiler/csharp_plugin.cc +++ b/src/compiler/csharp_plugin.cc @@ -48,7 +48,29 @@ class CSharpGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { const grpc::string ¶meter, grpc::protobuf::compiler::GeneratorContext *context, grpc::string *error) const { - grpc::string code = grpc_csharp_generator::GetServices(file); + std::vector<std::pair<grpc::string, grpc::string> > options; + grpc::protobuf::compiler::ParseGeneratorParameter(parameter, &options); + + bool generate_client = true; + bool generate_server = true; + bool internal_access = false; + for (size_t i = 0; i < options.size(); i++) { + if (options[i].first == "no_client") { + generate_client = false; + } else if (options[i].first == "no_server") { + generate_server = false; + } else if (options[i].first == "internal_access") { + internal_access = true; + } else { + *error = "Unknown generator option: " + options[i].first; + return false; + } + } + + grpc::string code = grpc_csharp_generator::GetServices(file, + generate_client, + generate_server, + internal_access); if (code.size() == 0) { return true; // don't generate a file if there are no services } diff --git a/src/compiler/generator_helpers.h b/src/compiler/generator_helpers.h index 3ed0500efc..bd077cf798 100644 --- a/src/compiler/generator_helpers.h +++ b/src/compiler/generator_helpers.h @@ -34,7 +34,11 @@ #ifndef GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H #define GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H +#include <iostream> #include <map> +#include <sstream> +#include <string> +#include <vector> #include "src/compiler/config.h" @@ -175,6 +179,111 @@ inline MethodType GetMethodType(const grpc::protobuf::MethodDescriptor *method) } } +inline void Split(const grpc::string &s, char delim, + std::vector<grpc::string> *append_to) { + std::istringstream iss(s); + grpc::string piece; + while (std::getline(iss, piece)) { + append_to->push_back(piece); + } +} + +enum CommentType { + COMMENTTYPE_LEADING, + COMMENTTYPE_TRAILING, + COMMENTTYPE_LEADING_DETACHED +}; + +// Get all the raw comments and append each line without newline to out. +template <typename DescriptorType> +inline void GetComment(const DescriptorType *desc, CommentType type, + std::vector<grpc::string> *out) { + grpc::protobuf::SourceLocation location; + if (!desc->GetSourceLocation(&location)) { + return; + } + if (type == COMMENTTYPE_LEADING || type == COMMENTTYPE_TRAILING) { + const grpc::string &comments = type == COMMENTTYPE_LEADING + ? location.leading_comments + : location.trailing_comments; + Split(comments, '\n', out); + } else if (type == COMMENTTYPE_LEADING_DETACHED) { + for (unsigned int i = 0; i < location.leading_detached_comments.size(); + i++) { + Split(location.leading_detached_comments[i], '\n', out); + out->push_back(""); + } + } else { + std::cerr << "Unknown comment type " << type << std::endl; + abort(); + } +} + +// Each raw comment line without newline is appended to out. +// For file level leading and detached leading comments, we return comments +// above syntax line. Return nothing for trailing comments. +template <> +inline void GetComment(const grpc::protobuf::FileDescriptor *desc, + CommentType type, std::vector<grpc::string> *out) { + if (type == COMMENTTYPE_TRAILING) { + return; + } + grpc::protobuf::SourceLocation location; + std::vector<int> path; + path.push_back(grpc::protobuf::FileDescriptorProto::kSyntaxFieldNumber); + if (!desc->GetSourceLocation(path, &location)) { + return; + } + if (type == COMMENTTYPE_LEADING) { + Split(location.leading_comments, '\n', out); + } else if (type == COMMENTTYPE_LEADING_DETACHED) { + for (unsigned int i = 0; i < location.leading_detached_comments.size(); + i++) { + Split(location.leading_detached_comments[i], '\n', out); + out->push_back(""); + } + } else { + std::cerr << "Unknown comment type " << type << std::endl; + abort(); + } +} + +// Add prefix and newline to each comment line and concatenate them together. +// Make sure there is a space after the prefix unless the line is empty. +inline grpc::string GenerateCommentsWithPrefix( + const std::vector<grpc::string> &in, const grpc::string &prefix) { + std::ostringstream oss; + for (const grpc::string &elem : in) { + if (elem.empty()) { + oss << prefix << "\n"; + } else if (elem[0] == ' ') { + oss << prefix << elem << "\n"; + } else { + oss << prefix << " " << elem << "\n"; + } + } + return oss.str(); +} + +// Get leading or trailing comments in a string. Comment lines start with "// ". +// Leading detached comments are put in in front of leading comments. +template <typename DescriptorType> +inline grpc::string GetCppComments(const DescriptorType *desc, bool leading) { + std::vector<grpc::string> out; + if (leading) { + grpc_generator::GetComment( + desc, grpc_generator::COMMENTTYPE_LEADING_DETACHED, &out); + std::vector<grpc::string> leading; + grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING, + &leading); + out.insert(out.end(), leading.begin(), leading.end()); + } else { + grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_TRAILING, + &out); + } + return GenerateCommentsWithPrefix(out, "//"); +} + } // namespace grpc_generator #endif // GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc index ff092053ad..465491e385 100644 --- a/src/compiler/objective_c_generator.cc +++ b/src/compiler/objective_c_generator.cc @@ -75,11 +75,11 @@ void PrintMethodSignature(Printer *printer, const MethodDescriptor *method, if (method->server_streaming()) { printer->Print(vars, " eventHandler:(void(^)(BOOL done, " - "$response_class$ *response, NSError *error))eventHandler"); + "$response_class$ *_Nullable response, NSError *_Nullable error))eventHandler"); } else { printer->Print(vars, - " handler:(void(^)($response_class$ *response, " - "NSError *error))handler"); + " handler:(void(^)($response_class$ *_Nullable response, " + "NSError *_Nullable error))handler"); } } diff --git a/src/compiler/objective_c_plugin.cc b/src/compiler/objective_c_plugin.cc index 17440358bb..3ccfd5b037 100644 --- a/src/compiler/objective_c_plugin.cc +++ b/src/compiler/objective_c_plugin.cc @@ -81,8 +81,12 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { declarations += grpc_objective_c_generator::GetHeader(service); } + static const ::grpc::string kNonNullBegin = "\nNS_ASSUME_NONNULL_BEGIN\n\n"; + static const ::grpc::string kNonNullEnd = "\nNS_ASSUME_NONNULL_END\n"; + Write(context, file_name + ".pbrpc.h", - imports + '\n' + proto_imports + '\n' + declarations); + imports + '\n' + proto_imports + '\n' + kNonNullBegin + + declarations + kNonNullEnd); } { diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc index 02c032800b..59137e1c92 100644 --- a/src/compiler/python_generator.cc +++ b/src/compiler/python_generator.cc @@ -190,7 +190,7 @@ bool PrintBetaServicer(const ServiceDescriptor* service, "Documentation", doc, }); out->Print("\n"); - out->Print(dict, "class Beta$Service$Servicer(six.with_metaclass(abc.ABCMeta, object)):\n"); + out->Print(dict, "class Beta$Service$Servicer(object):\n"); { IndentScope raii_class_indent(out); out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); @@ -198,12 +198,11 @@ bool PrintBetaServicer(const ServiceDescriptor* service, auto meth = service->method(i); grpc::string arg_name = meth->client_streaming() ? "request_iterator" : "request"; - out->Print("@abc.abstractmethod\n"); out->Print("def $Method$(self, $ArgName$, context):\n", "Method", meth->name(), "ArgName", arg_name); { IndentScope raii_method_indent(out); - out->Print("raise NotImplementedError()\n"); + out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n"); } } } @@ -218,7 +217,7 @@ bool PrintBetaStub(const ServiceDescriptor* service, "Documentation", doc, }); out->Print("\n"); - out->Print(dict, "class Beta$Service$Stub(six.with_metaclass(abc.ABCMeta, object)):\n"); + out->Print(dict, "class Beta$Service$Stub(object):\n"); { IndentScope raii_class_indent(out); out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); @@ -227,7 +226,6 @@ bool PrintBetaStub(const ServiceDescriptor* service, grpc::string arg_name = meth->client_streaming() ? "request_iterator" : "request"; auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name}); - out->Print("@abc.abstractmethod\n"); out->Print(methdict, "def $Method$(self, $ArgName$, timeout):\n"); { IndentScope raii_method_indent(out); @@ -450,6 +448,8 @@ bool PrintPreamble(const FileDescriptor* file, out->Print("import six\n"); out->Print("from $Package$ import implementations as beta_implementations\n", "Package", config.beta_package_root); + out->Print("from $Package$ import interfaces as beta_interfaces\n", + "Package", config.beta_package_root); out->Print("from grpc.framework.common import cardinality\n"); out->Print("from grpc.framework.interfaces.face import utilities as face_utilities\n"); return true; |