Drop memory-mapped files, since ghc doesn't play well with those
All files are now "redirected", either user-created, or created by ghc-mod itself.
This commit is contained in:
parent
20d6d4bae7
commit
a5dae2a82d
@ -66,6 +66,7 @@ module Language.Haskell.GhcMod (
|
|||||||
, gmUnsafeErrStrLn
|
, gmUnsafeErrStrLn
|
||||||
-- * FileMapping
|
-- * FileMapping
|
||||||
, loadMappedFile
|
, loadMappedFile
|
||||||
|
, loadMappedFileSource
|
||||||
, unloadMappedFile
|
, unloadMappedFile
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
module Language.Haskell.GhcMod.FileMapping
|
module Language.Haskell.GhcMod.FileMapping
|
||||||
( loadMappedFile
|
( loadMappedFile
|
||||||
|
, loadMappedFileSource
|
||||||
, unloadMappedFile
|
, unloadMappedFile
|
||||||
, mapFile
|
, mapFile
|
||||||
, fileModSummaryWithMapping
|
, fileModSummaryWithMapping
|
||||||
@ -11,43 +12,55 @@ import Language.Haskell.GhcMod.Gap
|
|||||||
import Language.Haskell.GhcMod.HomeModuleGraph
|
import Language.Haskell.GhcMod.HomeModuleGraph
|
||||||
import Language.Haskell.GhcMod.Utils
|
import Language.Haskell.GhcMod.Utils
|
||||||
|
|
||||||
import Data.Time
|
import System.IO
|
||||||
|
import System.FilePath
|
||||||
|
import System.Directory
|
||||||
|
|
||||||
import Control.Monad.Trans.Maybe
|
import Control.Monad.Trans.Maybe
|
||||||
import GHC
|
import GHC
|
||||||
|
import Control.Monad
|
||||||
|
import Control.Monad.Trans (lift)
|
||||||
|
|
||||||
loadMappedFile :: IOish m => FilePath -> FileMapping -> GhcModT m ()
|
loadMappedFile :: IOish m => FilePath -> FilePath -> GhcModT m ()
|
||||||
loadMappedFile from fm =
|
loadMappedFile from to =
|
||||||
getCanonicalFileNameSafe from >>= (`addMMappedFile` fm)
|
getCanonicalFileNameSafe from >>= (`addMMappedFile` FileMapping to False)
|
||||||
|
|
||||||
mapFile :: (IOish m, GmState m, GhcMonad m) =>
|
loadMappedFileSource :: IOish m => FilePath -> String -> GhcModT m ()
|
||||||
|
loadMappedFileSource from src = do
|
||||||
|
tmpdir <- cradleTempDir `fmap` cradle
|
||||||
|
to <- liftIO $ do
|
||||||
|
(fn, h) <- openTempFile tmpdir (takeFileName from)
|
||||||
|
hPutStr h src
|
||||||
|
hClose h
|
||||||
|
return fn
|
||||||
|
getCanonicalFileNameSafe from >>= (`addMMappedFile` FileMapping to True)
|
||||||
|
|
||||||
|
mapFile :: (IOish m, GmState m, GhcMonad m, GmEnv m) =>
|
||||||
HscEnv -> Target -> m Target
|
HscEnv -> Target -> m Target
|
||||||
mapFile _ (Target tid@(TargetFile filePath _) taoc _) = do
|
mapFile _ (Target tid@(TargetFile filePath _) taoc _) = do
|
||||||
mapping <- lookupMMappedFile filePath
|
mapping <- lookupMMappedFile filePath
|
||||||
mkMappedTarget tid taoc mapping
|
mkMappedTarget (Just filePath) tid taoc mapping
|
||||||
mapFile env (Target tid@(TargetModule moduleName) taoc _) = do
|
mapFile env (Target tid@(TargetModule moduleName) taoc _) = do
|
||||||
mapping <- runMaybeT $ do
|
(fp, mapping) <- do
|
||||||
filePath <- MaybeT $ liftIO $ findModulePath env moduleName
|
filePath <- fmap (fmap mpPath) (liftIO $ findModulePath env moduleName)
|
||||||
MaybeT $ lookupMMappedFile $ mpPath filePath
|
mmf <- runMaybeT $ MaybeT (return filePath) >>= MaybeT . lookupMMappedFile
|
||||||
mkMappedTarget tid taoc mapping
|
return (filePath, mmf)
|
||||||
|
mkMappedTarget fp tid taoc mapping
|
||||||
|
|
||||||
mkMappedTarget :: (IOish m, GmState m, GhcMonad m) =>
|
mkMappedTarget :: (IOish m, GmState m, GmEnv m, GhcMonad m) =>
|
||||||
TargetId -> Bool -> Maybe FileMapping -> m Target
|
Maybe FilePath -> TargetId -> Bool -> Maybe FileMapping -> m Target
|
||||||
mkMappedTarget _ taoc (Just (RedirectedMapping to)) =
|
mkMappedTarget _ _ taoc (Just to) =
|
||||||
return $ mkTarget (TargetFile to Nothing) taoc Nothing
|
return $ mkTarget (TargetFile (fmPath to) Nothing) taoc Nothing
|
||||||
mkMappedTarget tid taoc (Just (MemoryMapping (Just src))) = do
|
mkMappedTarget _ tid taoc _ = return $ mkTarget tid taoc Nothing
|
||||||
sb <- toStringBuffer [src]
|
|
||||||
ct <- liftIO getCurrentTime
|
|
||||||
return $ mkTarget tid taoc $ Just (sb, ct)
|
|
||||||
mkMappedTarget tid taoc _ = return $ mkTarget tid taoc Nothing
|
|
||||||
|
|
||||||
unloadMappedFile :: IOish m => FilePath -> GhcModT m ()
|
unloadMappedFile :: IOish m => FilePath -> GhcModT m ()
|
||||||
unloadMappedFile = (delMMappedFile =<<) . getCanonicalFileNameSafe
|
unloadMappedFile what = void $ runMaybeT $ do
|
||||||
|
cfn <- lift $ getCanonicalFileNameSafe what
|
||||||
|
fm <- MaybeT $ lookupMMappedFile cfn
|
||||||
|
liftIO $ when (fmTemp fm) $ removeFile (fmPath fm)
|
||||||
|
delMMappedFile cfn
|
||||||
|
|
||||||
fileModSummaryWithMapping :: (IOish m, GmState m, GhcMonad m, GmEnv m) =>
|
fileModSummaryWithMapping :: (IOish m, GmState m, GhcMonad m, GmEnv m) =>
|
||||||
FilePath -> m ModSummary
|
FilePath -> m ModSummary
|
||||||
fileModSummaryWithMapping fn = do
|
fileModSummaryWithMapping fn =
|
||||||
mmf <- getCanonicalFileNameSafe fn >>= lookupMMappedFile
|
withMappedFile fn $ \fn' -> fileModSummary fn'
|
||||||
case mmf of
|
|
||||||
Just (RedirectedMapping to) -> fileModSummary to
|
|
||||||
_ -> fileModSummary fn
|
|
||||||
|
@ -44,6 +44,7 @@ import Control.Arrow ((&&&))
|
|||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
|
import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
|
||||||
|
import Control.Monad.Trans (lift)
|
||||||
import Control.Monad.State.Strict (execStateT)
|
import Control.Monad.State.Strict (execStateT)
|
||||||
import Control.Monad.State.Class
|
import Control.Monad.State.Class
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
@ -62,7 +63,7 @@ import Language.Haskell.GhcMod.Logging
|
|||||||
import Language.Haskell.GhcMod.Logger
|
import Language.Haskell.GhcMod.Logger
|
||||||
import Language.Haskell.GhcMod.Monad.Types
|
import Language.Haskell.GhcMod.Monad.Types
|
||||||
import Language.Haskell.GhcMod.Types
|
import Language.Haskell.GhcMod.Types
|
||||||
import Language.Haskell.GhcMod.Utils (getMappedFileSource)
|
import Language.Haskell.GhcMod.Utils (withMappedFile)
|
||||||
import Language.Haskell.GhcMod.Gap (parseModuleHeader)
|
import Language.Haskell.GhcMod.Gap (parseModuleHeader)
|
||||||
|
|
||||||
-- | Turn module graph into a graphviz dot file
|
-- | Turn module graph into a graphviz dot file
|
||||||
@ -247,19 +248,9 @@ preprocessFile :: (IOish m, GmEnv m, GmState m) =>
|
|||||||
HscEnv -> FilePath -> m (Either [String] ([String], (DynFlags, FilePath)))
|
HscEnv -> FilePath -> m (Either [String] ([String], (DynFlags, FilePath)))
|
||||||
preprocessFile env file =
|
preprocessFile env file =
|
||||||
withLogger' env $ \setDf -> do
|
withLogger' env $ \setDf -> do
|
||||||
src <- runMaybeT $ getMappedFileSource file
|
withMappedFile file $ \fn -> do
|
||||||
let env' = env { hsc_dflags = setDf (hsc_dflags env) }
|
let env' = env { hsc_dflags = setDf (hsc_dflags env) }
|
||||||
maybe
|
liftIO $ preprocess env' (fn, Nothing)
|
||||||
(liftIO $ preprocess env' (file, Nothing))
|
|
||||||
(preprocessWithTemp env' file)
|
|
||||||
src
|
|
||||||
where
|
|
||||||
preprocessWithTemp env' fn src = do
|
|
||||||
tmpdir <- cradleTempDir <$> cradle
|
|
||||||
liftIO $ withTempFile tmpdir fn $ \fn' hndl -> do
|
|
||||||
hPutStr hndl src
|
|
||||||
hClose hndl
|
|
||||||
preprocess env' (fn', Nothing)
|
|
||||||
|
|
||||||
fileModuleName :: (IOish m, GmEnv m, GmState m) =>
|
fileModuleName :: (IOish m, GmEnv m, GmState m) =>
|
||||||
HscEnv -> FilePath -> m (Either [String] (Maybe ModuleName))
|
HscEnv -> FilePath -> m (Either [String] (Maybe ModuleName))
|
||||||
@ -269,11 +260,12 @@ fileModuleName env fn = do
|
|||||||
case ep of
|
case ep of
|
||||||
Left errs -> do
|
Left errs -> do
|
||||||
return $ Left errs
|
return $ Left errs
|
||||||
Right (_warns, (dflags, procdFile)) -> handler $ do
|
Right (_warns, (dflags, procdFile)) -> leftM (errBagToStrList env) =<< handler (do
|
||||||
src <- readFile procdFile
|
src <- readFile procdFile
|
||||||
case parseModuleHeader src dflags procdFile of
|
case parseModuleHeader src dflags procdFile of
|
||||||
Left errs -> do
|
Left errs -> return $ Left errs
|
||||||
return $ Left $ errBagToStrList env errs
|
|
||||||
Right (_, lmdl) -> do
|
Right (_, lmdl) -> do
|
||||||
let HsModule {..} = unLoc lmdl
|
let HsModule {..} = unLoc lmdl
|
||||||
return $ Right $ unLoc <$> hsmodName
|
return $ Right $ unLoc <$> hsmodName)
|
||||||
|
where
|
||||||
|
leftM f = either (return . Left <=< f) (return . Right)
|
||||||
|
@ -108,12 +108,16 @@ withLogger' env action = do
|
|||||||
|
|
||||||
return ((,) ls <$> a)
|
return ((,) ls <$> a)
|
||||||
|
|
||||||
errBagToStrList :: HscEnv -> Bag ErrMsg -> [String]
|
errBagToStrList :: (Functor m, GmState m, GmEnv m) => HscEnv -> Bag ErrMsg -> m [String]
|
||||||
errBagToStrList env errs = let
|
errBagToStrList env errs = let
|
||||||
dflags = hsc_dflags env
|
dflags = hsc_dflags env
|
||||||
pu = icPrintUnqual dflags (hsc_IC env)
|
pu = icPrintUnqual dflags (hsc_IC env)
|
||||||
st = mkUserStyle pu AllTheWay
|
st = mkUserStyle pu AllTheWay
|
||||||
in runReader (errsToStr (bagToList errs)) GmPprEnv{gpeDynFlags=dflags, gpePprStyle=st}
|
in do
|
||||||
|
rfm <- mkRevRedirMapFunc
|
||||||
|
return $ runReader
|
||||||
|
(errsToStr (bagToList errs))
|
||||||
|
GmPprEnv{gpeDynFlags=dflags, gpePprStyle=st, gpeMapFile=rfm}
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ runGmlTWith efnmns' mdf wrapper action = do
|
|||||||
|
|
||||||
let (fns, mns) = partitionEithers efnmns'
|
let (fns, mns) = partitionEithers efnmns'
|
||||||
ccfns = map (cradleCurrentDir crdl </>) fns
|
ccfns = map (cradleCurrentDir crdl </>) fns
|
||||||
cfns <- liftIO $ mapM canonicalizePath ccfns
|
cfns <- mapM getCanonicalFileNameSafe ccfns
|
||||||
let serfnmn = Set.fromList $ map Right mns ++ map Left cfns
|
let serfnmn = Set.fromList $ map Right mns ++ map Left cfns
|
||||||
opts <- targetGhcOptions crdl serfnmn
|
opts <- targetGhcOptions crdl serfnmn
|
||||||
let opts' = opts ++ ["-O0"] ++ ghcUserOptions
|
let opts' = opts ++ ["-O0"] ++ ghcUserOptions
|
||||||
|
@ -69,8 +69,7 @@ data OutputStyle = LispStyle -- ^ S expression style.
|
|||||||
-- | The type for line separator. Historically, a Null string is used.
|
-- | The type for line separator. Historically, a Null string is used.
|
||||||
newtype LineSeparator = LineSeparator String deriving (Show)
|
newtype LineSeparator = LineSeparator String deriving (Show)
|
||||||
|
|
||||||
data FileMapping = RedirectedMapping FilePath
|
data FileMapping = FileMapping {fmPath :: FilePath, fmTemp :: Bool}
|
||||||
| MemoryMapping (Maybe String)
|
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
type FileMappingMap = Map FilePath FileMapping
|
type FileMappingMap = Map FilePath FileMapping
|
||||||
@ -99,7 +98,7 @@ data Options = Options {
|
|||||||
-- | If 'True', 'browse' will return fully qualified name
|
-- | If 'True', 'browse' will return fully qualified name
|
||||||
, qualified :: Bool
|
, qualified :: Bool
|
||||||
, hlintOpts :: [String]
|
, hlintOpts :: [String]
|
||||||
, fileMappings :: [(FilePath,FileMapping)]
|
, fileMappings :: [(FilePath, Maybe FilePath)]
|
||||||
} deriving (Show)
|
} deriving (Show)
|
||||||
|
|
||||||
-- | A default 'Options'.
|
-- | A default 'Options'.
|
||||||
|
@ -26,25 +26,23 @@ module Language.Haskell.GhcMod.Utils (
|
|||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Data.Char
|
import Data.Char
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
import Data.Maybe (mapMaybe, fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
import Exception
|
import Exception
|
||||||
import Language.Haskell.GhcMod.Error
|
import Language.Haskell.GhcMod.Error
|
||||||
import Language.Haskell.GhcMod.Types
|
import Language.Haskell.GhcMod.Types
|
||||||
import Language.Haskell.GhcMod.Monad.Types
|
import Language.Haskell.GhcMod.Monad.Types
|
||||||
import System.Directory (getCurrentDirectory, setCurrentDirectory, doesFileExist,
|
import System.Directory (getCurrentDirectory, setCurrentDirectory, doesFileExist,
|
||||||
getTemporaryDirectory, canonicalizePath, removeFile)
|
getTemporaryDirectory, canonicalizePath)
|
||||||
import System.Environment
|
import System.Environment
|
||||||
import System.FilePath (splitDrive, takeDirectory, takeFileName, pathSeparators,
|
import System.FilePath (splitDrive, takeDirectory, takeFileName, pathSeparators,
|
||||||
(</>), makeRelative)
|
(</>), makeRelative)
|
||||||
import System.IO.Temp (createTempDirectory, openTempFile)
|
import System.IO.Temp (createTempDirectory)
|
||||||
import System.IO (hPutStr, hClose)
|
|
||||||
import System.Process (readProcess)
|
import System.Process (readProcess)
|
||||||
import Text.Printf
|
import Text.Printf
|
||||||
|
|
||||||
import Paths_ghc_mod (getLibexecDir)
|
import Paths_ghc_mod (getLibexecDir)
|
||||||
import Utils
|
import Utils
|
||||||
import Prelude
|
import Prelude
|
||||||
import Control.Monad.Trans.Maybe
|
|
||||||
|
|
||||||
-- dropWhileEnd is not provided prior to base 4.5.0.0.
|
-- dropWhileEnd is not provided prior to base 4.5.0.0.
|
||||||
dropWhileEnd :: (a -> Bool) -> [a] -> [a]
|
dropWhileEnd :: (a -> Bool) -> [a] -> [a]
|
||||||
@ -167,44 +165,26 @@ withMappedFile :: (IOish m, GmState m, GmEnv m) =>
|
|||||||
forall a. FilePath -> (FilePath -> m a) -> m a
|
forall a. FilePath -> (FilePath -> m a) -> m a
|
||||||
withMappedFile file action = getCanonicalFileNameSafe file >>= lookupMMappedFile >>= runWithFile
|
withMappedFile file action = getCanonicalFileNameSafe file >>= lookupMMappedFile >>= runWithFile
|
||||||
where
|
where
|
||||||
runWithFile (Just (RedirectedMapping to)) = action to
|
runWithFile (Just to) = action $ fmPath to
|
||||||
runWithFile (Just (MemoryMapping (Just src))) = do
|
|
||||||
crdl <- cradle
|
|
||||||
(fp,hndl) <- liftIO $ openTempFile (cradleTempDir crdl) (takeFileName file)
|
|
||||||
liftIO $ hPutStr hndl src
|
|
||||||
liftIO $ hClose hndl
|
|
||||||
result <- action fp
|
|
||||||
liftIO $ removeFile fp
|
|
||||||
return result
|
|
||||||
runWithFile _ = action file
|
runWithFile _ = action file
|
||||||
|
|
||||||
getCanonicalFileNameSafe :: (IOish m, GmEnv m) => FilePath -> m FilePath
|
getCanonicalFileNameSafe :: (IOish m, GmEnv m) => FilePath -> m FilePath
|
||||||
getCanonicalFileNameSafe fn = do
|
getCanonicalFileNameSafe fn = do
|
||||||
crdl <- cradle
|
crdl <- cradle
|
||||||
let ccfn = cradleCurrentDir crdl </> fn
|
let ccfn = cradleRootDir crdl </> fn
|
||||||
fex <- liftIO $ doesFileExist ccfn
|
fex <- liftIO $ doesFileExist ccfn
|
||||||
if fex
|
if fex
|
||||||
then liftIO $ canonicalizePath ccfn
|
then liftIO $ canonicalizePath ccfn
|
||||||
else return ccfn
|
else return ccfn
|
||||||
|
|
||||||
getMappedFileSource :: (IOish m, GmEnv m, GmState m) => FilePath -> MaybeT m String
|
|
||||||
getMappedFileSource fn = do
|
|
||||||
mf <- MaybeT $ getCanonicalFileNameSafe fn >>= lookupMMappedFile
|
|
||||||
case mf of
|
|
||||||
RedirectedMapping fn' -> liftIO $ readFile fn'
|
|
||||||
MemoryMapping (Just src) -> return src
|
|
||||||
_ -> mzero
|
|
||||||
|
|
||||||
mkRevRedirMapFunc :: (Functor m, GmState m, GmEnv m) => m (FilePath -> FilePath)
|
mkRevRedirMapFunc :: (Functor m, GmState m, GmEnv m) => m (FilePath -> FilePath)
|
||||||
mkRevRedirMapFunc = do
|
mkRevRedirMapFunc = do
|
||||||
rm <- M.fromList <$> mapMaybe (uncurry mf) <$> M.toList <$> getMMappedFiles
|
rm <- M.fromList <$> map (uncurry mf) <$> M.toList <$> getMMappedFiles
|
||||||
crdl <- cradle
|
crdl <- cradle
|
||||||
return $ \key ->
|
return $ \key ->
|
||||||
fromMaybe key
|
fromMaybe key
|
||||||
$ makeRelative (cradleRootDir crdl)
|
$ makeRelative (cradleRootDir crdl)
|
||||||
<$> M.lookup key rm
|
<$> M.lookup key rm
|
||||||
where
|
where
|
||||||
mf :: FilePath -> FileMapping -> Maybe (FilePath, FilePath)
|
mf :: FilePath -> FileMapping -> (FilePath, FilePath)
|
||||||
mf from (RedirectedMapping to)
|
mf from to = (fmPath to, from)
|
||||||
= Just (to, from)
|
|
||||||
mf _ _ = Nothing
|
|
||||||
|
@ -274,8 +274,8 @@ globalArgSpec =
|
|||||||
, option "" ["map-file"] "Redirect one file to another, --map-file \"file1.hs=file2.hs\"" $
|
, option "" ["map-file"] "Redirect one file to another, --map-file \"file1.hs=file2.hs\"" $
|
||||||
reqArg "OPT" $ \g o ->
|
reqArg "OPT" $ \g o ->
|
||||||
let m = case second (drop 1) $ span (/='=') g of
|
let m = case second (drop 1) $ span (/='=') g of
|
||||||
(s,"") -> (s, MemoryMapping Nothing)
|
(s,"") -> (s, Nothing)
|
||||||
(f,t) -> (f, RedirectedMapping t)
|
(f,t) -> (f, Just t)
|
||||||
in
|
in
|
||||||
Right $ o { fileMappings = m : fileMappings o }
|
Right $ o { fileMappings = m : fileMappings o }
|
||||||
|
|
||||||
@ -359,16 +359,10 @@ main = do
|
|||||||
|
|
||||||
progMain :: (Options,[String]) -> IO ()
|
progMain :: (Options,[String]) -> IO ()
|
||||||
progMain (globalOptions,cmdArgs) = hndle $ runGhcModT globalOptions $ handler $ do
|
progMain (globalOptions,cmdArgs) = hndle $ runGhcModT globalOptions $ handler $ do
|
||||||
let
|
|
||||||
loadMMappedFiles from (MemoryMapping Nothing) = do
|
|
||||||
src <- liftIO getFileSourceFromStdin
|
|
||||||
return (from, MemoryMapping $ Just src)
|
|
||||||
loadMMappedFiles from x = return (from, x)
|
|
||||||
fileMappings' <- forM (reverse $ fileMappings globalOptions) $ uncurry loadMMappedFiles
|
|
||||||
case globalCommands cmdArgs of
|
case globalCommands cmdArgs of
|
||||||
Just s -> gmPutStr s
|
Just s -> gmPutStr s
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
mapM_ (uncurry loadMappedFile) fileMappings'
|
forM_ (reverse $ fileMappings globalOptions) $ uncurry loadMMappedFiles
|
||||||
ghcCommands cmdArgs
|
ghcCommands cmdArgs
|
||||||
where
|
where
|
||||||
hndle action = do
|
hndle action = do
|
||||||
@ -378,6 +372,10 @@ progMain (globalOptions,cmdArgs) = hndle $ runGhcModT globalOptions $ handler $
|
|||||||
return ()
|
return ()
|
||||||
Left ed ->
|
Left ed ->
|
||||||
exitError' globalOptions $ renderStyle ghcModStyle (gmeDoc ed)
|
exitError' globalOptions $ renderStyle ghcModStyle (gmeDoc ed)
|
||||||
|
loadMMappedFiles from (Just to) = loadMappedFile from to
|
||||||
|
loadMMappedFiles from (Nothing) = do
|
||||||
|
src <- liftIO getFileSourceFromStdin
|
||||||
|
loadMappedFileSource from src
|
||||||
|
|
||||||
globalCommands :: [String] -> Maybe String
|
globalCommands :: [String] -> Maybe String
|
||||||
globalCommands (cmd:_)
|
globalCommands (cmd:_)
|
||||||
@ -447,7 +445,7 @@ legacyInteractiveLoop symdbreq world = do
|
|||||||
"browse" -> browseCmd args
|
"browse" -> browseCmd args
|
||||||
|
|
||||||
"map-file" -> liftIO getFileSourceFromStdin
|
"map-file" -> liftIO getFileSourceFromStdin
|
||||||
>>= loadMappedFile arg . MemoryMapping . Just
|
>>= loadMappedFileSource arg
|
||||||
>> return ""
|
>> return ""
|
||||||
|
|
||||||
"unmap-file" -> unloadMappedFile arg
|
"unmap-file" -> unloadMappedFile arg
|
||||||
|
@ -7,6 +7,7 @@ import TestUtils
|
|||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
import Dir
|
import Dir
|
||||||
import System.IO.Temp
|
import System.IO.Temp
|
||||||
|
import System.Directory
|
||||||
|
|
||||||
import Language.Haskell.GhcMod
|
import Language.Haskell.GhcMod
|
||||||
|
|
||||||
@ -16,45 +17,74 @@ spec = do
|
|||||||
it "inserts a given FilePath FileMapping into state with canonicalized path" $ do
|
it "inserts a given FilePath FileMapping into state with canonicalized path" $ do
|
||||||
withDirectory_ "test/data/file-mapping" $ do
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
mappedFiles <- runD $ do
|
mappedFiles <- runD $ do
|
||||||
loadMappedFile "File.hs" (MemoryMapping Nothing)
|
loadMappedFile "File.hs" "File.hs"
|
||||||
getMMappedFiles
|
getMMappedFiles
|
||||||
dir <- getCurrentDirectory
|
dir <- getCurrentDirectory
|
||||||
show mappedFiles `shouldBe` show (M.fromList [(dir </> "File.hs", MemoryMapping Nothing)])
|
show mappedFiles `shouldBe` show (M.fromList [(dir </> "File.hs", FileMapping "File.hs" False)])
|
||||||
it "should try to guess a canonical name if file doesn't exist" $ do
|
it "should try to guess a canonical name if file doesn't exist" $ do
|
||||||
withDirectory_ "test/data/file-mapping" $ do
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
mappedFiles <- runD $ do
|
mappedFiles <- runD $ do
|
||||||
loadMappedFile "NonExistantFile.hs" (MemoryMapping Nothing)
|
loadMappedFile "NonExistantFile.hs" "File.hs"
|
||||||
getMMappedFiles
|
getMMappedFiles
|
||||||
dir <- getCurrentDirectory
|
dir <- getCurrentDirectory
|
||||||
show mappedFiles `shouldBe` show (M.fromList [(dir </> "NonExistantFile.hs", MemoryMapping Nothing)])
|
show mappedFiles `shouldBe` show (M.fromList [(dir </> "NonExistantFile.hs", FileMapping "File.hs" False)])
|
||||||
|
|
||||||
|
describe "loadMappedFileSource" $ do
|
||||||
|
it "inserts a given FilePath FileMapping into state with canonicalized path" $ do
|
||||||
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
|
mappedFiles <- runD $ do
|
||||||
|
loadMappedFileSource "File.hs" "main :: IO ()"
|
||||||
|
getMMappedFiles
|
||||||
|
dir <- getCurrentDirectory
|
||||||
|
-- TODO
|
||||||
|
M.toList mappedFiles `shouldSatisfy` \[(fn, FileMapping _to True)] ->
|
||||||
|
fn == dir </> "File.hs"
|
||||||
|
it "should try to guess a canonical name if file doesn't exist" $ do
|
||||||
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
|
mappedFiles <- runD $ do
|
||||||
|
loadMappedFileSource "NonExistantFile.hs" "main :: IO ()"
|
||||||
|
getMMappedFiles
|
||||||
|
dir <- getCurrentDirectory
|
||||||
|
-- TODO
|
||||||
|
M.toList mappedFiles `shouldSatisfy` \[(fn, FileMapping _to True)] ->
|
||||||
|
fn == dir </> "NonExistantFile.hs"
|
||||||
|
|
||||||
describe "unloadMappedFile" $ do
|
describe "unloadMappedFile" $ do
|
||||||
it "removes a given FilePath from state" $ do
|
it "removes a given FilePath from state" $ do
|
||||||
withDirectory_ "test/data/file-mapping" $ do
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
mappedFiles <- runD $ do
|
mappedFiles <- runD $ do
|
||||||
loadMappedFile "File.hs" (MemoryMapping Nothing)
|
loadMappedFile "File.hs" "File2.hs"
|
||||||
unloadMappedFile "File.hs"
|
unloadMappedFile "File.hs"
|
||||||
getMMappedFiles
|
getMMappedFiles
|
||||||
show mappedFiles `shouldBe` show (M.fromList ([] :: [(FilePath, FileMapping)]))
|
show mappedFiles `shouldBe` show (M.fromList ([] :: [(FilePath, FileMapping)]))
|
||||||
it "should work even if file does not exist" $ do
|
it "should work even if file does not exist" $ do
|
||||||
withDirectory_ "test/data/file-mapping" $ do
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
mappedFiles <- runD $ do
|
mappedFiles <- runD $ do
|
||||||
loadMappedFile "NonExistantFile.hs" (MemoryMapping Nothing)
|
loadMappedFile "NonExistantFile.hs" "File2.hs"
|
||||||
unloadMappedFile "NonExistantFile.hs"
|
unloadMappedFile "NonExistantFile.hs"
|
||||||
getMMappedFiles
|
getMMappedFiles
|
||||||
show mappedFiles `shouldBe` show (M.fromList ([] :: [(FilePath, FileMapping)]))
|
show mappedFiles `shouldBe` show (M.fromList ([] :: [(FilePath, FileMapping)]))
|
||||||
|
it "should remove created temporary files" $ do
|
||||||
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
|
dir <- getCurrentDirectory
|
||||||
|
fileExists <- runD $ do
|
||||||
|
loadMappedFileSource "NonExistantFile.hs" "main :: IO ()"
|
||||||
|
fp <- maybe undefined fmPath `fmap` lookupMMappedFile (dir </> "NonExistantFile.hs")
|
||||||
|
unloadMappedFile "NonExistantFile.hs"
|
||||||
|
liftIO $ doesFileExist fp
|
||||||
|
not fileExists `shouldBe` True
|
||||||
|
|
||||||
describe "withMappedFile" $ do
|
describe "withMappedFile" $ do
|
||||||
it "checks if there is a redirected file and calls and action with its FilePath" $ do
|
it "checks if there is a redirected file and calls and action with its FilePath" $ do
|
||||||
withDirectory_ "test/data/file-mapping" $ do
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
res <- runD $ do
|
res <- runD $ do
|
||||||
loadMappedFile "File.hs" (RedirectedMapping "File_Redir.hs")
|
loadMappedFile "File.hs" "File_Redir.hs"
|
||||||
withMappedFile "File.hs" return
|
withMappedFile "File.hs" return
|
||||||
res `shouldBe` "File_Redir.hs"
|
res `shouldBe` "File_Redir.hs"
|
||||||
it "checks if there is an in-memory file and calls and action with temporary file" $ do
|
it "checks if there is an in-memory file and calls and action with temporary file" $ do
|
||||||
withDirectory_ "test/data/file-mapping" $ do
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
(fn, src) <- runD $ do
|
(fn, src) <- runD $ do
|
||||||
loadMappedFile "File.hs" (MemoryMapping $ Just "main = test")
|
loadMappedFileSource "File.hs" "main = test"
|
||||||
withMappedFile "File.hs" $ \fn -> do
|
withMappedFile "File.hs" $ \fn -> do
|
||||||
src <- liftIO $ readFile fn
|
src <- liftIO $ readFile fn
|
||||||
return (fn, src)
|
return (fn, src)
|
||||||
@ -69,101 +99,107 @@ spec = do
|
|||||||
describe "integration tests" $ do
|
describe "integration tests" $ do
|
||||||
it "checks redirected file if one is specified and outputs original filename" $ do
|
it "checks redirected file if one is specified and outputs original filename" $ do
|
||||||
withDirectory_ "test/data/file-mapping" $ do
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
let fm = [("File.hs", RedirectedMapping "File_Redir.hs")]
|
let fm = [("File.hs", "File_Redir.hs")]
|
||||||
res <- run defaultOptions $ do
|
res <- run defaultOptions $ do
|
||||||
mapM_ (uncurry loadMappedFile) fm
|
mapM_ (uncurry loadMappedFile) fm
|
||||||
checkSyntax ["File.hs"]
|
checkSyntax ["File.hs"]
|
||||||
res `shouldBe` "File.hs:1:1:Warning: Top-level binding with no type signature: main :: IO ()\n"
|
res `shouldBe` "File.hs:1:1:Warning: Top-level binding with no type signature: main :: IO ()\n"
|
||||||
it "checks in-memory file if one is specified and outputs original filename" $ do
|
it "checks in-memory file if one is specified and outputs original filename" $ do
|
||||||
withDirectory_ "test/data/file-mapping" $ do
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
let fm = [("File.hs", MemoryMapping $ Just "main = putStrLn \"Hello World!\"\n")]
|
let fm = [("File.hs", "main = putStrLn \"Hello World!\"\n")]
|
||||||
res <- run defaultOptions $ do
|
res <- run defaultOptions $ do
|
||||||
mapM_ (uncurry loadMappedFile) fm
|
mapM_ (uncurry loadMappedFileSource) fm
|
||||||
checkSyntax ["File.hs"]
|
checkSyntax ["File.hs"]
|
||||||
res `shouldBe` "File.hs:1:1:Warning: Top-level binding with no type signature: main :: IO ()\n"
|
res `shouldBe` "File.hs:1:1:Warning: Top-level binding with no type signature: main :: IO ()\n"
|
||||||
|
it "should work even if file doesn't exist" $ do
|
||||||
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
|
let fm = [("Nonexistent.hs", "main = putStrLn \"Hello World!\"\n")]
|
||||||
|
res <- run defaultOptions{logLevel=GmDebug} $ do
|
||||||
|
mapM_ (uncurry loadMappedFileSource) fm
|
||||||
|
checkSyntax ["Nonexistent.hs"]
|
||||||
|
res `shouldBe` "Nonexistent.hs:1:1:Warning: Top-level binding with no type signature: main :: IO ()\n"
|
||||||
it "lints redirected file if one is specified and outputs original filename" $ do
|
it "lints redirected file if one is specified and outputs original filename" $ do
|
||||||
withDirectory_ "test/data/file-mapping" $ do
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
res <- runD $ do
|
res <- runD $ do
|
||||||
loadMappedFile "File.hs" (RedirectedMapping "File_Redir_Lint.hs")
|
loadMappedFile "File.hs" "File_Redir_Lint.hs"
|
||||||
lint "File.hs"
|
lint "File.hs"
|
||||||
res `shouldBe` "File.hs:4:1: Error: Eta reduce\NULFound:\NUL func a b = (*) a b\NULWhy not:\NUL func = (*)\n"
|
res `shouldBe` "File.hs:4:1: Error: Eta reduce\NULFound:\NUL func a b = (*) a b\NULWhy not:\NUL func = (*)\n"
|
||||||
it "lints in-memory file if one is specified and outputs original filename" $ do
|
it "lints in-memory file if one is specified and outputs original filename" $ do
|
||||||
withDirectory_ "test/data/file-mapping" $ do
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
res <- runD $ do
|
res <- runD $ do
|
||||||
loadMappedFile "File.hs" (MemoryMapping $ Just "func a b = (++) a b\n")
|
loadMappedFileSource "File.hs" "func a b = (++) a b\n"
|
||||||
lint "File.hs"
|
lint "File.hs"
|
||||||
res `shouldBe` "File.hs:1:1: Error: Eta reduce\NULFound:\NUL func a b = (++) a b\NULWhy not:\NUL func = (++)\n"
|
res `shouldBe` "File.hs:1:1: Error: Eta reduce\NULFound:\NUL func a b = (++) a b\NULWhy not:\NUL func = (++)\n"
|
||||||
it "shows types of the expression for redirected files" $ do
|
it "shows types of the expression for redirected files" $ do
|
||||||
let tdir = "test/data/file-mapping"
|
let tdir = "test/data/file-mapping"
|
||||||
res <- runD' tdir $ do
|
res <- runD' tdir $ do
|
||||||
loadMappedFile "File.hs" (RedirectedMapping "File_Redir_Lint.hs")
|
loadMappedFile "File.hs" "File_Redir_Lint.hs"
|
||||||
types "File.hs" 4 12
|
types "File.hs" 4 12
|
||||||
res `shouldBe` "4 12 4 15 \"a -> a -> a\"\n4 12 4 17 \"a -> a\"\n4 12 4 19 \"a\"\n4 1 4 19 \"a -> a -> a\"\n"
|
res `shouldBe` "4 12 4 15 \"a -> a -> a\"\n4 12 4 17 \"a -> a\"\n4 12 4 19 \"a\"\n4 1 4 19 \"a -> a -> a\"\n"
|
||||||
it "shows types of the expression for in-memory files" $ do
|
it "shows types of the expression for in-memory files" $ do
|
||||||
let tdir = "test/data/file-mapping"
|
let tdir = "test/data/file-mapping"
|
||||||
res <- runD' tdir $ do
|
res <- runD' tdir $ do
|
||||||
loadMappedFile "File.hs" (MemoryMapping $ Just "main = putStrLn \"Hello!\"")
|
loadMappedFileSource "File.hs" "main = putStrLn \"Hello!\""
|
||||||
types "File.hs" 1 14
|
types "File.hs" 1 14
|
||||||
res `shouldBe` "1 8 1 16 \"String -> IO ()\"\n1 8 1 25 \"IO ()\"\n1 1 1 25 \"IO ()\"\n"
|
res `shouldBe` "1 8 1 16 \"String -> IO ()\"\n1 8 1 25 \"IO ()\"\n1 1 1 25 \"IO ()\"\n"
|
||||||
it "shows info for the expression for redirected files" $ do
|
it "shows info for the expression for redirected files" $ do
|
||||||
let tdir = "test/data/file-mapping"
|
let tdir = "test/data/file-mapping"
|
||||||
res <- runD' tdir $ do
|
res <- runD' tdir $ do
|
||||||
loadMappedFile "File.hs" (RedirectedMapping "File_Redir_Lint.hs")
|
loadMappedFile "File.hs" "File_Redir_Lint.hs"
|
||||||
info "File.hs" $ Expression "func"
|
info "File.hs" $ Expression "func"
|
||||||
res `shouldBe` "func :: Num a => a -> a -> a \t-- Defined at File.hs:4:1\n"
|
res `shouldBe` "func :: Num a => a -> a -> a \t-- Defined at File.hs:4:1\n"
|
||||||
it "shows info for the expression for in-memory files" $ do
|
it "shows info for the expression for in-memory files" $ do
|
||||||
let tdir = "test/data/file-mapping"
|
let tdir = "test/data/file-mapping"
|
||||||
res <- runD' tdir $ do
|
res <- runD' tdir $ do
|
||||||
loadMappedFile "File.hs" (MemoryMapping $ Just "module File where\n\ntestfun = putStrLn \"Hello!\"")
|
loadMappedFileSource "File.hs" "module File where\n\ntestfun = putStrLn \"Hello!\""
|
||||||
info "File.hs" $ Expression "testfun"
|
info "File.hs" $ Expression "testfun"
|
||||||
res `shouldBe` "testfun :: IO () \t-- Defined at File.hs:3:1\n"
|
res `shouldBe` "testfun :: IO () \t-- Defined at File.hs:3:1\n"
|
||||||
|
|
||||||
describe "preprocessor tests" $ do
|
describe "preprocessor tests" $ do
|
||||||
it "checks redirected file if one is specified and outputs original filename" $ do
|
it "checks redirected file if one is specified and outputs original filename" $ do
|
||||||
withDirectory_ "test/data/file-mapping/preprocessor" $ do
|
withDirectory_ "test/data/file-mapping/preprocessor" $ do
|
||||||
let fm = [("File.hs", RedirectedMapping "File_Redir.hs")]
|
let fm = [("File.hs", "File_Redir.hs")]
|
||||||
res <- run defaultOptions $ do
|
res <- run defaultOptions $ do
|
||||||
mapM_ (uncurry loadMappedFile) fm
|
mapM_ (uncurry loadMappedFile) fm
|
||||||
checkSyntax ["File.hs"]
|
checkSyntax ["File.hs"]
|
||||||
res `shouldBe` "File.hs:3:1:Warning: Top-level binding with no type signature: main :: IO ()\n"
|
res `shouldBe` "File.hs:3:1:Warning: Top-level binding with no type signature: main :: IO ()\n"
|
||||||
it "doesn't check in-memory file" $ do
|
it "checks in-memory file" $ do
|
||||||
withDirectory_ "test/data/file-mapping/preprocessor" $ do
|
withDirectory_ "test/data/file-mapping/preprocessor" $ do
|
||||||
src <- readFile "File_Redir.hs"
|
src <- readFile "File_Redir.hs"
|
||||||
let fm = [("File.hs", MemoryMapping $ Just src)]
|
let fm = [("File.hs", src)]
|
||||||
res <- run defaultOptions $ do
|
res <- run defaultOptions $ do
|
||||||
mapM_ (uncurry loadMappedFile) fm
|
mapM_ (uncurry loadMappedFileSource) fm
|
||||||
checkSyntax ["File.hs"]
|
checkSyntax ["File.hs"]
|
||||||
res `shouldBe` "buffer needs preprocesing; interactive check disabled\n"
|
res `shouldBe` "File.hs:3:1:Warning: Top-level binding with no type signature: main :: IO ()\n"
|
||||||
it "lints redirected file if one is specified and outputs original filename" $ do
|
it "lints redirected file if one is specified and outputs original filename" $ do
|
||||||
withDirectory_ "test/data/file-mapping/preprocessor" $ do
|
withDirectory_ "test/data/file-mapping/preprocessor" $ do
|
||||||
res <- runD $ do
|
res <- runD $ do
|
||||||
loadMappedFile "File.hs" (RedirectedMapping "File_Redir_Lint.hs")
|
loadMappedFile "File.hs" "File_Redir_Lint.hs"
|
||||||
lint "File.hs"
|
lint "File.hs"
|
||||||
res `shouldBe` "File.hs:6:1: Error: Eta reduce\NULFound:\NUL func a b = (*) a b\NULWhy not:\NUL func = (*)\n"
|
res `shouldBe` "File.hs:6:1: Error: Eta reduce\NULFound:\NUL func a b = (*) a b\NULWhy not:\NUL func = (*)\n"
|
||||||
it "lints in-memory file if one is specified and outputs original filename" $ do
|
it "lints in-memory file if one is specified and outputs original filename" $ do
|
||||||
withDirectory_ "test/data/file-mapping/preprocessor" $ do
|
withDirectory_ "test/data/file-mapping/preprocessor" $ do
|
||||||
src <- readFile "File_Redir_Lint.hs"
|
src <- readFile "File_Redir_Lint.hs"
|
||||||
res <- runD $ do
|
res <- runD $ do
|
||||||
loadMappedFile "File.hs" (MemoryMapping $ Just src)
|
loadMappedFileSource "File.hs" src
|
||||||
lint "File.hs"
|
lint "File.hs"
|
||||||
res `shouldBe` "File.hs:6:1: Error: Eta reduce\NULFound:\NUL func a b = (*) a b\NULWhy not:\NUL func = (*)\n"
|
res `shouldBe` "File.hs:6:1: Error: Eta reduce\NULFound:\NUL func a b = (*) a b\NULWhy not:\NUL func = (*)\n"
|
||||||
describe "literate haskell tests" $ do
|
describe "literate haskell tests" $ do
|
||||||
it "checks redirected file if one is specified and outputs original filename" $ do
|
it "checks redirected file if one is specified and outputs original filename" $ do
|
||||||
withDirectory_ "test/data/file-mapping/lhs" $ do
|
withDirectory_ "test/data/file-mapping/lhs" $ do
|
||||||
let fm = [("File.lhs", RedirectedMapping "File_Redir.lhs")]
|
let fm = [("File.lhs", "File_Redir.lhs")]
|
||||||
res <- run defaultOptions $ do
|
res <- run defaultOptions $ do
|
||||||
mapM_ (uncurry loadMappedFile) fm
|
mapM_ (uncurry loadMappedFile) fm
|
||||||
checkSyntax ["File.lhs"]
|
checkSyntax ["File.lhs"]
|
||||||
res `shouldBe` "File.lhs:1:3:Warning: Top-level binding with no type signature: main :: IO ()\n"
|
res `shouldBe` "File.lhs:1:3:Warning: Top-level binding with no type signature: main :: IO ()\n"
|
||||||
-- NOTE: GHC can't 'unliterate' a file in-memory, so this won't work
|
it "checks in-memory file if one is specified and outputs original filename" $ do
|
||||||
-- it "checks in-memory file if one is specified and outputs original filename" $ do
|
withDirectory_ "test/data/file-mapping/lhs" $ do
|
||||||
-- withDirectory_ "test/data/file-mapping/lhs" $ do
|
src <- readFile "File_Redir.lhs"
|
||||||
-- src <- readFile "File_Redir.lhs"
|
let fm = [("File.lhs", src)]
|
||||||
-- let fm = [("File.lhs", MemoryMapping $ Just src)]
|
res <- run defaultOptions $ do
|
||||||
-- res <- run defaultOptions $ do
|
mapM_ (uncurry loadMappedFileSource) fm
|
||||||
-- mapM_ (uncurry loadMappedFile) fm
|
checkSyntax ["File.lhs"]
|
||||||
-- checkSyntax ["File.lhs"]
|
res `shouldBe` "File.lhs:1:3:Warning: Top-level binding with no type signature: main :: IO ()\n"
|
||||||
-- res `shouldBe` "File.lhs:1:3:Warning: Top-level binding with no type signature: main :: IO ()\n"
|
|
||||||
-- NOTE: There is a bug in hlint that prevents it from linting lhs files.
|
-- NOTE: There is a bug in hlint that prevents it from linting lhs files.
|
||||||
-- it "lints redirected file if one is specified and outputs original filename" $ do
|
-- it "lints redirected file if one is specified and outputs original filename" $ do
|
||||||
-- withDirectory_ "test/data/file-mapping/lhs" $ do
|
-- withDirectory_ "test/data/file-mapping/lhs" $ do
|
||||||
@ -186,9 +222,9 @@ spec = do
|
|||||||
withDirectory_ "test/data/file-mapping" $ do
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
writeFile (tmpdir </> "Foo_Redir.hs") srcFoo
|
writeFile (tmpdir </> "Foo_Redir.hs") srcFoo
|
||||||
writeFile (tmpdir </> "Bar_Redir.hs") srcBar
|
writeFile (tmpdir </> "Bar_Redir.hs") srcBar
|
||||||
let fm = [("Foo.hs", RedirectedMapping $ tmpdir </> "Foo_Redir.hs")
|
let fm = [("Foo.hs", tmpdir </> "Foo_Redir.hs")
|
||||||
,("Bar.hs", RedirectedMapping $ tmpdir </> "Bar_Redir.hs")]
|
,("Bar.hs", tmpdir </> "Bar_Redir.hs")]
|
||||||
res <- run defaultOptions $ do
|
res <- run defaultOptions{logLevel = GmDebug} $ do
|
||||||
mapM_ (uncurry loadMappedFile) fm
|
mapM_ (uncurry loadMappedFile) fm
|
||||||
types "Bar.hs" 5 1
|
types "Bar.hs" 5 1
|
||||||
res `shouldBe` unlines ["5 1 5 20 \"[Char]\""]
|
res `shouldBe` unlines ["5 1 5 20 \"[Char]\""]
|
||||||
@ -196,9 +232,9 @@ spec = do
|
|||||||
srcFoo <- readFile "test/data/template-haskell/Foo.hs"
|
srcFoo <- readFile "test/data/template-haskell/Foo.hs"
|
||||||
srcBar <- readFile "test/data/template-haskell/Bar.hs"
|
srcBar <- readFile "test/data/template-haskell/Bar.hs"
|
||||||
withDirectory_ "test/data/file-mapping" $ do
|
withDirectory_ "test/data/file-mapping" $ do
|
||||||
let fm = [("Foo.hs", MemoryMapping $ Just srcFoo)
|
let fm = [("Foo.hs", srcFoo)
|
||||||
,("Bar.hs", MemoryMapping $ Just srcBar)]
|
,("Bar.hs", srcBar)]
|
||||||
res <- run defaultOptions $ do
|
res <- run defaultOptions{logLevel = GmDebug} $ do
|
||||||
mapM_ (uncurry loadMappedFile) fm
|
mapM_ (uncurry loadMappedFileSource) fm
|
||||||
types "Bar.hs" 5 1
|
types "Bar.hs" 5 1
|
||||||
res `shouldBe` unlines ["5 1 5 20 \"[Char]\""]
|
res `shouldBe` unlines ["5 1 5 20 \"[Char]\""]
|
||||||
|
Loading…
Reference in New Issue
Block a user