@@ -16,7 +16,19 @@
1616{-# LANGUAGE PackageImports #-}
1717{-# LANGUAGE TemplateHaskell #-}
1818
19−module Language.PureScript.Ide.State where
19+module Language.PureScript.Ide.State
20+ ( getPscIdeState
21+ , getExternFiles
22+ , getModule
23+ , getModuleWithReexports
24+ , getAllModulesWithReexports
25+ , getAllModulesWithReexportsAndCache
26+ , insertModule
27+ , insertModuleSTM
28+ , getCachedRebuild
29+ , resetPscIdeState
30+ , setCachedRebuild
31+ ) where
2032
2133import Prelude ()
2234import Prelude.Compat
@@ -26,74 +38,106 @@ import Control.Monad.IO.Class
2638import "monad-logger" Control.Monad.Logger
2739import Control.Monad.Reader.Class
2840import qualified Data.Map.Lazy as M
29−import Data.Maybe (catMaybes)
41+import Data.Maybe (mapMaybe)
3042import Data.Monoid
31−import qualified Data.Text as T
3243import Language.PureScript.Externs
3344import Language.PureScript.Ide.Externs
3445import Language.PureScript.Ide.Reexports
3546import Language.PureScript.Ide.Types
36−import Language.PureScript.Names
47+import Language.PureScript.Ide.Util
48+import qualified Language.PureScript as P
3749
50+-- | Resets the PscIdeState to emptyPscIdeState
3851resetPscIdeState :: PscIde m => m ()
3952resetPscIdeState = do
4053 stateVar <- envStateVar <$> ask
4154 liftIO $ atomically (writeTVar stateVar emptyPscIdeState)
4255
43−getPscIdeState :: (PscIde m) =>
44− m (M.Map ModuleIdent [ExternDecl])
56+-- | Gets the entire PscIdeState
57+getPscIdeState :: PscIde m => m PscIdeState
4558getPscIdeState = do
4659 stateVar <- envStateVar <$> ask
47− liftIO $ pscStateModules <$> readTVarIO stateVar
60+ liftIO (readTVarIO stateVar)
4861
49−getExternFiles :: (PscIde m) =>
50− m (M.Map ModuleName ExternsFile)
62+-- | Gets all loaded ExternFiles
63+getExternFiles :: (PscIde m) => m (M.Map P.ModuleName ExternsFile)
5164getExternFiles = do
5265 stateVar <- envStateVar <$> ask
53− liftIO (externsFiles <$> readTVarIO stateVar)
54−
55−getExternFile :: (PscIde m) =>
56− ModuleName -> m (Maybe ExternsFile)
57−getExternFile mn = M.lookup mn <$> getExternFiles
58−
59−getAllDecls :: (PscIde m) => m [ExternDecl]
60−getAllDecls = concat <$> getPscIdeState
61−
62−getAllModules :: (PscIde m) => m [Module]
63−getAllModules = M.toList <$> getPscIdeState
64−
65−getAllModulesWithReexports :: (PscIde m, MonadLogger m) =>
66− m [Module]
67−getAllModulesWithReexports = do
68− mis <- M.keys <$> getPscIdeState
69− ms <- traverse getModuleWithReexports mis
70− pure (catMaybes ms)
71−
72−getModule :: (PscIde m, MonadLogger m) =>
73− ModuleIdent -> m (Maybe Module)
74−getModule m = do
75− modules <- getPscIdeState
76− pure ((m,) <$> M.lookup m modules)
77−
78−getModuleWithReexports :: (PscIde m, MonadLogger m) =>
79− ModuleIdent -> m (Maybe Module)
80−getModuleWithReexports mi = do
81− m <- getModule mi
82− modules <- getPscIdeState
83− pure $ resolveReexports modules <$> m
84−
85−insertModule ::(PscIde m, MonadLogger m) =>
66+ liftIO (pscIdeStateExternsFiles <$> readTVarIO stateVar)
67+
68+-- | Gets all loaded Modules and resolves Reexports
69+getAllModulesWithReexports :: (PscIde m) => m [Module]
70+getAllModulesWithReexports = getAllModulesWithReexports' <$> getPscIdeState
71+
72+-- | Pure version of @getAllModulesWithReexports@
73+getAllModulesWithReexports' :: PscIdeState -> [Module]
74+getAllModulesWithReexports' state =
75+ mapMaybe (getModuleWithReexports' state) (M.keys (pscIdeStateModules state))
76+
77+-- | Checks if the given ModuleName matches the last rebuild cache and if it
78+-- does, runs @getAllModulesWithReexports@ with the cached module replacing the
79+-- loaded module
80+getAllModulesWithReexportsAndCache
81+ :: (PscIde m)
82+ => Maybe P.ModuleName
83+ -> m [Module]
84+getAllModulesWithReexportsAndCache Nothing = getAllModulesWithReexports
85+getAllModulesWithReexportsAndCache (Just mn) = do
86+ state <- getPscIdeState
87+ cachedRebuild <- getCachedRebuild
88+ case cachedRebuild of
89+ Just (cachedIdent, ef) | cachedIdent == mn ->
90+ pure (getAllModulesWithReexports' (insertModule' ef state))
91+ _ -> getAllModulesWithReexports
92+
93+-- | Looks up a single Module inside the loaded Modules
94+getModule :: (PscIde m, MonadLogger m) => ModuleIdent -> m (Maybe Module)
95+getModule m = getModule' <$> getPscIdeState <*> pure m
96+
97+-- | Pure version of @getModule@
98+getModule' :: PscIdeState -> ModuleIdent -> Maybe Module
99+getModule' ps mi = (mi,) <$> M.lookup mi (pscIdeStateModules ps)
100+
101+-- | Looks up a single Module and resolves its Reexports
102+getModuleWithReexports :: PscIde m => ModuleIdent -> m (Maybe Module)
103+getModuleWithReexports i = getModuleWithReexports' <$> getPscIdeState <*> pure i
104+
105+-- | Pure version of @getModuleWithReexports@
106+getModuleWithReexports' :: PscIdeState -> ModuleIdent -> Maybe Module
107+getModuleWithReexports' ps mi =
108+ resolveReexports (pscIdeStateModules ps) <$> getModule' ps mi
109+
110+-- | Inserts an @ExternsFile@ into the PscIdeState. Also converts the
111+-- ExternsFile into psc-ide's internal Declaration format
112+insertModule :: (PscIde m, MonadLogger m) =>
86113 ExternsFile -> m ()
87114insertModule externsFile = do
88− env <- ask
115+ stateVar <- envStateVar <$> ask
89116 let moduleName = efModuleName externsFile
90− $(logDebug) $ "Inserting Module: " <> T.pack (runModuleName moduleName)
91− liftIO . atomically $ insertModule' (envStateVar env) externsFile
92−
93−insertModule' :: TVar PscIdeState -> ExternsFile -> STM ()
94−insertModule' st ef =
95− modifyTVar st $ \x ->
96− x { externsFiles = M.insert (efModuleName ef) ef (externsFiles x)
97− , pscStateModules = let (mn, decls) = convertExterns ef
98− in M.insert mn decls (pscStateModules x)
99− }
117+ $(logDebug) $ "Inserting Module: " <> runModuleNameT moduleName
118+ liftIO . atomically $ insertModuleSTM stateVar externsFile
119+
120+-- | STM version of insertModule
121+insertModuleSTM :: TVar PscIdeState -> ExternsFile -> STM ()
122+insertModuleSTM st ef = modifyTVar st (insertModule' ef)
123+
124+-- | Pure version of insertModule
125+insertModule' :: ExternsFile -> PscIdeState -> PscIdeState
126+insertModule' ef state =
127+ state
128+ { pscIdeStateExternsFiles =
129+ M.insert (efModuleName ef) ef (pscIdeStateExternsFiles state)
130+ , pscIdeStateModules = let (mn, decls) = convertExterns ef
131+ in M.insert mn decls (pscIdeStateModules state)
132+ }
133+
134+-- | Sets rebuild cache to the given ExternsFile
135+setCachedRebuild :: PscIde m => ExternsFile -> m ()
136+setCachedRebuild ef = do
137+ st <- envStateVar <$> ask
138+ liftIO . atomically . modifyTVar st $ \x ->
139+ x { pscIdeStateCachedRebuild = Just (efModuleName ef, ef) }
140+
141+-- | Retrieves the rebuild cache
142+getCachedRebuild :: PscIde m => m (Maybe (P.ModuleName, ExternsFile))
143+getCachedRebuild = pscIdeStateCachedRebuild <$> getPscIdeState