diff --git a/build/Packages.props b/build/Packages.props
index 58f17d70d3..a61c7199b4 100644
--- a/build/Packages.props
+++ b/build/Packages.props
@@ -62,8 +62,8 @@
-
-
+
+
diff --git a/tests/OmniSharp.Lsp.Tests/AbstractLanguageServerTestBase.cs b/tests/OmniSharp.Lsp.Tests/AbstractLanguageServerTestBase.cs
index dd96b84198..8a46508ab0 100644
--- a/tests/OmniSharp.Lsp.Tests/AbstractLanguageServerTestBase.cs
+++ b/tests/OmniSharp.Lsp.Tests/AbstractLanguageServerTestBase.cs
@@ -98,7 +98,7 @@ public async Task Restart(IConfiguration configuration = null, IDictionary())
.Build();
await InitializeAsync();
@@ -106,7 +106,7 @@ public async Task Restart(IConfiguration configuration = null, IDictionary
+ var(client, configurationProvider) = await InitializeClientWithConfiguration(x =>
{
x.WithCapability(new WorkspaceEditCapability()
{
@@ -117,107 +117,109 @@ public async Task InitializeAsync()
ResourceOperationKind.Create, ResourceOperationKind.Delete, ResourceOperationKind.Rename
}
});
- });
- Client.Register(c => c.OnApplyWorkspaceEdit(async @params =>
- {
- if (@params.Edit?.Changes != null)
+ x.OnApplyWorkspaceEdit(async @params =>
{
- foreach (var change in @params.Edit.Changes)
+ if (@params.Edit?.Changes != null)
{
- var changes = change.Value
- .Select(change => new LinePositionSpanTextChange()
- {
- NewText = change.NewText,
- StartColumn = Convert.ToInt32(change.Range.Start.Character),
- StartLine = Convert.ToInt32(change.Range.Start.Line),
- EndColumn = Convert.ToInt32(change.Range.End.Character),
- EndLine = Convert.ToInt32(change.Range.End.Line),
- })
- .ToArray();
-
- await OmniSharpTestHost.Workspace.BufferManager.UpdateBufferAsync(new UpdateBufferRequest()
+ foreach (var change in @params.Edit.Changes)
{
- FileName = LanguageServerProtocol.Helpers.FromUri(change.Key),
- Changes = changes
- });
+ var changes = change.Value
+ .Select(change => new LinePositionSpanTextChange()
+ {
+ NewText = change.NewText,
+ StartColumn = Convert.ToInt32(change.Range.Start.Character),
+ StartLine = Convert.ToInt32(change.Range.Start.Line),
+ EndColumn = Convert.ToInt32(change.Range.End.Character),
+ EndLine = Convert.ToInt32(change.Range.End.Line),
+ })
+ .ToArray();
+
+ await OmniSharpTestHost.Workspace.BufferManager.UpdateBufferAsync(new UpdateBufferRequest()
+ {
+ FileName = LanguageServerProtocol.Helpers.FromUri(change.Key),
+ Changes = changes
+ });
+ }
}
- }
- else if (@params.Edit?.DocumentChanges != null)
- {
- foreach (var change in @params.Edit.DocumentChanges)
+ else if (@params.Edit?.DocumentChanges != null)
{
- if (change.IsTextDocumentEdit)
+ foreach (var change in @params.Edit.DocumentChanges)
{
- var contentChanges = change.TextDocumentEdit.Edits.ToArray();
- if (contentChanges.Length == 1 && contentChanges[0].Range == null)
+ if (change.IsTextDocumentEdit)
{
- var c = contentChanges[0];
- await OmniSharpTestHost.Workspace.BufferManager.UpdateBufferAsync(
- new UpdateBufferRequest()
- {
- FileName = LanguageServerProtocol.Helpers.FromUri(change.TextDocumentEdit
- .TextDocument.Uri),
- Buffer = c.NewText
- });
- }
- else
- {
- var changes = contentChanges
- .Select(change => new LinePositionSpanTextChange()
- {
- NewText = change.NewText,
- StartColumn = Convert.ToInt32(change.Range.Start.Character),
- StartLine = Convert.ToInt32(change.Range.Start.Line),
- EndColumn = Convert.ToInt32(change.Range.End.Character),
- EndLine = Convert.ToInt32(change.Range.End.Line),
- })
- .ToArray();
+ var contentChanges = change.TextDocumentEdit.Edits.ToArray();
+ if (contentChanges.Length == 1 && contentChanges[0].Range == null)
+ {
+ var c = contentChanges[0];
+ await OmniSharpTestHost.Workspace.BufferManager.UpdateBufferAsync(
+ new UpdateBufferRequest()
+ {
+ FileName = LanguageServerProtocol.Helpers.FromUri(change.TextDocumentEdit
+ .TextDocument.Uri),
+ Buffer = c.NewText
+ });
+ }
+ else
+ {
+ var changes = contentChanges
+ .Select(change => new LinePositionSpanTextChange()
+ {
+ NewText = change.NewText,
+ StartColumn = Convert.ToInt32(change.Range.Start.Character),
+ StartLine = Convert.ToInt32(change.Range.Start.Line),
+ EndColumn = Convert.ToInt32(change.Range.End.Character),
+ EndLine = Convert.ToInt32(change.Range.End.Line),
+ })
+ .ToArray();
- await OmniSharpTestHost.Workspace.BufferManager.UpdateBufferAsync(
- new UpdateBufferRequest()
- {
- FileName = LanguageServerProtocol.Helpers.FromUri(change.TextDocumentEdit
- .TextDocument.Uri),
- Changes = changes
- });
+ await OmniSharpTestHost.Workspace.BufferManager.UpdateBufferAsync(
+ new UpdateBufferRequest()
+ {
+ FileName = LanguageServerProtocol.Helpers.FromUri(change.TextDocumentEdit
+ .TextDocument.Uri),
+ Changes = changes
+ });
+ }
}
- }
- if (change.IsRenameFile)
- {
- var documents =
- OmniSharpTestHost.Workspace.GetDocuments(change.RenameFile.OldUri.GetFileSystemPath());
- foreach (var oldDocument in documents)
+ if (change.IsRenameFile)
{
- var text = await oldDocument.GetTextAsync();
- var newFilePath = change.RenameFile.NewUri.GetFileSystemPath();
- var newFileName = Path.GetFileName(newFilePath);
- OmniSharpTestHost.Workspace.TryApplyChanges(
- OmniSharpTestHost.Workspace.CurrentSolution
- .RemoveDocument(oldDocument.Id)
- .AddDocument(
- DocumentId.CreateNewId(oldDocument.Project.Id, newFileName),
- newFileName,
- text,
- oldDocument.Folders,
- newFilePath
- )
- );
+ var documents =
+ OmniSharpTestHost.Workspace.GetDocuments(
+ change.RenameFile.OldUri.GetFileSystemPath());
+ foreach (var oldDocument in documents)
+ {
+ var text = await oldDocument.GetTextAsync();
+ var newFilePath = change.RenameFile.NewUri.GetFileSystemPath();
+ var newFileName = Path.GetFileName(newFilePath);
+ OmniSharpTestHost.Workspace.TryApplyChanges(
+ OmniSharpTestHost.Workspace.CurrentSolution
+ .RemoveDocument(oldDocument.Id)
+ .AddDocument(
+ DocumentId.CreateNewId(oldDocument.Project.Id, newFileName),
+ newFileName,
+ text,
+ oldDocument.Folders,
+ newFilePath
+ )
+ );
+ }
}
}
}
- }
- await ClientEvents.SettleNext();
+ await ClientEvents.SettleNext();
+
+ return new ApplyWorkspaceEditResponse()
+ {
+ Applied = true
+ };
+ });
+ });
+ Client = client;
- return new ApplyWorkspaceEditResponse()
- {
- Applied = true
- };
- }));
await startUpTask;
- Configuration = new ConfigurationProvider(Server, Client, CancellationToken);
- Client.Register(x => x.AddHandler(Configuration));
+ Configuration = new ConfigurationProvider(Server, Client, configurationProvider, CancellationToken);
}
public Task DisposeAsync()
diff --git a/tests/OmniSharp.Lsp.Tests/ConfigurationProvider.cs b/tests/OmniSharp.Lsp.Tests/ConfigurationProvider.cs
index 687c448234..3543062801 100644
--- a/tests/OmniSharp.Lsp.Tests/ConfigurationProvider.cs
+++ b/tests/OmniSharp.Lsp.Tests/ConfigurationProvider.cs
@@ -7,29 +7,29 @@
using MediatR;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq;
+using OmniSharp.Extensions.LanguageProtocol.Testing;
using OmniSharp.Extensions.LanguageServer.Protocol;
using OmniSharp.Extensions.LanguageServer.Protocol.Client;
-using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
-using OmniSharp.Extensions.LanguageServer.Protocol.Workspace;
-using TestUtility;
namespace OmniSharp.Lsp.Tests
{
- public class ConfigurationProvider: IConfigurationHandler
+ public class ConfigurationProvider
{
private readonly ILanguageServer _server;
private readonly ILanguageClient _client;
+ private readonly TestConfigurationProvider _configurationProvider;
private readonly CancellationToken _cancellationToken;
- private readonly ConcurrentDictionary<(string section, DocumentUri scope), IConfiguration> _scopedConfigurations =
- new ConcurrentDictionary<(string section, DocumentUri scope), IConfiguration>();
-
- public ConfigurationProvider(ILanguageServer server, ILanguageClient client,
+ public ConfigurationProvider(
+ ILanguageServer server,
+ ILanguageClient client,
+ TestConfigurationProvider configurationProvider,
CancellationToken cancellationToken)
{
_server = server;
_client = client;
+ _configurationProvider = configurationProvider;
_cancellationToken = cancellationToken;
}
@@ -54,7 +54,7 @@ public Task Update(string section, DocumentUri documentUri, IDictionary configuration);
+ _configurationProvider.Update(section, documentUri, configuration);
return TriggerChange();
}
@@ -65,128 +65,13 @@ public Task Reset(string section)
public Task Reset(string section, DocumentUri documentUri)
{
- _scopedConfigurations.TryRemove((section, documentUri), out _);
- _client.Workspace.DidChangeConfiguration(new DidChangeConfigurationParams());
+ _configurationProvider.Reset(section, documentUri);
return TriggerChange();
}
- private IConfiguration Get(ConfigurationItem configurationItem)
- {
- if (_scopedConfigurations.TryGetValue(
- (configurationItem.Section, configurationItem.ScopeUri),
- out var configuration)
- )
- {
- return new Microsoft.Extensions.Configuration.ConfigurationBuilder()
- .AddConfiguration(configuration, false)
- .Build();
- }
-
- return new Microsoft.Extensions.Configuration.ConfigurationBuilder().Build();
- }
-
private async Task TriggerChange()
{
- _client.Workspace.DidChangeConfiguration(new DidChangeConfigurationParams());
await _server.Configuration.WaitForChange(_cancellationToken);
}
-
- Task> IRequestHandler>. Handle(ConfigurationParams request, CancellationToken cancellationToken)
- {
- var results = new List();
- foreach (var item in request.Items)
- {
- var config = Get(item);
- results.Add(Parse(config.AsEnumerable(true).Where(x => x.Value != null)));
- }
-
- return Task.FromResult>(results);
- }
-
- private JObject Parse(IEnumerable> values)
- {
- if (values == null)
- {
- throw new ArgumentNullException(nameof(values));
- }
-
- var result = new JObject();
- foreach (var item in values)
- {
- var keys = item.Key.Split(new [] { ":" }, StringSplitOptions.RemoveEmptyEntries);
- var prop = keys.Last();
- JToken root = result;
-
- // This produces a simple look ahead
- var zippedKeys = keys
- .Zip(keys.Skip(1), (prev, current) => (prev, current));
-
- foreach (var (key, next) in zippedKeys)
- {
- if (int.TryParse(next, out var value))
- {
- root = SetValueToToken(root, key, new JArray());
- }
- else
- {
- root = SetValueToToken(root, key, new JObject());
- }
- }
-
- SetValueToToken(root, prop, new JValue(item.Value));
- }
- return result;
- }
- private T SetValueToToken(JToken root, string key, T value)
- where T : JToken
- {
- var currentValue = GetValueFromToken(root, key);
- if (currentValue == null || currentValue.Type == JTokenType.Null)
- {
- if (root is JArray arr)
- {
- if (int.TryParse(key, out var index))
- {
- if (arr.Count <= index)
- {
- while (arr.Count < index)
- arr.Add(null!);
- arr.Add(value);
- }
- else
- {
- arr[index] = value;
- }
-
- return value;
- }
- }
- else
- {
- root[key] = value;
- return value;
- }
- }
-
- if (root is JArray arr2 && int.TryParse(key, out var i))
- {
- return (T)arr2[i];
- }
- return root[key] as T;
- }
-
- private static JToken GetValueFromToken(JToken root, string key)
- {
- if (root is JArray arr)
- {
- if (int.TryParse(key, out var index))
- {
- if (arr.Count <= index) return null;
- return arr[index];
- }
- throw new IndexOutOfRangeException(key);
- }
- return root[key];
- }
}
}
diff --git a/tests/OmniSharp.Lsp.Tests/LanguageServerFoundationFacts.cs b/tests/OmniSharp.Lsp.Tests/LanguageServerFoundationFacts.cs
index 2e115b6a19..e0e4dd83a7 100644
--- a/tests/OmniSharp.Lsp.Tests/LanguageServerFoundationFacts.cs
+++ b/tests/OmniSharp.Lsp.Tests/LanguageServerFoundationFacts.cs
@@ -1,5 +1,8 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
+using System.Reflection;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@@ -7,6 +10,9 @@
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json.Linq;
+using OmniSharp.Extensions.JsonRpc;
+using OmniSharp.Extensions.JsonRpc.Server;
+using OmniSharp.Extensions.LanguageProtocol.Testing;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Workspace;
using OmniSharp.Options;
@@ -46,5 +52,63 @@ await Task.WhenAll(
Assert.Equal(12, options.CurrentValue.FormattingOptions.IndentationSize);
Assert.True(options.CurrentValue.RenameOptions.RenameOverloads);
}
+
+ ///
+ /// This ensures the server has registered all handlers
+ ///
+ ///
+ [Theory]
+ [ClassData(typeof(RegistersAllKnownOmniSharpHandlersData))]
+ public void Registers_all_known_OmniSharp_handlers(string method)
+ {
+ var descriptor = Server.GetRequiredService().Descriptors
+ .FirstOrDefault(z => z.Method == $"o#{method}".ToLowerInvariant());
+ Assert.NotNull(descriptor);
+ }
+
+ ///
+ /// This ensures that the client can call the methods (the server has properly registered it)
+ ///
+ ///
+ ///
+ [Theory]
+ [ClassData(typeof(RegistersAllKnownOmniSharpHandlersData))]
+ public async Task All_known_OmniSharp_handlers_are_callable(string method)
+ {
+ try
+ {
+ var cts = CancellationTokenSource.CreateLinkedTokenSource(CancellationToken);
+ cts.CancelAfter(TimeSpan.FromSeconds(1));
+ await Client.SendRequest($"o#{method}".ToLowerInvariant(), new object()).ReturningVoid(cts.Token);
+ }
+ catch (MethodNotSupportedException)
+ {
+ Assert.False(true, "Method should be supported!");
+ }
+ catch (Exception e)
+ {
+ Logger.LogWarning(e, "got exception");
+ }
+ }
+
+ class RegistersAllKnownOmniSharpHandlersData : TheoryData
+ {
+ public RegistersAllKnownOmniSharpHandlersData()
+ {
+ var v1Fields = typeof(OmniSharpEndpoints).GetFields(BindingFlags.Public | BindingFlags.Static)
+ .Where(z => z.FieldType == typeof(string));
+ foreach (var field in v1Fields)
+ {
+ Add(field.GetValue(null) as string);
+ }
+
+ var v2Fields = typeof(OmniSharpEndpoints.V2).GetFields(BindingFlags.Public | BindingFlags.Static)
+ .Where(z => z.FieldType == typeof(string));
+ foreach (var field in v2Fields)
+ {
+ Add(field.GetValue(null) as string);
+ }
+ }
+ }
}
}
diff --git a/tests/OmniSharp.Lsp.Tests/OmniSharpCodeActionHandlerFacts.cs b/tests/OmniSharp.Lsp.Tests/OmniSharpCodeActionHandlerFacts.cs
index 5d9055e3f7..296335b981 100644
--- a/tests/OmniSharp.Lsp.Tests/OmniSharpCodeActionHandlerFacts.cs
+++ b/tests/OmniSharp.Lsp.Tests/OmniSharpCodeActionHandlerFacts.cs
@@ -95,7 +95,7 @@ public class c {public c() {Guid.NewGuid();}}";
var response =
(await RunRefactoringAsync(code, "Remove Unnecessary Usings",
isAnalyzersEnabled: roslynAnalyzersEnabled)).Single();
- var updatedText = await OmniSharpTestHost.Workspace.GetDocument(response.FileName).GetTextAsync();
+ var updatedText = await OmniSharpTestHost.Workspace.GetDocument(response.FileName).GetTextAsync(CancellationToken);
AssertUtils.AssertIgnoringIndent(expected, updatedText.ToString());
}
@@ -199,7 +199,7 @@ private static void NewMethod()
var response =
(await RunRefactoringAsync(code, "Extract Method", isAnalyzersEnabled: roslynAnalyzersEnabled))
.Single();
- var updatedText = await OmniSharpTestHost.Workspace.GetDocument(response.FileName).GetTextAsync();
+ var updatedText = await OmniSharpTestHost.Workspace.GetDocument(response.FileName).GetTextAsync(CancellationToken);
AssertUtils.AssertIgnoringIndent(expected, updatedText.ToString());
}
@@ -224,7 +224,7 @@ await Client.ExecuteCommand(Command.Create("omnisharp/executeCodeAction")
}), CancellationToken);
var updatedDocument = OmniSharpTestHost.Workspace.GetDocument(Path.Combine(Path.GetDirectoryName(document.FilePath), "Z.cs"));
- var updateDocumentText = await updatedDocument.GetTextAsync();
+ var updateDocumentText = await updatedDocument.GetTextAsync(CancellationToken);
Assert.Equal(@"namespace ConsoleApplication
{
@@ -296,7 +296,7 @@ private async Task> FindRefactoringsAsync(string code,
Context = new CodeActionContext() { },
Range = LanguageServerProtocol.Helpers.ToRange(range),
TextDocument = new TextDocumentIdentifier(bufferPath)
- });
+ }, CancellationToken);
return response.Where(z => z.IsCodeAction).Select(z => z.CodeAction);
}
@@ -309,7 +309,7 @@ private async Task> RunRefactoringsAsync(string code, Comm
OmniSharpTestHost.AddFilesToWorkspace(testFile);
- await Client.Workspace.ExecuteCommand(command);
+ await Client.Workspace.ExecuteCommand(command, CancellationToken);
return new[] {testFile};
}
diff --git a/tests/TestUtility/ConfigurationHelpers.cs b/tests/TestUtility/ConfigurationHelpers.cs
index 52f5afb034..f0ccf86f3c 100644
--- a/tests/TestUtility/ConfigurationHelpers.cs
+++ b/tests/TestUtility/ConfigurationHelpers.cs
@@ -19,32 +19,5 @@ public static IConfiguration ToConfiguration(this IEnumerable(observer =>
- {
- var reloadToken = configuration.GetReloadToken();
- return reloadToken.RegisterChangeCallback(_ =>
- {
- observer.OnNext(Unit.Default);
- observer.OnCompleted();
- }, Unit.Default);
- }).ToTask(cancellationToken);
- }
-
- public static Task WaitForChange(this IOptionsMonitor options, CancellationToken cancellationToken)
- {
- if (options == null) throw new ArgumentNullException(nameof(options));
- return Observable.Create(observer =>
- {
- return options.OnChange(_ =>
- {
- observer.OnNext(Unit.Default);
- observer.OnCompleted();
- });
- }).ToTask(cancellationToken);
- }
}
}