lsp-client-0.1.0.0: src/Language/LSP/Client.hs
{- |
This module provides utilities to run an LSP `Session` in `IO`.
-}
module Language.LSP.Client where
import Control.Concurrent.STM
import Control.Monad (forever)
import Control.Monad.IO.Class (MonadIO (liftIO))
import Control.Monad.Reader (asks, runReaderT)
import Data.ByteString.Lazy qualified as LazyByteString
import Data.Dependent.Map qualified as DMap
import Data.Either (fromLeft)
import Data.Generics.Labels ()
import Language.LSP.Client.Decoding
import Language.LSP.Client.Encoding (encode)
import Language.LSP.Client.Session
import Language.LSP.Types (From, Method, MethodType, SMethod (..))
import Language.LSP.Types qualified as LSP
import Language.LSP.VFS (initVFS)
import System.IO (Handle, stdin, stdout)
import UnliftIO (concurrently_, race)
import Prelude
{- | Starts a new session, using the specified handles to communicate with the
server.
-}
runSessionWithHandles
:: Handle
-- ^ The input handle: messages sent from the server to the client will be read from here
-> Handle
-- ^ The output handle: messages sent by the client will be written here
-> Session a
-- ^ Session actions
-> IO a
runSessionWithHandles input output action = initVFS $ \vfs -> do
initialState <- defaultSessionState vfs
flip runReaderT initialState $ do
actionResult <- race action $ do
let send = do
message <- asks outgoing >>= liftIO . atomically . readTQueue
liftIO $ LazyByteString.hPut output $ encode message
let receive = do
serverBytes <- liftIO $ getNextMessage input
(serverMessage, requestCallback) <-
asks pendingRequests
>>= liftIO . atomically . flip stateTVar (decodeFromServerMsg serverBytes)
handleServerMessage serverMessage
liftIO requestCallback
case serverMessage of
LSP.FromServerMess smethod msg -> case methodType smethod of
Notification -> do
handlers :: NotificationMap <- asks notificationHandlers >>= liftIO . readTVarIO
let NotificationCallback cb = DMap.findWithDefault (NotificationCallback (const $ pure ())) smethod handlers
liftIO $ cb msg
_ -> pure ()
_ -> pure ()
concurrently_ (forever send) (forever receive)
pure $ fromLeft (error "runSessionWithHandle: send/receive thread should not exit") actionResult
data SMethodType (t :: MethodType) where
Notification :: SMethodType 'LSP.Notification
Request :: SMethodType 'LSP.Request
methodType :: forall (f :: From) (t :: MethodType) (m :: Method f t). SMethod m -> SMethodType t
methodType SInitialize = Request
methodType SInitialized = Notification
methodType SShutdown = Request
methodType SExit = Notification
methodType SWorkspaceDidChangeWorkspaceFolders = Notification
methodType SWorkspaceDidChangeConfiguration = Notification
methodType SWorkspaceDidChangeWatchedFiles = Notification
methodType SWorkspaceSymbol = Request
methodType SWorkspaceExecuteCommand = Request
methodType STextDocumentDidOpen = Notification
methodType STextDocumentDidChange = Notification
methodType STextDocumentWillSave = Notification
methodType STextDocumentWillSaveWaitUntil = Request
methodType STextDocumentDidSave = Notification
methodType STextDocumentDidClose = Notification
methodType STextDocumentCompletion = Request
methodType SCompletionItemResolve = Request
methodType STextDocumentHover = Request
methodType STextDocumentSignatureHelp = Request
methodType STextDocumentDeclaration = Request
methodType STextDocumentDefinition = Request
methodType STextDocumentTypeDefinition = Request
methodType STextDocumentImplementation = Request
methodType STextDocumentReferences = Request
methodType STextDocumentDocumentHighlight = Request
methodType STextDocumentDocumentSymbol = Request
methodType STextDocumentCodeAction = Request
methodType STextDocumentCodeLens = Request
methodType SCodeLensResolve = Request
methodType STextDocumentDocumentLink = Request
methodType SDocumentLinkResolve = Request
methodType STextDocumentDocumentColor = Request
methodType STextDocumentColorPresentation = Request
methodType STextDocumentFormatting = Request
methodType STextDocumentRangeFormatting = Request
methodType STextDocumentOnTypeFormatting = Request
methodType STextDocumentRename = Request
methodType STextDocumentPrepareRename = Request
methodType STextDocumentFoldingRange = Request
methodType STextDocumentSelectionRange = Request
methodType STextDocumentPrepareCallHierarchy = Request
methodType SCallHierarchyIncomingCalls = Request
methodType SCallHierarchyOutgoingCalls = Request
methodType STextDocumentSemanticTokens = Request
methodType STextDocumentSemanticTokensFull = Request
methodType STextDocumentSemanticTokensFullDelta = Request
methodType STextDocumentSemanticTokensRange = Request
methodType SWindowShowMessage = Notification
methodType SWindowShowMessageRequest = Request
methodType SWindowShowDocument = Request
methodType SWindowLogMessage = Notification
methodType SWindowWorkDoneProgressCancel = Notification
methodType SWindowWorkDoneProgressCreate = Request
methodType SProgress = Notification
methodType STelemetryEvent = Notification
methodType SClientRegisterCapability = Request
methodType SClientUnregisterCapability = Request
methodType SWorkspaceWorkspaceFolders = Request
methodType SWorkspaceConfiguration = Request
methodType SWorkspaceApplyEdit = Request
methodType SWorkspaceSemanticTokensRefresh = Request
methodType STextDocumentPublishDiagnostics = Notification
methodType SCancelRequest = Notification
methodType (SCustomMethod _) = undefined