rzk-0.9.2: src/Language/Rzk/VSCode/Lsp.hs
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedStrings #-}
module Language.Rzk.VSCode.Lsp where
import Control.Monad.IO.Class
import Control.Monad.Reader
import Data.Default.Class (Default (def))
import qualified Data.Text as T
import Language.LSP.Protocol.Message
import Language.LSP.Protocol.Types
import Language.LSP.Server
import Data.Aeson (Result (Error, Success),
fromJSON)
import qualified Language.Rzk.VSCode.Config as RzkConfig
import Language.Rzk.VSCode.Env
import Language.Rzk.VSCode.Handlers
-- | The maximum number of diagnostic messages to send to the client
maxDiagnosticCount :: Int
maxDiagnosticCount = 100
handlers :: Handlers LSP
handlers =
mconcat
[ notificationHandler SMethod_Initialized $ const $
spawnTypecheckWorker typecheckFromConfigFile
-- TODO: add logging
-- Empty handlers to silence the errors
, notificationHandler SMethod_TextDocumentDidOpen $ \_msg -> pure ()
, notificationHandler SMethod_TextDocumentDidChange $ \_msg -> pure ()
, notificationHandler SMethod_TextDocumentDidClose $ \_msg -> pure ()
, notificationHandler SMethod_WorkspaceDidChangeWatchedFiles handleFilesChanged
, notificationHandler SMethod_TextDocumentDidSave $ \_msg -> do
-- TODO: check if the file is included in the config's `include` list.
-- If not (and not in `exclude`) either, issue a warning.
return () -- FIXME: typecheck standalone files (if they are not a part of the project)
-- An empty hadler is needed to silence the error since it is already handled by the LSP package
, notificationHandler SMethod_WorkspaceDidChangeConfiguration $ const $ pure ()
-- Progress cancellation is handled by the lsp library's bookkeeping (it
-- cancels the corresponding withProgress action); the empty handler only
-- silences the missing-handler warning.
, notificationHandler SMethod_WindowWorkDoneProgressCancel $ const $ pure ()
, requestHandler SMethod_TextDocumentHover provideHover
, requestHandler SMethod_TextDocumentDocumentSymbol provideSymbols
, requestHandler SMethod_WorkspaceSymbol provideWorkspaceSymbols
, requestHandler SMethod_TextDocumentDefinition findDefinition
, requestHandler SMethod_TextDocumentReferences findReferences
, requestHandler SMethod_TextDocumentCompletion provideCompletions
, requestHandler SMethod_TextDocumentSemanticTokensFull provideSemanticTokens
, requestHandler SMethod_TextDocumentFormatting formatDocument
]
syncOptions :: TextDocumentSyncOptions
syncOptions = TextDocumentSyncOptions
{ _openClose = Just True
, _change = Just TextDocumentSyncKind_Full
, _willSave = Just False
, _willSaveWaitUntil = Just False
, _save = Just $ InR $ SaveOptions { _includeText = Just True }
}
runLsp :: IO Int
runLsp = do
rzkEnv <- defaultRzkEnv
runServer $
ServerDefinition
{ configSection = "rzk"
, parseConfig = \_oldConfig newObject -> case fromJSON newObject of
-- TODO: handle partial config updates from VS Code by updating oldConfig rather than parsing from scratch
Error err -> Left $ T.pack err
Success rzkConfig -> Right rzkConfig
, onConfigChange = const $ pure ()
, doInitialize = const . pure . Right
, staticHandlers = const handlers
, interpretHandler = \env -> Iso (flip runReaderT rzkEnv . runLspT env) liftIO
, options = defaultOptions { optTextDocumentSync = Just syncOptions }
, defaultConfig = def :: RzkConfig.ServerConfig
}