Skip to content
This repository was archived by the owner on Apr 25, 2020. It is now read-only.

Commit 496f53a

Browse files
committed
Merge pull request #137 from nh2/multiple-files
Multiple files
2 parents fc77e05 + 4758a60 commit 496f53a

8 files changed

Lines changed: 48 additions & 29 deletions

File tree

Language/Haskell/GhcMod/Check.hs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,29 @@ import Prelude
1616
-- Warnings and errors are returned.
1717
checkSyntax :: Options
1818
-> Cradle
19-
-> FilePath -- ^ A target file
19+
-> [FilePath] -- ^ The target files
2020
-> IO String
21-
checkSyntax opt cradle file = unlines <$> withGHC file (check opt cradle file)
21+
checkSyntax _ _ [] = error "ghc-mod: checkSyntax: No files given"
22+
checkSyntax opt cradle files = unlines <$> withGHC sessionName (check opt cradle files)
23+
where
24+
sessionName = case files of
25+
[file] -> file
26+
_ -> "MultipleFiles"
2227

2328
----------------------------------------------------------------
2429

2530
-- | Checking syntax of a target file using GHC.
2631
-- Warnings and errors are returned.
2732
check :: Options
2833
-> Cradle
29-
-> FilePath -- ^ A target file
34+
-> [FilePath] -- ^ The target files
3035
-> Ghc [String]
31-
check opt cradle fileName = checkIt `gcatch` handleErrMsg ls
36+
check _ _ [] = error "ghc-mod: check: No files given"
37+
check opt cradle fileNames = checkIt `gcatch` handleErrMsg ls
3238
where
3339
checkIt = do
3440
readLog <- initializeFlagsWithCradle opt cradle options True
35-
setTargetFile fileName
41+
setTargetFiles fileNames
3642
checkSlowAndSet
3743
void $ load LoadAllTargets
3844
liftIO readLog

