diff --git a/Sources/SafeDICore/Models/CombinedScope.swift b/Sources/SafeDICore/Models/CombinedScope.swift index 594086fd..fae850cc 100644 --- a/Sources/SafeDICore/Models/CombinedScope.swift +++ b/Sources/SafeDICore/Models/CombinedScope.swift @@ -169,10 +169,7 @@ actor CombinedScope { private func hasResolvedAllPropertiesRequired(for instantiable: Instantiable) -> Bool { !instantiable .dependencies - .filter { - $0.source != .instantiated - && $0.source != .forwarded - } + .filter { $0.source != .forwarded } .map(\.property) .contains(where: { !isPropertyResolved($0) }) } diff --git a/Tests/SafeDIPluginTests/SafeDIPluginTests.swift b/Tests/SafeDIPluginTests/SafeDIPluginTests.swift index cd3f5b47..3387f590 100644 --- a/Tests/SafeDIPluginTests/SafeDIPluginTests.swift +++ b/Tests/SafeDIPluginTests/SafeDIPluginTests.swift @@ -749,8 +749,135 @@ final class SafeDIPluginTests: XCTestCase { ) } + func test_run_writesConvenienceExtensionOnRootOfTree_whenRootInstantiatesPropertiesWithMultipleTreesThatInstantiateTheSameProperty() async throws { + let output = try await SafeDIPlugin.run( + swiftFileContent: [ + """ + @Instantiable() + public final class Root { + public init(childA: ChildA, childB: ChildB) { + self.childA = childA + self.childB = childB + } + + @Instantiated + let childA: ChildA + @Instantiated + let childB: ChildB + } + """, + """ + @Instantiable() + public final class ChildA { + public init(grandchildAA: GrandchildAA, grandchildAB: GrandchildAB) { + self.grandchildAA = grandchildAA + self.grandchildAB = grandchildAB + } + + @Instantiated + let grandchildAA: GrandchildAA + @Instantiated + let grandchildAB: GrandchildAB + } + """, + """ + @Instantiable() + public final class GrandchildAA { + public init(greatGrandchild: GreatGrandchild) { + self.greatGrandchild = greatGrandchild + } + + @Instantiated + let greatGrandchild: GreatGrandchild + } + """, + """ + @Instantiable() + public final class GrandchildAB { + public init(greatGrandchild: GreatGrandchild) { + self.greatGrandchild = greatGrandchild + } + + @Instantiated + let greatGrandchild: GreatGrandchild + } + """, + """ + @Instantiable() + public final class ChildB { + public init(grandchildBA: GrandchildBA, grandchildBB: GrandchildBB) { + self.grandchildAA = grandchildAA + self.grandchildAB = grandchildAB + } + + @Instantiated + let grandchildBA: GrandchildBA + @Instantiated + let grandchildBB: GrandchildBB + } + """, + """ + @Instantiable() + public final class GrandchildBA { + public init(greatGrandchild: GreatGrandchild) { + self.greatGrandchild = greatGrandchild + } + + @Instantiated + let greatGrandchild: GreatGrandchild + } + """, + """ + @Instantiable() + public final class GrandchildBB { + public init(greatGrandchild: GreatGrandchild) { + self.greatGrandchild = greatGrandchild + } + + @Instantiated + let greatGrandchild: GreatGrandchild + } + """, + """ + @Instantiable() + public final class GreatGrandchild { + public init() {} + } + """, + + ], + dependentModuleNames: [], + dependentInstantiables: [[]], + buildDependencyTreeOutput: true + ) + + XCTAssertEqual( + try XCTUnwrap(output.dependencyTree), + """ + // This file was generated by the SafeDIGenerateDependencyTree build tool plugin. + // Any modifications made to this file will be overwritten on subsequent builds. + // Please refrain from editing this file directly. + + import SwiftUI + import UIKit + + extension Root { + @convenience init() { + let greatGrandchild = GreatGrandchild() + let grandchildAA = GrandchildAA(greatGrandchild: greatGrandchild) + let grandchildAB = GrandchildAB(greatGrandchild: greatGrandchild) + let childA = ChildA(grandchildAA: grandchildAA, grandchildAB: grandchildAB) + let grandchildBA = GrandchildBA(greatGrandchild: greatGrandchild) + let grandchildBB = GrandchildBB(greatGrandchild: greatGrandchild) + let childB = ChildB(grandchildBA: grandchildBA, grandchildBB: grandchildBB) + self.init(childA: childA, childB: childB) + } + } + """ // showstopper TODO: Is this the output we want!? Multiple @Instantiated properties are shared... this doesn't seem right. + ) + } + // showstopper TODO: multi-module test - // showstopper TODO: same instantiated dependency in multiple trees (same name + type, instantiated in two separate trees) // MARK: Error Tests