From d7791d1aa77be8247bc010cccded45793155d2cd Mon Sep 17 00:00:00 2001 From: yoshiki-tsukada Date: Sun, 22 Dec 2024 00:27:49 +0900 Subject: [PATCH 1/3] Support Sendable conformed protocol --- Sources/SpyableMacro/Factories/SpyFactory.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Sources/SpyableMacro/Factories/SpyFactory.swift b/Sources/SpyableMacro/Factories/SpyFactory.swift index 954b29a..9070e2d 100644 --- a/Sources/SpyableMacro/Factories/SpyFactory.swift +++ b/Sources/SpyableMacro/Factories/SpyFactory.swift @@ -112,7 +112,10 @@ struct SpyFactory { genericParameterClause: genericParameterClause, inheritanceClause: InheritanceClauseSyntax { InheritedTypeSyntax( - type: IdentifierTypeSyntax(name: protocolDeclaration.name) + type: TypeSyntax(stringLiteral: protocolDeclaration.name.text) + ) + InheritedTypeSyntax( + type: TypeSyntax(stringLiteral: "@unchecked Sendable") ) }, memberBlockBuilder: { From de37c38b3c85482032da3d8a645974a8b068ff24 Mon Sep 17 00:00:00 2001 From: yoshiki-tsukada Date: Sun, 22 Dec 2024 00:30:23 +0900 Subject: [PATCH 2/3] Fix failed test cases --- .../Factories/UT_SpyFactory.swift | 44 +++++++++---------- .../Macro/UT_SpyableMacro.swift | 22 +++++----- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Tests/SpyableMacroTests/Factories/UT_SpyFactory.swift b/Tests/SpyableMacroTests/Factories/UT_SpyFactory.swift index 687d14c..02a5ddc 100644 --- a/Tests/SpyableMacroTests/Factories/UT_SpyFactory.swift +++ b/Tests/SpyableMacroTests/Factories/UT_SpyFactory.swift @@ -9,7 +9,7 @@ final class UT_SpyFactory: XCTestCase { try assertProtocol( withDeclaration: "protocol Foo {}", expectingClassDeclaration: """ - class FooSpy: Foo { + class FooSpy: Foo, @unchecked Sendable { init() { } } @@ -25,7 +25,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ServiceSpy: Service { + class ServiceSpy: Service, @unchecked Sendable { init() { } var fetchCallsCount = 0 @@ -50,7 +50,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ViewModelProtocolSpy: ViewModelProtocol { + class ViewModelProtocolSpy: ViewModelProtocol, @unchecked Sendable { init() { } var fooTextCountCallsCount = 0 @@ -79,7 +79,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ViewModelProtocolSpy: ViewModelProtocol { + class ViewModelProtocolSpy: ViewModelProtocol, @unchecked Sendable { init() { } var fooModelCallsCount = 0 @@ -108,7 +108,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ViewModelProtocolSpy: ViewModelProtocol { + class ViewModelProtocolSpy: ViewModelProtocol, @unchecked Sendable { init() { } var fooModelCallsCount = 0 @@ -137,7 +137,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ViewModelProtocolSpy: ViewModelProtocol { + class ViewModelProtocolSpy: ViewModelProtocol, @unchecked Sendable { init() { } var fooModelCallsCount = 0 @@ -166,7 +166,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ViewModelProtocolSpy: ViewModelProtocol { + class ViewModelProtocolSpy: ViewModelProtocol, @unchecked Sendable { init() { } var fooModelCallsCount = 0 @@ -202,7 +202,7 @@ final class UT_SpyFactory: XCTestCase { assertBuildResult( result, """ - class ViewModelProtocolSpy: ViewModelProtocol { + class ViewModelProtocolSpy: ViewModelProtocol, @unchecked Sendable { init() { } var fooTextValueCallsCount = 0 @@ -236,7 +236,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ViewModelProtocolSpy: ViewModelProtocol { + class ViewModelProtocolSpy: ViewModelProtocol, @unchecked Sendable { init() { } var fooActionCallsCount = 0 @@ -265,7 +265,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ViewModelProtocolSpy: ViewModelProtocol { + class ViewModelProtocolSpy: ViewModelProtocol, @unchecked Sendable { init() { } var fooActionCallsCount = 0 @@ -290,7 +290,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class BarSpy: Bar { + class BarSpy: Bar, @unchecked Sendable { init() { } var printCallsCount = 0 @@ -320,7 +320,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ServiceProtocolSpy: ServiceProtocol { + class ServiceProtocolSpy: ServiceProtocol, @unchecked Sendable { init() { } var fooTextCountCallsCount = 0 @@ -354,7 +354,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ServiceProtocolSpy: ServiceProtocol { + class ServiceProtocolSpy: ServiceProtocol, @unchecked Sendable { init() { } var fooCallsCount = 0 @@ -392,7 +392,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ServiceProtocolSpy: ServiceProtocol { + class ServiceProtocolSpy: ServiceProtocol, @unchecked Sendable { init() { } var fooCallsCount = 0 @@ -422,7 +422,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ServiceProtocolSpy: ServiceProtocol { + class ServiceProtocolSpy: ServiceProtocol, @unchecked Sendable { init() { } var fooCallsCount = 0 @@ -452,7 +452,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ServiceProtocolSpy: ServiceProtocol { + class ServiceProtocolSpy: ServiceProtocol, @unchecked Sendable { init() { } var data: Data { @@ -477,7 +477,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ServiceProtocolSpy: ServiceProtocol { + class ServiceProtocolSpy: ServiceProtocol, @unchecked Sendable { init() { } var data: Data? @@ -494,7 +494,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ServiceProtocolSpy: ServiceProtocol { + class ServiceProtocolSpy: ServiceProtocol, @unchecked Sendable { init() { } var data: String! @@ -511,7 +511,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ServiceProtocolSpy: ServiceProtocol { + class ServiceProtocolSpy: ServiceProtocol, @unchecked Sendable { init() { } var data: any Codable { @@ -536,7 +536,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class ServiceProtocolSpy: ServiceProtocol { + class ServiceProtocolSpy: ServiceProtocol, @unchecked Sendable { init() { } var completion: () -> Void { @@ -563,7 +563,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class FooSpy: Foo { + class FooSpy: Foo, @unchecked Sendable { init() { } } @@ -580,7 +580,7 @@ final class UT_SpyFactory: XCTestCase { } """, expectingClassDeclaration: """ - class FooSpy: Foo { + class FooSpy: Foo, @unchecked Sendable { init() { } } diff --git a/Tests/SpyableMacroTests/Macro/UT_SpyableMacro.swift b/Tests/SpyableMacroTests/Macro/UT_SpyableMacro.swift index b629ac8..60f87de 100644 --- a/Tests/SpyableMacroTests/Macro/UT_SpyableMacro.swift +++ b/Tests/SpyableMacroTests/Macro/UT_SpyableMacro.swift @@ -50,7 +50,7 @@ final class UT_SpyableMacro: XCTestCase { \(protocolDeclaration) - public class ServiceProtocolSpy: ServiceProtocol { + public class ServiceProtocolSpy: ServiceProtocol, @unchecked Sendable { public init() { } public var name: String { @@ -223,7 +223,7 @@ final class UT_SpyableMacro: XCTestCase { \(protocolDeclaration) - class MyProtocolSpy: MyProtocol { + class MyProtocolSpy: MyProtocol, @unchecked Sendable { init() { } } @@ -244,7 +244,7 @@ final class UT_SpyableMacro: XCTestCase { \(protocolDeclaration) - class MyProtocolSpy: MyProtocol { + class MyProtocolSpy: MyProtocol, @unchecked Sendable { init() { } } @@ -266,7 +266,7 @@ final class UT_SpyableMacro: XCTestCase { \(protocolDeclaration) #if CUSTOM - class MyProtocolSpy: MyProtocol { + class MyProtocolSpy: MyProtocol, @unchecked Sendable { init() { } } @@ -293,7 +293,7 @@ final class UT_SpyableMacro: XCTestCase { \(protocolDeclaration) #if CUSTOM - class MyProtocolSpy: MyProtocol { + class MyProtocolSpy: MyProtocol, @unchecked Sendable { init() { } } @@ -315,7 +315,7 @@ final class UT_SpyableMacro: XCTestCase { \(protocolDeclaration) - class MyProtocolSpy: MyProtocol { + class MyProtocolSpy: MyProtocol, @unchecked Sendable { init() { } } @@ -353,7 +353,7 @@ final class UT_SpyableMacro: XCTestCase { let myCustomFlag = "DEBUG" \(protocolDeclaration) - class MyProtocolSpy: MyProtocol { + class MyProtocolSpy: MyProtocol, @unchecked Sendable { init() { } } @@ -404,7 +404,7 @@ final class UT_SpyableMacro: XCTestCase { \(protocolDefinition) - \(mapping.spyClassAccessLevel) class ServiceProtocolSpy: ServiceProtocol { + \(mapping.spyClassAccessLevel) class ServiceProtocolSpy: ServiceProtocol, @unchecked Sendable { \(mapping.spyClassAccessLevel) init() { } \(mapping.spyClassAccessLevel) @@ -458,7 +458,7 @@ final class UT_SpyableMacro: XCTestCase { \(protocolDefinition) - \(mapping.spyClassAccessLevel) class ServiceProtocolSpy: ServiceProtocol { + \(mapping.spyClassAccessLevel) class ServiceProtocolSpy: ServiceProtocol, @unchecked Sendable { \(mapping.spyClassAccessLevel) init() { } \(mapping.spyClassAccessLevel) @@ -503,7 +503,7 @@ final class UT_SpyableMacro: XCTestCase { \(protocolDeclaration) - fileprivate class ServiceProtocolSpy: ServiceProtocol { + fileprivate class ServiceProtocolSpy: ServiceProtocol, @unchecked Sendable { fileprivate init() { } fileprivate @@ -546,7 +546,7 @@ final class UT_SpyableMacro: XCTestCase { \(protocolDeclaration) #if CUSTOM_FLAG - package class MyProtocolSpy: MyProtocol { + package class MyProtocolSpy: MyProtocol, @unchecked Sendable { package init() { } } From 8ea114aff5f613cc4b8d40c6271b0a32aad4e0db Mon Sep 17 00:00:00 2001 From: yoshiki-tsukada Date: Sun, 22 Dec 2024 00:31:02 +0900 Subject: [PATCH 3/3] Add Sendable test case --- .../Factories/UT_SpyFactory.swift | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/Tests/SpyableMacroTests/Factories/UT_SpyFactory.swift b/Tests/SpyableMacroTests/Factories/UT_SpyFactory.swift index 02a5ddc..096dead 100644 --- a/Tests/SpyableMacroTests/Factories/UT_SpyFactory.swift +++ b/Tests/SpyableMacroTests/Factories/UT_SpyFactory.swift @@ -42,6 +42,56 @@ final class UT_SpyFactory: XCTestCase { ) } + func testDeclarationWithSendable() throws { + try assertProtocol( + withDeclaration: """ + protocol Service: Sendable { + func fetch() + } + """, + expectingClassDeclaration: """ + class ServiceSpy: Service, @unchecked Sendable { + init() { + } + var fetchCallsCount = 0 + var fetchCalled: Bool { + return fetchCallsCount > 0 + } + var fetchClosure: (() -> Void)? + func fetch() { + fetchCallsCount += 1 + fetchClosure?() + } + } + """ + ) + } + + func testDeclarationWithUncheckedSendable() throws { + try assertProtocol( + withDeclaration: """ + protocol Service: @unchecked Sendable { + func fetch() + } + """, + expectingClassDeclaration: """ + class ServiceSpy: Service, @unchecked Sendable { + init() { + } + var fetchCallsCount = 0 + var fetchCalled: Bool { + return fetchCallsCount > 0 + } + var fetchClosure: (() -> Void)? + func fetch() { + fetchCallsCount += 1 + fetchClosure?() + } + } + """ + ) + } + func testDeclarationArguments() throws { try assertProtocol( withDeclaration: """