Fix merge conflict, dropdown-list no longer needed

This commit is contained in:
Alejandro Serrano 2014-08-14 18:02:58 +02:00
parent 8eeeacd58d
commit 890658f9cb
26 changed files with 219 additions and 110 deletions

View File

@ -18,6 +18,7 @@ module Language.Haskell.GhcMod (
-- * Monad Types -- * Monad Types
, GhcModT , GhcModT
, IOish , IOish
, GhcModError(..)
-- * Monad utilities -- * Monad utilities
, runGhcModT , runGhcModT
, withOptions , withOptions

View File

@ -11,14 +11,16 @@ module Language.Haskell.GhcMod.CabalApi (
) where ) where
import Language.Haskell.GhcMod.CabalConfig import Language.Haskell.GhcMod.CabalConfig
import Language.Haskell.GhcMod.Gap (benchmarkBuildInfo, benchmarkTargets, toModuleString) import Language.Haskell.GhcMod.Gap (benchmarkBuildInfo, benchmarkTargets,
toModuleString)
import Language.Haskell.GhcMod.GhcPkg import Language.Haskell.GhcMod.GhcPkg
import Language.Haskell.GhcMod.Types import Language.Haskell.GhcMod.Types
import MonadUtils (MonadIO, liftIO)
import Control.Applicative ((<$>)) import Control.Applicative ((<$>))
import qualified Control.Exception as E import qualified Control.Exception as E
import Control.Monad (filterM) import Control.Monad (filterM)
import CoreMonad (liftIO) import Control.Monad.Error.Class (Error, MonadError(..))
import Data.Maybe (maybeToList) import Data.Maybe (maybeToList)
import Data.Set (fromList, toList) import Data.Set (fromList, toList)
import Distribution.Package (Dependency(Dependency) import Distribution.Package (Dependency(Dependency)
@ -69,19 +71,21 @@ includeDirectories cdir wdir dirs = uniqueAndSort (extdirs ++ [cdir,wdir])
---------------------------------------------------------------- ----------------------------------------------------------------
-- | Parsing a cabal file and returns 'PackageDescription'. -- | Parse a cabal file and return a 'PackageDescription'.
-- 'IOException' is thrown if parsing fails. parseCabalFile :: (MonadIO m, Error e, MonadError e m)
parseCabalFile :: FilePath -> IO PackageDescription => FilePath
-> m PackageDescription
parseCabalFile file = do parseCabalFile file = do
cid <- getGHCId cid <- liftIO getGHCId
epgd <- readPackageDescription silent file epgd <- liftIO $ readPackageDescription silent file
case toPkgDesc cid epgd of case toPkgDesc cid epgd of
Left deps -> E.throwIO $ userError $ show deps ++ " are not installed" Left deps -> fail $ show deps ++ " are not installed"
Right (pd,_) -> if nullPkg pd Right (pd,_) -> if nullPkg pd
then E.throwIO $ userError $ file ++ " is broken" then fail $ file ++ " is broken"
else return pd else return pd
where where
toPkgDesc cid = finalizePackageDescription [] (const True) buildPlatform cid [] toPkgDesc cid =
finalizePackageDescription [] (const True) buildPlatform cid []
nullPkg pd = name == "" nullPkg pd = name == ""
where where
PackageName name = C.pkgName (P.package pd) PackageName name = C.pkgName (P.package pd)

View File

@ -4,7 +4,6 @@ module Language.Haskell.GhcMod.CaseSplit (
splits splits
) where ) where
import CoreMonad (liftIO)
import Data.List (find, intercalate) import Data.List (find, intercalate)
import Data.Maybe (isJust) import Data.Maybe (isJust)
import qualified Data.Text as T import qualified Data.Text as T

View File

@ -8,8 +8,10 @@ module Language.Haskell.GhcMod.Check (
import Control.Applicative ((<$>)) import Control.Applicative ((<$>))
import Language.Haskell.GhcMod.DynFlags import Language.Haskell.GhcMod.DynFlags
import qualified Language.Haskell.GhcMod.Gap as Gap import qualified Language.Haskell.GhcMod.Gap as Gap
import qualified GHC as G
import Language.Haskell.GhcMod.Logger import Language.Haskell.GhcMod.Logger
import Language.Haskell.GhcMod.Monad (IOish, GhcModT, withErrorHandler) import Language.Haskell.GhcMod.Monad (IOish, GhcModT, withErrorHandler
, overrideGhcUserOptions)
import Language.Haskell.GhcMod.Target (setTargetFiles) import Language.Haskell.GhcMod.Target (setTargetFiles)
---------------------------------------------------------------- ----------------------------------------------------------------
@ -34,8 +36,9 @@ checkSyntax files = withErrorHandler sessionName $
check :: IOish m check :: IOish m
=> [FilePath] -- ^ The target files. => [FilePath] -- ^ The target files.
-> GhcModT m (Either String String) -> GhcModT m (Either String String)
check fileNames = check fileNames = overrideGhcUserOptions $ \ghcOpts ->
withLogger (setAllWaringFlags . setNoMaxRelevantBindings) $ withLogger (setAllWaringFlags . setNoMaxRelevantBindings . Gap.setWarnTypedHoles . Gap.setDeferTypeErrors) $ do
_ <- G.setSessionDynFlags =<< addCmdOpts ghcOpts =<< G.getSessionDynFlags
setTargetFiles fileNames setTargetFiles fileNames
---------------------------------------------------------------- ----------------------------------------------------------------

View File

@ -1,7 +1,6 @@
module Language.Haskell.GhcMod.Debug (debugInfo, rootInfo) where module Language.Haskell.GhcMod.Debug (debugInfo, rootInfo) where
import Control.Applicative ((<$>)) import Control.Applicative ((<$>))
import CoreMonad (liftIO)
import Data.List (intercalate) import Data.List (intercalate)
import Data.Maybe (isJust, fromJust) import Data.Maybe (isJust, fromJust)
import Language.Haskell.GhcMod.Convert import Language.Haskell.GhcMod.Convert
@ -30,10 +29,10 @@ debugInfo = cradle >>= \c -> convert' =<< do
] ]
where where
simpleCompilerOption = options >>= \op -> simpleCompilerOption = options >>= \op ->
return $ CompilerOptions (ghcOpts op) [] [] return $ CompilerOptions (ghcUserOptions op) [] []
fromCabalFile c = options >>= \opts -> liftIO $ do fromCabalFile c = options >>= \opts -> do
pkgDesc <- parseCabalFile $ fromJust $ cradleCabalFile c pkgDesc <- parseCabalFile $ fromJust $ cradleCabalFile c
getCompilerOptions (ghcOpts opts) c pkgDesc liftIO $ getCompilerOptions (ghcUserOptions opts) c pkgDesc
---------------------------------------------------------------- ----------------------------------------------------------------

