Skip to content

Commit 21dd233

Browse files
committed
better error handling in session loader
1 parent 98999f5 commit 21dd233

File tree

1 file changed

+29
-36
lines changed

1 file changed

+29
-36
lines changed

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

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -489,16 +489,6 @@ addToPending :: SessionState -> FilePath -> STM ()
489489
addToPending state file =
490490
S.insert file (pendingFileSet state)
491491

492-
-- | Common pattern: Insert file flags, insert file mapping, and remove from pending
493-
completeFileProcessing :: SessionState -> Maybe FilePath -> NormalizedFilePath -> FilePath -> (IdeResult HscEnvEq, DependencyInfo) -> IO ()
494-
completeFileProcessing state hieYaml ncfp file flags = do
495-
-- remove cfp from pending files
496-
addErrorLoadingFile state file
497-
removeCradleFile state file
498-
atomically $ do
499-
insertFileFlags state hieYaml ncfp flags
500-
insertFileMapping state hieYaml ncfp
501-
removeFromPending state file
502492

503493
-- | Insert multiple file mappings at once
504494
insertAllFileMappings :: SessionState -> [(Maybe FilePath, NormalizedFilePath)] -> STM ()
@@ -516,10 +506,20 @@ getPendingFiles state = atomically $ Set.fromList <$> S.toUnOrderedList (pending
516506
-- | Handle errors during session loading by recording file as having error and removing from pending
517507
handleSessionError :: SessionState -> Maybe FilePath -> FilePath -> PackageSetupException -> IO ()
518508
handleSessionError state hieYaml file e = do
519-
dep <- getDependencyInfo $ maybe [] pure hieYaml
509+
handleFileProcessingError state hieYaml file [renderPackageSetupException file e] mempty
510+
511+
-- | Common pattern: Insert file flags, insert file mapping, and remove from pending
512+
handleFileProcessingError :: SessionState -> Maybe FilePath -> FilePath -> [FileDiagnostic] -> [FilePath] -> IO ()
513+
handleFileProcessingError state hieYaml file diags extraDepFiles = do
514+
addErrorLoadingFile state file
515+
removeCradleFile state file
516+
dep <- getDependencyInfo $ maybeToList hieYaml <> extraDepFiles
520517
let ncfp = toNormalizedFilePath' file
521-
let errorResult = (([renderPackageSetupException file e], Nothing), dep)
522-
completeFileProcessing state hieYaml ncfp file errorResult
518+
let flags = ((diags, Nothing), dep)
519+
atomically $ do
520+
insertFileFlags state hieYaml ncfp flags
521+
insertFileMapping state hieYaml ncfp
522+
removeFromPending state file
523523

524524
-- | Get the set of extra files to load based on the current file path
525525
-- If the current file is in error loading files, we fallback to single loading mode (empty set)
@@ -679,8 +679,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
679679
pure (Map.insert hieYaml (NE.toList all_deps) m, (new,old))
680680

681681

682-
let session :: (Maybe FilePath, NormalizedFilePath, ComponentOptions, FilePath)
683-
-> IO ((IdeResult HscEnvEq,DependencyInfo), HashSet FilePath, IO ())
682+
let session :: (Maybe FilePath, NormalizedFilePath, ComponentOptions, FilePath) -> IO ()
684683
session args@(hieYaml, _cfp, _opts, _libDir) = do
685684
(new_deps, old_deps) <- packageSetup args
686685

@@ -695,7 +694,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
695694
let flags_map' = HM.fromList (concatMap toFlagsMap all_targets')
696695
all_targets' = concat all_target_details
697696
this_dep_info <- getDependencyInfo $ maybeToList hieYaml
698-
let (all_targets, this_flags_map, this_options)
697+
let (all_targets, this_flags_map, _this_options)
699698
= case HM.lookup _cfp flags_map' of
700699
Just this -> (all_targets', flags_map', this)
701700
Nothing -> (this_target_details : all_targets', HM.insert _cfp this_flags flags_map', this_flags)
@@ -710,17 +709,24 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
710709
])
711710
Nothing
712711

