Call into the BuildSystemManager from SwiftLanguageServer to get build settings

Instead of storing build settings inside the language servers based on update notifications from the build system, always call into the `BuildSystemManager` to get the build settings.

Overall, I think this is a much clearer separation of concerns and will allow us to remove `SourceKitServer.documentToPendingQueue` in a follow-up commit as `SwiftLanguageServer` can always directly call into `BuildSystemManager` to get build settings and we don’t need to wait for the initial notification to receive the first build settings.

This requies `BuildServerBuildSystem` to keep track of the build settings it has received from the BSP server.

`ClangLanguageServer` still caches build settings locally. `ClangLanguageServer` will change to the same pull-based model in a follow-up commit.
This commit is contained in:
Alex Hoppen
2023-09-21 19:51:38 -07:00
parent ded0cf0168
commit f1548bd757
21 changed files with 221 additions and 137 deletions

View File

@@ -65,6 +65,9 @@ public final class BuildServerBuildSystem: MessageHandler {
/// Delegate to handle any build system events.
public weak var delegate: BuildSystemDelegate?
/// The build settings that have been received from the build server.
private var buildSettings: [DocumentURI: FileBuildSettings] = [:]
public init(projectRoot: AbsolutePath, buildFolder: AbsolutePath?, fileSystem: FileSystem = localFileSystem) throws {
let configPath = projectRoot.appending(component: "buildServer.json")
let config = try loadBuildServerConfig(path: configPath, fileSystem: fileSystem)
@@ -195,7 +198,18 @@ public final class BuildServerBuildSystem: MessageHandler {
let result = notification.params.updatedOptions
let settings = FileBuildSettings(
compilerArguments: result.options, workingDirectory: result.workingDirectory)
self.delegate?.fileBuildSettingsChanged([notification.params.uri: .modified(settings)])
self.buildSettingsChanged(for: notification.params.uri, settings: settings)
}
/// Record the new build settings for the given document and inform the delegate
/// about the changed build settings.
private func buildSettingsChanged(for document: DocumentURI, settings: FileBuildSettings?) {
buildSettings[document] = settings
if let settings {
self.delegate?.fileBuildSettingsChanged([document: .modified(settings)])
} else {
self.delegate?.fileBuildSettingsChanged([document: .removedOrUnavailable])
}
}
}
@@ -208,19 +222,14 @@ private func readReponseDataKey(data: LSPAny?, key: String) -> String? {
return nil
}
extension BuildServerBuildSystem {
/// Exposed for *testing*.
public func _settings(for uri: DocumentURI) -> FileBuildSettings? {
if let response = try? self.buildServer?.sendSync(SourceKitOptions(uri: uri)) {
return FileBuildSettings(
compilerArguments: response.options,
workingDirectory: response.workingDirectory)
}
return nil
}
}
extension BuildServerBuildSystem: BuildSystem {
/// The build settings for the given file.
///
/// Returns `nil` if no build settings have been received from the build
/// server yet or if no build settings are available for this file.
public func buildSettings(for document: DocumentURI, language: Language) async throws -> FileBuildSettings? {
return buildSettings[document]
}
public func registerForChangeNotifications(for uri: DocumentURI, language: Language) {
let request = RegisterForChanges(uri: uri, action: .register)
@@ -230,7 +239,7 @@ extension BuildServerBuildSystem: BuildSystem {
// BuildServer registration failed, so tell our delegate that no build
// settings are available.
self.delegate?.fileBuildSettingsChanged([uri: .removedOrUnavailable])
self.buildSettingsChanged(for: uri, settings: nil)
}
})
}