module IdPropCaching ( MonadIdPropCaching(..) , modifyIdPropCache , extendIdPropCache , recordIdPropType ) where import Control.Applicative ((<|>)) import System.IO.Unsafe (unsafePerformIO) import IdeSession.Types.Private (IdPropPtr(..), IdProp(..)) import IdeSession.Types.Public (Type) import IdeSession.Strict.IORef import IdeSession.Strict.Container import qualified IdeSession.Strict.IntMap as IntMap import qualified IdeSession.Strict.Maybe as Maybe import GHC (Ghc) import MonadUtils class Monad m => MonadIdPropCaching m where getIdPropCache :: m (Strict IntMap IdProp) putIdPropCache :: Strict IntMap IdProp -> m () idPropCacheRef :: StrictIORef (Strict IntMap IdProp) {-# NOINLINE idPropCacheRef #-} idPropCacheRef = unsafePerformIO $ newIORef IntMap.empty instance MonadIdPropCaching IO where getIdPropCache = readIORef idPropCacheRef putIdPropCache = writeIORef idPropCacheRef instance MonadIdPropCaching Ghc where getIdPropCache = liftIO $ getIdPropCache putIdPropCache = liftIO . putIdPropCache modifyIdPropCache :: MonadIdPropCaching m => IdPropPtr -> (IdProp -> IdProp) -> m () modifyIdPropCache ptr f = do cache <- getIdPropCache putIdPropCache $ IntMap.adjust f (idPropPtr ptr) cache extendIdPropCache :: MonadIdPropCaching m => IdPropPtr -> IdProp -> m () extendIdPropCache ptr prop = do cache <- getIdPropCache putIdPropCache $ IntMap.insertWith update (idPropPtr ptr) prop cache where -- We need to make sure not to lose information that we learned earlier update :: IdProp -> IdProp -> IdProp update new old = new { idType = idType new <|> idType old , idHomeModule = idHomeModule new <|> idHomeModule old } recordIdPropType :: MonadIdPropCaching m => IdPropPtr -> Type -> m () recordIdPropType ptr tp = modifyIdPropCache ptr $ \idInfo -> idInfo { idType = Maybe.just tp }