Skip to content

Commit 5b1d68b

Browse files
Added new method to allow adding a handler with a given method name (avoiding have to hav have the method attribute on everything)
1 parent 80e1b38 commit 5b1d68b

File tree

6 files changed

+92
-35
lines changed

6 files changed

+92
-35
lines changed

src/JsonRpc/HandlerCollection.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ private void Remove(IJsonRpcHandler handler)
5151
}
5252

5353
public IDisposable Add(IJsonRpcHandler handler)
54+
{
55+
return Add(GetMethodName(handler.GetType()), handler);
56+
}
57+
58+
public IDisposable Add(string method, IJsonRpcHandler handler)
5459
{
5560
var type = handler.GetType();
5661
var @interface = GetHandlerInterface(type);
@@ -61,12 +66,17 @@ public IDisposable Add(IJsonRpcHandler handler)
6166
@params = @interface.GetTypeInfo().GetGenericArguments()[0];
6267
}
6368

64-
var h = new HandlerInstance(GetMethodName(type), handler, @interface, @params, () => Remove(handler));
69+
var h = new HandlerInstance(method, handler, @interface, @params, () => Remove(handler));
6570
_handlers.Add(h);
6671
return h;
6772
}
6873

69-
private static readonly Type[] HandlerTypes = { typeof(INotificationHandler), typeof(INotificationHandler<>), typeof(IRequestHandler<>), typeof(IRequestHandler<,>), };
74+
private static readonly Type[] HandlerTypes = {
75+
typeof(INotificationHandler),
76+
typeof(INotificationHandler<>),
77+
typeof(IRequestHandler<>),
78+
typeof(IRequestHandler<,>),
79+
};
7080

