@@ -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+
393403extension 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
@@ -655,13 +669,15 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
655669 }
656670
657671 /// Returns the resolved target description for the given file, if one is known.
658- private func buildTarget( for file: AbsolutePath ) throws -> SwiftBuildTarget ? {
672+ private func buildTarget( for file: DocumentURI ) -> SwiftBuildTarget ? {
659673 if let td = fileToTarget [ file] {
660674 return td
661675 }
662676
663- let realpath = try resolveSymlinks ( file)
664- if realpath != file, let td = fileToTarget [ realpath] {
677+ if let fileURL = file. fileURL,
678+ let realpath = try ? resolveSymlinks ( AbsolutePath ( validating: fileURL. path) ) ,
679+ let td = fileToTarget [ DocumentURI ( realpath. asURL) ]
680+ {
665681 fileToTarget [ file] = td
666682 return td
667683 }
@@ -704,11 +720,7 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
704720 // If a Swift file within a target is updated, reload all the other files within the target since they might be
705721 // referring to a function in the updated file.
706722 for event in events {
707- guard let url = event. uri. fileURL,
708- url. pathExtension == " swift " ,
709- let absolutePath = try ? AbsolutePath ( validating: url. path) ,
710- let target = fileToTarget [ absolutePath]
711- else {
723+ guard event. uri. fileURL? . pathExtension == " swift " , let target = fileToTarget [ event. uri] else {
712724 continue
713725 }
714726 filesWithUpdatedDependencies. formUnion ( target. sources. map { DocumentURI ( $0) } )
@@ -724,7 +736,7 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
724736 // If we have background indexing enabled, this is not necessary because we call `fileDependenciesUpdated` when
725737 // preparation of a target finishes.
726738 if !isForIndexBuild, events. contains ( where: { $0. uri. fileURL? . pathExtension == " swiftmodule " } ) {
727- filesWithUpdatedDependencies. formUnion ( self . fileToTarget. keys. map { DocumentURI ( $0 . asURL ) } )
739+ filesWithUpdatedDependencies. formUnion ( self . fileToTarget. keys)
728740 }
729741 await self . fileDependenciesUpdatedDebouncer. scheduleCall ( filesWithUpdatedDependencies)
730742 }
@@ -737,11 +749,11 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
737749 }
738750
739751 public func sourceFiles( ) -> [ SourceFileInfo ] {
740- return fileToTarget. compactMap { ( path , target) -> SourceFileInfo ? in
752+ return fileToTarget. compactMap { ( uri , target) -> SourceFileInfo ? in
741753 // We should only set mayContainTests to `true` for files from test targets
742754 // (https://github.com/apple/sourcekit-lsp/issues/1174).
743755 return SourceFileInfo (
744- uri: DocumentURI ( path . asURL ) ,
756+ uri: uri ,
745757 isPartOfRootProject: target. isPartOfRootPackage,
746758 mayContainTests: true
747759 )
@@ -782,7 +794,7 @@ extension SwiftPMBuildSystem {
782794 func impl( _ path: AbsolutePath ) throws -> ConfiguredTarget ? {
783795 var dir = path. parentDirectory
784796 while !dir. isRoot {
785- if let buildTarget = sourceDirToTarget [ dir] {
797+ if let buildTarget = sourceDirToTarget [ DocumentURI ( dir. asURL ) ] {
786798 return ConfiguredTarget ( buildTarget)
787799 }
788800 dir = dir. parentDirectory
0 commit comments