{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE OverloadedStrings #-}

module Language.LSP.Test.Parsing
  ( -- $receiving
    satisfy
  , satisfyMaybe
  , message
  , response
  , responseForId
  , customRequest
  , customNotification
  , anyRequest
  , anyResponse
  , anyNotification
  , anyMessage
  , loggingNotification
  , publishDiagnosticsNotification
  ) where

import Control.Applicative
import Control.Concurrent
import Control.Monad.IO.Class
import Control.Monad
import Data.Conduit.Parser hiding (named)
import qualified Data.Conduit.Parser (named)
import qualified Data.Text as T
import Data.Typeable
import Language.LSP.Types
import Language.LSP.Test.Session

-- $receiving
-- To receive a message, specify the method of the message to expect:
--
-- @
-- msg1 <- message SWorkspaceApplyEdit
-- msg2 <- message STextDocumentHover
-- @
--
-- 'Language.LSP.Test.Session' is actually just a parser
-- that operates on messages under the hood. This means that you
-- can create and combine parsers to match speicifc sequences of
-- messages that you expect.
--
-- For example, if you wanted to match either a definition or
-- references request:
--
-- > defOrImpl = message STextDocumentDefinition
-- >          <|> message STextDocumentReferences
--
-- If you wanted to match any number of telemetry
-- notifications immediately followed by a response:
--
-- @
-- logThenDiags =
--  skipManyTill (message STelemetryEvent)
--               anyResponse
-- @

-- | Consumes and returns the next message, if it satisfies the specified predicate.
--
-- @since 0.5.2.0
satisfy :: (FromServerMessage -> Bool) -> Session FromServerMessage
satisfy :: (FromServerMessage -> Bool) -> Session FromServerMessage
satisfy FromServerMessage -> Bool
pred = (FromServerMessage -> Maybe FromServerMessage)
-> Session FromServerMessage
forall a. (FromServerMessage -> Maybe a) -> Session a
satisfyMaybe (\FromServerMessage
msg -> if FromServerMessage -> Bool
pred FromServerMessage
msg then FromServerMessage -> Maybe FromServerMessage
forall a. a -> Maybe a
Just FromServerMessage
msg else Maybe FromServerMessage
forall a. Maybe a
Nothing)

-- | Consumes and returns the result of the specified predicate if it returns `Just`.
--
-- @since 0.6.1.0
satisfyMaybe :: (FromServerMessage -> Maybe a) -> Session a
satisfyMaybe :: (FromServerMessage -> Maybe a) -> Session a
satisfyMaybe FromServerMessage -> Maybe a
pred = (FromServerMessage -> Session (Maybe a)) -> Session a
forall a. (FromServerMessage -> Session (Maybe a)) -> Session a
satisfyMaybeM (Maybe a -> Session (Maybe a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe a -> Session (Maybe a))
-> (FromServerMessage -> Maybe a)
-> FromServerMessage
-> Session (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FromServerMessage -> Maybe a
pred)

satisfyMaybeM :: (FromServerMessage -> Session (Maybe a)) -> Session a
satisfyMaybeM :: (FromServerMessage -> Session (Maybe a)) -> Session a
satisfyMaybeM FromServerMessage -> Session (Maybe a)
pred = do 
  
  Bool
skipTimeout <- SessionState -> Bool
overridingTimeout (SessionState -> Bool) -> Session SessionState -> Session Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Session SessionState
forall s (m :: * -> *). HasState s m => m s
get
  Int
timeoutId <- Session Int
forall (m :: * -> *).
(HasReader SessionContext m, MonadIO m) =>
m Int
getCurTimeoutId
  Maybe ThreadId
mtid <-
    if Bool
skipTimeout
    then Maybe ThreadId -> Session (Maybe ThreadId)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe ThreadId
forall a. Maybe a
Nothing
    else ThreadId -> Maybe ThreadId
forall a. a -> Maybe a
Just (ThreadId -> Maybe ThreadId)
-> Session ThreadId -> Session (Maybe ThreadId)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> do
      Chan SessionMessage
chan <- (SessionContext -> Chan SessionMessage)
-> Session (Chan SessionMessage)
forall r (m :: * -> *) b. HasReader r m => (r -> b) -> m b
asks SessionContext -> Chan SessionMessage
messageChan
      Int
timeout <- (SessionContext -> Int) -> Session Int
forall r (m :: * -> *) b. HasReader r m => (r -> b) -> m b
asks (SessionConfig -> Int
messageTimeout (SessionConfig -> Int)
-> (SessionContext -> SessionConfig) -> SessionContext -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SessionContext -> SessionConfig
config)
      IO ThreadId -> Session ThreadId
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ThreadId -> Session ThreadId)
-> IO ThreadId -> Session ThreadId
forall a b. (a -> b) -> a -> b
$ IO () -> IO ThreadId
forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
forall a b. (a -> b) -> a -> b
$ do
        Int -> IO ()
threadDelay (Int
timeout Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
1000000)
        Chan SessionMessage -> SessionMessage -> IO ()
forall a. Chan a -> a -> IO ()
writeChan Chan SessionMessage
chan (Int -> SessionMessage
TimeoutMessage Int
timeoutId)

  FromServerMessage
x <- ConduitParser
  FromServerMessage
  (StateT SessionState (ReaderT SessionContext IO))
  FromServerMessage
-> Session FromServerMessage
forall a.
ConduitParser
  FromServerMessage
  (StateT SessionState (ReaderT SessionContext IO))
  a
-> Session a
Session ConduitParser
  FromServerMessage
  (StateT SessionState (ReaderT SessionContext IO))
  FromServerMessage
forall (m :: * -> *) i. Monad m => ConduitParser i m i
await

  Maybe ThreadId -> (ThreadId -> Session ()) -> Session ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe ThreadId
mtid ((ThreadId -> Session ()) -> Session ())
-> (ThreadId -> Session ()) -> Session ()
forall a b. (a -> b) -> a -> b
$ \ThreadId
tid -> do
    Int -> Session ()
forall (m :: * -> *).
(HasReader SessionContext m, MonadIO m) =>
Int -> m ()
bumpTimeoutId Int
timeoutId
    IO () -> Session ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Session ()) -> IO () -> Session ()
