Skip to content

Commit efc1caa

Browse files
committed
batch load
1 parent fa28306 commit efc1caa

File tree

1 file changed

+52
-42
lines changed

1 file changed

+52
-42
lines changed

ghcide/session-loader/Development/IDE/Session.hs

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
479479
-- files in the project so that `knownFiles` can learn about them and
480480
-- we can generate a complete module graph
481481
let extendKnownTargets newTargets = do
482-
knownTargets <- concatForM newTargets $ \TargetDetails{..} ->
482+
knownTargets <- concatForM newTargets $ \TargetDetails{..} ->
483483
case targetTarget of
484484
TargetFile f -> do
485485
-- If a target file has multiple possible locations, then we
@@ -563,9 +563,27 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
563563
let (new,old) = NE.splitAt (NE.length new_deps) all_deps'
564564
pure (Map.insert hieYaml (NE.toList all_deps) m, (new,old))
565565

566+
let restartSession all_targets new_deps = do
567+
restartShakeSession VFSUnmodified "new component" [] $ do
568+
keys2 <- invalidateShakeCache
569+
keys1 <- extendKnownTargets all_targets
570+
return [keys1, keys2]
571+
572+
-- Typecheck all files in the project on startup
573+
checkProject <- getCheckProject
574+
unless (null new_deps || not checkProject) $ do
575+
cfps' <- liftIO $ filterM (IO.doesFileExist . fromNormalizedFilePath) (concatMap targetLocations all_targets)
576+
void $ shakeEnqueue extras $ mkDelayedAction "InitialLoad" Debug $ void $ do
577+
mmt <- uses GetModificationTime cfps'
578+
let cs_exist = catMaybes (zipWith (<$) cfps' mmt)
579+
modIfaces <- uses GetModIface cs_exist
580+
-- update exports map
581+
shakeExtras <- getShakeExtras
582+
let !exportsMap' = createExportsMap $ mapMaybe (fmap hirModIface) modIfaces
583+
liftIO $ atomically $ modifyTVar' (exportsMap shakeExtras) (exportsMap' <>)
566584

567585
let session :: (Maybe FilePath, NormalizedFilePath, ComponentOptions, FilePath)
568-
-> IO (IdeResult HscEnvEq,[FilePath])
586+
-> IO ((IdeResult HscEnvEq,[FilePath]), ([TargetDetails], [ComponentInfo]))
569587
session args@(hieYaml, _cfp, _opts, _libDir) = do
570588
(new_deps, old_deps) <- packageSetup args
571589

@@ -576,14 +594,15 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
576594
hscEnv <- emptyHscEnv ideNc _libDir
577595
let new_cache = newComponentCache recorder optExtensions _cfp hscEnv
578596
all_target_details <- new_cache old_deps new_deps
579-
597+
let all_targets' = concat all_target_details
598+
flags_map' = HM.fromList (concatMap toFlagsMap all_targets')
580599
this_dep_info <- getDependencyInfo $ maybeToList hieYaml
600+
581601
let (all_targets, this_flags_map, this_options)
582602
= case HM.lookup _cfp flags_map' of
583603
Just this -> (all_targets', flags_map', this)
584604
Nothing -> (this_target_details : all_targets', HM.insert _cfp this_flags flags_map', this_flags)
585-
where all_targets' = concat all_target_details
586-
flags_map' = HM.fromList (concatMap toFlagsMap all_targets')
605+
where
587606
this_target_details = TargetDetails (TargetFile _cfp) this_error_env this_dep_info [_cfp]
588607
this_flags = (this_error_env, this_dep_info)
589608
this_error_env = ([this_error], Nothing)
@@ -598,25 +617,8 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
598617
-- The VFS doesn't change on cradle edits, re-use the old one.
599618
-- Invalidate all the existing GhcSession build nodes by restarting the Shake session
600619
-- todo result only when batch cradle loading is done
601-
keys2 <- invalidateShakeCache
602-
restartShakeSession VFSUnmodified "new component" [] $ do
603-
keys1 <- extendKnownTargets all_targets
604-
return [keys1, keys2]
605-
606-
-- Typecheck all files in the project on startup
607-
checkProject <- getCheckProject
608-
unless (null new_deps || not checkProject) $ do
609-
cfps' <- liftIO $ filterM (IO.doesFileExist . fromNormalizedFilePath) (concatMap targetLocations all_targets)
610-
void $ shakeEnqueue extras $ mkDelayedAction "InitialLoad" Debug $ void $ do
611-
mmt <- uses GetModificationTime cfps'
612-
let cs_exist = catMaybes (zipWith (<$) cfps' mmt)
613-
modIfaces <- uses GetModIface cs_exist
614-
-- update exports map
615-
shakeExtras <- getShakeExtras
616-
let !exportsMap' = createExportsMap $ mapMaybe (fmap hirModIface) modIfaces
617-
liftIO $ atomically $ modifyTVar' (exportsMap shakeExtras) (exportsMap' <>)
618-
619-
return $ second Map.keys this_options
620+
-- restartSession all_targets new_deps
621+
return $ (second Map.keys this_options, (all_targets, new_deps))
620622