7181
private string GetMethodName(Type type)
7282
{

src/Lsp/Abstractions/IHandlerCollection.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using OmniSharp.Extensions.JsonRpc;
44

55
namespace OmniSharp.Extensions.LanguageServer.Abstractions
66
{
77
public interface IHandlerCollection : IEnumerable<ILspHandlerDescriptor>
88
{
9+
IDisposable Add(string method, IJsonRpcHandler handler);
910
IDisposable Add(params IJsonRpcHandler[] handlers);
1011
IDisposable Add(IEnumerable<IJsonRpcHandler> handlers);
1112
}

src/Lsp/HandlerCollection.cs

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ IEnumerator IEnumerable.GetEnumerator()
2323
return GetEnumerator();
2424
}
2525

26+
public IDisposable Add(string method, IJsonRpcHandler handler)
27+
{
28+
var descriptor = GetDescriptor(method, handler.GetType(), handler);
29+
_handlers.Add(descriptor);
30+
return descriptor;
31+
}
32+
2633
public IDisposable Add(IEnumerable<IJsonRpcHandler> handlers)
2734
{
2835
return Add(handlers.ToArray());
@@ -33,40 +40,12 @@ public IDisposable Add(params IJsonRpcHandler[] handlers)
3340
var descriptors = new HashSet<HandlerDescriptor>();
3441
foreach (var handler in handlers)
3542
{
36-
foreach (var implementedInterface in handler.GetType().GetTypeInfo()
43+
foreach (var (method, implementedInterface) in handler.GetType().GetTypeInfo()
3744
.ImplementedInterfaces
38-
.Where(x => !string.IsNullOrWhiteSpace(LspHelper.GetMethodName(x))))
45+
.Select(x => (method: LspHelper.GetMethodName(x), implementedInterface: x))
46+
.Where(x => !string.IsNullOrWhiteSpace(x.method)))
3947
{
40-
var @interface = HandlerTypeHelpers.GetHandlerInterface(implementedInterface);
41-
var registration = UnwrapGenericType(typeof(IRegistration<>), implementedInterface);
42-
var capability = UnwrapGenericType(typeof(ICapability<>), implementedInterface);
43-
44-
Type @params = null;
45-
if (@interface.GetTypeInfo().IsGenericType)
46-
{
47-
@params = @interface.GetTypeInfo().GetGenericArguments()[0];
48-
}
49-
50-
var key = "default";
51-
if (handler is IRegistration<TextDocumentRegistrationOptions>)
52-
{
53-
if (GetTextDocumentRegistrationOptionsMethod
54-
.MakeGenericMethod(registration)
55-
.Invoke(handler, new object[] { handler }) is TextDocumentRegistrationOptions options)
56-
key = options.DocumentSelector;
57-
}
58-
59-
var h = new HandlerDescriptor(
60-
LspHelper.GetMethodName(implementedInterface),
61-
key,
62-
handler,
63-
@interface,
64-
@params,
65-
registration,
66-
capability,
67-
() => _handlers.RemoveWhere(instance => instance.Handler == handler));
68-
69-
descriptors.Add(h);
48+
descriptors.Add(GetDescriptor(method, implementedInterface, handler));
7049
}
7150
}
7251

@@ -78,6 +57,38 @@ public IDisposable Add(params IJsonRpcHandler[] handlers)
7857
return new ImmutableDisposable(descriptors);
7958
}
8059

60+
private HandlerDescriptor GetDescriptor(string method, Type implementedType, IJsonRpcHandler handler)
61+
{
62+
var @interface = HandlerTypeHelpers.GetHandlerInterface(implementedType);
63+
var registration = UnwrapGenericType(typeof(IRegistration<>), implementedType);
64+
var capability = UnwrapGenericType(typeof(ICapability<>), implementedType);
65+
66+
Type @params = null;
67+
if (@interface.GetTypeInfo().IsGenericType)
68+
{
69+
@params = @interface.GetTypeInfo().GetGenericArguments()[0];
70+
}
71+
72+
var key = "default";
73+
if (handler is IRegistration<TextDocumentRegistrationOptions>)
74+
{
75+
if (GetTextDocumentRegistrationOptionsMethod
76+
.MakeGenericMethod(registration)
77+
.Invoke(handler, new object[] { handler }) is TextDocumentRegistrationOptions options)
78+
key = options.DocumentSelector;
79+
}
80+
81+
return new HandlerDescriptor(
82+
method,
83+
key,
84+
handler,
85+
@interface,
86+
@params,
87+
registration,
88+
capability,
89+
() => _handlers.RemoveWhere(instance => instance.Handler == handler));
90+
}
91+
8192
private static readonly MethodInfo GetTextDocumentRegistrationOptionsMethod = typeof(HandlerCollection).GetTypeInfo()
8293
.GetMethod(nameof(GetTextDocumentRegistrationOptions), BindingFlags.Static | BindingFlags.NonPublic);
8394

src/Lsp/ILanguageServer.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace OmniSharp.Extensions.LanguageServer
77
{
88
public interface ILanguageServer : IResponseRouter
99
{
10+
IDisposable AddHandler(string method, IJsonRpcHandler handler);
1011
IDisposable AddHandler(IJsonRpcHandler handler);
1112
IDisposable AddHandlers(IEnumerable<IJsonRpcHandler> handlers);
1213
IDisposable AddHandlers(params IJsonRpcHandler[] handlers);

src/Lsp/LanguageServer.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,26 @@ internal LanguageServer(Stream input, IOutputHandler output, LspReciever recieve
5959
public InitializeParams Client { get; private set; }
6060
public InitializeResult Server { get; private set; }
6161

62+
public IDisposable AddHandler(string method, IJsonRpcHandler handler)
63+
{
64+
var handlerDisposable = _collection.Add(method, handler);
65+
66+
return new ImmutableDisposable(
67+
handlerDisposable,
68+
new Disposable(() => {
69+
var foundItems = _collection
70+
.Where(x => handler == x.Handler)
71+
.Where(x => x.AllowsDynamicRegistration)
72+
.Select(x => x.Registration)
73+
.Where(x => x != null)
74+
.ToArray();
75+
76+
Task.Run(() => this.UnregisterCapability(new UnregistrationParams() {
77+
Unregisterations = foundItems
78+
}));
79+
}));
80+
}
81+
6282
public IDisposable AddHandler(IJsonRpcHandler handler)
6383
{
6484
return AddHandlers(handler);

test/Lsp.Tests/HandlerResolverTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,5 +168,19 @@ public void Should_Contain_AllDefinedMethods_OnLanguageServer_WithDifferentKeys(
168168
handler._handlers.Should().Contain(x => x.Method == key2);
169169
handler._handlers.Count.Should().Be(count);
170170
}
171+
172+
[Theory]
173+
[InlineData("somemethod", typeof(IRequestHandler<object, object>))]
174+
public void Should_AllowSpecificHandlers_ToBeAdded(string method, Type handlerType)
175+
{
176+
var handler = new HandlerCollection();
177+
var sub = (IJsonRpcHandler)Substitute.For(new Type[] { handlerType }, new object[0]);
178+
var sub2= (IJsonRpcHandler)Substitute.For(new Type[] { handlerType }, new object[0]);
179+
handler.Add(method, sub);
180+
handler.Add(method, sub2);
181+
handler._handlers.Should().Contain(x => x.Method == method);
182+
handler._handlers.Should().Contain(x => x.Method == method);
183+
handler._handlers.Count.Should().Be(1);
184+
}
171185
}
172186
}

0 commit comments

Comments
 (0)