{-# LANGUAGE DeriveAnyClass     #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GADTs              #-}
-- | A plugin that adds custom messages for use in tests
module Development.IDE.Plugin.Test
  ( TestRequest(..)
  , WaitForIdeRuleResult(..)
  , plugin
  , blockCommandDescriptor
  , blockCommandId
  ) where

import           Control.Concurrent             (threadDelay)
import           Control.Monad
import           Control.Monad.IO.Class
import           Control.Monad.STM
import           Data.Aeson
import           Data.Aeson.Types
import           Data.Bifunctor
import           Data.CaseInsensitive           (CI, original)
import           Data.Maybe                     (isJust)
import           Data.String
import           Data.Text                      (Text, pack)
import           Development.IDE.Core.RuleTypes
import           Development.IDE.Core.Service
import           Development.IDE.Core.Shake
import           Development.IDE.GHC.Compat
import           Development.IDE.LSP.Server
import           Development.IDE.Plugin
import           Development.IDE.Types.Action
import           Development.IDE.Types.HscEnvEq (HscEnvEq (hscEnv))
import           Development.IDE.Types.Location (fromUri)
import           Development.Shake              (Action)
import           GHC.Generics                   (Generic)
import           GhcPlugins                     (HscEnv (hsc_dflags))
import           Ide.Types
import qualified Language.LSP.Server            as LSP
import           Language.LSP.Types
import           System.Time.Extra

data TestRequest
    = BlockSeconds Seconds           -- ^ :: Null
    | GetInterfaceFilesDir FilePath  -- ^ :: String
    | GetShakeSessionQueueCount      -- ^ :: Number
    | WaitForShakeQueue -- ^ Block until the Shake queue is empty. Returns Null
    | WaitForIdeRule String Uri      -- ^ :: WaitForIdeRuleResult
    deriving (forall x. TestRequest -> Rep TestRequest x)
-> (forall x. Rep TestRequest x -> TestRequest)
-> Generic TestRequest
forall x. Rep TestRequest x -> TestRequest
forall x. TestRequest -> Rep TestRequest x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TestRequest x -> TestRequest
$cfrom :: forall x. TestRequest -> Rep TestRequest x
Generic
    deriving anyclass (Value -> Parser [TestRequest]
Value -> Parser TestRequest
(Value -> Parser TestRequest)
-> (Value -> Parser [TestRequest]) -> FromJSON TestRequest
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [TestRequest]
$cparseJSONList :: Value -> Parser [TestRequest]
parseJSON :: Value -> Parser TestRequest
$cparseJSON :: Value -> Parser TestRequest
FromJSON, [TestRequest] -> Encoding
[TestRequest] -> Value
TestRequest -> Encoding
TestRequest -> Value
(TestRequest -> Value)
-> (TestRequest -> Encoding)
-> ([TestRequest] -> Value)
-> ([TestRequest] -> Encoding)
-> ToJSON TestRequest
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [TestRequest] -> Encoding
$ctoEncodingList :: [TestRequest] -> Encoding
toJSONList :: [TestRequest] -> Value
$ctoJSONList :: [TestRequest] -> Value
toEncoding :: TestRequest -> Encoding
$ctoEncoding :: TestRequest -> Encoding
toJSON :: TestRequest -> Value
$ctoJSON :: TestRequest -> Value
ToJSON)

newtype WaitForIdeRuleResult = WaitForIdeRuleResult { WaitForIdeRuleResult -> Bool
ideResultSuccess::Bool}
    deriving newtype (Value -> Parser [WaitForIdeRuleResult]
Value -> Parser WaitForIdeRuleResult
(Value -> Parser WaitForIdeRuleResult)
-> (Value -> Parser [WaitForIdeRuleResult])
-> FromJSON WaitForIdeRuleResult
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [WaitForIdeRuleResult]
$cparseJSONList :: Value -> Parser [WaitForIdeRuleResult]
parseJSON :: Value -> Parser WaitForIdeRuleResult
$cparseJSON :: Value -> Parser WaitForIdeRuleResult
FromJSON, [WaitForIdeRuleResult] -> Encoding
[WaitForIdeRuleResult] -> Value
WaitForIdeRuleResult -> Encoding
WaitForIdeRuleResult -> Value
(WaitForIdeRuleResult -> Value)
-> (WaitForIdeRuleResult -> Encoding)
-> ([WaitForIdeRuleResult] -> Value)
-> ([WaitForIdeRuleResult] -> Encoding)
-> ToJSON WaitForIdeRuleResult
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [WaitForIdeRuleResult] -> Encoding
$ctoEncodingList :: [WaitForIdeRuleResult] -> Encoding
toJSONList :: [WaitForIdeRuleResult] -> Value
$ctoJSONList :: [WaitForIdeRuleResult] -> Value
toEncoding :: WaitForIdeRuleResult -> Encoding
$ctoEncoding :: WaitForIdeRuleResult -> Encoding
toJSON :: WaitForIdeRuleResult -> Value
$ctoJSON :: WaitForIdeRuleResult -> Value
ToJSON)

plugin :: Plugin c
plugin :: Plugin c
plugin = Plugin :: forall c. Rules () -> Handlers (ServerM c) -> Plugin c
Plugin {
    pluginRules :: Rules ()
pluginRules = () -> Rules ()
forall (m :: * -> *) a. Monad m => a -> m a
return (),
    pluginHandlers :: Handlers (ServerM c)
pluginHandlers = SMethod 'CustomMethod
-> (IdeState
    -> MessageParams 'CustomMethod
    -> LspM c (Either ResponseError (ResponseResult 'CustomMethod)))
-> Handlers (ServerM c)
forall (m :: Method 'FromClient 'Request) c.
HasTracing (MessageParams m) =>
SMethod m
-> (IdeState
    -> MessageParams m
    -> LspM c (Either ResponseError (ResponseResult m)))
-> Handlers (ServerM c)
requestHandler (Text -> SMethod 'CustomMethod
forall (f :: From) (t :: MethodType). Text -> SMethod 'CustomMethod
SCustomMethod Text
"test") IdeState
-> MessageParams 'CustomMethod
-> LspM c (Either ResponseError (ResponseResult 'CustomMethod))
forall c. IdeState -> Value -> LspM c (Either ResponseError Value)
testRequestHandler'
}
  where
      testRequestHandler' :: IdeState -> Value -> LspM c (Either ResponseError Value)
testRequestHandler' IdeState
ide Value
req
        | Just TestRequest
customReq <- (Value -> Parser TestRequest) -> Value -> Maybe TestRequest
forall a b. (a -> Parser b) -> a -> Maybe b
parseMaybe Value -> Parser TestRequest
forall a. FromJSON a => Value -> Parser a
parseJSON Value
req
        = IdeState -> TestRequest -> LspM c (Either ResponseError Value)
forall c.
IdeState -> TestRequest -> LspM c (Either ResponseError Value)
testRequestHandler IdeState
ide TestRequest
customReq
        | Bool
otherwise
        = Either ResponseError Value -> LspM c (Either ResponseError Value)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either ResponseError Value -> LspM c (Either ResponseError Value))
-> Either ResponseError Value
-> LspM c (Either ResponseError Value)
forall a b. (a -> b) -> a -> b
$ ResponseError -> Either ResponseError Value
forall a b. a -> Either a b
Left
        (ResponseError -> Either ResponseError Value)
-> ResponseError -> Either ResponseError Value
forall a b. (a -> b) -> a -> b
$ ErrorCode -> Text -> Maybe Value -> ResponseError
ResponseError ErrorCode
InvalidRequest Text
"Cannot parse request" Maybe Value
forall a. Maybe a
Nothing


testRequestHandler ::  IdeState
                -> TestRequest
                -> LSP.LspM c (Either ResponseError Value)
testRequestHandler :: IdeState -> TestRequest -> LspM c (Either ResponseError Value)
testRequestHandler IdeState
_ (BlockSeconds Seconds
secs) = do
    SServerMethod 'CustomMethod
-> MessageParams 'CustomMethod -> LspT c IO ()
forall (m :: Method 'FromServer 'Notification) (f :: * -> *)
       config.
MonadLsp config f =>
SServerMethod m -> MessageParams m -> f ()
LSP.sendNotification (Text -> SServerMethod 'CustomMethod
forall (f :: From) (t :: MethodType). Text -> SMethod 'CustomMethod
SCustomMethod Text
"ghcide/blocking/request") (MessageParams 'CustomMethod -> LspT c IO ())
-> MessageParams 'CustomMethod -> LspT c IO ()
forall a b. (a -> b) -> a -> b
$
      Seconds -> Value
forall a. ToJSON a => a -> Value
toJSON Seconds
secs
    IO () -> LspT c IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> LspT c IO ()) -> IO () -> LspT c IO ()
forall a b. (a -> b) -> a -> b
$ Seconds -> IO ()
sleep Seconds
secs
    return (Value -> Either ResponseError Value
forall a b. b -> Either a b
Right Value
Null)
testRequestHandler IdeState
s (GetInterfaceFilesDir FilePath
fp) = IO (Either ResponseError Value)
-> LspM c (Either ResponseError Value)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either ResponseError Value)
 -> LspM c (Either ResponseError Value))
-> IO (Either ResponseError Value)
-> LspM c (Either ResponseError Value)
forall a b. (a -> b) -> a -> b
$ do
    let nfp :: NormalizedFilePath
nfp = FilePath -> NormalizedFilePath
toNormalizedFilePath FilePath
fp
    HscEnvEq
sess <- FilePath -> IdeState -> Action HscEnvEq -> IO HscEnvEq
forall a. FilePath -> IdeState -> Action a -> IO a
runAction FilePath
"Test - GhcSession" IdeState
s (Action HscEnvEq -> IO HscEnvEq) -> Action HscEnvEq -> IO HscEnvEq
forall a b. (a -> b) -> a -> b
$ GhcSession -> NormalizedFilePath -> Action HscEnvEq
forall k v. IdeRule k v => k -> NormalizedFilePath -> Action v
use_ GhcSession
GhcSession NormalizedFilePath
nfp
    let hiPath :: Maybe FilePath
hiPath = DynFlags -> Maybe FilePath
hiDir (DynFlags -> Maybe FilePath) -> DynFlags -> Maybe FilePath
forall a b. (a -> b) -> a -> b
$ HscEnv -> DynFlags
hsc_dflags (HscEnv -> DynFlags) -> HscEnv -> DynFlags
forall a b. (a -> b) -> a -> b
$ HscEnvEq -> HscEnv
hscEnv HscEnvEq
sess
    Either ResponseError Value -> IO (Either ResponseError Value)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either ResponseError Value -> IO (Either ResponseError Value))
-> Either ResponseError Value -> IO (Either ResponseError Value)
forall a b. (a -> b) -> a -> b
$ Value -> Either ResponseError Value
forall a b. b -> Either a b
Right (Maybe FilePath -> Value
forall a. ToJSON a => a -> Value
toJSON Maybe FilePath
hiPath)
testRequestHandler IdeState
s TestRequest
GetShakeSessionQueueCount = IO (Either ResponseError Value)
-> LspM c (Either ResponseError Value)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either ResponseError Value)
 -> LspM c (Either ResponseError Value))
