@@ -95,8 +95,11 @@ import System.Info
95
95
import Control.Applicative (Alternative ((<|>) ))
96
96
import Data.Void
97
97
98
- import Control.Concurrent.STM.Stats (atomically , modifyTVar' ,
99
- readTVar , writeTVar )
98
+ import Control.Concurrent.STM.Stats (TVar , atomically ,
99
+ modifyTVar' , newTVar ,
100
+ newTVarIO , readTVar ,
101
+ readTVarIO , stateTVar ,
102
+ swapTVar , writeTVar )
100
103
import Control.Concurrent.STM.TQueue
101
104
import Control.DeepSeq
102
105
import Control.Exception (evaluate )
@@ -161,11 +164,15 @@ data Log
161
164
| LogNewComponentCache ! (([FileDiagnostic ], Maybe HscEnvEq ), DependencyInfo )
162
165
| LogHieBios HieBios. Log
163
166
| LogSessionLoadingChanged
167
+ | LogCacheVersion NormalizedFilePath ! Int
168
+ | LogClearingCache ! NormalizedFilePath
164
169
deriving instance Show Log
165
170
166
171
167
172
instance Pretty Log where
168
173
pretty = \ case
174
+ LogClearingCache path ->
175
+ " Clearing cache for" <+> pretty (fromNormalizedFilePath path)
169
176
LogNoneCradleFound path ->
170
177
" None cradle found for" <+> pretty path <+> " , ignoring the file"
171
178
LogSettingInitialDynFlags ->
@@ -235,6 +242,8 @@ instance Pretty Log where
235
242
LogSessionLoadingChanged ->
236
243
" Session Loading config changed, reloading the full session."
237
244
LogShake msg -> pretty msg
245
+ LogCacheVersion path version ->
246
+ " Cache version for" <+> pretty (fromNormalizedFilePath path) <+> " is" <+> pretty version
238
247
239
248
-- | Bump this version number when making changes to the format of the data stored in hiedb
240
249
hiedbDataVersion :: String
@@ -460,31 +469,34 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir = do
460
469
-- Mapping from hie.yaml file to HscEnv, one per hie.yaml file
461
470
hscEnvs <- newVar Map. empty :: IO (Var HieMap )
462
471
-- Mapping from a Filepath to HscEnv
463
- fileToFlags <- newVar Map. empty :: IO (Var FlagsMap )
472
+ fileToFlags <- newTVarIO Map. empty :: IO (TVar FlagsMap )
464
473
-- Mapping from a Filepath to its 'hie.yaml' location.
465
474
-- Should hold the same Filepaths as 'fileToFlags', otherwise
466
475
-- they are inconsistent. So, everywhere you modify 'fileToFlags',
467
476
-- you have to modify 'filesMap' as well.
468
- filesMap <- newVar HM. empty :: IO (Var FilesMap )
477
+ filesMap <- newTVarIO HM. empty :: IO (TVar FilesMap )
469
478
470
479
-- Version of the mappings above
471
480
version <- newVar 0
472
481
482
+
483
+ restartKeys <- newTVarIO []
484
+ targetFiles <- newTVarIO []
473
485
-- version of the whole rebuild
474
- cacheVersion <- newVar 0
475
- lastRestartVersion <- newVar 0
486
+ cacheVersion <- newTVarIO 0
476
487
cradleLock <- newMVar ()
477
- -- putMVar cradleLock ()
478
488
biosSessionLoadingVar <- newVar Nothing :: IO (Var (Maybe SessionLoadingPreferenceConfig ))
479
489
480
490
let returnWithVersion fun = IdeGhcSession fun <$> liftIO (readVar version)
481
491
482
492
483
493
let clearCache = do
484
- modifyVar_ cacheVersion $ pure . succ
485
- modifyVar_ hscEnvs $ \ _ -> pure Map. empty
486
- modifyVar_ fileToFlags $ \ _ -> pure Map. empty
487
- modifyVar_ filesMap $ \ _ -> pure HM. empty
494
+ atomically $ modifyTVar' restartKeys ([toNoFileKey SessionCacheVersion ] ++ )
495
+ atomically $ modifyTVar' cacheVersion succ
496
+ void $ modifyVar' hscEnvs $ \ _ -> Map. empty
497
+ -- modifyTVar' hscEnvs $ \_ -> Map.empty
498
+ atomically $ modifyTVar' fileToFlags $ \ _ -> Map. empty
499
+ atomically $ modifyTVar' filesMap $ \ _ -> HM. empty
488
500
let
489
501
-- | We allow users to specify a loading strategy.
490
502
-- Check whether this config was changed since the last time we have loaded
@@ -546,8 +558,8 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir = do
546
558
, " If you are using a .cabal file, please ensure that this module is listed in either the exposed-modules or other-modules section"
547
559
]
548
560
549
- liftIO $ void $ modifyVar ' fileToFlags $ Map. insert hieYaml this_flags_map
550
- liftIO $ void $ modifyVar ' filesMap $ flip HM. union (HM. fromList (map ((,hieYaml) . fst ) $ concatMap toFlagsMap all_targets))
561
+ liftIO $ void $ atomically $ modifyTVar ' fileToFlags $ Map. insert hieYaml this_flags_map
562
+ liftIO $ void $ atomically $ modifyTVar ' filesMap $ flip HM. union (HM. fromList (map ((,hieYaml) . fst ) $ concatMap toFlagsMap all_targets))
551
563
-- The VFS doesn't change on cradle edits, re-use the old one.
552
564
-- Invalidate all the existing GhcSession build nodes by restarting the Shake session
553
565
keys2 <- liftIO invalidateShakeCache
@@ -667,7 +679,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir = do
667
679
ShakeExtras {lspEnv } <- getShakeExtras
668
680
IdeOptions { optTesting = IdeTesting optTesting } <- getIdeOptions
669
681
hieYamlOld <- use_ CradleLoc cfp
670
- cachedHieYamlLocation <- join <$> liftIO (HM. lookup cfp <$> readVar filesMap)
682
+ cachedHieYamlLocation <- join <$> liftIO (HM. lookup cfp <$> readTVarIO filesMap)
671
683
let hieYaml = fromMaybe cachedHieYamlLocation (Just hieYamlOld)
672
684
let lfpLog = makeRelative rootDir (fromNormalizedFilePath cfp)
673
685
logWith recorder Info $ LogCradlePath lfpLog
@@ -706,49 +718,66 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir = do
706
718
Left err -> do
707
719
dep_info <- liftIO $ getDependencyInfo (maybeToList hieYaml)
708
720
let res = (map (\ err' -> renderCradleError err' cradle cfp) err, Nothing )
709
- liftIO $ void $ modifyVar ' fileToFlags $
721
+ liftIO $ atomically $ modifyTVar ' fileToFlags $
710
722
Map. insertWith HM. union hieYaml (HM. singleton cfp (res, dep_info))
711
- liftIO $ void $ modifyVar ' filesMap $ HM. insert cfp hieYaml
723
+ liftIO $ atomically $ modifyTVar ' filesMap $ HM. insert cfp hieYaml
712
724
return (res, maybe [] pure hieYaml ++ concatMap cradleErrorDependencies err,[] ,[] )
713
725
714
726
sessionCacheVersionRule :: Rules ()
715
727
sessionCacheVersionRule = defineNoFile (cmapWithPrio LogShake recorder) $ \ SessionCacheVersion -> do
716
- v <- liftIO $ readVar cacheVersion
728
+ alwaysRerun
729
+ v <- liftIO $ readTVarIO cacheVersion
717
730
pure v
718
731
719
732
hieYamlRule :: Rules ()
720
- hieYamlRule = defineNoDiagnostics (cmapWithPrio LogShake recorder) $ \ HieYaml file ->
721
- -- only one cradle consult at a time
722
- UnliftIO. withMVar cradleLock $ const $ do
733
+ hieYamlRule = defineNoDiagnostics (cmapWithPrio LogShake recorder) $ \ HieYaml file -> do
723
734
hieYaml <- use_ CradleLoc file
724
735
-- check the reason we are called
725
- v <- Map. findWithDefault HM. empty hieYaml <$> (liftIO$ readVar fileToFlags)
726
- case HM. lookup file v of
736
+ v <- Map. findWithDefault HM. empty hieYaml <$> (liftIO$ readTVarIO fileToFlags)
737
+ someThing <- case HM. lookup file v of
727
738
-- we already have the cache but it is still called, it must be deps changed
728
739
-- clear the cache and reconsult
729
740
-- we bump the version of the cache to inform others
730
- Just _ -> do
731
- liftIO clearCache
732
- -- we don't have the cache, consult
733
- Nothing -> pure ()
734
- -- install cache version check to avoid recompilation
735
- _ <- useNoFile_ SessionCacheVersion
736
- catchError file hieYaml $ do
737
- result@ (_, deps, _, _) <- consultCradle file
738
- -- add the deps to the Shake graph
739
- mapM_ addDependency deps
740
- return $ Just result
741
- where
742
- catchError file hieYaml f =
743
- f `Safe.catch` \ e -> do
744
- -- install dep so it can be recorvered
745
- mapM_ addDependency hieYaml
746
- return $ Just (([renderPackageSetupException file e], Nothing ), maybe [] pure hieYaml, [] , [] )
747
- addDependency fp = do
748
- -- VSCode uses absolute paths in its filewatch notifications
749
- let nfp = toNormalizedFilePath' fp
750
- itExists <- getFileExists nfp
751
- when itExists $ void $ do use_ GetModificationTime nfp
741
+ Just (opts, old_di) -> do
742
+ -- need to differ two kinds of invocation, one is the file is changed
743
+ -- other is the cache version bumped
744
+ deps_ok <- liftIO $ checkDependencyInfo old_di
745
+ if not deps_ok
746
+ then do
747
+ logWith recorder Debug $ LogClearingCache file
748
+ liftIO clearCache
749
+ return Nothing
750
+ else return $ Just (opts, Map. keys old_di, [] , [] )
751
+ Nothing -> return Nothing
752
+ -- install cache version check to get notified when the cache is changed
753
+ -- todo but some how it is informing other, then other inform us, causing a loop
754
+ case someThing of
755
+ Just result@ (_, deps, _files, _keys) -> do
756
+ mapM_ addDependency deps
757
+ return $ Just result
758
+ Nothing -> do
759
+ v <- useNoFile_ SessionCacheVersion
760
+ logWith recorder Debug $ LogCacheVersion file v
761
+
762
+ catchError file hieYaml $ do
763
+ result@ (_, deps, files, keys) <- consultCradle file
764
+ -- add the deps to the Shake graph
765
+ liftIO $ atomically $ do
766
+ modifyTVar' targetFiles (files ++ )
767
+ modifyTVar' restartKeys (keys ++ )
768
+ mapM_ addDependency deps
769
+ return $ Just result
770
+ where
771
+ catchError file hieYaml f =
772
+ f `Safe.catch` \ e -> do
773
+ -- install dep so it can be recorvered
774
+ mapM_ addDependency hieYaml
775
+ return $ Just (([renderPackageSetupException file e], Nothing ), maybe [] pure hieYaml, [] , [] )
776
+ addDependency fp = do
777
+ -- VSCode uses absolute paths in its filewatch notifications
778
+ let nfp = toNormalizedFilePath' fp
779
+ itExists <- getFileExists nfp
780
+ when itExists $ void $ do use_ GetModificationTime nfp
752
781
753
782
cradleLocRule :: Rules ()
754
783
cradleLocRule = defineNoDiagnostics (cmapWithPrio LogShake recorder) $ \ CradleLoc file -> do
@@ -769,18 +798,22 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir = do
769
798
-- before attempting to do so.
770
799
ShakeExtras {restartShakeSession } <- getShakeExtras
771
800
IdeOptions { optCheckProject = getCheckProject} <- getIdeOptions
772
- returnWithVersion $ \ file -> do
773
- _opts@ (a, b, files, keys) <- use_ HieYaml file
774
- -- wait for the restart
775
- lastRestartVersion' <- liftIO $ readVar lastRestartVersion
776
- cacheVersion' <- liftIO $ readVar cacheVersion
777
- liftIO $ when ((notNull files || notNull keys) && lastRestartVersion' /= cacheVersion') $ do
778
- liftIO $ writeVar lastRestartVersion cacheVersion'
779
- checkProject <- getCheckProject
780
- -- think of not to restart a second time
781
- async <- UnliftIO. async $ restartShakeSession VFSUnmodified " new component" (if checkProject then return (typecheckAll files) else mempty ) $ pure keys
801
+ returnWithVersion $ \ file ->
802
+ -- only one cradle consult at a time
803
+ UnliftIO. withMVar cradleLock $ const $ do
804
+ -- we need to find a way to get rid of the (files, keys)
805
+ _opts@ (a, b, _files, _keys) <- use_ HieYaml file
806
+ -- _opts@(a, b, _files, _keys) <- getOptions file
807
+ async <- UnliftIO. async $ do
808
+ files <- liftIO $ atomically $ swapTVar targetFiles []
809
+ keys <- liftIO $ atomically $ swapTVar restartKeys []
810
+ _ <- useNoFile_ SessionCacheVersion
811
+ liftIO $ when (notNull files || notNull keys) $ do
812
+ checkProject <- getCheckProject
813
+ -- think of not to restart a second time
814
+ restartShakeSession VFSUnmodified " new component" (if checkProject then return (typecheckAll files) else mempty ) $ pure keys
782
815
UnliftIO. wait async
783
- pure $ (fmap . fmap ) toAbsolutePath (a, b))
816
+ pure $ (fmap . fmap ) toAbsolutePath (a, b))
784
817
785
818
786
819
-- | Run the specific cradle on a specific FilePath via hie-bios.
0 commit comments