@@ -12,18 +12,15 @@ module Main(main) where
12
12
13
13
import Arguments
14
14
import Control.Concurrent.Extra
15
- import Control.DeepSeq (NFData )
16
15
import Control.Exception
17
16
import Control.Monad.Extra
18
17
import Control.Monad.IO.Class
19
18
import qualified Crypto.Hash.SHA1 as H
20
- import Data.Binary (Binary )
21
19
import Data.ByteString.Base16
22
20
import qualified Data.ByteString.Char8 as B
23
21
import Data.Default
24
- import Data.Dynamic ( Typeable )
22
+ import Data.Functor ( (<&>) )
25
23
import qualified Data.HashSet as HashSet
26
- import Data.Hashable (Hashable )
27
24
import Data.List.Extra
28
25
import qualified Data.Map.Strict as Map
29
26
import Data.Maybe
@@ -46,10 +43,9 @@ import Development.IDE.Types.Diagnostics
46
43
import Development.IDE.Types.Location
47
44
import Development.IDE.Types.Logger
48
45
import Development.IDE.Types.Options
49
- import Development.Shake (Action , RuleResult , Rules , action , doesFileExist , need )
46
+ import Development.Shake (Action , Rules , action , doesFileExist , doesDirectoryExist , need )
50
47
import DynFlags
51
48
import GHC hiding (def )
52
- import GHC.Generics (Generic )
53
49
-- import qualified GHC.Paths
54
50
import HIE.Bios
55
51
import HIE.Bios.Cradle
@@ -63,6 +59,7 @@ import Language.Haskell.LSP.Types (LspId(IdInt))
63
59
import qualified Language.Haskell.LSP.Core as LSP
64
60
import Linker
65
61
-- import Paths_haskell_language_server
62
+ import RuleTypes
66
63
import qualified System.Directory.Extra as IO
67
64
-- import System.Environment
68
65
import System.Exit
@@ -152,7 +149,7 @@ main = do
152
149
, optShakeProfiling = argsShakeProfiling
153
150
}
154
151
debouncer <- newAsyncDebouncer
155
- initialise caps (loadGhcSessionIO >> mainRule >> pluginRules plugins >> action kick)
152
+ initialise caps (cradleRules >> mainRule >> pluginRules plugins >> action kick)
156
153
getLspId event (logger minBound ) debouncer options vfs
157
154
else do
158
155
putStrLn $ " (haskell-language-server)Ghcide setup tester in " ++ dir ++ " ."
@@ -189,7 +186,7 @@ main = do
189
186
let options =
190
187
(defaultIdeOptions $ return $ return . grab)
191
188
{ optShakeProfiling = argsShakeProfiling }
192
- ide <- initialise def (loadGhcSessionIO >> mainRule) (pure $ IdInt 0 ) (showEvent lock) (logger Info ) noopDebouncer options vfs
189
+ ide <- initialise def (cradleRules >> mainRule) (pure $ IdInt 0 ) (showEvent lock) (logger Info ) noopDebouncer options vfs
193
190
194
191
putStrLn " \n Step 6/6: Type checking the files"
195
192
setFilesOfInterest ide $ HashSet. fromList $ map toNormalizedFilePath files
@@ -203,6 +200,10 @@ main = do
203
200
204
201
unless (null failed) exitFailure
205
202
203
+ cradleRules :: Rules ()
204
+ cradleRules = do
205
+ loadGhcSessionIO
206
+ cradleToSession
206
207
207
208
expandFiles :: [FilePath ] -> IO [FilePath ]
208
209
expandFiles = concatMapM $ \ x -> do
@@ -230,19 +231,6 @@ showEvent lock (EventFileDiagnostics (toNormalizedFilePath -> file) diags) =
230
231
showEvent lock e = withLock lock $ print e
231
232
232
233
233
- -- Rule type for caching GHC sessions.
234
- type instance RuleResult GetHscEnv = HscEnvEq
235
-
236
- data GetHscEnv = GetHscEnv
237
- { hscenvOptions :: [String ] -- componentOptions from hie-bios
238
- , hscenvDependencies :: [FilePath ] -- componentDependencies from hie-bios
239
- }
240
- deriving (Eq , Show , Typeable , Generic )
241
- instance Hashable GetHscEnv
242
- instance NFData GetHscEnv
243
- instance Binary GetHscEnv
244
-
245
-
246
234
loadGhcSessionIO :: Rules ()
247
235
loadGhcSessionIO =
248
236
-- This rule is for caching the GHC session. E.g., even when the cabal file
@@ -255,6 +243,7 @@ loadGhcSessionIO =
255
243
getComponentOptions :: Cradle a -> IO ComponentOptions
256
244
getComponentOptions cradle = do
257
245
let showLine s = putStrLn (" > " ++ s)
246
+ -- WARNING 'runCradle is very expensive and must be called as few times as possible
258
247
cradleRes <- runCradle (cradleOptsProg cradle) showLine " "
259
248
case cradleRes of
260
249
CradleSuccess r -> pure r
@@ -310,8 +299,14 @@ setHiDir f d =
310
299
-- override user settings to avoid conflicts leading to recompilation
311
300
d { hiDir = Just f}
312
301
313
- cradleToSession :: Maybe FilePath -> Cradle a -> Action HscEnvEq
314
- cradleToSession mbYaml cradle = do
302
+ cradleToSession :: Rules ()
303
+ cradleToSession = define $ \ LoadCradle nfp -> do
304
+ let f = fromNormalizedFilePath nfp
305
+
306
+ -- If the path points to a directory, load the implicit cradle
307
+ mbYaml <- doesDirectoryExist f <&> \ isDir -> if isDir then Nothing else Just f
308
+ cradle <- liftIO $ maybe (loadImplicitCradle $ addTrailingPathSeparator f) loadCradle mbYaml
309
+
315
310
cmpOpts <- liftIO $ getComponentOptions cradle
316
311
let opts = componentOptions cmpOpts
317
312
deps = componentDependencies cmpOpts
@@ -321,7 +316,7 @@ cradleToSession mbYaml cradle = do
321
316
_ -> deps
322
317
existingDeps <- filterM doesFileExist deps'
323
318
need existingDeps
324
- useNoFile_ $ GetHscEnv opts deps
319
+ ( [] ,) . pure <$> useNoFile_ ( GetHscEnv opts deps)
325
320
326
321
327
322
loadSession :: FilePath -> Action (FilePath -> Action HscEnvEq )
@@ -335,8 +330,9 @@ loadSession dir = liftIO $ do
335
330
return $ normalise <$> res'
336
331
let session :: Maybe FilePath -> Action HscEnvEq
337
332
session file = do
338
- c <- liftIO $ maybe (loadImplicitCradle $ addTrailingPathSeparator dir) loadCradle file
339
- cradleToSession file c
333
+ -- In the absence of a cradle file, just pass the directory from where to calculate an implicit cradle
334
+ let cradle = toNormalizedFilePath $ fromMaybe dir file
335
+ use_ LoadCradle cradle
340
336
return $ \ file -> session =<< liftIO (cradleLoc file)
341
337
342
338
0 commit comments