Skip to content

Commit add70e4

Browse files
committed
Update to use mpickering ghcide from wip/multi-rebase
haskell/ghcide#522
1 parent 1456333 commit add70e4

File tree

9 files changed

+105
-42
lines changed

9 files changed

+105
-42
lines changed

cabal.project

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ packages:
44

55
source-repository-package
66
type: git
7-
location: https://github.com/jneira/cabal-helper.git
8-
tag: ffb1f57a5ffc6b7ac3c46a9974c4420a6d2bb9b2
7+
location: https://github.com/DanielG/cabal-helper.git
8+
tag: a18bbb2af92e9b4337e7f930cb80754f2408bcfd
99

1010
tests: true
1111
documentation: false

exe/Main.hs

Lines changed: 85 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
-- Copyright (c) 2019 The DAML Authors. All rights reserved.
22
-- SPDX-License-Identifier: Apache-2.0
3+
{-# LANGUAGE CPP #-} -- To get precise GHC version
4+
{-# LANGUAGE TemplateHaskell #-}
35
{-# OPTIONS_GHC -Wno-dodgy-imports #-} -- GHC no longer exports def in GHC 8.6 and above
46
{-# LANGUAGE DeriveGeneric #-}
57
{-# LANGUAGE OverloadedStrings #-}
@@ -28,6 +30,7 @@ import qualified Data.Map.Strict as Map
2830
import Data.Maybe
2931
import qualified Data.Text as T
3032
import qualified Data.Text.IO as T
33+
import Data.Time.Clock (UTCTime)
3134
-- import Data.Version
3235
-- import Development.GitRev
3336
import Development.IDE.Core.Debouncer
@@ -50,7 +53,7 @@ import DynFlags (gopt_set, gopt_unset,
5053
updOptLevel)
5154
import DynFlags (PackageFlag(..), PackageArg(..))
5255
import GHC hiding (def)
53-
-- import qualified GHC.Paths
56+
import GHC.Check (runTimeVersion, compileTimeVersionFromLibdir)
5457
-- import GhcMonad
5558
import HIE.Bios.Cradle
5659
import HIE.Bios.Environment (addCmdOpts)
@@ -243,10 +246,10 @@ showEvent lock (EventFileDiagnostics (toNormalizedFilePath' -> file) diags) =
243246
showEvent lock e = withLock lock $ print e
244247

245248

246-
cradleToSessionOpts :: Lock -> Cradle a -> FilePath -> IO ComponentOptions
247-
cradleToSessionOpts lock cradle file = do
249+
cradleToSessionOpts :: Cradle a -> FilePath -> IO ComponentOptions
250+
cradleToSessionOpts cradle file = do
248251
let showLine s = putStrLn ("> " ++ s)
249-
cradleRes <- withLock lock $ mask $ \_ -> runCradle (cradleOptsProg cradle) showLine file
252+
cradleRes <- runCradle (cradleOptsProg cradle) showLine file
250253
opts <- case cradleRes of
251254
CradleSuccess r -> pure r
252255
CradleFail err -> throwIO err
@@ -271,7 +274,7 @@ targetToFile :: [FilePath] -> TargetId -> IO [NormalizedFilePath]
271274
targetToFile is (TargetModule mod) = do
272275
let fps = [i </> (moduleNameSlashes mod) -<.> ext | ext <- exts, i <- is ]
273276
exts = ["hs", "hs-boot", "lhs"]
274-
mapM (fmap (toNormalizedFilePath') . canonicalizePath) fps
277+
mapM (fmap toNormalizedFilePath' . canonicalizePath) fps
275278
targetToFile _ (TargetFile f _) = do
276279
f' <- canonicalizePath f
277280
return [(toNormalizedFilePath' f')]
@@ -288,6 +291,7 @@ loadSession dir = liftIO $ do
288291
hscEnvs <- newVar Map.empty
289292
-- Mapping from a filepath to HscEnv
290293
fileToFlags <- newVar Map.empty
294+
291295
-- This caches the mapping from Mod.hs -> hie.yaml
292296
cradleLoc <- memoIO $ \v -> do
293297
res <- findCradle v
@@ -301,11 +305,12 @@ loadSession dir = liftIO $ do
301305
-- If the hieYaml file already has an HscEnv, the new component is
302306
-- combined with the components in the old HscEnv into a new HscEnv
303307
-- which contains both.
304-
packageSetup <- return $ \(hieYaml, opts) -> do
308+
packageSetup <- return $ \(hieYaml, cfp, opts) -> do
305309
-- Parse DynFlags for the newly discovered component
306310
hscEnv <- emptyHscEnv
307311
(df, targets) <- evalGhcEnv hscEnv $ do
308312
setOptions opts (hsc_dflags hscEnv)
313+
dep_info <- getDependencyInfo (componentDependencies opts)
309314
-- Now lookup to see whether we are combining with an exisiting HscEnv
310315
-- or making a new one. The lookup returns the HscEnv and a list of
311316
-- information about other components loaded into the HscEnv
@@ -318,13 +323,13 @@ loadSession dir = liftIO $ do
318323
-- We will modify the unitId and DynFlags used for
319324
-- compilation but these are the true source of
320325
-- information.
321-
new_deps = (thisInstalledUnitId df, df, targets) : maybe [] snd oldDeps
326+
new_deps = (thisInstalledUnitId df, df, targets, cfp, dep_info) : maybe [] snd oldDeps
322327
-- Get all the unit-ids for things in this component
323-
inplace = map (\(a, _, _) -> a) new_deps
328+
inplace = map (\(a, _, _, _, _) -> a) new_deps
324329
-- Remove all inplace dependencies from package flags for
325330
-- components in this HscEnv
326-
rearrange (uid, (df, uids), ts) = (uid, (df, uids, ts))
327-
do_one (uid,df, ts) = rearrange (uid, removeInplacePackages inplace df, ts)
331+
rearrange (uid, (df, uids), ts, cfp, di) = (uid, (df, uids, ts, cfp, di))
332+
do_one (uid,df, ts, cfp, di) = rearrange (uid, removeInplacePackages inplace df, ts, cfp, di)
328333
-- All deps, but without any packages which are also loaded
329334
-- into memory
330335
new_deps' = map do_one new_deps
@@ -352,62 +357,106 @@ loadSession dir = liftIO $ do
352357
pure (Map.insert hieYaml (newHscEnv, new_deps) m, (newHscEnv, head new_deps', tail new_deps'))
353358

354359

355-
session <- return $ \(hieYaml, opts) -> do
356-
(hscEnv, new, old_deps) <- packageSetup (hieYaml, opts)
360+
session <- return $ \(hieYaml, cfp, opts) -> do
361+
(hscEnv, new, old_deps) <- packageSetup (hieYaml, cfp, opts)
357362
-- TODO Handle the case where there is no hie.yaml
358363
-- Make a map from unit-id to DynFlags, this is used when trying to
359364
-- resolve imports.
360-
let uids = map (\(iuid, (df, _uis, _targets)) -> (iuid, df)) (new : old_deps)
365+
let uids = map (\(iuid, (df, _uis, _targets, _cfp, _di)) -> (iuid, df)) (new : old_deps)
361366

362367
-- For each component, now make a new HscEnvEq which contains the
363368
-- HscEnv for the hie.yaml file but the DynFlags for that component
364369
--
365370
-- Then look at the targets for each component and create a map
366371
-- from FilePath to the HscEnv
367-
let new_cache (_iuid, (df, _uis, targets)) = do
372+
let new_cache (_iuid, (df, _uis, targets, cfp, di)) = do
368373
let hscEnv' = hscEnv { hsc_dflags = df
369374
, hsc_IC = (hsc_IC hscEnv) { ic_dflags = df } }
370375

371-
res <- newHscEnvEq hscEnv' uids
376+
versionMismatch <- evalGhcEnv hscEnv' checkGhcVersion
377+
henv <- case versionMismatch of
378+
Just mismatch -> return mismatch
379+
Nothing -> newHscEnvEq hscEnv' uids
380+
let res = (henv, di)
381+
print res
372382

373383
let is = importPaths df
374384
ctargets <- concatMapM (targetToFile is . targetId) targets
385+
-- A special target for the file which caused this wonderful
386+
-- component to be created.
387+
let special_target = (cfp, res)
375388
--pprTraceM "TARGETS" (ppr (map (text . show) ctargets))
376389
let xs = map (,res) ctargets
377-
return (xs, res)
390+
return (special_target:xs, res)
378391

379392
-- New HscEnv for the component in question
380393
(cs, res) <- new_cache new
381394
-- Modified cache targets for everything else in the hie.yaml file
382395
-- which now uses the same EPS and so on
383396
cached_targets <- concatMapM (fmap fst . new_cache) old_deps
384397
modifyVar_ fileToFlags $ \var -> do
385-
pure $ Map.insert hieYaml (HM.fromList (cs ++ cached_targets))var
398+
pure $ Map.insert hieYaml (HM.fromList (cs ++ cached_targets)) var
399+
386400
return res
387401

388402
lock <- newLock
389403
cradle_lock <- newLock
390404

391405
-- This caches the mapping from hie.yaml + Mod.hs -> [String]
392406
sessionOpts <- return $ \(hieYaml, file) -> do
407+
408+
393409
fm <- readVar fileToFlags
394410
let mv = Map.lookup hieYaml fm
395411
let v = fromMaybe HM.empty mv
396412
cfp <- liftIO $ canonicalizePath file
413+
case HM.lookup (toNormalizedFilePath' cfp) v of
414+
Just (_, old_di) -> do
415+
deps_ok <- checkDependencyInfo old_di
416+
unless deps_ok $ do
417+
modifyVar_ fileToFlags (const (return Map.empty))
418+
-- Keep the same name cache
419+
modifyVar_ hscEnvs (return . Map.adjust (\(h, _) -> (h, [])) hieYaml )
420+
Nothing -> return ()
397421
-- We sort so exact matches come first.
398422
case HM.lookup (toNormalizedFilePath' cfp) v of
399423
Just opts -> do
400424
--putStrLn $ "Cached component of " <> show file
401-
pure opts
425+
pure (fst opts)
402426
Nothing-> do
403-
putStrLn $ "Shelling out to cabal " <> show file
404-
cradle <- maybe (loadImplicitCradle $ addTrailingPathSeparator dir) loadCradle hieYaml
405-
opts <- cradleToSessionOpts cradle_lock cradle file
406-
print opts
407-
session (hieYaml, opts)
408-
return $ \file -> liftIO $ withLock lock $ do
409-
hieYaml <- cradleLoc file
410-
sessionOpts (hieYaml, file)
427+
finished_barrier <- newBarrier
428+
-- fork a new thread here which won't be killed by shake
429+
-- throwing an async exception
430+
void $ forkIO $ withLock cradle_lock $ do
431+
putStrLn $ "Shelling out to cabal " <> show file
432+
cradle <- maybe (loadImplicitCradle $ addTrailingPathSeparator dir) loadCradle hieYaml
433+
opts <- cradleToSessionOpts cradle cfp
434+
print opts
435+
res <- fst <$> session (hieYaml, toNormalizedFilePath' cfp, opts)
436+
signalBarrier finished_barrier res
437+
waitBarrier finished_barrier
438+
return $ \file -> liftIO $ mask_ $ withLock lock $ do
439+
hieYaml <- cradleLoc file
440+
sessionOpts (hieYaml, file)
441+
442+
checkDependencyInfo :: Map.Map FilePath (Maybe UTCTime) -> IO Bool
443+
checkDependencyInfo old_di = do
444+
di <- getDependencyInfo (Map.keys old_di)
445+
return (di == old_di)
446+
447+
448+
449+
getDependencyInfo :: [FilePath] -> IO (Map.Map FilePath (Maybe UTCTime))
450+
getDependencyInfo fs = Map.fromList <$> mapM do_one fs
451+
452+
where
453+
do_one fp = do
454+
exists <- IO.doesFileExist fp
455+
if exists
456+
then do
457+
mtime <- getModificationTime fp
458+
return (fp, Just mtime)
459+
else return (fp, Nothing)
411460

412461
-- This function removes all the -package flags which refer to packages we
413462
-- are going to deal with ourselves. For example, if a executable depends
@@ -497,3 +546,13 @@ getCacheDir opts = IO.getXdgDirectory IO.XdgCache (cacheDir </> opts_hash)
497546
-- Prefix for the cache path
498547
cacheDir :: String
499548
cacheDir = "ghcide"
549+
550+
compileTimeGhcVersion :: Version
551+
compileTimeGhcVersion = $$(compileTimeVersionFromLibdir getLibdir)
552+
553+
checkGhcVersion :: Ghc (Maybe HscEnvEq)
554+
checkGhcVersion = do
555+
v <- runTimeVersion
556+
return $ if v == Just compileTimeGhcVersion
557+
then Nothing
558+
else Just GhcVersionMismatch {compileTime = compileTimeGhcVersion, runTime = v}

haskell-language-server.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ executable haskell-language-server
133133
-- which works for now.
134134
, ghc
135135
--------------------------------------------------------------
136+
, ghc-check
136137
, ghc-paths
137138
, ghcide
138139
, gitrev
@@ -144,6 +145,7 @@ executable haskell-language-server
144145
, optparse-applicative
145146
, shake >= 0.17.5
146147
, text
148+
, time
147149
, unordered-containers
148150
default-language: Haskell2010
149151

stack-8.6.4.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ extra-deps:
99
- butcher-1.3.2.1
1010
- bytestring-trie-0.2.5.0
1111
# - cabal-helper-1.0.0.0
12-
- github: jneira/cabal-helper
13-
commit: ffb1f57a5ffc6b7ac3c46a9974c4420a6d2bb9b2
12+
- github: DanielG/cabal-helper
13+
commit: a18bbb2af92e9b4337e7f930cb80754f2408bcfd
1414
- cabal-plan-0.5.0.0
1515
- constrained-dynamic-0.1.0.0
1616
# - ghcide-0.1.0
@@ -30,7 +30,7 @@ extra-deps:
3030
- hlint-2.2.8
3131
- hoogle-5.0.17.11
3232
- hsimport-0.11.0
33-
- lsp-test-0.10.1.0
33+
- lsp-test-0.10.2.0
3434
- monad-dijkstra-0.1.1.2
3535
- monad-memo-0.4.1
3636
- multistate-0.8.0.1

stack-8.6.5.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ extra-deps:
88
- ansi-terminal-0.10.2
99
- base-compat-0.11.0
1010
# - cabal-helper-1.0.0.0
11-
- github: jneira/cabal-helper
12-
commit: ffb1f57a5ffc6b7ac3c46a9974c4420a6d2bb9b2
11+
- github: DanielG/cabal-helper
12+
commit: a18bbb2af92e9b4337e7f930cb80754f2408bcfd
1313
- cabal-plan-0.6.2.0
1414
- clock-0.7.2
1515
- floskell-0.10.2
@@ -22,7 +22,7 @@ extra-deps:
2222
- haskell-lsp-types-0.21.0.0
2323
- hie-bios-0.4.0
2424
- indexed-profunctors-0.1
25-
- lsp-test-0.10.1.0
25+
- lsp-test-0.10.2.0
2626
- monad-dijkstra-0.1.1.2
2727
- optics-core-0.2
2828
- optparse-applicative-0.15.1.0

stack-8.8.2.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ extra-deps:
88
- apply-refact-0.7.0.0
99
- bytestring-trie-0.2.5.0
1010
# - cabal-helper-1.0.0.0
11-
- github: jneira/cabal-helper
12-
commit: ffb1f57a5ffc6b7ac3c46a9974c4420a6d2bb9b2
11+
- github: DanielG/cabal-helper
12+
commit: a18bbb2af92e9b4337e7f930cb80754f2408bcfd
1313
- clock-0.7.2
1414
- constrained-dynamic-0.1.0.0
1515
- floskell-0.10.2
@@ -25,6 +25,7 @@ extra-deps:
2525
- hoogle-5.0.17.11
2626
- hsimport-0.11.0
2727
- ilist-0.3.1.0
28+
- lsp-test-0.10.2.0
2829
- monad-dijkstra-0.1.1.2
2930
- semigroups-0.18.5
3031
- temporary-1.2.1.1

stack-8.8.3.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ extra-deps:
88
- apply-refact-0.7.0.0
99
- bytestring-trie-0.2.5.0
1010
# - cabal-helper-1.0.0.0
11-
- github: jneira/cabal-helper
12-
commit: ffb1f57a5ffc6b7ac3c46a9974c4420a6d2bb9b2
11+
- github: DanielG/cabal-helper
12+
commit: a18bbb2af92e9b4337e7f930cb80754f2408bcfd
1313
- clock-0.7.2
1414
- constrained-dynamic-0.1.0.0
1515
- floskell-0.10.2
@@ -25,6 +25,7 @@ extra-deps:
2525
- hoogle-5.0.17.11
2626
- hsimport-0.11.0
2727
- ilist-0.3.1.0
28+
- lsp-test-0.10.2.0
2829
- monad-dijkstra-0.1.1.2
2930
- semigroups-0.18.5
3031
- temporary-1.2.1.1

stack.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ extra-deps:
88
- ansi-terminal-0.10.2
99
- base-compat-0.11.0
1010
# - cabal-helper-1.0.0.0
11-
- github: jneira/cabal-helper
12-
commit: ffb1f57a5ffc6b7ac3c46a9974c4420a6d2bb9b2
11+
- github: DanielG/cabal-helper
12+
commit: a18bbb2af92e9b4337e7f930cb80754f2408bcfd
1313
- cabal-plan-0.6.2.0
1414
- clock-0.7.2
1515
- floskell-0.10.2
@@ -22,7 +22,7 @@ extra-deps:
2222
- haskell-lsp-types-0.21.0.0
2323
- hie-bios-0.4.0
2424
- indexed-profunctors-0.1
25-
- lsp-test-0.10.1.0
25+
- lsp-test-0.10.2.0
2626
- monad-dijkstra-0.1.1.2
2727
- optics-core-0.2
2828
- optparse-applicative-0.15.1.0

0 commit comments

Comments
 (0)