Skip to content

Commit ad4af51

Browse files
committed
fix(language-server): support LSP clients that only support workspace/configuration.
See OmniSharp/csharp-language-server-protocol#1101 for the upstream bug that necessitates this. We can revert to unscoped configuration when that is resolved.
1 parent 62fa42f commit ad4af51

File tree

10 files changed

+57
-34
lines changed

10 files changed

+57
-34
lines changed

src/language-server/Contextive.LanguageServer.Tests/CompletionTests.fs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ let completionTests =
3030
$"Given {fileName} contextive, in document {text} at position {position} respond with expected completion list " {
3131
let config =
3232
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
33-
ConfigurationSection.contextivePathOptionsBuilder $"{fileName}.yml" ]
33+
ConfigurationSection.contextivePathBuilder $"{fileName}.yml" ]
3434

3535
use! client = TestClient(config) |> init
3636

src/language-server/Contextive.LanguageServer.Tests/ConfigurationTests.fs

+19-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ let definitionsTests =
1313
[ testAsync "Can receive configuration value" {
1414
let config =
1515
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
16-
ConfigurationSection.contextivePathOptionsBuilder "one.yml" ]
16+
ConfigurationSection.contextivePathBuilder "one.yml" ]
1717

1818
use! client = TestClient(config) |> init
1919

@@ -29,7 +29,7 @@ let definitionsTests =
2929

3030
let config =
3131
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
32-
ConfigurationSection.contextivePathLoaderOptionsBuilder pathLoader ]
32+
ConfigurationSection.contextivePathLoaderBuilder pathLoader ]
3333

3434
use! client = TestClient(config) |> init
3535

@@ -42,4 +42,21 @@ let definitionsTests =
4242

4343
}
4444

45+
testAsync "Can handle client that doesn't support didChangeConfiguration" {
46+
let mutable path = "one.yml"
47+
48+
let pathLoader () : obj = path
49+
50+
let config =
51+
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
52+
ConfigurationSection.contextivePathLoaderBuilder pathLoader ]
53+
54+
use! client = TestClient(config) |> init
55+
56+
let! labels = Completion.getCompletionLabels client
57+
58+
test <@ (labels, Fixtures.One.expectedCompletionLabels) ||> Seq.compareWith compare = 0 @>
59+
60+
}
61+
4562
]

src/language-server/Contextive.LanguageServer.Tests/DefinitionsTests.fs

+1-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ let definitionsTests =
163163

164164
let config =
165165
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
166-
ConfigurationSection.contextivePathLoaderOptionsBuilder pathLoader ]
166+
ConfigurationSection.contextivePathLoaderBuilder pathLoader ]
167167

168168
use! client = TestClient(config) |> init
169169

src/language-server/Contextive.LanguageServer.Tests/Helpers/ConfigurationSection.fs

+17-10
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,32 @@ let private createHandler section configValuesLoader =
3838
else
3939
Task.FromResult(configSectionResultFromMap <| Map [])
4040

41-
let optionsBuilder section configValuesLoader (b: LanguageClientOptions) =
41+
let configurationHandlerBuilder section configValuesLoader (b: LanguageClientOptions) =
4242
let handler = createHandler section configValuesLoader
43-
43+
b.OnConfiguration(handler) |> ignore
4444
b
45-
.WithCapability(Capabilities.DidChangeConfigurationCapability(DynamicRegistration = true))
46-
.OnConfiguration(handler)
45+
46+
let private didChangeConfigurationBuilder (b: LanguageClientOptions) =
47+
b.WithCapability(Capabilities.DidChangeConfigurationCapability(DynamicRegistration = true))
4748
|> ignore
4849

4950
b
5051

51-
type PathLoader = unit -> obj
52+
type ValueLoader = unit -> obj
53+
54+
let private mapLoader (key: string) (valueLoader: ValueLoader) () = Map[(key, valueLoader ())]
55+
56+
let private mapPathLoader = mapLoader "path"
5257

53-
let mapLoader (pathLoader: PathLoader) () = Map[("path", pathLoader ())]
58+
let private contextivePathConfigurationHandlerBuilder (pathLoader: ValueLoader) =
59+
configurationHandlerBuilder "contextive" <| mapPathLoader pathLoader
5460

55-
let contextivePathLoaderOptionsBuilder (pathLoader: PathLoader) =
56-
optionsBuilder "contextive" <| mapLoader pathLoader
61+
let contextivePathLoaderBuilder (pathLoader: ValueLoader) =
62+
contextivePathConfigurationHandlerBuilder pathLoader
63+
>> didChangeConfigurationBuilder
5764

