Skip to content

Commit 42a0a63

Browse files
Fixed an issue with registration for semantic tokens
1 parent 4ee5be0 commit 42a0a63

File tree

11 files changed

+506
-446
lines changed

11 files changed

+506
-446
lines changed

sample/SampleServer/Program.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,6 @@ static async Task MainAsync(string[] args)
5353
.WithHandler<MyWorkspaceSymbolsHandler>()
5454
.WithHandler<MyDocumentSymbolHandler>()
5555
.WithHandler<SemanticTokensHandler>()
56-
// Linking here because the spec changed but vscode is behind
57-
.WithLink(TextDocumentNames.SemanticTokensFull, "textDocument/semanticTokens")
58-
.WithLink(TextDocumentNames.SemanticTokensFullDelta, "textDocument/semanticTokens/edits")
5956
.WithServices(x => x.AddLogging(b => b.SetMinimumLevel(LogLevel.Trace)))
6057
.WithServices(services => {
6158
services.AddSingleton(provider => {

src/Protocol/Document/Proposals/ISemanticTokensDeltaHandler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ public interface ISemanticTokensHandler : IJsonRpcRequestHandler<SemanticTokensP
2222
[Parallel, Method(TextDocumentNames.SemanticTokensFullDelta, Direction.ClientToServer)]
2323
public interface ISemanticTokensDeltaHandler :
2424
IJsonRpcRequestHandler<SemanticTokensDeltaParams, SemanticTokensFullOrDelta>,
25-
IRegistration<SemanticTokensRegistrationOptions>, ICapability<SemanticTokensCapability>
25+
IRegistration<SemanticTokensRegistrationOptions>, ICapability<SemanticTokensCapability>, IDoesNotParticipateInRegistration
2626
{
2727
}
2828

2929
[Obsolete(Constants.Proposal)]
3030
[Parallel, Method(TextDocumentNames.SemanticTokensRange, Direction.ClientToServer)]
3131
public interface ISemanticTokensRangeHandler : IJsonRpcRequestHandler<SemanticTokensRangeParams, SemanticTokens>,
32-
IRegistration<SemanticTokensRegistrationOptions>, ICapability<SemanticTokensCapability>
32+
IRegistration<SemanticTokensRegistrationOptions>, ICapability<SemanticTokensCapability>, IDoesNotParticipateInRegistration
3333
{
3434
}
3535

src/Protocol/IRegistration.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,12 @@ public interface IRegistration<out TOptions>
55
{
66
TOptions GetRegistrationOptions();
77
}
8+
9+
/// <summary>
10+
/// Identifies a handler that does not participate in dynamic registration.
11+
/// </summary>
12+
public interface IDoesNotParticipateInRegistration
13+
{
14+
15+
}
816
}

src/Protocol/Shared/LspHandlerDescriptor.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ public LspHandlerDescriptor(
2727
Func<bool> allowsDynamicRegistration,
2828
Type capabilityType,
2929
RequestProcessType? requestProcessType,
30-
Action disposeAction)
30+
Action disposeAction,
31+
ILspHandlerTypeDescriptor typeDescriptor)
3132
{
3233
_disposeAction = disposeAction;
3334
Id = Guid.NewGuid();
@@ -76,6 +77,7 @@ public LspHandlerDescriptor(
7677
z.IsGenericType && typeof(IJsonRpcNotificationHandler<>).IsAssignableFrom(z.GetGenericTypeDefinition()));
7778
IsRequest = !IsNotification;
7879
RequestProcessType = requestProcessType;
80+
TypeDescriptor = typeDescriptor;
7981
}
8082

8183
public Type ImplementationType { get; }
@@ -106,6 +108,7 @@ public LspHandlerDescriptor(
106108
public bool IsNotification { get; }
107109
public bool IsRequest { get; }
108110
public RequestProcessType? RequestProcessType { get; }
111+
public ILspHandlerTypeDescriptor TypeDescriptor { get; }
109112

110113
public void Dispose()
111114
{

src/Server/LanguageServer.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,11 @@ private IDisposable RegisterHandlers(IEnumerable<ILspHandlerDescriptor> collecti
523523
var registrations = new List<Registration>();
524524
foreach (var descriptor in collection)
525525
{
526+
if (descriptor is LspHandlerDescriptor lspHandlerDescriptor &&
527+
typeof(IDoesNotParticipateInRegistration).IsAssignableFrom(lspHandlerDescriptor.TypeDescriptor.HandlerType))
528+
{
529+
continue;
530+
}
526531
if (descriptor.HasCapability && _supportedCapabilities.AllowsDynamicRegistration(descriptor.CapabilityType))
527532
{
528533
if (descriptor.RegistrationOptions is IWorkDoneProgressOptions wdpo)

src/Shared/SharedHandlerCollection.cs

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,15 @@ IDisposable IHandlersManager.AddLink(string sourceMethod, string destinationMeth
5454
{
5555
var source = _handlers.First(z => z.Method == sourceMethod);
5656
LspHandlerDescriptor descriptor = null;
57-
descriptor = GetDescriptor(destinationMethod, source.HandlerType, source.Handler,
58-
source.RequestProcessType.HasValue ? new JsonRpcHandlerOptions() {RequestProcessType = source.RequestProcessType.Value} : null);
57+
descriptor = GetDescriptor(
58+
destinationMethod,
59+
source.HandlerType,
60+
source.Handler,
61+
source.RequestProcessType.HasValue ? new JsonRpcHandlerOptions() {RequestProcessType = source.RequestProcessType.Value} : null,
62+
source.TypeDescriptor,
63+
source.HandlerType,
64+
source.RegistrationType,
65+
source.CapabilityType);
5966
_handlers.Add(descriptor);
6067
var cd = new CompositeDisposable();
6168
if (descriptor.Handler is ITextDocumentIdentifier textDocumentIdentifier)
@@ -141,7 +148,9 @@ public LspHandlerDescriptorDisposable Add(params IJsonRpcHandler[] handlers)
141148
foreach (var (method, implementedInterface) in handler.GetType().GetTypeInfo()
142149
.ImplementedInterfaces
143150
.Select(x => (method: HandlerTypeDescriptorHelper.GetMethodName(x), implementedInterface: x))
144-
.Where(x => !string.IsNullOrWhiteSpace(x.method)))
151+
.Distinct(new EqualityComparer())
152+
.Where(x => !string.IsNullOrWhiteSpace(x.method))
153+
)
145154
{
146155
var descriptor = GetDescriptor(method, implementedInterface, handler, null);
147156
descriptors.Add(descriptor);
@@ -156,6 +165,20 @@ public LspHandlerDescriptorDisposable Add(params IJsonRpcHandler[] handlers)
156165
return new LspHandlerDescriptorDisposable(descriptors, cd);
157166
}
158167

168+
class EqualityComparer : IEqualityComparer<(string method, Type implementedInterface)>
169+
{
170+
171+
public bool Equals((string method, Type implementedInterface) x, (string method, Type implementedInterface) y)
172+
{
173+
return x.method?.Equals(y.method) == true;
174+
}
175+
176+
public int GetHashCode((string method, Type implementedInterface) obj)
177+
{
178+
return obj.method?.GetHashCode() ?? 0;
179+
}
180+
}
181+
159182
private LspHandlerDescriptorDisposable Add(IJsonRpcHandler[] handlers, JsonRpcHandlerOptions options)
160183
{
161184
var descriptors = new HashSet<LspHandlerDescriptor>();
@@ -196,12 +219,17 @@ private LspHandlerDescriptor GetDescriptor(string method, Type handlerType, IJso
196219
var typeDescriptor = LspHandlerTypeDescriptorHelper.GetHandlerTypeDescriptor(method);
197220
var @interface = HandlerTypeDescriptorHelper.GetHandlerInterface(handlerType);
198221
var registrationType = typeDescriptor?.RegistrationType ??
199-
HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration<>), handlerType) ??
200-
HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration<>), handler.GetType());
222+
HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration<>), handlerType);
201223
var capabilityType = typeDescriptor?.CapabilityType ??
202-
HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(ICapability<>), handlerType) ??
203-
HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(ICapability<>), handler.GetType());
224+
HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(ICapability<>), handlerType);
204225

226+
return GetDescriptor(method, handlerType, handler, options, typeDescriptor, @interface, registrationType, capabilityType);
227+
}
228+
229+
private LspHandlerDescriptor GetDescriptor(string method, Type handlerType, IJsonRpcHandler handler, JsonRpcHandlerOptions options,
230+
ILspHandlerTypeDescriptor typeDescriptor,
231+
Type @interface, Type registrationType, Type capabilityType)
232+
{
205233
Type @params = null;
206234
object registrationOptions = null;
207235
if (@interface.GetTypeInfo().IsGenericType)
@@ -256,7 +284,8 @@ private LspHandlerDescriptor GetDescriptor(string method, Type handlerType, IJso
256284
(registrationType == null ? (Func<bool>) (() => false) : (() => _supportedCapabilities.AllowsDynamicRegistration(capabilityType))),
257285
capabilityType,
258286
requestProcessType,
259-
() => { _handlers.RemoveWhere(d => d.Handler == handler); });
287+
() => { _handlers.RemoveWhere(d => d.Handler == handler); },
288+
typeDescriptor);
260289