-> IO (Either ResponseError Value)
-> LspM c (Either ResponseError Value)
forall a b. (a -> b) -> a -> b
$ do
    Natural
n <- STM Natural -> IO Natural
forall a. STM a -> IO a
atomically (STM Natural -> IO Natural) -> STM Natural -> IO Natural
forall a b. (a -> b) -> a -> b
$ ActionQueue -> STM Natural
countQueue (ActionQueue -> STM Natural) -> ActionQueue -> STM Natural
forall a b. (a -> b) -> a -> b
$ ShakeExtras -> ActionQueue
actionQueue (ShakeExtras -> ActionQueue) -> ShakeExtras -> ActionQueue
forall a b. (a -> b) -> a -> b
$ IdeState -> ShakeExtras
shakeExtras IdeState
s
    return $ Value -> Either ResponseError Value
forall a b. b -> Either a b
Right (Natural -> Value
forall a. ToJSON a => a -> Value
toJSON Natural
n)
testRequestHandler IdeState
s TestRequest
WaitForShakeQueue = IO (Either ResponseError Value)
-> LspM c (Either ResponseError Value)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either ResponseError Value)
 -> LspM c (Either ResponseError Value))
-> IO (Either ResponseError Value)
-> LspM c (Either ResponseError Value)
forall a b. (a -> b) -> a -> b
$ do
    STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        Natural
