From 475e181942744bdd9339f29a5cf97fa20d06dec0 Mon Sep 17 00:00:00 2001 From: maximkrouk Date: Sat, 28 Sep 2024 17:11:36 +0200 Subject: [PATCH] feat(Swift 6.0): Prepare package for swift update --- .../xcshareddata/swiftpm/Package.resolved | 20 +-- .gitignore | 1 + .spi.yml | 2 +- Package.resolved | 18 +-- Package.swift | 17 ++- Package@swift-6.0.swift | 120 ++++++++++++++++++ .../Interception/NSObject+Interception.swift | 5 + .../Macros/MethodSelectorMacro.swift | 2 +- .../Macros/PropertySelectorMacro.swift | 2 +- .../_InterceptionUtils/ObjC+Constants.swift | 7 +- .../ObjC+RuntimeSubclassing.swift | 2 + .../MethodSelectorTests.swift | 2 +- .../PropertySelectorTests.swift | 2 +- .../InterceptionMacrosTests.swift | 2 +- .../InterceptionTests/InterceptionTests.swift | 2 +- 15 files changed, 173 insertions(+), 31 deletions(-) create mode 100644 Package@swift-6.0.swift diff --git a/.github/package.xcworkspace/xcshareddata/swiftpm/Package.resolved b/.github/package.xcworkspace/xcshareddata/swiftpm/Package.resolved index 0368460..08be743 100644 --- a/.github/package.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/.github/package.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -3,10 +3,10 @@ { "identity" : "swift-macro-testing", "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-macro-testing.git", + "location" : "https://github.com/pointfreeco/swift-macro-testing", "state" : { - "revision" : "10dcef36314ddfea6f60442169b0b320204cbd35", - "version" : "0.2.2" + "revision" : "20c1a8f3b624fb5d1503eadcaa84743050c350f4", + "version" : "0.5.2" } }, { @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/stackotter/swift-macro-toolkit.git", "state" : { - "revision" : "106daeb38eb3f52b1540aed981fc63fa22274576", - "version" : "0.3.1" + "revision" : "2eded9c9a98cba42d70fb179d516231fffcff1e4", + "version" : "0.5.0" } }, { @@ -23,17 +23,17 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-snapshot-testing", "state" : { - "revision" : "8e68404f641300bfd0e37d478683bb275926760c", - "version" : "1.15.2" + "revision" : "7b0bbbae90c41f848f90ac7b4df6c4f50068256d", + "version" : "1.17.5" } }, { "identity" : "swift-syntax", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax.git", + "location" : "https://github.com/swiftlang/swift-syntax", "state" : { - "revision" : "74203046135342e4a4a627476dd6caf8b28fe11b", - "version" : "509.0.0" + "revision" : "2bc86522d115234d1f588efe2bcb4ce4be8f8b82", + "version" : "510.0.3" } } ], diff --git a/.gitignore b/.gitignore index 0023a53..47bd4c1 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ DerivedData/ .swiftpm/configuration/registries.json .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata .netrc +Package.resolved diff --git a/.spi.yml b/.spi.yml index ef0bb96..0ee44d8 100644 --- a/.spi.yml +++ b/.spi.yml @@ -2,4 +2,4 @@ version: 1 builder: configs: - documentation_targets: [Interception] - swift_version: 5.9 + swift_version: 5.10 diff --git a/Package.resolved b/Package.resolved index 0368460..c342ec2 100644 --- a/Package.resolved +++ b/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-macro-testing.git", "state" : { - "revision" : "10dcef36314ddfea6f60442169b0b320204cbd35", - "version" : "0.2.2" + "revision" : "20c1a8f3b624fb5d1503eadcaa84743050c350f4", + "version" : "0.5.2" } }, { @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/stackotter/swift-macro-toolkit.git", "state" : { - "revision" : "106daeb38eb3f52b1540aed981fc63fa22274576", - "version" : "0.3.1" + "revision" : "2eded9c9a98cba42d70fb179d516231fffcff1e4", + "version" : "0.5.0" } }, { @@ -23,17 +23,17 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-snapshot-testing", "state" : { - "revision" : "8e68404f641300bfd0e37d478683bb275926760c", - "version" : "1.15.2" + "revision" : "7b0bbbae90c41f848f90ac7b4df6c4f50068256d", + "version" : "1.17.5" } }, { "identity" : "swift-syntax", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax.git", + "location" : "https://github.com/swiftlang/swift-syntax", "state" : { - "revision" : "74203046135342e4a4a627476dd6caf8b28fe11b", - "version" : "509.0.0" + "revision" : "2bc86522d115234d1f588efe2bcb4ce4be8f8b82", + "version" : "510.0.3" } } ], diff --git a/Package.swift b/Package.swift index f6388fe..60aee04 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.9 +// swift-tools-version:5.10 import PackageDescription import CompilerPluginSupport @@ -10,7 +10,7 @@ let package = Package( .macOS(.v10_15), .tvOS(.v13), .macCatalyst(.v13), - .watchOS(.v6) + .watchOS(.v6), ], products: [ .library( @@ -42,11 +42,11 @@ let package = Package( dependencies: [ .package( url: "https://github.com/stackotter/swift-macro-toolkit.git", - .upToNextMinor(from: "0.3.0") + .upToNextMinor(from: "0.5.0") ), .package( url: "https://github.com/pointfreeco/swift-macro-testing.git", - .upToNextMinor(from: "0.2.2") + .upToNextMinor(from: "0.5.0") ) ], targets: [ @@ -109,3 +109,12 @@ let package = Package( ), ] ) + +#if compiler(>=6) +for target in package.targets where target.type != .system && target.type != .test { + target.swiftSettings = target.swiftSettings ?? [] + target.swiftSettings?.append(contentsOf: [ + .enableUpcomingFeature("InferSendableFromCaptures") + ]) +} +#endif diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift new file mode 100644 index 0000000..b479db6 --- /dev/null +++ b/Package@swift-6.0.swift @@ -0,0 +1,120 @@ +// swift-tools-version:6.0 + +import PackageDescription +import CompilerPluginSupport + +let package = Package( + name: "swift-interception", + platforms: [ + .iOS(.v13), + .macOS(.v10_15), + .tvOS(.v13), + .macCatalyst(.v13), + .watchOS(.v6), + ], + products: [ + .library( + name: "_InterceptionCustomSelectors", + type: .static, + targets: ["_InterceptionCustomSelectors"] + ), + .library( + name: "_InterceptionMacros", + type: .static, + targets: ["_InterceptionMacros"] + ), + .library( + name: "_InterceptionUtils", + type: .static, + targets: ["_InterceptionUtils"] + ), + .library( + name: "Interception", + type: .static, + targets: ["Interception"] + ), + .library( + name: "InterceptionMacros", + type: .static, + targets: ["InterceptionMacros"] + ), + ], + dependencies: [ + .package( + url: "https://github.com/stackotter/swift-macro-toolkit.git", + .upToNextMinor(from: "0.5.0") + ), + .package( + url: "https://github.com/pointfreeco/swift-macro-testing.git", + .upToNextMinor(from: "0.5.2") + ) + ], + targets: [ + .target( + name: "_InterceptionMacros", + dependencies: [ + .target(name: "InterceptionMacrosPlugin"), + .target(name: "_InterceptionCustomSelectors") + ] + ), + .target(name: "_InterceptionCustomSelectors"), + .target(name: "_InterceptionUtilsObjc"), + .target( + name: "_InterceptionUtils", + dependencies: [ + .target(name: "_InterceptionUtilsObjc"), + ] + ), + .target( + name: "Interception", + dependencies: [ + .target(name: "_InterceptionCustomSelectors"), + .target(name: "_InterceptionUtils"), + ] + ), + .target( + name: "InterceptionMacros", + dependencies: [ + .target(name: "_InterceptionMacros"), + .target(name: "Interception") + ] + ), + .macro( + name: "InterceptionMacrosPlugin", + dependencies: [ + .product( + name: "MacroToolkit", + package: "swift-macro-toolkit" + ) + ] + ), + .testTarget( + name: "InterceptionMacrosPluginTests", + dependencies: [ + .target(name: "InterceptionMacrosPlugin"), + .product(name: "MacroTesting", package: "swift-macro-testing"), + ] + ), + .testTarget( + name: "InterceptionTests", + dependencies: [ + .target(name: "Interception"), + ] + ), + .testTarget( + name: "InterceptionMacrosTests", + dependencies: [ + .target(name: "InterceptionMacros"), + ] + ), + ], + swiftLanguageModes: [.v6] +) + +for target in package.targets where target.type == .system || target.type == .test { + target.swiftSettings?.append(contentsOf: [ + .swiftLanguageMode(.v5), + .enableExperimentalFeature("StrictConcurrency"), + .enableUpcomingFeature("InferSendableFromCaptures"), + ]) +} diff --git a/Sources/Interception/NSObject+Interception.swift b/Sources/Interception/NSObject+Interception.swift index f1c4a70..c30ccb3 100644 --- a/Sources/Interception/NSObject+Interception.swift +++ b/Sources/Interception/NSObject+Interception.swift @@ -5,14 +5,18 @@ import _InterceptionCustomSelectors /// Whether the runtime subclass has already been prepared for method /// interception. +nonisolated(unsafe) private let interceptedKey = AssociationKey(default: false) /// Holds the method signature cache of the runtime subclass. +nonisolated(unsafe) private let signatureCacheKey = AssociationKey() /// Holds the method selector cache of the runtime subclass. +nonisolated(unsafe) private let selectorCacheKey = AssociationKey() +nonisolated(unsafe) internal let noImplementation: IMP = unsafeBitCast(Int(0), to: IMP.self) extension NSObject { @@ -327,6 +331,7 @@ private func setupMethodSignatureCaching(_ realClass: AnyClass, _ signatureCache @_spi(Internals) public struct SwiftInterceptionDefaultInterceptionHandlerKey: Hashable { + nonisolated(unsafe) public static let shared: Self = .init() private init() {} diff --git a/Sources/InterceptionMacrosPlugin/Macros/MethodSelectorMacro.swift b/Sources/InterceptionMacrosPlugin/Macros/MethodSelectorMacro.swift index 0fc687b..2f7f593 100644 --- a/Sources/InterceptionMacrosPlugin/Macros/MethodSelectorMacro.swift +++ b/Sources/InterceptionMacrosPlugin/Macros/MethodSelectorMacro.swift @@ -11,7 +11,7 @@ public struct MethodSelectorMacro: ExpressionMacro { of node: Node, in context: Context ) -> ExprSyntax { - guard let arg = node.argumentList.first.map(\.expression) + guard let arg = node.arguments.first.map(\.expression) else { fatalError("compiler bug: the macro does not have any arguments") } return """ diff --git a/Sources/InterceptionMacrosPlugin/Macros/PropertySelectorMacro.swift b/Sources/InterceptionMacrosPlugin/Macros/PropertySelectorMacro.swift index e9ce530..40e2de3 100644 --- a/Sources/InterceptionMacrosPlugin/Macros/PropertySelectorMacro.swift +++ b/Sources/InterceptionMacrosPlugin/Macros/PropertySelectorMacro.swift @@ -10,7 +10,7 @@ public struct PropertySelectorMacro: ExpressionMacro { of node: Node, in context: Context ) -> ExprSyntax { - guard let arg = node.argumentList.first.map(\.expression) + guard let arg = node.arguments.first.map(\.expression) else { fatalError("compiler bug: the macro does not have any arguments") } return """ diff --git a/Sources/_InterceptionUtils/ObjC+Constants.swift b/Sources/_InterceptionUtils/ObjC+Constants.swift index bff2775..fb43b9f 100644 --- a/Sources/_InterceptionUtils/ObjC+Constants.swift +++ b/Sources/_InterceptionUtils/ObjC+Constants.swift @@ -9,10 +9,15 @@ public enum ObjCSelector { // Method encoding of the unavailable selectors. public enum ObjCMethodEncoding { + nonisolated(unsafe) public static let forwardInvocation = extract("v@:@") + + nonisolated(unsafe) public static let methodSignatureForSelector = extract("v@::") + + nonisolated(unsafe) public static let getClass = extract("#@:") - + private static func extract(_ string: StaticString) -> UnsafePointer { return UnsafeRawPointer(string.utf8Start).assumingMemoryBound(to: CChar.self) } diff --git a/Sources/_InterceptionUtils/ObjC+RuntimeSubclassing.swift b/Sources/_InterceptionUtils/ObjC+RuntimeSubclassing.swift index 7560ac7..e9a6368 100644 --- a/Sources/_InterceptionUtils/ObjC+RuntimeSubclassing.swift +++ b/Sources/_InterceptionUtils/ObjC+RuntimeSubclassing.swift @@ -3,10 +3,12 @@ import Combine import Foundation /// Whether the runtime subclass has already been swizzled. +nonisolated(unsafe) private let runtimeSubclassedKey = AssociationKey(default: false) /// A known combine-interception runtime subclass of the instance. `nil` if the runtime subclass /// has not been requested for the instance before. +nonisolated(unsafe) private let knownRuntimeSubclassKey = AssociationKey(default: nil) extension NSObject { diff --git a/Tests/InterceptionMacrosPluginTests/MethodSelectorTests.swift b/Tests/InterceptionMacrosPluginTests/MethodSelectorTests.swift index 7850e67..b853288 100644 --- a/Tests/InterceptionMacrosPluginTests/MethodSelectorTests.swift +++ b/Tests/InterceptionMacrosPluginTests/MethodSelectorTests.swift @@ -5,7 +5,7 @@ import InterceptionMacrosPlugin final class MethodSelectorTests: XCTestCase { override func invokeTest() { withMacroTesting( - isRecording: false, + record: false, macros: [ "methodSelector": MethodSelectorMacro.self ] diff --git a/Tests/InterceptionMacrosPluginTests/PropertySelectorTests.swift b/Tests/InterceptionMacrosPluginTests/PropertySelectorTests.swift index 553071b..e5832e3 100644 --- a/Tests/InterceptionMacrosPluginTests/PropertySelectorTests.swift +++ b/Tests/InterceptionMacrosPluginTests/PropertySelectorTests.swift @@ -5,7 +5,7 @@ import InterceptionMacrosPlugin final class PropertySelectorTests: XCTestCase { override func invokeTest() { withMacroTesting( - isRecording: false, + record: false, macros: [ "propertySelector": PropertySelectorMacro.self ] diff --git a/Tests/InterceptionMacrosTests/InterceptionMacrosTests.swift b/Tests/InterceptionMacrosTests/InterceptionMacrosTests.swift index 26726b5..f01ddb7 100644 --- a/Tests/InterceptionMacrosTests/InterceptionMacrosTests.swift +++ b/Tests/InterceptionMacrosTests/InterceptionMacrosTests.swift @@ -127,7 +127,7 @@ final class InterceptionMacrosTests: XCTestCase { } } -fileprivate class Object: NSObject { +fileprivate final class Object: NSObject, Sendable { @discardableResult @objc dynamic func zero() -> Int { 0 } diff --git a/Tests/InterceptionTests/InterceptionTests.swift b/Tests/InterceptionTests/InterceptionTests.swift index 4c131b8..ce0fc19 100644 --- a/Tests/InterceptionTests/InterceptionTests.swift +++ b/Tests/InterceptionTests/InterceptionTests.swift @@ -142,7 +142,7 @@ final class InterceptionTests: XCTestCase { } } -fileprivate class Object: NSObject { +fileprivate final class Object: NSObject, Sendable { @discardableResult @objc dynamic func zero() -> Int { 0 }