@@ -53,8 +53,10 @@ noProgressReporting = return $ ProgressReporting
5353
5454-- | A 'ProgressReporting' that sends the WorkDone Begin and End notifications
5555-- synchronously. Progress notifications are sent from a sampling thread.
56+ --
57+ -- This 'ProgressReporting' is currently used only in tests.
5658directProgressReporting
57- :: Double -- ^ sampling rate
59+ :: Seconds -- ^ sampling rate
5860 -> Maybe (LSP. LanguageContextEnv config )
5961 -> ProgressReportingStyle
6062 -> IO ProgressReporting
@@ -64,8 +66,11 @@ directProgressReporting sample env style = do
6466
6567 let progressUpdate KickStarted = do
6668 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)
6974 progressUpdate KickCompleted = do
7075 mbToken <- atomicModifyIORef st (Nothing ,)
7176 for_ mbToken $ \ u ->
@@ -78,17 +83,17 @@ directProgressReporting sample env style = do
7883 f file shift = atomicModifyIORef'_ inProgressVar $
7984 HMap. insertWith (\ _ x -> shift x) file (shift 0 )
8085
81- progressLoop :: Double -> LSP. LspM a ()
86+ progressLoop :: Seconds -> LSP. LspM a ()
8287 progressLoop prev = do
8388 mbToken <- liftIO $ readIORef st
84- case mbToken of
89+ next <- case mbToken of
8590 Nothing ->
86- liftIO (sleep sample) >> progressLoop 0
91+ pure 0
8792 Just t -> do
8893 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
9297
9398 progressThread <- async $ mRunLspT env $ progressLoop 0
9499 let progressStop = cancel progressThread
@@ -100,7 +105,7 @@ directProgressReporting sample env style = do
100105-- before the end of the grace period).
101106-- Avoid using in tests where progress notifications are used to assert invariants.
102107delayedProgressReporting
103- :: Double -- ^ sampling rate, also used as grace period before Begin
108+ :: Seconds -- ^ sampling rate, also used as grace period before Begin
104109 -> Maybe (LSP. LanguageContextEnv c )
105110 -> ProgressReportingStyle
106111 -> IO ProgressReporting
@@ -121,6 +126,9 @@ delayedProgressReporting sample lspEnv style = do
121126 -- And two transitions, modelled by 'ProgressEvent':
122127 -- 1. KickCompleted - transitions from Reporting into Idle
123128 -- 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.
124132 progressThread mostRecentProgressEvent inProgress = progressLoopIdle
125133 where
126134 progressLoopIdle = do
@@ -147,10 +155,10 @@ delayedProgressReporting sample lspEnv style = do
147155 lspShakeProgress style inProgress = do
148156 u <- liftIO newProgressToken
149157
150- void $ LSP. sendRequest LSP. SWindowWorkDoneProgressCreate
151- LSP. WorkDoneProgressCreateParams { _token = u } $ const (pure () )
158+ ready <- create u
152159
153- bracket_ (start u) (stop u) (loop u 0 )
160+ for_ ready $ \ _ ->
161+ bracket_ (start u) (stop u) (loop u 0 )
154162 where
155163 loop id prev = do
156164 liftIO $ sleep sample
@@ -167,6 +175,16 @@ delayedProgressReporting sample lspEnv style = do
167175newProgressToken :: IO ProgressToken
168176newProgressToken = ProgressTextToken . T. pack . show . hashUnique <$> liftIO newUnique
169177
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
170188
171189start :: LSP. MonadLsp config f => ProgressToken -> f ()
172190start id = LSP. sendNotification LSP. SProgress $
@@ -189,7 +207,7 @@ stop id = LSP.sendNotification LSP.SProgress
189207 }
190208
191209progress :: (LSP. MonadLsp config f ) =>
192- ProgressReportingStyle -> Double -> HashMap NormalizedFilePath Int -> ProgressToken -> f Double
210+ ProgressReportingStyle -> Seconds -> HashMap NormalizedFilePath Int -> ProgressToken -> f Seconds
193211progress style prev current id = do
194212 let done = length $ filter (== 0 ) $ HMap. elems current
195213 let todo = HMap. size current
0 commit comments