58-
let contextivePathOptionsBuilder path =
59-
contextivePathLoaderOptionsBuilder (fun () -> path)
65+
let contextivePathBuilder path =
66+
contextivePathConfigurationHandlerBuilder (fun () -> path)
6067

6168
let didChange (client: ILanguageClient) path =
6269
let setting = jTokenFromMap <| Map[("path", path)]

src/language-server/Contextive.LanguageServer.Tests/HoverTests.fs

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ let hoverTests =
3737
$"Given definitions file '{fileName}' and file contents '{multiLineToSingleLine text}', server responds to hover request at Position {position} with '{expectedTerm}'" {
3838
let config =
3939
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
40-
ConfigurationSection.contextivePathOptionsBuilder $"{fileName}.yml" ]
40+
ConfigurationSection.contextivePathBuilder $"{fileName}.yml" ]
4141

4242
use! client = TestClient(config) |> init
4343

@@ -89,7 +89,7 @@ let hoverTests =
8989

9090
let config =
9191
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
92-
ConfigurationSection.contextivePathOptionsBuilder $"{fileName}.yml" ]
92+
ConfigurationSection.contextivePathBuilder $"{fileName}.yml" ]
9393

9494
use! client = TestClient(config) |> init
9595

@@ -129,7 +129,7 @@ let hoverTests =
129129

130130
let config =
131131
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
132-
ConfigurationSection.contextivePathOptionsBuilder $"{fileName}.yml" ]
132+
ConfigurationSection.contextivePathBuilder $"{fileName}.yml" ]
133133

134134
use! client = TestClient(config) |> init
135135

src/language-server/Contextive.LanguageServer.Tests/InitializationTests.fs

+4-8
Original file line numberDiff line numberDiff line change
@@ -28,38 +28,34 @@ let initializationTests =
2828

2929
let config =
3030
[ Workspace.optionsBuilder ""
31-
ConfigurationSection.contextivePathOptionsBuilder pathValue ]
31+
ConfigurationSection.contextivePathBuilder pathValue ]
3232

3333
let! (client, reply) = TestClient(config) |> initAndWaitForReply
3434

3535
test <@ client.ClientSettings.Capabilities.Workspace.Configuration.IsSupported @>
36-
test <@ client.ClientSettings.Capabilities.Workspace.DidChangeConfiguration.IsSupported @>
3736

3837
test <@ (defaultArg reply "").Contains(pathValue) @>
3938
}
4039

4140
testAsync "Server loads contextive file from absolute location without workspace" {
4241
let pathValue = Guid.NewGuid().ToString()
4342

44-
let config =
45-
[ ConfigurationSection.contextivePathOptionsBuilder $"/tmp/{pathValue}" ]
43+
let config = [ ConfigurationSection.contextivePathBuilder $"/tmp/{pathValue}" ]
4644

4745
let! (client, reply) = TestClient(config) |> initAndWaitForReply
4846

4947
test <@ client.ClientSettings.Capabilities.Workspace.Configuration.IsSupported @>
50-
test <@ client.ClientSettings.Capabilities.Workspace.DidChangeConfiguration.IsSupported @>
5148

5249
test <@ (defaultArg reply "").Contains(pathValue) @>
5350
}
5451

5552
testAsync "Server does NOT load contextive file from relative location without workspace" {
5653
let pathValue = Guid.NewGuid().ToString()
57-
let config = [ ConfigurationSection.contextivePathOptionsBuilder pathValue ]
54+
let config = [ ConfigurationSection.contextivePathBuilder pathValue ]
5855

5956
let! (client, reply) = TestClientWithCustomInitWait(config, Some pathValue) |> initAndWaitForReply
6057

6158
test <@ client.ClientSettings.Capabilities.Workspace.Configuration.IsSupported @>
62-
test <@ client.ClientSettings.Capabilities.Workspace.DidChangeConfiguration.IsSupported @>
6359

6460
test
6561
<@
@@ -71,7 +67,7 @@ let initializationTests =
7167
testAsync "Server loads contextive file from default location when no configuration supplied" {
7268
let config =
7369
[ Workspace.optionsBuilder ""
74-
ConfigurationSection.optionsBuilder "dummySection" (fun () -> Map []) ]
70+
ConfigurationSection.configurationHandlerBuilder "dummySection" (fun () -> Map []) ]
7571

7672
let defaultPath = ".contextive/definitions.yml"
7773

src/language-server/Contextive.LanguageServer.Tests/SurveyTests.fs

+3-3
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ let initializationTests =
4848
let config =
4949
[ showMessageRequestHandlerBuilder <| handler messageAwaiter null
5050
Workspace.optionsBuilder ""
51-
ConfigurationSection.contextivePathOptionsBuilder pathValue ]
51+
ConfigurationSection.contextivePathBuilder pathValue ]
5252

