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
11 changes: 9 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,18 @@ 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>()
// Linking here because the spec changed but vscode is behind
.WithLink(TextDocumentNames.SemanticTokensFull, "textDocument/semanticTokens")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TylerLeonhardt this lets us fake out the vscode client for now, until it's updated to line up with the spec.

.WithLink(TextDocumentNames.SemanticTokensFullDelta, "textDocument/semanticTokens/edits")
.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
7 changes: 4 additions & 3 deletions src/Client/LanguageClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class LanguageClient : JsonRpcServerBase, ILanguageClient
private readonly object _initializationOptions;
private readonly IWorkspaceFoldersManager _workspaceFoldersManager;
private readonly DocumentUri _rootUri;
private readonly InitializeTrace _trace;
private readonly TraceValue _traceValue;
private readonly IRegistrationManager _registrationManager;
private readonly ClientCapabilities _clientCapabilities;
private readonly IProgressManager _progressManager;
Expand Down Expand Up @@ -121,7 +121,7 @@ internal LanguageClient(LanguageClientOptions options) : base(options)
// _initializedDelegates = initializedDelegates;
_startedDelegates = options.StartedDelegates;
_rootUri = options.RootUri;
_trace = options.Trace;
_traceValue = options.TraceValue;
_initializationOptions = options.InitializationOptions;

services.AddSingleton<IOutputHandler>(_ =>
Expand Down 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 All @@ -220,7 +221,7 @@ internal LanguageClient(LanguageClientOptions options) : base(options)
public async Task Initialize(CancellationToken token)
{
var @params = new InitializeParams {
Trace = _trace,
Trace = _traceValue,
Capabilities = _clientCapabilities,
ClientInfo = _clientInfo,
RootUri = _rootUri,
Expand Down
2 changes: 1 addition & 1 deletion src/Client/LanguageClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public string RootPath
set => RootUri = DocumentUri.FromFileSystemPath(value);
}

public InitializeTrace Trace { get; set; }
public TraceValue TraceValue { get; set; }

public object InitializationOptions { get; set; }

Expand Down
4 changes: 2 additions & 2 deletions src/Client/LanguageClientOptionsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ public static LanguageClientOptions WithRootPath(this LanguageClientOptions opti
return options;
}

public static LanguageClientOptions WithTrace(this LanguageClientOptions options, InitializeTrace trace)
public static LanguageClientOptions WithTrace(this LanguageClientOptions options, TraceValue traceValue)
{
options.Trace = trace;
options.TraceValue = traceValue;
return options;
}

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>
{
}
}
Loading