Skip to content

Commit 4189f45

Browse files
committed
factor out progress reporting
1 parent 1976ea2 commit 4189f45

File tree

1 file changed

+46
-19
lines changed

1 file changed

+46
-19
lines changed

ghcide/src/Development/IDE/Core/Shake.hs

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
{-# LANGUAGE ConstraintKinds #-}
55
{-# LANGUAGE DerivingStrategies #-}
6+
{-# LANGUAGE DuplicateRecordFields #-}
67
{-# LANGUAGE ExistentialQuantification #-}
78
{-# LANGUAGE PolyKinds #-}
89
{-# LANGUAGE RankNTypes #-}
@@ -183,8 +184,8 @@ data ShakeExtras = ShakeExtras
183184
-- positions in a version of that document to positions in the latest version
184185
-- First mapping is delta from previous version and second one is an
185186
-- accumlation of all previous mappings.
186-
,inProgress :: Var (HMap.HashMap NormalizedFilePath Int)
187-
-- ^ How many rules are running for each file
187+
,inProgress :: forall a . NormalizedFilePath -> Action a -> Action a
188+
-- ^ Report progress for a rule
188189
,progressUpdate :: ProgressEvent -> IO ()
189190
,ideTesting :: IdeTesting
190191
-- ^ Whether to enable additional lsp messages used by the test suite for checking invariants
@@ -473,9 +474,8 @@ shakeOpen :: Maybe (LSP.LanguageContextEnv Config)
473474
-> Rules ()
474475
-> IO IdeState
475476
shakeOpen lspEnv defaultConfig logger debouncer
476-
shakeProfileDir (IdeReportProgress reportProgress) ideTesting@(IdeTesting testing) hiedb indexQueue vfs opts rules = mdo
477+
shakeProfileDir (IdeReportProgress inProgress) ideTesting@(IdeTesting testing) hiedb indexQueue vfs opts rules = mdo
477478

478-
inProgress <- newVar HMap.empty
479479
us <- mkSplitUniqSupply 'r'
480480
ideNc <- newIORef (initNameCache us knownKeyNames)
481481
(shakeExtras, stopProgressReporting) <- do
@@ -487,23 +487,23 @@ shakeOpen lspEnv defaultConfig logger debouncer
487487
positionMapping <- newVar HMap.empty
488488
knownTargetsVar <- newVar $ hashed HMap.empty
489489
let restartShakeSession = shakeRestart ideState
490-
mostRecentProgressEvent <- newTVarIO KickCompleted
491490
persistentKeys <- newVar HMap.empty
492-
let progressUpdate = atomically . writeTVar mostRecentProgressEvent
493491
indexPending <- newTVarIO HMap.empty
494492
indexCompleted <- newTVarIO 0
495493
indexProgressToken <- newVar Nothing
496494
let hiedbWriter = HieDbWriter{..}
497-
progressAsync <- async $
498-
when reportProgress $
499-
progressThread optProgressStyle mostRecentProgressEvent inProgress
500495
exportsMap <- newVar mempty
501496

497+
ProgressReporting{..} <-
498+
if inProgress
499+
then delayedProgressReporting lspEnv optProgressStyle
500+
else noProgressReporting
502501
actionQueue <- newQueue
503502

504503
let clientCapabilities = maybe def LSP.resClientCapabilities lspEnv
504+
extras = ShakeExtras{..}
505505

506-
pure (ShakeExtras{..}, cancel progressAsync)
506+
pure (extras, progressStop)
507507
(shakeDbM, shakeClose) <-
508508
shakeOpenDatabase
509509
opts { shakeExtra = newShakeExtra shakeExtras }
@@ -520,6 +520,34 @@ shakeOpen lspEnv defaultConfig logger debouncer
520520
startTelemetry otProfilingEnabled logger $ state shakeExtras
521521

522522
return ideState
523+
524+
data ProgressReporting = ProgressReporting
525+
{ progressUpdate :: ProgressEvent -> IO ()
526+
, inProgress :: forall a. NormalizedFilePath -> Action a -> Action a
527+
, progressStop :: IO ()
528+
}
529+
530+
noProgressReporting :: IO ProgressReporting
531+
noProgressReporting = return $ ProgressReporting
532+
{ progressUpdate = const $ pure ()
533+
, inProgress = const id
534+
, progressStop = pure ()
535+
}
536+
537+
delayedProgressReporting
538+
:: Maybe (LSP.LanguageContextEnv c)
539+
-> ProgressReportingStyle
540+
-> IO ProgressReporting
541+
delayedProgressReporting lspEnv optProgressStyle = do
542+
inProgressVar <- newVar HMap.empty
543+
mostRecentProgressEvent <- newTVarIO KickCompleted
544+
progressAsync <- async $
545+
progressThread optProgressStyle mostRecentProgressEvent inProgressVar
546+
let progressUpdate = atomically . writeTVar mostRecentProgressEvent
547+
progressStop = cancel progressAsync
548+
inProgress :: NormalizedFilePath -> Action a -> Action a
549+
inProgress = withProgressVar inProgressVar
550+
return ProgressReporting{..}
523551
where
524552
-- The progress thread is a state machine with two states:
525553
-- 1. Idle
@@ -550,7 +578,7 @@ shakeOpen lspEnv defaultConfig logger debouncer
550578
lspShakeProgress = do
551579
-- first sleep a bit, so we only show progress messages if it's going to take
552580
-- a "noticable amount of time" (we often expect a thread kill to arrive before the sleep finishes)
553-
liftIO $ unless testing $ sleep 0.1
581+
liftIO $ sleep 0.1
554582
u <- ProgressTextToken . T.pack . show . hashUnique <$> liftIO newUnique
555583

556584
void $ LSP.sendRequest LSP.SWindowWorkDoneProgressCreate
@@ -608,6 +636,12 @@ shakeOpen lspEnv defaultConfig logger debouncer
608636
}
609637
loop id next
610638

639+
withProgressVar var file = actionBracket (f succ) (const $ f pred) . const
640+
-- This functions are deliberately eta-expanded to avoid space leaks.
641+
-- Do not remove the eta-expansion without profiling a session with at
642+
-- least 1000 modifications.
643+
where f shift = void $ modifyVar' var $ HMap.insertWith (\_ x -> shift x) file (shift 0)
644+
611645
-- | Must be called in the 'Initialized' handler and only once
612646
shakeSessionInit :: IdeState -> IO ()
613647
shakeSessionInit IdeState{..} = do
@@ -952,7 +986,7 @@ defineEarlyCutoff'
952986
defineEarlyCutoff' doDiagnostics key file old mode action = do
953987
extras@ShakeExtras{state, inProgress, logger} <- getShakeExtras
954988
options <- getIdeOptions
955-
(if optSkipProgress options key then id else withProgressVar inProgress file) $ do
989+
(if optSkipProgress options key then id else inProgress file) $ do
956990
val <- case old of
957991
Just old | mode == RunDependenciesSame -> do
958992
v <- liftIO $ getValues state key file
@@ -1001,13 +1035,6 @@ defineEarlyCutoff' doDiagnostics key file old mode action = do
10011035
A res
10021036
where
10031037

1004-
withProgressVar :: (Eq a, Hashable a) => Var (HMap.HashMap a Int) -> a -> Action b -> Action b
1005-
withProgressVar var file = actionBracket (f succ) (const $ f pred) . const
1006-
-- This functions are deliberately eta-expanded to avoid space leaks.
1007-
-- Do not remove the eta-expansion without profiling a session with at
1008-
-- least 1000 modifications.
1009-
where f shift = void $ modifyVar' var $ HMap.insertWith (\_ x -> shift x) file (shift 0)
1010-
10111038
isSuccess :: RunResult (A v) -> Bool
10121039
isSuccess (RunResult _ _ (A Failed{})) = False
10131040
isSuccess _ = True

0 commit comments

Comments
 (0)