261290
return descriptor;
262291
}

test/Lsp.Tests/Integration/DynamicRegistrationTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ public async Task Should_Gather_Linked_Registrations()
102102
await Events.Settle().Take(2);
103103

104104
client.RegistrationManager.CurrentRegistrations.Should().Contain(x => x.Method == TextDocumentNames.SemanticTokensFull);
105+
client.RegistrationManager.CurrentRegistrations.Should().NotContain(x => x.Method == TextDocumentNames.SemanticTokensFullDelta);
106+
client.RegistrationManager.CurrentRegistrations.Should().NotContain(x => x.Method == TextDocumentNames.SemanticTokensRange);
105107
client.RegistrationManager.CurrentRegistrations.Should().Contain(x => x.Method == "@/" + TextDocumentNames.SemanticTokensFull);
106108
}
107109

test/Lsp.Tests/Matchers/ExecuteCommandHandlerMatcherTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ public void Should_Return_Handler_Descriptor()
7070
() => true,
7171
typeof(ExecuteCommandCapability),
7272
null,
73-
() => { })
73+
() => { },
74+
Substitute.For<ILspHandlerTypeDescriptor>())
7475
});
7576

7677
// Then

test/Lsp.Tests/Matchers/ResolveCommandMatcherTests.cs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ public void Should_Not_Throw_Given_Another_Descriptor()
6969
() => false,
7070
null,
7171
null,
72-
() => { });
72+
() => { },
73+
Substitute.For<ILspHandlerTypeDescriptor>());
7374
var handlerMatcher = new ResolveCommandPipeline<CodeLensParams, CodeLensContainer>(
7475
new RequestContext() {Descriptor = handlerDescriptor},
7576
LoggerFactory.CreateLogger<ResolveCommandPipeline<CodeLensParams, CodeLensContainer>>());
@@ -104,7 +105,8 @@ public void Should_Return_CodeLensResolve_Descriptor()
104105
() => false,
105106
null,
106107
null,
107-
() => { }),
108+
() => { },
109+
Substitute.For<ILspHandlerTypeDescriptor>()),
108110
new LspHandlerDescriptor(TextDocumentNames.CodeLensResolve,
109111
"Key2",
110112
resolveHandler2,
@@ -115,7 +117,8 @@ public void Should_Return_CodeLensResolve_Descriptor()
115117
() => false,
116118
null,
117119
null,
118-
() => { }),
120+
() => { },
121+
Substitute.For<ILspHandlerTypeDescriptor>()),
119122
})
120123
.ToArray();
121124