713-
let newLoaded = Set.fromList $ fromNormalizedFilePath <$> HM.keys this_flags_map
712+
pendingFiles <- getPendingFiles sessionState
713+
-- this_flags_map might contains files not in pendingFiles, take the intersection
714+
let newLoaded = pendingFiles `Set.intersection` Set.fromList (fromNormalizedFilePath <$> HM.keys this_flags_map)
714715
atomically $ do
715716
STM.insert this_flags_map hieYaml (fileToFlags sessionState)
716717
insertAllFileMappings sessionState $ map ((hieYaml,) . fst) $ concatMap toFlagsMap all_targets
717718
forM_ newLoaded $ flip S.delete (pendingFileSet sessionState)
718719

720+
logWith recorder Info $ LogSessionNewLoadedFiles $ Set.toList newLoaded
721+
-- remove all new loaded file from error loading files
722+
mapM_ (removeErrorLoadingFile sessionState) (Set.toList newLoaded)
723+
addCradleFiles sessionState newLoaded
719724
-- Typecheck all files in the project on startup
720725
checkProject <- getCheckProject
726+
721727
-- The VFS doesn't change on cradle edits, re-use the old one.
722728
-- Invalidate all the existing GhcSession build nodes by restarting the Shake session
723-
let restart = restartShakeSession VFSUnmodified "new component" [] $ do
729+
restartShakeSession VFSUnmodified "new component" [] $ do
724730
keys2 <- invalidateShakeCache
725731
keys1 <- extendKnownTargets all_targets
726732
unless (null new_deps || not checkProject) $ do
@@ -734,7 +740,6 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
734740
let !exportsMap' = createExportsMap $ mapMaybe (fmap hirModIface) modIfaces
735741
liftIO $ atomically $ modifyTVar' (exportsMap shakeExtras) (exportsMap' <>)
736742
return [keys1, keys2]
737-
return (this_options, newLoaded, restart)
738743

739744
let consultCradle :: Maybe FilePath -> FilePath -> IO ()
740745
consultCradle hieYaml cfp = do
@@ -759,29 +764,19 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
759764
return res
760765

761766
logWith recorder Debug $ LogSessionLoadingResult eopts
767+
let ncfp = toNormalizedFilePath' cfp
762768
case eopts of
763769
-- The cradle gave us some options so get to work turning them
764770
-- into and HscEnv.
765771
Right (opts, libDir, version) -> do
766-
let ncfp = toNormalizedFilePath' cfp
767772
let compileTime = fullCompilerVersion
768773
case reverse $ readP_to_S parseVersion version of
769774
[] -> error $ "GHC version could not be parsed: " <> version
770775
((runTime, _):_)
771-
| compileTime == runTime -> do
772-
(_results, allNewLoaded, restart) <- session (hieYaml, ncfp, opts, libDir)
773-
pendingFiles <- getPendingFiles sessionState
774-
let newLoaded = pendingFiles `Set.intersection` allNewLoaded
775-
-- log new loaded files
776-
logWith recorder Info $ LogSessionNewLoadedFiles $ Set.toList newLoaded
777-
-- remove all new loaded file from error loading files
778-
mapM_ (removeErrorLoadingFile sessionState) (Set.toList allNewLoaded)
779-
addCradleFiles sessionState newLoaded
780-
restart
776+
| compileTime == runTime -> session (hieYaml, ncfp, opts, libDir)
781777
| otherwise -> do
782778
-- Use the common pattern here: updateFileState
783-
completeFileProcessing sessionState hieYaml ncfp cfp
784-
(([renderPackageSetupException cfp GhcVersionMismatch{..}], Nothing), mempty)
779+
handleFileProcessingError sessionState hieYaml cfp [renderPackageSetupException cfp GhcVersionMismatch{..}] mempty
785780
-- Failure case, either a cradle error or the none cradle
786781
Left err -> do
787782
-- what if the error to load file is one of old_files ?
@@ -802,10 +797,8 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
802797
consultCradle hieYaml cfp
803798
else do
804799
-- we are only loading this file and it failed
805-
dep_info <- getDependencyInfo (maybeToList hieYaml ++ concatMap cradleErrorDependencies err)
806-
let ncfp = toNormalizedFilePath' cfp
807-
let res = (map (\err' -> renderCradleError err' cradle ncfp) err, Nothing)
808-
completeFileProcessing sessionState hieYaml ncfp cfp (res, dep_info)
800+
let res = map (\err' -> renderCradleError err' cradle ncfp) err
801+
handleFileProcessingError sessionState hieYaml cfp res $ concatMap cradleErrorDependencies err
809802

810803
let
811804
-- | We allow users to specify a loading strategy.

0 commit comments

Comments
 (0)