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
20 import System.Console.ANSI
22 satisfy :: (MonadIO m, MonadSessionConfig m) => (FromServerMessage -> Bool) -> ConduitParser FromServerMessage m FromServerMessage
24 timeout <- timeout <$> lift sessionConfig
25 tId <- liftIO myThreadId
26 timeoutThread <- liftIO $ forkIO $ do
27 threadDelay (timeout * 1000000)
28 throwTo tId TimeoutException
30 liftIO $ killThread timeoutThread
35 setSGR [SetColor Foreground Vivid Magenta]
36 putStrLn $ "<-- " ++ B.unpack (encodeMsg x)
41 -- | Matches if the message is a notification.
42 anyNotification :: (MonadIO m, MonadSessionConfig m) => ConduitParser FromServerMessage m FromServerMessage
43 anyNotification = named "Any notification" $ satisfy isServerNotification
45 notification :: forall m a. (MonadIO m, MonadSessionConfig m, FromJSON a) => ConduitParser FromServerMessage m (NotificationMessage ServerMethod a)
46 notification = named "Notification" $ do
47 let parser = decode . encodeMsg :: FromServerMessage -> Maybe (NotificationMessage ServerMethod a)
48 x <- satisfy (isJust . parser)
51 -- | Matches if the message is a request.
52 anyRequest :: (MonadIO m, MonadSessionConfig m) => ConduitParser FromServerMessage m FromServerMessage
53 anyRequest = named "Any request" $ satisfy isServerRequest
55 request :: forall m a b. (MonadIO m, MonadSessionConfig m, FromJSON a, FromJSON b) => ConduitParser FromServerMessage m (RequestMessage ServerMethod a b)
56 request = named "Request" $ do
57 let parser = decode . encodeMsg :: FromServerMessage -> Maybe (RequestMessage ServerMethod a b)
58 x <- satisfy (isJust . parser)
61 -- | Matches if the message is a response.
62 anyResponse :: (MonadIO m, MonadSessionConfig m) => ConduitParser FromServerMessage m FromServerMessage
63 anyResponse = named "Any response" $ satisfy isServerResponse
65 response :: forall m a. (MonadIO m, MonadSessionConfig m, FromJSON a) => ConduitParser FromServerMessage m (ResponseMessage a)
66 response = named "Response" $ do
67 let parser = decode . encodeMsg :: FromServerMessage -> Maybe (ResponseMessage a)
68 x <- satisfy (isJust . parser)
71 -- | A stupid method for getting out the inner message.
72 castMsg :: FromJSON a => FromServerMessage -> a
73 castMsg = fromMaybe (error "Failed casting a message") . decode . encodeMsg
75 -- | A version of encode that encodes FromServerMessages as if they
77 encodeMsg :: FromServerMessage -> B.ByteString
78 encodeMsg = encode . genericToJSON (defaultOptions { sumEncoding = UntaggedValue })
80 -- | Matches if the message is a log message notification or a show message notification/request.
81 loggingNotification :: (MonadIO m, MonadSessionConfig m) => ConduitParser FromServerMessage m FromServerMessage
82 loggingNotification = named "Logging notification" $ satisfy shouldSkip
84 shouldSkip (NotLogMessage _) = True
85 shouldSkip (NotShowMessage _) = True
86 shouldSkip (ReqShowMessage _) = True
89 publishDiagnosticsNotification :: (MonadIO m, MonadSessionConfig m) => ConduitParser FromServerMessage m PublishDiagnosticsNotification
90 publishDiagnosticsNotification = named "Publish diagnostics notification" $ do
91 NotPublishDiagnostics diags <- satisfy test
93 where test (NotPublishDiagnostics _) = True