浏览代码

[CodeGenLib] Typealias translator configuration for client and server (#1750)

Motivation:

The typealias translator should generate typealias for the client and server protocols only if the associated code (client/server code) will be generated as well. Also, at the moment the Typealias translator doesn't generate the ClientProtocol typealias.

Modifications:

- added a new initialiser for the TypealiasTranslator that sets the client and server property.
- Based on the client and server properties' values the typealias translator generates or not the protocol typealiases.
- created method gor client protocol typalias generation.
- modified tests, so they include the client code.
- added new tests for generating only client or server code.

Result:

The typealias translator will generate typealiases for client and server protocols only when the associated code is also generated, getting rid of the possibility of an error (when the protocol doesn't exist).
Stefana-Ioana Dranca 2 年之前
父节点
当前提交
61456310e1

+ 2 - 2
Sources/GRPCCodeGen/Internal/Translator/IDLToStructuredSwiftTranslator.swift

@@ -15,7 +15,6 @@
  */
 
 struct IDLToStructuredSwiftTranslator: Translator {
-  private let typealiasTranslator = TypealiasTranslator()
   private let serverCodeTranslator = ServerCodeTranslator()
 
   func translate(
@@ -23,13 +22,14 @@ struct IDLToStructuredSwiftTranslator: Translator {
     client: Bool,
     server: Bool
   ) throws -> StructuredSwiftRepresentation {
+    let typealiasTranslator = TypealiasTranslator(client: client, server: server)
     let topComment = Comment.doc(codeGenerationRequest.leadingTrivia)
     let imports: [ImportDescription] = [
       ImportDescription(moduleName: "GRPCCore")
     ]
     var codeBlocks: [CodeBlock] = []
     codeBlocks.append(
-      contentsOf: try self.typealiasTranslator.translate(from: codeGenerationRequest)
+      contentsOf: try typealiasTranslator.translate(from: codeGenerationRequest)
     )
 
     if server {

+ 45 - 18
Sources/GRPCCodeGen/Internal/Translator/TypealiasTranslator.swift

@@ -53,6 +53,14 @@
 /// A ``CodeGenerationRequest`` can contain multiple namespaces, so the TypealiasTranslator will create a ``CodeBlock``
 /// for each namespace.
 struct TypealiasTranslator: SpecializedTranslator {
+  let client: Bool
+  let server: Bool
+
+  init(client: Bool, server: Bool) {
+    self.client = client
+    self.server = server
+  }
+
   func translate(from codeGenerationRequest: CodeGenerationRequest) throws -> [CodeBlock] {
     var codeBlocks: [CodeBlock] = []
     let services = codeGenerationRequest.services
@@ -169,9 +177,21 @@ extension TypealiasTranslator {
     let methodDescriptorsDeclaration = self.makeMethodDescriptors(for: service)
     serviceEnum.members.append(methodDescriptorsDeclaration)
 
-    // Create the streaming and non-streaming service protocol type aliases.
-    let serviceProtocols = self.makeServiceProtocolsTypealiases(for: service)
-    serviceEnum.members.append(contentsOf: serviceProtocols)
+    if self.server {
+      // Create the streaming and non-streaming service protocol type aliases.
+      let serviceProtocols = self.makeServiceProtocolsTypealiases(for: service)
+      serviceEnum.members.append(contentsOf: serviceProtocols)
+    }
+
+    if self.client {
+      // Create the client protocol type alias.
+      let clientProtocol = self.makeClientProtocolTypealias(for: service)
+      serviceEnum.members.append(clientProtocol)
+
+      // Create type alias for Client struct.
+      let clientStruct = self.makeClientStructTypealias(for: service)
+      serviceEnum.members.append(clientStruct)
+    }
 
     return .enum(serviceEnum)
   }
@@ -236,7 +256,7 @@ extension TypealiasTranslator {
 
     let descriptorDeclarationRight = Expression.functionCall(
       FunctionCallDescription(
-        calledExpression: .identifierType(.member(["MethodDescriptor"])),
+        calledExpression: .identifierType(.member("MethodDescriptor")),
         arguments: [
           FunctionArgumentDescription(
             label: "service",
@@ -277,7 +297,7 @@ extension TypealiasTranslator {
       isStatic: true,
       kind: .let,
       left: .identifier(.pattern("methods")),
-      type: .array(.member(["MethodDescriptor"])),
+      type: .array(.member("MethodDescriptor")),
       right: .literal(.array(methodDescriptors))
     )
   }
@@ -285,26 +305,33 @@ extension TypealiasTranslator {
   private func makeServiceProtocolsTypealiases(
     for service: CodeGenerationRequest.ServiceDescriptor
   ) -> [Declaration] {
-    let namespacedPrefix: String
-
-    if service.namespace.isEmpty {
-      namespacedPrefix = service.name
-    } else {
-      namespacedPrefix = "\(service.namespace)_\(service.name)"
-    }
-
-    let streamingServiceProtocolName = "\(namespacedPrefix)ServiceStreamingProtocol"
     let streamingServiceProtocolTypealias = Declaration.typealias(
       name: "StreamingServiceProtocol",
-      existingType: .member([streamingServiceProtocolName])
+      existingType: .member("\(service.namespacedPrefix)ServiceStreamingProtocol")
     )
-
-    let serviceProtocolName = "\(namespacedPrefix)ServiceProtocol"
     let serviceProtocolTypealias = Declaration.typealias(
       name: "ServiceProtocol",
-      existingType: .member([serviceProtocolName])
+      existingType: .member("\(service.namespacedPrefix)ServiceProtocol")
     )
 
     return [streamingServiceProtocolTypealias, serviceProtocolTypealias]
   }
+
+  private func makeClientProtocolTypealias(
+    for service: CodeGenerationRequest.ServiceDescriptor
+  ) -> Declaration {
+    return .typealias(
+      name: "ClientProtocol",
+      existingType: .member("\(service.namespacedPrefix)ClientProtocol")
+    )
+  }
+
+  private func makeClientStructTypealias(
+    for service: CodeGenerationRequest.ServiceDescriptor
+  ) -> Declaration {
+    return .typealias(
+      name: "Client",
+      existingType: .member("\(service.namespacedPrefix)Client")
+    )
+  }
 }

+ 164 - 14
Tests/GRPCCodeGenTests/Internal/Translator/TypealiasTranslatorSnippetBasedTests.swift

@@ -58,13 +58,125 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
               ]
               typealias StreamingServiceProtocol = namespaceA_ServiceAServiceStreamingProtocol
               typealias ServiceProtocol = namespaceA_ServiceAServiceProtocol
+              typealias ClientProtocol = namespaceA_ServiceAClientProtocol
+              typealias Client = namespaceA_ServiceAClient
           }
       }
       """
 
     try self.assertTypealiasTranslation(
       codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
-      expectedSwift: expectedSwift
+      expectedSwift: expectedSwift,
+      client: true,
+      server: true
+    )
+  }
+
+  func testTypealiasTranslatorNoMethodsServiceClientAndServer() throws {
+    let service = ServiceDescriptor(
+      documentation: "Documentation for ServiceA",
+      name: "ServiceA",
+      namespace: "namespaceA",
+      methods: []
+    )
+    let expectedSwift =
+      """
+      enum namespaceA {
+          enum ServiceA {
+              enum Methods {}
+              static let methods: [MethodDescriptor] = []
+              typealias StreamingServiceProtocol = namespaceA_ServiceAServiceStreamingProtocol
+              typealias ServiceProtocol = namespaceA_ServiceAServiceProtocol
+              typealias ClientProtocol = namespaceA_ServiceAClientProtocol
+              typealias Client = namespaceA_ServiceAClient
+          }
+      }
+      """
+
+    try self.assertTypealiasTranslation(
+      codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
+      expectedSwift: expectedSwift,
+      client: true,
+      server: true
+    )
+  }
+
+  func testTypealiasTranslatorServer() throws {
+    let service = ServiceDescriptor(
+      documentation: "Documentation for ServiceA",
+      name: "ServiceA",
+      namespace: "namespaceA",
+      methods: []
+    )
+    let expectedSwift =
+      """
+      enum namespaceA {
+          enum ServiceA {
+              enum Methods {}
+              static let methods: [MethodDescriptor] = []
+              typealias StreamingServiceProtocol = namespaceA_ServiceAServiceStreamingProtocol
+              typealias ServiceProtocol = namespaceA_ServiceAServiceProtocol
+          }
+      }
+      """
+
+    try self.assertTypealiasTranslation(
+      codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
+      expectedSwift: expectedSwift,
+      client: false,
+      server: true
+    )
+  }
+
+  func testTypealiasTranslatorClient() throws {
+    let service = ServiceDescriptor(
+      documentation: "Documentation for ServiceA",
+      name: "ServiceA",
+      namespace: "namespaceA",
+      methods: []
+    )
+    let expectedSwift =
+      """
+      enum namespaceA {
+          enum ServiceA {
+              enum Methods {}
+              static let methods: [MethodDescriptor] = []
+              typealias ClientProtocol = namespaceA_ServiceAClientProtocol
+              typealias Client = namespaceA_ServiceAClient
+          }
+      }
+      """
+
+    try self.assertTypealiasTranslation(
+      codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
+      expectedSwift: expectedSwift,
+      client: true,
+      server: false
+    )
+  }
+
+  func testTypealiasTranslatorNoClientNoServer() throws {
+    let service = ServiceDescriptor(
+      documentation: "Documentation for ServiceA",
+      name: "ServiceA",
+      namespace: "namespaceA",
+      methods: []
+    )
+    let expectedSwift =
+      """
+      enum namespaceA {
+          enum ServiceA {
+              enum Methods {}
+              static let methods: [MethodDescriptor] = []
+          }
+      }
+      """
+
+    try self.assertTypealiasTranslation(
+      codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
+      expectedSwift: expectedSwift,
+      client: false,
+      server: false
     )
   }
 
@@ -101,12 +213,16 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
           ]
           typealias StreamingServiceProtocol = ServiceAServiceStreamingProtocol
           typealias ServiceProtocol = ServiceAServiceProtocol
+          typealias ClientProtocol = ServiceAClientProtocol
+          typealias Client = ServiceAClient
       }
       """
 
     try self.assertTypealiasTranslation(
       codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
-      expectedSwift: expectedSwift
+      expectedSwift: expectedSwift,
+      client: true,
+      server: true
     )
   }
 
@@ -161,13 +277,17 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
               ]
               typealias StreamingServiceProtocol = namespaceA_ServiceAServiceStreamingProtocol
               typealias ServiceProtocol = namespaceA_ServiceAServiceProtocol
+              typealias ClientProtocol = namespaceA_ServiceAClientProtocol
+              typealias Client = namespaceA_ServiceAClient
           }
       }
       """
 
     try self.assertTypealiasTranslation(
       codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
-      expectedSwift: expectedSwift
+      expectedSwift: expectedSwift,
+      client: true,
+      server: true
     )
   }
 
@@ -186,13 +306,17 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
               static let methods: [MethodDescriptor] = []
               typealias StreamingServiceProtocol = namespaceA_ServiceAServiceStreamingProtocol
               typealias ServiceProtocol = namespaceA_ServiceAServiceProtocol
+              typealias ClientProtocol = namespaceA_ServiceAClientProtocol
+              typealias Client = namespaceA_ServiceAClient
           }
       }
       """
 
     try self.assertTypealiasTranslation(
       codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
-      expectedSwift: expectedSwift
+      expectedSwift: expectedSwift,
+      client: true,
+      server: true
     )
   }
 
@@ -219,19 +343,25 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
               static let methods: [MethodDescriptor] = []
               typealias StreamingServiceProtocol = namespacea_AServiceServiceStreamingProtocol
               typealias ServiceProtocol = namespacea_AServiceServiceProtocol
+              typealias ClientProtocol = namespacea_AServiceClientProtocol
+              typealias Client = namespacea_AServiceClient
           }
           enum BService {
               enum Methods {}
               static let methods: [MethodDescriptor] = []
               typealias StreamingServiceProtocol = namespacea_BServiceServiceStreamingProtocol
               typealias ServiceProtocol = namespacea_BServiceServiceProtocol
+              typealias ClientProtocol = namespacea_BServiceClientProtocol
+              typealias Client = namespacea_BServiceClient
           }
       }
       """
 
     try self.assertTypealiasTranslation(
       codeGenerationRequest: makeCodeGenerationRequest(services: [serviceB, serviceA]),
-      expectedSwift: expectedSwift
+      expectedSwift: expectedSwift,
+      client: true,
+      server: true
     )
   }
 
@@ -257,18 +387,24 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
           static let methods: [MethodDescriptor] = []
           typealias StreamingServiceProtocol = AServiceServiceStreamingProtocol
           typealias ServiceProtocol = AServiceServiceProtocol
+          typealias ClientProtocol = AServiceClientProtocol
+          typealias Client = AServiceClient
       }
       enum BService {
           enum Methods {}
           static let methods: [MethodDescriptor] = []
           typealias StreamingServiceProtocol = BServiceServiceStreamingProtocol
           typealias ServiceProtocol = BServiceServiceProtocol
+          typealias ClientProtocol = BServiceClientProtocol
+          typealias Client = BServiceClient
       }
       """
 
     try self.assertTypealiasTranslation(
       codeGenerationRequest: makeCodeGenerationRequest(services: [serviceB, serviceA]),
-      expectedSwift: expectedSwift
+      expectedSwift: expectedSwift,
+      client: true,
+      server: true
     )
   }
 
@@ -295,6 +431,8 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
               static let methods: [MethodDescriptor] = []
               typealias StreamingServiceProtocol = anamespace_AServiceServiceStreamingProtocol
               typealias ServiceProtocol = anamespace_AServiceServiceProtocol
+              typealias ClientProtocol = anamespace_AServiceClientProtocol
+              typealias Client = anamespace_AServiceClient
           }
       }
       enum bnamespace {
@@ -303,13 +441,17 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
               static let methods: [MethodDescriptor] = []
               typealias StreamingServiceProtocol = bnamespace_BServiceServiceStreamingProtocol
               typealias ServiceProtocol = bnamespace_BServiceServiceProtocol
+              typealias ClientProtocol = bnamespace_BServiceClientProtocol
+              typealias Client = bnamespace_BServiceClient
           }
       }
       """
 
     try self.assertTypealiasTranslation(
       codeGenerationRequest: makeCodeGenerationRequest(services: [serviceB, serviceA]),
-      expectedSwift: expectedSwift
+      expectedSwift: expectedSwift,
+      client: true,
+      server: true
     )
   }
 
@@ -333,6 +475,8 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
           static let methods: [MethodDescriptor] = []
           typealias StreamingServiceProtocol = BServiceServiceStreamingProtocol
           typealias ServiceProtocol = BServiceServiceProtocol
+          typealias ClientProtocol = BServiceClientProtocol
+          typealias Client = BServiceClient
       }
       enum anamespace {
           enum AService {
@@ -340,13 +484,17 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
               static let methods: [MethodDescriptor] = []
               typealias StreamingServiceProtocol = anamespace_AServiceServiceStreamingProtocol
               typealias ServiceProtocol = anamespace_AServiceServiceProtocol
+              typealias ClientProtocol = anamespace_AServiceClientProtocol
+              typealias Client = anamespace_AServiceClient
           }
       }
       """
 
     try self.assertTypealiasTranslation(
       codeGenerationRequest: makeCodeGenerationRequest(services: [serviceA, serviceB]),
-      expectedSwift: expectedSwift
+      expectedSwift: expectedSwift,
+      client: true,
+      server: true
     )
   }
 
