lsp-test-0.13.0.0: test/dummy-server/Main.hs
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad
import Control.Monad.Reader
import Data.Aeson hiding (defaultOptions)
import qualified Data.HashMap.Strict as HM
import Data.List (isSuffixOf)
import Data.String
import Language.LSP.Server
import Language.LSP.Types
import System.Directory
import System.FilePath
import UnliftIO
import UnliftIO.Concurrent
main = do
handlerEnv <- HandlerEnv <$> newEmptyMVar <*> newEmptyMVar
runServer $ ServerDefinition
{ doInitialize = \env _req -> pure $ Right env,
onConfigurationChange = const $ pure $ Right (),
staticHandlers = handlers,
interpretHandler = \env ->
Iso
(\m -> runLspT env (runReaderT m handlerEnv))
liftIO,
options = defaultOptions {executeCommandCommands = Just ["doAnEdit"]}
}
data HandlerEnv = HandlerEnv
{ relRegToken :: MVar (RegistrationToken WorkspaceDidChangeWatchedFiles),
absRegToken :: MVar (RegistrationToken WorkspaceDidChangeWatchedFiles)
}
handlers :: Handlers (ReaderT HandlerEnv (LspM ()))
handlers =
mconcat
[ notificationHandler SInitialized $
\_noti ->
sendNotification SWindowLogMessage $
LogMessageParams MtLog "initialized"
, requestHandler STextDocumentHover $
\_req responder ->
responder $
Right $
Just $
Hover (HoverContents (MarkupContent MkPlainText "hello")) Nothing
, requestHandler STextDocumentDocumentSymbol $
\_req responder ->
responder $
Right $
InL $
List
[ DocumentSymbol
"foo"
Nothing
SkObject
Nothing
(mkRange 0 0 3 6)
(mkRange 0 0 3 6)
Nothing
]
, notificationHandler STextDocumentDidOpen $
\noti -> do
let NotificationMessage _ _ (DidOpenTextDocumentParams doc) = noti
TextDocumentItem uri _ _ _ = doc
Just fp = uriToFilePath uri
diag =
Diagnostic
(mkRange 0 0 0 1)
(Just DsWarning)
(Just (InL 42))
(Just "dummy-server")
"Here's a warning"
Nothing
Nothing
withRunInIO $
\runInIO -> do
when (".hs" `isSuffixOf` fp) $
void $
forkIO $
do
threadDelay (2 * 10 ^ 6)
runInIO $
sendNotification STextDocumentPublishDiagnostics $
PublishDiagnosticsParams uri Nothing (List [diag])
-- also act as a registerer for workspace/didChangeWatchedFiles
when (".register" `isSuffixOf` fp) $
do
let regOpts =
DidChangeWatchedFilesRegistrationOptions $
List
[ FileSystemWatcher
"*.watch"
(Just (WatchKind True True True))
]
Just token <- runInIO $
registerCapability SWorkspaceDidChangeWatchedFiles regOpts $
\_noti ->
sendNotification SWindowLogMessage $
LogMessageParams MtLog "got workspace/didChangeWatchedFiles"
runInIO $ asks relRegToken >>= \v -> putMVar v token
when (".register.abs" `isSuffixOf` fp) $
do
curDir <- getCurrentDirectory
let regOpts =
DidChangeWatchedFilesRegistrationOptions $
List
[ FileSystemWatcher
(fromString $ curDir </> "*.watch")
(Just (WatchKind True True True))
]
Just token <- runInIO $
registerCapability SWorkspaceDidChangeWatchedFiles regOpts $
\_noti ->
sendNotification SWindowLogMessage $
LogMessageParams MtLog "got workspace/didChangeWatchedFiles"
runInIO $ asks absRegToken >>= \v -> putMVar v token
-- also act as an unregisterer for workspace/didChangeWatchedFiles
when (".unregister" `isSuffixOf` fp) $
do
Just token <- runInIO $ asks relRegToken >>= tryReadMVar
runInIO $ unregisterCapability token
when (".unregister.abs" `isSuffixOf` fp) $
do
Just token <- runInIO $ asks absRegToken >>= tryReadMVar
runInIO $ unregisterCapability token
, requestHandler SWorkspaceExecuteCommand $ \req resp -> do
let RequestMessage _ _ _ (ExecuteCommandParams Nothing "doAnEdit" (Just (List [val]))) = req
Success docUri = fromJSON val
edit = List [TextEdit (mkRange 0 0 0 5) "howdy"]
params =
ApplyWorkspaceEditParams (Just "Howdy edit") $
WorkspaceEdit (Just (HM.singleton docUri edit)) Nothing
resp $ Right Null
void $ sendRequest SWorkspaceApplyEdit params (const (pure ()))
, requestHandler STextDocumentCodeAction $ \req resp -> do
let RequestMessage _ _ _ params = req
CodeActionParams _ _ _ _ cactx = params
CodeActionContext diags _ = cactx
codeActions = fmap diag2ca diags
diag2ca d =
CodeAction
"Delete this"
Nothing
(Just (List [d]))
Nothing
Nothing
Nothing
(Just (Command "" "deleteThis" Nothing))
resp $ Right $ InR <$> codeActions
, requestHandler STextDocumentCompletion $ \_req resp -> do
let res = CompletionList True (List [item])
item =
CompletionItem
"foo"
(Just CiConstant)
(Just (List []))
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
resp $ Right $ InR res
]