Pārlūkot izejas kodu

Add explicit access-level modifier support for imports in code generator (#2010)

## Motivation
This is a follow-up of https://github.com/grpc/grpc-swift/pull/2003.
As of 5.9, Swift supports access-level modifiers on imports. In an
upcoming Swift 6.x release, the default modifier will become `internal`.

## Modifications
This PR adds explicit access-level modifiers to the generated code and a
few other modules that use this generated code.

## Result
Explicit access level imports present in more places.
Gustavo Cairo 1 gadu atpakaļ
vecāks
revīzija
3dce993af9
32 mainītis faili ar 253 papildinājumiem un 132 dzēšanām
  1. 14 3
      Package@swift-6.swift
  2. 2 2
      Sources/Examples/v2/Echo/Generated/echo.grpc.swift
  3. 4 4
      Sources/Examples/v2/Echo/Subcommands/Collect.swift
  4. 7 2
      Sources/GRPCCodeGen/CodeGenerationRequest.swift
  5. 6 3
      Sources/GRPCCodeGen/Internal/Renderer/TextBasedRenderer.swift
  6. 7 0
      Sources/GRPCCodeGen/Internal/StructuredSwiftRepresentation.swift
  7. 15 3
      Sources/GRPCCodeGen/Internal/Translator/IDLToStructuredSwiftTranslator.swift
  8. 10 4
      Sources/GRPCProtobufCodeGen/ProtobufCodeGenParser.swift
  9. 2 1
      Sources/GRPCProtobufCodeGen/ProtobufCodeGenerator.swift
  10. 2 2
      Sources/InteroperabilityTests/Generated/empty_service.grpc.swift
  11. 2 2
      Sources/InteroperabilityTests/Generated/test.grpc.swift
  12. 2 2
      Sources/Services/Health/Generated/health.grpc.swift
  13. 1 1
      Sources/Services/Health/Health.swift
  14. 1 1
      Sources/Services/Health/HealthService.swift
  15. 4 4
      Sources/performance-worker/BenchmarkClient.swift
  16. 2 2
      Sources/performance-worker/BenchmarkService.swift
  17. 2 2
      Sources/performance-worker/Generated/grpc_testing_benchmark_service.grpc.swift
  18. 2 2
      Sources/performance-worker/Generated/grpc_testing_worker_service.grpc.swift
  19. 5 5
      Sources/performance-worker/PerformanceWorker.swift
  20. 3 3
      Sources/performance-worker/RPCStats.swift
  21. 33 6
      Tests/GRPCCodeGenTests/Internal/Renderer/TextBasedRendererTests.swift
  22. 83 37
      Tests/GRPCCodeGenTests/Internal/Translator/IDLToStructuredSwiftTranslatorSnippetBasedTests.swift
  23. 1 1
      Tests/GRPCHTTP2TransportTests/ControlService.swift
  24. 2 2
      Tests/GRPCHTTP2TransportTests/Generated/control.grpc.swift
  25. 4 4
      Tests/GRPCHTTP2TransportTests/HTTP2TransportNIOPosixTests.swift
  26. 4 4
      Tests/GRPCHTTP2TransportTests/HTTP2TransportNIOTransportServicesTests.swift
  27. 6 6
      Tests/GRPCHTTP2TransportTests/HTTP2TransportTests.swift
  28. 5 5
      Tests/GRPCHTTP2TransportTests/Test Utilities/HTTP2StatusCodeServer.swift
  29. 2 2
      Tests/GRPCHTTP2TransportTests/Test Utilities/XCTest+Utilities.swift
  30. 2 2
      Tests/GRPCHTTP2TransportTests/XCTestCase+Vsock.swift
  31. 6 3
      Tests/GRPCProtobufCodeGenTests/ProtobufCodeGenParserTests.swift
  32. 12 12
      Tests/GRPCProtobufCodeGenTests/ProtobufCodeGeneratorTests.swift

+ 14 - 3
Package@swift-6.swift

@@ -340,7 +340,11 @@ extension Target {
         .nioFileSystem,
         .argumentParser
       ],
-      swiftSettings: [.swiftLanguageMode(.v6), .enableUpcomingFeature("ExistentialAny")]
+      swiftSettings: [
+        .swiftLanguageMode(.v6),
+        .enableUpcomingFeature("ExistentialAny"),
+        .enableUpcomingFeature("InternalImportsByDefault")
+      ]
     )
   }
 
@@ -538,7 +542,10 @@ extension Target {
         .grpcCore,
         .grpcProtobuf
       ],