@@ -359,7 +507,7 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
     )
 
     let codeGenerationRequest = makeCodeGenerationRequest(services: [serviceA, serviceA])
-    let translator = TypealiasTranslator()
+    let translator = TypealiasTranslator(client: true, server: true)
     XCTAssertThrowsError(
       ofType: CodeGenError.self,
       try translator.translate(from: codeGenerationRequest)
@@ -387,7 +535,7 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
     )
 
     let codeGenerationRequest = makeCodeGenerationRequest(services: [serviceA, serviceA])
-    let translator = TypealiasTranslator()
+    let translator = TypealiasTranslator(client: true, server: true)
     XCTAssertThrowsError(
       ofType: CodeGenError.self,
       try translator.translate(from: codeGenerationRequest)
@@ -423,7 +571,7 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
     )
 
     let codeGenerationRequest = makeCodeGenerationRequest(services: [service])
-    let translator = TypealiasTranslator()
+    let translator = TypealiasTranslator(client: true, server: true)
     XCTAssertThrowsError(
       ofType: CodeGenError.self,
       try translator.translate(from: codeGenerationRequest)
@@ -456,7 +604,7 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
       methods: []
     )
     let codeGenerationRequest = makeCodeGenerationRequest(services: [serviceA, serviceB])
-    let translator = TypealiasTranslator()
+    let translator = TypealiasTranslator(client: true, server: true)
     XCTAssertThrowsError(
       ofType: CodeGenError.self,
       try translator.translate(from: codeGenerationRequest)
@@ -479,9 +627,11 @@ final class TypealiasTranslatorSnippetBasedTests: XCTestCase {
 extension TypealiasTranslatorSnippetBasedTests {
   private func assertTypealiasTranslation(
     codeGenerationRequest: CodeGenerationRequest,
-    expectedSwift: String
+    expectedSwift: String,
+    client: Bool,
+    server: Bool
   ) throws {
-    let translator = TypealiasTranslator()
+    let translator = TypealiasTranslator(client: client, server: server)
     let codeBlocks = try translator.translate(from: codeGenerationRequest)
     let renderer = TextBasedRenderer.default
     renderer.renderCodeBlocks(codeBlocks)