@@ -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