diff --git a/src/language-server/Contextive.LanguageServer.Tests/CompletionTests.fs b/src/language-server/Contextive.LanguageServer.Tests/CompletionTests.fs
index 7fd5c41c..686ea0f9 100644
--- a/src/language-server/Contextive.LanguageServer.Tests/CompletionTests.fs
+++ b/src/language-server/Contextive.LanguageServer.Tests/CompletionTests.fs
@@ -30,7 +30,7 @@ let completionTests =
$"Given {fileName} contextive, in document {text} at position {position} respond with expected completion list " {
let config =
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
- ConfigurationSection.contextivePathOptionsBuilder $"{fileName}.yml" ]
+ ConfigurationSection.contextivePathBuilder $"{fileName}.yml" ]
use! client = TestClient(config) |> init
diff --git a/src/language-server/Contextive.LanguageServer.Tests/ConfigurationTests.fs b/src/language-server/Contextive.LanguageServer.Tests/ConfigurationTests.fs
index c7f484a8..b08e996f 100644
--- a/src/language-server/Contextive.LanguageServer.Tests/ConfigurationTests.fs
+++ b/src/language-server/Contextive.LanguageServer.Tests/ConfigurationTests.fs
@@ -13,7 +13,7 @@ let definitionsTests =
[ testAsync "Can receive configuration value" {
let config =
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
- ConfigurationSection.contextivePathOptionsBuilder "one.yml" ]
+ ConfigurationSection.contextivePathBuilder "one.yml" ]
use! client = TestClient(config) |> init
@@ -29,12 +29,12 @@ let definitionsTests =
let config =
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
- ConfigurationSection.contextivePathLoaderOptionsBuilder pathLoader ]
+ ConfigurationSection.contextivePathLoaderBuilder pathLoader ]
use! client = TestClient(config) |> init
path <- "two.yml"
- ConfigurationSection.didChange client path
+ ConfigurationSection.didChangePath client path
let! labels = Completion.getCompletionLabels client
@@ -42,4 +42,19 @@ let definitionsTests =
}
+ testAsync "Can handle client that doesn't support didChangeConfiguration" {
+ let mutable path = "one.yml"
+
+ let config =
+ [ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
+ ConfigurationSection.contextivePathBuilder path ]
+
+ use! client = TestClient(config) |> init
+
+ let! labels = Completion.getCompletionLabels client
+
+ test <@ (labels, Fixtures.One.expectedCompletionLabels) ||> Seq.compareWith compare = 0 @>
+
+ }
+
]
diff --git a/src/language-server/Contextive.LanguageServer.Tests/DefinitionsTests.fs b/src/language-server/Contextive.LanguageServer.Tests/DefinitionsTests.fs
index b1a3f262..62454a90 100644
--- a/src/language-server/Contextive.LanguageServer.Tests/DefinitionsTests.fs
+++ b/src/language-server/Contextive.LanguageServer.Tests/DefinitionsTests.fs
@@ -163,7 +163,7 @@ let definitionsTests =
let config =
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
- ConfigurationSection.contextivePathLoaderOptionsBuilder pathLoader ]
+ ConfigurationSection.contextivePathLoaderBuilder pathLoader ]
use! client = TestClient(config) |> init
@@ -171,13 +171,13 @@ let definitionsTests =
test <@ (termsWhenValidAtStart, Fixtures.One.expectedCompletionLabels) ||> compareList = 0 @>
path <- $"{fileName}.yml"
- ConfigurationSection.didChange client path
+ ConfigurationSection.didChangePath client path
let! termsWhenInvalid = Completion.getCompletionLabels client
test <@ Seq.length termsWhenInvalid = 0 @>
path <- validPath
- ConfigurationSection.didChange client path
+ ConfigurationSection.didChangePath client path
let! termsWhenValidAtEnd = Completion.getCompletionLabels client
test <@ (termsWhenValidAtEnd, Fixtures.One.expectedCompletionLabels) ||> compareList = 0 @>
diff --git a/src/language-server/Contextive.LanguageServer.Tests/Helpers/ConfigurationSection.fs b/src/language-server/Contextive.LanguageServer.Tests/Helpers/ConfigurationSection.fs
index 6382a5f1..5901bff5 100644
--- a/src/language-server/Contextive.LanguageServer.Tests/Helpers/ConfigurationSection.fs
+++ b/src/language-server/Contextive.LanguageServer.Tests/Helpers/ConfigurationSection.fs
@@ -9,7 +9,7 @@ open OmniSharp.Extensions.LanguageServer.Protocol.Client
open OmniSharp.Extensions.LanguageServer.Protocol.Workspace
open System.Threading.Tasks
-let jTokenFromMap values =
+let private jTokenFromMap values =
let configValue = JObject()
values
@@ -38,27 +38,50 @@ let private createHandler section configValuesLoader =
else
Task.FromResult(configSectionResultFromMap <| Map [])
-let optionsBuilder section configValuesLoader (b: LanguageClientOptions) =
+let configurationHandlerBuilder section configValuesLoader (b: LanguageClientOptions) =
let handler = createHandler section configValuesLoader
-
+ b.OnConfiguration(handler) |> ignore
b
- .WithCapability(Capabilities.DidChangeConfigurationCapability(DynamicRegistration = true))
- .OnConfiguration(handler)
+
+let private didChangeConfigurationBuilder (b: LanguageClientOptions) =
+ b.WithCapability(Capabilities.DidChangeConfigurationCapability(DynamicRegistration = true))
|> ignore
b
-type PathLoader = unit -> obj
-
-let mapLoader (pathLoader: PathLoader) () = Map[("path", pathLoader ())]
-
-let contextivePathLoaderOptionsBuilder (pathLoader: PathLoader) =
- optionsBuilder "contextive" <| mapLoader pathLoader
-
-let contextivePathOptionsBuilder path =
- contextivePathLoaderOptionsBuilder (fun () -> path)
-
-let didChange (client: ILanguageClient) path =
+type ValueLoader = unit -> obj
+
+let private mapLoader (key: string) (valueLoader: ValueLoader) () = Map[(key, valueLoader ())]
+
+let private mapPathLoader = mapLoader "path"
+
+let private contextivePathConfigurationHandlerBuilder (pathLoader: ValueLoader) =
+ configurationHandlerBuilder "contextive" <| mapPathLoader pathLoader
+
+///
+/// Use when you have a setting value that needs to change during the test.
+/// The test client will support `workspace/configuration` AND `workspace/didChangeConfiguration`.
+/// When a `workspace/configuration` request is received, the `pathLoader` function will be invoked to get the current value.
+/// To trigger a `workspace/didChangeConfiguration` notification, use didChangePath.
+///
+let contextivePathLoaderBuilder (pathLoader: ValueLoader) =
+ contextivePathConfigurationHandlerBuilder pathLoader
+ >> didChangeConfigurationBuilder
+
+///
+/// Use when you have a fixed setting value.
+/// The test client will ONLY support `workspace/configuration` and will always supply this fixed value
+/// Using didChangePath will have no impact as the server will not support the `workspace/didChangeConfiguration` notification
+///
+let contextivePathBuilder path =
+ contextivePathConfigurationHandlerBuilder (fun () -> path)
+
+///
+/// Trigger a `workspace/didChangeConfiguration` notification with the new value.
+/// This will only work if the TestClient was created with the contextivePathLoaderBuilder.
+/// Ensure this method is invoked with the same path value as will be returned from the `pathLoader` registered with the TestClient.
+///
+let didChangePath (client: ILanguageClient) path =
let setting = jTokenFromMap <| Map[("path", path)]
let configSection = jTokenFromMap <| Map[("contextive", setting)]
diff --git a/src/language-server/Contextive.LanguageServer.Tests/HoverTests.fs b/src/language-server/Contextive.LanguageServer.Tests/HoverTests.fs
index dfe5dcf8..47f8eb83 100644
--- a/src/language-server/Contextive.LanguageServer.Tests/HoverTests.fs
+++ b/src/language-server/Contextive.LanguageServer.Tests/HoverTests.fs
@@ -37,7 +37,7 @@ let hoverTests =
$"Given definitions file '{fileName}' and file contents '{multiLineToSingleLine text}', server responds to hover request at Position {position} with '{expectedTerm}'" {
let config =
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
- ConfigurationSection.contextivePathOptionsBuilder $"{fileName}.yml" ]
+ ConfigurationSection.contextivePathBuilder $"{fileName}.yml" ]
use! client = TestClient(config) |> init
@@ -89,7 +89,7 @@ let hoverTests =
let config =
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
- ConfigurationSection.contextivePathOptionsBuilder $"{fileName}.yml" ]
+ ConfigurationSection.contextivePathBuilder $"{fileName}.yml" ]
use! client = TestClient(config) |> init
@@ -129,7 +129,7 @@ let hoverTests =
let config =
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
- ConfigurationSection.contextivePathOptionsBuilder $"{fileName}.yml" ]
+ ConfigurationSection.contextivePathBuilder $"{fileName}.yml" ]
use! client = TestClient(config) |> init
diff --git a/src/language-server/Contextive.LanguageServer.Tests/InitializationTests.fs b/src/language-server/Contextive.LanguageServer.Tests/InitializationTests.fs
index 825f623f..2474a636 100644
--- a/src/language-server/Contextive.LanguageServer.Tests/InitializationTests.fs
+++ b/src/language-server/Contextive.LanguageServer.Tests/InitializationTests.fs
@@ -28,12 +28,11 @@ let initializationTests =
let config =
[ Workspace.optionsBuilder ""
- ConfigurationSection.contextivePathOptionsBuilder pathValue ]
+ ConfigurationSection.contextivePathBuilder pathValue ]
let! (client, reply) = TestClient(config) |> initAndWaitForReply
test <@ client.ClientSettings.Capabilities.Workspace.Configuration.IsSupported @>
- test <@ client.ClientSettings.Capabilities.Workspace.DidChangeConfiguration.IsSupported @>
test <@ (defaultArg reply "").Contains(pathValue) @>
}
@@ -41,25 +40,22 @@ let initializationTests =
testAsync "Server loads contextive file from absolute location without workspace" {
let pathValue = Guid.NewGuid().ToString()
- let config =
- [ ConfigurationSection.contextivePathOptionsBuilder $"/tmp/{pathValue}" ]
+ let config = [ ConfigurationSection.contextivePathBuilder $"/tmp/{pathValue}" ]
let! (client, reply) = TestClient(config) |> initAndWaitForReply
test <@ client.ClientSettings.Capabilities.Workspace.Configuration.IsSupported @>
- test <@ client.ClientSettings.Capabilities.Workspace.DidChangeConfiguration.IsSupported @>
test <@ (defaultArg reply "").Contains(pathValue) @>
}
testAsync "Server does NOT load contextive file from relative location without workspace" {
let pathValue = Guid.NewGuid().ToString()
- let config = [ ConfigurationSection.contextivePathOptionsBuilder pathValue ]
+ let config = [ ConfigurationSection.contextivePathBuilder pathValue ]
let! (client, reply) = TestClientWithCustomInitWait(config, Some pathValue) |> initAndWaitForReply
test <@ client.ClientSettings.Capabilities.Workspace.Configuration.IsSupported @>
- test <@ client.ClientSettings.Capabilities.Workspace.DidChangeConfiguration.IsSupported @>
test
<@
@@ -71,7 +67,7 @@ let initializationTests =
testAsync "Server loads contextive file from default location when no configuration supplied" {
let config =
[ Workspace.optionsBuilder ""
- ConfigurationSection.optionsBuilder "dummySection" (fun () -> Map []) ]
+ ConfigurationSection.configurationHandlerBuilder "dummySection" (fun () -> Map []) ]
let defaultPath = ".contextive/definitions.yml"
diff --git a/src/language-server/Contextive.LanguageServer.Tests/SurveyTests.fs b/src/language-server/Contextive.LanguageServer.Tests/SurveyTests.fs
index 75671e90..aba553d1 100644
--- a/src/language-server/Contextive.LanguageServer.Tests/SurveyTests.fs
+++ b/src/language-server/Contextive.LanguageServer.Tests/SurveyTests.fs
@@ -48,7 +48,7 @@ let initializationTests =
let config =
[ showMessageRequestHandlerBuilder <| handler messageAwaiter null
Workspace.optionsBuilder ""
- ConfigurationSection.contextivePathOptionsBuilder pathValue ]
+ ConfigurationSection.contextivePathBuilder pathValue ]
let! (client, reply) = TestClient(config) |> initAndWaitForReply
@@ -75,7 +75,7 @@ let initializationTests =
let config =
[ showMessageRequestHandlerBuilder <| handler messageAwaiter null
Workspace.optionsBuilder ""
- ConfigurationSection.contextivePathOptionsBuilder pathValue ]
+ ConfigurationSection.contextivePathBuilder pathValue ]
let! (client, reply) = TestClient(config) |> initAndWaitForReply
@@ -102,7 +102,7 @@ let initializationTests =
[ showMessageRequestHandlerBuilder <| handler messageAwaiter response
showDocumentRequestHandlerBuilder <| handler showDocAwaiter showDocResponse
Workspace.optionsBuilder ""
- ConfigurationSection.contextivePathOptionsBuilder pathValue ]
+ ConfigurationSection.contextivePathBuilder pathValue ]
let! (client, reply) = TestClient(config) |> initAndWaitForReply
diff --git a/src/language-server/Contextive.LanguageServer.Tests/TextDocumentTests.fs b/src/language-server/Contextive.LanguageServer.Tests/TextDocumentTests.fs
index 50e1318e..d5f5371a 100644
--- a/src/language-server/Contextive.LanguageServer.Tests/TextDocumentTests.fs
+++ b/src/language-server/Contextive.LanguageServer.Tests/TextDocumentTests.fs
@@ -52,7 +52,7 @@ let textDocumentTests =
testAsync "Server supports full sync" {
let config =
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
- ConfigurationSection.contextivePathOptionsBuilder $"one.yml" ]
+ ConfigurationSection.contextivePathBuilder $"one.yml" ]
use! client = TestClient(config) |> init
test <@ client.ServerSettings.Capabilities.TextDocumentSync.Options.Change = TextDocumentSyncKind.Full @>
diff --git a/src/language-server/Contextive.LanguageServer.Tests/WatchedFilesTests.fs b/src/language-server/Contextive.LanguageServer.Tests/WatchedFilesTests.fs
index 345c3e8a..739e2030 100644
--- a/src/language-server/Contextive.LanguageServer.Tests/WatchedFilesTests.fs
+++ b/src/language-server/Contextive.LanguageServer.Tests/WatchedFilesTests.fs
@@ -36,7 +36,7 @@ let watchedFileTests =
let config =
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
- ConfigurationSection.contextivePathOptionsBuilder $"one.yml"
+ ConfigurationSection.contextivePathBuilder $"one.yml"
WatchedFiles.optionsBuilder registrationAwaiter ]
let! client = TestClient(config) |> init
@@ -62,7 +62,7 @@ let watchedFileTests =
let config =
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
- ConfigurationSection.contextivePathLoaderOptionsBuilder pathLoader
+ ConfigurationSection.contextivePathLoaderBuilder pathLoader
WatchedFiles.optionsBuilder registrationAwaiter ]
let! client = TestClient(config) |> init
@@ -72,7 +72,7 @@ let watchedFileTests =
ConditionAwaiter.clear registrationAwaiter 500
definitionsFile <- newDefinitionsFile
- ConfigurationSection.didChange client definitionsFile
+ ConfigurationSection.didChangePath client definitionsFile
let! secondRegistrationMsg =
ConditionAwaiter.waitFor
@@ -113,7 +113,7 @@ let watchedFileTests =
let config =
[ Workspace.optionsBuilder relativePath
- ConfigurationSection.contextivePathOptionsBuilder definitionsFile ]
+ ConfigurationSection.contextivePathBuilder definitionsFile ]
let! client = TestClient(config) |> init
@@ -153,7 +153,7 @@ let watchedFileTests =
let config =
[ Workspace.optionsBuilder relativePath
- ConfigurationSection.contextivePathOptionsBuilder definitionsFile ]
+ ConfigurationSection.contextivePathBuilder definitionsFile ]
let! client = TestClient(config) |> init
diff --git a/src/language-server/Contextive.LanguageServer/Server.fs b/src/language-server/Contextive.LanguageServer/Server.fs
index d8a1a3ce..0dccd9a7 100644
--- a/src/language-server/Contextive.LanguageServer/Server.fs
+++ b/src/language-server/Contextive.LanguageServer/Server.fs
@@ -30,7 +30,10 @@ let private getConfig (s: ILanguageServer) section key =
Log.Logger.Information $"Getting {section} {key} config..."
let! config =
- s.Configuration.GetConfiguration(ConfigurationItem(Section = configSection))
+ // We need to use `GetScopedConfiguration` because of https://github.com/OmniSharp/csharp-language-server-protocol/issues/1101
+ // We can revert to `GetConfiguration` when that bug is fixed.
+ s.Configuration.GetScopedConfiguration("file:///", System.Threading.CancellationToken.None)
+ //s.Configuration.GetConfiguration(ConfigurationItem(Section = configSection))
|> Async.AwaitTask
let configValue = config.GetSection(section).Item(key)