Skip to content

Commit 99ce493

Browse files
Merge pull request #36 from OmniSharp/fix/lsprouter-support-manyhandlers-tests
LspRouter update, update `Supports<>`
2 parents a191b5f + 0ea948d commit 99ce493

24 files changed

+419
-83
lines changed

src/Lsp/Capabilities/Client/Supports.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using Newtonsoft.Json;
33
using OmniSharp.Extensions.LanguageServer.Converters;
44

@@ -38,8 +38,9 @@ public static implicit operator Supports<T>(T value)
3838
public static class Supports
3939
{
4040
public static Supports<T> OfValue<T>(T value)
41+
where T : class
4142
{
42-
return new Supports<T>(true, value);
43+
return new Supports<T>(value != null, value);
4344
}
4445

4546
public static Supports<T> OfBoolean<T>(bool isSupported)

src/Lsp/Capabilities/Client/TextDocumentClientCapabilities.cs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Newtonsoft.Json;
1+
using System.ComponentModel;
2+
using Newtonsoft.Json;
23
using Newtonsoft.Json.Serialization;
34

45
namespace OmniSharp.Extensions.LanguageServer.Capabilities.Client
@@ -8,74 +9,119 @@ public class TextDocumentClientCapabilities
89
{
910
public Supports<SynchronizationCapability> Synchronization { get; set; }
1011

12+
[EditorBrowsable(EditorBrowsableState.Never)]
13+
public bool ShouldSerializeSynchronization() => Synchronization.IsSupported;
14+
1115
/// <summary>
1216
/// Capabilities specific to the `textDocument/completion`
1317
/// </summary>
1418
public Supports<CompletionCapability> Completion { get; set; }
1519

20+
[EditorBrowsable(EditorBrowsableState.Never)]
21+
public bool ShouldSerializeCompletion() => Completion.IsSupported;
22+
1623
/// <summary>
1724
/// Capabilities specific to the `textDocument/hover`
1825
/// </summary>
1926
public Supports<HoverCapability> Hover { get; set; }
2027

28+
[EditorBrowsable(EditorBrowsableState.Never)]
29+
public bool ShouldSerializeHover() => Hover.IsSupported;
30+
2131
/// <summary>
2232
/// Capabilities specific to the `textDocument/signatureHelp`
2333
/// </summary>
2434
public Supports<SignatureHelpCapability> SignatureHelp { get; set; }
2535

36+
[EditorBrowsable(EditorBrowsableState.Never)]
37+
public bool ShouldSerializeSignatureHelp() => SignatureHelp.IsSupported;
38+
2639
/// <summary>
2740
/// Capabilities specific to the `textDocument/references`
2841
/// </summary>
2942
public Supports<ReferencesCapability> References { get; set; }
3043

44+
[EditorBrowsable(EditorBrowsableState.Never)]
45+
public bool ShouldSerializeReferences() => References.IsSupported;
46+
3147
/// <summary>
3248
/// Capabilities specific to the `textDocument/documentHighlight`
3349
/// </summary>
3450
public Supports<DocumentHighlightCapability> DocumentHighlight { get; set; }
3551

52+
[EditorBrowsable(EditorBrowsableState.Never)]
53+
public bool ShouldSerializeDocumentHighlight() => DocumentHighlight.IsSupported;
54+
3655
/// <summary>
3756
/// Capabilities specific to the `textDocument/documentSymbol`
3857
/// </summary>
3958
public Supports<DocumentSymbolCapability> DocumentSymbol { get; set; }
4059

60+
[EditorBrowsable(EditorBrowsableState.Never)]
61+
public bool ShouldSerializeDocumentSymbol() => DocumentSymbol.IsSupported;
62+
4163
/// <summary>
4264
/// Capabilities specific to the `textDocument/formatting`
4365
/// </summary>
4466
public Supports<DocumentFormattingCapability> Formatting { get; set; }
4567

68+
[EditorBrowsable(EditorBrowsableState.Never)]
69+
public bool ShouldSerializeFormatting() => Formatting.IsSupported;
70+
4671
/// <summary>
4772
/// Capabilities specific to the `textDocument/rangeFormatting`
4873
/// </summary>
4974
public Supports<DocumentRangeFormattingCapability> RangeFormatting { get; set; }
5075

76+
[EditorBrowsable(EditorBrowsableState.Never)]
77+
public bool ShouldSerializeRangeFormatting() => RangeFormatting.IsSupported;
78+
5179
/// <summary>
5280
/// Capabilities specific to the `textDocument/onTypeFormatting`
5381
/// </summary>
5482
public Supports<DocumentOnTypeFormattingCapability> OnTypeFormatting { get; set; }
5583

84+
[EditorBrowsable(EditorBrowsableState.Never)]
85+
public bool ShouldSerializeOnTypeFormatting() => OnTypeFormatting.IsSupported;
86+
5687
/// <summary>
5788
/// Capabilities specific to the `textDocument/definition`
5889
/// </summary>
5990
public Supports<DefinitionCapability> Definition { get; set; }
6091

92+
[EditorBrowsable(EditorBrowsableState.Never)]
93+
public bool ShouldSerializeDefinition() => Definition.IsSupported;
94+
6195
/// <summary>
6296
/// Capabilities specific to the `textDocument/codeAction`
6397
/// </summary>
6498
public Supports<CodeActionCapability> CodeAction { get; set; }
6599

100+
[EditorBrowsable(EditorBrowsableState.Never)]
101+
public bool ShouldSerializeCodeAction() => CodeAction.IsSupported;
102+
66103
/// <summary>
67104
/// Capabilities specific to the `textDocument/codeLens`
68105
/// </summary>
69106
public Supports<CodeLensCapability> CodeLens { get; set; }
70107

108+
[EditorBrowsable(EditorBrowsableState.Never)]
109+
public bool ShouldSerializeCodeLens() => CodeLens.IsSupported;
110+
71111
/// <summary>
72112
/// Capabilities specific to the `textDocument/documentLink`
73113
/// </summary>
74114
public Supports<DocumentLinkCapability> DocumentLink { get; set; }
75115

116+
[EditorBrowsable(EditorBrowsableState.Never)]
117+
public bool ShouldSerializeDocumentLink() => DocumentLink.IsSupported;
118+
76119
/// <summary>
77120
/// Capabilities specific to the `textDocument/rename`
78121
/// </summary>
79122
public Supports<RenameCapability> Rename { get; set; }
123+
124+
[EditorBrowsable(EditorBrowsableState.Never)]
125+
public bool ShouldSerializeRename() => Rename.IsSupported;
80126
}
81127
}

