Skip to content

Commit 20b3af2

Browse files
Merge pull request #81 from mholo65/feature/improve-resolve
Improve resolve handler matching
2 parents fae86e0 + 178aaa1 commit 20b3af2

File tree

5 files changed

+38
-7
lines changed

5 files changed

+38
-7
lines changed

src/Protocol/Models/DocumentSelector.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ public static implicit operator DocumentSelector(List<DocumentFilter> items)
3939

4040
public static implicit operator string(DocumentSelector documentSelector)
4141
{
42-
return string.Join(", ", documentSelector.Select(x => (string)x));
42+
return documentSelector != null ?
43+
string.Join(", ", documentSelector.Select(x => (string)x)) :
44+
null;
4345
}
4446

4547
public bool IsMatch(TextDocumentAttributes attributes)

src/Server/HandlerCollection.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,13 @@ private HandlerDescriptor GetDescriptor(string method, Type implementedType, IJs
8282

8383
var key = "default";
8484
// This protects against the case where class implements many, possibly conflicting, interfaces.
85-
if (registration != null &&
86-
typeof(TextDocumentRegistrationOptions).GetTypeInfo().IsAssignableFrom(registration) &&
85+
if ((registration != null && typeof(TextDocumentRegistrationOptions).GetTypeInfo().IsAssignableFrom(registration) ||
86+
registration == null && implementedType.GetTypeInfo().ImplementedInterfaces.Any(x => x.GetTypeInfo().IsGenericType && x.GetTypeInfo().GetGenericTypeDefinition() == typeof(ICanBeResolvedHandler<>))) &&
8787
handler is IRegistration<TextDocumentRegistrationOptions> handlerRegistration)
8888
{
89-
key = handlerRegistration.GetRegistrationOptions()?.DocumentSelector ?? key;
89+
key = string.IsNullOrEmpty(handlerRegistration?.GetRegistrationOptions()?.DocumentSelector)
90+
? key
91+
: handlerRegistration?.GetRegistrationOptions()?.DocumentSelector;
9092
}
9193

9294
return new HandlerDescriptor(

src/Server/Matchers/ResolveCommandMatcher.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class ResolveCommandMatcher : IHandlerMatcher, IHandlerPreProcessorMatche
1313
{
1414
private readonly ILogger _logger;
1515
internal static string PrivateHandlerTypeName = "$$___handlerType___$$";
16+
internal static string PrivateHandlerKey = "$$___handlerKey___$$";
1617

1718
public ResolveCommandMatcher(ILogger logger)
1819
{
@@ -30,10 +31,15 @@ public IEnumerable<ILspHandlerDescriptor> FindHandler(object parameters, IEnumer
3031
if (parameters is ICanBeResolved canBeResolved)
3132
{
3233
string handlerType = null;
34+
string handlerKey = null;
3335
if (canBeResolved.Data != null && canBeResolved.Data.Type == JTokenType.Object)
36+
{
3437
handlerType = canBeResolved.Data?[PrivateHandlerTypeName]?.ToString();
38+
handlerKey = canBeResolved.Data?[PrivateHandlerKey]?.ToString();
39+
}
3540

36-
if (string.IsNullOrWhiteSpace(handlerType))
41+
if (string.IsNullOrWhiteSpace(handlerType) &&
42+
string.IsNullOrWhiteSpace(handlerKey))
3743
{
3844
foreach (var descriptor in descriptors)
3945
{
@@ -65,7 +71,8 @@ public IEnumerable<ILspHandlerDescriptor> FindHandler(object parameters, IEnumer
6571
_logger.LogTrace("Checking handler {Method}:{Handler}",
6672
descriptor.Method,
6773
descriptor.Handler.GetType().FullName);
68-
if (descriptor.Handler.GetType().FullName == handlerType || descriptor.HandlerType.FullName == handlerType)
74+
if ((descriptor.Handler.GetType().FullName == handlerType || descriptor.HandlerType.FullName == handlerType) &&
75+
((descriptor is HandlerDescriptor handlerDescriptor) && handlerDescriptor.Key == handlerKey))
6976
{
7077
yield return descriptor;
7178
}
@@ -121,7 +128,8 @@ public object Process(ILspHandlerDescriptor descriptor, object parameters)
121128
public object Process(ILspHandlerDescriptor descriptor, object parameters, object response)
122129
{
123130
// Only pin the handler type, if we know the source handler (codelens) is also the resolver.
124-
if (response is IEnumerable<ICanBeResolved> canBeResolveds &&
131+
if (descriptor is HandlerDescriptor handlerDescriptor &&
132+
response is IEnumerable<ICanBeResolved> canBeResolveds &&
125133
descriptor?.CanBeResolvedHandlerType?.GetTypeInfo().IsAssignableFrom(descriptor.Handler.GetType()) == true)
126134
{
127135
_logger.LogTrace("Updating Resolve items with wrapped data for {Method}:{Handler}",
@@ -135,6 +143,7 @@ public object Process(ILspHandlerDescriptor descriptor, object parameters, objec
135143
var data = new JObject();
136144
data["data"] = item.Data;
137145
data[PrivateHandlerTypeName] = descriptor.Handler.GetType().FullName;
146+
data[PrivateHandlerKey] = handlerDescriptor.Key;
138147
item.Data = data;
139148
}
140149
}

test/Lsp.Tests/HandlerResolverTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,22 @@ public void Should_DealWithClassesThatImplementMultipleHandlers_WithoutConflicti
192192
descriptor.Key.Should().Be("default");
193193
}
194194

195+
[Fact]
196+
public void Should_DealWithClassesThatImplementMultipleHandlers_BySettingKeyAccordingly()
197+
{
198+
var codeLensHandler = Substitute.For(new Type[] { typeof(ICodeLensHandler), typeof(ICodeLensResolveHandler) }, new object[0]);
199+
((ICodeLensHandler)codeLensHandler).GetRegistrationOptions()
200+
.Returns(new CodeLensRegistrationOptions() {
201+
DocumentSelector = new DocumentSelector(DocumentFilter.ForLanguage("foo"))
202+
});
203+
204+
var handler = new HandlerCollection();
205+
handler.Add(codeLensHandler as IJsonRpcHandler);
206+
207+
var descriptor = handler._handlers.Select(x => x.Key);
208+
descriptor.ShouldAllBeEquivalentTo(new [] { "[foo]", "[foo]" });
209+
}
210+
195211
public static IEnumerable<object[]> Should_DealWithClassesThatImplementMultipleHandlers_WithoutConflictingRegistrations_Data()
196212
{
197213
var codeLensHandler = Substitute.For(new Type[] { typeof(ICodeLensHandler), typeof(ICodeLensResolveHandler) }, new object[0]);

test/Lsp.Tests/Matchers/ResolveCommandMatcherTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ public void Should_Update_CompletionItems_With_HandlerType()
374374
(response as CompletionList).Items.Should().Contain(item);
375375
var responseItem = (response as CompletionList).Items.First();
376376
responseItem.Data[ResolveCommandMatcher.PrivateHandlerTypeName].Value<string>().Should().NotBeNullOrEmpty();
377+
responseItem.Data[ResolveCommandMatcher.PrivateHandlerKey].Value<string>().Should().NotBeNullOrEmpty();
377378
responseItem.Data["data"]["hello"].Value<string>().Should().Be("world");
378379
}
379380

@@ -412,6 +413,7 @@ public void Should_Update_CodeLensContainer_With_HandlerType()
412413
(response as CodeLensContainer).Should().Contain(item);
413414
var responseItem = (response as CodeLensContainer).First();
414415
responseItem.Data[ResolveCommandMatcher.PrivateHandlerTypeName].Value<string>().Should().NotBeNullOrEmpty();
416+
responseItem.Data[ResolveCommandMatcher.PrivateHandlerKey].Value<string>().Should().NotBeNullOrEmpty();
415417
responseItem.Data["data"]["hello"].Value<string>().Should().Be("world");
416418
}
417419

0 commit comments

Comments
 (0)