Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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