Skip to content

Commit 3c5d8b9

Browse files
committed
Change SwiftPMBuildSystem to use DocumentURI instead of URL
1 parent f84cfec commit 3c5d8b9

File tree

3 files changed

+152
-70
lines changed

3 files changed

+152
-70
lines changed

Sources/SKSwiftPMWorkspace/SwiftPMBuildSystem.swift

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ public actor SwiftPMBuildSystem {
146146
}
147147
}
148148

149-
var fileToTarget: [AbsolutePath: SwiftBuildTarget] = [:]
150-
var sourceDirToTarget: [AbsolutePath: SwiftBuildTarget] = [:]
149+
var fileToTarget: [DocumentURI: SwiftBuildTarget] = [:]
150+
var sourceDirToTarget: [DocumentURI: SwiftBuildTarget] = [:]
151151

152152
/// Maps configured targets ids to their SwiftPM build target as well as an index in their topological sorting.
153153
///
@@ -286,15 +286,18 @@ public actor SwiftPMBuildSystem {
286286
/// - reloadPackageStatusCallback: Will be informed when `reloadPackage` starts and ends executing.
287287
/// - Returns: nil if `workspacePath` is not part of a package or there is an error.
288288
public init?(
289-
url: URL,
289+
uri: DocumentURI,
290290
toolchainRegistry: ToolchainRegistry,
291291
buildSetup: BuildSetup,
292292
isForIndexBuild: Bool,
293293
reloadPackageStatusCallback: @escaping (ReloadPackageStatus) async -> Void
294294
) async {
295+
guard let fileURL = uri.fileURL else {
296+
return nil
297+
}
295298
do {
296299
try await self.init(
297-
workspacePath: try TSCAbsolutePath(validating: url.path),
300+
workspacePath: try TSCAbsolutePath(validating: fileURL.path),
298301
toolchainRegistry: toolchainRegistry,
299302
fileSystem: localFileSystem,
300303
buildSetup: buildSetup,
@@ -304,7 +307,7 @@ public actor SwiftPMBuildSystem {
304307
} catch Error.noManifest {
305308
return nil
306309
} catch {
307-
logger.error("failed to create SwiftPMWorkspace at \(url.path): \(error.forLogging)")
310+
logger.error("failed to create SwiftPMWorkspace at \(uri.forLogging): \(error.forLogging)")
308311
return nil
309312
}
310313
}
@@ -351,13 +354,13 @@ extension SwiftPMBuildSystem {
351354
}
352355
)
353356

354-
self.fileToTarget = [AbsolutePath: SwiftBuildTarget](
357+
self.fileToTarget = [DocumentURI: SwiftBuildTarget](
355358
modulesGraph.allTargets.flatMap { target in
356359
return target.sources.paths.compactMap {
357360
guard let buildTarget = buildDescription.getBuildTarget(for: target, in: modulesGraph) else {
358361
return nil
359362
}
360-
return (key: $0, value: buildTarget)
363+
return (key: DocumentURI($0.asURL), value: buildTarget)
361364
}
362365
},
363366
uniquingKeysWith: { td, _ in
@@ -366,12 +369,12 @@ extension SwiftPMBuildSystem {
366369
}
367370
)
368371

369-
self.sourceDirToTarget = [AbsolutePath: SwiftBuildTarget](
370-
modulesGraph.allTargets.compactMap { (target) -> (AbsolutePath, SwiftBuildTarget)? in
372+
self.sourceDirToTarget = [DocumentURI: SwiftBuildTarget](
373+
modulesGraph.allTargets.compactMap { (target) -> (DocumentURI, SwiftBuildTarget)? in
371374
guard let buildTarget = buildDescription.getBuildTarget(for: target, in: modulesGraph) else {
372375
return nil
373376
}
374-
return (key: target.sources.root, value: buildTarget)
377+
return (key: DocumentURI(target.sources.root.asURL), value: buildTarget)
375378
},
376379
uniquingKeysWith: { td, _ in
377380
// FIXME: is there a preferred target?
@@ -390,6 +393,13 @@ extension SwiftPMBuildSystem {
390393
}
391394
}
392395

396+
fileprivate struct NonFileURIError: Error, CustomStringConvertible {
397+
let uri: DocumentURI
398+
var description: String {
399+
"Trying to get build settings for non-file URI: \(uri)"
400+
}
401+
}
402+
393403
extension SwiftPMBuildSystem: SKCore.BuildSystem {
394404
public nonisolated var supportsPreparation: Bool { true }
395405

@@ -410,8 +420,11 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
410420

411421
/// Return the compiler arguments for the given source file within a target, making any necessary adjustments to
412422
/// account for differences in the SwiftPM versions being linked into SwiftPM and being installed in the toolchain.
413-
private func compilerArguments(for file: URL, in buildTarget: any SwiftBuildTarget) async throws -> [String] {
414-
let compileArguments = try buildTarget.compileArguments(for: file)
423+
private func compilerArguments(for file: DocumentURI, in buildTarget: any SwiftBuildTarget) async throws -> [String] {
424+
guard let fileURL = file.fileURL else {
425+
throw NonFileURIError(uri: file)
426+
}
427+
let compileArguments = try buildTarget.compileArguments(for: fileURL)
415428

416429
#if compiler(>=6.1)
417430
#warning("When we drop support for Swift 5.10 we no longer need to adjust compiler arguments for the Modules move")
@@ -449,9 +462,10 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
449462
return nil
450463
}
451464

452-
if !buildTarget.sources.contains(url),
465+
if !buildTarget.sources.lazy.map(DocumentURI.init).contains(uri),
453466
let substituteFile = buildTarget.sources.sorted(by: { $0.path < $1.path }).first
454467
{
468+
logger.info("Getting compiler arguments for \(url) using substitute file \(substituteFile)")
455469
// If `url` is not part of the target's source, it's most likely a header file. Fake compiler arguments for it
456470
// from a substitute file within the target.
457471
// Even if the file is not a header, this should give reasonable results: Say, there was a new `.cpp` file in a
@@ -460,13 +474,13 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
460474
// getting its compiler arguments and then patching up the compiler arguments by replacing the substitute file
461475
// with the `.cpp` file.
462476
return FileBuildSettings(
463-
compilerArguments: try await compilerArguments(for: substituteFile, in: buildTarget),
477+
compilerArguments: try await compilerArguments(for: DocumentURI(substituteFile), in: buildTarget),
464478
workingDirectory: workspacePath.pathString
465479
).patching(newFile: try resolveSymlinks(path).pathString, originalFile: substituteFile.absoluteString)
466480
}
467481

468482
return FileBuildSettings(
469-
compilerArguments: try await compilerArguments(for: url, in: buildTarget),
483+
compilerArguments: try await compilerArguments(for: uri, in: buildTarget),
470484
workingDirectory: workspacePath.pathString
471485
)
472486
}
@@ -483,7 +497,7 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
483497
return []
484498
}
485499

486-
if let target = try? buildTarget(for: path) {
500+
if let target = buildTarget(for: uri) {
487501
return [ConfiguredTarget(target)]
488502
}
489503

@@ -626,13 +640,15 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
626640
}
627641

628642
/// Returns the resolved target description for the given file, if one is known.
629-
private func buildTarget(for file: AbsolutePath) throws -> SwiftBuildTarget? {
643+
private func buildTarget(for file: DocumentURI) -> SwiftBuildTarget? {
630644
if let td = fileToTarget[file] {
631645
return td
632646
}
633647

634-
let realpath = try resolveSymlinks(file)
635-
if realpath != file, let td = fileToTarget[realpath] {
648+
if let fileURL = file.fileURL,
649+
let realpath = try? resolveSymlinks(AbsolutePath(validating: fileURL.path)),
650+
let td = fileToTarget[DocumentURI(realpath.asURL)]
651+
{
636652
fileToTarget[file] = td
637653
return td
638654
}
@@ -675,11 +691,7 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
675691
// If a Swift file within a target is updated, reload all the other files within the target since they might be
676692
// referring to a function in the updated file.
677693
for event in events {
678-
guard let url = event.uri.fileURL,
679-
url.pathExtension == "swift",
680-
let absolutePath = try? AbsolutePath(validating: url.path),
681-
let target = fileToTarget[absolutePath]
682-
else {
694+
guard event.uri.fileURL?.pathExtension == "swift", let target = fileToTarget[event.uri] else {
683695
continue
684696
}
685697
filesWithUpdatedDependencies.formUnion(target.sources.map { DocumentURI($0) })
@@ -695,7 +707,7 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
695707
// If we have background indexing enabled, this is not necessary because we call `fileDependenciesUpdated` when
696708
// preparation of a target finishes.
697709
if !isForIndexBuild, events.contains(where: { $0.uri.fileURL?.pathExtension == "swiftmodule" }) {
698-
filesWithUpdatedDependencies.formUnion(self.fileToTarget.keys.map { DocumentURI($0.asURL) })
710+
filesWithUpdatedDependencies.formUnion(self.fileToTarget.keys)
699711
}
700712
await self.fileDependenciesUpdatedDebouncer.scheduleCall(filesWithUpdatedDependencies)
701713
}
@@ -708,11 +720,11 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
708720
}
709721

710722
public func sourceFiles() -> [SourceFileInfo] {
711-
return fileToTarget.compactMap { (path, target) -> SourceFileInfo? in
723+
return fileToTarget.compactMap { (uri, target) -> SourceFileInfo? in
712724
// We should only set mayContainTests to `true` for files from test targets
713725
// (https://github.com/apple/sourcekit-lsp/issues/1174).
714726
return SourceFileInfo(
715-
uri: DocumentURI(path.asURL),
727+
uri: uri,
716728
isPartOfRootProject: target.isPartOfRootPackage,
717729
mayContainTests: true
718730
)
@@ -753,7 +765,7 @@ extension SwiftPMBuildSystem {
753765
func impl(_ path: AbsolutePath) throws -> ConfiguredTarget? {
754766
var dir = path.parentDirectory
755767
while !dir.isRoot {
756-
if let buildTarget = sourceDirToTarget[dir] {
768+
if let buildTarget = sourceDirToTarget[DocumentURI(dir.asURL)] {
757769
return ConfiguredTarget(buildTarget)
758770
}
759771
dir = dir.parentDirectory

Sources/SourceKitLSP/CreateBuildSystem.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ func createBuildSystem(
3333
)
3434
return nil
3535
}
36-
func createSwiftPMBuildSystem(rootUrl: URL) async -> SwiftPMBuildSystem? {
36+
func createSwiftPMBuildSystem(rootUri: DocumentURI) async -> SwiftPMBuildSystem? {
3737
return await SwiftPMBuildSystem(
38-
url: rootUrl,
38+
uri: rootUri,
3939
toolchainRegistry: toolchainRegistry,
4040
buildSetup: options.buildSetup,
4141
isForIndexBuild: options.indexOptions.enableBackgroundIndexing,
@@ -58,14 +58,14 @@ func createBuildSystem(
5858
switch options.buildSetup.defaultWorkspaceType {
5959
case .buildServer: await createBuildServerBuildSystem(rootPath: rootPath)
6060
case .compilationDatabase: createCompilationDatabaseBuildSystem(rootPath: rootPath)
61-
case .swiftPM: await createSwiftPMBuildSystem(rootUrl: rootUrl)
61+
case .swiftPM: await createSwiftPMBuildSystem(rootUri: rootUri)
6262
case nil: nil
6363
}
6464
if let defaultBuildSystem {
6565
return defaultBuildSystem
6666
} else if let buildServer = await createBuildServerBuildSystem(rootPath: rootPath) {
6767
return buildServer
68-
} else if let swiftpm = await createSwiftPMBuildSystem(rootUrl: rootUrl) {
68+
} else if let swiftpm = await createSwiftPMBuildSystem(rootUri: rootUri) {
6969
return swiftpm
7070
} else if let compdb = createCompilationDatabaseBuildSystem(rootPath: rootPath) {
7171
return compdb

0 commit comments

Comments
 (0)