View File

@ -88,8 +88,8 @@ withCmdFlags :: GhcMonad m => [GHCOption] -> m a -> m a
withCmdFlags flags body = G.gbracket setup teardown (\_ -> body) withCmdFlags flags body = G.gbracket setup teardown (\_ -> body)
where where
setup = do setup = do
dflags <- G.getSessionDynFlags >>= addCmdOpts flags dflags <- G.getSessionDynFlags
void $ G.setSessionDynFlags dflags void $ G.setSessionDynFlags =<< addCmdOpts flags dflags
return dflags return dflags
teardown = void . G.setSessionDynFlags teardown = void . G.setSessionDynFlags

View File

@ -20,7 +20,6 @@ import Language.Haskell.GhcMod.Convert
import Language.Haskell.GhcMod.Monad import Language.Haskell.GhcMod.Monad
import Language.Haskell.GhcMod.SrcUtils import Language.Haskell.GhcMod.SrcUtils
import Language.Haskell.GhcMod.Types import Language.Haskell.GhcMod.Types
import CoreMonad (liftIO)
import Outputable (PprStyle) import Outputable (PprStyle)
import qualified Type as Ty import qualified Type as Ty
import qualified HsBinds as Ty import qualified HsBinds as Ty
@ -119,11 +118,11 @@ getSignature modSum lineNo colNo = do
G.DataFamily -> Data G.DataFamily -> Data
#endif #endif
#if __GLASGOW_HASKELL__ >= 706 #if __GLASGOW_HASKELL__ >= 706
getTyFamVarName = \x -> case x of getTyFamVarName x = case x of
L _ (G.UserTyVar n) -> n L _ (G.UserTyVar n) -> n
L _ (G.KindedTyVar n _) -> n L _ (G.KindedTyVar n _) -> n
#else #else
getTyFamVarName = \x -> case x of -- In GHC 7.4, HsTyVarBndr's have an extra arg getTyFamVarName x = case x of -- In GHC 7.4, HsTyVarBndr's have an extra arg
L _ (G.UserTyVar n _) -> n L _ (G.UserTyVar n _) -> n
L _ (G.KindedTyVar n _ _) -> n L _ (G.KindedTyVar n _ _) -> n
#endif #endif
@ -170,7 +169,7 @@ initialBody' fname args = initialHead fname args ++ " = "
initialFamBody :: FnArgsInfo ty name => DynFlags -> PprStyle -> name -> [name] -> String initialFamBody :: FnArgsInfo ty name => DynFlags -> PprStyle -> name -> [name] -> String
initialFamBody dflag style name args = initialHead (getFnName dflag style name) initialFamBody dflag style name args = initialHead (getFnName dflag style name)
(map (\arg -> FnExplicitName (getFnName dflag style arg)) args) (map (FnExplicitName . getFnName dflag style) args)
++ " = ()" ++ " = ()"
initialHead :: String -> [FnArg] -> String initialHead :: String -> [FnArg] -> String
@ -299,7 +298,7 @@ findVar dflag style tcm tcs lineNo colNo =
then let Just (s,t) = tyInfo then let Just (s,t) = tyInfo
b = case others of -- If inside an App, we need parenthesis b = case others of -- If inside an App, we need parenthesis
[] -> False [] -> False
(L _ (G.HsApp (L _ a1) (L _ a2))):_ -> L _ (G.HsApp (L _ a1) (L _ a2)):_ ->
isSearchedVar i a1 || isSearchedVar i a2 isSearchedVar i a1 || isSearchedVar i a2
_ -> False _ -> False
in return $ Just (s, name, t, b) in return $ Just (s, name, t, b)
@ -340,9 +339,9 @@ auto file lineNo colNo = ghandle handler body
topLevel <- getEverythingInTopLevel minfo topLevel <- getEverythingInTopLevel minfo
let (f,pats) = getPatsForVariable tcs (lineNo,colNo) let (f,pats) = getPatsForVariable tcs (lineNo,colNo)
-- Remove self function to prevent recursion, and id to trim cases -- Remove self function to prevent recursion, and id to trim cases
filterFn = (\(n,_) -> let funName = G.getOccString n filterFn (n,_) = let funName = G.getOccString n
recName = G.getOccString (G.getName f) recName = G.getOccString (G.getName f)
in not $ funName `elem` recName:notWantedFuns) in funName `notElem` recName:notWantedFuns
-- Find without using other functions in top-level -- Find without using other functions in top-level
localBnds = M.unions $ map (\(L _ pat) -> getBindingsForPat pat) pats localBnds = M.unions $ map (\(L _ pat) -> getBindingsForPat pat) pats
lbn = filter filterFn (M.toList localBnds) lbn = filter filterFn (M.toList localBnds)

View File

