From c29fe977388bb2206656524be7a1f5e7e03f2895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Saulius=20Menkevic=CC=8Cius?= Date: Mon, 15 Aug 2022 10:35:18 +0300 Subject: [PATCH] Server.fs: load solution-in-sync when initializing This will help "server initializing" notification work better for clients that depend on `initialize` request not to complete until the server/solution is properly loaded initialized. should fix #40 (lsp-mode loading spinner no longer working) --- src/CSharpLanguageServer/RoslynHelpers.fs | 13 +++++++++++-- src/CSharpLanguageServer/Server.fs | 12 ++++++------ src/CSharpLanguageServer/State.fs | 22 ++++++++-------------- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/CSharpLanguageServer/RoslynHelpers.fs b/src/CSharpLanguageServer/RoslynHelpers.fs index 86c8686d..5cb68d74 100644 --- a/src/CSharpLanguageServer/RoslynHelpers.fs +++ b/src/CSharpLanguageServer/RoslynHelpers.fs @@ -1,11 +1,9 @@ module CSharpLanguageServer.RoslynHelpers open System -open System.Linq open System.Collections.Generic open System.IO open System.Reflection -open System.Threading open Ionide.LanguageServerProtocol.Types open Microsoft.CodeAnalysis open Microsoft.CodeAnalysis.CodeActions @@ -574,6 +572,17 @@ let findAndLoadSolutionOnDir logMessage dir = async { return solution } +let loadSolutionOnSolutionPathOrCwd logMessage solutionPathMaybe = + match solutionPathMaybe with + | Some solutionPath -> + logMessage (sprintf "loading specified solution file: %s.." solutionPath) + tryLoadSolutionOnPath logMessage solutionPath + + | None -> + let cwd = Directory.GetCurrentDirectory() + logMessage (sprintf "attempting to find and load solution based on cwd: \"%s\".." cwd) + findAndLoadSolutionOnDir logMessage cwd + let getRoslynCodeActions (doc: Document) (textSpan: TextSpan): Async = async { let! ct = Async.CancellationToken diff --git a/src/CSharpLanguageServer/Server.fs b/src/CSharpLanguageServer/Server.fs index d8f9f5e3..9e132a44 100644 --- a/src/CSharpLanguageServer/Server.fs +++ b/src/CSharpLanguageServer/Server.fs @@ -214,7 +214,12 @@ let setupServerHandlers options (lspClient: LspClient) = } } - initializeResult |> success |> async.Return + async { + // load solution (on stateActor) + do! stateActor.PostAndAsyncReply(SolutionReloadInSync) + + return initializeResult |> success + } let handleInitialized (scope: ServerRequestScope) (_p: InitializedParams): Async> = logMessage "\"initialized\" notification received from client" @@ -238,11 +243,6 @@ let setupServerHandlers options (lspClient: LspClient) = | Ok _ -> () | Error error -> infoMessage (sprintf " ...didChangeWatchedFiles registration has failed with %s" (error |> string)) - // - // start solution loading (on stateActor) - // - scope.Emit(SolutionReload) - return LspResult.Ok() } diff --git a/src/CSharpLanguageServer/State.fs b/src/CSharpLanguageServer/State.fs index d964e12b..ae462f5b 100644 --- a/src/CSharpLanguageServer/State.fs +++ b/src/CSharpLanguageServer/State.fs @@ -107,6 +107,7 @@ type ServerStateEvent = | ProcessRequestQueue | SolutionReloadRequest | SolutionReload + | SolutionReloadInSync of AsyncReplyChannel | PeriodicTimerTick let getDocumentForUriOfType state docType (u: string) = @@ -224,20 +225,13 @@ let processServerEvent logMessage state postMsg msg: Async = async return { state with SolutionReloadPending = DateTime.Now.AddSeconds(5) |> Some } | SolutionReload -> - let! solution = - match state.Options.SolutionPath with - | Some solutionPath -> async { - logMessage (sprintf "loading specified solution file: %s.." solutionPath) - return! tryLoadSolutionOnPath logMessage solutionPath - } - - | None -> async { - let cwd = Directory.GetCurrentDirectory() - logMessage (sprintf "attempting to find and load solution based on cwd: \"%s\".." cwd) - return! findAndLoadSolutionOnDir logMessage cwd - } - - return { state with Solution = solution } + let! newSolution = loadSolutionOnSolutionPathOrCwd logMessage state.Options.SolutionPath + return { state with Solution = newSolution } + + | SolutionReloadInSync replyChannel -> + let! newSolution = loadSolutionOnSolutionPathOrCwd logMessage state.Options.SolutionPath + replyChannel.Reply(()) + return { state with Solution = newSolution } | PeriodicTimerTick -> let solutionReloadTime = state.SolutionReloadPending