@@ -63,6 +63,14 @@ private func getDefaultToolchain(_ toolchainRegistry: ToolchainRegistry) async -
6363 return await toolchainRegistry. default
6464}
6565
66+ fileprivate extension ConfiguredTarget {
67+ init ( _ buildTarget: any SwiftBuildTarget ) {
68+ self . init ( targetID: buildTarget. name, runDestinationID: " dummy " )
69+ }
70+
71+ static let forPackageManifest = ConfiguredTarget ( targetID: " " , runDestinationID: " " )
72+ }
73+
6674/// Swift Package Manager build system and workspace support.
6775///
6876/// This class implements the `BuildSystem` interface to provide the build settings for a Swift
@@ -101,10 +109,10 @@ public actor SwiftPMBuildSystem {
101109 var fileToTarget : [ AbsolutePath : SwiftBuildTarget ] = [ : ]
102110 var sourceDirToTarget : [ AbsolutePath : SwiftBuildTarget ] = [ : ]
103111
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 ) ] = [ : ]
112+ /// Maps configured targets ids to their SwiftPM build target as well as an index in their topological sorting.
113+ ///
114+ /// Targets with lower index are more low level, ie. targets with higher indices depend on targets with lower indices.
115+ var targets : [ ConfiguredTarget : ( index: Int , buildTarget: SwiftBuildTarget ) ] = [ : ]
108116
109117 /// The URIs for which the delegate has registered for change notifications,
110118 /// mapped to the language the delegate specified when registering for change notifications.
@@ -289,7 +297,7 @@ extension SwiftPMBuildSystem {
289297
290298 self . targets = Dictionary (
291299 try buildDescription. allTargetsInTopologicalOrder ( in: modulesGraph) . enumerated ( ) . map { ( index, target) in
292- return ( key: target. name , ( index, target) )
300+ return ( key: ConfiguredTarget ( target) , ( index, target) )
293301 } ,
294302 uniquingKeysWith: { first, second in
295303 logger. fault ( " Found two targets with the same name \( first. buildTarget. name) " )
@@ -362,11 +370,11 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
362370 return nil
363371 }
364372
365- if configuredTarget. targetID == " " {
373+ if configuredTarget == . forPackageManifest {
366374 return try settings ( forPackageManifest: path)
367375 }
368376
369- guard let buildTarget = self . targets [ configuredTarget. targetID ] ? . buildTarget else {
377+ guard let buildTarget = self . targets [ configuredTarget] ? . buildTarget else {
370378 logger. error ( " Did not find target with name \( configuredTarget. targetID) " )
371379 return nil
372380 }
@@ -397,13 +405,13 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
397405 }
398406
399407 if let target = try ? buildTarget ( for: path) {
400- return [ ConfiguredTarget ( targetID : target. name , runDestinationID : " dummy " ) ]
408+ return [ ConfiguredTarget ( target) ]
401409 }
402410
403411 if path. basename == " Package.swift " {
404412 // We use an empty target name to represent the package manifest since an empty target name is not valid for any
405413 // user-defined target.
406- return [ ConfiguredTarget ( targetID : " " , runDestinationID : " dummy " ) ]
414+ return [ ConfiguredTarget . forPackageManifest ]
407415 }
408416
409417 if url. pathExtension == " h " , let target = try ? target ( forHeader: path) {
@@ -415,19 +423,40 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
415423
416424 public func topologicalSort( of targets: [ ConfiguredTarget ] ) -> [ ConfiguredTarget ] ? {
417425 return targets. sorted { ( lhs: ConfiguredTarget , rhs: ConfiguredTarget ) -> Bool in
418- let lhsIndex = self . targets [ lhs. targetID ] ? . index ?? self . targets. count
419- let rhsIndex = self . targets [ lhs. targetID ] ? . index ?? self . targets. count
426+ let lhsIndex = self . targets [ lhs] ? . index ?? self . targets. count
427+ let rhsIndex = self . targets [ lhs] ? . index ?? self . targets. count
420428 return lhsIndex < rhsIndex
421429 }
422430 }
423431
432+ public func targets( dependingOn targets: [ ConfiguredTarget ] ) -> [ ConfiguredTarget ] ? {
433+ let targetIndices = targets. compactMap { self . targets [ $0] ? . index }
434+ let minimumTargetIndex : Int ?
435+ if targetIndices. count == targets. count {
436+ minimumTargetIndex = targetIndices. min ( )
437+ } else {
438+ // One of the targets didn't have an entry in self.targets. We don't know what might depend on it.
439+ minimumTargetIndex = nil
440+ }
441+
442+ // Files that occur before the target in the topological sorting don't depend on it.
443+ // Ideally, we should consult the dependency graph here for more accurate dependency analysis instead of relying on
444+ // a flattened list (https://github.com/apple/sourcekit-lsp/issues/1312).
445+ return self . targets. compactMap { ( configuredTarget, value) -> ConfiguredTarget ? in
446+ if let minimumTargetIndex, value. index <= minimumTargetIndex {
447+ return nil
448+ }
449+ return configuredTarget
450+ }
451+ }
452+
424453 public func prepare( targets: [ ConfiguredTarget ] ) async throws {
425454 // TODO (indexing): Support preparation of multiple targets at once.
426455 // https://github.com/apple/sourcekit-lsp/issues/1262
427456 for target in targets {
428457 try await prepare ( singleTarget: target)
429458 }
430- let filesInPreparedTargets = targets. flatMap { self . targets [ $0. targetID ] ? . buildTarget. sources ?? [ ] }
459+ let filesInPreparedTargets = targets. flatMap { self . targets [ $0] ? . buildTarget. sources ?? [ ] }
431460 await fileDependenciesUpdatedDebouncer. scheduleCall ( Set ( filesInPreparedTargets. map ( DocumentURI . init) ) )
432461 }
433462
@@ -620,7 +649,7 @@ extension SwiftPMBuildSystem {
620649 var dir = path. parentDirectory
621650 while !dir. isRoot {
622651 if let buildTarget = sourceDirToTarget [ dir] {
623- return ConfiguredTarget ( targetID : buildTarget. name , runDestinationID : " dummy " )
652+ return ConfiguredTarget ( buildTarget)
624653 }
625654 dir = dir. parentDirectory
626655 }
0 commit comments