diff --git a/Cabal.hs b/Cabal.hs index ab51d47..a7f6e57 100644 --- a/Cabal.hs +++ b/Cabal.hs @@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings, RecordWildCards #-} -module Cabal (initializeGHC) where +module Cabal (initializeGHC, getDirs, fromCabal) where import CabalApi (cabalParseFile, cabalBuildInfo, cabalDependPackages) import Control.Applicative @@ -30,20 +30,26 @@ initializeGHC opt fileName ghcOptions logging = withCabal ||> withoutCabal logReader <- initSession opt ghcOptions importDirs Nothing logging return (fileName,logReader) withCabal = do - (owdir,cdir,cfile) <- liftIO getDirs - cabal <- liftIO $ cabalParseFile cfile - binfo@BuildInfo{..} <- liftIO $ cabalBuildInfo cabal - let exts = map (addX . Gap.extensionToString) $ usedExtensions binfo - lang = maybe "-XHaskell98" (addX . show) defaultLanguage - libs = map ("-l" ++) extraLibs - libDirs = map ("-L" ++) extraLibDirs - gopts = ghcOptions ++ exts ++ [lang] ++ libs ++ libDirs - idirs = case hsSourceDirs of - [] -> [cdir,owdir] - dirs -> map (cdir ) dirs ++ [owdir] - depPkgs <- liftIO $ cabalDependPackages cabal + (gopts,idirs,depPkgs) <- liftIO $ fromCabal ghcOptions logReader <- initSession opt gopts idirs (Just depPkgs) logging return (fileName,logReader) + +fromCabal :: [String] -> IO ([String], [FilePath], [String]) +fromCabal ghcOptions = do + (owdir,cdir,cfile) <- getDirs + cabal <- cabalParseFile cfile + binfo@BuildInfo{..} <- cabalBuildInfo cabal + let exts = map (addX . Gap.extensionToString) $ usedExtensions binfo + lang = maybe "-XHaskell98" (addX . show) defaultLanguage + libs = map ("-l" ++) extraLibs + libDirs = map ("-L" ++) extraLibDirs + gopts = ghcOptions ++ exts ++ [lang] ++ libs ++ libDirs + idirs = case hsSourceDirs of + [] -> [cdir,owdir] + dirs -> map (cdir ) dirs ++ [owdir] + depPkgs <- cabalDependPackages cabal + return (gopts,idirs,depPkgs) + where addX = ("-X" ++) ---------------------------------------------------------------- diff --git a/ghc-mod.cabal b/ghc-mod.cabal index 9f1969e..4bdb7f7 100644 --- a/ghc-mod.cabal +++ b/ghc-mod.cabal @@ -68,6 +68,8 @@ Test-Suite spec Type: exitcode-stdio-1.0 Other-Modules: Expectation BrowseSpec + CabalSpec + CabalApiSpec FlagSpec LangSpec LintSpec diff --git a/test/CabalApiSpec.hs b/test/CabalApiSpec.hs new file mode 100644 index 0000000..d51f868 --- /dev/null +++ b/test/CabalApiSpec.hs @@ -0,0 +1,17 @@ +module CabalApiSpec where + +import Test.Hspec +import CabalApi + +spec :: Spec +spec = do + describe "cabalDependPackages" $ do + it "extracts dependent packages" $ do + pkgs <- cabalParseFile "test/data/cabalapi.cabal" >>= cabalDependPackages + pkgs `shouldBe` ["Cabal","base","containers","convertible","directory","filepath","ghc","ghc-paths","ghc-syb-utils","hlint","hspec","io-choice","old-time","process","regex-posix","syb","time","transformers"] + + describe "cabalBuildInfo" $ do + it "extracts build info" $ do + info <- cabalParseFile "test/data/cabalapi.cabal" >>= cabalBuildInfo + let infoStr = show info + infoStr `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 = []}" diff --git a/test/CabalSpec.hs b/test/CabalSpec.hs new file mode 100644 index 0000000..eda834b --- /dev/null +++ b/test/CabalSpec.hs @@ -0,0 +1,22 @@ +module CabalSpec where + +import Control.Applicative +import System.Directory +import Test.Hspec +import Cabal +import Expectation + +spec :: Spec +spec = do + describe "getDirs" $ do + it "obtains two directories and a cabal file" $ do + len <- length <$> getCurrentDirectory + withDirectory "test/data/subdir1/subdir2" $ do + (x,y,z) <- getDirs + (drop len x, drop len y, drop len z) `shouldBe` ("/test/data/subdir1/subdir2","/test/data","/test/data/cabalapi.cabal") + + describe "getDirs" $ do + it "obtains two directories and a cabal file" $ do + withDirectory "test/data/subdir1/subdir2" $ do + (x,y,z) <- fromCabal [] + (x,y,z) `shouldBe` (["-XHaskell98"],["/Users/kazu/work/ghc-mod/test/data","/Users/kazu/work/ghc-mod/test/data/subdir1/subdir2"],["Cabal","base","containers","convertible","directory","filepath","ghc","ghc-paths","ghc-syb-utils","hlint","hspec","io-choice","old-time","process","regex-posix","syb","time","transformers"]) diff --git a/test/Expectation.hs b/test/Expectation.hs index 3fbf6aa..3794af1 100644 --- a/test/Expectation.hs +++ b/test/Expectation.hs @@ -1,8 +1,15 @@ module Expectation where import Test.Hspec +import System.Directory +import Control.Exception as E shouldContain :: Eq a => [a] -> a -> Expectation shouldContain containers element = do let res = element `elem` containers res `shouldBe` True + +withDirectory :: FilePath -> IO a -> IO a +withDirectory dir action = bracket getCurrentDirectory + setCurrentDirectory + (\_ -> setCurrentDirectory dir >> action) diff --git a/test/data/cabalapi.cabal b/test/data/cabalapi.cabal new file mode 100644 index 0000000..820a4aa --- /dev/null +++ b/test/data/cabalapi.cabal @@ -0,0 +1,97 @@ +Name: ghc-mod +Version: 1.11.3 +Author: Kazu Yamamoto +Maintainer: Kazu Yamamoto +License: BSD3 +License-File: LICENSE +Homepage: http://www.mew.org/~kazu/proj/ghc-mod/ +Synopsis: Happy Haskell programming on Emacs/Vim +Description: This packages includes Elisp files + and a Haskell command, "ghc-mod". + "ghc*.el" enable completion of + Haskell symbols on Emacs. + Flymake is also integrated. + "ghc-mod" is a backend of "ghc*.el". + It lists up all installed modules + or extracts names of functions, classes, + and data declarations. + To use "ghc-mod" on Vim, + see or + +Category: Development +Cabal-Version: >= 1.6 +Build-Type: Simple +Data-Dir: elisp +Data-Files: Makefile ghc.el ghc-func.el ghc-doc.el ghc-comp.el + ghc-flymake.el ghc-command.el ghc-info.el + ghc-ins-mod.el ghc-indent.el +Executable ghc-mod + Main-Is: GHCMod.hs + Other-Modules: Browse + CabalApi + Cabal + CabalDev + Check + ErrMsg + Flag + GHCApi + GHCChoice + Gap + Info + Lang + Lint + List + Paths_ghc_mod + Types + GHC-Options: -Wall + Build-Depends: base >= 4.0 && < 5 + , Cabal >= 1.10 + , containers + , convertible + , directory + , filepath + , ghc + , ghc-paths + , ghc-syb-utils + , hlint >= 1.7.1 + , io-choice + , old-time + , process + , regex-posix + , syb + , time + , transformers + +Test-Suite spec + Main-Is: Spec.hs + Hs-Source-Dirs: test, . + Type: exitcode-stdio-1.0 + Other-Modules: Expectation + BrowseSpec + CabalApiSpec + FlagSpec + LangSpec + LintSpec + ListSpec + Build-Depends: base >= 4.0 && < 5 + , Cabal >= 1.10 + , containers + , convertible + , directory + , filepath + , ghc + , ghc-paths + , ghc-syb-utils + , hlint >= 1.7.1 + , io-choice + , old-time + , process + , regex-posix + , syb + , time + , transformers + , hspec + +Source-Repository head + Type: git + Location: git://github.com/kazu-yamamoto/ghc-mod.git diff --git a/test/data/subdir1/subdir2/dummy b/test/data/subdir1/subdir2/dummy new file mode 100644 index 0000000..421376d --- /dev/null +++ b/test/data/subdir1/subdir2/dummy @@ -0,0 +1 @@ +dummy