-      swiftSettings: [.swiftLanguageMode(.v6), .enableUpcomingFeature("ExistentialAny")]
+      swiftSettings: [
+        .swiftLanguageMode(.v6),
+        .enableUpcomingFeature("ExistentialAny")
+      ]
     )
   }
 
@@ -694,7 +701,11 @@ extension Target {
         .nioSSL, if: includeNIOSSL
       ),
       path: "Sources/Examples/v2/Echo",
-      swiftSettings: [.swiftLanguageMode(.v6), .enableUpcomingFeature("ExistentialAny")]
+      swiftSettings: [
+        .swiftLanguageMode(.v6),
+        .enableUpcomingFeature("ExistentialAny"),
+        .enableUpcomingFeature("InternalImportsByDefault")
+      ]
     )
   }
 

+ 2 - 2
Sources/Examples/v2/Echo/Generated/echo.grpc.swift

@@ -21,8 +21,8 @@
 // For information on using the generated types, please see the documentation:
 //   https://github.com/grpc/grpc-swift
 
-import GRPCCore
-import GRPCProtobuf
+internal import GRPCCore
+internal import GRPCProtobuf
 
 internal enum Echo_Echo {
     internal static let descriptor = ServiceDescriptor.echo_Echo

+ 4 - 4
Sources/Examples/v2/Echo/Subcommands/Collect.swift

@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-import ArgumentParser
-import GRPCCore
-import GRPCHTTP2Core
-import GRPCHTTP2TransportNIOPosix
+internal import ArgumentParser
+private import GRPCCore
+private import GRPCHTTP2Core
+private import GRPCHTTP2TransportNIOPosix
 
 @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
 struct Collect: AsyncParsableCommand {

+ 7 - 2
Sources/GRPCCodeGen/CodeGenerationRequest.swift

@@ -84,7 +84,10 @@ public struct CodeGenerationRequest {
   public struct Dependency: Equatable {
     /// If the dependency is an item, the property's value is the item representation.
     /// If the dependency is a module, this property is nil.
-    public var item: Item? = nil
+    public var item: Item?
+
+    /// The access level to be included in imports of this dependency.
+    public var accessLevel: SourceGenerator.Configuration.AccessLevel
 
     /// The name of the imported module or of the module an item is imported from.
     public var module: String
@@ -102,12 +105,14 @@ public struct CodeGenerationRequest {
       item: Item? = nil,
       module: String,
       spi: String? = nil,
-      preconcurrency: PreconcurrencyRequirement = .notRequired
+      preconcurrency: PreconcurrencyRequirement = .notRequired,
+      accessLevel: SourceGenerator.Configuration.AccessLevel
     ) {
       self.item = item
       self.module = module
       self.spi = spi
       self.preconcurrency = preconcurrency
+      self.accessLevel = accessLevel
     }
 
     /// Represents an item imported from a module.

+ 6 - 3
Sources/GRPCCodeGen/Internal/Renderer/TextBasedRenderer.swift

@@ -198,17 +198,20 @@ struct TextBasedRenderer: RendererProtocol {
     func render(preconcurrency: Bool) {
       let spiPrefix = description.spi.map { "@_spi(\($0)) " } ?? ""
       let preconcurrencyPrefix = preconcurrency ? "@preconcurrency " : ""
+      let accessLevel = description.accessLevel.map { "\($0) " } ?? ""
 
       if let item = description.item {
         writer.writeLine(
-          "\(preconcurrencyPrefix)\(spiPrefix)import \(item.kind) \(description.moduleName).\(item.name)"
+          "\(preconcurrencyPrefix)\(spiPrefix)\(accessLevel)import \(item.kind) \(description.moduleName).\(item.name)"
         )
       } else if let moduleTypes = description.moduleTypes {
         for type in moduleTypes {
-          writer.writeLine("\(preconcurrencyPrefix)\(spiPrefix)import \(type)")
+          writer.writeLine("\(preconcurrencyPrefix)\(spiPrefix)\(accessLevel)import \(type)")
         }
       } else {
-        writer.writeLine("\(preconcurrencyPrefix)\(spiPrefix)import \(description.moduleName)")
+        writer.writeLine(
+          "\(preconcurrencyPrefix)\(spiPrefix)\(accessLevel)import \(description.moduleName)"
+        )
       }
     }
 

+ 7 - 0
Sources/GRPCCodeGen/Internal/StructuredSwiftRepresentation.swift

@@ -31,6 +31,13 @@
 ///
 /// For example: `import Foo`.
 struct ImportDescription: Equatable, Codable {
+  /// The access level of the imported module.
+  ///
+  /// For example, the `public` in `public import Foo`.
+  ///
+  /// - Note: This is optional, as explicit access-level modifiers are not required on `import` statements.
+  var accessLevel: AccessModifier? = nil
+
   /// The name of the imported module.
   ///
   /// For example, the `Foo` in `import Foo`.

+ 15 - 3
Sources/GRPCCodeGen/Internal/Translator/IDLToStructuredSwiftTranslator.swift

@@ -30,10 +30,9 @@ struct IDLToStructuredSwiftTranslator: Translator {
       server: server,
       accessLevel: accessLevel
     )
-
     let topComment = Comment.preFormatted(codeGenerationRequest.leadingTrivia)
     let imports = try codeGenerationRequest.dependencies.reduce(
-      into: [ImportDescription(moduleName: "GRPCCore")]
+      into: [ImportDescription(accessLevel: AccessModifier(accessLevel), moduleName: "GRPCCore")]
     ) { partialResult, newDependency in
       try partialResult.append(translateImport(dependency: newDependency))
     }
@@ -68,11 +67,24 @@ struct IDLToStructuredSwiftTranslator: Translator {
   }
 }
 
+extension AccessModifier {
+  fileprivate init(_ accessLevel: SourceGenerator.Configuration.AccessLevel) {
+    switch accessLevel.level {
+    case .internal: self = .internal
+    case .package: self = .package
+    case .public: self = .public
+    }
+  }
+}
+
 extension IDLToStructuredSwiftTranslator {
   private func translateImport(
     dependency: CodeGenerationRequest.Dependency
   ) throws -> ImportDescription {
-    var importDescription = ImportDescription(moduleName: dependency.module)
+    var importDescription = ImportDescription(
+      accessLevel: AccessModifier(dependency.accessLevel),
+      moduleName: dependency.module
+    )
     if let item = dependency.item {
       if let matchedKind = ImportDescription.Kind(rawValue: item.kind.value.rawValue) {
         importDescription.item = ImportDescription.Item(kind: matchedKind, name: item.name)

+ 10 - 4
Sources/GRPCProtobufCodeGen/ProtobufCodeGenParser.swift

@@ -19,6 +19,7 @@ internal import SwiftProtobuf
 internal import SwiftProtobufPluginLibrary
 
 internal import struct GRPCCodeGen.CodeGenerationRequest
+internal import struct GRPCCodeGen.SourceGenerator
 
 /// Parses a ``FileDescriptor`` object into a ``CodeGenerationRequest`` object.
 internal struct ProtobufCodeGenParser {
@@ -26,11 +27,13 @@ internal struct ProtobufCodeGenParser {
   let namer: SwiftProtobufNamer
   let extraModuleImports: [String]
   let protoToModuleMappings: ProtoFileToModuleMappings
+  let accessLevel: SourceGenerator.Configuration.AccessLevel
 
   internal init(
     input: FileDescriptor,
     protoFileModuleMappings: ProtoFileToModuleMappings,
-    extraModuleImports: [String]
+    extraModuleImports: [String],
+    accessLevel: SourceGenerator.Configuration.AccessLevel
   ) {
     self.input = input
     self.extraModuleImports = extraModuleImports
@@ -39,6 +42,7 @@ internal struct ProtobufCodeGenParser {
       currentFile: input,
       protoFileToModuleMappings: protoFileModuleMappings
     )
+    self.accessLevel = accessLevel
   }
 
   internal func parse() throws -> CodeGenerationRequest {
@@ -86,18 +90,20 @@ internal struct ProtobufCodeGenParser {
 
 extension ProtobufCodeGenParser {
   fileprivate var codeDependencies: [CodeGenerationRequest.Dependency] {
-    var codeDependencies: [CodeGenerationRequest.Dependency] = [.init(module: "GRPCProtobuf")]
+    var codeDependencies: [CodeGenerationRequest.Dependency] = [
+      .init(module: "GRPCProtobuf", accessLevel: .internal)
+    ]
     // Adding as dependencies the modules containing generated code or types for
     // '.proto' files imported in the '.proto' file we are parsing.
     codeDependencies.append(
       contentsOf: (self.protoToModuleMappings.neededModules(forFile: self.input) ?? []).map {
-        CodeGenerationRequest.Dependency(module: $0)
+        CodeGenerationRequest.Dependency(module: $0, accessLevel: self.accessLevel)
       }
     )
     // Adding extra imports passed in as an option to the plugin.
     codeDependencies.append(
       contentsOf: self.extraModuleImports.sorted().map {
-        CodeGenerationRequest.Dependency(module: $0)
+        CodeGenerationRequest.Dependency(module: $0, accessLevel: self.accessLevel)
       }
     )
     return codeDependencies

+ 2 - 1
Sources/GRPCProtobufCodeGen/ProtobufCodeGenerator.swift

@@ -34,7 +34,8 @@ public struct ProtobufCodeGenerator {
     let parser = ProtobufCodeGenParser(
       input: fileDescriptor,
       protoFileModuleMappings: protoFileModuleMappings,
-      extraModuleImports: extraModuleImports
+      extraModuleImports: extraModuleImports,
+      accessLevel: self.configuration.accessLevel
     )
     let sourceGenerator = SourceGenerator(configuration: self.configuration)
 

+ 2 - 2
Sources/InteroperabilityTests/Generated/empty_service.grpc.swift

@@ -21,8 +21,8 @@
 // For information on using the generated types, please see the documentation:
 //   https://github.com/grpc/grpc-swift
 
-import GRPCCore
-import GRPCProtobuf
+public import GRPCCore
+internal import GRPCProtobuf
 
 public enum Grpc_Testing_EmptyService {
     public static let descriptor = ServiceDescriptor.grpc_testing_EmptyService

+ 2 - 2
Sources/InteroperabilityTests/Generated/test.grpc.swift

@@ -24,8 +24,8 @@
 // For information on using the generated types, please see the documentation:
 //   https://github.com/grpc/grpc-swift
 
-import GRPCCore
-import GRPCProtobuf
+public import GRPCCore
+internal import GRPCProtobuf
 
 public enum Grpc_Testing_ReconnectService {
     public static let descriptor = ServiceDescriptor.grpc_testing_ReconnectService

+ 2 - 2
Sources/Services/Health/Generated/health.grpc.swift

@@ -24,8 +24,8 @@
 // For information on using the generated types, please see the documentation:
 //   https://github.com/grpc/grpc-swift
 
-import GRPCCore
-import GRPCProtobuf
+package import GRPCCore
+internal import GRPCProtobuf
 
 package enum Grpc_Health_V1_Health {
     package static let descriptor = ServiceDescriptor.grpc_health_v1_Health

+ 1 - 1
Sources/Services/Health/Health.swift

@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-import GRPCCore
+public import GRPCCore
 
 /// ``Health`` is gRPC’s mechanism for checking whether a server is able to handle RPCs. Its semantics are documented in
 /// https://github.com/grpc/grpc/blob/master/doc/health-checking.md.

+ 1 - 1
Sources/Services/Health/HealthService.swift

@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-import GRPCCore
+internal import GRPCCore
 
 @available(macOS 15.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
 internal struct HealthService: Grpc_Health_V1_HealthServiceProtocol {

+ 4 - 4
Sources/performance-worker/BenchmarkClient.swift

@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-import Atomics
-import Foundation
-import GRPCCore
-import NIOConcurrencyHelpers
+private import Atomics
+private import Foundation
+internal import GRPCCore
+private import NIOConcurrencyHelpers
 
 @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
 struct BenchmarkClient {

+ 2 - 2
Sources/performance-worker/BenchmarkService.swift

@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-import Atomics
-import GRPCCore
+private import Atomics
+internal import GRPCCore
 
 import struct Foundation.Data
 

+ 2 - 2
Sources/performance-worker/Generated/grpc_testing_benchmark_service.grpc.swift

@@ -24,8 +24,8 @@
 // For information on using the generated types, please see the documentation:
 //   https://github.com/grpc/grpc-swift
 
-import GRPCCore
-import GRPCProtobuf
+internal import GRPCCore
+internal import GRPCProtobuf
 
 internal enum Grpc_Testing_BenchmarkService {
     internal static let descriptor = ServiceDescriptor.grpc_testing_BenchmarkService

+ 2 - 2
Sources/performance-worker/Generated/grpc_testing_worker_service.grpc.swift

@@ -24,8 +24,8 @@
 // For information on using the generated types, please see the documentation:
 //   https://github.com/grpc/grpc-swift
 
-import GRPCCore
-import GRPCProtobuf
+internal import GRPCCore
+internal import GRPCProtobuf
 
 internal enum Grpc_Testing_WorkerService {
     internal static let descriptor = ServiceDescriptor.grpc_testing_WorkerService

+ 5 - 5
Sources/performance-worker/PerformanceWorker.swift

@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-import ArgumentParser
-import GRPCCore
-import GRPCHTTP2Core
-import GRPCHTTP2TransportNIOPosix
-import NIOPosix
+internal import ArgumentParser
+private import GRPCCore
+private import GRPCHTTP2Core
+private import GRPCHTTP2TransportNIOPosix
+private import NIOPosix
 
 @main
 @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)

+ 3 - 3
Sources/performance-worker/RPCStats.swift

@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-import Foundation
-import GRPCCore
-import NIOConcurrencyHelpers
+private import Foundation
+internal import GRPCCore
+internal import NIOConcurrencyHelpers
 
 /// Stores the real time latency histogram and error code count dictionary,
 /// for the RPCs made by a particular GRPCClient. It gets updated after

+ 33 - 6
Tests/GRPCCodeGenTests/Internal/Renderer/TextBasedRendererTests.swift

@@ -110,11 +110,24 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testImports() throws {
     try _test(nil, renderedBy: { $0.renderImports(_:) }, rendersAs: "")
     try _test(
-      [ImportDescription(moduleName: "Foo"), ImportDescription(moduleName: "Bar")],
+      [
+        ImportDescription(moduleName: "Foo"),
+        ImportDescription(moduleName: "Bar"),
+        ImportDescription(accessLevel: .fileprivate, moduleName: "BazFileprivate"),
+        ImportDescription(accessLevel: .private, moduleName: "BazPrivate"),
+        ImportDescription(accessLevel: .internal, moduleName: "BazInternal"),
+        ImportDescription(accessLevel: .package, moduleName: "BazPackage"),
+        ImportDescription(accessLevel: .public, moduleName: "BazPublic"),
+      ],
       renderedBy: { $0.renderImports(_:) },
       rendersAs: #"""
         import Foo
         import Bar
+        fileprivate import BazFileprivate
+        private import BazPrivate
+        internal import BazInternal
+        package import BazPackage
+        public import BazPublic
         """#
     )
     try _test(
@@ -125,7 +138,12 @@ final class Test_TextBasedRenderer: XCTestCase {
         """#
     )
     try _test(
-      [ImportDescription(moduleName: "Foo", preconcurrency: .onOS(["Bar", "Baz"]))],
+      [
+        ImportDescription(
+          moduleName: "Foo",
+          preconcurrency: .onOS(["Bar", "Baz"])
+        )
+      ],
       renderedBy: { $0.renderImports(_:) },
       rendersAs: #"""
         #if os(Bar) || os(Baz)
@@ -138,7 +156,11 @@ final class Test_TextBasedRenderer: XCTestCase {
     try _test(
       [
         ImportDescription(moduleName: "Foo", preconcurrency: .always),
-        ImportDescription(moduleName: "Bar", spi: "Secret", preconcurrency: .always),
+        ImportDescription(
+          moduleName: "Bar",
+          spi: "Secret",
+          preconcurrency: .always
+        ),
       ],
       renderedBy: { $0.renderImports(_:) },
       rendersAs: #"""
@@ -169,8 +191,14 @@ final class Test_TextBasedRenderer: XCTestCase {
           moduleName: "Foo",
           item: ImportDescription.Item(kind: .protocol, name: "Bat")
         ),
-        ImportDescription(moduleName: "Foo", item: ImportDescription.Item(kind: .let, name: "Bam")),
-        ImportDescription(moduleName: "Foo", item: ImportDescription.Item(kind: .var, name: "Bag")),
+        ImportDescription(
+          moduleName: "Foo",
+          item: ImportDescription.Item(kind: .let, name: "Bam")
+        ),
+        ImportDescription(
+          moduleName: "Foo",
+          item: ImportDescription.Item(kind: .var, name: "Bag")
+        ),
         ImportDescription(
           moduleName: "Foo",
           item: ImportDescription.Item(kind: .func, name: "Bak")
@@ -952,7 +980,6 @@ final class Test_TextBasedRenderer: XCTestCase {
 }
 
 extension Test_TextBasedRenderer {
-
   func _test<Input>(
     _ input: Input,
     renderedBy renderClosure: (TextBasedRenderer) -> ((Input) -> String),

+ 83 - 37
Tests/GRPCCodeGenTests/Internal/Translator/IDLToStructuredSwiftTranslatorSnippetBasedTests.swift

@@ -27,46 +27,78 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase {
 
   func testImports() throws {
     var dependencies = [CodeGenerationRequest.Dependency]()
-    dependencies.append(CodeGenerationRequest.Dependency(module: "Foo"))
+    dependencies.append(CodeGenerationRequest.Dependency(module: "Foo", accessLevel: .public))
     dependencies.append(
-      CodeGenerationRequest.Dependency(item: .init(kind: .typealias, name: "Bar"), module: "Foo")
+      CodeGenerationRequest.Dependency(
+        item: .init(kind: .typealias, name: "Bar"),
+        module: "Foo",
+        accessLevel: .internal
+      )
     )
     dependencies.append(
-      CodeGenerationRequest.Dependency(item: .init(kind: .struct, name: "Baz"), module: "Foo")
+      CodeGenerationRequest.Dependency(
+        item: .init(kind: .struct, name: "Baz"),
+        module: "Foo",
+        accessLevel: .package
+      )
     )
     dependencies.append(
-      CodeGenerationRequest.Dependency(item: .init(kind: .class, name: "Bac"), module: "Foo")
+      CodeGenerationRequest.Dependency(
+        item: .init(kind: .class, name: "Bac"),
+        module: "Foo",
+        accessLevel: .package
+      )
     )
     dependencies.append(
-      CodeGenerationRequest.Dependency(item: .init(kind: .enum, name: "Bap"), module: "Foo")
+      CodeGenerationRequest.Dependency(
+        item: .init(kind: .enum, name: "Bap"),
+        module: "Foo",
+        accessLevel: .package
+      )
     )
     dependencies.append(
-      CodeGenerationRequest.Dependency(item: .init(kind: .protocol, name: "Bat"), module: "Foo")
+      CodeGenerationRequest.Dependency(
+        item: .init(kind: .protocol, name: "Bat"),
+        module: "Foo",
+        accessLevel: .package
+      )
     )
     dependencies.append(
-      CodeGenerationRequest.Dependency(item: .init(kind: .let, name: "Baq"), module: "Foo")
+      CodeGenerationRequest.Dependency(
+        item: .init(kind: .let, name: "Baq"),
+        module: "Foo",
+        accessLevel: .package
+      )
     )
     dependencies.append(
-      CodeGenerationRequest.Dependency(item: .init(kind: .var, name: "Bag"), module: "Foo")
+      CodeGenerationRequest.Dependency(
+        item: .init(kind: .var, name: "Bag"),
+        module: "Foo",
+        accessLevel: .package
+      )
     )
     dependencies.append(
-      CodeGenerationRequest.Dependency(item: .init(kind: .func, name: "Bak"), module: "Foo")
+      CodeGenerationRequest.Dependency(
+        item: .init(kind: .func, name: "Bak"),
+        module: "Foo",
+        accessLevel: .package
+      )
     )
 
     let expectedSwift =
       """
       /// Some really exciting license header 2023.
 
-      import GRPCCore
-      import Foo
-      import typealias Foo.Bar
-      import struct Foo.Baz
-      import class Foo.Bac
-      import enum Foo.Bap
-      import protocol Foo.Bat
-      import let Foo.Baq
-      import var Foo.Bag
-      import func Foo.Bak
+      public import GRPCCore
+      public import Foo
+      internal import typealias Foo.Bar
+      package import struct Foo.Baz
+      package import class Foo.Bac
+      package import enum Foo.Bap
+      package import protocol Foo.Bat
+      package import let Foo.Baq
+      package import var Foo.Bag
+      package import func Foo.Bak
 
       """
     try self.assertIDLToStructuredSwiftTranslation(
@@ -78,31 +110,39 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase {
 
   func testPreconcurrencyImports() throws {
     var dependencies = [CodeGenerationRequest.Dependency]()
-    dependencies.append(CodeGenerationRequest.Dependency(module: "Foo", preconcurrency: .required))
+    dependencies.append(
+      CodeGenerationRequest.Dependency(
+        module: "Foo",
+        preconcurrency: .required,
+        accessLevel: .internal
+      )
+    )
     dependencies.append(
       CodeGenerationRequest.Dependency(
         item: .init(kind: .enum, name: "Bar"),
         module: "Foo",
-        preconcurrency: .required
+        preconcurrency: .required,
+        accessLevel: .internal
       )
     )
     dependencies.append(
       CodeGenerationRequest.Dependency(
         module: "Baz",
-        preconcurrency: .requiredOnOS(["Deq", "Der"])
+        preconcurrency: .requiredOnOS(["Deq", "Der"]),
+        accessLevel: .internal
       )
     )
     let expectedSwift =
       """
       /// Some really exciting license header 2023.
 
-      import GRPCCore
-      @preconcurrency import Foo
-      @preconcurrency import enum Foo.Bar
+      public import GRPCCore
+      @preconcurrency internal import Foo
+      @preconcurrency internal import enum Foo.Bar
       #if os(Deq) || os(Der)
-      @preconcurrency import Baz
+      @preconcurrency internal import Baz
       #else
-      import Baz
+      internal import Baz
       #endif
 
       """
@@ -115,12 +155,15 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase {
 
   func testSPIImports() throws {
     var dependencies = [CodeGenerationRequest.Dependency]()
-    dependencies.append(CodeGenerationRequest.Dependency(module: "Foo", spi: "Secret"))
+    dependencies.append(
+      CodeGenerationRequest.Dependency(module: "Foo", spi: "Secret", accessLevel: .internal)
+    )
     dependencies.append(
       CodeGenerationRequest.Dependency(
         item: .init(kind: .enum, name: "Bar"),
         module: "Foo",
-        spi: "Secret"
+        spi: "Secret",
+        accessLevel: .internal
       )
     )
 
@@ -128,9 +171,9 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase {
       """
       /// Some really exciting license header 2023.
 
-      import GRPCCore
-      @_spi(Secret) import Foo
-      @_spi(Secret) import enum Foo.Bar
+      public import GRPCCore
+      @_spi(Secret) internal import Foo
+      @_spi(Secret) internal import enum Foo.Bar
 
       """
     try self.assertIDLToStructuredSwiftTranslation(
@@ -142,12 +185,15 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase {
 
   func testGeneration() throws {
     var dependencies = [CodeGenerationRequest.Dependency]()
-    dependencies.append(CodeGenerationRequest.Dependency(module: "Foo", spi: "Secret"))
+    dependencies.append(
+      CodeGenerationRequest.Dependency(module: "Foo", spi: "Secret", accessLevel: .internal)
+    )
     dependencies.append(
       CodeGenerationRequest.Dependency(
         item: .init(kind: .enum, name: "Bar"),
         module: "Foo",
-        spi: "Secret"
+        spi: "Secret",
+        accessLevel: .internal
       )
     )
 
@@ -166,9 +212,9 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase {
       """
       /// Some really exciting license header 2023.
 
-      import GRPCCore
-      @_spi(Secret) import Foo
-      @_spi(Secret) import enum Foo.Bar
+      public import GRPCCore
+      @_spi(Secret) internal import Foo
+      @_spi(Secret) internal import enum Foo.Bar
 
       public enum NamespaceA_ServiceA {
           public static let descriptor = ServiceDescriptor.namespaceA_ServiceA

+ 1 - 1
Tests/GRPCHTTP2TransportTests/ControlService.swift

@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-import GRPCCore
+internal import GRPCCore
 
 import struct Foundation.Data
 

+ 2 - 2
Tests/GRPCHTTP2TransportTests/Generated/control.grpc.swift

@@ -22,8 +22,8 @@
 // For information on using the generated types, please see the documentation:
 //   https://github.com/grpc/grpc-swift
 
-import GRPCCore
-import GRPCProtobuf
+internal import GRPCCore
+internal import GRPCProtobuf
 
 internal enum Control {
     internal static let descriptor = ServiceDescriptor.Control

+ 4 - 4
Tests/GRPCHTTP2TransportTests/HTTP2TransportNIOPosixTests.swift

@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-import GRPCCore
-import GRPCHTTP2Core
-import GRPCHTTP2TransportNIOPosix
-import XCTest
+private import GRPCCore
+private import GRPCHTTP2Core
+private import GRPCHTTP2TransportNIOPosix
+internal import XCTest
 
 @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
 final class HTTP2TransportNIOPosixTests: XCTestCase {

+ 4 - 4
Tests/GRPCHTTP2TransportTests/HTTP2TransportNIOTransportServicesTests.swift

@@ -15,10 +15,10 @@
  */
 
 #if canImport(Network)
-import GRPCCore
-import GRPCHTTP2Core
-import GRPCHTTP2TransportNIOTransportServices
-import XCTest
+private import GRPCCore
+private import GRPCHTTP2Core
+internal import GRPCHTTP2TransportNIOTransportServices
+internal import XCTest
 
 @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
 final class HTTP2TransportNIOTransportServicesTests: XCTestCase {

+ 6 - 6
Tests/GRPCHTTP2TransportTests/HTTP2TransportTests.swift

@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-import GRPCCore
-import GRPCHTTP2Core
-import GRPCHTTP2TransportNIOPosix
-import GRPCHTTP2TransportNIOTransportServices
-import GRPCProtobuf
-import XCTest
+internal import GRPCCore
+private import GRPCHTTP2Core
+private import GRPCHTTP2TransportNIOPosix
+private import GRPCHTTP2TransportNIOTransportServices
+private import GRPCProtobuf
+internal import XCTest
 
 @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
 final class HTTP2TransportTests: XCTestCase {

+ 5 - 5
Tests/GRPCHTTP2TransportTests/Test Utilities/HTTP2StatusCodeServer.swift

@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-import GRPCHTTP2Core
-import NIOCore
-import NIOHPACK
-import NIOHTTP2
-import NIOPosix
+internal import GRPCHTTP2Core
+private import NIOCore
+private import NIOHPACK
+private import NIOHTTP2
+private import NIOPosix
 
 /// An HTTP/2 test server which only responds to request headers by sending response headers and
 /// then closing. Each stream will be closed with the ":status" set to the value of the

+ 2 - 2
Tests/GRPCHTTP2TransportTests/Test Utilities/XCTest+Utilities.swift

@@ -13,8 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import GRPCCore
-import XCTest
+
+private import XCTest
 
 func XCTAssertThrowsError<T, E: Error>(
   ofType: E.Type,

+ 2 - 2
Tests/GRPCHTTP2TransportTests/XCTestCase+Vsock.swift

@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-import NIOPosix
-import XCTest
+private import NIOPosix
+internal import XCTest
 
 extension XCTestCase {
   func vsockAvailable() -> Bool {

+ 6 - 3
Tests/GRPCProtobufCodeGenTests/ProtobufCodeGenParserTests.swift

@@ -55,7 +55,8 @@ final class ProtobufCodeGenParserTests: XCTestCase {
     let parsedCodeGenRequest = try ProtobufCodeGenParser(
       input: fileDescriptor,
       protoFileModuleMappings: ProtoFileToModuleMappings(moduleMappingsProto: moduleMappings),
-      extraModuleImports: ["ExtraModule"]
+      extraModuleImports: ["ExtraModule"],
+      accessLevel: .internal
     ).parse()
 
     self.testCommonHelloworldParsedRequestFields(for: parsedCodeGenRequest)
@@ -136,7 +137,8 @@ final class ProtobufCodeGenParserTests: XCTestCase {
     let parsedCodeGenRequest = try ProtobufCodeGenParser(
       input: fileDescriptor,
       protoFileModuleMappings: ProtoFileToModuleMappings(moduleMappingsProto: moduleMappings),
-      extraModuleImports: ["ExtraModule"]
+      extraModuleImports: ["ExtraModule"],
+      accessLevel: .internal
     ).parse()
 
     self.testCommonHelloworldParsedRequestFields(for: parsedCodeGenRequest)
@@ -217,7 +219,8 @@ final class ProtobufCodeGenParserTests: XCTestCase {
     let parsedCodeGenRequest = try ProtobufCodeGenParser(
       input: fileDescriptor,
       protoFileModuleMappings: ProtoFileToModuleMappings(moduleMappingsProto: moduleMappings),
-      extraModuleImports: ["ExtraModule"]
+      extraModuleImports: ["ExtraModule"],
+      accessLevel: .internal
     ).parse()
 
     self.testCommonHelloworldParsedRequestFields(for: parsedCodeGenRequest)

+ 12 - 12
Tests/GRPCProtobufCodeGenTests/ProtobufCodeGeneratorTests.swift

@@ -54,10 +54,10 @@ final class ProtobufCodeGeneratorTests: XCTestCase {
         // For information on using the generated types, please see the documentation:
         //   https://github.com/grpc/grpc-swift
 
-        import GRPCCore
-        import GRPCProtobuf
-        import DifferentModule
-        import ExtraModule
+        internal import GRPCCore
+        internal import GRPCProtobuf
+        internal import DifferentModule
+        internal import ExtraModule
 
         internal enum Hello_World_Greeter {
             internal static let descriptor = ServiceDescriptor.hello_world_Greeter
@@ -204,10 +204,10 @@ final class ProtobufCodeGeneratorTests: XCTestCase {
         // For information on using the generated types, please see the documentation:
         //   https://github.com/grpc/grpc-swift
 
-        import GRPCCore
-        import GRPCProtobuf
-        import DifferentModule
-        import ExtraModule
+        public import GRPCCore
+        internal import GRPCProtobuf
+        public import DifferentModule
+        public import ExtraModule
 
         public enum Helloworld_Greeter {
           public static let descriptor = ServiceDescriptor.helloworld_Greeter
@@ -307,10 +307,10 @@ final class ProtobufCodeGeneratorTests: XCTestCase {
         // For information on using the generated types, please see the documentation:
         //   https://github.com/grpc/grpc-swift
 
-        import GRPCCore
-        import GRPCProtobuf
-        import DifferentModule
-        import ExtraModule
+        package import GRPCCore
+        internal import GRPCProtobuf
+        package import DifferentModule
+        package import ExtraModule
 
         package enum Greeter {
           package static let descriptor = ServiceDescriptor.Greeter