Skip to content

Commit f93f973

Browse files
Updated latest version of the 0.16 spec (#263)
* Updated latest version of the 0.16 spec * fixed semantic tokens (RAINBOWS BACK BABY!). Added ability to link rpc methods together, so that if you need to support cases where the method has changed, you can now. * fixed Trace property * Added method that takes in a range to be similar to the vscode api, however watch for allocations * fixed back tracevalue * rollback initialze trace change... will do it later * Fixed an issue with registration for semantic tokens * fixed issue with dynamic registration and the sub handlers for semantic tokens * fixed failed tests * Added back missing comments
1 parent 9407981 commit f93f973

File tree

86 files changed

+1662
-1364
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+1662
-1364
lines changed

Directory.Build.targets

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
<PackageReference Update="xunit" Version="2.4.1"/>
2727
<PackageReference Update="FluentAssertions" Version="5.10.2"/>
2828
<PackageReference Update="NSubstitute" Version="4.2.1"/>
29-
<PackageReference Update="Autofac" Version="4.8.1"/>
30-
<PackageReference Update="Autofac.Extensions.DependencyInjection" Version="4.3.1"/>
29+
<PackageReference Update="DryIoc.dll" Version="4.2.5" />
30+
<PackageReference Update="DryIoc.Microsoft.DependencyInjection " Version="4.0.0" />
3131
<PackageReference Update="Serilog.Extensions.Logging" Version="2.0.2"/>
3232
<PackageReference Update="Serilog.Sinks.XUnit" Version="1.0.21"/>
3333
<PackageReference Update="XunitXml.TestLogger" Version="2.1.26"/>

sample/SampleServer/Program.cs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
using System;
2+
using System.Diagnostics;
23
using System.Threading.Tasks;
34
using Microsoft.Extensions.Configuration;
45
using Microsoft.Extensions.DependencyInjection;
56
using Microsoft.Extensions.Logging;
67
using Newtonsoft.Json.Linq;
8+
using OmniSharp.Extensions.JsonRpc;
9+
using OmniSharp.Extensions.LanguageServer.Protocol;
710
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
11+
using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals;
812
using OmniSharp.Extensions.LanguageServer.Server;
913
using Serilog;
1014

@@ -40,15 +44,15 @@ static async Task MainAsync(string[] args)
4044
.WithInput(Console.OpenStandardInput())
4145
.WithOutput(Console.OpenStandardOutput())
4246
.ConfigureLogging(x => x
43-
.AddSerilog()
47+
.AddSerilog(Log.Logger)
4448
.AddLanguageProtocolLogging()
4549
.SetMinimumLevel(LogLevel.Debug))
4650
.WithHandler<TextDocumentHandler>()
4751
.WithHandler<DidChangeWatchedFilesHandler>()
4852
.WithHandler<FoldingRangeHandler>()
4953
.WithHandler<MyWorkspaceSymbolsHandler>()
5054
.WithHandler<MyDocumentSymbolHandler>()
51-
.WithHandler<SemanticTokens>()
55+
.WithHandler<SemanticTokensHandler>()
5256
.WithServices(x => x.AddLogging(b => b.SetMinimumLevel(LogLevel.Trace)))
5357
.WithServices(services => {
5458
services.AddSingleton(provider => {

sample/SampleServer/SemanticTokens.cs renamed to sample/SampleServer/SemanticTokensHandler.cs

+10-10
Original file line numberDiff line numberDiff line change
@@ -7,45 +7,45 @@
77
using Microsoft.Extensions.Logging;
88
using Newtonsoft.Json;
99
using OmniSharp.Extensions.LanguageServer.Protocol;
10+
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
1011
using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals;
1112
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
1213
using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals;
1314

1415
namespace SampleServer
1516
{
1617
#pragma warning disable 618
17-
public class SemanticTokens : SemanticTokensHandler
18+
public class SemanticTokensHandler : SemanticTokensHandlerBase
1819
{
1920
private readonly ILogger _logger;
2021

21-
public SemanticTokens(ILogger<SemanticTokens> logger) : base(new SemanticTokensRegistrationOptions() {
22+
public SemanticTokensHandler(ILogger<SemanticTokensHandler> logger) : base(new SemanticTokensRegistrationOptions() {
2223
DocumentSelector = DocumentSelector.ForLanguage("csharp"),
2324
Legend = new SemanticTokensLegend(),
24-
DocumentProvider = new Supports<SemanticTokensDocumentProviderOptions>(true,
25-
new SemanticTokensDocumentProviderOptions() {
26-
Edits = true
27-
}),
28-
RangeProvider = true
25+
Full = new SemanticTokensCapabilityRequestFull() {
26+
Delta = true
27+
},
28+
Range = true
2929
})
3030
{
3131
_logger = logger;
3232
}
3333

34-
public override async Task<OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals.SemanticTokens> Handle(
34+
public override async Task<SemanticTokens> Handle(
3535
SemanticTokensParams request, CancellationToken cancellationToken)
3636
{
3737
var result = await base.Handle(request, cancellationToken);
3838
return result;
3939
}
4040

41-
public override async Task<OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals.SemanticTokens> Handle(
41+
public override async Task<SemanticTokens> Handle(
4242
SemanticTokensRangeParams request, CancellationToken cancellationToken)
4343
{
4444
var result = await base.Handle(request, cancellationToken);
4545
return result;
4646
}
4747

48-
public override async Task<SemanticTokensOrSemanticTokensEdits> Handle(SemanticTokensEditsParams request,
48+
public override async Task<SemanticTokensFullOrDelta> Handle(SemanticTokensDeltaParams request,
4949
CancellationToken cancellationToken)
5050
{
5151
var result = await base.Handle(request, cancellationToken);

src/Client/LanguageClient.cs

+1
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ internal LanguageClient(LanguageClientOptions options) : base(options)
200200
var serviceIdentifiers = _serviceProvider.GetServices<ITextDocumentIdentifier>().ToArray();
201201
_disposable.Add(_textDocumentIdentifiers.Add(serviceIdentifiers));
202202
_disposable.Add(_collection.Add(serviceHandlers));
203+
options.AddLinks(_collection);
203204
}
204205

205206
public ITextDocumentLanguageClient TextDocument { get; }

src/Client/RegistrationManager.cs

+10-3
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,23 @@ public RegistrationManager(ISerializer serializer, ILogger<RegistrationManager>
3636

3737
Task<Unit> IRequestHandler<RegistrationParams, Unit>.Handle(RegistrationParams request, CancellationToken cancellationToken)
3838
{
39-
Register(request.Registrations.ToArray());
39+
lock (this)
40+
{
41+
Register(request.Registrations.ToArray());
42+
}
43+
4044
_registrationSubject.OnNext(_registrations.Values);
4145
return Unit.Task;
4246
}
4347

4448
Task<Unit> IRequestHandler<UnregistrationParams, Unit>.Handle(UnregistrationParams request, CancellationToken cancellationToken)
4549
{
46-
foreach (var item in request.Unregisterations ?? new UnregistrationContainer())
50+
lock (this)
4751
{
48-
_registrations.TryRemove(item.Id, out _);
52+
foreach (var item in request.Unregisterations ?? new UnregistrationContainer())
53+
{
54+
_registrations.TryRemove(item.Id, out _);
55+
}
4956
}
5057

5158
_registrationSubject.OnNext(_registrations.Values);

src/JsonRpc.Testing/AggregateSettler.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public Task SettleNext()
1919
{
2020
return _settlers.ToObservable()
2121
.Select(z => z.Settle())
22-
.Switch()
22+
.Merge()
2323
.Take(1)
2424
//.Amb(Observable.Timer(_waitTime + _waitTime).Select(z => Unit.Value))
2525
.ToTask();

src/JsonRpc.Testing/Settler.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ public Settler(TimeSpan waitTime, TimeSpan timeout, CancellationToken cancellati
2727
acc += next;
2828
return acc;
2929
})
30-
.Select(z => z <= 0 ? Observable.Timer(waitTime).Select(_ => Unit.Default).Timeout(timeout, Observable.Return(Unit.Default)) : Observable.Never<Unit>())
31-
.Switch()
3230
.Replay(1)
33-
.RefCount();
31+
.RefCount()
32+
.Select(z => z <= 0 ? Observable.Timer(waitTime).Select(_ => Unit.Default).Timeout(timeout, Observable.Return(Unit.Default)) : Observable.Never<Unit>())
33+
.Switch();
3434
_requester = subject;
3535
}
3636

@@ -43,7 +43,7 @@ public Task SettleNext()
4343

4444
public IObservable<Unit> Settle()
4545
{
46-
return _settle;
46+
return _settle.Timeout(_timeout).Catch<Unit, Exception>(_ => Observable.Empty<Unit>());
4747
}
4848

4949
void IRequestSettler.OnStartRequest()

src/JsonRpc/CompositeHandlersManager.cs

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public IDisposable Add(string method, IJsonRpcHandler handler, JsonRpcHandlerOpt
2727
return result;
2828
}
2929

30+
public IDisposable AddLink(string sourceMethod, string destinationMethod) => _parent.AddLink(sourceMethod, destinationMethod);
31+
3032
public CompositeDisposable GetDisposable() => _compositeDisposable;
3133
}
3234
}

src/JsonRpc/HandlerCollection.cs

+51-3
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99

1010
namespace OmniSharp.Extensions.JsonRpc
1111
{
12+
13+
1214
public class HandlerCollection : IEnumerable<IHandlerDescriptor>, IHandlersManager
1315
{
14-
internal readonly List<HandlerInstance> _handlers = new List<HandlerInstance>();
16+
internal readonly List<IHandlerDescriptor> _handlers = new List<IHandlerDescriptor>();
1517

1618
public HandlerCollection() { }
1719

@@ -70,6 +72,41 @@ public void Dispose()
7072
}
7173
}
7274

75+
[DebuggerDisplay("{Method}")]
76+
internal class LinkedHandler : IHandlerDescriptor, IDisposable
77+
{
78+
private readonly IHandlerDescriptor _descriptor;
79+
private readonly Action _disposeAction;
80+
81+
public LinkedHandler(string method, IHandlerDescriptor descriptor, Action disposeAction)
82+
{
83+
_descriptor = descriptor;
84+
_disposeAction = disposeAction;
85+
Method = method;
86+
}
87+
public string Method { get; }
88+
public Type HandlerType => _descriptor.HandlerType;
89+
90+
public Type ImplementationType => _descriptor.ImplementationType;
91+
92+
public Type Params => _descriptor.Params;
93+
94+
public Type Response => _descriptor.Response;
95+
96+
public bool HasReturnType => _descriptor.HasReturnType;
97+
98+
public bool IsDelegatingHandler => _descriptor.IsDelegatingHandler;
99+
100+
public IJsonRpcHandler Handler => _descriptor.Handler;
101+
102+
public RequestProcessType? RequestProcessType => _descriptor.RequestProcessType;
103+
104+
public void Dispose()
105+
{
106+
_disposeAction();
107+
}
108+
}
109+
73110
public IEnumerator<IHandlerDescriptor> GetEnumerator()
74111
{
75112
return _handlers.GetEnumerator();
@@ -82,8 +119,11 @@ IEnumerator IEnumerable.GetEnumerator()
82119

83120
private void Remove(IJsonRpcHandler handler)
84121
{
85-
var i = _handlers.Find(instance => instance.Handler == handler);
86-
if (i != null) _handlers.Remove(i);
122+
var handlers = _handlers.FindAll(instance => instance.Handler == handler);
123+
foreach (var item in handlers)
124+
{
125+
_handlers.Remove(item);
126+
}
87127
}
88128

89129
public IDisposable Add(params IJsonRpcHandler[] handlers)
@@ -132,6 +172,14 @@ public IDisposable Add(string method, IJsonRpcHandler handler, JsonRpcHandlerOpt
132172
return h;
133173
}
134174

175+
public IDisposable AddLink(string sourceMethod, string destinationMethod)
176+
{
177+
var source = _handlers.Find(z => z.Method == sourceMethod);
178+
var h = new LinkedHandler(destinationMethod, source, () => _handlers.RemoveAll(z => z.Method == destinationMethod));
179+
_handlers.Add(h);
180+
return h;
181+
}
182+
135183
private static readonly Type[] HandlerTypes = {
136184
typeof(IJsonRpcNotificationHandler),
137185
typeof(IJsonRpcNotificationHandler<>),

src/JsonRpc/IHandlersManager.cs

+1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ public interface IHandlersManager
66
{
77
IDisposable Add(IJsonRpcHandler handler, JsonRpcHandlerOptions options);
88
IDisposable Add(string method, IJsonRpcHandler handler, JsonRpcHandlerOptions options);
9+
IDisposable AddLink(string sourceMethod, string destinationMethod);
910
}
1011
}

src/JsonRpc/JsonRpcOptionsRegistryBase.cs

+10
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
using System;
2+
using System.Collections.Generic;
23
using Microsoft.Extensions.DependencyInjection;
34

45
namespace OmniSharp.Extensions.JsonRpc
56
{
67
public abstract class JsonRpcOptionsRegistryBase<T> : JsonRpcCommonMethodsBase<T> where T : IJsonRpcHandlerRegistry<T>
78
{
89
public IServiceCollection Services { get; set; } = new ServiceCollection();
10+
protected internal HashSet<(string source, string destination)> Links= new HashSet<(string source, string destination)>();
11+
12+
public void AddLinks(IHandlersManager handlersManager)
13+
{
14+
foreach (var link in Links)
15+
{
16+
handlersManager.AddLink(link.source, link.destination);
17+
}
18+
}
919

1020
#region AddHandler
1121

src/JsonRpc/JsonRpcServer.cs

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ internal JsonRpcServer(JsonRpcServerOptions options) : base(options)
9898
);
9999
_disposable.Add(_connection);
100100
_collection.Add(_serviceProvider.GetRequiredService<IEnumerable<IJsonRpcHandler>>().ToArray());
101+
options.AddLinks(_collection);
101102
}
102103

103104
private async Task Initialize(CancellationToken cancellationToken)

src/JsonRpc/JsonRpcServerOptionsBase.cs

+6
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,11 @@ public T WithMaximumRequestTimeout(TimeSpan maximumRequestTimeout)
139139
MaximumRequestTimeout = maximumRequestTimeout;
140140
return (T)(object) this;
141141
}
142+
143+
public T WithLink(string source, string destination)
144+
{
145+
Links.Add((source, destination));
146+
return (T)(object) this;
147+
}
142148
}
143149
}

src/Protocol/AbstractHandlers.cs

+2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ async Task<TResponse> IRequestHandler<TItem, TResponse>.Handle(TItem request,
6868
}
6969

7070
var subject = new AsyncSubject<TItem>();
71+
// in the event nothing is emitted...
72+
subject.OnNext(default);
7173
Handle(request, subject, cancellationToken);
7274
return _factory(await subject);
7375
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals;
3+
4+
namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
5+
{
6+
/// <summary>
7+
/// Capabilities specific to the `textDocument/callHierarchy`.
8+
///
9+
/// @since 3.16.0
10+
/// </summary>
11+
[Obsolete(Constants.Proposal)]
12+
public class CallHierarchyCapability : DynamicCapability, ConnectedCapability<ICallHierarchyHandler>,
13+
ConnectedCapability<ICallHierarchyIncomingHandler>, ConnectedCapability<ICallHierarchyOutgoingHandler>
14+
{
15+
}
16+
}

src/Protocol/Client/Capabilities/CompletionItemCapability.cs

+22-4
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ public class CompletionItemCapability
3030
public Container<MarkupKind> DocumentationFormat { get; set; }
3131

3232
/// <summary>
33-
/// Client supports the deprecated property on a completion item.
34-
/// </summary>
33+
/// Client supports the deprecated property on a completion item.
34+
/// </summary>
3535
[Optional]
3636
public bool DeprecatedSupport { get; set; }
3737

3838
/// <summary>
39-
/// Client supports the preselect property on a completion item.
40-
/// </summary>
39+
/// Client supports the preselect property on a completion item.
40+
/// </summary>
4141
[Optional]
4242
public bool PreselectSupport { get; set; }
4343

@@ -51,5 +51,23 @@ public class CompletionItemCapability
5151
/// </summary>
5252
[Optional]
5353
public Supports<CompletionItemTagSupportCapability> TagSupport { get; set; }
54+
55+
/// <summary>
56+
/// Client support insert replace edit to control different behavior if a
57+
/// completion item is inserted in the text or should replace text.
58+
///
59+
/// @since 3.16.0 - Proposed state
60+
/// </summary>
61+
[Optional]
62+
public bool InsertReplaceSupport { get; set; }
63+
64+
/// <summary>
65+
/// Client supports to resolve `additionalTextEdits` in the `completionItem/resolve`
66+
/// request. So servers can postpone computing them.
67+
///
68+
/// @since 3.16.0 - Proposed state
69+
/// </summary>
70+
[Optional]
71+
public bool ResolveAdditionalTextEditsSupport { get; set; }
5472
}
5573
}

0 commit comments

Comments
 (0)