Implement topologicalSort inside BuildSystemManager using dependency information

This commit is contained in:
Alex Hoppen
2024-08-24 18:11:52 -07:00
parent bb96ff4c68
commit cc11fe1b02
5 changed files with 59 additions and 59 deletions

View File

@@ -210,10 +210,8 @@ package actor SwiftPMBuildSystem {
/// Maps source and header files to the target that include them.
private var fileToTargets: [DocumentURI: Set<BuildTargetIdentifier>] = [:]
/// Maps target ids to their SwiftPM build target as well as the depth at which they occur in the build
/// graph. Top level targets on which no other target depends have a depth of `1`. Targets with dependencies have a
/// greater depth.
private var targets: [BuildTargetIdentifier: (buildTarget: SwiftBuildTarget, depth: Int)] = [:]
/// Maps target ids to their SwiftPM build target.
private var swiftPMTargets: [BuildTargetIdentifier: SwiftBuildTarget] = [:]
private var targetDependencies: [BuildTargetIdentifier: Set<BuildTargetIdentifier>] = [:]
@@ -442,7 +440,7 @@ extension SwiftPMBuildSystem {
/// properties because otherwise we might end up in an inconsistent state
/// with only some properties modified.
self.targets = [:]
self.swiftPMTargets = [:]
self.fileToTargets = [:]
self.targetDependencies = [:]
@@ -451,10 +449,7 @@ extension SwiftPMBuildSystem {
guard let targetIdentifier else {
return
}
var depth = depth
if let existingDepth = targets[targetIdentifier]?.depth {
depth = max(existingDepth, depth)
} else {
if swiftPMTargets[targetIdentifier] == nil {
for source in buildTarget.sources + buildTarget.headers {
fileToTargets[DocumentURI(source), default: []].insert(targetIdentifier)
}
@@ -464,7 +459,7 @@ extension SwiftPMBuildSystem {
{
self.targetDependencies[parentIdentifier, default: []].insert(targetIdentifier)
}
targets[targetIdentifier] = (buildTarget, depth)
swiftPMTargets[targetIdentifier] = buildTarget
}
await messageHandler?.sendNotificationToSourceKitLSP(DidChangeBuildTargetNotification(changes: nil))
@@ -523,9 +518,9 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
}
package func buildTargets(request: BuildTargetsRequest) async throws -> BuildTargetsResponse {
let targets = self.targets.map { (targetId, target) in
let targets = self.swiftPMTargets.map { (targetId, target) in
var tags: [BuildTargetTag] = [.test]
if target.depth != 1 {
if !target.isPartOfRootPackage {
tags.append(.dependency)
}
return BuildTarget(
@@ -547,10 +542,10 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
// TODO: Query The SwiftPM build system for the document's language and add it to SourceItem.data
// (https://github.com/swiftlang/sourcekit-lsp/issues/1267)
for target in request.targets {
guard let swiftPMTarget = self.targets[target] else {
guard let swiftPMTarget = self.swiftPMTargets[target] else {
continue
}
let sources = swiftPMTarget.buildTarget.sources.map {
let sources = swiftPMTarget.sources.map {
SourceItem(uri: DocumentURI($0), kind: .file, generated: false)
}
result.append(SourcesItem(target: target, sources: sources))
@@ -568,13 +563,13 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
return try settings(forPackageManifest: path)
}
guard let buildTarget = self.targets[request.target]?.buildTarget else {
guard let swiftPMTarget = self.swiftPMTargets[request.target] else {
logger.fault("Did not find target \(request.target.forLogging)")
return nil
}
if !buildTarget.sources.lazy.map(DocumentURI.init).contains(request.textDocument.uri),
let substituteFile = buildTarget.sources.sorted(by: { $0.path < $1.path }).first
if !swiftPMTarget.sources.lazy.map(DocumentURI.init).contains(request.textDocument.uri),
let substituteFile = swiftPMTarget.sources.sorted(by: { $0.path < $1.path }).first
{
logger.info("Getting compiler arguments for \(url) using substitute file \(substituteFile)")
// If `url` is not part of the target's source, it's most likely a header file. Fake compiler arguments for it
@@ -585,7 +580,7 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
// getting its compiler arguments and then patching up the compiler arguments by replacing the substitute file
// with the `.cpp` file.
let buildSettings = FileBuildSettings(
compilerArguments: try await compilerArguments(for: DocumentURI(substituteFile), in: buildTarget),
compilerArguments: try await compilerArguments(for: DocumentURI(substituteFile), in: swiftPMTarget),
workingDirectory: projectRoot.pathString
).patching(newFile: try resolveSymlinks(path).pathString, originalFile: substituteFile.absoluteString)
return SourceKitOptionsResponse(
@@ -595,7 +590,7 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
}
return SourceKitOptionsResponse(
compilerArguments: try await compilerArguments(for: request.textDocument.uri, in: buildTarget),
compilerArguments: try await compilerArguments(for: request.textDocument.uri, in: swiftPMTarget),
workingDirectory: projectRoot.pathString
)
}
@@ -635,14 +630,6 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
await self.packageLoadingQueue.async {}.valuePropagatingCancellation
}
package func topologicalSort(of targets: [BuildTargetIdentifier]) -> [BuildTargetIdentifier]? {
return targets.sorted { (lhs: BuildTargetIdentifier, rhs: BuildTargetIdentifier) -> Bool in
let lhsDepth = self.targets[lhs]?.depth ?? 0
let rhsDepth = self.targets[rhs]?.depth ?? 0
return lhsDepth > rhsDepth
}
}
package func prepare(request: PrepareTargetsRequest) async throws -> VoidResponse {
// TODO: Support preparation of multiple targets at once. (https://github.com/swiftlang/sourcekit-lsp/issues/1262)
for target in request.targets {
@@ -804,21 +791,6 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
}
}
package func sourceFiles() -> [SourceFileInfo] {
var sourceFiles: [DocumentURI: SourceFileInfo] = [:]
for (buildTarget, depth) in self.targets.values {
for sourceFile in buildTarget.sources {
let uri = DocumentURI(sourceFile)
sourceFiles[uri] = SourceFileInfo(
uri: uri,
isPartOfRootProject: depth == 1 || (sourceFiles[uri]?.isPartOfRootProject ?? false),
mayContainTests: true
)
}
}
return sourceFiles.values.sorted { $0.uri.pseudoPath < $1.uri.pseudoPath }
}
package func addSourceFilesDidChangeCallback(_ callback: @Sendable @escaping () async -> Void) async {
testFilesDidChangeCallbacks.append(callback)
}