forall a b. (a -> b) -> a -> b
$ ThreadId -> IO ()
killThread ThreadId
tid

  (SessionState -> SessionState) -> Session ()
forall s (m :: * -> *). HasState s m => (s -> s) -> m ()
modify ((SessionState -> SessionState) -> Session ())
-> (SessionState -> SessionState) -> Session ()
forall a b. (a -> b) -> a -> b
$ \SessionState
s -> SessionState
s { lastReceivedMessage :: Maybe FromServerMessage
lastReceivedMessage = FromServerMessage -> Maybe FromServerMessage
forall a. a -> Maybe a
Just FromServerMessage
x }

  Maybe a
res <- FromServerMessage -> Session (Maybe a)
pred FromServerMessage
x

  case Maybe a
res of
    Just a
a -> do
      LogMsgType -> FromServerMessage -> Session ()
forall a (m :: * -> *).
(ToJSON a, MonadIO m, HasReader SessionContext m) =>
LogMsgType -> a -> m ()
logMsg LogMsgType
LogServer FromServerMessage
x
      a -> Session a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
    Maybe a
Nothing -> Session a
forall (f :: * -> *) a. Alternative f => f a
empty

named :: T.Text -> Session a -> Session a
named :: Text -> Session a -> Session a
named Text
s (Session ConduitParser
  FromServerMessage
  (StateT SessionState (ReaderT SessionContext IO))
  a
x) = ConduitParser
  FromServerMessage
  (StateT SessionState (ReaderT SessionContext IO))
  a
-> Session a
forall a.
ConduitParser
  FromServerMessage
  (StateT SessionState (ReaderT SessionContext IO))
  a
