1-- Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2-- SPDX-License-Identifier: Apache-2.0
4{-# LANGUAGE DuplicateRecordFields #-}
5{-# LANGUAGE OverloadedStrings #-}
6{-# LANGUAGE RankNTypes #-}
8-- WARNING: A copy of DA.Service.Daml.LanguageServer, try to keep them in sync
9-- This version removes the daml: handling
10module Development.IDE.LSP.LanguageServer
14import Development.IDE.LSP.Protocol
15import Development.IDE.LSP.Server
17import Control.Monad.IO.Class
18import qualified Development.IDE.LSP.Definition as LS.Definition
19import qualified Development.IDE.LSP.Hover as LS.Hover
20import qualified Development.IDE.Logger as Logger
21import Development.IDE.State.Service
23import qualified Data.Aeson as Aeson
24import qualified Data.Rope.UTF16 as Rope
25import qualified Data.Set as S
26import qualified Data.Text as T
28import Development.IDE.State.FileStore
29import Development.IDE.Types.Diagnostics
31import qualified Network.URI as URI
33import qualified System.Exit
35import Language.Haskell.LSP.Core (LspFuncs(..))
36import Language.Haskell.LSP.Messages
37import Language.Haskell.LSP.VFS
39textShow :: Show a => a -> T.Text
40textShow = T.pack . show
42------------------------------------------------------------------------
44------------------------------------------------------------------------
49 -> (forall resp. resp -> ResponseMessage resp)
50 -> (ErrorCode -> ResponseMessage ())
52 -> IO FromServerMessage
53handleRequest loggerH compilerH makeResponse makeErrorResponse = \case
55 Logger.logInfo loggerH "Shutdown request received, terminating."
56 System.Exit.exitSuccess
58 KeepAlive -> pure $ RspCustomServer $ makeResponse Aeson.Null
60 Definition params -> RspDefinition . makeResponse <$> LS.Definition.handle loggerH compilerH params
61 Hover params -> RspHover . makeResponse <$> LS.Hover.handle loggerH compilerH params
62 CodeLens _params -> pure $ RspCodeLens $ makeResponse mempty
65 Logger.logWarning loggerH ("Method not found" <> T.pack (show req))
66 pure $ RspError $ makeErrorResponse MethodNotFound
69handleNotification :: LspFuncs () -> Logger.Handle -> IdeState -> ServerNotification -> IO ()
70handleNotification lspFuncs loggerH compilerH = \case
72 DidOpenTextDocument (DidOpenTextDocumentParams item) -> do
73 case URI.parseURI $ T.unpack $ getUri $ _uri (item :: TextDocumentItem) of
75 | URI.uriScheme uri == "file:"
76 -> handleDidOpenFile item
79 -> Logger.logWarning loggerH $ "Unknown scheme in URI: "
82 _ -> Logger.logSeriousError loggerH $ "Invalid URI in DidOpenTextDocument: "
83 <> textShow (_uri (item :: TextDocumentItem))
85 DidChangeTextDocument (DidChangeTextDocumentParams docId _) -> do
86 let uri = _uri (docId :: VersionedTextDocumentIdentifier)
88 case uriToFilePath' uri of
89 Just (toNormalizedFilePath -> filePath) -> do
90 mbVirtual <- getVirtualFileFunc lspFuncs $ toNormalizedUri uri
91 let contents = maybe "" (Rope.toText . (_text :: VirtualFile -> Rope.Rope)) mbVirtual
92 onFileModified compilerH filePath (Just contents)
93 Logger.logInfo loggerH
94 $ "Updated text document: " <> textShow (fromNormalizedFilePath filePath)
97 Logger.logSeriousError loggerH
98 $ "Invalid file path: " <> textShow (_uri (docId :: VersionedTextDocumentIdentifier))
100 DidCloseTextDocument (DidCloseTextDocumentParams (TextDocumentIdentifier uri)) ->
101 case URI.parseURI $ T.unpack $ getUri uri of
103 | URI.uriScheme uri' == "file:" -> do
104 Just fp <- pure $ toNormalizedFilePath <$> uriToFilePath' uri
105 handleDidCloseFile fp
106 | otherwise -> Logger.logWarning loggerH $ "Unknown scheme in URI: " <> textShow uri
108 _ -> Logger.logSeriousError loggerH
109 $ "Invalid URI in DidCloseTextDocument: "
112 DidSaveTextDocument _params ->
115 UnknownNotification _method _params -> return ()
117 -- Note that the state changes here are not atomic.
118 -- When we have parallel compilation we could manage the state
119 -- changes in STM so that we can atomically change the state.
120 -- Internally it should be done via the IO oracle. See PROD-2808.
121 handleDidOpenFile (TextDocumentItem uri _ _ contents) = do
122 Just filePath <- pure $ toNormalizedFilePath <$> uriToFilePath' uri
123 onFileModified compilerH filePath (Just contents)
124 modifyFilesOfInterest compilerH (S.insert filePath)
125 Logger.logInfo loggerH $ "Opened text document: " <> textShow filePath
127 handleDidCloseFile filePath = do
128 Logger.logInfo loggerH $ "Closed text document: " <> textShow (fromNormalizedFilePath filePath)
129 onFileModified compilerH filePath Nothing
130 modifyFilesOfInterest compilerH (S.delete filePath)
132-- | Manages the file store (caching compilation results and unsaved content).
135 -> NormalizedFilePath
138onFileModified service fp mbContents = do
139 logDebug service $ "File modified " <> T.pack (show fp)
140 setBufferModified service fp mbContents
142------------------------------------------------------------------------
144------------------------------------------------------------------------
148 -> ((FromServerMessage -> IO ()) -> VFSHandle -> IO IdeState)
150runLanguageServer loggerH getIdeState = do
151 let getHandlers lspFuncs = do
152 compilerH <- getIdeState (sendFunc lspFuncs) (makeLSPVFSHandle lspFuncs)
153 pure $ Handlers (handleRequest loggerH compilerH) (handleNotification lspFuncs loggerH compilerH)
154 liftIO $ runServer loggerH getHandlers
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list