src/Lsp/Capabilities/Client/WorkspaceClientCapabilites.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Newtonsoft.Json;
1+
using System.ComponentModel;
2+
using Newtonsoft.Json;
23
using Newtonsoft.Json.Serialization;
34

45
namespace OmniSharp.Extensions.LanguageServer.Capabilities.Client
@@ -10,28 +11,46 @@ public class WorkspaceClientCapabilites
1011
/// The client supports applying batch edits
1112
/// to the workspace.
1213
/// </summary>
13-
public bool ApplyEdit { get; set; }
14+
public Supports<bool> ApplyEdit { get; set; }
15+
16+
[EditorBrowsable(EditorBrowsableState.Never)]
17+
public bool ShouldSerializeApplyEdit() => ApplyEdit.IsSupported;
1418

1519
public Supports<WorkspaceEditCapability> WorkspaceEdit { get; set; }
1620

21+
[EditorBrowsable(EditorBrowsableState.Never)]
22+
public bool ShouldSerializeWorkspaceEdit() => WorkspaceEdit.IsSupported;
23+
1724
/// <summary>
1825
/// Capabilities specific to the `workspace/didChangeConfiguration` notification.
1926
/// </summary>
2027
public Supports<DidChangeConfigurationCapability> DidChangeConfiguration { get; set; }
2128

29+
[EditorBrowsable(EditorBrowsableState.Never)]
30+
public bool ShouldSerializeDidChangeConfiguration() => DidChangeConfiguration.IsSupported;
31+
2232
/// <summary>
2333
/// Capabilities specific to the `workspace/didChangeWatchedFiles` notification.
2434
/// </summary>
2535
public Supports<DidChangeWatchedFilesCapability> DidChangeWatchedFiles { get; set; }
2636

37+
[EditorBrowsable(EditorBrowsableState.Never)]
38+
public bool ShouldSerializeDidChangeWatchedFiles() => DidChangeWatchedFiles.IsSupported;
39+
2740
/// <summary>
2841
/// Capabilities specific to the `workspace/symbol` request.
2942
/// </summary>
3043
public Supports<WorkspaceSymbolCapability> Symbol { get; set; }
3144

