From 911d8707376a05a8591849c862d40517ae3201b8 Mon Sep 17 00:00:00 2001 From: Florian Friedrich Date: Tue, 12 Mar 2024 09:25:48 +0100 Subject: [PATCH] Add Swift 5.10 support --- .github/workflows/swift-test.yml | 7 +- Package.swift | 21 ++++-- Package@swift-5.9.swift | 67 +++++++++++++++++++ .../BWA/Platforms/BWA+CoreGraphics.swift | 2 +- .../XYZ/Platforms/CIEXYZA+CoreGraphics.swift | 2 +- .../Helpers/CGColor+RequireColorSpace.swift | 5 ++ .../RGBA/Platforms/RGBA+CoreGraphics.swift | 2 +- .../ImageColorsCalculatorTests.swift | 8 +-- .../BWA/Platforms/BWA+SwiftUITests.swift | 8 ++- .../XYZ/Platforms/CIEXYZA+SwiftUITests.swift | 8 ++- .../HSBA/Platforms/HSBA+SwiftUITests.swift | 8 ++- .../HSLA/Platforms/HSLA+SwiftUITests.swift | 8 ++- .../RGBA/Platforms/RGBA+SwiftUITests.swift | 8 ++- .../RGBA/RGBA+HexTests.swift | 2 +- 14 files changed, 123 insertions(+), 33 deletions(-) create mode 100644 Package@swift-5.9.swift diff --git a/.github/workflows/swift-test.yml b/.github/workflows/swift-test.yml index cceeaaeb..3558cd44 100644 --- a/.github/workflows/swift-test.yml +++ b/.github/workflows/swift-test.yml @@ -12,7 +12,7 @@ permissions: jobs: variables: outputs: - max-supported-swift-version: '5.9' + max-supported-swift-version: '5.10' xcode-scheme: color-components-Package xcode-platform-version: latest fail-if-codecov-fails: true @@ -25,7 +25,7 @@ jobs: strategy: matrix: os: [ macOS, ubuntu ] - swift-version-offset: [ 0 ] + swift-version-offset: [ 0, 1 ] uses: sersoft-gmbh/oss-common-actions/.github/workflows/swift-test-spm.yml@main with: os: ${{ matrix.os }} @@ -45,7 +45,8 @@ jobs: - iPadOS - tvOS - watchOS - swift-version-offset: [ 0 ] + - visionOS + swift-version-offset: [ 0, 1 ] uses: sersoft-gmbh/oss-common-actions/.github/workflows/swift-test-xcode.yml@main with: xcode-scheme: ${{ needs.variables.outputs.xcode-scheme }} diff --git a/Package.swift b/Package.swift index 34a740aa..930f488c 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.9 +// swift-tools-version:5.10 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription @@ -8,9 +8,16 @@ let swiftSettings: Array = [ .enableUpcomingFeature("ExistentialAny"), .enableUpcomingFeature("BareSlashRegexLiterals"), .enableUpcomingFeature("DisableOutwardActorInference"), + .enableUpcomingFeature("IsolatedDefaultValues"), + .enableUpcomingFeature("DeprecateApplicationMain"), // .enableExperimentalFeature("AccessLevelOnImport"), // .enableExperimentalFeature("VariadicGenerics"), -// .unsafeFlags(["-warn-concurrency"], .when(configuration: .debug)), +] + +let concurrencySwiftSettings: Array = [ + // Not yet possible for ColorCalculations due to CIFormat constants being mutable. + .enableExperimentalFeature("StrictConcurrency"), + .enableExperimentalFeature("GlobalConcurrency"), ] let package = Package( @@ -32,16 +39,16 @@ let package = Package( // Targets can depend on other targets in this package, and on products in packages this package depends on. .target( name: "ColorComponents", - swiftSettings: swiftSettings), + swiftSettings: swiftSettings + concurrencySwiftSettings), .target( name: "ColorCalculations", dependencies: ["ColorComponents"], swiftSettings: swiftSettings), .target( name: "XCHelpers", - swiftSettings: swiftSettings, + swiftSettings: swiftSettings + concurrencySwiftSettings, linkerSettings: [ - .linkedFramework("XCTest", .when(platforms: [.iOS, .macOS, .macCatalyst, .tvOS, .watchOS])), + .linkedFramework("XCTest", .when(platforms: [.iOS, .macOS, .macCatalyst, .tvOS, .watchOS, .visionOS])), ]), .testTarget( name: "ColorComponentsTests", @@ -49,7 +56,7 @@ let package = Package( "ColorComponents", "XCHelpers", ], - swiftSettings: swiftSettings), + swiftSettings: swiftSettings + concurrencySwiftSettings), .testTarget( name: "ColorCalculationsTests", dependencies: [ @@ -59,6 +66,6 @@ let package = Package( resources: [ .copy("TestImages"), ], - swiftSettings: swiftSettings), + swiftSettings: swiftSettings + concurrencySwiftSettings), ] ) diff --git a/Package@swift-5.9.swift b/Package@swift-5.9.swift new file mode 100644 index 00000000..71491e03 --- /dev/null +++ b/Package@swift-5.9.swift @@ -0,0 +1,67 @@ +// swift-tools-version:5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let swiftSettings: Array = [ + .enableUpcomingFeature("ConciseMagicFile"), + .enableUpcomingFeature("ExistentialAny"), + .enableUpcomingFeature("BareSlashRegexLiterals"), + .enableUpcomingFeature("DisableOutwardActorInference"), +// .enableExperimentalFeature("VariadicGenerics"), +] + +let concurrencySwiftSettings: Array = [ + // Not yet possible for ColorCalculations due to CIFormat constants being mutable. + .enableExperimentalFeature("StrictConcurrency"), +] + +let package = Package( + name: "color-components", + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "ColorComponents", + targets: ["ColorComponents"]), + .library( + name: "ColorCalculations", + targets: ["ColorCalculations"]), + ], + dependencies: [ + .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "ColorComponents", + swiftSettings: swiftSettings + concurrencySwiftSettings), + .target( + name: "ColorCalculations", + dependencies: ["ColorComponents"], + swiftSettings: swiftSettings), + .target( + name: "XCHelpers", + swiftSettings: swiftSettings + concurrencySwiftSettings, + linkerSettings: [ + .linkedFramework("XCTest", .when(platforms: [.iOS, .macOS, .macCatalyst, .tvOS, .watchOS, .visionOS])), + ]), + .testTarget( + name: "ColorComponentsTests", + dependencies: [ + "ColorComponents", + "XCHelpers", + ], + swiftSettings: swiftSettings + concurrencySwiftSettings), + .testTarget( + name: "ColorCalculationsTests", + dependencies: [ + "ColorCalculations", + "XCHelpers", + ], + resources: [ + .copy("TestImages"), + ], + swiftSettings: swiftSettings + concurrencySwiftSettings), + ] +) diff --git a/Sources/ColorComponents/BWA/Platforms/BWA+CoreGraphics.swift b/Sources/ColorComponents/BWA/Platforms/BWA+CoreGraphics.swift index dd532fc3..77bd1fba 100644 --- a/Sources/ColorComponents/BWA/Platforms/BWA+CoreGraphics.swift +++ b/Sources/ColorComponents/BWA/Platforms/BWA+CoreGraphics.swift @@ -7,7 +7,7 @@ extension CGColor { func _extractBW(alpha: UnsafeMutablePointer? = nil) -> BW { let color = _requireColorSpace(named: CGColorSpace.genericGray) let components = color._requireCompontens(in: 1...2) - if let alpha = alpha { + if let alpha { alpha.pointee = color.alpha } return .init(white: components[0]) diff --git a/Sources/ColorComponents/CIE/XYZ/Platforms/CIEXYZA+CoreGraphics.swift b/Sources/ColorComponents/CIE/XYZ/Platforms/CIEXYZA+CoreGraphics.swift index 3b50b874..0c6493c6 100644 --- a/Sources/ColorComponents/CIE/XYZ/Platforms/CIEXYZA+CoreGraphics.swift +++ b/Sources/ColorComponents/CIE/XYZ/Platforms/CIEXYZA+CoreGraphics.swift @@ -7,7 +7,7 @@ extension CGColor { func _extractCIEXYZ(alpha: UnsafeMutablePointer? = nil) -> CIE.XYZ { let color = _requireColorSpace(named: CGColorSpace.genericXYZ) let components = color._requireCompontens(in: 3...4) - if let alpha = alpha { + if let alpha { alpha.pointee = color.alpha } return .init(x: components[0], y: components[1], z: components[2]) diff --git a/Sources/ColorComponents/Helpers/CGColor+RequireColorSpace.swift b/Sources/ColorComponents/Helpers/CGColor+RequireColorSpace.swift index 3154aa89..60b5caac 100644 --- a/Sources/ColorComponents/Helpers/CGColor+RequireColorSpace.swift +++ b/Sources/ColorComponents/Helpers/CGColor+RequireColorSpace.swift @@ -3,8 +3,13 @@ import CoreGraphics extension CGColorSpace { // There seems to be no constants for these in CoreGraphics... +#if compiler(>=5.10) && hasFeature(StrictConcurrency) && hasFeature(GlobalConcurrency) + static nonisolated(unsafe) let genericGray: CFString = "kCGColorSpaceGenericGray" as CFString + static nonisolated(unsafe) let genericRGB: CFString = "kCGColorSpaceGenericRGB" as CFString +#else static let genericGray: CFString = "kCGColorSpaceGenericGray" as CFString static let genericRGB: CFString = "kCGColorSpaceGenericRGB" as CFString +#endif } extension CGColorSpace { diff --git a/Sources/ColorComponents/RGBA/Platforms/RGBA+CoreGraphics.swift b/Sources/ColorComponents/RGBA/Platforms/RGBA+CoreGraphics.swift index e87b09e8..6f154c6e 100644 --- a/Sources/ColorComponents/RGBA/Platforms/RGBA+CoreGraphics.swift +++ b/Sources/ColorComponents/RGBA/Platforms/RGBA+CoreGraphics.swift @@ -7,7 +7,7 @@ extension CGColor { func _extractRGB(alpha: UnsafeMutablePointer? = nil) -> RGB { let color = _requireColorSpace(named: CGColorSpace.genericRGB) let components = color._requireCompontens(in: 3...4) - if let alpha = alpha { + if let alpha { alpha.pointee = color.alpha } return .init(red: components[0], green: components[1], blue: components[2]) diff --git a/Tests/ColorCalculationsTests/ImageColorsCalculatorTests.swift b/Tests/ColorCalculationsTests/ImageColorsCalculatorTests.swift index 73e540fc..3968dda8 100644 --- a/Tests/ColorCalculationsTests/ImageColorsCalculatorTests.swift +++ b/Tests/ColorCalculationsTests/ImageColorsCalculatorTests.swift @@ -162,7 +162,7 @@ final class ImageColorsCalculatorTests: XCTestCase { #endif } - func testUIImageInitializer() throws { + func testUIImageInitializer() async throws { #if !canImport(CoreImage) || !canImport(UIKit) try skipUnavailableAPI() #else @@ -182,13 +182,13 @@ final class ImageColorsCalculatorTests: XCTestCase { let uiImage = try XCTUnwrap(UIImage(contentsOfFile: img1URL.path)) let calculator = ImageColorsCalculator(uiImage: uiImage) XCTAssertNotNil(calculator) - let uiImage2 = try XCTUnwrap(NonCIUIImage(contentsOfFile: img2URL.path)) + let uiImage2 = try await MainActor.run { [img2URL] in try XCTUnwrap(NonCIUIImage(contentsOfFile: img2URL.path)) } let calculator2 = ImageColorsCalculator(uiImage: uiImage2) XCTAssertNotNil(calculator2) - let uiImage3 = try NonCGUIImage(ciImage: XCTUnwrap(CIImage(contentsOf: img1URL))) + let uiImage3 = try await MainActor.run { [img1URL] in try NonCGUIImage(ciImage: XCTUnwrap(CIImage(contentsOf: img1URL))) } let calculator3 = ImageColorsCalculator(uiImage: uiImage3) XCTAssertNotNil(calculator3) - let uiImage4 = try XCTUnwrap(NonBackingUIImage(contentsOfFile: img1URL.path)) + let uiImage4 = try await MainActor.run { [img1URL] in try XCTUnwrap(NonBackingUIImage(contentsOfFile: img1URL.path)) } let calculator4 = ImageColorsCalculator(uiImage: uiImage4) XCTAssertNil(calculator4) #endif diff --git a/Tests/ColorComponentsTests/BWA/Platforms/BWA+SwiftUITests.swift b/Tests/ColorComponentsTests/BWA/Platforms/BWA+SwiftUITests.swift index 85b49d15..314332f4 100644 --- a/Tests/ColorComponentsTests/BWA/Platforms/BWA+SwiftUITests.swift +++ b/Tests/ColorComponentsTests/BWA/Platforms/BWA+SwiftUITests.swift @@ -108,7 +108,7 @@ final class BWA_SwiftUITests: XCTestCase { #endif } - func testViewConformance() throws { + func testViewConformance() async throws { #if arch(arm64) || arch(x86_64) #if canImport(SwiftUI) && canImport(Combine) && (canImport(UIKit) || (canImport(AppKit) && !targetEnvironment(macCatalyst)) || canImport(CoreGraphics)) guard #available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) @@ -117,8 +117,10 @@ final class BWA_SwiftUITests: XCTestCase { let bw = BW(white: 0.5) let bwa = BWA(bw: bw, alpha: 0.25) - XCTAssertEqual(bw.body as? Color, Color(bw)) - XCTAssertEqual(bwa.body as? Color, Color(bwa)) + await MainActor.run { + XCTAssertEqual(bw.body as? Color, Color(bw)) + XCTAssertEqual(bwa.body as? Color, Color(bwa)) + } #else try skipUnavailableAPI() #endif diff --git a/Tests/ColorComponentsTests/CIE/XYZ/Platforms/CIEXYZA+SwiftUITests.swift b/Tests/ColorComponentsTests/CIE/XYZ/Platforms/CIEXYZA+SwiftUITests.swift index eb52e829..941d7dad 100644 --- a/Tests/ColorComponentsTests/CIE/XYZ/Platforms/CIEXYZA+SwiftUITests.swift +++ b/Tests/ColorComponentsTests/CIE/XYZ/Platforms/CIEXYZA+SwiftUITests.swift @@ -120,7 +120,7 @@ final class CIEXYZA_SwiftUITests: XCTestCase { #endif } - func testViewConformance() throws { + func testViewConformance() async throws { #if arch(arm64) || arch(x86_64) #if canImport(SwiftUI) && canImport(Combine) && (canImport(UIKit) || (canImport(AppKit) && !targetEnvironment(macCatalyst)) || canImport(CoreGraphics)) guard #available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) @@ -129,8 +129,10 @@ final class CIEXYZA_SwiftUITests: XCTestCase { let cieXYZ = CIE.XYZ(x: 0.5, y: 0.25, z: 0.75) let cieXYZA = CIE.XYZA(xyz: cieXYZ, alpha: 0.25) - XCTAssertEqual(cieXYZ.body as? Color, Color(cieXYZ)) - XCTAssertEqual(cieXYZA.body as? Color, Color(cieXYZA)) + await MainActor.run { + XCTAssertEqual(cieXYZ.body as? Color, Color(cieXYZ)) + XCTAssertEqual(cieXYZA.body as? Color, Color(cieXYZA)) + } #else try skipUnavailableAPI() #endif diff --git a/Tests/ColorComponentsTests/HSBA/Platforms/HSBA+SwiftUITests.swift b/Tests/ColorComponentsTests/HSBA/Platforms/HSBA+SwiftUITests.swift index ba30bc1d..4c8a0a2e 100644 --- a/Tests/ColorComponentsTests/HSBA/Platforms/HSBA+SwiftUITests.swift +++ b/Tests/ColorComponentsTests/HSBA/Platforms/HSBA+SwiftUITests.swift @@ -124,7 +124,7 @@ final class HSBA_SwiftUITests: XCTestCase { #endif } - func testViewConformance() throws { + func testViewConformance() async throws { #if arch(arm64) || arch(x86_64) #if canImport(SwiftUI) && canImport(Combine) && (canImport(UIKit) || (canImport(AppKit) && !targetEnvironment(macCatalyst)) || canImport(CoreGraphics)) guard #available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) @@ -133,8 +133,10 @@ final class HSBA_SwiftUITests: XCTestCase { let hsb = HSB(hue: 0.5, saturation: 0.25, brightness: 0.75) let hsba = HSBA(hsb: hsb, alpha: 0.25) - XCTAssertEqual(hsb.body as? Color, Color(hsb)) - XCTAssertEqual(hsba.body as? Color, Color(hsba)) + await MainActor.run { + XCTAssertEqual(hsb.body as? Color, Color(hsb)) + XCTAssertEqual(hsba.body as? Color, Color(hsba)) + } #else try skipUnavailableAPI() #endif diff --git a/Tests/ColorComponentsTests/HSLA/Platforms/HSLA+SwiftUITests.swift b/Tests/ColorComponentsTests/HSLA/Platforms/HSLA+SwiftUITests.swift index 0bf98dfb..f6b471ed 100644 --- a/Tests/ColorComponentsTests/HSLA/Platforms/HSLA+SwiftUITests.swift +++ b/Tests/ColorComponentsTests/HSLA/Platforms/HSLA+SwiftUITests.swift @@ -124,7 +124,7 @@ final class HSLA_SwiftUITests: XCTestCase { #endif } - func testViewConformance() throws { + func testViewConformance() async throws { #if arch(arm64) || arch(x86_64) #if canImport(SwiftUI) && canImport(Combine) && (canImport(UIKit) || (canImport(AppKit) && !targetEnvironment(macCatalyst)) || canImport(CoreGraphics)) guard #available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) @@ -133,8 +133,10 @@ final class HSLA_SwiftUITests: XCTestCase { let hsl = HSL(hue: 0.5, saturation: 0.25, luminance: 0.75) let hsla = HSLA(hsl: hsl, alpha: 0.25) - XCTAssertEqual(hsl.body as? Color, Color(hsl)) - XCTAssertEqual(hsla.body as? Color, Color(hsla)) + await MainActor.run { + XCTAssertEqual(hsl.body as? Color, Color(hsl)) + XCTAssertEqual(hsla.body as? Color, Color(hsla)) + } #else try skipUnavailableAPI() #endif diff --git a/Tests/ColorComponentsTests/RGBA/Platforms/RGBA+SwiftUITests.swift b/Tests/ColorComponentsTests/RGBA/Platforms/RGBA+SwiftUITests.swift index d4539636..44fbb5cf 100644 --- a/Tests/ColorComponentsTests/RGBA/Platforms/RGBA+SwiftUITests.swift +++ b/Tests/ColorComponentsTests/RGBA/Platforms/RGBA+SwiftUITests.swift @@ -123,7 +123,7 @@ final class RGBA_SwiftUITests: XCTestCase { #endif } - func testViewConformance() throws { + func testViewConformance() async throws { #if arch(arm64) || arch(x86_64) #if canImport(SwiftUI) && canImport(Combine) && (canImport(UIKit) || (canImport(AppKit) && !targetEnvironment(macCatalyst)) || canImport(CoreGraphics)) guard #available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) @@ -132,8 +132,10 @@ final class RGBA_SwiftUITests: XCTestCase { let rgb = RGB(red: 0.5, green: 0.25, blue: 0.75) let rgba = RGBA(rgb: rgb, alpha: 0.25) - XCTAssertEqual(rgb.body as? Color, Color(rgb)) - XCTAssertEqual(rgba.body as? Color, Color(rgba)) + await MainActor.run { + XCTAssertEqual(rgb.body as? Color, Color(rgb)) + XCTAssertEqual(rgba.body as? Color, Color(rgba)) + } #else try skipUnavailableAPI() #endif diff --git a/Tests/ColorComponentsTests/RGBA/RGBA+HexTests.swift b/Tests/ColorComponentsTests/RGBA/RGBA+HexTests.swift index 293f204a..d7945314 100644 --- a/Tests/ColorComponentsTests/RGBA/RGBA+HexTests.swift +++ b/Tests/ColorComponentsTests/RGBA/RGBA+HexTests.swift @@ -87,7 +87,7 @@ final class RGBA_HexTests: XCTestCase { XCTAssertNil(rgbInvalid) XCTAssertNil(rgbaInvalid) - if let rgb = rgb { + if let rgb { XCTAssertEqual(rgb.red, 1, accuracy: .ulpOfOne) XCTAssertEqual(rgb.green, 0x80 / 0xFF, accuracy: .ulpOfOne) XCTAssertEqual(rgb.blue, 0x55 / 0xFF, accuracy: .ulpOfOne)