@@ -63,6 +63,14 @@ private func getDefaultToolchain(_ toolchainRegistry: ToolchainRegistry) async -
63
63
return await toolchainRegistry. default
64
64
}
65
65
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
+
66
74
/// Swift Package Manager build system and workspace support.
67
75
///
68
76
/// This class implements the `BuildSystem` interface to provide the build settings for a Swift
@@ -101,10 +109,10 @@ public actor SwiftPMBuildSystem {
101
109
var fileToTarget : [ AbsolutePath : SwiftBuildTarget ] = [ : ]
102
110
var sourceDirToTarget : [ AbsolutePath : SwiftBuildTarget ] = [ : ]
103
111
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 ) ] = [ : ]
108
116
109
117
/// The URIs for which the delegate has registered for change notifications,
110
118
/// mapped to the language the delegate specified when registering for change notifications.
@@ -289,7 +297,7 @@ extension SwiftPMBuildSystem {
289
297
290
298
self . targets = Dictionary (
291
299
try buildDescription. allTargetsInTopologicalOrder ( in: modulesGraph) . enumerated ( ) . map { ( index, target) in
292
- return ( key: target. name , ( index, target) )
300
+ return ( key: ConfiguredTarget ( target) , ( index, target) )
293
301
} ,
294
302
uniquingKeysWith: { first, second in
295
303
logger. fault ( " Found two targets with the same name \( first. buildTarget. name) " )
@@ -362,11 +370,11 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
362
370
return nil
363
371
}
364
372
365
- if configuredTarget. targetID == " " {
373
+ if configuredTarget == . forPackageManifest {
366
374
return try settings ( forPackageManifest: path)
367
375
}
368
376
369
- guard let buildTarget = self . targets [ configuredTarget. targetID ] ? . buildTarget else {
377
+ guard let buildTarget = self . targets [ configuredTarget] ? . buildTarget else {
370
378
logger. error ( " Did not find target with name \( configuredTarget. targetID) " )
371
379
return nil
372
380
}
@@ -406,13 +414,13 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
406
414
}
407
415
408
416
if let target = try ? buildTarget ( for: path) {
409
- return [ ConfiguredTarget ( targetID : target. name , runDestinationID : " dummy " ) ]
417
+ return [ ConfiguredTarget ( target) ]
410
418
}
411
419
412
420
if path. basename == " Package.swift " {
413
421
// We use an empty target name to represent the package manifest since an empty target name is not valid for any
414
422
// user-defined target.
415
- return [ ConfiguredTarget ( targetID : " " , runDestinationID : " dummy " ) ]
423
+ return [ ConfiguredTarget . forPackageManifest ]
416
424
}
417
425
418
426
if let target = try ? inferredTarget ( for: path) {
@@ -424,19 +432,40 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
424
432
425
433
public func topologicalSort( of targets: [ ConfiguredTarget ] ) -> [ ConfiguredTarget ] ? {
426
434
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
429
437
return lhsIndex < rhsIndex
430
438
}
431
439
}
432
440
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
+
433
462
public func prepare( targets: [ ConfiguredTarget ] ) async throws {
434
463
// TODO (indexing): Support preparation of multiple targets at once.
435
464
// https://github.com/apple/sourcekit-lsp/issues/1262
436
465
for target in targets {
437
466
try await prepare ( singleTarget: target)
438
467
}
439
- let filesInPreparedTargets = targets. flatMap { self . targets [ $0. targetID ] ? . buildTarget. sources ?? [ ] }
468
+ let filesInPreparedTargets = targets. flatMap { self . targets [ $0] ? . buildTarget. sources ?? [ ] }
440
469
await fileDependenciesUpdatedDebouncer. scheduleCall ( Set ( filesInPreparedTargets. map ( DocumentURI . init) ) )
441
470
}
442
471
@@ -631,7 +660,7 @@ extension SwiftPMBuildSystem {
631
660
var dir = path. parentDirectory
632
661
while !dir. isRoot {
633
662
if let buildTarget = sourceDirToTarget [ dir] {
634
- return ConfiguredTarget ( targetID : buildTarget. name , runDestinationID : " dummy " )
663
+ return ConfiguredTarget ( buildTarget)
635
664
}
636
665
dir = dir. parentDirectory
637
666
}
0 commit comments