@@ -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
}
@@ -397,13 +405,13 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
397
405
}
398
406
399
407
if let target = try ? buildTarget ( for: path) {
400
- return [ ConfiguredTarget ( targetID : target. name , runDestinationID : " dummy " ) ]
408
+ return [ ConfiguredTarget ( target) ]
401
409
}
402
410
403
411
if path. basename == " Package.swift " {
404
412
// We use an empty target name to represent the package manifest since an empty target name is not valid for any
405
413
// user-defined target.
406
- return [ ConfiguredTarget ( targetID : " " , runDestinationID : " dummy " ) ]
414
+ return [ ConfiguredTarget . forPackageManifest ]
407
415
}
408
416
409
417
if url. pathExtension == " h " , let target = try ? target ( forHeader: path) {
@@ -415,19 +423,40 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
415
423
416
424
public func topologicalSort( of targets: [ ConfiguredTarget ] ) -> [ ConfiguredTarget ] ? {
417
425
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
420
428
return lhsIndex < rhsIndex
421
429
}
422
430
}
423
431
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
+
424
453
public func prepare( targets: [ ConfiguredTarget ] ) async throws {
425
454
// TODO (indexing): Support preparation of multiple targets at once.
426
455
// https://github.com/apple/sourcekit-lsp/issues/1262
427
456
for target in targets {
428
457
try await prepare ( singleTarget: target)
429
458
}
430
- let filesInPreparedTargets = targets. flatMap { self . targets [ $0. targetID ] ? . buildTarget. sources ?? [ ] }
459
+ let filesInPreparedTargets = targets. flatMap { self . targets [ $0] ? . buildTarget. sources ?? [ ] }
431
460
await fileDependenciesUpdatedDebouncer. scheduleCall ( Set ( filesInPreparedTargets. map ( DocumentURI . init) ) )
432
461
}
433
462
@@ -620,7 +649,7 @@ extension SwiftPMBuildSystem {
620
649
var dir = path. parentDirectory
621
650
while !dir. isRoot {
622
651
if let buildTarget = sourceDirToTarget [ dir] {
623
- return ConfiguredTarget ( targetID : buildTarget. name , runDestinationID : " dummy " )
652
+ return ConfiguredTarget ( buildTarget)
624
653
}
625
654
dir = dir. parentDirectory
626
655
}
0 commit comments