ghc-mod 2.0.2 → 2.0.3
raw patch · 4 files changed
+86/−76 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- ChangeLog +10/−0
- Language/Haskell/GhcMod/CabalApi.hs +63/−65
- ghc-mod.cabal +2/−2
- test/CabalApiSpec.hs +11/−9
ChangeLog view
@@ -1,3 +1,13 @@+2013-05-30 v2.0.3+ * Using finalizePackageDescription to enable "if else" in a cabal+ file.++2013-05-21 v2.0.2+ * Document fixes.++2013-05-21 v2.0.1+ * Document fixes.+ 2013-05-21 v2.0.0 * ghc-mod also provides a library (Language.Haskell.GhcMod)
Language/Haskell/GhcMod/CabalApi.hs view
@@ -2,26 +2,31 @@ module Language.Haskell.GhcMod.CabalApi ( fromCabalFile- , cabalParseFile- , cabalBuildInfo+ , parseCabalFile , cabalAllDependPackages , cabalAllSourceDirs+ , cabalAllBuildInfo , getGHCVersion ) where -import Control.Applicative+import Control.Applicative ((<$>)) import Control.Exception (throwIO) import Data.List (intercalate)-import Data.Maybe (maybeToList, listToMaybe)+import Data.Maybe (maybeToList) import Data.Set (fromList, toList)-import Distribution.Package (Dependency(Dependency), PackageName(PackageName))+import Distribution.Package (Dependency(Dependency)+ , PackageName(PackageName)+ , PackageIdentifier(pkgName)) import Distribution.PackageDescription+import Distribution.PackageDescription.Configuration (finalizePackageDescription) import Distribution.PackageDescription.Parse (readPackageDescription)+import Distribution.Simple.Compiler (CompilerId(..), CompilerFlavor(..)) import Distribution.Simple.Program (ghcProgram) import Distribution.Simple.Program.Types (programName, programFindVersion)+import Distribution.System (buildPlatform) import Distribution.Text (display) import Distribution.Verbosity (silent)-import Distribution.Version (versionBranch)+import Distribution.Version (versionBranch, Version) import Language.Haskell.GhcMod.Types import System.FilePath @@ -31,33 +36,48 @@ -> Cradle -> IO ([GHCOption],[IncludeDir],[Package]) fromCabalFile ghcOptions cradle = do- cabal <- cabalParseFile cfile- case cabalBuildInfo cabal of- Nothing -> throwIO $ userError "cabal file is broken"- Just binfo -> return $ cookInfo ghcOptions cradle cabal binfo+ cabal <- parseCabalFile cfile+ return $ cookInfo ghcOptions cradle cabal where Just cfile = cradleCabalFile cradle -cookInfo :: [String] -> Cradle -> GenericPackageDescription -> BuildInfo+cookInfo :: [String] -> Cradle -> PackageDescription -> ([GHCOption],[IncludeDir],[Package])-cookInfo ghcOptions cradle cabal binfo = (gopts,idirs,depPkgs)+cookInfo ghcOptions cradle cabal = (gopts,idirs,depPkgs) where wdir = cradleCurrentDir cradle Just cdir = cradleCabalDir cradle Just cfile = cradleCabalFile cradle- gopts = getGHCOptions ghcOptions binfo- idirs = includeDirectories cdir wdir $ cabalAllSourceDirs cabal- depPkgs = removeMe cfile $ cabalAllDependPackages cabal+ buildInfos = cabalAllBuildInfo cabal+ gopts = getGHCOptions ghcOptions $ head buildInfos+ idirs = includeDirectories cdir wdir $ cabalAllSourceDirs buildInfos+ depPkgs = removeMe cfile $ cabalAllDependPackages buildInfos removeMe :: FilePath -> [String] -> [String] removeMe cabalfile = filter (/= me) where me = dropExtension $ takeFileName cabalfile +includeDirectories :: String -> String -> [FilePath] -> [String]+includeDirectories cdir wdir [] = uniqueAndSort [cdir,wdir]+includeDirectories cdir wdir dirs = uniqueAndSort (map (cdir </>) dirs ++ [cdir,wdir])+ ---------------------------------------------------------------- -cabalParseFile :: FilePath -> IO GenericPackageDescription-cabalParseFile = readPackageDescription silent+parseCabalFile :: FilePath -> IO PackageDescription+parseCabalFile file = do+ cid <- getGHCId+ epgd <- readPackageDescription silent file+ case toPkgDesc cid epgd of+ Left deps -> throwIO $ userError $ show deps ++ " are not installed"+ Right (pd,_) -> if nullPkg pd+ then throwIO $ userError $ file ++ " is broken"+ else return pd+ where+ toPkgDesc cid = finalizePackageDescription [] (const True) buildPlatform cid []+ nullPkg pd = name == ""+ where+ PackageName name = pkgName (package pd) ---------------------------------------------------------------- @@ -71,56 +91,26 @@ ---------------------------------------------------------------- --- Causes error, catched in the upper function.-cabalBuildInfo :: GenericPackageDescription -> Maybe BuildInfo-cabalBuildInfo pd = fromLibrary pd <|> fromExecutable pd+cabalAllBuildInfo :: PackageDescription -> [BuildInfo]+cabalAllBuildInfo pd = libBI ++ execBI ++ testBI ++ benchBI where- fromLibrary c = libBuildInfo . condTreeData <$> condLibrary c- fromExecutable c = buildInfo . condTreeData . snd <$> listToMaybe (condExecutables c)+ libBI = map libBuildInfo $ maybeToList $ library pd+ execBI = map buildInfo $ executables pd+ testBI = map testBuildInfo $ testSuites pd+ benchBI = map benchmarkBuildInfo $ benchmarks pd ---------------------------------------------------------------- -cabalAllSourceDirs :: GenericPackageDescription -> [FilePath]-cabalAllSourceDirs = fromPackageDescription (f libBuildInfo) (f buildInfo) (f testBuildInfo) (f benchmarkBuildInfo)- where- f getBuildInfo = concatMap (hsSourceDirs . getBuildInfo . condTreeData)--cabalAllDependPackages :: GenericPackageDescription -> [Package]-cabalAllDependPackages pd = uniqueAndSort pkgs- where- pkgs = map getDependencyPackageName $ cabalAllDependency pd--cabalAllDependency :: GenericPackageDescription -> [Dependency]-cabalAllDependency = fromPackageDescription getDeps getDeps getDeps getDeps- where- getDeps :: [Tree a] -> [Dependency]- getDeps = concatMap condTreeConstraints--getDependencyPackageName :: Dependency -> Package-getDependencyPackageName (Dependency (PackageName nm) _) = nm+cabalAllSourceDirs :: [BuildInfo] -> [FilePath]+cabalAllSourceDirs bis = uniqueAndSort $ concatMap hsSourceDirs bis ---------------------------------------------------------------- -type Tree = CondTree ConfVar [Dependency]--fromPackageDescription :: ([Tree Library] -> [a])- -> ([Tree Executable] -> [a])- -> ([Tree TestSuite] -> [a])- -> ([Tree Benchmark] -> [a])- -> GenericPackageDescription- -> [a]-fromPackageDescription f1 f2 f3 f4 pd = lib ++ exe ++ tests ++ bench+cabalAllDependPackages :: [BuildInfo] -> [Package]+cabalAllDependPackages bis = uniqueAndSort $ pkgs where- lib = f1 . maybeToList . condLibrary $ pd- exe = f2 . map snd . condExecutables $ pd- tests = f3 . map snd . condTestSuites $ pd- bench = f4 . map snd . condBenchmarks $ pd--------------------------------------------------------------------includeDirectories :: String -> String -> [FilePath] -> [String]-includeDirectories cdir wdir [] = uniqueAndSort [cdir,wdir]-includeDirectories cdir wdir dirs = uniqueAndSort (map (cdir </>) dirs ++ [cdir,wdir])+ pkgs = map getDependencyPackageName $ concatMap targetBuildDepends bis+ getDependencyPackageName (Dependency (PackageName nm) _) = nm ---------------------------------------------------------------- @@ -131,14 +121,22 @@ -- | Getting GHC version. 7.6.3 becames 706 in the second of the result. getGHCVersion :: IO (GHCVersion, Int)-getGHCVersion = ghcVer >>= toTupple+getGHCVersion = toTupple <$> getGHC where- ghcVer = programFindVersion ghcProgram silent (programName ghcProgram)- toTupple Nothing = throwIO $ userError "ghc not found"- toTupple (Just v)- | length vs < 2 = return (verstr, 0)- | otherwise = return (verstr, ver)+ toTupple v+ | length vs < 2 = (verstr, 0)+ | otherwise = (verstr, ver) where vs = versionBranch v ver = (vs !! 0) * 100 + (vs !! 1) verstr = intercalate "." . map show $ vs++getGHCId :: IO CompilerId+getGHCId = CompilerId GHC <$> getGHC++getGHC :: IO Version+getGHC = do+ mv <- programFindVersion ghcProgram silent (programName ghcProgram)+ case mv of+ Nothing -> throwIO $ userError "ghc not found"+ Just v -> return $ v
ghc-mod.cabal view
@@ -1,5 +1,5 @@ Name: ghc-mod-Version: 2.0.2+Version: 2.0.3 Author: Kazu Yamamoto <kazu@iij.ad.jp> Maintainer: Kazu Yamamoto <kazu@iij.ad.jp> License: BSD3@@ -14,7 +14,7 @@ This package includes the ghc-mod command, the ghc-mod library, and Emacs front-end (for historical reasons).- For more information, please see ts home page.+ For more information, please see its home page. Category: Development Cabal-Version: >= 1.10
test/CabalApiSpec.hs view
@@ -1,27 +1,29 @@+{-# LANGUAGE ScopedTypeVariables #-}+ module CabalApiSpec where import Control.Applicative+import Control.Exception import Language.Haskell.GhcMod.CabalApi import Test.Hspec spec :: Spec spec = do+ describe "parseCabalFile" $ do+ it "throws an exception if the cabal file is broken" $ do+ parseCabalFile "test/data/broken-cabal/broken.cabal" `shouldThrow` (\(e::IOException) -> True)+ describe "cabalAllDependPackages" $ do it "extracts dependent packages" $ do- pkgs <- cabalAllDependPackages <$> cabalParseFile "test/data/cabalapi.cabal"+ pkgs <- cabalAllDependPackages . cabalAllBuildInfo <$> parseCabalFile "test/data/cabalapi.cabal" pkgs `shouldBe` ["Cabal","base","template-haskell"] describe "cabalAllSourceDirs" $ do it "extracts all hs-source-dirs" $ do- dirs <- cabalAllSourceDirs <$> cabalParseFile "test/data/check-test-subdir/check-test-subdir.cabal"+ dirs <- cabalAllSourceDirs . cabalAllBuildInfo <$> parseCabalFile "test/data/check-test-subdir/check-test-subdir.cabal" dirs `shouldBe` ["src", "test"] describe "cabalBuildInfo" $ do it "extracts build info" $ do- info <- cabalBuildInfo <$> cabalParseFile "test/data/cabalapi.cabal"- let infoStr = show info- infoStr `shouldBe` "Just (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 = []})"-- it "returns Nothing if the cabal file is broken" $ do- info <- cabalBuildInfo <$> cabalParseFile "test/data/broken-cabal/broken.cabal"- info `shouldBe` Nothing+ info <- cabalAllBuildInfo <$> 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 = []})))]}]"