Skip to content

Commit 9d94fe3

Browse files
committed
Migrate defaultLanguage(for:) to BSP
1 parent dd50183 commit 9d94fe3

9 files changed

+69
-35
lines changed

Sources/BuildServerProtocol/BuildTargetSourcesRequest.swift

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,5 +97,30 @@ public struct SourceItemDataKind: RawRepresentable, Codable, Hashable, Sendable
9797
}
9898

9999
/// `data` field must contain a JvmSourceItemData object.
100-
public static let jvm = "jvm"
100+
public static let jvm = SourceItemDataKind(rawValue: "jvm")
101+
102+
/// `data` field must contain a `SourceKitSourceItemData` object.
103+
public static let sourceKit = SourceItemDataKind(rawValue: "sourceKit")
104+
}
105+
106+
public struct SourceKitSourceItemData: LSPAnyCodable, Codable {
107+
public var language: Language?
108+
109+
public init(language: Language? = nil) {
110+
self.language = language
111+
}
112+
113+
public init?(fromLSPDictionary dictionary: [String: LanguageServerProtocol.LSPAny]) {
114+
if case .string(let language) = dictionary[CodingKeys.language.stringValue] {
115+
self.language = Language(rawValue: language)
116+
}
117+
}
118+
119+
public func encodeToLSPAny() -> LanguageServerProtocol.LSPAny {
120+
var result: [String: LSPAny] = [:]
121+
if let language {
122+
result[CodingKeys.language.stringValue] = .string(language.rawValue)
123+
}
124+
return .dictionary(result)
125+
}
101126
}

Sources/BuildSystemIntegration/BuildServerBuildSystem.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,6 @@ extension BuildServerBuildSystem: BuiltInBuildSystem {
338338
)
339339
}
340340

341-
package func defaultLanguage(for document: DocumentURI) async -> Language? {
342-
return nil
343-
}
344-
345341
package func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain? {
346342
return nil
347343
}

Sources/BuildSystemIntegration/BuildSystemManager.swift

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,38 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
191191
self.mainFilesProvider = mainFilesProvider
192192
}
193193