@@ -145,7 +148,8 @@ public void Should_Handle_Null_Data()
145148
() => false,
146149
null,
147150
null,
148-
() => { }),
151+
() => { },
152+
Substitute.For<ILspHandlerTypeDescriptor>()),
149153
})
150154
.ToArray();
151155

@@ -177,7 +181,8 @@ public void Should_Handle_Simple_Json_Data()
177181
() => false,
178182
null,
179183
null,
180-
() => { }),
184+
() => { },
185+
Substitute.For<ILspHandlerTypeDescriptor>()),
181186
})
182187
.ToArray();
183188

@@ -211,7 +216,8 @@ public void Should_Return_CompletionResolve_Descriptor()
211216
() => false,
212217
null,
213218
null,
214-
() => { }),
219+
() => { },
220+
Substitute.For<ILspHandlerTypeDescriptor>()),
215221
new LspHandlerDescriptor(TextDocumentNames.CompletionResolve,
216222
"Key2",
217223
resolveHandler2,
@@ -222,7 +228,8 @@ public void Should_Return_CompletionResolve_Descriptor()
222228
() => false,
223229
null,
224230
null,
225-
() => { }),
231+
() => { },
232+
Substitute.For<ILspHandlerTypeDescriptor>()),
226233
})
227234
.ToArray();
228235

