1 {-# LANGUAGE OverloadedStrings #-}
2 {-# LANGUAGE TupleSections #-}
4 {-# LANGUAGE PolyKinds #-}
5 {-# LANGUAGE KindSignatures #-}
6 {-# LANGUAGE DataKinds #-}
7 module Language.Haskell.LSP.Test.Decoding where
9 import Prelude hiding ( id )
11 import Data.Aeson.Types
13 import Data.Functor.Product
14 import Data.Functor.Const
15 import Control.Exception
17 import qualified Data.ByteString.Lazy.Char8 as B
20 import System.IO.Error
21 import Language.Haskell.LSP.Types
22 import Language.Haskell.LSP.Types.Lens
23 import Language.Haskell.LSP.Test.Exceptions
24 import qualified Data.HashMap.Strict as HM
30 getAllMessages :: Handle -> IO [B.ByteString]
36 msg <- getNextMessage h
38 (msg :) <$> getAllMessages h
40 -- | Fetches the next message bytes based on
41 -- the Content-Length header
42 getNextMessage :: Handle -> IO B.ByteString
44 headers <- getHeaders h
45 case read . init <$> lookup "Content-Length" headers of
46 Nothing -> throw NoContentLengthHeader
47 Just size -> B.hGet h size
49 addHeader :: B.ByteString -> B.ByteString
50 addHeader content = B.concat
52 , B.pack $ show $ B.length content
58 getHeaders :: Handle -> IO [(String, String)]
60 l <- catch (hGetLine h) eofHandler
61 let (name, val) = span (/= ':') l
62 if null val then return [] else ((name, drop 2 val) :) <$> getHeaders h
64 | isEOFError e = throw UnexpectedServerTermination
67 type RequestMap = IxMap LspId (SMethod :: Method FromClient Request -> Type )
69 newRequestMap :: RequestMap
70 newRequestMap = emptyIxMap
72 updateRequestMap :: RequestMap -> LspId m -> SClientMethod m -> Maybe RequestMap
73 updateRequestMap reqMap id method = insertIxMap id method reqMap
75 getRequestMap :: [FromClientMessage] -> RequestMap
76 getRequestMap = foldl' helper emptyIxMap
78 helper :: RequestMap -> FromClientMessage -> RequestMap
79 helper acc msg = case msg of
80 FromClientMess m mess -> case splitClientMethod m of
82 IsClientReq -> fromJust $ updateRequestMap acc (mess ^. id) m
83 IsClientEither -> case mess of
85 ReqMess msg -> fromJust $ updateRequestMap acc (msg ^. id) m
88 decodeFromServerMsg :: RequestMap -> B.ByteString -> (FromServerMessage, RequestMap)
89 decodeFromServerMsg reqMap bytes = unP $ fromJust $ parseMaybe p obj
90 where obj = fromJust $ decode bytes :: Value
91 p = parseServerMessage $ \lid ->
92 let (mm, newMap) = pickFromIxMap lid reqMap
95 Just m -> Just $ (m, Pair m (Const newMap))
96 unP (FromServerMess m msg) = (FromServerMess m msg, reqMap)
97 unP (FromServerRsp (Pair m (Const newMap)) msg) = (FromServerRsp m msg, newMap)
99 WorkspaceWorkspaceFolders -> error "ReqWorkspaceFolders not supported yet"
100 WorkspaceConfiguration -> error "ReqWorkspaceConfiguration not supported yet"
102 | "id" `HM.member` obj && "method" `HM.member` obj -> ReqCustomServer $ fromJust $ decode bytes
103 | "id" `HM.member` obj -> RspCustomServer $ fromJust $ decode bytes
104 | otherwise -> NotCustomServer $ fromJust $ decode bytes