Skip to content

Commit 755fc37

Browse files
wz1000pepeiborrapeterwicksstringfield
authored
References via hiedb (#704)
* Integrate hiedb 1. Add 'indexHieFile' and rule 'GetModIfaceFromDiskAndIndex' to maintain database integrity - 'writeHieFile' -> 'writeAndIndexHieFile' 2. References fromm database 3. Use db for go to definition - Return multiple definitions for things defined in boot files - More robust definitions for multi-component 4. Add persistent stale rules to answer queries immedidately on startup - Setup `unsafeGlobalDynFlags` on startup 5. Add hiedb command line to ghcide and hls Co-authored-by: Pepe Iborra <[email protected]> Co-authored-by: Peter Wicks Stringfield <[email protected]> * Update ghcide/bench/lib/Experiments.hs Co-authored-by: Pepe Iborra <[email protected]> * Clear deleted files from hiedb * make garbage collection async * bump hiedb Co-authored-by: Pepe Iborra <[email protected]> Co-authored-by: Peter Wicks Stringfield <[email protected]>
1 parent 46d2a3d commit 755fc37

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1466
-412
lines changed

cabal.project

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ package ghcide
3030

3131
write-ghc-environment-files: never
3232

33-
index-state: 2021-01-17T17:47:48Z
33+
index-state: 2021-01-28T17:47:48Z
3434

3535
allow-newer:
3636
active:base,

exe/Wrapper.hs

+10-6
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,24 @@ main = do
4343
VersionMode PrintNumericVersion ->
4444
putStrLn haskellLanguageServerNumericVersion
4545

46-
LspMode lspArgs ->
47-
launchHaskellLanguageServer lspArgs
46+
_ -> launchHaskellLanguageServer args
4847

49-
launchHaskellLanguageServer :: LspArguments -> IO ()
50-
launchHaskellLanguageServer LspArguments{..} = do
51-
whenJust argsCwd setCurrentDirectory
48+
launchHaskellLanguageServer :: Arguments -> IO ()
49+
launchHaskellLanguageServer parsedArgs = do
50+
case parsedArgs of
51+
LspMode LspArguments{..} -> whenJust argsCwd setCurrentDirectory
52+
_ -> pure ()
5253

5354
d <- getCurrentDirectory
5455

5556
-- Get the cabal directory from the cradle
5657
cradle <- findLocalCradle (d </> "a")
5758
setCurrentDirectory $ cradleRootDir cradle
5859

59-
when argsProjectGhcVersion $ getRuntimeGhcVersion' cradle >>= putStrLn >> exitSuccess
60+
case parsedArgs of
61+
LspMode LspArguments{..} ->
62+
when argsProjectGhcVersion $ getRuntimeGhcVersion' cradle >>= putStrLn >> exitSuccess
63+
_ -> pure ()
6064

6165
progName <- getProgName
6266
hPutStrLn stderr $ "Run entered for haskell-language-server-wrapper(" ++ progName ++ ") "

ghcide/.hlint.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
- Development.IDE.Spans.Calculate
8989
- Development.IDE.Spans.Documentation
9090
- Development.IDE.Spans.Common
91+
- Development.IDE.Spans.AtPoint
9192
- Development.IDE.Plugin.CodeAction
9293
- Development.IDE.Plugin.Completions
9394
- Development.IDE.Plugin.Completions.Logic

ghcide/bench/lib/Experiments.hs

+8-2
Original file line numberDiff line numberDiff line change
@@ -324,9 +324,15 @@ data BenchRun = BenchRun
324324
badRun :: BenchRun
325325
badRun = BenchRun 0 0 0 0 0 False
326326

327+
-- | Wait for all progress to be done
328+
-- Needs at least one progress done notification to return
327329
waitForProgressDone :: Session ()
328-
waitForProgressDone =
329-
void(skipManyTill anyMessage message :: Session WorkDoneProgressEndNotification)
330+
waitForProgressDone = loop
331+
where
332+
loop = do
333+
void (skipManyTill anyMessage message :: Session WorkDoneProgressEndNotification)
334+
done <- null <$> getIncompleteProgressSessions
335+
unless done loop
330336

331337
runBench ::
332338
(?config :: Config) =>

ghcide/exe/Arguments.hs

+17-6
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,52 @@
11
-- Copyright (c) 2019 The DAML Authors. All rights reserved.
22
-- SPDX-License-Identifier: Apache-2.0
33

4-
module Arguments(Arguments(..), getArguments) where
4+
module Arguments(Arguments, Arguments'(..), getArguments, IdeCmd(..)) where
55

66
import Options.Applicative
7+
import HieDb.Run
78

9+
type Arguments = Arguments' IdeCmd
810

9-
data Arguments = Arguments
11+
data IdeCmd = Typecheck [FilePath] | DbCmd Options Command | LSP
12+
13+
data Arguments' a = Arguments
1014
{argLSP :: Bool
1115
,argsCwd :: Maybe FilePath
12-
,argFiles :: [FilePath]
1316
,argsVersion :: Bool
1417
,argsShakeProfiling :: Maybe FilePath
1518
,argsOTMemoryProfiling :: Bool
1619
,argsTesting :: Bool
1720
,argsDisableKick :: Bool
1821
,argsThreads :: Int
1922
,argsVerbose :: Bool
23+
,argFilesOrCmd :: a
2024
}
2125

2226
getArguments :: IO Arguments
2327
getArguments = execParser opts
2428
where
2529
opts = info (arguments <**> helper)
2630
( fullDesc
27-
<> progDesc "Used as a test bed to check your IDE will work"
2831
<> header "ghcide - the core of a Haskell IDE")
2932

3033
arguments :: Parser Arguments
3134
arguments = Arguments
32-
<$> switch (long "lsp" <> help "Start talking to an LSP server")
35+
<$> switch (long "lsp" <> help "Start talking to an LSP client")
3336
<*> optional (strOption $ long "cwd" <> metavar "DIR" <> help "Change to this directory")
34-
<*> many (argument str (metavar "FILES/DIRS..."))
3537
<*> switch (long "version" <> help "Show ghcide and GHC versions")
3638
<*> optional (strOption $ long "shake-profiling" <> metavar "DIR" <> help "Dump profiling reports to this directory")
3739
<*> switch (long "ot-memory-profiling" <> help "Record OpenTelemetry info to the eventlog. Needs the -l RTS flag to have an effect")
3840
<*> switch (long "test" <> help "Enable additional lsp messages used by the testsuite")
3941
<*> switch (long "test-no-kick" <> help "Disable kick. Useful for testing cancellation")
4042
<*> option auto (short 'j' <> help "Number of threads (0: automatic)" <> metavar "NUM" <> value 0 <> showDefault)
4143
<*> switch (long "verbose" <> help "Include internal events in logging output")
44+
<*> ( hsubparser (command "typecheck" (info (Typecheck <$> fileCmd) fileInfo)
45+
<> command "hiedb" (info (DbCmd <$> optParser "" True <*> cmdParser <**> helper) hieInfo)
46+
<> command "lsp" (info (pure LSP <**> helper) lspInfo) )
47+
<|> Typecheck <$> fileCmd )
48+
where
49+
fileCmd = many (argument str (metavar "FILES/DIRS..."))
50+
lspInfo = fullDesc <> progDesc "Start talking to an LSP client"
51+
fileInfo = fullDesc <> progDesc "Used as a test bed to check your IDE will work"
52+
hieInfo = fullDesc <> progDesc "Query .hie files"

ghcide/exe/Main.hs

+37-9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module Main(main) where
88
import Arguments
99
import Control.Concurrent.Extra
1010
import Control.Monad.Extra
11+
import Control.Exception.Safe
1112
import Control.Lens ( (^.) )
1213
import Data.Default
1314
import Data.List.Extra
@@ -29,7 +30,7 @@ import Development.IDE.Types.Options
2930
import Development.IDE.Types.Logger
3031
import Development.IDE.Plugin
3132
import Development.IDE.Plugin.Test as Test
32-
import Development.IDE.Session (loadSession)
33+
import Development.IDE.Session (loadSession, setInitialDynFlags, getHieDbLoc, runWithDb)
3334
import Development.Shake (ShakeOptions (shakeThreads))
3435
import qualified Language.Haskell.LSP.Core as LSP
3536
import Language.Haskell.LSP.Messages
@@ -58,6 +59,8 @@ import Development.IDE.Plugin.HLS.GhcIde as GhcIde
5859
import Ide.Plugin.Config
5960
import Ide.PluginUtils (allLspCmdIds', getProcessID, pluginDescToIdePlugins)
6061

62+
import HieDb.Run (Options(..), runCommand)
63+
6164
ghcideVersion :: IO String
6265
ghcideVersion = do
6366
path <- getExecutablePath
@@ -78,13 +81,30 @@ main = do
7881
if argsVersion then ghcideVersion >>= putStrLn >> exitSuccess
7982
else hPutStrLn stderr {- see WARNING above -} =<< ghcideVersion
8083

84+
whenJust argsCwd IO.setCurrentDirectory
85+
86+
87+
dir <- IO.getCurrentDirectory
88+
dbLoc <- getHieDbLoc dir
89+
90+
case argFilesOrCmd of
91+
DbCmd opts cmd -> do
92+
mlibdir <- setInitialDynFlags
93+
case mlibdir of
94+
Nothing -> exitWith $ ExitFailure 1
95+
Just libdir ->
96+
runCommand libdir opts{database = dbLoc} cmd
97+
Typecheck (Just -> argFilesOrCmd) | not argLSP -> runWithDb dbLoc $ runIde Arguments{..}
98+
_ -> let argFilesOrCmd = Nothing in runWithDb dbLoc $ runIde Arguments{..}
99+
100+
101+
runIde :: Arguments' (Maybe [FilePath]) -> HieDb -> IndexQueue -> IO ()
102+
runIde Arguments{..} hiedb hiechan = do
81103
-- lock to avoid overlapping output on stdout
82104
lock <- newLock
83105
let logger p = Logger $ \pri msg -> when (pri >= p) $ withLock lock $
84106
T.putStrLn $ T.pack ("[" ++ upper (show pri) ++ "] ") <> msg
85107

86-
whenJust argsCwd IO.setCurrentDirectory
87-
88108
dir <- IO.getCurrentDirectory
89109

90110
let hlsPlugins = pluginDescToIdePlugins $
@@ -107,14 +127,22 @@ main = do
107127
options = def { LSP.executeCommandCommands = Just hlsCommands
108128
, LSP.completionTriggerCharacters = Just "."
109129
}
110-
111-
if argLSP then do
130+
case argFilesOrCmd of
131+
Nothing -> do
112132
t <- offsetTime
113133
hPutStrLn stderr "Starting LSP server..."
114134
hPutStrLn stderr "If you are seeing this in a terminal, you probably should have run ghcide WITHOUT the --lsp option!"
115135
runLanguageServer options (pluginHandler plugins) onInitialConfiguration onConfigurationChange $ \getLspId event vfs caps wProg wIndefProg getConfig rootPath -> do
116136
t <- t
117137
hPutStrLn stderr $ "Started LSP server in " ++ showDuration t
138+
139+
-- We want to set the global DynFlags right now, so that we can use
140+
-- `unsafeGlobalDynFlags` even before the project is configured
141+
-- We do it here since haskell-lsp changes our working directory to the correct place ('rootPath')
142+
-- before calling this function
143+
_mlibdir <- setInitialDynFlags
144+
`catchAny` (\e -> (hPutStrLn stderr $ "setInitialDynFlags: " ++ displayException e) >> pure Nothing)
145+
118146
sessionLoader <- loadSession $ fromMaybe dir rootPath
119147
config <- fromMaybe def <$> getConfig
120148
let options = defOptions
@@ -138,8 +166,8 @@ main = do
138166
unless argsDisableKick $
139167
action kick
140168
initialise caps rules
141-
getLspId event wProg wIndefProg (logger logLevel) debouncer options vfs
142-
else do
169+
getLspId event wProg wIndefProg (logger logLevel) debouncer options vfs hiedb hiechan
170+
Just argFiles -> do
143171
-- GHC produces messages with UTF8 in them, so make sure the terminal doesn't error
144172
hSetEncoding stdout utf8
145173
hSetEncoding stderr utf8
@@ -174,7 +202,7 @@ main = do
174202
}
175203
defOptions = defaultIdeOptions sessionLoader
176204
logLevel = if argsVerbose then minBound else Info
177-
ide <- initialise def mainRule (pure $ IdInt 0) (showEvent lock) dummyWithProg (const (const id)) (logger logLevel) debouncer options vfs
205+
ide <- initialise def mainRule (pure $ IdInt 0) (showEvent lock) dummyWithProg (const (const id)) (logger logLevel) debouncer options vfs hiedb hiechan
178206

179207
putStrLn "\nStep 4/4: Type checking the files"
180208
setFilesOfInterest ide $ HashMap.fromList $ map ((, OnDisk) . toNormalizedFilePath') files
@@ -203,7 +231,7 @@ main = do
203231

204232
unless (null failed) (exitWith $ ExitFailure (length failed))
205233

206-
{-# ANN main ("HLint: ignore Use nubOrd" :: String) #-}
234+
{-# ANN runIde ("HLint: ignore Use nubOrd" :: String) #-}
207235

208236
expandFiles :: [FilePath] -> IO [FilePath]
209237
expandFiles = concatMapM $ \x -> do

ghcide/ghcide.cabal

+13-3
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ library
4747
deepseq,
4848
directory,
4949
dlist,
50-
extra,
50+
extra >= 1.7.4,
5151
fuzzy,
5252
filepath,
5353
fingertree,
@@ -60,6 +60,7 @@ library
6060
hie-compat,
6161
hls-plugin-api >= 0.6,
6262
lens,
63+
hiedb == 0.3.0.1,
6364
mtl,
6465
network-uri,
6566
parallel,
@@ -73,6 +74,7 @@ library
7374
safe-exceptions,
7475
shake >= 0.18.4,
7576
sorted-list,
77+
sqlite-simple,
7678
stm,
7779
syb,
7880
text,
@@ -82,6 +84,9 @@ library
8284
utf8-string,
8385
vector,
8486
hslogger,
87+
Diff,
88+
vector,
89+
bytestring-encoding,
8590
opentelemetry >=0.6.1,
8691
heapsize ==0.3.*
8792
if flag(ghc-lib)
@@ -251,6 +256,8 @@ executable ghcide
251256
if flag(ghc-lib)
252257
buildable: False
253258
default-language: Haskell2010
259+
include-dirs:
260+
include
254261
hs-source-dirs: exe
255262
ghc-options:
256263
-threaded
@@ -264,13 +271,16 @@ executable ghcide
264271
"-with-rtsopts=-I0 -A128M"
265272
main-is: Main.hs
266273
build-depends:
274+
hiedb,
267275
aeson,
268276
base == 4.*,
269277
data-default,
270278
directory,
271279
extra,
272280
filepath,
273281
gitrev,
282+
safe-exceptions,
283+
ghc,
274284
hashable,
275285
haskell-lsp,
276286
haskell-lsp-types,
@@ -337,7 +347,7 @@ test-suite ghcide-tests
337347
hls-plugin-api,
338348
network-uri,
339349
lens,
340-
lsp-test >= 0.11.0.6 && < 0.12,
350+
lsp-test >= 0.12.0.0 && < 0.13,
341351
optparse-applicative,
342352
process,
343353
QuickCheck,
@@ -394,7 +404,7 @@ executable ghcide-bench
394404
extra,
395405
filepath,
396406
ghcide,
397-
lsp-test >= 0.11.0.2 && < 0.12,
407+
lsp-test >= 0.12.0.0 && < 0.13,
398408
optparse-applicative,
399409
process,
400410
safe-exceptions,

0 commit comments

Comments
 (0)