45+
[EditorBrowsable(EditorBrowsableState.Never)]
46+
public bool ShouldSerializeSymbol() => Symbol.IsSupported;
47+
3248
/// <summary>
3349
/// Capabilities specific to the `workspace/executeCommand` request.
3450
/// </summary>
3551
public Supports<ExecuteCommandCapability> ExecuteCommand { get; set; }
52+
53+
[EditorBrowsable(EditorBrowsableState.Never)]
54+
public bool ShouldSerializeExecuteCommand() => ExecuteCommand.IsSupported;
3655
}
3756
}

src/Lsp/Converters/SupportsConverter.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Reflection;
33
using Newtonsoft.Json;
44
using OmniSharp.Extensions.LanguageServer.Capabilities.Client;
@@ -35,7 +35,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
3535
}
3636
else
3737
{
38-
serializer.Serialize(writer, false);
38+
serializer.Serialize(writer, null);
3939
}
4040
}
4141

@@ -44,6 +44,10 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
4444
var targetType = objectType.GetTypeInfo().GetGenericArguments()[0];
4545
if (reader.TokenType == JsonToken.Boolean)
4646
{
47+
if (targetType == typeof(bool))
48+
{
49+
return new Supports<bool>(true, (bool)reader.Value);
50+
}
4751
return OfBooleanMethod
4852
.MakeGenericMethod(targetType)
4953
.Invoke(null, new [] { reader.Value });
@@ -60,4 +64,4 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
6064

6165
public override bool CanConvert(Type objectType) => objectType.GetGenericTypeDefinition() == typeof(Supports<>);
6266
}
63-
}
67+
}

src/Lsp/HandlerCollection.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections;
33
using System.Collections.Generic;
44
using System.Linq;
@@ -48,9 +48,11 @@ public IDisposable Add(params IJsonRpcHandler[] handlers)
4848
}
4949

5050
var key = "default";
51-
if (handler is IRegistration<TextDocumentRegistrationOptions> textDocumentRegistration)
51+
if (handler is IRegistration<TextDocumentRegistrationOptions>)
5252
{
53-
var options = textDocumentRegistration.GetRegistrationOptions();
53+
var options = GetTextDocumentRegistrationOptionsMethod
54+
.MakeGenericMethod(registration)
55+
.Invoke(handler, new object[] { handler }) as TextDocumentRegistrationOptions;
5456
key = options.DocumentSelector;
5557
}
5658

@@ -76,6 +78,15 @@ public IDisposable Add(params IJsonRpcHandler[] handlers)
7678
return new ImmutableDisposable(descriptors);
7779
}
7880

