-- Copyright (c) 2019 The DAML Authors. All rights reserved.
-- SPDX-License-Identifier: Apache-2.0

{-# LANGUAGE TypeFamilies               #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes #-}

-- | A Shake implementation of the compiler service, built
--   using the "Shaker" abstraction layer for in-memory use.
--
module Development.IDE.Core.Service(
    getIdeOptions, getIdeOptionsIO,
    IdeState, initialise, shutdown,
    runAction,
    writeProfile,
    getDiagnostics, unsafeClearDiagnostics,
    ideLogger,
    updatePositionMapping,
    ) where

import Data.Maybe
import Development.IDE.Types.Options (IdeOptions(..))
import Development.IDE.Core.Debouncer
import           Development.IDE.Core.FileStore  (VFSHandle, fileStoreRules)
import           Development.IDE.Core.FileExists (fileExistsRules)
import           Development.IDE.Core.OfInterest
import Development.IDE.Types.Logger as Logger
import           Development.Shake
import qualified Language.Haskell.LSP.Messages as LSP
import qualified Language.Haskell.LSP.Types as LSP
import qualified Language.Haskell.LSP.Types.Capabilities as LSP

import           Development.IDE.Core.Shake
import Control.Monad



------------------------------------------------------------
-- Exposed API

-- | Initialise the Compiler Service.
initialise :: LSP.ClientCapabilities
           -> Rules ()
           -> IO LSP.LspId
           -> (LSP.FromServerMessage -> IO ())
           -> WithProgressFunc
           -> WithIndefiniteProgressFunc
           -> Logger
           -> Debouncer LSP.NormalizedUri
           -> IdeOptions
           -> VFSHandle
           -> IO IdeState
initialise :: ClientCapabilities
-> Rules ()
-> IO LspId
-> (FromServerMessage -> IO ())
-> WithProgressFunc
-> WithIndefiniteProgressFunc
-> Logger
-> Debouncer NormalizedUri
-> IdeOptions
-> VFSHandle
-> IO IdeState
initialise ClientCapabilities
caps Rules ()
mainRule IO LspId
getLspId FromServerMessage -> IO ()
toDiags WithProgressFunc
wProg WithIndefiniteProgressFunc
wIndefProg Logger
logger Debouncer NormalizedUri
debouncer IdeOptions
options VFSHandle
vfs =
    IO LspId
-> (FromServerMessage -> IO ())
-> WithProgressFunc
-> WithIndefiniteProgressFunc
-> Logger
-> Debouncer NormalizedUri
-> Maybe FilePath
-> IdeReportProgress
-> IdeTesting
-> ShakeOptions
-> Rules ()
-> IO IdeState
shakeOpen
        IO LspId
getLspId
        FromServerMessage -> IO ()
toDiags
        WithProgressFunc
wProg
        WithIndefiniteProgressFunc
wIndefProg
        Logger
logger
        Debouncer NormalizedUri
debouncer
        (IdeOptions -> Maybe FilePath
optShakeProfiling IdeOptions
options)
        (IdeOptions -> IdeReportProgress
optReportProgress IdeOptions
options)
        (IdeOptions -> IdeTesting
optTesting IdeOptions
options)
        ShakeOptions
shakeOptions
          { shakeThreads :: Int
shakeThreads = IdeOptions -> Int
optThreads IdeOptions
options
          , shakeFiles :: FilePath
shakeFiles   = FilePath -> Maybe FilePath -> FilePath
forall a. a -> Maybe a -> a
fromMaybe FilePath
"/dev/null" (IdeOptions -> Maybe FilePath
optShakeFiles IdeOptions
options)
          } (Rules () -> IO IdeState) -> Rules () -> IO IdeState
forall a b. (a -> b) -> a -> b
$ do
            GlobalIdeOptions -> Rules ()
forall a. IsIdeGlobal a => a -> Rules ()
addIdeGlobal (GlobalIdeOptions -> Rules ()) -> GlobalIdeOptions -> Rules ()
forall a b. (a -> b) -> a -> b
$ IdeOptions -> GlobalIdeOptions
GlobalIdeOptions IdeOptions
options
            VFSHandle -> Rules ()
fileStoreRules VFSHandle
vfs
            Rules ()
ofInterestRules
            ClientCapabilities -> VFSHandle -> Rules ()
fileExistsRules ClientCapabilities
caps VFSHandle
vfs
            Rules ()
mainRule

writeProfile :: IdeState -> FilePath -> IO ()
writeProfile :: IdeState -> FilePath -> IO ()
writeProfile = IdeState -> FilePath -> IO ()
shakeProfile

-- | Shutdown the Compiler Service.
shutdown :: IdeState -> IO ()
shutdown :: IdeState -> IO ()
shutdown = IdeState -> IO ()
shakeShut

-- This will return as soon as the result of the action is
-- available.  There might still be other rules running at this point,
-- e.g., the ofInterestRule.
runAction :: String -> IdeState -> Action a -> IO a
runAction :: FilePath -> IdeState -> Action a -> IO a
runAction FilePath
herald IdeState
ide Action a
act =
  IO (IO a) -> IO a
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (IO (IO a) -> IO a) -> IO (IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ ShakeExtras -> DelayedAction a -> IO (IO a)
forall a. ShakeExtras -> DelayedAction a -> IO (IO a)
shakeEnqueue (IdeState -> ShakeExtras
shakeExtras IdeState
ide) (FilePath -> Priority -> Action a -> DelayedAction a
forall a. FilePath -> Priority -> Action a -> DelayedAction a
mkDelayedAction FilePath
herald Priority
Logger.Info Action a
act)