@ -1,4 +1,4 @@
{-# LANGUAGE CPP, BangPatterns #-} {-# LANGUAGE CPP #-}
module Language.Haskell.GhcMod.Find module Language.Haskell.GhcMod.Find
#ifndef SPEC #ifndef SPEC
@ -19,7 +19,6 @@ import Control.Applicative ((<$>))
import Control.Exception (handle, SomeException(..)) import Control.Exception (handle, SomeException(..))
import Control.Monad (when, void) import Control.Monad (when, void)
import Control.Monad.Error.Class import Control.Monad.Error.Class
import CoreMonad (liftIO)
import Data.Function (on) import Data.Function (on)
import Data.List (groupBy, sort) import Data.List (groupBy, sort)
import Data.List.Split (splitOn) import Data.List.Split (splitOn)
@ -59,8 +58,14 @@ newtype SymbolDb = SymbolDb (Map Symbol [ModuleString])
---------------------------------------------------------------- ----------------------------------------------------------------
-- | When introducing incompatible changes to the 'symbolCache' file format
-- increment this version number.
symbolCacheVersion :: Integer
symbolCacheVersion = 0
-- | Filename of the symbol table cache file.
symbolCache :: String symbolCache :: String
symbolCache = "ghc-mod.cache" symbolCache = "ghc-mod-"++ show symbolCacheVersion ++".cache"
packageCache :: String packageCache :: String
packageCache = "package.cache" packageCache = "package.cache"
@ -89,6 +94,8 @@ lookupSym sym (SymbolDb db) = fromMaybe [] $ M.lookup sym db
loadSymbolDb :: IO SymbolDb loadSymbolDb :: IO SymbolDb
loadSymbolDb = SymbolDb <$> readSymbolDb loadSymbolDb = SymbolDb <$> readSymbolDb
-- | Returns the path to the currently running ghc-mod executable. With ghc<7.6
-- this is a guess but >=7.6 uses 'getExecutablePath'.
ghcModExecutable :: IO FilePath ghcModExecutable :: IO FilePath
#ifndef SPEC #ifndef SPEC
ghcModExecutable = do ghcModExecutable = do
@ -130,7 +137,6 @@ getSymbolCachePath = do
-- if the file does not exist or is invalid. -- if the file does not exist or is invalid.
-- The file name is printed. -- The file name is printed.
-- TODO: Before releaseing add a version number to the name of the cache file
dumpSymbol :: IOish m => GhcModT m String dumpSymbol :: IOish m => GhcModT m String
dumpSymbol = do dumpSymbol = do
dir <- getSymbolCachePath dir <- getSymbolCachePath
@ -144,7 +150,7 @@ dumpSymbol = do
writeSymbolCache :: FilePath writeSymbolCache :: FilePath
-> [(Symbol,[ModuleString])] -> [(Symbol,[ModuleString])]
-> IO () -> IO ()
writeSymbolCache cache sm = do writeSymbolCache cache sm =
void . withFile cache WriteMode $ \hdl -> void . withFile cache WriteMode $ \hdl ->
mapM (hPrint hdl) sm mapM (hPrint hdl) sm

View File

@ -21,10 +21,3 @@ goNext = liftIO . GE.throwIO $ userError "goNext"
-- | Run any one 'Ghc' monad. -- | Run any one 'Ghc' monad.
runAnyOne :: GhcMonad m => [m a] -> m a runAnyOne :: GhcMonad m => [m a] -> m a
runAnyOne = foldr (||>) goNext runAnyOne = foldr (||>) goNext
----------------------------------------------------------------
-- | Try the left 'GhcMonad' action. If 'IOException' occurs, try
-- the right 'GhcMonad' action.
(|||>) :: GhcMonad m => m a -> m a -> m a
x |||> y = x `GE.gcatch` (\(_ :: IOException) -> y)

View File

@ -44,12 +44,10 @@ module Language.Haskell.GhcMod.Internal (
, getCompilerMode , getCompilerMode
, setCompilerMode , setCompilerMode
, withOptions , withOptions
-- * 'Ghc' Choice -- * 'GhcMonad' Choice
, (||>) , (||>)
, goNext , goNext
, runAnyOne , runAnyOne
-- * 'GhcMonad' Choice
, (|||>)
) where ) where
import GHC.Paths (libdir) import GHC.Paths (libdir)

View File

@ -2,7 +2,6 @@ module Language.Haskell.GhcMod.Lint where
import Exception (ghandle) import Exception (ghandle)
import Control.Exception (SomeException(..)) import Control.Exception (SomeException(..))
import CoreMonad (liftIO)
import Language.Haskell.GhcMod.Logger (checkErrorPrefix) import Language.Haskell.GhcMod.Logger (checkErrorPrefix)
import Language.Haskell.GhcMod.Convert import Language.Haskell.GhcMod.Convert
import Language.Haskell.GhcMod.Monad import Language.Haskell.GhcMod.Monad

View File