Language/Haskell/GhcMod/Debug.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ debug opt cradle ver fileName = do
3636
return (ghcOpts opt, [], [])
3737
[fast] <- do
3838
void $ initializeFlagsWithCradle opt cradle gopts True
39-
setTargetFile fileName
39+
setTargetFiles [fileName]
4040
pure . canCheckFast <$> depanal [] False
4141
return [
4242
"GHC version: " ++ ver

Language/Haskell/GhcMod/GHCApi.hs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Language.Haskell.GhcMod.GHCApi (
55
, withGHCDummyFile
66
, initializeFlags
77
, initializeFlagsWithCradle
8-
, setTargetFile
8+
, setTargetFiles
99
, getDynamicFlags
1010
, setSlowDynFlags
1111
, checkSlowAndSet
@@ -154,11 +154,12 @@ modifyFlagsWithOpts dflags cmdOpts =
154154

155155
----------------------------------------------------------------
156156

157-
-- | Set the file that GHC will load / compile
158-
setTargetFile :: (GhcMonad m) => String -> m ()
159-
setTargetFile file = do
160-
target <- guessTarget file Nothing
161-
setTargets [target]
157+
-- | Set the files that GHC will load / compile
158+
setTargetFiles :: (GhcMonad m) => [String] -> m ()
159+
setTargetFiles [] = error "ghc-mod: setTargetFiles: No target files given"
160+
setTargetFiles files = do
161+
targets <- forM files $ \file -> guessTarget file Nothing
162+
setTargets targets
162163

163164
----------------------------------------------------------------
164165

Language/Haskell/GhcMod/Info.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ inModuleContext cmd opt cradle file modstr action errmsg =
148148
valid = do
149149
void $ initializeFlagsWithCradle opt cradle ["-w:"] False
150150
when (cmd == Info) setSlowDynFlags
151-
setTargetFile file
151+
setTargetFiles [file]
152152
checkSlowAndSet
153153
void $ load LoadAllTargets
154154
doif setContextFromTarget action

Language/Haskell/GhcMod/Internal.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Language.Haskell.GhcMod.Internal (
55
LogReader
66
, GHCOption
77
, initializeFlagsWithCradle
8-
, setTargetFile
8+
, setTargetFiles
99
, checkSlowAndSet
1010
, getDynamicFlags
1111
) where

src/GHCMod.hs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module Main where
44

55
import Control.Applicative
66
import Control.Exception
7+
import Control.Monad
78
import Data.Typeable
89
import Data.Version
910
import Language.Haskell.GhcMod
@@ -12,6 +13,7 @@ import Prelude
1213
import System.Console.GetOpt
1314
import System.Directory
1415
import System.Environment (getArgs)
16+
import System.Exit (exitFailure)
1517
import System.IO (hPutStr, hPutStrLn, stdout, stderr, hSetEncoding, utf8)
1618

1719
----------------------------------------------------------------
@@ -26,8 +28,8 @@ usage = "ghc-mod version " ++ showVersion version ++ "\n"
2628
++ "\t ghc-mod lang [-l]\n"
2729
++ "\t ghc-mod flag [-l]\n"
2830
++ "\t ghc-mod browse" ++ ghcOptHelp ++ "[-l] [-o] [-d] <module> [<module> ...]\n"
29-
++ "\t ghc-mod check" ++ ghcOptHelp ++ "<HaskellFile>\n"
30-
++ "\t ghc-mod expand" ++ ghcOptHelp ++ "<HaskellFile>\n"
31+
++ "\t ghc-mod check" ++ ghcOptHelp ++ "<HaskellFiles...>\n"
32+
++ "\t ghc-mod expand" ++ ghcOptHelp ++ "<HaskellFiles...>\n"
3133
++ "\t ghc-mod debug" ++ ghcOptHelp ++ "<HaskellFile>\n"
3234
++ "\t ghc-mod info" ++ ghcOptHelp ++ "<HaskellFile> <module> <expression>\n"
3335
++ "\t ghc-mod type" ++ ghcOptHelp ++ "<HaskellFile> <module> <line-no> <column-no>\n"
@@ -70,6 +72,7 @@ parseArgs spec argv
7072
----------------------------------------------------------------
7173

7274
data GHCModError = SafeList
75+
| TooManyArguments String
7376
| NoSuchCommand String
7477
| CmdArg [String]
7578
| FileNotExist String deriving (Show, Typeable)
@@ -93,15 +96,19 @@ main = flip catches handlers $ do
9396
cmdArg2 = cmdArg !. 2
9497
cmdArg3 = cmdArg !. 3
9598
cmdArg4 = cmdArg !. 4
99+
remainingArgs = tail cmdArg
100+
nArgs n f = if length remainingArgs == n
101+
then f
102+
else throw (TooManyArguments cmdArg0)
96103
res <- case cmdArg0 of
97-
"browse" -> concat <$> mapM (browseModule opt) (tail cmdArg)
104+
"browse" -> concat <$> mapM (browseModule opt) remainingArgs
98105
"list" -> listModules opt
99-
"check" -> checkSyntax opt cradle cmdArg1
100-
"expand" -> checkSyntax opt { expandSplice = True } cradle cmdArg1
101-
"debug" -> debugInfo opt cradle strVer cmdArg1
102-
"type" -> typeExpr opt cradle cmdArg1 cmdArg2 (read cmdArg3) (read cmdArg4)
103-
"info" -> infoExpr opt cradle cmdArg1 cmdArg2 cmdArg3
104-
"lint" -> withFile (lintSyntax opt) cmdArg1
106+
"check" -> checkSyntax opt cradle remainingArgs
107+
"expand" -> checkSyntax opt { expandSplice = True } cradle remainingArgs
108+
"debug" -> nArgs 1 $ debugInfo opt cradle strVer cmdArg1
109+
"type" -> nArgs 4 $ typeExpr opt cradle cmdArg1 cmdArg2 (read cmdArg3) (read cmdArg4)
110+
"info" -> nArgs 3 infoExpr opt cradle cmdArg1 cmdArg2 cmdArg3
111+
"lint" -> nArgs 1 withFile (lintSyntax opt) cmdArg1
105112
"lang" -> listLanguages opt
106113
"flag" -> listFlags opt
107114
"boot" -> do
@@ -110,14 +117,19 @@ main = flip catches handlers $ do
110117
flags <- listFlags opt
111118
pre <- concat <$> mapM (browseModule opt) preBrowsedModules
112119
return $ mods ++ langs ++ flags ++ pre
120+
"help" -> return $ usageInfo usage argspec
113121
cmd -> throw (NoSuchCommand cmd)
114122
putStr res
115123
where
116-
handlers = [Handler handler1, Handler handler2]
124+
handlers = [Handler (handleThenExit handler1), Handler (handleThenExit handler2)]
125+
handleThenExit handler = \e -> handler e >> exitFailure
117126
handler1 :: ErrorCall -> IO ()
118127
handler1 = print -- for debug
119128
handler2 :: GHCModError -> IO ()
120129
handler2 SafeList = printUsage
130+
handler2 (TooManyArguments cmd) = do
131+
hPutStrLn stderr $ "\"" ++ cmd ++ "\": Too many arguments"
132+
printUsage
121133
handler2 (NoSuchCommand cmd) = do
122134
hPutStrLn stderr $ "\"" ++ cmd ++ "\" not supported"
123135
printUsage

test/CabalApiSpec.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ spec :: Spec
1111
spec = do
1212
describe "parseCabalFile" $ do
1313
it "throws an exception if the cabal file is broken" $ do
14-
parseCabalFile "test/data/broken-cabal/broken.cabal" `shouldThrow` (\(e::IOException) -> True)
14+
parseCabalFile "test/data/broken-cabal/broken.cabal" `shouldThrow` (\(_::IOException) -> True)
1515

1616
describe "cabalAllDependPackages" $ do
1717
it "extracts dependent packages" $ do

test/CheckSpec.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,24 @@ spec = do
1414
withDirectory_ "test/data/ghc-mod-check" $ do
1515
(strVer,_) <- getGHCVersion
1616
cradle <- findCradle Nothing strVer
17-
res <- checkSyntax defaultOptions cradle "main.hs"
17+
res <- checkSyntax defaultOptions cradle ["main.hs"]
1818
res `shouldBe` "main.hs:5:1:Warning: Top-level binding with no type signature: main :: IO ()\NUL\n"
1919

2020
it "can check even if a test module imports another test module located at different directory" $ do
2121
withDirectory_ "test/data/check-test-subdir" $ do
2222
cradle <- getGHCVersion >>= findCradle Nothing . fst
23-
res <- checkSyntax defaultOptions cradle "test/Bar/Baz.hs"
23+
res <- checkSyntax defaultOptions cradle ["test/Bar/Baz.hs"]
2424
res `shouldSatisfy` (("test" </> "Foo.hs:3:1:Warning: Top-level binding with no type signature: foo :: [Char]\NUL\n") `isSuffixOf`)
2525

2626
it "can detect mutually imported modules" $ do
2727
withDirectory_ "test/data" $ do
2828
(strVer,_) <- getGHCVersion
2929
cradle <- findCradle Nothing strVer
30-
res <- checkSyntax defaultOptions cradle "Mutual1.hs"
30+
res <- checkSyntax defaultOptions cradle ["Mutual1.hs"]
3131
res `shouldSatisfy` ("Module imports form a cycle" `isInfixOf`)
3232

3333
it "can check a module using QuasiQuotes" $ do
3434
withDirectory_ "test/data" $ do
3535
cradle <- getGHCVersion >>= findCradle Nothing . fst
36-
res <- checkSyntax defaultOptions cradle "Baz.hs"
36+
res <- checkSyntax defaultOptions cradle ["Baz.hs"]
3737
res `shouldSatisfy` ("Baz.hs:5:1:Warning:" `isPrefixOf`)

0 commit comments

Comments
 (0)