on debugging help sign in
100 lines 3.4 kB history raw
1-- Copyright (c) 2019 The DAML Authors. All rights reserved.
2-- SPDX-License-Identifier: Apache-2.0
4{-# LANGUAGE TypeFamilies #-}
5{-# LANGUAGE FlexibleInstances #-}
7-- | A Shake implementation of the compiler service, built
8-- using the "Shaker" abstraction layer for in-memory use.
9--
10module Development.IDE.Core.Service(
11 getIdeOptions,
12 IdeState, initialise, shutdown,
13 runAction,
14 runActionSync,
15 writeProfile,
16 getDiagnostics, unsafeClearDiagnostics,
17 ideLogger,
18 updatePositionMapping,
19 ) where
21import Control.Concurrent.Extra
22import Control.Concurrent.Async
23import Data.Maybe
24import Development.IDE.Types.Options (IdeOptions(..))
25import Control.Monad
26import Development.IDE.Core.FileStore
27import Development.IDE.Core.OfInterest
28import Development.IDE.Types.Logger
29import Development.Shake
30import Data.Either.Extra
31import qualified Language.Haskell.LSP.Messages as LSP
32import qualified Language.Haskell.LSP.Types as LSP
34import Development.IDE.Core.Shake
38newtype GlobalIdeOptions = GlobalIdeOptions IdeOptions
39instance IsIdeGlobal GlobalIdeOptions
41------------------------------------------------------------
42-- Exposed API
44-- | Initialise the Compiler Service.
45initialise :: Rules ()
46 -> IO LSP.LspId
47 -> (LSP.FromServerMessage -> IO ())
48 -> Logger
49 -> IdeOptions
50 -> VFSHandle
51 -> IO IdeState
52initialise mainRule getLspId toDiags logger options vfs =
53 shakeOpen
54 getLspId
55 toDiags
56 logger
57 (optShakeProfiling options)
58 (optReportProgress options)
59 shakeOptions
60 { shakeThreads = optThreads options
61 , shakeFiles = fromMaybe "/dev/null" (optShakeFiles options)
62 } $ do
63 addIdeGlobal $ GlobalIdeOptions options
64 fileStoreRules vfs
65 ofInterestRules
66 mainRule
68writeProfile :: IdeState -> FilePath -> IO ()
69writeProfile = shakeProfile
71-- | Shutdown the Compiler Service.
72shutdown :: IdeState -> IO ()
73shutdown = shakeShut
75-- This will return as soon as the result of the action is
76-- available. There might still be other rules running at this point,
77-- e.g., the ofInterestRule.
78runAction :: IdeState -> Action a -> IO a
79runAction ide action = do
80 bar <- newBarrier
81 res <- shakeRun ide [do v <- action; liftIO $ signalBarrier bar v; return v]
82 -- shakeRun might throw an exception (either through action or a default rule),
83 -- in which case action may not complete successfully, and signalBarrier might not be called.
84 -- Therefore we wait for either res (which propagates the exception) or the barrier.
85 -- Importantly, if the barrier does finish, cancelling res only kills waiting for the result,
86 -- it doesn't kill the actual work
87 fmap fromEither $ race (head <$> res) $ waitBarrier bar
90-- | `runActionSync` is similar to `runAction` but it will
91-- wait for all rules (so in particular the `ofInterestRule`) to
92-- finish running. This is mainly useful in tests, where you want
93-- to wait for all rules to fire so you can check diagnostics.
94runActionSync :: IdeState -> Action a -> IO a
95runActionSync s act = fmap head $ join $ shakeRun s [act]
97getIdeOptions :: Action IdeOptions
98getIdeOptions = do
99 GlobalIdeOptions x <- getIdeGlobalAction
100 return x