81+
private static readonly MethodInfo GetTextDocumentRegistrationOptionsMethod = typeof(HandlerCollection).GetTypeInfo()
82+
.GetMethod(nameof(GetTextDocumentRegistrationOptions), BindingFlags.Static | BindingFlags.NonPublic);
83+
84+
private static TextDocumentRegistrationOptions GetTextDocumentRegistrationOptions<T>(IRegistration<T> instance)
85+
where T : TextDocumentRegistrationOptions
86+
{
87+
return instance.GetRegistrationOptions();
88+
}
89+
7990
private Type UnwrapGenericType(Type genericType, Type type)
8091
{
8192
return type?.GetTypeInfo()

src/Lsp/InitializeDelegate.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
using System.Threading.Tasks;
2+
using OmniSharp.Extensions.LanguageServer.Models;
3+
4+
namespace OmniSharp.Extensions.LanguageServer
5+
{
6+
public delegate Task InitializeDelegate(InitializeParams request);
7+
}

src/Lsp/LanguageServer.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818

1919
namespace OmniSharp.Extensions.LanguageServer
2020
{
21-
public delegate Task InitializeDelegate(InitializeParams request);
22-
2321
public class LanguageServer : ILanguageServer, IInitializeHandler, IInitializedHandler, IDisposable, IAwaitableTermination
2422
{
2523
private readonly Connection _connection;

src/Lsp/LspRequestRouter.cs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
using System;
1+
using System;
22
using System.Collections.Concurrent;
3+
using System.Collections.Generic;
34
using System.Linq;
45
using System.Reflection;
56
using System.Threading;
@@ -18,7 +19,7 @@ namespace OmniSharp.Extensions.LanguageServer
1819
class LspRequestRouter : IRequestRouter
1920
{
2021
private readonly IHandlerCollection _collection;
21-
private ITextDocumentSyncHandler _textDocumentSyncHandler;
22+
private ITextDocumentSyncHandler[] _textDocumentSyncHandlers;
2223
private readonly ConcurrentDictionary<string, CancellationTokenSource> _requests = new ConcurrentDictionary<string, CancellationTokenSource>();
2324

2425
public LspRequestRouter(IHandlerCollection collection)
@@ -43,22 +44,23 @@ private string GetId(object id)
4344

4445
private ILspHandlerDescriptor FindDescriptor(string method, JToken @params)
4546
{
46-
var descriptor = _collection.FirstOrDefault(x => x.Method == method);
47+
var descriptor = _collection.FirstOrDefault(x => x.Method.Equals(method, StringComparison.OrdinalIgnoreCase));
4748
if (descriptor is null) return null;
4849

49-
if (_textDocumentSyncHandler == null)
50+
if (_textDocumentSyncHandlers == null)
5051
{
51-
_textDocumentSyncHandler = _collection
52+
_textDocumentSyncHandlers = _collection
5253
.Select(x => x.Handler is ITextDocumentSyncHandler r ? r : null)
53-
.FirstOrDefault(x => x != null);
54+
.Where(x => x != null)
55+
.ToArray();
5456
}
5557

56-
if (_textDocumentSyncHandler is null) return descriptor;
57-
5858
if (typeof(ITextDocumentIdentifierParams).GetTypeInfo().IsAssignableFrom(descriptor.Params))
5959
{
6060
var textDocumentIdentifierParams = @params.ToObject(descriptor.Params) as ITextDocumentIdentifierParams;
61-
var attributes = _textDocumentSyncHandler.GetTextDocumentAttributes(textDocumentIdentifierParams.TextDocument.Uri);
61+
var attributes = _textDocumentSyncHandlers
62+
.Select(x => x.GetTextDocumentAttributes(textDocumentIdentifierParams.TextDocument.Uri))
63+
.Where(x => x != null);
6264

6365
return GetHandler(method, attributes);
6466
}
@@ -75,6 +77,13 @@ private ILspHandlerDescriptor FindDescriptor(string method, JToken @params)
7577
return descriptor;
7678
}
7779

80+
private ILspHandlerDescriptor GetHandler(string method, IEnumerable<TextDocumentAttributes> attributes)
81+
{
82+
return attributes
83+
.Select(x => GetHandler(method, x))
84+
.FirstOrDefault(x => x != null);
85+
}
86+
7887
private ILspHandlerDescriptor GetHandler(string method, TextDocumentAttributes attributes)
7988
{
8089
foreach (var handler in _collection.Where(x => x.Method == method))

src/Lsp/Models/CodeActionParams.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
using Newtonsoft.Json;
1+
using Newtonsoft.Json;
22
using Newtonsoft.Json.Serialization;
33

44
namespace OmniSharp.Extensions.LanguageServer.Models
55
{
6-
public interface ITextDocumentIdentifierParams
7-
{
8-
TextDocumentIdentifier TextDocument { get; }
9-
}
10-
116
/// <summary>
127
/// Params for the CodeActionRequest
138
/// </summary>

src/Lsp/Models/DocumentFilter.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System.Collections.Generic;
2+
using System.Linq;
23
using System.Text;
34
using Minimatch;
45
using Newtonsoft.Json;
@@ -108,5 +109,20 @@ public bool IsMatch(TextDocumentAttributes attributes)
108109

109110
return false;
110111
}
112+
113+
public static DocumentFilter ForPattern(string wildcard)
114+
{
115+
return new DocumentFilter() { Pattern = wildcard };
116+
}
117+
118+
public static DocumentFilter ForLanguage(string language)
119+
{
120+
return new DocumentFilter() { Language = language };
121+
}
122+
123+
public static DocumentFilter ForScheme(string scheme)
124+
{
125+
return new DocumentFilter() { Scheme = scheme };
126+
}
111127
}
112128
}

0 commit comments

Comments
 (0)