5353
let! (client, reply) = TestClient(config) |> initAndWaitForReply
5454

@@ -75,7 +75,7 @@ let initializationTests =
7575
let config =
7676
[ showMessageRequestHandlerBuilder <| handler messageAwaiter null
7777
Workspace.optionsBuilder ""
78-
ConfigurationSection.contextivePathOptionsBuilder pathValue ]
78+
ConfigurationSection.contextivePathBuilder pathValue ]
7979

8080
let! (client, reply) = TestClient(config) |> initAndWaitForReply
8181

@@ -102,7 +102,7 @@ let initializationTests =
102102
[ showMessageRequestHandlerBuilder <| handler messageAwaiter response
103103
showDocumentRequestHandlerBuilder <| handler showDocAwaiter showDocResponse
104104
Workspace.optionsBuilder ""
105-
ConfigurationSection.contextivePathOptionsBuilder pathValue ]
105+
ConfigurationSection.contextivePathBuilder pathValue ]
106106

107107
let! (client, reply) = TestClient(config) |> initAndWaitForReply
108108

src/language-server/Contextive.LanguageServer.Tests/TextDocumentTests.fs

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ let textDocumentTests =
5252
testAsync "Server supports full sync" {
5353
let config =
5454
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
55-
ConfigurationSection.contextivePathOptionsBuilder $"one.yml" ]
55+
ConfigurationSection.contextivePathBuilder $"one.yml" ]
5656

5757
use! client = TestClient(config) |> init
5858
test <@ client.ServerSettings.Capabilities.TextDocumentSync.Options.Change = TextDocumentSyncKind.Full @>

src/language-server/Contextive.LanguageServer.Tests/WatchedFilesTests.fs

+4-4
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ let watchedFileTests =
3636

3737
let config =
3838
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
39-
ConfigurationSection.contextivePathOptionsBuilder $"one.yml"
39+
ConfigurationSection.contextivePathBuilder $"one.yml"
4040
WatchedFiles.optionsBuilder registrationAwaiter ]
4141

4242
let! client = TestClient(config) |> init
@@ -62,7 +62,7 @@ let watchedFileTests =
6262

6363
let config =
6464
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
65-
ConfigurationSection.contextivePathLoaderOptionsBuilder pathLoader
65+
ConfigurationSection.contextivePathLoaderBuilder pathLoader
6666
WatchedFiles.optionsBuilder registrationAwaiter ]
6767

6868
let! client = TestClient(config) |> init
@@ -113,7 +113,7 @@ let watchedFileTests =
113113

114114
let config =
115115
[ Workspace.optionsBuilder relativePath
116-
ConfigurationSection.contextivePathOptionsBuilder definitionsFile ]
116+
ConfigurationSection.contextivePathBuilder definitionsFile ]
117117

118118
let! client = TestClient(config) |> init
119119

@@ -153,7 +153,7 @@ let watchedFileTests =
153153

154154
let config =
155155
[ Workspace.optionsBuilder relativePath
156-
ConfigurationSection.contextivePathOptionsBuilder definitionsFile ]
156+
ConfigurationSection.contextivePathBuilder definitionsFile ]
157157

158158
let! client = TestClient(config) |> init
159159

src/language-server/Contextive.LanguageServer/Server.fs

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ let private getConfig (s: ILanguageServer) section key =
3030
Log.Logger.Information $"Getting {section} {key} config..."
3131

3232
let! config =
33-
s.Configuration.GetConfiguration(ConfigurationItem(Section = configSection))
33+
// We need to use `GetScopedConfiguration` because of https://github.com/OmniSharp/csharp-language-server-protocol/issues/1101
34+
// We can revert to `GetConfiguration` when that bug is fixed.
35+
s.Configuration.GetScopedConfiguration("file:///", System.Threading.CancellationToken.None)
36+
//s.Configuration.GetConfiguration(ConfigurationItem(Section = configSection))
3437
|> Async.AwaitTask
3538

3639
let configValue = config.GetSection(section).Item(key)

0 commit comments

Comments
 (0)