From 564aa4f9781a977061fb01a68b80486aba7d58f8 Mon Sep 17 00:00:00 2001 From: Chris Simon Date: Tue, 2 Nov 2021 21:28:27 +0000 Subject: [PATCH 1/5] Update dev container to .net 6 to allow use of c# record with init properties - see https://github.com/dotnet/fsharp/pull/11552; update debug and testing tasks --- .devcontainer/Dockerfile | 4 ++-- .vscode/tasks.json | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index fb52ee41..d983725c 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,8 +3,8 @@ FROM mcr.microsoft.com/vscode/devcontainers/dotnet:0-6.0-focal # Install other dotnet versions (required for adr tool and dotnet suggest) RUN curl -sSL https://dot.net/v1/dotnet-install.sh > /tmp/dotnet-install.sh \ && chmod u+x /tmp/dotnet-install.sh -RUN sudo bash -s -- --install-dir /usr/share/dotnet --channel 3.1 --runtime dotnet -RUN sudo bash -s -- --install-dir /usr/share/dotnet --channel 3.1 --runtime dotnet +RUN sudo /tmp/dotnet-install.sh --install-dir /usr/share/dotnet --channel 5.0 --runtime dotnet +RUN sudo /tmp/dotnet-install.sh --install-dir /usr/share/dotnet --channel 3.1 --runtime dotnet # [Choice] Node.js version: none, lts/*, 16, 14, 12, 10 ARG NODE_VERSION="lts/*" diff --git a/.vscode/tasks.json b/.vscode/tasks.json index a9a569f9..e0c7a121 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -38,6 +38,20 @@ }, "group": "build", "problemMatcher": "$msCompile" + }, + { + "label": "watch tests", + "command": "dotnet", + "type": "shell", + "args": [ + "watch", + "run" + ], + "options": { + "cwd": "${workspaceFolder}/src/Ubictionary.LanguageServer.Tests" + }, + "group": "test", + "problemMatcher": "$msCompile" } ] } \ No newline at end of file From 35588aa1541973f90be522a882985e13b58f225c Mon Sep 17 00:00:00 2001 From: Chris Simon Date: Tue, 2 Nov 2021 21:48:18 +0000 Subject: [PATCH 2/5] Initial cut of server requesting config values on startup --- .../InitializationTests.fs | 88 ++++++++++++++++++- .../TestClient.fs | 8 +- src/Ubictionary.LanguageServer/Program.fs | 2 +- src/Ubictionary.LanguageServer/Server.fs | 43 ++++----- 4 files changed, 115 insertions(+), 26 deletions(-) diff --git a/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs b/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs index ba048c33..60c7925c 100644 --- a/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs +++ b/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs @@ -1,12 +1,57 @@ module Ubictionary.LanguageServer.Tests.InitializationTests + +open System +open System.Threading.Tasks open Expecto +open Newtonsoft.Json.Linq open Swensen.Unquote +open System.Collections.Generic +open OmniSharp.Extensions.JsonRpc +open OmniSharp.Extensions.LanguageServer.Protocol.Models +open OmniSharp.Extensions.LanguageServer.Protocol.Client +open OmniSharp.Extensions.LanguageServer.Client + +let private initTestClient = async { + let testClient = new TestClient() + return! testClient.Initialize(None) |> Async.AwaitTask +} -let initTestClient = async { +let private initTestClientWithConfig clientConfigBuilder = async { let testClient = new TestClient() - return! testClient.Initialize() |> Async.AwaitTask + return! testClient.Initialize(Some clientConfigBuilder) |> Async.AwaitTask } +let private configSection values = + let results = new List() + let configValue = JObject() + results.Add(configValue) + values |> Map.iter (fun k (v:string) -> + configValue.[k] <- JValue(v)) + Container(results) + +let private configRequestIncludesSection section (configRequest:ConfigurationParams) = + configRequest.Items |> Seq.map (fun ci -> ci.Section) |> Seq.contains section + +let private handleConfigurationRequest section configValues (configRequested:ref) = + let configSectionResult = configSection configValues + let handler c = + if configRequestIncludesSection section c then + configRequested := true + Task.FromResult(configSectionResult) + else + Task.FromResult(null) + Func>>(handler) + +type WaitForCondition = + { + ReplyChannel: AsyncReplyChannel + Message: string + } + +type Command = + | Received of String + | WaitFor of WaitForCondition + [] let initializationTests = testList "Initialization Tests" [ @@ -20,7 +65,44 @@ let initializationTests = testAsync "Has Correct ServerInfo Name" { use! client = initTestClient test <@ client.ServerSettings.ServerInfo.Name = "Ubictionary" @> - } + } + + testAsync "Server requests ubictionary file location configuration" { + let pathValue = Guid.NewGuid().ToString() + let configRequested = ref false + + let configHandler = handleConfigurationRequest "ubictionary" (Map [("ubictionary_path", pathValue)]) configRequested + + // let logAwaiter = MailboxProcessor.Start(fun inbox -> + // let rec loop (conditions: WaitForCondition list) = async { + // let! (msg: Command) = inbox.Receive() + // let newState = + // match msg with + // | Received msg -> + // conditions |> Seq.iter (fun c -> if msg.Contains(c.Message) then c.ReplyChannel.Reply(msg)) + // conditions + // | WaitFor waitFor -> waitFor :: conditions + // return! loop newState + // } + // loop []) + + // let logHandler (l:LogMessageParams) = + // Received (l.Message) |> logAwaiter.Post + // Task.CompletedTask + + let clientOptionsBuilder (b:LanguageClientOptions) = + b.OnRequest("workspace/configuration", configHandler, JsonRpcHandlerOptions()) + //.OnRequest("window/logMessage", logHandler, JsonRpcHandlerOptions()) + .WithCapability(Capabilities.DidChangeConfigurationCapability()) + |> ignore + use! client = clientOptionsBuilder |> initTestClientWithConfig + test <@ client.ClientSettings.Capabilities.Workspace.Configuration.IsSupported @> + test <@ client.ClientSettings.Capabilities.Workspace.DidChangeConfiguration.IsSupported @> + do! Async.Sleep 5000 + //let! reply = logAwaiter.PostAndTryAsyncReply((fun r -> (WaitFor ({ReplyChannel=r; Message="Loading ubictionary"}))), 2000) + //test <@ reply = Some "ubictionary" @> + test <@ configRequested.Value @> + } ] \ No newline at end of file diff --git a/src/Ubictionary.LanguageServer.Tests/TestClient.fs b/src/Ubictionary.LanguageServer.Tests/TestClient.fs index d0a01167..1c0b90e7 100644 --- a/src/Ubictionary.LanguageServer.Tests/TestClient.fs +++ b/src/Ubictionary.LanguageServer.Tests/TestClient.fs @@ -1,7 +1,9 @@ namespace Ubictionary.LanguageServer.Tests +open System open System.IO.Pipelines open OmniSharp.Extensions.LanguageProtocol.Testing +open OmniSharp.Extensions.LanguageServer.Client open OmniSharp.Extensions.JsonRpc.Testing open Ubictionary.LanguageServer.Server @@ -16,5 +18,7 @@ type TestClient() = |> Async.Start (clientPipe.Reader.AsStream(), serverPipe.Writer.AsStream()) - member _.Initialize() = - base.InitializeClient(null) \ No newline at end of file + member _.Initialize clientOptsBuilder = + match clientOptsBuilder with + | Some f -> base.InitializeClient(Action(f)) + | None -> base.InitializeClient(null) \ No newline at end of file diff --git a/src/Ubictionary.LanguageServer/Program.fs b/src/Ubictionary.LanguageServer/Program.fs index 17dd857b..4094c785 100644 --- a/src/Ubictionary.LanguageServer/Program.fs +++ b/src/Ubictionary.LanguageServer/Program.fs @@ -8,7 +8,7 @@ let setupLogging = Log.Logger <- LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.FromLogContext() - .WriteTo.File("log.txt") + .WriteTo.File("log.txt", rollingInterval = RollingInterval.Day) .CreateLogger(); let private startWithConsole = diff --git a/src/Ubictionary.LanguageServer/Server.fs b/src/Ubictionary.LanguageServer/Server.fs index f886049e..250acd58 100644 --- a/src/Ubictionary.LanguageServer/Server.fs +++ b/src/Ubictionary.LanguageServer/Server.fs @@ -4,35 +4,38 @@ open System.Threading.Tasks open OmniSharp.Extensions.LanguageServer.Server open OmniSharp.Extensions.LanguageServer.Protocol.Server open OmniSharp.Extensions.LanguageServer.Protocol.Models +open OmniSharp.Extensions.LanguageServer.Protocol.Window +open Microsoft.Extensions.Configuration +open Microsoft.Extensions.Logging +open Microsoft.Extensions.DependencyInjection open Serilog open System.IO -open Microsoft.Extensions.DependencyInjection -open Microsoft.Extensions.Logging -let private onInitializeEvent msg server request response _cancellationToken = - Log.Logger.Information $"Ubictionary: {msg} {server} {request} {response}" - Task.CompletedTask -let private onInitialize s r = onInitializeEvent "Initializing" s r None -let private onInitialized = onInitializeEvent "Initialized" -let private onStarted s = onInitializeEvent "Started" s None None +let configSection = "ubictionary" + +let getConfig section key (config:IConfiguration) = + config.GetSection("ubictionary").Item("ubictionary_path") + +let private requestConfig (s:ILanguageServer) _cancellationToken = + async { + Log.Logger.Information "Getting config..." + let! config = + s.Configuration.GetConfiguration(ConfigurationItem(Section = configSection)) + |> Async.AwaitTask + let path = config |> getConfig configSection "ubictionary_path" + Log.Logger.Information $"Got path {path}" + //s.Window.LogInfo $"Loading ubictionary from {path}" + } |> Async.StartAsTask :> Task let configureServer (input: Stream) (output: Stream) (opts:LanguageServerOptions) = opts .WithInput(input) .WithOutput(output) - .ConfigureLogging(fun b -> - b.AddLanguageProtocolLogging() - .AddSerilog(Log.Logger) - .SetMinimumLevel(LogLevel.Trace) - |> ignore) - .OnInitialize(OnLanguageServerInitializeDelegate(onInitialize)) - .OnInitialized(OnLanguageServerInitializedDelegate(onInitialized)) - .OnStarted(OnLanguageServerStartedDelegate(onStarted)) + .OnStarted(OnLanguageServerStartedDelegate(requestConfig)) + //.WithConfigurationSection(configSection) // Add back in when implementing didConfigurationChanged handling + .ConfigureLogging(fun z -> z.AddLanguageProtocolLogging().AddSerilog(Log.Logger).SetMinimumLevel(LogLevel.Trace) |> ignore) + // .WithServices(fun s -> s.AddLogging(fun b -> b.SetMinimumLevel(LogLevel.Trace) |> ignore) |> ignore) .WithServerInfo(ServerInfo(Name = "Ubictionary")) - .WithServices(fun x -> - x.AddLogging(fun b -> - b.SetMinimumLevel(LogLevel.Trace) |> ignore) - |> ignore) |> ignore From 970719a9375df0850c86989594dffafb0ca48b94 Mon Sep 17 00:00:00 2001 From: Chris Simon Date: Tue, 2 Nov 2021 22:13:06 +0000 Subject: [PATCH 3/5] Switch to mailboxprocessor based waiting for startup log message --- .github/workflows/language-server-build.yml | 2 +- .../InitializationTests.fs | 53 +++++++++---------- src/Ubictionary.LanguageServer/Server.fs | 2 +- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/.github/workflows/language-server-build.yml b/.github/workflows/language-server-build.yml index aa00d85f..2cc242ca 100644 --- a/.github/workflows/language-server-build.yml +++ b/.github/workflows/language-server-build.yml @@ -28,7 +28,7 @@ jobs: working-directory: ./src - name: Build and Test Language Server run: | - dotnet run --project ./src/Ubictionary.LanguageServer.Tests/Ubictionary.LanguageServer.Tests.fsproj -- --nunit-summary TestResults-${{ matrix.dotnet-version }}.xml + dotnet run --project ./src/Ubictionary.LanguageServer.Tests/Ubictionary.LanguageServer.Tests.fsproj -- --fail-on-focused-tests --nunit-summary TestResults-${{ matrix.dotnet-version }}.xml - name: Upload dotnet test results uses: actions/upload-artifact@v2 with: diff --git a/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs b/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs index 60c7925c..c0f97a70 100644 --- a/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs +++ b/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs @@ -32,11 +32,10 @@ let private configSection values = let private configRequestIncludesSection section (configRequest:ConfigurationParams) = configRequest.Items |> Seq.map (fun ci -> ci.Section) |> Seq.contains section -let private handleConfigurationRequest section configValues (configRequested:ref) = +let private handleConfigurationRequest section configValues = let configSectionResult = configSection configValues let handler c = if configRequestIncludesSection section c then - configRequested := true Task.FromResult(configSectionResult) else Task.FromResult(null) @@ -69,39 +68,39 @@ let initializationTests = testAsync "Server requests ubictionary file location configuration" { let pathValue = Guid.NewGuid().ToString() - let configRequested = ref false - - let configHandler = handleConfigurationRequest "ubictionary" (Map [("ubictionary_path", pathValue)]) configRequested - - // let logAwaiter = MailboxProcessor.Start(fun inbox -> - // let rec loop (conditions: WaitForCondition list) = async { - // let! (msg: Command) = inbox.Receive() - // let newState = - // match msg with - // | Received msg -> - // conditions |> Seq.iter (fun c -> if msg.Contains(c.Message) then c.ReplyChannel.Reply(msg)) - // conditions - // | WaitFor waitFor -> waitFor :: conditions - // return! loop newState - // } - // loop []) - - // let logHandler (l:LogMessageParams) = - // Received (l.Message) |> logAwaiter.Post - // Task.CompletedTask + + let configHandler = handleConfigurationRequest "ubictionary" (Map [("ubictionary_path", pathValue)]) + + let logAwaiter = MailboxProcessor.Start(fun inbox -> + let rec loop (conditions: WaitForCondition list) = async { + let! (msg: Command) = inbox.Receive() + let newState = + match msg with + | Received msg -> + conditions |> Seq.iter (fun c -> if msg.Contains(c.Message) then c.ReplyChannel.Reply(msg)) + conditions + | WaitFor waitFor -> waitFor :: conditions + return! loop newState + } + loop []) + + let logHandler (l:LogMessageParams) = + Received (l.Message) |> logAwaiter.Post + Serilog.Log.Logger.Information("Received Log Message: {l}", l) + Task.CompletedTask let clientOptionsBuilder (b:LanguageClientOptions) = b.OnRequest("workspace/configuration", configHandler, JsonRpcHandlerOptions()) - //.OnRequest("window/logMessage", logHandler, JsonRpcHandlerOptions()) + .OnNotification("window/logMessage", logHandler, JsonRpcHandlerOptions()) .WithCapability(Capabilities.DidChangeConfigurationCapability()) |> ignore use! client = clientOptionsBuilder |> initTestClientWithConfig test <@ client.ClientSettings.Capabilities.Workspace.Configuration.IsSupported @> test <@ client.ClientSettings.Capabilities.Workspace.DidChangeConfiguration.IsSupported @> - do! Async.Sleep 5000 - //let! reply = logAwaiter.PostAndTryAsyncReply((fun r -> (WaitFor ({ReplyChannel=r; Message="Loading ubictionary"}))), 2000) - //test <@ reply = Some "ubictionary" @> - test <@ configRequested.Value @> + let! reply = logAwaiter.PostAndTryAsyncReply((fun r -> (WaitFor ({ReplyChannel=r; Message="Loading ubictionary"}))), 2000) + test <@ match reply with + | Some replyMsg -> replyMsg.Contains(pathValue) + | None -> false @> } ] diff --git a/src/Ubictionary.LanguageServer/Server.fs b/src/Ubictionary.LanguageServer/Server.fs index 250acd58..f1cfc295 100644 --- a/src/Ubictionary.LanguageServer/Server.fs +++ b/src/Ubictionary.LanguageServer/Server.fs @@ -24,7 +24,7 @@ let private requestConfig (s:ILanguageServer) _cancellationToken = |> Async.AwaitTask let path = config |> getConfig configSection "ubictionary_path" Log.Logger.Information $"Got path {path}" - //s.Window.LogInfo $"Loading ubictionary from {path}" + s.Window.LogInfo $"Loading ubictionary from {path}" } |> Async.StartAsTask :> Task let configureServer (input: Stream) (output: Stream) (opts:LanguageServerOptions) = From 4c3dcf6bab30597ebd598cb077465ee10392ca8c Mon Sep 17 00:00:00 2001 From: Chris Simon Date: Wed, 3 Nov 2021 01:13:32 +0000 Subject: [PATCH 4/5] Refactor condition awaiter into generic --- .../ConditionAwaiter.fs | 31 +++++++++++++++++++ .../InitializationTests.fs | 28 +++-------------- .../Ubictionary.LanguageServer.Tests.fsproj | 1 + 3 files changed, 36 insertions(+), 24 deletions(-) create mode 100644 src/Ubictionary.LanguageServer.Tests/ConditionAwaiter.fs diff --git a/src/Ubictionary.LanguageServer.Tests/ConditionAwaiter.fs b/src/Ubictionary.LanguageServer.Tests/ConditionAwaiter.fs new file mode 100644 index 00000000..74805105 --- /dev/null +++ b/src/Ubictionary.LanguageServer.Tests/ConditionAwaiter.fs @@ -0,0 +1,31 @@ +module Ubictionary.LanguageServer.Tests.ConditionAwaiter + +type WaitForCondition<'T> = + { + ReplyChannel: AsyncReplyChannel<'T> + Condition: 'T -> bool + } + +type Message<'T> = + | Received of 'T + | WaitFor of WaitForCondition<'T> + + +let create<'T>() = MailboxProcessor.Start(fun inbox -> + let rec loop (conditions: WaitForCondition<'T> list) = async { + let! (msg: Message<'T>) = inbox.Receive() + let newState = + match msg with + | Received msg -> + conditions |> Seq.iter (fun c -> if c.Condition msg then c.ReplyChannel.Reply(msg)) + conditions + | WaitFor waitFor -> waitFor :: conditions + return! loop newState + } + loop []) + +let received (awaiter: MailboxProcessor>) msg = + awaiter.Post(Received(msg)) + +let waitFor (awaiter: MailboxProcessor>) condition timeout = + awaiter.PostAndTryAsyncReply((fun rc -> WaitFor({ReplyChannel=rc;Condition=condition})), timeout) \ No newline at end of file diff --git a/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs b/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs index c0f97a70..d2fea321 100644 --- a/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs +++ b/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs @@ -41,16 +41,6 @@ let private handleConfigurationRequest section configValues = Task.FromResult(null) Func>>(handler) -type WaitForCondition = - { - ReplyChannel: AsyncReplyChannel - Message: string - } - -type Command = - | Received of String - | WaitFor of WaitForCondition - [] let initializationTests = testList "Initialization Tests" [ @@ -71,21 +61,10 @@ let initializationTests = let configHandler = handleConfigurationRequest "ubictionary" (Map [("ubictionary_path", pathValue)]) - let logAwaiter = MailboxProcessor.Start(fun inbox -> - let rec loop (conditions: WaitForCondition list) = async { - let! (msg: Command) = inbox.Receive() - let newState = - match msg with - | Received msg -> - conditions |> Seq.iter (fun c -> if msg.Contains(c.Message) then c.ReplyChannel.Reply(msg)) - conditions - | WaitFor waitFor -> waitFor :: conditions - return! loop newState - } - loop []) + let logAwaiter = ConditionAwaiter.create() let logHandler (l:LogMessageParams) = - Received (l.Message) |> logAwaiter.Post + l.Message |> ConditionAwaiter.received logAwaiter Serilog.Log.Logger.Information("Received Log Message: {l}", l) Task.CompletedTask @@ -97,7 +76,8 @@ let initializationTests = use! client = clientOptionsBuilder |> initTestClientWithConfig test <@ client.ClientSettings.Capabilities.Workspace.Configuration.IsSupported @> test <@ client.ClientSettings.Capabilities.Workspace.DidChangeConfiguration.IsSupported @> - let! reply = logAwaiter.PostAndTryAsyncReply((fun r -> (WaitFor ({ReplyChannel=r; Message="Loading ubictionary"}))), 2000) + let logCondition = fun (m:string) -> m.Contains("Loading ubictionary") + let! reply = ConditionAwaiter.waitFor logAwaiter logCondition 1500 test <@ match reply with | Some replyMsg -> replyMsg.Contains(pathValue) | None -> false @> diff --git a/src/Ubictionary.LanguageServer.Tests/Ubictionary.LanguageServer.Tests.fsproj b/src/Ubictionary.LanguageServer.Tests/Ubictionary.LanguageServer.Tests.fsproj index 75202dd1..128a43a6 100644 --- a/src/Ubictionary.LanguageServer.Tests/Ubictionary.LanguageServer.Tests.fsproj +++ b/src/Ubictionary.LanguageServer.Tests/Ubictionary.LanguageServer.Tests.fsproj @@ -6,6 +6,7 @@ false + From c6f70ab37858de3c9e1949fad9ad2d8db3e521b8 Mon Sep 17 00:00:00 2001 From: Chris Simon Date: Wed, 3 Nov 2021 02:26:59 +0000 Subject: [PATCH 5/5] Refactor configurationSection --- .../ConfigurationSection.fs | 16 ++++++++++++ .../InitializationTests.fs | 25 +++++-------------- .../Ubictionary.LanguageServer.Tests.fsproj | 1 + 3 files changed, 23 insertions(+), 19 deletions(-) create mode 100644 src/Ubictionary.LanguageServer.Tests/ConfigurationSection.fs diff --git a/src/Ubictionary.LanguageServer.Tests/ConfigurationSection.fs b/src/Ubictionary.LanguageServer.Tests/ConfigurationSection.fs new file mode 100644 index 00000000..ae188ac6 --- /dev/null +++ b/src/Ubictionary.LanguageServer.Tests/ConfigurationSection.fs @@ -0,0 +1,16 @@ +module Ubictionary.LanguageServer.Tests.ConfigurationSection + +open Newtonsoft.Json.Linq +open System.Collections.Generic +open OmniSharp.Extensions.LanguageServer.Protocol.Models + +let fromMap values = + let results = new List() + let configValue = JObject() + results.Add(configValue) + values |> Map.iter (fun k (v:string) -> + configValue.[k] <- JValue(v)) + Container(results) + +let includesSection section (configRequest:ConfigurationParams) = + configRequest.Items |> Seq.map (fun ci -> ci.Section) |> Seq.contains section \ No newline at end of file diff --git a/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs b/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs index d2fea321..0338daaa 100644 --- a/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs +++ b/src/Ubictionary.LanguageServer.Tests/InitializationTests.fs @@ -3,9 +3,7 @@ module Ubictionary.LanguageServer.Tests.InitializationTests open System open System.Threading.Tasks open Expecto -open Newtonsoft.Json.Linq open Swensen.Unquote -open System.Collections.Generic open OmniSharp.Extensions.JsonRpc open OmniSharp.Extensions.LanguageServer.Protocol.Models open OmniSharp.Extensions.LanguageServer.Protocol.Client @@ -21,25 +19,13 @@ let private initTestClientWithConfig clientConfigBuilder = async { return! testClient.Initialize(Some clientConfigBuilder) |> Async.AwaitTask } -let private configSection values = - let results = new List() - let configValue = JObject() - results.Add(configValue) - values |> Map.iter (fun k (v:string) -> - configValue.[k] <- JValue(v)) - Container(results) - -let private configRequestIncludesSection section (configRequest:ConfigurationParams) = - configRequest.Items |> Seq.map (fun ci -> ci.Section) |> Seq.contains section - let private handleConfigurationRequest section configValues = - let configSectionResult = configSection configValues - let handler c = - if configRequestIncludesSection section c then + let configSectionResult = ConfigurationSection.fromMap configValues + fun c -> + if ConfigurationSection.includesSection section c then Task.FromResult(configSectionResult) else Task.FromResult(null) - Func>>(handler) [] let initializationTests = @@ -62,10 +48,8 @@ let initializationTests = let configHandler = handleConfigurationRequest "ubictionary" (Map [("ubictionary_path", pathValue)]) let logAwaiter = ConditionAwaiter.create() - let logHandler (l:LogMessageParams) = l.Message |> ConditionAwaiter.received logAwaiter - Serilog.Log.Logger.Information("Received Log Message: {l}", l) Task.CompletedTask let clientOptionsBuilder (b:LanguageClientOptions) = @@ -73,9 +57,12 @@ let initializationTests = .OnNotification("window/logMessage", logHandler, JsonRpcHandlerOptions()) .WithCapability(Capabilities.DidChangeConfigurationCapability()) |> ignore + use! client = clientOptionsBuilder |> initTestClientWithConfig + test <@ client.ClientSettings.Capabilities.Workspace.Configuration.IsSupported @> test <@ client.ClientSettings.Capabilities.Workspace.DidChangeConfiguration.IsSupported @> + let logCondition = fun (m:string) -> m.Contains("Loading ubictionary") let! reply = ConditionAwaiter.waitFor logAwaiter logCondition 1500 test <@ match reply with diff --git a/src/Ubictionary.LanguageServer.Tests/Ubictionary.LanguageServer.Tests.fsproj b/src/Ubictionary.LanguageServer.Tests/Ubictionary.LanguageServer.Tests.fsproj index 128a43a6..155f86bb 100644 --- a/src/Ubictionary.LanguageServer.Tests/Ubictionary.LanguageServer.Tests.fsproj +++ b/src/Ubictionary.LanguageServer.Tests/Ubictionary.LanguageServer.Tests.fsproj @@ -6,6 +6,7 @@ false +