@@ -196,7 +196,7 @@ main = do
196
196
hPutStrLn stderr $ " with arguments: " <> show args
197
197
hPutStrLn stderr $ " with plugins: " <> show (Map. keys $ ipMap idePlugins')
198
198
hPutStrLn stderr " If you are seeing this in a terminal, you probably should have run ghcide WITHOUT the --lsp option!"
199
- runLanguageServer options (pluginHandler plugins) getInitialConfig getConfigFromNotification $ \ getLspId event vfs caps -> do
199
+ runLanguageServer options (pluginHandler plugins) getInitialConfig getConfigFromNotification $ \ getLspId event vfs caps wProg wIndefProg -> do
200
200
t <- t
201
201
hPutStrLn stderr $ " Started LSP server in " ++ showDuration t
202
202
let options = (defaultIdeOptions $ loadSessionShake dir)
@@ -207,7 +207,7 @@ main = do
207
207
}
208
208
debouncer <- newAsyncDebouncer
209
209
initialise caps (mainRule >> pluginRules plugins)
210
- getLspId event hlsLogger debouncer options vfs
210
+ getLspId event wProg wIndefProg hlsLogger debouncer options vfs
211
211
else do
212
212
-- GHC produces messages with UTF8 in them, so make sure the terminal doesn't error
213
213
hSetEncoding stdout utf8
@@ -230,7 +230,8 @@ main = do
230
230
putStrLn " \n Step 3/4: Initializing the IDE"
231
231
vfs <- makeVFSHandle
232
232
debouncer <- newAsyncDebouncer
233
- ide <- initialise def mainRule (pure $ IdInt 0 ) (showEvent lock) (logger Info ) debouncer (defaultIdeOptions $ loadSessionShake dir) vfs
233
+ let dummyWithProg _ _ f = f (const (pure () ))
234
+ ide <- initialise def mainRule (pure $ IdInt 0 ) (showEvent lock) dummyWithProg (const (const id )) (logger Info ) debouncer (defaultIdeOptions $ loadSessionShake dir) vfs
234
235
235
236
putStrLn " \n Step 4/4: Type checking the files"
236
237
setFilesOfInterest ide $ HashSet. fromList $ map toNormalizedFilePath' files
@@ -304,13 +305,13 @@ loadSessionShake fp = do
304
305
se <- getShakeExtras
305
306
IdeOptions {optTesting = IdeTesting ideTesting} <- getIdeOptions
306
307
res <- liftIO $ loadSession ideTesting se fp
307
- return ( fmap liftIO res)
308
+ return res
308
309
309
310
-- | This is the key function which implements multi-component support. All
310
311
-- components mapping to the same hie.yaml file are mapped to the same
311
312
-- HscEnv which is updated as new components are discovered.
312
- loadSession :: Bool -> ShakeExtras -> FilePath -> IO (FilePath -> IO (IdeResult HscEnvEq ))
313
- loadSession optTesting ShakeExtras {logger, eventer, restartShakeSession , ideNc} dir = do
313
+ loadSession :: Bool -> ShakeExtras -> FilePath -> IO (FilePath -> Action (IdeResult HscEnvEq ))
314
+ loadSession optTesting ShakeExtras {logger, eventer, withIndefiniteProgress , ideNc} dir = do
314
315
-- Mapping from hie.yaml file to HscEnv, one per hie.yaml file
315
316
hscEnvs <- newVar Map. empty :: IO (Var HieMap )
316
317
-- Mapping from a Filepath to HscEnv
@@ -403,7 +404,7 @@ loadSession optTesting ShakeExtras{logger, eventer, restartShakeSession, ideNc}
403
404
-- existing packages
404
405
pure (Map. insert hieYaml (newHscEnv, new_deps) m, (newHscEnv, head new_deps', tail new_deps'))
405
406
406
- let session :: (Maybe FilePath , NormalizedFilePath , ComponentOptions ) -> IO (IdeResult HscEnvEq )
407
+ let session :: (Maybe FilePath , NormalizedFilePath , ComponentOptions ) -> IO ([ NormalizedFilePath ], IdeResult HscEnvEq )
407
408
session (hieYaml, cfp, opts) = do
408
409
(hscEnv, new, old_deps) <- packageSetup (hieYaml, cfp, opts)
409
410
-- Make a map from unit-id to DynFlags, this is used when trying to
@@ -424,16 +425,22 @@ loadSession optTesting ShakeExtras{logger, eventer, restartShakeSession, ideNc}
424
425
pure $ Map. insert hieYaml (HM. fromList (cs ++ cached_targets)) var
425
426
426
427
-- Invalidate all the existing GhcSession build nodes by restarting the Shake session
427
- restartShakeSession [kick]
428
+ -- restartShakeSession [kick]
428
429
429
- return (fst res)
430
+ return (map fst cs, fst res)
430
431
431
- let consultCradle :: Maybe FilePath -> FilePath -> IO (IdeResult HscEnvEq )
432
+ let consultCradle :: Maybe FilePath -> FilePath -> IO ([ NormalizedFilePath ], IdeResult HscEnvEq )
432
433
consultCradle hieYaml cfp = do
433
434
when optTesting $ eventer $ notifyCradleLoaded cfp
434
435
logInfo logger $ T. pack (" Consulting the cradle for " <> show cfp)
436
+
435
437
cradle <- maybe (loadImplicitCradle $ addTrailingPathSeparator dir) loadCradle hieYaml
436
- eopts <- cradleToSessionOpts cradle cfp
438
+ -- Display a user friendly progress message here: They probably don't know what a
439
+ -- cradle is
440
+ let progMsg = " Setting up project " <> T. pack (takeBaseName (cradleRootDir cradle))
441
+ eopts <- withIndefiniteProgress progMsg LSP. NotCancellable $
442
+ cradleToSessionOpts cradle cfp
443
+
437
444
logDebug logger $ T. pack (" Session loading result: " <> show eopts)
438
445
case eopts of
439
446
-- The cradle gave us some options so get to work turning them
@@ -447,10 +454,10 @@ loadSession optTesting ShakeExtras{logger, eventer, restartShakeSession, ideNc}
447
454
let res = (map (renderCradleError ncfp) err, Nothing )
448
455
modifyVar_ fileToFlags $ \ var -> do
449
456
pure $ Map. insertWith HM. union hieYaml (HM. singleton ncfp (res, dep_info)) var
450
- return res
457
+ return ([ncfp], res)
451
458
452
459
-- This caches the mapping from hie.yaml + Mod.hs -> [String]
453
- let sessionOpts :: (Maybe FilePath , FilePath ) -> IO (IdeResult HscEnvEq )
460
+ let sessionOpts :: (Maybe FilePath , FilePath ) -> IO ([ NormalizedFilePath ], IdeResult HscEnvEq )
454
461
sessionOpts (hieYaml, file) = do
455
462
v <- fromMaybe HM. empty . Map. lookup hieYaml <$> readVar fileToFlags
456
463
cfp <- canonicalizePath file
@@ -465,7 +472,7 @@ loadSession optTesting ShakeExtras{logger, eventer, restartShakeSession, ideNc}
465
472
-- Keep the same name cache
466
473
modifyVar_ hscEnvs (return . Map. adjust (\ (h, _) -> (h, [] )) hieYaml )
467
474
consultCradle hieYaml cfp
468
- else return opts
475
+ else return ( [] , opts)
469
476
Nothing -> consultCradle hieYaml cfp
470
477
471
478
dummyAs <- async $ return (error " Uninitialised" )
@@ -474,18 +481,26 @@ loadSession optTesting ShakeExtras{logger, eventer, restartShakeSession, ideNc}
474
481
-- at a time. Therefore the IORef contains the currently running cradle, if we try
475
482
-- to get some more options then we wait for the currently running action to finish
476
483
-- before attempting to do so.
477
- let getOptions :: FilePath -> IO (IdeResult HscEnvEq )
484
+ let getOptions :: FilePath -> IO ([ NormalizedFilePath ], IdeResult HscEnvEq )
478
485
getOptions file = do
479
486
hieYaml <- cradleLoc file
480
- sessionOpts (hieYaml, file) `catch` \ e ->
481
- return ([renderPackageSetupException compileTime file e], Nothing )
487
+ sessionOpts (hieYaml, file) `catch` \ e -> do
488
+ return ([] ,([ renderPackageSetupException compileTime file e], Nothing ) )
482
489
483
490
return $ \ file -> do
484
- join $ mask_ $ modifyVar runningCradle $ \ as -> do
491
+ (cs, opts) <- liftIO $ join $ mask_ $ modifyVar runningCradle $ \ as -> do
485
492
-- If the cradle is not finished, then wait for it to finish.
486
493
void $ wait as
487
494
as <- async $ getOptions file
488
- return (as, wait as)
495
+ return $ (fmap snd as, wait as)
496
+ let cfps = cs
497
+ unless (null cs) $
498
+ delay " InitialLoad" $ void $ do
499
+ cfps' <- liftIO $ filterM (IO. doesFileExist . fromNormalizedFilePath) cfps
500
+ mmt <- uses GetModificationTime cfps'
501
+ let cs_exist = catMaybes (zipWith (<$) cfps' mmt)
502
+ uses GetModIface cs_exist
503
+ pure opts
489
504
490
505
491
506
@@ -577,7 +592,7 @@ setCacheDir logger prefix hscComponents comps dflags = do
577
592
liftIO $ logInfo logger $ " Using interface files cache dir: " <> T. pack cacheDir
578
593
pure $ dflags
579
594
& setHiDir cacheDir
580
- & setDefaultHieDir cacheDir
595
+ & setHieDir cacheDir
581
596
582
597
583
598
renderCradleError :: NormalizedFilePath -> CradleError -> FileDiagnostic
0 commit comments