@@ -10,13 +10,11 @@ module Development.IDE.Core.FileExists
10
10
)
11
11
where
12
12
13
- import Control.Concurrent.Strict
13
+ import Control.Concurrent.STM ( atomically )
14
14
import Control.Exception
15
15
import Control.Monad.Extra
16
16
import Control.Monad.IO.Class
17
17
import qualified Data.ByteString as BS
18
- import Data.HashMap.Strict (HashMap )
19
- import qualified Data.HashMap.Strict as HashMap
20
18
import Data.List (partition )
21
19
import Data.Maybe
22
20
import Development.IDE.Core.FileStore
@@ -26,9 +24,11 @@ import Development.IDE.Core.Shake
26
24
import Development.IDE.Graph
27
25
import Development.IDE.Types.Location
28
26
import Development.IDE.Types.Options
27
+ import qualified Focus
29
28
import Ide.Plugin.Config (Config )
30
29
import Language.LSP.Server hiding (getVirtualFile )
31
30
import Language.LSP.Types
31
+ import qualified StmContainers.Map as STM
32
32
import qualified System.Directory as Dir
33
33
import qualified System.FilePath.Glob as Glob
34
34
@@ -74,32 +74,34 @@ fast path by a check that the path also matches our watching patterns.
74
74
-- | A map for tracking the file existence.
75
75
-- If a path maps to 'True' then it exists; if it maps to 'False' then it doesn't exist'; and
76
76
-- if it's not in the map then we don't know.
77
- type FileExistsMap = ( HashMap NormalizedFilePath Bool )
77
+ type FileExistsMap = STM. Map NormalizedFilePath Bool
78
78
79
79
-- | A wrapper around a mutable 'FileExistsState'
80
- newtype FileExistsMapVar = FileExistsMapVar ( Var FileExistsMap )
80
+ newtype FileExistsMapVar = FileExistsMapVar FileExistsMap
81
81
82
82
instance IsIdeGlobal FileExistsMapVar
83
83
84
84
-- | Grab the current global value of 'FileExistsMap' without acquiring a dependency
85
85
getFileExistsMapUntracked :: Action FileExistsMap
86
86
getFileExistsMapUntracked = do
87
87
FileExistsMapVar v <- getIdeGlobalAction
88
- liftIO $ readVar v
88
+ return v
89
89
90
90
-- | Modify the global store of file exists.
91
91
modifyFileExists :: IdeState -> [(NormalizedFilePath , FileChangeType )] -> IO ()
92
92
modifyFileExists state changes = do
93
93
FileExistsMapVar var <- getIdeGlobalState state
94
- changesMap <- evaluate $ HashMap. fromList changes
95
94
-- Masked to ensure that the previous values are flushed together with the map update
96
95
mask $ \ _ -> do
97
96
-- update the map
98
- void $ modifyVar' var $ HashMap. union (HashMap. mapMaybe fromChange changesMap)
97
+ void $ atomically $ forM_ changes $ \ (f,c) ->
98
+ case fromChange c of
99
+ Just c' -> STM. focus (Focus. insert c') f var
100
+ Nothing -> pure ()
99
101
-- See Note [Invalidating file existence results]
100
102
-- flush previous values
101
103
let (fileModifChanges, fileExistChanges) =
102
- partition ((== FcChanged ) . snd ) ( HashMap. toList changesMap)
104
+ partition ((== FcChanged ) . snd ) changes
103
105
mapM_ (deleteValue (shakeExtras state) GetFileExists . fst ) fileExistChanges
104
106
recordDirtyKeys (shakeExtras state) GetFileExists $ map fst fileExistChanges
105
107
recordDirtyKeys (shakeExtras state) GetModificationTime $ map fst fileModifChanges
@@ -161,7 +163,7 @@ fileExistsRules lspEnv vfs = do
161
163
-- Create the global always, although it should only be used if we have fast rules.
162
164
-- But there's a chance someone will send unexpected notifications anyway,
163
165
-- e.g. https://github.com/haskell/ghcide/issues/599
164
- addIdeGlobal . FileExistsMapVar =<< liftIO (newVar [] )
166
+ addIdeGlobal . FileExistsMapVar =<< liftIO STM. newIO
165
167
166
168
extras <- getShakeExtrasRules
167
169
opts <- liftIO $ getIdeOptionsIO extras
@@ -210,7 +212,7 @@ fileExistsFast vfs file = do
210
212
-- Could in principle use 'alwaysRerun' here, but it's too slwo, See Note [Invalidating file existence results]
211
213
mp <- getFileExistsMapUntracked
212
214
213
- let mbFilesWatched = HashMap .lookup file mp
215
+ mbFilesWatched <- liftIO $ atomically $ STM .lookup file mp
214
216
exist <- case mbFilesWatched of
215
217
Just exist -> pure exist
216
218
-- We don't know about it: use the slow route.
0 commit comments