Fix re-init of ghc-modi session after environment change

Using `dropSession` instead of a weird exception cludge
This commit is contained in:
Daniel Gröber 2015-08-05 08:52:52 +02:00
parent 20bccae1fc
commit f61dd0a9e6
4 changed files with 14 additions and 49 deletions

View File

@ -28,6 +28,7 @@ module Language.Haskell.GhcMod (
-- * Monad utilities -- * Monad utilities
, runGhcModT , runGhcModT
, withOptions , withOptions
, dropSession
-- * 'GhcMod' utilities -- * 'GhcMod' utilities
, boot , boot
, browse , browse
@ -73,3 +74,4 @@ import Language.Haskell.GhcMod.Modules
import Language.Haskell.GhcMod.Monad import Language.Haskell.GhcMod.Monad
import Language.Haskell.GhcMod.PkgDoc import Language.Haskell.GhcMod.PkgDoc
import Language.Haskell.GhcMod.Types import Language.Haskell.GhcMod.Types
import Language.Haskell.GhcMod.Target

View File

@ -110,6 +110,8 @@ initSession opts mdf = do
_ <- setSessionDynFlags =<< setDf =<< getSessionDynFlags _ <- setSessionDynFlags =<< setDf =<< getSessionDynFlags
getSession getSession
-- | Drop the currently active GHC session, the next that requires a GHC session
-- will initialize a new one.
dropSession :: IOish m => GhcModT m () dropSession :: IOish m => GhcModT m ()
dropSession = do dropSession = do
s <- gmsGet s <- gmsGet
@ -120,10 +122,10 @@ dropSession = do
liftIO $ writeIORef ref (error "HscEnv: session was dropped") liftIO $ writeIORef ref (error "HscEnv: session was dropped")
-- Not available on ghc<7.8; didn't really help anyways -- Not available on ghc<7.8; didn't really help anyways
-- liftIO $ setUnsafeGlobalDynFlags (error "DynFlags: session was dropped") -- liftIO $ setUnsafeGlobalDynFlags (error "DynFlags: session was dropped")
gmsPut s { gmGhcSession = Nothing }
Nothing -> return () Nothing -> return ()
gmsPut s { gmGhcSession = Nothing }
runGmlT :: IOish m => [Either FilePath ModuleName] -> GmlT m a -> GhcModT m a runGmlT :: IOish m => [Either FilePath ModuleName] -> GmlT m a -> GhcModT m a
runGmlT fns action = runGmlT' fns return action runGmlT fns action = runGmlT' fns return action

View File

@ -341,12 +341,11 @@ progMain (globalOptions,cmdArgs) = do
-- ghc-modi -- ghc-modi
legacyInteractive :: IOish m => GhcModT m () legacyInteractive :: IOish m => GhcModT m ()
legacyInteractive = legacyInteractive = do
liftIO emptyNewUnGetLine >>= \ref -> do
opt <- options opt <- options
symdbreq <- liftIO $ newSymDbReq opt symdbreq <- liftIO $ newSymDbReq opt
world <- liftIO . getCurrentWorld =<< cradle world <- liftIO . getCurrentWorld =<< cradle
legacyInteractiveLoop symdbreq ref world legacyInteractiveLoop symdbreq world
bug :: String -> IO () bug :: String -> IO ()
bug msg = do bug msg = do
@ -363,19 +362,18 @@ replace :: String -> String -> String -> String
replace needle replacement = intercalate replacement . splitOn needle replace needle replacement = intercalate replacement . splitOn needle
legacyInteractiveLoop :: IOish m legacyInteractiveLoop :: IOish m
=> SymDbReq -> UnGetLine -> World -> GhcModT m () => SymDbReq -> World -> GhcModT m ()
legacyInteractiveLoop symdbreq ref world = do legacyInteractiveLoop symdbreq world = do
liftIO . setCurrentDirectory =<< cradleRootDir <$> cradle liftIO . setCurrentDirectory =<< cradleRootDir <$> cradle
-- blocking -- blocking
cmdArg <- liftIO $ getCommand ref cmdArg <- liftIO $ getLine
-- after blocking, we need to see if the world has changed. -- after blocking, we need to see if the world has changed.
changed <- liftIO . didWorldChange world =<< cradle changed <- liftIO . didWorldChange world =<< cradle
when changed $ do when changed $ do
liftIO $ ungetCommand ref cmdArg dropSession
throw Restart
let (cmd':args') = split (keepDelimsR $ condense $ whenElt isSpace) cmdArg let (cmd':args') = split (keepDelimsR $ condense $ whenElt isSpace) cmdArg
arg = concat args' arg = concat args'
@ -405,7 +403,7 @@ legacyInteractiveLoop symdbreq ref world = do
_ -> fatalError $ "unknown command: `" ++ cmd ++ "'" _ -> fatalError $ "unknown command: `" ++ cmd ++ "'"
liftIO $ putStr res >> putStrLn "OK" >> hFlush stdout liftIO $ putStr res >> putStrLn "OK" >> hFlush stdout
legacyInteractiveLoop symdbreq ref world legacyInteractiveLoop symdbreq world
globalCommands :: [String] -> Maybe String globalCommands :: [String] -> Maybe String
globalCommands [] = Nothing globalCommands [] = Nothing

View File

@ -1,13 +1,7 @@
{-# LANGUAGE DeriveDataTypeable, CPP #-} {-# LANGUAGE DeriveDataTypeable, CPP #-}
module Misc ( module Misc (
GHCModiError(..) SymDbReq
, Restart(..)
, UnGetLine
, emptyNewUnGetLine
, ungetCommand
, getCommand
, SymDbReq
, newSymDbReq , newSymDbReq
, getDb , getDb
, checkDb , checkDb
@ -26,37 +20,6 @@ import Language.Haskell.GhcMod.Internal
---------------------------------------------------------------- ----------------------------------------------------------------
data GHCModiError = CmdArg [String] deriving (Show, Typeable)
instance Exception GHCModiError
----------------------------------------------------------------
data Restart = Restart deriving (Show, Typeable)
instance Exception Restart
----------------------------------------------------------------
newtype UnGetLine = UnGetLine (IORef (Maybe String))
emptyNewUnGetLine :: IO UnGetLine
emptyNewUnGetLine = UnGetLine <$> newIORef Nothing
ungetCommand :: UnGetLine -> String -> IO ()
ungetCommand (UnGetLine ref) cmd = writeIORef ref (Just cmd)
getCommand :: UnGetLine -> IO String
getCommand (UnGetLine ref) = do
mcmd <- readIORef ref
case mcmd of
Nothing -> getLine
Just cmd -> do
writeIORef ref Nothing
return cmd
----------------------------------------------------------------
type SymDbReqAction = (Either GhcModError SymbolDb, GhcModLog) type SymDbReqAction = (Either GhcModError SymbolDb, GhcModLog)
data SymDbReq = SymDbReq (IORef (Async SymDbReqAction)) (IO SymDbReqAction) data SymDbReq = SymDbReq (IORef (Async SymDbReqAction)) (IO SymDbReqAction)