Fix an issue that caused us to not get compiler arguments when opening a SwiftPM package at a symlink

When you had a package at `/pkg_real` and a symlink `/pkg` pointing to `/pkg_real`, then opened a workspace at `/pkg`, we wouldn’t get any build settings for any of the files. This was masked in tests because they still called `SwiftPMBuildSystem.targets(for:)`, which handled symlink resolution but wasn’t called in production.

Handle symlink resolution `BuildSystemManager`, remove `SwiftPMBuildSystem.targets(for:)` and its related members/methods, and migrate the tests to go through `BuildSystemManager`, which is what production code does. A nice side effect of this is that the tests will log the requests sent to the build system.
This commit is contained in:
Alex Hoppen
2024-09-18 11:51:04 -07:00
parent 41f8354710
commit 14765bbca8
3 changed files with 206 additions and 231 deletions

View File

@@ -204,9 +204,6 @@ package actor SwiftPMBuildSystem: BuiltInBuildSystem {
/// The entry point via with we can access the `SourceKitLSPAPI` provided by SwiftPM.
private var buildDescription: SourceKitLSPAPI.BuildDescription?
/// 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.
private var swiftPMTargets: [BuildTargetIdentifier: SwiftBuildTarget] = [:]
@@ -405,7 +402,6 @@ package actor SwiftPMBuildSystem: BuiltInBuildSystem {
/// with only some properties modified.
self.swiftPMTargets = [:]
self.fileToTargets = [:]
self.targetDependencies = [:]
buildDescription.traverseModules { buildTarget, parent, depth in
@@ -413,11 +409,6 @@ package actor SwiftPMBuildSystem: BuiltInBuildSystem {
guard let targetIdentifier else {
return
}
if swiftPMTargets[targetIdentifier] == nil {
for source in buildTarget.sources + buildTarget.headers {
fileToTargets[DocumentURI(source), default: []].insert(targetIdentifier)
}
}
if let parent,
let parentIdentifier = orLog("Getting parent build target identifier", { try BuildTargetIdentifier(parent) })
{
@@ -576,27 +567,6 @@ package actor SwiftPMBuildSystem: BuiltInBuildSystem {
)
}
package func targets(for uri: DocumentURI) -> [BuildTargetIdentifier] {
guard let url = uri.fileURL, let path = try? AbsolutePath(validating: url.path) else {
// We can't determine targets for non-file URIs.
return []
}
let targets = buildTargets(for: uri)
if !targets.isEmpty {
// Sort targets to get deterministic ordering. The actual order does not matter.
return targets.sorted { $0.uri.stringValue < $1.uri.stringValue }
}
if path.basename == "Package.swift"
&& projectRoot == (try? TSCBasic.resolveSymlinks(TSCBasic.AbsolutePath(path.parentDirectory)))
{
return [BuildTargetIdentifier.forPackageManifest]
}
return []
}
package func waitForBuildSystemUpdates(request: WorkspaceWaitForBuildSystemUpdatesRequest) async -> VoidResponse {
await self.packageLoadingQueue.async {}.valuePropagatingCancellation
return VoidResponse()
@@ -707,23 +677,6 @@ package actor SwiftPMBuildSystem: BuiltInBuildSystem {
}
}
/// Returns the resolved target descriptions for the given file, if one is known.
private func buildTargets(for file: DocumentURI) -> Set<BuildTargetIdentifier> {
if let targets = fileToTargets[file] {
return targets
}
if let fileURL = file.fileURL,
let realpath = try? resolveSymlinks(AbsolutePath(validating: fileURL.path)),
let targets = fileToTargets[DocumentURI(realpath.asURL)]
{
fileToTargets[file] = targets
return targets
}
return []
}
/// An event is relevant if it modifies a file that matches one of the file rules used by the SwiftPM workspace.
private func fileEventShouldTriggerPackageReload(event: FileEvent) -> Bool {
guard let fileURL = event.uri.fileURL else {