194+
/// Ask the build system if it explicitly specifies a language for this document. Return `nil` if it does not.
195+
private func languageInferredFromBuildSystem(
196+
for document: DocumentURI,
197+
in target: BuildTargetIdentifier
198+
) async throws -> Language? {
199+
let sourcesItems = try await self.sourceFiles(in: [target])
200+
let sourceFiles = sourcesItems.flatMap(\.sources)
201+
var result: Language? = nil
202+
for sourceFile in sourceFiles {
203+
guard sourceFile.uri == document, sourceFile.dataKind == .sourceKit, case .dictionary(let data) = sourceFile.data,
204+
let sourceKitData = SourceKitSourceItemData(fromLSPDictionary: data),
205+
let language = sourceKitData.language
206+
else {
207+
continue
208+
}
209+
if result != nil && result != language {
210+
logger.error("Conflicting languages for \(document.forLogging) in \(target)")
211+
return nil
212+
}
213+
result = language
214+
}
215+
return result
216+
}
217+
194218
/// Returns the language that a document should be interpreted in for background tasks where the editor doesn't
195219
/// specify the document's language.
196-
package func defaultLanguage(for document: DocumentURI) async -> Language? {
197-
if let defaultLanguage = await buildSystem?.underlyingBuildSystem.defaultLanguage(for: document) {
198-
return defaultLanguage
220+
package func defaultLanguage(for document: DocumentURI, in target: BuildTargetIdentifier) async -> Language? {
221+
let language = await orLog("Getting source files to determine default language") {
222+
try await languageInferredFromBuildSystem(for: document, in: target)
223+
}
224+
if let language {
225+
return language
199226
}
200227
switch document.fileURL?.pathExtension {
201228
case "c": return .c
@@ -237,7 +264,7 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
237264

238265
/// Returns the target's module name as parsed from the `BuildTargetIdentifier`'s compiler arguments.
239266
package func moduleName(for document: DocumentURI, in target: BuildTargetIdentifier) async -> String? {
240-
guard let language = await self.defaultLanguage(for: document),
267+
guard let language = await self.defaultLanguage(for: document, in: target),
241268
let buildSettings = await buildSettings(for: document, in: target, language: language)
242269
else {
243270
return nil
@@ -406,6 +433,8 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
406433
return []
407434
}
408435

436+
// FIXME: (BSP migration) If we have a cached request for a superset of the targets, serve the result from that
437+
// cache entry.
409438
let request = BuildTargetSourcesRequest.init(targets: targets)
410439
let response = try await cachedTargetSources.get(request) { request in
411440
try await buildSystem.send(request)
@@ -416,6 +445,7 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
416445
package func sourceFiles() async throws -> [SourceFileInfo] {
417446
// FIXME: (BSP Migration): Consider removing this method and letting callers get all targets first and then
418447
// retrieving the source files for those targets.
448+
// FIXME: (BSP Migration) Handle source files that are in multiple targets
419449
let targets = try await self.buildTargets()
420450
let targetsById = Dictionary(elements: targets, keyedBy: \.id)
421451
let sourceFiles = try await self.sourceFiles(in: targets.map(\.id)).flatMap { sourcesItem in

Sources/BuildSystemIntegration/BuiltInBuildSystem.swift

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,13 +139,6 @@ package protocol BuiltInBuildSystem: AnyObject, Sendable {
139139
/// Returning `nil` indicates that all targets should be considered depending on the given target.
140140
func targets(dependingOn targets: [BuildTargetIdentifier]) async -> [BuildTargetIdentifier]?
141141

142-
/// If the build system has knowledge about the language that this document should be compiled in, return it.
143-
///
144-
/// This is used to determine the language in which a source file should be background indexed.
145-
///
146-
/// If `nil` is returned, the language based on the file's extension.
147-
func defaultLanguage(for document: DocumentURI) async -> Language?
148-
149142
/// The toolchain that should be used to open the given document.
150143
///
151144
/// 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
@@ -160,10 +160,6 @@ extension CompilationDatabaseBuildSystem: BuiltInBuildSystem {
160160
)
161161
}
162162

163-
package func defaultLanguage(for document: DocumentURI) async -> Language? {
164-
return nil
165-
}
166-
167163
package func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain? {
168164
return nil
169165
}

Sources/BuildSystemIntegration/SwiftPMBuildSystem.swift

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,8 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
563563

564564
package func buildTargetSources(request: BuildTargetSourcesRequest) async throws -> BuildTargetSourcesResponse {
565565
var result: [SourcesItem] = []
566+
// TODO: Query The SwiftPM build system for the document's language and add it to SourceItem.data
567+
// (https://github.com/swiftlang/sourcekit-lsp/issues/1267)
566568
for target in request.targets {
567569
guard let swiftPMTarget = self.targets[target] else {
568570
continue
@@ -617,11 +619,6 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
617619
)
618620
}
619621

620-
package func defaultLanguage(for document: DocumentURI) -> Language? {
621-
// TODO: Query The SwiftPM build system for the document's language. (https://github.com/swiftlang/sourcekit-lsp/issues/1267)
622-
return nil
623-
}
624-
625622
package func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain? {
626623
return toolchain
627624
}

Sources/BuildSystemIntegration/TestBuildSystem.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,6 @@ package actor TestBuildSystem: BuiltInBuildSystem {
7676
return buildSettingsByFile[request.textDocument.uri]
7777
}
7878

79-
package func defaultLanguage(for document: DocumentURI) async -> Language? {
80-
return nil
81-
}
82-
8379
package func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain? {
8480
return nil
8581
}

Sources/SemanticIndex/SemanticIndexManager.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -590,11 +590,6 @@ package final actor SemanticIndexManager {
590590
if await indexStoreUpToDateTracker.isUpToDate($0.sourceFile) {
591591
return false
592592
}
593-
guard let language = await buildSystemManager.defaultLanguage(for: $0.mainFile),
594-
UpdateIndexStoreTaskDescription.canIndex(language: language)
595-
else {
596-
return false
597-
}
598593
return true
599594
}
600595
// sort files to get deterministic indexing order
@@ -611,6 +606,12 @@ package final actor SemanticIndexManager {
611606
)
612607
continue
613608
}
609+
guard let language = await buildSystemManager.defaultLanguage(for: fileToIndex.mainFile, in: target),
610+
UpdateIndexStoreTaskDescription.canIndex(language: language)
611+
else {
612+
continue
613+
}
614+
614615
filesByTarget[target, default: []].append(fileToIndex)
615616
}
616617

Sources/SemanticIndex/UpdateIndexStoreTaskDescription.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ package struct UpdateIndexStoreTaskDescription: IndexTaskDescription {
235235
if file.mainFile != file.sourceFile {
236236
logger.log("Updating index store of \(file.forLogging) using main file \(file.mainFile.forLogging)")
237237
}
238-
guard let language = await buildSystemManager.defaultLanguage(for: file.mainFile) else {
238+
guard let language = await buildSystemManager.defaultLanguage(for: file.mainFile, in: target) else {
239239
logger.error("Not indexing \(file.forLogging) because its language could not be determined")
240240
return
241241
}

0 commit comments

Comments
 (0)