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

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

-- | 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,
    getDiagnostics,
    ideLogger,
    updatePositionMapping,
    ) where

import           Control.Applicative             ((<|>))
import           Development.IDE.Core.Debouncer
import           Development.IDE.Core.FileExists (fileExistsRules)
import           Development.IDE.Core.OfInterest
import           Development.IDE.Graph
import           Development.IDE.Types.Logger    as Logger
import           Development.IDE.Types.Options   (IdeOptions (..))
import           Ide.Plugin.Config
import qualified Language.LSP.Server             as LSP
import qualified Language.LSP.Types              as LSP

import           Control.Monad
import           Development.IDE.Core.Shake
import           Development.IDE.Types.Shake     (WithHieDb)
import           System.Environment              (lookupEnv)


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

-- | Initialise the Compiler Service.
initialise :: Config
           -> Rules ()
           -> Maybe (LSP.LanguageContextEnv Config)
           -> Logger
           -> Debouncer LSP.NormalizedUri
           -> IdeOptions
           -> VFSHandle
           -> WithHieDb
           -> IndexQueue
           -> IO IdeState
initialise :: Config
-> Rules ()
-> Maybe (LanguageContextEnv Config)
-> Logger
-> Debouncer NormalizedUri
-> IdeOptions
-> VFSHandle
-> WithHieDb
-> IndexQueue
-> IO IdeState
initialise Config
defaultConfig Rules ()
mainRule Maybe (LanguageContextEnv Config)
lspEnv Logger
logger Debouncer NormalizedUri
debouncer IdeOptions
options VFSHandle
vfs WithHieDb
withHieDb IndexQueue
hiedbChan = do
    Maybe FilePath
shakeProfiling <- do
        let fromConf :: Maybe FilePath
fromConf = IdeOptions -> Maybe FilePath
optShakeProfiling IdeOptions
options
        Maybe FilePath
fromEnv <- FilePath -> IO (Maybe FilePath)
lookupEnv FilePath
"GHCIDE_BUILD_PROFILING"
        Maybe FilePath -> IO (Maybe FilePath)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe FilePath -> IO (Maybe FilePath))
-> Maybe FilePath -> IO (Maybe FilePath)
forall a b. (a -> b) -> a -> b
$ Maybe FilePath
fromConf Maybe FilePath -> Maybe FilePath -> Maybe FilePath
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Maybe FilePath
fromEnv
    Maybe (LanguageContextEnv Config)
-> Config
-> Logger
-> Debouncer NormalizedUri
-> Maybe FilePath
-> IdeReportProgress
-> IdeTesting
-> WithHieDb
-> IndexQueue
-> VFSHandle
-> ShakeOptions
-> Rules ()
-> IO IdeState
shakeOpen
        Maybe (LanguageContextEnv Config)
lspEnv
        Config
defaultConfig
        Logger
logger
        Debouncer NormalizedUri
debouncer
        Maybe FilePath
shakeProfiling
        (IdeOptions -> IdeReportProgress
optReportProgress IdeOptions
options)
        (IdeOptions -> IdeTesting
optTesting IdeOptions
options)
        WithHieDb
withHieDb
        IndexQueue
hiedbChan
        VFSHandle
vfs
        (IdeOptions -> ShakeOptions
optShakeOptions 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
            Rules ()
ofInterestRules
            Maybe (LanguageContextEnv Config) -> VFSHandle -> Rules ()
fileExistsRules Maybe (LanguageContextEnv Config)
lspEnv VFSHandle
vfs
            Rules ()
mainRule

-- | 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)