Skip to content

Commit

Permalink
Add 'nonisolated' to generated initializers (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
dfed authored Jan 13, 2024
1 parent 58d9116 commit b3f0773
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 23 deletions.
47 changes: 38 additions & 9 deletions Sources/SafeDICore/Models/Initializer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,18 +124,11 @@ public struct Initializer: Codable, Hashable {

public static func generateRequiredInitializer(
for dependencies: [Dependency],
declarationType: ConcreteDeclType,
andAdditionalPropertiesWithLabels additionalPropertyLabels: [String] = []
) -> InitializerDeclSyntax {
InitializerDeclSyntax(
modifiers: DeclModifierListSyntax(
arrayLiteral: DeclModifierSyntax(
name: TokenSyntax(
TokenKind.identifier("public"),
presence: .present
),
trailingTrivia: .space
)
),
modifiers: declarationType.initializerModifiers,
signature: FunctionSignatureSyntax(
parameterClause: FunctionParameterClauseSyntax(
parameters: FunctionParameterListSyntax(itemsBuilder: {
Expand Down Expand Up @@ -261,3 +254,39 @@ public struct Initializer: Codable, Hashable {

static let dependenciesToken: TokenSyntax = .identifier("dependencies")
}

// MARK: - ConcreteDeclType

extension ConcreteDeclType {
fileprivate var initializerModifiers: DeclModifierListSyntax {
switch self {
case .actorType:
DeclModifierListSyntax(
arrayLiteral: DeclModifierSyntax(
name: TokenSyntax(
TokenKind.identifier("public"),
presence: .present
),
trailingTrivia: .space
)
)
case .classType, .structType:
DeclModifierListSyntax(
arrayLiteral: DeclModifierSyntax(
name: TokenSyntax(
TokenKind.identifier("nonisolated"),
presence: .present
),
trailingTrivia: .space
),
DeclModifierSyntax(
name: TokenSyntax(
TokenKind.identifier("public"),
presence: .present
),
trailingTrivia: .space
)
)
}
}
}
6 changes: 5 additions & 1 deletion Sources/SafeDIMacros/Macros/InstantiableMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ public struct InstantiableMacro: MemberMacro {
.contains(where: { $0.isValid(forFulfilling: visitor.dependencies) })
guard hasMemberwiseInitializerForInjectableProperties else {
if visitor.uninitializedNonOptionalPropertyNames.isEmpty {
var initializer = Initializer.generateRequiredInitializer(for: visitor.dependencies)
var initializer = Initializer.generateRequiredInitializer(
for: visitor.dependencies,
declarationType: concreteDeclaration.declType
)
initializer.leadingTrivia = Trivia(stringLiteral: """
// A generated initializer that has one argument per SafeDI-injected property.
// Because this initializer is generated by a Swift Macro, it can not be used by other Swift Macros.
Expand All @@ -74,6 +77,7 @@ public struct InstantiableMacro: MemberMacro {
leadingTrivia: .newline,
decl: Initializer.generateRequiredInitializer(
for: visitor.dependencies,
declarationType: concreteDeclaration.declType,
andAdditionalPropertiesWithLabels: visitor.uninitializedNonOptionalPropertyNames
),
trailingTrivia: .newline
Expand Down
72 changes: 59 additions & 13 deletions Tests/SafeDIMacrosTests/InstantiableMacroTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ final class InstantiableMacroTests: XCTestCase {

// MARK: Generation tests

func test_declaration_generatesRequiredInitializerWithoutAnyDependencies() {
func test_declaration_generatesRequiredInitializerWithoutAnyDependenciesOnStruct() {
assertMacro {
"""
@Instantiable
Expand All @@ -57,6 +57,52 @@ final class InstantiableMacroTests: XCTestCase {
"""
public struct ExampleService {
// A generated initializer that has one argument per SafeDI-injected property.
// Because this initializer is generated by a Swift Macro, it can not be used by other Swift Macros.
// As a result, this initializer can not be used within a #Preview macro closure.
// This initializer is only generated because you have not written this macro yourself.
// Copy/pasting this generated initializer into your code will enable this initializer to be used within other Swift Macros.
nonisolated public init() {
}
}
"""
}
}

func test_declaration_generatesRequiredInitializerWithoutAnyDependenciesOnClass() {
assertMacro {
"""
@Instantiable
public class ExampleService {
}
"""
} expansion: {
"""
public class ExampleService {
// A generated initializer that has one argument per SafeDI-injected property.
// Because this initializer is generated by a Swift Macro, it can not be used by other Swift Macros.
// As a result, this initializer can not be used within a #Preview macro closure.
// This initializer is only generated because you have not written this macro yourself.
// Copy/pasting this generated initializer into your code will enable this initializer to be used within other Swift Macros.
nonisolated public init() {
}
}
"""
}
}

func test_declaration_generatesRequiredInitializerWithoutAnyDependenciesOnActor() {
assertMacro {
"""
@Instantiable
public actor ExampleService {
}
"""
} expansion: {
"""
public actor ExampleService {
// A generated initializer that has one argument per SafeDI-injected property.
// Because this initializer is generated by a Swift Macro, it can not be used by other Swift Macros.
// As a result, this initializer can not be used within a #Preview macro closure.
Expand Down Expand Up @@ -104,7 +150,7 @@ final class InstantiableMacroTests: XCTestCase {
// As a result, this initializer can not be used within a #Preview macro closure.
// This initializer is only generated because you have not written this macro yourself.
// Copy/pasting this generated initializer into your code will enable this initializer to be used within other Swift Macros.
public init() {
nonisolated public init() {
}
}
"""
Expand All @@ -129,7 +175,7 @@ final class InstantiableMacroTests: XCTestCase {
// As a result, this initializer can not be used within a #Preview macro closure.
// This initializer is only generated because you have not written this macro yourself.
// Copy/pasting this generated initializer into your code will enable this initializer to be used within other Swift Macros.
public init() {
nonisolated public init() {
}
}
"""
Expand Down Expand Up @@ -181,7 +227,7 @@ final class InstantiableMacroTests: XCTestCase {
// As a result, this initializer can not be used within a #Preview macro closure.
// This initializer is only generated because you have not written this macro yourself.
// Copy/pasting this generated initializer into your code will enable this initializer to be used within other Swift Macros.
public init(instantiatedA: InstantiatedA) {
nonisolated public init(instantiatedA: InstantiatedA) {
self.instantiatedA = instantiatedA
}
}
Expand Down Expand Up @@ -212,7 +258,7 @@ final class InstantiableMacroTests: XCTestCase {
// As a result, this initializer can not be used within a #Preview macro closure.
// This initializer is only generated because you have not written this macro yourself.
// Copy/pasting this generated initializer into your code will enable this initializer to be used within other Swift Macros.
public init(instantiatedA: InstantiatedA) {
nonisolated public init(instantiatedA: InstantiatedA) {
self.instantiatedA = instantiatedA
}
}
Expand Down Expand Up @@ -243,7 +289,7 @@ final class InstantiableMacroTests: XCTestCase {
// As a result, this initializer can not be used within a #Preview macro closure.
// This initializer is only generated because you have not written this macro yourself.
// Copy/pasting this generated initializer into your code will enable this initializer to be used within other Swift Macros.
public init(instantiatedA: InstantiatedA) {
nonisolated public init(instantiatedA: InstantiatedA) {
self.instantiatedA = instantiatedA
}
}
Expand Down Expand Up @@ -287,7 +333,7 @@ final class InstantiableMacroTests: XCTestCase {
// As a result, this initializer can not be used within a #Preview macro closure.
// This initializer is only generated because you have not written this macro yourself.
// Copy/pasting this generated initializer into your code will enable this initializer to be used within other Swift Macros.
public init(forwardedA: ForwardedA, receivedA: ReceivedA, receivedB: ReceivedB) {
nonisolated public init(forwardedA: ForwardedA, receivedA: ReceivedA, receivedB: ReceivedB) {
self.forwardedA = forwardedA
self.receivedA = receivedA
self.receivedB = receivedB
Expand Down Expand Up @@ -322,7 +368,7 @@ final class InstantiableMacroTests: XCTestCase {
// As a result, this initializer can not be used within a #Preview macro closure.
// This initializer is only generated because you have not written this macro yourself.
// Copy/pasting this generated initializer into your code will enable this initializer to be used within other Swift Macros.
public init(userID: String, userName: String) {
nonisolated public init(userID: String, userName: String) {
self.userID = userID
self.userName = userName
}
Expand Down Expand Up @@ -352,7 +398,7 @@ final class InstantiableMacroTests: XCTestCase {
// As a result, this initializer can not be used within a #Preview macro closure.
// This initializer is only generated because you have not written this macro yourself.
// Copy/pasting this generated initializer into your code will enable this initializer to be used within other Swift Macros.
public init(instantiatableAInstantiator: Instantiator<ReceivedA>) {
nonisolated public init(instantiatableAInstantiator: Instantiator<ReceivedA>) {
self.instantiatableAInstantiator = instantiatableAInstantiator
}
}
Expand Down Expand Up @@ -668,7 +714,7 @@ final class InstantiableMacroTests: XCTestCase {
"""
@Instantiable
public struct ExampleService {
public init(receivedA: ReceivedA) {
nonisolated public init(receivedA: ReceivedA) {
self.receivedA = receivedA
uninitializedProperty = <#T##assign_uninitializedProperty#>
}
Expand All @@ -682,7 +728,7 @@ final class InstantiableMacroTests: XCTestCase {
} expansion: {
"""
public struct ExampleService {
public init(receivedA: ReceivedA) {
nonisolated public init(receivedA: ReceivedA) {
self.receivedA = receivedA
uninitializedProperty = <#T##assign_uninitializedProperty#>
}
Expand Down Expand Up @@ -725,7 +771,7 @@ final class InstantiableMacroTests: XCTestCase {
"""
@Instantiable
public struct ExampleService {
public init(receivedA: ReceivedA) {
nonisolated public init(receivedA: ReceivedA) {
self.receivedA = receivedA
uninitializedProperty1 = <#T##assign_uninitializedProperty1#>
uninitializedProperty2 = <#T##assign_uninitializedProperty2#>
Expand All @@ -744,7 +790,7 @@ final class InstantiableMacroTests: XCTestCase {
} expansion: {
"""
public struct ExampleService {
public init(receivedA: ReceivedA) {
nonisolated public init(receivedA: ReceivedA) {
self.receivedA = receivedA
uninitializedProperty1 = <#T##assign_uninitializedProperty1#>
uninitializedProperty2 = <#T##assign_uninitializedProperty2#>
Expand Down

0 comments on commit b3f0773

Please sign in to comment.