[Swift] Append namespace for Swift Grpc implementation (#6049)
authorLiu Liu <i@liuliu.me>
Fri, 31 Jul 2020 07:07:45 +0000 (00:07 -0700)
committerGitHub <noreply@github.com>
Fri, 31 Jul 2020 07:07:45 +0000 (10:07 +0300)
* [Swift] Append namespace for Swift Grpc implementation
* Separate ServiceName from ServiceQualifiedName.

grpc/src/compiler/schema_interface.h
grpc/src/compiler/swift_generator.cc
src/idl_gen_grpc.cpp
tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test.grpc.swift

index 9611642..444b864 100644 (file)
@@ -62,7 +62,9 @@ struct Method : public CommentHolder {
       grpc::string *str, grpc::string generator_file_name,
       bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0;
 
+  virtual std::vector<grpc::string> get_input_namespace_parts() const = 0;
   virtual grpc::string get_input_type_name() const = 0;
+  virtual std::vector<grpc::string> get_output_namespace_parts() const = 0;
   virtual grpc::string get_output_type_name() const = 0;
 
   virtual grpc::string get_fb_builder() const = 0;
@@ -77,6 +79,7 @@ struct Method : public CommentHolder {
 struct Service : public CommentHolder {
   virtual ~Service() {}
 
+  virtual std::vector<grpc::string> namespace_parts() const = 0;
   virtual grpc::string name() const = 0;
 
   virtual int method_count() const = 0;
index a6016af..8733201 100644 (file)
 
 namespace grpc_swift_generator {
 
-grpc::string GenerateMessage(const grpc::string &name) {
-  return "Message<" + name + ">";
+std::string WrapInNameSpace(const std::vector<std::string> &components, const grpc::string &name) {
+  std::string qualified_name;
+  for (auto it = components.begin(); it != components.end(); ++it)
+    qualified_name += *it + "_";
+  return qualified_name + name;
+}
+
+grpc::string GenerateMessage(const std::vector<std::string> &components, const grpc::string &name) {
+  return "Message<" + WrapInNameSpace(components, name) + ">";
 }
 
 // MARK: - Client
@@ -85,12 +92,12 @@ void GenerateClientProtocol(const grpc_generator::Service *service,
                             grpc_generator::Printer *printer,
                             std::map<grpc::string, grpc::string> *dictonary) {
   auto vars = *dictonary;
-  printer->Print(vars, "$ACCESS$ protocol $ServiceName$Service {\n");
+  printer->Print(vars, "$ACCESS$ protocol $ServiceQualifiedName$Service {\n");
   vars["GenAccess"] = "";
   for (auto it = 0; it < service->method_count(); it++) {
     auto method = service->method(it);
-    vars["Input"] = GenerateMessage(method->get_input_type_name());
-    vars["Output"] = GenerateMessage(method->get_output_type_name());
+    vars["Input"] = GenerateMessage(method->get_input_namespace_parts(), method->get_input_type_name());
+    vars["Output"] = GenerateMessage(method->get_output_namespace_parts(), method->get_output_type_name());
     vars["MethodName"] = method->name();
     vars["isNil"] = "";
     printer->Print("\t");
@@ -106,8 +113,8 @@ void GenerateClientClass(const grpc_generator::Service *service,
                          std::map<grpc::string, grpc::string> *dictonary) {
   auto vars = *dictonary;
   printer->Print(vars,
-                 "$ACCESS$ final class $ServiceName$ServiceClient: GRPCClient, "
-                 "$ServiceName$Service {\n");
+                 "$ACCESS$ final class $ServiceQualifiedName$ServiceClient: GRPCClient, "
+                 "$ServiceQualifiedName$Service {\n");
   printer->Print(vars, "\t$ACCESS$ let channel: GRPCChannel\n");
   printer->Print(vars, "\t$ACCESS$ var defaultCallOptions: CallOptions\n");
   printer->Print("\n");
@@ -121,8 +128,8 @@ void GenerateClientClass(const grpc_generator::Service *service,
   vars["GenAccess"] = "public";
   for (auto it = 0; it < service->method_count(); it++) {
     auto method = service->method(it);
-    vars["Input"] = GenerateMessage(method->get_input_type_name());
-    vars["Output"] = GenerateMessage(method->get_output_type_name());
+    vars["Input"] = GenerateMessage(method->get_input_namespace_parts(), method->get_input_type_name());
+    vars["Output"] = GenerateMessage(method->get_output_namespace_parts(), method->get_output_type_name());
     vars["MethodName"] = method->name();
     vars["isNil"] = " = nil";
     printer->Print("\n\t");
@@ -208,11 +215,11 @@ void GenerateServerProtocol(const grpc_generator::Service *service,
                             std::map<grpc::string, grpc::string> *dictonary) {
   auto vars = *dictonary;
   printer->Print(
-      vars, "$ACCESS$ protocol $ServiceName$Provider: CallHandlerProvider {\n");
+      vars, "$ACCESS$ protocol $ServiceQualifiedName$Provider: CallHandlerProvider {\n");
   for (auto it = 0; it < service->method_count(); it++) {
     auto method = service->method(it);
-    vars["Input"] = GenerateMessage(method->get_input_type_name());
-    vars["Output"] = GenerateMessage(method->get_output_type_name());
+    vars["Input"] = GenerateMessage(method->get_input_namespace_parts(), method->get_input_type_name());
+    vars["Output"] = GenerateMessage(method->get_output_namespace_parts(), method->get_output_type_name());
     vars["MethodName"] = method->name();
     printer->Print("\t");
     auto func = GenerateServerFuncName(method.get());
@@ -221,7 +228,7 @@ void GenerateServerProtocol(const grpc_generator::Service *service,
   }
   printer->Print("}\n\n");
 
-  printer->Print(vars, "$ACCESS$ extension $ServiceName$Provider {\n");
+  printer->Print(vars, "$ACCESS$ extension $ServiceQualifiedName$Provider {\n");
   printer->Print(vars,
                  "\tvar serviceName: String { return "
                  "\"$PATH$$ServiceName$\" }\n");
@@ -231,8 +238,8 @@ void GenerateServerProtocol(const grpc_generator::Service *service,
   printer->Print("\t\tswitch methodName {\n");
   for (auto it = 0; it < service->method_count(); it++) {
     auto method = service->method(it);
-    vars["Input"] = GenerateMessage(method->get_input_type_name());
-    vars["Output"] = GenerateMessage(method->get_output_type_name());
+    vars["Input"] = GenerateMessage(method->get_input_namespace_parts(), method->get_input_type_name());
+    vars["Output"] = GenerateMessage(method->get_output_namespace_parts(), method->get_output_type_name());
     vars["MethodName"] = method->name();
     auto body = GenerateServerExtensionBody(method.get());
     printer->Print(vars, body.c_str());
@@ -250,11 +257,12 @@ grpc::string Generate(grpc_generator::File *file,
   std::map<grpc::string, grpc::string> vars;
   vars["PATH"] = file->package();
   if (!file->package().empty()) { vars["PATH"].append("."); }
+  vars["ServiceQualifiedName"] = WrapInNameSpace(service->namespace_parts(), service->name());
   vars["ServiceName"] = service->name();
   vars["ACCESS"] = "public";
   auto printer = file->CreatePrinter(&output);
   printer->Print(vars,
-                 "/// Usage: instantiate $ServiceName$ServiceClient, then call "
+                 "/// Usage: instantiate $ServiceQualifiedName$ServiceClient, then call "
                  "methods of this protocol to make API calls.\n");
   GenerateClientProtocol(service, &*printer, &vars);
   GenerateClientClass(service, &*printer, &vars);
index 96560ff..a9d4d7d 100644 (file)
@@ -59,12 +59,18 @@ class FlatBufMethod : public grpc_generator::Method {
 
   std::string name() const { return method_->name; }
 
+  // TODO: This method need to incorporate namespace for C++ side. Other language bindings
+  // simply don't use this method.
   std::string GRPCType(const StructDef &sd) const {
     return "flatbuffers::grpc::Message<" + sd.name + ">";
   }
 
+  std::vector<std::string> get_input_namespace_parts() const { return (*method_->request).defined_namespace->components; }
+
   std::string get_input_type_name() const { return (*method_->request).name; }
 
+  std::vector<std::string>  get_output_namespace_parts() const { return (*method_->response).defined_namespace->components; }
+
   std::string get_output_type_name() const { return (*method_->response).name; }
 
   bool get_module_and_message_path_input(grpc::string * /*str*/,
@@ -111,6 +117,8 @@ class FlatBufService : public grpc_generator::Service {
     return service_->doc_comment;
   }
 
+  std::vector<grpc::string> namespace_parts() const { return service_->defined_namespace->components; }
+
   std::string name() const { return service_->name; }
 
   int method_count() const {
index f635b75..66bac37 100644 (file)
@@ -19,15 +19,15 @@ public extension GRPCFlatBufPayload {
 }
 extension Message: GRPCFlatBufPayload {}
 
-/// Usage: instantiate MonsterStorageServiceClient, then call methods of this protocol to make API calls.
-public protocol MonsterStorageService {
-        func Store(_ request: Message<Monster>, callOptions: CallOptions?) -> UnaryCall<Message<Monster>,Message<Stat>>
-        func Retrieve(_ request: Message<Stat>, callOptions: CallOptions?, handler: @escaping (Message<Monster>) -> Void) -> ServerStreamingCall<Message<Stat>, Message<Monster>>
-        func GetMaxHitPoint(callOptions: CallOptions?) -> ClientStreamingCall<Message<Monster>,Message<Stat>>
-        func GetMinMaxHitPoints(callOptions: CallOptions?, handler: @escaping (Message<Stat>) -> Void) -> BidirectionalStreamingCall<Message<Monster>, Message<Stat>>
+/// Usage: instantiate MyGame_Example_MonsterStorageServiceClient, then call methods of this protocol to make API calls.
+public protocol MyGame_Example_MonsterStorageService {
+        func Store(_ request: Message<MyGame_Example_Monster>, callOptions: CallOptions?) -> UnaryCall<Message<MyGame_Example_Monster>,Message<MyGame_Example_Stat>>
+        func Retrieve(_ request: Message<MyGame_Example_Stat>, callOptions: CallOptions?, handler: @escaping (Message<MyGame_Example_Monster>) -> Void) -> ServerStreamingCall<Message<MyGame_Example_Stat>, Message<MyGame_Example_Monster>>
+        func GetMaxHitPoint(callOptions: CallOptions?) -> ClientStreamingCall<Message<MyGame_Example_Monster>,Message<MyGame_Example_Stat>>
+        func GetMinMaxHitPoints(callOptions: CallOptions?, handler: @escaping (Message<MyGame_Example_Stat>) -> Void) -> BidirectionalStreamingCall<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>
 }
 
-public final class MonsterStorageServiceClient: GRPCClient, MonsterStorageService {
+public final class MyGame_Example_MonsterStorageServiceClient: GRPCClient, MyGame_Example_MonsterStorageService {
        public let channel: GRPCChannel
        public var defaultCallOptions: CallOptions
 
@@ -36,31 +36,31 @@ public final class MonsterStorageServiceClient: GRPCClient, MonsterStorageServic
                self.defaultCallOptions = defaultCallOptions
        }
 
-       public func Store(_ request: Message<Monster>, callOptions: CallOptions? = nil) -> UnaryCall<Message<Monster>,Message<Stat>> {
+       public func Store(_ request: Message<MyGame_Example_Monster>, callOptions: CallOptions? = nil) -> UnaryCall<Message<MyGame_Example_Monster>,Message<MyGame_Example_Stat>> {
                return self.makeUnaryCall(path: "/MyGame.Example.MonsterStorage/Store", request: request, callOptions: callOptions ?? self.defaultCallOptions)
        }
 
-       public func Retrieve(_ request: Message<Stat>, callOptions: CallOptions? = nil, handler: @escaping (Message<Monster>) -> Void) -> ServerStreamingCall<Message<Stat>, Message<Monster>> {
+       public func Retrieve(_ request: Message<MyGame_Example_Stat>, callOptions: CallOptions? = nil, handler: @escaping (Message<MyGame_Example_Monster>) -> Void) -> ServerStreamingCall<Message<MyGame_Example_Stat>, Message<MyGame_Example_Monster>> {
                return self.makeServerStreamingCall(path: "/MyGame.Example.MonsterStorage/Retrieve", request: request, callOptions: callOptions ?? self.defaultCallOptions, handler: handler)
        }
 
-       public func GetMaxHitPoint(callOptions: CallOptions? = nil) -> ClientStreamingCall<Message<Monster>,Message<Stat>> {
+       public func GetMaxHitPoint(callOptions: CallOptions? = nil) -> ClientStreamingCall<Message<MyGame_Example_Monster>,Message<MyGame_Example_Stat>> {
                return self.makeClientStreamingCall(path: "/MyGame.Example.MonsterStorage/GetMaxHitPoint", callOptions: callOptions ?? self.defaultCallOptions)
        }
 
-       public func GetMinMaxHitPoints(callOptions: CallOptions? = nil, handler: @escaping (Message<Stat>) -> Void) -> BidirectionalStreamingCall<Message<Monster>, Message<Stat>> {
+       public func GetMinMaxHitPoints(callOptions: CallOptions? = nil, handler: @escaping (Message<MyGame_Example_Stat>) -> Void) -> BidirectionalStreamingCall<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>> {
                return self.makeBidirectionalStreamingCall(path: "/MyGame.Example.MonsterStorage/GetMinMaxHitPoints", callOptions: callOptions ?? self.defaultCallOptions, handler: handler)
        }
 }
 
-public protocol MonsterStorageProvider: CallHandlerProvider {
-       func Store(_ request: Message<Monster>, context: StatusOnlyCallContext) -> EventLoopFuture<Message<Stat>>
-       func Retrieve(request: Message<Stat>, context: StreamingResponseCallContext<Message<Monster>>) -> EventLoopFuture<GRPCStatus>
-       func GetMaxHitPoint(context: UnaryResponseCallContext<Message<Stat>>) -> EventLoopFuture<(StreamEvent<Message<Monster>>) -> Void>
-       func GetMinMaxHitPoints(context: StreamingResponseCallContext<Message<Stat>>) -> EventLoopFuture<(StreamEvent<Message<Monster>>) -> Void>
+public protocol MyGame_Example_MonsterStorageProvider: CallHandlerProvider {
+       func Store(_ request: Message<MyGame_Example_Monster>, context: StatusOnlyCallContext) -> EventLoopFuture<Message<MyGame_Example_Stat>>
+       func Retrieve(request: Message<MyGame_Example_Stat>, context: StreamingResponseCallContext<Message<MyGame_Example_Monster>>) -> EventLoopFuture<GRPCStatus>
+       func GetMaxHitPoint(context: UnaryResponseCallContext<Message<MyGame_Example_Stat>>) -> EventLoopFuture<(StreamEvent<Message<MyGame_Example_Monster>>) -> Void>
+       func GetMinMaxHitPoints(context: StreamingResponseCallContext<Message<MyGame_Example_Stat>>) -> EventLoopFuture<(StreamEvent<Message<MyGame_Example_Monster>>) -> Void>
 }
 
-public extension MonsterStorageProvider {
+public extension MyGame_Example_MonsterStorageProvider {
        var serviceName: String { return "MyGame.Example.MonsterStorage" }
        func handleMethod(_ methodName: String, callHandlerContext: CallHandlerContext) -> GRPCCallHandler? {
                switch methodName {