Skip to content

Commit 221c9b2

Browse files
committed
Move logic to select the toolchain for a document from SourceKitLSPServer to BuildSystemManager
This allows us to determine the toolchain to use during background indexing. It also moves toolchain selection closer to the build system, which is good because when we support multiple toolchains for a single workspace, the build system is what decides which toolchain to use for which document.
1 parent 9c01f87 commit 221c9b2

File tree

5 files changed

+67
-40
lines changed

5 files changed

+67
-40
lines changed

Sources/SKCore/BuildSystemManager.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ public actor BuildSystemManager {
5050
/// Build system delegate that will receive notifications about setting changes, etc.
5151
var delegate: BuildSystemDelegate?
5252

53+
/// The list of toolchains that are available.
54+
///
55+
/// Used to determine which toolchain to use for a given document.
56+
private let toolchainRegistry: ToolchainRegistry
57+
5358
/// The root of the project that this build system manages. For example, for SwiftPM packages, this is the folder
5459
/// containing Package.swift. For compilation databases it is the root folder based on which the compilation database
5560
/// was found.
@@ -65,13 +70,15 @@ public actor BuildSystemManager {
6570
buildSystem: BuildSystem?,
6671
fallbackBuildSystem: FallbackBuildSystem?,
6772
mainFilesProvider: MainFilesProvider?,
73+
toolchainRegistry: ToolchainRegistry,
6874
fallbackSettingsTimeout: DispatchTimeInterval = .seconds(3)
6975
) async {
7076
let buildSystemHasDelegate = await buildSystem?.delegate != nil
7177
precondition(!buildSystemHasDelegate)
7278
self.buildSystem = buildSystem
7379
self.fallbackBuildSystem = fallbackBuildSystem
7480
self.mainFilesProvider = mainFilesProvider
81+
self.toolchainRegistry = toolchainRegistry
7582
self.fallbackSettingsTimeout = fallbackSettingsTimeout
7683
await self.buildSystem?.setDelegate(self)
7784
}
@@ -87,6 +94,13 @@ extension BuildSystemManager {
8794
self.delegate = delegate
8895
}
8996

97+
/// Returns the toolchain that should be used to process the given document.
98+
public func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain? {
99+
// To support multiple toolchains within a single workspace, we need to ask the build system which toolchain to use
100+
// for this document.
101+
return await toolchainRegistry.defaultToolchain(for: language)
102+
}
103+
90104
/// - Note: Needed so we can set the delegate from a different isolation context.
91105
public func setMainFilesProvider(_ mainFilesProvider: MainFilesProvider?) {
92106
self.mainFilesProvider = mainFilesProvider

Sources/SKCore/ToolchainRegistry.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import Dispatch
1414
import Foundation
15+
import LanguageServerProtocol
1516
import SKSupport
1617

1718
import struct TSCBasic.AbsolutePath
@@ -244,6 +245,33 @@ public final actor ToolchainRegistry {
244245
public var darwinToolchainIdentifier: String {
245246
return darwinToolchainOverride ?? ToolchainRegistry.darwinDefaultToolchainIdentifier
246247
}
248+
249+
/// The toolchain to use for a document in the given language if the build system doesn't override it.
250+
func defaultToolchain(for language: Language) -> Toolchain? {
251+
let supportsLang = { (toolchain: Toolchain) -> Bool in
252+
// FIXME: the fact that we're looking at clangd/sourcekitd instead of the compiler indicates this method needs a parameter stating what kind of tool we're looking for.
253+
switch language {
254+
case .swift:
255+
return toolchain.sourcekitd != nil
256+
case .c, .cpp, .objective_c, .objective_cpp:
257+
return toolchain.clangd != nil
258+
default:
259+
return false
260+
}
261+
}
262+
263+
if let toolchain = self.default, supportsLang(toolchain) {
264+
return toolchain
265+
}
266+
267+
for toolchain in toolchains {
268+
if supportsLang(toolchain) {
269+
return toolchain
270+
}
271+
}
272+
273+
return nil
274+
}
247275
}
248276

249277
/// Inspecting internal state for testing purposes.

Sources/SourceKitLSP/SourceKitLSPServer.swift

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -653,32 +653,6 @@ public actor SourceKitLSPServer {
653653
return try await client.send(request)
654654
}
655655

656-
func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain? {
657-
let supportsLang = { (toolchain: Toolchain) -> Bool in
658-
// FIXME: the fact that we're looking at clangd/sourcekitd instead of the compiler indicates this method needs a parameter stating what kind of tool we're looking for.
659-
switch language {
660-
case .swift:
661-
return toolchain.sourcekitd != nil
662-
case .c, .cpp, .objective_c, .objective_cpp:
663-
return toolchain.clangd != nil
664-
default:
665-
return false
666-
}
667-
}
668-
669-
if let toolchain = await toolchainRegistry.default, supportsLang(toolchain) {
670-
return toolchain
671-
}
672-
673-
for toolchain in await toolchainRegistry.toolchains {
674-
if supportsLang(toolchain) {
675-
return toolchain
676-
}
677-
}
678-
679-
return nil
680-
}
681-
682656
/// After the language service has crashed, send `DidOpenTextDocumentNotification`s to a newly instantiated language service for previously open documents.
683657
func reopenDocuments(for languageService: LanguageService) async {
684658
for documentUri in self.documentManager.openDocuments {
@@ -815,7 +789,7 @@ public actor SourceKitLSPServer {
815789
return service
816790
}
817791

818-
guard let toolchain = await toolchain(for: uri, language),
792+
guard let toolchain = await workspace.buildSystemManager.toolchain(for: uri, language),
819793
let service = await languageService(for: toolchain, language, in: workspace)
820794
else {
821795
return nil

Sources/SourceKitLSP/Workspace.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ public final class Workspace {
9191
self.buildSystemManager = await BuildSystemManager(
9292
buildSystem: underlyingBuildSystem,
9393
fallbackBuildSystem: FallbackBuildSystem(buildSetup: buildSetup),
94-
mainFilesProvider: uncheckedIndex
94+
mainFilesProvider: uncheckedIndex,
95+
toolchainRegistry: toolchainRegistry
9596
)
9697
await indexDelegate?.addMainFileChangedCallback { [weak self] in
9798
await self?.buildSystemManager.mainFilesChanged()

Tests/SKCoreTests/BuildSystemManagerTests.swift

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import BuildServerProtocol
1414
import LSPTestSupport
1515
import LanguageServerProtocol
16-
import SKCore
16+
@_spi(Testing) import SKCore
1717
import TSCBasic
1818
import XCTest
1919

@@ -37,7 +37,8 @@ final class BuildSystemManagerTests: XCTestCase {
3737
let bsm = await BuildSystemManager(
3838
buildSystem: nil,
3939
fallbackBuildSystem: FallbackBuildSystem(buildSetup: .default),
40-
mainFilesProvider: mainFiles
40+
mainFilesProvider: mainFiles,
41+
toolchainRegistry: ToolchainRegistry.forTesting
4142
)
4243
defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks.
4344

@@ -88,13 +89,14 @@ final class BuildSystemManagerTests: XCTestCase {
8889
}
8990

9091
func testSettingsMainFile() async throws {
91-
let a = try try DocumentURI(string: "bsm:a.swift")
92+
let a = try DocumentURI(string: "bsm:a.swift")
9293
let mainFiles = ManualMainFilesProvider([a: [a]])
9394
let bs = ManualBuildSystem()
9495
let bsm = await BuildSystemManager(
9596
buildSystem: bs,
9697
fallbackBuildSystem: nil,
97-
mainFilesProvider: mainFiles
98+
mainFilesProvider: mainFiles,
99+
toolchainRegistry: ToolchainRegistry.forTesting
98100
)
99101
defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks.
100102
let del = await BSMDelegate(bsm)
@@ -117,7 +119,8 @@ final class BuildSystemManagerTests: XCTestCase {
117119
let bsm = await BuildSystemManager(
118120
buildSystem: bs,
119121
fallbackBuildSystem: nil,
120-
mainFilesProvider: mainFiles
122+
mainFilesProvider: mainFiles,
123+
toolchainRegistry: ToolchainRegistry.forTesting
121124
)
122125
defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks.
123126
let del = await BSMDelegate(bsm)
@@ -139,7 +142,8 @@ final class BuildSystemManagerTests: XCTestCase {
139142
let bsm = await BuildSystemManager(
140143
buildSystem: bs,
141144
fallbackBuildSystem: fallback,
142-
mainFilesProvider: mainFiles
145+
mainFilesProvider: mainFiles,
146+
toolchainRegistry: ToolchainRegistry.forTesting
143147
)
144148
defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks.
145149
let del = await BSMDelegate(bsm)
@@ -168,7 +172,8 @@ final class BuildSystemManagerTests: XCTestCase {
168172
let bsm = await BuildSystemManager(
169173
buildSystem: bs,
170174
fallbackBuildSystem: nil,
171-
mainFilesProvider: mainFiles
175+
mainFilesProvider: mainFiles,
176+
toolchainRegistry: ToolchainRegistry.forTesting
172177
)
173178
defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks.
174179
let del = await BSMDelegate(bsm)
@@ -208,7 +213,8 @@ final class BuildSystemManagerTests: XCTestCase {
208213
let bsm = await BuildSystemManager(
209214
buildSystem: bs,
210215
fallbackBuildSystem: nil,
211-
mainFilesProvider: mainFiles
216+
mainFilesProvider: mainFiles,
217+
toolchainRegistry: ToolchainRegistry.forTesting
212218
)
213219
defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks.
214220
let del = await BSMDelegate(bsm)
@@ -246,7 +252,8 @@ final class BuildSystemManagerTests: XCTestCase {
246252
let bsm = await BuildSystemManager(
247253
buildSystem: bs,
248254
fallbackBuildSystem: nil,
249-
mainFilesProvider: mainFiles
255+
mainFilesProvider: mainFiles,
256+
toolchainRegistry: ToolchainRegistry.forTesting
250257
)
251258
defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks.
252259
let del = await BSMDelegate(bsm)
@@ -300,7 +307,8 @@ final class BuildSystemManagerTests: XCTestCase {
300307
let bsm = await BuildSystemManager(
301308
buildSystem: bs,
302309
fallbackBuildSystem: nil,
303-
mainFilesProvider: mainFiles
310+
mainFilesProvider: mainFiles,
311+
toolchainRegistry: ToolchainRegistry.forTesting
304312
)
305313
defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks.
306314
let del = await BSMDelegate(bsm)
@@ -341,7 +349,8 @@ final class BuildSystemManagerTests: XCTestCase {
341349
let bsm = await BuildSystemManager(
342350
buildSystem: bs,
343351
fallbackBuildSystem: nil,
344-
mainFilesProvider: mainFiles
352+
mainFilesProvider: mainFiles,
353+
toolchainRegistry: ToolchainRegistry.forTesting
345354
)
346355
defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks.
347356
let del = await BSMDelegate(bsm)
@@ -383,7 +392,8 @@ final class BuildSystemManagerTests: XCTestCase {
383392
let bsm = await BuildSystemManager(
384393
buildSystem: bs,
385394
fallbackBuildSystem: nil,
386-
mainFilesProvider: mainFiles
395+
mainFilesProvider: mainFiles,
396+
toolchainRegistry: ToolchainRegistry.forTesting
387397
)
388398
defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks.
389399
let del = await BSMDelegate(bsm)

0 commit comments

Comments
 (0)