-- | A session representing one instance of launching and connecting to a server.
--
--- You can send and receive messages to the server within 'Session' via 'getMessage',
--- 'sendRequest' and 'sendNotification'.
---
+-- You can send and receive messages to the server within 'Session' via
+-- 'Language.Haskell.LSP.Test.message',
+-- 'Language.Haskell.LSP.Test.sendRequest' and
+-- 'Language.Haskell.LSP.Test.sendNotification'.
type Session = ParserStateReader FromServerMessage SessionState SessionContext IO
hSetBuffering serverIn NoBuffering
hSetBuffering serverOut NoBuffering
+ -- This is required to make sure that we don’t get any
+ -- newline conversion or weird encoding issues.
+ hSetBinaryMode serverIn True
+ hSetBinaryMode serverOut True
reqMap <- newMVar newRequestMap
messageChan <- newChan
initRsp <- newEmptyMVar
+ mainThreadId <- myThreadId
+
let context = SessionContext serverIn absRootDir messageChan reqMap initRsp config caps
initState = SessionState (IdInt 0) mempty mempty 0 False Nothing
-
- threadId <- forkIO $ void $ serverHandler serverOut context
- (result, _) <- runSession context initState session
-
- killThread threadId
+ launchServerHandler = forkIO $ catch (serverHandler serverOut context)
+ (throwTo mainThreadId :: SessionException -> IO ())
+ (result, _) <- bracket launchServerHandler killThread $
+ const $ runSession context initState session
return result
forM_ bumpedVersions $ \(VersionedTextDocumentIdentifier uri v) ->
modify $ \s ->
let oldVFS = vfs s
- update (VirtualFile oldV t) = VirtualFile (fromMaybe oldV v) t
+ update (VirtualFile oldV t mf) = VirtualFile (fromMaybe oldV v) t mf
newVFS = Map.adjust update uri oldVFS
in s { vfs = newVFS }
logMsg LogClient msg
liftIO $ B.hPut h (addHeader $ encode msg)
--- | Execute a block f that will throw a 'TimeoutException'
+-- | Execute a block f that will throw a 'Timeout' exception
-- after duration seconds. This will override the global timeout
-- for waiting for messages to arrive defined in 'SessionConfig'.
withTimeout :: Int -> Session a -> Session a
| otherwise = Cyan
showPretty = B.unpack . encodePretty
+