@ -7,7 +7,6 @@ module Language.Haskell.GhcMod.Logger (
import Bag (Bag, bagToList) import Bag (Bag, bagToList)
import Control.Applicative ((<$>)) import Control.Applicative ((<$>))
import CoreMonad (liftIO)
import Data.IORef (IORef, newIORef, readIORef, writeIORef, modifyIORef) import Data.IORef (IORef, newIORef, readIORef, writeIORef, modifyIORef)
import Data.List (isPrefixOf) import Data.List (isPrefixOf)
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
@ -64,7 +63,7 @@ withLogger :: IOish m
-> GhcModT m (Either String String) -> GhcModT m (Either String String)
withLogger setDF body = ghandle sourceError $ do withLogger setDF body = ghandle sourceError $ do
logref <- liftIO newLogRef logref <- liftIO newLogRef
wflags <- filter ("-fno-warn" `isPrefixOf`) . ghcOpts <$> options wflags <- filter ("-fno-warn" `isPrefixOf`) . ghcUserOptions <$> options
withDynFlags (setLogger logref . setDF) $ withDynFlags (setLogger logref . setDF) $
withCmdFlags wflags $ do withCmdFlags wflags $ do
body body
@ -106,7 +105,15 @@ ppMsg spn sev dflag style msg = prefix ++ cts
(line,col,_,_) <- Gap.getSrcSpan spn (line,col,_,_) <- Gap.getSrcSpan spn
file <- normalise <$> Gap.getSrcFile spn file <- normalise <$> Gap.getSrcFile spn
let severityCaption = Gap.showSeverityCaption sev let severityCaption = Gap.showSeverityCaption sev
return $ file ++ ":" ++ show line ++ ":" ++ show col ++ ":" ++ severityCaption pref0
| typeWarning1 `isPrefixOf` cts ||
typeWarning2 `isPrefixOf` cts = file ++ ":" ++ show line ++ ":" ++ show col ++ ":"
| otherwise = file ++ ":" ++ show line ++ ":" ++ show col ++ ":" ++ severityCaption
return pref0
-- DeferTypeErrors turns a type error to a warning.
-- So, let's turns it the error again.
typeWarning1 = "Couldn't match expected type"
typeWarning2 = "Couldn't match type"
checkErrorPrefix :: String checkErrorPrefix :: String
checkErrorPrefix = "Dummy:0:0:Error:" checkErrorPrefix = "Dummy:0:0:Error:"

View File

@ -1,7 +1,6 @@
{-# LANGUAGE CPP, GeneralizedNewtypeDeriving, FlexibleInstances #-} {-# LANGUAGE CPP, GeneralizedNewtypeDeriving, FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts, MultiParamTypeClasses, RankNTypes #-} {-# LANGUAGE FlexibleContexts, MultiParamTypeClasses, RankNTypes #-}
{-# LANGUAGE TypeFamilies, UndecidableInstances, RecordWildCards #-} {-# LANGUAGE TypeFamilies, UndecidableInstances, RecordWildCards #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_GHC -fno-warn-orphans #-}
module Language.Haskell.GhcMod.Monad ( module Language.Haskell.GhcMod.Monad (
@ -23,15 +22,18 @@ module Language.Haskell.GhcMod.Monad (
-- ** Conversion -- ** Conversion
, toGhcModT , toGhcModT
-- ** Accessing 'GhcModEnv' and 'GhcModState' -- ** Accessing 'GhcModEnv' and 'GhcModState'
, gmsGet
, gmsPut
, options , options
, cradle , cradle
, getCompilerMode , getCompilerMode
, setCompilerMode , setCompilerMode
, withOptions , withOptions
-- ** Exporting convenient modules , withTempSession
, overrideGhcUserOptions
-- ** Re-exporting convenient stuff
, liftIO
, module Control.Monad.Reader.Class , module Control.Monad.Reader.Class
, module Control.Monad.Writer.Class
, module Control.Monad.State.Class
, module Control.Monad.Journal.Class , module Control.Monad.Journal.Class
) where ) where
@ -57,7 +59,7 @@ import Exception
import GHC import GHC
import qualified GHC as G import qualified GHC as G
import GHC.Paths (libdir) import GHC.Paths (libdir)
import GhcMonad import GhcMonad hiding (withTempSession)
#if __GLASGOW_HASKELL__ <= 702 #if __GLASGOW_HASKELL__ <= 702
import HscTypes import HscTypes
#endif #endif
@ -85,15 +87,16 @@ import Control.Monad.Trans.Control (MonadBaseControl(..), StM, liftBaseWith,
import Control.Monad.Trans.Class import Control.Monad.Trans.Class
import Control.Monad.Reader.Class import Control.Monad.Reader.Class
import Control.Monad.Writer.Class import Control.Monad.Writer.Class (MonadWriter)
import Control.Monad.State.Class import Control.Monad.State.Class (MonadState(..))
import Control.Monad.Error (Error(..), MonadError, ErrorT, runErrorT) import Control.Monad.Error (MonadError, ErrorT, runErrorT)
import Control.Monad.Reader (ReaderT, runReaderT) import Control.Monad.Reader (ReaderT, runReaderT)
import Control.Monad.State.Strict (StateT, runStateT) import Control.Monad.State.Strict (StateT, runStateT)
import Control.Monad.Trans.Journal (JournalT, runJournalT) import Control.Monad.Trans.Journal (JournalT, runJournalT)
#ifdef MONADIO_INSTANCES #ifdef MONADIO_INSTANCES
import Control.Monad.Trans.Maybe (MaybeT) import Control.Monad.Trans.Maybe (MaybeT)
import Control.Monad.Error (Error(..))
#endif #endif
import Control.Monad.Journal.Class import Control.Monad.Journal.Class
@ -122,16 +125,6 @@ data CompilerMode = Simple | Intelligent deriving (Eq,Show,Read)
defaultState :: GhcModState defaultState :: GhcModState
defaultState = GhcModState Simple defaultState = GhcModState Simple
data GhcModError = GMENoMsg
| GMEString String
| GMECabal
| GMEGhc
deriving (Eq,Show,Read)
instance Error GhcModError where
noMsg = GMENoMsg
strMsg = GMEString
---------------------------------------------------------------- ----------------------------------------------------------------
-- | A constraint alias (-XConstraintKinds) to make functions dealing with -- | A constraint alias (-XConstraintKinds) to make functions dealing with
@ -163,15 +156,21 @@ newtype GhcModT m a = GhcModT {
#if DIFFERENT_MONADIO #if DIFFERENT_MONADIO
, Control.Monad.IO.Class.MonadIO , Control.Monad.IO.Class.MonadIO
#endif #endif
, MonadReader GhcModEnv , MonadReader GhcModEnv -- TODO: make MonadReader instance
-- pass-through like MonadState
, MonadWriter w , MonadWriter w
, MonadState GhcModState
, MonadError GhcModError , MonadError GhcModError
) )
instance MonadTrans GhcModT where instance MonadTrans GhcModT where
lift = GhcModT . lift . lift . lift . lift lift = GhcModT . lift . lift . lift . lift
instance MonadState s m => MonadState s (GhcModT m) where
get = GhcModT $ lift $ lift $ lift get
put = GhcModT . lift . lift . lift . put
state = GhcModT . lift . lift . lift . state
#if MONADIO_INSTANCES #if MONADIO_INSTANCES
instance MonadIO m => MonadIO (StateT s m) where instance MonadIO m => MonadIO (StateT s m) where
liftIO = lift . liftIO liftIO = lift . liftIO
@ -194,7 +193,7 @@ instance MonadIO m => MonadIO (MaybeT m) where
-- | Initialize the 'DynFlags' relating to the compilation of a single -- | Initialize the 'DynFlags' relating to the compilation of a single
-- file or GHC session according to the 'Cradle' and 'Options' -- file or GHC session according to the 'Cradle' and 'Options'
-- provided. -- provided.
initializeFlagsWithCradle :: GhcMonad m initializeFlagsWithCradle :: (GhcMonad m, MonadError GhcModError m)
=> Options => Options
-> Cradle -> Cradle
-> m () -> m ()
@ -204,9 +203,9 @@ initializeFlagsWithCradle opt c
where where
mCradleFile = cradleCabalFile c mCradleFile = cradleCabalFile c
cabal = isJust mCradleFile cabal = isJust mCradleFile
ghcopts = ghcOpts opt ghcopts = ghcUserOptions opt
withCabal = do withCabal = do
pkgDesc <- liftIO $ parseCabalFile $ fromJust mCradleFile pkgDesc <- parseCabalFile $ fromJust mCradleFile
compOpts <- liftIO $ getCompilerOptions ghcopts c pkgDesc compOpts <- liftIO $ getCompilerOptions ghcopts c pkgDesc
initSession CabalPkg opt compOpts initSession CabalPkg opt compOpts
withSandbox = initSession SingleFile opt compOpts withSandbox = initSession SingleFile opt compOpts
@ -253,7 +252,7 @@ runGhcModT :: IOish m
-> m (Either GhcModError a, GhcModLog) -> m (Either GhcModError a, GhcModLog)
runGhcModT opt action = do runGhcModT opt action = do
env <- liftBase $ newGhcModEnv opt =<< getCurrentDirectory env <- liftBase $ newGhcModEnv opt =<< getCurrentDirectory
first (fmap fst) <$> (runGhcModT' env defaultState $ do first (fst <$>) <$> (runGhcModT' env defaultState $ do
dflags <- getSessionDynFlags dflags <- getSessionDynFlags
defaultCleanupHandler dflags $ do defaultCleanupHandler dflags $ do
initializeFlagsWithCradle opt (gmCradle env) initializeFlagsWithCradle opt (gmCradle env)
@ -271,9 +270,9 @@ runGhcModT' :: IOish m
-> m (Either GhcModError (a, GhcModState), GhcModLog) -> m (Either GhcModError (a, GhcModState), GhcModLog)
runGhcModT' r s a = do runGhcModT' r s a = do
(res, w') <- (res, w') <-
flip runReaderT r $ runJournalT $ runErrorT $ flip runStateT s flip runReaderT r $ runJournalT $ runErrorT $
$ (unGhcModT $ initGhcMonad (Just libdir) >> a) runStateT (unGhcModT $ initGhcMonad (Just libdir) >> a) s
return $ (res, w') return (res, w')
---------------------------------------------------------------- ----------------------------------------------------------------
withErrorHandler :: IOish m => String -> GhcModT m a -> GhcModT m a withErrorHandler :: IOish m => String -> GhcModT m a -> GhcModT m a
@ -285,6 +284,28 @@ withErrorHandler label = ghandle ignore
hPrint stderr e hPrint stderr e
exitSuccess exitSuccess
-- | Make a copy of the 'gmGhcSession' IORef, run the action and restore the
-- original 'HscEnv'.
withTempSession :: IOish m => GhcModT m a -> GhcModT m a
withTempSession action = do
session <- gmGhcSession <$> ask
savedHscEnv <- liftIO $ readIORef session
a <- action
liftIO $ writeIORef session savedHscEnv
return a
-- | This is a very ugly workaround don't use it.
overrideGhcUserOptions :: IOish m => ([GHCOption] -> GhcModT m b) -> GhcModT m b
overrideGhcUserOptions action = withTempSession $ do
env <- ask
opt <- options
let ghcOpts = ghcUserOptions opt
opt' = opt { ghcUserOptions = [] }
initializeFlagsWithCradle opt' (gmCradle env)
action ghcOpts
-- | This is only a transitional mechanism don't use it for new code. -- | This is only a transitional mechanism don't use it for new code.
toGhcModT :: IOish m => Ghc a -> GhcModT m a toGhcModT :: IOish m => Ghc a -> GhcModT m a
toGhcModT a = do toGhcModT a = do
@ -293,17 +314,23 @@ toGhcModT a = do
---------------------------------------------------------------- ----------------------------------------------------------------
gmsGet :: IOish m => GhcModT m GhcModState
gmsGet = GhcModT get
gmsPut :: IOish m => GhcModState -> GhcModT m ()
gmsPut = GhcModT . put
options :: IOish m => GhcModT m Options options :: IOish m => GhcModT m Options
options = gmOptions <$> ask options = gmOptions <$> ask
cradle :: IOish m => GhcModT m Cradle cradle :: IOish m => GhcModT m Cradle
cradle = gmCradle <$> ask cradle = gmCradle <$> ask
getCompilerMode :: (Functor m, MonadState GhcModState m) => m CompilerMode getCompilerMode :: IOish m => GhcModT m CompilerMode
getCompilerMode = gmCompilerMode <$> get getCompilerMode = gmCompilerMode <$> gmsGet
setCompilerMode :: MonadState GhcModState m => CompilerMode -> m () setCompilerMode :: IOish m => CompilerMode -> GhcModT m ()
setCompilerMode mode = (\s -> put s { gmCompilerMode = mode } ) =<< get setCompilerMode mode = (\s -> gmsPut s { gmCompilerMode = mode } ) =<< gmsGet
---------------------------------------------------------------- ----------------------------------------------------------------

View File

@ -1,6 +1,5 @@
module Language.Haskell.GhcMod.PkgDoc (pkgDoc) where module Language.Haskell.GhcMod.PkgDoc (pkgDoc) where
import CoreMonad (liftIO)
import Language.Haskell.GhcMod.Types import Language.Haskell.GhcMod.Types
import Language.Haskell.GhcMod.GhcPkg import Language.Haskell.GhcMod.GhcPkg
import Language.Haskell.GhcMod.Monad import Language.Haskell.GhcMod.Monad

View File

@ -15,7 +15,7 @@ setTargetFiles :: IOish m => [FilePath] -> GhcModT m ()
setTargetFiles files = do setTargetFiles files = do
targets <- forM files $ \file -> G.guessTarget file Nothing targets <- forM files $ \file -> G.guessTarget file Nothing
G.setTargets targets G.setTargets targets
mode <- gmCompilerMode <$> get mode <- getCompilerMode
if mode == Intelligent then if mode == Intelligent then
loadTargets Intelligent loadTargets Intelligent
else do else do

View File

@ -2,9 +2,22 @@ module Language.Haskell.GhcMod.Types where
import Data.List (intercalate) import Data.List (intercalate)
import qualified Data.Map as M import qualified Data.Map as M
import Control.Monad.Error (Error(..))
import PackageConfig (PackageConfig) import PackageConfig (PackageConfig)
-- |
data GhcModError = GMENoMsg
-- ^ Unknown error
| GMEString String
-- ^ Some Error with a message. These are produced mostly by
-- 'fail' calls on GhcModT.
deriving (Eq,Show,Read)
instance Error GhcModError where
noMsg = GMENoMsg
strMsg = GMEString
-- | Output style. -- | Output style.
data OutputStyle = LispStyle -- ^ S expression style. data OutputStyle = LispStyle -- ^ S expression style.
| PlainStyle -- ^ Plain textstyle. | PlainStyle -- ^ Plain textstyle.
@ -15,7 +28,8 @@ newtype LineSeparator = LineSeparator String
data Options = Options { data Options = Options {
outputStyle :: OutputStyle outputStyle :: OutputStyle
, hlintOpts :: [String] , hlintOpts :: [String]
, ghcOpts :: [GHCOption] -- | GHC command line options set on the @ghc-mod@ command line
, ghcUserOptions:: [GHCOption]
-- | If 'True', 'browse' also returns operators. -- | If 'True', 'browse' also returns operators.
, operators :: Bool , operators :: Bool
-- | If 'True', 'browse' also returns types. -- | If 'True', 'browse' also returns types.
@ -31,7 +45,7 @@ defaultOptions :: Options
defaultOptions = Options { defaultOptions = Options {
outputStyle = PlainStyle outputStyle = PlainStyle
, hlintOpts = [] , hlintOpts = []
, ghcOpts = [] , ghcUserOptions= []
, operators = False , operators = False
, detailed = False , detailed = False
, qualified = False , qualified = False

View File

@ -133,6 +133,7 @@ Executable ghc-modi
Default-Language: Haskell2010 Default-Language: Haskell2010
Main-Is: GHCModi.hs Main-Is: GHCModi.hs
Other-Modules: Paths_ghc_mod Other-Modules: Paths_ghc_mod
Utils
GHC-Options: -Wall -threaded GHC-Options: -Wall -threaded
Default-Extensions: ConstraintKinds, FlexibleContexts Default-Extensions: ConstraintKinds, FlexibleContexts
HS-Source-Dirs: src HS-Source-Dirs: src

View File

@ -63,8 +63,11 @@ argspec = [ Option "l" ["tolisp"]
(ReqArg (\h opts -> opts { hlintOpts = h : hlintOpts opts }) "hlintOpt") (ReqArg (\h opts -> opts { hlintOpts = h : hlintOpts opts }) "hlintOpt")
"hlint options" "hlint options"
, Option "g" ["ghcOpt"] , Option "g" ["ghcOpt"]
(ReqArg (\g opts -> opts { ghcOpts = g : ghcOpts opts }) "ghcOpt") (ReqArg (\g opts -> opts { ghcUserOptions = g : ghcUserOptions opts }) "ghcOpt")
"GHC options" "GHC options"
, Option "v" ["verbose"]
(NoArg (\opts -> opts { ghcUserOptions = "-v" : ghcUserOptions opts }))
"verbose"
, Option "o" ["operators"] , Option "o" ["operators"]
(NoArg (\opts -> opts { operators = True })) (NoArg (\opts -> opts { operators = True }))
"print operators, too" "print operators, too"
@ -138,7 +141,8 @@ main = flip E.catches handlers $ do
cmd -> E.throw (NoSuchCommand cmd) cmd -> E.throw (NoSuchCommand cmd)
case res of case res of
Right s -> putStr s Right s -> putStr s
Left e -> error $ show e Left (GMENoMsg) -> hPutStrLn stderr "Unknown error"
Left (GMEString msg) -> hPutStrLn stderr msg
where where
handlers = [Handler (handleThenExit handler1), Handler (handleThenExit handler2)] handlers = [Handler (handleThenExit handler1), Handler (handleThenExit handler2)]
handleThenExit handler e = handler e >> exitFailure handleThenExit handler e = handler e >> exitFailure

View File

@ -39,6 +39,8 @@ import System.Directory (setCurrentDirectory)
import System.Environment (getArgs) import System.Environment (getArgs)
import System.IO (hFlush,stdout) import System.IO (hFlush,stdout)
import Utils
---------------------------------------------------------------- ----------------------------------------------------------------
type Logger = IO String type Logger = IO String
@ -56,7 +58,7 @@ argspec = [ Option "b" ["boundary"]
(NoArg (\opts -> opts { outputStyle = LispStyle })) (NoArg (\opts -> opts { outputStyle = LispStyle }))
"print as a list of Lisp" "print as a list of Lisp"
, Option "g" [] , Option "g" []
(ReqArg (\s opts -> opts { ghcOpts = s : ghcOpts opts }) "flag") "specify a ghc flag" (ReqArg (\s opts -> opts { ghcUserOptions = s : ghcUserOptions opts }) "flag") "specify a ghc flag"
] ]
usage :: String usage :: String
@ -231,7 +233,7 @@ showInfo :: IOish m
-> FilePath -> FilePath
-> GhcModT m (String, Bool, Set FilePath) -> GhcModT m (String, Bool, Set FilePath)
showInfo set fileArg = do showInfo set fileArg = do
let [file, expr] = words fileArg let [file, expr] = splitN 2 fileArg
set' <- newFileSet set file set' <- newFileSet set file
ret <- info file expr ret <- info file expr
return (ret, True, set') return (ret, True, set')
@ -241,7 +243,7 @@ showType :: IOish m
-> FilePath -> FilePath
-> GhcModT m (String, Bool, Set FilePath) -> GhcModT m (String, Bool, Set FilePath)
showType set fileArg = do showType set fileArg = do
let [file, line, column] = words fileArg let [file, line, column] = splitN 3 fileArg
set' <- newFileSet set file set' <- newFileSet set file
ret <- types file (read line) (read column) ret <- types file (read line) (read column)
return (ret, True, set') return (ret, True, set')
@ -251,7 +253,7 @@ doSplit :: IOish m
-> FilePath -> FilePath
-> GhcModT m (String, Bool, Set FilePath) -> GhcModT m (String, Bool, Set FilePath)
doSplit set fileArg = do doSplit set fileArg = do
let [file, line, column] = words fileArg let [file, line, column] = splitN 3 fileArg
set' <- newFileSet set file set' <- newFileSet set file
ret <- splits file (read line) (read column) ret <- splits file (read line) (read column)
return (ret, True, set') return (ret, True, set')
@ -261,7 +263,7 @@ doSig :: IOish m
-> FilePath -> FilePath
-> GhcModT m (String, Bool, Set FilePath) -> GhcModT m (String, Bool, Set FilePath)
doSig set fileArg = do doSig set fileArg = do
let [file, line, column] = words fileArg let [file, line, column] = splitN 3 fileArg
set' <- newFileSet set file set' <- newFileSet set file
ret <- sig file (read line) (read column) ret <- sig file (read line) (read column)
return (ret, True, set') return (ret, True, set')
@ -271,7 +273,7 @@ doRefine :: IOish m
-> FilePath -> FilePath
-> GhcModT m (String, Bool, Set FilePath) -> GhcModT m (String, Bool, Set FilePath)
doRefine set fileArg = do doRefine set fileArg = do
let [file, line, column, expr] = words fileArg let [file, line, column, expr] = splitN 4 fileArg
set' <- newFileSet set file set' <- newFileSet set file
ret <- refine file (read line) (read column) expr ret <- refine file (read line) (read column) expr
return (ret, True, set') return (ret, True, set')
@ -281,7 +283,7 @@ doAuto :: IOish m
-> FilePath -> FilePath
-> GhcModT m (String, Bool, Set FilePath) -> GhcModT m (String, Bool, Set FilePath)
doAuto set fileArg = do doAuto set fileArg = do
let [file, line, column] = words fileArg let [file, line, column] = splitN 3 fileArg
set' <- newFileSet set file set' <- newFileSet set file
ret <- auto file (read line) (read column) ret <- auto file (read line) (read column)
return (ret, True, set') return (ret, True, set')

27
src/Utils.hs Normal file
View File

@ -0,0 +1,27 @@
module Utils where
-- |
--
-- >>> split "foo bar baz"
-- ["foo","bar baz"]
-- >>> split "foo bar baz"
-- ["foo","bar baz"]
split :: String -> [String]
split xs = [ys, dropWhile isSpace zs]
where
isSpace = (== ' ')
(ys,zs) = break isSpace xs
-- |
--
-- >>> splitN 0 "foo bar baz"
-- ["foo","bar baz"]
-- >>> splitN 2 "foo bar baz"
-- ["foo","bar baz"]
-- >>> splitN 3 "foo bar baz"
-- ["foo","bar","baz"]
splitN :: Int -> String -> [String]
splitN n xs
| n <= 2 = split xs
| otherwise = let [ys,zs] = split xs
in ys : splitN (n - 1) zs

View File

@ -13,6 +13,7 @@ import System.Directory
import System.FilePath import System.FilePath
import Dir import Dir
import TestUtils
import Config (cProjectVersionInt) -- ghc version import Config (cProjectVersionInt) -- ghc version
@ -23,14 +24,16 @@ spec :: Spec
spec = do spec = do
describe "parseCabalFile" $ do describe "parseCabalFile" $ do
it "throws an exception if the cabal file is broken" $ do it "throws an exception if the cabal file is broken" $ do
parseCabalFile "test/data/broken-cabal/broken.cabal" `shouldThrow` (\(_::IOException) -> True) shouldReturnError $
runD' $ parseCabalFile "test/data/broken-cabal/broken.cabal"
describe "getCompilerOptions" $ do describe "getCompilerOptions" $ do
it "gets necessary CompilerOptions" $ do it "gets necessary CompilerOptions" $ do
cwd <- getCurrentDirectory cwd <- getCurrentDirectory
withDirectory "test/data/subdir1/subdir2" $ \dir -> do withDirectory "test/data/subdir1/subdir2" $ \dir -> do
cradle <- findCradle cradle <- findCradle
pkgDesc <- parseCabalFile $ fromJust $ cradleCabalFile cradle pkgDesc <- runD $ parseCabalFile $ fromJust $ cradleCabalFile cradle
res <- getCompilerOptions [] cradle pkgDesc res <- getCompilerOptions [] cradle pkgDesc
let res' = res { let res' = res {
ghcOptions = ghcOptions res ghcOptions = ghcOptions res
@ -45,18 +48,18 @@ spec = do
describe "cabalDependPackages" $ do describe "cabalDependPackages" $ do
it "extracts dependent packages" $ do it "extracts dependent packages" $ do
pkgs <- cabalDependPackages . cabalAllBuildInfo <$> parseCabalFile "test/data/cabalapi.cabal" pkgs <- cabalDependPackages . cabalAllBuildInfo <$> runD (parseCabalFile "test/data/cabalapi.cabal")
pkgs `shouldBe` ["Cabal","base","template-haskell"] pkgs `shouldBe` ["Cabal","base","template-haskell"]
describe "cabalSourceDirs" $ do describe "cabalSourceDirs" $ do
it "extracts all hs-source-dirs" $ do it "extracts all hs-source-dirs" $ do
dirs <- cabalSourceDirs . cabalAllBuildInfo <$> parseCabalFile "test/data/check-test-subdir/check-test-subdir.cabal" dirs <- cabalSourceDirs . cabalAllBuildInfo <$> runD (parseCabalFile "test/data/check-test-subdir/check-test-subdir.cabal")
dirs `shouldBe` ["src", "test"] dirs `shouldBe` ["src", "test"]
it "extracts all hs-source-dirs including \".\"" $ do it "extracts all hs-source-dirs including \".\"" $ do
dirs <- cabalSourceDirs . cabalAllBuildInfo <$> parseCabalFile "test/data/cabalapi.cabal" dirs <- cabalSourceDirs . cabalAllBuildInfo <$> runD (parseCabalFile "test/data/cabalapi.cabal")
dirs `shouldBe` [".", "test"] dirs `shouldBe` [".", "test"]
describe "cabalAllBuildInfo" $ do describe "cabalAllBuildInfo" $ do
it "extracts build info" $ do it "extracts build info" $ do
info <- cabalAllBuildInfo <$> parseCabalFile "test/data/cabalapi.cabal" info <- cabalAllBuildInfo <$> runD (parseCabalFile "test/data/cabalapi.cabal")
show info `shouldBe` "[BuildInfo {buildable = True, buildTools = [], cppOptions = [], ccOptions = [], ldOptions = [], pkgconfigDepends = [], frameworks = [], cSources = [], hsSourceDirs = [\".\"], otherModules = [ModuleName [\"Browse\"],ModuleName [\"CabalApi\"],ModuleName [\"Cabal\"],ModuleName [\"CabalDev\"],ModuleName [\"Check\"],ModuleName [\"ErrMsg\"],ModuleName [\"Flag\"],ModuleName [\"GHCApi\"],ModuleName [\"GHCChoice\"],ModuleName [\"Gap\"],ModuleName [\"Info\"],ModuleName [\"Lang\"],ModuleName [\"Lint\"],ModuleName [\"List\"],ModuleName [\"Paths_ghc_mod\"],ModuleName [\"Types\"]], defaultLanguage = Nothing, otherLanguages = [], defaultExtensions = [], otherExtensions = [], oldExtensions = [], extraLibs = [], extraLibDirs = [], includeDirs = [], includes = [], installIncludes = [], options = [(GHC,[\"-Wall\"])], ghcProfOptions = [], ghcSharedOptions = [], customFieldsBI = [], targetBuildDepends = [Dependency (PackageName \"Cabal\") (UnionVersionRanges (ThisVersion (Version {versionBranch = [1,10], versionTags = []})) (LaterVersion (Version {versionBranch = [1,10], versionTags = []}))),Dependency (PackageName \"base\") (IntersectVersionRanges (UnionVersionRanges (ThisVersion (Version {versionBranch = [4,0], versionTags = []})) (LaterVersion (Version {versionBranch = [4,0], versionTags = []}))) (EarlierVersion (Version {versionBranch = [5], versionTags = []}))),Dependency (PackageName \"template-haskell\") AnyVersion]},BuildInfo {buildable = True, buildTools = [], cppOptions = [], ccOptions = [], ldOptions = [], pkgconfigDepends = [], frameworks = [], cSources = [], hsSourceDirs = [\"test\",\".\"], otherModules = [ModuleName [\"Expectation\"],ModuleName [\"BrowseSpec\"],ModuleName [\"CabalApiSpec\"],ModuleName [\"FlagSpec\"],ModuleName [\"LangSpec\"],ModuleName [\"LintSpec\"],ModuleName [\"ListSpec\"]], defaultLanguage = Nothing, otherLanguages = [], defaultExtensions = [], otherExtensions = [], oldExtensions = [], extraLibs = [], extraLibDirs = [], includeDirs = [], includes = [], installIncludes = [], options = [], ghcProfOptions = [], ghcSharedOptions = [], customFieldsBI = [], targetBuildDepends = [Dependency (PackageName \"Cabal\") (UnionVersionRanges (ThisVersion (Version {versionBranch = [1,10], versionTags = []})) (LaterVersion (Version {versionBranch = [1,10], versionTags = []}))),Dependency (PackageName \"base\") (IntersectVersionRanges (UnionVersionRanges (ThisVersion (Version {versionBranch = [4,0], versionTags = []})) (LaterVersion (Version {versionBranch = [4,0], versionTags = []}))) (EarlierVersion (Version {versionBranch = [5], versionTags = []})))]}]" show info `shouldBe` "[BuildInfo {buildable = True, buildTools = [], cppOptions = [], ccOptions = [], ldOptions = [], pkgconfigDepends = [], frameworks = [], cSources = [], hsSourceDirs = [\".\"], otherModules = [ModuleName [\"Browse\"],ModuleName [\"CabalApi\"],ModuleName [\"Cabal\"],ModuleName [\"CabalDev\"],ModuleName [\"Check\"],ModuleName [\"ErrMsg\"],ModuleName [\"Flag\"],ModuleName [\"GHCApi\"],ModuleName [\"GHCChoice\"],ModuleName [\"Gap\"],ModuleName [\"Info\"],ModuleName [\"Lang\"],ModuleName [\"Lint\"],ModuleName [\"List\"],ModuleName [\"Paths_ghc_mod\"],ModuleName [\"Types\"]], defaultLanguage = Nothing, otherLanguages = [], defaultExtensions = [], otherExtensions = [], oldExtensions = [], extraLibs = [], extraLibDirs = [], includeDirs = [], includes = [], installIncludes = [], options = [(GHC,[\"-Wall\"])], ghcProfOptions = [], ghcSharedOptions = [], customFieldsBI = [], targetBuildDepends = [Dependency (PackageName \"Cabal\") (UnionVersionRanges (ThisVersion (Version {versionBranch = [1,10], versionTags = []})) (LaterVersion (Version {versionBranch = [1,10], versionTags = []}))),Dependency (PackageName \"base\") (IntersectVersionRanges (UnionVersionRanges (ThisVersion (Version {versionBranch = [4,0], versionTags = []})) (LaterVersion (Version {versionBranch = [4,0], versionTags = []}))) (EarlierVersion (Version {versionBranch = [5], versionTags = []}))),Dependency (PackageName \"template-haskell\") AnyVersion]},BuildInfo {buildable = True, buildTools = [], cppOptions = [], ccOptions = [], ldOptions = [], pkgconfigDepends = [], frameworks = [], cSources = [], hsSourceDirs = [\"test\",\".\"], otherModules = [ModuleName [\"Expectation\"],ModuleName [\"BrowseSpec\"],ModuleName [\"CabalApiSpec\"],ModuleName [\"FlagSpec\"],ModuleName [\"LangSpec\"],ModuleName [\"LintSpec\"],ModuleName [\"ListSpec\"]], defaultLanguage = Nothing, otherLanguages = [], defaultExtensions = [], otherExtensions = [], oldExtensions = [], extraLibs = [], extraLibDirs = [], includeDirs = [], includes = [], installIncludes = [], options = [], ghcProfOptions = [], ghcSharedOptions = [], customFieldsBI = [], targetBuildDepends = [Dependency (PackageName \"Cabal\") (UnionVersionRanges (ThisVersion (Version {versionBranch = [1,10], versionTags = []})) (LaterVersion (Version {versionBranch = [1,10], versionTags = []}))),Dependency (PackageName \"base\") (IntersectVersionRanges (UnionVersionRanges (ThisVersion (Version {versionBranch = [4,0], versionTags = []})) (LaterVersion (Version {versionBranch = [4,0], versionTags = []}))) (EarlierVersion (Version {versionBranch = [5], versionTags = []})))]}]"

View File

@ -11,7 +11,9 @@ import TestUtils
main = do main = do
let sandboxes = [ "test/data", "test/data/check-packageid" let sandboxes = [ "test/data", "test/data/check-packageid"
, "test/data/duplicate-pkgver/" ] , "test/data/duplicate-pkgver/"
, "test/data/broken-cabal/"
]
genSandboxCfg dir = withDirectory dir $ \cwd -> do genSandboxCfg dir = withDirectory dir $ \cwd -> do
system ("sed 's|@CWD@|" ++ cwd ++ "|g' cabal.sandbox.config.in > cabal.sandbox.config") system ("sed 's|@CWD@|" ++ cwd ++ "|g' cabal.sandbox.config.in > cabal.sandbox.config")
pkgDirs = pkgDirs =

View File

@ -3,6 +3,7 @@ module MonadSpec where
import Test.Hspec import Test.Hspec
import Dir import Dir
import TestUtils
import Control.Applicative import Control.Applicative
import Control.Monad.Error.Class import Control.Monad.Error.Class
import Language.Haskell.GhcMod.Types import Language.Haskell.GhcMod.Types
@ -23,5 +24,9 @@ spec = do
describe "runGhcModT" $ describe "runGhcModT" $
it "complains if the cabal file fails to parse while a sandbox is present" $ withDirectory_ "test/data/broken-cabal" $ do it "complains if the cabal file fails to parse while a sandbox is present" $ withDirectory_ "test/data/broken-cabal" $ do
(a,_) <- runGhcModT defaultOptions (gmCradle <$> ask) shouldReturnError $ runD' (gmCradle <$> ask)
a `shouldSatisfy` (\(Left _) -> True)
describe "gmsGet/Put" $
it "work" $ do
(runD $ gmsPut (GhcModState Intelligent) >> gmsGet)
`shouldReturn` (GhcModState Intelligent)

View File

@ -1,10 +1,12 @@
module TestUtils ( module TestUtils (
run run
, runD , runD
, runD'
, runI , runI
, runID , runID
, runIsolatedGhcMod , runIsolatedGhcMod
, isolateCradle , isolateCradle
, shouldReturnError
, module Language.Haskell.GhcMod.Monad , module Language.Haskell.GhcMod.Monad
, module Language.Haskell.GhcMod.Types , module Language.Haskell.GhcMod.Types
) where ) where
@ -12,6 +14,8 @@ module TestUtils (
import Language.Haskell.GhcMod.Monad import Language.Haskell.GhcMod.Monad
import Language.Haskell.GhcMod.Types import Language.Haskell.GhcMod.Types
import Test.Hspec
isolateCradle :: IOish m => GhcModT m a -> GhcModT m a isolateCradle :: IOish m => GhcModT m a -> GhcModT m a
isolateCradle action = isolateCradle action =
local modifyEnv $ action local modifyEnv $ action
@ -42,3 +46,16 @@ run opt a = extract $ runGhcModT opt a
-- | Run GhcMod with default options -- | Run GhcMod with default options
runD :: GhcModT IO a -> IO a runD :: GhcModT IO a -> IO a
runD = extract . runGhcModT defaultOptions runD = extract . runGhcModT defaultOptions
runD' :: GhcModT IO a -> IO (Either GhcModError a, GhcModLog)
runD' = runGhcModT defaultOptions
shouldReturnError :: Show a
=> IO (Either GhcModError a, GhcModLog)
-> Expectation
shouldReturnError action = do
(a,_) <- action
a `shouldSatisfy` isLeft
where
isLeft (Left _) = True
isLeft _ = False