{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
module Development.IDE.Session
(SessionLoadingOptions(..)
,CacheDirs(..)
,loadSession
,loadSessionWithOptions
,setInitialDynFlags
,getHieDbLoc
,runWithDb
,retryOnSqliteBusy
,retryOnException
) where
import Control.Concurrent.Async
import Control.Concurrent.Strict
import Control.Exception.Safe as Safe
import Control.Monad
import Control.Monad.Extra
import Control.Monad.IO.Class
import qualified Crypto.Hash.SHA1 as H
import Data.Aeson
import Data.Bifunctor
import qualified Data.ByteString.Base16 as B16
import qualified Data.ByteString.Char8 as B
import Data.Default
import Data.Either.Extra
import Data.Function
import qualified Data.HashMap.Strict as HM
import Data.Hashable
import Data.IORef
import Data.List
import qualified Data.Map.Strict as Map
import Data.Maybe
import qualified Data.Text as T
import Data.Time.Clock
import Data.Version
import Development.IDE.Core.RuleTypes
import Development.IDE.Core.Shake hiding (withHieDb)
import qualified Development.IDE.GHC.Compat as Compat
import Development.IDE.GHC.Compat.Core hiding (Target,
TargetFile, TargetModule,
Var)
import qualified Development.IDE.GHC.Compat.Core as GHC
import Development.IDE.GHC.Compat.Env hiding (Logger)
import Development.IDE.GHC.Compat.Units (UnitId)
import Development.IDE.GHC.Util
import Development.IDE.Graph (Action)
import Development.IDE.Session.VersionCheck
import Development.IDE.Types.Diagnostics
import Development.IDE.Types.Exports
import Development.IDE.Types.HscEnvEq (HscEnvEq, newHscEnvEq,
newHscEnvEqPreserveImportPaths)
import Development.IDE.Types.Location
import Development.IDE.Types.Logger
import Development.IDE.Types.Options
import GHC.Check
import qualified HIE.Bios as HieBios
import HIE.Bios.Environment hiding (getCacheDir)
import HIE.Bios.Types
import Hie.Implicit.Cradle (loadImplicitHieCradle)
import Language.LSP.Server
import Language.LSP.Types
import System.Directory
import qualified System.Directory.Extra as IO
import System.FilePath
import System.IO
import System.Info
import Control.Applicative (Alternative ((<|>)))
import Data.Void
import Control.Concurrent.STM.Stats (atomically, modifyTVar',
readTVar, writeTVar)
import Control.Concurrent.STM.TQueue
import Data.Foldable (for_)
import qualified Data.HashSet as Set
import Database.SQLite.Simple
import Development.IDE.Core.Tracing (withTrace)
import Development.IDE.Types.Shake (WithHieDb)
import HieDb.Create
import HieDb.Types
import HieDb.Utils
import System.Random (RandomGen)
import qualified System.Random as Random
hiedbDataVersion :: String
hiedbDataVersion :: String
hiedbDataVersion = String
"1"
data CacheDirs = CacheDirs
{ CacheDirs -> Maybe String
hiCacheDir, CacheDirs -> Maybe String
hieCacheDir, CacheDirs -> Maybe String
oCacheDir :: Maybe FilePath}
data SessionLoadingOptions = SessionLoadingOptions
{ SessionLoadingOptions -> String -> IO (Maybe String)
findCradle :: FilePath -> IO (Maybe FilePath)
, SessionLoadingOptions -> Maybe String -> String -> IO (Cradle Void)
loadCradle :: Maybe FilePath -> FilePath -> IO (HieBios.Cradle Void)
, SessionLoadingOptions -> String -> [String] -> IO CacheDirs
getCacheDirs :: String -> [String] -> IO CacheDirs
, SessionLoadingOptions -> Logger -> String -> IO (Maybe LibDir)
getInitialGhcLibDir :: Logger -> FilePath -> IO (Maybe LibDir)
, SessionLoadingOptions -> UnitId
fakeUid :: UnitId
}
instance Default SessionLoadingOptions where
def :: SessionLoadingOptions
def = SessionLoadingOptions :: (String -> IO (Maybe String))
-> (Maybe String -> String -> IO (Cradle Void))
-> (String -> [String] -> IO CacheDirs)
-> (Logger -> String -> IO (Maybe LibDir))
-> UnitId
-> SessionLoadingOptions
SessionLoadingOptions
{findCradle :: String -> IO (Maybe String)
findCradle = String -> IO (Maybe String)
HieBios.findCradle
,loadCradle :: Maybe String -> String -> IO (Cradle Void)
loadCradle = Maybe String -> String -> IO (Cradle Void)
loadWithImplicitCradle
,getCacheDirs :: String -> [String] -> IO CacheDirs
getCacheDirs = String -> [String] -> IO CacheDirs
getCacheDirsDefault
,getInitialGhcLibDir :: Logger -> String -> IO (Maybe LibDir)
getInitialGhcLibDir = Logger -> String -> IO (Maybe LibDir)
getInitialGhcLibDirDefault
,fakeUid :: UnitId
fakeUid = UnitId -> UnitId
Compat.toUnitId (String -> UnitId
Compat.stringToUnit String
"main")
}
loadWithImplicitCradle :: Maybe FilePath
-> FilePath
-> IO (HieBios.Cradle Void)
loadWithImplicitCradle :: Maybe String -> String -> IO (Cradle Void)
loadWithImplicitCradle Maybe String
mHieYaml String
rootDir = do
case Maybe String
mHieYaml of
Just String
yaml -> String -> IO (Cradle Void)
HieBios.loadCradle String
yaml
Maybe String
Nothing -> String -> IO (Cradle Void)
forall a. String -> IO (Cradle a)
loadImplicitHieCradle (String -> IO (Cradle Void)) -> String -> IO (Cradle Void)
forall a b. (a -> b) -> a -> b
$ String -> String
addTrailingPathSeparator String
rootDir
getInitialGhcLibDirDefault :: Logger -> FilePath -> IO (Maybe LibDir)
getInitialGhcLibDirDefault :: Logger -> String -> IO (Maybe LibDir)
getInitialGhcLibDirDefault Logger
logger String
rootDir = do
Maybe String
hieYaml <- SessionLoadingOptions -> String -> IO (Maybe String)
findCradle SessionLoadingOptions
forall a. Default a => a
def String
rootDir
Cradle Void
cradle <- SessionLoadingOptions -> Maybe String -> String -> IO (Cradle Void)
loadCradle SessionLoadingOptions
forall a. Default a => a
def Maybe String
hieYaml String
rootDir
Logger -> Text -> IO ()
logDebug Logger
logger (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
"setInitialDynFlags cradle: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Cradle Void -> String
forall a. Show a => a -> String
show Cradle Void
cradle
CradleLoadResult String
libDirRes <- Cradle Void -> IO (CradleLoadResult String)
forall a. Cradle a -> IO (CradleLoadResult String)
getRuntimeGhcLibDir Cradle Void
cradle
case CradleLoadResult String
libDirRes of
CradleSuccess String
libdir -> Maybe LibDir -> IO (Maybe LibDir)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe LibDir -> IO (Maybe LibDir))
-> Maybe LibDir -> IO (Maybe LibDir)
forall a b. (a -> b) -> a -> b
$ LibDir -> Maybe LibDir
forall a. a -> Maybe a
Just (LibDir -> Maybe LibDir) -> LibDir -> Maybe LibDir
forall a b. (a -> b) -> a -> b
$ String -> LibDir
LibDir String
libdir
CradleFail CradleError
err -> do
Handle -> String -> IO ()
hPutStrLn Handle
stderr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Couldn't load cradle for libdir: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ (CradleError, String, Maybe String, Cradle Void) -> String
forall a. Show a => a -> String
show (CradleError
err,String
rootDir,Maybe String
hieYaml,Cradle Void
cradle)
Maybe LibDir -> IO (Maybe LibDir)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe LibDir
forall a. Maybe a
Nothing
CradleLoadResult String
CradleNone -> do
Handle -> String -> IO ()
hPutStrLn Handle
stderr String
"Couldn't load cradle (CradleNone)"
Maybe LibDir -> IO (Maybe LibDir)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe LibDir
forall a. Maybe a
Nothing
setInitialDynFlags :: Logger -> FilePath -> SessionLoadingOptions -> IO (Maybe LibDir)
setInitialDynFlags :: Logger -> String -> SessionLoadingOptions -> IO (Maybe LibDir)
setInitialDynFlags Logger
logger String
rootDir SessionLoadingOptions{UnitId
String -> IO (Maybe String)
String -> [String] -> IO CacheDirs
Maybe String -> String -> IO (Cradle Void)
Logger -> String -> IO (Maybe LibDir)
fakeUid :: UnitId
getInitialGhcLibDir :: Logger -> String -> IO (Maybe LibDir)
getCacheDirs :: String -> [String] -> IO CacheDirs
loadCradle :: Maybe String -> String -> IO (Cradle Void)
findCradle :: String -> IO (Maybe String)
fakeUid :: SessionLoadingOptions -> UnitId
getInitialGhcLibDir :: SessionLoadingOptions -> Logger -> String -> IO (Maybe LibDir)
getCacheDirs :: SessionLoadingOptions -> String -> [String] -> IO CacheDirs
loadCradle :: SessionLoadingOptions -> Maybe String -> String -> IO (Cradle Void)
findCradle :: SessionLoadingOptions -> String -> IO (Maybe String)
..} = do
Maybe LibDir
libdir <- Logger -> String -> IO (Maybe LibDir)
getInitialGhcLibDir Logger
logger String
rootDir
Maybe DynFlags
dynFlags <- (LibDir -> IO DynFlags) -> Maybe LibDir -> IO (Maybe DynFlags)
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM LibDir -> IO DynFlags
dynFlagsForPrinting Maybe LibDir
libdir
(DynFlags -> IO ()) -> Maybe DynFlags -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ DynFlags -> IO ()
setUnsafeGlobalDynFlags Maybe DynFlags
dynFlags
Maybe LibDir -> IO (Maybe LibDir)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe LibDir
libdir
retryOnException
:: (MonadIO m, MonadCatch m, RandomGen g, Exception e)
=> (e -> Maybe e)
-> Logger
-> Int
-> Int
-> Int
-> g
-> m a
-> m a
retryOnException :: (e -> Maybe e) -> Logger -> Int -> Int -> Int -> g -> m a -> m a
retryOnException e -> Maybe e
exceptionPred Logger
logger Int
maxDelay !Int
baseDelay !Int
maxRetryCount g
rng m a
action = do
Either e a
result <- (e -> Maybe e) -> m a -> m (Either e a)
forall (m :: * -> *) e b a.
(MonadCatch m, Exception e) =>
(e -> Maybe b) -> m a -> m (Either b a)
tryJust e -> Maybe e
exceptionPred m a
action
case Either e a
result of
Left e
e
| Int
maxRetryCount Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 -> do
let newBaseDelay :: Int
newBaseDelay = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
maxDelay (Int
baseDelay Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
2)
let (Int
delay, g
newRng) = (Int, Int) -> g -> (Int, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
Random.randomR (Int
0, Int
newBaseDelay) g
rng
let newMaxRetryCount :: Int
newMaxRetryCount = Int
maxRetryCount Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ do
Logger -> Text -> IO ()
logWarning Logger
logger (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text
"Retrying - " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Either Int Int -> Int -> e -> Text
makeLogMsgComponentsText (Int -> Either Int Int
forall a b. b -> Either a b
Right Int
delay) Int
newMaxRetryCount e
e
Int -> IO ()
threadDelay Int
delay
(e -> Maybe e) -> Logger -> Int -> Int -> Int -> g -> m a -> m a
forall (m :: * -> *) g e a.
(MonadIO m, MonadCatch m, RandomGen g, Exception e) =>
(e -> Maybe e) -> Logger -> Int -> Int -> Int -> g -> m a -> m a
retryOnException e -> Maybe e
exceptionPred Logger
logger Int
maxDelay Int
newBaseDelay Int
newMaxRetryCount g
newRng m a
action
| Bool
otherwise -> do
IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ do
Logger -> Text -> IO ()
logWarning Logger
logger (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text
"Retries exhausted - " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Either Int Int -> Int -> e -> Text
makeLogMsgComponentsText (Int -> Either Int Int
forall a b. a -> Either a b
Left Int
baseDelay) Int
maxRetryCount e
e
e -> IO a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO e
e
Right a
b -> a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
b
where
makeLogMsgComponentsText :: Either Int Int -> Int -> e -> Text
makeLogMsgComponentsText Either Int Int
delay Int
newMaxRetryCount e
e =
let
logMsgComponents :: [Text]
logMsgComponents =
[ (Int -> Text) -> (Int -> Text) -> Either Int Int -> Text
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either
((Text
"base delay: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) (Text -> Text) -> (Int -> Text) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack (String -> Text) -> (Int -> String) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show)
((Text
"delay: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) (Text -> Text) -> (Int -> Text) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack (String -> Text) -> (Int -> String) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show)
Either Int Int
delay
, Text
"maximumDelay: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
maxDelay)
, Text
"maxRetryCount: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
newMaxRetryCount)
, Text
"exception: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (e -> String
forall a. Show a => a -> String
show e
e)]
in
Text -> [Text] -> Text
T.intercalate Text
", " [Text]
logMsgComponents
oneSecond :: Int
oneSecond :: Int
oneSecond = Int
1000000
oneMillisecond :: Int
oneMillisecond :: Int
oneMillisecond = Int
1000
maxRetryCount :: Int
maxRetryCount :: Int
maxRetryCount = Int
10
retryOnSqliteBusy :: (MonadIO m, MonadCatch m, RandomGen g)
=> Logger -> g -> m a -> m a
retryOnSqliteBusy :: Logger -> g -> m a -> m a
retryOnSqliteBusy Logger
logger g
rng m a
action =
let isErrorBusy :: SQLError -> Maybe SQLError
isErrorBusy SQLError
e
| SQLError{ sqlError :: SQLError -> Error
sqlError = Error
ErrorBusy } <- SQLError
e = SQLError -> Maybe SQLError
forall a. a -> Maybe a
Just SQLError
e
| Bool
otherwise = Maybe SQLError
forall a. Maybe a
Nothing
in
(SQLError -> Maybe SQLError)
-> Logger -> Int -> Int -> Int -> g -> m a -> m a
forall (m :: * -> *) g e a.
(MonadIO m, MonadCatch m, RandomGen g, Exception e) =>
(e -> Maybe e) -> Logger -> Int -> Int -> Int -> g -> m a -> m a
retryOnException SQLError -> Maybe SQLError
isErrorBusy Logger
logger Int
oneSecond Int
oneMillisecond Int
maxRetryCount g
rng m a
action
makeWithHieDbRetryable :: RandomGen g => Logger -> g -> HieDb -> WithHieDb
makeWithHieDbRetryable :: Logger -> g -> HieDb -> WithHieDb
makeWithHieDbRetryable Logger
logger g
rng HieDb
hieDb HieDb -> IO a
f =
Logger -> g -> IO a -> IO a
forall (m :: * -> *) g a.
(MonadIO m, MonadCatch m, RandomGen g) =>
Logger -> g -> m a -> m a
retryOnSqliteBusy Logger
logger g
rng (HieDb -> IO a
f HieDb
hieDb)
runWithDb :: Logger -> FilePath -> (WithHieDb -> IndexQueue -> IO ()) -> IO ()
runWithDb :: Logger -> String -> (WithHieDb -> IndexQueue -> IO ()) -> IO ()
runWithDb Logger
logger String
fp WithHieDb -> IndexQueue -> IO ()
k = do
StdGen
rng <- IO StdGen
forall (m :: * -> *). MonadIO m => m StdGen
Random.newStdGen
Logger -> StdGen -> IO () -> IO ()
forall (m :: * -> *) g a.
(MonadIO m, MonadCatch m, RandomGen g) =>
Logger -> g -> m a -> m a
retryOnSqliteBusy
Logger
logger
StdGen
rng
(String -> (HieDb -> IO ()) -> IO ()
forall a. String -> (HieDb -> IO a) -> IO a
withHieDb String
fp (IO () -> HieDb -> IO ()
forall a b. a -> b -> a
const (IO () -> HieDb -> IO ()) -> IO () -> HieDb -> IO ()
forall a b. (a -> b) -> a -> b
$ () -> IO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) IO () -> (HieDbException -> IO ()) -> IO ()
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> (e -> m a) -> m a
`Safe.catch` \IncompatibleSchemaVersion{} -> String -> IO ()
removeFile String
fp)
String -> (HieDb -> IO ()) -> IO ()
forall a. String -> (HieDb -> IO a) -> IO a
withHieDb String
fp ((HieDb -> IO ()) -> IO ()) -> (HieDb -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \HieDb
writedb -> do
let withWriteDbRetryable :: WithHieDb
withWriteDbRetryable :: (HieDb -> IO a) -> IO a
withWriteDbRetryable = Logger -> StdGen -> HieDb -> WithHieDb
forall g. RandomGen g => Logger -> g -> HieDb -> WithHieDb
makeWithHieDbRetryable Logger
logger StdGen
rng HieDb
writedb
(HieDb -> IO ()) -> IO ()
WithHieDb
withWriteDbRetryable HieDb -> IO ()
initConn
IndexQueue
chan <- IO IndexQueue
forall a. IO (TQueue a)
newTQueueIO
IO () -> (Async () -> IO ()) -> IO ()
forall a b. IO a -> (Async a -> IO b) -> IO b
withAsync (WithHieDb -> IndexQueue -> IO ()
writerThread WithHieDb
withWriteDbRetryable IndexQueue
chan) ((Async () -> IO ()) -> IO ()) -> (Async () -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Async ()
_ -> do
String -> (HieDb -> IO ()) -> IO ()
forall a. String -> (HieDb -> IO a) -> IO a
withHieDb String
fp (\HieDb
readDb -> WithHieDb -> IndexQueue -> IO ()
k (Logger -> StdGen -> HieDb -> WithHieDb
forall g. RandomGen g => Logger -> g -> HieDb -> WithHieDb
makeWithHieDbRetryable Logger
logger StdGen
rng HieDb
readDb) IndexQueue
chan)
where
writerThread :: WithHieDb -> IndexQueue -> IO ()
writerThread :: WithHieDb -> IndexQueue -> IO ()
writerThread WithHieDb
withHieDbRetryable IndexQueue
chan = do
()
_ <- (HieDb -> IO ()) -> IO ()
WithHieDb
withHieDbRetryable HieDb -> IO ()
deleteMissingRealFiles
Int
_ <- (HieDb -> IO Int) -> IO Int
WithHieDb
withHieDbRetryable HieDb -> IO Int
garbageCollectTypeNames
IO () -> IO ()
forall (f :: * -> *) a b. Applicative f => f a -> f b
forever (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
((HieDb -> IO ()) -> IO ()) -> IO ()
k <- STM (((HieDb -> IO ()) -> IO ()) -> IO ())
-> IO (((HieDb -> IO ()) -> IO ()) -> IO ())
forall a. STM a -> IO a
atomically (STM (((HieDb -> IO ()) -> IO ()) -> IO ())
-> IO (((HieDb -> IO ()) -> IO ()) -> IO ()))
-> STM (((HieDb -> IO ()) -> IO ()) -> IO ())
-> IO (((HieDb -> IO ()) -> IO ()) -> IO ())
forall a b. (a -> b) -> a -> b
$ IndexQueue -> STM (((HieDb -> IO ()) -> IO ()) -> IO ())
forall a. TQueue a -> STM a
readTQueue IndexQueue
chan
((HieDb -> IO ()) -> IO ()) -> IO ()
k (HieDb -> IO ()) -> IO ()
WithHieDb
withHieDbRetryable
IO () -> (SQLError -> IO ()) -> IO ()
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> (e -> m a) -> m a
`Safe.catch` \e :: SQLError
e@SQLError{} -> do
Logger -> Text -> IO ()
logDebug Logger
logger (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
"SQLite error in worker, ignoring: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ SQLError -> String
forall a. Show a => a -> String
show SQLError
e
IO () -> (SomeException -> IO ()) -> IO ()
forall (m :: * -> *) a.
MonadCatch m =>
m a -> (SomeException -> m a) -> m a
`Safe.catchAny` \SomeException
e -> do
Logger -> Text -> IO ()
logDebug Logger
logger (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
"Uncaught error in database worker, ignoring: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ SomeException -> String
forall a. Show a => a -> String
show SomeException
e
getHieDbLoc :: FilePath -> IO FilePath
getHieDbLoc :: String -> IO String
getHieDbLoc String
dir = do
let db :: String
db = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"-" [String
dirHash, String -> String
takeBaseName String
dir, String
Compat.ghcVersionStr, String
hiedbDataVersion] String -> String -> String
<.> String
"hiedb"
dirHash :: String
dirHash = ByteString -> String
B.unpack (ByteString -> String) -> ByteString -> String
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
B16.encode (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
H.hash (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ String -> ByteString
B.pack String
dir
String
cDir <- XdgDirectory -> String -> IO String
IO.getXdgDirectory XdgDirectory
IO.XdgCache String
cacheDir
Bool -> String -> IO ()
createDirectoryIfMissing Bool
True String
cDir
String -> IO String
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String
cDir String -> String -> String
</> String
db)
loadSession :: FilePath -> IO (Action IdeGhcSession)
loadSession :: String -> IO (Action IdeGhcSession)
loadSession = SessionLoadingOptions -> String -> IO (Action IdeGhcSession)
loadSessionWithOptions SessionLoadingOptions
forall a. Default a => a
def
loadSessionWithOptions :: SessionLoadingOptions -> FilePath -> IO (Action IdeGhcSession)
loadSessionWithOptions :: SessionLoadingOptions -> String -> IO (Action IdeGhcSession)
loadSessionWithOptions SessionLoadingOptions{UnitId
String -> IO (Maybe String)
String -> [String] -> IO CacheDirs
Maybe String -> String -> IO (Cradle Void)
Logger -> String -> IO (Maybe LibDir)
fakeUid :: UnitId
getInitialGhcLibDir :: Logger -> String -> IO (Maybe LibDir)
getCacheDirs :: String -> [String] -> IO CacheDirs
loadCradle :: Maybe String -> String -> IO (Cradle Void)
findCradle :: String -> IO (Maybe String)
fakeUid :: SessionLoadingOptions -> UnitId
getInitialGhcLibDir :: SessionLoadingOptions -> Logger -> String -> IO (Maybe LibDir)
getCacheDirs :: SessionLoadingOptions -> String -> [String] -> IO CacheDirs
loadCradle :: SessionLoadingOptions -> Maybe String -> String -> IO (Cradle Void)
findCradle :: SessionLoadingOptions -> String -> IO (Maybe String)
..} String
dir = do
Var HieMap
hscEnvs <- HieMap -> IO (Var HieMap)
forall a. a -> IO (Var a)
newVar HieMap
forall k a. Map k a
Map.empty :: IO (Var HieMap)
Var FlagsMap
fileToFlags <- FlagsMap -> IO (Var FlagsMap)
forall a. a -> IO (Var a)
newVar FlagsMap
forall k a. Map k a
Map.empty :: IO (Var FlagsMap)
Var FilesMap
filesMap <- FilesMap -> IO (Var FilesMap)
forall a. a -> IO (Var a)
newVar FilesMap
forall k v. HashMap k v
HM.empty :: IO (Var FilesMap)
Var Int
version <- Int -> IO (Var Int)
forall a. a -> IO (Var a)
newVar Int
0
let returnWithVersion :: (String -> IO (IdeResult HscEnvEq, [String]))
-> Action IdeGhcSession
returnWithVersion String -> IO (IdeResult HscEnvEq, [String])
fun = (String -> IO (IdeResult HscEnvEq, [String]))
-> Int -> IdeGhcSession
IdeGhcSession String -> IO (IdeResult HscEnvEq, [String])
fun (Int -> IdeGhcSession) -> Action Int -> Action IdeGhcSession
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Int -> Action Int
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Var Int -> IO Int
forall a. Var a -> IO a
readVar Var Int
version)
String -> IO (Maybe String)
cradleLoc <- IO (String -> IO (Maybe String))
-> IO (String -> IO (Maybe String))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (String -> IO (Maybe String))
-> IO (String -> IO (Maybe String)))
-> IO (String -> IO (Maybe String))
-> IO (String -> IO (Maybe String))
forall a b. (a -> b) -> a -> b
$ (String -> IO (Maybe String)) -> IO (String -> IO (Maybe String))
forall a b. Ord a => (a -> IO b) -> IO (a -> IO b)
memoIO ((String -> IO (Maybe String)) -> IO (String -> IO (Maybe String)))
-> (String -> IO (Maybe String))
-> IO (String -> IO (Maybe String))
forall a b. (a -> b) -> a -> b
$ \String
v -> do
Maybe String
res <- String -> IO (Maybe String)
findCradle String
v
Maybe String
res' <- (String -> IO String) -> Maybe String -> IO (Maybe String)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse String -> IO String
makeAbsolute Maybe String
res
Maybe String -> IO (Maybe String)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe String -> IO (Maybe String))
-> Maybe String -> IO (Maybe String)
forall a b. (a -> b) -> a -> b
$ String -> String
normalise (String -> String) -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe String
res'
Async (IdeResult HscEnvEq, [String])
dummyAs <- IO (IdeResult HscEnvEq, [String])
-> IO (Async (IdeResult HscEnvEq, [String]))
forall a. IO a -> IO (Async a)
async (IO (IdeResult HscEnvEq, [String])
-> IO (Async (IdeResult HscEnvEq, [String])))
-> IO (IdeResult HscEnvEq, [String])
-> IO (Async (IdeResult HscEnvEq, [String]))
forall a b. (a -> b) -> a -> b
$ (IdeResult HscEnvEq, [String]) -> IO (IdeResult HscEnvEq, [String])
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> (IdeResult HscEnvEq, [String])
forall a. HasCallStack => String -> a
error String
"Uninitialised")
Var (Async (IdeResult HscEnvEq, [String]))
runningCradle <- Async (IdeResult HscEnvEq, [String])
-> IO (Var (Async (IdeResult HscEnvEq, [String])))
forall a. a -> IO (Var a)
newVar Async (IdeResult HscEnvEq, [String])
dummyAs :: IO (Var (Async (IdeResult HscEnvEq,[FilePath])))
Action IdeGhcSession -> IO (Action IdeGhcSession)
forall (m :: * -> *) a. Monad m => a -> m a
return (Action IdeGhcSession -> IO (Action IdeGhcSession))
-> Action IdeGhcSession -> IO (Action IdeGhcSession)
forall a b. (a -> b) -> a -> b
$ do
extras :: ShakeExtras
extras@ShakeExtras{Logger
$sel:logger:ShakeExtras :: ShakeExtras -> Logger
logger :: Logger
logger, String -> [DelayedAction ()] -> IO ()
$sel:restartShakeSession:ShakeExtras :: ShakeExtras -> String -> [DelayedAction ()] -> IO ()
restartShakeSession :: String -> [DelayedAction ()] -> IO ()
restartShakeSession, IORef NameCache
$sel:ideNc:ShakeExtras :: ShakeExtras -> IORef NameCache
ideNc :: IORef NameCache
ideNc, TVar (Hashed KnownTargets)
$sel:knownTargetsVar:ShakeExtras :: ShakeExtras -> TVar (Hashed KnownTargets)
knownTargetsVar :: TVar (Hashed KnownTargets)
knownTargetsVar, Maybe (LanguageContextEnv Config)
$sel:lspEnv:ShakeExtras :: ShakeExtras -> Maybe (LanguageContextEnv Config)
lspEnv :: Maybe (LanguageContextEnv Config)
lspEnv
} <- Action ShakeExtras
getShakeExtras
let invalidateShakeCache :: IO ()
invalidateShakeCache :: IO ()
invalidateShakeCache = do
IO Int -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO Int -> IO ()) -> IO Int -> IO ()
forall a b. (a -> b) -> a -> b
$ Var Int -> (Int -> Int) -> IO Int
forall a. Var a -> (a -> a) -> IO a
modifyVar' Var Int
version Int -> Int
forall a. Enum a => a -> a
succ
IO (IO ()) -> IO ()
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (IO (IO ()) -> IO ()) -> IO (IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ STM (IO ()) -> IO (IO ())
forall a. STM a -> IO a
atomically (STM (IO ()) -> IO (IO ())) -> STM (IO ()) -> IO (IO ())
forall a b. (a -> b) -> a -> b
$ ShakeExtras -> GhcSessionIO -> [NormalizedFilePath] -> STM (IO ())
forall k.
ShakeValue k =>
ShakeExtras -> k -> [NormalizedFilePath] -> STM (IO ())
recordDirtyKeys ShakeExtras
extras GhcSessionIO
GhcSessionIO [NormalizedFilePath
emptyFilePath]
IdeOptions{ optTesting :: IdeOptions -> IdeTesting
optTesting = IdeTesting Bool
optTesting
, optCheckProject :: IdeOptions -> IO Bool
optCheckProject = IO Bool
getCheckProject
, [String]
optExtensions :: IdeOptions -> [String]
optExtensions :: [String]
optExtensions
} <- Action IdeOptions
getIdeOptions
let extendKnownTargets :: [TargetDetails] -> IO ()
extendKnownTargets [TargetDetails]
newTargets = do
[(Target, [NormalizedFilePath])]
knownTargets <- [TargetDetails]
-> (TargetDetails -> IO (Target, [NormalizedFilePath]))
-> IO [(Target, [NormalizedFilePath])]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [TargetDetails]
newTargets ((TargetDetails -> IO (Target, [NormalizedFilePath]))
-> IO [(Target, [NormalizedFilePath])])
-> (TargetDetails -> IO (Target, [NormalizedFilePath]))
-> IO [(Target, [NormalizedFilePath])]
forall a b. (a -> b) -> a -> b
$ \TargetDetails{[NormalizedFilePath]
IdeResult HscEnvEq
DependencyInfo
Target
targetLocations :: TargetDetails -> [NormalizedFilePath]
targetDepends :: TargetDetails -> DependencyInfo
targetEnv :: TargetDetails -> IdeResult HscEnvEq
targetTarget :: TargetDetails -> Target
targetLocations :: [NormalizedFilePath]
targetDepends :: DependencyInfo
targetEnv :: IdeResult HscEnvEq
targetTarget :: Target
..} ->
case Target
targetTarget of
TargetFile NormalizedFilePath
f -> (Target, [NormalizedFilePath]) -> IO (Target, [NormalizedFilePath])
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Target
targetTarget, [NormalizedFilePath
f])
TargetModule ModuleName
_ -> do
[NormalizedFilePath]
found <- (NormalizedFilePath -> IO Bool)
-> [NormalizedFilePath] -> IO [NormalizedFilePath]
forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (String -> IO Bool
IO.doesFileExist (String -> IO Bool)
-> (NormalizedFilePath -> String) -> NormalizedFilePath -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NormalizedFilePath -> String
fromNormalizedFilePath) [NormalizedFilePath]
targetLocations
(Target, [NormalizedFilePath]) -> IO (Target, [NormalizedFilePath])
forall (m :: * -> *) a. Monad m => a -> m a
return (Target
targetTarget, [NormalizedFilePath]
found)
Maybe KnownTargets
hasUpdate <- IO (IO (Maybe KnownTargets)) -> IO (Maybe KnownTargets)
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (IO (IO (Maybe KnownTargets)) -> IO (Maybe KnownTargets))
-> IO (IO (Maybe KnownTargets)) -> IO (Maybe KnownTargets)
forall a b. (a -> b) -> a -> b
$ STM (IO (Maybe KnownTargets)) -> IO (IO (Maybe KnownTargets))
forall a. STM a -> IO a
atomically (STM (IO (Maybe KnownTargets)) -> IO (IO (Maybe KnownTargets)))
-> STM (IO (Maybe KnownTargets)) -> IO (IO (Maybe KnownTargets))
forall a b. (a -> b) -> a -> b
$ do
Hashed KnownTargets
known <- TVar (Hashed KnownTargets) -> STM (Hashed KnownTargets)
forall a. TVar a -> STM a
readTVar TVar (Hashed KnownTargets)
knownTargetsVar
let known' :: Hashed KnownTargets
known' = ((KnownTargets -> KnownTargets)
-> Hashed KnownTargets -> Hashed KnownTargets)
-> Hashed KnownTargets
-> (KnownTargets -> KnownTargets)
-> Hashed KnownTargets
forall a b c. (a -> b -> c) -> b -> a -> c
flip (KnownTargets -> KnownTargets)
-> Hashed KnownTargets -> Hashed KnownTargets
forall b a. Hashable b => (a -> b) -> Hashed a -> Hashed b
mapHashed Hashed KnownTargets
known ((KnownTargets -> KnownTargets) -> Hashed KnownTargets)
-> (KnownTargets -> KnownTargets) -> Hashed KnownTargets
forall a b. (a -> b) -> a -> b
$ \KnownTargets
k ->
(HashSet NormalizedFilePath
-> HashSet NormalizedFilePath -> HashSet NormalizedFilePath)
-> KnownTargets -> KnownTargets -> KnownTargets
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> HashMap k v -> HashMap k v -> HashMap k v
HM.unionWith HashSet NormalizedFilePath
-> HashSet NormalizedFilePath -> HashSet NormalizedFilePath
forall a. Semigroup a => a -> a -> a
(<>) KnownTargets
k (KnownTargets -> KnownTargets) -> KnownTargets -> KnownTargets
forall a b. (a -> b) -> a -> b
$ [(Target, HashSet NormalizedFilePath)] -> KnownTargets
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HM.fromList ([(Target, HashSet NormalizedFilePath)] -> KnownTargets)
-> [(Target, HashSet NormalizedFilePath)] -> KnownTargets
forall a b. (a -> b) -> a -> b
$ ((Target, [NormalizedFilePath])
-> (Target, HashSet NormalizedFilePath))
-> [(Target, [NormalizedFilePath])]
-> [(Target, HashSet NormalizedFilePath)]
forall a b. (a -> b) -> [a] -> [b]
map (([NormalizedFilePath] -> HashSet NormalizedFilePath)
-> (Target, [NormalizedFilePath])
-> (Target, HashSet NormalizedFilePath)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second [NormalizedFilePath] -> HashSet NormalizedFilePath
forall a. (Eq a, Hashable a) => [a] -> HashSet a
Set.fromList) [(Target, [NormalizedFilePath])]
knownTargets
hasUpdate :: Maybe KnownTargets
hasUpdate = if Hashed KnownTargets
known Hashed KnownTargets -> Hashed KnownTargets -> Bool
forall a. Eq a => a -> a -> Bool
/= Hashed KnownTargets
known' then KnownTargets -> Maybe KnownTargets
forall a. a -> Maybe a
Just (Hashed KnownTargets -> KnownTargets
forall a. Hashed a -> a
unhashed Hashed KnownTargets
known') else Maybe KnownTargets
forall a. Maybe a
Nothing
TVar (Hashed KnownTargets) -> Hashed KnownTargets -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (Hashed KnownTargets)
knownTargetsVar Hashed KnownTargets
known'
IO ()
logDirtyKeys <- ShakeExtras
-> GetKnownTargets -> [NormalizedFilePath] -> STM (IO ())
forall k.
ShakeValue k =>
ShakeExtras -> k -> [NormalizedFilePath] -> STM (IO ())
recordDirtyKeys ShakeExtras
extras GetKnownTargets
GetKnownTargets [NormalizedFilePath
emptyFilePath]
IO (Maybe KnownTargets) -> STM (IO (Maybe KnownTargets))
forall (m :: * -> *) a. Monad m => a -> m a
return (IO ()
logDirtyKeys IO () -> IO (Maybe KnownTargets) -> IO (Maybe KnownTargets)
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe KnownTargets -> IO (Maybe KnownTargets)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe KnownTargets
hasUpdate)
Maybe KnownTargets -> (KnownTargets -> IO ()) -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ Maybe KnownTargets
hasUpdate ((KnownTargets -> IO ()) -> IO ())
-> (KnownTargets -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \KnownTargets
x ->
Logger -> Text -> IO ()
logDebug Logger
logger (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text
"Known files updated: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
String -> Text
T.pack(HashMap Target (HashSet String) -> String
forall a. Show a => a -> String
show (HashMap Target (HashSet String) -> String)
-> HashMap Target (HashSet String) -> String
forall a b. (a -> b) -> a -> b
$ ((HashSet NormalizedFilePath -> HashSet String)
-> KnownTargets -> HashMap Target (HashSet String)
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map ((HashSet NormalizedFilePath -> HashSet String)
-> KnownTargets -> HashMap Target (HashSet String))
-> ((NormalizedFilePath -> String)
-> HashSet NormalizedFilePath -> HashSet String)
-> (NormalizedFilePath -> String)
-> KnownTargets
-> HashMap Target (HashSet String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NormalizedFilePath -> String)
-> HashSet NormalizedFilePath -> HashSet String
forall b a.
(Hashable b, Eq b) =>
(a -> b) -> HashSet a -> HashSet b
Set.map) NormalizedFilePath -> String
fromNormalizedFilePath KnownTargets
x)
let packageSetup :: (Maybe FilePath, NormalizedFilePath, ComponentOptions, FilePath)
-> IO (HscEnv, ComponentInfo, [ComponentInfo])
packageSetup :: (Maybe String, NormalizedFilePath, ComponentOptions, String)
-> IO (HscEnv, ComponentInfo, [ComponentInfo])
packageSetup (Maybe String
hieYaml, NormalizedFilePath
cfp, ComponentOptions
opts, String
libDir) = do
HscEnv
hscEnv <- IORef NameCache -> String -> IO HscEnv
emptyHscEnv IORef NameCache
ideNc String
libDir
(DynFlags
df, [Target]
targets) <- HscEnv -> Ghc (DynFlags, [Target]) -> IO (DynFlags, [Target])
forall b. HscEnv -> Ghc b -> IO b
evalGhcEnv HscEnv
hscEnv (Ghc (DynFlags, [Target]) -> IO (DynFlags, [Target]))
-> Ghc (DynFlags, [Target]) -> IO (DynFlags, [Target])
forall a b. (a -> b) -> a -> b
$ ComponentOptions -> DynFlags -> Ghc (DynFlags, [Target])
forall (m :: * -> *).
GhcMonad m =>
ComponentOptions -> DynFlags -> m (DynFlags, [Target])
setOptions ComponentOptions
opts (HscEnv -> DynFlags
hsc_dflags HscEnv
hscEnv)
let deps :: [String]
deps = ComponentOptions -> [String]
componentDependencies ComponentOptions
opts [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ Maybe String -> [String]
forall a. Maybe a -> [a]
maybeToList Maybe String
hieYaml
DependencyInfo
dep_info <- [String] -> IO DependencyInfo
getDependencyInfo [String]
deps
Var HieMap
-> (HieMap
-> IO (HieMap, (HscEnv, ComponentInfo, [ComponentInfo])))
-> IO (HscEnv, ComponentInfo, [ComponentInfo])
forall a b. Var a -> (a -> IO (a, b)) -> IO b
modifyVar Var HieMap
hscEnvs ((HieMap -> IO (HieMap, (HscEnv, ComponentInfo, [ComponentInfo])))
-> IO (HscEnv, ComponentInfo, [ComponentInfo]))
-> (HieMap
-> IO (HieMap, (HscEnv, ComponentInfo, [ComponentInfo])))
-> IO (HscEnv, ComponentInfo, [ComponentInfo])
forall a b. (a -> b) -> a -> b
$ \HieMap
m -> do
let oldDeps :: Maybe (HscEnv, [RawComponentInfo])
oldDeps = Maybe String -> HieMap -> Maybe (HscEnv, [RawComponentInfo])
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Maybe String
hieYaml HieMap
m
let
new_deps :: [RawComponentInfo]
new_deps = UnitId
-> DynFlags
-> [Target]
-> NormalizedFilePath
-> ComponentOptions
-> DependencyInfo
-> RawComponentInfo
RawComponentInfo (DynFlags -> UnitId
homeUnitId_ DynFlags
df) DynFlags
df [Target]
targets NormalizedFilePath
cfp ComponentOptions
opts DependencyInfo
dep_info
RawComponentInfo -> [RawComponentInfo] -> [RawComponentInfo]
forall a. a -> [a] -> [a]
: [RawComponentInfo]
-> ((HscEnv, [RawComponentInfo]) -> [RawComponentInfo])
-> Maybe (HscEnv, [RawComponentInfo])
-> [RawComponentInfo]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (HscEnv, [RawComponentInfo]) -> [RawComponentInfo]
forall a b. (a, b) -> b
snd Maybe (HscEnv, [RawComponentInfo])
oldDeps
inplace :: [UnitId]
inplace = (RawComponentInfo -> UnitId) -> [RawComponentInfo] -> [UnitId]
forall a b. (a -> b) -> [a] -> [b]
map RawComponentInfo -> UnitId
rawComponentUnitId [RawComponentInfo]
new_deps
[ComponentInfo]
new_deps' <- [RawComponentInfo]
-> (RawComponentInfo -> IO ComponentInfo) -> IO [ComponentInfo]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [RawComponentInfo]
new_deps ((RawComponentInfo -> IO ComponentInfo) -> IO [ComponentInfo])
-> (RawComponentInfo -> IO ComponentInfo) -> IO [ComponentInfo]
forall a b. (a -> b) -> a -> b
$ \RawComponentInfo{[Target]
DependencyInfo
UnitId
DynFlags
ComponentOptions
NormalizedFilePath
rawComponentDependencyInfo :: RawComponentInfo -> DependencyInfo
rawComponentCOptions :: RawComponentInfo -> ComponentOptions
rawComponentFP :: RawComponentInfo -> NormalizedFilePath
rawComponentTargets :: RawComponentInfo -> [Target]
rawComponentDynFlags :: RawComponentInfo -> DynFlags
rawComponentDependencyInfo :: DependencyInfo
rawComponentCOptions :: ComponentOptions
rawComponentFP :: NormalizedFilePath
rawComponentTargets :: [Target]
rawComponentDynFlags :: DynFlags
rawComponentUnitId :: UnitId
rawComponentUnitId :: RawComponentInfo -> UnitId
..} -> do
let (DynFlags
df2, [UnitId]
uids) = UnitId -> [UnitId] -> DynFlags -> (DynFlags, [UnitId])
removeInplacePackages UnitId
fakeUid [UnitId]
inplace DynFlags
rawComponentDynFlags
let prefix :: String
prefix = UnitId -> String
forall a. Show a => a -> String
show UnitId
rawComponentUnitId
let hscComponents :: [String]
hscComponents = [String] -> [String]
forall a. Ord a => [a] -> [a]
sort ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ (UnitId -> String) -> [UnitId] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map UnitId -> String
forall a. Show a => a -> String
show [UnitId]
uids
cacheDirOpts :: [String]
cacheDirOpts = [String]
hscComponents [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ ComponentOptions -> [String]
componentOptions ComponentOptions
opts
CacheDirs
cacheDirs <- IO CacheDirs -> IO CacheDirs
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO CacheDirs -> IO CacheDirs) -> IO CacheDirs -> IO CacheDirs
forall a b. (a -> b) -> a -> b
$ String -> [String] -> IO CacheDirs
getCacheDirs String
prefix [String]
cacheDirOpts
DynFlags
processed_df <- Logger -> CacheDirs -> DynFlags -> IO DynFlags
forall (m :: * -> *).
MonadIO m =>
Logger -> CacheDirs -> DynFlags -> m DynFlags
setCacheDirs Logger
logger CacheDirs
cacheDirs DynFlags
df2
ComponentInfo -> IO ComponentInfo
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ComponentInfo -> IO ComponentInfo)
-> ComponentInfo -> IO ComponentInfo
forall a b. (a -> b) -> a -> b
$ UnitId
-> DynFlags
-> [UnitId]
-> [Target]
-> NormalizedFilePath
-> ComponentOptions
-> DependencyInfo
-> ComponentInfo
ComponentInfo UnitId
rawComponentUnitId
DynFlags
processed_df
[UnitId]
uids
[Target]
rawComponentTargets
NormalizedFilePath
rawComponentFP
ComponentOptions
rawComponentCOptions
DependencyInfo
rawComponentDependencyInfo
Logger -> Text -> IO ()
logInfo Logger
logger (String -> Text
T.pack (String
"Making new HscEnv" String -> String -> String
forall a. [a] -> [a] -> [a]
++ [UnitId] -> String
forall a. Show a => a -> String
show [UnitId]
inplace))
HscEnv
hscEnv <- IORef NameCache -> String -> IO HscEnv
emptyHscEnv IORef NameCache
ideNc String
libDir
HscEnv
newHscEnv <-
HscEnv -> Ghc HscEnv -> IO HscEnv
forall b. HscEnv -> Ghc b -> IO b
evalGhcEnv HscEnv
hscEnv (Ghc HscEnv -> IO HscEnv) -> Ghc HscEnv -> IO HscEnv
forall a b. (a -> b) -> a -> b
$ do
[InstalledUnitId]
_ <- DynFlags -> Ghc [InstalledUnitId]
forall (m :: * -> *). GhcMonad m => DynFlags -> m [InstalledUnitId]
setSessionDynFlags (DynFlags -> Ghc [InstalledUnitId])
-> DynFlags -> Ghc [InstalledUnitId]
forall a b. (a -> b) -> a -> b
$ UnitId -> DynFlags -> DynFlags
setHomeUnitId_ UnitId
fakeUid DynFlags
df
Ghc HscEnv
forall (m :: * -> *). GhcMonad m => m HscEnv
getSession
(HieMap, (HscEnv, ComponentInfo, [ComponentInfo]))
-> IO (HieMap, (HscEnv, ComponentInfo, [ComponentInfo]))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe String -> (HscEnv, [RawComponentInfo]) -> HieMap -> HieMap
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert Maybe String
hieYaml (HscEnv
newHscEnv, [RawComponentInfo]
new_deps) HieMap
m, (HscEnv
newHscEnv, [ComponentInfo] -> ComponentInfo
forall a. [a] -> a
head [ComponentInfo]
new_deps', [ComponentInfo] -> [ComponentInfo]
forall a. [a] -> [a]
tail [ComponentInfo]
new_deps'))
let session :: (Maybe FilePath, NormalizedFilePath, ComponentOptions, FilePath)
-> IO (IdeResult HscEnvEq,[FilePath])
session :: (Maybe String, NormalizedFilePath, ComponentOptions, String)
-> IO (IdeResult HscEnvEq, [String])
session args :: (Maybe String, NormalizedFilePath, ComponentOptions, String)
args@(Maybe String
hieYaml, NormalizedFilePath
_cfp, ComponentOptions
_opts, String
_libDir) = do
(HscEnv
hscEnv, ComponentInfo
new, [ComponentInfo]
old_deps) <- (Maybe String, NormalizedFilePath, ComponentOptions, String)
-> IO (HscEnv, ComponentInfo, [ComponentInfo])
packageSetup (Maybe String, NormalizedFilePath, ComponentOptions, String)
args
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (String
os String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"linux") (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
HscEnv -> IO ()
initObjLinker HscEnv
hscEnv
Maybe String
res <- HscEnv -> String -> IO (Maybe String)
loadDLL HscEnv
hscEnv String
"libm.so.6"
case Maybe String
res of
Maybe String
Nothing -> () -> IO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just String
err -> Logger -> Text -> IO ()
logDebug Logger
logger (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$
String
"Error dynamically loading libm.so.6:\n" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
err
let uids :: [(UnitId, DynFlags)]
uids = (ComponentInfo -> (UnitId, DynFlags))
-> [ComponentInfo] -> [(UnitId, DynFlags)]
forall a b. (a -> b) -> [a] -> [b]
map (\ComponentInfo
ci -> (ComponentInfo -> UnitId
componentUnitId ComponentInfo
ci, ComponentInfo -> DynFlags
componentDynFlags ComponentInfo
ci)) (ComponentInfo
new ComponentInfo -> [ComponentInfo] -> [ComponentInfo]
forall a. a -> [a] -> [a]
: [ComponentInfo]
old_deps)
let new_cache :: ComponentInfo
-> IO ([TargetDetails], (IdeResult HscEnvEq, DependencyInfo))
new_cache = Logger
-> [String]
-> Maybe String
-> NormalizedFilePath
-> HscEnv
-> [(UnitId, DynFlags)]
-> ComponentInfo
-> IO ([TargetDetails], (IdeResult HscEnvEq, DependencyInfo))
newComponentCache Logger
logger [String]
optExtensions Maybe String
hieYaml NormalizedFilePath
_cfp HscEnv
hscEnv [(UnitId, DynFlags)]
uids
([TargetDetails]
cs, (IdeResult HscEnvEq, DependencyInfo)
res) <- ComponentInfo
-> IO ([TargetDetails], (IdeResult HscEnvEq, DependencyInfo))
new_cache ComponentInfo
new
[TargetDetails]
cached_targets <- (ComponentInfo -> IO [TargetDetails])
-> [ComponentInfo] -> IO [TargetDetails]
forall (m :: * -> *) a b. Monad m => (a -> m [b]) -> [a] -> m [b]
concatMapM ((([TargetDetails], (IdeResult HscEnvEq, DependencyInfo))
-> [TargetDetails])
-> IO ([TargetDetails], (IdeResult HscEnvEq, DependencyInfo))
-> IO [TargetDetails]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([TargetDetails], (IdeResult HscEnvEq, DependencyInfo))
-> [TargetDetails]
forall a b. (a, b) -> a
fst (IO ([TargetDetails], (IdeResult HscEnvEq, DependencyInfo))
-> IO [TargetDetails])
-> (ComponentInfo
-> IO ([TargetDetails], (IdeResult HscEnvEq, DependencyInfo)))
-> ComponentInfo
-> IO [TargetDetails]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ComponentInfo
-> IO ([TargetDetails], (IdeResult HscEnvEq, DependencyInfo))
new_cache) [ComponentInfo]
old_deps
let all_targets :: [TargetDetails]
all_targets = [TargetDetails]
cs [TargetDetails] -> [TargetDetails] -> [TargetDetails]
forall a. [a] -> [a] -> [a]
++ [TargetDetails]
cached_targets
IO FlagsMap -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO FlagsMap -> IO ()) -> IO FlagsMap -> IO ()
forall a b. (a -> b) -> a -> b
$ Var FlagsMap -> (FlagsMap -> FlagsMap) -> IO FlagsMap
forall a. Var a -> (a -> a) -> IO a
modifyVar' Var FlagsMap
fileToFlags ((FlagsMap -> FlagsMap) -> IO FlagsMap)
-> (FlagsMap -> FlagsMap) -> IO FlagsMap
forall a b. (a -> b) -> a -> b
$
Maybe String
-> HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
-> FlagsMap
-> FlagsMap
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert Maybe String
hieYaml ([(NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))]
-> HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HM.fromList ((TargetDetails
-> [(NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))])
-> [TargetDetails]
-> [(NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap TargetDetails
-> [(NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))]
toFlagsMap [TargetDetails]
all_targets))
IO FilesMap -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO FilesMap -> IO ()) -> IO FilesMap -> IO ()
forall a b. (a -> b) -> a -> b
$ Var FilesMap -> (FilesMap -> FilesMap) -> IO FilesMap
forall a. Var a -> (a -> a) -> IO a
modifyVar' Var FilesMap
filesMap ((FilesMap -> FilesMap) -> IO FilesMap)
-> (FilesMap -> FilesMap) -> IO FilesMap
forall a b. (a -> b) -> a -> b
$
(FilesMap -> FilesMap -> FilesMap)
-> FilesMap -> FilesMap -> FilesMap
forall a b c. (a -> b -> c) -> b -> a -> c
flip FilesMap -> FilesMap -> FilesMap
forall k v.
(Eq k, Hashable k) =>
HashMap k v -> HashMap k v -> HashMap k v
HM.union ([(NormalizedFilePath, Maybe String)] -> FilesMap
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HM.fromList ([NormalizedFilePath]
-> [Maybe String] -> [(NormalizedFilePath, Maybe String)]
forall a b. [a] -> [b] -> [(a, b)]
zip (((NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))
-> NormalizedFilePath)
-> [(NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))]
-> [NormalizedFilePath]
forall a b. (a -> b) -> [a] -> [b]
map (NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))
-> NormalizedFilePath
forall a b. (a, b) -> a
fst ([(NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))]
-> [NormalizedFilePath])
-> [(NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))]
-> [NormalizedFilePath]
forall a b. (a -> b) -> a -> b
$ (TargetDetails
-> [(NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))])
-> [TargetDetails]
-> [(NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap TargetDetails
-> [(NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))]
toFlagsMap [TargetDetails]
all_targets) (Maybe String -> [Maybe String]
forall a. a -> [a]
repeat Maybe String
hieYaml)))
IO () -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ [TargetDetails] -> IO ()
extendKnownTargets [TargetDetails]
all_targets
IO ()
invalidateShakeCache
String -> [DelayedAction ()] -> IO ()
restartShakeSession String
"new component" []
Bool
checkProject <- IO Bool
getCheckProject
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([TargetDetails] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [TargetDetails]
cs Bool -> Bool -> Bool
|| Bool -> Bool
not Bool
checkProject) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
[NormalizedFilePath]
cfps' <- IO [NormalizedFilePath] -> IO [NormalizedFilePath]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [NormalizedFilePath] -> IO [NormalizedFilePath])
-> IO [NormalizedFilePath] -> IO [NormalizedFilePath]
forall a b. (a -> b) -> a -> b
$ (NormalizedFilePath -> IO Bool)
-> [NormalizedFilePath] -> IO [NormalizedFilePath]
forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (String -> IO Bool
IO.doesFileExist (String -> IO Bool)
-> (NormalizedFilePath -> String) -> NormalizedFilePath -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NormalizedFilePath -> String
fromNormalizedFilePath) ((TargetDetails -> [NormalizedFilePath])
-> [TargetDetails] -> [NormalizedFilePath]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap TargetDetails -> [NormalizedFilePath]
targetLocations [TargetDetails]
cs)
IO (IO ()) -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO (IO ()) -> IO ()) -> IO (IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ ShakeExtras -> DelayedAction () -> IO (IO ())
forall a. ShakeExtras -> DelayedAction a -> IO (IO a)
shakeEnqueue ShakeExtras
extras (DelayedAction () -> IO (IO ())) -> DelayedAction () -> IO (IO ())
forall a b. (a -> b) -> a -> b
$ String -> Priority -> Action () -> DelayedAction ()
forall a. String -> Priority -> Action a -> DelayedAction a
mkDelayedAction String
"InitialLoad" Priority
Debug (Action () -> DelayedAction ()) -> Action () -> DelayedAction ()
forall a b. (a -> b) -> a -> b
$ Action () -> Action ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Action () -> Action ()) -> Action () -> Action ()
forall a b. (a -> b) -> a -> b
$ do
[Maybe FileVersion]
mmt <- GetModificationTime
-> [NormalizedFilePath] -> Action [Maybe FileVersion]
forall k v.
IdeRule k v =>
k -> [NormalizedFilePath] -> Action [Maybe v]
uses GetModificationTime
GetModificationTime [NormalizedFilePath]
cfps'
let cs_exist :: [NormalizedFilePath]
cs_exist = [Maybe NormalizedFilePath] -> [NormalizedFilePath]
forall a. [Maybe a] -> [a]
catMaybes ((NormalizedFilePath
-> Maybe FileVersion -> Maybe NormalizedFilePath)
-> [NormalizedFilePath]
-> [Maybe FileVersion]
-> [Maybe NormalizedFilePath]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith NormalizedFilePath -> Maybe FileVersion -> Maybe NormalizedFilePath
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
(<$) [NormalizedFilePath]
cfps' [Maybe FileVersion]
mmt)
[Maybe HiFileResult]
modIfaces <- GetModIface -> [NormalizedFilePath] -> Action [Maybe HiFileResult]
forall k v.
IdeRule k v =>
k -> [NormalizedFilePath] -> Action [Maybe v]
uses GetModIface
GetModIface [NormalizedFilePath]
cs_exist
ShakeExtras
extras <- Action ShakeExtras
getShakeExtras
let !exportsMap' :: ExportsMap
exportsMap' = [ModIface] -> ExportsMap
createExportsMap ([ModIface] -> ExportsMap) -> [ModIface] -> ExportsMap
forall a b. (a -> b) -> a -> b
$ (Maybe HiFileResult -> Maybe ModIface)
-> [Maybe HiFileResult] -> [ModIface]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ((HiFileResult -> ModIface) -> Maybe HiFileResult -> Maybe ModIface
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap HiFileResult -> ModIface
hirModIface) [Maybe HiFileResult]
modIfaces
IO () -> Action ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Action ()) -> IO () -> Action ()
forall a b. (a -> b) -> a -> b
$ STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar ExportsMap -> (ExportsMap -> ExportsMap) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' (ShakeExtras -> TVar ExportsMap
exportsMap ShakeExtras
extras) (ExportsMap
exportsMap' ExportsMap -> ExportsMap -> ExportsMap
forall a. Semigroup a => a -> a -> a
<>)
(IdeResult HscEnvEq, [String]) -> IO (IdeResult HscEnvEq, [String])
forall (m :: * -> *) a. Monad m => a -> m a
return ((DependencyInfo -> [String])
-> (IdeResult HscEnvEq, DependencyInfo)
-> (IdeResult HscEnvEq, [String])
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second DependencyInfo -> [String]
forall k a. Map k a -> [k]
Map.keys (IdeResult HscEnvEq, DependencyInfo)
res)
let consultCradle :: Maybe FilePath -> FilePath -> IO (IdeResult HscEnvEq, [FilePath])
consultCradle :: Maybe String -> String -> IO (IdeResult HscEnvEq, [String])
consultCradle Maybe String
hieYaml String
cfp = do
String
lfp <- (String -> String -> String) -> String -> String -> String
forall a b c. (a -> b -> c) -> b -> a -> c
flip String -> String -> String
makeRelative String
cfp (String -> String) -> IO String -> IO String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO String
getCurrentDirectory
Logger -> Text -> IO ()
logInfo Logger
logger (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String
"Consulting the cradle for " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> String
forall a. Show a => a -> String
show String
lfp)
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe String -> Bool
forall a. Maybe a -> Bool
isNothing Maybe String
hieYaml) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
Logger -> Text -> IO ()
logWarning Logger
logger (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> Text
implicitCradleWarning String
lfp
Cradle Void
cradle <- Maybe String -> String -> IO (Cradle Void)
loadCradle Maybe String
hieYaml String
dir
String
lfp <- (String -> String -> String) -> String -> String -> String
forall a b c. (a -> b -> c) -> b -> a -> c
flip String -> String -> String
makeRelative String
cfp (String -> String) -> IO String -> IO String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO String
getCurrentDirectory
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
optTesting (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Maybe (LanguageContextEnv Config) -> LspT Config IO () -> IO ()
forall (m :: * -> *) c.
Applicative m =>
Maybe (LanguageContextEnv c) -> LspT c m () -> m ()
mRunLspT Maybe (LanguageContextEnv Config)
lspEnv (LspT Config IO () -> IO ()) -> LspT Config IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
SServerMethod 'CustomMethod
-> MessageParams 'CustomMethod -> LspT Config IO ()
forall (m :: Method 'FromServer 'Notification) (f :: * -> *)
config.
MonadLsp config f =>
SServerMethod m -> MessageParams m -> f ()
sendNotification (Text -> SServerMethod 'CustomMethod
forall (f :: From) (t :: MethodType). Text -> SMethod 'CustomMethod
SCustomMethod Text
"ghcide/cradle/loaded") (String -> Value
forall a. ToJSON a => a -> Value
toJSON String
cfp)
let progMsg :: Text
progMsg = Text
"Setting up " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (String -> String
takeBaseName (Cradle Void -> String
forall a. Cradle a -> String
cradleRootDir Cradle Void
cradle))
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" (for " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
lfp Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
Either [CradleError] (ComponentOptions, String)
eopts <- Maybe (LanguageContextEnv Config)
-> (LspT
Config IO (Either [CradleError] (ComponentOptions, String))
-> LspT
Config IO (Either [CradleError] (ComponentOptions, String)))
-> IO (Either [CradleError] (ComponentOptions, String))
-> IO (Either [CradleError] (ComponentOptions, String))
forall (m :: * -> *) c a.
Monad m =>
Maybe (LanguageContextEnv c)
-> (LspT c m a -> LspT c m a) -> m a -> m a
mRunLspTCallback Maybe (LanguageContextEnv Config)
lspEnv (Text
-> ProgressCancellable
-> LspT Config IO (Either [CradleError] (ComponentOptions, String))
-> LspT Config IO (Either [CradleError] (ComponentOptions, String))
forall c (m :: * -> *) a.
MonadLsp c m =>
Text -> ProgressCancellable -> m a -> m a
withIndefiniteProgress Text
progMsg ProgressCancellable
NotCancellable) (IO (Either [CradleError] (ComponentOptions, String))
-> IO (Either [CradleError] (ComponentOptions, String)))
-> IO (Either [CradleError] (ComponentOptions, String))
-> IO (Either [CradleError] (ComponentOptions, String))
forall a b. (a -> b) -> a -> b
$
String
-> ((String -> String -> IO ())
-> IO (Either [CradleError] (ComponentOptions, String)))
-> IO (Either [CradleError] (ComponentOptions, String))
forall (m :: * -> *) a.
(MonadMask m, MonadIO m) =>
String -> ((String -> String -> m ()) -> m a) -> m a
withTrace String
"Load cradle" (((String -> String -> IO ())
-> IO (Either [CradleError] (ComponentOptions, String)))
-> IO (Either [CradleError] (ComponentOptions, String)))
-> ((String -> String -> IO ())
-> IO (Either [CradleError] (ComponentOptions, String)))
-> IO (Either [CradleError] (ComponentOptions, String))
forall a b. (a -> b) -> a -> b
$ \String -> String -> IO ()
addTag -> do
String -> String -> IO ()
addTag String
"file" String
lfp
Either [CradleError] (ComponentOptions, String)
res <- Logger
-> Cradle Void
-> String
-> IO (Either [CradleError] (ComponentOptions, String))
forall a.
Show a =>
Logger
-> Cradle a
-> String
-> IO (Either [CradleError] (ComponentOptions, String))
cradleToOptsAndLibDir Logger
logger Cradle Void
cradle String
cfp
String -> String -> IO ()
addTag String
"result" (Either [CradleError] (ComponentOptions, String) -> String
forall a. Show a => a -> String
show Either [CradleError] (ComponentOptions, String)
res)
Either [CradleError] (ComponentOptions, String)
-> IO (Either [CradleError] (ComponentOptions, String))
forall (m :: * -> *) a. Monad m => a -> m a
return Either [CradleError] (ComponentOptions, String)
res
Logger -> Text -> IO ()
logDebug Logger
logger (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String
"Session loading result: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Either [CradleError] (ComponentOptions, String) -> String
forall a. Show a => a -> String
show Either [CradleError] (ComponentOptions, String)
eopts)
case Either [CradleError] (ComponentOptions, String)
eopts of
Right (ComponentOptions
opts, String
libDir) -> do
InstallationCheck
installationCheck <- GhcVersionChecker
ghcVersionChecker String
libDir
case InstallationCheck
installationCheck of
InstallationNotFound{String
$sel:libdir:InstallationChecked :: InstallationCheck -> String
libdir :: String
..} ->
String -> IO (IdeResult HscEnvEq, [String])
forall a. HasCallStack => String -> a
error (String -> IO (IdeResult HscEnvEq, [String]))
-> String -> IO (IdeResult HscEnvEq, [String])
forall a b. (a -> b) -> a -> b
$ String
"GHC installation not found in libdir: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
libdir
InstallationMismatch{String
Version
$sel:compileTime:InstallationChecked :: InstallationCheck -> Version
$sel:runTime:InstallationChecked :: InstallationCheck -> Version
runTime :: Version
compileTime :: Version
libdir :: String
$sel:libdir:InstallationChecked :: InstallationCheck -> String
..} ->
(IdeResult HscEnvEq, [String]) -> IO (IdeResult HscEnvEq, [String])
forall (m :: * -> *) a. Monad m => a -> m a
return (([String
-> PackageSetupException
-> (NormalizedFilePath, ShowDiagnostic, Diagnostic)
renderPackageSetupException String
cfp GhcVersionMismatch :: Version -> Version -> PackageSetupException
GhcVersionMismatch{Version
runTime :: Version
compileTime :: Version
runTime :: Version
compileTime :: Version
..}], Maybe HscEnvEq
forall a. Maybe a
Nothing),[])
InstallationChecked Version
_compileTime Ghc PackageCheckResult
_ghcLibCheck ->
(Maybe String, NormalizedFilePath, ComponentOptions, String)
-> IO (IdeResult HscEnvEq, [String])
session (Maybe String
hieYaml, String -> NormalizedFilePath
toNormalizedFilePath' String
cfp, ComponentOptions
opts, String
libDir)
Left [CradleError]
err -> do
DependencyInfo
dep_info <- [String] -> IO DependencyInfo
getDependencyInfo (Maybe String -> [String]
forall a. Maybe a -> [a]
maybeToList Maybe String
hieYaml)
let ncfp :: NormalizedFilePath
ncfp = String -> NormalizedFilePath
toNormalizedFilePath' String
cfp
let res :: IdeResult HscEnvEq
res = ((CradleError -> (NormalizedFilePath, ShowDiagnostic, Diagnostic))
-> [CradleError]
-> [(NormalizedFilePath, ShowDiagnostic, Diagnostic)]
forall a b. (a -> b) -> [a] -> [b]
map (NormalizedFilePath
-> CradleError -> (NormalizedFilePath, ShowDiagnostic, Diagnostic)
renderCradleError NormalizedFilePath
ncfp) [CradleError]
err, Maybe HscEnvEq
forall a. Maybe a
Nothing)
IO FlagsMap -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO FlagsMap -> IO ()) -> IO FlagsMap -> IO ()
forall a b. (a -> b) -> a -> b
$ Var FlagsMap -> (FlagsMap -> FlagsMap) -> IO FlagsMap
forall a. Var a -> (a -> a) -> IO a
modifyVar' Var FlagsMap
fileToFlags ((FlagsMap -> FlagsMap) -> IO FlagsMap)
-> (FlagsMap -> FlagsMap) -> IO FlagsMap
forall a b. (a -> b) -> a -> b
$
(HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
-> HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
-> HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo))
-> Maybe String
-> HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
-> FlagsMap
-> FlagsMap
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
Map.insertWith HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
-> HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
-> HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
forall k v.
(Eq k, Hashable k) =>
HashMap k v -> HashMap k v -> HashMap k v
HM.union Maybe String
hieYaml (NormalizedFilePath
-> (IdeResult HscEnvEq, DependencyInfo)
-> HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
forall k v. Hashable k => k -> v -> HashMap k v
HM.singleton NormalizedFilePath
ncfp (IdeResult HscEnvEq
res, DependencyInfo
dep_info))
IO FilesMap -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO FilesMap -> IO ()) -> IO FilesMap -> IO ()
forall a b. (a -> b) -> a -> b
$ Var FilesMap -> (FilesMap -> FilesMap) -> IO FilesMap
forall a. Var a -> (a -> a) -> IO a
modifyVar' Var FilesMap
filesMap ((FilesMap -> FilesMap) -> IO FilesMap)
-> (FilesMap -> FilesMap) -> IO FilesMap
forall a b. (a -> b) -> a -> b
$ NormalizedFilePath -> Maybe String -> FilesMap -> FilesMap
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
HM.insert NormalizedFilePath
ncfp Maybe String
hieYaml
(IdeResult HscEnvEq, [String]) -> IO (IdeResult HscEnvEq, [String])
forall (m :: * -> *) a. Monad m => a -> m a
return (IdeResult HscEnvEq
res, [String] -> (String -> [String]) -> Maybe String -> [String]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] String -> [String]
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe String
hieYaml [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ (CradleError -> [String]) -> [CradleError] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap CradleError -> [String]
cradleErrorDependencies [CradleError]
err)
let sessionOpts :: (Maybe FilePath, FilePath)
-> IO (IdeResult HscEnvEq, [FilePath])
sessionOpts :: (Maybe String, String) -> IO (IdeResult HscEnvEq, [String])
sessionOpts (Maybe String
hieYaml, String
file) = do
HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
v <- HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
-> Maybe String
-> FlagsMap
-> HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
forall k v. HashMap k v
HM.empty Maybe String
hieYaml (FlagsMap
-> HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo))
-> IO FlagsMap
-> IO
(HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Var FlagsMap -> IO FlagsMap
forall a. Var a -> IO a
readVar Var FlagsMap
fileToFlags
String
cfp <- String -> IO String
makeAbsolute String
file
case NormalizedFilePath
-> HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
-> Maybe (IdeResult HscEnvEq, DependencyInfo)
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HM.lookup (String -> NormalizedFilePath
toNormalizedFilePath' String
cfp) HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo)
v of
Just (IdeResult HscEnvEq
opts, DependencyInfo
old_di) -> do
Bool
deps_ok <- DependencyInfo -> IO Bool
checkDependencyInfo DependencyInfo
old_di
if Bool -> Bool
not Bool
deps_ok
then do
Var FlagsMap -> (FlagsMap -> IO FlagsMap) -> IO ()
forall a. Var a -> (a -> IO a) -> IO ()
modifyVar_ Var FlagsMap
fileToFlags (IO FlagsMap -> FlagsMap -> IO FlagsMap
forall a b. a -> b -> a
const (FlagsMap -> IO FlagsMap
forall (m :: * -> *) a. Monad m => a -> m a
return FlagsMap
forall k a. Map k a
Map.empty))
Var HieMap -> (HieMap -> IO HieMap) -> IO ()
forall a. Var a -> (a -> IO a) -> IO ()
modifyVar_ Var HieMap
hscEnvs (HieMap -> IO HieMap
forall (m :: * -> *) a. Monad m => a -> m a
return (HieMap -> IO HieMap) -> (HieMap -> HieMap) -> HieMap -> IO HieMap
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((HscEnv, [RawComponentInfo]) -> (HscEnv, [RawComponentInfo]))
-> Maybe String -> HieMap -> HieMap
forall k a. Ord k => (a -> a) -> k -> Map k a -> Map k a
Map.adjust (\(HscEnv
h, [RawComponentInfo]
_) -> (HscEnv
h, [])) Maybe String
hieYaml )
Maybe String -> String -> IO (IdeResult HscEnvEq, [String])
consultCradle Maybe String
hieYaml String
cfp
else (IdeResult HscEnvEq, [String]) -> IO (IdeResult HscEnvEq, [String])
forall (m :: * -> *) a. Monad m => a -> m a
return (IdeResult HscEnvEq
opts, DependencyInfo -> [String]
forall k a. Map k a -> [k]
Map.keys DependencyInfo
old_di)
Maybe (IdeResult HscEnvEq, DependencyInfo)
Nothing -> Maybe String -> String -> IO (IdeResult HscEnvEq, [String])
consultCradle Maybe String
hieYaml String
cfp
let getOptions :: FilePath -> IO (IdeResult HscEnvEq, [FilePath])
getOptions :: String -> IO (IdeResult HscEnvEq, [String])
getOptions String
file = do
NormalizedFilePath
ncfp <- String -> NormalizedFilePath
toNormalizedFilePath' (String -> NormalizedFilePath)
-> IO String -> IO NormalizedFilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO String
makeAbsolute String
file
Maybe (Maybe String)
cachedHieYamlLocation <- NormalizedFilePath -> FilesMap -> Maybe (Maybe String)
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HM.lookup NormalizedFilePath
ncfp (FilesMap -> Maybe (Maybe String))
-> IO FilesMap -> IO (Maybe (Maybe String))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Var FilesMap -> IO FilesMap
forall a. Var a -> IO a
readVar Var FilesMap
filesMap
Maybe String
hieYaml <- String -> IO (Maybe String)
cradleLoc String
file
(Maybe String, String) -> IO (IdeResult HscEnvEq, [String])
sessionOpts (Maybe (Maybe String) -> Maybe String
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join Maybe (Maybe String)
cachedHieYamlLocation Maybe String -> Maybe String -> Maybe String
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Maybe String
hieYaml, String
file) IO (IdeResult HscEnvEq, [String])
-> (PackageSetupException -> IO (IdeResult HscEnvEq, [String]))
-> IO (IdeResult HscEnvEq, [String])
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> (e -> m a) -> m a
`Safe.catch` \PackageSetupException
e ->
(IdeResult HscEnvEq, [String]) -> IO (IdeResult HscEnvEq, [String])
forall (m :: * -> *) a. Monad m => a -> m a
return (([String
-> PackageSetupException
-> (NormalizedFilePath, ShowDiagnostic, Diagnostic)
renderPackageSetupException String
file PackageSetupException
e], Maybe HscEnvEq
forall a. Maybe a
Nothing), [String] -> (String -> [String]) -> Maybe String -> [String]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] String -> [String]
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe String
hieYaml)
(String -> IO (IdeResult HscEnvEq, [String]))
-> Action IdeGhcSession
returnWithVersion ((String -> IO (IdeResult HscEnvEq, [String]))
-> Action IdeGhcSession)
-> (String -> IO (IdeResult HscEnvEq, [String]))
-> Action IdeGhcSession
forall a b. (a -> b) -> a -> b
$ \String
file -> do
(IdeResult HscEnvEq, [String])
opts <- IO (IdeResult HscEnvEq, [String])
-> IO (IdeResult HscEnvEq, [String])
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (IdeResult HscEnvEq, [String])
-> IO (IdeResult HscEnvEq, [String]))
-> IO (IdeResult HscEnvEq, [String])
-> IO (IdeResult HscEnvEq, [String])
forall a b. (a -> b) -> a -> b
$ IO (IO (IdeResult HscEnvEq, [String]))
-> IO (IdeResult HscEnvEq, [String])
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (IO (IO (IdeResult HscEnvEq, [String]))
-> IO (IdeResult HscEnvEq, [String]))
-> IO (IO (IdeResult HscEnvEq, [String]))
-> IO (IdeResult HscEnvEq, [String])
forall a b. (a -> b) -> a -> b
$ IO (IO (IdeResult HscEnvEq, [String]))
-> IO (IO (IdeResult HscEnvEq, [String]))
forall (m :: * -> *) a. MonadMask m => m a -> m a
mask_ (IO (IO (IdeResult HscEnvEq, [String]))
-> IO (IO (IdeResult HscEnvEq, [String])))
-> IO (IO (IdeResult HscEnvEq, [String]))
-> IO (IO (IdeResult HscEnvEq, [String]))
forall a b. (a -> b) -> a -> b
$ Var (Async (IdeResult HscEnvEq, [String]))
-> (Async (IdeResult HscEnvEq, [String])
-> IO
(Async (IdeResult HscEnvEq, [String]),
IO (IdeResult HscEnvEq, [String])))
-> IO (IO (IdeResult HscEnvEq, [String]))
forall a b. Var a -> (a -> IO (a, b)) -> IO b
modifyVar Var (Async (IdeResult HscEnvEq, [String]))
runningCradle ((Async (IdeResult HscEnvEq, [String])
-> IO
(Async (IdeResult HscEnvEq, [String]),
IO (IdeResult HscEnvEq, [String])))
-> IO (IO (IdeResult HscEnvEq, [String])))
-> (Async (IdeResult HscEnvEq, [String])
-> IO
(Async (IdeResult HscEnvEq, [String]),
IO (IdeResult HscEnvEq, [String])))
-> IO (IO (IdeResult HscEnvEq, [String]))
forall a b. (a -> b) -> a -> b
$ \Async (IdeResult HscEnvEq, [String])
as -> do
IO (IdeResult HscEnvEq, [String]) -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO (IdeResult HscEnvEq, [String]) -> IO ())
-> IO (IdeResult HscEnvEq, [String]) -> IO ()
forall a b. (a -> b) -> a -> b
$ Async (IdeResult HscEnvEq, [String])
-> IO (IdeResult HscEnvEq, [String])
forall a. Async a -> IO a
wait Async (IdeResult HscEnvEq, [String])
as
Async (IdeResult HscEnvEq, [String])
as <- IO (IdeResult HscEnvEq, [String])
-> IO (Async (IdeResult HscEnvEq, [String]))
forall a. IO a -> IO (Async a)
async (IO (IdeResult HscEnvEq, [String])
-> IO (Async (IdeResult HscEnvEq, [String])))
-> IO (IdeResult HscEnvEq, [String])
-> IO (Async (IdeResult HscEnvEq, [String]))
forall a b. (a -> b) -> a -> b
$ String -> IO (IdeResult HscEnvEq, [String])
getOptions String
file
(Async (IdeResult HscEnvEq, [String]),
IO (IdeResult HscEnvEq, [String]))
-> IO
(Async (IdeResult HscEnvEq, [String]),
IO (IdeResult HscEnvEq, [String]))
forall (m :: * -> *) a. Monad m => a -> m a
return (Async (IdeResult HscEnvEq, [String])
as, Async (IdeResult HscEnvEq, [String])
-> IO (IdeResult HscEnvEq, [String])
forall a. Async a -> IO a
wait Async (IdeResult HscEnvEq, [String])
as)
(IdeResult HscEnvEq, [String]) -> IO (IdeResult HscEnvEq, [String])
forall (f :: * -> *) a. Applicative f => a -> f a
pure (IdeResult HscEnvEq, [String])
opts
cradleToOptsAndLibDir :: Show a => Logger -> Cradle a -> FilePath
-> IO (Either [CradleError] (ComponentOptions, FilePath))
cradleToOptsAndLibDir :: Logger
-> Cradle a
-> String
-> IO (Either [CradleError] (ComponentOptions, String))
cradleToOptsAndLibDir Logger
logger Cradle a
cradle String
file = do
Logger -> Text -> IO ()
logDebug Logger
logger (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
"Output from setting up the cradle " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Cradle a -> String
forall a. Show a => a -> String
show Cradle a
cradle
CradleLoadResult ComponentOptions
cradleRes <- String -> Cradle a -> IO (CradleLoadResult ComponentOptions)
forall a.
String -> Cradle a -> IO (CradleLoadResult ComponentOptions)
HieBios.getCompilerOptions String
file Cradle a
cradle
case CradleLoadResult ComponentOptions
cradleRes of
CradleSuccess ComponentOptions
r -> do
CradleLoadResult String
libDirRes <- Cradle a -> IO (CradleLoadResult String)
forall a. Cradle a -> IO (CradleLoadResult String)
getRuntimeGhcLibDir Cradle a
cradle
case CradleLoadResult String
libDirRes of
CradleSuccess String
libDir -> Either [CradleError] (ComponentOptions, String)
-> IO (Either [CradleError] (ComponentOptions, String))
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((ComponentOptions, String)
-> Either [CradleError] (ComponentOptions, String)
forall a b. b -> Either a b
Right (ComponentOptions
r, String
libDir))
CradleFail CradleError
err -> Either [CradleError] (ComponentOptions, String)
-> IO (Either [CradleError] (ComponentOptions, String))
forall (m :: * -> *) a. Monad m => a -> m a
return ([CradleError] -> Either [CradleError] (ComponentOptions, String)
forall a b. a -> Either a b
Left [CradleError
err])
CradleLoadResult String
CradleNone -> Either [CradleError] (ComponentOptions, String)
-> IO (Either [CradleError] (ComponentOptions, String))
forall (m :: * -> *) a. Monad m => a -> m a
return ([CradleError] -> Either [CradleError] (ComponentOptions, String)
forall a b. a -> Either a b
Left [])
CradleFail CradleError
err -> Either [CradleError] (ComponentOptions, String)
-> IO (Either [CradleError] (ComponentOptions, String))
forall (m :: * -> *) a. Monad m => a -> m a
return ([CradleError] -> Either [CradleError] (ComponentOptions, String)
forall a b. a -> Either a b
Left [CradleError
err])
CradleLoadResult ComponentOptions
CradleNone -> Either [CradleError] (ComponentOptions, String)
-> IO (Either [CradleError] (ComponentOptions, String))
forall (m :: * -> *) a. Monad m => a -> m a
return ([CradleError] -> Either [CradleError] (ComponentOptions, String)
forall a b. a -> Either a b
Left [])
emptyHscEnv :: IORef NameCache -> FilePath -> IO HscEnv
emptyHscEnv :: IORef NameCache -> String -> IO HscEnv
emptyHscEnv IORef NameCache
nc String
libDir = do
HscEnv
env <- Maybe String -> Ghc HscEnv -> IO HscEnv
forall a. Maybe String -> Ghc a -> IO a
runGhc (String -> Maybe String
forall a. a -> Maybe a
Just String
libDir) Ghc HscEnv
forall (m :: * -> *). GhcMonad m => m HscEnv
getSession
HscEnv -> IO ()
initDynLinker HscEnv
env
HscEnv -> IO HscEnv
forall (f :: * -> *) a. Applicative f => a -> f a
pure (HscEnv -> IO HscEnv) -> HscEnv -> IO HscEnv
forall a b. (a -> b) -> a -> b
$ IORef NameCache -> HscEnv -> HscEnv
setNameCache IORef NameCache
nc (DynFlags -> HscEnv -> HscEnv
hscSetFlags ((HscEnv -> DynFlags
hsc_dflags HscEnv
env){useUnicode :: Bool
useUnicode = Bool
True }) HscEnv
env)
data TargetDetails = TargetDetails
{
TargetDetails -> Target
targetTarget :: !Target,
TargetDetails -> IdeResult HscEnvEq
targetEnv :: !(IdeResult HscEnvEq),
TargetDetails -> DependencyInfo
targetDepends :: !DependencyInfo,
TargetDetails -> [NormalizedFilePath]
targetLocations :: ![NormalizedFilePath]
}
fromTargetId :: [FilePath]
-> [String]
-> TargetId
-> IdeResult HscEnvEq
-> DependencyInfo
-> IO [TargetDetails]
fromTargetId :: [String]
-> [String]
-> TargetId
-> IdeResult HscEnvEq
-> DependencyInfo
-> IO [TargetDetails]
fromTargetId [String]
is [String]
exts (GHC.TargetModule ModuleName
mod) IdeResult HscEnvEq
env DependencyInfo
dep = do
let fps :: [String]
fps = [String
i String -> String -> String
</> ModuleName -> String
moduleNameSlashes ModuleName
mod String -> String -> String
-<.> String
ext String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
boot
| String
ext <- [String]
exts
, String
i <- [String]
is
, String
boot <- [String
"", String
"-boot"]
]
[NormalizedFilePath]
locs <- (String -> IO NormalizedFilePath)
-> [String] -> IO [NormalizedFilePath]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ((String -> NormalizedFilePath)
-> IO String -> IO NormalizedFilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> NormalizedFilePath
toNormalizedFilePath' (IO String -> IO NormalizedFilePath)
-> (String -> IO String) -> String -> IO NormalizedFilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> IO String
makeAbsolute) [String]
fps
[TargetDetails] -> IO [TargetDetails]
forall (m :: * -> *) a. Monad m => a -> m a
return [Target
-> IdeResult HscEnvEq
-> DependencyInfo
-> [NormalizedFilePath]
-> TargetDetails
TargetDetails (ModuleName -> Target
TargetModule ModuleName
mod) IdeResult HscEnvEq
env DependencyInfo
dep [NormalizedFilePath]
locs]
fromTargetId [String]
_ [String]
_ (GHC.TargetFile String
f Maybe Phase
_) IdeResult HscEnvEq
env DependencyInfo
deps = do
NormalizedFilePath
nf <- String -> NormalizedFilePath
toNormalizedFilePath' (String -> NormalizedFilePath)
-> IO String -> IO NormalizedFilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO String
makeAbsolute String
f
[TargetDetails] -> IO [TargetDetails]
forall (m :: * -> *) a. Monad m => a -> m a
return [Target
-> IdeResult HscEnvEq
-> DependencyInfo
-> [NormalizedFilePath]
-> TargetDetails
TargetDetails (NormalizedFilePath -> Target
TargetFile NormalizedFilePath
nf) IdeResult HscEnvEq
env DependencyInfo
deps [NormalizedFilePath
nf]]
toFlagsMap :: TargetDetails -> [(NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))]
toFlagsMap :: TargetDetails
-> [(NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))]
toFlagsMap TargetDetails{[NormalizedFilePath]
IdeResult HscEnvEq
DependencyInfo
Target
targetLocations :: [NormalizedFilePath]
targetDepends :: DependencyInfo
targetEnv :: IdeResult HscEnvEq
targetTarget :: Target
targetLocations :: TargetDetails -> [NormalizedFilePath]
targetDepends :: TargetDetails -> DependencyInfo
targetEnv :: TargetDetails -> IdeResult HscEnvEq
targetTarget :: TargetDetails -> Target
..} =
[ (NormalizedFilePath
l, (IdeResult HscEnvEq
targetEnv, DependencyInfo
targetDepends)) | NormalizedFilePath
l <- [NormalizedFilePath]
targetLocations]
setNameCache :: IORef NameCache -> HscEnv -> HscEnv
setNameCache :: IORef NameCache -> HscEnv -> HscEnv
setNameCache IORef NameCache
nc HscEnv
hsc = HscEnv
hsc { hsc_NC :: IORef NameCache
hsc_NC = IORef NameCache
nc }
newComponentCache
:: Logger
-> [String]
-> Maybe FilePath
-> NormalizedFilePath
-> HscEnv
-> [(UnitId, DynFlags)]
-> ComponentInfo
-> IO ( [TargetDetails], (IdeResult HscEnvEq, DependencyInfo))
newComponentCache :: Logger
-> [String]
-> Maybe String
-> NormalizedFilePath
-> HscEnv
-> [(UnitId, DynFlags)]
-> ComponentInfo
-> IO ([TargetDetails], (IdeResult HscEnvEq, DependencyInfo))
newComponentCache Logger
logger [String]
exts Maybe String
cradlePath NormalizedFilePath
cfp HscEnv
hsc_env [(UnitId, DynFlags)]
uids ComponentInfo
ci = do
let df :: DynFlags
df = ComponentInfo -> DynFlags
componentDynFlags ComponentInfo
ci
let hscEnv' :: HscEnv
hscEnv' = DynFlags -> HscEnv -> HscEnv
hscSetFlags DynFlags
df HscEnv
hsc_env
{ hsc_IC :: InteractiveContext
hsc_IC = (HscEnv -> InteractiveContext
hsc_IC HscEnv
hsc_env) { ic_dflags :: DynFlags
ic_dflags = DynFlags
df } }
let newFunc :: HscEnv -> [(UnitId, DynFlags)] -> IO HscEnvEq
newFunc = (HscEnv -> [(UnitId, DynFlags)] -> IO HscEnvEq)
-> (String -> HscEnv -> [(UnitId, DynFlags)] -> IO HscEnvEq)
-> Maybe String
-> HscEnv
-> [(UnitId, DynFlags)]
-> IO HscEnvEq
forall b a. b -> (a -> b) -> Maybe a -> b
maybe HscEnv -> [(UnitId, DynFlags)] -> IO HscEnvEq
newHscEnvEqPreserveImportPaths String -> HscEnv -> [(UnitId, DynFlags)] -> IO HscEnvEq
newHscEnvEq Maybe String
cradlePath
HscEnvEq
henv <- HscEnv -> [(UnitId, DynFlags)] -> IO HscEnvEq
newFunc HscEnv
hscEnv' [(UnitId, DynFlags)]
uids
let targetEnv :: IdeResult HscEnvEq
targetEnv = ([], HscEnvEq -> Maybe HscEnvEq
forall a. a -> Maybe a
Just HscEnvEq
henv)
targetDepends :: DependencyInfo
targetDepends = ComponentInfo -> DependencyInfo
componentDependencyInfo ComponentInfo
ci
res :: (IdeResult HscEnvEq, DependencyInfo)
res = (IdeResult HscEnvEq
targetEnv, DependencyInfo
targetDepends)
Logger -> Text -> IO ()
logDebug Logger
logger (Text
"New Component Cache HscEnvEq: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack ((IdeResult HscEnvEq, DependencyInfo) -> String
forall a. Show a => a -> String
show (IdeResult HscEnvEq, DependencyInfo)
res))
let mk :: Target -> IO [TargetDetails]
mk Target
t = [String]
-> [String]
-> TargetId
-> IdeResult HscEnvEq
-> DependencyInfo
-> IO [TargetDetails]
fromTargetId (DynFlags -> [String]
importPaths DynFlags
df) [String]
exts (Target -> TargetId
targetId Target
t) IdeResult HscEnvEq
targetEnv DependencyInfo
targetDepends
[TargetDetails]
ctargets <- (Target -> IO [TargetDetails]) -> [Target] -> IO [TargetDetails]
forall (m :: * -> *) a b. Monad m => (a -> m [b]) -> [a] -> m [b]
concatMapM Target -> IO [TargetDetails]
mk (ComponentInfo -> [Target]
componentTargets ComponentInfo
ci)
let special_target :: TargetDetails
special_target = Target
-> IdeResult HscEnvEq
-> DependencyInfo
-> [NormalizedFilePath]
-> TargetDetails
TargetDetails (NormalizedFilePath -> Target
TargetFile NormalizedFilePath
cfp) IdeResult HscEnvEq
targetEnv DependencyInfo
targetDepends [ComponentInfo -> NormalizedFilePath
componentFP ComponentInfo
ci]
([TargetDetails], (IdeResult HscEnvEq, DependencyInfo))
-> IO ([TargetDetails], (IdeResult HscEnvEq, DependencyInfo))
forall (m :: * -> *) a. Monad m => a -> m a
return (TargetDetails
special_targetTargetDetails -> [TargetDetails] -> [TargetDetails]
forall a. a -> [a] -> [a]
:[TargetDetails]
ctargets, (IdeResult HscEnvEq, DependencyInfo)
res)
setCacheDirs :: MonadIO m => Logger -> CacheDirs -> DynFlags -> m DynFlags
setCacheDirs :: Logger -> CacheDirs -> DynFlags -> m DynFlags
setCacheDirs Logger
logger CacheDirs{Maybe String
oCacheDir :: Maybe String
hieCacheDir :: Maybe String
hiCacheDir :: Maybe String
oCacheDir :: CacheDirs -> Maybe String
hieCacheDir :: CacheDirs -> Maybe String
hiCacheDir :: CacheDirs -> Maybe String
..} DynFlags
dflags = do
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Logger -> Text -> IO ()
logInfo Logger
logger (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text
"Using interface files cache dir: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
cacheDir Maybe String
hiCacheDir)
DynFlags -> m DynFlags
forall (f :: * -> *) a. Applicative f => a -> f a
pure (DynFlags -> m DynFlags) -> DynFlags -> m DynFlags
forall a b. (a -> b) -> a -> b
$ DynFlags
dflags
DynFlags -> (DynFlags -> DynFlags) -> DynFlags
forall a b. a -> (a -> b) -> b
& (DynFlags -> DynFlags)
-> (String -> DynFlags -> DynFlags)
-> Maybe String
-> DynFlags
-> DynFlags
forall b a. b -> (a -> b) -> Maybe a -> b
maybe DynFlags -> DynFlags
forall a. a -> a
id String -> DynFlags -> DynFlags
setHiDir Maybe String
hiCacheDir
DynFlags -> (DynFlags -> DynFlags) -> DynFlags
forall a b. a -> (a -> b) -> b
& (DynFlags -> DynFlags)
-> (String -> DynFlags -> DynFlags)
-> Maybe String
-> DynFlags
-> DynFlags
forall b a. b -> (a -> b) -> Maybe a -> b
maybe DynFlags -> DynFlags
forall a. a -> a
id String -> DynFlags -> DynFlags
setHieDir Maybe String
hieCacheDir
DynFlags -> (DynFlags -> DynFlags) -> DynFlags
forall a b. a -> (a -> b) -> b
& (DynFlags -> DynFlags)
-> (String -> DynFlags -> DynFlags)
-> Maybe String
-> DynFlags
-> DynFlags
forall b a. b -> (a -> b) -> Maybe a -> b
maybe DynFlags -> DynFlags
forall a. a -> a
id String -> DynFlags -> DynFlags
setODir Maybe String
oCacheDir
renderCradleError :: NormalizedFilePath -> CradleError -> FileDiagnostic
renderCradleError :: NormalizedFilePath
-> CradleError -> (NormalizedFilePath, ShowDiagnostic, Diagnostic)
renderCradleError NormalizedFilePath
nfp (CradleError [String]
_ ExitCode
_ec [String]
t) =
Maybe Text
-> Maybe DiagnosticSeverity
-> NormalizedFilePath
-> Text
-> (NormalizedFilePath, ShowDiagnostic, Diagnostic)
forall a.
Maybe Text
-> Maybe DiagnosticSeverity
-> a
-> Text
-> (a, ShowDiagnostic, Diagnostic)
ideErrorWithSource (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"cradle") (DiagnosticSeverity -> Maybe DiagnosticSeverity
forall a. a -> Maybe a
Just DiagnosticSeverity
DsError) NormalizedFilePath
nfp ([Text] -> Text
T.unlines ((String -> Text) -> [String] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map String -> Text
T.pack [String]
t))
type DependencyInfo = Map.Map FilePath (Maybe UTCTime)
type HieMap = Map.Map (Maybe FilePath) (HscEnv, [RawComponentInfo])
type FlagsMap = Map.Map (Maybe FilePath) (HM.HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo))
type FilesMap = HM.HashMap NormalizedFilePath (Maybe FilePath)
data RawComponentInfo = RawComponentInfo
{ RawComponentInfo -> UnitId
rawComponentUnitId :: UnitId
, RawComponentInfo -> DynFlags
rawComponentDynFlags :: DynFlags
, RawComponentInfo -> [Target]
rawComponentTargets :: [GHC.Target]
, RawComponentInfo -> NormalizedFilePath
rawComponentFP :: NormalizedFilePath
, RawComponentInfo -> ComponentOptions
rawComponentCOptions :: ComponentOptions
, RawComponentInfo -> DependencyInfo
rawComponentDependencyInfo :: DependencyInfo
}
data ComponentInfo = ComponentInfo
{ ComponentInfo -> UnitId
componentUnitId :: UnitId
, ComponentInfo -> DynFlags
componentDynFlags :: DynFlags
, ComponentInfo -> [UnitId]
_componentInternalUnits :: [UnitId]
, ComponentInfo -> [Target]
componentTargets :: [GHC.Target]
, ComponentInfo -> NormalizedFilePath
componentFP :: NormalizedFilePath
, ComponentInfo -> ComponentOptions
_componentCOptions :: ComponentOptions
, ComponentInfo -> DependencyInfo
componentDependencyInfo :: DependencyInfo
}
checkDependencyInfo :: DependencyInfo -> IO Bool
checkDependencyInfo :: DependencyInfo -> IO Bool
checkDependencyInfo DependencyInfo
old_di = do
DependencyInfo
di <- [String] -> IO DependencyInfo
getDependencyInfo (DependencyInfo -> [String]
forall k a. Map k a -> [k]
Map.keys DependencyInfo
old_di)
Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (DependencyInfo
di DependencyInfo -> DependencyInfo -> Bool
forall a. Eq a => a -> a -> Bool
== DependencyInfo
old_di)
getDependencyInfo :: [FilePath] -> IO DependencyInfo
getDependencyInfo :: [String] -> IO DependencyInfo
getDependencyInfo [String]
fs = [(String, Maybe UTCTime)] -> DependencyInfo
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(String, Maybe UTCTime)] -> DependencyInfo)
-> IO [(String, Maybe UTCTime)] -> IO DependencyInfo
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String -> IO (String, Maybe UTCTime))
-> [String] -> IO [(String, Maybe UTCTime)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM String -> IO (String, Maybe UTCTime)
do_one [String]
fs
where
tryIO :: IO a -> IO (Either IOException a)
tryIO :: IO a -> IO (Either IOException a)
tryIO = IO a -> IO (Either IOException a)
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> m (Either e a)
Safe.try
do_one :: FilePath -> IO (FilePath, Maybe UTCTime)
do_one :: String -> IO (String, Maybe UTCTime)
do_one String
fp = (String
fp,) (Maybe UTCTime -> (String, Maybe UTCTime))
-> (Either IOException UTCTime -> Maybe UTCTime)
-> Either IOException UTCTime
-> (String, Maybe UTCTime)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either IOException UTCTime -> Maybe UTCTime
forall a b. Either a b -> Maybe b
eitherToMaybe (Either IOException UTCTime -> (String, Maybe UTCTime))
-> IO (Either IOException UTCTime) -> IO (String, Maybe UTCTime)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO UTCTime -> IO (Either IOException UTCTime)
forall a. IO a -> IO (Either IOException a)
tryIO (String -> IO UTCTime
getModificationTime String
fp)
removeInplacePackages
:: UnitId
-> [UnitId]
-> DynFlags
-> (DynFlags, [UnitId])
removeInplacePackages :: UnitId -> [UnitId] -> DynFlags -> (DynFlags, [UnitId])
removeInplacePackages UnitId
fake_uid [UnitId]
us DynFlags
df = (UnitId -> DynFlags -> DynFlags
setHomeUnitId_ UnitId
fake_uid (DynFlags -> DynFlags) -> DynFlags -> DynFlags
forall a b. (a -> b) -> a -> b
$
DynFlags
df { packageFlags :: [PackageFlag]
packageFlags = [PackageFlag]
ps }, [UnitId]
uids)
where
([UnitId]
uids, [PackageFlag]
ps) = [UnitId] -> [PackageFlag] -> ([UnitId], [PackageFlag])
Compat.filterInplaceUnits [UnitId]
us (DynFlags -> [PackageFlag]
packageFlags DynFlags
df)
memoIO :: Ord a => (a -> IO b) -> IO (a -> IO b)
memoIO :: (a -> IO b) -> IO (a -> IO b)
memoIO a -> IO b
op = do
Var (Map a (IO b))
ref <- Map a (IO b) -> IO (Var (Map a (IO b)))
forall a. a -> IO (Var a)
newVar Map a (IO b)
forall k a. Map k a
Map.empty
(a -> IO b) -> IO (a -> IO b)
forall (m :: * -> *) a. Monad m => a -> m a
return ((a -> IO b) -> IO (a -> IO b)) -> (a -> IO b) -> IO (a -> IO b)
forall a b. (a -> b) -> a -> b
$ \a
k -> IO (IO b) -> IO b
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (IO (IO b) -> IO b) -> IO (IO b) -> IO b
forall a b. (a -> b) -> a -> b
$ IO (IO b) -> IO (IO b)
forall (m :: * -> *) a. MonadMask m => m a -> m a
mask_ (IO (IO b) -> IO (IO b)) -> IO (IO b) -> IO (IO b)
forall a b. (a -> b) -> a -> b
$ Var (Map a (IO b))
-> (Map a (IO b) -> IO (Map a (IO b), IO b)) -> IO (IO b)
forall a b. Var a -> (a -> IO (a, b)) -> IO b
modifyVar Var (Map a (IO b))
ref ((Map a (IO b) -> IO (Map a (IO b), IO b)) -> IO (IO b))
-> (Map a (IO b) -> IO (Map a (IO b), IO b)) -> IO (IO b)
forall a b. (a -> b) -> a -> b
$ \Map a (IO b)
mp ->
case a -> Map a (IO b) -> Maybe (IO b)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup a
k Map a (IO b)
mp of
Maybe (IO b)
Nothing -> do
IO b
res <- IO b -> IO (IO b)
forall a. IO a -> IO (IO a)
onceFork (IO b -> IO (IO b)) -> IO b -> IO (IO b)
forall a b. (a -> b) -> a -> b
$ a -> IO b
op a
k
(Map a (IO b), IO b) -> IO (Map a (IO b), IO b)
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> IO b -> Map a (IO b) -> Map a (IO b)
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert a
k IO b
res Map a (IO b)
mp, IO b
res)
Just IO b
res -> (Map a (IO b), IO b) -> IO (Map a (IO b), IO b)
forall (m :: * -> *) a. Monad m => a -> m a
return (Map a (IO b)
mp, IO b
res)
setOptions :: GhcMonad m => ComponentOptions -> DynFlags -> m (DynFlags, [GHC.Target])
setOptions :: ComponentOptions -> DynFlags -> m (DynFlags, [Target])
setOptions (ComponentOptions [String]
theOpts String
compRoot [String]
_) DynFlags
dflags = do
(DynFlags
dflags', [Target]
targets') <- [String] -> DynFlags -> m (DynFlags, [Target])
forall (m :: * -> *).
GhcMonad m =>
[String] -> DynFlags -> m (DynFlags, [Target])
addCmdOpts [String]
theOpts DynFlags
dflags
let targets :: [Target]
targets = String -> [Target] -> [Target]
makeTargetsAbsolute String
compRoot [Target]
targets'
let dflags'' :: DynFlags
dflags'' =
DynFlags -> DynFlags
disableWarningsAsErrors (DynFlags -> DynFlags) -> DynFlags -> DynFlags
forall a b. (a -> b) -> a -> b
$
(DynFlags -> GeneralFlag -> DynFlags)
-> GeneralFlag -> DynFlags -> DynFlags
forall a b c. (a -> b -> c) -> b -> a -> c
flip DynFlags -> GeneralFlag -> DynFlags
gopt_unset GeneralFlag
Opt_WriteInterface (DynFlags -> DynFlags) -> DynFlags -> DynFlags
forall a b. (a -> b) -> a -> b
$
DynFlags -> DynFlags
dontWriteHieFiles (DynFlags -> DynFlags) -> DynFlags -> DynFlags
forall a b. (a -> b) -> a -> b
$
DynFlags -> DynFlags
setIgnoreInterfacePragmas (DynFlags -> DynFlags) -> DynFlags -> DynFlags
forall a b. (a -> b) -> a -> b
$
DynFlags -> DynFlags
setBytecodeLinkerOptions (DynFlags -> DynFlags) -> DynFlags -> DynFlags
forall a b. (a -> b) -> a -> b
$
DynFlags -> DynFlags
disableOptimisation (DynFlags -> DynFlags) -> DynFlags -> DynFlags
forall a b. (a -> b) -> a -> b
$
DynFlags -> DynFlags
Compat.setUpTypedHoles (DynFlags -> DynFlags) -> DynFlags -> DynFlags
forall a b. (a -> b) -> a -> b
$
String -> DynFlags -> DynFlags
makeDynFlagsAbsolute String
compRoot DynFlags
dflags'
HscEnv
env <- DynFlags -> HscEnv -> HscEnv
hscSetFlags DynFlags
dflags'' (HscEnv -> HscEnv) -> m HscEnv -> m HscEnv
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m HscEnv
forall (m :: * -> *). GhcMonad m => m HscEnv
getSession
HscEnv
final_env' <- IO HscEnv -> m HscEnv
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO HscEnv -> m HscEnv) -> IO HscEnv -> m HscEnv
forall a b. (a -> b) -> a -> b
$ IO HscEnv -> IO HscEnv
forall a. IO a -> IO a
wrapPackageSetupException (IO HscEnv -> IO HscEnv) -> IO HscEnv -> IO HscEnv
forall a b. (a -> b) -> a -> b
$ HscEnv -> IO HscEnv
Compat.initUnits HscEnv
env
(DynFlags, [Target]) -> m (DynFlags, [Target])
forall (m :: * -> *) a. Monad m => a -> m a
return (HscEnv -> DynFlags
hsc_dflags HscEnv
final_env', [Target]
targets)
setIgnoreInterfacePragmas :: DynFlags -> DynFlags
setIgnoreInterfacePragmas :: DynFlags -> DynFlags
setIgnoreInterfacePragmas DynFlags
df =
DynFlags -> GeneralFlag -> DynFlags
gopt_set (DynFlags -> GeneralFlag -> DynFlags
gopt_set DynFlags
df GeneralFlag
Opt_IgnoreInterfacePragmas) GeneralFlag
Opt_IgnoreOptimChanges
disableOptimisation :: DynFlags -> DynFlags
disableOptimisation :: DynFlags -> DynFlags
disableOptimisation DynFlags
df = Int -> DynFlags -> DynFlags
updOptLevel Int
0 DynFlags
df
setHiDir :: FilePath -> DynFlags -> DynFlags
setHiDir :: String -> DynFlags -> DynFlags
setHiDir String
f DynFlags
d =
DynFlags
d { hiDir :: Maybe String
hiDir = String -> Maybe String
forall a. a -> Maybe a
Just String
f}
setODir :: FilePath -> DynFlags -> DynFlags
setODir :: String -> DynFlags -> DynFlags
setODir String
f DynFlags
d =
DynFlags
d { objectDir :: Maybe String
objectDir = String -> Maybe String
forall a. a -> Maybe a
Just String
f}
getCacheDirsDefault :: String -> [String] -> IO CacheDirs
getCacheDirsDefault :: String -> [String] -> IO CacheDirs
getCacheDirsDefault String
prefix [String]
opts = do
Maybe String
dir <- String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> IO String -> IO (Maybe String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> XdgDirectory -> String -> IO String
getXdgDirectory XdgDirectory
XdgCache (String
cacheDir String -> String -> String
</> String
prefix String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"-" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
opts_hash)
CacheDirs -> IO CacheDirs
forall (m :: * -> *) a. Monad m => a -> m a
return (CacheDirs -> IO CacheDirs) -> CacheDirs -> IO CacheDirs
forall a b. (a -> b) -> a -> b
$ Maybe String -> Maybe String -> Maybe String -> CacheDirs
CacheDirs Maybe String
dir Maybe String
dir Maybe String
dir
where
opts_hash :: String
opts_hash = ByteString -> String
B.unpack (ByteString -> String) -> ByteString -> String
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
B16.encode (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ Ctx -> ByteString
H.finalize (Ctx -> ByteString) -> Ctx -> ByteString
forall a b. (a -> b) -> a -> b
$ Ctx -> [ByteString] -> Ctx
H.updates Ctx
H.init ((String -> ByteString) -> [String] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
map String -> ByteString
B.pack [String]
opts)
cacheDir :: String
cacheDir :: String
cacheDir = String
"ghcide"
implicitCradleWarning :: FilePath -> T.Text
implicitCradleWarning :: String -> Text
implicitCradleWarning String
fp =
Text
"No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
fp Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text
".\n Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).\n"Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text
"You should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error."
data PackageSetupException
= PackageSetupException
{ PackageSetupException -> String
message :: !String
}
| GhcVersionMismatch
{ PackageSetupException -> Version
compileTime :: !Version
, PackageSetupException -> Version
runTime :: !Version
}
| PackageCheckFailed !NotCompatibleReason
deriving (PackageSetupException -> PackageSetupException -> Bool
(PackageSetupException -> PackageSetupException -> Bool)
-> (PackageSetupException -> PackageSetupException -> Bool)
-> Eq PackageSetupException
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PackageSetupException -> PackageSetupException -> Bool
$c/= :: PackageSetupException -> PackageSetupException -> Bool
== :: PackageSetupException -> PackageSetupException -> Bool
$c== :: PackageSetupException -> PackageSetupException -> Bool
Eq, Int -> PackageSetupException -> String -> String
[PackageSetupException] -> String -> String
PackageSetupException -> String
(Int -> PackageSetupException -> String -> String)
-> (PackageSetupException -> String)
-> ([PackageSetupException] -> String -> String)
-> Show PackageSetupException
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [PackageSetupException] -> String -> String
$cshowList :: [PackageSetupException] -> String -> String
show :: PackageSetupException -> String
$cshow :: PackageSetupException -> String
showsPrec :: Int -> PackageSetupException -> String -> String
$cshowsPrec :: Int -> PackageSetupException -> String -> String
Show, Typeable)
instance Exception PackageSetupException
wrapPackageSetupException :: IO a -> IO a
wrapPackageSetupException :: IO a -> IO a
wrapPackageSetupException = (SomeException -> IO a) -> IO a -> IO a
forall (m :: * -> *) a.
MonadCatch m =>
(SomeException -> m a) -> m a -> m a
handleAny ((SomeException -> IO a) -> IO a -> IO a)
-> (SomeException -> IO a) -> IO a -> IO a
forall a b. (a -> b) -> a -> b
$ \case
SomeException
e | Just (PackageSetupException
pkgE :: PackageSetupException) <- SomeException -> Maybe PackageSetupException
forall e. Exception e => SomeException -> Maybe e
fromException SomeException
e -> PackageSetupException -> IO a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO PackageSetupException
pkgE
SomeException
e -> (PackageSetupException -> IO a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO (PackageSetupException -> IO a)
-> (SomeException -> PackageSetupException)
-> SomeException
-> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> PackageSetupException
PackageSetupException (String -> PackageSetupException)
-> (SomeException -> String)
-> SomeException
-> PackageSetupException
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SomeException -> String
forall a. Show a => a -> String
show) SomeException
e
showPackageSetupException :: PackageSetupException -> String
showPackageSetupException :: PackageSetupException -> String
showPackageSetupException GhcVersionMismatch{Version
runTime :: Version
compileTime :: Version
runTime :: PackageSetupException -> Version
compileTime :: PackageSetupException -> Version
..} = [String] -> String
unwords
[String
"ghcide compiled against GHC"
,Version -> String
showVersion Version
compileTime
,String
"but currently using"
,Version -> String
showVersion Version
runTime
,String
"\nThis is unsupported, ghcide must be compiled with the same GHC version as the project."
]
showPackageSetupException PackageSetupException{String
message :: String
message :: PackageSetupException -> String
..} = [String] -> String
unwords
[ String
"ghcide compiled by GHC", Version -> String
showVersion Version
compilerVersion
, String
"failed to load packages:", String
message String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"."
, String
"\nPlease ensure that ghcide is compiled with the same GHC installation as the project."]
showPackageSetupException (PackageCheckFailed PackageVersionMismatch{String
Version
$sel:compileTime:PackageVersionMismatch :: NotCompatibleReason -> Version
$sel:runTime:PackageVersionMismatch :: NotCompatibleReason -> Version
$sel:packageName:PackageVersionMismatch :: NotCompatibleReason -> String
packageName :: String
runTime :: Version
compileTime :: Version
..}) = [String] -> String
unwords
[String
"ghcide compiled with package "
, String
packageName String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"-" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Version -> String
showVersion Version
compileTime
,String
"but project uses package"
, String
packageName String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"-" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Version -> String
showVersion Version
runTime
,String
"\nThis is unsupported, ghcide must be compiled with the same GHC installation as the project."
]
showPackageSetupException (PackageCheckFailed BasePackageAbiMismatch{String
Version
$sel:compileTimeAbi:PackageVersionMismatch :: NotCompatibleReason -> String
$sel:runTimeAbi:PackageVersionMismatch :: NotCompatibleReason -> String
compileTime :: Version
runTimeAbi :: String
compileTimeAbi :: String
$sel:compileTime:PackageVersionMismatch :: NotCompatibleReason -> Version
..}) = [String] -> String
unwords
[String
"ghcide compiled with base-" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Version -> String
showVersion Version
compileTime String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"-" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
compileTimeAbi
,String
"but project uses base-" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Version -> String
showVersion Version
compileTime String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"-" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
runTimeAbi
,String
"\nThis is unsupported, ghcide must be compiled with the same GHC installation as the project."
]
renderPackageSetupException :: FilePath -> PackageSetupException -> (NormalizedFilePath, ShowDiagnostic, Diagnostic)
renderPackageSetupException :: String
-> PackageSetupException
-> (NormalizedFilePath, ShowDiagnostic, Diagnostic)
renderPackageSetupException String
fp PackageSetupException
e =
Maybe Text
-> Maybe DiagnosticSeverity
-> NormalizedFilePath
-> Text
-> (NormalizedFilePath, ShowDiagnostic, Diagnostic)
forall a.
Maybe Text
-> Maybe DiagnosticSeverity
-> a
-> Text
-> (a, ShowDiagnostic, Diagnostic)
ideErrorWithSource (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"cradle") (DiagnosticSeverity -> Maybe DiagnosticSeverity
forall a. a -> Maybe a
Just DiagnosticSeverity
DsError) (String -> NormalizedFilePath
toNormalizedFilePath' String
fp) (String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ PackageSetupException -> String
showPackageSetupException PackageSetupException
e)