@@ -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 }
@@ -406,13 +414,13 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
406414 }
407415
408416 if let target = try ? buildTarget ( for: path) {
409- return [ ConfiguredTarget ( targetID : target. name , runDestinationID : " dummy " ) ]
417+ return [ ConfiguredTarget ( target) ]
410418 }
411419
412420 if path. basename == " Package.swift " {
413421 // We use an empty target name to represent the package manifest since an empty target name is not valid for any
414422 // user-defined target.
415- return [ ConfiguredTarget ( targetID : " " , runDestinationID : " dummy " ) ]
423+ return [ ConfiguredTarget . forPackageManifest ]
416424 }
417425
418426 if let target = try ? inferredTarget ( for: path) {
@@ -424,19 +432,40 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
424432
425433 public func topologicalSort( of targets: [ ConfiguredTarget ] ) -> [ ConfiguredTarget ] ? {
426434 return targets. sorted { ( lhs: ConfiguredTarget , rhs: ConfiguredTarget ) -> Bool in
427- let lhsIndex = self . targets [ lhs. targetID ] ? . index ?? self . targets. count
428- let rhsIndex = self . targets [ lhs. targetID ] ? . index ?? self . targets. count
435+ let lhsIndex = self . targets [ lhs] ? . index ?? self . targets. count
436+ let rhsIndex = self . targets [ lhs] ? . index ?? self . targets. count
429437 return lhsIndex < rhsIndex
430438 }
431439 }
432440
441+ public func targets( dependingOn targets: [ ConfiguredTarget ] ) -> [ ConfiguredTarget ] ? {
442+ let targetIndices = targets. compactMap { self . targets [ $0] ? . index }
443+ let minimumTargetIndex : Int ?
444+ if targetIndices. count == targets. count {
445+ minimumTargetIndex = targetIndices. min ( )
446+ } else {
447+ // One of the targets didn't have an entry in self.targets. We don't know what might depend on it.
448+ minimumTargetIndex = nil
449+ }
450+
451+ // Files that occur before the target in the topological sorting don't depend on it.
452+ // Ideally, we should consult the dependency graph here for more accurate dependency analysis instead of relying on
453+ // a flattened list (https://github.com/apple/sourcekit-lsp/issues/1312).
454+ return self . targets. compactMap { ( configuredTarget, value) -> ConfiguredTarget ? in
455+ if let minimumTargetIndex, value. index <= minimumTargetIndex {
456+ return nil
457+ }
458+ return configuredTarget
459+ }
460+ }
461+
433462 public func prepare( targets: [ ConfiguredTarget ] ) async throws {
434463 // TODO (indexing): Support preparation of multiple targets at once.
435464 // https://github.com/apple/sourcekit-lsp/issues/1262
436465 for target in targets {
437466 try await prepare ( singleTarget: target)
438467 }
439- let filesInPreparedTargets = targets. flatMap { self . targets [ $0. targetID ] ? . buildTarget. sources ?? [ ] }
468+ let filesInPreparedTargets = targets. flatMap { self . targets [ $0] ? . buildTarget. sources ?? [ ] }
440469 await fileDependenciesUpdatedDebouncer. scheduleCall ( Set ( filesInPreparedTargets. map ( DocumentURI . init) ) )
441470 }
442471
@@ -631,7 +660,7 @@ extension SwiftPMBuildSystem {
631660 var dir = path. parentDirectory
632661 while !dir. isRoot {
633662 if let buildTarget = sourceDirToTarget [ dir] {
634- return ConfiguredTarget ( targetID : buildTarget. name , runDestinationID : " dummy " )
663+ return ConfiguredTarget ( buildTarget)
635664 }
636665 dir = dir. parentDirectory
637666 }
0 commit comments