From e8902f32bd73d6728c917722143187f3e92c9bae Mon Sep 17 00:00:00 2001 From: Pepe Iborra Date: Sun, 18 Apr 2021 13:41:44 +0100 Subject: [PATCH] Handle LSP Initialize request synchronously The LSP spec. has strong restrictions around what messages are allowed in between the Initialize request and response. Handling the message synchronously goes a long way towards satisfying those invariants. --- ghcide/src/Development/IDE/LSP/LanguageServer.hs | 4 +++- ghcide/src/Development/IDE/LSP/Server.hs | 10 ++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ghcide/src/Development/IDE/LSP/LanguageServer.hs b/ghcide/src/Development/IDE/LSP/LanguageServer.hs index 9fcc520db2..556e6351af 100644 --- a/ghcide/src/Development/IDE/LSP/LanguageServer.hs +++ b/ghcide/src/Development/IDE/LSP/LanguageServer.hs @@ -154,7 +154,9 @@ runLanguageServer options inH outH getHieDbLoc defaultConfig onConfigurationChan logError (ideLogger ide) $ T.pack $ "Unexpected exception on notification, please report!\n" ++ "Exception: " ++ show e - ReactorRequest _id act k -> void $ async $ + ReactorRequestSync _id act k -> + checkCancelled ide clearReqId waitForCancel _id act k + ReactorRequestAsync _id act k -> void $ async $ checkCancelled ide clearReqId waitForCancel _id act k pure $ Right (env,ide) diff --git a/ghcide/src/Development/IDE/LSP/Server.hs b/ghcide/src/Development/IDE/LSP/Server.hs index f2edc004db..c72532cc89 100644 --- a/ghcide/src/Development/IDE/LSP/Server.hs +++ b/ghcide/src/Development/IDE/LSP/Server.hs @@ -26,7 +26,8 @@ import UnliftIO.Chan data ReactorMessage = ReactorNotification (IO ()) - | ReactorRequest SomeLspId (IO ()) (ResponseError -> IO ()) + | ReactorRequestSync SomeLspId (IO ()) (ResponseError -> IO ()) + | ReactorRequestAsync SomeLspId (IO ()) (ResponseError -> IO ()) type ReactorChan = Chan ReactorMessage type ServerM c = ReaderT (ReactorChan, IdeState) (LspM c) @@ -43,7 +44,12 @@ requestHandler m k = LSP.requestHandler m $ \RequestMessage{_method,_id,_params} trace x = otTracedHandler "Request" (show _method) $ \sp -> do traceWithSpan sp _params x - writeChan chan $ ReactorRequest (SomeLspId _id) (trace $ LSP.runLspT env $ resp' =<< k ide _params) (LSP.runLspT env . resp' . Left) + item = case _method of + SInitialize -> + ReactorRequestSync (SomeLspId _id) (trace $ LSP.runLspT env $ resp' =<< k ide _params) (LSP.runLspT env . resp' . Left) + _other -> + ReactorRequestAsync (SomeLspId _id) (trace $ LSP.runLspT env $ resp' =<< k ide _params) (LSP.runLspT env . resp' . Left) + writeChan chan item notificationHandler :: forall (m :: Method FromClient Notification) c. (HasTracing (MessageParams m)) =>