1 {-# LANGUAGE MultiParamTypeClasses #-}
2 {-# LANGUAGE ScopedTypeVariables #-}
3 {-# LANGUAGE RankNTypes #-}
4 {-# LANGUAGE OverloadedStrings #-}
5 module Language.Haskell.LSP.Test.Parsing where
7 import Control.Applicative
8 import Control.Concurrent
9 import Control.Monad.IO.Class
10 import Control.Monad.Trans.Class
12 import qualified Data.ByteString.Lazy.Char8 as B
13 import Data.Conduit.Parser
15 import Language.Haskell.LSP.Messages
16 import Language.Haskell.LSP.Types hiding (error)
17 import Language.Haskell.LSP.Test.Exceptions
18 import Language.Haskell.LSP.Test.Messages
19 import Language.Haskell.LSP.Test.Session
21 satisfy :: (MonadIO m, MonadSessionConfig m) => (a -> Bool) -> ConduitParser a m a
23 timeout <- timeout <$> lift sessionConfig
24 tId <- liftIO myThreadId
25 timeoutThread <- liftIO $ forkIO $ do
26 threadDelay (timeout * 1000000)
27 throwTo tId TimeoutException
29 liftIO $ killThread timeoutThread
34 -- | Matches if the message is a notification.
35 anyNotification :: (MonadIO m, MonadSessionConfig m) => ConduitParser FromServerMessage m FromServerMessage
36 anyNotification = named "Any notification" $ satisfy isServerNotification
38 notification :: forall m a. (MonadIO m, MonadSessionConfig m, FromJSON a) => ConduitParser FromServerMessage m (NotificationMessage ServerMethod a)
39 notification = named "Notification" $ do
40 let parser = decode . encodeMsg :: FromServerMessage -> Maybe (NotificationMessage ServerMethod a)
41 x <- satisfy (isJust . parser)
44 -- | Matches if the message is a request.
45 anyRequest :: (MonadIO m, MonadSessionConfig m) => ConduitParser FromServerMessage m FromServerMessage
46 anyRequest = named "Any request" $ satisfy isServerRequest
48 request :: forall m a b. (MonadIO m, MonadSessionConfig m, FromJSON a, FromJSON b) => ConduitParser FromServerMessage m (RequestMessage ServerMethod a b)
49 request = named "Request" $ do
50 let parser = decode . encodeMsg :: FromServerMessage -> Maybe (RequestMessage ServerMethod a b)
51 x <- satisfy (isJust . parser)
54 -- | Matches if the message is a response.
55 anyResponse :: (MonadIO m, MonadSessionConfig m) => ConduitParser FromServerMessage m FromServerMessage
56 anyResponse = named "Any response" $ satisfy isServerResponse
58 response :: forall m a. (MonadIO m, MonadSessionConfig m, FromJSON a) => ConduitParser FromServerMessage m (ResponseMessage a)
59 response = named "Response" $ do
60 let parser = decode . encodeMsg :: FromServerMessage -> Maybe (ResponseMessage a)
61 x <- satisfy (isJust . parser)
64 -- | A stupid method for getting out the inner message.
65 castMsg :: FromJSON a => FromServerMessage -> a
66 castMsg = fromMaybe (error "Failed casting a message") . decode . encodeMsg
68 -- | A version of encode that encodes FromServerMessages as if they
70 encodeMsg :: FromServerMessage -> B.ByteString
71 encodeMsg = encode . genericToJSON (defaultOptions { sumEncoding = UntaggedValue })
73 -- | Matches if the message is a log message notification or a show message notification/request.
74 loggingNotification :: (MonadIO m, MonadSessionConfig m) => ConduitParser FromServerMessage m FromServerMessage
75 loggingNotification = named "Logging notification" $ satisfy shouldSkip
77 shouldSkip (NotLogMessage _) = True
78 shouldSkip (NotShowMessage _) = True
79 shouldSkip (ReqShowMessage _) = True
82 publishDiagnosticsNotification :: (MonadIO m, MonadSessionConfig m) => ConduitParser FromServerMessage m PublishDiagnosticsNotification
83 publishDiagnosticsNotification = named "Publish diagnostics notification" $ do
84 NotPublishDiagnostics diags <- satisfy test
86 where test (NotPublishDiagnostics _) = True