Skip to content

Updated latest version of the 0.16 spec #263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jul 24, 2020
4 changes: 2 additions & 2 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
<PackageReference Update="xunit" Version="2.4.1"/>
<PackageReference Update="FluentAssertions" Version="5.10.2"/>
<PackageReference Update="NSubstitute" Version="4.2.1"/>
<PackageReference Update="Autofac" Version="4.8.1"/>
<PackageReference Update="Autofac.Extensions.DependencyInjection" Version="4.3.1"/>
<PackageReference Update="DryIoc.dll" Version="4.2.5" />
<PackageReference Update="DryIoc.Microsoft.DependencyInjection " Version="4.0.0" />
<PackageReference Update="Serilog.Extensions.Logging" Version="2.0.2"/>
<PackageReference Update="Serilog.Sinks.XUnit" Version="1.0.21"/>
<PackageReference Update="XunitXml.TestLogger" Version="2.1.26"/>
Expand Down
8 changes: 6 additions & 2 deletions sample/SampleServer/Program.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using OmniSharp.Extensions.JsonRpc;
using OmniSharp.Extensions.LanguageServer.Protocol;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals;
using OmniSharp.Extensions.LanguageServer.Server;
using Serilog;

Expand Down Expand Up @@ -40,15 +44,15 @@ static async Task MainAsync(string[] args)
.WithInput(Console.OpenStandardInput())
.WithOutput(Console.OpenStandardOutput())
.ConfigureLogging(x => x
.AddSerilog()
.AddSerilog(Log.Logger)
.AddLanguageProtocolLogging()
.SetMinimumLevel(LogLevel.Debug))
.WithHandler<TextDocumentHandler>()
.WithHandler<DidChangeWatchedFilesHandler>()
.WithHandler<FoldingRangeHandler>()
.WithHandler<MyWorkspaceSymbolsHandler>()
.WithHandler<MyDocumentSymbolHandler>()
.WithHandler<SemanticTokens>()
.WithHandler<SemanticTokensHandler>()
.WithServices(x => x.AddLogging(b => b.SetMinimumLevel(LogLevel.Trace)))
.WithServices(services => {
services.AddSingleton(provider => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,45 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using OmniSharp.Extensions.LanguageServer.Protocol;
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals;

namespace SampleServer
{
#pragma warning disable 618
public class SemanticTokens : SemanticTokensHandler
public class SemanticTokensHandler : SemanticTokensHandlerBase
{
private readonly ILogger _logger;

public SemanticTokens(ILogger<SemanticTokens> logger) : base(new SemanticTokensRegistrationOptions() {
public SemanticTokensHandler(ILogger<SemanticTokensHandler> logger) : base(new SemanticTokensRegistrationOptions() {
DocumentSelector = DocumentSelector.ForLanguage("csharp"),
Legend = new SemanticTokensLegend(),
DocumentProvider = new Supports<SemanticTokensDocumentProviderOptions>(true,
new SemanticTokensDocumentProviderOptions() {
Edits = true
}),
RangeProvider = true
Full = new SemanticTokensCapabilityRequestFull() {
Delta = true
},
Range = true
})
{
_logger = logger;
}

public override async Task<OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals.SemanticTokens> Handle(
public override async Task<SemanticTokens> Handle(
SemanticTokensParams request, CancellationToken cancellationToken)
{
var result = await base.Handle(request, cancellationToken);
return result;
}

public override async Task<OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals.SemanticTokens> Handle(
public override async Task<SemanticTokens> Handle(
SemanticTokensRangeParams request, CancellationToken cancellationToken)
{
var result = await base.Handle(request, cancellationToken);
return result;
}

public override async Task<SemanticTokensOrSemanticTokensEdits> Handle(SemanticTokensEditsParams request,
public override async Task<SemanticTokensFullOrDelta> Handle(SemanticTokensDeltaParams request,
CancellationToken cancellationToken)
{
var result = await base.Handle(request, cancellationToken);
Expand Down
1 change: 1 addition & 0 deletions src/Client/LanguageClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ internal LanguageClient(LanguageClientOptions options) : base(options)
var serviceIdentifiers = _serviceProvider.GetServices<ITextDocumentIdentifier>().ToArray();
_disposable.Add(_textDocumentIdentifiers.Add(serviceIdentifiers));
_disposable.Add(_collection.Add(serviceHandlers));
options.AddLinks(_collection);
}

public ITextDocumentLanguageClient TextDocument { get; }
Expand Down
13 changes: 10 additions & 3 deletions src/Client/RegistrationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,23 @@ public RegistrationManager(ISerializer serializer, ILogger<RegistrationManager>

Task<Unit> IRequestHandler<RegistrationParams, Unit>.Handle(RegistrationParams request, CancellationToken cancellationToken)
{
Register(request.Registrations.ToArray());
lock (this)
{
Register(request.Registrations.ToArray());
}

_registrationSubject.OnNext(_registrations.Values);
return Unit.Task;
}

Task<Unit> IRequestHandler<UnregistrationParams, Unit>.Handle(UnregistrationParams request, CancellationToken cancellationToken)
{
foreach (var item in request.Unregisterations ?? new UnregistrationContainer())
lock (this)
{
_registrations.TryRemove(item.Id, out _);
foreach (var item in request.Unregisterations ?? new UnregistrationContainer())
{
_registrations.TryRemove(item.Id, out _);
}
}

_registrationSubject.OnNext(_registrations.Values);
Expand Down
2 changes: 1 addition & 1 deletion src/JsonRpc.Testing/AggregateSettler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public Task SettleNext()
{
return _settlers.ToObservable()
.Select(z => z.Settle())
.Switch()
.Merge()
.Take(1)
//.Amb(Observable.Timer(_waitTime + _waitTime).Select(z => Unit.Value))
.ToTask();
Expand Down
8 changes: 4 additions & 4 deletions src/JsonRpc.Testing/Settler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ public Settler(TimeSpan waitTime, TimeSpan timeout, CancellationToken cancellati
acc += next;
return acc;
})
.Select(z => z <= 0 ? Observable.Timer(waitTime).Select(_ => Unit.Default).Timeout(timeout, Observable.Return(Unit.Default)) : Observable.Never<Unit>())
.Switch()
.Replay(1)
.RefCount();
.RefCount()
.Select(z => z <= 0 ? Observable.Timer(waitTime).Select(_ => Unit.Default).Timeout(timeout, Observable.Return(Unit.Default)) : Observable.Never<Unit>())
.Switch();
_requester = subject;
}

Expand All @@ -43,7 +43,7 @@ public Task SettleNext()

public IObservable<Unit> Settle()
{
return _settle;
return _settle.Timeout(_timeout).Catch<Unit, Exception>(_ => Observable.Empty<Unit>());
}

void IRequestSettler.OnStartRequest()
Expand Down
2 changes: 2 additions & 0 deletions src/JsonRpc/CompositeHandlersManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public IDisposable Add(string method, IJsonRpcHandler handler, JsonRpcHandlerOpt
return result;
}

public IDisposable AddLink(string sourceMethod, string destinationMethod) => _parent.AddLink(sourceMethod, destinationMethod);

public CompositeDisposable GetDisposable() => _compositeDisposable;
}
}
54 changes: 51 additions & 3 deletions src/JsonRpc/HandlerCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@

namespace OmniSharp.Extensions.JsonRpc
{


public class HandlerCollection : IEnumerable<IHandlerDescriptor>, IHandlersManager
{
internal readonly List<HandlerInstance> _handlers = new List<HandlerInstance>();
internal readonly List<IHandlerDescriptor> _handlers = new List<IHandlerDescriptor>();

public HandlerCollection() { }

Expand Down Expand Up @@ -70,6 +72,41 @@ public void Dispose()
}
}

[DebuggerDisplay("{Method}")]
internal class LinkedHandler : IHandlerDescriptor, IDisposable
{
private readonly IHandlerDescriptor _descriptor;
private readonly Action _disposeAction;

public LinkedHandler(string method, IHandlerDescriptor descriptor, Action disposeAction)
{
_descriptor = descriptor;
_disposeAction = disposeAction;
Method = method;
}
public string Method { get; }
public Type HandlerType => _descriptor.HandlerType;

public Type ImplementationType => _descriptor.ImplementationType;

public Type Params => _descriptor.Params;

public Type Response => _descriptor.Response;

public bool HasReturnType => _descriptor.HasReturnType;

public bool IsDelegatingHandler => _descriptor.IsDelegatingHandler;

public IJsonRpcHandler Handler => _descriptor.Handler;

public RequestProcessType? RequestProcessType => _descriptor.RequestProcessType;

public void Dispose()
{
_disposeAction();
}
}

public IEnumerator<IHandlerDescriptor> GetEnumerator()
{
return _handlers.GetEnumerator();
Expand All @@ -82,8 +119,11 @@ IEnumerator IEnumerable.GetEnumerator()

private void Remove(IJsonRpcHandler handler)
{
var i = _handlers.Find(instance => instance.Handler == handler);
if (i != null) _handlers.Remove(i);
var handlers = _handlers.FindAll(instance => instance.Handler == handler);
foreach (var item in handlers)
{
_handlers.Remove(item);
}
}

public IDisposable Add(params IJsonRpcHandler[] handlers)
Expand Down Expand Up @@ -132,6 +172,14 @@ public IDisposable Add(string method, IJsonRpcHandler handler, JsonRpcHandlerOpt
return h;
}

public IDisposable AddLink(string sourceMethod, string destinationMethod)
{
var source = _handlers.Find(z => z.Method == sourceMethod);
var h = new LinkedHandler(destinationMethod, source, () => _handlers.RemoveAll(z => z.Method == destinationMethod));
_handlers.Add(h);
return h;
}

private static readonly Type[] HandlerTypes = {
typeof(IJsonRpcNotificationHandler),
typeof(IJsonRpcNotificationHandler<>),
Expand Down
1 change: 1 addition & 0 deletions src/JsonRpc/IHandlersManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ public interface IHandlersManager
{
IDisposable Add(IJsonRpcHandler handler, JsonRpcHandlerOptions options);
IDisposable Add(string method, IJsonRpcHandler handler, JsonRpcHandlerOptions options);
IDisposable AddLink(string sourceMethod, string destinationMethod);
}
}
10 changes: 10 additions & 0 deletions src/JsonRpc/JsonRpcOptionsRegistryBase.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;

namespace OmniSharp.Extensions.JsonRpc
{
public abstract class JsonRpcOptionsRegistryBase<T> : JsonRpcCommonMethodsBase<T> where T : IJsonRpcHandlerRegistry<T>
{
public IServiceCollection Services { get; set; } = new ServiceCollection();
protected internal HashSet<(string source, string destination)> Links= new HashSet<(string source, string destination)>();

public void AddLinks(IHandlersManager handlersManager)
{
foreach (var link in Links)
{
handlersManager.AddLink(link.source, link.destination);
}
}

#region AddHandler

Expand Down
1 change: 1 addition & 0 deletions src/JsonRpc/JsonRpcServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ internal JsonRpcServer(JsonRpcServerOptions options) : base(options)
);
_disposable.Add(_connection);
_collection.Add(_serviceProvider.GetRequiredService<IEnumerable<IJsonRpcHandler>>().ToArray());
options.AddLinks(_collection);
}

private async Task Initialize(CancellationToken cancellationToken)
Expand Down
6 changes: 6 additions & 0 deletions src/JsonRpc/JsonRpcServerOptionsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,5 +139,11 @@ public T WithMaximumRequestTimeout(TimeSpan maximumRequestTimeout)
MaximumRequestTimeout = maximumRequestTimeout;
return (T)(object) this;
}

public T WithLink(string source, string destination)
{
Links.Add((source, destination));
return (T)(object) this;
}
}
}
2 changes: 2 additions & 0 deletions src/Protocol/AbstractHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ async Task<TResponse> IRequestHandler<TItem, TResponse>.Handle(TItem request,
}

var subject = new AsyncSubject<TItem>();
// in the event nothing is emitted...
subject.OnNext(default);
Handle(request, subject, cancellationToken);
return _factory(await subject);
}
Expand Down
16 changes: 16 additions & 0 deletions src/Protocol/Client/Capabilities/CallHierarchyCapability.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals;

namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
/// <summary>
/// Capabilities specific to the `textDocument/callHierarchy`.
///
/// @since 3.16.0
/// </summary>
[Obsolete(Constants.Proposal)]
public class CallHierarchyCapability : DynamicCapability, ConnectedCapability<ICallHierarchyHandler>,
ConnectedCapability<ICallHierarchyIncomingHandler>, ConnectedCapability<ICallHierarchyOutgoingHandler>
{
}
}
26 changes: 22 additions & 4 deletions src/Protocol/Client/Capabilities/CompletionItemCapability.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ public class CompletionItemCapability
public Container<MarkupKind> DocumentationFormat { get; set; }

/// <summary>
/// Client supports the deprecated property on a completion item.
/// </summary>
/// Client supports the deprecated property on a completion item.
/// </summary>
[Optional]
public bool DeprecatedSupport { get; set; }

/// <summary>
/// Client supports the preselect property on a completion item.
/// </summary>
/// Client supports the preselect property on a completion item.
/// </summary>
[Optional]
public bool PreselectSupport { get; set; }

Expand All @@ -51,5 +51,23 @@ public class CompletionItemCapability
/// </summary>
[Optional]
public Supports<CompletionItemTagSupportCapability> TagSupport { get; set; }

/// <summary>
/// Client support insert replace edit to control different behavior if a
/// completion item is inserted in the text or should replace text.
///
/// @since 3.16.0 - Proposed state
/// </summary>
[Optional]
public bool InsertReplaceSupport { get; set; }

/// <summary>
/// Client supports to resolve `additionalTextEdits` in the `completionItem/resolve`
/// request. So servers can postpone computing them.
///
/// @since 3.16.0 - Proposed state
/// </summary>
[Optional]
public bool ResolveAdditionalTextEditsSupport { get; set; }
}
}
Loading