diff --git a/Sources/GRPCCodeGen/CodeGenerator.swift b/Sources/GRPCCodeGen/CodeGenerator.swift index 25d17a6cf..07ffd9848 100644 --- a/Sources/GRPCCodeGen/CodeGenerator.swift +++ b/Sources/GRPCCodeGen/CodeGenerator.swift @@ -42,6 +42,8 @@ public struct CodeGenerator: Sendable { public var server: Bool /// The name of the core gRPC module. public var grpcCoreModuleName: String + /// The availability annotations to use on the generated code. + public var availability: AvailabilityAnnotations = .default /// Creates a new configuration. /// @@ -84,6 +86,50 @@ public struct CodeGenerator: Sendable { /// The generated code will have `package` access level. public static var `package`: Self { Self(level: .`package`) } } + + // The availability that generated code is annotated with. + public struct AvailabilityAnnotations: Sendable, Hashable { + public struct Platform: Sendable, Hashable { + /// The name of the OS, e.g. 'macOS'. + public var os: String + /// The version of the OS, e.g. '15.0'. + public var version: String + + public init(os: String, version: String) { + self.os = os + self.version = version + } + } + + fileprivate enum Wrapped: Sendable, Hashable { + case macOS15Aligned + case custom([Platform]) + } + + fileprivate var wrapped: Wrapped + + private init(_ wrapped: Wrapped) { + self.wrapped = wrapped + } + + /// Use the default availability. + /// + /// The default platform availability is: + /// - macOS 15.0 + /// - iOS 18.0 + /// - tvOS 18.0 + /// - watchOS 11.0 + /// - visionOS 2.0 + public static var `default`: Self { + Self(.macOS15Aligned) + } + + /// Use a custom set of availability attributes. + /// - Parameter platforms: Availability requirements. + public static func custom(_ platforms: [Platform]) -> Self { + Self(.custom(platforms)) + } + } } /// Transforms a ``CodeGenerationRequest`` object into a ``SourceFile`` object containing @@ -100,7 +146,8 @@ public struct CodeGenerator: Sendable { accessLevelOnImports: self.config.accessLevelOnImports, client: self.config.client, server: self.config.server, - grpcCoreModuleName: self.config.grpcCoreModuleName + grpcCoreModuleName: self.config.grpcCoreModuleName, + availability: AvailabilityDescription(self.config.availability) ) let sourceFile = try textRenderer.render(structured: structuredSwiftRepresentation) @@ -108,3 +155,16 @@ public struct CodeGenerator: Sendable { return sourceFile } } + +extension AvailabilityDescription { + init(_ availability: CodeGenerator.Config.AvailabilityAnnotations) throws { + switch availability.wrapped { + case .macOS15Aligned: + self = .macOS15Aligned + case .custom(let platforms): + self.osVersions = platforms.map { + .init(os: .init(name: $0.os), version: $0.version) + } + } + } +} diff --git a/Sources/GRPCCodeGen/Internal/Renderer/TextBasedRenderer.swift b/Sources/GRPCCodeGen/Internal/Renderer/TextBasedRenderer.swift index e1fac9546..e4cb173af 100644 --- a/Sources/GRPCCodeGen/Internal/Renderer/TextBasedRenderer.swift +++ b/Sources/GRPCCodeGen/Internal/Renderer/TextBasedRenderer.swift @@ -877,6 +877,8 @@ struct TextBasedRenderer: RendererProtocol { renderCommentableDeclaration(comment: comment, declaration: nestedDeclaration) case let .deprecated(deprecation, nestedDeclaration): renderDeprecatedDeclaration(deprecation: deprecation, declaration: nestedDeclaration) + case let .guarded(availability, nestedDeclaration): + renderGuardedDeclaration(availability: availability, declaration: nestedDeclaration) case .variable(let variableDescription): renderVariable(variableDescription) case .extension(let extensionDescription): renderExtension(extensionDescription) case .struct(let structDescription): renderStruct(structDescription) diff --git a/Sources/GRPCCodeGen/Internal/StructuredSwift+ServiceMetadata.swift b/Sources/GRPCCodeGen/Internal/StructuredSwift+ServiceMetadata.swift index dd51eb496..7e06ec07a 100644 --- a/Sources/GRPCCodeGen/Internal/StructuredSwift+ServiceMetadata.swift +++ b/Sources/GRPCCodeGen/Internal/StructuredSwift+ServiceMetadata.swift @@ -14,6 +14,18 @@ * limitations under the License. */ +extension AvailabilityDescription { + package static let macOS15Aligned = AvailabilityDescription( + osVersions: [ + OSVersion(os: .macOS, version: "15.0"), + OSVersion(os: .iOS, version: "18.0"), + OSVersion(os: .watchOS, version: "11.0"), + OSVersion(os: .tvOS, version: "18.0"), + OSVersion(os: .visionOS, version: "2.0"), + ] + ) +} + extension TypealiasDescription { /// `typealias Input = ` package static func methodInput( @@ -341,6 +353,7 @@ extension [CodeBlock] { package static func serviceMetadata( accessModifier: AccessModifier? = nil, service: ServiceDescriptor, + availability: AvailabilityDescription, namer: Namer = Namer() ) -> Self { var blocks: [CodeBlock] = [] @@ -357,7 +370,7 @@ extension [CodeBlock] { comment: .doc( "Namespace containing generated types for the \"\(service.name.identifyingName)\" service." ), - item: .declaration(.enum(serviceNamespace)) + item: .declaration(.guarded(availability, .enum(serviceNamespace))) ) ) @@ -367,7 +380,9 @@ extension [CodeBlock] { literalFullyQualifiedService: service.name.identifyingName, namer: namer ) - blocks.append(CodeBlock(item: .declaration(.extension(descriptorExtension)))) + blocks.append( + CodeBlock(item: .declaration(.guarded(availability, .extension(descriptorExtension)))) + ) return blocks } diff --git a/Sources/GRPCCodeGen/Internal/StructuredSwiftRepresentation.swift b/Sources/GRPCCodeGen/Internal/StructuredSwiftRepresentation.swift index 8db1cca87..52ad2ffae 100644 --- a/Sources/GRPCCodeGen/Internal/StructuredSwiftRepresentation.swift +++ b/Sources/GRPCCodeGen/Internal/StructuredSwiftRepresentation.swift @@ -797,6 +797,9 @@ indirect enum Declaration: Equatable, Codable, Sendable { /// A declaration that adds a comment on top of the provided declaration. case deprecated(DeprecationDescription, Declaration) + /// A declaration that adds an availability guard on top of the provided declaration. + case guarded(AvailabilityDescription, Declaration) + /// A variable declaration. case variable(VariableDescription) @@ -837,18 +840,18 @@ struct DeprecationDescription: Equatable, Codable, Sendable { /// A description of an availability guard. /// /// For example: `@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)` -struct AvailabilityDescription: Equatable, Codable, Sendable { +package struct AvailabilityDescription: Equatable, Codable, Sendable { /// The array of OSes and versions which are specified in the availability guard. - var osVersions: [OSVersion] - init(osVersions: [OSVersion]) { + package var osVersions: [OSVersion] + package init(osVersions: [OSVersion]) { self.osVersions = osVersions } /// An OS and its version. - struct OSVersion: Equatable, Codable, Sendable { - var os: OS - var version: String - init(os: OS, version: String) { + package struct OSVersion: Equatable, Codable, Sendable { + package var os: OS + package var version: String + package init(os: OS, version: String) { self.os = os self.version = version } @@ -856,18 +859,18 @@ struct AvailabilityDescription: Equatable, Codable, Sendable { /// One of the possible OSes. // swift-format-ignore: DontRepeatTypeInStaticProperties - struct OS: Equatable, Codable, Sendable { - var name: String + package struct OS: Equatable, Codable, Sendable { + package var name: String - init(name: String) { + package init(name: String) { self.name = name } - static let macOS = Self(name: "macOS") - static let iOS = Self(name: "iOS") - static let watchOS = Self(name: "watchOS") - static let tvOS = Self(name: "tvOS") - static let visionOS = Self(name: "visionOS") + package static let macOS = Self(name: "macOS") + package static let iOS = Self(name: "iOS") + package static let watchOS = Self(name: "watchOS") + package static let tvOS = Self(name: "tvOS") + package static let visionOS = Self(name: "visionOS") } } @@ -1873,6 +1876,7 @@ extension Declaration { switch self { case .commentable(_, let declaration): return declaration.accessModifier case .deprecated(_, let declaration): return declaration.accessModifier + case .guarded(_, let declaration): return declaration.accessModifier case .variable(let variableDescription): return variableDescription.accessModifier case .extension(let extensionDescription): return extensionDescription.accessModifier case .struct(let structDescription): return structDescription.accessModifier @@ -1891,6 +1895,9 @@ extension Declaration { case .deprecated(let deprecationDescription, var declaration): declaration.accessModifier = newValue self = .deprecated(deprecationDescription, declaration) + case .guarded(let availability, var declaration): + declaration.accessModifier = newValue + self = .guarded(availability, declaration) case .variable(var variableDescription): variableDescription.accessModifier = newValue self = .variable(variableDescription) diff --git a/Sources/GRPCCodeGen/Internal/Translator/ClientCodeTranslator.swift b/Sources/GRPCCodeGen/Internal/Translator/ClientCodeTranslator.swift index d4d9f87ad..443bf9c17 100644 --- a/Sources/GRPCCodeGen/Internal/Translator/ClientCodeTranslator.swift +++ b/Sources/GRPCCodeGen/Internal/Translator/ClientCodeTranslator.swift @@ -81,6 +81,7 @@ struct ClientCodeTranslator { func translate( accessModifier: AccessModifier, service: ServiceDescriptor, + availability: AvailabilityDescription, namer: Namer = Namer(), serializer: (String) -> String, deserializer: (String) -> String @@ -132,7 +133,7 @@ struct ClientCodeTranslator { ), ] ) - blocks.append(.declaration(.extension(`extension`))) + blocks.append(.declaration(.guarded(availability, .extension(`extension`)))) let extensionWithDefaults: ExtensionDescription = .clientMethodSignatureWithDefaults( accessLevel: accessModifier, @@ -145,7 +146,7 @@ struct ClientCodeTranslator { blocks.append( CodeBlock( comment: .inline("Helpers providing default arguments to 'ClientProtocol' methods."), - item: .declaration(.extension(extensionWithDefaults)) + item: .declaration(.guarded(availability, .extension(extensionWithDefaults))) ) ) @@ -158,7 +159,7 @@ struct ClientCodeTranslator { blocks.append( CodeBlock( comment: .inline("Helpers providing sugared APIs for 'ClientProtocol' methods."), - item: .declaration(.extension(extensionWithExplodedAPI)) + item: .declaration(.guarded(availability, .extension(extensionWithExplodedAPI))) ) ) diff --git a/Sources/GRPCCodeGen/Internal/Translator/IDLToStructuredSwiftTranslator.swift b/Sources/GRPCCodeGen/Internal/Translator/IDLToStructuredSwiftTranslator.swift index e83fa34c7..c496980b7 100644 --- a/Sources/GRPCCodeGen/Internal/Translator/IDLToStructuredSwiftTranslator.swift +++ b/Sources/GRPCCodeGen/Internal/Translator/IDLToStructuredSwiftTranslator.swift @@ -26,7 +26,8 @@ package struct IDLToStructuredSwiftTranslator { accessLevelOnImports: Bool, client: Bool, server: Bool, - grpcCoreModuleName: String + grpcCoreModuleName: String, + availability: AvailabilityDescription ) throws -> StructuredSwiftRepresentation { try self.validateInput(codeGenerationRequest) let accessModifier = AccessModifier(accessLevel) @@ -46,6 +47,7 @@ package struct IDLToStructuredSwiftTranslator { let metadata = metadataTranslator.translate( accessModifier: accessModifier, service: service, + availability: availability, namer: namer ) codeBlocks.append(contentsOf: metadata) @@ -58,6 +60,7 @@ package struct IDLToStructuredSwiftTranslator { let blocks = serverTranslator.translate( accessModifier: accessModifier, service: service, + availability: availability, namer: namer, serializer: codeGenerationRequest.makeSerializerCodeSnippet, deserializer: codeGenerationRequest.makeDeserializerCodeSnippet @@ -72,6 +75,7 @@ package struct IDLToStructuredSwiftTranslator { let blocks = clientTranslator.translate( accessModifier: accessModifier, service: service, + availability: availability, namer: namer, serializer: codeGenerationRequest.makeSerializerCodeSnippet, deserializer: codeGenerationRequest.makeDeserializerCodeSnippet diff --git a/Sources/GRPCCodeGen/Internal/Translator/MetadataTranslator.swift b/Sources/GRPCCodeGen/Internal/Translator/MetadataTranslator.swift index 41252995e..2fc64821c 100644 --- a/Sources/GRPCCodeGen/Internal/Translator/MetadataTranslator.swift +++ b/Sources/GRPCCodeGen/Internal/Translator/MetadataTranslator.swift @@ -20,8 +20,14 @@ struct MetadataTranslator { func translate( accessModifier: AccessModifier, service: ServiceDescriptor, + availability: AvailabilityDescription, namer: Namer = Namer() ) -> [CodeBlock] { - .serviceMetadata(accessModifier: accessModifier, service: service, namer: namer) + .serviceMetadata( + accessModifier: accessModifier, + service: service, + availability: availability, + namer: namer + ) } } diff --git a/Sources/GRPCCodeGen/Internal/Translator/ServerCodeTranslator.swift b/Sources/GRPCCodeGen/Internal/Translator/ServerCodeTranslator.swift index 2bf06757f..caf981742 100644 --- a/Sources/GRPCCodeGen/Internal/Translator/ServerCodeTranslator.swift +++ b/Sources/GRPCCodeGen/Internal/Translator/ServerCodeTranslator.swift @@ -63,6 +63,7 @@ struct ServerCodeTranslator { func translate( accessModifier: AccessModifier, service: ServiceDescriptor, + availability: AvailabilityDescription, namer: Namer = Namer(), serializer: (String) -> String, deserializer: (String) -> String @@ -129,7 +130,7 @@ struct ServerCodeTranslator { ), ] ) - blocks.append(.declaration(.extension(`extension`))) + blocks.append(.declaration(.guarded(availability, .extension(`extension`)))) // extension .StreamingServiceProtocol> { ... } let registerExtension: ExtensionDescription = .registrableRPCServiceDefaultImplementation( @@ -144,7 +145,7 @@ struct ServerCodeTranslator { blocks.append( CodeBlock( comment: .inline("Default implementation of 'registerMethods(with:)'."), - item: .declaration(.extension(registerExtension)) + item: .declaration(.guarded(availability, .extension(registerExtension))) ) ) @@ -161,7 +162,7 @@ struct ServerCodeTranslator { comment: .inline( "Default implementation of streaming methods from 'StreamingServiceProtocol'." ), - item: .declaration(.extension(streamingServiceDefaultImplExtension)) + item: .declaration(.guarded(availability, .extension(streamingServiceDefaultImplExtension))) ) ) @@ -175,7 +176,7 @@ struct ServerCodeTranslator { blocks.append( CodeBlock( comment: .inline("Default implementation of methods from 'ServiceProtocol'."), - item: .declaration(.extension(serviceDefaultImplExtension)) + item: .declaration(.guarded(availability, .extension(serviceDefaultImplExtension))) ) ) diff --git a/Tests/GRPCCodeGenTests/Internal/Translator/ClientCodeTranslatorSnippetBasedTests.swift b/Tests/GRPCCodeGenTests/Internal/Translator/ClientCodeTranslatorSnippetBasedTests.swift index fd380c806..064791b78 100644 --- a/Tests/GRPCCodeGenTests/Internal/Translator/ClientCodeTranslatorSnippetBasedTests.swift +++ b/Tests/GRPCCodeGenTests/Internal/Translator/ClientCodeTranslatorSnippetBasedTests.swift @@ -42,6 +42,7 @@ struct ClientCodeTranslatorSnippetBasedTests { ) let expectedSwift = """ + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension NamespaceA_ServiceA { /// Generated client protocol for the "namespaceA.ServiceA" service. /// @@ -132,6 +133,7 @@ struct ClientCodeTranslatorSnippetBasedTests { } } // Helpers providing default arguments to 'ClientProtocol' methods. + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension NamespaceA_ServiceA.ClientProtocol { /// Call the "MethodA" method. /// @@ -163,6 +165,7 @@ struct ClientCodeTranslatorSnippetBasedTests { } } // Helpers providing sugared APIs for 'ClientProtocol' methods. + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension NamespaceA_ServiceA.ClientProtocol { /// Call the "MethodA" method. /// @@ -208,7 +211,11 @@ struct ClientCodeTranslatorSnippetBasedTests { service: ServiceDescriptor ) -> String { let translator = ClientCodeTranslator() - let codeBlocks = translator.translate(accessModifier: accessLevel, service: service) { + let codeBlocks = translator.translate( + accessModifier: accessLevel, + service: service, + availability: .macOS15Aligned + ) { "GRPCProtobuf.ProtobufSerializer<\($0)>()" } deserializer: { "GRPCProtobuf.ProtobufDeserializer<\($0)>()" diff --git a/Tests/GRPCCodeGenTests/Internal/Translator/IDLToStructuredSwiftTranslatorSnippetBasedTests.swift b/Tests/GRPCCodeGenTests/Internal/Translator/IDLToStructuredSwiftTranslatorSnippetBasedTests.swift index 05375ae4f..eb9c85e5a 100644 --- a/Tests/GRPCCodeGenTests/Internal/Translator/IDLToStructuredSwiftTranslatorSnippetBasedTests.swift +++ b/Tests/GRPCCodeGenTests/Internal/Translator/IDLToStructuredSwiftTranslatorSnippetBasedTests.swift @@ -56,6 +56,7 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase { // MARK: - namespaceA.ServiceA /// Namespace containing generated types for the "namespaceA.ServiceA" service. + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) public enum NamespaceA_ServiceA { /// Service descriptor for the "namespaceA.ServiceA" service. public static let descriptor = GRPCCore.ServiceDescriptor(fullyQualifiedService: "namespaceA.ServiceA") @@ -66,6 +67,7 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase { } } + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension GRPCCore.ServiceDescriptor { /// Service descriptor for the "namespaceA.ServiceA" service. public static let namespaceA_ServiceA = GRPCCore.ServiceDescriptor(fullyQualifiedService: "namespaceA.ServiceA") @@ -73,6 +75,7 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase { // MARK: namespaceA.ServiceA (server) + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension NamespaceA_ServiceA { /// Streaming variant of the service protocol for the "namespaceA.ServiceA" service. /// @@ -116,15 +119,18 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase { } // Default implementation of 'registerMethods(with:)'. + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension NamespaceA_ServiceA.StreamingServiceProtocol { public func registerMethods(with router: inout GRPCCore.RPCRouter) where Transport: GRPCCore.ServerTransport {} } // Default implementation of streaming methods from 'StreamingServiceProtocol'. + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension NamespaceA_ServiceA.ServiceProtocol { } // Default implementation of methods from 'ServiceProtocol'. + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension NamespaceA_ServiceA.SimpleServiceProtocol { } """ @@ -207,7 +213,8 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase { accessLevelOnImports: false, client: true, server: true, - grpcCoreModuleName: String("GRPCCore".reversed()) + grpcCoreModuleName: String("GRPCCore".reversed()), + availability: .macOS15Aligned ) let renderer = TextBasedRenderer.default let sourceFile = try renderer.render(structured: structuredSwift) @@ -248,7 +255,8 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase { accessLevelOnImports: true, client: false, server: server, - grpcCoreModuleName: grpcCoreModuleName + grpcCoreModuleName: grpcCoreModuleName, + availability: .macOS15Aligned ) let renderer = TextBasedRenderer.default let sourceFile = try renderer.render(structured: structuredSwift) @@ -277,7 +285,8 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase { accessLevelOnImports: true, client: true, server: true, - grpcCoreModuleName: "GRPCCore" + grpcCoreModuleName: "GRPCCore", + availability: .macOS15Aligned ) ) { error in @@ -325,7 +334,8 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase { accessLevelOnImports: true, client: true, server: true, - grpcCoreModuleName: "GRPCCore" + grpcCoreModuleName: "GRPCCore", + availability: .macOS15Aligned ) ) { error in @@ -361,7 +371,8 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase { accessLevelOnImports: true, client: true, server: true, - grpcCoreModuleName: "GRPCCore" + grpcCoreModuleName: "GRPCCore", + availability: .macOS15Aligned ) ) { error in @@ -408,7 +419,8 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase { accessLevelOnImports: true, client: true, server: true, - grpcCoreModuleName: "GRPCCore" + grpcCoreModuleName: "GRPCCore", + availability: .macOS15Aligned ) ) { error in XCTAssertEqual( @@ -453,7 +465,8 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase { accessLevelOnImports: true, client: true, server: true, - grpcCoreModuleName: "GRPCCore" + grpcCoreModuleName: "GRPCCore", + availability: .macOS15Aligned ) ) { error in XCTAssertEqual( @@ -514,7 +527,8 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase { accessLevelOnImports: true, client: true, server: true, - grpcCoreModuleName: "GRPCCore" + grpcCoreModuleName: "GRPCCore", + availability: .macOS15Aligned ) ) { error in XCTAssertEqual( @@ -568,7 +582,8 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase { accessLevelOnImports: true, client: true, server: true, - grpcCoreModuleName: "GRPCCore" + grpcCoreModuleName: "GRPCCore", + availability: .macOS15Aligned ) ) { error in @@ -615,7 +630,8 @@ final class IDLToStructuredSwiftTranslatorSnippetBasedTests: XCTestCase { accessLevelOnImports: true, client: true, server: true, - grpcCoreModuleName: "GRPCCore" + grpcCoreModuleName: "GRPCCore", + availability: .macOS15Aligned ) ) { error in diff --git a/Tests/GRPCCodeGenTests/Internal/Translator/ServerCodeTranslatorSnippetBasedTests.swift b/Tests/GRPCCodeGenTests/Internal/Translator/ServerCodeTranslatorSnippetBasedTests.swift index 1b41acc1c..bdbfcba9d 100644 --- a/Tests/GRPCCodeGenTests/Internal/Translator/ServerCodeTranslatorSnippetBasedTests.swift +++ b/Tests/GRPCCodeGenTests/Internal/Translator/ServerCodeTranslatorSnippetBasedTests.swift @@ -42,6 +42,7 @@ final class ServerCodeTranslatorSnippetBasedTests { ) let expectedSwift = """ + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension NamespaceA_ServiceA { /// Streaming variant of the service protocol for the "namespaceA.AlongNameForServiceA" service. /// @@ -138,6 +139,7 @@ final class ServerCodeTranslatorSnippetBasedTests { } } // Default implementation of 'registerMethods(with:)'. + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension NamespaceA_ServiceA.StreamingServiceProtocol { public func registerMethods(with router: inout GRPCCore.RPCRouter) where Transport: GRPCCore.ServerTransport { router.registerHandler( @@ -154,6 +156,7 @@ final class ServerCodeTranslatorSnippetBasedTests { } } // Default implementation of streaming methods from 'StreamingServiceProtocol'. + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension NamespaceA_ServiceA.ServiceProtocol { public func unary( request: GRPCCore.StreamingServerRequest, @@ -167,6 +170,7 @@ final class ServerCodeTranslatorSnippetBasedTests { } } // Default implementation of methods from 'ServiceProtocol'. + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension NamespaceA_ServiceA.SimpleServiceProtocol { public func unary( request: GRPCCore.ServerRequest, @@ -192,7 +196,11 @@ final class ServerCodeTranslatorSnippetBasedTests { service: ServiceDescriptor ) -> String { let translator = ServerCodeTranslator() - let codeBlocks = translator.translate(accessModifier: accessLevel, service: service) { + let codeBlocks = translator.translate( + accessModifier: accessLevel, + service: service, + availability: .macOS15Aligned + ) { "GRPCProtobuf.ProtobufSerializer<\($0)>()" } deserializer: { "GRPCProtobuf.ProtobufDeserializer<\($0)>()" diff --git a/Tests/GRPCCodeGenTests/Internal/Translator/TypealiasTranslatorSnippetBasedTests.swift b/Tests/GRPCCodeGenTests/Internal/Translator/TypealiasTranslatorSnippetBasedTests.swift index ba6d4d249..4f6168c4b 100644 --- a/Tests/GRPCCodeGenTests/Internal/Translator/TypealiasTranslatorSnippetBasedTests.swift +++ b/Tests/GRPCCodeGenTests/Internal/Translator/TypealiasTranslatorSnippetBasedTests.swift @@ -42,6 +42,7 @@ struct TypealiasTranslatorSnippetBasedTests { let expectedSwift = """ /// Namespace containing generated types for the "namespaceA.ServiceA" service. + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) public enum NamespaceA_ServiceA { /// Service descriptor for the "namespaceA.ServiceA" service. public static let descriptor = GRPCCore.ServiceDescriptor(fullyQualifiedService: "namespaceA.ServiceA") @@ -65,6 +66,7 @@ struct TypealiasTranslatorSnippetBasedTests { ] } } + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension GRPCCore.ServiceDescriptor { /// Service descriptor for the "namespaceA.ServiceA" service. public static let namespaceA_ServiceA = GRPCCore.ServiceDescriptor(fullyQualifiedService: "namespaceA.ServiceA") @@ -83,7 +85,8 @@ extension TypealiasTranslatorSnippetBasedTests { let translator = MetadataTranslator() let codeBlocks = translator.translate( accessModifier: AccessModifier(accessLevel), - service: service + service: service, + availability: .macOS15Aligned ) let renderer = TextBasedRenderer.default