Skip to content

Commit 3e7157d

Browse files
Fixed an issue where handler descriptors would fail to be created of a given handler implemented two or more intefaces. Where one interface has IRegistartion<> and the other does not.
1 parent bbbb6ec commit 3e7157d

File tree

2 files changed

+32
-18
lines changed

2 files changed

+32
-18
lines changed

src/Server/HandlerCollection.cs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,12 @@ private HandlerDescriptor GetDescriptor(string method, Type implementedType, IJs
7171
}
7272

7373
var key = "default";
74-
if (handler is IRegistration<TextDocumentRegistrationOptions>)
74+
// This protects against the case where class implements many, possibly conflicting, interfaces.
75+
if (registration != null &&
76+
typeof(TextDocumentRegistrationOptions).GetTypeInfo().IsAssignableFrom(registration) &&
77+
handler is IRegistration<TextDocumentRegistrationOptions> handlerRegistration)
7578
{
76-
if (GetTextDocumentRegistrationOptionsMethod
77-
.MakeGenericMethod(registration)
78-
.Invoke(handler, new object[] { handler }) is TextDocumentRegistrationOptions options)
79-
key = options.DocumentSelector;
79+
key = handlerRegistration.GetRegistrationOptions()?.DocumentSelector ?? key;
8080
}
8181

8282
return new HandlerDescriptor(
@@ -90,15 +90,6 @@ private HandlerDescriptor GetDescriptor(string method, Type implementedType, IJs
9090
() => _handlers.RemoveWhere(instance => instance.Handler == handler));
9191
}
9292

93-
private static readonly MethodInfo GetTextDocumentRegistrationOptionsMethod = typeof(HandlerCollection).GetTypeInfo()
94-
.GetMethod(nameof(GetTextDocumentRegistrationOptions), BindingFlags.Static | BindingFlags.NonPublic);
95-
96-
private static TextDocumentRegistrationOptions GetTextDocumentRegistrationOptions<T>(IRegistration<T> instance)
97-
where T : TextDocumentRegistrationOptions
98-
{
99-
return instance.GetRegistrationOptions();
100-
}
101-
10293
private Type UnwrapGenericType(Type genericType, Type type)
10394
{
10495
return type?.GetTypeInfo()

test/Lsp.Tests/HandlerResolverTests.cs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
1212
using Xunit;
1313
using HandlerCollection = OmniSharp.Extensions.LanguageServer.Server.HandlerCollection;
14+
using System.Collections.Generic;
1415

1516
namespace Lsp.Tests
1617
{
@@ -133,7 +134,8 @@ public void Should_Contain_AllDefinedMethods_OnLanguageServer(Type requestHandle
133134
var sub = (IJsonRpcHandler)Substitute.For(new Type[] { requestHandler, type2 }, new object[0]);
134135
if (sub is IRegistration<TextDocumentRegistrationOptions> reg)
135136
reg.GetRegistrationOptions()
136-
.Returns(new TextDocumentRegistrationOptions() {
137+
.Returns(new TextDocumentRegistrationOptions()
138+
{
137139
DocumentSelector = new DocumentSelector()
138140
});
139141
handler.Add(sub);
@@ -150,13 +152,15 @@ public void Should_Contain_AllDefinedMethods_OnLanguageServer_WithDifferentKeys(
150152
var sub = (IJsonRpcHandler)Substitute.For(new Type[] { requestHandler, type2 }, new object[0]);
151153
if (sub is IRegistration<TextDocumentRegistrationOptions> reg)
152154
reg.GetRegistrationOptions()
153-
.Returns(new TextDocumentRegistrationOptions() {
155+
.Returns(new TextDocumentRegistrationOptions()
156+
{
154157
DocumentSelector = new DocumentSelector()
155158
});
156159
var sub2 = (IJsonRpcHandler)Substitute.For(new Type[] { requestHandler, type2 }, new object[0]);
157160
if (sub2 is IRegistration<TextDocumentRegistrationOptions> reg2)
158161
reg2.GetRegistrationOptions()
159-
.Returns(new TextDocumentRegistrationOptions() {
162+
.Returns(new TextDocumentRegistrationOptions()
163+
{
160164
DocumentSelector = new DocumentSelector()
161165
});
162166
handler.Add(sub);
@@ -172,12 +176,31 @@ public void Should_AllowSpecificHandlers_ToBeAdded(string method, Type handlerTy
172176
{
173177
var handler = new HandlerCollection();
174178
var sub = (IJsonRpcHandler)Substitute.For(new Type[] { handlerType }, new object[0]);
175-
var sub2= (IJsonRpcHandler)Substitute.For(new Type[] { handlerType }, new object[0]);
179+
var sub2 = (IJsonRpcHandler)Substitute.For(new Type[] { handlerType }, new object[0]);
176180
handler.Add(method, sub);
177181
handler.Add(method, sub2);
178182
handler._handlers.Should().Contain(x => x.Method == method);
179183
handler._handlers.Should().Contain(x => x.Method == method);
180184
handler._handlers.Count.Should().Be(1);
181185
}
186+
187+
[Theory]
188+
[MemberData(nameof(Should_DealWithClassesThatImplementMultipleHandlers_WithoutConflictingRegistrations_Data))]
189+
public void Should_DealWithClassesThatImplementMultipleHandlers_WithoutConflictingRegistrations(string method, IJsonRpcHandler sub)
190+
{
191+
var handler = new HandlerCollection();
192+
handler.Add(sub);
193+
194+
var descriptor = handler._handlers.First(x => x.Method == method);
195+
descriptor.Key.Should().Be("default");
196+
}
197+
198+
public static IEnumerable<object[]> Should_DealWithClassesThatImplementMultipleHandlers_WithoutConflictingRegistrations_Data()
199+
{
200+
yield return new object[] {
201+
DocumentNames.CodeLensResolve,
202+
Substitute.For(new Type[] { typeof(ICodeLensHandler), typeof(ICodeLensResolveHandler) }, new object[0])
203+
};
204+
}
182205
}
183206
}

0 commit comments

Comments
 (0)