Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ main = do
Success (App.GHCIDOptions {args}) -> ghcid args
argsRes -> do
staticEnvOpts <- App.handleParseResultWithSuppression jsonOrDefaultOpts argsRes
_ <- StaticLS.runServer staticEnvOpts logger
StaticLS.runServer staticEnvOpts logger
pure ()
6 changes: 6 additions & 0 deletions src/StaticLS/Handlers.hs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import System.Directory (doesFileExist)
import System.FSNotify qualified as FSNotify
import Text.Parsec.Text qualified as Parsec
import UnliftIO.Exception qualified as Exception
import Control.Concurrent.MVar

-----------------------------------------------------------------
--------------------- LSP event handlers ------------------------
Expand Down Expand Up @@ -352,3 +353,8 @@ clearDiagnostics = LSP.flushDiagnosticsBySource 100 (Just "haskell")

testing :: (Show a) => [a] -> String
testing = show

handleExit :: MVar () -> Handlers (LspT c StaticLsM)
handleExit clientMsgVar = LSP.notificationHandler LSP.SMethod_Exit $ \_ -> do
_ <- liftIO $ tryPutMVar clientMsgVar ()
pure ()
27 changes: 22 additions & 5 deletions src/StaticLS/Server.hs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import System.FSNotify qualified as FSNotify
import System.FilePath qualified as FilePath
import UnliftIO.Concurrent qualified as Conc
import UnliftIO.Exception qualified as Exception
import Control.Concurrent.MVar
import Control.Concurrent.Async

type LspConfig = ()

Expand Down Expand Up @@ -168,8 +170,8 @@ initServer reactorChan staticEnvOptions logger serverConfig _ = do
Just p -> Right p
#endif

serverDef :: StaticEnvOptions -> LoggerM IO -> IO (ServerDefinition ())
serverDef options logger = do
serverDef :: StaticEnvOptions -> LoggerM IO -> MVar () -> IO (ServerDefinition ())
serverDef options logger clientMsgVar = do
reactorChan <- liftIO Conc.newChan
let
-- TODO: actually respond to the client with an error
Expand Down Expand Up @@ -227,6 +229,7 @@ serverDef options logger = do
, handleDocumentSymbols
, handleCompletion
, handleCompletionItemResolve
, handleExit clientMsgVar
]
<> (if options.provideInlays then [handleInlayHintRequest options, handleResolveInlayHint] else [])
<> ( case options.fourmoluCommand of
Expand Down Expand Up @@ -276,7 +279,21 @@ lspOptions =
, LSP.optCompletionTriggerCharacters = Just ['.']
}

runServer :: StaticEnvOptions -> LoggerM IO -> IO Int
runServer :: StaticEnvOptions -> LoggerM IO -> IO ()
runServer argOptions logger = do
server <- serverDef argOptions logger
LSP.runServer server
-- This MVar becomes full when the server thread exits or we receive exit message from client.
-- LSP server will be canceled when it's full.
clientMsgVar <- newEmptyMVar

server <- serverDef argOptions logger clientMsgVar
untilMVar clientMsgVar $ do
_ <- LSP.runServer server
pure ()

-- | Runs the action until it ends or until the given MVar is put.
-- It is important, that the thread that puts the 'MVar' is not dropped before it puts the 'MVar' i.e. it should
-- occur as the final action in a 'finally' or 'bracket', because otherwise this thread will finish early (as soon
-- as the thread receives the BlockedIndefinitelyOnMVar exception)
-- Rethrows any exceptions.
untilMVar :: MVar () -> IO a -> IO ()
untilMVar mvar io = race_ (readMVar mvar) io
Loading