{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveGeneric #-}
module Server
( run
) where
import qualified Agda
import Control.Concurrent ( writeChan )
import Control.Monad.Reader ( MonadIO(liftIO)
, void
)
import Data.Aeson ( FromJSON
, ToJSON
)
import qualified Data.Aeson as JSON
import Data.Text ( pack )
import GHC.IO.IOMode ( IOMode(ReadWriteMode) )
import Language.LSP.Server hiding ( Options )
import Language.LSP.Types hiding ( Options(..)
, TextDocumentSyncClientCapabilities(..)
)
import Monad
import qualified Network.Simple.TCP as TCP
import Network.Socket ( socketToHandle )
import qualified Switchboard
import Switchboard ( Switchboard )
import qualified Server.Handler as Handler
import qualified Language.LSP.Server as LSP
import Options
run :: Options -> IO Int
run :: Options -> IO Int
run Options
options = do
case Options -> Maybe Int
optViaTCP Options
options of
Just Int
port -> do
forall (f :: * -> *) a. Functor f => f a -> f ()
void
forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
MonadIO m =>
HostPreference -> String -> ((Socket, SockAddr) -> IO ()) -> m a
TCP.serve (String -> HostPreference
TCP.Host String
"127.0.0.1") (forall a. Show a => a -> String
show Int
port)
forall a b. (a -> b) -> a -> b
$ \(Socket
sock, SockAddr
_remoteAddr) -> do
Handle
handle <- Socket -> IOMode -> IO Handle
socketToHandle Socket
sock IOMode
ReadWriteMode
Int
_ <- forall config.
LogAction IO (WithSeverity LspServerLog)
-> LogAction (LspM config) (WithSeverity LspServerLog)
-> Handle
-> Handle
-> ServerDefinition config
-> IO Int
runServerWithHandles
#if MIN_VERSION_lsp(1,5,0)
forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty
#endif
Handle
handle Handle
handle (Options -> ServerDefinition Config
serverDefn Options
options)
forall (m :: * -> *) a. Monad m => a -> m a
return ()
forall (m :: * -> *) a. Monad m => a -> m a
return Int
0
Maybe Int
Nothing -> do
forall config. ServerDefinition config -> IO Int
runServer (Options -> ServerDefinition Config
serverDefn Options
options)
where
serverDefn :: Options -> ServerDefinition Config
serverDefn :: Options -> ServerDefinition Config
serverDefn Options
options = ServerDefinition
{ defaultConfig :: Config
defaultConfig = Config
initConfig
, onConfigurationChange :: Config -> Value -> Either Text Config
onConfigurationChange = \Config
old Value
newRaw -> case forall a. FromJSON a => Value -> Result a
JSON.fromJSON Value
newRaw of
JSON.Error String
s -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ String -> Text
pack forall a b. (a -> b) -> a -> b
$ String
"Cannot parse server configuration: " forall a. Semigroup a => a -> a -> a
<> String
s
JSON.Success Config
new -> forall a b. b -> Either a b
Right Config
new
, doInitialize :: LanguageContextEnv Config
-> Message 'Initialize
-> IO (Either ResponseError (LanguageContextEnv Config, Env))
doInitialize = \LanguageContextEnv Config
ctxEnv Message 'Initialize
_req -> do
Env
env <- forall config (m :: * -> *) a.
LanguageContextEnv config -> LspT config m a -> m a
runLspT LanguageContextEnv Config
ctxEnv (forall (m :: * -> *).
(MonadIO m, MonadLsp Config m) =>
Options -> m Env
createInitEnv Options
options)
Switchboard
switchboard <- Env -> IO Switchboard
Switchboard.new Env
env
Switchboard -> LanguageContextEnv Config -> IO ()
Switchboard.setupLanguageContextEnv Switchboard
switchboard LanguageContextEnv Config
ctxEnv
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right (LanguageContextEnv Config
ctxEnv, Env
env)
, staticHandlers :: Handlers (ServerM (LspM Config))
staticHandlers = Handlers (ServerM (LspM Config))
handlers
, interpretHandler :: (LanguageContextEnv Config, Env) -> ServerM (LspM Config) <~> IO
interpretHandler = \(LanguageContextEnv Config
ctxEnv, Env
env) ->
forall {k} (m :: k -> *) (n :: k -> *).
(forall (a :: k). m a -> n a)
-> (forall (a :: k). n a -> m a) -> m <~> n
Iso (forall config (m :: * -> *) a.
LanguageContextEnv config -> LspT config m a -> m a
runLspT LanguageContextEnv Config
ctxEnv forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. Env -> ServerM m a -> m a
runServerM Env
env) forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO
, options :: Options
options = Options
lspOptions
}
lspOptions :: LSP.Options
lspOptions :: Options
lspOptions = Options
defaultOptions { textDocumentSync :: Maybe TextDocumentSyncOptions
textDocumentSync = forall a. a -> Maybe a
Just TextDocumentSyncOptions
syncOptions }
syncOptions :: TextDocumentSyncOptions
syncOptions :: TextDocumentSyncOptions
syncOptions = TextDocumentSyncOptions { $sel:_openClose:TextDocumentSyncOptions :: Maybe Bool
_openClose = forall a. a -> Maybe a
Just Bool
True
, $sel:_change:TextDocumentSyncOptions :: Maybe TextDocumentSyncKind
_change = forall a. a -> Maybe a
Just TextDocumentSyncKind
changeOptions
, $sel:_willSave:TextDocumentSyncOptions :: Maybe Bool
_willSave = forall a. a -> Maybe a
Just Bool
False
, $sel:_willSaveWaitUntil:TextDocumentSyncOptions :: Maybe Bool
_willSaveWaitUntil = forall a. a -> Maybe a
Just Bool
False
, $sel:_save:TextDocumentSyncOptions :: Maybe (Bool |? SaveOptions)
_save = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a b. b -> a |? b
InR SaveOptions
saveOptions
}
changeOptions :: TextDocumentSyncKind
changeOptions :: TextDocumentSyncKind
changeOptions = TextDocumentSyncKind
TdSyncIncremental
saveOptions :: SaveOptions
saveOptions :: SaveOptions
saveOptions = Maybe Bool -> SaveOptions
SaveOptions (forall a. a -> Maybe a
Just Bool
True)
handlers :: Handlers (ServerM (LspM Config))
handlers :: Handlers (ServerM (LspM Config))
handlers = forall a. Monoid a => [a] -> a
mconcat
[
forall (m :: Method 'FromClient 'Request) (f :: * -> *).
SMethod m -> Handler f m -> Handlers f
requestHandler (forall {f :: From} {t :: MethodType}. Text -> SMethod 'CustomMethod
SCustomMethod Text
"agda") forall a b. (a -> b) -> a -> b
$ \RequestMessage 'CustomMethod
req Either ResponseError Value -> ReaderT Env (LspM Config) ()
responder -> do
let RequestMessage Text
_ LspId 'CustomMethod
_i SMethod 'CustomMethod
_ MessageParams 'CustomMethod
params = RequestMessage 'CustomMethod
req
Value
response <- forall (m :: * -> *). MonadIO m => Value -> ServerM m Value
Agda.sendCommand MessageParams 'CustomMethod
params
Either ResponseError Value -> ReaderT Env (LspM Config) ()
responder forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right Value
response
,
forall (m :: Method 'FromClient 'Request) (f :: * -> *).
SMethod m -> Handler f m -> Handlers f
requestHandler SMethod 'TextDocumentHover
STextDocumentHover forall a b. (a -> b) -> a -> b
$ \RequestMessage 'TextDocumentHover
req Either ResponseError (Maybe Hover) -> ReaderT Env (LspM Config) ()
responder -> do
let
RequestMessage Text
_ LspId 'TextDocumentHover
_ SMethod 'TextDocumentHover
_ (HoverParams (TextDocumentIdentifier Uri
uri) Position
pos Maybe ProgressToken
_workDone)
= RequestMessage 'TextDocumentHover
req
Maybe Hover
result <- Uri -> Position -> ServerM (LspM Config) (Maybe Hover)
Handler.onHover Uri
uri Position
pos
Either ResponseError (Maybe Hover) -> ReaderT Env (LspM Config) ()
responder forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right Maybe Hover
result
]