{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE LambdaCase #-} module Main where import qualified Language.Haskell.LSP.TH.DataTypesJSON as LSP import qualified Language.Haskell.LSP.TH.ClientCapabilities as LSP import Data.Proxy import qualified Data.Text.IO as T import Control.Concurrent import System.Process import Control.Lens import System.IO import System.Exit import System.Environment import System.Directory import Control.Monad import qualified LSP.Client as Client import qualified Compat main :: IO () main = do progName <- getProgName args <- getArgs when (length args /= 1) $ do hPutStrLn stderr ("This program expects one argument: " ++ progName ++ " FILEPATH") exitFailure let [path] = args exists <- doesFileExist path when (not exists) $ do hPutStrLn stderr ("File does not exist: " ++ path) exitFailure file <- canonicalizePath path pid <- Compat.getPID let caps = LSP.ClientCapabilities (Just workspaceCaps) (Just textDocumentCaps) Nothing workspaceCaps = LSP.WorkspaceClientCapabilities (Just False) (Just (LSP.WorkspaceEditClientCapabilities (Just False))) (Just (LSP.DidChangeConfigurationClientCapabilities (Just False))) (Just (LSP.DidChangeWatchedFilesClientCapabilities (Just False))) (Just (LSP.SymbolClientCapabilities (Just False))) (Just (LSP.ExecuteClientCapabilities (Just False))) textDocumentCaps = LSP.TextDocumentClientCapabilities (Just (LSP.SynchronizationTextDocumentClientCapabilities (Just False) (Just False) (Just False) (Just False))) (Just (LSP.CompletionClientCapabilities (Just False) (Just (LSP.CompletionItemClientCapabilities (Just False))))) (Just (LSP.HoverClientCapabilities (Just False))) (Just (LSP.SignatureHelpClientCapabilities (Just False))) (Just (LSP.ReferencesClientCapabilities (Just False))) (Just (LSP.DocumentHighlightClientCapabilities (Just False))) (Just (LSP.DocumentSymbolClientCapabilities (Just False))) (Just (LSP.FormattingClientCapabilities (Just False))) (Just (LSP.RangeFormattingClientCapabilities (Just False))) (Just (LSP.OnTypeFormattingClientCapabilities (Just False))) (Just (LSP.DefinitionClientCapabilities (Just False))) (Just (LSP.CodeActionClientCapabilities (Just False))) (Just (LSP.CodeLensClientCapabilities (Just False))) (Just (LSP.DocumentLinkClientCapabilities (Just False))) (Just (LSP.RenameClientCapabilities (Just False))) initializeParams :: LSP.InitializeParams initializeParams = LSP.InitializeParams (Just pid) Nothing Nothing Nothing caps Nothing (Just inp, Just out, _, _) <- createProcess (proc "hie" ["--lsp"]) {std_in = CreatePipe, std_out = CreatePipe, std_err = CreatePipe} reqVar <- Client.start (Client.Config inp out testNotificationMessageHandler testRequestMessageHandler) Client.sendClientRequest (Proxy :: Proxy LSP.InitializeRequest) reqVar LSP.Initialize initializeParams -- >>= print Client.sendClientNotification reqVar LSP.Initialized (Just LSP.InitializedParams) txt <- T.readFile file let uri = LSP.filePathToUri file Client.sendClientNotification reqVar LSP.TextDocumentDidOpen (Just (LSP.DidOpenTextDocumentParams (LSP.TextDocumentItem uri "haskell" 1 txt))) Client.sendClientRequest (Proxy :: Proxy LSP.DocumentSymbolRequest) reqVar LSP.TextDocumentDocumentSymbol (LSP.DocumentSymbolParams (LSP.TextDocumentIdentifier uri)) >>= \case Just (Right as) -> mapM_ T.putStrLn (as ^.. traverse . LSP.name) _ -> putStrLn "Server couldn't give us document symbol information" Client.sendClientRequest (Proxy :: Proxy LSP.ShutdownRequest) reqVar LSP.Shutdown Nothing -- >>= print Client.sendClientNotification reqVar LSP.Exit (Just LSP.ExitParams) testRequestMessageHandler :: Client.RequestMessageHandler testRequestMessageHandler = Client.RequestMessageHandler (\m -> emptyResponse m <$ print m) (\m -> emptyResponse m <$ print m) (\m -> emptyResponse m <$ print m) (\m -> emptyResponse m <$ print m) where toRspId (LSP.IdInt i) = LSP.IdRspInt i toRspId (LSP.IdString t) = LSP.IdRspString t emptyResponse :: LSP.RequestMessage m req resp -> LSP.ResponseMessage a emptyResponse m = LSP.ResponseMessage (m ^. LSP.jsonrpc) (toRspId (m ^. LSP.id)) Nothing Nothing testNotificationMessageHandler :: Client.NotificationMessageHandler testNotificationMessageHandler = Client.NotificationMessageHandler (T.putStrLn . view (LSP.params . LSP.message)) (T.putStrLn . view (LSP.params . LSP.message)) (print . view LSP.params) (mapM_ T.putStrLn . (^.. LSP.params . LSP.diagnostics . traverse . LSP.message))