Skip to content

Commit 13176b0

Browse files
committed
Address review comments
1 parent 5e83d7d commit 13176b0

File tree

6 files changed

+45
-32
lines changed

6 files changed

+45
-32
lines changed

Sources/SKCore/BuildSystemManager.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ extension BuildSystemManager {
212212
try await self.buildSystem?.generateBuildGraph()
213213
}
214214

215-
public func topologicalSort(of targets: [ConfiguredTarget]) async throws -> [ConfiguredTarget] {
216-
return await buildSystem?.topologicalSort(of: targets) ?? targets
215+
public func topologicalSort(of targets: [ConfiguredTarget]) async throws -> [ConfiguredTarget]? {
216+
return await buildSystem?.topologicalSort(of: targets)
217217
}
218218

219219
public func prepare(targets: [ConfiguredTarget]) async throws {

Sources/SKSwiftPMWorkspace/SwiftPMBuildSystem.swift

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,11 @@ public actor SwiftPMBuildSystem {
100100

101101
var fileToTarget: [AbsolutePath: SwiftBuildTarget] = [:]
102102
var sourceDirToTarget: [AbsolutePath: SwiftBuildTarget] = [:]
103-
var targets: [SwiftBuildTarget] = []
103+
104+
/// Maps target ids (aka. `ConfiguredTarget.targetID`) to their SwiftPM build target as well as an index in their
105+
/// topological sorting. Targets with lower index are more low level, ie. targets with higher indices depend on
106+
/// targets with lower indices.
107+
var targets: [String: (index: Int, buildTarget: SwiftBuildTarget)] = [:]
104108

105109
/// The URIs for which the delegate has registered for change notifications,
106110
/// mapped to the language the delegate specified when registering for change notifications.
@@ -119,6 +123,11 @@ public actor SwiftPMBuildSystem {
119123
/// Force-unwrapped optional because initializing it requires access to `self`.
120124
var fileDependenciesUpdatedDebouncer: Debouncer<Set<DocumentURI>>! = nil
121125

126+
/// A `ObservabilitySystem` from `SwiftPM` that logs.
127+
private let observabilitySystem = ObservabilitySystem({ scope, diagnostic in
128+
logger.log(level: diagnostic.severity.asLogLevel, "SwiftPM log: \(diagnostic.description)")
129+
})
130+
122131
/// Creates a build system using the Swift Package Manager, if this workspace is a package.
123132
///
124133
/// - Parameters:
@@ -238,9 +247,6 @@ public actor SwiftPMBuildSystem {
238247

239248
extension SwiftPMBuildSystem {
240249
public func generateBuildGraph() async throws {
241-
let observabilitySystem = ObservabilitySystem({ scope, diagnostic in
242-
logger.log(level: diagnostic.severity.asLogLevel, "SwiftPM log: \(diagnostic.description)")
243-
})
244250
try self.workspace.resolve(
245251
root: PackageGraphRootInput(packages: [AbsolutePath(projectRoot)]),
246252
observabilityScope: observabilitySystem.topScope
@@ -258,10 +264,6 @@ extension SwiftPMBuildSystem {
258264
}
259265
}
260266

261-
let observabilitySystem = ObservabilitySystem({ scope, diagnostic in
262-
logger.log(level: diagnostic.severity.asLogLevel, "SwiftPM log: \(diagnostic.description)")
263-
})
264-
265267
let modulesGraph = try self.workspace.loadPackageGraph(
266268
rootInput: PackageGraphRootInput(packages: [AbsolutePath(projectRoot)]),
267269
forceResolvedVersions: true,
@@ -282,7 +284,15 @@ extension SwiftPMBuildSystem {
282284
/// with only some properties modified.
283285
self.modulesGraph = modulesGraph
284286

285-
self.targets = try buildDescription.allTargetsInTopologicalOrder(in: modulesGraph)
287+
self.targets = Dictionary(
288+
try buildDescription.allTargetsInTopologicalOrder(in: modulesGraph).enumerated().map { (index, target) in
289+
return (key: target.name, (index, target))
290+
},
291+
uniquingKeysWith: { first, second in
292+
logger.fault("Found two targets with the same name \(first.buildTarget.name)")
293+
return second
294+
}
295+
)
286296

287297
self.fileToTarget = [AbsolutePath: SwiftBuildTarget](
288298
modulesGraph.allTargets.flatMap { target in
@@ -353,14 +363,8 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
353363
return try settings(forPackageManifest: path)
354364
}
355365

356-
let buildTargets = self.targets.filter({ $0.name == configuredTarget.targetID })
357-
if buildTargets.count > 1 {
358-
logger.error("Found multiple targets with name \(configuredTarget.targetID). Picking the first one")
359-
}
360-
guard let buildTarget = buildTargets.first else {
361-
if buildTargets.isEmpty {
362-
logger.error("Did not find target with name \(configuredTarget.targetID)")
363-
}
366+
guard let buildTarget = self.targets[configuredTarget.targetID]?.buildTarget else {
367+
logger.error("Did not find target with name \(configuredTarget.targetID)")
364368
return nil
365369
}
366370

@@ -408,8 +412,8 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
408412

409413
public func topologicalSort(of targets: [ConfiguredTarget]) -> [ConfiguredTarget]? {
410414
return targets.sorted { (lhs: ConfiguredTarget, rhs: ConfiguredTarget) -> Bool in
411-
let lhsIndex = self.targets.firstIndex(where: { $0.name == lhs.targetID }) ?? self.targets.count
412-
let rhsIndex = self.targets.firstIndex(where: { $0.name == rhs.targetID }) ?? self.targets.count
415+
let lhsIndex = self.targets[lhs.targetID]?.index ?? self.targets.count
416+
let rhsIndex = self.targets[lhs.targetID]?.index ?? self.targets.count
413417
return lhsIndex < rhsIndex
414418
}
415419
}
@@ -443,7 +447,7 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
443447
]
444448
let process = Process(
445449
arguments: arguments,
446-
workingDirectory: try TSCBasic.AbsolutePath(validating: workspacePath.pathString)
450+
workingDirectory: workspacePath
447451
)
448452
try process.launch()
449453
let result = try await process.waitUntilExitSendingSigIntOnTaskCancellation()
@@ -456,7 +460,7 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
456460
let stderr = (try? String(bytes: result.stderrOutput.get(), encoding: .utf8)) ?? "<no stderr>"
457461
logger.debug(
458462
"""
459-
Preparation of targets \(target.targetID) terminated with non-zero exit code \(code)
463+
Preparation of target \(target.targetID) terminated with non-zero exit code \(code)
460464
Stderr:
461465
\(stderr)
462466
Stdout:
@@ -468,11 +472,11 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
468472
// The indexing job finished with a signal. Could be because the compiler crashed.
469473
// Ignore signal exit codes if this task has been cancelled because the compiler exits with SIGINT if it gets
470474
// interrupted.
471-
logger.error("Preparation of targets \(target.targetID) signaled \(signal)")
475+
logger.error("Preparation of target \(target.targetID) signaled \(signal)")
472476
}
473477
case .abnormal(exception: let exception):
474478
if !Task.isCancelled {
475-
logger.error("Preparation of targets \(target.targetID) exited abnormally \(exception)")
479+
logger.error("Preparation of target \(target.targetID) exited abnormally \(exception)")
476480
}
477481
}
478482
}

Sources/SKTestSupport/FileManager+findFiles.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ extension FileManager {
2525
return result
2626
}
2727

28-
/// Returns the URLs of all files with the given file extension in the given directory (recursively).
28+
/// Returns the URLs of all files with the given file name in the given directory (recursively).
2929
public func findFiles(named name: String, in directory: URL) -> [URL] {
3030
var result: [URL] = []
3131
let enumerator = self.enumerator(at: directory, includingPropertiesForKeys: nil)

Sources/SemanticIndex/PreparationTaskDescription.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ import class TSCBasic.Process
2121

2222
private var preparationIDForLogging = AtomicUInt32(initialValue: 1)
2323

24-
/// Describes a task to index a set of source files.
24+
/// Describes a task to prepare a set of targets.
2525
///
2626
/// This task description can be scheduled in a `TaskScheduler`.
2727
public struct PreparationTaskDescription: TaskDescriptionProtocol {
2828
public let id = preparationIDForLogging.fetchAndIncrement()
2929

30-
/// The files that should be indexed.
30+
/// The targets that should be prepared.
3131
private let targetsToPrepare: [ConfiguredTarget]
3232

3333
/// The build system manager that is used to get the toolchain and build settings for the files to index.
@@ -38,7 +38,7 @@ public struct PreparationTaskDescription: TaskDescriptionProtocol {
3838
/// Intended for testing purposes.
3939
private let didFinishCallback: @Sendable (PreparationTaskDescription) -> Void
4040

41-
/// The task is idempotent because indexing the same file twice produces the same result as indexing it once.
41+
/// The task is idempotent because preparing the same target twice produces the same result as preparing it once.
4242
public var isIdempotent: Bool { true }
4343

4444
public var estimatedCPUCoreCount: Int { 1 }
@@ -73,7 +73,10 @@ public struct PreparationTaskDescription: TaskDescriptionProtocol {
7373
let targetsToPrepare = targetsToPrepare.sorted(by: {
7474
($0.targetID, $0.runDestinationID) < ($1.targetID, $1.runDestinationID)
7575
})
76-
let targetsToPrepareDescription = targetsToPrepare.map { $0.targetID }.joined(separator: ", ")
76+
let targetsToPrepareDescription =
77+
targetsToPrepare
78+
.map { "\($0.targetID)-\($0.runDestinationID)" }
79+
.joined(separator: ", ")
7780
logger.log(
7881
"Starting preparation with priority \(Task.currentPriority.rawValue, privacy: .public): \(targetsToPrepareDescription)"
7982
)

Sources/SemanticIndex/SemanticIndexManager.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,9 @@ public final actor SemanticIndexManager {
191191

192192
var sortedTargets: [ConfiguredTarget] =
193193
await orLog("Sorting targets") { try await buildSystemManager.topologicalSort(of: Array(filesByTarget.keys)) }
194-
?? Array(filesByTarget.keys).sorted(by: { $0.targetID < $1.targetID })
194+
?? Array(filesByTarget.keys).sorted(by: {
195+
($0.targetID, $0.runDestinationID) < ($1.targetID, $1.runDestinationID)
196+
})
195197

196198
if Set(sortedTargets) != Set(filesByTarget.keys) {
197199
logger.fault(
@@ -200,7 +202,9 @@ public final actor SemanticIndexManager {
200202
\(sortedTargets.map(\.targetID).joined(separator: ", ")) != \(filesByTarget.keys.map(\.targetID).joined(separator: ", "))
201203
"""
202204
)
203-
sortedTargets = Array(filesByTarget.keys).sorted(by: { $0.targetID < $1.targetID })
205+
sortedTargets = Array(filesByTarget.keys).sorted(by: {
206+
($0.targetID, $0.runDestinationID) < ($1.targetID, $1.runDestinationID)
207+
})
204208
}
205209

206210
var indexTasks: [Task<Void, Never>] = []

Tests/SourceKitLSPTests/BackgroundIndexingTests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ final class BackgroundIndexingTests: XCTestCase {
106106
}
107107

108108
func testBackgroundIndexingOfMultiModuleProject() async throws {
109+
try await SkipUnless.swiftpmStoresModulesInSubdirectory()
109110
let project = try await SwiftPMTestProject(
110111
files: [
111112
"LibA/MyFile.swift": """
@@ -211,6 +212,7 @@ final class BackgroundIndexingTests: XCTestCase {
211212
}
212213

213214
func testBackgroundIndexingOfPackageDependency() async throws {
215+
try await SkipUnless.swiftpmStoresModulesInSubdirectory()
214216
let dependencyContents = """
215217
public func 1️⃣doSomething() {}
216218
"""

0 commit comments

Comments
 (0)