Skip to content

Commit bb96ff4

Browse files
committed
Migrate targets(dependingOn:) to BSP
1 parent 897cd5e commit bb96ff4

9 files changed

+45
-65
lines changed

Sources/BuildSystemIntegration/BuildServerBuildSystem.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,6 @@ extension BuildServerBuildSystem: BuiltInBuildSystem {
340340
return nil
341341
}
342342

343-
package func targets(dependingOn targets: [BuildTargetIdentifier]) -> [BuildTargetIdentifier]? {
344-
return nil
345-
}
346-
347343
package func addSourceFilesDidChangeCallback(_ callback: @escaping () async -> Void) {
348344
// BuildServerBuildSystem does not support syntactic test discovery or background indexing.
349345
// (https://github.com/swiftlang/sourcekit-lsp/issues/1173).

Sources/BuildSystemIntegration/BuildSystemManager.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,8 +489,14 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
489489
return await buildSystem?.underlyingBuildSystem.topologicalSort(of: targets)
490490
}
491491

492-
package func targets(dependingOn targets: [BuildTargetIdentifier]) async -> [BuildTargetIdentifier]? {
493-
return await buildSystem?.underlyingBuildSystem.targets(dependingOn: targets)
492+
/// Returns the list of targets that might depend on the given target and that need to be re-prepared when a file in
493+
/// `target` is modified.
494+
package func targets(dependingOn targetIds: Set<BuildTargetIdentifier>) async -> [BuildTargetIdentifier] {
495+
guard let buildTargets = await orLog("Getting build targets for dependencies", { try await self.buildTargets() })
496+
else {
497+
return []
498+
}
499+
return buildTargets.filter { $0.dependencies.contains(anyIn: targetIds) }.map { $0.id }
494500
}
495501

496502
package func prepare(

Sources/BuildSystemIntegration/BuiltInBuildSystem.swift

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,6 @@ package protocol BuiltInBuildSystem: AnyObject, Sendable {
113113
/// `nil` if the build system doesn't support topological sorting of targets.
114114
func topologicalSort(of targets: [BuildTargetIdentifier]) async -> [BuildTargetIdentifier]?
115115

116-
/// Returns the list of targets that might depend on the given target and that need to be re-prepared when a file in
117-
/// `target` is modified.
118-
///
119-
/// The returned list can be an over-approximation, in which case the indexer will perform more work than strictly
120-
/// necessary by scheduling re-preparation of a target where it isn't necessary.
121-
///
122-
/// Returning `nil` indicates that all targets should be considered depending on the given target.
123-
func targets(dependingOn targets: [BuildTargetIdentifier]) async -> [BuildTargetIdentifier]?
124-
125116
/// The toolchain that should be used to open the given document.
126117
///
127118
/// If `nil` is returned, then the default toolchain for the given language is used.

Sources/BuildSystemIntegration/CompilationDatabaseBuildSystem.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,6 @@ extension CompilationDatabaseBuildSystem: BuiltInBuildSystem {
163163
return nil
164164
}
165165

166-
package func targets(dependingOn targets: [BuildTargetIdentifier]) -> [BuildTargetIdentifier]? {
167-
return nil
168-
}
169-
170166
private func database(for uri: DocumentURI) -> CompilationDatabase? {
171167
if let url = uri.fileURL, let path = try? AbsolutePath(validating: url.path) {
172168
return database(for: path)

Sources/BuildSystemIntegration/SwiftPMBuildSystem.swift

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ package actor SwiftPMBuildSystem {
215215
/// greater depth.
216216
private var targets: [BuildTargetIdentifier: (buildTarget: SwiftBuildTarget, depth: Int)] = [:]
217217

218+
private var targetDependencies: [BuildTargetIdentifier: Set<BuildTargetIdentifier>] = [:]
219+
218220
static package func projectRoot(
219221
for path: TSCBasic.AbsolutePath,
220222
options: SourceKitLSPOptions
@@ -442,6 +444,8 @@ extension SwiftPMBuildSystem {
442444

443445
self.targets = [:]
444446
self.fileToTargets = [:]
447+
self.targetDependencies = [:]
448+
445449
buildDescription.traverseModules { buildTarget, parent, depth in
446450
let targetIdentifier = orLog("Getting build target identifier") { try BuildTargetIdentifier(buildTarget) }
447451
guard let targetIdentifier else {
@@ -455,6 +459,11 @@ extension SwiftPMBuildSystem {
455459
fileToTargets[DocumentURI(source), default: []].insert(targetIdentifier)
456460
}
457461
}
462+
if let parent,
463+
let parentIdentifier = orLog("Getting parent build target identifier", { try BuildTargetIdentifier(parent) })
464+
{
465+
self.targetDependencies[parentIdentifier, default: []].insert(targetIdentifier)
466+
}
458467
targets[targetIdentifier] = (buildTarget, depth)
459468
}
460469

@@ -527,8 +536,7 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
527536
capabilities: BuildTargetCapabilities(),
528537
// Be conservative with the languages that might be used in the target. SourceKit-LSP doesn't use this property.
529538
languageIds: [.c, .cpp, .objective_c, .objective_cpp, .swift],
530-
// FIXME: (BSP migration) List the target's dependencies
531-
dependencies: []
539+
dependencies: self.targetDependencies[targetId, default: []].sorted { $0.uri.stringValue < $1.uri.stringValue }
532540
)
533541
}
534542
return BuildTargetsResponse(targets: targets)
@@ -635,27 +643,6 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
635643
}
636644
}
637645

638-
package func targets(dependingOn targets: [BuildTargetIdentifier]) -> [BuildTargetIdentifier]? {
639-
let targetDepths = targets.compactMap { self.targets[$0]?.depth }
640-
let minimumTargetDepth: Int?
641-
if targetDepths.count == targets.count {
642-
minimumTargetDepth = targetDepths.max()
643-
} else {
644-
// One of the targets didn't have an entry in self.targets. We don't know what might depend on it.
645-
minimumTargetDepth = nil
646-
}
647-
648-
// Files that occur before the target in the topological sorting don't depend on it.
649-
// Ideally, we should consult the dependency graph here for more accurate dependency analysis instead of relying on
650-
// a flattened list (https://github.com/swiftlang/sourcekit-lsp/issues/1312).
651-
return self.targets.compactMap { (targets, value) -> BuildTargetIdentifier? in
652-
if let minimumTargetDepth, value.depth >= minimumTargetDepth {
653-
return nil
654-
}
655-
return targets
656-
}
657-
}
658-
659646
package func prepare(request: PrepareTargetsRequest) async throws -> VoidResponse {
660647
// TODO: Support preparation of multiple targets at once. (https://github.com/swiftlang/sourcekit-lsp/issues/1262)
661648
for target in request.targets {

Sources/BuildSystemIntegration/TestBuildSystem.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,5 @@ package actor TestBuildSystem: BuiltInBuildSystem {
8080
return nil
8181
}
8282

83-
package func targets(dependingOn targets: [BuildTargetIdentifier]) -> [BuildTargetIdentifier]? {
84-
return nil
85-
}
86-
8783
package func addSourceFilesDidChangeCallback(_ callback: @escaping () async -> Void) async {}
8884
}

Sources/SemanticIndex/SemanticIndexManager.swift

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -348,25 +348,14 @@ package final actor SemanticIndexManager {
348348
await indexStoreUpToDateTracker.markOutOfDate(changedFiles)
349349

350350
let targets = await changedFiles.asyncMap { await buildSystemManager.targets(for: $0) }.flatMap { $0 }
351-
if let dependentTargets = await buildSystemManager.targets(dependingOn: targets) {
352-
logger.info(
353-
"""
354-
Marking targets as out-of-date: \
355-
\(String(dependentTargets.map(\.uri.stringValue).joined(separator: ", ")))
356-
"""
357-
)
358-
await preparationUpToDateTracker.markOutOfDate(dependentTargets)
359-
} else {
360-
logger.info("Marking all targets as out-of-date")
361-
await preparationUpToDateTracker.markAllKnownOutOfDate()
362-
// `markAllOutOfDate` only marks targets out-of-date that have been indexed before. Also mark all targets with
363-
// in-progress preparation out of date. So we don't get into the following situation, which would result in an
364-
// incorrect up-to-date status of a target
365-
// - Target preparation starts for the first time
366-
// - Files changed
367-
// - Target preparation finishes.
368-
await preparationUpToDateTracker.markOutOfDate(inProgressPreparationTasks.keys)
369-
}
351+
let dependentTargets = await buildSystemManager.targets(dependingOn: Set(targets))
352+
logger.info(
353+
"""
354+
Marking targets as out-of-date: \
355+
\(String(dependentTargets.map(\.uri.stringValue).joined(separator: ", ")))
356+
"""
357+
)
358+
await preparationUpToDateTracker.markOutOfDate(dependentTargets)
370359

371360
await scheduleBackgroundIndex(files: changedFiles, indexFilesWithUpToDateUnit: false)
372361
}

Sources/SwiftExtensions/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_library(SwiftExtensions STATIC
1010
PipeAsStringHandler.swift
1111
ResultExtensions.swift
1212
Sequence+AsyncMap.swift
13+
Sequence+ContainsAnyIn.swift
1314
Task+WithPriorityChangedHandler.swift
1415
ThreadSafeBox.swift
1516
)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
extension Sequence {
14+
/// Returns `true` if the intersection of `self` and `other` is not empty.
15+
package func contains(anyIn other: Set<Element>) -> Bool where Element: Hashable {
16+
return self.contains { other.contains($0) }
17+
}
18+
}

0 commit comments

Comments
 (0)