Skip to content

Commit 60864fe

Browse files
committed
Respect failed work done progress creation
When the client replies with an error to the `CreateWorkDoneProgressRequest`, we shouldn’t be sending updates for it.
1 parent 814f3c5 commit 60864fe

File tree

1 file changed

+30
-10
lines changed

1 file changed

+30
-10
lines changed

Sources/SourceKitLSP/WorkDoneProgressManager.swift

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,19 @@ final class WorkDoneProgressManager {
2222
private let token: ProgressToken
2323
private let queue = AsyncQueue<Serial>()
2424
private let server: SourceKitLSPServer
25+
/// `true` if the client returned without an error from the `CreateWorkDoneProgressRequest`.
26+
///
27+
/// Since all work done progress reports are being sent on `queue`, we never access it in a state where the
28+
/// `CreateWorkDoneProgressRequest` is still in progress.
29+
///
30+
/// Must be a reference because `deinit` captures it and wants to observe changes to it from `init` eg. in the
31+
/// following:
32+
/// - `init` is called
33+
/// - `deinit` is called
34+
/// - The task from `init` gets executed
35+
/// - The task from `deinit` gets executed
36+
/// - This should have `workDoneProgressCreated == true` so that it can send the work progress end.
37+
private let workDoneProgressCreated: ThreadSafeBox<Bool> & AnyObject = ThreadSafeBox<Bool>(initialValue: false)
2538

2639
convenience init?(server: SourceKitLSPServer, title: String, message: String? = nil, percentage: Int? = nil) async {
2740
guard let capabilityRegistry = await server.capabilityRegistry else {
@@ -42,25 +55,29 @@ final class WorkDoneProgressManager {
4255
}
4356
self.token = .string("WorkDoneProgress-\(UUID())")
4457
self.server = server
45-
queue.async { [server, token] in
58+
queue.async { [server, token, workDoneProgressCreated] in
4659
await server.waitUntilInitialized()
47-
await withCheckedContinuation { (continuation: CheckedContinuation<Void, Never>) in
48-
_ = server.client.send(CreateWorkDoneProgressRequest(token: token)) { result in
49-
continuation.resume()
50-
}
60+
do {
61+
_ = try await server.client.send(CreateWorkDoneProgressRequest(token: token))
62+
} catch {
63+
return
5164
}
52-
await server.sendNotificationToClient(
65+
server.sendNotificationToClient(
5366
WorkDoneProgress(
5467
token: token,
5568
value: .begin(WorkDoneProgressBegin(title: title, message: message, percentage: percentage))
5669
)
5770
)
71+
workDoneProgressCreated.value = true
5872
}
5973
}
6074

6175
func update(message: String? = nil, percentage: Int? = nil) {
62-
queue.async { [server, token] in
63-
await server.sendNotificationToClient(
76+
queue.async { [server, token, workDoneProgressCreated] in
77+
guard workDoneProgressCreated.value else {
78+
return
79+
}
80+
server.sendNotificationToClient(
6481
WorkDoneProgress(
6582
token: token,
6683
value: .report(WorkDoneProgressReport(cancellable: false, message: message, percentage: percentage))
@@ -70,8 +87,11 @@ final class WorkDoneProgressManager {
7087
}
7188

7289
deinit {
73-
queue.async { [server, token] in
74-
await server.sendNotificationToClient(WorkDoneProgress(token: token, value: .end(WorkDoneProgressEnd())))
90+
queue.async { [server, token, workDoneProgressCreated] in
91+
guard workDoneProgressCreated.value else {
92+
return
93+
}
94+
server.sendNotificationToClient(WorkDoneProgress(token: token, value: .end(WorkDoneProgressEnd())))
7595
}
7696
}
7797
}

0 commit comments

Comments
 (0)