packages feed

hie-bios 0.1.1 → 0.2.0

raw patch · 26 files changed

+1334/−1052 lines, 26 filesdep ~containersdep ~directorydep ~filepathPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: containers, directory, filepath, ghc, temporary, time, transformers

API changes (from Hackage documentation)

- HIE.Bios: initializeFlagsWithCradle :: GhcMonad m => FilePath -> Cradle -> m ()
- HIE.Bios: initializeFlagsWithCradleWithMessage :: GhcMonad m => Maybe Messager -> FilePath -> Cradle -> m ()
- HIE.Bios: loadFile :: GhcMonad m => (FilePath, FilePath) -> m (Maybe TypecheckedModule, [TypecheckedModule])
- HIE.Bios: loadFileWithMessage :: GhcMonad m => Maybe Messager -> (FilePath, FilePath) -> m (Maybe TypecheckedModule, [TypecheckedModule])
- HIE.Bios: withGhcT :: (ExceptionMonad m, MonadIO m, Monad m) => GhcT m a -> m a
- HIE.Bios.Check: check :: GhcMonad m => Options -> [FilePath] -> m (Either String String)
- HIE.Bios.Check: checkSyntax :: Options -> Cradle -> [FilePath] -> IO String
- HIE.Bios.Check: expand :: Options -> [FilePath] -> Ghc (Either String String)
- HIE.Bios.Check: expandTemplate :: Options -> Cradle -> [FilePath] -> IO String
- HIE.Bios.Config: instance Data.Aeson.Types.FromJSON.FromJSON HIE.Bios.Config.CradleConfig
- HIE.Bios.Cradle: findCradleWithOpts :: CradleOpts -> FilePath -> IO Cradle
- HIE.Bios.Doc: getStyle :: GhcMonad m => DynFlags -> m PprStyle
- HIE.Bios.Doc: showDocWith :: DynFlags -> Mode -> Doc -> String
- HIE.Bios.Doc: showOneLine :: DynFlags -> PprStyle -> SDoc -> String
- HIE.Bios.Doc: showPage :: DynFlags -> PprStyle -> SDoc -> String
- HIE.Bios.Doc: styleUnqualified :: DynFlags -> PprStyle
- HIE.Bios.GHCApi: CradleError :: String -> CradleError
- HIE.Bios.GHCApi: data CradleError
- HIE.Bios.GHCApi: getDynamicFlags :: IO DynFlags
- HIE.Bios.GHCApi: getSystemLibDir :: IO (Maybe FilePath)
- HIE.Bios.GHCApi: initializeFlagsWithCradle :: GhcMonad m => FilePath -> Cradle -> m ()
- HIE.Bios.GHCApi: initializeFlagsWithCradleWithMessage :: GhcMonad m => Maybe Messager -> FilePath -> Cradle -> m ()
- HIE.Bios.GHCApi: instance GHC.Classes.Eq HIE.Bios.GHCApi.Build
- HIE.Bios.GHCApi: instance GHC.Exception.Type.Exception HIE.Bios.GHCApi.CradleError
- HIE.Bios.GHCApi: instance GHC.Show.Show HIE.Bios.GHCApi.CradleError
- HIE.Bios.GHCApi: setAllWarningFlags :: DynFlags -> DynFlags
- HIE.Bios.GHCApi: setDeferTypeErrors :: DynFlags -> DynFlags
- HIE.Bios.GHCApi: setNoWarningFlags :: DynFlags -> DynFlags
- HIE.Bios.GHCApi: withCmdFlags :: GhcMonad m => [String] -> m a -> m a
- HIE.Bios.GHCApi: withDynFlags :: GhcMonad m => (DynFlags -> DynFlags) -> m a -> m a
- HIE.Bios.GHCApi: withGHC :: FilePath -> Ghc a -> IO a
- HIE.Bios.GHCApi: withGHC' :: Ghc a -> IO a
- HIE.Bios.GHCApi: withGhcT :: (ExceptionMonad m, MonadIO m, Monad m) => GhcT m a -> m a
- HIE.Bios.Gap: emptyWarnFlags :: WarnFlags
- HIE.Bios.Gap: fixInfo :: (a, b, c, d, e) -> (a, b, c, d)
- HIE.Bios.Gap: getModSummaries :: ModuleGraph -> [ModSummary]
- HIE.Bios.Gap: getModuleName :: (a, b) -> a
- HIE.Bios.Gap: getTyThing :: (a, b, c, d, e) -> a
- HIE.Bios.Gap: inTypes :: MatchGroup GhcTc LExpression -> [Type]
- HIE.Bios.Gap: makeUserStyle :: DynFlags -> PrintUnqualified -> PprStyle
- HIE.Bios.Gap: outType :: MatchGroup GhcTc LExpression -> Type
- HIE.Bios.Gap: type LBinding = LHsBind GhcTc
- HIE.Bios.Gap: type LExpression = LHsExpr GhcTc
- HIE.Bios.Gap: type LPattern = LPat GhcTc
- HIE.Bios.Gap: type WarnFlags = EnumSet WarningFlag
- HIE.Bios.Load: loadFile :: GhcMonad m => (FilePath, FilePath) -> m (Maybe TypecheckedModule, [TypecheckedModule])
- HIE.Bios.Load: loadFileWithMessage :: GhcMonad m => Maybe Messager -> (FilePath, FilePath) -> m (Maybe TypecheckedModule, [TypecheckedModule])
- HIE.Bios.Load: setTargetFiles :: GhcMonad m => [(FilePath, FilePath)] -> m ()
- HIE.Bios.Load: setTargetFilesWithMessage :: GhcMonad m => Maybe Messager -> [(FilePath, FilePath)] -> m ()
- HIE.Bios.Logger: checkErrorPrefix :: String
- HIE.Bios.Logger: getSrcSpan :: SrcSpan -> Maybe (Int, Int, Int, Int)
- HIE.Bios.Logger: withLogger :: GhcMonad m => Options -> (DynFlags -> DynFlags) -> m () -> m (Either String String)
- HIE.Bios.Things: GtA :: Type -> GapThing
- HIE.Bios.Things: GtN :: GapThing
- HIE.Bios.Things: GtPatSyn :: PatSyn -> GapThing
- HIE.Bios.Things: GtT :: TyCon -> GapThing
- HIE.Bios.Things: data GapThing
- HIE.Bios.Things: fromTyThing :: TyThing -> GapThing
- HIE.Bios.Things: infoThing :: String -> Ghc SDoc
- HIE.Bios.Types: instance GHC.Base.Alternative GhcMonad.Ghc
+ HIE.Bios: CompilerOptions :: [String] -> CompilerOptions
+ HIE.Bios: [ghcOptions] :: CompilerOptions -> [String]
+ HIE.Bios: data CompilerOptions
+ HIE.Bios: getCompilerOptions :: FilePath -> Cradle -> IO (Either CradleError CompilerOptions)
+ HIE.Bios: initSession :: GhcMonad m => CompilerOptions -> m [Target]
+ HIE.Bios: loadCradle :: FilePath -> IO Cradle
+ HIE.Bios: loadImplicitCradle :: FilePath -> IO Cradle
+ HIE.Bios.Config: CradleConfig :: [FilePath] -> CradleType -> CradleConfig
+ HIE.Bios.Config: [cradleDependencies] :: CradleConfig -> [FilePath]
+ HIE.Bios.Config: [cradleType] :: CradleConfig -> CradleType
+ HIE.Bios.Config: [depsProg] :: CradleType -> Maybe FilePath
+ HIE.Bios.Config: data CradleType
+ HIE.Bios.Config: instance Data.Aeson.Types.FromJSON.FromJSON HIE.Bios.Config.CradleType
+ HIE.Bios.Config: instance GHC.Show.Show HIE.Bios.Config.CradleType
+ HIE.Bios.Cradle: loadCradle :: FilePath -> IO Cradle
+ HIE.Bios.Cradle: loadImplicitCradle :: FilePath -> IO Cradle
+ HIE.Bios.Environment: addCmdOpts :: GhcMonad m => [String] -> DynFlags -> m (DynFlags, [Target])
+ HIE.Bios.Environment: getDynamicFlags :: IO DynFlags
+ HIE.Bios.Environment: getSystemLibDir :: IO (Maybe FilePath)
+ HIE.Bios.Environment: initSession :: GhcMonad m => CompilerOptions -> m [Target]
+ HIE.Bios.Flags: data CradleError
+ HIE.Bios.Flags: getCompilerOptions :: FilePath -> Cradle -> IO (Either CradleError CompilerOptions)
+ HIE.Bios.Flags: instance GHC.Exception.Type.Exception HIE.Bios.Flags.CradleError
+ HIE.Bios.Flags: instance GHC.Show.Show HIE.Bios.Flags.CradleError
+ HIE.Bios.Ghc.Api: getDynamicFlags :: IO DynFlags
+ HIE.Bios.Ghc.Api: getSystemLibDir :: IO (Maybe FilePath)
+ HIE.Bios.Ghc.Api: initializeFlagsWithCradle :: GhcMonad m => FilePath -> Cradle -> m ()
+ HIE.Bios.Ghc.Api: initializeFlagsWithCradleWithMessage :: GhcMonad m => Maybe Messager -> FilePath -> Cradle -> m ()
+ HIE.Bios.Ghc.Api: setAllWarningFlags :: DynFlags -> DynFlags
+ HIE.Bios.Ghc.Api: setDeferTypeErrors :: DynFlags -> DynFlags
+ HIE.Bios.Ghc.Api: setNoWarningFlags :: DynFlags -> DynFlags
+ HIE.Bios.Ghc.Api: withCmdFlags :: GhcMonad m => [String] -> m a -> m a
+ HIE.Bios.Ghc.Api: withDynFlags :: GhcMonad m => (DynFlags -> DynFlags) -> m a -> m a
+ HIE.Bios.Ghc.Api: withGHC :: FilePath -> Ghc a -> IO a
+ HIE.Bios.Ghc.Api: withGHC' :: Ghc a -> IO a
+ HIE.Bios.Ghc.Api: withGhcT :: (ExceptionMonad m, MonadIO m, Monad m) => GhcT m a -> m a
+ HIE.Bios.Ghc.Check: check :: GhcMonad m => Options -> [FilePath] -> m (Either String String)
+ HIE.Bios.Ghc.Check: checkSyntax :: Options -> Cradle -> [FilePath] -> IO String
+ HIE.Bios.Ghc.Check: expand :: Options -> [FilePath] -> Ghc (Either String String)
+ HIE.Bios.Ghc.Check: expandTemplate :: Options -> Cradle -> [FilePath] -> IO String
+ HIE.Bios.Ghc.Doc: getStyle :: GhcMonad m => DynFlags -> m PprStyle
+ HIE.Bios.Ghc.Doc: showDocWith :: DynFlags -> Mode -> Doc -> String
+ HIE.Bios.Ghc.Doc: showOneLine :: DynFlags -> PprStyle -> SDoc -> String
+ HIE.Bios.Ghc.Doc: showPage :: DynFlags -> PprStyle -> SDoc -> String
+ HIE.Bios.Ghc.Doc: styleUnqualified :: DynFlags -> PprStyle
+ HIE.Bios.Ghc.Gap: emptyWarnFlags :: WarnFlags
+ HIE.Bios.Ghc.Gap: fixInfo :: (a, b, c, d, e) -> (a, b, c, d)
+ HIE.Bios.Ghc.Gap: getModSummaries :: ModuleGraph -> [ModSummary]
+ HIE.Bios.Ghc.Gap: getModuleName :: (a, b) -> a
+ HIE.Bios.Ghc.Gap: getTyThing :: (a, b, c, d, e) -> a
+ HIE.Bios.Ghc.Gap: inTypes :: MatchGroup GhcTc LExpression -> [Type]
+ HIE.Bios.Ghc.Gap: makeUserStyle :: DynFlags -> PrintUnqualified -> PprStyle
+ HIE.Bios.Ghc.Gap: mapMG :: (ModSummary -> ModSummary) -> ModuleGraph -> ModuleGraph
+ HIE.Bios.Ghc.Gap: mgModSummaries :: ModuleGraph -> [ModSummary]
+ HIE.Bios.Ghc.Gap: outType :: MatchGroup GhcTc LExpression -> Type
+ HIE.Bios.Ghc.Gap: type LBinding = LHsBind GhcTc
+ HIE.Bios.Ghc.Gap: type LExpression = LHsExpr GhcTc
+ HIE.Bios.Ghc.Gap: type LPattern = LPat GhcTc
+ HIE.Bios.Ghc.Gap: type WarnFlags = EnumSet WarningFlag
+ HIE.Bios.Ghc.Load: loadFile :: GhcMonad m => (FilePath, FilePath) -> m (Maybe TypecheckedModule, [TypecheckedModule])
+ HIE.Bios.Ghc.Load: loadFileWithMessage :: GhcMonad m => Maybe Messager -> (FilePath, FilePath) -> m (Maybe TypecheckedModule, [TypecheckedModule])
+ HIE.Bios.Ghc.Load: setTargetFiles :: GhcMonad m => [(FilePath, FilePath)] -> m ()
+ HIE.Bios.Ghc.Load: setTargetFilesWithMessage :: GhcMonad m => Maybe Messager -> [(FilePath, FilePath)] -> m ()
+ HIE.Bios.Ghc.Logger: checkErrorPrefix :: String
+ HIE.Bios.Ghc.Logger: getSrcSpan :: SrcSpan -> Maybe (Int, Int, Int, Int)
+ HIE.Bios.Ghc.Logger: withLogger :: GhcMonad m => Options -> (DynFlags -> DynFlags) -> m () -> m (Either String String)
+ HIE.Bios.Ghc.Things: GtA :: Type -> GapThing
+ HIE.Bios.Ghc.Things: GtN :: GapThing
+ HIE.Bios.Ghc.Things: GtPatSyn :: PatSyn -> GapThing
+ HIE.Bios.Ghc.Things: GtT :: TyCon -> GapThing
+ HIE.Bios.Ghc.Things: data GapThing
+ HIE.Bios.Ghc.Things: fromTyThing :: TyThing -> GapThing
+ HIE.Bios.Ghc.Things: infoThing :: String -> Ghc SDoc
+ HIE.Bios.Types: [getDependencies] :: CradleAction -> IO [FilePath]
- HIE.Bios: defaultCradle :: FilePath -> Cradle
+ HIE.Bios: defaultCradle :: FilePath -> [FilePath] -> Cradle
- HIE.Bios: findCradle :: FilePath -> IO Cradle
+ HIE.Bios: findCradle :: FilePath -> IO (Maybe FilePath)
- HIE.Bios.Config: Bazel :: CradleConfig
+ HIE.Bios.Config: Bazel :: CradleType
- HIE.Bios.Config: Bios :: FilePath -> CradleConfig
+ HIE.Bios.Config: Bios :: FilePath -> Maybe FilePath -> CradleType
- HIE.Bios.Config: Cabal :: Maybe String -> CradleConfig
+ HIE.Bios.Config: Cabal :: Maybe String -> CradleType
- HIE.Bios.Config: Default :: CradleConfig
+ HIE.Bios.Config: Default :: CradleType
- HIE.Bios.Config: Direct :: [String] -> CradleConfig
+ HIE.Bios.Config: Direct :: [String] -> CradleType
- HIE.Bios.Config: Obelisk :: CradleConfig
+ HIE.Bios.Config: Obelisk :: CradleType
- HIE.Bios.Config: Stack :: CradleConfig
+ HIE.Bios.Config: Stack :: CradleType
- HIE.Bios.Config: [arguments] :: CradleConfig -> [String]
+ HIE.Bios.Config: [arguments] :: CradleType -> [String]
- HIE.Bios.Config: [component] :: CradleConfig -> Maybe String
+ HIE.Bios.Config: [component] :: CradleType -> Maybe String
- HIE.Bios.Config: [prog] :: CradleConfig -> FilePath
+ HIE.Bios.Config: [prog] :: CradleType -> FilePath
- HIE.Bios.Cradle: defaultCradle :: FilePath -> Cradle
+ HIE.Bios.Cradle: defaultCradle :: FilePath -> [FilePath] -> Cradle
- HIE.Bios.Cradle: findCradle :: FilePath -> IO Cradle
+ HIE.Bios.Cradle: findCradle :: FilePath -> IO (Maybe FilePath)
- HIE.Bios.Types: CradleAction :: String -> (FilePath -> IO (ExitCode, String, [String])) -> CradleAction
+ HIE.Bios.Types: CradleAction :: String -> IO [FilePath] -> (FilePath -> IO (ExitCode, String, [String])) -> CradleAction

