@@ -43,10 +43,7 @@ func executable(_ name: String) -> String {
43
43
///
44
44
/// Provides build settings from a build server launched based on a
45
45
/// `buildServer.json` configuration file provided in the repo root.
46
- public final class BuildServerBuildSystem : MessageHandler {
47
- /// The handler's request queue. `delegate` will always be called on this queue.
48
- public let queue : DispatchQueue = DispatchQueue ( label: " language-server-queue " , qos: . userInitiated)
49
-
46
+ public actor BuildServerBuildSystem : MessageHandler {
50
47
let projectRoot : AbsolutePath
51
48
let buildFolder : AbsolutePath ?
52
49
let serverConfig : BuildServerConfig
@@ -65,10 +62,15 @@ public final class BuildServerBuildSystem: MessageHandler {
65
62
/// Delegate to handle any build system events.
66
63
public weak var delegate : BuildSystemDelegate ?
67
64
65
+ /// - Note: Needed to set the delegate from a different actor isolation context
66
+ public func setDelegate( _ delegate: BuildSystemDelegate ? ) async {
67
+ self . delegate = delegate
68
+ }
69
+
68
70
/// The build settings that have been received from the build server.
69
71
private var buildSettings : [ DocumentURI : FileBuildSettings ] = [ : ]
70
72
71
- public init ( projectRoot: AbsolutePath , buildFolder: AbsolutePath ? , fileSystem: FileSystem = localFileSystem) throws {
73
+ public init ( projectRoot: AbsolutePath , buildFolder: AbsolutePath ? , fileSystem: FileSystem = localFileSystem) async throws {
72
74
let configPath = projectRoot. appending ( component: " buildServer.json " )
73
75
let config = try loadBuildServerConfig ( path: configPath, fileSystem: fileSystem)
74
76
#if os(Windows)
@@ -90,12 +92,11 @@ public final class BuildServerBuildSystem: MessageHandler {
90
92
/// Creates a build system using the Build Server Protocol config.
91
93
///
92
94
/// - Returns: nil if `projectRoot` has no config or there is an error parsing it.
93
- public convenience init ? ( projectRoot: AbsolutePath ? , buildSetup: BuildSetup )
94
- {
95
+ public init ? ( projectRoot: AbsolutePath ? , buildSetup: BuildSetup ) async {
95
96
if projectRoot == nil { return nil }
96
97
97
98
do {
98
- try self . init ( projectRoot: projectRoot!, buildFolder: buildSetup. path)
99
+ try await self . init ( projectRoot: projectRoot!, buildFolder: buildSetup. path)
99
100
} catch _ as FileSystemError {
100
101
// config file was missing, no build server for this workspace
101
102
return nil
@@ -166,13 +167,11 @@ public final class BuildServerBuildSystem: MessageHandler {
166
167
/// the build server has sent us a notification.
167
168
///
168
169
/// We need to notify the delegate about any updated build settings.
169
- public func handle( _ params: some NotificationType , from clientID: ObjectIdentifier ) {
170
- queue. async {
171
- if let params = params as? BuildTargetsChangedNotification {
172
- self . handleBuildTargetsChanged ( Notification ( params, clientID: clientID) )
173
- } else if let params = params as? FileOptionsChangedNotification {
174
- self . handleFileOptionsChanged ( Notification ( params, clientID: clientID) )
175
- }
170
+ public func handle( _ params: some NotificationType , from clientID: ObjectIdentifier ) async {
171
+ if let params = params as? BuildTargetsChangedNotification {
172
+ await self . handleBuildTargetsChanged ( Notification ( params, clientID: clientID) )
173
+ } else if let params = params as? FileOptionsChangedNotification {
174
+ await self . handleFileOptionsChanged ( Notification ( params, clientID: clientID) )
176
175
}
177
176
}
178
177
@@ -185,30 +184,28 @@ public final class BuildServerBuildSystem: MessageHandler {
185
184
from clientID: ObjectIdentifier ,
186
185
reply: @escaping ( LSPResult < R . Response > ) -> Void
187
186
) {
188
- queue. async {
189
- reply ( . failure( ResponseError . methodNotFound ( R . method) ) )
190
- }
187
+ reply ( . failure( ResponseError . methodNotFound ( R . method) ) )
191
188
}
192
189
193
- func handleBuildTargetsChanged( _ notification: LanguageServerProtocol . Notification < BuildTargetsChangedNotification > ) {
194
- self . delegate? . buildTargetsChanged ( notification. params. changes)
190
+ func handleBuildTargetsChanged( _ notification: LanguageServerProtocol . Notification < BuildTargetsChangedNotification > ) async {
191
+ await self . delegate? . buildTargetsChanged ( notification. params. changes)
195
192
}
196
193
197
- func handleFileOptionsChanged( _ notification: LanguageServerProtocol . Notification < FileOptionsChangedNotification > ) {
194
+ func handleFileOptionsChanged( _ notification: LanguageServerProtocol . Notification < FileOptionsChangedNotification > ) async {
198
195
let result = notification. params. updatedOptions
199
196
let settings = FileBuildSettings (
200
197
compilerArguments: result. options, workingDirectory: result. workingDirectory)
201
- self . buildSettingsChanged ( for: notification. params. uri, settings: settings)
198
+ await self . buildSettingsChanged ( for: notification. params. uri, settings: settings)
202
199
}
203
200
204
201
/// Record the new build settings for the given document and inform the delegate
205
202
/// about the changed build settings.
206
- private func buildSettingsChanged( for document: DocumentURI , settings: FileBuildSettings ? ) {
203
+ private func buildSettingsChanged( for document: DocumentURI , settings: FileBuildSettings ? ) async {
207
204
buildSettings [ document] = settings
208
205
if let settings {
209
- self . delegate? . fileBuildSettingsChanged ( [ document: . modified( settings) ] )
206
+ await self . delegate? . fileBuildSettingsChanged ( [ document: . modified( settings) ] )
210
207
} else {
211
- self . delegate? . fileBuildSettingsChanged ( [ document: . removedOrUnavailable] )
208
+ await self . delegate? . fileBuildSettingsChanged ( [ document: . removedOrUnavailable] )
212
209
}
213
210
}
214
211
}
@@ -234,12 +231,14 @@ extension BuildServerBuildSystem: BuildSystem {
234
231
public func registerForChangeNotifications( for uri: DocumentURI , language: Language ) {
235
232
let request = RegisterForChanges ( uri: uri, action: . register)
236
233
_ = self . buildServer? . send ( request, queue: requestQueue, reply: { result in
237
- if let error = result. failure {
238
- log ( " error registering \( uri) : \( error) " , level: . error)
239
-
240
- // BuildServer registration failed, so tell our delegate that no build
241
- // settings are available.
242
- self . buildSettingsChanged ( for: uri, settings: nil )
234
+ Task {
235
+ if let error = result. failure {
236
+ log ( " error registering \( uri) : \( error) " , level: . error)
237
+
238
+ // BuildServer registration failed, so tell our delegate that no build
239
+ // settings are available.
240
+ await self . buildSettingsChanged ( for: uri, settings: nil )
241
+ }
243
242
}
244
243
} )
245
244
}
0 commit comments