Fix merge conflict, dropdown-list no longer needed
This commit is contained in:
parent
8eeeacd58d
commit
890658f9cb
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
@ -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
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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:"
|
||||||
|
@ -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
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
27
src/Utils.hs
Normal 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
|
@ -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 = []})))]}]"
|
||||||
|
@ -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 =
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user