Browse Source

Only generate SwiftProtobuf import for well-known types (#17)

Motivation:

In (#16) an import for SwiftProtobuf was added to account for well-known
types. However, if no well-known types are used then warnings are
emitted when the access level is included on the import.

Modifications:

- Only generate the SwiftProtobuf import for well-known types

Result:

Fewer warnings
George Barnett 1 year ago
parent
commit
97dfddeb46

+ 16 - 2
Sources/GRPCProtobufCodeGen/ProtobufCodeGenParser.swift

@@ -96,9 +96,23 @@ extension ProtobufCodeGenParser {
     file: FileDescriptor
     file: FileDescriptor
   ) -> [Dependency] {
   ) -> [Dependency] {
     var codeDependencies: [Dependency] = [
     var codeDependencies: [Dependency] = [
-      Dependency(module: "GRPCProtobuf", accessLevel: .internal),
-      Dependency(module: "SwiftProtobuf", accessLevel: self.accessLevel),
+      Dependency(module: "GRPCProtobuf", accessLevel: .internal)
     ]
     ]
+
+    // If any services in the file depend on well-known Protobuf types then also import
+    // SwiftProtobuf. Importing SwiftProtobuf unconditionally results in warnings in the generated
+    // code if access-levels are used on imports and no well-known types are used.
+    let usesAnyWellKnownTypesInServices = file.services.contains { service in
+      service.methods.contains { method in
+        let inputIsWellKnown = method.inputType.wellKnownType != nil
+        let outputIsWellKnown = method.outputType.wellKnownType != nil
+        return inputIsWellKnown || outputIsWellKnown
+      }
+    }
+    if usesAnyWellKnownTypesInServices {
+      codeDependencies.append(Dependency(module: "SwiftProtobuf", accessLevel: self.accessLevel))
+    }
+
     // Adding as dependencies the modules containing generated code or types for
     // Adding as dependencies the modules containing generated code or types for
     // '.proto' files imported in the '.proto' file we are parsing.
     // '.proto' files imported in the '.proto' file we are parsing.
     codeDependencies.append(
     codeDependencies.append(

BIN
Tests/GRPCProtobufCodeGenTests/Generated/wkt-service.pb


+ 24 - 4
Tests/GRPCProtobufCodeGenTests/ProtobufCodeGenParserTests.swift

@@ -61,8 +61,7 @@ struct ProtobufCodeGenParserTests {
     @Test("Dependencies")
     @Test("Dependencies")
     func dependencies() {
     func dependencies() {
       let expected: [GRPCCodeGen.Dependency] = [
       let expected: [GRPCCodeGen.Dependency] = [
-        .init(module: "GRPCProtobuf", accessLevel: .internal),  // Always an internal import
-        .init(module: "SwiftProtobuf", accessLevel: .internal),
+        .init(module: "GRPCProtobuf", accessLevel: .internal)  // Always an internal import
       ]
       ]
       #expect(self.codeGen.dependencies == expected)
       #expect(self.codeGen.dependencies == expected)
     }
     }
@@ -174,8 +173,7 @@ struct ProtobufCodeGenParserTests {
     @Test("Dependencies")
     @Test("Dependencies")
     func dependencies() {
     func dependencies() {
       let expected: [GRPCCodeGen.Dependency] = [
       let expected: [GRPCCodeGen.Dependency] = [
-        .init(module: "GRPCProtobuf", accessLevel: .internal),  // Always an internal import
-        .init(module: "SwiftProtobuf", accessLevel: .internal),
+        .init(module: "GRPCProtobuf", accessLevel: .internal)  // Always an internal import
       ]
       ]
       #expect(self.codeGen.dependencies == expected)
       #expect(self.codeGen.dependencies == expected)
     }
     }
@@ -237,4 +235,26 @@ struct ProtobufCodeGenParserTests {
       #expect(self.service.namespace.base == "")
       #expect(self.service.namespace.base == "")
     }
     }
   }
   }
+
+  @Suite("Service using 'well-known types' (wkt-service.proto)")
+  struct WKTService: UsesDescriptorSet {
+    static let descriptorSetName = "wkt-service"
+    static let fileDescriptorName = "wkt-service"
+
+    let codeGen: CodeGenerationRequest
+
+    init() throws {
+      let descriptor = try #require(try Self.fileDescriptor)
+      self.codeGen = try parseDescriptor(descriptor)
+    }
+
+    @Test("Dependencies")
+    func dependencies() {
+      let expected: [Dependency] = [
+        Dependency(module: "GRPCProtobuf", accessLevel: .internal),
+        Dependency(module: "SwiftProtobuf", accessLevel: .internal),
+      ]
+      #expect(self.codeGen.dependencies == expected)
+    }
+  }
 }
 }

+ 0 - 1
Tests/GRPCProtobufCodeGenTests/ProtobufCodeGeneratorTests.swift

@@ -67,7 +67,6 @@ struct ProtobufCodeGeneratorTests: UsesDescriptorSet {
 
 
       import GRPCCore
       import GRPCCore
       import GRPCProtobuf
       import GRPCProtobuf
-      import SwiftProtobuf
 
 
       // MARK: - test.TestService
       // MARK: - test.TestService
 
 

+ 12 - 0
dev/protos/generate.sh

@@ -59,9 +59,21 @@ function generate_bar_service_descriptor_set {
     --include_imports
     --include_imports
 }
 }
 
 
+function generate_wkt_service_descriptor_set {
+  local proto proto_path output
+  proto="$here/local/wkt-service.proto"
+  proto_path="$(dirname "$proto")"
+  output="$root/Tests/GRPCProtobufCodeGenTests/Generated/wkt-service.pb"
+
+  invoke_protoc --descriptor_set_out="$output" "$proto" -I "$proto_path" \
+    --include_source_info \
+    --include_imports
+}
+
 #------------------------------------------------------------------------------
 #------------------------------------------------------------------------------
 
 
 # Descriptor sets
 # Descriptor sets
 generate_test_service_descriptor_set
 generate_test_service_descriptor_set
 generate_foo_service_descriptor_set
 generate_foo_service_descriptor_set
 generate_bar_service_descriptor_set
 generate_bar_service_descriptor_set
+generate_wkt_service_descriptor_set

+ 10 - 0
dev/protos/local/wkt-service.proto

@@ -0,0 +1,10 @@
+// Leading trivia.
+syntax = "proto3";
+
+package test;
+
+import "google/protobuf/any.proto";
+
+service WKTService {
+  rpc Method (google.protobuf.Any) returns (google.protobuf.Any) {}
+}