n <- ActionQueue -> STM Natural
countQueue (ActionQueue -> STM Natural) -> ActionQueue -> STM Natural
forall a b. (a -> b) -> a -> b
$ ShakeExtras -> ActionQueue
actionQueue (ShakeExtras -> ActionQueue) -> ShakeExtras -> ActionQueue
forall a b. (a -> b) -> a -> b
$ IdeState -> ShakeExtras
shakeExtras IdeState
s
        Bool -> STM () -> STM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Natural
nNatural -> Natural -> Bool
forall a. Ord a => a -> a -> Bool
>Natural
0) STM ()
forall a. STM a
retry
    return $ Value -> Either ResponseError Value
forall a b. b -> Either a b
Right Value
Null
testRequestHandler IdeState
s (WaitForIdeRule FilePath
k Uri
file) = IO (Either ResponseError Value)
-> LspM c (Either ResponseError Value)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either ResponseError Value)
 -> LspM c (Either ResponseError Value))
-> IO (Either ResponseError Value)
-> LspM c (Either ResponseError Value)
forall a b. (a -> b) -> a -> b
$ do
    let nfp :: NormalizedFilePath
nfp = NormalizedUri -> NormalizedFilePath
fromUri (NormalizedUri -> NormalizedFilePath)
-> NormalizedUri -> NormalizedFilePath
forall a b. (a -> b) -> a -> b
$ Uri -> NormalizedUri
toNormalizedUri Uri
file
    Either Text Bool
