Browse Source

Support protobuf separately to `GRPCPayload` for the client (#889)

Motivation:

To support payloads other than `SwiftProtobuf.Message` we required that
all messages conform to `GRPCPayload`. For protobuf messages we added
`GRPCProtobufPayload` which provides a default implemenation of
`GRPCPayload` for protobuf messages. We generated this conformance for
all protobuf messages we saw. This lead to a number issues and
workarounds including: #738, #778, #801, #837, #877, #881.

The intention is to continue to support `GRPCPayload` in addition to
protobuf, however, support for protobuf will not be via the
`GRPCProtobufPayload` protocol.

This PR builds on #886 by increasing the surface area of the client APIs
so that they are not constrained to `GRPCPayload`. The surface API now
has variants for `GRPCPayload` and `SwiftProtobuf.Message`. Internally
the client deals with serializers and deserializers.

Modifications:

- `GRPCClientChannelHandler` and `GRPCClientStateMachine` are no longer
  generic over a request and response type, rather they deal with the
  serialzed version of requests and response (i.e. `ByteBuffer`s) and
  defer the (de/)serialization to a separate handler.
- Added `GRCPClientCodecHandler` to handle (de/)serialization of
  messages
- Clients are no longer constrained to having their request/response
  payloads conform to `GRPCPayload`
- Conformance to `GRPCProtobufPayload` is no longer generated and the
  protocol is deprecated and has no requirements.
- Drop the 'GenerateConformance' option from the codegen since it is no
  longer required
- Reintroduce a filter to the codegen so that we only consider files
  which contain services, this avoids generating empty files
- Regenerate code where necessary

Result:

- `GRPCProtobufPayload` is no longer required
George Barnett 5 years ago
parent
commit
966e597175

+ 0 - 39
Sources/protoc-gen-grpc-swift/Generator-Conformance.swift

@@ -1,39 +0,0 @@
-/*
- * Copyright 2020, gRPC Authors All rights reserved.
- *
- * 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.
- */
-import SwiftProtobuf
-import SwiftProtobufPluginLibrary
-
-extension Generator {
-  internal func printProtobufExtensions() {
-    if self.file.messages.isEmpty {
-      return
-    }
-    println("// Provides conformance to `GRPCPayload`")
-    for message in self.file.messages {
-      self.printProtobufExtensions(for: message)
-    }
-  }
-
-  internal func printProtobufExtensions(for message: Descriptor) {
-    let name = self.protobufNamer.fullName(message: message)
-    self.println("extension \(name): GRPCProtobufPayload {}")
-
-    // Messages may be nested.
-    for message in message.messages {
-      self.printProtobufExtensions(for: message)
-    }
-  }
-}

+ 0 - 5
Sources/protoc-gen-grpc-swift/Generator.swift

@@ -118,10 +118,5 @@ class Generator {
         printServer()
       }
     }
-
-    if options.generatePayloadConformance {
-      self.println()
-      self.printProtobufExtensions()
-    }
   }
 }

+ 2 - 4
Sources/protoc-gen-grpc-swift/main.swift

@@ -102,10 +102,8 @@ func main() throws {
   // Build the SwiftProtobufPluginLibrary model of the plugin input
   let descriptorSet = DescriptorSet(protos: request.protoFile)
 
-  // process each .proto file in filename order in an attempt to stabilise the output (i.e. where
-  // conformance to `GRPCPayload` is generated)
-  for name in request.fileToGenerate.sorted() {
-    let fileDescriptor = descriptorSet.lookupFileDescriptor(protoName: name)
+  // Only generate output for services.
+  for fileDescriptor in descriptorSet.files where !fileDescriptor.services.isEmpty {
     let grpcFileName = uniqueOutputFileName(component: "grpc", fileDescriptor: fileDescriptor, fileNamingOption: options.fileNaming)
     let grpcGenerator = Generator(fileDescriptor, options: options)
     var grpcFile = Google_Protobuf_Compiler_CodeGeneratorResponse.File()

+ 0 - 8
Sources/protoc-gen-grpc-swift/options.swift

@@ -55,7 +55,6 @@ final class GeneratorOptions {
   private(set) var generateServer = true
   private(set) var generateClient = true
   private(set) var generateTestClient = false
-  private(set) var generatePayloadConformance = true
   private(set) var protoToModuleMappings = ProtoFileToModuleMappings()
   private(set) var fileNaming = FileNaming.FullPath
   private(set) var extraModuleImports: [String] = []
@@ -91,13 +90,6 @@ final class GeneratorOptions {
           throw GenerationError.invalidParameterValue(name: pair.key, value: pair.value)
         }
 
-      case "PayloadConformance":
-        if let value = Bool(pair.value) {
-          self.generatePayloadConformance = value
-        } else {
-          throw GenerationError.invalidParameterValue(name: pair.key, value: pair.value)
-        }
-
       case "ProtoPathModuleMappings":
         if !pair.value.isEmpty {
           do {