@@ -9,6 +9,8 @@ module Development.IDE.Core.ProgressReporting
99 -- for tests
1010 , recordProgress
1111 , InProgressState (.. )
12+ -- simple counter
13+ , progressCounter
1214 )
1315 where
1416
@@ -33,7 +35,7 @@ import Language.LSP.Server (ProgressAmount (..),
3335 withProgress )
3436import qualified Language.LSP.Server as LSP
3537import qualified StmContainers.Map as STM
36- import UnliftIO (Async , async , cancel )
38+ import UnliftIO (Async , STM , async , cancel )
3739
3840data ProgressEvent
3941 = KickStarted
@@ -103,40 +105,46 @@ progressReporting
103105 :: Maybe (LSP. LanguageContextEnv c )
104106 -> ProgressReportingStyle
105107 -> IO ProgressReporting
108+ progressReporting _ optProgressStyle | optProgressStyle == NoProgress = noProgressReporting
106109progressReporting Nothing _optProgressStyle = noProgressReporting
107- progressReporting (Just lspEnv) optProgressStyle = do
108- inProgressState <- newInProgress
110+ progressReporting (Just lspEnv) _optProgressStyle = do
111+ inProgressState@ InProgressState {todoVar, doneVar} <- newInProgress
109112 progressState <- newVar NotStarted
110113 let progressUpdate event = updateStateVar $ Event event
111114 progressStop = updateStateVar StopProgress
112- updateStateVar = modifyVar_ progressState . updateState (lspShakeProgressNew inProgressState )
115+ updateStateVar = modifyVar_ progressState . updateState (progressCounter lspEnv (readTVar todoVar) (readTVar doneVar) )
113116 inProgress = updateStateForFile inProgressState
114117 return ProgressReporting {.. }
115118 where
116- lspShakeProgressNew :: InProgressState -> IO ()
117- lspShakeProgressNew InProgressState {.. } =
118- LSP. runLspT lspEnv $ withProgress " Processing" Nothing NotCancellable $ \ update -> loop update 0
119- where
120- loop _ _ | optProgressStyle == NoProgress = forever $ liftIO $ threadDelay maxBound
121- loop update prevPct = do
122- (todo, done, nextPct) <- liftIO $ atomically $ do
123- todo <- readTVar todoVar
124- done <- readTVar doneVar
125- let nextFrac :: Double
126- nextFrac = if todo == 0 then 0 else fromIntegral done / fromIntegral todo
127- nextPct :: UInt
128- nextPct = floor $ 100 * nextFrac
129- when (nextPct == prevPct) retry
130- pure (todo, done, nextPct)
119+ updateStateForFile inProgress file = actionBracket (f succ ) (const $ f pred ) . const
120+ -- This functions are deliberately eta-expanded to avoid space leaks.
121+ -- Do not remove the eta-expansion without profiling a session with at
122+ -- least 1000 modifications.
123+ where
124+ f shift = recordProgress inProgress file shift
131125
132- _ <- update (ProgressAmount (Just nextPct) (Just $ T. pack $ show done <> " /" <> show todo))
133- loop update nextPct
134- updateStateForFile inProgress file = actionBracket (f succ ) (const $ f pred ) . const
135- -- This functions are deliberately eta-expanded to avoid space leaks.
136- -- Do not remove the eta-expansion without profiling a session with at
137- -- least 1000 modifications.
138- where
139- f shift = recordProgress inProgress file shift
126+ -- Kill this to complete the progress session
127+ progressCounter
128+ :: LSP. LanguageContextEnv c
129+ -> STM Int
130+ -> STM Int
131+ -> IO ()
132+ progressCounter lspEnv getTodo getDone =
133+ LSP. runLspT lspEnv $ withProgress " Processing" Nothing NotCancellable $ \ update -> loop update 0
134+ where
135+ loop update prevPct = do
136+ (todo, done, nextPct) <- liftIO $ atomically $ do
137+ todo <- getTodo
138+ done <- getDone
139+ let nextFrac :: Double
140+ nextFrac = if todo == 0 then 0 else fromIntegral done / fromIntegral todo
141+ nextPct :: UInt
142+ nextPct = floor $ 100 * nextFrac
143+ when (nextPct == prevPct) retry
144+ pure (todo, done, nextPct)
145+
146+ _ <- update (ProgressAmount (Just nextPct) (Just $ T. pack $ show done <> " /" <> show todo))
147+ loop update nextPct
140148
141149mRunLspT :: Applicative m => Maybe (LSP. LanguageContextEnv c ) -> LSP. LspT c m () -> m ()
142150mRunLspT (Just lspEnv) f = LSP. runLspT lspEnv f
0 commit comments