success <- FilePath
-> IdeState -> Action (Either Text Bool) -> IO (Either Text Bool)
forall a. FilePath -> IdeState -> Action a -> IO a
runAction (FilePath
"WaitForIdeRule " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
k FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
" " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> Uri -> FilePath
forall a. Show a => a -> FilePath
show Uri
file) IdeState
s (Action (Either Text Bool) -> IO (Either Text Bool))
-> Action (Either Text Bool) -> IO (Either Text Bool)
forall a b. (a -> b) -> a -> b
$ CI FilePath -> NormalizedFilePath -> Action (Either Text Bool)
parseAction (FilePath -> CI FilePath
forall a. IsString a => FilePath -> a
fromString FilePath
k) NormalizedFilePath
nfp
    let res :: Either Text WaitForIdeRuleResult
res = Bool -> WaitForIdeRuleResult
WaitForIdeRuleResult (Bool -> WaitForIdeRuleResult)
-> Either Text Bool -> Either Text WaitForIdeRuleResult
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Either Text Bool
success
    Either ResponseError Value -> IO (Either ResponseError Value)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either ResponseError Value -> IO (Either ResponseError Value))
-> Either ResponseError Value -> IO (Either ResponseError Value)
forall a b. (a -> b) -> a -> b
$ (Text -> ResponseError)
-> (WaitForIdeRuleResult -> Value)
-> Either Text WaitForIdeRuleResult
-> Either ResponseError Value
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap Text -> ResponseError
mkResponseError WaitForIdeRuleResult -> Value
forall a. ToJSON a => a -> Value
toJSON Either Text WaitForIdeRuleResult
res