@@ -263,7 +270,8 @@ public void Should_Deal_WithHandlers_That_Not_Also_Resolvers()
263270
() => false,
264271
null,
265272
null,
266-
() => { }),
273+
() => { },
274+
Substitute.For<ILspHandlerTypeDescriptor>()),
267275
new LspHandlerDescriptor(TextDocumentNames.CompletionResolve,
268276
"Key2",
269277
resolveHandler2 as IJsonRpcHandler,
@@ -274,7 +282,8 @@ public void Should_Deal_WithHandlers_That_Not_Also_Resolvers()
274282
() => false,
275283
null,
276284
null,
277-
() => { }),
285+
() => { },
286+
Substitute.For<ILspHandlerTypeDescriptor>()),
278287
})
279288
.ToArray();
280289

@@ -311,7 +320,8 @@ public void Should_Deal_WithHandlers_That_Not_Also_Resolvers2()
311320
() => false,
312321
null,
313322
null,
314-
() => { }),
323+
() => { },
324+
Substitute.For<ILspHandlerTypeDescriptor>()),
315325
new LspHandlerDescriptor(TextDocumentNames.CompletionResolve,
316326
"Key2",
317327
resolveHandler2 as IJsonRpcHandler,
@@ -322,7 +332,8 @@ public void Should_Deal_WithHandlers_That_Not_Also_Resolvers2()
322332
() => false,
323333
null,
324334
null,
325-
() => { }),
335+
() => { },
336+
Substitute.For<ILspHandlerTypeDescriptor>()),
326337
})
327338
.ToArray();
328339

@@ -351,7 +362,8 @@ public async Task Should_Update_CompletionItems_With_HandlerType()
351362
() => false,
352363
null,
353364
null,
354-
() => { });
365+
() => { },
366+
Substitute.For<ILspHandlerTypeDescriptor>());
355367
var handlerMatcher = new ResolveCommandPipeline<CompletionParams, CompletionList>(
356368
new RequestContext() {Descriptor = descriptor},
357369
Substitute.For<ILogger<ResolveCommandPipeline<CompletionParams, CompletionList>>>());
@@ -395,7 +407,8 @@ public async Task Should_Update_CodeLensContainer_With_HandlerType()
395407
() => false,
396408
null,
397409
null,
398-
() => { });
410+
() => { },
411+
Substitute.For<ILspHandlerTypeDescriptor>());
399412
var handlerMatcher = new ResolveCommandPipeline<CodeLensParams, CodeLensContainer>(
400413
new RequestContext() {Descriptor = descriptor},
401414
Substitute.For<ILogger<ResolveCommandPipeline<CodeLensParams, CodeLensContainer>>>());
@@ -439,7 +452,8 @@ public async Task Should_Update_CodeLens_Removing_HandlerType()
439452
() => false,
440453
null,
441454
null,
442-
() => { });
455+
() => { },
456+
Substitute.For<ILspHandlerTypeDescriptor>());
443457
var handlerMatcher = new ResolveCommandPipeline<CodeLens, CodeLens>(
444458
new RequestContext() {Descriptor = descriptor},
445459
Substitute.For<ILogger<ResolveCommandPipeline<CodeLens, CodeLens>>>());

0 commit comments

Comments
 (0)