Files

ChangeLog view
@@ -1,3 +1,12 @@+2019-09-18 - 0.2++	* Compat with 8.2 and 8.8+	* Add support for explicitly specifying dependencies for a cradle+	* Separate arguments by null bytes, so arguments can contain spaces+	(cabal/stack wrapper)+	* Add --help to CLI+	* Fix the directories that certain processes run in+ 2019-09-07 - 0.1.1  	* Compat with GHC 8.4
exe/Main.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveDataTypeable, LambdaCase #-}  module Main where @@ -6,16 +6,18 @@  import Control.Exception (Exception, Handler(..), ErrorCall(..)) import qualified Control.Exception as E+import Control.Monad ( forM ) import Data.Typeable (Typeable) import Data.Version (showVersion) import System.Directory (getCurrentDirectory) import System.Environment (getArgs) import System.Exit (exitFailure) import System.IO (hPutStr, hPutStrLn, stdout, stderr, hSetEncoding, utf8)+import System.FilePath( (</>) )  import HIE.Bios import HIE.Bios.Types-import HIE.Bios.Check+import HIE.Bios.Ghc.Check import HIE.Bios.Debug import Paths_hie_bios @@ -30,9 +32,12 @@ usage :: String usage =    progVersion         ++ "Usage:\n"-        ++ "\t biosc check" ++ ghcOptHelp ++ "<HaskellFiles...>\n"-        ++ "\t biosc version\n"-        ++ "\t biosc help\n"+        ++ "\t hie-bios check" ++ ghcOptHelp ++ "<HaskellFiles...>\n"+        ++ "\t hie-bios expand <HaskellFiles...>\n"+        ++ "\t hie-bios flags <HaskellFiles...>\n"+        ++ "\t hie-bios debug\n"+        ++ "\t hie-bios root\n"+        ++ "\t hie-bios version\n"  ---------------------------------------------------------------- @@ -52,7 +57,9 @@     args <- getArgs     cradle <- getCurrentDirectory >>= \cwd ->         -- find cradle does a takeDirectory on the argument, so make it into a file-        findCradle $ cwd ++ "/File.hs"+        findCradle (cwd </> "File.hs") >>= \case+          Just yaml -> loadCradle yaml+          Nothing -> loadImplicitCradle (cwd </> "File.hs")     let cmdArg0 = args !. 0         remainingArgs = tail args         opt = defaultOptions@@ -62,6 +69,18 @@       "debug"   -> debugInfo opt cradle       "root"    -> rootInfo opt cradle       "version" -> return progVersion+      "flags"   -> do+        res <- forM remainingArgs $ \fp -> do+                res <- getCompilerOptions fp cradle+                case res of+                    Left err -> return $ "Failed to show flags for \"" ++ fp ++ "\": " ++ show err+                    Right opts -> return $ "CompilerOptions: " ++ show (ghcOptions opts)+        return (unlines res)++      "help"    -> return usage+      "--help"  -> return usage+      "-h"      -> return usage+       cmd       -> E.throw (NoSuchCommand cmd)     putStr res   where@@ -70,11 +89,13 @@     handler1 :: ErrorCall -> IO ()     handler1 = print -- for debug     handler2 :: HhpcError -> IO ()-    handler2 SafeList = return ()+    handler2 SafeList = hPutStr stderr usage     handler2 (TooManyArguments cmd) = do         hPutStrLn stderr $ "\"" ++ cmd ++ "\": Too many arguments"     handler2 (NoSuchCommand cmd) = do         hPutStrLn stderr $ "\"" ++ cmd ++ "\" not supported"+        hPutStrLn stderr ""+        hPutStr stderr usage     handler2 (CmdArg errs) = do         mapM_ (hPutStr stderr) errs     handler2 (FileNotExist file) = do
hie-bios.cabal view
@@ -1,12 +1,12 @@ Name:                   hie-bios-Version:                0.1.1+Version:                0.2.0 Author:                 Matthew Pickering <matthewtpickering@gmail.com> Maintainer:             Matthew Pickering <matthewtpickering@gmail.com> License:                BSD3 License-File:           LICENSE Homepage:               https://github.com/mpickering/hie-bios Synopsis:               Set up a GHC API session-Description:+Description:            Set up a GHC API session and obtain flags required to compile a source file  Category:               Development Cabal-Version:          >= 1.10@@ -16,38 +16,42 @@                         wrappers/cabal                         wrappers/cabal.hs +tested-with: GHC==8.6.4, GHC==8.4.4, GHC==8.2.2+ Library   Default-Language:     Haskell2010   GHC-Options:          -Wall   HS-Source-Dirs:       src   Exposed-Modules:      HIE.Bios-                        HIE.Bios.Check+                        HIE.Bios.Config                         HIE.Bios.Cradle+                        HIE.Bios.Environment                         HIE.Bios.Debug-                        HIE.Bios.GHCApi-                        HIE.Bios.Gap-                        HIE.Bios.Doc-                        HIE.Bios.Load-                        HIE.Bios.Logger+                        HIE.Bios.Flags                         HIE.Bios.Types-                        HIE.Bios.Things-                        HIE.Bios.Config+                        HIE.Bios.Ghc.Api+                        HIE.Bios.Ghc.Check+                        HIE.Bios.Ghc.Doc+                        HIE.Bios.Ghc.Gap+                        HIE.Bios.Ghc.Load+                        HIE.Bios.Ghc.Logger+                        HIE.Bios.Ghc.Things   Build-Depends:                         base >= 4.8 && < 5,                         base16-bytestring    >= 0.1.1 && < 0.2,                         bytestring           >= 0.10.8 && < 0.11,                         deepseq              >= 1.4.3 && < 1.5,-                        containers           >= 0.5.11 && < 0.7,+                        containers           >= 0.5.10 && < 0.7,                         cryptohash-sha1      >= 0.11.100 && < 0.12,-                        directory            >= 1.3.1 && < 1.4,-                        filepath             >= 1.4.2 && < 1.5,-                        time                 >= 1.8.0 && < 1.9,+                        directory            >= 1.3.0 && < 1.4,+                        filepath             >= 1.4.1 && < 1.5,+                        time                 >= 1.8.0 && < 1.10,                         extra                >= 1.6.18 && < 1.7,                         process              >= 1.6.1 && < 1.7,                         file-embed           >= 0.0.11 && < 0.1,-                        ghc                  >= 8.4.1 && < 8.7,-                        transformers         >= 0.5.5 && < 0.6,-                        temporary            >= 1.3 && < 1.4,+                        ghc                  >= 8.2.2 && < 8.9,+                        transformers         >= 0.5.2 && < 0.6,+                        temporary            >= 1.2 && < 1.4,                         text                 >= 1.2.3 && < 1.3,                         unix-compat          >= 0.5.2 && < 0.6,                         unordered-containers >= 0.2.10 && < 0.3,
src/HIE/Bios.hs view
@@ -1,20 +1,20 @@ -- | The HIE Bios  module HIE.Bios (-  -- * Initialise a session+  -- * Find and load a Cradle     Cradle(..)   , findCradle+  , loadCradle+  , loadImplicitCradle   , defaultCradle-  , initializeFlagsWithCradle-  , initializeFlagsWithCradleWithMessage-  -- * Load a module into a session-  , loadFile-  , loadFileWithMessage-  -- * Eliminate a session to IO-  , withGhcT+  -- * Compiler Options+  , CompilerOptions(..)+  , getCompilerOptions+  -- * Initialise session+  , initSession   ) where  import HIE.Bios.Cradle import HIE.Bios.Types-import HIE.Bios.GHCApi-import HIE.Bios.Load+import HIE.Bios.Flags+import HIE.Bios.Environment
− src/HIE/Bios/Check.hs
@@ -1,75 +0,0 @@-module HIE.Bios.Check (-    checkSyntax-  , check-  , expandTemplate-  , expand-  ) where--import DynFlags (dopt_set, DumpFlag(Opt_D_dump_splices))-import GHC (Ghc, DynFlags(..), GhcMonad)--import HIE.Bios.GHCApi-import HIE.Bios.Logger-import HIE.Bios.Types-import HIE.Bios.Load-import Outputable---------------------------------------------------------------------- | Checking syntax of a target file using GHC.---   Warnings and errors are returned.-checkSyntax :: Options-            -> Cradle-            -> [FilePath]  -- ^ The target files.-            -> IO String-checkSyntax _   _      []    = return ""-checkSyntax opt cradle files = withGhcT $ do-    pprTrace "cradble" (text $ show cradle) (return ())-    initializeFlagsWithCradle (head files) cradle-    either id id <$> check opt files-  where-    {--    sessionName = case files of-      [file] -> file-      _      -> "MultipleFiles"-      -}---------------------------------------------------------------------- | Checking syntax of a target file using GHC.---   Warnings and errors are returned.-check :: (GhcMonad m)-      => Options-      -> [FilePath]  -- ^ The target files.-      -> m (Either String String)-check opt fileNames = withLogger opt setAllWarningFlags $ setTargetFiles (map dup fileNames)--dup :: a -> (a, a)-dup x = (x, x)---------------------------------------------------------------------- | Expanding Haskell Template.-expandTemplate :: Options-               -> Cradle-               -> [FilePath]  -- ^ The target files.-               -> IO String-expandTemplate _   _      []    = return ""-expandTemplate opt cradle files = withGHC sessionName $ do-    initializeFlagsWithCradle (head files) cradle-    either id id <$> expand opt files-  where-    sessionName = case files of-      [file] -> file-      _      -> "MultipleFiles"---------------------------------------------------------------------- | Expanding Haskell Template.-expand :: Options-      -> [FilePath]  -- ^ The target files.-      -> Ghc (Either String String)-expand opt fileNames = withLogger opt (setDumpSplices . setNoWarningFlags) $ setTargetFiles (map dup fileNames)--setDumpSplices :: DynFlags -> DynFlags-setDumpSplices dflag = dopt_set dflag Opt_D_dump_splices
src/HIE/Bios/Config.hs view
@@ -1,45 +1,117 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ViewPatterns #-} module HIE.Bios.Config(     readConfig,     Config(..),-    CradleConfig(..)+    CradleConfig(..),+    CradleType(..)     ) where  import qualified Data.Text as T import qualified Data.Vector as V import qualified Data.HashMap.Strict as Map-import Data.Yaml+import           Data.Yaml +data CradleConfig =+    CradleConfig+        { cradleDependencies :: [FilePath]+        -- ^ Dependencies of a cradle.+        -- Dependencies are expected to be relative to the root directory.+        -- The given files are not required to exist.+        , cradleType :: CradleType+        -- ^ Type of the cradle to use. Actions to obtain+        -- compiler flags from are dependant on this field.+        }+        deriving (Show) -data CradleConfig = Cabal { component :: Maybe String }-                  | Stack-                  | Bazel-                  | Obelisk-                  | Bios { prog :: FilePath }-                  | Direct { arguments :: [String] }-                  | Default-                  deriving (Show)+data CradleType+    = Cabal { component :: Maybe String }+    | Stack+    | Bazel+    | Obelisk+    | Bios+        { prog :: FilePath+        -- ^ Path to program that retrieves options to compile a file+        , depsProg :: Maybe FilePath+        -- ^ Optional Path to program to obtain cradle dependencies.+        -- Each cradle dependency is to be expected to be on a separate line+        -- and relative to the root dir of the cradle, not relative+        -- to the location of this program.+        }+    | Direct { arguments :: [String] }+    | Default+    deriving (Show) -instance FromJSON CradleConfig where-    parseJSON (Object (Map.toList -> [(key, val)]))-        | key == "cabal" = case val of-            Object x | Just (String v) <- Map.lookup "component" x -> return $ Cabal $ Just $ T.unpack v-            _ -> return $ Cabal Nothing-        | key == "stack" = return Stack-        | key == "bazel" = return Bazel-        | key == "obelisk" = return Obelisk-        | key == "bios", Object x <- val, Just (String v) <- Map.lookup "program" x = return $ Bios $ T.unpack v-        | key == "direct", Object x <- val, Just (Array v) <- Map.lookup "arguments" x = return $ Direct [T.unpack s | String s <- V.toList v]-        | key == "default" = return Default-    parseJSON _ = fail "Not a known configuration"+instance FromJSON CradleType where+    parseJSON (Object o) = parseCradleType o+    parseJSON _ = fail "Not a known cradle type. Possible are: cabal, stack, bazel, obelisk, bios, direct, default" +parseCradleType :: Object -> Parser CradleType+parseCradleType o+    | Just val <- Map.lookup "cabal" o = parseCabal val+    | Just _val <- Map.lookup "stack" o = return Stack+    | Just _val <- Map.lookup "bazel" o = return Bazel+    | Just _val <- Map.lookup "obelisk" o = return Obelisk+    | Just val <- Map.lookup "bios" o = parseBios val+    | Just val <- Map.lookup "direct" o = parseDirect val+    | Just _val <- Map.lookup "default" o = return Default+parseCradleType o = fail $ "Unknown cradle type: " ++ show o++parseCabal :: Value -> Parser CradleType+parseCabal (Object x)+    | Map.size x == 1+    , Just (String cabalComponent) <- Map.lookup "component" x+    = return $ Cabal $ Just $ T.unpack cabalComponent++    | Map.null x+    = return $ Cabal Nothing++    | otherwise+    = fail "Not a valid Cabal Configuration type, following keys are allowed: component"+parseCabal _ = fail "Cabal Configuration is expected to be an object."++parseBios :: Value -> Parser CradleType+parseBios (Object x)+    | 2 == Map.size x+    , Just (String biosProgram) <- Map.lookup "program" x+    , Just (String biosDepsProgram) <- Map.lookup "dependency-program" x+    = return $ Bios (T.unpack biosProgram) (Just (T.unpack biosDepsProgram))++    | 1 == Map.size x+    , Just (String biosProgram) <- Map.lookup "program" x+    = return $ Bios (T.unpack biosProgram) Nothing++    | otherwise+    = fail "Not a valid Bios Configuration type, following keys are allowed: program, dependency-program"+parseBios _ = fail "Bios Configuration is expected to be an object."++parseDirect :: Value -> Parser CradleType+parseDirect (Object x)+    | Map.size x == 1+    , Just (Array v) <- Map.lookup "arguments" x+    = return $ Direct [T.unpack s | String s <- V.toList v]++    | otherwise+    = fail "Not a valid Direct Configuration type, following keys are allowed: arguments"+parseDirect _ = fail "Direct Configuration is expected to be an object."+ data Config = Config { cradle :: CradleConfig }     deriving (Show)  instance FromJSON Config where-    parseJSON (Object (Map.toList -> [("cradle", x)])) = Config <$> parseJSON x-    parseJSON _ = fail "Expected a cradle: key containing the preferences"+    parseJSON (Object val) = do+            crd     <- val .: "cradle"+            crdDeps <- case Map.size val of+                1 -> return []+                2 -> val .: "dependencies"+                _ -> fail "Unknown key, following keys are allowed: cradle, dependencies" +            return Config+                { cradle = CradleConfig { cradleType         = crd+                                        , cradleDependencies = crdDeps+                                        }+                }++    parseJSON _ = fail "Expected a cradle: key containing the preferences, possible values: cradle, dependencies"+ readConfig :: FilePath -> IO Config-readConfig fp = decodeFileThrow fp+readConfig = decodeFileThrow
src/HIE/Bios/Cradle.hs view
@@ -2,7 +2,8 @@ {-# LANGUAGE TupleSections #-} module HIE.Bios.Cradle (       findCradle-    , findCradleWithOpts+    , loadCradle+    , loadImplicitCradle     , defaultCradle   ) where @@ -21,50 +22,77 @@ import System.IO.Temp import Data.List -import Debug.Trace import System.PosixCompat.Files  -----------------------------------------------------------------findCradle :: FilePath -> IO Cradle-findCradle = findCradleWithOpts defaultCradleOpts +-- | Given root/foo/bar.hs, return root/hie.yaml, or wherever the yaml file was found+findCradle :: FilePath -> IO (Maybe FilePath)+findCradle wfile = do+    let wdir = takeDirectory wfile+    runMaybeT (yamlConfig wdir)++-- | Given root/hie.yaml load the Cradle+loadCradle :: FilePath -> IO Cradle+loadCradle = loadCradleWithOpts defaultCradleOpts++-- | Given root/foo/bar.hs, load an implicit cradle+loadImplicitCradle :: FilePath -> IO Cradle+loadImplicitCradle wfile = do+  let wdir = takeDirectory wfile+  cfg <- runMaybeT (implicitConfig wdir)+  return $ case cfg of+    Just bc -> getCradle bc+    Nothing -> defaultCradle wdir []+ -- | Finding 'Cradle'. --   Find a cabal file by tracing ancestor directories. --   Find a sandbox according to a cabal sandbox config --   in a cabal directory.-findCradleWithOpts :: CradleOpts -> FilePath -> IO Cradle-findCradleWithOpts _copts wfile = do-    let wdir = takeDirectory wfile-    cfg <- runMaybeT (dhallConfig wdir <|> implicitConfig wdir)-    return $ case cfg of-      Just bc -> getCradle bc-      Nothing -> (defaultCradle wdir)-+loadCradleWithOpts :: CradleOpts -> FilePath -> IO Cradle+loadCradleWithOpts _copts wfile = do+    cradleConfig <- readCradleConfig wfile+    return $ getCradle (cradleConfig, takeDirectory wfile)  getCradle :: (CradleConfig, FilePath) -> Cradle-getCradle (cc, wdir) = case cc of-                 Cabal mc -> cabalCradle wdir mc-                 Stack -> stackCradle wdir-                 Bazel -> rulesHaskellCradle wdir-                 Obelisk -> obeliskCradle wdir-                 Bios bios -> biosCradle wdir bios-                 Direct xs -> directCradle wdir xs-                 Default   -> defaultCradle wdir+getCradle (cc, wdir) = case cradleType cc of+    Cabal mc -> cabalCradle wdir mc cradleDeps+    Stack -> stackCradle wdir cradleDeps+    Bazel -> rulesHaskellCradle wdir cradleDeps+    Obelisk -> obeliskCradle wdir cradleDeps+    Bios bios deps  -> biosCradle wdir bios deps cradleDeps+    Direct xs -> directCradle wdir xs cradleDeps+    Default   -> defaultCradle wdir cradleDeps+    where+      cradleDeps = cradleDependencies cc  implicitConfig :: FilePath -> MaybeT IO (CradleConfig, FilePath)-implicitConfig fp =-         (\wdir -> (Bios (wdir </> ".hie-bios"), wdir)) <$> biosWorkDir fp+implicitConfig fp = do+  (crdType, wdir) <- implicitConfig' fp+  return (CradleConfig [] crdType, wdir)++implicitConfig' :: FilePath -> MaybeT IO (CradleType, FilePath)+implicitConfig' fp = (\wdir ->+         (Bios (wdir </> ".hie-bios") Nothing, wdir)) <$> biosWorkDir fp      <|> (Obelisk,) <$> obeliskWorkDir fp      <|> (Bazel,) <$> rulesHaskellWorkDir fp      <|> (Stack,) <$> stackWorkDir fp      <|> ((Cabal Nothing,) <$> cabalWorkDir fp) -dhallConfig :: FilePath -> MaybeT IO (CradleConfig, FilePath)-dhallConfig fp = do-  wdir <- findFileUpwards (configFileName ==) fp-  cfg  <- liftIO $ readConfig (wdir </> configFileName)-  return (cradle cfg, wdir) +yamlConfig :: FilePath ->  MaybeT IO FilePath+yamlConfig fp = do+  configDir <- yamlConfigDirectory fp+  return (configDir </> configFileName)++yamlConfigDirectory :: FilePath -> MaybeT IO FilePath+yamlConfigDirectory = findFileUpwards (configFileName ==)++readCradleConfig :: FilePath -> IO CradleConfig+readCradleConfig yamlHie = do+  cfg  <- liftIO $ readConfig yamlHie+  return (cradle cfg)+ configFileName :: FilePath configFileName = "hie.yaml" @@ -73,38 +101,59 @@ -- Default cradle has no special options, not very useful for loading -- modules. -defaultCradle :: FilePath -> Cradle-defaultCradle cur_dir =-  Cradle {-      cradleRootDir = cur_dir-    , cradleOptsProg = CradleAction "default" (const $ return (ExitSuccess, "", []))+defaultCradle :: FilePath -> [FilePath] -> Cradle+defaultCradle cur_dir deps =+  Cradle+    { cradleRootDir = cur_dir+    , cradleOptsProg = CradleAction+        { actionName = "default"+        , getDependencies = return deps+        , getOptions = const $ return (ExitSuccess, "", [])+        }     }  ------------------------------------------------------------------------- -directCradle :: FilePath -> [String] -> Cradle-directCradle wdir args =-  Cradle {-      cradleRootDir = wdir-    , cradleOptsProg = CradleAction "direct" (const $ return (ExitSuccess, "", args))-  }-+directCradle :: FilePath -> [String] -> [FilePath] -> Cradle+directCradle wdir args deps =+  Cradle+    { cradleRootDir = wdir+    , cradleOptsProg = CradleAction+        { actionName = "direct"+        , getDependencies = return deps+        , getOptions = const $ return (ExitSuccess, "", args)+        }+    }  -------------------------------------------------------------------------   -- | Find a cradle by finding an executable `hie-bios` file which will -- be executed to find the correct GHC options to use.-biosCradle :: FilePath -> FilePath -> Cradle-biosCradle wdir bios = do-  Cradle {-      cradleRootDir    = wdir-    , cradleOptsProg   = CradleAction "bios" (biosAction wdir bios)-  }+biosCradle :: FilePath -> FilePath -> Maybe FilePath -> [FilePath] -> Cradle+biosCradle wdir biosProg biosDepsProg deps =+  Cradle+    { cradleRootDir    = wdir+    , cradleOptsProg   = CradleAction+        { actionName = "bios"+        , getDependencies = fmap (deps `union`) (biosDepsAction biosDepsProg)+        -- Execute the bios action and add dependencies of the cradle.+        -- Removes all duplicates.+        , getOptions = biosAction wdir biosProg+        }+    }  biosWorkDir :: FilePath -> MaybeT IO FilePath biosWorkDir = findFileUpwards (".hie-bios" ==) +biosDepsAction :: Maybe FilePath -> IO [FilePath]+biosDepsAction (Just biosDepsProg) = do+  biosDeps' <- canonicalizePath biosDepsProg+  (ex, sout, serr) <- readProcessWithExitCode biosDeps' [] []+  case ex of+    ExitFailure _ ->  error $ show (ex, sout, serr)+    ExitSuccess -> return (lines sout)+biosDepsAction Nothing = return []  biosAction :: FilePath -> FilePath -> FilePath -> IO (ExitCode, String, [String]) biosAction _wdir bios fp = do@@ -117,13 +166,27 @@ -- Works for new-build by invoking `v2-repl` does not support components -- yet. -cabalCradle :: FilePath -> Maybe String -> Cradle-cabalCradle wdir mc = do-  Cradle {-      cradleRootDir    = wdir-    , cradleOptsProg   = CradleAction "cabal" (cabalAction wdir mc)-  }+cabalCradle :: FilePath -> Maybe String -> [FilePath] -> Cradle+cabalCradle wdir mc deps =+  Cradle+    { cradleRootDir    = wdir+    , cradleOptsProg   = CradleAction+        { actionName = "cabal"+        , getDependencies = fmap (deps `union`) (cabalCradleDependencies wdir)+        , getOptions = cabalAction wdir mc+        }+    } +cabalCradleDependencies :: FilePath -> IO [FilePath]+cabalCradleDependencies rootDir = do+    cabalFiles <- findCabalFiles rootDir+    return $ cabalFiles ++ ["cabal.project"]++findCabalFiles :: FilePath -> IO [FilePath]+findCabalFiles wdir = do+  dirContent <- listDirectory wdir+  return $ filter ((== ".cabal") . takeExtension) dirContent+ cabalWrapper :: String cabalWrapper = $(embedStringFile "wrappers/cabal") @@ -134,9 +197,20 @@ processCabalWrapperArgs args =     case lines args of         [dir, ghc_args] ->-            let final_args = removeInteractive $ map (fixImportDirs dir) (words ghc_args)-            in trace dir $ Just final_args+            let final_args =+                    removeInteractive+                    $ map (fixImportDirs dir)+                    $ limited ghc_args+            in Just final_args         _ -> Nothing+  where+    limited :: String -> [String]+    limited = unfoldr $ \argstr ->+        if null argstr+        then Nothing+        else+            let (arg, argstr') = break (== '\NUL') argstr+            in Just (arg, drop 1 argstr')  -- generate a fake GHC that can be passed to cabal -- when run with --interactive, it will print out its@@ -149,7 +223,9 @@         wrapper_hs <- writeSystemTempFile "wrapper.hs" cabalWrapperHs         -- the initial contents will be overwritten immediately after by ghc         wrapper_fp <- writeSystemTempFile "wrapper.exe" ""-        callProcess "ghc" ["-o", wrapper_fp, wrapper_hs]+        let ghc = (proc "ghc" ["-o", wrapper_fp, wrapper_hs])+                    { cwd = Just (takeDirectory wrapper_hs) }+        readCreateProcess ghc "" >>= putStr         return wrapper_fp       else do         writeSystemTempFile "bios-wrapper" cabalWrapper@@ -163,7 +239,7 @@   let cab_args = ["v2-repl", "-v0", "--disable-documentation", "--with-compiler", wrapper_fp]                   ++ [component_name | Just component_name <- [mc]]   (ex, args, stde) <--      withCurrentDirectory work_dir (readProcessWithExitCode "cabal" cab_args [])+    readProcessWithExitCodeInDirectory work_dir "cabal" cab_args []   case processCabalWrapperArgs args of       Nothing -> error (show (ex, stde, args))       Just final_args -> pure (ex, stde, final_args)@@ -175,7 +251,7 @@ fixImportDirs base_dir arg =   if "-i" `isPrefixOf` arg     then let dir = drop 2 arg-         in if isRelative dir then ("-i" <> base_dir <> "/" <> dir)+         in if isRelative dir then ("-i" ++ base_dir ++ "/" ++ dir)                               else arg     else arg @@ -189,13 +265,22 @@ -- Stack Cradle -- Works for by invoking `stack repl` with a wrapper script -stackCradle :: FilePath -> Cradle-stackCradle wdir =-  Cradle {-      cradleRootDir    = wdir-    , cradleOptsProg   = CradleAction "stack" (stackAction wdir)-  }+stackCradle :: FilePath -> [FilePath] -> Cradle+stackCradle wdir deps =+  Cradle+    { cradleRootDir    = wdir+    , cradleOptsProg   = CradleAction+        { actionName = "stack"+        , getDependencies = fmap (deps `union`) (stackCradleDependencies wdir)+        , getOptions = stackAction wdir+        }+    } +stackCradleDependencies :: FilePath -> IO [FilePath]+stackCradleDependencies wdir = do+    cabalFiles <- findCabalFiles wdir+    return $ cabalFiles ++ ["package.yaml", "stack.yaml"]+ -- Same wrapper works as with cabal stackWrapper :: String stackWrapper = $(embedStringFile "wrappers/cabal")@@ -205,12 +290,13 @@   wrapper_fp <- writeSystemTempFile "wrapper" stackWrapper   -- TODO: This isn't portable for windows   setFileMode wrapper_fp accessModes-  check <- readFile wrapper_fp-  traceM check+  -- TODO: this is for debugging+  -- check <- readFile wrapper_fp+  -- traceM check   (ex1, args, stde) <--      withCurrentDirectory work_dir (readProcessWithExitCode "stack" ["repl", "--silent", "--no-load", "--with-ghc", wrapper_fp, fp ] [])+      readProcessWithExitCodeInDirectory work_dir "stack" ["repl", "--silent", "--no-load", "--with-ghc", wrapper_fp, fp ] []   (ex2, pkg_args, stdr) <--      withCurrentDirectory work_dir (readProcessWithExitCode "stack" ["path", "--ghc-package-path"] [])+      readProcessWithExitCodeInDirectory work_dir "stack" ["path", "--ghc-package-path"] []   let split_pkgs = splitSearchPath (init pkg_args)       pkg_ghc_args = concatMap (\p -> ["-package-db", p] ) split_pkgs   case processCabalWrapperArgs args of@@ -224,13 +310,11 @@     go a _ = a  - stackWorkDir :: FilePath -> MaybeT IO FilePath stackWorkDir = findFileUpwards isStack   where     isStack name = name == "stack.yaml" - ---------------------------------------------------------------------------- -- rules_haskell - Thanks for David Smith for helping with this one. -- Looks for the directory containing a WORKSPACE file@@ -239,13 +323,19 @@ rulesHaskellWorkDir fp =   findFileUpwards (== "WORKSPACE") fp -rulesHaskellCradle :: FilePath -> Cradle-rulesHaskellCradle wdir = do-  Cradle {-      cradleRootDir  = wdir-    , cradleOptsProg   = CradleAction "bazel" (rulesHaskellAction wdir)+rulesHaskellCradle :: FilePath -> [FilePath] -> Cradle+rulesHaskellCradle wdir deps =+  Cradle+    { cradleRootDir  = wdir+    , cradleOptsProg   = CradleAction+        { actionName = "bazel"+        , getDependencies = fmap (deps `union`) (rulesHaskellCradleDependencies wdir)+        , getOptions = rulesHaskellAction wdir+        }     } +rulesHaskellCradleDependencies :: FilePath -> IO [FilePath]+rulesHaskellCradleDependencies _wdir = return ["BUILD.bazel", "WORKSPACE"]  bazelCommand :: String bazelCommand = $(embedStringFile "wrappers/bazel")@@ -255,12 +345,9 @@   wrapper_fp <- writeSystemTempFile "wrapper" bazelCommand   -- TODO: This isn't portable for windows   setFileMode wrapper_fp accessModes-  check <- readFile wrapper_fp-  traceM check   let rel_path = makeRelative work_dir fp-  traceM rel_path   (ex, args, stde) <--      withCurrentDirectory work_dir (readProcessWithExitCode wrapper_fp [rel_path] [])+      readProcessWithExitCodeInDirectory work_dir wrapper_fp [rel_path] []   let args'  = filter (/= '\'') args   let args'' = filter (/= "\"$GHCI_LOCATION\"") (words args')   return (ex, stde, args'')@@ -279,18 +366,24 @@   unless check (fail "Not obelisk dir")   return wdir +obeliskCradleDependencies :: FilePath -> IO [FilePath]+obeliskCradleDependencies _wdir = return [] -obeliskCradle :: FilePath -> Cradle-obeliskCradle wdir =-  Cradle {-      cradleRootDir  = wdir-    , cradleOptsProg = CradleAction "obelisk" (obeliskAction wdir)+obeliskCradle :: FilePath -> [FilePath] -> Cradle+obeliskCradle wdir deps =+  Cradle+    { cradleRootDir  = wdir+    , cradleOptsProg = CradleAction+        { actionName = "obelisk"+        , getDependencies = fmap (deps `union`) (obeliskCradleDependencies wdir)+        , getOptions = obeliskAction wdir+        }     }  obeliskAction :: FilePath -> FilePath -> IO (ExitCode, String, [String]) obeliskAction work_dir _fp = do   (ex, args, stde) <--      withCurrentDirectory work_dir (readProcessWithExitCode "ob" ["ide-args"] [])+      readProcessWithExitCodeInDirectory work_dir "ob" ["ide-args"] []   return (ex, stde, words args)  @@ -316,3 +409,11 @@   where     getFiles = filter p <$> getDirectoryContents dir     doesPredFileExist file = doesFileExist $ dir </> file++-- | Call a process with the given arguments and the given stdin+-- in the given working directory.+readProcessWithExitCodeInDirectory+  :: FilePath -> FilePath -> [String] -> String -> IO (ExitCode, String, String)+readProcessWithExitCodeInDirectory work_dir fp args stdin =+  let process = (proc fp args) { cwd = Just work_dir }+  in  readCreateProcessWithExitCode process stdin
src/HIE/Bios/Debug.hs view
@@ -1,10 +1,11 @@ module HIE.Bios.Debug (debugInfo, rootInfo) where -import CoreMonad (liftIO)+import Control.Monad.IO.Class (liftIO) +import qualified Data.Char as Char import Data.Maybe (fromMaybe) -import HIE.Bios.GHCApi+import HIE.Bios.Ghc.Api import HIE.Bios.Types  ----------------------------------------------------------------@@ -15,14 +16,19 @@           -> IO String debugInfo opt cradle = convert opt <$> do     (_ex, _sterr, gopts) <- getOptions (cradleOptsProg cradle) (cradleRootDir cradle)+    deps  <- getDependencies (cradleOptsProg cradle)     mglibdir <- liftIO getSystemLibDir     return [         "Root directory:      " ++ rootDir-      , "GHC options:         " ++ unwords gopts+      , "GHC options:         " ++ unwords (map quoteIfNeeded gopts)       , "System libraries:    " ++ fromMaybe "" mglibdir+      , "Dependencies:        " ++ unwords deps       ]   where     rootDir    = cradleRootDir cradle+    quoteIfNeeded option+      | any Char.isSpace option = "\"" ++ option ++ "\""+      | otherwise = option  ---------------------------------------------------------------- 
− src/HIE/Bios/Doc.hs
@@ -1,24 +0,0 @@-module HIE.Bios.Doc where--import GHC (DynFlags, getPrintUnqual, pprCols, GhcMonad)-import Outputable (PprStyle, SDoc, withPprStyleDoc, neverQualify)-import Pretty (Mode(..), Doc, Style(..), renderStyle, style)--import HIE.Bios.Gap (makeUserStyle)--showPage :: DynFlags -> PprStyle -> SDoc -> String-showPage dflag stl = showDocWith dflag PageMode . withPprStyleDoc dflag stl--showOneLine :: DynFlags -> PprStyle -> SDoc -> String-showOneLine dflag stl = showDocWith dflag OneLineMode . withPprStyleDoc dflag stl--getStyle :: (GhcMonad m) => DynFlags -> m PprStyle-getStyle dflags = makeUserStyle dflags <$> getPrintUnqual--styleUnqualified :: DynFlags -> PprStyle-styleUnqualified dflags = makeUserStyle dflags neverQualify--showDocWith :: DynFlags -> Mode -> Doc -> String-showDocWith dflags md = renderStyle mstyle-  where-    mstyle = style { mode = md, lineLength = pprCols dflags }
+ src/HIE/Bios/Environment.hs view
@@ -0,0 +1,209 @@+{-# LANGUAGE RecordWildCards, CPP #-}+module HIE.Bios.Environment (initSession, getSystemLibDir, addCmdOpts, getDynamicFlags) where++import CoreMonad (liftIO)+import GHC (DynFlags(..), GhcLink(..), HscTarget(..), GhcMonad)+import qualified GHC as G+import qualified DriverPhases as G+import qualified Util as G+import DynFlags++import Control.Monad (void, when)++import System.Process (readProcess)+import System.Directory+import System.FilePath++import qualified Crypto.Hash.SHA1 as H+import qualified Data.ByteString.Char8 as B+import Data.ByteString.Base16+import Data.List++import HIE.Bios.Types++initSession :: (GhcMonad m)+    => CompilerOptions+    -> m [G.Target]+initSession  CompilerOptions {..} = do+    df <- G.getSessionDynFlags+    -- traceShowM (length ghcOptions)++    let opts_hash = B.unpack $ encode $ H.finalize $ H.updates H.init (map B.pack ghcOptions)+    fp <- liftIO $ getCacheDir opts_hash+    -- For now, clear the cache initially rather than persist it across+    -- sessions+    liftIO $ clearInterfaceCache opts_hash+    (df', targets) <- addCmdOpts ghcOptions df+    void $ G.setSessionDynFlags+        (disableOptimisation+        $ setIgnoreInterfacePragmas+        $ resetPackageDb+        -- --  $ ignorePackageEnv+        $ writeInterfaceFiles (Just fp)+        $ setVerbosity 0++        $ setLinkerOptions df'+        )+    G.setLogAction (\_df _wr _s _ss _pp _m -> return ())+#if __GLASGOW_HASKELL__ < 806+        (\_df -> return ())+#endif++    return targets++----------------------------------------------------------------++-- | Obtaining the directory for system libraries.+getSystemLibDir :: IO (Maybe FilePath)+getSystemLibDir = do+    res <- readProcess "ghc" ["--print-libdir"] []+    return $ case res of+        ""   -> Nothing+        dirn -> Just (init dirn)++----------------------------------------------------------------+++cacheDir :: String+cacheDir = "haskell-ide-engine"++clearInterfaceCache :: FilePath -> IO ()+clearInterfaceCache fp = do+  cd <- getCacheDir fp+  res <- doesPathExist cd+  when res (removeDirectoryRecursive cd)++getCacheDir :: FilePath -> IO FilePath+getCacheDir fp = getXdgDirectory XdgCache (cacheDir </> fp)++----------------------------------------------------------------++-- we don't want to generate object code so we compile to bytecode+-- (HscInterpreted) which implies LinkInMemory+-- HscInterpreted+setLinkerOptions :: DynFlags -> DynFlags+setLinkerOptions df = df {+    ghcLink   = LinkInMemory+  , hscTarget = HscNothing+  , ghcMode = CompManager+  }++resetPackageDb :: DynFlags -> DynFlags+resetPackageDb df = df { pkgDatabase = Nothing }++--ignorePackageEnv :: DynFlags -> DynFlags+--ignorePackageEnv df = df { packageEnv = Just "-" }++setIgnoreInterfacePragmas :: DynFlags -> DynFlags+setIgnoreInterfacePragmas df = gopt_set df Opt_IgnoreInterfacePragmas++setVerbosity :: Int -> DynFlags -> DynFlags+setVerbosity n df = df { verbosity = n }++writeInterfaceFiles :: Maybe FilePath -> DynFlags -> DynFlags+writeInterfaceFiles Nothing df = df+writeInterfaceFiles (Just hi_dir) df = setHiDir hi_dir (gopt_set df Opt_WriteInterface)++setHiDir :: FilePath -> DynFlags -> DynFlags+setHiDir f d = d { hiDir      = Just f}+++addCmdOpts :: (GhcMonad m)+           => [String] -> DynFlags -> m (DynFlags, [G.Target])+addCmdOpts cmdOpts df1 = do+  (df2, leftovers, _warns) <- G.parseDynamicFlags df1 (map G.noLoc cmdOpts)+  -- TODO: remove this trace+  -- What about warnings?+  -- traceShowM (map G.unLoc leftovers, length warns)++  let+     -- To simplify the handling of filepaths, we normalise all filepaths right+     -- away. Note the asymmetry of FilePath.normalise:+     --    Linux:   p/q -> p/q; p\q -> p\q+     --    Windows: p/q -> p\q; p\q -> p\q+     -- #12674: Filenames starting with a hypen get normalised from ./-foo.hs+     -- to -foo.hs. We have to re-prepend the current directory.+    normalise_hyp fp+        | strt_dot_sl && "-" `isPrefixOf` nfp = cur_dir ++ nfp+        | otherwise                           = nfp+        where+#if defined(mingw32_HOST_OS)+          strt_dot_sl = "./" `isPrefixOf` fp || ".\\" `isPrefixOf` fp+#else+          strt_dot_sl = "./" `isPrefixOf` fp+#endif+          cur_dir = '.' : [pathSeparator]+          nfp = normalise fp+    normal_fileish_paths = map (normalise_hyp . G.unLoc) leftovers+  let+   (srcs, objs) = partition_args normal_fileish_paths [] []+   df3 = df2 { ldInputs = map (FileOption "") objs ++ ldInputs df2 }+  ts <- mapM (uncurry G.guessTarget) srcs+  return (df3, ts)+    -- TODO: Need to handle these as well+    -- Ideally it requires refactoring to work in GHCi monad rather than+    -- Ghc monad and then can just use newDynFlags.+    {-+    liftIO $ G.handleFlagWarnings idflags1 warns+    when (not $ null leftovers)+        (throwGhcException . CmdLineError+         $ "Some flags have not been recognized: "+         ++ (concat . intersperse ", " $ map unLoc leftovers))+    when (interactive_only && packageFlagsChanged idflags1 idflags0) $ do+       liftIO $ hPutStrLn stderr "cannot set package flags with :seti; use :set"+    -}++----------------------------------------------------------------++-- | Return the 'DynFlags' currently in use in the GHC session.+getDynamicFlags :: IO DynFlags+getDynamicFlags = do+    mlibdir <- getSystemLibDir+    G.runGhc mlibdir G.getSessionDynFlags+++-- partition_args, along with some of the other code in this file,+-- was copied from ghc/Main.hs+-- -----------------------------------------------------------------------------+-- Splitting arguments into source files and object files.  This is where we+-- interpret the -x <suffix> option, and attach a (Maybe Phase) to each source+-- file indicating the phase specified by the -x option in force, if any.+partition_args :: [String] -> [(String, Maybe G.Phase)] -> [String]+               -> ([(String, Maybe G.Phase)], [String])+partition_args [] srcs objs = (reverse srcs, reverse objs)+partition_args ("-x":suff:args) srcs objs+  | "none" <- suff      = partition_args args srcs objs+  | G.StopLn <- phase     = partition_args args srcs (slurp ++ objs)+  | otherwise           = partition_args rest (these_srcs ++ srcs) objs+        where phase = G.startPhase suff+              (slurp,rest) = break (== "-x") args+              these_srcs = zip slurp (repeat (Just phase))+partition_args (arg:args) srcs objs+  | looks_like_an_input arg = partition_args args ((arg,Nothing):srcs) objs+  | otherwise               = partition_args args srcs (arg:objs)++    {-+      We split out the object files (.o, .dll) and add them+      to ldInputs for use by the linker.+      The following things should be considered compilation manager inputs:+       - haskell source files (strings ending in .hs, .lhs or other+         haskellish extension),+       - module names (not forgetting hierarchical module names),+       - things beginning with '-' are flags that were not recognised by+         the flag parser, and we want them to generate errors later in+         checkOptions, so we class them as source files (#5921)+       - and finally we consider everything without an extension to be+         a comp manager input, as shorthand for a .hs or .lhs filename.+      Everything else is considered to be a linker object, and passed+      straight through to the linker.+    -}+looks_like_an_input :: String -> Bool+looks_like_an_input m =  G.isSourceFilename m+                      || G.looksLikeModuleName m+                      || "-" `isPrefixOf` m+                      || not (hasExtension m)++-- --------------------------------------------------------++disableOptimisation :: DynFlags -> DynFlags+disableOptimisation df = updOptLevel 0 df
+ src/HIE/Bios/Flags.hs view
@@ -0,0 +1,29 @@+module HIE.Bios.Flags (getCompilerOptions, CradleError) where++import Control.Monad.IO.Class+import Control.Exception ( Exception )++import System.Exit (ExitCode(..))++import HIE.Bios.Types (Cradle, CompilerOptions(..), getOptions, cradleOptsProg)++-- | Initialize the 'DynFlags' relating to the compilation of a single+-- file or GHC session according to the 'Cradle' and 'Options'+-- provided.+getCompilerOptions ::+    FilePath -- The file we are loading it because of+    -> Cradle+    -> IO (Either CradleError CompilerOptions)+getCompilerOptions fp cradle = do+  (ex, err, ghcOpts) <- liftIO $ getOptions (cradleOptsProg cradle) fp+  case ex of+    ExitFailure _ -> return $ Left (CradleError err)+    _ -> do+        let compOpts = CompilerOptions ghcOpts+        return $ Right compOpts++data CradleError = CradleError String deriving (Show)++instance Exception CradleError where++----------------------------------------------------------------
− src/HIE/Bios/GHCApi.hs
@@ -1,343 +0,0 @@-{-# LANGUAGE ScopedTypeVariables, RecordWildCards, CPP #-}--module HIE.Bios.GHCApi (-    withGHC-  , withGHC'-  , withGhcT-  , initializeFlagsWithCradle-  , initializeFlagsWithCradleWithMessage-  , getDynamicFlags-  , getSystemLibDir-  , withDynFlags-  , withCmdFlags-  , setNoWarningFlags-  , setAllWarningFlags-  , setDeferTypeErrors-  , CradleError(..)-  ) where--import CoreMonad (liftIO)-import Exception (ghandle, SomeException(..), ExceptionMonad(..), throwIO, Exception(..))-import GHC (Ghc, DynFlags(..), GhcLink(..), HscTarget(..), LoadHowMuch(..), GhcMonad, GhcT)-import qualified GHC as G-import qualified DriverPhases as G-import qualified Outputable as G-import qualified MonadUtils as G-import qualified HscMain as G-import qualified GhcMake as G-import qualified Util as G-import DynFlags--import Control.Monad (void, when)-import System.Exit (exitSuccess, ExitCode(..))-import System.IO (hPutStr, hPrint, stderr)-import System.IO.Unsafe (unsafePerformIO)-import System.Process (readProcess)--import System.Directory-import System.FilePath--import qualified HIE.Bios.Gap as Gap-import HIE.Bios.Types-import Debug.Trace-import qualified Crypto.Hash.SHA1 as H-import qualified Data.ByteString.Char8 as B-import Data.ByteString.Base16-import Data.List---------------------------------------------------------------------- | Obtaining the directory for system libraries.-getSystemLibDir :: IO (Maybe FilePath)-getSystemLibDir = do-    res <- readProcess "ghc" ["--print-libdir"] []-    return $ case res of-        ""   -> Nothing-        dirn -> Just (init dirn)---------------------------------------------------------------------- | Converting the 'Ghc' monad to the 'IO' monad.-withGHC :: FilePath  -- ^ A target file displayed in an error message.-        -> Ghc a -- ^ 'Ghc' actions created by the Ghc utilities.-        -> IO a-withGHC file body = ghandle ignore $ withGHC' body-  where-    ignore :: SomeException -> IO a-    ignore e = do-        hPutStr stderr $ file ++ ":0:0:Error:"-        hPrint stderr e-        exitSuccess--withGHC' :: Ghc a -> IO a-withGHC' body = do-    mlibdir <- getSystemLibDir-    G.runGhc mlibdir body--withGhcT :: (Exception.ExceptionMonad m, G.MonadIO m, Monad m) => GhcT m a -> m a-withGhcT body = do-  mlibdir <- G.liftIO $ getSystemLibDir-  G.runGhcT mlibdir body--------------------------------------------------------------------data Build = CabalPkg | SingleFile deriving Eq--initializeFlagsWithCradle ::-        (GhcMonad m)-        => FilePath -- The file we are loading it because of-        -> Cradle-        -> m ()-initializeFlagsWithCradle = initializeFlagsWithCradleWithMessage (Just G.batchMsg)---- | Initialize the 'DynFlags' relating to the compilation of a single--- file or GHC session according to the 'Cradle' and 'Options'--- provided.-initializeFlagsWithCradleWithMessage ::-        (GhcMonad m)-        => Maybe G.Messager-        -> FilePath -- The file we are loading it because of-        -> Cradle-        -> m ()-initializeFlagsWithCradleWithMessage msg fp cradle = do-      (ex, err, ghcOpts) <- liftIO $ getOptions (cradleOptsProg cradle) fp-      G.pprTrace "res" (G.text (show (ex, err, ghcOpts, fp))) (return ())-      case ex of-        ExitFailure _ -> throwCradleError err-        _ -> return ()-      let compOpts = CompilerOptions ghcOpts-      liftIO $ hPrint stderr ghcOpts-      initSessionWithMessage msg compOpts--data CradleError = CradleError String deriving (Show)--instance Exception CradleError where--throwCradleError :: GhcMonad m => String -> m ()-throwCradleError = liftIO . throwIO . CradleError-------------------------------------------------------------------cacheDir :: String-cacheDir = "haskell-ide-engine"--clearInterfaceCache :: FilePath -> IO ()-clearInterfaceCache fp = do-  cd <- getCacheDir fp-  res <- doesPathExist cd-  when res (removeDirectoryRecursive cd)--getCacheDir :: FilePath -> IO FilePath-getCacheDir fp = getXdgDirectory XdgCache (cacheDir ++ "/" ++ fp)--initSessionWithMessage :: (GhcMonad m)-            => Maybe G.Messager-            -> CompilerOptions-            -> m ()-initSessionWithMessage msg CompilerOptions {..} = do-    df <- G.getSessionDynFlags-    traceShowM (length ghcOptions)--    let opts_hash = B.unpack $ encode $ H.finalize $ H.updates H.init (map B.pack ghcOptions)-    fp <- liftIO $ getCacheDir opts_hash-    -- For now, clear the cache initially rather than persist it across-    -- sessions-    liftIO $ clearInterfaceCache opts_hash-    (df', targets) <- addCmdOpts ghcOptions df-    void $ G.setSessionDynFlags-      (disableOptimisation-      $ setIgnoreInterfacePragmas-      $ resetPackageDb---      $ ignorePackageEnv-      $ writeInterfaceFiles (Just fp)-      $ setVerbosity 0--      $ setLinkerOptions df'-      )-    G.setLogAction (\_df _wr _s _ss _pp _m -> return ())-#if __GLASGOW_HASKELL__ < 806-        (\_df -> return ())-#endif-    G.setTargets targets-    -- Get the module graph using the function `getModuleGraph`-    mod_graph <- G.depanal [] True-    void $ G.load' LoadAllTargets msg mod_graph---------------------------------------------------------------------- we don't want to generate object code so we compile to bytecode--- (HscInterpreted) which implies LinkInMemory--- HscInterpreted-setLinkerOptions :: DynFlags -> DynFlags-setLinkerOptions df = df {-    ghcLink   = LinkInMemory-  , hscTarget = HscNothing-  , ghcMode = CompManager-  }--resetPackageDb :: DynFlags -> DynFlags-resetPackageDb df = df { pkgDatabase = Nothing }----ignorePackageEnv :: DynFlags -> DynFlags---ignorePackageEnv df = df { packageEnv = Just "-" }--setIgnoreInterfacePragmas :: DynFlags -> DynFlags-setIgnoreInterfacePragmas df = gopt_set df Opt_IgnoreInterfacePragmas--setVerbosity :: Int -> DynFlags -> DynFlags-setVerbosity n df = df { verbosity = n }--writeInterfaceFiles :: Maybe FilePath -> DynFlags -> DynFlags-writeInterfaceFiles Nothing df = df-writeInterfaceFiles (Just hi_dir) df = setHiDir hi_dir (gopt_set df Opt_WriteInterface)--setHiDir :: FilePath -> DynFlags -> DynFlags-setHiDir f d = d { hiDir      = Just f}---addCmdOpts :: (GhcMonad m)-           => [String] -> DynFlags -> m (DynFlags, [G.Target])-addCmdOpts cmdOpts df1 = do-  (df2, leftovers, warns) <- G.parseDynamicFlags df1 (map G.noLoc cmdOpts)-  traceShowM (map G.unLoc leftovers, length warns)--  let-     -- To simplify the handling of filepaths, we normalise all filepaths right-     -- away. Note the asymmetry of FilePath.normalise:-     --    Linux:   p/q -> p/q; p\q -> p\q-     --    Windows: p/q -> p\q; p\q -> p\q-     -- #12674: Filenames starting with a hypen get normalised from ./-foo.hs-     -- to -foo.hs. We have to re-prepend the current directory.-    normalise_hyp fp-        | strt_dot_sl && "-" `isPrefixOf` nfp = cur_dir ++ nfp-        | otherwise                           = nfp-        where-#if defined(mingw32_HOST_OS)-          strt_dot_sl = "./" `isPrefixOf` fp || ".\\" `isPrefixOf` fp-#else-          strt_dot_sl = "./" `isPrefixOf` fp-#endif-          cur_dir = '.' : [pathSeparator]-          nfp = normalise fp-    normal_fileish_paths = map (normalise_hyp . G.unLoc) leftovers-  let-   (srcs, objs) = partition_args normal_fileish_paths [] []-   df3 = df2 { ldInputs = map (FileOption "") objs ++ ldInputs df2 }-  ts <- mapM (uncurry G.guessTarget) srcs-  return (df3, ts)-    -- TODO: Need to handle these as well-    -- Ideally it requires refactoring to work in GHCi monad rather than-    -- Ghc monad and then can just use newDynFlags.-    {--    liftIO $ G.handleFlagWarnings idflags1 warns-    when (not $ null leftovers)-        (throwGhcException . CmdLineError-         $ "Some flags have not been recognized: "-         ++ (concat . intersperse ", " $ map unLoc leftovers))-    when (interactive_only && packageFlagsChanged idflags1 idflags0) $ do-       liftIO $ hPutStrLn stderr "cannot set package flags with :seti; use :set"-    -}----------------------------------------------------------------------------------------------------------------------------------------- | Return the 'DynFlags' currently in use in the GHC session.-getDynamicFlags :: IO DynFlags-getDynamicFlags = do-    mlibdir <- getSystemLibDir-    G.runGhc mlibdir G.getSessionDynFlags--withDynFlags ::-  (GhcMonad m)-  => (DynFlags -> DynFlags) -> m a -> m a-withDynFlags setFlag body = G.gbracket setup teardown (\_ -> body)-  where-    setup = do-        dflag <- G.getSessionDynFlags-        void $ G.setSessionDynFlags (setFlag dflag)-        return dflag-    teardown = void . G.setSessionDynFlags--withCmdFlags ::-  (GhcMonad m)-  => [String] -> m a ->  m a-withCmdFlags flags body = G.gbracket setup teardown (\_ -> body)-  where-    setup = do-        (dflag, _) <- G.getSessionDynFlags >>= addCmdOpts flags-        void $ G.setSessionDynFlags dflag-        return dflag-    teardown = void . G.setSessionDynFlags---- partition_args, along with some of the other code in this file,--- was copied from ghc/Main.hs--- -------------------------------------------------------------------------------- Splitting arguments into source files and object files.  This is where we--- interpret the -x <suffix> option, and attach a (Maybe Phase) to each source--- file indicating the phase specified by the -x option in force, if any.-partition_args :: [String] -> [(String, Maybe G.Phase)] -> [String]-               -> ([(String, Maybe G.Phase)], [String])-partition_args [] srcs objs = (reverse srcs, reverse objs)-partition_args ("-x":suff:args) srcs objs-  | "none" <- suff      = partition_args args srcs objs-  | G.StopLn <- phase     = partition_args args srcs (slurp ++ objs)-  | otherwise           = partition_args rest (these_srcs ++ srcs) objs-        where phase = G.startPhase suff-              (slurp,rest) = break (== "-x") args-              these_srcs = zip slurp (repeat (Just phase))-partition_args (arg:args) srcs objs-  | looks_like_an_input arg = partition_args args ((arg,Nothing):srcs) objs-  | otherwise               = partition_args args srcs (arg:objs)--    {--      We split out the object files (.o, .dll) and add them-      to ldInputs for use by the linker.-      The following things should be considered compilation manager inputs:-       - haskell source files (strings ending in .hs, .lhs or other-         haskellish extension),-       - module names (not forgetting hierarchical module names),-       - things beginning with '-' are flags that were not recognised by-         the flag parser, and we want them to generate errors later in-         checkOptions, so we class them as source files (#5921)-       - and finally we consider everything without an extension to be-         a comp manager input, as shorthand for a .hs or .lhs filename.-      Everything else is considered to be a linker object, and passed-      straight through to the linker.-    -}-looks_like_an_input :: String -> Bool-looks_like_an_input m =  G.isSourceFilename m-                      || G.looksLikeModuleName m-                      || "-" `isPrefixOf` m-                      || not (hasExtension m)---------------------------------------------------------------------setDeferTypeErrors :: DynFlags -> DynFlags-setDeferTypeErrors-  = foldDFlags (flip wopt_set) [Opt_WarnTypedHoles, Opt_WarnDeferredTypeErrors, Opt_WarnDeferredOutOfScopeVariables]-  . foldDFlags setGeneralFlag' [Opt_DeferTypedHoles, Opt_DeferTypeErrors, Opt_DeferOutOfScopeVariables]--foldDFlags :: (a -> DynFlags -> DynFlags) -> [a] -> DynFlags -> DynFlags-foldDFlags f xs x = foldr f x xs---- | Set 'DynFlags' equivalent to "-w:".-setNoWarningFlags :: DynFlags -> DynFlags-setNoWarningFlags df = df { warningFlags = Gap.emptyWarnFlags}---- | Set 'DynFlags' equivalent to "-Wall".-setAllWarningFlags :: DynFlags -> DynFlags-setAllWarningFlags df = df { warningFlags = allWarningFlags }--disableOptimisation :: DynFlags -> DynFlags-disableOptimisation df = updOptLevel 0 df--{-# NOINLINE allWarningFlags #-}-allWarningFlags :: Gap.WarnFlags-allWarningFlags = unsafePerformIO $ do-    mlibdir <- getSystemLibDir-    G.runGhcT mlibdir $ do-        df <- G.getSessionDynFlags-        (df', _) <- addCmdOpts ["-Wall"] df-        return $ G.warningFlags df'
− src/HIE/Bios/Gap.hs
@@ -1,129 +0,0 @@-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, CPP #-}--module HIE.Bios.Gap (-    WarnFlags-  , emptyWarnFlags-  , makeUserStyle-  , getModuleName-  , getTyThing-  , fixInfo-  , getModSummaries-  , LExpression-  , LBinding-  , LPattern-  , inTypes-  , outType-  ) where--import DynFlags (DynFlags)-import GHC(LHsBind, LHsExpr, LPat, Type)-import HsExpr (MatchGroup)-import Outputable (PrintUnqualified, PprStyle, Depth(AllTheWay), mkUserStyle)-------------------------------------------------------------------------------------------------------------------------------------#if __GLASGOW_HASKELL__ >= 802-#else-import GHC.PackageDb (ExposedModule(..))-#endif--#if __GLASGOW_HASKELL__ >= 804-import DynFlags (WarningFlag)-import qualified EnumSet as E (EnumSet, empty)-import GHC (mgModSummaries, ModSummary, ModuleGraph)-#else-import qualified Data.IntSet as I (IntSet, empty)-#endif--#if __GLASGOW_HASKELL__ >= 806-import HsExpr (MatchGroupTc(..))-import HsExtension (GhcTc)-import GHC (mg_ext)-#elif __GLASGOW_HASKELL__ >= 804-import HsExtension (GhcTc)-import GHC (mg_res_ty, mg_arg_tys)-#else-import GHC (Id, mg_res_ty, mg_arg_tys)-#endif-------------------------------------------------------------------------------------------------------------------------------------makeUserStyle :: DynFlags -> PrintUnqualified -> PprStyle-#if __GLASGOW_HASKELL__ >= 802-makeUserStyle dflags style = mkUserStyle dflags style AllTheWay-#else-makeUserStyle _      style = mkUserStyle        style AllTheWay-#endif--#if __GLASGOW_HASKELL__ >= 802-getModuleName :: (a, b) -> a-getModuleName = fst-#else-getModuleName :: ExposedModule unitid modulename -> modulename-getModuleName = exposedName-#endif--------------------------------------------------------------------#if __GLASGOW_HASKELL__ >= 804-type WarnFlags = E.EnumSet WarningFlag-emptyWarnFlags :: WarnFlags-emptyWarnFlags = E.empty-#else-type WarnFlags = I.IntSet-emptyWarnFlags :: WarnFlags-emptyWarnFlags = I.empty-#endif--#if __GLASGOW_HASKELL__ >= 804-getModSummaries :: ModuleGraph -> [ModSummary]-getModSummaries = mgModSummaries--getTyThing :: (a, b, c, d, e) -> a-getTyThing (t,_,_,_,_) = t--fixInfo :: (a, b, c, d, e) -> (a, b, c, d)-fixInfo (t,f,cs,fs,_) = (t,f,cs,fs)-#else-getModSummaries :: a -> a-getModSummaries = id--getTyThing :: (a, b, c, d) -> a-getTyThing (t,_,_,_) = t--fixInfo :: (a, b, c, d) -> (a, b, c, d)-fixInfo = id-#endif--------------------------------------------------------------------#if __GLASGOW_HASKELL__ >= 806-type LExpression = LHsExpr GhcTc-type LBinding    = LHsBind GhcTc-type LPattern    = LPat    GhcTc--inTypes :: MatchGroup GhcTc LExpression -> [Type]-inTypes = mg_arg_tys . mg_ext-outType :: MatchGroup GhcTc LExpression -> Type-outType = mg_res_ty . mg_ext-#elif __GLASGOW_HASKELL__ >= 804-type LExpression = LHsExpr GhcTc-type LBinding    = LHsBind GhcTc-type LPattern    = LPat    GhcTc--inTypes :: MatchGroup GhcTc LExpression -> [Type]-inTypes = mg_arg_tys-outType :: MatchGroup GhcTc LExpression -> Type-outType = mg_res_ty-#else-type LExpression = LHsExpr Id-type LBinding    = LHsBind Id-type LPattern    = LPat    Id--inTypes :: MatchGroup Id LExpression -> [Type]-inTypes = mg_arg_tys-outType :: MatchGroup Id LExpression -> Type-outType = mg_res_ty-#endif
+ src/HIE/Bios/Ghc/Api.hs view
@@ -0,0 +1,148 @@+{-# LANGUAGE ScopedTypeVariables, RecordWildCards, CPP #-}++module HIE.Bios.Ghc.Api (+    withGHC+  , withGHC'+  , withGhcT+  , initializeFlagsWithCradle+  , initializeFlagsWithCradleWithMessage+  , getDynamicFlags+  , getSystemLibDir+  , withDynFlags+  , withCmdFlags+  , setNoWarningFlags+  , setAllWarningFlags+  , setDeferTypeErrors+  ) where++import CoreMonad (liftIO)+import Exception (ghandle, SomeException(..), ExceptionMonad(..), throwIO)+import GHC (Ghc, LoadHowMuch(..), GhcMonad, GhcT)+import DynFlags++import qualified GHC as G+import qualified MonadUtils as G+import qualified HscMain as G+import qualified GhcMake as G++import Control.Monad (void)+import System.Exit (exitSuccess)+import System.IO (hPutStr, hPrint, stderr)+import System.IO.Unsafe (unsafePerformIO)++import qualified HIE.Bios.Ghc.Gap as Gap+import HIE.Bios.Types+import HIE.Bios.Environment+import HIE.Bios.Flags++++----------------------------------------------------------------++-- | Converting the 'Ghc' monad to the 'IO' monad.+withGHC :: FilePath  -- ^ A target file displayed in an error message.+        -> Ghc a -- ^ 'Ghc' actions created by the Ghc utilities.+        -> IO a+withGHC file body = ghandle ignore $ withGHC' body+  where+    ignore :: SomeException -> IO a+    ignore e = do+        hPutStr stderr $ file ++ ":0:0:Error:"+        hPrint stderr e+        exitSuccess++withGHC' :: Ghc a -> IO a+withGHC' body = do+    mlibdir <- getSystemLibDir+    G.runGhc mlibdir body++withGhcT :: (Exception.ExceptionMonad m, G.MonadIO m, Monad m) => GhcT m a -> m a+withGhcT body = do+  mlibdir <- G.liftIO $ getSystemLibDir+  G.runGhcT mlibdir body++----------------------------------------------------------------++++initializeFlagsWithCradle ::+    GhcMonad m+    => FilePath -- The file we are loading it because of+    -> Cradle+    -> m ()+initializeFlagsWithCradle = initializeFlagsWithCradleWithMessage (Just G.batchMsg)++initializeFlagsWithCradleWithMessage ::+  GhcMonad m+  => Maybe G.Messager+  -> FilePath -- The file we are loading it because of+  -> Cradle+  -> m ()+initializeFlagsWithCradleWithMessage msg fp cradle = do+    compOpts <- liftIO $ getCompilerOptions fp cradle+    case compOpts of+      Left err -> liftIO $ throwIO err+      Right opts -> initSessionWithMessage msg opts++initSessionWithMessage :: (GhcMonad m)+            => Maybe G.Messager+            -> CompilerOptions+            -> m ()+initSessionWithMessage msg compOpts = do+    targets <- initSession compOpts+    G.setTargets targets+    -- Get the module graph using the function `getModuleGraph`+    mod_graph <- G.depanal [] True+    void $ G.load' LoadAllTargets msg mod_graph++----------------------------------------------------------------++withDynFlags ::+  (GhcMonad m)+  => (DynFlags -> DynFlags) -> m a -> m a+withDynFlags setFlag body = G.gbracket setup teardown (\_ -> body)+  where+    setup = do+        dflag <- G.getSessionDynFlags+        void $ G.setSessionDynFlags (setFlag dflag)+        return dflag+    teardown = void . G.setSessionDynFlags++withCmdFlags ::+  (GhcMonad m)+  => [String] -> m a ->  m a+withCmdFlags flags body = G.gbracket setup teardown (\_ -> body)+  where+    setup = do+        (dflag, _) <- G.getSessionDynFlags >>= addCmdOpts flags+        void $ G.setSessionDynFlags dflag+        return dflag+    teardown = void . G.setSessionDynFlags++----------------------------------------------------------------++setDeferTypeErrors :: DynFlags -> DynFlags+setDeferTypeErrors+    = foldDFlags (flip wopt_set) [Opt_WarnTypedHoles, Opt_WarnDeferredTypeErrors, Opt_WarnDeferredOutOfScopeVariables]+    . foldDFlags setGeneralFlag' [Opt_DeferTypedHoles, Opt_DeferTypeErrors, Opt_DeferOutOfScopeVariables]++foldDFlags :: (a -> DynFlags -> DynFlags) -> [a] -> DynFlags -> DynFlags+foldDFlags f xs x = foldr f x xs++-- | Set 'DynFlags' equivalent to "-w:".+setNoWarningFlags :: DynFlags -> DynFlags+setNoWarningFlags df = df { warningFlags = Gap.emptyWarnFlags}++-- | Set 'DynFlags' equivalent to "-Wall".+setAllWarningFlags :: DynFlags -> DynFlags+setAllWarningFlags df = df { warningFlags = allWarningFlags }+++{-# NOINLINE allWarningFlags #-}+allWarningFlags :: Gap.WarnFlags+allWarningFlags = unsafePerformIO $ do+    mlibdir <- getSystemLibDir+    G.runGhcT mlibdir $ do+        df <- G.getSessionDynFlags+        (df', _) <- addCmdOpts ["-Wall"] df+        return $ G.warningFlags df'
+ src/HIE/Bios/Ghc/Check.hs view
@@ -0,0 +1,75 @@+module HIE.Bios.Ghc.Check (+    checkSyntax+  , check+  , expandTemplate+  , expand+  ) where++import DynFlags (dopt_set, DumpFlag(Opt_D_dump_splices))+import GHC (Ghc, DynFlags(..), GhcMonad)++import HIE.Bios.Ghc.Api+import HIE.Bios.Ghc.Logger+import HIE.Bios.Types+import HIE.Bios.Ghc.Load+import Outputable++----------------------------------------------------------------++-- | Checking syntax of a target file using GHC.+--   Warnings and errors are returned.+checkSyntax :: Options+            -> Cradle+            -> [FilePath]  -- ^ The target files.+            -> IO String+checkSyntax _   _      []    = return ""+checkSyntax opt cradle files = withGhcT $ do+    pprTrace "cradle" (text $ show cradle) (return ())+    initializeFlagsWithCradle (head files) cradle+    either id id <$> check opt files+  where+    {-+    sessionName = case files of+      [file] -> file+      _      -> "MultipleFiles"+      -}++----------------------------------------------------------------++-- | Checking syntax of a target file using GHC.+--   Warnings and errors are returned.+check :: (GhcMonad m)+      => Options+      -> [FilePath]  -- ^ The target files.+      -> m (Either String String)+check opt fileNames = withLogger opt setAllWarningFlags $ setTargetFiles (map dup fileNames)++dup :: a -> (a, a)+dup x = (x, x)++----------------------------------------------------------------++-- | Expanding Haskell Template.+expandTemplate :: Options+               -> Cradle+               -> [FilePath]  -- ^ The target files.+               -> IO String+expandTemplate _   _      []    = return ""+expandTemplate opt cradle files = withGHC sessionName $ do+    initializeFlagsWithCradle (head files) cradle+    either id id <$> expand opt files+  where+    sessionName = case files of+      [file] -> file+      _      -> "MultipleFiles"++----------------------------------------------------------------++-- | Expanding Haskell Template.+expand :: Options+      -> [FilePath]  -- ^ The target files.+      -> Ghc (Either String String)+expand opt fileNames = withLogger opt (setDumpSplices . setNoWarningFlags) $ setTargetFiles (map dup fileNames)++setDumpSplices :: DynFlags -> DynFlags+setDumpSplices dflag = dopt_set dflag Opt_D_dump_splices
+ src/HIE/Bios/Ghc/Doc.hs view
@@ -0,0 +1,24 @@+module HIE.Bios.Ghc.Doc where++import GHC (DynFlags, getPrintUnqual, pprCols, GhcMonad)+import Outputable (PprStyle, SDoc, withPprStyleDoc, neverQualify)+import Pretty (Mode(..), Doc, Style(..), renderStyle, style)++import HIE.Bios.Ghc.Gap (makeUserStyle)++showPage :: DynFlags -> PprStyle -> SDoc -> String+showPage dflag stl = showDocWith dflag PageMode . withPprStyleDoc dflag stl++showOneLine :: DynFlags -> PprStyle -> SDoc -> String+showOneLine dflag stl = showDocWith dflag OneLineMode . withPprStyleDoc dflag stl++getStyle :: (GhcMonad m) => DynFlags -> m PprStyle+getStyle dflags = makeUserStyle dflags <$> getPrintUnqual++styleUnqualified :: DynFlags -> PprStyle+styleUnqualified dflags = makeUserStyle dflags neverQualify++showDocWith :: DynFlags -> Mode -> Doc -> String+showDocWith dflags md = renderStyle mstyle+  where+    mstyle = style { mode = md, lineLength = pprCols dflags }
+ src/HIE/Bios/Ghc/Gap.hs view
@@ -0,0 +1,143 @@+{-# LANGUAGE FlexibleInstances, CPP #-}++module HIE.Bios.Ghc.Gap (+    WarnFlags+  , emptyWarnFlags+  , makeUserStyle+  , getModuleName+  , getTyThing+  , fixInfo+  , getModSummaries+  , LExpression+  , LBinding+  , LPattern+  , inTypes+  , outType+  , mapMG+  , mgModSummaries+  ) where++import DynFlags (DynFlags)+import GHC(LHsBind, LHsExpr, LPat, Type, ModSummary, ModuleGraph)+import HsExpr (MatchGroup)+import Outputable (PrintUnqualified, PprStyle, Depth(AllTheWay), mkUserStyle)++----------------------------------------------------------------+----------------------------------------------------------------++#if __GLASGOW_HASKELL__ >= 802+#else+import GHC.PackageDb (ExposedModule(..))+#endif++#if __GLASGOW_HASKELL__ >= 804+import DynFlags (WarningFlag)+import qualified EnumSet as E (EnumSet, empty)+import GHC (mgModSummaries, mapMG)+#else+import qualified Data.IntSet as I (IntSet, empty)+#endif++#if __GLASGOW_HASKELL__ >= 806+import HsExpr (MatchGroupTc(..))+import HsExtension (GhcTc)+import GHC (mg_ext)+#elif __GLASGOW_HASKELL__ >= 804+import HsExtension (GhcTc)+import GHC (mg_res_ty, mg_arg_tys)+#else+import GHC (Id, mg_res_ty, mg_arg_tys)+#endif++----------------------------------------------------------------+----------------------------------------------------------------++makeUserStyle :: DynFlags -> PrintUnqualified -> PprStyle+#if __GLASGOW_HASKELL__ >= 802+makeUserStyle dflags style = mkUserStyle dflags style AllTheWay+#else+makeUserStyle _      style = mkUserStyle        style AllTheWay+#endif++#if __GLASGOW_HASKELL__ >= 802+getModuleName :: (a, b) -> a+getModuleName = fst+#else+getModuleName :: ExposedModule unitid modulename -> modulename+getModuleName = exposedName+#endif++----------------------------------------------------------------++#if __GLASGOW_HASKELL__ >= 804+type WarnFlags = E.EnumSet WarningFlag+emptyWarnFlags :: WarnFlags+emptyWarnFlags = E.empty+#else+type WarnFlags = I.IntSet+emptyWarnFlags :: WarnFlags+emptyWarnFlags = I.empty+#endif++#if __GLASGOW_HASKELL__ >= 804+getModSummaries :: ModuleGraph -> [ModSummary]+getModSummaries = mgModSummaries++getTyThing :: (a, b, c, d, e) -> a+getTyThing (t,_,_,_,_) = t++fixInfo :: (a, b, c, d, e) -> (a, b, c, d)+fixInfo (t,f,cs,fs,_) = (t,f,cs,fs)+#else+getModSummaries :: a -> a+getModSummaries = id++getTyThing :: (a, b, c, d) -> a+getTyThing (t,_,_,_) = t++fixInfo :: (a, b, c, d) -> (a, b, c, d)+fixInfo = id+#endif++----------------------------------------------------------------++#if __GLASGOW_HASKELL__ >= 806+type LExpression = LHsExpr GhcTc+type LBinding    = LHsBind GhcTc+type LPattern    = LPat    GhcTc++inTypes :: MatchGroup GhcTc LExpression -> [Type]+inTypes = mg_arg_tys . mg_ext+outType :: MatchGroup GhcTc LExpression -> Type+outType = mg_res_ty . mg_ext+#elif __GLASGOW_HASKELL__ >= 804+type LExpression = LHsExpr GhcTc+type LBinding    = LHsBind GhcTc+type LPattern    = LPat    GhcTc++inTypes :: MatchGroup GhcTc LExpression -> [Type]+inTypes = mg_arg_tys+outType :: MatchGroup GhcTc LExpression -> Type+outType = mg_res_ty+#else+type LExpression = LHsExpr Id+type LBinding    = LHsBind Id+type LPattern    = LPat    Id++inTypes :: MatchGroup Id LExpression -> [Type]+inTypes = mg_arg_tys+outType :: MatchGroup Id LExpression -> Type+outType = mg_res_ty+#endif++#if __GLASGOW_HASKELL__ >= 804+#else+mapMG :: (ModSummary -> ModSummary) -> ModuleGraph -> ModuleGraph+mapMG = map+#endif++#if __GLASGOW_HASKELL__ >= 804+#else+mgModSummaries :: ModuleGraph -> [ModSummary]+mgModSummaries = id+#endif
+ src/HIE/Bios/Ghc/Load.hs view
@@ -0,0 +1,135 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE CPP #-}+module HIE.Bios.Ghc.Load ( loadFileWithMessage, loadFile, setTargetFiles, setTargetFilesWithMessage) where++import CoreMonad (liftIO)+import GHC+import qualified GHC as G+import qualified GhcMake as G+import qualified HscMain as G+import HscTypes+import Outputable+import Control.Monad.IO.Class++import Data.IORef++import System.Directory+import Hooks+import TcRnTypes (FrontendResult(..))+import Control.Monad (forM, void)+import GhcMonad+import HscMain+import Debug.Trace+import Data.List++import Data.Time.Clock+import qualified HIE.Bios.Ghc.Gap as Gap++#if __GLASGOW_HASKELL__ < 806+pprTraceM :: Monad m => String -> SDoc -> m ()+pprTraceM x s = pprTrace x s (return ())+#endif++-- | Obtaining type of a target expression. (GHCi's type:)+loadFileWithMessage :: GhcMonad m+         => Maybe G.Messager+         -> (FilePath, FilePath)     -- ^ A target file.+         -> m (Maybe TypecheckedModule, [TypecheckedModule])+loadFileWithMessage msg file = do+  dir <- liftIO $ getCurrentDirectory+  pprTraceM "loadFile:2" (text dir)+  df <- getSessionDynFlags+  pprTraceM "loadFile:3" (ppr $ optLevel df)+  (_, tcs) <- collectASTs $ do+    (setTargetFilesWithMessage msg [file])+  pprTraceM "loaded" (text (fst file) $$ text (snd file))+  let get_fp = ml_hs_file . ms_location . pm_mod_summary . tm_parsed_module+  traceShowM ("tms", (map get_fp tcs))+  let findMod [] = Nothing+      findMod (x:xs) = case get_fp x of+                         Just fp -> if fp `isSuffixOf` (snd file) then Just x else findMod xs+                         Nothing -> findMod xs+  return (findMod tcs, tcs)++loadFile :: (GhcMonad m)+         => (FilePath, FilePath)+         -> m (Maybe TypecheckedModule, [TypecheckedModule])+loadFile = loadFileWithMessage (Just G.batchMsg)++{-+fileModSummary :: GhcMonad m => FilePath -> m ModSummary+fileModSummary file = do+    mss <- getModSummaries <$> G.getModuleGraph+    let [ms] = filter (\m -> G.ml_hs_file (G.ms_location m) == Just file) mss+    return ms+    -}+++setTargetFiles :: GhcMonad m => [(FilePath, FilePath)] -> m ()+setTargetFiles = setTargetFilesWithMessage (Just G.batchMsg)++msTargetIs :: ModSummary -> Target -> Bool+msTargetIs ms t = case targetId t of+  TargetModule m -> moduleName (ms_mod ms) == m+  TargetFile f _ -> ml_hs_file (ms_location ms) == Just f++-- | We bump the times for any ModSummary's that are Targets, to+-- fool the recompilation checker so that we can get the typechecked modules+updateTime :: MonadIO m => [Target] -> ModuleGraph -> m ModuleGraph+updateTime ts graph = liftIO $ do+  cur_time <- getCurrentTime+  let go ms+        | any (msTargetIs ms) ts = ms {ms_hs_date = cur_time}+        | otherwise = ms+  pure $ Gap.mapMG go graph++-- | Set the files as targets and load them.+setTargetFilesWithMessage :: (GhcMonad m)  => Maybe G.Messager -> [(FilePath, FilePath)] -> m ()+setTargetFilesWithMessage msg files = do+    targets <- forM files guessTargetMapped+    pprTrace "setTargets" (vcat (map (\(a,b) -> parens $ text a <+> text "," <+> text b) files) $$ ppr targets) (return ())+    G.setTargets (map (\t -> t { G.targetAllowObjCode = False }) targets)+    mod_graph <- updateTime targets =<< depanal [] False+    pprTrace "modGraph" (ppr $ Gap.mgModSummaries mod_graph) (return ())+    pprTrace "modGraph" (ppr $ map ms_location $ Gap.mgModSummaries mod_graph) (return ())+    dflags1 <- getSessionDynFlags+    pprTrace "hidir" (ppr $ hiDir dflags1) (return ())+    void $ G.load' LoadAllTargets msg mod_graph++collectASTs :: (GhcMonad m) => m a -> m (a, [TypecheckedModule])+collectASTs action = do+  dflags0 <- getSessionDynFlags+  ref1 <- liftIO $ newIORef []+  let dflags1 = dflags0 { hooks = (hooks dflags0)+                          { hscFrontendHook = traceShow "Use hook" $ Just (astHook ref1) }+                        }+  void $ setSessionDynFlags $ dflags1 -- gopt_set dflags1 Opt_ForceRecomp+  res <- action+  tcs <- liftIO $ readIORef ref1+  return (res, tcs)++astHook :: IORef [TypecheckedModule] -> ModSummary -> Hsc FrontendResult+astHook tc_ref ms = ghcInHsc $ do+  p <- G.parseModule ms+  tcm <- G.typecheckModule p+  let tcg_env = fst (tm_internals_ tcm)+  liftIO $ modifyIORef tc_ref (tcm :)+  return $ FrontendTypecheck tcg_env++ghcInHsc :: Ghc a -> Hsc a+ghcInHsc gm = do+  hsc_session <- getHscEnv+  session <- liftIO $ newIORef hsc_session+  liftIO $ reflectGhc gm (Session session)+++guessTargetMapped :: (GhcMonad m) => (FilePath, FilePath) -> m Target+guessTargetMapped (orig_file_name, mapped_file_name) = do+  t <- G.guessTarget orig_file_name Nothing+  return (setTargetFilename mapped_file_name t)++setTargetFilename :: FilePath -> Target -> Target+setTargetFilename fn t =+  t { targetId = case targetId t of+                  TargetFile _ p -> TargetFile fn p+                  tid -> tid }
+ src/HIE/Bios/Ghc/Logger.hs view
@@ -0,0 +1,124 @@+{-# LANGUAGE BangPatterns #-}++module HIE.Bios.Ghc.Logger (+    withLogger+  , checkErrorPrefix+  , getSrcSpan+  ) where++import Bag (Bag, bagToList)+import CoreMonad (liftIO)+import DynFlags (LogAction, dopt, DumpFlag(Opt_D_dump_splices))+import ErrUtils+import Exception (ghandle)+import FastString (unpackFS)+import GHC (DynFlags(..), SrcSpan(..), Severity(SevError), GhcMonad)+import qualified GHC as G+import HscTypes (SourceError, srcErrorMessages)+import Outputable (PprStyle, SDoc)++import Data.IORef (IORef, newIORef, readIORef, writeIORef, modifyIORef)+import Data.List (isPrefixOf)+import Data.Maybe (fromMaybe)+import System.FilePath (normalise)++import HIE.Bios.Ghc.Doc (showPage, getStyle)+import HIE.Bios.Ghc.Api (withDynFlags, withCmdFlags)+import HIE.Bios.Types (Options(..), convert)++----------------------------------------------------------------++type Builder = [String] -> [String]++newtype LogRef = LogRef (IORef Builder)++newLogRef :: IO LogRef+newLogRef = LogRef <$> newIORef id++readAndClearLogRef :: Options -> LogRef -> IO String+readAndClearLogRef opt (LogRef ref) = do+    b <- readIORef ref+    writeIORef ref id+    return $! convert opt (b [])++appendLogRef :: DynFlags -> LogRef -> LogAction+appendLogRef df (LogRef ref) _ _ sev src style msg = do+        let !l = ppMsg src sev df style msg+        modifyIORef ref (\b -> b . (l:))++----------------------------------------------------------------++-- | Set the session flag (e.g. "-Wall" or "-w:") then+--   executes a body. Log messages are returned as 'String'.+--   Right is success and Left is failure.+withLogger ::+  (GhcMonad m)+  => Options -> (DynFlags -> DynFlags) -> m () -> m (Either String String)+withLogger opt setDF body = ghandle (sourceError opt) $ do+    logref <- liftIO newLogRef+    withDynFlags (setLogger logref . setDF) $ do+        withCmdFlags wflags $ do+            body+            liftIO $ Right <$> readAndClearLogRef opt logref+  where+    setLogger logref df = df { log_action =  appendLogRef df logref }+    wflags = filter ("-fno-warn" `isPrefixOf`) $ ghcOpts opt++----------------------------------------------------------------++-- | Converting 'SourceError' to 'String'.+sourceError ::+  (GhcMonad m)+  => Options -> SourceError -> m (Either String String)+sourceError opt err = do+    dflag <- G.getSessionDynFlags+    style <- getStyle dflag+    let ret = convert opt . errBagToStrList dflag style . srcErrorMessages $ err+    return (Left ret)++errBagToStrList :: DynFlags -> PprStyle -> Bag ErrMsg -> [String]+errBagToStrList dflag style = map (ppErrMsg dflag style) . reverse . bagToList++----------------------------------------------------------------++ppErrMsg :: DynFlags -> PprStyle -> ErrMsg -> String+ppErrMsg dflag style err = ppMsg spn SevError dflag style msg -- ++ ext+   where+     spn = errMsgSpan err+     msg = pprLocErrMsg err+     -- fixme+--     ext = showPage dflag style (pprLocErrMsg $ errMsgReason err)++ppMsg :: SrcSpan -> Severity-> DynFlags -> PprStyle -> SDoc -> String+ppMsg spn sev dflag style msg = prefix ++ cts+  where+    cts  = showPage dflag style msg+    defaultPrefix+      | isDumpSplices dflag = ""+      | otherwise           = checkErrorPrefix+    prefix = fromMaybe defaultPrefix $ do+        (line,col,_,_) <- getSrcSpan spn+        file <- normalise <$> getSrcFile spn+        let severityCaption = showSeverityCaption sev+        return $ file ++ ":" ++ show line ++ ":" ++ show col ++ ":" ++ severityCaption++checkErrorPrefix :: String+checkErrorPrefix = "Dummy:0:0:Error:"++showSeverityCaption :: Severity -> String+showSeverityCaption SevWarning = "Warning: "+showSeverityCaption _          = ""++getSrcFile :: SrcSpan -> Maybe String+getSrcFile (G.RealSrcSpan spn) = Just . unpackFS . G.srcSpanFile $ spn+getSrcFile _                   = Nothing++isDumpSplices :: DynFlags -> Bool+isDumpSplices dflag = dopt Opt_D_dump_splices dflag++getSrcSpan :: SrcSpan -> Maybe (Int,Int,Int,Int)+getSrcSpan (RealSrcSpan spn) = Just ( G.srcSpanStartLine spn+                                    , G.srcSpanStartCol spn+                                    , G.srcSpanEndLine spn+                                    , G.srcSpanEndCol spn)+getSrcSpan _ = Nothing
+ src/HIE/Bios/Ghc/Things.hs view
@@ -0,0 +1,63 @@+module HIE.Bios.Ghc.Things (+    GapThing(..)+  , fromTyThing+  , infoThing+  ) where++import ConLike (ConLike(..))+import FamInstEnv+import GHC+import HscTypes+import qualified InstEnv+import NameSet+import Outputable+import PatSyn+import PprTyThing+import Var (varType)++import Data.List (intersperse)+import Data.Maybe (catMaybes)++import HIE.Bios.Ghc.Gap (getTyThing, fixInfo)++-- from ghc/InteractiveUI.hs++----------------------------------------------------------------++data GapThing = GtA Type+              | GtT TyCon+              | GtN+              | GtPatSyn PatSyn++fromTyThing :: TyThing -> GapThing+fromTyThing (AnId i)                   = GtA $ varType i+fromTyThing (AConLike (RealDataCon d)) = GtA $ dataConUserType d+fromTyThing (AConLike (PatSynCon p))   = GtPatSyn p+fromTyThing (ATyCon t)                 = GtT t+fromTyThing _                          = GtN++----------------------------------------------------------------++infoThing :: String -> Ghc SDoc+infoThing str = do+    names <- parseName str+    mb_stuffs <- mapM (getInfo False) names+    let filtered = filterOutChildren getTyThing $ catMaybes mb_stuffs+    return $ vcat (intersperse (text "") $ map (pprInfo . fixInfo) filtered)++filterOutChildren :: (a -> TyThing) -> [a] -> [a]+filterOutChildren get_thing xs+    = [x | x <- xs, not (getName (get_thing x) `elemNameSet` implicits)]+  where+    implicits = mkNameSet [getName t | x <- xs, t <- implicitTyThings (get_thing x)]++pprInfo :: (TyThing, GHC.Fixity, [InstEnv.ClsInst], [FamInst]) -> SDoc+pprInfo (thing, fixity, insts, famInsts)+    = pprTyThingInContextLoc thing+   $$ show_fixity fixity+   $$ InstEnv.pprInstances insts+   $$ pprFamInsts famInsts+  where+    show_fixity fx+      | fx == defaultFixity = Outputable.empty+      | otherwise           = ppr fx <+> ppr (getName thing)
− src/HIE/Bios/Load.hs
@@ -1,134 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE CPP #-}-module HIE.Bios.Load ( loadFileWithMessage, loadFile, setTargetFiles, setTargetFilesWithMessage) where--import CoreMonad (liftIO)-import GHC-import qualified GHC as G-import qualified GhcMake as G-import qualified HscMain as G-import HscTypes-import Outputable-import Control.Monad.IO.Class--import Data.IORef--import System.Directory-import Hooks-import TcRnTypes (FrontendResult(..))-import Control.Monad (forM, void)-import GhcMonad-import HscMain-import Debug.Trace-import Data.List--import Data.Time.Clock--#if __GLASGOW_HASKELL__ < 806-pprTraceM :: Monad m => String -> SDoc -> m ()-pprTraceM x s = pprTrace x s (return ())-#endif---- | Obtaining type of a target expression. (GHCi's type:)-loadFileWithMessage :: GhcMonad m-         => Maybe G.Messager-         -> (FilePath, FilePath)     -- ^ A target file.-         -> m (Maybe TypecheckedModule, [TypecheckedModule])-loadFileWithMessage msg file = do-  dir <- liftIO $ getCurrentDirectory-  pprTraceM "loadFile:2" (text dir)-  df <- getSessionDynFlags-  pprTraceM "loadFile:3" (ppr $ optLevel df)-  (_, tcs) <- collectASTs $ do-    (setTargetFilesWithMessage msg [file])-  pprTraceM "loaded" (text (fst file) $$ text (snd file))-  let get_fp = ml_hs_file . ms_location . pm_mod_summary . tm_parsed_module-  traceShowM ("tms", (map get_fp tcs))-  let findMod [] = Nothing-      findMod (x:xs) = case get_fp x of-                         Just fp -> if fp `isSuffixOf` (snd file) then Just x else findMod xs-                         Nothing -> findMod xs-  return (findMod tcs, tcs)--loadFile :: (GhcMonad m)-         => (FilePath, FilePath)-         -> m (Maybe TypecheckedModule, [TypecheckedModule])-loadFile = loadFileWithMessage (Just G.batchMsg)--{--fileModSummary :: GhcMonad m => FilePath -> m ModSummary-fileModSummary file = do-    mss <- getModSummaries <$> G.getModuleGraph-    let [ms] = filter (\m -> G.ml_hs_file (G.ms_location m) == Just file) mss-    return ms-    -}---setTargetFiles :: GhcMonad m => [(FilePath, FilePath)] -> m ()-setTargetFiles = setTargetFilesWithMessage (Just G.batchMsg)--msTargetIs :: ModSummary -> Target -> Bool-msTargetIs ms t = case targetId t of-  TargetModule m -> moduleName (ms_mod ms) == m-  TargetFile f _ -> ml_hs_file (ms_location ms) == Just f---- | We bump the times for any ModSummary's that are Targets, to--- fool the recompilation checker so that we can get the typechecked modules-updateTime :: MonadIO m => [Target] -> ModuleGraph -> m ModuleGraph-updateTime ts graph = liftIO $ do-  cur_time <- getCurrentTime-  let go ms-        | any (msTargetIs ms) ts = ms {ms_hs_date = cur_time}-        | otherwise = ms-  pure $ mapMG go graph---- | Set the files as targets and load them.-setTargetFilesWithMessage :: (GhcMonad m)  => Maybe G.Messager -> [(FilePath, FilePath)] -> m ()-setTargetFilesWithMessage msg files = do-    targets <- forM files guessTargetMapped-    pprTrace "setTargets" (vcat (map (\(a,b) -> parens $ text a <+> text "," <+> text b) files) $$ ppr targets) (return ())-    G.setTargets (map (\t -> t { G.targetAllowObjCode = False }) targets)-    mod_graph <- updateTime targets =<< depanal [] False-    pprTrace "modGraph" (ppr $ mgModSummaries mod_graph) (return ())-    pprTrace "modGraph" (ppr $ map ms_location $ mgModSummaries mod_graph) (return ())-    dflags1 <- getSessionDynFlags-    pprTrace "hidir" (ppr $ hiDir dflags1) (return ())-    void $ G.load' LoadAllTargets msg mod_graph--collectASTs :: (GhcMonad m) => m a -> m (a, [TypecheckedModule])-collectASTs action = do-  dflags0 <- getSessionDynFlags-  ref1 <- liftIO $ newIORef []-  let dflags1 = dflags0 { hooks = (hooks dflags0)-                          { hscFrontendHook = traceShow "Use hook" $ Just (astHook ref1) }-                        }-  void $ setSessionDynFlags $ dflags1 -- gopt_set dflags1 Opt_ForceRecomp-  res <- action-  tcs <- liftIO $ readIORef ref1-  return (res, tcs)--astHook :: IORef [TypecheckedModule] -> ModSummary -> Hsc FrontendResult-astHook tc_ref ms = ghcInHsc $ do-  p <- G.parseModule ms-  tcm <- G.typecheckModule p-  let tcg_env = fst (tm_internals_ tcm)-  liftIO $ modifyIORef tc_ref (tcm :)-  return $ FrontendTypecheck tcg_env--ghcInHsc :: Ghc a -> Hsc a-ghcInHsc gm = do-  hsc_session <- getHscEnv-  session <- liftIO $ newIORef hsc_session-  liftIO $ reflectGhc gm (Session session)---guessTargetMapped :: (GhcMonad m) => (FilePath, FilePath) -> m Target-guessTargetMapped (orig_file_name, mapped_file_name) = do-  t <- G.guessTarget orig_file_name Nothing-  return (setTargetFilename mapped_file_name t)--setTargetFilename :: FilePath -> Target -> Target-setTargetFilename fn t =-  t { targetId = case targetId t of-                  TargetFile _ p -> TargetFile fn p-                  tid -> tid }
− src/HIE/Bios/Logger.hs
@@ -1,124 +0,0 @@-{-# LANGUAGE BangPatterns #-}--module HIE.Bios.Logger (-    withLogger-  , checkErrorPrefix-  , getSrcSpan-  ) where--import Bag (Bag, bagToList)-import CoreMonad (liftIO)-import DynFlags (LogAction, dopt, DumpFlag(Opt_D_dump_splices))-import ErrUtils-import Exception (ghandle)-import FastString (unpackFS)-import GHC (DynFlags(..), SrcSpan(..), Severity(SevError), GhcMonad)-import qualified GHC as G-import HscTypes (SourceError, srcErrorMessages)-import Outputable (PprStyle, SDoc)--import Data.IORef (IORef, newIORef, readIORef, writeIORef, modifyIORef)-import Data.List (isPrefixOf)-import Data.Maybe (fromMaybe)-import System.FilePath (normalise)--import HIE.Bios.Doc (showPage, getStyle)-import HIE.Bios.GHCApi (withDynFlags, withCmdFlags)-import HIE.Bios.Types (Options(..), convert)--------------------------------------------------------------------type Builder = [String] -> [String]--newtype LogRef = LogRef (IORef Builder)--newLogRef :: IO LogRef-newLogRef = LogRef <$> newIORef id--readAndClearLogRef :: Options -> LogRef -> IO String-readAndClearLogRef opt (LogRef ref) = do-    b <- readIORef ref-    writeIORef ref id-    return $! convert opt (b [])--appendLogRef :: DynFlags -> LogRef -> LogAction-appendLogRef df (LogRef ref) _ _ sev src style msg = do-        let !l = ppMsg src sev df style msg-        modifyIORef ref (\b -> b . (l:))---------------------------------------------------------------------- | Set the session flag (e.g. "-Wall" or "-w:") then---   executes a body. Log messages are returned as 'String'.---   Right is success and Left is failure.-withLogger ::-  (GhcMonad m)-  => Options -> (DynFlags -> DynFlags) -> m () -> m (Either String String)-withLogger opt setDF body = ghandle (sourceError opt) $ do-    logref <- liftIO newLogRef-    withDynFlags (setLogger logref . setDF) $ do-        withCmdFlags wflags $ do-            body-            liftIO $ Right <$> readAndClearLogRef opt logref-  where-    setLogger logref df = df { log_action =  appendLogRef df logref }-    wflags = filter ("-fno-warn" `isPrefixOf`) $ ghcOpts opt---------------------------------------------------------------------- | Converting 'SourceError' to 'String'.-sourceError ::-  (GhcMonad m)-  => Options -> SourceError -> m (Either String String)-sourceError opt err = do-    dflag <- G.getSessionDynFlags-    style <- getStyle dflag-    let ret = convert opt . errBagToStrList dflag style . srcErrorMessages $ err-    return (Left ret)--errBagToStrList :: DynFlags -> PprStyle -> Bag ErrMsg -> [String]-errBagToStrList dflag style = map (ppErrMsg dflag style) . reverse . bagToList--------------------------------------------------------------------ppErrMsg :: DynFlags -> PprStyle -> ErrMsg -> String-ppErrMsg dflag style err = ppMsg spn SevError dflag style msg -- ++ ext-   where-     spn = errMsgSpan err-     msg = pprLocErrMsg err-     -- fixme---     ext = showPage dflag style (pprLocErrMsg $ errMsgReason err)--ppMsg :: SrcSpan -> Severity-> DynFlags -> PprStyle -> SDoc -> String-ppMsg spn sev dflag style msg = prefix ++ cts-  where-    cts  = showPage dflag style msg-    defaultPrefix-      | isDumpSplices dflag = ""-      | otherwise           = checkErrorPrefix-    prefix = fromMaybe defaultPrefix $ do-        (line,col,_,_) <- getSrcSpan spn-        file <- normalise <$> getSrcFile spn-        let severityCaption = showSeverityCaption sev-        return $ file ++ ":" ++ show line ++ ":" ++ show col ++ ":" ++ severityCaption--checkErrorPrefix :: String-checkErrorPrefix = "Dummy:0:0:Error:"--showSeverityCaption :: Severity -> String-showSeverityCaption SevWarning = "Warning: "-showSeverityCaption _          = ""--getSrcFile :: SrcSpan -> Maybe String-getSrcFile (G.RealSrcSpan spn) = Just . unpackFS . G.srcSpanFile $ spn-getSrcFile _                   = Nothing--isDumpSplices :: DynFlags -> Bool-isDumpSplices dflag = dopt Opt_D_dump_splices dflag--getSrcSpan :: SrcSpan -> Maybe (Int,Int,Int,Int)-getSrcSpan (RealSrcSpan spn) = Just ( G.srcSpanStartLine spn-                                    , G.srcSpanStartCol spn-                                    , G.srcSpanEndLine spn-                                    , G.srcSpanEndCol spn)-getSrcSpan _ = Nothing
− src/HIE/Bios/Things.hs
@@ -1,63 +0,0 @@-module HIE.Bios.Things (-    GapThing(..)-  , fromTyThing-  , infoThing-  ) where--import ConLike (ConLike(..))-import FamInstEnv-import GHC-import HscTypes-import qualified InstEnv-import NameSet-import Outputable-import PatSyn-import PprTyThing-import Var (varType)--import Data.List (intersperse)-import Data.Maybe (catMaybes)--import HIE.Bios.Gap (getTyThing, fixInfo)---- from ghc/InteractiveUI.hs--------------------------------------------------------------------data GapThing = GtA Type-              | GtT TyCon-              | GtN-              | GtPatSyn PatSyn--fromTyThing :: TyThing -> GapThing-fromTyThing (AnId i)                   = GtA $ varType i-fromTyThing (AConLike (RealDataCon d)) = GtA $ dataConUserType d-fromTyThing (AConLike (PatSynCon p))   = GtPatSyn p-fromTyThing (ATyCon t)                 = GtT t-fromTyThing _                          = GtN--------------------------------------------------------------------infoThing :: String -> Ghc SDoc-infoThing str = do-    names <- parseName str-    mb_stuffs <- mapM (getInfo False) names-    let filtered = filterOutChildren getTyThing $ catMaybes mb_stuffs-    return $ vcat (intersperse (text "") $ map (pprInfo . fixInfo) filtered)--filterOutChildren :: (a -> TyThing) -> [a] -> [a]-filterOutChildren get_thing xs-    = [x | x <- xs, not (getName (get_thing x) `elemNameSet` implicits)]-  where-    implicits = mkNameSet [getName t | x <- xs, t <- implicitTyThings (get_thing x)]--pprInfo :: (TyThing, GHC.Fixity, [InstEnv.ClsInst], [FamInst]) -> SDoc-pprInfo (thing, fixity, insts, famInsts)-    = pprTyThingInContextLoc thing-   $$ show_fixity fixity-   $$ InstEnv.pprInstances insts-   $$ pprFamInsts famInsts-  where-    show_fixity fx-      | fx == defaultFixity = Outputable.empty-      | otherwise           = ppr fx <+> ppr (getName thing)
src/HIE/Bios/Types.hs view
@@ -4,11 +4,6 @@  module HIE.Bios.Types where -import qualified Exception as GE-import GHC (Ghc)--import Control.Exception (IOException)-import Control.Applicative (Alternative(..)) import System.Exit import System.IO @@ -161,18 +156,29 @@  data CradleAction = CradleAction {                       actionName :: String-                      , getOptions ::  (FilePath -> IO (ExitCode, String, [String]))+                      -- ^ Name of the action+                      , getDependencies :: IO [FilePath]+                      -- ^ Dependencies of a cradle that might change the cradle.+                      -- Contains both files specified in hie.yaml as well as+                      -- specified by the build-tool if there is any.+                      -- FilePaths are expected to be relative to the `cradleRootDir`+                      -- to which this CradleAction belongs to.+                      -- Files returned by this action might not actually exist.+                      -- This is useful, because, sometimes, adding specific files+                      -- changes the options that a Cradle may return, thus, needs reload+                      -- as soon as these files are created.+                      , getOptions :: FilePath -> IO (ExitCode, String, [String])+                      -- ^ Options to compile the given file with.+                      -- The result consists of the return code of the operation+                      -- that has been run, the stdout of the process, and a list of+                      -- options that are needed to compile the given file.                       }  instance Show CradleAction where-  show (CradleAction name _) = "CradleAction: " ++ name+  show CradleAction { actionName = name } = "CradleAction: " ++ name ----------------------------------------------------------------  -- | Option information for GHC data CompilerOptions = CompilerOptions {     ghcOptions  :: [String]  -- ^ Command line options   } deriving (Eq, Show)--instance Alternative Ghc where-    x <|> y = x `GE.gcatch` (\(_ :: IOException) -> y)-    empty = undefined
wrappers/cabal view
@@ -1,7 +1,10 @@ #!/usr/bin/env bash if [ "$1" == "--interactive" ]; then   pwd-  echo "$@"+  for arg in "$@"; do+    echo -ne "$arg\x00"+  done+  echo -ne "\n" else   ghc "$@" fi
wrappers/cabal.hs view
@@ -10,9 +10,11 @@   case args of     "--interactive":_ -> do       getCurrentDirectory >>= putStrLn-      -- note this probably breaks if paths have spaces in-      putStrLn $ unwords args+      putStrLn $ delimited args     _ -> do       ph <- spawnProcess "ghc" args       code <- waitForProcess ph       exitWith code++delimited :: [String] -> String+delimited = concatMap (++ "\NUL")