@@ -53,8 +53,10 @@ noProgressReporting = return $ ProgressReporting
53
53
54
54
-- | A 'ProgressReporting' that sends the WorkDone Begin and End notifications
55
55
-- synchronously. Progress notifications are sent from a sampling thread.
56
+ --
57
+ -- This 'ProgressReporting' is currently used only in tests.
56
58
directProgressReporting
57
- :: Double -- ^ sampling rate
59
+ :: Seconds -- ^ sampling rate
58
60
-> Maybe (LSP. LanguageContextEnv config )
59
61
-> ProgressReportingStyle
60
62
-> IO ProgressReporting
@@ -64,8 +66,11 @@ directProgressReporting sample env style = do
64
66
65
67
let progressUpdate KickStarted = do
66
68
u <- newProgressToken
67
- writeIORef st (Just u)
68
- mRunLspT env $ start u
69
+ mRunLspT env $ do
70
+ ready <- create u
71
+ for_ ready $ \ _ -> do
72
+ start u
73
+ liftIO $ writeIORef st (Just u)
69
74
progressUpdate KickCompleted = do
70
75
mbToken <- atomicModifyIORef st (Nothing ,)
71
76
for_ mbToken $ \ u ->
@@ -78,17 +83,17 @@ directProgressReporting sample env style = do
78
83
f file shift = atomicModifyIORef'_ inProgressVar $
79
84
HMap. insertWith (\ _ x -> shift x) file (shift 0 )
80
85
81
- progressLoop :: Double -> LSP. LspM a ()
86
+ progressLoop :: Seconds -> LSP. LspM a ()
82
87
progressLoop prev = do
83
88
mbToken <- liftIO $ readIORef st
84
- case mbToken of
89
+ next <- case mbToken of
85
90
Nothing ->
86
- liftIO (sleep sample) >> progressLoop 0
91
+ pure 0
87
92
Just t -> do
88
93
current <- liftIO $ readIORef inProgressVar
89
- prev <- progress style prev current t
90
- liftIO $ sleep sample
91
- progressLoop prev
94
+ progress style prev current t
95
+ liftIO $ sleep sample
96
+ progressLoop next
92
97
93
98
progressThread <- async $ mRunLspT env $ progressLoop 0
94
99
let progressStop = cancel progressThread
@@ -100,7 +105,7 @@ directProgressReporting sample env style = do
100
105
-- before the end of the grace period).
101
106
-- Avoid using in tests where progress notifications are used to assert invariants.
102
107
delayedProgressReporting
103
- :: Double -- ^ sampling rate, also used as grace period before Begin
108
+ :: Seconds -- ^ sampling rate, also used as grace period before Begin
104
109
-> Maybe (LSP. LanguageContextEnv c )
105
110
-> ProgressReportingStyle
106
111
-> IO ProgressReporting
@@ -121,6 +126,9 @@ delayedProgressReporting sample lspEnv style = do
121
126
-- And two transitions, modelled by 'ProgressEvent':
122
127
-- 1. KickCompleted - transitions from Reporting into Idle
123
128
-- 2. KickStarted - transitions from Idle into Reporting
129
+ -- When transitioning from Idle to Reporting a new async is spawned that
130
+ -- sends progress updates in a loop. The async is cancelled when transitioning
131
+ -- from Reporting to Idle.
124
132
progressThread mostRecentProgressEvent inProgress = progressLoopIdle
125
133
where
126
134
progressLoopIdle = do
@@ -147,10 +155,10 @@ delayedProgressReporting sample lspEnv style = do
147
155
lspShakeProgress style inProgress = do
148
156
u <- liftIO newProgressToken
149
157
150
- void $ LSP. sendRequest LSP. SWindowWorkDoneProgressCreate
151
- LSP. WorkDoneProgressCreateParams { _token = u } $ const (pure () )
158
+ ready <- create u
152
159
153
- bracket_ (start u) (stop u) (loop u 0 )
160
+ for_ ready $ \ _ ->
161
+ bracket_ (start u) (stop u) (loop u 0 )
154
162
where
155
163
loop id prev = do
156
164
liftIO $ sleep sample
@@ -167,6 +175,16 @@ delayedProgressReporting sample lspEnv style = do
167
175
newProgressToken :: IO ProgressToken
168
176
newProgressToken = ProgressTextToken . T. pack . show . hashUnique <$> liftIO newUnique
169
177
178
+ create
179
+ :: LSP. MonadLsp config f
180
+ => ProgressToken
181
+ -> f (Either ResponseError Empty )
182
+ create u = do
183
+ b <- liftIO newBarrier
184
+ _ <- LSP. sendRequest LSP. SWindowWorkDoneProgressCreate
185
+ LSP. WorkDoneProgressCreateParams { _token = u }
186
+ (liftIO . signalBarrier b)
187
+ liftIO $ waitBarrier b
170
188
171
189
start :: LSP. MonadLsp config f => ProgressToken -> f ()
172
190
start id = LSP. sendNotification LSP. SProgress $
@@ -189,7 +207,7 @@ stop id = LSP.sendNotification LSP.SProgress
189
207
}
190
208
191
209
progress :: (LSP. MonadLsp config f ) =>
192
- ProgressReportingStyle -> Double -> HashMap NormalizedFilePath Int -> ProgressToken -> f Double
210
+ ProgressReportingStyle -> Seconds -> HashMap NormalizedFilePath Int -> ProgressToken -> f Seconds
193
211
progress style prev current id = do
194
212
let done = length $ filter (== 0 ) $ HMap. elems current
195
213
let todo = HMap. size current
0 commit comments