mkResponseError :: Text -> ResponseError
mkResponseError :: Text -> ResponseError
mkResponseError Text
msg = ErrorCode -> Text -> Maybe Value -> ResponseError
ResponseError ErrorCode
InvalidRequest Text
msg Maybe Value
forall a. Maybe a
Nothing

parseAction :: CI String -> NormalizedFilePath -> Action (Either Text Bool)
parseAction :: CI FilePath -> NormalizedFilePath -> Action (Either Text Bool)
parseAction CI FilePath
"typecheck" NormalizedFilePath
fp = Bool -> Either Text Bool
forall a b. b -> Either a b
Right (Bool -> Either Text Bool)
-> (Maybe TcModuleResult -> Bool)
-> Maybe TcModuleResult
-> Either Text Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe TcModuleResult -> Bool
forall a. Maybe a -> Bool
isJust (Maybe TcModuleResult -> Either Text Bool)
-> Action (Maybe TcModuleResult) -> Action (Either Text Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TypeCheck -> NormalizedFilePath -> Action (Maybe TcModuleResult)
forall k v.
IdeRule k v =>
k -> NormalizedFilePath -> Action (Maybe v)
use TypeCheck
TypeCheck NormalizedFilePath
fp
parseAction CI FilePath
"getLocatedImports" NormalizedFilePath
fp = Bool -> Either Text Bool
forall a b. b -> Either a b
Right (Bool -> Either Text Bool)
-> (Maybe [(Located ModuleName, Maybe ArtifactsLocation)] -> Bool)
-> Maybe [(Located ModuleName, Maybe ArtifactsLocation)]
-> Either Text Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe [(Located ModuleName, Maybe ArtifactsLocation)] -> Bool
forall a. Maybe a -> Bool
isJust (Maybe [(Located ModuleName, Maybe ArtifactsLocation)]
 -> Either Text Bool)
-> Action (Maybe [(Located ModuleName, Maybe ArtifactsLocation)])
-> Action (Either Text Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GetLocatedImports
-> NormalizedFilePath
-> Action (Maybe [(Located ModuleName, Maybe ArtifactsLocation)])
forall k v.
IdeRule k v =>
k -> NormalizedFilePath -> Action (Maybe v)
use GetLocatedImports
GetLocatedImports NormalizedFilePath
fp
parseAction CI FilePath
"getmodsummary" NormalizedFilePath
fp = Bool -> Either Text Bool
forall a b. b -> Either a b
Right (Bool -> Either Text Bool)
-> (Maybe ModSummaryResult -> Bool)
-> Maybe ModSummaryResult
-> Either Text Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe ModSummaryResult -> Bool
forall a. Maybe a -> Bool
isJust (Maybe ModSummaryResult -> Either Text Bool)
-> Action (Maybe ModSummaryResult) -> Action (Either Text Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GetModSummary
-> NormalizedFilePath -> Action (Maybe ModSummaryResult)
forall k v.
IdeRule k v =>
k -> NormalizedFilePath -> Action (Maybe v)
use GetModSummary
GetModSummary NormalizedFilePath
fp
parseAction CI FilePath
"getmodsummarywithouttimestamps" NormalizedFilePath
fp = Bool -> Either Text Bool
forall a b. b -> Either a b
Right (Bool -> Either Text Bool)
-> (Maybe ModSummaryResult -> Bool)
-> Maybe ModSummaryResult
-> Either Text Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe ModSummaryResult -> Bool
forall a. Maybe a -> Bool
isJust (Maybe ModSummaryResult -> Either Text Bool)
-> Action (Maybe ModSummaryResult) -> Action (Either Text Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GetModSummaryWithoutTimestamps
-> NormalizedFilePath -> Action (Maybe ModSummaryResult)
forall k v.
IdeRule k v =>
k -> NormalizedFilePath -> Action (Maybe v)
use GetModSummaryWithoutTimestamps
GetModSummaryWithoutTimestamps NormalizedFilePath
fp
parseAction CI FilePath
"getparsedmodule" NormalizedFilePath
fp = Bool -> Either Text Bool
forall a b. b -> Either a b
Right (Bool -> Either Text Bool)
-> (Maybe ParsedModule -> Bool)
-> Maybe ParsedModule
-> Either Text Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe ParsedModule -> Bool
forall a. Maybe a -> Bool
isJust (Maybe ParsedModule -> Either Text Bool)
-> Action (Maybe ParsedModule) -> Action (Either Text Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GetParsedModule
-> NormalizedFilePath -> Action (Maybe ParsedModule)
forall k v.
IdeRule k v =>
k -> NormalizedFilePath -> Action (Maybe v)
use GetParsedModule
GetParsedModule NormalizedFilePath
fp
parseAction CI FilePath
"ghcsession" NormalizedFilePath
fp = Bool -> Either Text Bool
forall a b. b -> Either a b
Right (Bool -> Either Text Bool)
-> (Maybe HscEnvEq -> Bool) -> Maybe HscEnvEq -> Either Text Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe HscEnvEq -> Bool
forall a. Maybe a -> Bool
isJust (Maybe HscEnvEq -> Either Text Bool)
-> Action (Maybe HscEnvEq) -> Action (Either Text Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GhcSession -> NormalizedFilePath -> Action (Maybe HscEnvEq)
forall k v.
IdeRule k v =>
k -> NormalizedFilePath -> Action (Maybe v)
use GhcSession
GhcSession NormalizedFilePath
fp
parseAction CI FilePath
"ghcsessiondeps" NormalizedFilePath
fp = Bool -> Either Text Bool
forall a b. b -> Either a b
Right (Bool -> Either Text Bool)
-> (Maybe HscEnvEq -> Bool) -> Maybe HscEnvEq -> Either Text Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe HscEnvEq -> Bool
forall a. Maybe a -> Bool
isJust (Maybe HscEnvEq -> Either Text Bool)
-> Action (Maybe HscEnvEq) -> Action (Either Text Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GhcSessionDeps -> NormalizedFilePath -> Action (Maybe HscEnvEq)
forall k v.
IdeRule k v =>
k -> NormalizedFilePath -> Action (Maybe v)
use GhcSessionDeps
GhcSessionDeps NormalizedFilePath
fp
parseAction CI FilePath
"gethieast" NormalizedFilePath
fp = Bool -> Either Text Bool
forall a b. b -> Either a b
Right (Bool -> Either Text Bool)
-> (Maybe HieAstResult -> Bool)
-> Maybe HieAstResult
-> Either Text Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe HieAstResult -> Bool
forall a. Maybe a -> Bool
isJust (Maybe HieAstResult -> Either Text Bool)
-> Action (Maybe HieAstResult) -> Action (Either Text Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GetHieAst -> NormalizedFilePath -> Action (Maybe HieAstResult)
forall k v.
IdeRule k v =>
k -> NormalizedFilePath -> Action (Maybe v)
use GetHieAst
GetHieAst NormalizedFilePath
fp
parseAction CI FilePath
"getDependencies" NormalizedFilePath
fp = Bool -> Either Text Bool
forall a b. b -> Either a b
Right (Bool -> Either Text Bool)
-> (Maybe TransitiveDependencies -> Bool)
-> Maybe TransitiveDependencies
-> Either Text Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe TransitiveDependencies -> Bool
forall a. Maybe a -> Bool
isJust (Maybe TransitiveDependencies -> Either Text Bool)
-> Action (Maybe TransitiveDependencies)
-> Action (Either Text Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GetDependencies
-> NormalizedFilePath -> Action (Maybe TransitiveDependencies)
forall k v.
IdeRule k v =>
k -> NormalizedFilePath -> Action (Maybe v)
use GetDependencies
GetDependencies NormalizedFilePath
fp
parseAction CI FilePath
"getFileContents" NormalizedFilePath
fp = Bool -> Either Text Bool
forall a b. b -> Either a b
Right (Bool -> Either Text Bool)
-> (Maybe (FileVersion, Maybe Text) -> Bool)
-> Maybe (FileVersion, Maybe Text)
-> Either Text Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (FileVersion, Maybe Text) -> Bool
forall a. Maybe a -> Bool
isJust (Maybe (FileVersion, Maybe Text) -> Either Text Bool)
-> Action (Maybe (FileVersion, Maybe Text))
-> Action (Either Text Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GetFileContents
-> NormalizedFilePath -> Action (Maybe (FileVersion, Maybe Text))
forall k v.
IdeRule k v =>
k -> NormalizedFilePath -> Action (Maybe v)
use GetFileContents
GetFileContents NormalizedFilePath
fp
parseAction CI FilePath
other NormalizedFilePath
_ = Either Text Bool -> Action (Either Text Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either Text Bool -> Action (Either Text Bool))
-> Either Text Bool -> Action (Either Text Bool)
forall a b. (a -> b) -> a -> b
$ Text -> Either Text Bool
forall a b. a -> Either a b
Left (Text -> Either Text Bool) -> Text -> Either Text Bool
forall a b. (a -> b) -> a -> b
$ Text
"Cannot parse ide rule: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> FilePath -> Text
pack (CI FilePath -> FilePath
forall s. CI s -> s
original CI FilePath
other)

-- | a command that blocks forever. Used for testing
blockCommandId :: Text
blockCommandId :: Text
blockCommandId = Text
"ghcide.command.block"

blockCommandDescriptor :: PluginId -> PluginDescriptor state
blockCommandDescriptor :: PluginId -> PluginDescriptor state
blockCommandDescriptor PluginId
plId = (PluginId -> PluginDescriptor state
forall ideState. PluginId -> PluginDescriptor ideState
defaultPluginDescriptor PluginId
plId) {
    pluginCommands :: [PluginCommand state]
pluginCommands = [CommandId
-> Text
-> CommandFunction state ExecuteCommandParams
-> PluginCommand state
forall ideState a.
FromJSON a =>
CommandId
-> Text -> CommandFunction ideState a -> PluginCommand ideState
PluginCommand (Text -> CommandId
CommandId Text
blockCommandId) Text
"blocks forever" CommandFunction state ExecuteCommandParams
forall state. CommandFunction state ExecuteCommandParams
blockCommandHandler]
}

blockCommandHandler :: CommandFunction state ExecuteCommandParams
blockCommandHandler :: CommandFunction state ExecuteCommandParams
blockCommandHandler state
_ideState ExecuteCommandParams
_params = do
  SServerMethod 'CustomMethod
-> MessageParams 'CustomMethod -> LspT Config IO ()
forall (m :: Method 'FromServer 'Notification) (f :: * -> *)
       config.
MonadLsp config f =>
SServerMethod m -> MessageParams m -> f ()
LSP.sendNotification (Text -> SServerMethod 'CustomMethod
forall (f :: From) (t :: MethodType). Text -> SMethod 'CustomMethod
SCustomMethod Text
"ghcide/blocking/command") Value
MessageParams 'CustomMethod
Null
  IO () -> LspT Config IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> LspT Config IO ()) -> IO () -> LspT Config IO ()
forall a b. (a -> b) -> a -> b
$ Int -> IO ()
threadDelay Int
forall a. Bounded a => a
maxBound
  return (Value -> Either ResponseError Value
forall a b. b -> Either a b
Right Value
Null)