Skip to content

Commit 85cfe06

Browse files
authored
Move code for finding test targets into PackageGraph (#2109)
Other clients might also want to know which test targets are relevant for a particular executable target. rdar://problem/47648572
1 parent a02da00 commit 85cfe06

File tree

2 files changed

+35
-18
lines changed

2 files changed

+35
-18
lines changed

Sources/PackageGraph/PackageGraph.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,36 @@ public struct PackageGraph {
101101
self.reachableTargets = reachableTargets
102102
self.reachableProducts = reachableProducts
103103
}
104+
105+
/// Computes a map from each executable target in any of the root packages to the corresponding test targets.
106+
public func computeTestTargetsForExecutableTargets() -> [ResolvedTarget: [ResolvedTarget]] {
107+
var result = [ResolvedTarget: [ResolvedTarget]]()
108+
109+
let rootTargets = rootPackages.map({ $0.targets }).flatMap({ $0 })
110+
111+
// Create map of test target to set of its direct dependencies.
112+
let testTargetDepMap: [ResolvedTarget: Set<ResolvedTarget>] = {
113+
let testTargetDeps = rootTargets.filter({ $0.type == .test }).map({
114+
($0, Set($0.dependencies.compactMap({ $0.target })))
115+
})
116+
return Dictionary(uniqueKeysWithValues: testTargetDeps)
117+
}()
118+
119+
for target in rootTargets where target.type == .executable {
120+
// Find all dependencies of this target within its package.
121+
let dependencies = try! topologicalSort(target.dependencies, successors: {
122+
$0.dependencies.compactMap({ $0.target }).map(ResolvedTarget.Dependency.target)
123+
}).compactMap({ $0.target })
124+
125+
// Include the test targets whose dependencies intersect with the
126+
// current target's (recursive) dependencies.
127+
let testTargets = testTargetDepMap.filter({ (testTarget, deps) in
128+
!deps.intersection(dependencies + [target]).isEmpty
129+
}).map({ $0.key })
130+
131+
result[target] = testTargets
132+
}
133+
134+
return result
135+
}
104136
}

Sources/Xcodeproj/SchemesGenerator.swift

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -63,31 +63,16 @@ final class SchemesGenerator {
6363

6464
var schemes: [Scheme] = []
6565

66-
// Create map of test target to set of its direct dependencies.
67-
let testTargetDepMap: [ResolvedTarget: Set<ResolvedTarget>] = {
68-
let testTargetDeps = rootPackage.targets.filter({ $0.type == .test }).map({
69-
($0, Set($0.dependencies.compactMap({ $0.target })))
70-
})
71-
return Dictionary(uniqueKeysWithValues: testTargetDeps)
72-
}()
66+
let testTargetsMap = graph.computeTestTargetsForExecutableTargets()
7367

7468
// Create one scheme per executable target.
7569
for target in rootPackage.targets where target.type == .executable {
76-
// Find all dependencies of this target within its package.
77-
let dependencies = try! topologicalSort(target.dependencies, successors: {
78-
$0.dependencies.compactMap({ $0.target }).map(ResolvedTarget.Dependency.target)
79-
}).compactMap({ $0.target })
80-
81-
// Include the test targets whose dependencies intersect with the
82-
// current target's (recursive) dependencies.
83-
let testTargets = testTargetDepMap.filter({ (testTarget, deps) in
84-
!deps.intersection(dependencies + [target]).isEmpty
85-
}).map({ $0.key })
70+
let testTargets = testTargetsMap[target]
8671

8772
schemes.append(Scheme(
8873
name: target.name,
8974
regularTargets: [target],
90-
testTargets: testTargets
75+
testTargets: testTargets ?? []
9176
))
9277
}
9378

0 commit comments

Comments
 (0)