-> Session a
Session (Text
-> ConduitParser
     FromServerMessage
     (StateT SessionState (ReaderT SessionContext IO))
     a
-> ConduitParser
     FromServerMessage
     (StateT SessionState (ReaderT SessionContext IO))
     a
forall (m :: * -> *) i a.
Monad m =>
Text -> ConduitParser i m a -> ConduitParser i m a
Data.Conduit.Parser.named Text
s ConduitParser
  FromServerMessage
  (StateT SessionState (ReaderT SessionContext IO))
  a
x)


-- | Matches a request or a notification coming from the server.
-- Doesn't match Custom Messages
message :: SServerMethod m -> Session (ServerMessage m)
message :: SServerMethod m -> Session (ServerMessage m)
message (SCustomMethod Text
_) = [Char] -> Session (CustomMessage 'FromServer t)
forall a. HasCallStack => [Char] -> a
error [Char]
"message can't be used with CustomMethod, use customRequest or customNotification instead"
message SServerMethod m
m1 = Text -> Session (ServerMessage m) -> Session (ServerMessage m)
forall a. Text -> Session a -> Session a
named ([Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$ [Char]
"Request for: " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> SServerMethod m -> [Char]
forall a. Show a => a -> [Char]
show SServerMethod m
m1) (Session (ServerMessage m) -> Session (ServerMessage m))
-> Session (ServerMessage m) -> Session (ServerMessage m)
forall a b. (a -> b) -> a -> b
$ (FromServerMessage -> Maybe (ServerMessage m))
-> Session (ServerMessage m)
forall a. (FromServerMessage -> Maybe a) -> Session a
satisfyMaybe ((FromServerMessage -> Maybe (ServerMessage m))
 -> Session (ServerMessage m))
-> (FromServerMessage -> Maybe (ServerMessage m))
-> Session (ServerMessage m)
forall a b. (a -> b) -> a -> b
$ \case
  FromServerMess SMethod m
m2 Message m
msg -> do
    Either (CustomEq m m) (m :~~: m)
res <- SServerMethod m
-> SMethod m -> Maybe (Either (CustomEq m m) (m :~~: m))
forall (t1 :: MethodType) (t2 :: MethodType)
       (m1 :: Method 'FromServer t1) (m2 :: Method 'FromServer t2).
SServerMethod m1
-> SServerMethod m2 -> Maybe (Either (CustomEq m1 m2) (m1 :~~: m2))
mEqServer SServerMethod m
m1 SMethod m
m2
    case Either (CustomEq m m) (m :~~: m)
res of
      Right m :~~: m
HRefl -> ServerMessage m -> Maybe (ServerMessage m)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ServerMessage m
Message m
msg
      Left CustomEq m m
_f -> Maybe (ServerMessage m)
forall a. Maybe a
Nothing
  FromServerMessage
_ -> Maybe (ServerMessage m)
forall a. Maybe a
Nothing

customRequest :: T.Text -> Session (ServerMessage (CustomMethod :: Method FromServer Request))
customRequest :: Text -> Session (ServerMessage 'CustomMethod)
customRequest Text
m = Text
-> Session (CustomMessage 'FromServer 'Request)
-> Session (CustomMessage 'FromServer 'Request)
forall a. Text -> Session a -> Session a
named Text
m (Session (CustomMessage 'FromServer 'Request)
 -> Session (CustomMessage 'FromServer 'Request))
-> Session (CustomMessage 'FromServer 'Request)
-> Session (CustomMessage 'FromServer 'Request)
forall a b. (a -> b) -> a -> b
$ (FromServerMessage -> Maybe (CustomMessage 'FromServer 'Request))
-> Session (CustomMessage 'FromServer 'Request)
forall a. (FromServerMessage -> Maybe a) -> Session a
satisfyMaybe ((FromServerMessage -> Maybe (CustomMessage 'FromServer 'Request))
 -> Session (CustomMessage 'FromServer 'Request))
-> (FromServerMessage
    -> Maybe (CustomMessage 'FromServer 'Request))
-> Session (CustomMessage 'FromServer 'Request)
forall a b. (a -> b) -> a -> b
$ \case
  FromServerMess SMethod m
m1 Message m
msg -> case SMethod m -> ServerNotOrReq m
forall (t :: MethodType) (m :: Method 'FromServer t).
SServerMethod m -> ServerNotOrReq m
splitServerMethod SMethod m
m1 of
    ServerNotOrReq m
IsServerEither -> case Message m
msg of
      ReqMess _ | SMethod m
m1 SMethod m -> SMethod m -> Bool
forall a. Eq a => a -> a -> Bool
== Text -> SMethod 'CustomMethod
forall (f :: From) (t :: MethodType). Text -> SMethod 'CustomMethod
SCustomMethod Text
m -> CustomMessage 'FromServer 'Request
-> Maybe (CustomMessage 'FromServer 'Request)
forall a. a -> Maybe a
Just Message m
CustomMessage 'FromServer 'Request
msg
      Message m
_ -> Maybe (CustomMessage 'FromServer 'Request)
forall a. Maybe a
Nothing
    ServerNotOrReq m
_ -> Maybe (CustomMessage 'FromServer 'Request)
forall a. Maybe a
Nothing
  FromServerMessage
_ -> Maybe (CustomMessage 'FromServer 'Request)
forall a. Maybe a
Nothing

customNotification :: T.Text -> Session (ServerMessage (CustomMethod :: Method FromServer Notification))
customNotification :: Text -> Session (ServerMessage 'CustomMethod)
customNotification Text
m = Text
-> Session (CustomMessage 'FromServer 'Notification)
-> Session (CustomMessage 'FromServer 'Notification)
forall a. Text -> Session a -> Session a
named Text
m (Session (CustomMessage 'FromServer 'Notification)
 -> Session (CustomMessage 'FromServer 'Notification))
-> Session (CustomMessage 'FromServer 'Notification)
-> Session (CustomMessage 'FromServer 'Notification)
forall a b. (a -> b) -> a -> b
$ (FromServerMessage
 -> Maybe (CustomMessage 'FromServer 'Notification))
-> Session (CustomMessage 'FromServer 'Notification)
forall a. (FromServerMessage -> Maybe a) -> Session a
satisfyMaybe ((FromServerMessage
  -> Maybe (CustomMessage 'FromServer 'Notification))
 -> Session (CustomMessage 'FromServer 'Notification))
-> (FromServerMessage
    -> Maybe (CustomMessage 'FromServer 'Notification))
-> Session (CustomMessage 'FromServer 'Notification)
forall a b. (a -> b) -> a -> b
$ \case
  FromServerMess SMethod m
m1 Message m
msg -> case SMethod m -> ServerNotOrReq m
forall (t :: MethodType) (m :: Method 'FromServer t).
SServerMethod m -> ServerNotOrReq m
splitServerMethod SMethod m
m1 of
    ServerNotOrReq m
IsServerEither -> case Message m
msg of
      NotMess _ | SMethod m
m1 SMethod m -> SMethod m -> Bool
forall a. Eq a => a -> a -> Bool
== Text -> SMethod 'CustomMethod
forall (f :: From) (t :: MethodType). Text -> SMethod 'CustomMethod
SCustomMethod Text
m -> CustomMessage 'FromServer 'Notification
-> Maybe (CustomMessage 'FromServer 'Notification)
forall a. a -> Maybe a
Just Message m
CustomMessage 'FromServer 'Notification
msg
      Message m
_ -> Maybe (CustomMessage 'FromServer 'Notification)
forall a. Maybe a
Nothing
    ServerNotOrReq m
_ -> Maybe (CustomMessage 'FromServer 'Notification)
forall a. Maybe a
Nothing
  FromServerMessage
_ -> Maybe (CustomMessage 'FromServer 'Notification)
forall a. Maybe a
Nothing

-- | Matches if the message is a notification.
anyNotification :: Session FromServerMessage
anyNotification :: Session FromServerMessage
anyNotification = Text -> Session FromServerMessage -> Session FromServerMessage
forall a. Text -> Session a -> Session a
named Text
"Any notification" (Session FromServerMessage -> Session FromServerMessage)
-> Session FromServerMessage -> Session FromServerMessage
forall a b. (a -> b) -> a -> b
$ (FromServerMessage -> Bool) -> Session FromServerMessage
satisfy ((FromServerMessage -> Bool) -> Session FromServerMessage)
-> (FromServerMessage -> Bool) -> Session FromServerMessage
forall a b. (a -> b) -> a -> b
$ \case
  FromServerMess SMethod m
m Message m
msg -> case SMethod m -> ServerNotOrReq m
forall (t :: MethodType) (m :: Method 'FromServer t).
SServerMethod m -> ServerNotOrReq m
splitServerMethod SMethod m
m of
    ServerNotOrReq m
IsServerNot -> Bool
True
    ServerNotOrReq m
IsServerEither -> case Message m
msg of
      NotMess _ -> Bool
True
      Message m
_ -> Bool
False
    ServerNotOrReq m
_ -> Bool
False
  FromServerRsp SMethod m
_ ResponseMessage m
_ -> Bool
False

-- | Matches if the message is a request.
anyRequest :: Session FromServerMessage
anyRequest :: Session FromServerMessage
anyRequest = Text -> Session FromServerMessage -> Session FromServerMessage
forall a. Text -> Session a -> Session a
named Text
"Any request" (Session FromServerMessage -> Session FromServerMessage)
-> Session FromServerMessage -> Session FromServerMessage
forall a b. (a -> b) -> a -> b
$ (FromServerMessage -> Bool) -> Session FromServerMessage
satisfy ((FromServerMessage -> Bool) -> Session FromServerMessage)
-> (FromServerMessage -> Bool) -> Session FromServerMessage
forall a b. (a -> b) -> a -> b
$ \case
  FromServerMess SMethod m
m Message m
_ -> case SMethod m -> ServerNotOrReq m
forall (t :: MethodType) (m :: Method 'FromServer t).
SServerMethod m -> ServerNotOrReq m
splitServerMethod SMethod m
m of
    ServerNotOrReq m
IsServerReq -> Bool
True
    ServerNotOrReq m
_ -> Bool
False
  FromServerRsp SMethod m
_ ResponseMessage m
_ -> Bool
False

-- | Matches if the message is a response.
anyResponse :: Session FromServerMessage
anyResponse :: Session FromServerMessage
anyResponse = Text -> Session FromServerMessage -> Session FromServerMessage
forall a. Text -> Session a -> Session a
named Text
"Any response" (Session FromServerMessage -> Session FromServerMessage)
-> Session FromServerMessage -> Session FromServerMessage
forall a b. (a -> b) -> a -> b
$ (FromServerMessage -> Bool) -> Session FromServerMessage
satisfy ((FromServerMessage -> Bool) -> Session FromServerMessage)
-> (FromServerMessage -> Bool) -> Session FromServerMessage
forall a b. (a -> b) -> a -> b
$ \case
  FromServerMess SMethod m
_ Message m
_ -> Bool
False
  FromServerRsp SMethod m
_ ResponseMessage m
_ -> Bool
True

-- | Matches a response coming from the server.
response :: SMethod (m :: Method FromClient Request) -> Session (ResponseMessage m)
response :: SMethod m -> Session (ResponseMessage m)
response SMethod m
m1 = Text -> Session (ResponseMessage m) -> Session (ResponseMessage m)
forall a. Text -> Session a -> Session a
named ([Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$ [Char]
"Response for: " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> SMethod m -> [Char]
forall a. Show a => a -> [Char]
show SMethod m
m1) (Session (ResponseMessage m) -> Session (ResponseMessage m))
-> Session (ResponseMessage m) -> Session (ResponseMessage m)
forall a b. (a -> b) -> a -> b
$ (FromServerMessage -> Maybe (ResponseMessage m))
-> Session (ResponseMessage m)
forall a. (FromServerMessage -> Maybe a) -> Session a
satisfyMaybe ((FromServerMessage -> Maybe (ResponseMessage m))
 -> Session (ResponseMessage m))
-> (FromServerMessage -> Maybe (ResponseMessage m))
-> Session (ResponseMessage m)
forall a b. (a -> b) -> a -> b
$ \case
  FromServerRsp SMethod m
m2 ResponseMessage m
msg -> do
    m :~~: m
HRefl <- (SMethod m
 -> SMethod m -> Maybe (Either (CustomEq m m) (m :~~: m)))
-> SMethod m -> SMethod m -> Maybe (m :~~: m)
forall (t1 :: MethodType) (t2 :: MethodType) (f :: From)
       (m1 :: Method f t1) (m2 :: Method f t2).
(t1 ~ t2) =>
(SMethod m1
 -> SMethod m2 -> Maybe (Either (CustomEq m1 m2) (m1 :~~: m2)))
-> SMethod m1 -> SMethod m2 -> Maybe (m1 :~~: m2)
runEq SMethod m -> SMethod m -> Maybe (Either (CustomEq m m) (m :~~: m))
forall (t1 :: MethodType) (t2 :: MethodType)
       (m1 :: Method 'FromClient t1) (m2 :: Method 'FromClient t2).
SClientMethod m1
-> SClientMethod m2 -> Maybe (Either (CustomEq m1 m2) (m1 :~~: m2))
mEqClient SMethod m
m1 SMethod m
m2
    ResponseMessage m -> Maybe (ResponseMessage m)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ResponseMessage m
msg
  FromServerMessage
_ -> Maybe (ResponseMessage m)
forall a. Maybe a
Nothing

-- | Like 'response', but matches a response for a specific id.
responseForId :: SMethod (m :: Method FromClient Request) -> LspId m -> Session (ResponseMessage m)
responseForId :: SMethod m -> LspId m -> Session (ResponseMessage m)
responseForId SMethod m
m LspId m
lid = Text -> Session (ResponseMessage m) -> Session (ResponseMessage m)
forall a. Text -> Session a -> Session a
named ([Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$ [Char]
"Response for id: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ LspId m -> [Char]
forall a. Show a => a -> [Char]
show LspId m
lid) (Session (ResponseMessage m) -> Session (ResponseMessage m))
-> Session (ResponseMessage m) -> Session (ResponseMessage m)
forall a b. (a -> b) -> a -> b
$ do
  (FromServerMessage -> Maybe (ResponseMessage m))
-> Session (ResponseMessage m)
forall a. (FromServerMessage -> Maybe a) -> Session a
satisfyMaybe ((FromServerMessage -> Maybe (ResponseMessage m))
 -> Session (ResponseMessage m))
-> (FromServerMessage -> Maybe (ResponseMessage m))
-> Session (ResponseMessage m)
forall a b. (a -> b) -> a -> b
$ \FromServerMessage
msg -> do
    case FromServerMessage
msg of
      FromServerMess SMethod m
_ Message m
_ -> Maybe (ResponseMessage m)
forall a. Maybe a
Nothing
      FromServerRsp SMethod m
m' rspMsg :: ResponseMessage m
rspMsg@(ResponseMessage Text
_ Maybe (LspId m)
lid' Either ResponseError (ResponseResult m)
_) -> do
        m :~~: m
HRefl <- (SMethod m
 -> SMethod m -> Maybe (Either (CustomEq m m) (m :~~: m)))
-> SMethod m -> SMethod m -> Maybe (m :~~: m)
forall (t1 :: MethodType) (t2 :: MethodType) (f :: From)
       (m1 :: Method f t1) (m2 :: Method f t2).
(t1 ~ t2) =>
(SMethod m1
 -> SMethod m2 -> Maybe (Either (CustomEq m1 m2) (m1 :~~: m2)))
-> SMethod m1 -> SMethod m2 -> Maybe (m1 :~~: m2)
runEq SMethod m -> SMethod m -> Maybe (Either (CustomEq m m) (m :~~: m))
forall (t1 :: MethodType) (t2 :: MethodType)
       (m1 :: Method 'FromClient t1) (m2 :: Method 'FromClient t2).
SClientMethod m1
-> SClientMethod m2 -> Maybe (Either (CustomEq m1 m2) (m1 :~~: m2))
mEqClient SMethod m
m SMethod m
m'
        Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (LspId m -> Maybe (LspId m)
forall a. a -> Maybe a
Just LspId m
lid Maybe (LspId m) -> Maybe (LspId m) -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe (LspId m)
Maybe (LspId m)
lid')
        ResponseMessage m -> Maybe (ResponseMessage m)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ResponseMessage m
rspMsg

-- | Matches any type of message.
anyMessage :: Session FromServerMessage
anyMessage :: Session FromServerMessage
anyMessage = (FromServerMessage -> Bool) -> Session FromServerMessage
satisfy (Bool -> FromServerMessage -> Bool
forall a b. a -> b -> a
const Bool
True)

-- | Matches if the message is a log message notification or a show message notification/request.
loggingNotification :: Session FromServerMessage
loggingNotification :: Session FromServerMessage
loggingNotification = Text -> Session FromServerMessage -> Session FromServerMessage
forall a. Text -> Session a -> Session a
named Text
"Logging notification" (Session FromServerMessage -> Session FromServerMessage)
-> Session FromServerMessage -> Session FromServerMessage
forall a b. (a -> b) -> a -> b
$ (FromServerMessage -> Bool) -> Session FromServerMessage
satisfy FromServerMessage -> Bool
forall (a :: Method 'FromClient 'Request -> *).
FromServerMessage' a -> Bool
shouldSkip
  where
    shouldSkip :: FromServerMessage' a -> Bool
shouldSkip (FromServerMess SMethod m
SWindowLogMessage Message m
_) = Bool
True
    shouldSkip (FromServerMess SMethod m
SWindowShowMessage Message m
_) = Bool
True
    shouldSkip (FromServerMess SMethod m
SWindowShowMessageRequest Message m
_) = Bool
True
    shouldSkip FromServerMessage' a
_ = Bool
False

-- | Matches a 'Language.LSP.Types.TextDocumentPublishDiagnostics'
-- (textDocument/publishDiagnostics) notification.
publishDiagnosticsNotification :: Session (Message TextDocumentPublishDiagnostics)
publishDiagnosticsNotification :: Session (Message 'TextDocumentPublishDiagnostics)
publishDiagnosticsNotification = Text
-> Session (NotificationMessage 'TextDocumentPublishDiagnostics)
-> Session (NotificationMessage 'TextDocumentPublishDiagnostics)
forall a. Text -> Session a -> Session a
named Text
"Publish diagnostics notification" (Session (NotificationMessage 'TextDocumentPublishDiagnostics)
 -> Session (NotificationMessage 'TextDocumentPublishDiagnostics))
-> Session (NotificationMessage 'TextDocumentPublishDiagnostics)
-> Session (NotificationMessage 'TextDocumentPublishDiagnostics)
forall a b. (a -> b) -> a -> b
$
  (FromServerMessage
 -> Maybe (NotificationMessage 'TextDocumentPublishDiagnostics))
-> Session (NotificationMessage 'TextDocumentPublishDiagnostics)
forall a. (FromServerMessage -> Maybe a) -> Session a
satisfyMaybe ((FromServerMessage
  -> Maybe (NotificationMessage 'TextDocumentPublishDiagnostics))
 -> Session (NotificationMessage 'TextDocumentPublishDiagnostics))
-> (FromServerMessage
    -> Maybe (NotificationMessage 'TextDocumentPublishDiagnostics))
-> Session (NotificationMessage 'TextDocumentPublishDiagnostics)
forall a b. (a -> b) -> a -> b
$ \FromServerMessage
msg -> case FromServerMessage
msg of
    FromServerMess SMethod m
STextDocumentPublishDiagnostics Message m
diags -> NotificationMessage 'TextDocumentPublishDiagnostics
-> Maybe (NotificationMessage 'TextDocumentPublishDiagnostics)
forall a. a -> Maybe a
Just Message m
NotificationMessage 'TextDocumentPublishDiagnostics
diags
    FromServerMessage
_ -> Maybe (NotificationMessage 'TextDocumentPublishDiagnostics)
forall a. Maybe a
Nothing