621623
let eoptsHscEnv (hieYaml, cfp, cradle, eopts) =
622624
case eopts of
@@ -629,8 +631,8 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
629631
((runTime, _):_)
630632
| compileTime == runTime -> do
631633
atomicModifyIORef' cradle_files (\xs -> (cfp:xs,()))
632-
session (hieYaml, toNormalizedFilePath' cfp, opts, libDir)
633-
| otherwise -> return (([renderPackageSetupException cfp GhcVersionMismatch{..}], Nothing),[])
634+
fmap (fmap Just) $ session (hieYaml, toNormalizedFilePath' cfp, opts, libDir)
635+
| otherwise -> return ((([renderPackageSetupException cfp GhcVersionMismatch{..}], Nothing),[]), Nothing)
634636
-- Failure case, either a cradle error or the none cradle
635637
Left err -> do
636638
dep_info <- getDependencyInfo (maybeToList hieYaml)
@@ -639,10 +641,11 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
639641
void $ modifyVar' fileToFlags $
640642
Map.insertWith HM.union hieYaml (HM.singleton ncfp (res, dep_info))
641643
void $ modifyVar' filesMap $ HM.insert ncfp hieYaml
642-
return (res, maybe [] pure hieYaml ++ concatMap cradleErrorDependencies err)
644+
return ((res, maybe [] pure hieYaml ++ concatMap cradleErrorDependencies err), Nothing)
643645

644-
let consultCradles :: [(Maybe FilePath, FilePath)] -> IO [(IdeResult HscEnvEq, [FilePath])]
645-
consultCradles hyCfpList = do
646+
let
647+
consultCradles [] = return []
648+
consultCradles hyCfpList = do
646649
let cfps = map snd hyCfpList
647650
let lfpLogs = map (makeRelative rootDir . snd) hyCfpList
648651
logWith recorder Info $ LogCradlePaths lfpLogs
@@ -656,7 +659,8 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
656659
return res
657660
mapM eoptsHscEnv (zipWith (\((hieYaml, fp), cr) eopts -> (hieYaml, fp, cr, eopts) ) (zip hyCfpList cradles) eoptsList)
658661

659-
let consultCradle :: Maybe FilePath -> FilePath -> IO (IdeResult HscEnvEq, [FilePath])
662+
let
663+
-- consultCradle :: Maybe FilePath -> FilePath -> IO (IdeResult HscEnvEq, [FilePath])
660664
consultCradle hieYaml cfp = do
661665
let lfpLog = makeRelative rootDir cfp
662666
logWith recorder Info $ LogCradlePath lfpLog
@@ -697,7 +701,8 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
697701

698702
-- This caches the mapping from hie.yaml + Mod.hs -> [String]
699703
-- Returns the Ghc session and the cradle dependencies
700-
let sessionOpts :: (Maybe FilePath, FilePath) -> IO (IdeResult HscEnvEq, [FilePath])
704+
let
705+
-- sessionOpts :: (Maybe FilePath, FilePath) -> IO (IdeResult HscEnvEq, [FilePath])
701706
sessionOpts (hieYaml, file) = do
702707
Extra.whenM didSessionLoadingPreferenceConfigChange $ do
703708
logWith recorder Info LogSessionLoadingChanged
@@ -722,7 +727,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
722727
-- Keep the same name cache
723728
modifyVar_ hscEnvs (return . Map.adjust (const []) hieYaml )
724729
consultCradle hieYaml cfp
725-
else return (opts, Map.keys old_di)
730+
else return ((opts, Map.keys old_di), Nothing)
726731
Nothing -> consultCradle hieYaml cfp
727732

728733
let readSessionOptsFromCache (hieYaml, file) = do
@@ -748,7 +753,11 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
748753
cached <- mapM readSessionOptsFromCache yamlFiles
749754
let (toConsults, cachedResults) = partitionEithers cached
750755
results <- consultCradles toConsults
751-
let consultMap = Map.fromList $ zip (map snd toConsults) results
756+
let envs = map fst results
757+
let mergeDeps (x, y) (a, b) = (x <> a, y <> b)
758+
let (tgs, deps) = foldr mergeDeps ([], []) $ mapMaybe snd results
759+
Extra.whenM (return $ notNull toConsults) (restartSession tgs deps)
760+
let consultMap = Map.fromList $ zip (map snd toConsults) envs
752761
let cachedMap = Map.fromList cachedResults
753762
return $ consultMap <> cachedMap
754763

@@ -767,13 +776,13 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
767776
-- at a time. Therefore the IORef contains the currently running cradle, if we try
768777
-- to get some more options then we wait for the currently running action to finish
769778
-- before attempting to do so.
770-
let getOptions :: FilePath -> IO (IdeResult HscEnvEq, [FilePath])
771-
getOptions file = do
772-
let ncfp = toNormalizedFilePath' (toAbsolutePath file)
773-
cachedHieYamlLocation <- HM.lookup ncfp <$> readVar filesMap
774-
hieYaml <- cradleLoc file
775-
sessionOpts (join cachedHieYamlLocation <|> hieYaml, file) `Safe.catch` \e ->
776-
return (([renderPackageSetupException file e], Nothing), maybe [] pure hieYaml)
779+
-- let getOptions :: FilePath -> IO (IdeResult HscEnvEq, [FilePath])
780+
-- getOptions file = do
781+
-- let ncfp = toNormalizedFilePath' (toAbsolutePath file)
782+
-- cachedHieYamlLocation <- HM.lookup ncfp <$> readVar filesMap
783+
-- hieYaml <- cradleLoc file
784+
-- sessionOpts (join cachedHieYamlLocation <|> hieYaml, file) `Safe.catch` \e ->
785+
-- return (([renderPackageSetupException file e], Nothing), maybe [] pure hieYaml)
777786

778787
let getOptionsBatch :: FilePath -> IO (IdeResult HscEnvEq, [FilePath])
779788
getOptionsBatch file' = do
@@ -799,9 +808,10 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
799808
-- how we do batch loading of cradles depends on the the type of cradle we are using
800809
cradleToOptsAndLibDirs :: Recorder (WithPriority Log) -> SessionLoadingPreferenceConfig -> [(Cradle Void, FilePath)] -> [FilePath]
801810
-> IO [Either [CradleError] (ComponentOptions, FilePath, String)]
802-
cradleToOptsAndLibDirs recorder loadConfig cradleFiles old_fps = do
811+
cradleToOptsAndLibDirs recorder loadConfig [] old_fps = error "cradleToOptsAndLibDirs: empty list of cradles"
812+
cradleToOptsAndLibDirs recorder loadConfig cradleFiles@(cr:crs) old_fps = do
803813
-- let result :: [([FilePath], CradleLoadResult ComponentOptions)]
804-
results <- HieBios.getCompilerOptionsInBatch (LoadWithContext old_fps) cradleFiles
814+
results <- HieBios.getCompilerOptionsInBatch (LoadWithContext old_fps) (cr :| crs)
805815
let resultMap :: Map.Map FilePath (CradleLoadResult ComponentOptions)
806816
resultMap = Map.fromList $ [ (fp, r) | (fps, r) <- results, fp <- fps ]
807817
mapM (\(cr, fp) -> collectBiosResult recorder cr fp (resultMap Map.! fp)) cradleFiles

0 commit comments

Comments
 (0)