From 74e84e89ac962513e0fe05db0573f3e8d8381e84 Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Thu, 17 Jul 2014 14:04:28 +0900 Subject: [PATCH 01/19] deleting GhcMod.Ghc. --- Language/Haskell/GhcMod.hs | 6 ++++++ Language/Haskell/GhcMod/Find.hs | 24 ++++++++++++++---------- Language/Haskell/GhcMod/Ghc.hs | 6 ------ ghc-mod.cabal | 1 - src/GHCMod.hs | 1 - src/GHCModi.hs | 3 +-- 6 files changed, 21 insertions(+), 20 deletions(-) delete mode 100644 Language/Haskell/GhcMod/Ghc.hs diff --git a/Language/Haskell/GhcMod.hs b/Language/Haskell/GhcMod.hs index 01c0e04..f1bb0f2 100644 --- a/Language/Haskell/GhcMod.hs +++ b/Language/Haskell/GhcMod.hs @@ -13,6 +13,8 @@ module Language.Haskell.GhcMod ( , ModuleString , Expression , GhcPkgDb + , Symbol + , SymbolDb -- * 'GhcMod' utilities , boot , browse @@ -21,6 +23,7 @@ module Language.Haskell.GhcMod ( , debugInfo , expandTemplate , findSymbol + , dumpSymbol , info , lint , pkgDoc @@ -31,6 +34,9 @@ module Language.Haskell.GhcMod ( , modules , languages , flags + -- * SymbolDb + , loadSymbolDb + , lookupSymbol ) where import Language.Haskell.GhcMod.Boot diff --git a/Language/Haskell/GhcMod/Find.hs b/Language/Haskell/GhcMod/Find.hs index f08ac77..e8ef11b 100644 --- a/Language/Haskell/GhcMod/Find.hs +++ b/Language/Haskell/GhcMod/Find.hs @@ -3,7 +3,7 @@ module Language.Haskell.GhcMod.Find ( Symbol , SymbolDb - , getSymbolDb + , loadSymbolDb , lookupSymbol , dumpSymbol , findSymbol @@ -44,10 +44,10 @@ import qualified Data.Map as M ---------------------------------------------------------------- --- | Type of key for `SymbolDb`. +-- | Type of function and operation names. type Symbol = String type Db = Map Symbol [ModuleString] --- | Database from 'Symbol' to modules. +-- | Database from 'Symbol' to \['ModuleString'\]. newtype SymbolDb = SymbolDb Db ---------------------------------------------------------------- @@ -65,23 +65,24 @@ packageConfDir = "package.conf.d" -- | Finding modules to which the symbol belong. findSymbol :: IOish m => Symbol -> GhcModT m String -findSymbol sym = convert' =<< lookupSymbol' sym <$> liftIO getSymbolDb +findSymbol sym = convert' =<< lookupSymbol' sym <$> liftIO loadSymbolDb lookupSymbol' :: Symbol -> SymbolDb -> [ModuleString] lookupSymbol' sym (SymbolDb db) = fromMaybe [] (M.lookup sym db) --- | Looking up 'SymbolDb' with 'Symbol' to find modules. +-- | Looking up 'SymbolDb' with 'Symbol' to \['ModuleString'\] +-- which will be concatenated. lookupSymbol :: Options -> Symbol -> SymbolDb -> String lookupSymbol opt sym db = convert opt $ lookupSymbol' sym db --------------------------------------------------------------- --- | Creating 'SymbolDb'. -getSymbolDb :: IO SymbolDb -getSymbolDb = SymbolDb <$> loadSymbolDb +-- | Loading a file and creates 'SymbolDb'. +loadSymbolDb :: IO SymbolDb +loadSymbolDb = SymbolDb <$> readSymbolDb -loadSymbolDb :: IO Db -loadSymbolDb = handle (\(SomeException _) -> return M.empty) $ do +readSymbolDb :: IO Db +readSymbolDb = handle (\(SomeException _) -> return M.empty) $ do file <- chop <$> readProcess "ghc-mod" ["dumpsym"] [] M.fromAscList . map conv . lines <$> readFile file where @@ -101,6 +102,9 @@ getPath = do [] -> return Nothing u:_ -> liftIO $ resolvePackageDb df u +-- | Dumping a set of ('Symbol',\['ModuleString'\]) to a file +-- if the file does not exist or is invalid. +-- The file name is printed. dumpSymbol :: IOish m => GhcModT m String dumpSymbol = do mdir <- getPath diff --git a/Language/Haskell/GhcMod/Ghc.hs b/Language/Haskell/GhcMod/Ghc.hs deleted file mode 100644 index ce9b3e2..0000000 --- a/Language/Haskell/GhcMod/Ghc.hs +++ /dev/null @@ -1,6 +0,0 @@ -module Language.Haskell.GhcMod.Ghc ( - -- * 'SymMdlDb' - module Language.Haskell.GhcMod.Find - ) where - -import Language.Haskell.GhcMod.Find diff --git a/ghc-mod.cabal b/ghc-mod.cabal index 9a23d1e..7587bb9 100644 --- a/ghc-mod.cabal +++ b/ghc-mod.cabal @@ -53,7 +53,6 @@ Library GHC-Options: -Wall Default-Extensions: ConstraintKinds, FlexibleContexts Exposed-Modules: Language.Haskell.GhcMod - Language.Haskell.GhcMod.Ghc Language.Haskell.GhcMod.Monad Language.Haskell.GhcMod.Internal Other-Modules: Language.Haskell.GhcMod.Boot diff --git a/src/GHCMod.hs b/src/GHCMod.hs index 561aa86..9018157 100644 --- a/src/GHCMod.hs +++ b/src/GHCMod.hs @@ -10,7 +10,6 @@ import qualified Control.Exception as E import Data.Typeable (Typeable) import Data.Version (showVersion) import Language.Haskell.GhcMod -import Language.Haskell.GhcMod.Ghc import Language.Haskell.GhcMod.Monad import Paths_ghc_mod import System.Console.GetOpt (OptDescr(..), ArgDescr(..), ArgOrder(..)) diff --git a/src/GHCModi.hs b/src/GHCModi.hs index 16554c3..f380ff6 100644 --- a/src/GHCModi.hs +++ b/src/GHCModi.hs @@ -34,7 +34,6 @@ import Data.Version (showVersion) import GHC (GhcMonad) import qualified GHC as G import Language.Haskell.GhcMod -import Language.Haskell.GhcMod.Ghc import Language.Haskell.GhcMod.Monad import Paths_ghc_mod import System.Console.GetOpt @@ -116,7 +115,7 @@ replace (x:xs) = x : replace xs ---------------------------------------------------------------- setupDB :: MVar SymbolDb -> IO () -setupDB mvar = getSymbolDb >>= putMVar mvar +setupDB mvar = loadSymbolDb >>= putMVar mvar ---------------------------------------------------------------- From cf0df265601dce3fe2bd9c471b018c353b5a042b Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Thu, 17 Jul 2014 14:30:42 +0900 Subject: [PATCH 02/19] Monad.hs is now exported by GhcMod.hs. --- Language/Haskell/GhcMod.hs | 6 +++-- Language/Haskell/GhcMod/Lint.hs | 1 + Language/Haskell/GhcMod/List.hs | 3 ++- Language/Haskell/GhcMod/Logger.hs | 1 + Language/Haskell/GhcMod/Monad.hs | 42 +++++++++++++++---------------- ghc-mod.cabal | 14 +++++------ src/GHCMod.hs | 1 - src/GHCModi.hs | 1 - 8 files changed, 36 insertions(+), 33 deletions(-) diff --git a/Language/Haskell/GhcMod.hs b/Language/Haskell/GhcMod.hs index f1bb0f2..cfb75f7 100644 --- a/Language/Haskell/GhcMod.hs +++ b/Language/Haskell/GhcMod.hs @@ -15,6 +15,7 @@ module Language.Haskell.GhcMod ( , GhcPkgDb , Symbol , SymbolDb + , module Language.Haskell.GhcMod.Monad -- * 'GhcMod' utilities , boot , browse @@ -41,16 +42,17 @@ module Language.Haskell.GhcMod ( import Language.Haskell.GhcMod.Boot import Language.Haskell.GhcMod.Browse +import Language.Haskell.GhcMod.CaseSplit import Language.Haskell.GhcMod.Check import Language.Haskell.GhcMod.Cradle import Language.Haskell.GhcMod.Debug +import Language.Haskell.GhcMod.FillSig import Language.Haskell.GhcMod.Find import Language.Haskell.GhcMod.Flag import Language.Haskell.GhcMod.Info import Language.Haskell.GhcMod.Lang import Language.Haskell.GhcMod.Lint import Language.Haskell.GhcMod.List +import Language.Haskell.GhcMod.Monad import Language.Haskell.GhcMod.PkgDoc -import Language.Haskell.GhcMod.FillSig -import Language.Haskell.GhcMod.CaseSplit import Language.Haskell.GhcMod.Types diff --git a/Language/Haskell/GhcMod/Lint.hs b/Language/Haskell/GhcMod/Lint.hs index 934f6d4..cfa915f 100644 --- a/Language/Haskell/GhcMod/Lint.hs +++ b/Language/Haskell/GhcMod/Lint.hs @@ -6,6 +6,7 @@ import CoreMonad (liftIO) import Language.Haskell.GhcMod.Logger (checkErrorPrefix) import Language.Haskell.GhcMod.Convert import Language.Haskell.GhcMod.Monad +import Language.Haskell.GhcMod.Types import Language.Haskell.HLint (hlint) -- | Checking syntax of a target file using hlint. diff --git a/Language/Haskell/GhcMod/List.hs b/Language/Haskell/GhcMod/List.hs index 675e21d..dd8f700 100644 --- a/Language/Haskell/GhcMod/List.hs +++ b/Language/Haskell/GhcMod/List.hs @@ -4,8 +4,9 @@ import Control.Applicative ((<$>)) import Control.Exception (SomeException(..)) import Data.List (nub, sort) import qualified GHC as G -import Language.Haskell.GhcMod.Monad import Language.Haskell.GhcMod.Convert +import Language.Haskell.GhcMod.Monad +import Language.Haskell.GhcMod.Types import Packages (pkgIdMap, exposedModules, sourcePackageId, display) import UniqFM (eltsUFM) diff --git a/Language/Haskell/GhcMod/Logger.hs b/Language/Haskell/GhcMod/Logger.hs index 6f9ce6c..e46c2d7 100644 --- a/Language/Haskell/GhcMod/Logger.hs +++ b/Language/Haskell/GhcMod/Logger.hs @@ -21,6 +21,7 @@ import Language.Haskell.GhcMod.DynFlags (withDynFlags, withCmdFlags) import qualified Language.Haskell.GhcMod.Gap as Gap import Language.Haskell.GhcMod.Convert (convert') import Language.Haskell.GhcMod.Monad +import Language.Haskell.GhcMod.Types import Outputable (PprStyle, SDoc) import System.FilePath (normalise) diff --git a/Language/Haskell/GhcMod/Monad.hs b/Language/Haskell/GhcMod/Monad.hs index 02e9df4..f4390a7 100644 --- a/Language/Haskell/GhcMod/Monad.hs +++ b/Language/Haskell/GhcMod/Monad.hs @@ -5,27 +5,27 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} module Language.Haskell.GhcMod.Monad ( - GhcMod - , runGhcMod - , liftGhcMod - , GhcModT - , IOish - , GhcModEnv(..) - , GhcModWriter - , GhcModState(..) - , runGhcModT' - , runGhcModT - , newGhcModEnv - , withErrorHandler - , toGhcMod - , options - , cradle - , Options(..) - , defaultOptions - , module Control.Monad.Reader.Class - , module Control.Monad.Writer.Class - , module Control.Monad.State.Class - ) where + -- * Monad Types + GhcMod + , GhcModT + , IOish + , GhcModEnv(..) + , GhcModState(..) + , GhcModWriter + -- * Monad utilities + , runGhcMod + , runGhcModT + , runGhcModT' + , withErrorHandler + , liftGhcMod + , toGhcMod + , newGhcModEnv + , options + , cradle + , module Control.Monad.Reader.Class + , module Control.Monad.Writer.Class + , module Control.Monad.State.Class + ) where #if __GLASGOW_HASKELL__ < 708 -- 'CoreMonad.MonadIO' and 'Control.Monad.IO.Class.MonadIO' are different diff --git a/ghc-mod.cabal b/ghc-mod.cabal index 7587bb9..228e2d5 100644 --- a/ghc-mod.cabal +++ b/ghc-mod.cabal @@ -53,18 +53,17 @@ Library GHC-Options: -Wall Default-Extensions: ConstraintKinds, FlexibleContexts Exposed-Modules: Language.Haskell.GhcMod - Language.Haskell.GhcMod.Monad Language.Haskell.GhcMod.Internal Other-Modules: Language.Haskell.GhcMod.Boot Language.Haskell.GhcMod.Browse - Language.Haskell.GhcMod.CabalApi - Language.Haskell.GhcMod.CabalConfig Language.Haskell.GhcMod.Cabal16 Language.Haskell.GhcMod.Cabal18 + Language.Haskell.GhcMod.CabalApi + Language.Haskell.GhcMod.CabalConfig Language.Haskell.GhcMod.CaseSplit Language.Haskell.GhcMod.Check - Language.Haskell.GhcMod.Cradle Language.Haskell.GhcMod.Convert + Language.Haskell.GhcMod.Cradle Language.Haskell.GhcMod.Debug Language.Haskell.GhcMod.Doc Language.Haskell.GhcMod.DynFlags @@ -75,16 +74,17 @@ Library Language.Haskell.GhcMod.GHCChoice Language.Haskell.GhcMod.Gap Language.Haskell.GhcMod.GhcPkg - Language.Haskell.GhcMod.Logger Language.Haskell.GhcMod.Info Language.Haskell.GhcMod.Lang Language.Haskell.GhcMod.Lint Language.Haskell.GhcMod.List + Language.Haskell.GhcMod.Logger + Language.Haskell.GhcMod.Monad Language.Haskell.GhcMod.PkgDoc - Language.Haskell.GhcMod.Utils - Language.Haskell.GhcMod.Types Language.Haskell.GhcMod.Read Language.Haskell.GhcMod.SrcUtils + Language.Haskell.GhcMod.Types + Language.Haskell.GhcMod.Utils Build-Depends: base >= 4.0 && < 5 , containers , deepseq diff --git a/src/GHCMod.hs b/src/GHCMod.hs index 9018157..8dac821 100644 --- a/src/GHCMod.hs +++ b/src/GHCMod.hs @@ -10,7 +10,6 @@ import qualified Control.Exception as E import Data.Typeable (Typeable) import Data.Version (showVersion) import Language.Haskell.GhcMod -import Language.Haskell.GhcMod.Monad import Paths_ghc_mod import System.Console.GetOpt (OptDescr(..), ArgDescr(..), ArgOrder(..)) import qualified System.Console.GetOpt as O diff --git a/src/GHCModi.hs b/src/GHCModi.hs index f380ff6..a33ad1f 100644 --- a/src/GHCModi.hs +++ b/src/GHCModi.hs @@ -34,7 +34,6 @@ import Data.Version (showVersion) import GHC (GhcMonad) import qualified GHC as G import Language.Haskell.GhcMod -import Language.Haskell.GhcMod.Monad import Paths_ghc_mod import System.Console.GetOpt import System.Directory (setCurrentDirectory) From 05f45f1d361ac59a67c0bd7c61baad3b60e95021 Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Thu, 17 Jul 2014 14:40:35 +0900 Subject: [PATCH 03/19] adding error handling. --- Language/Haskell/GhcMod/Find.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Language/Haskell/GhcMod/Find.hs b/Language/Haskell/GhcMod/Find.hs index e8ef11b..db7346c 100644 --- a/Language/Haskell/GhcMod/Find.hs +++ b/Language/Haskell/GhcMod/Find.hs @@ -19,7 +19,7 @@ import Data.List (groupBy, sort) import Data.List.Split (splitOn) import Data.Maybe (fromMaybe) import DynFlags (DynFlags(..), systemPackageConfig) -import Exception (handleIO) +import Exception (ghandle, handleIO) import qualified GHC as G import Language.Haskell.GhcMod.Convert import Language.Haskell.GhcMod.Monad @@ -113,7 +113,7 @@ dumpSymbol = do Just dir -> do let cache = dir symbolCache pkgdb = dir packageCache - do -- fixme: bracket + ghandle (\(SomeException _) -> return "") $ do create <- liftIO $ needToCreate cache pkgdb when create $ do sm <- getSymbol From cffa7463eb44d909b1bcf408f4574f9b12376122 Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Thu, 17 Jul 2014 17:16:44 +0900 Subject: [PATCH 04/19] adopting hlint's suggestions. --- Language/Haskell/GhcMod/CabalConfig.hs | 6 +++++- Language/Haskell/GhcMod/CaseSplit.hs | 2 +- Language/Haskell/GhcMod/Check.hs | 7 +++---- Language/Haskell/GhcMod/Convert.hs | 4 ++-- Language/Haskell/GhcMod/Cradle.hs | 3 +-- Language/Haskell/GhcMod/Debug.hs | 2 +- Language/Haskell/GhcMod/DynFlags.hs | 5 ++--- Language/Haskell/GhcMod/FillSig.hs | 28 +++++++++++++------------- Language/Haskell/GhcMod/Find.hs | 4 ++-- Language/Haskell/GhcMod/GHCApi.hs | 8 +++----- Language/Haskell/GhcMod/Lint.hs | 2 +- Language/Haskell/GhcMod/List.hs | 2 +- Language/Haskell/GhcMod/Logger.hs | 8 ++++---- Language/Haskell/GhcMod/Monad.hs | 4 ++-- Language/Haskell/GhcMod/Utils.hs | 2 +- 15 files changed, 43 insertions(+), 44 deletions(-) diff --git a/Language/Haskell/GhcMod/CabalConfig.hs b/Language/Haskell/GhcMod/CabalConfig.hs index 7392ae4..5612535 100644 --- a/Language/Haskell/GhcMod/CabalConfig.hs +++ b/Language/Haskell/GhcMod/CabalConfig.hs @@ -14,6 +14,10 @@ import Language.Haskell.GhcMod.Types import qualified Language.Haskell.GhcMod.Cabal16 as C16 import qualified Language.Haskell.GhcMod.Cabal18 as C18 +#ifndef MIN_VERSION_mtl +#define MIN_VERSION_mtl(x,y,z) 1 +#endif + import qualified Control.Exception as E import Control.Applicative ((<$>)) import Control.Monad (mplus) @@ -59,7 +63,7 @@ configDependencies :: PackageIdentifier -> CabalConfig -> [Package] configDependencies thisPkg config = map fromInstalledPackageId deps where deps :: [InstalledPackageId] - deps = case (deps18 `mplus` deps16) of + deps = case deps18 `mplus` deps16 of Right ps -> ps Left msg -> error msg diff --git a/Language/Haskell/GhcMod/CaseSplit.hs b/Language/Haskell/GhcMod/CaseSplit.hs index 01fe777..11871ca 100644 --- a/Language/Haskell/GhcMod/CaseSplit.hs +++ b/Language/Haskell/GhcMod/CaseSplit.hs @@ -184,7 +184,7 @@ getBindingText text srcSpan = [T.drop (sc - 1) $ T.take ec $ head lines_] else -- several lines let (first,rest,last_) = (head lines_, tail $ init lines_, last lines_) - in (T.drop (sc - 1) first) : rest ++ [T.take ec last_] + in T.drop (sc - 1) first : rest ++ [T.take ec last_] srcSpanDifference :: SrcSpan -> SrcSpan -> (Int,Int,Int,Int) srcSpanDifference b v = diff --git a/Language/Haskell/GhcMod/Check.hs b/Language/Haskell/GhcMod/Check.hs index f30a48d..cd6591c 100644 --- a/Language/Haskell/GhcMod/Check.hs +++ b/Language/Haskell/GhcMod/Check.hs @@ -19,7 +19,7 @@ checkSyntax :: IOish m => [FilePath] -- ^ The target files. -> GhcModT m String checkSyntax [] = return "" -checkSyntax files = withErrorHandler sessionName $ do +checkSyntax files = withErrorHandler sessionName $ either id id <$> check files where sessionName = case files of @@ -33,8 +33,7 @@ checkSyntax files = withErrorHandler sessionName $ do check :: IOish m => [FilePath] -- ^ The target files. -> GhcModT m (Either String String) -check fileNames = do - withLogger setAllWaringFlags $ setTargetFiles fileNames +check fileNames = withLogger setAllWaringFlags $ setTargetFiles fileNames ---------------------------------------------------------------- @@ -43,7 +42,7 @@ expandTemplate :: IOish m => [FilePath] -- ^ The target files. -> GhcModT m String expandTemplate [] = return "" -expandTemplate files = withErrorHandler sessionName $ do +expandTemplate files = withErrorHandler sessionName $ either id id <$> expand files where sessionName = case files of diff --git a/Language/Haskell/GhcMod/Convert.hs b/Language/Haskell/GhcMod/Convert.hs index ee1398b..295f888 100644 --- a/Language/Haskell/GhcMod/Convert.hs +++ b/Language/Haskell/GhcMod/Convert.hs @@ -81,14 +81,14 @@ instance ToString ((Int,Int,Int,Int),String) where toPlain opt x = tupToString opt x instance ToString (String, (Int,Int,Int,Int),[String]) where - toLisp opt (s,x,y) = toSexp2 $ [toLisp opt s, ('(' :) . fourIntsToString opt x . (')' :), toLisp opt y] + toLisp opt (s,x,y) = toSexp2 [toLisp opt s, ('(' :) . fourIntsToString opt x . (')' :), toLisp opt y] toPlain opt (s,x,y) = inter '\n' [toPlain opt s, fourIntsToString opt x, toPlain opt y] toSexp1 :: Options -> [String] -> Builder toSexp1 opt ss = ('(' :) . inter ' ' (map (quote opt) ss) . (')' :) toSexp2 :: [Builder] -> Builder -toSexp2 ss = ('(' :) . (inter ' ' ss) . (')' :) +toSexp2 ss = ('(' :) . inter ' ' ss . (')' :) fourIntsToString :: Options -> (Int,Int,Int,Int) -> Builder fourIntsToString _ (a,b,c,d) = (show a ++) . (' ' :) diff --git a/Language/Haskell/GhcMod/Cradle.hs b/Language/Haskell/GhcMod/Cradle.hs index ecfc1c8..3f2209d 100644 --- a/Language/Haskell/GhcMod/Cradle.hs +++ b/Language/Haskell/GhcMod/Cradle.hs @@ -22,8 +22,7 @@ import System.FilePath ((), takeDirectory) -- Find a sandbox according to a cabal sandbox config -- in a cabal directory. findCradle :: IO Cradle -findCradle = do - findCradle' =<< getCurrentDirectory +findCradle = findCradle' =<< getCurrentDirectory findCradle' :: FilePath -> IO Cradle findCradle' dir = cabalCradle dir ||> sandboxCradle dir ||> plainCradle dir diff --git a/Language/Haskell/GhcMod/Debug.hs b/Language/Haskell/GhcMod/Debug.hs index 994411d..d9cd186 100644 --- a/Language/Haskell/GhcMod/Debug.hs +++ b/Language/Haskell/GhcMod/Debug.hs @@ -16,7 +16,7 @@ debugInfo :: IOish m => GhcModT m String debugInfo = cradle >>= \c -> convert' =<< do CompilerOptions gopts incDir pkgs <- if isJust $ cradleCabalFile c then - (fromCabalFile c ||> simpleCompilerOption) + fromCabalFile c ||> simpleCompilerOption else simpleCompilerOption return [ diff --git a/Language/Haskell/GhcMod/DynFlags.hs b/Language/Haskell/GhcMod/DynFlags.hs index 76b6da1..a4c75d6 100644 --- a/Language/Haskell/GhcMod/DynFlags.hs +++ b/Language/Haskell/GhcMod/DynFlags.hs @@ -101,8 +101,7 @@ needsFallback = any (hasTHorQQ . G.ms_hspp_opts) -- | Return the 'DynFlags' currently in use in the GHC session. getDynamicFlags :: IO DynFlags -getDynamicFlags = do - G.runGhc (Just libdir) G.getSessionDynFlags +getDynamicFlags = G.runGhc (Just libdir) G.getSessionDynFlags withDynFlags :: GhcMonad m => (DynFlags -> DynFlags) @@ -136,7 +135,7 @@ setAllWaringFlags :: DynFlags -> DynFlags setAllWaringFlags df = df { warningFlags = allWarningFlags } allWarningFlags :: Gap.WarnFlags -allWarningFlags = unsafePerformIO $ do +allWarningFlags = unsafePerformIO $ G.runGhc (Just libdir) $ do df <- G.getSessionDynFlags df' <- addCmdOpts ["-Wall"] df diff --git a/Language/Haskell/GhcMod/FillSig.hs b/Language/Haskell/GhcMod/FillSig.hs index 4698af1..2e103c0 100644 --- a/Language/Haskell/GhcMod/FillSig.hs +++ b/Language/Haskell/GhcMod/FillSig.hs @@ -5,7 +5,7 @@ module Language.Haskell.GhcMod.FillSig ( ) where import Data.Char (isSymbol) -import Data.List (find, intercalate) +import Data.List (find) import Exception (ghandle, SomeException(..)) import GHC (GhcMonad, Id, ParsedModule(..), TypecheckedModule(..), DynFlags, SrcSpan, Type, GenLocated(L)) import qualified GHC as G @@ -45,7 +45,7 @@ sig file lineNo colNo = ghandle handler body whenFound opt (getSignature modSum lineNo colNo) $ \s -> case s of Signature loc names ty -> ("function", fourInts loc, map (initialBody dflag style ty) names) - InstanceDecl loc cls -> do + InstanceDecl loc cls -> ("instance", fourInts loc, map (\x -> initialBody dflag style (G.idType x) x) (Ty.classMethods cls)) @@ -109,8 +109,8 @@ initialBody' fname args = case initialBodyArgs args infiniteVars infiniteFns of [] -> fname arglist -> if isSymbolName fname - then (head arglist) ++ " " ++ fname ++ " " ++ (intercalate " " (tail arglist)) - else fname ++ " " ++ (intercalate " " arglist) + then head arglist ++ " " ++ fname ++ " " ++ unwords (tail arglist) + else fname ++ " " ++ unwords arglist ++ " = " ++ (if isSymbolName fname then "" else '_':fname) ++ "_body" initialBodyArgs :: [FnArg] -> [String] -> [String] -> [String] @@ -133,11 +133,11 @@ instance FnArgsInfo (G.HsType G.RdrName) (G.RdrName) where getFnArgs (G.HsForAllTy _ _ _ (L _ iTy)) = getFnArgs iTy getFnArgs (G.HsParTy (L _ iTy)) = getFnArgs iTy getFnArgs (G.HsFunTy (L _ lTy) (L _ rTy)) = (if fnarg lTy then FnArgFunction else FnArgNormal):getFnArgs rTy - where fnarg = \ty -> case ty of - (G.HsForAllTy _ _ _ (L _ iTy)) -> fnarg iTy - (G.HsParTy (L _ iTy)) -> fnarg iTy - (G.HsFunTy _ _) -> True - _ -> False + where fnarg ty = case ty of + (G.HsForAllTy _ _ _ (L _ iTy)) -> fnarg iTy + (G.HsParTy (L _ iTy)) -> fnarg iTy + (G.HsFunTy _ _) -> True + _ -> False getFnArgs _ = [] instance FnArgsInfo (HE.Type HE.SrcSpanInfo) (HE.Name HE.SrcSpanInfo) where @@ -146,11 +146,11 @@ instance FnArgsInfo (HE.Type HE.SrcSpanInfo) (HE.Name HE.SrcSpanInfo) where getFnArgs (HE.TyForall _ _ _ iTy) = getFnArgs iTy getFnArgs (HE.TyParen _ iTy) = getFnArgs iTy getFnArgs (HE.TyFun _ lTy rTy) = (if fnarg lTy then FnArgFunction else FnArgNormal):getFnArgs rTy - where fnarg = \ty -> case ty of - (HE.TyForall _ _ _ iTy) -> fnarg iTy - (HE.TyParen _ iTy) -> fnarg iTy - (HE.TyFun _ _ _) -> True - _ -> False + where fnarg ty = case ty of + (HE.TyForall _ _ _ iTy) -> fnarg iTy + (HE.TyParen _ iTy) -> fnarg iTy + (HE.TyFun _ _ _) -> True + _ -> False getFnArgs _ = [] instance FnArgsInfo Type Id where diff --git a/Language/Haskell/GhcMod/Find.hs b/Language/Haskell/GhcMod/Find.hs index db7346c..cd0a6aa 100644 --- a/Language/Haskell/GhcMod/Find.hs +++ b/Language/Haskell/GhcMod/Find.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE CPP, BangPatterns #-} +{-# LANGUAGE CPP #-} module Language.Haskell.GhcMod.Find ( Symbol @@ -118,7 +118,7 @@ dumpSymbol = do when create $ do sm <- getSymbol void . liftIO $ withFile cache WriteMode $ \hdl -> - mapM (hPutStrLn hdl . show) sm + mapM (hPrint hdl) sm return cache return $ ret ++ "\n" diff --git a/Language/Haskell/GhcMod/GHCApi.hs b/Language/Haskell/GhcMod/GHCApi.hs index b765698..a3ac817 100644 --- a/Language/Haskell/GhcMod/GHCApi.hs +++ b/Language/Haskell/GhcMod/GHCApi.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE ScopedTypeVariables, RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} module Language.Haskell.GhcMod.GHCApi ( ghcPkgDb @@ -42,8 +42,7 @@ modules :: G.PackageConfig -> [ModuleString] modules = map G.moduleNameString . G.exposedModules findModule :: ModuleString -> PkgDb -> [Package] -findModule m db = do - M.elems $ package `M.map` (containsModule `M.filter` db) +findModule m db = M.elems $ package `M.map` (containsModule `M.filter` db) where containsModule :: G.PackageConfig -> Bool containsModule pkgConf = @@ -83,5 +82,4 @@ localModuleInfo :: GhcMonad m => ModuleString -> m (Maybe G.ModuleInfo) localModuleInfo mdl = moduleInfo Nothing mdl bindings :: G.ModuleInfo -> [Binding] -bindings minfo = do - map (G.occNameString . G.getOccName) $ G.modInfoExports minfo +bindings minfo = map (G.occNameString . G.getOccName) $ G.modInfoExports minfo diff --git a/Language/Haskell/GhcMod/Lint.hs b/Language/Haskell/GhcMod/Lint.hs index cfa915f..b126e25 100644 --- a/Language/Haskell/GhcMod/Lint.hs +++ b/Language/Haskell/GhcMod/Lint.hs @@ -16,7 +16,7 @@ lint :: IOish m -> GhcModT m String lint file = do opt <- options - ghandle handler . pack =<< (liftIO $ hlint $ file : "--quiet" : hlintOpts opt) + ghandle handler . pack =<< liftIO (hlint $ file : "--quiet" : hlintOpts opt) where pack = convert' . map (init . show) -- init drops the last \n. handler (SomeException e) = return $ checkErrorPrefix ++ show e ++ "\n" diff --git a/Language/Haskell/GhcMod/List.hs b/Language/Haskell/GhcMod/List.hs index dd8f700..6450e5e 100644 --- a/Language/Haskell/GhcMod/List.hs +++ b/Language/Haskell/GhcMod/List.hs @@ -16,7 +16,7 @@ import UniqFM (eltsUFM) modules :: IOish m => GhcModT m String modules = do opt <- options - convert opt . (arrange opt) <$> (getModules `G.gcatch` handler) + convert opt . arrange opt <$> (getModules `G.gcatch` handler) where getModules = getExposedModules <$> G.getSessionDynFlags getExposedModules = concatMap exposedModules' diff --git a/Language/Haskell/GhcMod/Logger.hs b/Language/Haskell/GhcMod/Logger.hs index e46c2d7..5167372 100644 --- a/Language/Haskell/GhcMod/Logger.hs +++ b/Language/Haskell/GhcMod/Logger.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE BangPatterns, CPP #-} +{-# LANGUAGE CPP #-} module Language.Haskell.GhcMod.Logger ( withLogger @@ -63,9 +63,9 @@ withLogger :: IOish m -> GhcModT m () -> GhcModT m (Either String String) withLogger setDF body = ghandle sourceError $ do - logref <- liftIO $ newLogRef + logref <- liftIO newLogRef wflags <- filter ("-fno-warn" `isPrefixOf`) . ghcOpts <$> options - withDynFlags (setLogger logref . setDF) $ do + withDynFlags (setLogger logref . setDF) $ withCmdFlags wflags $ do body Right <$> readAndClearLogRef logref @@ -80,7 +80,7 @@ sourceError :: IOish m => SourceError -> GhcModT m (Either String String) sourceError err = do dflags <- G.getSessionDynFlags style <- toGhcMod getStyle - ret <- convert' $ (errBagToStrList dflags style . srcErrorMessages $ err) + ret <- convert' (errBagToStrList dflags style . srcErrorMessages $ err) return $ Left ret errBagToStrList :: DynFlags -> PprStyle -> Bag ErrMsg -> [String] diff --git a/Language/Haskell/GhcMod/Monad.hs b/Language/Haskell/GhcMod/Monad.hs index f4390a7..919289d 100644 --- a/Language/Haskell/GhcMod/Monad.hs +++ b/Language/Haskell/GhcMod/Monad.hs @@ -188,8 +188,8 @@ initSession :: GhcMonad m -> m () initSession build Options {..} CompilerOptions {..} = do df <- G.getSessionDynFlags - void $ G.setSessionDynFlags =<< (addCmdOpts ghcOptions - $ setModeSimple + void $ G.setSessionDynFlags =<< addCmdOpts ghcOptions + ( setModeSimple $ setIncludeDirs includeDirs $ setBuildEnv build $ setEmptyLogger diff --git a/Language/Haskell/GhcMod/Utils.hs b/Language/Haskell/GhcMod/Utils.hs index cd04a3e..365f1b9 100644 --- a/Language/Haskell/GhcMod/Utils.hs +++ b/Language/Haskell/GhcMod/Utils.hs @@ -18,7 +18,7 @@ extractParens str = extractParens' str 0 extractParens' (s:ss) level | s `elem` "([{" = s : extractParens' ss (level+1) | level == 0 = extractParens' ss 0 - | s `elem` "}])" && level == 1 = s:[] + | s `elem` "}])" && level == 1 = [s] | s `elem` "}])" = s : extractParens' ss (level-1) | otherwise = s : extractParens' ss level From e61aaed023a3f593234de2f9cb615df1a1425202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= Date: Thu, 17 Jul 2014 15:52:33 +0200 Subject: [PATCH 05/19] Make `readProcess'`more generic --- Language/Haskell/GhcMod/Utils.hs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Language/Haskell/GhcMod/Utils.hs b/Language/Haskell/GhcMod/Utils.hs index 365f1b9..9937e78 100644 --- a/Language/Haskell/GhcMod/Utils.hs +++ b/Language/Haskell/GhcMod/Utils.hs @@ -1,5 +1,6 @@ module Language.Haskell.GhcMod.Utils where +import MonadUtils (MonadIO, liftIO) import Control.Exception (bracket) import System.Directory (getCurrentDirectory, setCurrentDirectory) import System.Process (readProcessWithExitCode) @@ -22,12 +23,12 @@ extractParens str = extractParens' str 0 | s `elem` "}])" = s : extractParens' ss (level-1) | otherwise = s : extractParens' ss level -readProcess' :: String -> [String] -> IO String +readProcess' :: MonadIO m => String -> [String] -> m String readProcess' cmd opts = do - (rv,output,err) <- readProcessWithExitCode cmd opts "" + (rv,output,err) <- liftIO $ readProcessWithExitCode cmd opts "" case rv of ExitFailure val -> do - hPutStrLn stderr err + liftIO $ hPutStrLn stderr err fail $ cmd ++ " " ++ unwords opts ++ " (exit " ++ show val ++ ")" ExitSuccess -> return output From 15e288decf703a2db57fb4118d4ed6dbdc85c677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= Date: Thu, 17 Jul 2014 15:53:04 +0200 Subject: [PATCH 06/19] Remove some redundant stuff from test suite --- test/CheckSpec.hs | 1 - test/InfoSpec.hs | 7 ------- 2 files changed, 8 deletions(-) diff --git a/test/CheckSpec.hs b/test/CheckSpec.hs index 8b9334e..5fee185 100644 --- a/test/CheckSpec.hs +++ b/test/CheckSpec.hs @@ -2,7 +2,6 @@ module CheckSpec where import Data.List (isSuffixOf, isInfixOf, isPrefixOf) import Language.Haskell.GhcMod -import Language.Haskell.GhcMod.Cradle import System.FilePath import Test.Hspec diff --git a/test/InfoSpec.hs b/test/InfoSpec.hs index caba4da..adfcb32 100644 --- a/test/InfoSpec.hs +++ b/test/InfoSpec.hs @@ -4,7 +4,6 @@ module InfoSpec where import Control.Applicative ((<$>)) import Data.List (isPrefixOf) import Language.Haskell.GhcMod -import Language.Haskell.GhcMod.Cradle #if __GLASGOW_HASKELL__ < 706 import System.Environment.Executable (getExecutablePath) #else @@ -22,38 +21,32 @@ spec = do describe "types" $ do it "shows types of the expression and its outers" $ do withDirectory_ "test/data/ghc-mod-check" $ do - cradle <- findCradleWithoutSandbox res <- runD $ types "Data/Foo.hs" 9 5 res `shouldBe` "9 5 11 40 \"Int -> a -> a -> a\"\n7 1 11 40 \"Int -> Integer\"\n" it "works with a module using TemplateHaskell" $ do withDirectory_ "test/data" $ do - cradle <- findCradleWithoutSandbox res <- runD $ types "Bar.hs" 5 1 res `shouldBe` unlines ["5 1 5 20 \"[Char]\""] it "works with a module that imports another module using TemplateHaskell" $ do withDirectory_ "test/data" $ do - cradle <- findCradleWithoutSandbox res <- runD $ types "Main.hs" 3 8 res `shouldBe` unlines ["3 8 3 16 \"String -> IO ()\"", "3 8 3 20 \"IO ()\"", "3 1 3 20 \"IO ()\""] describe "info" $ do it "works for non-export functions" $ do withDirectory_ "test/data" $ do - cradle <- findCradleWithoutSandbox res <- runD $ info "Info.hs" "fib" res `shouldSatisfy` ("fib :: Int -> Int" `isPrefixOf`) it "works with a module using TemplateHaskell" $ do withDirectory_ "test/data" $ do - cradle <- findCradleWithoutSandbox res <- runD $ info "Bar.hs" "foo" res `shouldSatisfy` ("foo :: ExpQ" `isPrefixOf`) it "works with a module that imports another module using TemplateHaskell" $ do withDirectory_ "test/data" $ do - cradle <- findCradleWithoutSandbox res <- runD $ info "Main.hs" "bar" res `shouldSatisfy` ("bar :: [Char]" `isPrefixOf`) From 4f0f5f09a6acbadd6e5b3ca2f0e2402d39a901a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= Date: Thu, 17 Jul 2014 15:54:59 +0200 Subject: [PATCH 07/19] Remove `type Db` it's only used once and makes things less clear --- Language/Haskell/GhcMod/Find.hs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Language/Haskell/GhcMod/Find.hs b/Language/Haskell/GhcMod/Find.hs index cd0a6aa..403b7bc 100644 --- a/Language/Haskell/GhcMod/Find.hs +++ b/Language/Haskell/GhcMod/Find.hs @@ -46,9 +46,8 @@ import qualified Data.Map as M -- | Type of function and operation names. type Symbol = String -type Db = Map Symbol [ModuleString] -- | Database from 'Symbol' to \['ModuleString'\]. -newtype SymbolDb = SymbolDb Db +newtype SymbolDb = SymbolDb (Map Symbol [ModuleString]) ---------------------------------------------------------------- @@ -81,7 +80,7 @@ lookupSymbol opt sym db = convert opt $ lookupSymbol' sym db loadSymbolDb :: IO SymbolDb loadSymbolDb = SymbolDb <$> readSymbolDb -readSymbolDb :: IO Db +readSymbolDb :: IO (Map Symbol [ModuleString]) readSymbolDb = handle (\(SomeException _) -> return M.empty) $ do file <- chop <$> readProcess "ghc-mod" ["dumpsym"] [] M.fromAscList . map conv . lines <$> readFile file From 0e17e8e15af08cbd9e927c80b0b04b4d0a669d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= Date: Thu, 17 Jul 2014 16:14:35 +0200 Subject: [PATCH 08/19] Add a CPP macro when compiling modules for the test suite --- ghc-mod.cabal | 1 + 1 file changed, 1 insertion(+) diff --git a/ghc-mod.cabal b/ghc-mod.cabal index 228e2d5..0ce7704 100644 --- a/ghc-mod.cabal +++ b/ghc-mod.cabal @@ -197,6 +197,7 @@ Test-Suite spec Build-Depends: Cabal >= 1.18 if impl(ghc < 7.6.0) Build-Depends: executable-path + CPP-Options: -DSPEC=1 Source-Repository head Type: git From 3c1b560068c98afb6c021e744970f1d84152ed85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= Date: Thu, 17 Jul 2014 16:15:02 +0200 Subject: [PATCH 09/19] Short circuit export list when compiling spec --- Language/Haskell/GhcMod/Find.hs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Language/Haskell/GhcMod/Find.hs b/Language/Haskell/GhcMod/Find.hs index 403b7bc..818e652 100644 --- a/Language/Haskell/GhcMod/Find.hs +++ b/Language/Haskell/GhcMod/Find.hs @@ -1,13 +1,17 @@ {-# LANGUAGE CPP #-} -module Language.Haskell.GhcMod.Find ( +module Language.Haskell.GhcMod.Find +#ifndef SPEC + ( Symbol , SymbolDb , loadSymbolDb , lookupSymbol , dumpSymbol , findSymbol - ) where + ) +#endif + where import Config (cProjectVersion,cTargetPlatformString) import Control.Applicative ((<$>)) From c3b959a8e5872db67f539f87ed5b770adebf50b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= Date: Thu, 17 Jul 2014 16:16:12 +0200 Subject: [PATCH 10/19] Add FindSpec --- test/FindSpec.hs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 test/FindSpec.hs diff --git a/test/FindSpec.hs b/test/FindSpec.hs new file mode 100644 index 0000000..0eedcb4 --- /dev/null +++ b/test/FindSpec.hs @@ -0,0 +1,16 @@ +module FindSpec where + +import Control.Applicative ((<$>)) +import Data.List (isPrefixOf) +import Language.Haskell.GhcMod.Find +import Test.Hspec +import TestUtils + +import qualified Data.Map + +spec :: Spec +spec = do + describe "db <- loadSymbolDb" $ do + it "lookupSymbol' db \"head\" contains at least `Data.List'" $ do + db <- loadSymbolDb + lookupSymbol' "head" db `shouldContain` ["Data.List"] From 3c04e78ba779dfbc7e1bf3e1e8a75646df55814e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= Date: Thu, 17 Jul 2014 16:17:17 +0200 Subject: [PATCH 11/19] Don't rely on ghc-mod being in PATH --- Language/Haskell/GhcMod/Find.hs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Language/Haskell/GhcMod/Find.hs b/Language/Haskell/GhcMod/Find.hs index 818e652..e1a8570 100644 --- a/Language/Haskell/GhcMod/Find.hs +++ b/Language/Haskell/GhcMod/Find.hs @@ -27,12 +27,13 @@ import Exception (ghandle, handleIO) import qualified GHC as G import Language.Haskell.GhcMod.Convert import Language.Haskell.GhcMod.Monad +import Language.Haskell.GhcMod.Utils import Language.Haskell.GhcMod.Types import Name (getOccString) import System.Directory (doesDirectoryExist, getAppUserDataDirectory, doesFileExist, getModificationTime) import System.FilePath (()) import System.IO -import System.Process (readProcess) +import System.Environment (getExecutablePath) #ifndef MIN_VERSION_containers #define MIN_VERSION_containers(x,y,z) 1 @@ -84,9 +85,18 @@ lookupSymbol opt sym db = convert opt $ lookupSymbol' sym db loadSymbolDb :: IO SymbolDb loadSymbolDb = SymbolDb <$> readSymbolDb +ghcModExecutable :: IO FilePath +ghcModExecutable = +#ifndef SPEC + getExecutablePath +#else + return "dist/build/ghc-mod/ghc-mod" +#endif + readSymbolDb :: IO (Map Symbol [ModuleString]) readSymbolDb = handle (\(SomeException _) -> return M.empty) $ do - file <- chop <$> readProcess "ghc-mod" ["dumpsym"] [] + ghcMod <- ghcModExecutable + file <- chop <$> readProcess' ghcMod ["dumpsym"] M.fromAscList . map conv . lines <$> readFile file where conv :: String -> (Symbol,[ModuleString]) From 0ce70ae22d801be9d94ced7083140222f6c1a233 Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Fri, 18 Jul 2014 10:52:57 +0900 Subject: [PATCH 12/19] set Opt_SpecConstr just in case. --- Language/Haskell/GhcMod/DynFlags.hs | 13 +++++++------ Language/Haskell/GhcMod/Monad.hs | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Language/Haskell/GhcMod/DynFlags.hs b/Language/Haskell/GhcMod/DynFlags.hs index a4c75d6..c5020c3 100644 --- a/Language/Haskell/GhcMod/DynFlags.hs +++ b/Language/Haskell/GhcMod/DynFlags.hs @@ -1,16 +1,14 @@ module Language.Haskell.GhcMod.DynFlags where -import qualified Language.Haskell.GhcMod.Gap as Gap -import Language.Haskell.GhcMod.Types - import Control.Applicative ((<$>)) import Control.Monad (forM, void, (>=>)) +import DynFlags (ExtensionFlag(..), xopt, GeneralFlag(..), gopt_unset) import GHC (DynFlags(..), GhcMode(..), GhcLink(..), HscTarget(..), LoadHowMuch(..)) import qualified GHC as G -import GhcMonad import GHC.Paths (libdir) -import DynFlags (ExtensionFlag(..), xopt) - +import GhcMonad +import qualified Language.Haskell.GhcMod.Gap as Gap +import Language.Haskell.GhcMod.Types import System.IO.Unsafe (unsafePerformIO) data Build = CabalPkg | SingleFile deriving Eq @@ -42,6 +40,9 @@ setModeIntelligent df = df { , optLevel = 0 } +setFlags :: DynFlags -> DynFlags +setFlags df = df `gopt_unset` Opt_SpecConstr -- consume memory if -O2 + setIncludeDirs :: [IncludeDir] -> DynFlags -> DynFlags setIncludeDirs idirs df = df { importPaths = idirs } diff --git a/Language/Haskell/GhcMod/Monad.hs b/Language/Haskell/GhcMod/Monad.hs index 919289d..91ec2b8 100644 --- a/Language/Haskell/GhcMod/Monad.hs +++ b/Language/Haskell/GhcMod/Monad.hs @@ -190,6 +190,7 @@ initSession build Options {..} CompilerOptions {..} = do df <- G.getSessionDynFlags void $ G.setSessionDynFlags =<< addCmdOpts ghcOptions ( setModeSimple + $ setFlags $ setIncludeDirs includeDirs $ setBuildEnv build $ setEmptyLogger From 233f4cf05e0bb50033cc11c32b9414355af8f492 Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Fri, 18 Jul 2014 11:09:11 +0900 Subject: [PATCH 13/19] moving setFlags to Gap. --- Language/Haskell/GhcMod/DynFlags.hs | 5 +---- Language/Haskell/GhcMod/Gap.hs | 11 +++++++++++ Language/Haskell/GhcMod/Monad.hs | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Language/Haskell/GhcMod/DynFlags.hs b/Language/Haskell/GhcMod/DynFlags.hs index c5020c3..43438f6 100644 --- a/Language/Haskell/GhcMod/DynFlags.hs +++ b/Language/Haskell/GhcMod/DynFlags.hs @@ -2,7 +2,7 @@ module Language.Haskell.GhcMod.DynFlags where import Control.Applicative ((<$>)) import Control.Monad (forM, void, (>=>)) -import DynFlags (ExtensionFlag(..), xopt, GeneralFlag(..), gopt_unset) +import DynFlags (ExtensionFlag(..), xopt) import GHC (DynFlags(..), GhcMode(..), GhcLink(..), HscTarget(..), LoadHowMuch(..)) import qualified GHC as G import GHC.Paths (libdir) @@ -40,9 +40,6 @@ setModeIntelligent df = df { , optLevel = 0 } -setFlags :: DynFlags -> DynFlags -setFlags df = df `gopt_unset` Opt_SpecConstr -- consume memory if -O2 - setIncludeDirs :: [IncludeDir] -> DynFlags -> DynFlags setIncludeDirs idirs df = df { importPaths = idirs } diff --git a/Language/Haskell/GhcMod/Gap.hs b/Language/Haskell/GhcMod/Gap.hs index 7bc9181..2db9972 100644 --- a/Language/Haskell/GhcMod/Gap.hs +++ b/Language/Haskell/GhcMod/Gap.hs @@ -39,6 +39,7 @@ module Language.Haskell.GhcMod.Gap ( , GLMatch , getClass , occName + , setFlags ) where import Control.Applicative hiding (empty) @@ -459,3 +460,13 @@ getClass _ = Nothing occName :: RdrName -> OccName occName = rdrNameOcc #endif + +---------------------------------------------------------------- +---------------------------------------------------------------- + +setFlags :: DynFlags -> DynFlags +#if __GLASGOW_HASKELL__ >= 708 +setFlags df = df `gopt_unset` Opt_SpecConstr -- consume memory if -O2 +#else +setFlags = id +#endif diff --git a/Language/Haskell/GhcMod/Monad.hs b/Language/Haskell/GhcMod/Monad.hs index 91ec2b8..a63b4e8 100644 --- a/Language/Haskell/GhcMod/Monad.hs +++ b/Language/Haskell/GhcMod/Monad.hs @@ -190,7 +190,7 @@ initSession build Options {..} CompilerOptions {..} = do df <- G.getSessionDynFlags void $ G.setSessionDynFlags =<< addCmdOpts ghcOptions ( setModeSimple - $ setFlags + $ Gap.setFlags $ setIncludeDirs includeDirs $ setBuildEnv build $ setEmptyLogger From 26316262aaab78602153d7421e1d2149c395ac6b Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Fri, 18 Jul 2014 14:05:20 +0900 Subject: [PATCH 14/19] converting GhcMonad to IOish. --- Language/Haskell/GhcMod/Browse.hs | 8 +++--- Language/Haskell/GhcMod/Check.hs | 3 ++- Language/Haskell/GhcMod/DynFlags.hs | 35 ++------------------------ Language/Haskell/GhcMod/GHCApi.hs | 9 ++++--- Language/Haskell/GhcMod/Internal.hs | 1 + Language/Haskell/GhcMod/SrcUtils.hs | 10 +++++--- Language/Haskell/GhcMod/Target.hs | 39 +++++++++++++++++++++++++++++ ghc-mod.cabal | 1 + 8 files changed, 60 insertions(+), 46 deletions(-) create mode 100644 Language/Haskell/GhcMod/Target.hs diff --git a/Language/Haskell/GhcMod/Browse.hs b/Language/Haskell/GhcMod/Browse.hs index b29fefd..4e6a00f 100644 --- a/Language/Haskell/GhcMod/Browse.hs +++ b/Language/Haskell/GhcMod/Browse.hs @@ -11,11 +11,11 @@ import Exception (ghandle) import FastString (mkFastString) import GHC (GhcException(CmdLineError), ModuleInfo, Name, TyThing, DynFlags, Type, TyCon) import qualified GHC as G -import Language.Haskell.GhcMod.Doc (showPage, styleUnqualified) -import Language.Haskell.GhcMod.DynFlags -import Language.Haskell.GhcMod.Gap -import Language.Haskell.GhcMod.Monad import Language.Haskell.GhcMod.Convert +import Language.Haskell.GhcMod.Doc (showPage, styleUnqualified) +import Language.Haskell.GhcMod.Gap +import Language.Haskell.GhcMod.Monad (IOish, GhcModT, options) +import Language.Haskell.GhcMod.Target (setTargetFiles) import Language.Haskell.GhcMod.Types import Name (getOccString) import Outputable (ppr, Outputable) diff --git a/Language/Haskell/GhcMod/Check.hs b/Language/Haskell/GhcMod/Check.hs index cd6591c..594ee9e 100644 --- a/Language/Haskell/GhcMod/Check.hs +++ b/Language/Haskell/GhcMod/Check.hs @@ -9,7 +9,8 @@ import Control.Applicative ((<$>)) import Language.Haskell.GhcMod.DynFlags import qualified Language.Haskell.GhcMod.Gap as Gap import Language.Haskell.GhcMod.Logger -import Language.Haskell.GhcMod.Monad +import Language.Haskell.GhcMod.Monad (IOish, GhcModT, withErrorHandler) +import Language.Haskell.GhcMod.Target (setTargetFiles) ---------------------------------------------------------------- diff --git a/Language/Haskell/GhcMod/DynFlags.hs b/Language/Haskell/GhcMod/DynFlags.hs index 43438f6..0134912 100644 --- a/Language/Haskell/GhcMod/DynFlags.hs +++ b/Language/Haskell/GhcMod/DynFlags.hs @@ -1,9 +1,8 @@ module Language.Haskell.GhcMod.DynFlags where import Control.Applicative ((<$>)) -import Control.Monad (forM, void, (>=>)) -import DynFlags (ExtensionFlag(..), xopt) -import GHC (DynFlags(..), GhcMode(..), GhcLink(..), HscTarget(..), LoadHowMuch(..)) +import Control.Monad (void) +import GHC (DynFlags(..), GhcMode(..), GhcLink(..), HscTarget(..)) import qualified GHC as G import GHC.Paths (libdir) import GhcMonad @@ -67,36 +66,6 @@ addCmdOpts cmdOpts df = ---------------------------------------------------------------- --- | Set the files as targets and load them. -setTargetFiles :: (GhcMonad m) => [FilePath] -> m () -setTargetFiles files = do - targets <- forM files $ \file -> G.guessTarget file Nothing - G.setTargets targets - xs <- G.depanal [] False - -- FIXME, checking state - loadTargets $ needsFallback xs - where - loadTargets False = do - -- Reporting error A and error B - void $ G.load LoadAllTargets - mss <- filter (\x -> G.ms_hspp_file x `elem` files) <$> G.getModuleGraph - -- Reporting error B and error C - mapM_ (G.parseModule >=> G.typecheckModule >=> G.desugarModule) mss - -- Error B duplicates. But we cannot ignore both error reportings, - -- sigh. So, the logger makes log messages unique by itself. - loadTargets True = do - df <- G.getSessionDynFlags - void $ G.setSessionDynFlags (setModeIntelligent df) - void $ G.load LoadAllTargets - -needsFallback :: G.ModuleGraph -> Bool -needsFallback = any (hasTHorQQ . G.ms_hspp_opts) - where - hasTHorQQ :: DynFlags -> Bool - hasTHorQQ dflags = any (`xopt` dflags) [Opt_TemplateHaskell, Opt_QuasiQuotes] - ----------------------------------------------------------------- - -- | Return the 'DynFlags' currently in use in the GHC session. getDynamicFlags :: IO DynFlags getDynamicFlags = G.runGhc (Just libdir) G.getSessionDynFlags diff --git a/Language/Haskell/GhcMod/GHCApi.hs b/Language/Haskell/GhcMod/GHCApi.hs index a3ac817..2cc22f3 100644 --- a/Language/Haskell/GhcMod/GHCApi.hs +++ b/Language/Haskell/GhcMod/GHCApi.hs @@ -11,7 +11,8 @@ module Language.Haskell.GhcMod.GHCApi ( ) where import Language.Haskell.GhcMod.GhcPkg -import Language.Haskell.GhcMod.DynFlags +import Language.Haskell.GhcMod.Monad (IOish, GhcModT) +import Language.Haskell.GhcMod.Target (setTargetFiles) import Language.Haskell.GhcMod.Types import Control.Applicative ((<$>)) @@ -64,10 +65,10 @@ type Binding = String -- should look for @module@ in the working directory. -- -- To map a 'ModuleString' to a package see 'findModule' -moduleInfo :: GhcMonad m +moduleInfo :: IOish m => Maybe Package -> ModuleString - -> m (Maybe G.ModuleInfo) + -> GhcModT m (Maybe G.ModuleInfo) moduleInfo mpkg mdl = do let mdlName = G.mkModuleName mdl mfsPkgId = G.packageIdFS . ghcPkgId <$> mpkg @@ -78,7 +79,7 @@ moduleInfo mpkg mdl = do Just _ -> return () Nothing -> setTargetFiles [mdl] -localModuleInfo :: GhcMonad m => ModuleString -> m (Maybe G.ModuleInfo) +localModuleInfo :: IOish m => ModuleString -> GhcModT m (Maybe G.ModuleInfo) localModuleInfo mdl = moduleInfo Nothing mdl bindings :: G.ModuleInfo -> [Binding] diff --git a/Language/Haskell/GhcMod/Internal.hs b/Language/Haskell/GhcMod/Internal.hs index a405ff5..52e4858 100644 --- a/Language/Haskell/GhcMod/Internal.hs +++ b/Language/Haskell/GhcMod/Internal.hs @@ -40,6 +40,7 @@ import Language.Haskell.GhcMod.CabalApi import Language.Haskell.GhcMod.DynFlags import Language.Haskell.GhcMod.GHCChoice import Language.Haskell.GhcMod.Logger +import Language.Haskell.GhcMod.Target import Language.Haskell.GhcMod.Types -- | Obtaining the directory for ghc system libraries. diff --git a/Language/Haskell/GhcMod/SrcUtils.hs b/Language/Haskell/GhcMod/SrcUtils.hs index 059bcad..c774032 100644 --- a/Language/Haskell/GhcMod/SrcUtils.hs +++ b/Language/Haskell/GhcMod/SrcUtils.hs @@ -9,17 +9,19 @@ import Data.Generics import Data.Maybe (fromMaybe) import Data.Ord as O import GHC (LHsExpr, LPat, Id, DynFlags, SrcSpan, Type, Located, ParsedSource, RenamedSource, TypecheckedSource, GenLocated(L)) -import GhcMonad import qualified GHC as G import GHC.SYB.Utils (Stage(..), everythingStaged) +import GhcMonad +import qualified Language.Haskell.Exts.Annotated as HE import Language.Haskell.GhcMod.Doc (showOneLine, getStyle) import Language.Haskell.GhcMod.DynFlags import Language.Haskell.GhcMod.Gap (HasType(..), setWarnTypedHoles, setDeferTypeErrors) import qualified Language.Haskell.GhcMod.Gap as Gap +import Language.Haskell.GhcMod.Monad (IOish, GhcModT) +import Language.Haskell.GhcMod.Target (setTargetFiles) +import OccName (OccName) import Outputable (PprStyle) import TcHsSyn (hsPatType) -import OccName (OccName) -import qualified Language.Haskell.Exts.Annotated as HE ---------------------------------------------------------------- @@ -79,7 +81,7 @@ pretty dflag style = showOneLine dflag style . Gap.typeForUser ---------------------------------------------------------------- -inModuleContext ::GhcMonad m => FilePath -> (DynFlags -> PprStyle -> m a) -> m a +inModuleContext :: IOish m => FilePath -> (DynFlags -> PprStyle -> GhcModT m a) -> GhcModT m a inModuleContext file action = withDynFlags (setWarnTypedHoles . setDeferTypeErrors . setNoWaringFlags) $ do setTargetFiles [file] diff --git a/Language/Haskell/GhcMod/Target.hs b/Language/Haskell/GhcMod/Target.hs new file mode 100644 index 0000000..f0dfb07 --- /dev/null +++ b/Language/Haskell/GhcMod/Target.hs @@ -0,0 +1,39 @@ +module Language.Haskell.GhcMod.Target ( + setTargetFiles + ) where + +import Control.Applicative ((<$>)) +import Control.Monad (forM, void, (>=>)) +import DynFlags (ExtensionFlag(..), xopt) +import GHC (DynFlags(..), LoadHowMuch(..)) +import qualified GHC as G +import Language.Haskell.GhcMod.DynFlags +import Language.Haskell.GhcMod.Monad (IOish, GhcModT) + +-- | Set the files as targets and load them. +setTargetFiles :: IOish m => [FilePath] -> GhcModT m () +setTargetFiles files = do + targets <- forM files $ \file -> G.guessTarget file Nothing + G.setTargets targets + xs <- G.depanal [] False + -- FIXME, checking state + loadTargets $ needsFallback xs + where + loadTargets False = do + -- Reporting error A and error B + void $ G.load LoadAllTargets + mss <- filter (\x -> G.ms_hspp_file x `elem` files) <$> G.getModuleGraph + -- Reporting error B and error C + mapM_ (G.parseModule >=> G.typecheckModule >=> G.desugarModule) mss + -- Error B duplicates. But we cannot ignore both error reportings, + -- sigh. So, the logger makes log messages unique by itself. + loadTargets True = do + df <- G.getSessionDynFlags + void $ G.setSessionDynFlags (setModeIntelligent df) + void $ G.load LoadAllTargets + +needsFallback :: G.ModuleGraph -> Bool +needsFallback = any (hasTHorQQ . G.ms_hspp_opts) + where + hasTHorQQ :: DynFlags -> Bool + hasTHorQQ dflags = any (`xopt` dflags) [Opt_TemplateHaskell, Opt_QuasiQuotes] diff --git a/ghc-mod.cabal b/ghc-mod.cabal index 0ce7704..f09f10e 100644 --- a/ghc-mod.cabal +++ b/ghc-mod.cabal @@ -83,6 +83,7 @@ Library Language.Haskell.GhcMod.PkgDoc Language.Haskell.GhcMod.Read Language.Haskell.GhcMod.SrcUtils + Language.Haskell.GhcMod.Target Language.Haskell.GhcMod.Types Language.Haskell.GhcMod.Utils Build-Depends: base >= 4.0 && < 5 From 7b079896b1105542dafec966e9eb9ea98fb3d9af Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Fri, 18 Jul 2014 14:13:59 +0900 Subject: [PATCH 15/19] doc sectioning. --- Language/Haskell/GhcMod/Monad.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Language/Haskell/GhcMod/Monad.hs b/Language/Haskell/GhcMod/Monad.hs index a63b4e8..4514609 100644 --- a/Language/Haskell/GhcMod/Monad.hs +++ b/Language/Haskell/GhcMod/Monad.hs @@ -9,7 +9,9 @@ module Language.Haskell.GhcMod.Monad ( GhcMod , GhcModT , IOish + -- ** Environment, state and logging , GhcModEnv(..) + , newGhcModEnv , GhcModState(..) , GhcModWriter -- * Monad utilities @@ -17,11 +19,13 @@ module Language.Haskell.GhcMod.Monad ( , runGhcModT , runGhcModT' , withErrorHandler + -- ** Conversion , liftGhcMod , toGhcMod - , newGhcModEnv + -- ** Accessing 'GhcModEnv' , options , cradle + -- ** Exporting convenient modules , module Control.Monad.Reader.Class , module Control.Monad.Writer.Class , module Control.Monad.State.Class From 6d42354a5bcb2eaf5b301039b66231184b26da66 Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Fri, 18 Jul 2014 14:29:50 +0900 Subject: [PATCH 16/19] setMode and getMode --- Language/Haskell/GhcMod/Monad.hs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/Language/Haskell/GhcMod/Monad.hs b/Language/Haskell/GhcMod/Monad.hs index 4514609..ff35dad 100644 --- a/Language/Haskell/GhcMod/Monad.hs +++ b/Language/Haskell/GhcMod/Monad.hs @@ -12,7 +12,9 @@ module Language.Haskell.GhcMod.Monad ( -- ** Environment, state and logging , GhcModEnv(..) , newGhcModEnv - , GhcModState(..) + , GhcModState + , defaultState + , Mode(..) , GhcModWriter -- * Monad utilities , runGhcMod @@ -22,9 +24,11 @@ module Language.Haskell.GhcMod.Monad ( -- ** Conversion , liftGhcMod , toGhcMod - -- ** Accessing 'GhcModEnv' + -- ** Accessing 'GhcModEnv' and 'GhcModState' , options , cradle + , getMode + , setMode -- ** Exporting convenient modules , module Control.Monad.Reader.Class , module Control.Monad.Writer.Class @@ -101,10 +105,12 @@ data GhcModEnv = GhcModEnv { , gmCradle :: Cradle } -data GhcModState = GhcModState deriving (Eq,Show,Read) +data GhcModState = GhcModState Mode deriving (Eq,Show,Read) + +data Mode = Simple | Intelligent deriving (Eq,Show,Read) defaultState :: GhcModState -defaultState = GhcModState +defaultState = GhcModState Simple type GhcModWriter = () @@ -281,6 +287,16 @@ options = gmOptions <$> ask cradle :: IOish m => GhcModT m Cradle cradle = gmCradle <$> ask +getMode :: IOish m => GhcModT m Mode +getMode = do + GhcModState mode <- get + return mode + +setMode :: IOish m => Mode -> GhcModT m () +setMode mode = put $ GhcModState mode + +---------------------------------------------------------------- + instance (MonadBaseControl IO m) => MonadBase IO (GhcModT m) where liftBase = GhcModT . liftBase From e1d9c3b881f5398fcfe3fc452b435ce981a9f4cb Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Fri, 18 Jul 2014 15:13:30 +0900 Subject: [PATCH 17/19] clean up lookupSymbol. --- Language/Haskell/GhcMod/Find.hs | 15 ++++++++------- src/GHCModi.hs | 3 +-- test/FindSpec.hs | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Language/Haskell/GhcMod/Find.hs b/Language/Haskell/GhcMod/Find.hs index e1a8570..6cda765 100644 --- a/Language/Haskell/GhcMod/Find.hs +++ b/Language/Haskell/GhcMod/Find.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE CPP #-} +{-# LANGUAGE CPP, BangPatterns #-} module Language.Haskell.GhcMod.Find #ifndef SPEC @@ -9,6 +9,7 @@ module Language.Haskell.GhcMod.Find , lookupSymbol , dumpSymbol , findSymbol + , lookupSym ) #endif where @@ -69,15 +70,15 @@ packageConfDir = "package.conf.d" -- | Finding modules to which the symbol belong. findSymbol :: IOish m => Symbol -> GhcModT m String -findSymbol sym = convert' =<< lookupSymbol' sym <$> liftIO loadSymbolDb - -lookupSymbol' :: Symbol -> SymbolDb -> [ModuleString] -lookupSymbol' sym (SymbolDb db) = fromMaybe [] (M.lookup sym db) +findSymbol sym = liftIO loadSymbolDb >>= lookupSymbol sym -- | Looking up 'SymbolDb' with 'Symbol' to \['ModuleString'\] -- which will be concatenated. -lookupSymbol :: Options -> Symbol -> SymbolDb -> String -lookupSymbol opt sym db = convert opt $ lookupSymbol' sym db +lookupSymbol :: IOish m => Symbol -> SymbolDb -> GhcModT m String +lookupSymbol sym db = convert' $ lookupSym sym db + +lookupSym :: Symbol -> SymbolDb -> [ModuleString] +lookupSym sym (SymbolDb db) = fromMaybe [] $ M.lookup sym db --------------------------------------------------------------- diff --git a/src/GHCModi.hs b/src/GHCModi.hs index a33ad1f..e3a888b 100644 --- a/src/GHCModi.hs +++ b/src/GHCModi.hs @@ -190,8 +190,7 @@ findSym :: IOish m => Set FilePath -> String -> MVar SymbolDb -> GhcModT m (String, Bool, Set FilePath) findSym set sym mvar = do db <- liftIO $ readMVar mvar - opt <- options - let ret = lookupSymbol opt sym db + ret <- lookupSymbol sym db return (ret, True, set) lintStx :: IOish m => Set FilePath diff --git a/test/FindSpec.hs b/test/FindSpec.hs index 0eedcb4..3480054 100644 --- a/test/FindSpec.hs +++ b/test/FindSpec.hs @@ -13,4 +13,4 @@ spec = do describe "db <- loadSymbolDb" $ do it "lookupSymbol' db \"head\" contains at least `Data.List'" $ do db <- loadSymbolDb - lookupSymbol' "head" db `shouldContain` ["Data.List"] + lookupSym "head" db `shouldContain` ["Data.List"] From 30ddd655cd061b7f083ec2400386b395547aa394 Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Fri, 18 Jul 2014 15:31:42 +0900 Subject: [PATCH 18/19] export minimum Monad stuff from GhcMod. --- Language/Haskell/GhcMod.hs | 7 ++++++- Language/Haskell/GhcMod/Logger.hs | 2 +- Language/Haskell/GhcMod/Monad.hs | 16 +++++++++++++--- src/GHCModi.hs | 12 +++++------- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/Language/Haskell/GhcMod.hs b/Language/Haskell/GhcMod.hs index cfb75f7..24833f8 100644 --- a/Language/Haskell/GhcMod.hs +++ b/Language/Haskell/GhcMod.hs @@ -15,7 +15,12 @@ module Language.Haskell.GhcMod ( , GhcPkgDb , Symbol , SymbolDb - , module Language.Haskell.GhcMod.Monad + -- * Monad Types + , GhcModT + , IOish + -- * Monad utilities + , runGhcModT + , withOptions -- * 'GhcMod' utilities , boot , browse diff --git a/Language/Haskell/GhcMod/Logger.hs b/Language/Haskell/GhcMod/Logger.hs index 5167372..17aa82a 100644 --- a/Language/Haskell/GhcMod/Logger.hs +++ b/Language/Haskell/GhcMod/Logger.hs @@ -79,7 +79,7 @@ withLogger setDF body = ghandle sourceError $ do sourceError :: IOish m => SourceError -> GhcModT m (Either String String) sourceError err = do dflags <- G.getSessionDynFlags - style <- toGhcMod getStyle + style <- toGhcModT getStyle ret <- convert' (errBagToStrList dflags style . srcErrorMessages $ err) return $ Left ret diff --git a/Language/Haskell/GhcMod/Monad.hs b/Language/Haskell/GhcMod/Monad.hs index ff35dad..a323f6b 100644 --- a/Language/Haskell/GhcMod/Monad.hs +++ b/Language/Haskell/GhcMod/Monad.hs @@ -23,12 +23,13 @@ module Language.Haskell.GhcMod.Monad ( , withErrorHandler -- ** Conversion , liftGhcMod - , toGhcMod + , toGhcModT -- ** Accessing 'GhcModEnv' and 'GhcModState' , options , cradle , getMode , setMode + , withOptions -- ** Exporting convenient modules , module Control.Monad.Reader.Class , module Control.Monad.Writer.Class @@ -274,8 +275,8 @@ withErrorHandler label = ghandle ignore exitSuccess -- | This is only a transitional mechanism don't use it for new code. -toGhcMod :: IOish m => Ghc a -> GhcModT m a -toGhcMod a = do +toGhcModT :: IOish m => Ghc a -> GhcModT m a +toGhcModT a = do s <- gmGhcSession <$> ask liftIO $ unGhc a $ Session s @@ -297,6 +298,15 @@ setMode mode = put $ GhcModState mode ---------------------------------------------------------------- +withOptions :: IOish m => (Options -> Options) -> GhcModT m a -> GhcModT m a +withOptions changeOpt action = local changeEnv action + where + changeEnv e = e { gmOptions = changeOpt opt } + where + opt = gmOptions e + +---------------------------------------------------------------- + instance (MonadBaseControl IO m) => MonadBase IO (GhcModT m) where liftBase = GhcModT . liftBase diff --git a/src/GHCModi.hs b/src/GHCModi.hs index e3a888b..efd94cf 100644 --- a/src/GHCModi.hs +++ b/src/GHCModi.hs @@ -31,7 +31,6 @@ import Data.Set (Set) import qualified Data.Set as S import Data.Typeable (Typeable) import Data.Version (showVersion) -import GHC (GhcMonad) import qualified GHC as G import Language.Haskell.GhcMod import Paths_ghc_mod @@ -151,14 +150,14 @@ checkStx :: IOish m -> FilePath -> GhcModT m (String, Bool, Set FilePath) checkStx set file = do - set' <- toGhcMod $ newFileSet set file + set' <- newFileSet set file let files = S.toList set' eret <- check files case eret of Right ret -> return (ret, True, set') Left ret -> return (ret, True, set) -- fxime: set -newFileSet :: GhcMonad m => Set FilePath -> FilePath -> m (Set FilePath) +newFileSet :: IOish m => Set FilePath -> FilePath -> GhcModT m (Set FilePath) newFileSet set file = do let set1 | S.member file set = set @@ -168,7 +167,7 @@ newFileSet set file = do Nothing -> set1 Just mainfile -> S.delete mainfile set1 -getModSummaryForMain :: GhcMonad m => m (Maybe G.ModSummary) +getModSummaryForMain :: IOish m => GhcModT m (Maybe G.ModSummary) getModSummaryForMain = find isMain <$> G.getModuleGraph where isMain m = G.moduleNameString (G.moduleName (G.ms_mod m)) == "Main" @@ -197,13 +196,12 @@ lintStx :: IOish m => Set FilePath -> FilePath -> GhcModT m (String, Bool, Set FilePath) lintStx set optFile = do - ret <- local env' $ lint file + ret <- withOptions changeOpt $ lint file return (ret, True, set) where (opts,file) = parseLintOptions optFile hopts = if opts == "" then [] else read opts - env' e = e { gmOptions = opt' $ gmOptions e } - opt' o = o { hlintOpts = hopts } + changeOpt o = o { hlintOpts = hopts } -- | -- >>> parseLintOptions "[\"--ignore=Use camelCase\", \"--ignore=Eta reduce\"] file name" From 0080f9b68c288145779b87d551983f2af8cee77c Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Fri, 18 Jul 2014 15:42:05 +0900 Subject: [PATCH 19/19] Internal exports extra Monad stuff. --- Language/Haskell/GhcMod.hs | 6 +++--- Language/Haskell/GhcMod/Find.hs | 3 ++- Language/Haskell/GhcMod/Internal.hs | 21 +++++++++++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Language/Haskell/GhcMod.hs b/Language/Haskell/GhcMod.hs index 24833f8..0c2d0a0 100644 --- a/Language/Haskell/GhcMod.hs +++ b/Language/Haskell/GhcMod.hs @@ -28,8 +28,6 @@ module Language.Haskell.GhcMod ( , checkSyntax , debugInfo , expandTemplate - , findSymbol - , dumpSymbol , info , lint , pkgDoc @@ -40,9 +38,11 @@ module Language.Haskell.GhcMod ( , modules , languages , flags + , findSymbol + , lookupSymbol + , dumpSymbol -- * SymbolDb , loadSymbolDb - , lookupSymbol ) where import Language.Haskell.GhcMod.Boot diff --git a/Language/Haskell/GhcMod/Find.hs b/Language/Haskell/GhcMod/Find.hs index 6cda765..16feba6 100644 --- a/Language/Haskell/GhcMod/Find.hs +++ b/Language/Haskell/GhcMod/Find.hs @@ -68,7 +68,8 @@ packageConfDir = "package.conf.d" ---------------------------------------------------------------- --- | Finding modules to which the symbol belong. +-- | Looking up 'SymbolDb' with 'Symbol' to \['ModuleString'\] +-- which will be concatenated. 'loadSymbolDb' is called internally. findSymbol :: IOish m => Symbol -> GhcModT m String findSymbol sym = liftIO loadSymbolDb >>= lookupSymbol sym diff --git a/Language/Haskell/GhcMod/Internal.hs b/Language/Haskell/GhcMod/Internal.hs index 52e4858..62d4063 100644 --- a/Language/Haskell/GhcMod/Internal.hs +++ b/Language/Haskell/GhcMod/Internal.hs @@ -26,6 +26,26 @@ module Language.Haskell.GhcMod.Internal ( , withLogger , setNoWaringFlags , setAllWaringFlags + -- * Environment, state and logging + , GhcModEnv(..) + , newGhcModEnv + , GhcModState + , defaultState + , Mode(..) + , GhcModWriter + -- * Monad utilities + , runGhcMod + , runGhcModT' + , withErrorHandler + -- ** Conversion + , liftGhcMod + , toGhcModT + -- ** Accessing 'GhcModEnv' and 'GhcModState' + , options + , cradle + , getMode + , setMode + , withOptions -- * 'Ghc' Choice , (||>) , goNext @@ -40,6 +60,7 @@ import Language.Haskell.GhcMod.CabalApi import Language.Haskell.GhcMod.DynFlags import Language.Haskell.GhcMod.GHCChoice import Language.Haskell.GhcMod.Logger +import Language.Haskell.GhcMod.Monad import Language.Haskell.GhcMod.Target import Language.Haskell.GhcMod.Types