diff --git a/Sources/ClientRuntime/Networking/CRTError+Error.swift b/Sources/ClientRuntime/Networking/CRTError+Error.swift deleted file mode 100644 index 8197645f8..000000000 --- a/Sources/ClientRuntime/Networking/CRTError+Error.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import AwsCommonRuntimeKit - -extension CRTError: Error { - - var localizedDescription: String { - message - } -} diff --git a/Sources/ClientRuntime/PrimitiveTypeExtensions/Indirect.swift b/Sources/ClientRuntime/PrimitiveTypeExtensions/Indirect.swift index 830276af2..2cf99856e 100644 --- a/Sources/ClientRuntime/PrimitiveTypeExtensions/Indirect.swift +++ b/Sources/ClientRuntime/PrimitiveTypeExtensions/Indirect.swift @@ -5,12 +5,28 @@ // SPDX-License-Identifier: Apache-2.0 // +import class Foundation.NSRecursiveLock + @propertyWrapper -public class Indirect { - public var wrappedValue: Optional +public final class Indirect: @unchecked Sendable { + private let lock = NSRecursiveLock() + private var _wrappedValue: Optional + + public var wrappedValue: Optional { + get { + lock.lock() + defer { lock.unlock() } + return _wrappedValue + } + set { + lock.lock() + defer { lock.unlock() } + _wrappedValue = newValue + } + } public init(wrappedValue: Optional) { - self.wrappedValue = wrappedValue + self._wrappedValue = wrappedValue } } diff --git a/Sources/Smithy/ByteStream.swift b/Sources/Smithy/ByteStream.swift index b71884662..d6d00abf3 100644 --- a/Sources/Smithy/ByteStream.swift +++ b/Sources/Smithy/ByteStream.swift @@ -8,7 +8,7 @@ import class Foundation.FileHandle import struct Foundation.Data -public enum ByteStream { +public enum ByteStream: Sendable { case data(Data?) case stream(Stream) case noStream diff --git a/Sources/Smithy/Document/SmithyDocument.swift b/Sources/Smithy/Document/SmithyDocument.swift index c5e295017..9133fc6c4 100644 --- a/Sources/Smithy/Document/SmithyDocument.swift +++ b/Sources/Smithy/Document/SmithyDocument.swift @@ -8,8 +8,9 @@ import struct Foundation.Data import struct Foundation.Date -public protocol SmithyDocument { +public protocol SmithyDocument: Sendable { + /// The Smithy type corresponding to the data stored in this document. var type: ShapeType { get } // "as" methods throw if the document doesn't match the requested type. @@ -116,6 +117,20 @@ public extension SmithyDocument { extension SmithyDocument { + /// Compares two `SmithyDocument`-conforming values, checking for equality. + /// + /// Two `SmithyDocument`s are equal if they have the same type and equal values. + /// + /// Two Smithy `list` documents are equal if they have equal documents at every index. + /// + /// Two Smithy `map` documents are equal if they have the same set of keys, and equal values for every key. + /// + /// - note: Because `SmithyDocument` is a protocol, it cannot conform to `Equatable`; the type-erased + /// container type ``Document`` is used to provide Smithy documents with equatability. + /// - Parameters: + /// - lhs: The first `SmithyDocument` to compare. + /// - rhs: The second `SmithyDocument` to compare. + /// - Returns: `true` if the two `SmithyDocument`s are equal, `false` otherwise. public static func isEqual(_ lhs: SmithyDocument, _ rhs: SmithyDocument) -> Bool { switch (lhs.type, rhs.type) { case (.blob, .blob): diff --git a/Sources/Smithy/Stream.swift b/Sources/Smithy/Stream.swift index 968545f12..c16fda8f7 100644 --- a/Sources/Smithy/Stream.swift +++ b/Sources/Smithy/Stream.swift @@ -8,7 +8,7 @@ import struct Foundation.Data /// Protocol that provides reading data from a stream -public protocol ReadableStream: AnyObject { +public protocol ReadableStream: AnyObject, Sendable { /// Returns the current position in the stream var position: Data.Index { get } @@ -45,7 +45,7 @@ public protocol ReadableStream: AnyObject { } /// Protocol that provides writing data to a stream -public protocol WriteableStream: AnyObject { +public protocol WriteableStream: AnyObject, Sendable { /// Writes the contents of `data` to the stream /// - Parameter data: data to write func write(contentsOf data: Data) throws diff --git a/Sources/SmithyChecksums/ChunkedStream.swift b/Sources/SmithyChecksums/ChunkedStream.swift index e77583327..661f2cf02 100644 --- a/Sources/SmithyChecksums/ChunkedStream.swift +++ b/Sources/SmithyChecksums/ChunkedStream.swift @@ -16,8 +16,8 @@ import class SmithyStreams.BufferedStream /// URLSessionHTTPClient streams chunked payloads using this stream type. /// CRTClientEngine uses only the reader provided by this type to create chunks, then it /// streams them itself. -public class ChunkedStream { - private var inputStream: Stream +public class ChunkedStream: @unchecked Sendable { + private let inputStream: Stream private var signingConfig: SigningConfig private var previousSignature: String private var trailingHeaders: Headers diff --git a/Sources/SmithyChecksums/ValidatingBufferedStream.swift b/Sources/SmithyChecksums/ValidatingBufferedStream.swift index e63e629e6..dbe2c92b7 100644 --- a/Sources/SmithyChecksums/ValidatingBufferedStream.swift +++ b/Sources/SmithyChecksums/ValidatingBufferedStream.swift @@ -12,7 +12,7 @@ import struct Foundation.Data import AwsCommonRuntimeKit import class SmithyStreams.BufferedStream -public class ValidatingBufferedStream { +public class ValidatingBufferedStream: @unchecked Sendable { private var stream: BufferedStream private var checksumAlgorithm: ChecksumAlgorithm private var checksum: (any Checksum) diff --git a/Sources/SmithyEventStreams/DefaultMessageEncoderStream.swift b/Sources/SmithyEventStreams/DefaultMessageEncoderStream.swift index 15e1359dd..a48245c99 100644 --- a/Sources/SmithyEventStreams/DefaultMessageEncoderStream.swift +++ b/Sources/SmithyEventStreams/DefaultMessageEncoderStream.swift @@ -11,7 +11,7 @@ import SmithyEventStreamsAuthAPI import struct Foundation.Data /// Stream adapter that encodes input into `Data` objects. -public class DefaultMessageEncoderStream: MessageEncoderStream, Stream { +public class DefaultMessageEncoderStream: MessageEncoderStream, Stream, @unchecked Sendable { let stream: AsyncThrowingStream let messageEncoder: MessageEncoder diff --git a/Sources/SmithyEventStreamsAPI/EventStreamError.swift b/Sources/SmithyEventStreamsAPI/EventStreamError.swift index ff69472cd..3b9f6c42d 100644 --- a/Sources/SmithyEventStreamsAPI/EventStreamError.swift +++ b/Sources/SmithyEventStreamsAPI/EventStreamError.swift @@ -15,11 +15,3 @@ public enum EventStreamError: Error { /// This may be due to missing required headers case invalidMessage(String) } - -extension AsyncThrowingStream: Equatable where Element: Equatable { - - public static func == (lhs: AsyncThrowingStream, rhs: AsyncThrowingStream) -> Bool { - // TODO: Remove as part of https://github.com/awslabs/aws-sdk-swift/issues/898 - return false - } -} diff --git a/Sources/SmithyHTTPAPI/Headers.swift b/Sources/SmithyHTTPAPI/Headers.swift index 8baeb35f8..eef01d9b8 100644 --- a/Sources/SmithyHTTPAPI/Headers.swift +++ b/Sources/SmithyHTTPAPI/Headers.swift @@ -5,7 +5,7 @@ // SPDX-License-Identifier: Apache-2.0 // -public struct Headers { +public struct Headers: Sendable { public var headers: [Header] = [] /// Creates an empty instance. @@ -197,7 +197,7 @@ extension Array where Element == Header { } } -public struct Header { +public struct Header: Sendable { public var name: String public var value: [String] diff --git a/Sources/SmithyStreams/BufferedStream.swift b/Sources/SmithyStreams/BufferedStream.swift index 20db3d23f..d720597f2 100644 --- a/Sources/SmithyStreams/BufferedStream.swift +++ b/Sources/SmithyStreams/BufferedStream.swift @@ -14,7 +14,7 @@ import protocol Smithy.Stream /// Note: This class is thread-safe and async-safe. /// Note: if data is not read from the stream, the buffer will grow indefinitely until the stream is closed. /// or reach the maximum size of a `Data` object. -public class BufferedStream: Stream { +public class BufferedStream: Stream, @unchecked Sendable { /// Returns the cumulative length of all data so far written to the stream, if known. /// For a buffered stream, the length will only be known if the stream has closed. diff --git a/Sources/SmithyStreams/FileStream.swift b/Sources/SmithyStreams/FileStream.swift index 3e654af29..857c2eed2 100644 --- a/Sources/SmithyStreams/FileStream.swift +++ b/Sources/SmithyStreams/FileStream.swift @@ -13,7 +13,7 @@ import protocol Smithy.Stream /// A `Stream` that wraps a `FileHandle` for reading the file. /// /// - Note: This class is thread-safe. -public final class FileStream: Stream { +public final class FileStream: Stream, @unchecked Sendable { /// Returns the length of the stream, if known public var length: Int? { @@ -26,7 +26,7 @@ public final class FileStream: Stream { let fileHandle: FileHandle /// Returns the current position of the stream. - public var position: Data.Index + public private(set) var position: Data.Index /// Returns true if length is zero, false otherwise. public var isEmpty: Bool { diff --git a/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/EnumGenerator.kt b/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/EnumGenerator.kt index 8013c7708..ce41d4878 100644 --- a/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/EnumGenerator.kt +++ b/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/EnumGenerator.kt @@ -143,8 +143,9 @@ class EnumGenerator( writer.writeShapeDocs(shape) writer.writeAvailableAttribute(null, shape) writer.openBlock( - "public enum \$enum.name:L: \$N, \$N, \$N, \$N {", + "public enum \$enum.name:L: \$N, \$N, \$N, \$N, \$N {", "}", + SwiftTypes.Protocols.Sendable, SwiftTypes.Protocols.Equatable, SwiftTypes.Protocols.RawRepresentable, SwiftTypes.Protocols.CaseIterable, diff --git a/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/IntEnumGenerator.kt b/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/IntEnumGenerator.kt index 45ab66970..45b27b3d7 100644 --- a/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/IntEnumGenerator.kt +++ b/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/IntEnumGenerator.kt @@ -29,6 +29,7 @@ class IntEnumGenerator( if (isNestedType) { val service = model.expectShape(settings.service) writer.openBlock("extension ${service.nestedNamespaceType(symbolProvider)} {", "}") { + writer.write("") renderEnum() } } else { @@ -41,8 +42,9 @@ class IntEnumGenerator( writer.writeShapeDocs(shape) writer.writeAvailableAttribute(null, shape) writer.openBlock( - "public enum \$enum.name:L: \$N, \$N, \$N, \$N {", + "public enum \$enum.name:L: \$N, \$N, \$N, \$N, \$N {", "}", + SwiftTypes.Protocols.Sendable, SwiftTypes.Protocols.Equatable, SwiftTypes.Protocols.RawRepresentable, SwiftTypes.Protocols.CaseIterable, diff --git a/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/StructureGenerator.kt b/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/StructureGenerator.kt index 8b512d05b..d11d00fd2 100644 --- a/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/StructureGenerator.kt +++ b/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/StructureGenerator.kt @@ -113,15 +113,15 @@ class StructureGenerator( } private fun generateStruct() { + writer.write("") writer.writeShapeDocs(shape) writer.writeAvailableAttribute(model, shape) - val equatableConformance = writer.format(": \$N ", SwiftTypes.Protocols.Equatable).takeIf { shape.hasTrait() } ?: "" - writer.openBlock("public struct \$struct.name:L $equatableConformance{") + val equatableConformance = writer.format(", \$N", SwiftTypes.Protocols.Equatable).takeIf { shape.hasTrait() } ?: "" + writer.openBlock("public struct \$struct.name:L: \$N$equatableConformance {", SwiftTypes.Protocols.Sendable) .call { generateStructMembers() } .write("") .call { generateInitializerForStructure(false) } .closeBlock("}") - .write("") } private fun generateStructMembers() { diff --git a/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/UnionGenerator.kt b/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/UnionGenerator.kt index 9c8bfec57..1cd21c3b2 100644 --- a/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/UnionGenerator.kt +++ b/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/UnionGenerator.kt @@ -64,6 +64,7 @@ class UnionGenerator( if (isNestedType) { val service = model.expectShape(settings.service) writer.openBlock("extension ${service.nestedNamespaceType(symbolProvider)} {", "}") { + writer.write("") renderUnion() } } else { @@ -76,8 +77,8 @@ class UnionGenerator( writer.writeShapeDocs(shape) writer.writeAvailableAttribute(model, shape) val indirectOrNot = "indirect ".takeIf { shape.hasTrait() } ?: "" - val equatableConformance = (": " + SwiftTypes.Protocols.Equatable + " ").takeIf { shape.hasTrait() } ?: "" - writer.openBlock("public ${indirectOrNot}enum \$union.name:L $equatableConformance{", "}\n") { + val equatableConformance = writer.format(", \$N", SwiftTypes.Protocols.Equatable).takeIf { shape.hasTrait() } ?: "" + writer.openBlock("public ${indirectOrNot}enum \$union.name:L: \$N$equatableConformance {", "}", SwiftTypes.Protocols.Sendable) { // event streams (@streaming union) MAY have variants that target errors. // These errors if encountered on the stream will be thrown as an exception rather // than showing up as one of the possible events the consumer will see on the stream (AsyncThrowingStream). diff --git a/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/swiftmodules/SwiftTypes.kt b/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/swiftmodules/SwiftTypes.kt index 166e2bc4a..9045179fd 100644 --- a/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/swiftmodules/SwiftTypes.kt +++ b/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/swiftmodules/SwiftTypes.kt @@ -31,6 +31,7 @@ object SwiftTypes { val RawRepresentable = builtInSymbol("RawRepresentable", SwiftDeclaration.PROTOCOL) val CaseIterable = builtInSymbol("CaseIterable", SwiftDeclaration.PROTOCOL) val CustomDebugStringConvertible = builtInSymbol("CustomDebugStringConvertible", SwiftDeclaration.PROTOCOL) + val Sendable = builtInSymbol("Sendable", SwiftDeclaration.PROTOCOL) } } diff --git a/smithy-swift-codegen/src/test/kotlin/EnumGeneratorTests.kt b/smithy-swift-codegen/src/test/kotlin/EnumGeneratorTests.kt index 937e891d0..7bd167f6f 100644 --- a/smithy-swift-codegen/src/test/kotlin/EnumGeneratorTests.kt +++ b/smithy-swift-codegen/src/test/kotlin/EnumGeneratorTests.kt @@ -39,7 +39,7 @@ class EnumGeneratorTests { val expectedGeneratedEnum = """ /// Really long multi-line Documentation for the enum -public enum MyEnum: Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { +public enum MyEnum: Swift.Sendable, Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { /// Documentation for BAR case bar case fooBazXap @@ -98,7 +98,7 @@ public enum MyEnum: Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, val expectedGeneratedEnum = """ /// Really long multi-line Documentation for the enum -public enum MyEnum: Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { +public enum MyEnum: Swift.Sendable, Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { /// ""${'"'} T2 instances are Burstable Performance Instances that provide a baseline level of CPU performance with the ability to burst above the baseline.""${'"'} case t2Micro case t2Nano @@ -141,7 +141,7 @@ public enum MyEnum: Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, var expectedGeneratedEnum = """ extension ExampleClientTypes { - public enum Suit: Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { + public enum Suit: Swift.Sendable, Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { case club case diamond case heart diff --git a/smithy-swift-codegen/src/test/kotlin/IntEnumGeneratorTests.kt b/smithy-swift-codegen/src/test/kotlin/IntEnumGeneratorTests.kt index 1b373c80d..cdb0b497e 100644 --- a/smithy-swift-codegen/src/test/kotlin/IntEnumGeneratorTests.kt +++ b/smithy-swift-codegen/src/test/kotlin/IntEnumGeneratorTests.kt @@ -16,7 +16,7 @@ class IntEnumGeneratorTests { .getFileString("Sources/example/models/Abcs.swift").get() Assertions.assertNotNull(enumShape) var expectedGeneratedEnum = """ -public enum Abcs: Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { +public enum Abcs: Swift.Sendable, Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { case a case b case c diff --git a/smithy-swift-codegen/src/test/kotlin/PaginatorGeneratorTest.kt b/smithy-swift-codegen/src/test/kotlin/PaginatorGeneratorTest.kt index 0968dcb12..206eddfb2 100644 --- a/smithy-swift-codegen/src/test/kotlin/PaginatorGeneratorTest.kt +++ b/smithy-swift-codegen/src/test/kotlin/PaginatorGeneratorTest.kt @@ -147,7 +147,7 @@ class PaginatorGeneratorTest { // Equatable conformance must have been generated for struct nested inside a pagination token. val contents = getFileContents(context.manifest, "Sources/Test/models/NestedInputTokenValue.swift") val expected = """ - public struct NestedInputTokenValue : Swift.Equatable { + public struct NestedInputTokenValue: Swift.Sendable, Swift.Equatable { """.trimIndent() contents.shouldContainOnlyOnce(expected) } @@ -158,7 +158,7 @@ class PaginatorGeneratorTest { // Equatable conformance must have been generated for struct nested under pagination token. val contents = getFileContents(context.manifest, "Sources/Test/models/DoublyNestedInputTokenValue.swift") val expected = """ - public struct DoublyNestedInputTokenValue : Swift.Equatable { + public struct DoublyNestedInputTokenValue: Swift.Sendable, Swift.Equatable { """.trimIndent() contents.shouldContainOnlyOnce(expected) } @@ -169,8 +169,8 @@ class PaginatorGeneratorTest { // Equatable conformance must have been generated for union nested under pagination token. val contents = getFileContents(context.manifest, "Sources/Test/models/InputPaginationUnion.swift") val expected = """ - public enum InputPaginationUnion : Swift.Equatable { - """.trimIndent() + public enum InputPaginationUnion: Swift.Sendable, Swift.Equatable { +""" contents.shouldContainOnlyOnce(expected) } diff --git a/smithy-swift-codegen/src/test/kotlin/RecursiveShapeBoxerTests.kt b/smithy-swift-codegen/src/test/kotlin/RecursiveShapeBoxerTests.kt index f2052964b..035d58506 100644 --- a/smithy-swift-codegen/src/test/kotlin/RecursiveShapeBoxerTests.kt +++ b/smithy-swift-codegen/src/test/kotlin/RecursiveShapeBoxerTests.kt @@ -48,85 +48,79 @@ internal class RecursiveShapeBoxerTests { val recursiveShapesInput = manifest .getFileString("Sources/example/models/RecursiveShapesInput.swift").get() Assertions.assertNotNull(recursiveShapesInput) - val expected = - """ - public struct RecursiveShapesInput { - public var nested: ExampleClientTypes.RecursiveShapesInputOutputNested1? - - public init( - nested: ExampleClientTypes.RecursiveShapesInputOutputNested1? = nil - ) - { - self.nested = nested - } - } - """.trimIndent() + val expected = """ +public struct RecursiveShapesInput: Swift.Sendable { + public var nested: ExampleClientTypes.RecursiveShapesInputOutputNested1? + + public init( + nested: ExampleClientTypes.RecursiveShapesInputOutputNested1? = nil + ) + { + self.nested = nested + } +} +""" recursiveShapesInput.shouldContain(expected) val recursiveShapesOutput = manifest .getFileString("Sources/example/models/RecursiveShapesOutput.swift").get() Assertions.assertNotNull(recursiveShapesOutput) - val expected2 = - """ - public struct RecursiveShapesOutput { - public var nested: ExampleClientTypes.RecursiveShapesInputOutputNested1? - - public init( - nested: ExampleClientTypes.RecursiveShapesInputOutputNested1? = nil - ) - { - self.nested = nested - } - } - """.trimIndent() + val expected2 = """ +public struct RecursiveShapesOutput: Swift.Sendable { + public var nested: ExampleClientTypes.RecursiveShapesInputOutputNested1? + + public init( + nested: ExampleClientTypes.RecursiveShapesInputOutputNested1? = nil + ) + { + self.nested = nested + } +} +""" recursiveShapesOutput.shouldContain(expected2) val recursiveShapesInputOutputNested1 = manifest .getFileString("Sources/example/models/RecursiveShapesInputOutputNested1.swift").get() Assertions.assertNotNull(recursiveShapesInputOutputNested1) - val expected3 = - """ - extension ExampleClientTypes { - public struct RecursiveShapesInputOutputNested1 { - public var foo: Swift.String? - @Indirect public var nested: ExampleClientTypes.RecursiveShapesInputOutputNested2? - - public init( - foo: Swift.String? = nil, - nested: ExampleClientTypes.RecursiveShapesInputOutputNested2? = nil - ) - { - self.foo = foo - self.nested = nested - } - } - - } - """.trimIndent() + val expected3 = """ +extension ExampleClientTypes { + + public struct RecursiveShapesInputOutputNested1: Swift.Sendable { + public var foo: Swift.String? + @Indirect public var nested: ExampleClientTypes.RecursiveShapesInputOutputNested2? + + public init( + foo: Swift.String? = nil, + nested: ExampleClientTypes.RecursiveShapesInputOutputNested2? = nil + ) + { + self.foo = foo + self.nested = nested + } + } +} +""" recursiveShapesInputOutputNested1.shouldContain(expected3) val recursiveShapesInputOutputNested2 = manifest .getFileString("Sources/example/models/RecursiveShapesInputOutputNested2.swift").get() Assertions.assertNotNull(recursiveShapesInputOutputNested2) - val expected4 = - """ - extension ExampleClientTypes { - public struct RecursiveShapesInputOutputNested2 { - public var bar: Swift.String? - public var recursiveMember: ExampleClientTypes.RecursiveShapesInputOutputNested1? - - public init( - bar: Swift.String? = nil, - recursiveMember: ExampleClientTypes.RecursiveShapesInputOutputNested1? = nil - ) - { - self.bar = bar - self.recursiveMember = recursiveMember - } - } - + val expected4 = """ + public struct RecursiveShapesInputOutputNested2: Swift.Sendable { + public var bar: Swift.String? + public var recursiveMember: ExampleClientTypes.RecursiveShapesInputOutputNested1? + + public init( + bar: Swift.String? = nil, + recursiveMember: ExampleClientTypes.RecursiveShapesInputOutputNested1? = nil + ) + { + self.bar = bar + self.recursiveMember = recursiveMember } - """.trimIndent() + } +} +""" recursiveShapesInputOutputNested2.shouldContain(expected4) } } diff --git a/smithy-swift-codegen/src/test/kotlin/ReservedWordsGeneratorTests.kt b/smithy-swift-codegen/src/test/kotlin/ReservedWordsGeneratorTests.kt index 3d9b9796c..0048f2cda 100644 --- a/smithy-swift-codegen/src/test/kotlin/ReservedWordsGeneratorTests.kt +++ b/smithy-swift-codegen/src/test/kotlin/ReservedWordsGeneratorTests.kt @@ -14,7 +14,7 @@ class ReservedWordsGeneratorTests { val expectedContents = """ extension ExampleClientTypes { - public enum ReservedWordsEnum: Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { + public enum ReservedWordsEnum: Swift.Sendable, Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { case any case `open` case `self` @@ -57,7 +57,7 @@ extension ExampleClientTypes { val expectedContents = """ extension ExampleClientTypes { - public enum ModelType: Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { + public enum ModelType: Swift.Sendable, Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { case foo case test case sdkUnknown(Swift.String) @@ -94,7 +94,7 @@ extension ExampleClientTypes { val expectedContents = """ extension ExampleClientTypes { - public enum ModelProtocol: Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { + public enum ModelProtocol: Swift.Sendable, Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { case bar case foo case sdkUnknown(Swift.String) diff --git a/smithy-swift-codegen/src/test/kotlin/ServiceRenamesTests.kt b/smithy-swift-codegen/src/test/kotlin/ServiceRenamesTests.kt index 008d252c5..a1c7847c0 100644 --- a/smithy-swift-codegen/src/test/kotlin/ServiceRenamesTests.kt +++ b/smithy-swift-codegen/src/test/kotlin/ServiceRenamesTests.kt @@ -19,19 +19,18 @@ class ServiceRenamesTests { ) val contents = getFileContents(context.manifest, "Sources/RestJson/models/MyTestOperationInput.swift") contents.shouldSyntacticSanityCheck() - val expectedContents = - """ - public struct MyTestOperationInput { - public var bar: ExampleClientTypes.RenamedGreeting? - - public init( - bar: ExampleClientTypes.RenamedGreeting? = nil - ) - { - self.bar = bar - } - } - """.trimIndent() + val expectedContents = """ +public struct MyTestOperationInput: Swift.Sendable { + public var bar: ExampleClientTypes.RenamedGreeting? + + public init( + bar: ExampleClientTypes.RenamedGreeting? = nil + ) + { + self.bar = bar + } +} +""" contents.shouldContainOnlyOnce(expectedContents) } @@ -47,19 +46,18 @@ class ServiceRenamesTests { ) val contents = getFileContents(context.manifest, "Sources/RestJson/models/MyTestOperationOutput.swift") contents.shouldSyntacticSanityCheck() - val expectedContents = - """ - public struct MyTestOperationOutput { - public var baz: ExampleClientTypes.GreetingStruct? - - public init( - baz: ExampleClientTypes.GreetingStruct? = nil - ) - { - self.baz = baz - } - } - """.trimIndent() + val expectedContents = """ +public struct MyTestOperationOutput: Swift.Sendable { + public var baz: ExampleClientTypes.GreetingStruct? + + public init( + baz: ExampleClientTypes.GreetingStruct? = nil + ) + { + self.baz = baz + } +} +""" contents.shouldContainOnlyOnce(expectedContents) } @@ -75,22 +73,21 @@ class ServiceRenamesTests { ) val contents = getFileContents(context.manifest, "Sources/RestJson/models/GreetingStruct.swift") contents.shouldSyntacticSanityCheck() - val expectedContents = - """ - extension ExampleClientTypes { - public struct GreetingStruct { - public var hi: Swift.String? - - public init( - hi: Swift.String? = nil - ) - { - self.hi = hi - } - } - - } - """.trimIndent() + val expectedContents = """ +extension ExampleClientTypes { + + public struct GreetingStruct: Swift.Sendable { + public var hi: Swift.String? + + public init( + hi: Swift.String? = nil + ) + { + self.hi = hi + } + } +} +""" contents.shouldContainOnlyOnce(expectedContents) } @@ -106,22 +103,21 @@ class ServiceRenamesTests { ) val contents = getFileContents(context.manifest, "Sources/RestJson/models/RenamedGreeting.swift") contents.shouldSyntacticSanityCheck() - val expectedContents = - """ - extension ExampleClientTypes { - public struct RenamedGreeting { - public var salutation: Swift.String? - - public init( - salutation: Swift.String? = nil - ) - { - self.salutation = salutation - } - } - - } - """.trimIndent() + val expectedContents = """ +extension ExampleClientTypes { + + public struct RenamedGreeting: Swift.Sendable { + public var salutation: Swift.String? + + public init( + salutation: Swift.String? = nil + ) + { + self.salutation = salutation + } + } +} +""" contents.shouldContainOnlyOnce(expectedContents) } diff --git a/smithy-swift-codegen/src/test/kotlin/StructEncodeGenerationIsolatedTests.kt b/smithy-swift-codegen/src/test/kotlin/StructEncodeGenerationIsolatedTests.kt index 19a6c0014..0d99b9261 100644 --- a/smithy-swift-codegen/src/test/kotlin/StructEncodeGenerationIsolatedTests.kt +++ b/smithy-swift-codegen/src/test/kotlin/StructEncodeGenerationIsolatedTests.kt @@ -32,12 +32,21 @@ class StructEncodeGenerationIsolatedTests { val context = setupTests("Isolated/EnumInput.smithy", "com.test#Example") val contents = getFileContents(context.manifest, "Sources/example/models/EnumInputInput.swift") contents.shouldSyntacticSanityCheck() - val expectedContents = - """ - public struct EnumInputInput { - public var enumHeader: ExampleClientTypes.MyEnum? - public var nestedWithEnum: ExampleClientTypes.NestedEnum? - """.trimIndent() + val expectedContents = """ +public struct EnumInputInput: Swift.Sendable { + public var enumHeader: ExampleClientTypes.MyEnum? + public var nestedWithEnum: ExampleClientTypes.NestedEnum? + + public init( + enumHeader: ExampleClientTypes.MyEnum? = nil, + nestedWithEnum: ExampleClientTypes.NestedEnum? = nil + ) + { + self.enumHeader = enumHeader + self.nestedWithEnum = nestedWithEnum + } +} +""" contents.shouldContainOnlyOnce(expectedContents) } @Test diff --git a/smithy-swift-codegen/src/test/kotlin/StructureGeneratorTests.kt b/smithy-swift-codegen/src/test/kotlin/StructureGeneratorTests.kt index d321e323b..39dd9c87d 100644 --- a/smithy-swift-codegen/src/test/kotlin/StructureGeneratorTests.kt +++ b/smithy-swift-codegen/src/test/kotlin/StructureGeneratorTests.kt @@ -32,27 +32,26 @@ class StructureGeneratorTests { val contents = writer.toString() contents.shouldContain(swiftSettings.copyrightNotice) - val expectedGeneratedStructure = - """ - /// This is documentation about the shape. - public struct MyStruct { - public var bar: Swift.Int - /// This is documentation about the member. - public var baz: Swift.Int? - public var foo: Swift.String? - - public init( - bar: Swift.Int = 0, - baz: Swift.Int? = nil, - foo: Swift.String? = nil - ) - { - self.bar = bar - self.baz = baz - self.foo = foo - } - } - """.trimIndent() + val expectedGeneratedStructure = """ +/// This is documentation about the shape. +public struct MyStruct: Swift.Sendable { + public var bar: Swift.Int + /// This is documentation about the member. + public var baz: Swift.Int? + public var foo: Swift.String? + + public init( + bar: Swift.Int = 0, + baz: Swift.Int? = nil, + foo: Swift.String? = nil + ) + { + self.bar = bar + self.baz = baz + self.foo = foo + } +} +""" contents.shouldContain(expectedGeneratedStructure) } @@ -66,61 +65,60 @@ class StructureGeneratorTests { val primitiveTypesInput = manifest .getFileString("Sources/example/models/PrimitiveTypesInput.swift").get() Assertions.assertNotNull(primitiveTypesInput) - val expected = - """ - public struct PrimitiveTypesInput { - public var booleanVal: Swift.Bool? - public var byteVal: Swift.Int8? - public var doubleVal: Swift.Double? - public var floatVal: Swift.Float? - public var intVal: Swift.Int? - public var longVal: Swift.Int? - public var primitiveBooleanVal: Swift.Bool - public var primitiveByteVal: Swift.Int8 - public var primitiveDoubleVal: Swift.Double - public var primitiveFloatVal: Swift.Float - public var primitiveIntVal: Swift.Int - public var primitiveLongVal: Swift.Int - public var primitiveShortVal: Swift.Int16 - public var shortVal: Swift.Int16? - public var str: Swift.String? - - public init( - booleanVal: Swift.Bool? = nil, - byteVal: Swift.Int8? = nil, - doubleVal: Swift.Double? = nil, - floatVal: Swift.Float? = nil, - intVal: Swift.Int? = nil, - longVal: Swift.Int? = nil, - primitiveBooleanVal: Swift.Bool = false, - primitiveByteVal: Swift.Int8 = 0, - primitiveDoubleVal: Swift.Double = 0.0, - primitiveFloatVal: Swift.Float = 0.0, - primitiveIntVal: Swift.Int = 0, - primitiveLongVal: Swift.Int = 0, - primitiveShortVal: Swift.Int16 = 0, - shortVal: Swift.Int16? = nil, - str: Swift.String? = nil - ) - { - self.booleanVal = booleanVal - self.byteVal = byteVal - self.doubleVal = doubleVal - self.floatVal = floatVal - self.intVal = intVal - self.longVal = longVal - self.primitiveBooleanVal = primitiveBooleanVal - self.primitiveByteVal = primitiveByteVal - self.primitiveDoubleVal = primitiveDoubleVal - self.primitiveFloatVal = primitiveFloatVal - self.primitiveIntVal = primitiveIntVal - self.primitiveLongVal = primitiveLongVal - self.primitiveShortVal = primitiveShortVal - self.shortVal = shortVal - self.str = str - } - } - """.trimIndent() + val expected = """ +public struct PrimitiveTypesInput: Swift.Sendable { + public var booleanVal: Swift.Bool? + public var byteVal: Swift.Int8? + public var doubleVal: Swift.Double? + public var floatVal: Swift.Float? + public var intVal: Swift.Int? + public var longVal: Swift.Int? + public var primitiveBooleanVal: Swift.Bool + public var primitiveByteVal: Swift.Int8 + public var primitiveDoubleVal: Swift.Double + public var primitiveFloatVal: Swift.Float + public var primitiveIntVal: Swift.Int + public var primitiveLongVal: Swift.Int + public var primitiveShortVal: Swift.Int16 + public var shortVal: Swift.Int16? + public var str: Swift.String? + + public init( + booleanVal: Swift.Bool? = nil, + byteVal: Swift.Int8? = nil, + doubleVal: Swift.Double? = nil, + floatVal: Swift.Float? = nil, + intVal: Swift.Int? = nil, + longVal: Swift.Int? = nil, + primitiveBooleanVal: Swift.Bool = false, + primitiveByteVal: Swift.Int8 = 0, + primitiveDoubleVal: Swift.Double = 0.0, + primitiveFloatVal: Swift.Float = 0.0, + primitiveIntVal: Swift.Int = 0, + primitiveLongVal: Swift.Int = 0, + primitiveShortVal: Swift.Int16 = 0, + shortVal: Swift.Int16? = nil, + str: Swift.String? = nil + ) + { + self.booleanVal = booleanVal + self.byteVal = byteVal + self.doubleVal = doubleVal + self.floatVal = floatVal + self.intVal = intVal + self.longVal = longVal + self.primitiveBooleanVal = primitiveBooleanVal + self.primitiveByteVal = primitiveByteVal + self.primitiveDoubleVal = primitiveDoubleVal + self.primitiveFloatVal = primitiveFloatVal + self.primitiveIntVal = primitiveIntVal + self.primitiveLongVal = primitiveLongVal + self.primitiveShortVal = primitiveShortVal + self.shortVal = shortVal + self.str = str + } +} +""" primitiveTypesInput.shouldContain(expected) } @@ -137,9 +135,8 @@ class StructureGeneratorTests { generator.render() } val contents = writer.toString() - val expected = - """ -public struct RecursiveShapesInputOutputNested1 { + val expected = """ +public struct RecursiveShapesInputOutputNested1: Swift.Sendable { public var foo: Swift.String? @Indirect public var nested: RecursiveShapesInputOutputNested2? @@ -153,7 +150,7 @@ public struct RecursiveShapesInputOutputNested1 { } } -public struct RecursiveShapesInputOutputNested2 { +public struct RecursiveShapesInputOutputNested2: Swift.Sendable { public var bar: Swift.String? public var recursiveMember: RecursiveShapesInputOutputNested1? @@ -168,7 +165,7 @@ public struct RecursiveShapesInputOutputNested2 { } /// This is documentation about the shape. -public struct RecursiveShapesInputOutput { +public struct RecursiveShapesInputOutput: Swift.Sendable { public var nested: RecursiveShapesInputOutputNested1? public init( @@ -178,7 +175,7 @@ public struct RecursiveShapesInputOutput { self.nested = nested } } - """.trimIndent() +""" contents.shouldContainOnlyOnce(expected) } @@ -195,9 +192,8 @@ public struct RecursiveShapesInputOutput { generator.render() } val contents = writer.toString() - val expected = - """ -public struct RecursiveShapesInputOutputNestedList1 { + val expected = """ +public struct RecursiveShapesInputOutputNestedList1: Swift.Sendable { public var foo: Swift.String? public var recursiveList: [RecursiveShapesInputOutputNested2]? @@ -211,7 +207,7 @@ public struct RecursiveShapesInputOutputNestedList1 { } } -public struct RecursiveShapesInputOutputNested2 { +public struct RecursiveShapesInputOutputNested2: Swift.Sendable { public var bar: Swift.String? public var recursiveMember: RecursiveShapesInputOutputNested1? @@ -226,7 +222,7 @@ public struct RecursiveShapesInputOutputNested2 { } /// This is documentation about the shape. -public struct RecursiveShapesInputOutputLists { +public struct RecursiveShapesInputOutputLists: Swift.Sendable { public var nested: RecursiveShapesInputOutputNested1? public init( @@ -236,7 +232,7 @@ public struct RecursiveShapesInputOutputLists { self.nested = nested } } - """.trimIndent() +""" contents.shouldContainOnlyOnce(expected) } @@ -309,7 +305,7 @@ public struct MyError: ClientRuntime.ModeledError, ClientRuntime.ServiceError, C contents.shouldSyntacticSanityCheck() val expectedContents = """ -public struct JsonListsInput { +public struct JsonListsInput: Swift.Sendable { public var booleanList: [Swift.Bool]? public var integerList: [Swift.Int]? public var nestedStringList: [[Swift.String]]? @@ -356,7 +352,7 @@ public struct JsonListsInput { .getFileString("Sources/example/models/JsonMapsInput.swift").get() Assertions.assertNotNull(jsonMapsInput) val expectedJsonMapsInput = """ -public struct JsonMapsInput { +public struct JsonMapsInput: Swift.Sendable { public var denseBooleanMap: [Swift.String: Swift.Bool]? public var denseNumberMap: [Swift.String: Swift.Int]? public var denseStringMap: [Swift.String: Swift.String]? @@ -394,7 +390,7 @@ public struct JsonMapsInput { .getFileString("Sources/example/models/JsonMapsOutput.swift").get() Assertions.assertNotNull(jsonMapsOutput) val expectedJsonMapsOutput = """ -public struct JsonMapsOutput { +public struct JsonMapsOutput: Swift.Sendable { public var denseBooleanMap: [Swift.String: Swift.Bool]? public var denseNumberMap: [Swift.String: Swift.Int]? public var denseStringMap: [Swift.String: Swift.String]? @@ -440,20 +436,22 @@ public struct JsonMapsOutput { .getFileString("Sources/example/models/StructWithDeprecatedTrait.swift").get() Assertions.assertNotNull(structWithDeprecatedTrait) var structContainsDeprecatedTrait = """ - extension ExampleClientTypes { - @available(*, deprecated, message: "This shape is no longer used. API deprecated since 1.3") - public struct StructWithDeprecatedTrait { - """.trimIndent() +extension ExampleClientTypes { + + @available(*, deprecated, message: "This shape is no longer used. API deprecated since 1.3") + public struct StructWithDeprecatedTrait: Swift.Sendable { +""" structWithDeprecatedTrait.shouldContain(structContainsDeprecatedTrait) structWithDeprecatedTrait = manifest .getFileString("Sources/example/models/StructSincePropertySet.swift").get() Assertions.assertNotNull(structWithDeprecatedTrait) structContainsDeprecatedTrait = """ - extension ExampleClientTypes { - @available(*, deprecated, message: "API deprecated since 2019-03-21") - public struct StructSincePropertySet { - """.trimIndent() +extension ExampleClientTypes { + + @available(*, deprecated, message: "API deprecated since 2019-03-21") + public struct StructSincePropertySet: Swift.Sendable { +""" structWithDeprecatedTrait.shouldContain(structContainsDeprecatedTrait) } @@ -468,18 +466,18 @@ public struct JsonMapsOutput { .getFileString("Sources/example/models/OperationWithDeprecatedTraitInput.swift").get() Assertions.assertNotNull(structWithDeprecatedTraitMember) val structContainsDeprecatedMember = """ - @available(*, deprecated, message: "This shape is no longer used. API deprecated since 1.3") - public struct OperationWithDeprecatedTraitInput { - public var bool: Swift.Bool? - public var foo: ExampleClientTypes.Foo? - public var intVal: Swift.Int? - @available(*, deprecated) - public var string: Swift.String? - @available(*, deprecated, message: "API deprecated since 2019-03-21") - public var structSincePropertySet: ExampleClientTypes.StructSincePropertySet? - @available(*, deprecated, message: "This shape is no longer used. API deprecated since 1.3") - public var structWithDeprecatedTrait: ExampleClientTypes.StructWithDeprecatedTrait? - """.trimIndent() +@available(*, deprecated, message: "This shape is no longer used. API deprecated since 1.3") +public struct OperationWithDeprecatedTraitInput: Swift.Sendable { + public var bool: Swift.Bool? + public var foo: ExampleClientTypes.Foo? + public var intVal: Swift.Int? + @available(*, deprecated) + public var string: Swift.String? + @available(*, deprecated, message: "API deprecated since 2019-03-21") + public var structSincePropertySet: ExampleClientTypes.StructSincePropertySet? + @available(*, deprecated, message: "This shape is no longer used. API deprecated since 1.3") + public var structWithDeprecatedTrait: ExampleClientTypes.StructWithDeprecatedTrait? +""" structWithDeprecatedTraitMember.shouldContain(structContainsDeprecatedMember) } @@ -494,14 +492,15 @@ public struct JsonMapsOutput { .getFileString("Sources/example/models/Foo.swift").get() Assertions.assertNotNull(structWithDeprecatedTraitMember) val structContainsDeprecatedMember = """ - extension ExampleClientTypes { - public struct Foo { - /// Test documentation with deprecated - @available(*, deprecated) - public var baz: Swift.String? - /// Test documentation with deprecated - public var qux: Swift.String? - """.trimIndent() +extension ExampleClientTypes { + + public struct Foo: Swift.Sendable { + /// Test documentation with deprecated + @available(*, deprecated) + public var baz: Swift.String? + /// Test documentation with deprecated + public var qux: Swift.String? +""" structWithDeprecatedTraitMember.shouldContain(structContainsDeprecatedMember) } } diff --git a/smithy-swift-codegen/src/test/kotlin/UnionGeneratorTests.kt b/smithy-swift-codegen/src/test/kotlin/UnionGeneratorTests.kt index 9e9585d5d..c82c48ddc 100644 --- a/smithy-swift-codegen/src/test/kotlin/UnionGeneratorTests.kt +++ b/smithy-swift-codegen/src/test/kotlin/UnionGeneratorTests.kt @@ -41,18 +41,16 @@ class UnionGeneratorTests { contents.shouldContain(settings.copyrightNotice) - val expectedGeneratedEnum = - """ - /// Really long multi-line Documentation for MyUnion - public enum MyUnion { - case foo(Swift.String) - case baz(Swift.Int) - /// Documentation for bar - case bar(Swift.Int) - case sdkUnknown(Swift.String) - } - """.trimIndent() - + val expectedGeneratedEnum = """ +/// Really long multi-line Documentation for MyUnion +public enum MyUnion: Swift.Sendable { + case foo(Swift.String) + case baz(Swift.Int) + /// Documentation for bar + case bar(Swift.Int) + case sdkUnknown(Swift.String) +} +""" contents.shouldContain(expectedGeneratedEnum) } @@ -85,18 +83,16 @@ class UnionGeneratorTests { contents.shouldContain(settings.copyrightNotice) - val expectedGeneratedEnum = - """ - /// Really long multi-line Documentation for MyUnion - public enum MyUnion { - case foo(Swift.String) - /// Documentation for bar - case bar(Swift.Int) - case mystruct(MyStruct) - case sdkUnknown(Swift.String) - } - """.trimIndent() - + val expectedGeneratedEnum = """ +/// Really long multi-line Documentation for MyUnion +public enum MyUnion: Swift.Sendable { + case foo(Swift.String) + /// Documentation for bar + case bar(Swift.Int) + case mystruct(MyStruct) + case sdkUnknown(Swift.String) +} +""" contents.shouldContain(expectedGeneratedEnum) } @@ -125,19 +121,16 @@ class UnionGeneratorTests { contents.shouldContain(settings.copyrightNotice) - val expectedGeneratedEnum = - """ - /// Really long multi-line Documentation for MyUnion - public indirect enum MyUnion { - /// Really long multi-line Documentation for MyUnion - case foo(MyUnion) - case baz(Swift.Int) - /// Documentation for bar - case bar(Swift.Int) - case sdkUnknown(Swift.String) - } - """.trimIndent() - + val expectedGeneratedEnum = """ +public indirect enum MyUnion: Swift.Sendable { + /// Really long multi-line Documentation for MyUnion + case foo(MyUnion) + case baz(Swift.Int) + /// Documentation for bar + case bar(Swift.Int) + case sdkUnknown(Swift.String) +} +""" contents.shouldContain(expectedGeneratedEnum) } diff --git a/smithy-swift-codegen/src/test/kotlin/serde/awsjson11/NestedListEncodeJSONGenerationTests.kt b/smithy-swift-codegen/src/test/kotlin/serde/awsjson11/NestedListEncodeJSONGenerationTests.kt index 6f6a1d19c..f51c098fd 100644 --- a/smithy-swift-codegen/src/test/kotlin/serde/awsjson11/NestedListEncodeJSONGenerationTests.kt +++ b/smithy-swift-codegen/src/test/kotlin/serde/awsjson11/NestedListEncodeJSONGenerationTests.kt @@ -16,7 +16,7 @@ class NestedListEncodeJSONGenerationTests { val contents = getFileContents(context.manifest, "Sources/Example/models/ListOfMapsOperationInput.swift") contents.shouldSyntacticSanityCheck() val expectedContents = """ -public struct ListOfMapsOperationInput { +public struct ListOfMapsOperationInput: Swift.Sendable { public var targetMaps: [[Swift.String: [Swift.String]]]? public init( diff --git a/smithy-swift-codegen/src/test/kotlin/serde/xml/UnionEncodeXMLGenerationTests.kt b/smithy-swift-codegen/src/test/kotlin/serde/xml/UnionEncodeXMLGenerationTests.kt index 1e24755af..c0845f0c3 100644 --- a/smithy-swift-codegen/src/test/kotlin/serde/xml/UnionEncodeXMLGenerationTests.kt +++ b/smithy-swift-codegen/src/test/kotlin/serde/xml/UnionEncodeXMLGenerationTests.kt @@ -75,7 +75,8 @@ extension RestXmlProtocolClientTypes.XmlUnionShape { val contents = getFileContents(context.manifest, "Sources/RestXml/models/XmlUnionShape.swift") val expectedContents = """ extension ExampleClientTypes { - public indirect enum XmlUnionShape { + + public indirect enum XmlUnionShape: Swift.Sendable { case doublevalue(Swift.Double) case datavalue(Foundation.Data) case unionvalue(ExampleClientTypes.XmlUnionShape) @@ -85,7 +86,6 @@ extension ExampleClientTypes { case timestampvalue(Foundation.Date) case sdkUnknown(Swift.String) } - } """ contents.shouldContainOnlyOnce(expectedContents)