diff --git a/Sources/SafeDICore/Generators/ScopeGenerator.swift b/Sources/SafeDICore/Generators/ScopeGenerator.swift index 2e364c5..9a116d3 100644 --- a/Sources/SafeDICore/Generators/ScopeGenerator.swift +++ b/Sources/SafeDICore/Generators/ScopeGenerator.swift @@ -245,6 +245,20 @@ actor ScopeGenerator: CustomStringConvertible, Sendable { "let \(property.asSource)" } + // Ideally we would be able to use an anonymous closure rather than a named function here. + // Unfortunately, there's a bug in Swift Concurrency that prevents us from doing this: https://github.com/swiftlang/swift/issues/75003 + let functionName = self.functionName(toBuild: property) + let functionDeclaration = if generatedProperties.isEmpty { + "" + } else { + """ + func \(functionName)() -> \(concreteTypeName) { + \(generatedProperties.joined(separator: "\n")) + \(Self.standardIndent)\(generatedProperties.isEmpty ? "" : "return ")\(returnLineSansReturn) + } + + """ + } let returnLineSansReturn = if erasedToConcreteExistential { "\(property.typeDescription.asSource)(\(returnLineSansReturn))" } else { @@ -253,14 +267,9 @@ actor ScopeGenerator: CustomStringConvertible, Sendable { let initializer = if generatedProperties.isEmpty { returnLineSansReturn } else { - """ - { - \(generatedProperties.joined(separator: "\n")) - \(Self.standardIndent)\(generatedProperties.isEmpty ? "" : "return ")\(returnLineSansReturn) - }() - """ + "\(functionName)()" } - return "\(propertyDeclaration) = \(initializer)\n" + return "\(functionDeclaration)\(propertyDeclaration) = \(initializer)\n" } case let .alias(property, fulfillingProperty, erasedToConcreteExistential): if erasedToConcreteExistential { diff --git a/Tests/SafeDIToolTests/SafeDIToolCodeGenerationTests.swift b/Tests/SafeDIToolTests/SafeDIToolCodeGenerationTests.swift index f5ec9a2..2ea512c 100644 --- a/Tests/SafeDIToolTests/SafeDIToolCodeGenerationTests.swift +++ b/Tests/SafeDIToolTests/SafeDIToolCodeGenerationTests.swift @@ -1357,10 +1357,11 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public convenience init() { - let child: Child = { + func __safeDI_child() -> Child { let grandchild = Grandchild() return Child(/* @Instantiable type is incorrectly configured. Fix errors from @Instantiable macro to fix this error. */) - }() + } + let child: Child = __safeDI_child() self.init(child: child) } } @@ -1411,10 +1412,11 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public convenience init() { - let child: Child = { + func __safeDI_child() -> Child { let grandchild = Grandchild() return Child(grandchild: grandchild) - }() + } + let child: Child = __safeDI_child() self.init(child: child) } } @@ -1458,10 +1460,11 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public convenience init() { - let child: Child = { + func __safeDI_child() -> Child { let grandchild = Grandchild() return Child(grandchild: grandchild) - }() + } + let child: Child = __safeDI_child() self.init(child: child) } } @@ -1505,10 +1508,11 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public convenience init() { - let child: Child = { + func __safeDI_child() -> Child { let grandchild = Grandchild() return Child(grandchild: grandchild) - }() + } + let child: Child = __safeDI_child() self.init(child: child) } } @@ -1597,16 +1601,18 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public convenience init() { let greatGrandchild = GreatGrandchild() - let childA: ChildA = { + func __safeDI_childA() -> ChildA { let grandchildAA = GrandchildAA(greatGrandchild: greatGrandchild) let grandchildAB = GrandchildAB(greatGrandchild: greatGrandchild) return ChildA(grandchildAA: grandchildAA, grandchildAB: grandchildAB) - }() - let childB: ChildB = { + } + let childA: ChildA = __safeDI_childA() + func __safeDI_childB() -> ChildB { let grandchildBA = GrandchildBA(greatGrandchild: greatGrandchild) let grandchildBB = GrandchildBB(greatGrandchild: greatGrandchild) return ChildB(grandchildBA: grandchildBA, grandchildBB: grandchildBB) - }() + } + let childB: ChildB = __safeDI_childB() self.init(childA: childA, childB: childB, greatGrandchild: greatGrandchild) } } @@ -1696,18 +1702,20 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public convenience init() { - let childA: ChildA = { + func __safeDI_childA() -> ChildA { let greatGrandchild = GreatGrandchild() let grandchildAA = GrandchildAA(greatGrandchild: greatGrandchild) let grandchildAB = GrandchildAB(greatGrandchild: greatGrandchild) return ChildA(grandchildAA: grandchildAA, grandchildAB: grandchildAB, greatGrandchild: greatGrandchild) - }() - let childB: ChildB = { + } + let childA: ChildA = __safeDI_childA() + func __safeDI_childB() -> ChildB { let greatGrandchild = GreatGrandchild() let grandchildBA = GrandchildBA(greatGrandchild: greatGrandchild) let grandchildBB = GrandchildBB(greatGrandchild: greatGrandchild) return ChildB(grandchildBA: grandchildBA, grandchildBB: grandchildBB, greatGrandchild: greatGrandchild) - }() + } + let childB: ChildB = __safeDI_childB() self.init(childA: childA, childB: childB) } } @@ -1770,15 +1778,17 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public convenience init() { - let child: Child = { - let grandchild: Grandchild = { + func __safeDI_child() -> Child { + func __safeDI_grandchild() -> Grandchild { let recreated = Recreated() let greatGrandchild = GreatGrandchild(recreated: recreated) return Grandchild(greatGrandchild: greatGrandchild, recreated: recreated) - }() + } + let grandchild: Grandchild = __safeDI_grandchild() let recreated = Recreated() return Child(grandchild: grandchild, recreated: recreated) - }() + } + let child: Child = __safeDI_child() self.init(child: child) } } @@ -1841,16 +1851,19 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public convenience init() { let recreated = Recreated() - let child: Child = { - let grandchild: Grandchild = { - let greatGrandchild: GreatGrandchild = { + func __safeDI_child() -> Child { + func __safeDI_grandchild() -> Grandchild { + func __safeDI_greatGrandchild() -> GreatGrandchild { let recreated = Recreated() return GreatGrandchild(recreated: recreated) - }() + } + let greatGrandchild: GreatGrandchild = __safeDI_greatGrandchild() return Grandchild(greatGrandchild: greatGrandchild) - }() + } + let grandchild: Grandchild = __safeDI_grandchild() return Child(grandchild: grandchild, recreated: recreated) - }() + } + let child: Child = __safeDI_child() self.init(child: child, recreated: recreated) } } @@ -1920,19 +1933,23 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public convenience init() { let recreated = Recreated() - let child: Child = { - let grandchild: Grandchild = { - let greatGrandchild: GreatGrandchild = { - let greatGreatGrandchild: GreatGreatGrandchild = { + func __safeDI_child() -> Child { + func __safeDI_grandchild() -> Grandchild { + func __safeDI_greatGrandchild() -> GreatGrandchild { + func __safeDI_greatGreatGrandchild() -> GreatGreatGrandchild { let recreated = Recreated() return GreatGreatGrandchild(recreated: recreated) - }() + } + let greatGreatGrandchild: GreatGreatGrandchild = __safeDI_greatGreatGrandchild() return GreatGrandchild(greatGreatGrandchild: greatGreatGrandchild, recreated: recreated) - }() + } + let greatGrandchild: GreatGrandchild = __safeDI_greatGrandchild() return Grandchild(greatGrandchild: greatGrandchild) - }() + } + let grandchild: Grandchild = __safeDI_grandchild() return Child(grandchild: grandchild) - }() + } + let child: Child = __safeDI_child() self.init(child: child, recreated: recreated) } } @@ -2010,27 +2027,33 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public convenience init() { - let child: Child = { + func __safeDI_child() -> Child { let recreated = Recreated() - let grandchild: Grandchild = { - let greatGrandchildA: GreatGrandchildA = { - let greatGreatGrandchild: GreatGreatGrandchild = { + func __safeDI_grandchild() -> Grandchild { + func __safeDI_greatGrandchildA() -> GreatGrandchildA { + func __safeDI_greatGreatGrandchild() -> GreatGreatGrandchild { let recreated = Recreated() return GreatGreatGrandchild(recreated: recreated) - }() + } + let greatGreatGrandchild: GreatGreatGrandchild = __safeDI_greatGreatGrandchild() return GreatGrandchildA(greatGreatGrandchild: greatGreatGrandchild, recreated: recreated) - }() - let greatGrandchildB: GreatGrandchildB = { - let greatGreatGrandchild: GreatGreatGrandchild = { + } + let greatGrandchildA: GreatGrandchildA = __safeDI_greatGrandchildA() + func __safeDI_greatGrandchildB() -> GreatGrandchildB { + func __safeDI_greatGreatGrandchild() -> GreatGreatGrandchild { let recreated = Recreated() return GreatGreatGrandchild(recreated: recreated) - }() + } + let greatGreatGrandchild: GreatGreatGrandchild = __safeDI_greatGreatGrandchild() return GreatGrandchildB(greatGreatGrandchild: greatGreatGrandchild) - }() + } + let greatGrandchildB: GreatGrandchildB = __safeDI_greatGrandchildB() return Grandchild(greatGrandchildA: greatGrandchildA, greatGrandchildB: greatGrandchildB) - }() + } + let grandchild: Grandchild = __safeDI_grandchild() return Child(grandchild: grandchild, recreated: recreated) - }() + } + let child: Child = __safeDI_child() self.init(child: child) } } @@ -2118,33 +2141,38 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public convenience init() { @Sendable func __safeDI_childABuilder(recreated: Recreated) -> ChildA { - let grandchildA: GrandchildA = { + func __safeDI_grandchildA() -> GrandchildA { let recreated = Recreated() let greatGrandchild = GreatGrandchild(recreated: recreated) return GrandchildA(greatGrandchild: greatGrandchild, recreated: recreated) - }() - let grandchildB: GrandchildB = { + } + let grandchildA: GrandchildA = __safeDI_grandchildA() + func __safeDI_grandchildB() -> GrandchildB { let greatGrandchild = GreatGrandchild(recreated: recreated) return GrandchildB(greatGrandchild: greatGrandchild) - }() + } + let grandchildB: GrandchildB = __safeDI_grandchildB() return ChildA(grandchildA: grandchildA, grandchildB: grandchildB, recreated: recreated) } let childABuilder = SendableErasedInstantiator { __safeDI_childABuilder(recreated: $0) } let recreated = Recreated() - let childB: ChildB = { - let grandchildA: GrandchildA = { + func __safeDI_childB() -> ChildB { + func __safeDI_grandchildA() -> GrandchildA { let recreated = Recreated() let greatGrandchild = GreatGrandchild(recreated: recreated) return GrandchildA(greatGrandchild: greatGrandchild, recreated: recreated) - }() - let grandchildB: GrandchildB = { + } + let grandchildA: GrandchildA = __safeDI_grandchildA() + func __safeDI_grandchildB() -> GrandchildB { let greatGrandchild = GreatGrandchild(recreated: recreated) return GrandchildB(greatGrandchild: greatGrandchild) - }() + } + let grandchildB: GrandchildB = __safeDI_grandchildB() return ChildB(grandchildA: grandchildA, grandchildB: grandchildB, recreated: recreated) - }() + } + let childB: ChildB = __safeDI_childB() self.init(childABuilder: childABuilder, childB: childB, recreated: recreated) } } @@ -2230,28 +2258,34 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public convenience init() { - let childA: ChildA = { - let grandchildAA: GrandchildAA = { + func __safeDI_childA() -> ChildA { + func __safeDI_grandchildAA() -> GrandchildAA { let greatGrandchild = GreatGrandchild() return GrandchildAA(greatGrandchild: greatGrandchild) - }() - let grandchildAB: GrandchildAB = { + } + let grandchildAA: GrandchildAA = __safeDI_grandchildAA() + func __safeDI_grandchildAB() -> GrandchildAB { let greatGrandchild = GreatGrandchild() return GrandchildAB(greatGrandchild: greatGrandchild) - }() + } + let grandchildAB: GrandchildAB = __safeDI_grandchildAB() return ChildA(grandchildAA: grandchildAA, grandchildAB: grandchildAB) - }() - let childB: ChildB = { - let grandchildBA: GrandchildBA = { + } + let childA: ChildA = __safeDI_childA() + func __safeDI_childB() -> ChildB { + func __safeDI_grandchildBA() -> GrandchildBA { let greatGrandchild = GreatGrandchild() return GrandchildBA(greatGrandchild: greatGrandchild) - }() - let grandchildBB: GrandchildBB = { + } + let grandchildBA: GrandchildBA = __safeDI_grandchildBA() + func __safeDI_grandchildBB() -> GrandchildBB { let greatGrandchild = GreatGrandchild() return GrandchildBB(greatGrandchild: greatGrandchild) - }() + } + let grandchildBB: GrandchildBB = __safeDI_grandchildBB() return ChildB(grandchildBA: grandchildBA, grandchildBB: grandchildBB) - }() + } + let childB: ChildB = __safeDI_childB() self.init(childA: childA, childB: childB) } } @@ -2595,34 +2629,40 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public convenience init() { - let childA: ChildA = { - let grandchildAA: GrandchildAA = { + func __safeDI_childA() -> ChildA { + func __safeDI_grandchildAA() -> GrandchildAA { let greatGrandchild = GreatGrandchild() return GrandchildAA(greatGrandchild: greatGrandchild) - }() - let grandchildAB: GrandchildAB = { + } + let grandchildAA: GrandchildAA = __safeDI_grandchildAA() + func __safeDI_grandchildAB() -> GrandchildAB { let greatGrandchild = GreatGrandchild() return GrandchildAB(greatGrandchild: greatGrandchild) - }() + } + let grandchildAB: GrandchildAB = __safeDI_grandchildAB() return ChildA(grandchildAA: grandchildAA, grandchildAB: grandchildAB) - }() - let childB: ChildB = { - let grandchildBA: GrandchildBA = { + } + let childA: ChildA = __safeDI_childA() + func __safeDI_childB() -> ChildB { + func __safeDI_grandchildBA() -> GrandchildBA { @Sendable func __safeDI_greatGrandchildInstantiator() -> GreatGrandchild { GreatGrandchild() } let greatGrandchildInstantiator = SendableInstantiator(__safeDI_greatGrandchildInstantiator) return GrandchildBA(greatGrandchildInstantiator: greatGrandchildInstantiator) - }() - let grandchildBB: GrandchildBB = { + } + let grandchildBA: GrandchildBA = __safeDI_grandchildBA() + func __safeDI_grandchildBB() -> GrandchildBB { @Sendable func __safeDI_greatGrandchildInstantiator() -> GreatGrandchild { GreatGrandchild() } let greatGrandchildInstantiator = SendableInstantiator(__safeDI_greatGrandchildInstantiator) return GrandchildBB(greatGrandchildInstantiator: greatGrandchildInstantiator) - }() + } + let grandchildBB: GrandchildBB = __safeDI_grandchildBB() return ChildB(grandchildBA: grandchildBA, grandchildBB: grandchildBB) - }() + } + let childB: ChildB = __safeDI_childB() self.init(childA: childA, childB: childB) } } @@ -3172,11 +3212,12 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension RootViewController { public convenience init() { - let authService: AuthService = { + func __safeDI_authService() -> DefaultAuthService { let networkService: NetworkService = DefaultNetworkService() let renamedNetworkService: NetworkService = networkService return DefaultAuthService(networkService: networkService, renamedNetworkService: renamedNetworkService) - }() + } + let authService: AuthService = __safeDI_authService() self.init(authService: authService) } } @@ -3256,11 +3297,12 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension RootViewController { public convenience init() { let networkService: NetworkService = DefaultNetworkService() - let authService: AuthService = { + func __safeDI_authService() -> DefaultAuthService { let renamedNetworkService: NetworkService = networkService let renamedAgainNetworkService: NetworkService = renamedNetworkService return DefaultAuthService(networkService: networkService, renamedNetworkService: renamedNetworkService, renamedAgainNetworkService: renamedAgainNetworkService) - }() + } + let authService: AuthService = __safeDI_authService() self.init(authService: authService, networkService: networkService) } } @@ -3620,12 +3662,13 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public convenience init() { - let child: Child = { + func __safeDI_child() -> Child { let greatGrandchild = GreatGrandchild() let grandchild = Grandchild(greatGrandchild: greatGrandchild) let unrelated = Unrelated() return Child(grandchild: grandchild, unrelated: unrelated, greatGrandchild: greatGrandchild) - }() + } + let child: Child = __safeDI_child() self.init(child: child) } } @@ -4165,17 +4208,19 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public init() { - let a: A = { - let b: B = { + func __safeDI_a() -> A { + func __safeDI_b() -> B { func __safeDI_cBuilder() -> C { let a = A(b: b) return C(a: a) } let cBuilder = Instantiator(__safeDI_cBuilder) return B(cBuilder: cBuilder) - }() + } + let b: B = __safeDI_b() return A(b: b) - }() + } + let a: A = __safeDI_a() self.init(a: a) } } @@ -4215,14 +4260,15 @@ final class SafeDIToolCodeGenerationTests: XCTestCase { extension Root { public init() { - let a: A = { + func __safeDI_a() -> A { func __safeDI_aBuilder() -> A { let aBuilder = Instantiator(__safeDI_aBuilder) return A(aBuilder: aBuilder) } let aBuilder = Instantiator(__safeDI_aBuilder) return A(aBuilder: aBuilder) - }() + } + let a: A = __safeDI_a() self.init(a: a) } }