@@ -16,7 +16,10 @@ import Control.DeepSeq (NFData)
16
16
import Control.Exception
17
17
import Control.Monad.Extra
18
18
import Control.Monad.IO.Class
19
+ import qualified Crypto.Hash.SHA1 as H
19
20
import Data.Binary (Binary )
21
+ import Data.ByteString.Base16
22
+ import qualified Data.ByteString.Char8 as B
20
23
import Data.Default
21
24
import Data.Dynamic (Typeable )
22
25
import qualified Data.HashSet as HashSet
@@ -26,6 +29,8 @@ import qualified Data.Map.Strict as Map
26
29
import Data.Maybe
27
30
import qualified Data.Text as T
28
31
import qualified Data.Text.IO as T
32
+ -- import Data.Version
33
+ -- import Development.GitRev
29
34
import Development.IDE.Core.Debouncer
30
35
import Development.IDE.Core.FileStore
31
36
import Development.IDE.Core.OfInterest
@@ -42,18 +47,22 @@ import Development.IDE.Types.Location
42
47
import Development.IDE.Types.Logger
43
48
import Development.IDE.Types.Options
44
49
import Development.Shake (Action , RuleResult , Rules , action , doesFileExist , need )
50
+ import DynFlags
45
51
import GHC hiding (def )
46
52
import GHC.Generics (Generic )
47
53
-- import qualified GHC.Paths
48
54
import HIE.Bios
49
55
import HIE.Bios.Cradle
56
+ import HIE.Bios.Environment
50
57
import HIE.Bios.Types
51
58
import Ide.Plugin
52
59
import Ide.Plugin.Config
53
60
-- import Ide.Plugin.Formatter
54
61
import Language.Haskell.LSP.Messages
55
62
import Language.Haskell.LSP.Types (LspId (IdInt ))
63
+ import qualified Language.Haskell.LSP.Core as LSP
56
64
import Linker
65
+ -- import Paths_haskell_language_server
57
66
import qualified System.Directory.Extra as IO
58
67
-- import System.Environment
59
68
import System.Exit
@@ -69,6 +78,7 @@ import Ide.Plugin.Example as Example
69
78
import Ide.Plugin.Example2 as Example2
70
79
import Ide.Plugin.Floskell as Floskell
71
80
import Ide.Plugin.Ormolu as Ormolu
81
+ import Ide.Plugin.Pragmas as Pragmas
72
82
73
83
-- ---------------------------------------------------------------------
74
84
@@ -82,13 +92,29 @@ idePlugins includeExample
82
92
CodeAction. plugin <>
83
93
formatterPlugins [(" ormolu" , Ormolu. provider)
84
94
,(" floskell" , Floskell. provider)] <>
85
- codeActionPlugins [(" eg" , Example. codeAction)
86
- ,(" eg2" , Example2. codeAction)] <>
95
+ codeActionPlugins [(" eg" , Example. codeAction)
96
+ ,(" eg2" , Example2. codeAction)
97
+ ,(" pragmas" , Pragmas. codeAction)] <>
98
+ executeCommandPlugins [(" pragmas" , Pragmas. commands)] <>
87
99
hoverPlugins [Example. hover, Example2. hover] <>
88
100
if includeExample then Example. plugin <> Example2. plugin
89
101
else mempty
90
102
103
+ commandIds :: T. Text -> [T. Text ]
104
+ commandIds pid = " typesignature.add" : allLspCmdIds pid [(" pragmas" , Pragmas. commands)]
105
+
91
106
-- ---------------------------------------------------------------------
107
+ -- Prefix for the cache path
108
+ cacheDir :: String
109
+ cacheDir = " ghcide"
110
+
111
+ getCacheDir :: [String ] -> IO FilePath
112
+ getCacheDir opts = IO. getXdgDirectory IO. XdgCache (cacheDir </> opts_hash)
113
+ where
114
+ -- Create a unique folder per set of different GHC options, assuming that each different set of
115
+ -- GHC options will create incompatible interface files.
116
+ opts_hash = B. unpack $ encode $ H. finalize $ H. updates H. init (map B. pack opts)
117
+
92
118
93
119
main :: IO ()
94
120
main = do
@@ -108,13 +134,17 @@ main = do
108
134
109
135
dir <- IO. getCurrentDirectory
110
136
137
+ pid <- getPid
111
138
let plugins = idePlugins argsExamplePlugin
139
+ options = def { LSP. executeCommandCommands = Just (commandIds pid)
140
+ , LSP. completionTriggerCharacters = Just " ."
141
+ }
112
142
113
143
if argLSP then do
114
144
t <- offsetTime
115
145
hPutStrLn stderr " Starting (haskell-language-server)LSP server..."
116
146
hPutStrLn stderr " If you are seeing this in a terminal, you probably should have run ghcide WITHOUT the --lsp option!"
117
- runLanguageServer def (pluginHandler plugins) getInitialConfig getConfigFromNotification $ \ getLspId event vfs caps -> do
147
+ runLanguageServer options (pluginHandler plugins) getInitialConfig getConfigFromNotification $ \ getLspId event vfs caps -> do
118
148
t <- t
119
149
hPutStrLn stderr $ " Started LSP server in " ++ showDuration t
120
150
let options = (defaultIdeOptions $ loadSession dir)
@@ -235,14 +265,50 @@ getComponentOptions cradle = do
235
265
236
266
237
267
createSession :: ComponentOptions -> IO HscEnvEq
238
- createSession opts = do
268
+ createSession ( ComponentOptions theOpts _) = do
239
269
libdir <- getLibdir
270
+
271
+ cacheDir <- Main. getCacheDir theOpts
272
+
240
273
env <- runGhc (Just libdir) $ do
241
- _targets <- initSession opts
274
+ dflags <- getSessionDynFlags
275
+ (dflags', _targets) <- addCmdOpts theOpts dflags
276
+ _ <- setSessionDynFlags $
277
+ -- disabled, generated directly by ghcide instead
278
+ flip gopt_unset Opt_WriteInterface $
279
+ -- disabled, generated directly by ghcide instead
280
+ -- also, it can confuse the interface stale check
281
+ dontWriteHieFiles $
282
+ setHiDir cacheDir $
283
+ setDefaultHieDir cacheDir $
284
+ setIgnoreInterfacePragmas $
285
+ setLinkerOptions $
286
+ disableOptimisation dflags'
242
287
getSession
243
288
initDynLinker env
244
289
newHscEnvEq env
245
290
291
+ -- we don't want to generate object code so we compile to bytecode
292
+ -- (HscInterpreted) which implies LinkInMemory
293
+ -- HscInterpreted
294
+ setLinkerOptions :: DynFlags -> DynFlags
295
+ setLinkerOptions df = df {
296
+ ghcLink = LinkInMemory
297
+ , hscTarget = HscNothing
298
+ , ghcMode = CompManager
299
+ }
300
+
301
+ setIgnoreInterfacePragmas :: DynFlags -> DynFlags
302
+ setIgnoreInterfacePragmas df =
303
+ gopt_set (gopt_set df Opt_IgnoreInterfacePragmas ) Opt_IgnoreOptimChanges
304
+
305
+ disableOptimisation :: DynFlags -> DynFlags
306
+ disableOptimisation df = updOptLevel 0 df
307
+
308
+ setHiDir :: FilePath -> DynFlags -> DynFlags
309
+ setHiDir f d =
310
+ -- override user settings to avoid conflicts leading to recompilation
311
+ d { hiDir = Just f}
246
312
247
313
cradleToSession :: Maybe FilePath -> Cradle a -> Action HscEnvEq
248
314
cradleToSession mbYaml cradle = do
0 commit comments